Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7ad2d31c authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau: move vram detection funcs to chipset-specific fb code



Also, display detected memory type in logs - though, we don't even try to
detect this yet.

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 83465324
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -57,6 +57,10 @@ MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM");
int nouveau_vram_notify = 0;
module_param_named(vram_notify, nouveau_vram_notify, int, 0400);

MODULE_PARM_DESC(vram_type, "Override detected VRAM type");
char *nouveau_vram_type;
module_param_named(vram_type, nouveau_vram_type, charp, 0400);

MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)");
int nouveau_duallink = 1;
module_param_named(duallink, nouveau_duallink, int, 0400);
+17 −1
Original line number Diff line number Diff line
@@ -772,6 +772,19 @@ struct drm_nouveau_private {
	} tile;

	/* VRAM/fb configuration */
	enum {
		NV_MEM_TYPE_UNKNOWN = 0,
		NV_MEM_TYPE_STOLEN,
		NV_MEM_TYPE_SGRAM,
		NV_MEM_TYPE_SDRAM,
		NV_MEM_TYPE_DDR1,
		NV_MEM_TYPE_DDR2,
		NV_MEM_TYPE_DDR3,
		NV_MEM_TYPE_GDDR2,
		NV_MEM_TYPE_GDDR3,
		NV_MEM_TYPE_GDDR4,
		NV_MEM_TYPE_GDDR5
	} vram_type;
	uint64_t vram_size;
	uint64_t vram_sys_base;

@@ -846,6 +859,7 @@ extern int nouveau_uscript_lvds;
extern int nouveau_uscript_tmds;
extern int nouveau_vram_pushbuf;
extern int nouveau_vram_notify;
extern char *nouveau_vram_type;
extern int nouveau_fbpercrtc;
extern int nouveau_tv_disable;
extern char *nouveau_tv_norm;
@@ -894,7 +908,6 @@ extern void nouveau_mem_gart_fini(struct drm_device *);
extern int  nouveau_mem_init_agp(struct drm_device *);
extern int  nouveau_mem_reset_agp(struct drm_device *);
extern void nouveau_mem_close(struct drm_device *);
extern int  nouveau_mem_detect(struct drm_device *);
extern bool nouveau_mem_flags_valid(struct drm_device *, u32 tile_flags);
extern struct nouveau_tile_reg *nv10_mem_set_tiling(
	struct drm_device *dev, uint32_t addr, uint32_t size,
@@ -1126,10 +1139,13 @@ void nouveau_dp_tu_update(struct drm_device *, int, int, u32, u32);
u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_entry *, u8 **);

/* nv04_fb.c */
extern int  nv04_fb_vram_init(struct drm_device *);
extern int  nv04_fb_init(struct drm_device *);
extern void nv04_fb_takedown(struct drm_device *);

/* nv10_fb.c */
extern int  nv10_fb_vram_init(struct drm_device *dev);
extern int  nv1a_fb_vram_init(struct drm_device *dev);
extern int  nv10_fb_init(struct drm_device *);
extern void nv10_fb_takedown(struct drm_device *);
extern void nv10_fb_init_tile_region(struct drm_device *dev, int i,
+33 −70
Original line number Diff line number Diff line
@@ -192,75 +192,6 @@ nouveau_mem_gart_fini(struct drm_device *dev)
	}
}

static uint32_t
nouveau_mem_detect_nv04(struct drm_device *dev)
{
	uint32_t boot0 = nv_rd32(dev, NV04_PFB_BOOT_0);

	if (boot0 & 0x00000100)
		return (((boot0 >> 12) & 0xf) * 2 + 2) * 1024 * 1024;

	switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) {
	case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB:
		return 32 * 1024 * 1024;
	case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB:
		return 16 * 1024 * 1024;
	case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB:
		return 8 * 1024 * 1024;
	case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB:
		return 4 * 1024 * 1024;
	}

	return 0;
}

static uint32_t
nouveau_mem_detect_nforce(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct pci_dev *bridge;
	uint32_t mem;

	bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1));
	if (!bridge) {
		NV_ERROR(dev, "no bridge device\n");
		return 0;
	}

	if (dev_priv->flags & NV_NFORCE) {
		pci_read_config_dword(bridge, 0x7C, &mem);
		return (uint64_t)(((mem >> 6) & 31) + 1)*1024*1024;
	} else
	if (dev_priv->flags & NV_NFORCE2) {
		pci_read_config_dword(bridge, 0x84, &mem);
		return (uint64_t)(((mem >> 4) & 127) + 1)*1024*1024;
	}

	NV_ERROR(dev, "impossible!\n");
	return 0;
}

int
nouveau_mem_detect(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;

	if (dev_priv->card_type == NV_04) {
		dev_priv->vram_size = nouveau_mem_detect_nv04(dev);
	} else
	if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) {
		dev_priv->vram_size = nouveau_mem_detect_nforce(dev);
	} else
	if (dev_priv->card_type < NV_50) {
		dev_priv->vram_size  = nv_rd32(dev, NV04_PFB_FIFO_DATA);
		dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK;
	}

	if (dev_priv->vram_size)
		return 0;
	return -ENOMEM;
}

bool
nouveau_mem_flags_valid(struct drm_device *dev, u32 tile_flags)
{
@@ -385,11 +316,29 @@ nouveau_mem_init_agp(struct drm_device *dev)
	return 0;
}

static const struct vram_types {
	int value;
	const char *name;
} vram_type_map[] = {
	{ NV_MEM_TYPE_STOLEN , "stolen system memory" },
	{ NV_MEM_TYPE_SGRAM  , "SGRAM" },
	{ NV_MEM_TYPE_SDRAM  , "SDRAM" },
	{ NV_MEM_TYPE_DDR1   , "DDR1" },
	{ NV_MEM_TYPE_DDR2   , "DDR2" },
	{ NV_MEM_TYPE_DDR3   , "DDR3" },
	{ NV_MEM_TYPE_GDDR2  , "GDDR2" },
	{ NV_MEM_TYPE_GDDR3  , "GDDR3" },
	{ NV_MEM_TYPE_GDDR4  , "GDDR4" },
	{ NV_MEM_TYPE_GDDR5  , "GDDR5" },
	{ NV_MEM_TYPE_UNKNOWN, "unknown type" }
};

int
nouveau_mem_vram_init(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
	const struct vram_types *vram_type;
	int ret, dma_bits;

	dma_bits = 32;
@@ -427,7 +376,21 @@ nouveau_mem_vram_init(struct drm_device *dev)
		return ret;
	}

	NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
	vram_type = vram_type_map;
	while (vram_type->value != NV_MEM_TYPE_UNKNOWN) {
		if (nouveau_vram_type) {
			if (!strcasecmp(nouveau_vram_type, vram_type->name))
				break;
			dev_priv->vram_type = vram_type->value;
		} else {
			if (vram_type->value == dev_priv->vram_type)
				break;
		}
		vram_type++;
	}

	NV_INFO(dev, "Detected %dMiB VRAM (%s)\n",
		(int)(dev_priv->vram_size >> 20), vram_type->name);
	if (dev_priv->vram_sys_base) {
		NV_INFO(dev, "Stolen system memory at: 0x%010llx\n",
			dev_priv->vram_sys_base);
+9 −5
Original line number Diff line number Diff line
@@ -87,7 +87,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
		engine->pm.clocks_get		= nv04_pm_clocks_get;
		engine->pm.clocks_pre		= nv04_pm_clocks_pre;
		engine->pm.clocks_set		= nv04_pm_clocks_set;
		engine->vram.init		= nouveau_mem_detect;
		engine->vram.init		= nv04_fb_vram_init;
		engine->vram.takedown		= nouveau_stub_takedown;
		engine->vram.flags_valid	= nouveau_mem_flags_valid;
		break;
@@ -134,7 +134,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
		engine->pm.clocks_get		= nv04_pm_clocks_get;
		engine->pm.clocks_pre		= nv04_pm_clocks_pre;
		engine->pm.clocks_set		= nv04_pm_clocks_set;
		engine->vram.init		= nouveau_mem_detect;
		if (dev_priv->chipset == 0x1a ||
		    dev_priv->chipset == 0x1f)
			engine->vram.init	= nv1a_fb_vram_init;
		else
			engine->vram.init	= nv10_fb_vram_init;
		engine->vram.takedown		= nouveau_stub_takedown;
		engine->vram.flags_valid	= nouveau_mem_flags_valid;
		break;
@@ -181,7 +185,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
		engine->pm.clocks_get		= nv04_pm_clocks_get;
		engine->pm.clocks_pre		= nv04_pm_clocks_pre;
		engine->pm.clocks_set		= nv04_pm_clocks_set;
		engine->vram.init		= nouveau_mem_detect;
		engine->vram.init		= nv10_fb_vram_init;
		engine->vram.takedown		= nouveau_stub_takedown;
		engine->vram.flags_valid	= nouveau_mem_flags_valid;
		break;
@@ -230,7 +234,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
		engine->pm.clocks_set		= nv04_pm_clocks_set;
		engine->pm.voltage_get		= nouveau_voltage_gpio_get;
		engine->pm.voltage_set		= nouveau_voltage_gpio_set;
		engine->vram.init		= nouveau_mem_detect;
		engine->vram.init		= nv10_fb_vram_init;
		engine->vram.takedown		= nouveau_stub_takedown;
		engine->vram.flags_valid	= nouveau_mem_flags_valid;
		break;
@@ -286,7 +290,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
		engine->pm.temp_get		= nv40_temp_get;
		engine->pm.pwm_get		= nv40_pm_pwm_get;
		engine->pm.pwm_set		= nv40_pm_pwm_set;
		engine->vram.init		= nouveau_mem_detect;
		engine->vram.init		= nv10_fb_vram_init;
		engine->vram.takedown		= nouveau_stub_takedown;
		engine->vram.flags_valid	= nouveau_mem_flags_valid;
		break;
+29 −0
Original line number Diff line number Diff line
@@ -3,6 +3,35 @@
#include "nouveau_drv.h"
#include "nouveau_drm.h"

int
nv04_fb_vram_init(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	u32 boot0 = nv_rd32(dev, NV04_PFB_BOOT_0);

	if (boot0 & 0x00000100) {
		dev_priv->vram_size  = ((boot0 >> 12) & 0xf) * 2 + 2;
		dev_priv->vram_size *= 1024 * 1024;
	} else {
		switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) {
		case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB:
			dev_priv->vram_size = 32 * 1024 * 1024;
			break;
		case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB:
			dev_priv->vram_size = 16 * 1024 * 1024;
			break;
		case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB:
			dev_priv->vram_size = 8 * 1024 * 1024;
			break;
		case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB:
			dev_priv->vram_size = 4 * 1024 * 1024;
			break;
		}
	}

	return 0;
}

int
nv04_fb_init(struct drm_device *dev)
{
Loading