rpms/kernel/F-11 drm-nouveau.patch, 1.55, 1.56 kernel.spec, 1.1661, 1.1662
Ben Skeggs
bskeggs at fedoraproject.org
Mon Jun 29 06:06:50 UTC 2009
Author: bskeggs
Update of /cvs/pkgs/rpms/kernel/F-11
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv14094
Modified Files:
drm-nouveau.patch kernel.spec
Log Message:
* Mon Jun 26 2009 Ben Skeggs <bskeggs at redhat.com> 2.6.29.5-200
- nouveau: backport nv50 output script fixes from upstream
drm-nouveau.patch:
Index: drm-nouveau.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-11/drm-nouveau.patch,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -p -r1.55 -r1.56
--- drm-nouveau.patch 29 Jun 2009 03:03:13 -0000 1.55
+++ drm-nouveau.patch 29 Jun 2009 06:06:48 -0000 1.56
@@ -375,10 +375,10 @@ index 0000000..e3d354f
+}
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
new file mode 100644
-index 0000000..b90beab
+index 0000000..d63baf3
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
-@@ -0,0 +1,4828 @@
+@@ -0,0 +1,4852 @@
+/*
+ * Copyright 2005-2006 Erik Waling
+ * Copyright 2006 Stephane Marchesin
@@ -3429,14 +3429,12 @@ index 0000000..b90beab
+ bios->fp.dual_link = bios->data[lvdsofs] & 1;
+ bios->fp.BITbit1 = bios->data[lvdsofs] & 2;
+ bios->fp.duallink_transition_clk = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 5]) * 10;
-+#if 0 // currently unused
+ break;
+ case 0x40:
+ /* fairly sure, but not 100% */
-+ bios->fp.dual_link = bios->data[lvdsofs] & 1;
++// bios->fp.dual_link = bios->data[lvdsofs] & 1;
+ bios->fp.duallink_transition_clk = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 5]) * 10;
+ break;
-+#endif
+ }
+
+ /* set dual_link flag for EDID case */
@@ -3448,69 +3446,6 @@ index 0000000..b90beab
+ return 0;
+}
+
-+static int
-+find_script_pointers(struct drm_device *dev, uint8_t *table, uint16_t *script0,
-+ uint16_t *script1, uint16_t headerlen, int pxclk,
-+ int cmpval)
-+{
-+ /* The output script tables describing a particular output type
-+ * look as follows:
-+ *
-+ * offset + 0 (32 bits): output this table matches (hash of DCB)
-+ * offset + 4 ( 8 bits): unknown
-+ * offset + 5 ( 8 bits): number of configurations
-+ * offset + 6 (16 bits): pointer to some script
-+ * offset + 8 (16 bits): pointer to some script
-+ *
-+ * headerlen == 10
-+ * offset + 10 : configuration 0
-+ *
-+ * headerlen == 12
-+ * offset + 10 : pointer to some script
-+ * offset + 12 : configuration 0
-+ *
-+ * Each config entry is as follows:
-+ *
-+ * offset + 0 (16 bits): unknown, assumed to be a match value
-+ * offset + 2 (16 bits): pointer to script table (clock set?)
-+ * offset + 4 (16 bits): pointer to script table (reset?)
-+ *
-+ * There doesn't appear to be a count value to say how many
-+ * entries exist in each script table, instead, a 0 value in
-+ * the first 16-bit word seems to indicate both the end of the
-+ * list and the default entry. The second 16-bit word in the
-+ * script tables is a pointer to the script to execute.
-+ */
-+
-+ struct drm_nouveau_private *dev_priv = dev->dev_private;
-+ struct nvbios *bios = &dev_priv->VBIOS;
-+ int i;
-+
-+ *script0 = *script1 = 0;
-+ for (i = 0; i < table[5]; i++) {
-+ uint16_t offset;
-+
-+ if (ROM16(table[headerlen + i*6 + 0]) != cmpval)
-+ continue;
-+
-+ offset = ROM16(table[headerlen + i*6 + 2]);
-+ if (offset)
-+ *script0 = clkcmptable(bios, offset, pxclk);
-+
-+ if (!*script0)
-+ NV_WARN(dev, "script0 missing!\n");
-+
-+ offset = ROM16(table[headerlen + i*6 + 4]);
-+ if (offset)
-+ *script1 = clkcmptable(bios, offset, pxclk);
-+
-+ return 0;
-+ }
-+
-+ NV_ERROR(dev, "couldn't find suitable output scripts\n");
-+ return 1;
-+}
-+
+int
+nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
+ int pxclk)
@@ -3542,19 +3477,48 @@ index 0000000..b90beab
+ struct nvbios *bios = &dev_priv->VBIOS;
+ uint8_t *table = &bios->data[bios->display.script_table_ptr];
+ uint8_t *entry, *otable = NULL;
-+ uint16_t script0, script1;
-+ int i;
++ uint16_t script;
++ int i, sub;
+
+ if (!bios->display.script_table_ptr) {
+ NV_ERROR(dev, "No pointer to output script table\n");
+ return 1;
+ }
+
-+ if (table[0] != 0x20) {
++ if (table[0] != 0x20 && table[0] != 0x21) {
+ NV_ERROR(dev, "Output script table version 0x%02x unknown\n", table[0]);
+ return 1;
+ }
+
++ /* The output script tables describing a particular output type
++ * look as follows:
++ *
++ * offset + 0 (32 bits): output this table matches (hash of DCB)
++ * offset + 4 ( 8 bits): unknown
++ * offset + 5 ( 8 bits): number of configurations
++ * offset + 6 (16 bits): pointer to some script
++ * offset + 8 (16 bits): pointer to some script
++ *
++ * headerlen == 10
++ * offset + 10 : configuration 0
++ *
++ * headerlen == 12
++ * offset + 10 : pointer to some script
++ * offset + 12 : configuration 0
++ *
++ * Each config entry is as follows:
++ *
++ * offset + 0 (16 bits): unknown, assumed to be a match value
++ * offset + 2 (16 bits): pointer to script table (clock set?)
++ * offset + 4 (16 bits): pointer to script table (reset?)
++ *
++ * There doesn't appear to be a count value to say how many
++ * entries exist in each script table, instead, a 0 value in
++ * the first 16-bit word seems to indicate both the end of the
++ * list and the default entry. The second 16-bit word in the
++ * script tables is a pointer to the script to execute.
++ */
++
+ NV_DEBUG(dev, "Searching for output entry for %d %d %d\n",
+ dcbent->type, dcbent->location, dcbent->or);
+ entry = table + table[1];
@@ -3578,29 +3542,89 @@ index 0000000..b90beab
+ return 1;
+ }
+
-+ if (find_script_pointers(dev, otable, &script0, &script1, table[4],
-+ pxclk, dcbent->type == OUTPUT_LVDS ?
-+ 0x0100 : (pxclk > 165000 ? 0x0105 : 0x0001)))
-+ return 1;
-+ bios->display.head = ffs(dcbent->or) - 1;
++ /* Anyone have an idea to know which to use for certain? */
++ switch (dcbent->type) {
++ case OUTPUT_LVDS:
++ sub = 0x0100; /* 0x0000 0x0100 0x0200 0x0300 */
++ break;
++ case OUTPUT_TMDS:
++ sub = 0x0001; /* 0x0001 0x0002 0x0105 */
++ break;
++ default:
++ sub = 0x0000; /* 0x0000 */
++ break;
++ }
+
-+ if (script0) {
-+ NV_TRACE(dev, "0x%04X: Parsing output Script0\n", script0);
-+ parse_init_table(dev, bios, script0, &iexec);
-+ } else {
-+ NV_ERROR(dev, "clock script missing!\n");
-+ return 1;
++ for (i = 0; i < otable[5]; i++) {
++ if (ROM16(otable[table[4] + i*6]) == sub)
++ break;
+ }
+
-+ if (script1) {
-+ NV_TRACE(dev, "0x%04X: Parsing output Script1\n", script1);
-+ parse_init_table(dev, bios, script1, &iexec);
++ if (i == otable[5])
++ i = 0;
++
++ bios->display.head = ffs(dcbent->or) - 1;
++
++ if (pxclk == 0) {
++ script = ROM16(otable[6]);
++ if (!script) {
++ NV_DEBUG(dev, "output script 0 not found\n");
++ return 1;
++ }
++
++ NV_TRACE(dev, "0x%04X: parsing output script 0\n", script);
++ parse_init_table(dev, bios, script, &iexec);
++ } else
++ if (pxclk == -1) {
++ script = ROM16(otable[8]);
++ if (!script) {
++ NV_DEBUG(dev, "output script 1 not found\n");
++ return 1;
++ }
++
++ NV_TRACE(dev, "0x%04X: parsing output script 1\n", script);
++ parse_init_table(dev, bios, script, &iexec);
++ } else
++ if (pxclk == -2) {
++ if (table[4] >= 12)
++ script = ROM16(otable[10]);
++ else
++ script = 0;
++ if (!script) {
++ NV_DEBUG(dev, "output script 2 not found\n");
++ return 1;
++ }
++
++ NV_TRACE(dev, "0x%04X: parsing output script 2\n", script);
++ parse_init_table(dev, bios, script, &iexec);
++ } else
++ if (pxclk > 0) {
++ script = ROM16(otable[table[4] + i*6 + 2]);
++ if (script)
++ script = clkcmptable(bios, script, pxclk);
++ if (!script) {
++ NV_ERROR(dev, "clock script 0 not found\n");
++ return 1;
++ }
++
++ NV_TRACE(dev, "0x%04X: parsing clock script 0\n", script);
++ parse_init_table(dev, bios, script, &iexec);
++ } else
++ if (pxclk < 0) {
++ script = ROM16(otable[table[4] + i*6 + 4]);
++ if (script)
++ script = clkcmptable(bios, script, -pxclk);
++ if (!script) {
++ NV_DEBUG(dev, "clock script 1 not found\n");
++ return 1;
++ }
++
++ NV_TRACE(dev, "0x%04X: parsing clock script 1\n", script);
++ parse_init_table(dev, bios, script, &iexec);
+ }
+
+ return 0;
+}
-+
-+
+int run_tmds_table(struct drm_device *dev, struct dcb_entry *dcbent, int head, int pxclk)
+{
+ /* the pxclk parameter is in kHz
@@ -7272,10 +7296,10 @@ index 0000000..578983e
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
new file mode 100644
-index 0000000..13d6f9d
+index 0000000..1140522
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
-@@ -0,0 +1,834 @@
+@@ -0,0 +1,836 @@
+/*
+ * Copyright 2005 Stephane Marchesin.
+ * All Rights Reserved.
@@ -7825,6 +7849,8 @@ index 0000000..13d6f9d
+extern int nouveau_bios_run_display_table(struct drm_device *,
+ struct dcb_entry *, int pxclk);
+bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *);
++int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl,
++ bool *if_is_24bit);
+
+/* nv04_fb.c */
+extern int nv04_fb_init(struct drm_device *);
@@ -12704,7 +12730,7 @@ index 0000000..f55ae7a
+}
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c
new file mode 100644
-index 0000000..c3ad906
+index 0000000..371108a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_irq.c
@@ -0,0 +1,592 @@
@@ -13226,20 +13252,20 @@ index 0000000..c3ad906
+static void
+nouveau_nv50_display_irq_handler(struct drm_device *dev)
+{
-+ uint32_t val = nv_rd32(NV50_PDISPLAY_SUPERVISOR);
++ uint32_t val = nv_rd32(NV50_PDISPLAY_INTR);
+
-+ NV_DEBUG(dev, "NV50_PDISPLAY_SUPERVISOR - 0x%08X\n", val);
++ NV_DEBUG(dev, "NV50_PDISPLAY_INTR - 0x%08X\n", val);
+
+ /* vblank interrupts */
-+ if (val & NV50_PDISPLAY_SUPERVISOR_CRTCn) {
-+ nv_wr32(NV50_PDISPLAY_SUPERVISOR, val & NV50_PDISPLAY_SUPERVISOR_CRTCn);
-+ val &= ~NV50_PDISPLAY_SUPERVISOR_CRTCn;
++ if (val & NV50_PDISPLAY_INTR_VBLANK_CRTCn) {
++ nv_wr32(NV50_PDISPLAY_INTR, val & NV50_PDISPLAY_INTR_VBLANK_CRTCn);
++ val &= ~NV50_PDISPLAY_INTR_VBLANK_CRTCn;
+ }
+
+ if (val)
+ NV_ERROR(dev, "unsupported NV50_DISPLAY_INTR - 0x%08X\n", val);
+
-+ nv_wr32(NV50_PDISPLAY_SUPERVISOR, val);
++ nv_wr32(NV50_PDISPLAY_INTR, val);
+}
+
+static void
@@ -15805,10 +15831,10 @@ index 0000000..5fed5cb
+}
diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h
new file mode 100644
-index 0000000..44337e6
+index 0000000..a22049a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_reg.h
-@@ -0,0 +1,835 @@
+@@ -0,0 +1,854 @@
+
+
+#define NV03_BOOT_0 0x00100000
@@ -16500,20 +16526,22 @@ index 0000000..44337e6
+#define NV50_PDISPLAY 0x00610000
+#define NV50_PDISPLAY__LEN 0x1
+#define NV50_PDISPLAY__ESIZE 0x10000
-+# define NV50_PDISPLAY_SUPERVISOR 0x00610024
-+# define NV50_PDISPLAY_SUPERVISOR_CRTCn 0x0000000c
-+# define NV50_PDISPLAY_SUPERVISOR_CRTCn__SHIFT 2
-+# define NV50_PDISPLAY_SUPERVISOR_CRTC0 (1<<2)
-+# define NV50_PDISPLAY_SUPERVISOR_CRTC1 (1<<3)
-+# define NV50_PDISPLAY_SUPERVISOR_CLK_MASK 0x00000070
-+# define NV50_PDISPLAY_SUPERVISOR_CLK_MASK__SHIFT 4
-+# define NV50_PDISPLAY_SUPERVISOR_CLK_UPDATE (1<<5)
-+# define NV50_PDISPLAY_SUPERVISOR_INTR 0x0061002c
-+# define NV50_PDISPLAY_SUPERVISOR_INTR_VBLANK_CRTC0 (1<<2)
-+# define NV50_PDISPLAY_SUPERVISOR_INTR_VBLANK_CRTC1 (1<<3)
-+# define NV50_PDISPLAY_SUPERVISOR_INTR_UNK1 (1<<4)
-+# define NV50_PDISPLAY_SUPERVISOR_INTR_CLK_UPDATE (1<<5)
-+# define NV50_PDISPLAY_SUPERVISOR_INTR_UNK4 (1<<6)
++# define NV50_PDISPLAY_OBJECTS 0x00610010
++# define NV50_PDISPLAY_INTR 0x00610024
++# define NV50_PDISPLAY_INTR_VBLANK_CRTCn 0x0000000c
++# define NV50_PDISPLAY_INTR_VBLANK_CRTCn__SHIFT 2
++# define NV50_PDISPLAY_INTR_VBLANK_CRTC(n) (1 << ((n) + 2))
++# define NV50_PDISPLAY_INTR_VBLANK_CRTC0 (1<<2)
++# define NV50_PDISPLAY_INTR_VBLANK_CRTC1 (1<<3)
++# define NV50_PDISPLAY_INTR_CLK_UNK10 (1<<4)
++# define NV50_PDISPLAY_INTR_CLK_UNK20 (1<<5)
++# define NV50_PDISPLAY_INTR_CLK_UNK40 (1<<6)
++# define NV50_PDISPLAY_INTR_EN 0x0061002c
++# define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC0 (1<<2)
++# define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC1 (1<<3)
++# define NV50_PDISPLAY_INTR_EN_CLK_UNK10 (1<<4)
++# define NV50_PDISPLAY_INTR_EN_CLK_UNK20 (1<<5)
++# define NV50_PDISPLAY_INTR_EN_CLK_UNK40 (1<<6)
+# define NV50_PDISPLAY_UNK30_CTRL 0x00610030
+# define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK0 (1<<9)
+# define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK1 (1<<10)
@@ -16526,6 +16554,17 @@ index 0000000..44337e6
+# define NV50_PDISPLAY_UNK50_CTRL_CRTC1_ACTIVE_MASK 0x00000300
+# define NV50_PDISPLAY_UNK50_CTRL_CRTC1_ACTIVE_MASK__SHIFT 8
+# define NV50_PDISPLAY_UNK200_CTRL 0x00610200
++# define NV50_PDISPLAY_CHANNEL_STAT(i) (0x00610200 + (i*0x10))
++# define NV50_PDISPLAY_CHANNEL_STAT_DMA 0x00000010
++# define NV50_PDISPLAY_CHANNEL_STAT_DMA_DISABLED 0x00000000
++# define NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED 0x00000010
++# define NV50_PDISPLAY_CHANNEL_DMA_CB(i) (0x00610204 + (i*0x10))
++# define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION 0x00000002
++# define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_VRAM 0x00000000
++# define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_SYSTEM 0x00000002
++# define NV50_PDISPLAY_CHANNEL_DMA_CB_VALID 0x00000001
++# define NV50_PDISPLAY_CHANNEL_UNK2(i) (0x00610208 + (i*0x10))
++# define NV50_PDISPLAY_CHANNEL_UNK3(i) (0x0061020c + (i*0x10))
+# define NV50_PDISPLAY_CURSOR 0x00610270
+# define NV50_PDISPLAY_CURSOR__LEN 0x2
+# define NV50_PDISPLAY_CURSOR__ESIZE 0x10
@@ -16543,58 +16582,63 @@ index 0000000..44337e6
+# define NV50_PDISPLAY_RAM_AMOUNT 0x00610384
+# define NV50_PDISPLAY_UNK_388 0x00610388
+# define NV50_PDISPLAY_UNK_38C 0x0061038c
-+# define NV50_PDISPLAY_CRTC_VAL 0x00610a00
-+# define NV50_PDISPLAY_CRTC_VAL__LEN 0x2
-+# define NV50_PDISPLAY_CRTC_VAL_UNK_900(i,j) (0x00610a18+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_CLUT_MODE(i,j) (0x00610a24+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_INTERLACE(i,j) (0x00610a48+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_SCALE_CTRL(i,j) (0x00610a50+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_CURSOR_CTRL(i,j) (0x00610a58+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_UNK_904(i,j) (0x00610ab8+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_DEPTH(i,j) (0x00610ac8+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_CLOCK(i,j) (0x00610ad0+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_COLOR_CTRL(i,j) (0x00610ae0+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_SYNC_START_TO_BLANK_END(i,j) (0x00610ae8+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_MODE_UNK1(i,j) (0x00610af0+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_DISPLAY_TOTAL(i,j) (0x00610af8+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_SYNC_DURATION(i,j) (0x00610b00+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_MODE_UNK2(i,j) (0x00610b08+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_UNK_828(i,j) (0x00610b10+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_FB_SIZE(i,j) (0x00610b18+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_FB_PITCH(i,j) (0x00610b20+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_FB_PITCH_LINEAR_FB (1<<20)
-+# define NV50_PDISPLAY_CRTC_VAL_FB_POS(i,j) (0x00610b28+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_SCALE_CENTER_OFFSET(i,j) (0x00610b38+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_REAL_RES(i,j) (0x00610b40+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_SCALE_RES1(i,j) (0x00610b48+(i)*0x540+(j)*0x4)
-+# define NV50_PDISPLAY_CRTC_VAL_SCALE_RES2(i,j) (0x00610b50+(i)*0x540+(j)*0x4)
-+
-+
-+# define NV50_PDISPLAY_DAC_VAL_MODE_CTRL(i,j) (0x00610b58+(i)*0x8+(j)*0x4)
-+
-+
-+# define NV50_PDISPLAY_SOR_VAL_MODE_CTRL(i,j) (0x00610b70+(i)*0x8+(j)*0x4)
-+
-+
-+# define NV50_PDISPLAY_DAC_VAL_MODE_CTRL2(i,j) (0x00610bdc+(i)*0x8+(j)*0x4)
-+
-+
-+# define NV50_PDISPLAY_CRTC_CLK 0x00614000
-+# define NV50_PDISPLAY_CRTC_CLK__LEN 0x2
-+# define NV50_PDISPLAY_CRTC_CLK_CLK_CTRL1(i) (0x00614100+(i)*0x800)
-+# define NV50_PDISPLAY_CRTC_CLK_CLK_CTRL1_CONNECTED 0x00000600
-+# define NV50_PDISPLAY_CRTC_CLK_CLK_CTRL1_CONNECTED__SHIFT 9
-+# define NV50_PDISPLAY_CRTC_CLK_VPLL_A(i) (0x00614104+(i)*0x800)
-+# define NV50_PDISPLAY_CRTC_CLK_VPLL_B(i) (0x00614108+(i)*0x800)
-+# define NV50_PDISPLAY_CRTC_CLK_CLK_CTRL2(i) (0x00614200+(i)*0x800)
-+
-+# define NV50_PDISPLAY_DAC_CLK 0x00614000
-+# define NV50_PDISPLAY_DAC_CLK__LEN 0x3
-+# define NV50_PDISPLAY_DAC_CLK_CLK_CTRL2(i) (0x00614280+(i)*0x800)
-+
-+# define NV50_PDISPLAY_SOR_CLK 0x00614000
-+# define NV50_PDISPLAY_SOR_CLK__LEN 0x3
-+# define NV50_PDISPLAY_SOR_CLK_CLK_CTRL2(i) (0x00614300+(i)*0x800)
++#define NV50_PDISPLAY_CRTC_P(i,r) ((i) * 0x540 + NV50_PDISPLAY_CRTC_##r)
++#define NV50_PDISPLAY_CRTC_C(i,r) (4 + (i) * 0x540 + NV50_PDISPLAY_CRTC_##r)
++#define NV50_PDISPLAY_CRTC_UNK_0A18 /* mthd 0x0900 */ 0x00610a18
++#define NV50_PDISPLAY_CRTC_CLUT_MODE 0x00610a24
++#define NV50_PDISPLAY_CRTC_INTERLACE 0x00610a48
++#define NV50_PDISPLAY_CRTC_SCALE_CTRL 0x00610a50
++#define NV50_PDISPLAY_CRTC_CURSOR_CTRL 0x00610a58
++#define NV50_PDISPLAY_CRTC_UNK0A78 /* mthd 0x0904 */ 0x00610a78
++#define NV50_PDISPLAY_CRTC_UNK0AB8 0x00610ab8
++#define NV50_PDISPLAY_CRTC_DEPTH 0x00610ac8
++#define NV50_PDISPLAY_CRTC_CLOCK 0x00610ad0
++#define NV50_PDISPLAY_CRTC_COLOR_CTRL 0x00610ae0
++#define NV50_PDISPLAY_CRTC_SYNC_START_TO_BLANK_END 0x00610ae8
++#define NV50_PDISPLAY_CRTC_MODE_UNK1 0x00610af0
++#define NV50_PDISPLAY_CRTC_DISPLAY_TOTAL 0x00610af8
++#define NV50_PDISPLAY_CRTC_SYNC_DURATION 0x00610b00
++#define NV50_PDISPLAY_CRTC_MODE_UNK2 0x00610b08
++#define NV50_PDISPLAY_CRTC_UNK_0B10 /* mthd 0x0828 */ 0x00610b10
++#define NV50_PDISPLAY_CRTC_FB_SIZE 0x00610b18
++#define NV50_PDISPLAY_CRTC_FB_PITCH 0x00610b20
++#define NV50_PDISPLAY_CRTC_FB_PITCH_LINEAR 0x00100000
++#define NV50_PDISPLAY_CRTC_FB_POS 0x00610b28
++#define NV50_PDISPLAY_CRTC_SCALE_CENTER_OFFSET 0x00610b38
++#define NV50_PDISPLAY_CRTC_REAL_RES 0x00610b40
++#define NV50_PDISPLAY_CRTC_SCALE_RES1 0x00610b48
++#define NV50_PDISPLAY_CRTC_SCALE_RES2 0x00610b50
++
++#define NV50_PDISPLAY_DAC_MODE_CTRL_P(i) (0x00610b58 + (i) * 0x8)
++#define NV50_PDISPLAY_DAC_MODE_CTRL_C(i) (0x00610b5c + (i) * 0x8)
++#define NV50_PDISPLAY_SOR_MODE_CTRL_P(i) (0x00610b70 + (i) * 0x8)
++#define NV50_PDISPLAY_SOR_MODE_CTRL_C(i) (0x00610b74 + (i) * 0x8)
++#define NV50_PDISPLAY_DAC_MODE_CTRL2_P(i) (0x00610bdc + (i) * 0x8)
++#define NV50_PDISPLAY_DAC_MODE_CTRL2_C(i) (0x00610be0 + (i) * 0x8)
++
++#define NV90_PDISPLAY_SOR_MODE_CTRL_P(i) (0x00610794 + (i) * 0x8)
++#define NV90_PDISPLAY_SOR_MODE_CTRL_C(i) (0x00610798 + (i) * 0x8)
++#define NV90_PDISPLAY_DAC_MODE_CTRL_P(i) (0x00610b58 + (i) * 0x8)
++#define NV90_PDISPLAY_DAC_MODE_CTRL_C(i) (0x00610b5c + (i) * 0x8)
++#define NV90_PDISPLAY_DAC_MODE_CTRL2_P(i) (0x00610b80 + (i) * 0x8)
++#define NV90_PDISPLAY_DAC_MODE_CTRL2_C(i) (0x00610b84 + (i) * 0x8)
++
++#define NV50_PDISPLAY_CRTC_CLK 0x00614000
++#define NV50_PDISPLAY_CRTC_CLK__LEN 0x2
++#define NV50_PDISPLAY_CRTC_CLK_CTRL1(i) ((i) * 0x800 + 0x614100)
++#define NV50_PDISPLAY_CRTC_CLK_CTRL1_CONNECTED 0x00000600
++#define NV50_PDISPLAY_CRTC_CLK_CTRL1_CONNECTED__SHIFT 9
++#define NV50_PDISPLAY_CRTC_CLK_VPLL_A(i) ((i) * 0x800 + 0x614104)
++#define NV50_PDISPLAY_CRTC_CLK_VPLL_B(i) ((i) * 0x800 + 0x614108)
++#define NV50_PDISPLAY_CRTC_CLK_CTRL2(i) ((i) * 0x800 + 0x614200)
++
++#define NV50_PDISPLAY_DAC_CLK 0x00614000
++#define NV50_PDISPLAY_DAC_CLK__LEN 0x3
++#define NV50_PDISPLAY_DAC_CLK_CTRL2(i) ((i) * 0x800 + 0x614280)
++
++#define NV50_PDISPLAY_SOR_CLK 0x00614000
++#define NV50_PDISPLAY_SOR_CLK__LEN 0x3
++#define NV50_PDISPLAY_SOR_CLK_CTRL2(i) ((i) * 0x800 + 0x614300)
+
+# define NV50_PDISPLAY_DAC_REGS 0x0061a000
+# define NV50_PDISPLAY_DAC_REGS__LEN 0x3
@@ -16632,12 +16676,13 @@ index 0000000..44337e6
+# define NV50_PDISPLAY_SOR_REGS_DPMS_STATE_ACTIVE__SHIFT 16
+# define NV50_PDISPLAY_SOR_REGS_DPMS_STATE_BLANKED (1<<19)
+# define NV50_PDISPLAY_SOR_REGS_DPMS_STATE_WAIT (1<<28)
++#define NV50_PDISPLAY_BACKLIGHT 0x0061c084
++# define NV50_PDISPLAY_BACKLIGHT_ENABLE 0x80000000
+
-+
-+#define NV50_UNK640000 0x00640000
-+#define NV50_UNK640000__LEN 0x6
-+#define NV50_UNK640000__ESIZE 0x1000
-+# define NV50_UNK640000_UNK_000(i) (0x00640000+(i)*0x1000)
++#define NV50_PDISPLAY_USER(i) (0x00640000 + (i)*0x1000)
++#define NV50_PDISPLAY_USER__SIZE 6
++#define NV50_PDISPLAY_USER_PUT(i) (0x00640000 + (i)*0x1000)
++#define NV50_PDISPLAY_USER_GET(i) (0x00640000 + (i)*0x1000)
+
+#define NV50_HW_CURSOR 0x00647000
+#define NV50_HW_CURSOR__LEN 0x2
@@ -24316,10 +24361,10 @@ index 0000000..fffb8f2
+}
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c
new file mode 100644
-index 0000000..8790d4c
+index 0000000..5ab448a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_crtc.c
-@@ -0,0 +1,807 @@
+@@ -0,0 +1,810 @@
+/*
+ * Copyright (C) 2008 Maarten Maathuis.
+ * All Rights Reserved.
@@ -24577,13 +24622,12 @@ index 0000000..8790d4c
+}
+
+static int
-+nv50_crtc_calc_clock(struct nouveau_crtc *crtc, struct drm_display_mode *mode,
++nv50_crtc_calc_clock(struct drm_device *dev, int head, int clk,
+ uint32_t *bestN1, uint32_t *bestN2, uint32_t *bestM1,
+ uint32_t *bestM2, uint32_t *bestlog2P)
+{
-+ struct drm_device *dev = crtc->base.dev;
+ struct pll_lims limits;
-+ int clk = mode->clock, vco2, crystal;
++ int vco2, crystal;
+ int minvco1, minvco2, minU1, maxU1, minU2, maxU2, minM1, maxM1;
+ int maxvco1, maxvco2, minN1, maxN1, minM2, maxM2, minN2, maxN2;
+ bool fixedgain2;
@@ -24596,8 +24640,8 @@ index 0000000..8790d4c
+ NV_DEBUG(dev, "\n");
+
+ /* These are in the g80 bios tables, at least in mine. */
-+ ret = get_pll_limits(crtc->base.dev,
-+ NV50_PDISPLAY_CRTC_CLK_CLK_CTRL1(crtc->index),
++ ret = get_pll_limits(dev,
++ NV50_PDISPLAY_CRTC_CLK_CTRL1(head),
+ &limits);
+ if (ret)
+ return ret;
@@ -24679,24 +24723,23 @@ index 0000000..8790d4c
+ return bestclk;
+}
+
-+static int
-+nv50_crtc_set_clock(struct nouveau_crtc *crtc, struct drm_display_mode *mode)
++int
++nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk)
+{
-+ struct drm_device *dev = crtc->base.dev;
-+ uint32_t pll_reg = NV50_PDISPLAY_CRTC_CLK_CLK_CTRL1(crtc->index);
++ uint32_t pll_reg = NV50_PDISPLAY_CRTC_CLK_CTRL1(head);
+ uint32_t N1 = 0, N2 = 0, M1 = 0, M2 = 0, log2P = 0;
+ uint32_t reg1 = nv_rd32(pll_reg + 4);
+ uint32_t reg2 = nv_rd32(pll_reg + 8);
+
+ NV_DEBUG(dev, "\n");
+
-+ nv_wr32(pll_reg, NV50_PDISPLAY_CRTC_CLK_CLK_CTRL1_CONNECTED | 0x10000011);
++ nv_wr32(pll_reg, NV50_PDISPLAY_CRTC_CLK_CTRL1_CONNECTED | 0x10000011);
+
+ /* The other bits are typically empty, but let's be on the safe side. */
+ reg1 &= 0xff00ff00;
+ reg2 &= 0x8000ff00;
+
-+ if (!nv50_crtc_calc_clock(crtc, mode, &N1, &N2, &M1, &M2, &log2P))
++ if (!nv50_crtc_calc_clock(dev, head, pclk, &N1, &N2, &M1, &M2, &log2P))
+ return -EINVAL;
+
+ NV_DEBUG(dev, "N1 %d N2 %d M1 %d M2 %d log2P %d\n", N1, N2, M1, M2, log2P);
@@ -24710,6 +24753,11 @@ index 0000000..8790d4c
+ return 0;
+}
+
++static int
++nv50_crtc_set_clock_old(struct nouveau_crtc *crtc, struct drm_display_mode *mode) {
++ return nv50_crtc_set_clock(crtc->base.dev, crtc->index, mode->clock);
++}
++
+static int nv50_crtc_set_clock_mode(struct nouveau_crtc *crtc)
+{
+ struct drm_device *dev = crtc->base.dev;
@@ -24717,7 +24765,7 @@ index 0000000..8790d4c
+ NV_DEBUG(dev, "\n");
+
+ /* This acknowledges a clock request. */
-+ nv_wr32(NV50_PDISPLAY_CRTC_CLK_CLK_CTRL2(crtc->index), 0);
++ nv_wr32(NV50_PDISPLAY_CRTC_CLK_CTRL2(crtc->index), 0);
+
+ return 0;
+}
@@ -25113,7 +25161,7 @@ index 0000000..8790d4c
+ /* set function pointers */
+ crtc->set_dither = nv50_crtc_set_dither;
+ crtc->set_scale = nv50_crtc_set_scale;
-+ crtc->set_clock = nv50_crtc_set_clock;
++ crtc->set_clock = nv50_crtc_set_clock_old;
+ crtc->set_clock_mode = nv50_crtc_set_clock_mode;
+
+ crtc->mode_set.crtc = &crtc->base;
@@ -25279,7 +25327,7 @@ index 0000000..763cffe
+
diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c
new file mode 100644
-index 0000000..ecd16d2
+index 0000000..6386052
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_dac.c
@@ -0,0 +1,280 @@
@@ -25338,7 +25386,7 @@ index 0000000..ecd16d2
+
+ NV_DEBUG(dev, "or %d\n", encoder->or);
+
-+ nv_wr32(NV50_PDISPLAY_DAC_CLK_CLK_CTRL2(encoder->or), 0);
++ nv_wr32(NV50_PDISPLAY_DAC_CLK_CTRL2(encoder->or), 0);
+ return 0;
+}
+
@@ -25565,10 +25613,10 @@ index 0000000..ecd16d2
+
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
new file mode 100644
-index 0000000..fd253c5
+index 0000000..c34e65f
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
-@@ -0,0 +1,421 @@
+@@ -0,0 +1,637 @@
+/*
+ * Copyright (C) 2008 Maarten Maathuis.
+ * All Rights Reserved.
@@ -25602,6 +25650,8 @@ index 0000000..fd253c5
+#include "nouveau_fb.h"
+#include "drm_crtc_helper.h"
+
++extern int nouveau_uscript;
++
+static int nv50_display_pre_init(struct drm_device *dev)
+{
+ uint32_t ram_amount;
@@ -25668,8 +25718,8 @@ index 0000000..fd253c5
+ /* The precise purpose is unknown, i suspect it has something to do
+ * with text mode.
+ */
-+ if (nv_rd32(NV50_PDISPLAY_SUPERVISOR) & 0x100) {
-+ nv_wr32(NV50_PDISPLAY_SUPERVISOR, 0x100);
++ if (nv_rd32(NV50_PDISPLAY_INTR) & 0x100) {
++ nv_wr32(NV50_PDISPLAY_INTR, 0x100);
+ nv_wr32(0x006194e8, nv_rd32(0x006194e8) & ~1);
+ if (!nv_wait(0x006194e8, 2, 0)) {
+ NV_ERROR(dev, "timeout: (0x6194e8 & 2) != 0\n");
@@ -25715,7 +25765,7 @@ index 0000000..fd253c5
+ OUT_MODE(NV50_CRTC0_UNK82C, 0);
+
+ /* enable clock change interrupts. */
-+// nv_wr32(NV50_PDISPLAY_SUPERVISOR_INTR, nv_rd32(NV50_PDISPLAY_SUPERVISOR_INTR) | 0x70);
++// nv_wr32(NV50_PDISPLAY_INTR_EN, nv_rd32(NV50_PDISPLAY_INTR_EN) | 0x70);
+
+ /* enable hotplug interrupts */
+ nv_wr32(NV50_PCONNECTOR_HOTPLUG_CTRL, 0x7FFF7FFF);
@@ -25748,12 +25798,12 @@ index 0000000..fd253c5
+ uint32_t mask;
+
+ if (crtc->index == 1)
-+ mask = NV50_PDISPLAY_SUPERVISOR_CRTC1;
++ mask = NV50_PDISPLAY_INTR_VBLANK_CRTC1;
+ else
-+ mask = NV50_PDISPLAY_SUPERVISOR_CRTC0;
++ mask = NV50_PDISPLAY_INTR_VBLANK_CRTC0;
+
-+ nv_wr32(NV50_PDISPLAY_SUPERVISOR, mask);
-+ if (!nv_wait(NV50_PDISPLAY_SUPERVISOR, mask, mask)) {
++ nv_wr32(NV50_PDISPLAY_INTR, mask);
++ if (!nv_wait(NV50_PDISPLAY_INTR, mask, mask)) {
+ NV_ERROR(dev, "timeout: (0x610024 & 0x%08x) == "
+ "0x%08x\n", mask, mask);
+ NV_ERROR(dev, "0x610024 = 0x%08x\n",
@@ -25780,8 +25830,8 @@ index 0000000..fd253c5
+ }
+
+ /* disable clock change interrupts. */
-+ nv_wr32(NV50_PDISPLAY_SUPERVISOR_INTR,
-+ nv_rd32(NV50_PDISPLAY_SUPERVISOR_INTR) & ~0x70);
++ nv_wr32(NV50_PDISPLAY_INTR_EN,
++ nv_rd32(NV50_PDISPLAY_INTR_EN) & ~0x70);
+
+ /* disable hotplug interrupts */
+ nv_wr32(NV50_PCONNECTOR_HOTPLUG_INTR, 0);
@@ -25952,6 +26002,216 @@ index 0000000..fd253c5
+ }
+}
+
++static int
++nv50_display_irq_head(struct drm_device *dev, int *phead,
++ struct dcb_entry **pdcbent)
++{
++ struct drm_nouveau_private *dev_priv = dev->dev_private;
++ uint32_t unk30 = nv_rd32(NV50_PDISPLAY_UNK30_CTRL);
++ uint32_t dac = 0, sor = 0;
++ int head, i, or;
++
++ /* We're assuming that head 0 *or* head 1 will be active here,
++ * and not both. I'm not sure if the hw will even signal both
++ * ever, but it definitely shouldn't for us as we commit each
++ * CRTC separately, and submission will be blocked by the GPU
++ * until we handle each in turn.
++ */
++ NV_DEBUG(dev, "0x610030: 0x%08x\n", unk30);
++ head = ffs((unk30 >> 9) & 3) - 1;
++ if (head < 0) {
++ NV_ERROR(dev, "no active heads: 0x%08x\n", nv_rd32(0x610030));
++ return -EINVAL;
++ }
++
++ /* This assumes CRTCs are never bound to multiple encoders, which
++ * should be the case.
++ */
++ for (i = 0; i < 3; i++) {
++ if (nv_rd32(NV50_PDISPLAY_DAC_MODE_CTRL_P(i)) & (1 << head))
++ dac |= (1 << i);
++ }
++
++ if (dev_priv->chipset < 0x90 || dev_priv->chipset == 0x92 ||
++ dev_priv->chipset == 0xa0) {
++ for (i = 0; i < 4; i++) {
++ if (nv_rd32(NV50_PDISPLAY_SOR_MODE_CTRL_P(i)) & (1 << head))
++ sor |= (1 << i);
++ }
++ } else {
++ for (i = 0; i < 4; i++) {
++ if (nv_rd32(NV90_PDISPLAY_SOR_MODE_CTRL_P(i)) & (1 << head))
++ sor |= (1 << i);
++ }
++ }
++
++ NV_DEBUG(dev, "dac: 0x%08x, sor: 0x%08x\n", dac, sor);
++
++ if (dac && sor) {
++ NV_ERROR(dev, "multiple encoders: 0x%08x 0x%08x\n", dac, sor);
++ return -1;
++ } else
++ if (dac) {
++ or = ffs(dac) - 1;
++ if (dac & ~(1 << or)) {
++ NV_ERROR(dev, "multiple DAC: 0x%08x\n", dac);
++ return -1;
++ }
++ } else
++ if (sor) {
++ or = ffs(sor) - 1;
++ if (sor & ~(1 << or)) {
++ NV_ERROR(dev, "multiple SOR: 0x%08x\n", sor);
++ return -1;
++ }
++ } else {
++ NV_ERROR(dev, "no encoders!\n");
++ return -1;
++ }
++
++ for (i = 0; i < dev_priv->vbios->dcb->entries; i++) {
++ struct dcb_entry *dcbent = &dev_priv->vbios->dcb->entry[i];
++
++ if (dac && (dcbent->type != OUTPUT_ANALOG &&
++ dcbent->type != OUTPUT_TV))
++ continue;
++ else
++ if (sor && (dcbent->type != OUTPUT_TMDS &&
++ dcbent->type != OUTPUT_LVDS))
++ continue;
++
++ if (dcbent->or & (1 << or)) {
++ *phead = head;
++ *pdcbent = dcbent;
++ return 0;
++ }
++ }
++
++ NV_ERROR(dev, "no DCB entry for %d %d\n", dac != 0, or);
++ return 0;
++}
++
++static void
++nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr)
++{
++ nv_wr32(NV50_PDISPLAY_INTR, intr & NV50_PDISPLAY_INTR_VBLANK_CRTCn);
++}
++
++static void
++nv50_display_unk10_handler(struct drm_device *dev)
++{
++ struct dcb_entry *dcbent;
++ int head, ret;
++
++ ret = nv50_display_irq_head(dev, &head, &dcbent);
++ if (ret)
++ goto ack;
++
++ nv_wr32(0x619494, nv_rd32(0x619494) & ~8);
++
++ nouveau_bios_run_display_table(dev, dcbent, -1);
++
++ack:
++ nv_wr32(NV50_PDISPLAY_INTR, NV50_PDISPLAY_INTR_CLK_UNK10);
++ nv_wr32(0x610030, 0x80000000);
++}
++
++static void
++nv50_display_unk20_handler(struct drm_device *dev)
++{
++ struct drm_nouveau_private *dev_priv = dev->dev_private;
++ struct nvbios *bios = &dev_priv->VBIOS;
++ struct dcb_entry *dcbent;
++ uint32_t tmp, pclk;
++ int head, or, ret;
++
++ ret = nv50_display_irq_head(dev, &head, &dcbent);
++ if (ret)
++ goto ack;
++ or = ffs(dcbent->or) - 1;
++ pclk = nv_rd32(NV50_PDISPLAY_CRTC_P(head, CLOCK)) & 0x3fffff;
++
++ NV_DEBUG(dev, "head %d pxclk: %dKHz\n", head, pclk);
++
++ nouveau_bios_run_display_table(dev, dcbent, -2);
++
++ nv50_crtc_set_clock(dev, head, pclk);
++
++ nouveau_bios_run_display_table(dev, dcbent, pclk);
++
++ tmp = nv_rd32(NV50_PDISPLAY_CRTC_CLK_CTRL2(head));
++ tmp &= ~0x000000f;
++ nv_wr32(NV50_PDISPLAY_CRTC_CLK_CTRL2(head), tmp);
++
++ if (dcbent->type != OUTPUT_ANALOG) {
++ int tclk;
++
++ if (dcbent->type == OUTPUT_LVDS)
++ tclk = bios->fp.duallink_transition_clk;
++ else
++ tclk = 165000;
++
++ tmp = nv_rd32(NV50_PDISPLAY_SOR_CLK_CTRL2(or));
++ tmp &= ~0x00000f0f;
++ if (pclk > tclk)
++ tmp |= 0x00000101;
++ nv_wr32(NV50_PDISPLAY_SOR_CLK_CTRL2(or), tmp);
++ } else {
++ nv_wr32(NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0);
++ }
++
++ack:
++ nv_wr32(NV50_PDISPLAY_INTR, NV50_PDISPLAY_INTR_CLK_UNK20);
++ nv_wr32(0x610030, 0x80000000);
++}
++
++static void
++nv50_display_unk40_handler(struct drm_device *dev)
++{
++ struct dcb_entry *dcbent;
++ int head, pclk, ret;
++
++ ret = nv50_display_irq_head(dev, &head, &dcbent);
++ if (ret)
++ goto ack;
++ pclk = nv_rd32(NV50_PDISPLAY_CRTC_P(head, CLOCK)) & 0x3fffff;
++
++ nouveau_bios_run_display_table(dev, dcbent, -pclk);
++
++ack:
++ nv_wr32(NV50_PDISPLAY_INTR, NV50_PDISPLAY_INTR_CLK_UNK40);
++ nv_wr32(0x610030, 0x80000000);
++ nv_wr32(0x619494, nv_rd32(0x619494) | 8);
++}
++
++static void
++nv50_display_irq_handler(struct drm_device *dev)
++{
++ uint32_t unk20 = nv_rd32(0x610020);
++ uint32_t intr = nv_rd32(NV50_PDISPLAY_INTR);
++ (void)unk20;
++
++ if (!intr)
++ return;
++ NV_DEBUG(dev, "PDISPLAY_INTR 0x%08x\n", intr);
++
++ if (intr & NV50_PDISPLAY_INTR_CLK_UNK10)
++ nv50_display_unk10_handler(dev);
++ else
++ if (intr & NV50_PDISPLAY_INTR_CLK_UNK20)
++ nv50_display_unk20_handler(dev);
++ else
++ if (intr & NV50_PDISPLAY_INTR_CLK_UNK40)
++ nv50_display_unk40_handler(dev);
++ else
++ if (intr & NV50_PDISPLAY_INTR_VBLANK_CRTCn)
++ nv50_display_vblank_handler(dev, intr);
++ else {
++ NV_ERROR(dev, "unknown PDISPLAY_INTR: 0x%08x\n", intr);
++ nv_wr32(NV50_PDISPLAY_INTR, intr);
++ }
++}
++
+void nv50_display_command(struct drm_device *dev, uint32_t mthd, uint32_t val)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -25967,19 +26227,23 @@ index 0000000..fd253c5
+
+ start = ptimer->read(dev);
+ while (nv_rd32(NV50_PDISPLAY_CTRL_STATE) & NV50_PDISPLAY_CTRL_STATE_PENDING) {
-+ const uint32_t super = nv_rd32(NV50_PDISPLAY_SUPERVISOR);
-+ uint32_t state;
++ if (nouveau_uscript) {
++ nv50_display_irq_handler(dev);
++ } else {
++ const uint32_t super = nv_rd32(NV50_PDISPLAY_INTR);
++ uint32_t state;
+
-+ state = (super & NV50_PDISPLAY_SUPERVISOR_CLK_MASK);
-+ state >>= NV50_PDISPLAY_SUPERVISOR_CLK_MASK__SHIFT;
-+ if (state) {
-+ if (state == 2)
-+ nv50_display_vclk_update(dev);
-+
-+ nv_wr32(NV50_PDISPLAY_SUPERVISOR,
-+ (super & NV50_PDISPLAY_SUPERVISOR_CLK_MASK));
-+ nv_wr32(NV50_PDISPLAY_UNK30_CTRL,
-+ NV50_PDISPLAY_UNK30_CTRL_PENDING);
++ state = (super & (NV50_PDISPLAY_INTR_CLK_UNK10 |
++ NV50_PDISPLAY_INTR_CLK_UNK20 |
++ NV50_PDISPLAY_INTR_CLK_UNK40));
++ if (state) {
++ if (state == NV50_PDISPLAY_INTR_CLK_UNK20)
++ nv50_display_vclk_update(dev);
++
++ nv_wr32(NV50_PDISPLAY_INTR, state);
++ nv_wr32(NV50_PDISPLAY_UNK30_CTRL,
++ NV50_PDISPLAY_UNK30_CTRL_PENDING);
++ }
+ }
+
+ if (ptimer->read(dev) - start > 1000000000ULL) {
@@ -25992,10 +26256,10 @@ index 0000000..fd253c5
+
diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h
new file mode 100644
-index 0000000..8cd7fe6
+index 0000000..6bfd56c
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_display.h
-@@ -0,0 +1,43 @@
+@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008 Maarten Maathuis.
+ * All Rights Reserved.
@@ -26037,6 +26301,7 @@ index 0000000..8cd7fe6
+int nv50_display_create(struct drm_device *dev);
+int nv50_display_destroy(struct drm_device *dev);
+int nv50_crtc_blank(struct nouveau_crtc *, bool blank);
++int nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk);
+
+#endif /* __NV50_DISPLAY_H__ */
diff --git a/drivers/gpu/drm/nouveau/nv50_display_commands.h b/drivers/gpu/drm/nouveau/nv50_display_commands.h
@@ -26819,7 +27084,7 @@ index 0000000..fbbc235
+}
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c
new file mode 100644
-index 0000000..1832c3f
+index 0000000..303edbc
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_graph.c
@@ -0,0 +1,336 @@
@@ -48536,10 +48801,10 @@ index 0000000..6572f12
+}
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c
new file mode 100644
-index 0000000..f26cc7b
+index 0000000..6528c9f
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_sor.c
-@@ -0,0 +1,292 @@
+@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2008 Maarten Maathuis.
+ * All Rights Reserved.
@@ -48618,7 +48883,7 @@ index 0000000..f26cc7b
+ * initialisation on certain gpu's. I presume it's some kind of
+ * clock setting, but what precisely i do not know.
+ */
-+ nv_wr32(NV50_PDISPLAY_SOR_CLK_CLK_CTRL2(encoder->or),
++ nv_wr32(NV50_PDISPLAY_SOR_CLK_CTRL2(encoder->or),
+ 0x70000 | ((mode->clock > limit) ? 0x101 : 0));
+
+ return 0;
@@ -48784,7 +49049,8 @@ index 0000000..f26cc7b
+int nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
+{
+ struct nouveau_encoder *encoder = NULL;
-+ int type;
++ int type, ret;
++ bool dum;
+
+ NV_DEBUG(dev, "\n");
+
@@ -48796,6 +49062,9 @@ index 0000000..f26cc7b
+ case OUTPUT_LVDS:
+ NV_INFO(dev, "Detected a LVDS output\n");
+ type = DRM_MODE_ENCODER_LVDS;
++ ret = nouveau_bios_parse_lvds_table(dev, 0, &dum, &dum);
++ if (ret)
++ NV_ERROR(dev, "Error parsing LVDS table: %d\n", ret);
+ break;
+ default:
+ return -EINVAL;
Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-11/kernel.spec,v
retrieving revision 1.1661
retrieving revision 1.1662
diff -u -p -r1.1661 -r1.1662
--- kernel.spec 29 Jun 2009 03:03:13 -0000 1.1661
+++ kernel.spec 29 Jun 2009 06:06:49 -0000 1.1662
@@ -2073,6 +2073,9 @@ fi
# and build.
%changelog
+* Mon Jun 26 2009 Ben Skeggs <bskeggs at redhat.com> 2.6.29.5-200
+- nouveau: backport nv50 output script fixes from upstream
+'
* Mon Jun 26 2009 Ben Skeggs <bskeggs at redhat.com>
- nouveau: fix GT200 context control, will allow use of 3D engine now
More information about the fedora-extras-commits
mailing list