drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.c
Extension
.c
Size
5081 bytes
Lines
176
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.

Dependency Surface

Detected Declarations

Annotated Snippet

#include "nv50.h"

#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
#include <subdev/bios/disp.h>
#include <subdev/bios/init.h>
#include <subdev/bios/pll.h>
#include <subdev/clk/pll.h>
#include <subdev/vga.h>

int
nv50_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq)
{
	struct nvkm_subdev *subdev = &init->subdev;
	struct nvkm_device *device = subdev->device;
	struct nvkm_bios *bios = device->bios;
	struct nvbios_pll info;
	int N1, M1, N2, M2, P;
	int ret;

	ret = nvbios_pll_parse(bios, type, &info);
	if (ret) {
		nvkm_error(subdev, "failed to retrieve pll data, %d\n", ret);
		return ret;
	}

	ret = nv04_pll_calc(subdev, &info, freq, &N1, &M1, &N2, &M2, &P);
	if (!ret) {
		nvkm_error(subdev, "failed pll calculation\n");
		return -EINVAL;
	}

	switch (info.type) {
	case PLL_VPLL0:
	case PLL_VPLL1:
		nvkm_wr32(device, info.reg + 0, 0x10000611);
		nvkm_mask(device, info.reg + 4, 0x00ff00ff, (M1 << 16) | N1);
		nvkm_mask(device, info.reg + 8, 0x7fff00ff, (P  << 28) |
							    (M2 << 16) | N2);
		break;
	case PLL_MEMORY:
		nvkm_mask(device, info.reg + 0, 0x01ff0000,
					        (P << 22) |
						(info.bias_p << 19) |
						(P << 16));
		nvkm_wr32(device, info.reg + 4, (N1 << 8) | M1);
		break;
	default:
		nvkm_mask(device, info.reg + 0, 0x00070000, (P << 16));
		nvkm_wr32(device, info.reg + 4, (N1 << 8) | M1);
		break;
	}

	return 0;
}

static void
nv50_devinit_disable(struct nvkm_devinit *init)
{
	struct nvkm_device *device = init->subdev.device;
	u32 r001540 = nvkm_rd32(device, 0x001540);

	if (!(r001540 & 0x40000000))
		nvkm_subdev_disable(device, NVKM_ENGINE_MPEG, 0);
}

void
nv50_devinit_preinit(struct nvkm_devinit *base)
{
	struct nvkm_subdev *subdev = &base->subdev;
	struct nvkm_device *device = subdev->device;

	/* our heuristics can't detect whether the board has had its
	 * devinit scripts executed or not if the display engine is
	 * missing, assume it's a secondary gpu which requires post
	 */
	if (!base->post) {
		nvkm_devinit_disable(base);
		if (!device->disp)
			base->post = true;
	}

	/* magic to detect whether or not x86 vbios code has executed
	 * the devinit scripts to initialise the board
	 */
	if (!base->post) {
		if (!nvkm_rdvgac(device, 0, 0x00) &&
		    !nvkm_rdvgac(device, 0, 0x1a)) {
			nvkm_debug(subdev, "adaptor not initialised\n");
			base->post = true;

Annotation

Implementation Notes