diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv50_instmem.c')
| -rw-r--r-- | drivers/gpu/drm/nouveau/nv50_instmem.c | 58 | 
1 files changed, 40 insertions, 18 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c index 94400f777e7..f0dc4e36ef0 100644 --- a/drivers/gpu/drm/nouveau/nv50_instmem.c +++ b/drivers/gpu/drm/nouveau/nv50_instmem.c @@ -76,6 +76,11 @@ nv50_instmem_init(struct drm_device *dev)  	for (i = 0x1700; i <= 0x1710; i += 4)  		priv->save1700[(i-0x1700)/4] = nv_rd32(dev, i); +	if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) +		dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10) << 12; +	else +		dev_priv->vram_sys_base = 0; +  	/* Reserve the last MiB of VRAM, we should probably try to avoid  	 * setting up the below tables over the top of the VBIOS image at  	 * some point. @@ -172,16 +177,28 @@ nv50_instmem_init(struct drm_device *dev)  	 * We map the entire fake channel into the start of the PRAMIN BAR  	 */  	ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pt_size, 0x1000, -							0, &priv->pramin_pt); +				     0, &priv->pramin_pt);  	if (ret)  		return ret; -	for (i = 0, v = c_offset; i < pt_size; i += 8, v += 0x1000) { -		if (v < (c_offset + c_size)) -			BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, v | 1); -		else -			BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, 0x00000009); +	v = c_offset | 1; +	if (dev_priv->vram_sys_base) { +		v += dev_priv->vram_sys_base; +		v |= 0x30; +	} + +	i = 0; +	while (v < dev_priv->vram_sys_base + c_offset + c_size) { +		BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, v); +		BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, 0x00000000); +		v += 0x1000; +		i += 8; +	} + +	while (i < pt_size) { +		BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, 0x00000000);  		BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, 0x00000000); +		i += 8;  	}  	BAR0_WI32(chan->vm_pd, 0x00, priv->pramin_pt->instance | 0x63); @@ -416,7 +433,9 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)  {  	struct drm_nouveau_private *dev_priv = dev->dev_private;  	struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; -	uint32_t pte, pte_end, vram; +	struct nouveau_gpuobj *pramin_pt = priv->pramin_pt->gpuobj; +	uint32_t pte, pte_end; +	uint64_t vram;  	if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound)  		return -EINVAL; @@ -424,20 +443,24 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)  	NV_DEBUG(dev, "st=0x%0llx sz=0x%0llx\n",  		 gpuobj->im_pramin->start, gpuobj->im_pramin->size); -	pte     = (gpuobj->im_pramin->start >> 12) << 3; -	pte_end = ((gpuobj->im_pramin->size >> 12) << 3) + pte; +	pte     = (gpuobj->im_pramin->start >> 12) << 1; +	pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte;  	vram    = gpuobj->im_backing_start;  	NV_DEBUG(dev, "pramin=0x%llx, pte=%d, pte_end=%d\n",  		 gpuobj->im_pramin->start, pte, pte_end);  	NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start); +	vram |= 1; +	if (dev_priv->vram_sys_base) { +		vram += dev_priv->vram_sys_base; +		vram |= 0x30; +	} +  	dev_priv->engine.instmem.prepare_access(dev, true);  	while (pte < pte_end) { -		nv_wo32(dev, priv->pramin_pt->gpuobj, (pte + 0)/4, vram | 1); -		nv_wo32(dev, priv->pramin_pt->gpuobj, (pte + 4)/4, 0x00000000); - -		pte += 8; +		nv_wo32(dev, pramin_pt, pte++, lower_32_bits(vram)); +		nv_wo32(dev, pramin_pt, pte++, upper_32_bits(vram));  		vram += NV50_INSTMEM_PAGE_SIZE;  	}  	dev_priv->engine.instmem.finish_access(dev); @@ -470,14 +493,13 @@ nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)  	if (gpuobj->im_bound == 0)  		return -EINVAL; -	pte     = (gpuobj->im_pramin->start >> 12) << 3; -	pte_end = ((gpuobj->im_pramin->size >> 12) << 3) + pte; +	pte     = (gpuobj->im_pramin->start >> 12) << 1; +	pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte;  	dev_priv->engine.instmem.prepare_access(dev, true);  	while (pte < pte_end) { -		nv_wo32(dev, priv->pramin_pt->gpuobj, (pte + 0)/4, 0x00000009); -		nv_wo32(dev, priv->pramin_pt->gpuobj, (pte + 4)/4, 0x00000000); -		pte += 8; +		nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); +		nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000);  	}  	dev_priv->engine.instmem.finish_access(dev);  |