diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/nouveau/Makefile | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_connector.h | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_crtc.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_display.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_hdmi.c | 123 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_crtc.c | 753 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_cursor.c | 132 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_dac.c | 276 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 462 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.h | 60 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_evo.c | 396 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_evo.h | 120 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_fence.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_pm.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_sor.c | 339 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv84_fence.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvc0_fence.c | 21 |
17 files changed, 31 insertions, 2700 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index ae9151af9e08..b834a340bbdb 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -192,7 +192,7 @@ nouveau-y += nv04_fence.o nv10_fence.o nv50_fence.o nv84_fence.o nvc0_fence.o # drm/kms nouveau-y += nouveau_bios.o nouveau_fbcon.o nouveau_display.o -nouveau-y += nouveau_connector.o nouveau_hdmi.o nouveau_dp.o +nouveau-y += nouveau_connector.o nouveau_dp.o nouveau-y += nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o # drm/kms/nv04:nv50 @@ -201,9 +201,7 @@ nouveau-y += nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o nouveau-y += nv04_crtc.o nv04_display.o nv04_cursor.o # drm/kms/nv50- -nouveau-y += nv50_display.o nvd0_display.o -nouveau-y += nv50_crtc.o nv50_dac.o nv50_sor.o nv50_cursor.o -nouveau-y += nv50_evo.o +nouveau-y += nvd0_display.o # drm/pm nouveau-y += nouveau_pm.o nouveau_volt.o nouveau_perf.o diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h index ebdb87670a8f..20eb84cce9e6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h @@ -28,6 +28,7 @@ #define __NOUVEAU_CONNECTOR_H__ #include <drm/drm_edid.h> +#include "nouveau_crtc.h" struct nouveau_i2c_port; @@ -80,6 +81,21 @@ static inline struct nouveau_connector *nouveau_connector( return container_of(con, struct nouveau_connector, base); } +static inline struct nouveau_connector * +nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc) +{ + struct drm_device *dev = nv_crtc->base.dev; + struct drm_connector *connector; + struct drm_crtc *crtc = to_drm_crtc(nv_crtc); + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (connector->encoder && connector->encoder->crtc == crtc) + return nouveau_connector(connector); + } + + return NULL; +} + struct drm_connector * nouveau_connector_create(struct drm_device *, int index); diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h index e6d0d1eb0133..74396e134ef2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_crtc.h +++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h @@ -91,7 +91,4 @@ int nv50_crtc_cursor_move(struct drm_crtc *drm_crtc, int x, int y); int nv04_cursor_init(struct nouveau_crtc *); int nv50_cursor_init(struct nouveau_crtc *); -struct nouveau_connector * -nouveau_crtc_connector_get(struct nouveau_crtc *crtc); - #endif /* __NOUVEAU_CRTC_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index f03b07556484..7a48f4578e1f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -98,12 +98,12 @@ nouveau_framebuffer_init(struct drm_device *dev, nv_fb->r_dma = NvEvoVRAM_LP; switch (fb->depth) { - case 8: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_8; break; - case 15: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_15; break; - case 16: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_16; break; + case 8: nv_fb->r_format = 0x1e00; break; + case 15: nv_fb->r_format = 0xe900; break; + case 16: nv_fb->r_format = 0xe800; break; case 24: - case 32: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_24; break; - case 30: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_30; break; + case 32: nv_fb->r_format = 0xcf00; break; + case 30: nv_fb->r_format = 0xd100; break; default: NV_ERROR(drm, "unknown depth %d\n", fb->depth); return -EINVAL; @@ -366,9 +366,6 @@ nouveau_display_create(struct drm_device *dev) if (nv_device(drm->device)->card_type < NV_50) ret = nv04_display_create(dev); else - if (nv_device(drm->device)->card_type < NV_D0) - ret = nv50_display_create(dev); - else ret = nvd0_display_create(dev); if (ret) goto disp_create_err; @@ -660,10 +657,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, /* Emit a page flip */ if (nv_device(drm->device)->card_type >= NV_50) { - if (nv_device(drm->device)->card_type >= NV_D0) - ret = nvd0_display_flip_next(crtc, fb, chan, 0); - else - ret = nv50_display_flip_next(crtc, fb, chan); + ret = nvd0_display_flip_next(crtc, fb, chan, 0); if (ret) { mutex_unlock(&chan->cli->mutex); goto fail_unreserve; diff --git a/drivers/gpu/drm/nouveau/nouveau_hdmi.c b/drivers/gpu/drm/nouveau/nouveau_hdmi.c deleted file mode 100644 index f730de319795..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_hdmi.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2011 Red Hat Inc. - * - * 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 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 HOLDER(S) OR AUTHOR(S) 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. - * - * Authors: Ben Skeggs - */ - -#include <drm/drmP.h> -#include "nouveau_drm.h" -#include "nouveau_connector.h" -#include "nouveau_encoder.h" -#include "nouveau_crtc.h" - -#include <core/class.h> - -#include "nv50_display.h" - -static bool -hdmi_sor(struct drm_encoder *encoder) -{ - struct nouveau_drm *drm = nouveau_drm(encoder->dev); - if (nv_device(drm->device)->chipset < 0xa3 || - nv_device(drm->device)->chipset == 0xaa || - nv_device(drm->device)->chipset == 0xac) - return false; - return true; -} - -static void -nouveau_audio_disconnect(struct drm_encoder *encoder) -{ - struct nv50_display *priv = nv50_display(encoder->dev); - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - u32 or = nv_encoder->or; - - if (hdmi_sor(encoder)) - nv_exec(priv->core, NVA3_DISP_SOR_HDA_ELD + or, NULL, 0); -} - -static void -nouveau_audio_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode) -{ - struct nv50_display *priv = nv50_display(encoder->dev); - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_connector *nv_connector; - - nv_connector = nouveau_encoder_connector_get(nv_encoder); - if (!drm_detect_monitor_audio(nv_connector->edid)) { - nouveau_audio_disconnect(encoder); - return; - } - - if (hdmi_sor(encoder)) { - drm_edid_to_eld(&nv_connector->base, nv_connector->edid); - nv_exec(priv->core, NVA3_DISP_SOR_HDA_ELD + nv_encoder->or, - nv_connector->base.eld, - nv_connector->base.eld[2] * 4); - } -} - -static void -nouveau_hdmi_disconnect(struct drm_encoder *encoder) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc); - struct nv50_display *priv = nv50_display(encoder->dev); - const u32 moff = (nv_crtc->index << 3) | nv_encoder->or; - - nouveau_audio_disconnect(encoder); - - nv_call(priv->core, NV84_DISP_SOR_HDMI_PWR + moff, 0x00000000); -} - -void -nouveau_hdmi_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc); - struct nv50_display *priv = nv50_display(encoder->dev); - const u32 moff = (nv_crtc->index << 3) | nv_encoder->or; - struct nouveau_connector *nv_connector; - u32 max_ac_packet, rekey; - - nv_connector = nouveau_encoder_connector_get(nv_encoder); - if (!mode || !nv_connector || !nv_connector->edid || - !drm_detect_hdmi_monitor(nv_connector->edid)) { - nouveau_hdmi_disconnect(encoder); - return; - } - - /* value matches nvidia binary driver, and tegra constant */ - rekey = 56; - - max_ac_packet = mode->htotal - mode->hdisplay; - max_ac_packet -= rekey; - max_ac_packet -= 18; /* constant from tegra */ - max_ac_packet /= 32; - - nv_call(priv->core, NV84_DISP_SOR_HDMI_PWR + moff, - NV84_DISP_SOR_HDMI_PWR_STATE_ON | - (max_ac_packet << 16) | rekey); - - nouveau_audio_mode_set(encoder, mode); -} diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c deleted file mode 100644 index 1ba98059a417..000000000000 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ /dev/null @@ -1,753 +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 <drm/drmP.h> -#include <drm/drm_crtc_helper.h> - -#include "nouveau_reg.h" -#include "nouveau_drm.h" -#include "nouveau_dma.h" -#include "nouveau_gem.h" -#include "nouveau_hw.h" -#include "nouveau_encoder.h" -#include "nouveau_crtc.h" -#include "nouveau_connector.h" -#include "nv50_display.h" - -#include <subdev/clock.h> - -static void -nv50_crtc_lut_load(struct drm_crtc *crtc) -{ - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo); - int i; - - for (i = 0; i < 256; i++) { - writew(nv_crtc->lut.r[i] >> 2, lut + 8*i + 0); - writew(nv_crtc->lut.g[i] >> 2, lut + 8*i + 2); - writew(nv_crtc->lut.b[i] >> 2, lut + 8*i + 4); - } - - if (nv_crtc->lut.depth == 30) { - writew(nv_crtc->lut.r[i - 1] >> 2, lut + 8*i + 0); - writew(nv_crtc->lut.g[i - 1] >> 2, lut + 8*i + 2); - writew(nv_crtc->lut.b[i - 1] >> 2, lut + 8*i + 4); - } -} - -int -nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) -{ - struct drm_device *dev = nv_crtc->base.dev; - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_channel *evo = nv50_display(dev)->master; - int index = nv_crtc->index, ret; - - NV_DEBUG(drm, "index %d\n", nv_crtc->index); - NV_DEBUG(drm, "%s\n", blanked ? "blanked" : "unblanked"); - - if (blanked) { - nv_crtc->cursor.hide(nv_crtc, false); - - ret = RING_SPACE(evo, nv_device(drm->device)->chipset != 0x50 ? 7 : 5); - if (ret) { - NV_ERROR(drm, "no space while blanking crtc\n"); - return ret; - } - BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, CLUT_MODE), 2); - OUT_RING(evo, NV50_EVO_CRTC_CLUT_MODE_BLANK); - OUT_RING(evo, 0); - if (nv_device(drm->device)->chipset != 0x50) { - BEGIN_NV04(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1); - OUT_RING(evo, NV84_EVO_CRTC_CLUT_DMA_HANDLE_NONE); - } - - BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, FB_DMA), 1); - OUT_RING(evo, NV50_EVO_CRTC_FB_DMA_HANDLE_NONE); - } else { - if (nv_crtc->cursor.visible) - nv_crtc->cursor.show(nv_crtc, false); - else - nv_crtc->cursor.hide(nv_crtc, false); - - ret = RING_SPACE(evo, nv_device(drm->device)->chipset != 0x50 ? 10 : 8); - if (ret) { - NV_ERROR(drm, "no space while unblanking crtc\n"); - return ret; - } - BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, CLUT_MODE), 2); - OUT_RING(evo, nv_crtc->lut.depth == 8 ? - NV50_EVO_CRTC_CLUT_MODE_OFF : - NV50_EVO_CRTC_CLUT_MODE_ON); - OUT_RING(evo, nv_crtc->lut.nvbo->bo.offset >> 8); - if (nv_device(drm->device)->chipset != 0x50) { - BEGIN_NV04(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1); - OUT_RING(evo, NvEvoVRAM); - } - - BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, FB_OFFSET), 2); - OUT_RING(evo, nv_crtc->fb.offset >> 8); - OUT_RING(evo, 0); - BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, FB_DMA), 1); - if (nv_device(drm->device)->chipset != 0x50) - if (nv_crtc->fb.tile_flags == 0x7a00 || - nv_crtc->fb.tile_flags == 0xfe00) - OUT_RING(evo, NvEvoFB32); - else - if (nv_crtc->fb.tile_flags == 0x7000) - OUT_RING(evo, NvEvoFB16); - else - OUT_RING(evo, NvEvoVRAM_LP); - else - OUT_RING(evo, NvEvoVRAM_LP); - } - - nv_crtc->fb.blanked = blanked; - return 0; -} - -static int -nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update) -{ - struct nouveau_channel *evo = nv50_display(nv_crtc->base.dev)->master; - struct nouveau_connector *nv_connector; - struct drm_connector *connector; - int head = nv_crtc->index, ret; - u32 mode = 0x00; - - nv_connector = nouveau_crtc_connector_get(nv_crtc); - connector = &nv_connector->base; - if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) { - if (nv_crtc->base.fb->depth > connector->display_info.bpc * 3) - mode = DITHERING_MODE_DYNAMIC2X2; - } else { - mode = nv_connector->dithering_mode; - } - - if (nv_connector->dithering_depth == DITHERING_DEPTH_AUTO) { - if (connector->display_info.bpc >= 8) - mode |= DITHERING_DEPTH_8BPC; - } else { - mode |= nv_connector->dithering_depth; - } - - ret = RING_SPACE(evo, 2 + (update ? 2 : 0)); - if (ret == 0) { - BEGIN_NV04(evo, 0, NV50_EVO_CRTC(head, DITHER_CTRL), 1); - OUT_RING (evo, mode); - if (update) { - BEGIN_NV04(evo, 0, NV50_EVO_UPDATE, 1); - OUT_RING (evo, 0); - FIRE_RING (evo); - } - } - - return ret; -} - -static int -nv50_crtc_set_color_vibrance(struct nouveau_crtc *nv_crtc, bool update) -{ - struct drm_device *dev = nv_crtc->base.dev; - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_channel *evo = nv50_display(dev)->master; - int ret; - int adj; - u32 hue, vib; - - NV_DEBUG(drm, "vibrance = %i, hue = %i\n", - nv_crtc->color_vibrance, nv_crtc->vibrant_hue); - - ret = RING_SPACE(evo, 2 + (update ? 2 : 0)); - if (ret) { - NV_ERROR(drm, "no space while setting color vibrance\n"); - return ret; - } - - adj = (nv_crtc->color_vibrance > 0) ? 50 : 0; - vib = ((nv_crtc->color_vibrance * 2047 + adj) / 100) & 0xfff; - - hue = ((nv_crtc->vibrant_hue * 2047) / 100) & 0xfff; - - BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, COLOR_CTRL), 1); - OUT_RING (evo, (hue << 20) | (vib << 8)); - - if (update) { - BEGIN_NV04(evo, 0, NV50_EVO_UPDATE, 1); - OUT_RING (evo, 0); - FIRE_RING (evo); - } - - return 0; -} - -struct nouveau_connector * -nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc) -{ - struct drm_device *dev = nv_crtc->base.dev; - struct drm_connector *connector; - struct drm_crtc *crtc = to_drm_crtc(nv_crtc); - - /* The safest approach is to find an encoder with the right crtc, that - * is also linked to a connector. */ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->encoder) - if (connector->encoder->crtc == crtc) - return nouveau_connector(connector); - } - - return NULL; -} - -static int -nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update) -{ - struct nouveau_connector *nv_connector; - struct drm_crtc *crtc = &nv_crtc->base; - struct drm_device *dev = crtc->dev; - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_channel *evo = nv50_display(dev)->master; - struct drm_display_mode *umode = &crtc->mode; - struct drm_display_mode *omode; - int scaling_mode, ret; - u32 ctrl = 0, oX, oY; - - nv_connector = nouveau_crtc_connector_get(nv_crtc); - if (!nv_connector || !nv_connector->native_mode) { - NV_ERROR(drm, "no native mode, forcing panel scaling\n"); - scaling_mode = DRM_MODE_SCALE_NONE; - } else { - scaling_mode = nv_connector->scaling_mode; - } - - /* start off at the resolution we programmed the crtc for, this - * effectively handles NONE/FULL scaling - */ - if (scaling_mode != DRM_MODE_SCALE_NONE) - omode = nv_connector->native_mode; - else - omode = umode; - - oX = omode->hdisplay; - oY = omode->vdisplay; - if (omode->flags & DRM_MODE_FLAG_DBLSCAN) - oY *= 2; - - /* add overscan compensation if necessary, will keep the aspect - * ratio the same as the backend mode unless overridden by the - * user setting both hborder and vborder properties. - */ - if (nv_connector && ( nv_connector->underscan == UNDERSCAN_ON || - (nv_connector->underscan == UNDERSCAN_AUTO && - nv_connector->edid && - drm_detect_hdmi_monitor(nv_connector->edid)))) { - u32 bX = nv_connector->underscan_hborder; - u32 bY = nv_connector->underscan_vborder; - u32 aspect = (oY << 19) / oX; - - if (bX) { - oX -= (bX * 2); - if (bY) oY -= (bY * 2); - else oY = ((oX * aspect) + (aspect / 2)) >> 19; - } else { - oX -= (oX >> 4) + 32; - if (bY) oY -= (bY * 2); - else oY = ((oX * aspect) + (aspect / 2)) >> 19; - } - } - - /* handle CENTER/ASPECT scaling, taking into account the areas - * removed already for overscan compensation - */ - switch (scaling_mode) { - case DRM_MODE_SCALE_CENTER: - oX = min((u32)umode->hdisplay, oX); - oY = min((u32)umode->vdisplay, oY); - /* fall-through */ - case DRM_MODE_SCALE_ASPECT: - if (oY < oX) { - u32 aspect = (umode->hdisplay << 19) / umode->vdisplay; - oX = ((oY * aspect) + (aspect / 2)) >> 19; - } else { - u32 aspect = (umode->vdisplay << 19) / umode->hdisplay; - oY = ((oX * aspect) + (aspect / 2)) >> 19; - } - break; - default: - break; - } - - if (umode->hdisplay != oX || umode->vdisplay != oY || - umode->flags & DRM_MODE_FLAG_INTERLACE || - umode->flags & DRM_MODE_FLAG_DBLSCAN) - ctrl |= NV50_EVO_CRTC_SCALE_CTRL_ACTIVE; - - ret = RING_SPACE(evo, 5); - if (ret) - return ret; - - BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_CTRL), 1); - OUT_RING (evo, ctrl); - BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_RES1), 2); - OUT_RING (evo, oY << 16 | oX); - OUT_RING (evo, oY << 16 | oX); - - if (update) { - nv50_display_flip_stop(crtc); - nv50_display_sync(dev); - nv50_display_flip_next(crtc, crtc->fb, NULL); - } - - return 0; -} - -int -nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) -{ - struct nouveau_device *device = nouveau_dev(dev); - struct nouveau_clock *clk = nouveau_clock(device); - - return clk->pll_set(clk, PLL_VPLL0 + head, pclk); -} - -static void -nv50_crtc_destroy(struct drm_crtc *crtc) -{ - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - - nouveau_bo_unmap(nv_crtc->lut.nvbo); - nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); - nouveau_bo_unmap(nv_crtc->cursor.nvbo); - nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); - drm_crtc_cleanup(&nv_crtc->base); - kfree(nv_crtc); -} - -int -nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, - uint32_t buffer_handle, uint32_t width, uint32_t height) -{ - struct drm_device *dev = crtc->dev; - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - struct nouveau_bo *cursor = NULL; - struct drm_gem_object *gem; - int ret = 0, i; - - if (!buffer_handle) { - nv_crtc->cursor.hide(nv_crtc, true); - return 0; - } - - if (width != 64 || height != 64) - return -EINVAL; - - gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); - if (!gem) - return -ENOENT; - cursor = nouveau_gem_object(gem); - - ret = nouveau_bo_map(cursor); - if (ret) - goto out; - - /* The simple will do for now. */ - for (i = 0; i < 64 * 64; i++) - nouveau_bo_wr32(nv_crtc->cursor.nvbo, i, nouveau_bo_rd32(cursor, i)); - - nouveau_bo_unmap(cursor); - - nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset); - nv_crtc->cursor.show(nv_crtc, true); - -out: - drm_gem_object_unreference_unlocked(gem); - return ret; -} - -int -nv50_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) -{ - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - - nv_crtc->cursor.set_pos(nv_crtc, x, y); - return 0; -} - -static void -nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, - uint32_t start, uint32_t size) -{ - int end = (start + size > 256) ? 256 : start + size, i; - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - - for (i = start; i < end; i++) { - nv_crtc->lut.r[i] = r[i]; - nv_crtc->lut.g[i] = g[i]; - nv_crtc->lut.b[i] = b[i]; - } - - /* We need to know the depth before we upload, but it's possible to - * get called before a framebuffer is bound. If this is the case, - * mark the lut values as dirty by setting depth==0, and it'll be - * uploaded on the first mode_set_base() - */ - if (!nv_crtc->base.fb) { - nv_crtc->lut.depth = 0; - return; - } - - nv50_crtc_lut_load(crtc); -} - -static void -nv50_crtc_save(struct drm_crtc *crtc) -{ - struct nouveau_drm *drm = nouveau_drm(crtc->dev); - NV_ERROR(drm, "!!\n"); -} - -static void -nv50_crtc_restore(struct drm_crtc *crtc) -{ - struct nouveau_drm *drm = nouveau_drm(crtc->dev); - NV_ERROR(drm, "!!\n"); -} - -static const struct drm_crtc_funcs nv50_crtc_funcs = { - .save = nv50_crtc_save, - .restore = nv50_crtc_restore, - .cursor_set = nv50_crtc_cursor_set, - .cursor_move = nv50_crtc_cursor_move, - .gamma_set = nv50_crtc_gamma_set, - .set_config = drm_crtc_helper_set_config, - .page_flip = nouveau_crtc_page_flip, - .destroy = nv50_crtc_destroy, -}; - -static void -nv50_crtc_dpms(struct drm_crtc *crtc, int mode) -{ -} - -static void -nv50_crtc_prepare(struct drm_crtc *crtc) -{ - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - struct drm_device *dev = crtc->dev; - struct nouveau_drm *drm = nouveau_drm(dev); - - NV_DEBUG(drm, "index %d\n", nv_crtc->index); - - nv50_display_flip_stop(crtc); - drm_vblank_pre_modeset(dev, nv_crtc->index); - nv50_crtc_blank(nv_crtc, true); -} - -static void -nv50_crtc_commit(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - - NV_DEBUG(drm, "index %d\n", nv_crtc->index); - - nv50_crtc_blank(nv_crtc, false); - drm_vblank_post_modeset(dev, nv_crtc->index); - nv50_display_sync(dev); - nv50_display_flip_next(crtc, crtc->fb, NULL); -} - -static bool -nv50_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - -static int -nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, - struct drm_framebuffer *passed_fb, - int x, int y, bool atomic) -{ - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - struct drm_device *dev = nv_crtc->base.dev; - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_channel *evo = nv50_display(dev)->master; - struct drm_framebuffer *drm_fb; - struct nouveau_framebuffer *fb; - int ret; - - NV_DEBUG(drm, "index %d\n", nv_crtc->index); - - /* no fb bound */ - if (!atomic && !crtc->fb) { - NV_DEBUG(drm, "No FB bound\n"); - return 0; - } - - /* If atomic, we want to switch to the fb we were passed, so - * now we update pointers to do that. (We don't pin; just - * assume we're already pinned and update the base address.) - */ - if (atomic) { - drm_fb = passed_fb; - fb = nouveau_framebuffer(passed_fb); - } else { - drm_fb = crtc->fb; - fb = nouveau_framebuffer(crtc->fb); - /* If not atomic, we can go ahead and pin, and unpin the - * old fb we were passed. - */ - ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM); - if (ret) - return ret; - - if (passed_fb) { - struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb); - nouveau_bo_unpin(ofb->nvbo); - } - } - - nv_crtc->fb.offset = fb->nvbo->bo.offset; - nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo); - nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8; - if (!nv_crtc->fb.blanked && nv_device(drm->device)->chipset != 0x50) { - ret = RING_SPACE(evo, 2); - if (ret) - return ret; - - BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_DMA), 1); - OUT_RING (evo, fb->r_dma); - } - - ret = RING_SPACE(evo, 12); - if (ret) - return ret; - - BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_OFFSET), 5); - OUT_RING (evo, nv_crtc->fb.offset >> 8); - OUT_RING (evo, 0); - OUT_RING (evo, (drm_fb->height << 16) | drm_fb->width); - OUT_RING (evo, fb->r_pitch); - OUT_RING (evo, fb->r_format); - - BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CLUT_MODE), 1); - OUT_RING (evo, fb->base.depth == 8 ? - NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON); - - BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_POS), 1); - OUT_RING (evo, (y << 16) | x); - - if (nv_crtc->lut.depth != fb->base.depth) { - nv_crtc->lut.depth = fb->base.depth; - nv50_crtc_lut_load(crtc); - } - - return 0; -} - -static int -nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode, - struct drm_display_mode *mode, int x, int y, - struct drm_framebuffer *old_fb) -{ - struct drm_device *dev = crtc->dev; - struct nouveau_channel *evo = nv50_display(dev)->master; - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - u32 head = nv_crtc->index * 0x400; - u32 ilace = (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 1; - u32 vscan = (mode->flags & DRM_MODE_FLAG_DBLSCAN) ? 2 : 1; - u32 hactive, hsynce, hbackp, hfrontp, hblanke, hblanks; - u32 vactive, vsynce, vbackp, vfrontp, vblanke, vblanks; - u32 vblan2e = 0, vblan2s = 1; - int ret; - - /* hw timing description looks like this: - * - * <sync> <back porch> <---------display---------> <front porch> - * ______ - * |____________|---------------------------|____________| - * - * ^ synce ^ blanke ^ blanks ^ active - * - * interlaced modes also have 2 additional values pointing at the end - * and start of the next field's blanking period. - */ - - hactive = mode->htotal; - hsynce = mode->hsync_end - mode->hsync_start - 1; - hbackp = mode->htotal - mode->hsync_end; - hblanke = hsynce + hbackp; - hfrontp = mode->hsync_start - mode->hdisplay; - hblanks = mode->htotal - hfrontp - 1; - - vactive = mode->vtotal * vscan / ilace; - vsynce = ((mode->vsync_end - mode->vsync_start) * vscan / ilace) - 1; - vbackp = (mode->vtotal - mode->vsync_end) * vscan / ilace; - vblanke = vsynce + vbackp; - vfrontp = (mode->vsync_start - mode->vdisplay) * vscan / ilace; - vblanks = vactive - vfrontp - 1; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) { - vblan2e = vactive + vsynce + vbackp; - vblan2s = vblan2e + (mode->vdisplay * vscan / ilace); - vactive = (vactive * 2) + 1; - } - - ret = RING_SPACE(evo, 18); - if (ret == 0) { - BEGIN_NV04(evo, 0, 0x0804 + head, 2); - OUT_RING (evo, 0x00800000 | mode->clock); - OUT_RING (evo, (ilace == 2) ? 2 : 0); - BEGIN_NV04(evo, 0, 0x0810 + head, 6); - OUT_RING (evo, 0x00000000); /* border colour */ - OUT_RING (evo, (vactive << 16) | hactive); - OUT_RING (evo, ( vsynce << 16) | hsynce); - OUT_RING (evo, (vblanke << 16) | hblanke); - OUT_RING (evo, (vblanks << 16) | hblanks); - OUT_RING (evo, (vblan2e << 16) | vblan2s); - BEGIN_NV04(evo, 0, 0x082c + head, 1); - OUT_RING (evo, 0x00000000); - BEGIN_NV04(evo, 0, 0x0900 + head, 1); - OUT_RING (evo, 0x00000311); /* makes sync channel work */ - BEGIN_NV04(evo, 0, 0x08c8 + head, 1); - OUT_RING (evo, (umode->vdisplay << 16) | umode->hdisplay); - BEGIN_NV04(evo, 0, 0x08d4 + head, 1); - OUT_RING (evo, 0x00000000); /* screen position */ - } - - nv_crtc->set_dither(nv_crtc, false); - nv_crtc->set_scale(nv_crtc, false); - nv_crtc->set_color_vibrance(nv_crtc, false); - - return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false); -} - -static int -nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb) -{ - int ret; - - nv50_display_flip_stop(crtc); - ret = nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false); - if (ret) - return ret; - - ret = nv50_display_sync(crtc->dev); - if (ret) - return ret; - - return nv50_display_flip_next(crtc, crtc->fb, NULL); -} - -static int -nv50_crtc_mode_set_base_atomic(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int x, int y, enum mode_set_atomic state) -{ - int ret; - - nv50_display_flip_stop(crtc); - ret = nv50_crtc_do_mode_set_base(crtc, fb, x, y, true); - if (ret) - return ret; - - return nv50_display_sync(crtc->dev); -} - -static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = { - .dpms = nv50_crtc_dpms, - .prepare = nv50_crtc_prepare, - .commit = nv50_crtc_commit, - .mode_fixup = nv50_crtc_mode_fixup, - .mode_set = nv50_crtc_mode_set, - .mode_set_base = nv50_crtc_mode_set_base, - .mode_set_base_atomic = nv50_crtc_mode_set_base_atomic, - .load_lut = nv50_crtc_lut_load, -}; - -int -nv50_crtc_create(struct drm_device *dev, int index) -{ - struct nouveau_crtc *nv_crtc = NULL; - int ret, i; - - nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL); - if (!nv_crtc) - return -ENOMEM; - - nv_crtc->index = index; - nv_crtc->set_dither = nv50_crtc_set_dither; - nv_crtc->set_scale = nv50_crtc_set_scale; - nv_crtc->set_color_vibrance = nv50_crtc_set_color_vibrance; - nv_crtc->color_vibrance = 50; - nv_crtc->vibrant_hue = 0; - nv_crtc->lut.depth = 0; - for (i = 0; i < 256; i++) { - nv_crtc->lut.r[i] = i << 8; - nv_crtc->lut.g[i] = i << 8; - nv_crtc->lut.b[i] = i << 8; - } - - drm_crtc_init(dev, &nv_crtc->base, &nv50_crtc_funcs); - drm_crtc_helper_add(&nv_crtc->base, &nv50_crtc_helper_funcs); - drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); - - ret = nouveau_bo_new(dev, 4096, 0x100, TTM_PL_FLAG_VRAM, - 0, 0x0000, NULL, &nv_crtc->lut.nvbo); - if (!ret) { - ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM); - if (!ret) - ret = nouveau_bo_map(nv_crtc->lut.nvbo); - if (ret) - nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); - } - - if (ret) - goto out; - - - ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, - 0, 0x0000, NULL, &nv_crtc->cursor.nvbo); - if (!ret) { - ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); - if (!ret) - ret = nouveau_bo_map(nv_crtc->cursor.nvbo); - if (ret) - nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); - } - - if (ret) - goto out; - - nv50_cursor_init(nv_crtc); -out: - if (ret) - nv50_crtc_destroy(&nv_crtc->base); - return ret; -} diff --git a/drivers/gpu/drm/nouveau/nv50_cursor.c b/drivers/gpu/drm/nouveau/nv50_cursor.c deleted file mode 100644 index 230b270bc318..000000000000 --- a/drivers/gpu/drm/nouveau/nv50_cursor.c +++ /dev/null @@ -1,132 +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 <drm/drmP.h> - -#include "nouveau_drm.h" -#include "nouveau_dma.h" -#include "nouveau_crtc.h" -#include "nv50_display.h" - -static void -nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update) -{ - struct drm_device *dev = nv_crtc->base.dev; - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_channel *evo = nv50_display(dev)->master; - int ret; - - if (update && nv_crtc->cursor.visible) - return; - - ret = RING_SPACE(evo, (nv_device(drm->device)->chipset != 0x50 ? 5 : 3) + update * 2); - if (ret) { - NV_ERROR(drm, "no space while unhiding cursor\n"); - return; - } - - if (nv_device(drm->device)->chipset != 0x50) { - BEGIN_NV04(evo, 0, NV84_EVO_CRTC(nv_crtc->index, CURSOR_DMA), 1); - OUT_RING(evo, NvEvoVRAM); - } - BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CURSOR_CTRL), 2); - OUT_RING(evo, NV50_EVO_CRTC_CURSOR_CTRL_SHOW); - OUT_RING(evo, nv_crtc->cursor.offset >> 8); - - if (update) { - BEGIN_NV04(evo, 0, NV50_EVO_UPDATE, 1); - OUT_RING(evo, 0); - FIRE_RING(evo); - nv_crtc->cursor.visible = true; - } -} - -static void -nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update) -{ - struct drm_device *dev = nv_crtc->base.dev; - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_channel *evo = nv50_display(dev)->master; - int ret; - - if (update && !nv_crtc->cursor.visible) - return; - - ret = RING_SPACE(evo, (nv_device(drm->device)->chipset != 0x50 ? 5 : 3) + update * 2); - if (ret) { - NV_ERROR(drm, "no space while hiding cursor\n"); - return; - } - BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CURSOR_CTRL), 2); - OUT_RING(evo, NV50_EVO_CRTC_CURSOR_CTRL_HIDE); - OUT_RING(evo, 0); - if (nv_device(drm->device)->chipset != 0x50) { - BEGIN_NV04(evo, 0, NV84_EVO_CRTC(nv_crtc->index, CURSOR_DMA), 1); - OUT_RING(evo, NV84_EVO_CRTC_CURSOR_DMA_HANDLE_NONE); - } - - if (update) { - BEGIN_NV04(evo, 0, NV50_EVO_UPDATE, 1); - OUT_RING(evo, 0); - FIRE_RING(evo); - nv_crtc->cursor.visible = false; - } -} - -static void -nv50_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y) -{ - struct nouveau_device *device = nouveau_dev(nv_crtc->base.dev); - - nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y; - nv_wr32(device, NV50_PDISPLAY_CURSOR_USER_POS(nv_crtc->index), - ((y & 0xFFFF) << 16) | (x & 0xFFFF)); - /* Needed to make the cursor move. */ - nv_wr32(device, NV50_PDISPLAY_CURSOR_USER_POS_CTRL(nv_crtc->index), 0); -} - -static void -nv50_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset) -{ - if (offset == nv_crtc->cursor.offset) - return; - - nv_crtc->cursor.offset = offset; - if (nv_crtc->cursor.visible) { - nv_crtc->cursor.visible = false; - nv_crtc->cursor.show(nv_crtc, true); - } -} - -int -nv50_cursor_init(struct nouveau_crtc *nv_crtc) -{ - nv_crtc->cursor.set_offset = nv50_cursor_set_offset; - nv_crtc->cursor.set_pos = nv50_cursor_set_pos; - nv_crtc->cursor.hide = nv50_cursor_hide; - nv_crtc->cursor.show = nv50_cursor_show; - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c deleted file mode 100644 index 622f0f9879ab..000000000000 --- a/drivers/gpu/drm/nouveau/nv50_dac.c +++ /dev/null @@ -1,276 +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 <drm/drmP.h> -#include <drm/drm_crtc_helper.h> - -#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) -#include "nouveau_reg.h" -#include "nouveau_drm.h" -#include "nouveau_dma.h" -#include "nouveau_encoder.h" -#include "nouveau_connector.h" -#include "nouveau_crtc.h" -#include "nv50_display.h" - -#include <core/class.h> - -#include <subdev/timer.h> - -static void -nv50_dac_disconnect(struct drm_encoder *encoder) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct drm_device *dev = encoder->dev; - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_channel *evo = nv50_display(dev)->master; - int ret; - - if (!nv_encoder->crtc) - return; - nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true); - - NV_DEBUG(drm, "Disconnecting DAC %d\n", nv_encoder->or); - - ret = RING_SPACE(evo, 4); - if (ret) { - NV_ERROR(drm, "no space while disconnecting DAC\n"); - return; - } - BEGIN_NV04(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 1); - OUT_RING (evo, 0); - BEGIN_NV04(evo, 0, NV50_EVO_UPDATE, 1); - OUT_RING (evo, 0); - - nv_encoder->crtc = NULL; -} - -static enum drm_connector_status -nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) -{ - struct nv50_display *priv = nv50_display(encoder->dev); - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_drm *drm = nouveau_drm(encoder->dev); - int or = nv_encoder->or, ret; - u32 load; - - if (drm->vbios.dactestval) - load = drm->vbios.dactestval; - else - load = 340; - - ret = nv_exec(priv->core, NV50_DISP_DAC_LOAD + or, &load, sizeof(load)); - if (ret || load != 7) - return connector_status_disconnected; - - return connector_status_connected; -} - -static void -nv50_dac_dpms(struct drm_encoder *encoder, int mode) -{ - struct nv50_display *priv = nv50_display(encoder->dev); - struct nouveau_drm *drm = nouveau_drm(encoder->dev); - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - uint32_t val; - int or = nv_encoder->or; - - NV_DEBUG(drm, "or %d mode %d\n", or, mode); - - if (mode != DRM_MODE_DPMS_ON) - val = NV50_PDISPLAY_DAC_DPMS_CTRL_BLANKED; - else - val = 0; - - switch (mode) { - case DRM_MODE_DPMS_STANDBY: - val |= NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF; - break; - case DRM_MODE_DPMS_SUSPEND: - val |= NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF; - break; - case DRM_MODE_DPMS_OFF: - val |= NV50_PDISPLAY_DAC_DPMS_CTRL_OFF; - val |= NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF; - val |= NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF; - break; - default: - break; - } - - nv_call(priv->core, NV50_DISP_DAC_PWR + or, val); -} - -static void -nv50_dac_save(struct drm_encoder *encoder) -{ - struct nouveau_drm *drm = nouveau_drm(encoder->dev); - NV_ERROR(drm, "!!\n"); -} - -static void -nv50_dac_restore(struct drm_encoder *encoder) -{ - struct nouveau_drm *drm = nouveau_drm(encoder->dev); - NV_ERROR(drm, "!!\n"); -} - -static bool -nv50_dac_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct nouveau_drm *drm = nouveau_drm(encoder->dev); - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_connector *connector; - - NV_DEBUG(drm, "or %d\n", nv_encoder->or); - - connector = nouveau_encoder_connector_get(nv_encoder); - if (!connector) { - NV_ERROR(drm, "Encoder has no connector\n"); - return false; - } - - if (connector->scaling_mode != DRM_MODE_SCALE_NONE && - connector->native_mode) - drm_mode_copy(adjusted_mode, connector->native_mode); - - return true; -} - -static void -nv50_dac_commit(struct drm_encoder *encoder) -{ -} - -static void -nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_drm *drm = nouveau_drm(encoder->dev); - struct drm_device *dev = encoder->dev; - struct nouveau_channel *evo = nv50_display(dev)->master; - struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); - uint32_t mode_ctl = 0, mode_ctl2 = 0; - int ret; - - NV_DEBUG(drm, "or %d type %d crtc %d\n", - nv_encoder->or, nv_encoder->dcb->type, crtc->index); - - nv50_dac_dpms(encoder, DRM_MODE_DPMS_ON); - - if (crtc->index == 1) - mode_ctl |= NV50_EVO_DAC_MODE_CTRL_CRTC1; - else - mode_ctl |= NV50_EVO_DAC_MODE_CTRL_CRTC0; - - /* Lacking a working tv-out, this is not a 100% sure. */ - if (nv_encoder->dcb->type == DCB_OUTPUT_ANALOG) - mode_ctl |= 0x40; - else - if (nv_encoder->dcb->type == DCB_OUTPUT_TV) - mode_ctl |= 0x100; - - if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) - mode_ctl2 |= NV50_EVO_DAC_MODE_CTRL2_NHSYNC; - - if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) - mode_ctl2 |= NV50_EVO_DAC_MODE_CTRL2_NVSYNC; - - ret = RING_SPACE(evo, 3); - if (ret) { - NV_ERROR(drm, "no space while connecting DAC\n"); - return; - } - BEGIN_NV04(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 2); - OUT_RING(evo, mode_ctl); - OUT_RING(evo, mode_ctl2); - - nv_encoder->crtc = encoder->crtc; -} - -static struct drm_crtc * -nv50_dac_crtc_get(struct drm_encoder *encoder) -{ - return nouveau_encoder(encoder)->crtc; -} - -static const struct drm_encoder_helper_funcs nv50_dac_helper_funcs = { - .dpms = nv50_dac_dpms, - .save = nv50_dac_save, - .restore = nv50_dac_restore, - .mode_fixup = nv50_dac_mode_fixup, - .prepare = nv50_dac_disconnect, - .commit = nv50_dac_commit, - .mode_set = nv50_dac_mode_set, - .get_crtc = nv50_dac_crtc_get, - .detect = nv50_dac_detect, - .disable = nv50_dac_disconnect -}; - -static void -nv50_dac_destroy(struct drm_encoder *encoder) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - - if (!encoder) - return; - - drm_encoder_cleanup(encoder); - kfree(nv_encoder); -} - -static const struct drm_encoder_funcs nv50_dac_encoder_funcs = { - .destroy = nv50_dac_destroy, -}; - -int -nv50_dac_create(struct drm_connector *connector, struct dcb_output *entry) -{ - struct nouveau_encoder *nv_encoder; - struct drm_encoder *encoder; - - nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); - if (!nv_encoder) - return -ENOMEM; - encoder = to_drm_encoder(nv_encoder); - - nv_encoder->dcb = entry; - nv_encoder->or = ffs(entry->or) - 1; - - drm_encoder_init(connector->dev, encoder, &nv50_dac_encoder_funcs, - DRM_MODE_ENCODER_DAC); - drm_encoder_helper_add(encoder, &nv50_dac_helper_funcs); - - encoder->possible_crtcs = entry->heads; - encoder->possible_clones = 0; - - drm_mode_connector_attach_encoder(connector, encoder); - return 0; -} - 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; -} diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h index bf3703807f99..13bc81889fd7 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.h +++ b/drivers/gpu/drm/nouveau/nv50_display.h @@ -30,65 +30,6 @@ #include "nouveau_display.h" #include "nouveau_crtc.h" #include "nouveau_reg.h" -#include "nv50_evo.h" - -struct nv50_display_crtc { - struct nouveau_channel *sync; - struct { - struct nouveau_bo *bo; - u32 offset; - u16 value; - } sem; -}; - -struct nv50_display { - struct nouveau_channel *master; - - struct nouveau_object *core; - struct nouveau_gpuobj *ramin; - u32 dmao; - u32 hash; - - struct nv50_display_crtc crtc[2]; - - struct tasklet_struct tasklet; - struct { - struct dcb_output *dcb; - u16 script; - u32 pclk; - } irq; -}; - -static inline struct nv50_display * -nv50_display(struct drm_device *dev) -{ - return nouveau_display(dev)->priv; -} - -int nv50_display_early_init(struct drm_device *dev); -void nv50_display_late_takedown(struct drm_device *dev); -int nv50_display_create(struct drm_device *dev); -int nv50_display_init(struct drm_device *dev); -void nv50_display_fini(struct drm_device *dev); -void nv50_display_destroy(struct drm_device *dev); -int nv50_crtc_blank(struct nouveau_crtc *, bool blank); -int nv50_crtc_set_clock(struct drm_device *, int head, int pclk); - -u32 nv50_display_active_crtcs(struct drm_device *); - -int nv50_display_sync(struct drm_device *); -int nv50_display_flip_next(struct drm_crtc *, struct drm_framebuffer *, - struct nouveau_channel *chan); -void nv50_display_flip_stop(struct drm_crtc *); - -int nv50_evo_create(struct drm_device *dev); -void nv50_evo_destroy(struct drm_device *dev); -int nv50_evo_init(struct drm_device *dev); -void nv50_evo_fini(struct drm_device *dev); -void nv50_evo_dmaobj_init(struct nouveau_gpuobj *, u32 memtype, u64 base, - u64 size); -int nv50_evo_dmaobj_new(struct nouveau_channel *, u32 handle, u32 memtype, - u64 base, u64 size, struct nouveau_gpuobj **); int nvd0_display_create(struct drm_device *); void nvd0_display_destroy(struct drm_device *); @@ -99,7 +40,6 @@ void nvd0_display_flip_stop(struct drm_crtc *); int nvd0_display_flip_next(struct drm_crtc *, struct drm_framebuffer *, struct nouveau_channel *, u32 swap_interval); -struct nouveau_bo *nv50_display_crtc_sema(struct drm_device *, int head); struct nouveau_bo *nvd0_display_crtc_sema(struct drm_device *, int head); #endif /* __NV50_DISPLAY_H__ */ diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c deleted file mode 100644 index 2fd043ec0fb3..000000000000 --- a/drivers/gpu/drm/nouveau/nv50_evo.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Copyright 2010 Red Hat Inc. - * - * 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 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 HOLDER(S) OR AUTHOR(S) 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. - * - * Authors: Ben Skeggs - */ - -#include <drm/drmP.h> - -#include "nouveau_drm.h" -#include "nouveau_dma.h" -#include "nv50_display.h" - -#include <core/gpuobj.h> - -#include <subdev/timer.h> -#include <subdev/fb.h> - -static u32 -nv50_evo_rd32(struct nouveau_object *object, u64 addr) -{ - void __iomem *iomem = object->oclass->ofuncs->rd08; - return ioread32_native(iomem + addr); -} - -static void -nv50_evo_wr32(struct nouveau_object *object, u64 addr, u32 data) -{ - void __iomem *iomem = object->oclass->ofuncs->rd08; - iowrite32_native(data, iomem + addr); -} - -static void -nv50_evo_channel_del(struct nouveau_channel **pevo) -{ - struct nouveau_channel *evo = *pevo; - - if (!evo) - return; - *pevo = NULL; - - nouveau_bo_unmap(evo->push.buffer); - nouveau_bo_ref(NULL, &evo->push.buffer); - - if (evo->object) - iounmap(evo->object->oclass->ofuncs); - - kfree(evo); -} - -int -nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 handle, u32 memtype, - u64 base, u64 size, struct nouveau_gpuobj **pobj) -{ - struct drm_device *dev = evo->fence; - struct nouveau_drm *drm = nouveau_drm(dev); - struct nv50_display *disp = nv50_display(dev); - u32 dmao = disp->dmao; - u32 hash = disp->hash; - u32 flags5; - - if (nv_device(drm->device)->chipset < 0xc0) { - /* not supported on 0x50, specified in format mthd */ - if (nv_device(drm->device)->chipset == 0x50) - memtype = 0; - flags5 = 0x00010000; - } else { - if (memtype & 0x80000000) - flags5 = 0x00000000; /* large pages */ - else - flags5 = 0x00020000; - } - - nv_wo32(disp->ramin, dmao + 0x00, 0x0019003d | (memtype << 22)); - nv_wo32(disp->ramin, dmao + 0x04, lower_32_bits(base + size - 1)); - nv_wo32(disp->ramin, dmao + 0x08, lower_32_bits(base)); - nv_wo32(disp->ramin, dmao + 0x0c, upper_32_bits(base + size - 1) << 24 | - upper_32_bits(base)); - nv_wo32(disp->ramin, dmao + 0x10, 0x00000000); - nv_wo32(disp->ramin, dmao + 0x14, flags5); - - nv_wo32(disp->ramin, hash + 0x00, handle); - nv_wo32(disp->ramin, hash + 0x04, (evo->handle << 28) | (dmao << 10) | - evo->handle); - - disp->dmao += 0x20; - disp->hash += 0x08; - return 0; -} - -static int -nv50_evo_channel_new(struct drm_device *dev, int chid, - struct nouveau_channel **pevo) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - struct nv50_display *disp = nv50_display(dev); - struct nouveau_channel *evo; - int ret; - - evo = kzalloc(sizeof(struct nouveau_channel), GFP_KERNEL); - if (!evo) - return -ENOMEM; - *pevo = evo; - - evo->drm = drm; - evo->handle = chid; - evo->fence = dev; - evo->user_get = 4; - evo->user_put = 0; - - ret = nouveau_bo_new(dev, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, NULL, - &evo->push.buffer); - if (ret == 0) - ret = nouveau_bo_pin(evo->push.buffer, TTM_PL_FLAG_VRAM); - if (ret) { - NV_ERROR(drm, "Error creating EVO DMA push buffer: %d\n", ret); - nv50_evo_channel_del(pevo); - return ret; - } - - ret = nouveau_bo_map(evo->push.buffer); - if (ret) { - NV_ERROR(drm, "Error mapping EVO DMA push buffer: %d\n", ret); - nv50_evo_channel_del(pevo); - return ret; - } - - evo->object = kzalloc(sizeof(*evo->object), GFP_KERNEL); -#ifdef NOUVEAU_OBJECT_MAGIC - evo->object->_magic = NOUVEAU_OBJECT_MAGIC; -#endif - evo->object->parent = nv_object(disp->ramin)->parent; - evo->object->engine = nv_object(disp->ramin)->engine; - evo->object->oclass = - kzalloc(sizeof(*evo->object->oclass), GFP_KERNEL); - evo->object->oclass->ofuncs = - kzalloc(sizeof(*evo->object->oclass->ofuncs), GFP_KERNEL); - evo->object->oclass->ofuncs->rd32 = nv50_evo_rd32; - evo->object->oclass->ofuncs->wr32 = nv50_evo_wr32; - evo->object->oclass->ofuncs->rd08 = - ioremap(pci_resource_start(dev->pdev, 0) + - NV50_PDISPLAY_USER(evo->handle), PAGE_SIZE); - return 0; -} - -static int -nv50_evo_channel_init(struct nouveau_channel *evo) -{ - struct nouveau_drm *drm = evo->drm; - struct nouveau_device *device = nv_device(drm->device); - int id = evo->handle, ret, i; - u64 pushbuf = evo->push.buffer->bo.offset; - u32 tmp; - - tmp = nv_rd32(device, NV50_PDISPLAY_EVO_CTRL(id)); - if ((tmp & 0x009f0000) == 0x00020000) - nv_wr32(device, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00800000); - - tmp = nv_rd32(device, NV50_PDISPLAY_EVO_CTRL(id)); - if ((tmp & 0x003f0000) == 0x00030000) - nv_wr32(device, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00600000); - - /* initialise fifo */ - nv_wr32(device, NV50_PDISPLAY_EVO_DMA_CB(id), pushbuf >> 8 | - NV50_PDISPLAY_EVO_DMA_CB_LOCATION_VRAM | - NV50_PDISPLAY_EVO_DMA_CB_VALID); - nv_wr32(device, NV50_PDISPLAY_EVO_UNK2(id), 0x00010000); - nv_wr32(device, NV50_PDISPLAY_EVO_HASH_TAG(id), id); - nv_mask(device, NV50_PDISPLAY_EVO_CTRL(id), NV50_PDISPLAY_EVO_CTRL_DMA, - NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED); - - nv_wr32(device, NV50_PDISPLAY_USER_PUT(id), 0x00000000); - nv_wr32(device, NV50_PDISPLAY_EVO_CTRL(id), 0x01000003 | - NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED); - if (!nv_wait(device, NV50_PDISPLAY_EVO_CTRL(id), 0x80000000, 0x00000000)) { - NV_ERROR(drm, "EvoCh %d init timeout: 0x%08x\n", id, - nv_rd32(device, NV50_PDISPLAY_EVO_CTRL(id))); - return -EBUSY; - } - - /* enable error reporting on the channel */ - nv_mask(device, 0x610028, 0x00000000, 0x00010001 << id); - - evo->dma.max = (4096/4) - 2; - evo->dma.max &= ~7; - evo->dma.put = 0; - evo->dma.cur = evo->dma.put; - evo->dma.free = evo->dma.max - evo->dma.cur; - - ret = RING_SPACE(evo, NOUVEAU_DMA_SKIPS); - if (ret) - return ret; - - for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) - OUT_RING(evo, 0); - - return 0; -} - -static void -nv50_evo_channel_fini(struct nouveau_channel *evo) -{ - struct nouveau_drm *drm = evo->drm; - struct nouveau_device *device = nv_device(drm->device); - int id = evo->handle; - - nv_mask(device, 0x610028, 0x00010001 << id, 0x00000000); - nv_mask(device, NV50_PDISPLAY_EVO_CTRL(id), 0x00001010, 0x00001000); - nv_wr32(device, NV50_PDISPLAY_INTR_0, (1 << id)); - nv_mask(device, NV50_PDISPLAY_EVO_CTRL(id), 0x00000003, 0x00000000); - if (!nv_wait(device, NV50_PDISPLAY_EVO_CTRL(id), 0x001e0000, 0x00000000)) { - NV_ERROR(drm, "EvoCh %d takedown timeout: 0x%08x\n", id, - nv_rd32(device, NV50_PDISPLAY_EVO_CTRL(id))); - } -} - -void -nv50_evo_destroy(struct drm_device *dev) -{ - struct nv50_display *disp = nv50_display(dev); - int i; - - for (i = 0; i < 2; i++) { - if (disp->crtc[i].sem.bo) { - nouveau_bo_unmap(disp->crtc[i].sem.bo); - nouveau_bo_ref(NULL, &disp->crtc[i].sem.bo); - } - nv50_evo_channel_del(&disp->crtc[i].sync); - } - nv50_evo_channel_del(&disp->master); -} - -int -nv50_evo_create(struct drm_device *dev) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_fb *pfb = nouveau_fb(drm->device); - struct nv50_display *disp = nv50_display(dev); - struct nouveau_channel *evo; - int ret, i, j; - - /* setup object management on it, any other evo channel will - * use this also as there's no per-channel support on the - * hardware - */ - disp->ramin = nv_gpuobj(disp->core->parent); - disp->hash = 0x0000; - disp->dmao = 0x1000; - - /* create primary evo channel, the one we use for modesetting - * purporses - */ - ret = nv50_evo_channel_new(dev, 0, &disp->master); - if (ret) - return ret; - evo = disp->master; - - ret = nv50_evo_dmaobj_new(disp->master, NvEvoSync, 0x0000, - disp->ramin->addr + 0x2000, 0x1000, NULL); - if (ret) - goto err; - - /* create some default objects for the scanout memtypes we support */ - ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM, 0x0000, - 0, pfb->ram.size, NULL); - if (ret) - goto err; - - ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM_LP, 0x80000000, - 0, pfb->ram.size, NULL); - if (ret) - goto err; - - ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB32, 0x80000000 | - (nv_device(drm->device)->chipset < 0xc0 ? 0x7a : 0xfe), - 0, pfb->ram.size, NULL); - if (ret) - goto err; - - ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB16, 0x80000000 | - (nv_device(drm->device)->chipset < 0xc0 ? 0x70 : 0xfe), - 0, pfb->ram.size, NULL); - if (ret) - goto err; - - /* create "display sync" channels and other structures we need - * to implement page flipping - */ - for (i = 0; i < 2; i++) { - struct nv50_display_crtc *dispc = &disp->crtc[i]; - u64 offset; - - ret = nv50_evo_channel_new(dev, 1 + i, &dispc->sync); - if (ret) - goto err; - - ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, - 0, 0x0000, NULL, &dispc->sem.bo); - if (!ret) { - ret = nouveau_bo_pin(dispc->sem.bo, TTM_PL_FLAG_VRAM); - if (!ret) - ret = nouveau_bo_map(dispc->sem.bo); - if (ret) - nouveau_bo_ref(NULL, &dispc->sem.bo); - offset = dispc->sem.bo->bo.offset; - } - - if (ret) - goto err; - - ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoSync, 0x0000, - offset, 4096, NULL); - if (ret) - goto err; - - ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoVRAM_LP, 0x80000000, - 0, pfb->ram.size, NULL); - if (ret) - goto err; - - ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB32, 0x80000000 | - (nv_device(drm->device)->chipset < 0xc0 ? - 0x7a : 0xfe), - 0, pfb->ram.size, NULL); - if (ret) - goto err; - - ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB16, 0x80000000 | - (nv_device(drm->device)->chipset < 0xc0 ? - 0x70 : 0xfe), - 0, pfb->ram.size, NULL); - if (ret) - goto err; - - for (j = 0; j < 4096; j += 4) - nouveau_bo_wr32(dispc->sem.bo, j / 4, 0x74b1e000); - dispc->sem.offset = 0; - } - - return 0; - -err: - nv50_evo_destroy(dev); - return ret; -} - -int -nv50_evo_init(struct drm_device *dev) -{ - struct nv50_display *disp = nv50_display(dev); - int ret, i; - - ret = nv50_evo_channel_init(disp->master); - if (ret) - return ret; - - for (i = 0; i < 2; i++) { - ret = nv50_evo_channel_init(disp->crtc[i].sync); - if (ret) - return ret; - } - - return 0; -} - -void -nv50_evo_fini(struct drm_device *dev) -{ - struct nv50_display *disp = nv50_display(dev); - int i; - - for (i = 0; i < 2; i++) { - if (disp->crtc[i].sync) - nv50_evo_channel_fini(disp->crtc[i].sync); - } - - if (disp->master) - nv50_evo_channel_fini(disp->master); -} diff --git a/drivers/gpu/drm/nouveau/nv50_evo.h b/drivers/gpu/drm/nouveau/nv50_evo.h deleted file mode 100644 index 771d879bc834..000000000000 --- a/drivers/gpu/drm/nouveau/nv50_evo.h +++ /dev/null @@ -1,120 +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. - * - */ - -#ifndef __NV50_EVO_H__ -#define __NV50_EVO_H__ - -#define NV50_EVO_UPDATE 0x00000080 -#define NV50_EVO_UNK84 0x00000084 -#define NV50_EVO_UNK84_NOTIFY 0x40000000 -#define NV50_EVO_UNK84_NOTIFY_DISABLED 0x00000000 -#define NV50_EVO_UNK84_NOTIFY_ENABLED 0x40000000 -#define NV50_EVO_DMA_NOTIFY 0x00000088 -#define NV50_EVO_DMA_NOTIFY_HANDLE 0xffffffff -#define NV50_EVO_DMA_NOTIFY_HANDLE_NONE 0x00000000 -#define NV50_EVO_UNK8C 0x0000008C - -#define NV50_EVO_DAC(n, r) ((n) * 0x80 + NV50_EVO_DAC_##r) -#define NV50_EVO_DAC_MODE_CTRL 0x00000400 -#define NV50_EVO_DAC_MODE_CTRL_CRTC0 0x00000001 -#define NV50_EVO_DAC_MODE_CTRL_CRTC1 0x00000002 -#define NV50_EVO_DAC_MODE_CTRL2 0x00000404 -#define NV50_EVO_DAC_MODE_CTRL2_NHSYNC 0x00000001 -#define NV50_EVO_DAC_MODE_CTRL2_NVSYNC 0x00000002 - -#define NV50_EVO_SOR(n, r) ((n) * 0x40 + NV50_EVO_SOR_##r) -#define NV50_EVO_SOR_MODE_CTRL 0x00000600 -#define NV50_EVO_SOR_MODE_CTRL_CRTC0 0x00000001 -#define NV50_EVO_SOR_MODE_CTRL_CRTC1 0x00000002 -#define NV50_EVO_SOR_MODE_CTRL_TMDS 0x00000100 -#define NV50_EVO_SOR_MODE_CTRL_TMDS_DUAL_LINK 0x00000400 -#define NV50_EVO_SOR_MODE_CTRL_NHSYNC 0x00001000 -#define NV50_EVO_SOR_MODE_CTRL_NVSYNC 0x00002000 - -#define NV50_EVO_CRTC(n, r) ((n) * 0x400 + NV50_EVO_CRTC_##r) -#define NV84_EVO_CRTC(n, r) ((n) * 0x400 + NV84_EVO_CRTC_##r) -#define NV50_EVO_CRTC_UNK0800 0x00000800 -#define NV50_EVO_CRTC_CLOCK 0x00000804 -#define NV50_EVO_CRTC_INTERLACE 0x00000808 -#define NV50_EVO_CRTC_DISPLAY_START 0x00000810 -#define NV50_EVO_CRTC_DISPLAY_TOTAL 0x00000814 -#define NV50_EVO_CRTC_SYNC_DURATION 0x00000818 -#define NV50_EVO_CRTC_SYNC_START_TO_BLANK_END 0x0000081c -#define NV50_EVO_CRTC_UNK0820 0x00000820 -#define NV50_EVO_CRTC_UNK0824 0x00000824 -#define NV50_EVO_CRTC_UNK082C 0x0000082c -#define NV50_EVO_CRTC_CLUT_MODE 0x00000840 -/* You can't have a palette in 8 bit mode (=OFF) */ -#define NV50_EVO_CRTC_CLUT_MODE_BLANK 0x00000000 -#define NV50_EVO_CRTC_CLUT_MODE_OFF 0x80000000 -#define NV50_EVO_CRTC_CLUT_MODE_ON 0xC0000000 -#define NV50_EVO_CRTC_CLUT_OFFSET 0x00000844 -#define NV84_EVO_CRTC_CLUT_DMA 0x0000085C -#define NV84_EVO_CRTC_CLUT_DMA_HANDLE 0xffffffff -#define NV84_EVO_CRTC_CLUT_DMA_HANDLE_NONE 0x00000000 -#define NV50_EVO_CRTC_FB_OFFSET 0x00000860 -#define NV50_EVO_CRTC_FB_SIZE 0x00000868 -#define NV50_EVO_CRTC_FB_CONFIG 0x0000086c -#define NV50_EVO_CRTC_FB_CONFIG_MODE 0x00100000 -#define NV50_EVO_CRTC_FB_CONFIG_MODE_TILE 0x00000000 -#define NV50_EVO_CRTC_FB_CONFIG_MODE_PITCH 0x00100000 -#define NV50_EVO_CRTC_FB_DEPTH 0x00000870 -#define NV50_EVO_CRTC_FB_DEPTH_8 0x00001e00 -#define NV50_EVO_CRTC_FB_DEPTH_15 0x0000e900 -#define NV50_EVO_CRTC_FB_DEPTH_16 0x0000e800 -#define NV50_EVO_CRTC_FB_DEPTH_24 0x0000cf00 -#define NV50_EVO_CRTC_FB_DEPTH_30 0x0000d100 -#define NV50_EVO_CRTC_FB_DMA 0x00000874 -#define NV50_EVO_CRTC_FB_DMA_HANDLE 0xffffffff -#define NV50_EVO_CRTC_FB_DMA_HANDLE_NONE 0x00000000 -#define NV50_EVO_CRTC_CURSOR_CTRL 0x00000880 -#define NV50_EVO_CRTC_CURSOR_CTRL_HIDE 0x05000000 -#define NV50_EVO_CRTC_CURSOR_CTRL_SHOW 0x85000000 -#define NV50_EVO_CRTC_CURSOR_OFFSET 0x00000884 -#define NV84_EVO_CRTC_CURSOR_DMA 0x0000089c -#define NV84_EVO_CRTC_CURSOR_DMA_HANDLE 0xffffffff -#define NV84_EVO_CRTC_CURSOR_DMA_HANDLE_NONE 0x00000000 -#define NV50_EVO_CRTC_DITHER_CTRL 0x000008a0 -#define NV50_EVO_CRTC_DITHER_CTRL_OFF 0x00000000 -#define NV50_EVO_CRTC_DITHER_CTRL_ON 0x00000011 -#define NV50_EVO_CRTC_SCALE_CTRL 0x000008a4 -#define NV50_EVO_CRTC_SCALE_CTRL_INACTIVE 0x00000000 -#define NV50_EVO_CRTC_SCALE_CTRL_ACTIVE 0x00000009 -#define NV50_EVO_CRTC_COLOR_CTRL 0x000008a8 -#define NV50_EVO_CRTC_COLOR_CTRL_VIBRANCE 0x000fff00 -#define NV50_EVO_CRTC_COLOR_CTRL_HUE 0xfff00000 -#define NV50_EVO_CRTC_FB_POS 0x000008c0 -#define NV50_EVO_CRTC_REAL_RES 0x000008c8 -#define NV50_EVO_CRTC_SCALE_CENTER_OFFSET 0x000008d4 -#define NV50_EVO_CRTC_SCALE_CENTER_OFFSET_VAL(x, y) \ - ((((unsigned)y << 16) & 0xFFFF0000) | (((unsigned)x) & 0x0000FFFF)) -/* Both of these are needed, otherwise nothing happens. */ -#define NV50_EVO_CRTC_SCALE_RES1 0x000008d8 -#define NV50_EVO_CRTC_SCALE_RES2 0x000008dc -#define NV50_EVO_CRTC_UNK900 0x00000900 -#define NV50_EVO_CRTC_UNK904 0x00000904 - -#endif diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c index e0763ea88ee2..43936badef82 100644 --- a/drivers/gpu/drm/nouveau/nv50_fence.c +++ b/drivers/gpu/drm/nouveau/nv50_fence.c @@ -70,7 +70,7 @@ nv50_fence_context_new(struct nouveau_channel *chan) /* dma objects for display sync channel semaphore blocks */ for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) { - struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); + struct nouveau_bo *bo = nvd0_display_crtc_sema(dev, i); ret = nouveau_object_new(nv_object(chan->cli), chan->handle, NvEvoSema0 + i, 0x003d, diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c index c4a65039b1ca..8bd5d2781baf 100644 --- a/drivers/gpu/drm/nouveau/nv50_pm.c +++ b/drivers/gpu/drm/nouveau/nv50_pm.c @@ -546,7 +546,7 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl, { struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_device *device = nouveau_dev(dev); - u32 crtc_mask = nv50_display_active_crtcs(dev); + u32 crtc_mask = 0; /*XXX: nv50_display_active_crtcs(dev); */ struct nouveau_mem_exec_func exec = { .dev = dev, .precharge = mclk_precharge, diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c deleted file mode 100644 index 5499c23cb795..000000000000 --- a/drivers/gpu/drm/nouveau/nv50_sor.c +++ /dev/null @@ -1,339 +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 <drm/drmP.h> -#include <drm/drm_crtc_helper.h> - -#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) -#include "nouveau_reg.h" -#include "nouveau_drm.h" -#include "nouveau_dma.h" -#include "nouveau_encoder.h" -#include "nouveau_connector.h" -#include "nouveau_crtc.h" -#include "nv50_display.h" - -#include <core/class.h> - -#include <subdev/timer.h> - -static void -nv50_sor_disconnect(struct drm_encoder *encoder) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_drm *drm = nouveau_drm(encoder->dev); - struct drm_device *dev = encoder->dev; - struct nouveau_channel *evo = nv50_display(dev)->master; - int ret; - - if (!nv_encoder->crtc) - return; - nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true); - - NV_DEBUG(drm, "Disconnecting SOR %d\n", nv_encoder->or); - - ret = RING_SPACE(evo, 4); - if (ret) { - NV_ERROR(drm, "no space while disconnecting SOR\n"); - return; - } - BEGIN_NV04(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); - OUT_RING (evo, 0); - BEGIN_NV04(evo, 0, NV50_EVO_UPDATE, 1); - OUT_RING (evo, 0); - - nouveau_hdmi_mode_set(encoder, NULL); - - nv_encoder->crtc = NULL; - nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; -} - -static void -nv50_sor_dpms(struct drm_encoder *encoder, int mode) -{ - struct nv50_display *priv = nv50_display(encoder->dev); - struct nouveau_drm *drm = nouveau_drm(encoder->dev); - struct drm_device *dev = encoder->dev; - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct drm_encoder *enc; - int or = nv_encoder->or; - - NV_DEBUG(drm, "or %d type %d mode %d\n", or, nv_encoder->dcb->type, mode); - - nv_encoder->last_dpms = mode; - list_for_each_entry(enc, &dev->mode_config.encoder_list, head) { - struct nouveau_encoder *nvenc = nouveau_encoder(enc); - - if (nvenc == nv_encoder || - (nvenc->dcb->type != DCB_OUTPUT_TMDS && - nvenc->dcb->type != DCB_OUTPUT_LVDS && - nvenc->dcb->type != DCB_OUTPUT_DP) || - nvenc->dcb->or != nv_encoder->dcb->or) - continue; - - if (nvenc->last_dpms == DRM_MODE_DPMS_ON) - return; - } - - nv_call(priv->core, NV50_DISP_SOR_PWR + or, (mode == DRM_MODE_DPMS_ON)); - - if (nv_encoder->dcb->type == DCB_OUTPUT_DP) - nouveau_dp_dpms(encoder, mode, nv_encoder->dp.datarate, priv->core); -} - -static void -nv50_sor_save(struct drm_encoder *encoder) -{ - struct nouveau_drm *drm = nouveau_drm(encoder->dev); - NV_ERROR(drm, "!!\n"); -} - -static void -nv50_sor_restore(struct drm_encoder *encoder) -{ - struct nouveau_drm *drm = nouveau_drm(encoder->dev); - NV_ERROR(drm, "!!\n"); -} - -static bool -nv50_sor_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct nouveau_drm *drm = nouveau_drm(encoder->dev); - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_connector *connector; - - NV_DEBUG(drm, "or %d\n", nv_encoder->or); - - connector = nouveau_encoder_connector_get(nv_encoder); - if (!connector) { - NV_ERROR(drm, "Encoder has no connector\n"); - return false; - } - - if (connector->scaling_mode != DRM_MODE_SCALE_NONE && - connector->native_mode) - drm_mode_copy(adjusted_mode, connector->native_mode); - - return true; -} - -static void -nv50_sor_prepare(struct drm_encoder *encoder) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - nv50_sor_disconnect(encoder); - if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { - /* avoid race between link training and supervisor intr */ - nv50_display_sync(encoder->dev); - } -} - -static void -nv50_sor_commit(struct drm_encoder *encoder) -{ -} - -static void -nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, - struct drm_display_mode *mode) -{ - struct nouveau_channel *evo = nv50_display(encoder->dev)->master; - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_drm *drm = nouveau_drm(encoder->dev); - struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); - struct nouveau_connector *nv_connector; - struct nv50_display *disp = nv50_display(encoder->dev); - struct nvbios *bios = &drm->vbios; - uint32_t mode_ctl = 0, script; - int ret; - - NV_DEBUG(drm, "or %d type %d -> crtc %d\n", - nv_encoder->or, nv_encoder->dcb->type, crtc->index); - nv_encoder->crtc = encoder->crtc; - - switch (nv_encoder->dcb->type) { - case DCB_OUTPUT_TMDS: - if (nv_encoder->dcb->sorconf.link & 1) { - if (mode->clock < 165000) - mode_ctl = 0x0100; - else - mode_ctl = 0x0500; - } else - mode_ctl = 0x0200; - - nouveau_hdmi_mode_set(encoder, mode); - break; - case DCB_OUTPUT_LVDS: - script = 0x0000; - if (bios->fp_no_ddc) { - if (bios->fp.dual_link) - script |= 0x0100; - if (bios->fp.if_is_24bit) - script |= 0x0200; - } else { - /* determine number of lvds links */ - nv_connector = nouveau_encoder_connector_get(nv_encoder); - if (nv_connector && nv_connector->edid && - nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) { - /* http://www.spwg.org */ - if (((u8 *)nv_connector->edid)[121] == 2) - script |= 0x0100; - } else - if (mode->clock >= bios->fp.duallink_transition_clk) { - script |= 0x0100; - } - - /* determine panel depth */ - if (script & 0x0100) { - if (bios->fp.strapless_is_24bit & 2) - script |= 0x0200; - } else { - if (bios->fp.strapless_is_24bit & 1) - script |= 0x0200; - } - - if (nv_connector && nv_connector->edid && - (nv_connector->edid->revision >= 4) && - (nv_connector->edid->input & 0x70) >= 0x20) - script |= 0x0200; - } - - nv_call(disp->core, NV50_DISP_SOR_LVDS_SCRIPT + nv_encoder->or, script); - break; - case DCB_OUTPUT_DP: - nv_connector = nouveau_encoder_connector_get(nv_encoder); - if (nv_connector && nv_connector->base.display_info.bpc == 6) { - nv_encoder->dp.datarate = mode->clock * 18 / 8; - mode_ctl |= 0x00020000; - } else { - nv_encoder->dp.datarate = mode->clock * 24 / 8; - mode_ctl |= 0x00050000; - } - - if (nv_encoder->dcb->sorconf.link & 1) - mode_ctl |= 0x00000800; - else - mode_ctl |= 0x00000900; - break; - default: - break; - } - - if (crtc->index == 1) - mode_ctl |= NV50_EVO_SOR_MODE_CTRL_CRTC1; - else - mode_ctl |= NV50_EVO_SOR_MODE_CTRL_CRTC0; - - if (mode->flags & DRM_MODE_FLAG_NHSYNC) - mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NHSYNC; - - if (mode->flags & DRM_MODE_FLAG_NVSYNC) - mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NVSYNC; - - nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON); - - ret = RING_SPACE(evo, 2); - if (ret) { - NV_ERROR(drm, "no space while connecting SOR\n"); - nv_encoder->crtc = NULL; - return; - } - BEGIN_NV04(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); - OUT_RING(evo, mode_ctl); -} - -static struct drm_crtc * -nv50_sor_crtc_get(struct drm_encoder *encoder) -{ - return nouveau_encoder(encoder)->crtc; -} - -static const struct drm_encoder_helper_funcs nv50_sor_helper_funcs = { - .dpms = nv50_sor_dpms, - .save = nv50_sor_save, - .restore = nv50_sor_restore, - .mode_fixup = nv50_sor_mode_fixup, - .prepare = nv50_sor_prepare, - .commit = nv50_sor_commit, - .mode_set = nv50_sor_mode_set, - .get_crtc = nv50_sor_crtc_get, - .detect = NULL, - .disable = nv50_sor_disconnect -}; - -static void -nv50_sor_destroy(struct drm_encoder *encoder) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - - drm_encoder_cleanup(encoder); - kfree(nv_encoder); -} - -static const struct drm_encoder_funcs nv50_sor_encoder_funcs = { - .destroy = nv50_sor_destroy, -}; - -int -nv50_sor_create(struct drm_connector *connector, struct dcb_output *entry) -{ - struct nouveau_encoder *nv_encoder = NULL; - struct drm_device *dev = connector->dev; - struct drm_encoder *encoder; - int type; - - switch (entry->type) { - case DCB_OUTPUT_TMDS: - case DCB_OUTPUT_DP: - type = DRM_MODE_ENCODER_TMDS; - break; - case DCB_OUTPUT_LVDS: - type = DRM_MODE_ENCODER_LVDS; - break; - default: - return -EINVAL; - } - - nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); - if (!nv_encoder) - return -ENOMEM; - encoder = to_drm_encoder(nv_encoder); - - nv_encoder->dcb = entry; - nv_encoder->or = ffs(entry->or) - 1; - nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; - - drm_encoder_init(dev, encoder, &nv50_sor_encoder_funcs, type); - drm_encoder_helper_add(encoder, &nv50_sor_helper_funcs); - - encoder->possible_crtcs = entry->heads; - encoder->possible_clones = 0; - - drm_mode_connector_attach_encoder(connector, encoder); - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c index c686650584b6..edaf5a1363f0 100644 --- a/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/drivers/gpu/drm/nouveau/nv84_fence.c @@ -127,7 +127,7 @@ nv84_fence_context_new(struct nouveau_channel *chan) /* dma objects for display sync channel semaphore blocks */ for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) { - struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); + struct nouveau_bo *bo = nvd0_display_crtc_sema(dev, i); ret = nouveau_object_new(nv_object(chan->cli), chan->handle, NvEvoSema0 + i, 0x003d, diff --git a/drivers/gpu/drm/nouveau/nvc0_fence.c b/drivers/gpu/drm/nouveau/nvc0_fence.c index 53299eac9676..25180f0ad95d 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fence.c +++ b/drivers/gpu/drm/nouveau/nvc0_fence.c @@ -114,17 +114,9 @@ nvc0_fence_context_del(struct nouveau_channel *chan) struct nvc0_fence_chan *fctx = chan->fence; int i; - if (nv_device(chan->drm->device)->card_type >= NV_D0) { - for (i = 0; i < dev->mode_config.num_crtc; i++) { - struct nouveau_bo *bo = nvd0_display_crtc_sema(dev, i); - nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); - } - } else - if (nv_device(chan->drm->device)->card_type >= NV_50) { - for (i = 0; i < dev->mode_config.num_crtc; i++) { - struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); - nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); - } + for (i = 0; i < dev->mode_config.num_crtc; i++) { + struct nouveau_bo *bo = nvd0_display_crtc_sema(dev, i); + nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); } nouveau_bo_vma_del(priv->bo, &fctx->vma); @@ -154,12 +146,7 @@ nvc0_fence_context_new(struct nouveau_channel *chan) /* map display semaphore buffers into channel's vm */ for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { - struct nouveau_bo *bo; - if (nv_device(chan->drm->device)->card_type >= NV_D0) - bo = nvd0_display_crtc_sema(chan->drm->dev, i); - else - bo = nv50_display_crtc_sema(chan->drm->dev, i); - + struct nouveau_bo *bo = nvd0_display_crtc_sema(chan->drm->dev, i); ret = nouveau_bo_vma_add(bo, client->vm, &fctx->dispc_vma[i]); } |