1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
|
![]() |
index : renesas/drm.git | |
libdrm, cloned from git://anongit.freedesktop.org/mesa/drm | Laurent Pinchart |
summaryrefslogtreecommitdiff |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
|
/*
* Copyright 2005-2006 Stephane Marchesin
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "drmP.h"
#include "drm.h"
#include "nouveau_drv.h"
#include "nouveau_drm.h"
/* returns the number of hw fifos */
int nouveau_fifo_number(drm_device_t* dev)
{
drm_nouveau_private_t *dev_priv=dev->dev_private;
switch(dev_priv->card_type)
{
case NV_03:
return 8;
case NV_04:
case NV_05:
return 16;
default:
return 32;
}
}
/* returns the size of fifo context */
int nouveau_fifo_ctx_size(drm_device_t* dev)
{
drm_nouveau_private_t *dev_priv=dev->dev_private;
if (dev_priv->card_type >= NV_40)
return 128;
else if (dev_priv->card_type >= NV_17)
return 64;
else
return 32;
}
/***********************************
* functions doing the actual work
***********************************/
/* voir nv_xaa.c : NVResetGraphics
* m�moire mapp�e par nv_driver.c : NVMapMem
* voir nv_driver.c : NVPreInit
*/
static int nouveau_fifo_instmem_configure(drm_device_t *dev)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
NV_WRITE(NV03_PFIFO_RAMHT,
(0x03 << 24) /* search 128 */ |
((dev_priv->ramht_bits - 9) << 16) |
(dev_priv->ramht_offset >> 8)
);
NV_WRITE(NV03_PFIFO_RAMRO, dev_priv->ramro_offset>>8);
switch(dev_priv->card_type)
{
case NV_50:
case NV_40:
NV_WRITE(NV40_PFIFO_RAMFC, 0x30002);
break;
case NV_44:
NV_WRITE(NV40_PFIFO_RAMFC, ((nouveau_mem_fb_amount(dev)-512*1024+dev_priv->ramfc_offset)>>16) |
(2 << 16));
break;
case NV_30:
case NV_20:
case NV_17:
NV_WRITE(NV03_PFIFO_RAMFC, (dev_priv->ramfc_offset>>8) |
(1 << 16) /* 64 Bytes entry*/);
/* XXX nvidia blob set bit 18, 21,23 for nv20 & nv30 */
break;
case NV_10:
case NV_04:
case NV_03:
NV_WRITE(NV03_PFIFO_RAMFC, dev_priv->ramfc_offset>>8);
break;
}
return 0;
}
int nouveau_fifo_init(drm_device_t *dev)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
int ret;
NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) &
~NV_PMC_ENABLE_PFIFO);
NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) |
NV_PMC_ENABLE_PFIFO);
NV_WRITE(NV03_PFIFO_CACHES, 0x00000000);
ret = nouveau_fifo_instmem_configure(dev);
if (ret) {
DRM_ERROR("Failed to configure instance memory\n");
return ret;
}
/* FIXME remove all the stuff that's done in nouveau_fifo_alloc */
DRM_DEBUG("Setting defaults for remaining PFIFO regs\n");
/* All channels into PIO mode */
NV_WRITE(NV04_PFIFO_MODE, 0x00000000);
NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000000);
NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000000);
/* Channel 0 active, PIO mode */
NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, 0x00000000);
/* PUT and GET to 0 */
NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT, 0x00000000);
NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET, 0x00000000);
/* No cmdbuf object */
NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE, 0x00000000);
NV_WRITE(NV03_PFIFO_CACHE0_PUSH0, 0x00000000);
NV_WRITE(NV03_PFIFO_CACHE0_PULL0, 0x00000000);
NV_WRITE(NV04_PFIFO_SIZE, 0x0000FFFF);
NV_WRITE(NV04_PFIFO_CACHE1_HASH, 0x0000FFFF);
NV_WRITE(NV04_PFIFO_CACHE0_PULL1, 0x00000001);
NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, 0x00000000);
NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000);
NV_WRITE(NV04_PFIFO_CACHE1_ENGINE, 0x00000000);
NV_WRITE(NV04_PFIFO_CACHE1_DMA_FETCH, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES |
NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 |
#ifdef __BIG_ENDIAN
NV_PFIFO_CACHE1_BIG_ENDIAN |
#endif
0x00000000);
NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001);
NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000001);
NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000001);
NV_WRITE(NV04_PFIFO_CACHE1_PULL1, 0x00000001);
/* FIXME on NV04 */
if (dev_priv->card_type >= NV_10) {
NV_WRITE(NV10_PGRAPH_CTX_USER, 0x0);
NV_WRITE(NV04_PFIFO_DELAY_0, 0xff /* retrycount*/ );
if (dev_priv->card_type >= NV_40)
NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x00002001);
else
NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10110000);
} else {
NV_WRITE(NV04_PGRAPH_CTX_USER, 0x0);
NV_WRITE(NV04_PFIFO_DELAY_0, 0xff /* retrycount*/ );
NV_WRITE(NV04_PGRAPH_CTX_CONTROL, 0x10110000);
}
NV_WRITE(NV04_PFIFO_DMA_TIMESLICE, 0x001fffff);
NV_WRITE(NV03_PFIFO_CACHES, 0x00000001);
return 0;
}
static int
nouveau_fifo_cmdbuf_alloc(struct drm_device *dev, int channel)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
struct nouveau_config *config = &dev_priv->config;
struct mem_block *cb;
struct nouveau_object *cb_dma = NULL;
int cb_min_size = max(NV03_FIFO_SIZE,PAGE_SIZE);
/* Defaults for unconfigured values */
if (!config->cmdbuf.location)
config->cmdbuf.location = NOUVEAU_MEM_FB;
if (!config->cmdbuf.size || config->cmdbuf.size < cb_min_size)
config->cmdbuf.size = cb_min_size;
cb = nouveau_mem_alloc(dev, 0, config->cmdbuf.size,
config->cmdbuf.location | NOUVEAU_MEM_MAPPED,
(DRMFILE)-2);
if (!cb) {
DRM_ERROR("Couldn't allocate DMA command buffer.\n");
return DRM_ERR(ENOMEM);
}
if (cb->flags & NOUVEAU_MEM_AGP) {
cb_dma = nouveau_object_dma_create(dev, channel,
NV_CLASS_DMA_IN_MEMORY,
cb->start - dev_priv->agp_phys,
cb->size,
NV_DMA_ACCESS_RO, NV_DMA_TARGET_AGP);
} else if (dev_priv->card_type != NV_04) {
cb_dma = nouveau_object_dma_create(dev, channel,
NV_CLASS_DMA_IN_MEMORY,
cb->start - drm_get_resource_start(dev, 1),
cb->size,
NV_DMA_ACCESS_RO, NV_DMA_TARGET_VIDMEM);
} else {
/* NV04 cmdbuf hack, from original ddx.. not sure of it's
* exact reason for existing :) PCI access to cmdbuf in
* VRAM.
*/
cb_dma = nouveau_object_dma_create(dev, channel,
NV_CLASS_DMA_IN_MEMORY,
cb->start, cb->size,
NV_DMA_ACCESS_RO, NV_DMA_TARGET_PCI);
}
if (!cb_dma) {
nouveau_mem_free(dev, cb);
DRM_ERROR("Failed to alloc DMA object for command buffer\n");
return DRM_ERR(ENOMEM);
}
dev_priv->fifos[channel].cmdbuf_mem = cb;
dev_priv->fifos[channel].cmdbuf_obj = cb_dma;
return 0;
}
#define RAMFC_WR(offset, val) NV_WRITE(fifoctx + NV04_RAMFC_##offset, (val))
static void nouveau_nv04_context_init(drm_device_t *dev, int channel)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
struct nouveau_object *cb_obj;
uint32_t fifoctx, ctx_size = 32;
int i;
cb_obj = dev_priv->fifos[channel].cmdbuf_obj;
fifoctx=NV_RAMIN+dev_priv->ramfc_offset+channel*ctx_size;
// clear the fifo context
for(i=0;i<ctx_size/4;i++)
NV_WRITE(fifoctx+4*i,0x0);
RAMFC_WR(DMA_INSTANCE , nouveau_chip_instance_get(dev, cb_obj->instance));
RAMFC_WR(DMA_FETCH, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES |
NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 |
#ifdef __BIG_ENDIAN
NV_PFIFO_CACHE1_BIG_ENDIAN |
#endif
0x00000000);
}
#undef RAMFC_WR
#define RAMFC_WR(offset, val) NV_WRITE(fifoctx + NV10_RAMFC_##offset, (val))
static void nouveau_nv10_context_init(drm_device_t *dev, int channel)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
struct nouveau_object *cb_obj;
uint32_t fifoctx;
int ctx_size = nouveau_fifo_ctx_size(dev);
int i;
cb_obj = dev_priv->fifos[channel].cmdbuf_obj;
fifoctx = NV_RAMIN + dev_priv->ramfc_offset + channel*ctx_size;
for (i=0;i<ctx_size;i+=4)
NV_WRITE(fifoctx + i, 0);
/* Fill entries that are seen filled in dumps of nvidia driver just
* after channel's is put into DMA mode
*/
RAMFC_WR(DMA_INSTANCE , nouveau_chip_instance_get(dev,
cb_obj->instance));
RAMFC_WR(DMA_FETCH, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES |
NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 |
#ifdef __BIG_ENDIAN
NV_PFIFO_CACHE1_BIG_ENDIAN |