drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllnv04.c
Source file repositories/reference/linux-study-clean/drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllnv04.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/drm/nouveau/nvkm/subdev/clk/pllnv04.c- Extension
.c- Size
- 6666 bytes
- Lines
- 246
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
pll.hsubdev/bios.hsubdev/bios/pll.h
Detected Declarations
function filesfunction getMNP_doublefunction nv04_pll_calc
Annotated Snippet
if (cv < 0x17 || cv == 0x1a || cv == 0x20) {
if (clk > 250000)
maxM = 6;
if (clk > 340000)
maxM = 2;
} else if (cv < 0x40) {
if (clk > 150000)
maxM = 6;
if (clk > 200000)
maxM = 4;
if (clk > 340000)
maxM = 2;
}
}
P = 1 << maxP;
if ((clk * P) < minvco) {
minvco = clk * maxP;
maxvco = minvco * 2;
}
if (clk + clk/200 > maxvco) /* +0.5% */
maxvco = clk + clk/200;
/* NV34 goes maxlog2P->0, NV20 goes 0->maxlog2P */
for (thisP = minP; thisP <= maxP; thisP++) {
P = 1 << thisP;
clkP = clk * P;
if (clkP < minvco)
continue;
if (clkP > maxvco)
return bestclk;
for (M = minM; M <= maxM; M++) {
if (crystal/M < minU)
return bestclk;
if (crystal/M > maxU)
continue;
/* add crystal/2 to round better */
N = (clkP * M + crystal/2) / crystal;
if (N < minN)
continue;
if (N > maxN)
break;
/* more rounding additions */
calcclk = ((N * crystal + P/2) / P + M/2) / M;
delta = abs(calcclk - clk);
/* we do an exhaustive search rather than terminating
* on an optimality condition...
*/
if (delta < bestdelta) {
bestdelta = delta;
bestclk = calcclk;
*pN = N;
*pM = M;
*pP = thisP;
if (delta == 0) /* except this one */
return bestclk;
}
}
}
return bestclk;
}
static int
getMNP_double(struct nvkm_subdev *subdev, struct nvbios_pll *info, int clk,
int *pN1, int *pM1, int *pN2, int *pM2, int *pP)
{
/* Find M, N and P for a two stage PLL
*
* Note that some bioses (NV30+) have lookup tables of precomputed MNP
* values, but we're too lazy to use those atm
*
* "clk" parameter in kHz
* returns calculated clock
*/
int chip_version = subdev->device->bios->version.chip;
int minvco1 = info->vco1.min_freq, maxvco1 = info->vco1.max_freq;
int minvco2 = info->vco2.min_freq, maxvco2 = info->vco2.max_freq;
int minU1 = info->vco1.min_inputfreq, minU2 = info->vco2.min_inputfreq;
int maxU1 = info->vco1.max_inputfreq, maxU2 = info->vco2.max_inputfreq;
int minM1 = info->vco1.min_m, maxM1 = info->vco1.max_m;
int minN1 = info->vco1.min_n, maxN1 = info->vco1.max_n;
int minM2 = info->vco2.min_m, maxM2 = info->vco2.max_m;
int minN2 = info->vco2.min_n, maxN2 = info->vco2.max_n;
Annotation
- Immediate include surface: `pll.h`, `subdev/bios.h`, `subdev/bios/pll.h`.
- Detected declarations: `function files`, `function getMNP_double`, `function nv04_pll_calc`.
- 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.