Skip to content
This repository
Browse code

add nvd0 display support

  • Loading branch information...
commit e6181245d4e88c69b2024438a6b261d95f1436bb 1 parent 9e97954
Maarten Lankhorst mlankhorst authored
2  pscnv/Makefile
@@ -7,7 +7,7 @@ pscnv-y := nouveau_drv.o nouveau_state.o \
7 7 nv10_gpio.o \
8 8 nv50_gpio.o nv50_grctx.o \
9 9 nv50_display.o nv50_crtc.o nv50_cursor.o nv50_calc.o nv50_dac.o \
10   - nv50_sor.o \
  10 + nv50_sor.o nvd0_display.o \
11 11 nv04_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o \
12 12 pscnv_mm.o pscnv_mem.o pscnv_vm.o pscnv_gem.o pscnv_ioctl.o \
13 13 pscnv_ramht.o pscnv_chan.o pscnv_sysram.o \
25 pscnv/nouveau_bios.c
@@ -301,6 +301,11 @@ munge_reg(struct nvbios *bios, uint32_t reg)
301 301 if (dev_priv->card_type < NV_50)
302 302 return reg;
303 303
  304 + if (reg & 0x80000000) {
  305 + BUG_ON(bios->display.crtc < 0);
  306 + reg += bios->display.crtc * 0x800;
  307 + }
  308 +
304 309 if (reg & 0x40000000) {
305 310 BUG_ON(!dcbent);
306 311
@@ -309,7 +314,7 @@ munge_reg(struct nvbios *bios, uint32_t reg)
309 314 reg += 0x00000080;
310 315 }
311 316
312   - reg &= ~0x60000000;
  317 + reg &= ~0xe0000000;
313 318 return reg;
314 319 }
315 320
@@ -4500,7 +4505,7 @@ nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent,
4500 4505
4501 4506 int
4502 4507 nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
4503   - uint32_t sub, int pxclk)
  4508 + int crtc, uint32_t sub, int pxclk)
4504 4509 {
4505 4510 /*
4506 4511 * The display script table is located by the BIT 'U' table.
@@ -4613,7 +4618,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
4613 4618 }
4614 4619
4615 4620 NV_DEBUG_KMS(dev, "0x%04X: parsing output script 0\n", script);
4616   - nouveau_bios_run_init_table(dev, script, dcbent);
  4621 + nouveau_bios_run_init_table(dev, script, dcbent, crtc);
4617 4622 } else
4618 4623 if (pxclk == -1) {
4619 4624 script = ROM16(otable[8]);
@@ -4623,7 +4628,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
4623 4628 }
4624 4629
4625 4630 NV_DEBUG_KMS(dev, "0x%04X: parsing output script 1\n", script);
4626   - nouveau_bios_run_init_table(dev, script, dcbent);
  4631 + nouveau_bios_run_init_table(dev, script, dcbent, crtc);
4627 4632 } else
4628 4633 if (pxclk == -2) {
4629 4634 if (table[4] >= 12)
@@ -4636,7 +4641,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
4636 4641 }
4637 4642
4638 4643 NV_DEBUG_KMS(dev, "0x%04X: parsing output script 2\n", script);
4639   - nouveau_bios_run_init_table(dev, script, dcbent);
  4644 + nouveau_bios_run_init_table(dev, script, dcbent, crtc);
4640 4645 } else
4641 4646 if (pxclk > 0) {
4642 4647 script = ROM16(otable[table[4] + i*6 + 2]);
@@ -4648,7 +4653,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
4648 4653 }
4649 4654
4650 4655 NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 0\n", script);
4651   - nouveau_bios_run_init_table(dev, script, dcbent);
  4656 + nouveau_bios_run_init_table(dev, script, dcbent, crtc);
4652 4657 } else
4653 4658 if (pxclk < 0) {
4654 4659 script = ROM16(otable[table[4] + i*6 + 4]);
@@ -4660,7 +4665,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
4660 4665 }
4661 4666
4662 4667 NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 1\n", script);
4663   - nouveau_bios_run_init_table(dev, script, dcbent);
  4668 + nouveau_bios_run_init_table(dev, script, dcbent, crtc);
4664 4669 }
4665 4670
4666 4671 return 0;
@@ -6766,7 +6771,7 @@ uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev)
6766 6771
6767 6772 void
6768 6773 nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table,
6769   - struct dcb_entry *dcbent)
  6774 + struct dcb_entry *dcbent, int crtc)
6770 6775 {
6771 6776 struct drm_nouveau_private *dev_priv = dev->dev_private;
6772 6777 struct nvbios *bios = &dev_priv->vbios;
@@ -6774,7 +6779,9 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table,
6774 6779
6775 6780 mutex_lock(&bios->lock);
6776 6781 bios->display.output = dcbent;
  6782 + bios->display.crtc = crtc;
6777 6783 parse_init_table(bios, table, &iexec);
  6784 + bios->display.crtc = -1;
6778 6785 bios->display.output = NULL;
6779 6786 mutex_unlock(&bios->lock);
6780 6787 }
@@ -6862,7 +6869,7 @@ nouveau_run_vbios_init(struct drm_device *dev)
6862 6869 for (i = 0; i < bios->dcb.entries; i++) {
6863 6870 nouveau_bios_run_display_table(dev,
6864 6871 &bios->dcb.entry[i],
6865   - 0, 0);
  6872 + -1, 0, 0);
6866 6873 }
6867 6874 }
6868 6875
6 pscnv/nouveau_bios.h
@@ -84,11 +84,16 @@ enum dcb_connector_type {
84 84 DCB_CONNECTOR_TV_3 = 0x13,
85 85 DCB_CONNECTOR_DVI_I = 0x30,
86 86 DCB_CONNECTOR_DVI_D = 0x31,
  87 + DCB_CONNECTOR_DMS59_0 = 0x38,
  88 + DCB_CONNECTOR_DMS59_1 = 0x39,
87 89 DCB_CONNECTOR_LVDS = 0x40,
  90 + DCB_CONNECTOR_LVDS_SPWG = 0x41,
88 91 DCB_CONNECTOR_DP = 0x46,
89 92 DCB_CONNECTOR_eDP = 0x47,
90 93 DCB_CONNECTOR_HDMI_0 = 0x60,
91 94 DCB_CONNECTOR_HDMI_1 = 0x61,
  95 + DCB_CONNECTOR_DMS59_DP0 = 0x64,
  96 + DCB_CONNECTOR_DMS59_DP1 = 0x65,
92 97 DCB_CONNECTOR_NONE = 0xff
93 98 };
94 99
@@ -293,6 +298,7 @@ struct nvbios {
293 298 struct dcb_entry *output;
294 299 uint16_t script_table_ptr;
295 300 uint16_t dp_table_ptr;
  301 + int crtc;
296 302 } display;
297 303
298 304 struct {
2  pscnv/nouveau_dma.h
@@ -80,6 +80,8 @@ enum {
80 80 NvEvoFB16 = 0x01000001,
81 81 NvEvoFB32 = 0x01000002,
82 82 NvEvoFE = 0x01000003,
  83 +
  84 + NvEvoSync = 0xcafe0000,
83 85 };
84 86
85 87 #if 0
7 pscnv/nouveau_dp.c
@@ -26,6 +26,7 @@
26 26
27 27 #include "nouveau_drv.h"
28 28 #include "nouveau_reg.h"
  29 +#include "nouveau_crtc.h"
29 30 #include "nouveau_i2c.h"
30 31 #include "nouveau_connector.h"
31 32 #include "nouveau_encoder.h"
@@ -303,7 +304,8 @@ nouveau_dp_link_train(struct drm_encoder *encoder)
303 304 if (dpe->script0) {
304 305 NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or);
305 306 nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0),
306   - nv_encoder->dcb);
  307 + nv_encoder->dcb,
  308 + nouveau_crtc(encoder->crtc)->index);
307 309 }
308 310
309 311 train:
@@ -436,7 +438,8 @@ nouveau_dp_link_train(struct drm_encoder *encoder)
436 438 if (dpe->script1) {
437 439 NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or);
438 440 nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1),
439   - nv_encoder->dcb);
  441 + nv_encoder->dcb,
  442 + nouveau_crtc(encoder->crtc)->index);
440 443 }
441 444
442 445 /* re-enable hotplug detect */
19 pscnv/nouveau_drv.h
@@ -132,6 +132,8 @@ struct nouveau_display_engine {
132 132 /* not really hue and saturation: */
133 133 struct drm_property *vibrant_hue_property;
134 134 struct drm_property *color_vibrance_property;
  135 +
  136 + void *priv;
135 137 };
136 138
137 139 struct nouveau_gpio_engine {
@@ -869,7 +871,7 @@ extern int nouveau_bios_init(struct drm_device *);
869 871 extern void nouveau_bios_takedown(struct drm_device *dev);
870 872 extern int nouveau_run_vbios_init(struct drm_device *);
871 873 extern void nouveau_bios_run_init_table(struct drm_device *, uint16_t table,
872   - struct dcb_entry *);
  874 + struct dcb_entry *, int crtc);
873 875 extern struct dcb_gpio_entry *nouveau_bios_gpio_entry(struct drm_device *,
874 876 enum dcb_gpio_tag);
875 877 extern struct dcb_connector_table_entry *
@@ -878,7 +880,7 @@ extern u32 get_pll_register(struct drm_device *, enum pll_types);
878 880 extern int get_pll_limits(struct drm_device *, uint32_t limit_match,
879 881 struct pll_lims *);
880 882 extern int nouveau_bios_run_display_table(struct drm_device *,
881   - struct dcb_entry *,
  883 + struct dcb_entry *, int crtc,
882 884 uint32_t script, int pxclk);
883 885 extern void *nouveau_bios_dp_table(struct drm_device *, struct dcb_entry *,
884 886 int *length);
@@ -1109,6 +1111,19 @@ extern int nv04_display_create(struct drm_device *);
1109 1111 extern int nv04_display_init(struct drm_device *);
1110 1112 extern void nv04_display_destroy(struct drm_device *);
1111 1113
  1114 +/* nvd0_display.c */
  1115 +extern int nvd0_display_create(struct drm_device *);
  1116 +extern void nvd0_display_destroy(struct drm_device *);
  1117 +extern int nvd0_display_init(struct drm_device *);
  1118 +extern void nvd0_display_fini(struct drm_device *);
  1119 +extern void nvd0_display_bh(struct work_struct *work);
  1120 +#if 0
  1121 +struct nouveau_bo *nvd0_display_crtc_sema(struct drm_device *, int crtc);
  1122 +void nvd0_display_flip_stop(struct drm_crtc *);
  1123 +int nvd0_display_flip_next(struct drm_crtc *, struct drm_framebuffer *,
  1124 + struct nouveau_channel *, u32 swap_interval);
  1125 +#endif
  1126 +
1112 1127 /* nv04_crtc.c */
1113 1128 extern int nv04_crtc_create(struct drm_device *, int index);
1114 1129
1  pscnv/nouveau_encoder.h
@@ -56,6 +56,7 @@ struct nouveau_encoder {
56 56 int link_nr;
57 57 int link_bw;
58 58 bool enhanced_frame;
  59 + uint32_t datarate; // TODO
59 60 } dp;
60 61 };
61 62 };
5 pscnv/nouveau_irq.c
@@ -59,7 +59,10 @@ nouveau_irq_preinstall(struct drm_device *dev)
59 59 nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
60 60
61 61 if (dev_priv->card_type >= NV_50) {
62   - INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh);
  62 + if (dev_priv->card_type < NV_D0)
  63 + INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh);
  64 + else
  65 + INIT_WORK(&dev_priv->irq_work, nvd0_display_bh);
63 66 INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh);
64 67 // INIT_LIST_HEAD(&dev_priv->vbl_waiting);
65 68 }
8 pscnv/nouveau_state.c
@@ -131,12 +131,18 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
131 131 #endif
132 132 NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
133 133 return -ENOSYS;
134   - } else {
  134 + } else if (dev_priv->chipset < 0xd0) {
135 135 engine->display.early_init = nv50_display_early_init;
136 136 engine->display.late_takedown = nv50_display_late_takedown;
137 137 engine->display.create = nv50_display_create;
138 138 engine->display.init = nv50_display_init;
139 139 engine->display.destroy = nv50_display_destroy;
  140 + } else {
  141 + engine->display.early_init = nouveau_stub_init;
  142 + engine->display.late_takedown = nouveau_stub_takedown;
  143 + engine->display.create = nvd0_display_create;
  144 + engine->display.init = nvd0_display_init;
  145 + engine->display.destroy = nvd0_display_destroy;
140 146 }
141 147
142 148 return 0;
13 pscnv/nv50_display.c
@@ -751,7 +751,7 @@ nv50_display_unk10_handler(struct drm_device *dev)
751 751 struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i];
752 752
753 753 if (dcb->type == type && (dcb->or & (1 << or))) {
754   - nouveau_bios_run_display_table(dev, dcb, 0, -1);
  754 + nouveau_bios_run_display_table(dev, dcb, -1, 0, -1);
755 755 dev_priv->evo_irq.dcb = dcb;
756 756 goto ack;
757 757 }
@@ -805,7 +805,7 @@ nv50_display_unk20_handler(struct drm_device *dev)
805 805 NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);
806 806 dcb = dev_priv->evo_irq.dcb;
807 807 if (dcb) {
808   - nouveau_bios_run_display_table(dev, dcb, 0, -2);
  808 + nouveau_bios_run_display_table(dev, dcb, -1, 0, -2);
809 809 dev_priv->evo_irq.dcb = NULL;
810 810 }
811 811
@@ -889,7 +889,7 @@ nv50_display_unk20_handler(struct drm_device *dev)
889 889 }
890 890
891 891 script = nv50_display_script_select(dev, dcb, mc, pclk);
892   - nouveau_bios_run_display_table(dev, dcb, script, pclk);
  892 + nouveau_bios_run_display_table(dev, dcb, -1, script, pclk);
893 893
894 894 nv50_display_unk20_dp_hack(dev, dcb);
895 895
@@ -956,7 +956,7 @@ nv50_display_unk40_handler(struct drm_device *dev)
956 956 if (!dcb)
957 957 goto ack;
958 958
959   - nouveau_bios_run_display_table(dev, dcb, script, -pclk);
  959 + nouveau_bios_run_display_table(dev, dcb, -1, script, -pclk);
960 960 nv50_display_unk40_dp_set_tmds(dev, dcb);
961 961
962 962 ack:
@@ -1015,7 +1015,6 @@ nv50_display_irq_hotplug_bh(struct work_struct *work)
1015 1015 container_of(work, struct drm_nouveau_private, hpd_work);
1016 1016 struct drm_device *dev = dev_priv->dev;
1017 1017 struct drm_connector *connector;
1018   - const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
1019 1018 uint32_t unplug_mask, plug_mask, change_mask;
1020 1019 uint32_t hpd0, hpd1 = 0;
1021 1020
@@ -1033,7 +1032,6 @@ nv50_display_irq_hotplug_bh(struct work_struct *work)
1033 1032 nouveau_connector(connector);
1034 1033 struct nouveau_encoder *nv_encoder;
1035 1034 struct dcb_gpio_entry *gpio;
1036   - uint32_t reg;
1037 1035 bool plugged;
1038 1036
1039 1037 if (!nv_connector->dcb)
@@ -1043,8 +1041,7 @@ nv50_display_irq_hotplug_bh(struct work_struct *work)
1043 1041 if (!gpio || !(change_mask & (1 << gpio->line)))
1044 1042 continue;
1045 1043
1046   - reg = nv_rd32(dev, gpio_reg[gpio->line >> 3]);
1047   - plugged = !!(reg & (4 << ((gpio->line & 7) << 2)));
  1044 + plugged = dev_priv->engine.gpio.get(dev, nv_connector->dcb->gpio_tag);
1048 1045 NV_INFO(dev, "%splugged %s\n", plugged ? "" : "un",
1049 1046 drm_get_connector_name(connector)) ;
1050 1047
8 pscnv/nv50_pm.c
@@ -809,12 +809,12 @@ nv50_pm_clocks_set(struct drm_device *dev, void *data)
809 809 /* execute some scripts that do ??? from the vbios.. */
810 810 if (!bit_table(dev, 'M', &M) && M.version == 1) {
811 811 if (M.length >= 6 && (script = ROM16(M.data[5])))
812   - nouveau_bios_run_init_table(dev, script, NULL);
  812 + nouveau_bios_run_init_table(dev, script, NULL, -1);
813 813 if (M.length >= 8 && (script = ROM16(M.data[7])))
814   - nouveau_bios_run_init_table(dev, script, NULL);
  814 + nouveau_bios_run_init_table(dev, script, NULL, -1);
815 815 if (M.length >= 10 && (script = ROM16(M.data[9])))
816   - nouveau_bios_run_init_table(dev, script, NULL);
817   - nouveau_bios_run_init_table(dev, info->mscript, NULL);
  816 + nouveau_bios_run_init_table(dev, script, NULL, -1);
  817 + nouveau_bios_run_init_table(dev, info->mscript, NULL, -1);
818 818 }
819 819
820 820 ret = prog_hwsq(dev, &info->mclk_hwsq);
2,175 pscnv/nvd0_display.c
... ... @@ -0,0 +1,2175 @@
  1 +/*
  2 + * Copyright 2011 Red Hat Inc.
  3 + *
  4 + * Permission is hereby granted, free of charge, to any person obtaining a
  5 + * copy of this software and associated documentation files (the "Software"),
  6 + * to deal in the Software without restriction, including without limitation
  7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8 + * and/or sell copies of the Software, and to permit persons to whom the
  9 + * Software is furnished to do so, subject to the following conditions:
  10 + *
  11 + * The above copyright notice and this permission notice shall be included in
  12 + * all copies or substantial portions of the Software.
  13 + *
  14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 + * OTHER DEALINGS IN THE SOFTWARE.
  21 + *
  22 + * Authors: Ben Skeggs
  23 + */
  24 +
  25 +#include <linux/dma-mapping.h>
  26 +
  27 +#include "drmP.h"
  28 +#include "drm_crtc_helper.h"
  29 +#include "pscnv_mem.h"
  30 +#include "pscnv_vm.h"
  31 +#include "pscnv_chan.h"
  32 +#include "nouveau_drv.h"
  33 +#include "nouveau_connector.h"
  34 +#include "nouveau_encoder.h"
  35 +#include "nouveau_crtc.h"
  36 +#include "nouveau_dma.h"
  37 +#include "nouveau_fb.h"
  38 +#include "nv50_display.h"
  39 +
  40 +#define EVO_DMA_NR 1
  41 +
  42 +#define EVO_MASTER (0x00)
  43 +#define EVO_FLIP(c) (0x01 + (c))
  44 +#define EVO_OVLY(c) (0x05 + (c))
  45 +#define EVO_OIMM(c) (0x09 + (c))
  46 +#define EVO_CURS(c) (0x0d + (c))
  47 +
  48 +/* offsets in shared sync bo of various structures */
  49 +#define EVO_SYNC(c, o) ((c) * 0x0100 + (o))
  50 +#define EVO_MAST_NTFY EVO_SYNC( 0, 0x00)
  51 +#define EVO_FLIP_SEM0(c) EVO_SYNC((c), 0x00)
  52 +#define EVO_FLIP_SEM1(c) EVO_SYNC((c), 0x10)
  53 +
  54 +struct evo {
  55 + int idx;
  56 + dma_addr_t handle;
  57 + u32 *ptr;
  58 + struct {
  59 + u32 offset;
  60 + u16 value;
  61 + } sem;
  62 +};
  63 +
  64 +struct nvd0_display {
  65 + struct pscnv_bo *mem;
  66 + struct pscnv_bo *sync;
  67 + struct evo evo[EVO_DMA_NR];
  68 +
  69 + u32 modeset;
  70 +};
  71 +
  72 +static struct nvd0_display *
  73 +nvd0_display(struct drm_device *dev)
  74 +{
  75 + struct drm_nouveau_private *dev_priv = dev->dev_private;
  76 + return dev_priv->engine.display.priv;
  77 +}
  78 +
  79 +static struct drm_crtc *
  80 +nvd0_display_crtc_get(struct drm_encoder *encoder)
  81 +{
  82 + return nouveau_encoder(encoder)->crtc;
  83 +}
  84 +
  85 +/******************************************************************************
  86 + * EVO channel helpers
  87 + *****************************************************************************/
  88 +static inline int
  89 +evo_icmd(struct drm_device *dev, int id, u32 mthd, u32 data)
  90 +{
  91 + int ret = 0;
  92 + nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000001);
  93 + nv_wr32(dev, 0x610704 + (id * 0x10), data);
  94 + nv_mask(dev, 0x610704 + (id * 0x10), 0x80000ffc, 0x80000000 | mthd);
  95 + if (!nv_wait(dev, 0x610704 + (id * 0x10), 0x80000000, 0x00000000))
  96 + ret = -EBUSY;
  97 + nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000000);
  98 + return ret;
  99 +}
  100 +
  101 +static u32 *
  102 +evo_wait(struct drm_device *dev, int id, int nr)
  103 +{
  104 + struct nvd0_display *disp = nvd0_display(dev);
  105 + u32 put = nv_rd32(dev, 0x640000 + (id * 0x1000)) / 4;
  106 +
  107 + if (put + nr >= (PAGE_SIZE / 4)) {
  108 + disp->evo[id].ptr[put] = 0x20000000;
  109 +
  110 + nv_wr32(dev, 0x640000 + (id * 0x1000), 0x00000000);
  111 + if (!nv_wait(dev, 0x640004 + (id * 0x1000), ~0, 0x00000000)) {
  112 + NV_ERROR(dev, "evo %d dma stalled\n", id);
  113 + return NULL;
  114 + }
  115 +
  116 + put = 0;
  117 + }
  118 +
  119 + if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)
  120 + NV_INFO(dev, "Evo%d: %p START\n", id, disp->evo[id].ptr + put);
  121 +
  122 + return disp->evo[id].ptr + put;
  123 +}
  124 +
  125 +static void
  126 +evo_kick(u32 *push, struct drm_device *dev, int id)
  127 +{
  128 + struct nvd0_display *disp = nvd0_display(dev);
  129 +
  130 + if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) {
  131 + u32 curp = nv_rd32(dev, 0x640000 + (id * 0x1000)) >> 2;
  132 + u32 *cur = disp->evo[id].ptr + curp;
  133 +
  134 + while (cur < push)
  135 + NV_INFO(dev, "Evo%d: 0x%08x\n", id, *cur++);
  136 + NV_INFO(dev, "Evo%d: %p KICK!\n", id, push);
  137 + }
  138 +
  139 + nv_wr32(dev, 0x640000 + (id * 0x1000), (push - disp->evo[id].ptr) << 2);
  140 +}
  141 +
  142 +#define evo_mthd(p,m,s) *((p)++) = (((s) << 18) | (m))
  143 +#define evo_data(p,d) *((p)++) = (d)
  144 +
  145 +static int
  146 +evo_init_dma(struct drm_device *dev, int ch)
  147 +{
  148 + struct nvd0_display *disp = nvd0_display(dev);
  149 + u32 flags;
  150 +
  151 + flags = 0x00000000;
  152 + if (ch == EVO_MASTER)
  153 + flags |= 0x01000000;
  154 +
  155 + nv_wr32(dev, 0x610494 + (ch * 0x0010), (disp->evo[ch].handle >> 8) | 3);
  156 + nv_wr32(dev, 0x610498 + (ch * 0x0010), 0x00010000);
  157 + nv_wr32(dev, 0x61049c + (ch * 0x0010), 0x00000001);
  158 + nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000010);
  159 + nv_wr32(dev, 0x640000 + (ch * 0x1000), 0x00000000);
  160 + nv_wr32(dev, 0x610490 + (ch * 0x0010), 0x00000013 | flags);
  161 + if (!nv_wait(dev, 0x610490 + (ch * 0x0010), 0x80000000, 0x00000000)) {
  162 + NV_ERROR(dev, "PDISP: ch%d 0x%08x\n", ch,
  163 + nv_rd32(dev, 0x610490 + (ch * 0x0010)));
  164 + return -EBUSY;
  165 + }
  166 +
  167 + nv_mask(dev, 0x610090, (1 << ch), (1 << ch));
  168 + nv_mask(dev, 0x6100a0, (1 << ch), (1 << ch));
  169 + return 0;
  170 +}
  171 +
  172 +static void
  173 +evo_fini_dma(struct drm_device *dev, int ch)
  174 +{
  175 + if (!(nv_rd32(dev, 0x610490 + (ch * 0x0010)) & 0x00000010))
  176 + return;
  177 +
  178 + nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000000);
  179 + nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000003, 0x00000000);
  180 + nv_wait(dev, 0x610490 + (ch * 0x0010), 0x80000000, 0x00000000);
  181 + nv_mask(dev, 0x610090, (1 << ch), 0x00000000);
  182 + nv_mask(dev, 0x6100a0, (1 << ch), 0x00000000);
  183 +}
  184 +
  185 +static inline void
  186 +evo_piow(struct drm_device *dev, int ch, u16 mthd, u32 data)
  187 +{
  188 + nv_wr32(dev, 0x640000 + (ch * 0x1000) + mthd, data);
  189 +}
  190 +
  191 +static int
  192 +evo_init_pio(struct drm_device *dev, int ch)
  193 +{
  194 + nv_wr32(dev, 0x610490 + (ch * 0x0010), 0x00000001);
  195 + if (!nv_wait(dev, 0x610490 + (ch * 0x0010), 0x00010000, 0x00010000)) {
  196 + NV_ERROR(dev, "PDISP: ch%d 0x%08x\n", ch,
  197 + nv_rd32(dev, 0x610490 + (ch * 0x0010)));
  198 + return -EBUSY;
  199 + }
  200 +
  201 + nv_mask(dev, 0x610090, (1 << ch), (1 << ch));
  202 + nv_mask(dev, 0x6100a0, (1 << ch), (1 << ch));
  203 + return 0;
  204 +}
  205 +
  206 +static void
  207 +evo_fini_pio(struct drm_device *dev, int ch)
  208 +{
  209 + if (!(nv_rd32(dev, 0x610490 + (ch * 0x0010)) & 0x00000001))
  210 + return;
  211 +
  212 + nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000010);
  213 + nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000001, 0x00000000);
  214 + nv_wait(dev, 0x610490 + (ch * 0x0010), 0x00010000, 0x00000000);
  215 + nv_mask(dev, 0x610090, (1 << ch), 0x00000000);
  216 + nv_mask(dev, 0x6100a0, (1 << ch), 0x00000000);
  217 +}
  218 +
  219 +static bool
  220 +evo_sync_wait(void *data)
  221 +{
  222 + return nv_rv32(data, EVO_MAST_NTFY) != 0x00000000;
  223 +}
  224 +
  225 +static int
  226 +evo_sync(struct drm_device *dev, int ch)
  227 +{
  228 + struct nvd0_display *disp = nvd0_display(dev);
  229 + u32 *push = evo_wait(dev, ch, 8);
  230 + if (push) {
  231 + nv_wv32(disp->sync, EVO_MAST_NTFY, 0x00000000);
  232 + evo_mthd(push, 0x0084, 1);
  233 + evo_data(push, 0x80000000 | EVO_MAST_NTFY);
  234 + evo_mthd(push, 0x0080, 2);
  235 + evo_data(push, 0x00000000);
  236 + evo_data(push, 0x00000000);
  237 + evo_kick(push, dev, ch);
  238 + if (nv_wait_cb(dev, evo_sync_wait, disp->sync))
  239 + return 0;
  240 + }
  241 +
  242 + return -EBUSY;
  243 +}
  244 +
  245 +/******************************************************************************
  246 + * Page flipping channel
  247 + *****************************************************************************/
  248 +struct pscnv_bo *
  249 +nvd0_display_crtc_sema(struct drm_device *dev, int crtc)
  250 +{
  251 + return nvd0_display(dev)->sync;
  252 +}
  253 +
  254 +void
  255 +nvd0_display_flip_stop(struct drm_crtc *crtc)
  256 +{
  257 + struct nvd0_display *disp = nvd0_display(crtc->dev);
  258 + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
  259 + struct evo *evo = &disp->evo[EVO_FLIP(nv_crtc->index)];
  260 + u32 *push;
  261 +
  262 + push = evo_wait(crtc->dev, evo->idx, 8);
  263 + if (push) {
  264 + evo_mthd(push, 0x0084, 1);
  265 + evo_data(push, 0x00000000);
  266 + evo_mthd(push, 0x0094, 1);
  267 + evo_data(push, 0x00000000);
  268 + evo_mthd(push, 0x00c0, 1);
  269 + evo_data(push, 0x00000000);
  270 + evo_mthd(push, 0x0080, 1);
  271 + evo_data(push, 0x00000000);
  272 + evo_kick(push, crtc->dev, evo->idx);
  273 + }
  274 +}
  275 +
  276 +int
  277 +nvd0_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
  278 + struct nouveau_channel *chan, u32 swap_interval)
  279 +{
  280 +#if 0
  281 + struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
  282 + struct nvd0_display *disp = nvd0_display(crtc->dev);
  283 + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
  284 + struct evo *evo = &disp->evo[EVO_FLIP(nv_crtc->index)];
  285 + u64 offset;
  286 + u32 *push;
  287 + int ret;
  288 +
  289 + evo_sync(crtc->dev, EVO_MASTER);
  290 +
  291 + swap_interval <<= 4;
  292 + if (swap_interval == 0)
  293 + swap_interval |= 0x100;
  294 +
  295 + push = evo_wait(crtc->dev, evo->idx, 128);
  296 + if (unlikely(push == NULL))
  297 + return -EBUSY;
  298 +
  299 + /* synchronise with the rendering channel, if necessary */
  300 + if (likely(chan)) {
  301 + ret = RING_SPACE(chan, 10);
  302 + if (ret)
  303 + return ret;
  304 +
  305 + offset = chan->dispc_vma[nv_crtc->index].offset;
  306 + offset += evo->sem.offset;
  307 +
  308 + BEGIN_NVC0(chan, 2, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
  309 + OUT_RING (chan, upper_32_bits(offset));
  310 + OUT_RING (chan, lower_32_bits(offset));
  311 + OUT_RING (chan, 0xf00d0000 | evo->sem.value);
  312 + OUT_RING (chan, 0x1002);
  313 + BEGIN_NVC0(chan, 2, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
  314 + OUT_RING (chan, upper_32_bits(offset));
  315 + OUT_RING (chan, lower_32_bits(offset ^ 0x10));
  316 + OUT_RING (chan, 0x74b1e000);
  317 + OUT_RING (chan, 0x1001);
  318 + FIRE_RING (chan);
  319 + } else {
  320 + nouveau_bo_wr32(disp->sync, evo->sem.offset / 4,
  321 + 0xf00d0000 | evo->sem.value);
  322 + evo_sync(crtc->dev, EVO_MASTER);
  323 + }
  324 +
  325 + /* queue the flip */
  326 + evo_mthd(push, 0x0100, 1);
  327 + evo_data(push, 0xfffe0000);
  328 + evo_mthd(push, 0x0084, 1);
  329 + evo_data(push, swap_interval);
  330 + if (!(swap_interval & 0x00000100)) {
  331 + evo_mthd(push, 0x00e0, 1);
  332 + evo_data(push, 0x40000000);
  333 + }
  334 + evo_mthd(push, 0x0088, 4);
  335 + evo_data(push, evo->sem.offset);
  336 + evo_data(push, 0xf00d0000 | evo->sem.value);
  337 + evo_data(push, 0x74b1e000);
  338 + evo_data(push, NvEvoSync);
  339 + evo_mthd(push, 0x00a0, 2);
  340 + evo_data(push, 0x00000000);
  341 + evo_data(push, 0x00000000);
  342 + evo_mthd(push, 0x00c0, 1);
  343 + evo_data(push, nv_fb->r_dma);
  344 + evo_mthd(push, 0x0110, 2);
  345 + evo_data(push, 0x00000000);
  346 + evo_data(push, 0x00000000);
  347 + evo_mthd(push, 0x0400, 5);
  348 + evo_data(push, nv_fb->nvbo->bo.offset >> 8);
  349 + evo_data(push, 0);
  350 + evo_data(push, (fb->height << 16) | fb->width);
  351 + evo_data(push, nv_fb->r_pitch);
  352 + evo_data(push, nv_fb->r_format);
  353 + evo_mthd(push, 0x0080, 1);
  354 + evo_data(push, 0x00000000);
  355 + evo_kick(push, crtc->dev, evo->idx);
  356 +
  357 + evo->sem.offset ^= 0x10;
  358 + evo->sem.value++;
  359 +#else
  360 + (void)evo_sync;
  361 +#endif
  362 + return 0;
  363 +}
  364 +
  365 +/******************************************************************************
  366 + * CRTC
  367 + *****************************************************************************/
  368 +static int
  369 +nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update)
  370 +{
  371 + struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private;
  372 + struct drm_device *dev = nv_crtc->base.dev;
  373 + struct nouveau_connector *nv_connector;
  374 + struct drm_connector *connector;
  375 + u32 *push, mode = 0x00;
  376 + u32 mthd;
  377 +
  378 + nv_connector = nouveau_crtc_connector_get(nv_crtc);
  379 + connector = &nv_connector->base;
  380 + if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) {
  381 + if (nv_crtc->base.fb->depth > connector->display_info.bpc * 3)
  382 + mode = DITHERING_MODE_DYNAMIC2X2;
  383 + } else {
  384 + mode = nv_connector->dithering_mode;
  385 + }
  386 +
  387 + if (nv_connector->dithering_depth == DITHERING_DEPTH_AUTO) {
  388 + if (connector->display_info.bpc >= 8)
  389 + mode |= DITHERING_DEPTH_8BPC;
  390 + } else {
  391 + mode |= nv_connector->dithering_depth;
  392 + }
  393 +
  394 + if (dev_priv->card_type < NV_E0)
  395 + mthd = 0x0490 + (nv_crtc->index * 0x0300);
  396 + else
  397 + mthd = 0x04a0 + (nv_crtc->index * 0x0300);
  398 +
  399 + push = evo_wait(dev, EVO_MASTER, 4);
  400 + if (push) {
  401 + evo_mthd(push, mthd, 1);
  402 + evo_data(push, mode);
  403 + if (update) {
  404 + evo_mthd(push, 0x0080, 1);
  405 + evo_data(push, 0x00000000);
  406 + }
  407 + evo_kick(push, dev, EVO_MASTER);
  408 + }
  409 +
  410 + return 0;
  411 +}
  412 +
  413 +static int
  414 +nvd0_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)
  415 +{
  416 + struct drm_display_mode *omode, *umode = &nv_crtc->base.mode;
  417 + struct drm_device *dev = nv_crtc->base.dev;
  418 + struct drm_crtc *crtc = &nv_crtc->base;
  419 + struct nouveau_connector *nv_connector;
  420 + int mode = DRM_MODE_SCALE_NONE;
  421 + u32 oX, oY, *push;
  422 +
  423 + /* start off at the resolution we programmed the crtc for, this
  424 + * effectively handles NONE/FULL scaling
  425 + */
  426 + nv_connector = nouveau_crtc_connector_get(nv_crtc);
  427 + if (nv_connector && nv_connector->native_mode)
  428 + mode = nv_connector->scaling_mode;
  429 +
  430 + if (mode != DRM_MODE_SCALE_NONE)
  431 + omode = nv_connector->native_mode;
  432 + else
  433 + omode = umode;
  434 +
  435 + oX = omode->hdisplay;
  436 + oY = omode->vdisplay;
  437 + if (omode->flags & DRM_MODE_FLAG_DBLSCAN)
  438 + oY *= 2;
  439 +
  440 + /* add overscan compensation if necessary, will keep the aspect
  441 + * ratio the same as the backend mode unless overridden by the
  442 + * user setting both hborder and vborder properties.
  443 + */
  444 + if (nv_connector && ( nv_connector->underscan == UNDERSCAN_ON ||
  445 + (nv_connector->underscan == UNDERSCAN_AUTO &&
  446 + nv_connector->edid &&
  447 + drm_detect_hdmi_monitor(nv_connector->edid)))) {
  448 + u32 bX = nv_connector->underscan_hborder;
  449 + u32 bY = nv_connector->underscan_vborder;
  450 + u32 aspect = (oY << 19) / oX;
  451 +
  452 + if (bX) {
  453 + oX -= (bX * 2);
  454 + if (bY) oY -= (bY * 2);
  455 + else oY = ((oX * aspect) + (aspect / 2)) >> 19;
  456 + } else {
  457 + oX -= (oX >> 4) + 32;
  458 + if (bY) oY -= (bY * 2);
  459 + else oY = ((oX * aspect) + (aspect / 2)) >> 19;
  460 + }
  461 + }
  462 +
  463 + /* handle CENTER/ASPECT scaling, taking into account the areas
  464 + * removed already for overscan compensation
  465 + */
  466 + switch (mode) {
  467 + case DRM_MODE_SCALE_CENTER:
  468 + oX = min((u32)umode->hdisplay, oX);
  469 + oY = min((u32)umode->vdisplay, oY);
  470 + /* fall-through */
  471 + case DRM_MODE_SCALE_ASPECT:
  472 + if (oY < oX) {
  473 + u32 aspect = (umode->hdisplay << 19) / umode->vdisplay;
  474 + oX = ((oY * aspect) + (aspect / 2)) >> 19;
  475 + } else {
  476 + u32 aspect = (umode->vdisplay << 19) / umode->hdisplay;
  477 + oY = ((oX * aspect) + (aspect / 2)) >> 19;
  478 + }
  479 + break;
  480 + default:
  481 + break;
  482 + }
  483 +
  484 + push = evo_wait(dev, EVO_MASTER, 8);
  485 + if (push) {
  486 + evo_mthd(push, 0x04c0 + (nv_crtc->index * 0x300), 3);
  487 + evo_data(push, (oY << 16) | oX);
  488 + evo_data(push, (oY << 16) | oX);
  489 + evo_data(push, (oY << 16) | oX);
  490 + evo_mthd(push, 0x0494 + (nv_crtc->index * 0x300), 1);
  491 + evo_data(push, 0x00000000);
  492 + evo_mthd(push, 0x04b8 + (nv_crtc->index * 0x300), 1);
  493 + evo_data(push, (umode->vdisplay << 16) | umode->hdisplay);
  494 + evo_kick(push, dev, EVO_MASTER);
  495 + if (update) {
  496 + nvd0_display_flip_stop(crtc);
  497 + nvd0_display_flip_next(crtc, crtc->fb, NULL, 1);
  498 + }
  499 + }
  500 +
  501 + return 0;
  502 +}
  503 +
  504 +static int nvd0_crtc_get_data(struct nouveau_crtc *nv_crtc,
  505 + struct drm_framebuffer *drm_fb,
  506 + uint32_t *pitch, uint32_t *dma,
  507 + uint32_t *format)
  508 +{
  509 + struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
  510 + switch (drm_fb->depth) {
  511 + case 8:
  512 + *format = NV50_EVO_CRTC_FB_DEPTH_8;
  513 + break;
  514 + case 15:
  515 + *format = NV50_EVO_CRTC_FB_DEPTH_15;
  516 + break;
  517 + case 16:
  518 + *format = NV50_EVO_CRTC_FB_DEPTH_16;
  519 + break;
  520 + case 24:
  521 + case 32:
  522 + *format = NV50_EVO_CRTC_FB_DEPTH_24;
  523 + break;
  524 + case 30:
  525 + *format = NV50_EVO_CRTC_FB_DEPTH_30;
  526 + break;
  527 + default:
  528 + NV_ERROR(drm_fb->dev, "unknown depth %d\n", drm_fb->depth);
  529 + return -EINVAL;
  530 + }
  531 +
  532 + switch (nv_crtc->fb.tile_flags) {
  533 + case 0xfe: *dma = NvEvoFE; break;
  534 + case 0x7a: *dma = NvEvoFB32; break;
  535 + case 0x70: *dma = NvEvoFB16; break;
  536 + default: *dma = NvEvoVRAM; break;
  537 + }
  538 +
  539 + if (!nv_crtc->fb.tile_flags) {
  540 +#ifdef PSCNV_KAPI_DRM_FB_PITCH
  541 + *pitch = drm_fb->pitch | (1 << 24);
  542 +#else
  543 + *pitch = drm_fb->pitches[0] | (1 << 24);
  544 +#endif
  545 + } else {
  546 +#ifdef PSCNV_KAPI_DRM_FB_PITCH
  547 + *pitch = ((drm_fb->pitch / 4) << 4) | fb->nvbo->user[0];
  548 +#else
  549 + *pitch = ((drm_fb->pitches[0] / 4) << 4) | fb->nvbo->user[0];
  550 +#endif
  551 + }
  552 +
  553 + return 0;
  554 +}
  555 +
  556 +static int
  557 +nvd0_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb,
  558 + int x, int y, bool update)
  559 +{
  560 + struct nouveau_framebuffer *nvfb = nouveau_framebuffer(fb);
  561 + u32 *push, r_pitch, r_dma, r_format;
  562 + int ret;
  563 + ret = nvd0_crtc_get_data(nv_crtc, fb, &r_pitch, &r_dma, &r_format);
  564 + if (ret < 0)
  565 + return ret;
  566 +
  567 + push = evo_wait(fb->dev, EVO_MASTER, 16);
  568 + if (push) {
  569 + evo_mthd(push, 0x0460 + (nv_crtc->index * 0x300), 1);
  570 + evo_data(push, nvfb->nvbo->start >> 8);
  571 + evo_mthd(push, 0x0468 + (nv_crtc->index * 0x300), 4);
  572 + evo_data(push, (fb->height << 16) | fb->width);
  573 + evo_data(push, r_pitch);
  574 + evo_data(push, r_format);
  575 + evo_data(push, r_dma);
  576 + evo_mthd(push, 0x04b0 + (nv_crtc->index * 0x300), 1);
  577 + evo_data(push, (y << 16) | x);
  578 + if (update) {
  579 + evo_mthd(push, 0x0080, 1);
  580 + evo_data(push, 0x00000000);
  581 + }
  582 + evo_kick(push, fb->dev, EVO_MASTER);
  583 + }
  584 +
  585 + nv_crtc->fb.tile_flags = r_dma;
  586 + return 0;
  587 +}
  588 +
  589 +static void
  590 +nvd0_crtc_cursor_show(struct nouveau_crtc *nv_crtc, bool show, bool update)
  591 +{
  592 + struct drm_device *dev = nv_crtc->base.dev;
  593 + u32 *push = evo_wait(dev, EVO_MASTER, 16);
  594 + if (push) {
  595 + if (show) {
  596 + evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2);
  597 + evo_data(push, 0x85000000);
  598 + evo_data(push, nv_crtc->cursor.nvbo->start >> 8);
  599 + evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
  600 + evo_data(push, NvEvoVRAM);
  601 + } else {
  602 + evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 1);
  603 + evo_data(push, 0x05000000);
  604 + evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
  605 + evo_data(push, 0x00000000);
  606 + }
  607 +
  608 + if (update) {
  609 + evo_mthd(push, 0x0080, 1);
  610 + evo_data(push, 0x00000000);
  611 + }
  612 +
  613 + evo_kick(push, dev, EVO_MASTER);
  614 + }
  615 +}
  616 +
  617 +static void
  618 +nvd0_crtc_dpms(struct drm_crtc *crtc, int mode)
  619 +{
  620 +}
  621 +
  622 +static void
  623 +nvd0_crtc_prepare(struct drm_crtc *crtc)
  624 +{
  625 + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
  626 + u32 *push;
  627 +
  628 + nvd0_display_flip_stop(crtc);
  629 +
  630 + push = evo_wait(crtc->dev, EVO_MASTER, 2);
  631 + if (push) {
  632 + evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
  633 + evo_data(push, 0x00000000);
  634 + evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 1);
  635 + evo_data(push, 0x03000000);
  636 + evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
  637 + evo_data(push, 0x00000000);
  638 + evo_kick(push, crtc->dev, EVO_MASTER);
  639 + }
  640 +
  641 + nvd0_crtc_cursor_show(nv_crtc, false, false);
  642 +}
  643 +
  644 +static void
  645 +nvd0_crtc_commit(struct drm_crtc *crtc)
  646 +{
  647 + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
  648 + u32 *push;
  649 +
  650 + push = evo_wait(crtc->dev, EVO_MASTER, 32);
  651 + if (push) {
  652 + evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
  653 + evo_data(push, nv_crtc->fb.tile_flags);
  654 + evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 4);
  655 + evo_data(push, 0x83000000);
  656 + evo_data(push, nv_crtc->lut.nvbo->start >> 8);
  657 + evo_data(push, 0x00000000);
  658 + evo_data(push, 0x00000000);
  659 + evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
  660 + evo_data(push, NvEvoVRAM);
  661 + evo_mthd(push, 0x0430 + (nv_crtc->index * 0x300), 1);
  662 + evo_data(push, 0xffffff00);
  663 + evo_kick(push, crtc->dev, EVO_MASTER);
  664 + }
  665 +
  666 + nvd0_crtc_cursor_show(nv_crtc, nv_crtc->cursor.visible, true);
  667 + nvd0_display_flip_next(crtc, crtc->fb, NULL, 1);
  668 +}
  669 +
  670 +static bool
  671 +nvd0_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode,
  672 + struct drm_display_mode *adjusted_mode)
  673 +{
  674 + return true;
  675 +}
  676 +
  677 +static int
  678 +nvd0_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
  679 +{
  680 +/* Unneeded */
  681 +#if 0
  682 + struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
  683 + int ret;
  684 +
  685 + ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM);
  686 + if (ret)
  687 + return ret;
  688 +
  689 + if (old_fb) {
  690 + nvfb = nouveau_framebuffer(old_fb);
  691 + nouveau_bo_unpin(nvfb->nvbo);
  692 + }
  693 +#endif
  694 + return 0;
  695 +}
  696 +
  697 +static int
  698 +nvd0_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
  699 + struct drm_display_mode *mode, int x, int y,
  700 + struct drm_framebuffer *old_fb)
  701 +{
  702 + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
  703 + struct nouveau_connector *nv_connector;
  704 + u32 ilace = (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 1;
  705 + u32 vscan = (mode->flags & DRM_MODE_FLAG_DBLSCAN) ? 2 : 1;
  706 + u32 hactive, hsynce, hbackp, hfrontp, hblanke, hblanks;
  707 + u32 vactive, vsynce, vbackp, vfrontp, vblanke, vblanks;
  708 + u32 vblan2e = 0, vblan2s = 1;
  709 + u32 *push;
  710 + int ret;
  711 +
  712 + hactive = mode->htotal;
  713 + hsynce = mode->hsync_end - mode->hsync_start - 1;
  714 + hbackp = mode->htotal - mode->hsync_end;
  715 + hblanke = hsynce + hbackp;
  716 + hfrontp = mode->hsync_start - mode->hdisplay;
  717 + hblanks = mode->htotal - hfrontp - 1;
  718 +
  719 + vactive = mode->vtotal * vscan / ilace;
  720 + vsynce = ((mode->vsync_end - mode->vsync_start) * vscan / ilace) - 1;
  721 + vbackp = (mode->vtotal - mode->vsync_end) * vscan / ilace;
  722 + vblanke = vsynce + vbackp;
  723 + vfrontp = (mode->vsync_start - mode->vdisplay) * vscan / ilace;
  724 + vblanks = vactive - vfrontp - 1;
  725 + if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
  726 + vblan2e = vactive + vsynce + vbackp;
  727 + vblan2s = vblan2e + (mode->vdisplay * vscan / ilace);
  728 + vactive = (vactive * 2) + 1;
  729 + }
  730 +
  731 + ret = nvd0_crtc_swap_fbs(crtc, old_fb);
  732 + if (ret)
  733 + return ret;
  734 +
  735 + push = evo_wait(crtc->dev, EVO_MASTER, 64);
  736 + if (push) {
  737 + evo_mthd(push, 0x0410 + (nv_crtc->index * 0x300), 6);
  738 + evo_data(push, 0x00000000);
  739 + evo_data(push, (vactive << 16) | hactive);
  740 + evo_data(push, ( vsynce << 16) | hsynce);
  741 + evo_data(push, (vblanke << 16) | hblanke);
  742 + evo_data(push, (vblanks << 16) | hblanks);
  743 + evo_data(push, (vblan2e << 16) | vblan2s);
  744 + evo_mthd(push, 0x042c + (nv_crtc->index * 0x300), 1);
  745 + evo_data(push, 0x00000000); /* ??? */
  746 + evo_mthd(push, 0x0450 + (nv_crtc->index * 0x300), 3);
  747 + evo_data(push, mode->clock * 1000);
  748 + evo_data(push, 0x00200000); /* ??? */
  749 + evo_data(push, mode->clock * 1000);
  750 + evo_mthd(push, 0x04d0 + (nv_crtc->index * 0x300), 2);
  751 + evo_data(push, 0x00000311);
  752 + evo_data(push, 0x00000100);
  753 + evo_kick(push, crtc->dev, EVO_MASTER);
  754 + }
  755 +
  756 + nv_connector = nouveau_crtc_connector_get(nv_crtc);
  757 + nvd0_crtc_set_dither(nv_crtc, false);
  758 + nvd0_crtc_set_scale(nv_crtc, false);
  759 + nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, false);
  760 + return 0;
  761 +}
  762 +
  763 +static int
  764 +nvd0_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
  765 + struct drm_framebuffer *old_fb)
  766 +{
  767 + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
  768 + int ret;
  769 +
  770 + if (!crtc->fb) {
  771 + NV_DEBUG_KMS(crtc->dev, "No FB bound\n");
  772 + return 0;
  773 + }
  774 +
  775 + ret = nvd0_crtc_swap_fbs(crtc, old_fb);
  776 + if (ret)
  777 + return ret;
  778 +
  779 + nvd0_display_flip_stop(crtc);
  780 + nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, true);
  781 + nvd0_display_flip_next(crtc, crtc->fb, NULL, 1);
  782 + return 0;
  783 +}
  784 +
  785 +static int
  786 +nvd0_crtc_mode_set_base_atomic(struct drm_crtc *crtc,
  787 + struct drm_framebuffer *fb, int x, int y,
  788 + enum mode_set_atomic state)
  789 +{
  790 + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
  791 + nvd0_display_flip_stop(crtc);
  792 + nvd0_crtc_set_image(nv_crtc, fb, x, y, true);
  793 + return 0;
  794 +}
  795 +
  796 +static void
  797 +nvd0_crtc_lut_load(struct drm_crtc *crtc)
  798 +{
  799 + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
  800 + int i;
  801 +
  802 + for (i = 0; i < 256; i++) {
  803 + uint16_t r, g, b;
  804 + r = 0x6000 + (nv_crtc->lut.r[i] >> 2);
  805 + g = 0x6000 + (nv_crtc->lut.g[i] >> 2);
  806 + b = 0x6000 + (nv_crtc->lut.b[i] >> 2);
  807 +
  808 + nv_wv32(nv_crtc->lut.nvbo, (i * 0x20) + 0, r | (g << 16));
  809 + nv_wv32(nv_crtc->lut.nvbo, (i * 0x20) + 4, b);
  810 + }
  811 +}
  812 +
  813 +static int
  814 +nvd0_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
  815 + uint32_t handle, uint32_t width, uint32_t height)
  816 +{
  817 + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
  818 + struct drm_device *dev = crtc->dev;
  819 + struct drm_gem_object *gem;
  820 + struct pscnv_bo *nvbo;
  821 + bool visible = (handle != 0);
  822 + int i, ret = 0;
  823 +
  824 + if (visible) {
  825 + if (width != 64 || height != 64)
  826 + return -EINVAL;
  827 +
  828 + gem = drm_gem_object_lookup(dev, file_priv, handle);
  829 + if (unlikely(!gem))
  830 + return -ENOENT;
  831 + nvbo = gem->driver_private;
  832 +
  833 + //ret = nouveau_bo_map(nvbo);
  834 + if (ret == 0) {
  835 + for (i = 0; i < 64 * 64; i++) {
  836 + u32 v = nv_rv32(nvbo, i);
  837 + nv_wv32(nv_crtc->cursor.nvbo, i, v);
  838 + }
  839 + //nouveau_bo_unmap(nvbo);
  840 + }
  841 +
  842 + drm_gem_object_unreference_unlocked(gem);
  843 + }
  844 +
  845 + if (visible != nv_crtc->cursor.visible) {
  846 + nvd0_crtc_cursor_show(nv_crtc, visible, true);
  847 + nv_crtc->cursor.visible = visible;
  848 + }
  849 +
  850 + return ret;
  851 +}
  852 +
  853 +static int
  854 +nvd0_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)