drivers/gpu/drm/nouveau/nvkm/subdev/therm/fanpwm.c
Source file repositories/reference/linux-study-clean/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fanpwm.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/drm/nouveau/nvkm/subdev/therm/fanpwm.c- Extension
.c- Size
- 3306 bytes
- Lines
- 111
- Domain
- Driver Families
- Bucket
- drivers/gpu
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
priv.hcore/option.hsubdev/bios.hsubdev/bios/fan.hsubdev/gpio.h
Detected Declarations
struct nvkm_fanpwmfunction nvkm_fanpwm_getfunction nvkm_fanpwm_setfunction nvkm_fanpwm_create
Annotated Snippet
struct nvkm_fanpwm {
struct nvkm_fan base;
struct dcb_gpio_func func;
};
static int
nvkm_fanpwm_get(struct nvkm_therm *therm)
{
struct nvkm_fanpwm *fan = (void *)therm->fan;
struct nvkm_device *device = therm->subdev.device;
struct nvkm_gpio *gpio = device->gpio;
int card_type = device->card_type;
u32 divs, duty;
int ret;
ret = therm->func->pwm_get(therm, fan->func.line, &divs, &duty);
if (ret == 0 && divs) {
divs = max(divs, duty);
if (card_type <= NV_40 || (fan->func.log[0] & 1))
duty = divs - duty;
return (duty * 100) / divs;
}
return nvkm_gpio_get(gpio, 0, fan->func.func, fan->func.line) * 100;
}
static int
nvkm_fanpwm_set(struct nvkm_therm *therm, int percent)
{
struct nvkm_fanpwm *fan = (void *)therm->fan;
int card_type = therm->subdev.device->card_type;
u32 divs, duty;
int ret;
divs = fan->base.perf.pwm_divisor;
if (fan->base.bios.pwm_freq) {
divs = 1;
if (therm->func->pwm_clock)
divs = therm->func->pwm_clock(therm, fan->func.line);
divs /= fan->base.bios.pwm_freq;
}
duty = ((divs * percent) + 99) / 100;
if (card_type <= NV_40 || (fan->func.log[0] & 1))
duty = divs - duty;
ret = therm->func->pwm_set(therm, fan->func.line, divs, duty);
if (ret == 0)
ret = therm->func->pwm_ctrl(therm, fan->func.line, true);
return ret;
}
int
nvkm_fanpwm_create(struct nvkm_therm *therm, struct dcb_gpio_func *func)
{
struct nvkm_device *device = therm->subdev.device;
struct nvkm_bios *bios = device->bios;
struct nvkm_fanpwm *fan;
struct nvbios_therm_fan info = {};
u32 divs, duty;
nvbios_fan_parse(bios, &info);
if (!nvkm_boolopt(device->cfgopt, "NvFanPWM", func->param) ||
!therm->func->pwm_ctrl || info.type == NVBIOS_THERM_FAN_TOGGLE ||
therm->func->pwm_get(therm, func->line, &divs, &duty) == -ENODEV)
return -ENODEV;
fan = kzalloc_obj(*fan);
if (!fan)
return -ENOMEM;
therm->fan = &fan->base;
fan->base.type = "PWM";
fan->base.get = nvkm_fanpwm_get;
fan->base.set = nvkm_fanpwm_set;
fan->func = *func;
return 0;
}
Annotation
- Immediate include surface: `priv.h`, `core/option.h`, `subdev/bios.h`, `subdev/bios/fan.h`, `subdev/gpio.h`.
- Detected declarations: `struct nvkm_fanpwm`, `function nvkm_fanpwm_get`, `function nvkm_fanpwm_set`, `function nvkm_fanpwm_create`.
- Atlas domain: Driver Families / drivers/gpu.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.