diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2012-11-16 05:54:31 +0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2012-11-29 03:57:58 +0400 |
commit | 4f6029da58ba9204c98e33f4f3737fe085c87a6f (patch) | |
tree | 90e25888ee8438f5d0ab56e0ae718d959a3e9e6b /drivers/gpu/drm/nouveau/nv50_display.c | |
parent | f9887d091149406de5c8b388f7e0bb6932dd621b (diff) | |
download | linux-4f6029da58ba9204c98e33f4f3737fe085c87a6f.tar.xz |
drm/nv50-nvc0: switch to common disp impl, removing previous version
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv50_display.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 462 |
1 files changed, 0 insertions, 462 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c deleted file mode 100644 index 2ba057661d53..000000000000 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ /dev/null @@ -1,462 +0,0 @@ -/* - * Copyright (C) 2008 Maarten Maathuis. - * 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 THE COPYRIGHT OWNER(S) 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 "nouveau_drm.h" -#include "nouveau_dma.h" - -#include "nv50_display.h" -#include "nouveau_crtc.h" -#include "nouveau_encoder.h" -#include "nouveau_connector.h" -#include "nouveau_fbcon.h" -#include <drm/drm_crtc_helper.h> -#include "nouveau_fence.h" - -#include <core/gpuobj.h> -#include <core/class.h> - -#include <subdev/timer.h> - -static inline int -nv50_sor_nr(struct drm_device *dev) -{ - struct nouveau_device *device = nouveau_dev(dev); - - if (device->chipset < 0x90 || - device->chipset == 0x92 || - device->chipset == 0xa0) - return 2; - - return 4; -} - -u32 -nv50_display_active_crtcs(struct drm_device *dev) -{ - struct nouveau_device *device = nouveau_dev(dev); - u32 mask = 0; - int i; - - if (device->chipset < 0x90 || - device->chipset == 0x92 || - device->chipset == 0xa0) { - for (i = 0; i < 2; i++) - mask |= nv_rd32(device, NV50_PDISPLAY_SOR_MODE_CTRL_C(i)); - } else { - for (i = 0; i < 4; i++) - mask |= nv_rd32(device, NV90_PDISPLAY_SOR_MODE_CTRL_C(i)); - } - - for (i = 0; i < 3; i++) - mask |= nv_rd32(device, NV50_PDISPLAY_DAC_MODE_CTRL_C(i)); - - return mask & 3; -} - -int -nv50_display_early_init(struct drm_device *dev) -{ - return 0; -} - -void -nv50_display_late_takedown(struct drm_device *dev) -{ -} - -int -nv50_display_sync(struct drm_device *dev) -{ - struct nv50_display *disp = nv50_display(dev); - struct nouveau_channel *evo = disp->master; - int ret; - - ret = RING_SPACE(evo, 6); - if (ret == 0) { - BEGIN_NV04(evo, 0, 0x0084, 1); - OUT_RING (evo, 0x80000000); - BEGIN_NV04(evo, 0, 0x0080, 1); - OUT_RING (evo, 0); - BEGIN_NV04(evo, 0, 0x0084, 1); - OUT_RING (evo, 0x00000000); - - nv_wo32(disp->ramin, 0x2000, 0x00000000); - FIRE_RING (evo); - - if (nv_wait_ne(disp->ramin, 0x2000, 0xffffffff, 0x00000000)) - return 0; - } - - return 0; -} - -int -nv50_display_init(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_device *device = nouveau_dev(dev); - struct nouveau_channel *evo; - int ret, i; - - for (i = 0; i < 3; i++) { - nv_wr32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(i), 0x00550000 | - NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); - nv_wr32(device, NV50_PDISPLAY_DAC_CLK_CTRL1(i), 0x00000001); - } - - for (i = 0; i < 2; i++) { - nv_wr32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0x2000); - if (!nv_wait(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), - NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { - NV_ERROR(drm, "timeout: CURSOR_CTRL2_STATUS == 0\n"); - NV_ERROR(drm, "CURSOR_CTRL2 = 0x%08x\n", - nv_rd32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); - return -EBUSY; - } - - nv_wr32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), - NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_ON); - if (!nv_wait(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), - NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, - NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE)) { - NV_ERROR(drm, "timeout: " - "CURSOR_CTRL2_STATUS_ACTIVE(%d)\n", i); - NV_ERROR(drm, "CURSOR_CTRL2(%d) = 0x%08x\n", i, - nv_rd32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); - return -EBUSY; - } - } - - ret = nv50_evo_init(dev); - if (ret) - return ret; - evo = nv50_display(dev)->master; - - ret = RING_SPACE(evo, 3); - if (ret) - return ret; - BEGIN_NV04(evo, 0, NV50_EVO_UNK84, 2); - OUT_RING (evo, NV50_EVO_UNK84_NOTIFY_DISABLED); - OUT_RING (evo, NvEvoSync); - - return nv50_display_sync(dev); -} - -void -nv50_display_fini(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_device *device = nouveau_dev(dev); - struct nv50_display *disp = nv50_display(dev); - struct nouveau_channel *evo = disp->master; - struct drm_crtc *drm_crtc; - int ret, i; - - list_for_each_entry(drm_crtc, &dev->mode_config.crtc_list, head) { - struct nouveau_crtc *crtc = nouveau_crtc(drm_crtc); - - nv50_crtc_blank(crtc, true); - } - - ret = RING_SPACE(evo, 2); - if (ret == 0) { - BEGIN_NV04(evo, 0, NV50_EVO_UPDATE, 1); - OUT_RING(evo, 0); - } - FIRE_RING(evo); - - /* Almost like ack'ing a vblank interrupt, maybe in the spirit of - * cleaning up? - */ - list_for_each_entry(drm_crtc, &dev->mode_config.crtc_list, head) { - struct nouveau_crtc *crtc = nouveau_crtc(drm_crtc); - uint32_t mask = NV50_PDISPLAY_INTR_1_VBLANK_CRTC_(crtc->index); - - if (!crtc->base.enabled) - continue; - - nv_wr32(device, NV50_PDISPLAY_INTR_1, mask); - if (!nv_wait(device, NV50_PDISPLAY_INTR_1, mask, mask)) { - NV_ERROR(drm, "timeout: (0x610024 & 0x%08x) == " - "0x%08x\n", mask, mask); - NV_ERROR(drm, "0x610024 = 0x%08x\n", - nv_rd32(device, NV50_PDISPLAY_INTR_1)); - } - } - - for (i = 0; i < 2; i++) { - nv_wr32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0); - if (!nv_wait(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), - NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { - NV_ERROR(drm, "timeout: CURSOR_CTRL2_STATUS == 0\n"); - NV_ERROR(drm, "CURSOR_CTRL2 = 0x%08x\n", - nv_rd32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); - } - } - - nv50_evo_fini(dev); - - for (i = 0; i < 3; i++) { - if (!nv_wait(device, NV50_PDISPLAY_SOR_DPMS_STATE(i), - NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) { - NV_ERROR(drm, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", i); - NV_ERROR(drm, "SOR_DPMS_STATE(%d) = 0x%08x\n", i, - nv_rd32(device, NV50_PDISPLAY_SOR_DPMS_STATE(i))); - } - } -} - -int -nv50_display_create(struct drm_device *dev) -{ - static const u16 oclass[] = { - NVA3_DISP_CLASS, - NV94_DISP_CLASS, - NVA0_DISP_CLASS, - NV84_DISP_CLASS, - NV50_DISP_CLASS, - }; - struct nouveau_drm *drm = nouveau_drm(dev); - struct dcb_table *dcb = &drm->vbios.dcb; - struct drm_connector *connector, *ct; - struct nv50_display *priv; - int ret, i; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - nouveau_display(dev)->priv = priv; - nouveau_display(dev)->dtor = nv50_display_destroy; - nouveau_display(dev)->init = nv50_display_init; - nouveau_display(dev)->fini = nv50_display_fini; - - /* attempt to allocate a supported evo display class */ - ret = -ENODEV; - for (i = 0; ret && i < ARRAY_SIZE(oclass); i++) { - ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE, - 0xd1500000, oclass[i], NULL, 0, - &priv->core); - } - - if (ret) - return ret; - - /* Create CRTC objects */ - for (i = 0; i < 2; i++) { - ret = nv50_crtc_create(dev, i); - if (ret) - return ret; - } - - /* We setup the encoders from the BIOS table */ - for (i = 0 ; i < dcb->entries; i++) { - struct dcb_output *entry = &dcb->entry[i]; - - if (entry->location != DCB_LOC_ON_CHIP) { - NV_WARN(drm, "Off-chip encoder %d/%d unsupported\n", - entry->type, ffs(entry->or) - 1); - continue; - } - - connector = nouveau_connector_create(dev, entry->connector); - if (IS_ERR(connector)) - continue; - - switch (entry->type) { - case DCB_OUTPUT_TMDS: - case DCB_OUTPUT_LVDS: - case DCB_OUTPUT_DP: - nv50_sor_create(connector, entry); - break; - case DCB_OUTPUT_ANALOG: - nv50_dac_create(connector, entry); - break; - default: - NV_WARN(drm, "DCB encoder %d unknown\n", entry->type); - continue; - } - } - - list_for_each_entry_safe(connector, ct, - &dev->mode_config.connector_list, head) { - if (!connector->encoder_ids[0]) { - NV_WARN(drm, "%s has no encoders, removing\n", - drm_get_connector_name(connector)); - connector->funcs->destroy(connector); - } - } - - ret = nv50_evo_create(dev); - if (ret) { - nv50_display_destroy(dev); - return ret; - } - - return 0; -} - -void -nv50_display_destroy(struct drm_device *dev) -{ - struct nv50_display *disp = nv50_display(dev); - - nv50_evo_destroy(dev); - kfree(disp); -} - -struct nouveau_bo * -nv50_display_crtc_sema(struct drm_device *dev, int crtc) -{ - return nv50_display(dev)->crtc[crtc].sem.bo; -} - -void -nv50_display_flip_stop(struct drm_crtc *crtc) -{ - struct nv50_display *disp = nv50_display(crtc->dev); - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - struct nv50_display_crtc *dispc = &disp->crtc[nv_crtc->index]; - struct nouveau_channel *evo = dispc->sync; - int ret; - - ret = RING_SPACE(evo, 8); - if (ret) { - WARN_ON(1); - return; - } - - BEGIN_NV04(evo, 0, 0x0084, 1); - OUT_RING (evo, 0x00000000); - BEGIN_NV04(evo, 0, 0x0094, 1); - OUT_RING (evo, 0x00000000); - BEGIN_NV04(evo, 0, 0x00c0, 1); - OUT_RING (evo, 0x00000000); - BEGIN_NV04(evo, 0, 0x0080, 1); - OUT_RING (evo, 0x00000000); - FIRE_RING (evo); -} - -int -nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, - struct nouveau_channel *chan) -{ - struct nouveau_drm *drm = nouveau_drm(crtc->dev); - struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); - struct nv50_display *disp = nv50_display(crtc->dev); - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - struct nv50_display_crtc *dispc = &disp->crtc[nv_crtc->index]; - struct nouveau_channel *evo = dispc->sync; - int ret; - - ret = RING_SPACE(evo, chan ? 25 : 27); - if (unlikely(ret)) - return ret; - - /* synchronise with the rendering channel, if necessary */ - if (likely(chan)) { - ret = RING_SPACE(chan, 10); - if (ret) { - WIND_RING(evo); - return ret; - } - - if (nv_device(drm->device)->chipset < 0xc0) { - BEGIN_NV04(chan, 0, 0x0060, 2); - OUT_RING (chan, NvEvoSema0 + nv_crtc->index); - OUT_RING (chan, dispc->sem.offset); - BEGIN_NV04(chan, 0, 0x006c, 1); - OUT_RING (chan, 0xf00d0000 | dispc->sem.value); - BEGIN_NV04(chan, 0, 0x0064, 2); - OUT_RING (chan, dispc->sem.offset ^ 0x10); - OUT_RING (chan, 0x74b1e000); - BEGIN_NV04(chan, 0, 0x0060, 1); - if (nv_device(drm->device)->chipset < 0x84) - OUT_RING (chan, NvSema); - else - OUT_RING (chan, chan->vram); - } else { - u64 offset = nvc0_fence_crtc(chan, nv_crtc->index); - offset += dispc->sem.offset; - BEGIN_NVC0(chan, 0, 0x0010, 4); - OUT_RING (chan, upper_32_bits(offset)); - OUT_RING (chan, lower_32_bits(offset)); - OUT_RING (chan, 0xf00d0000 | dispc->sem.value); - OUT_RING (chan, 0x1002); - BEGIN_NVC0(chan, 0, 0x0010, 4); - OUT_RING (chan, upper_32_bits(offset)); - OUT_RING (chan, lower_32_bits(offset ^ 0x10)); - OUT_RING (chan, 0x74b1e000); - OUT_RING (chan, 0x1001); - } - FIRE_RING (chan); - } else { - nouveau_bo_wr32(dispc->sem.bo, dispc->sem.offset / 4, - 0xf00d0000 | dispc->sem.value); - } - - /* queue the flip on the crtc's "display sync" channel */ - BEGIN_NV04(evo, 0, 0x0100, 1); - OUT_RING (evo, 0xfffe0000); - if (chan) { - BEGIN_NV04(evo, 0, 0x0084, 1); - OUT_RING (evo, 0x00000100); - } else { - BEGIN_NV04(evo, 0, 0x0084, 1); - OUT_RING (evo, 0x00000010); - /* allows gamma somehow, PDISP will bitch at you if - * you don't wait for vblank before changing this.. - */ - BEGIN_NV04(evo, 0, 0x00e0, 1); - OUT_RING (evo, 0x40000000); - } - BEGIN_NV04(evo, 0, 0x0088, 4); - OUT_RING (evo, dispc->sem.offset); - OUT_RING (evo, 0xf00d0000 | dispc->sem.value); - OUT_RING (evo, 0x74b1e000); - OUT_RING (evo, NvEvoSync); - BEGIN_NV04(evo, 0, 0x00a0, 2); - OUT_RING (evo, 0x00000000); - OUT_RING (evo, 0x00000000); - BEGIN_NV04(evo, 0, 0x00c0, 1); - OUT_RING (evo, nv_fb->r_dma); - BEGIN_NV04(evo, 0, 0x0110, 2); - OUT_RING (evo, 0x00000000); - OUT_RING (evo, 0x00000000); - BEGIN_NV04(evo, 0, 0x0800, 5); - OUT_RING (evo, nv_fb->nvbo->bo.offset >> 8); - OUT_RING (evo, 0); - OUT_RING (evo, (fb->height << 16) | fb->width); - OUT_RING (evo, nv_fb->r_pitch); - OUT_RING (evo, nv_fb->r_format); - BEGIN_NV04(evo, 0, 0x0080, 1); - OUT_RING (evo, 0x00000000); - FIRE_RING (evo); - - dispc->sem.offset ^= 0x10; - dispc->sem.value++; - return 0; -} |