diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv50_display.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 92 |
1 files changed, 56 insertions, 36 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 612fa6d6a0c..55c9663ef2b 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -30,8 +30,22 @@ #include "nouveau_connector.h" #include "nouveau_fb.h" #include "nouveau_fbcon.h" +#include "nouveau_ramht.h" #include "drm_crtc_helper.h" +static inline int +nv50_sor_nr(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->chipset < 0x90 || + dev_priv->chipset == 0x92 || + dev_priv->chipset == 0xa0) + return 2; + + return 4; +} + static void nv50_evo_channel_del(struct nouveau_channel **pchan) { @@ -42,6 +56,7 @@ nv50_evo_channel_del(struct nouveau_channel **pchan) *pchan = NULL; nouveau_gpuobj_channel_takedown(chan); + nouveau_bo_unmap(chan->pushbuf_bo); nouveau_bo_ref(NULL, &chan->pushbuf_bo); if (chan->user) @@ -65,23 +80,23 @@ nv50_evo_dmaobj_new(struct nouveau_channel *evo, uint32_t class, uint32_t name, return ret; obj->engine = NVOBJ_ENGINE_DISPLAY; - ret = nouveau_gpuobj_ref_add(dev, evo, name, obj, NULL); - if (ret) { - nouveau_gpuobj_del(dev, &obj); - return ret; - } - - nv_wo32(dev, obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); - nv_wo32(dev, obj, 1, limit); - nv_wo32(dev, obj, 2, offset); - nv_wo32(dev, obj, 3, 0x00000000); - nv_wo32(dev, obj, 4, 0x00000000); + nv_wo32(obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); + nv_wo32(obj, 4, limit); + nv_wo32(obj, 8, offset); + nv_wo32(obj, 12, 0x00000000); + nv_wo32(obj, 16, 0x00000000); if (dev_priv->card_type < NV_C0) - nv_wo32(dev, obj, 5, 0x00010000); + nv_wo32(obj, 20, 0x00010000); else - nv_wo32(dev, obj, 5, 0x00020000); + nv_wo32(obj, 20, 0x00020000); dev_priv->engine.instmem.flush(dev); + ret = nouveau_ramht_insert(evo, name, obj); + nouveau_gpuobj_ref(NULL, &obj); + if (ret) { + return ret; + } + return 0; } @@ -89,6 +104,7 @@ static int nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *ramht = NULL; struct nouveau_channel *chan; int ret; @@ -102,32 +118,35 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) chan->user_get = 4; chan->user_put = 0; - INIT_LIST_HEAD(&chan->ramht_refs); - - ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 32768, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin); + ret = nouveau_gpuobj_new(dev, NULL, 32768, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin); if (ret) { NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); nv50_evo_channel_del(pchan); return ret; } - ret = drm_mm_init(&chan->ramin_heap, - chan->ramin->gpuobj->im_pramin->start, 32768); + ret = drm_mm_init(&chan->ramin_heap, 0, 32768); if (ret) { NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); nv50_evo_channel_del(pchan); return ret; } - ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 4096, 16, - 0, &chan->ramht); + ret = nouveau_gpuobj_new(dev, chan, 4096, 16, 0, &ramht); if (ret) { NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); nv50_evo_channel_del(pchan); return ret; } + ret = nouveau_ramht_new(dev, ramht, &chan->ramht); + nouveau_gpuobj_ref(NULL, &ramht); + if (ret) { + nv50_evo_channel_del(pchan); + return ret; + } + if (dev_priv->chipset != 0x50) { ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoFB16, 0x70, 0x19, 0, 0xffffffff); @@ -227,11 +246,11 @@ nv50_display_init(struct drm_device *dev) nv_wr32(dev, 0x006101d0 + (i * 0x04), val); } /* SOR */ - for (i = 0; i < 4; i++) { + for (i = 0; i < nv50_sor_nr(dev); i++) { val = nv_rd32(dev, 0x0061c000 + (i * 0x800)); nv_wr32(dev, 0x006101e0 + (i * 0x04), val); } - /* Something not yet in use, tv-out maybe. */ + /* EXT */ for (i = 0; i < 3; i++) { val = nv_rd32(dev, 0x0061e000 + (i * 0x800)); nv_wr32(dev, 0x006101f0 + (i * 0x04), val); @@ -260,7 +279,7 @@ nv50_display_init(struct drm_device *dev) if (nv_rd32(dev, NV50_PDISPLAY_INTR_1) & 0x100) { nv_wr32(dev, NV50_PDISPLAY_INTR_1, 0x100); nv_wr32(dev, 0x006194e8, nv_rd32(dev, 0x006194e8) & ~1); - if (!nv_wait(0x006194e8, 2, 0)) { + if (!nv_wait(dev, 0x006194e8, 2, 0)) { NV_ERROR(dev, "timeout: (0x6194e8 & 2) != 0\n"); NV_ERROR(dev, "0x6194e8 = 0x%08x\n", nv_rd32(dev, 0x6194e8)); @@ -291,7 +310,8 @@ nv50_display_init(struct drm_device *dev) nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, NV50_PDISPLAY_CTRL_STATE_ENABLE); nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x1000b03); - if (!nv_wait(NV50_PDISPLAY_CHANNEL_STAT(0), 0x40000000, 0x40000000)) { + if (!nv_wait(dev, NV50_PDISPLAY_CHANNEL_STAT(0), + 0x40000000, 0x40000000)) { NV_ERROR(dev, "timeout: (0x610200 & 0x40000000) == 0x40000000\n"); NV_ERROR(dev, "0x610200 = 0x%08x\n", nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))); @@ -300,7 +320,7 @@ nv50_display_init(struct drm_device *dev) for (i = 0; i < 2; i++) { nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0x2000); - if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), + if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", @@ -310,7 +330,7 @@ nv50_display_init(struct drm_device *dev) nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_ON); - if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), + if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE)) { NV_ERROR(dev, "timeout: " @@ -321,16 +341,16 @@ nv50_display_init(struct drm_device *dev) } } - nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->instance >> 8) | 9); + nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9); /* initialise fifo */ nv_wr32(dev, NV50_PDISPLAY_CHANNEL_DMA_CB(0), - ((evo->pushbuf_bo->bo.mem.mm_node->start << PAGE_SHIFT) >> 8) | + ((evo->pushbuf_bo->bo.mem.start << PAGE_SHIFT) >> 8) | NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_VRAM | NV50_PDISPLAY_CHANNEL_DMA_CB_VALID); nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK2(0), 0x00010000); nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK3(0), 0x00000002); - if (!nv_wait(0x610200, 0x80000000, 0x00000000)) { + if (!nv_wait(dev, 0x610200, 0x80000000, 0x00000000)) { NV_ERROR(dev, "timeout: (0x610200 & 0x80000000) == 0\n"); NV_ERROR(dev, "0x610200 = 0x%08x\n", nv_rd32(dev, 0x610200)); return -EBUSY; @@ -370,7 +390,7 @@ nv50_display_init(struct drm_device *dev) BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK082C), 1); OUT_RING(evo, 0); FIRE_RING(evo); - if (!nv_wait(0x640004, 0xffffffff, evo->dma.put << 2)) + if (!nv_wait(dev, 0x640004, 0xffffffff, evo->dma.put << 2)) NV_ERROR(dev, "evo pushbuf stalled\n"); /* enable clock change interrupts. */ @@ -424,7 +444,7 @@ static int nv50_display_disable(struct drm_device *dev) continue; nv_wr32(dev, NV50_PDISPLAY_INTR_1, mask); - if (!nv_wait(NV50_PDISPLAY_INTR_1, mask, mask)) { + if (!nv_wait(dev, NV50_PDISPLAY_INTR_1, mask, mask)) { NV_ERROR(dev, "timeout: (0x610024 & 0x%08x) == " "0x%08x\n", mask, mask); NV_ERROR(dev, "0x610024 = 0x%08x\n", @@ -434,14 +454,14 @@ static int nv50_display_disable(struct drm_device *dev) nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0); nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, 0); - if (!nv_wait(NV50_PDISPLAY_CHANNEL_STAT(0), 0x1e0000, 0)) { + if (!nv_wait(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x1e0000, 0)) { NV_ERROR(dev, "timeout: (0x610200 & 0x1e0000) == 0\n"); NV_ERROR(dev, "0x610200 = 0x%08x\n", nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))); } for (i = 0; i < 3; i++) { - if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_STATE(i), + if (!nv_wait(dev, NV50_PDISPLAY_SOR_DPMS_STATE(i), NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) { NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", i); NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", i, @@ -710,7 +730,7 @@ nv50_display_unk10_handler(struct drm_device *dev) or = i; } - for (i = 0; type == OUTPUT_ANY && i < 4; i++) { + for (i = 0; type == OUTPUT_ANY && i < nv50_sor_nr(dev); i++) { if (dev_priv->chipset < 0x90 || dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0) @@ -841,7 +861,7 @@ nv50_display_unk20_handler(struct drm_device *dev) or = i; } - for (i = 0; type == OUTPUT_ANY && i < 4; i++) { + for (i = 0; type == OUTPUT_ANY && i < nv50_sor_nr(dev); i++) { if (dev_priv->chipset < 0x90 || dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0) |