rpms/kernel/F-13 drm-nouveau-drm-fixed-header.patch, NONE, 1.1 drm-nouveau-updates.patch, 1.7, 1.8 kernel.spec, 1.2008, 1.2009
Ben Skeggs
bskeggs at fedoraproject.org
Thu Apr 29 01:06:47 UTC 2010
Author: bskeggs
Update of /cvs/pkgs/rpms/kernel/F-13
In directory cvs01.phx2.fedoraproject.org:/tmp/cvs-serv26715
Modified Files:
drm-nouveau-updates.patch kernel.spec
Added Files:
drm-nouveau-drm-fixed-header.patch
Log Message:
* Thu Apr 29 2010 Ben Skeggs <bskeggs at redhat.com> 2.6.33.3-73
- nouveau: initial eDP support + DP suspend/resume fixes
- nouveau: fix monitor detection on certain chipsets with DP support
- nouveau: better CRTC PLL calculation on latest chipsets
- nouveau: send hotplug events down to userspace
drm-nouveau-drm-fixed-header.patch:
drm_fixed.h | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 67 insertions(+), 1 deletion(-)
--- NEW FILE drm-nouveau-drm-fixed-header.patch ---
>From 98b5715348686cb2d9d695c5010d3831d99b934b Mon Sep 17 00:00:00 2001
From: Ben Skeggs <bskeggs at redhat.com>
Date: Wed, 28 Apr 2010 15:19:10 +1000
Subject: [PATCH] drm-nouveau-drm-fixed-header
---
drivers/gpu/drm/nouveau/drm_fixed.h | 67 +++++++++++++++++++++++++++++++++++
1 files changed, 67 insertions(+), 0 deletions(-)
create mode 100644 drivers/gpu/drm/nouveau/drm_fixed.h
diff --git a/drivers/gpu/drm/nouveau/drm_fixed.h b/drivers/gpu/drm/nouveau/drm_fixed.h
new file mode 100644
index 0000000..4a08a66
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/drm_fixed.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2009 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: Dave Airlie
+ */
+#ifndef DRM_FIXED_H
+#define DRM_FIXED_H
+
+typedef union dfixed {
+ u32 full;
+} fixed20_12;
+
+
+#define dfixed_const(A) (u32)(((A) << 12))/* + ((B + 0.000122)*4096)) */
+#define dfixed_const_half(A) (u32)(((A) << 12) + 2048)
+#define dfixed_const_666(A) (u32)(((A) << 12) + 2731)
+#define dfixed_const_8(A) (u32)(((A) << 12) + 3277)
+#define dfixed_mul(A, B) ((u64)((u64)(A).full * (B).full + 2048) >> 12)
+#define dfixed_init(A) { .full = dfixed_const((A)) }
+#define dfixed_init_half(A) { .full = dfixed_const_half((A)) }
+#define dfixed_trunc(A) ((A).full >> 12)
+
+static inline u32 dfixed_floor(fixed20_12 A)
+{
+ u32 non_frac = dfixed_trunc(A);
+
+ return dfixed_const(non_frac);
+}
+
+static inline u32 dfixed_ceil(fixed20_12 A)
+{
+ u32 non_frac = dfixed_trunc(A);
+
+ if (A.full > dfixed_const(non_frac))
+ return dfixed_const(non_frac + 1);
+ else
+ return dfixed_const(non_frac);
+}
+
+static inline u32 dfixed_div(fixed20_12 A, fixed20_12 B)
+{
+ u64 tmp = ((u64)A.full << 13);
+
+ do_div(tmp, B.full);
+ tmp += 1;
+ tmp /= 2;
+ return lower_32_bits(tmp);
+}
+#endif
--
1.7.0.1
drm-nouveau-updates.patch:
Makefile | 7
nouveau_bios.c | 669 +++++++++-----
nouveau_bios.h | 132 +-
nouveau_bo.c | 68 -
nouveau_calc.c | 4
nouveau_channel.c | 15
nouveau_connector.c | 163 ++-
nouveau_connector.h | 3
nouveau_debugfs.c | 18
nouveau_dma.c | 5
nouveau_dp.c | 8
nouveau_drv.c | 14
nouveau_drv.h | 59 -
nouveau_encoder.h | 3
nouveau_gem.c | 55 -
nouveau_hw.c | 6
nouveau_i2c.c | 23
nouveau_irq.c | 615 ++++++++++++-
nouveau_mem.c | 124 +-
nouveau_reg.h | 1
nouveau_sgdma.c | 18
nouveau_state.c | 20
nv04_crtc.c | 6
nv04_dac.c | 8
nv04_dfp.c | 4
nv04_display.c | 49 -
nv04_fbcon.c | 6
nv04_fifo.c | 5
nv04_tv.c | 2
nv17_tv.c | 6
nv40_fifo.c | 7
nv40_graph.c | 21
nv50_calc.c | 88 +
nv50_crtc.c | 46 -
nv50_dac.c | 4
nv50_display.c | 111 +-
nv50_display.h | 1
nv50_fb.c | 32
nv50_fbcon.c | 17
nv50_fifo.c | 5
nv50_gpio.c | 76 +
nv50_graph.c | 103 +-
nv50_grctx.c | 2383 ++++++++++++++++++++++++++++++++++++++++++++++++++++
nv50_instmem.c | 18
nv50_sor.c | 31
45 files changed, 4295 insertions(+), 764 deletions(-)
Index: drm-nouveau-updates.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-13/drm-nouveau-updates.patch,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -p -r1.7 -r1.8
--- drm-nouveau-updates.patch 15 Apr 2010 22:53:44 -0000 1.7
+++ drm-nouveau-updates.patch 29 Apr 2010 01:06:41 -0000 1.8
@@ -1,7 +1,7 @@
-From 34fdacaf7508f5fd7219b415b533bbb4c52dd300 Mon Sep 17 00:00:00 2001
+From 42258564f2bcbf1e389a758c9d1249296004469d Mon Sep 17 00:00:00 2001
From: Marcin Slusarz <marcin.slusarz at gmail.com>
Date: Wed, 17 Feb 2010 19:04:00 +0100
-Subject: [PATCH 1/2] drm-nouveau-updates
+Subject: [PATCH] drm-nouveau-updates
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@@ -393,10 +393,48 @@ This reverts commit b30083bdb990bcc2829f
drm/nouveau: fix a nouveau_bo dereference after it's been destroyed
Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nouveau: bios parser fixes for eDP boards
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nouveau: dump pll limits entries when debugging is on
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nv50: output calculated crtc pll when debugging on
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nv50: fix suspend/resume with DP outputs
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nv50: store full dcb i2c entry from vbios
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nv50: fix monitor detection on certain chipsets
+
+There appears to be some kind of switch on certain chips to control whether
+the DP auxch or traditional i2c bus will be operational on a connector,
+this commit hopefully fixes nouveau to do the right thing.
+
+Likely only relevent on chips with DP outputs.
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nv50: send hotplug event to userspace
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
+
+drm/nv50: support fractional feedback divider on newer chips
+
+Signed-off-by: Ben Skeggs <bskeggs at redhat.com>
---
- drivers/gpu/drm/nouveau/Makefile | 6 +-
- drivers/gpu/drm/nouveau/nouveau_bios.c | 486 ++++---
- drivers/gpu/drm/nouveau/nouveau_bios.h | 131 +-
+ drivers/gpu/drm/nouveau/Makefile | 7 +-
+ drivers/gpu/drm/nouveau/nouveau_bios.c | 669 +++++---
+ drivers/gpu/drm/nouveau/nouveau_bios.h | 132 +-
drivers/gpu/drm/nouveau/nouveau_bo.c | 68 +-
drivers/gpu/drm/nouveau/nouveau_calc.c | 4 +-
drivers/gpu/drm/nouveau/nouveau_channel.c | 15 +-
@@ -406,13 +444,14 @@ Signed-off-by: Ben Skeggs <bskeggs at redha
drivers/gpu/drm/nouveau/nouveau_dma.c | 5 +
drivers/gpu/drm/nouveau/nouveau_dp.c | 8 +-
drivers/gpu/drm/nouveau/nouveau_drv.c | 14 +-
- drivers/gpu/drm/nouveau/nouveau_drv.h | 53 +-
- drivers/gpu/drm/nouveau/nouveau_encoder.h | 1 +
+ drivers/gpu/drm/nouveau/nouveau_drv.h | 59 +-
+ drivers/gpu/drm/nouveau/nouveau_encoder.h | 3 +
drivers/gpu/drm/nouveau/nouveau_gem.c | 55 +-
drivers/gpu/drm/nouveau/nouveau_hw.c | 6 +-
- drivers/gpu/drm/nouveau/nouveau_i2c.c | 10 +-
+ drivers/gpu/drm/nouveau/nouveau_i2c.c | 23 +-
drivers/gpu/drm/nouveau/nouveau_irq.c | 615 +++++++-
drivers/gpu/drm/nouveau/nouveau_mem.c | 124 +-
+ drivers/gpu/drm/nouveau/nouveau_reg.h | 1 +
drivers/gpu/drm/nouveau/nouveau_sgdma.c | 18 +
drivers/gpu/drm/nouveau/nouveau_state.c | 20 +-
drivers/gpu/drm/nouveau/nv04_crtc.c | 6 +-
@@ -425,8 +464,10 @@ Signed-off-by: Ben Skeggs <bskeggs at redha
drivers/gpu/drm/nouveau/nv17_tv.c | 6 +-
drivers/gpu/drm/nouveau/nv40_fifo.c | 7 +-
drivers/gpu/drm/nouveau/nv40_graph.c | 21 +
+ drivers/gpu/drm/nouveau/nv50_calc.c | 88 +
+ drivers/gpu/drm/nouveau/nv50_crtc.c | 46 +-
drivers/gpu/drm/nouveau/nv50_dac.c | 4 +-
- drivers/gpu/drm/nouveau/nv50_display.c | 76 +-
+ drivers/gpu/drm/nouveau/nv50_display.c | 111 +-
drivers/gpu/drm/nouveau/nv50_display.h | 1 +
drivers/gpu/drm/nouveau/nv50_fb.c | 32 +
drivers/gpu/drm/nouveau/nv50_fbcon.c | 17 +-
@@ -435,17 +476,18 @@ Signed-off-by: Ben Skeggs <bskeggs at redha
drivers/gpu/drm/nouveau/nv50_graph.c | 103 +-
drivers/gpu/drm/nouveau/nv50_grctx.c | 2383 +++++++++++++++++++++++++++
drivers/gpu/drm/nouveau/nv50_instmem.c | 18 +-
- drivers/gpu/drm/nouveau/nv50_sor.c | 25 +-
- 42 files changed, 3961 insertions(+), 716 deletions(-)
+ drivers/gpu/drm/nouveau/nv50_sor.c | 30 +-
+ 45 files changed, 4295 insertions(+), 763 deletions(-)
+ create mode 100644 drivers/gpu/drm/nouveau/nv50_calc.c
create mode 100644 drivers/gpu/drm/nouveau/nv50_fb.c
create mode 100644 drivers/gpu/drm/nouveau/nv50_gpio.c
create mode 100644 drivers/gpu/drm/nouveau/nv50_grctx.c
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
-index 48c290b..453df3f 100644
+index 48c290b..acd31ed 100644
--- a/drivers/gpu/drm/nouveau/Makefile
+++ b/drivers/gpu/drm/nouveau/Makefile
-@@ -12,17 +12,17 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
+@@ -12,17 +12,18 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
nouveau_dp.o nouveau_grctx.o \
nv04_timer.o \
nv04_mc.o nv40_mc.o nv50_mc.o \
@@ -462,15 +504,24 @@ index 48c290b..453df3f 100644
nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \
- nv17_gpio.o
-+ nv17_gpio.o nv50_gpio.o
++ nv17_gpio.o nv50_gpio.o \
++ nv50_calc.o
nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o
nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
-index 0e9cd1d..4b0d67c 100644
+index 0e9cd1d..97d63e1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
-@@ -311,11 +311,11 @@ valid_reg(struct nvbios *bios, uint32_t reg)
+@@ -26,6 +26,7 @@
+ #define NV_DEBUG_NOTRACE
+ #include "nouveau_drv.h"
+ #include "nouveau_hw.h"
++#include "nouveau_encoder.h"
+
+ /* these defines are made up */
+ #define NV_CIO_CRE_44_HEADA 0x0
+@@ -311,11 +312,11 @@ valid_reg(struct nvbios *bios, uint32_t reg)
/* C51 has misaligned regs on purpose. Marvellous */
if (reg & 0x2 ||
@@ -484,7 +535,7 @@ index 0e9cd1d..4b0d67c 100644
reg != 0x130d && reg != 0x1311 && reg != 0x60081d)
NV_WARN(dev, "=== C51 misaligned reg 0x%08X not verified ===\n",
reg);
-@@ -420,7 +420,7 @@ bios_wr32(struct nvbios *bios, uint32_t reg, uint32_t data)
+@@ -420,7 +421,7 @@ bios_wr32(struct nvbios *bios, uint32_t reg, uint32_t data)
LOG_OLD_VALUE(bios_rd32(bios, reg));
BIOSLOG(bios, " Write: Reg: 0x%08X, Data: 0x%08X\n", reg, data);
@@ -493,7 +544,7 @@ index 0e9cd1d..4b0d67c 100644
still_alive();
nv_wr32(bios->dev, reg, data);
}
-@@ -647,7 +647,7 @@ nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk)
+@@ -647,7 +648,7 @@ nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk)
reg0 = (reg0 & 0xfff8ffff) | (pll.log2P << 16);
reg1 = (reg1 & 0xffff0000) | (pll.N1 << 8) | pll.M1;
@@ -502,7 +553,7 @@ index 0e9cd1d..4b0d67c 100644
still_alive();
nv_wr32(dev, reg + 4, reg1);
nv_wr32(dev, reg + 0, reg0);
-@@ -689,7 +689,7 @@ setPLL(struct nvbios *bios, uint32_t reg, uint32_t clk)
+@@ -689,7 +690,7 @@ setPLL(struct nvbios *bios, uint32_t reg, uint32_t clk)
static int dcb_entry_idx_from_crtchead(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -511,7 +562,7 @@ index 0e9cd1d..4b0d67c 100644
/*
* For the results of this function to be correct, CR44 must have been
-@@ -700,7 +700,7 @@ static int dcb_entry_idx_from_crtchead(struct drm_device *dev)
+@@ -700,7 +701,7 @@ static int dcb_entry_idx_from_crtchead(struct drm_device *dev)
uint8_t dcb_entry = NVReadVgaCrtc5758(dev, bios->state.crtchead, 0);
@@ -520,7 +571,7 @@ index 0e9cd1d..4b0d67c 100644
NV_ERROR(dev, "CR58 doesn't have a valid DCB entry currently "
"(%02X)\n", dcb_entry);
dcb_entry = 0x7f; /* unused / invalid marker */
-@@ -713,25 +713,26 @@ static struct nouveau_i2c_chan *
+@@ -713,25 +714,26 @@ static struct nouveau_i2c_chan *
init_i2c_device_find(struct drm_device *dev, int i2c_index)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -552,7 +603,7 @@ index 0e9cd1d..4b0d67c 100644
{
/*
* For mlv < 0x80, it is an index into a table of TMDS base addresses.
-@@ -744,6 +745,7 @@ static uint32_t get_tmds_index_reg(struct drm_device *dev, uint8_t mlv)
+@@ -744,6 +746,7 @@ static uint32_t get_tmds_index_reg(struct drm_device *dev, uint8_t mlv)
*/
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -560,7 +611,7 @@ index 0e9cd1d..4b0d67c 100644
const int pramdac_offset[13] = {
0, 0, 0x8, 0, 0x2000, 0, 0, 0, 0x2008, 0, 0, 0, 0x2000 };
const uint32_t pramdac_table[4] = {
-@@ -756,13 +758,12 @@ static uint32_t get_tmds_index_reg(struct drm_device *dev, uint8_t mlv)
+@@ -756,13 +759,12 @@ static uint32_t get_tmds_index_reg(struct drm_device *dev, uint8_t mlv)
dcb_entry = dcb_entry_idx_from_crtchead(dev);
if (dcb_entry == 0x7f)
return 0;
@@ -576,7 +627,134 @@ index 0e9cd1d..4b0d67c 100644
NV_ERROR(dev, "Magic Lookup Value too big (%02X)\n",
mlv);
return 0;
-@@ -2572,48 +2573,34 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+@@ -1066,6 +1068,126 @@ init_io_flag_condition(struct nvbios *bios, uint16_t offset,
+ }
+
+ static int
++init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
++{
++ /*
++ * INIT_DP_CONDITION opcode: 0x3A ('')
++ *
++ * offset (8 bit): opcode
++ * offset + 1 (8 bit): "sub" opcode
++ * offset + 2 (8 bit): unknown
++ *
++ */
++
++ struct bit_displayport_encoder_table *dpe = NULL;
++ struct dcb_entry *dcb = bios->display.output;
++ struct drm_device *dev = bios->dev;
++ uint8_t cond = bios->data[offset + 1];
++ int dummy;
++
++ BIOSLOG(bios, "0x%04X: subop 0x%02X\n", offset, cond);
++
++ if (!iexec->execute)
++ return 3;
++
++ dpe = nouveau_bios_dp_table(dev, dcb, &dummy);
++ if (!dpe) {
++ NV_ERROR(dev, "0x%04X: INIT_3A: no encoder table!!\n", offset);
++ return -EINVAL;
++ }
++
++ switch (cond) {
++ case 0:
++ {
++ struct dcb_connector_table_entry *ent =
++ &bios->dcb.connector.entry[dcb->connector];
++
++ if (ent->type != DCB_CONNECTOR_eDP)
++ iexec->execute = false;
++ }
++ break;
++ case 1:
++ case 2:
++ if (!(dpe->unknown & cond))
++ iexec->execute = false;
++ break;
++ case 5:
++ {
++ struct nouveau_i2c_chan *auxch;
++ int ret;
++
++ auxch = nouveau_i2c_find(dev, bios->display.output->i2c_index);
++ if (!auxch)
++ return -ENODEV;
++
++ ret = nouveau_dp_auxch(auxch, 9, 0xd, &cond, 1);
++ if (ret)
++ return ret;
++
++ if (cond & 1)
++ iexec->execute = false;
++ }
++ break;
++ default:
++ NV_WARN(dev, "0x%04X: unknown INIT_3A op: %d\n", offset, cond);
++ break;
++ }
++
++ if (iexec->execute)
++ BIOSLOG(bios, "0x%04X: continuing to execute\n", offset);
++ else
++ BIOSLOG(bios, "0x%04X: skipping following commands\n", offset);
++
++ return 3;
++}
++
++static int
++init_op_3b(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
++{
++ /*
++ * INIT_3B opcode: 0x3B ('')
++ *
++ * offset (8 bit): opcode
++ * offset + 1 (8 bit): crtc index
++ *
++ */
++
++ uint8_t or = ffs(bios->display.output->or) - 1;
++ uint8_t index = bios->data[offset + 1];
++ uint8_t data;
++
++ if (!iexec->execute)
++ return 2;
++
++ data = bios_idxprt_rd(bios, 0x3d4, index);
++ bios_idxprt_wr(bios, 0x3d4, index, data & ~(1 << or));
++ return 2;
++}
++
++static int
++init_op_3c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
++{
++ /*
++ * INIT_3C opcode: 0x3C ('')
++ *
++ * offset (8 bit): opcode
++ * offset + 1 (8 bit): crtc index
++ *
++ */
++
++ uint8_t or = ffs(bios->display.output->or) - 1;
++ uint8_t index = bios->data[offset + 1];
++ uint8_t data;
++
++ if (!iexec->execute)
++ return 2;
++
++ data = bios_idxprt_rd(bios, 0x3d4, index);
++ bios_idxprt_wr(bios, 0x3d4, index, data | (1 << or));
++ return 2;
++}
++
++static int
+ init_idx_addr_latched(struct nvbios *bios, uint16_t offset,
+ struct init_exec *iexec)
+ {
+@@ -2572,48 +2694,34 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
* each GPIO according to various values listed in each entry
*/
@@ -593,32 +771,31 @@ index 0e9cd1d..4b0d67c 100644
- if (bios->bdcb.version != 0x40) {
- NV_ERROR(bios->dev, "DCB table not version 4.0\n");
- return 0;
+- }
+-
+- if (!bios->bdcb.gpio_table_ptr) {
+- NV_WARN(bios->dev, "Invalid pointer to INIT_8E table\n");
+- return 0;
+ if (dev_priv->card_type != NV_50) {
+ NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n");
+ return -ENODEV;
}
-- if (!bios->bdcb.gpio_table_ptr) {
-- NV_WARN(bios->dev, "Invalid pointer to INIT_8E table\n");
-- return 0;
-- }
-+ if (!iexec->execute)
-+ return 1;
-
- gpio_entry = gpio_table + gpio_table[1];
- for (i = 0; i < gpio_table[2]; i++, gpio_entry += gpio_table[3]) {
- uint32_t entry = ROM32(gpio_entry[0]), r, s, v;
- int line = (entry & 0x0000001f);
++ if (!iexec->execute)
++ return 1;
+
+- BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, entry);
+ for (i = 0; i < bios->dcb.gpio.entries; i++) {
+ struct dcb_gpio_entry *gpio = &bios->dcb.gpio.entry[i];
+ uint32_t r, s, v;
-- BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, entry);
-+ BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry);
-
- if ((entry & 0x0000ff00) == 0x0000ff00)
- continue;
-+ nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default);
++ BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry);
- r = nv50_gpio_reg[line >> 3];
- s = (line & 0x07) << 2;
@@ -628,7 +805,8 @@ index 0e9cd1d..4b0d67c 100644
- else
- v |= (((entry & 0x18000000) >> 27) ^ 2) << s;
- bios_wr32(bios, r, v);
--
++ nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default);
+
- r = nv50_gpio_ctl[line >> 4];
- s = (line & 0x0f);
+ /* The NVIDIA binary driver doesn't appear to actually do
@@ -643,7 +821,17 @@ index 0e9cd1d..4b0d67c 100644
case 1:
v |= (0x00000001 << s);
break;
-@@ -3123,7 +3110,7 @@ run_digital_op_script(struct drm_device *dev, uint16_t scriptptr,
+@@ -2947,6 +3055,9 @@ static struct init_tbl_entry itbl_entry[] = {
+ { "INIT_COPY" , 0x37, init_copy },
+ { "INIT_NOT" , 0x38, init_not },
+ { "INIT_IO_FLAG_CONDITION" , 0x39, init_io_flag_condition },
++ { "INIT_DP_CONDITION" , 0x3A, init_dp_condition },
++ { "INIT_OP_3B" , 0x3B, init_op_3b },
++ { "INIT_OP_3C" , 0x3C, init_op_3c },
+ { "INIT_INDEX_ADDRESS_LATCHED" , 0x49, init_idx_addr_latched },
+ { "INIT_IO_RESTRICT_PLL2" , 0x4A, init_io_restrict_pll2 },
+ { "INIT_PLL2" , 0x4B, init_pll2 },
+@@ -3123,7 +3234,7 @@ run_digital_op_script(struct drm_device *dev, uint16_t scriptptr,
struct dcb_entry *dcbent, int head, bool dl)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -652,7 +840,7 @@ index 0e9cd1d..4b0d67c 100644
struct init_exec iexec = {true, false};
NV_TRACE(dev, "0x%04X: Parsing digital output script table\n",
-@@ -3140,7 +3127,7 @@ run_digital_op_script(struct drm_device *dev, uint16_t scriptptr,
+@@ -3140,7 +3251,7 @@ run_digital_op_script(struct drm_device *dev, uint16_t scriptptr,
static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entry *dcbent, int head, enum LVDS_script script)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -661,7 +849,7 @@ index 0e9cd1d..4b0d67c 100644
uint8_t sub = bios->data[bios->fp.xlated_entry + script] + (bios->fp.link_c_increment && dcbent->or & OUTPUT_C ? 1 : 0);
uint16_t scriptofs = ROM16(bios->data[bios->init_script_tbls_ptr + sub * 2]);
-@@ -3194,10 +3181,9 @@ static int run_lvds_table(struct drm_device *dev, struct dcb_entry *dcbent, int
+@@ -3194,10 +3305,9 @@ static int run_lvds_table(struct drm_device *dev, struct dcb_entry *dcbent, int
* of a list of pxclks and script pointers.
*/
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -673,7 +861,7 @@ index 0e9cd1d..4b0d67c 100644
/*
* For now we assume version 3.0 table - g80 support will need some
-@@ -3216,26 +3202,29 @@ static int run_lvds_table(struct drm_device *dev, struct dcb_entry *dcbent, int
+@@ -3216,26 +3326,29 @@ static int run_lvds_table(struct drm_device *dev, struct dcb_entry *dcbent, int
scriptptr = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 11 + outputset * 2]);
break;
case LVDS_RESET:
@@ -714,7 +902,7 @@ index 0e9cd1d..4b0d67c 100644
if (!clktable) {
NV_ERROR(dev, "Pixel clock comparison table not found\n");
return -ENOENT;
-@@ -3261,7 +3250,7 @@ int call_lvds_script(struct drm_device *dev, struct dcb_entry *dcbent, int head,
+@@ -3261,7 +3374,7 @@ int call_lvds_script(struct drm_device *dev, struct dcb_entry *dcbent, int head,
*/
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -723,7 +911,7 @@ index 0e9cd1d..4b0d67c 100644
uint8_t lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer];
uint32_t sel_clk_binding, sel_clk;
int ret;
-@@ -3395,7 +3384,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios)
+@@ -3395,7 +3508,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios)
#ifndef __powerpc__
NV_ERROR(dev, "Pointer to flat panel table invalid\n");
#endif
@@ -732,7 +920,7 @@ index 0e9cd1d..4b0d67c 100644
return 0;
}
-@@ -3428,7 +3417,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios)
+@@ -3428,7 +3541,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios)
* fptable[4] is the minimum
* RAMDAC_FP_HCRTC -> RAMDAC_FP_HSYNC_START gap
*/
@@ -741,7 +929,7 @@ index 0e9cd1d..4b0d67c 100644
ofs = -7;
break;
default:
-@@ -3467,7 +3456,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios)
+@@ -3467,7 +3580,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios)
/* nv4x cards need both a strap value and fpindex of 0xf to use DDC */
if (lth.lvds_ver > 0x10)
@@ -750,7 +938,7 @@ index 0e9cd1d..4b0d67c 100644
/*
* If either the strap or xlated fpindex value are 0xf there is no
-@@ -3491,7 +3480,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios)
+@@ -3491,7 +3604,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios)
bool nouveau_bios_fp_mode(struct drm_device *dev, struct drm_display_mode *mode)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -759,7 +947,7 @@ index 0e9cd1d..4b0d67c 100644
uint8_t *mode_entry = &bios->data[bios->fp.mode_ptr];
if (!mode) /* just checking whether we can produce a mode */
-@@ -3562,11 +3551,11 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b
+@@ -3562,11 +3675,11 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b
* until later, when this function should be called with non-zero pxclk
*/
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -773,7 +961,7 @@ index 0e9cd1d..4b0d67c 100644
ret = parse_lvds_manufacturer_table_header(dev, bios, <h);
if (ret)
-@@ -3637,37 +3626,40 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b
+@@ -3637,37 +3750,40 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b
*if_is_24bit = bios->data[lvdsofs] & 16;
break;
case 0x30:
@@ -829,7 +1017,7 @@ index 0e9cd1d..4b0d67c 100644
/* set dual_link flag for EDID case */
if (pxclk && (chip_version < 0x25 || chip_version > 0x28))
bios->fp.dual_link = (pxclk >= bios->fp.duallink_transition_clk);
-@@ -3682,7 +3674,7 @@ bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent,
+@@ -3682,7 +3798,7 @@ bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent,
uint16_t record, int record_len, int record_nr)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -838,7 +1026,7 @@ index 0e9cd1d..4b0d67c 100644
uint32_t entry;
uint16_t table;
int i, v;
-@@ -3716,7 +3708,7 @@ nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent,
+@@ -3716,7 +3832,7 @@ nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent,
int *length)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -847,7 +1035,7 @@ index 0e9cd1d..4b0d67c 100644
uint8_t *table;
if (!bios->display.dp_table_ptr) {
-@@ -3725,7 +3717,7 @@ nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent,
+@@ -3725,7 +3841,7 @@ nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent,
}
table = &bios->data[bios->display.dp_table_ptr];
@@ -856,7 +1044,7 @@ index 0e9cd1d..4b0d67c 100644
NV_ERROR(dev, "DisplayPort table version 0x%02x unknown\n",
table[0]);
return NULL;
-@@ -3765,7 +3757,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
+@@ -3765,7 +3881,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
*/
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -865,7 +1053,7 @@ index 0e9cd1d..4b0d67c 100644
uint8_t *table = &bios->data[bios->display.script_table_ptr];
uint8_t *otable = NULL;
uint16_t script;
-@@ -3918,8 +3910,8 @@ int run_tmds_table(struct drm_device *dev, struct dcb_entry *dcbent, int head, i
+@@ -3918,8 +4034,8 @@ int run_tmds_table(struct drm_device *dev, struct dcb_entry *dcbent, int head, i
*/
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -876,7 +1064,7 @@ index 0e9cd1d..4b0d67c 100644
uint16_t clktable = 0, scriptptr;
uint32_t sel_clk_binding, sel_clk;
-@@ -3978,8 +3970,8 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims
+@@ -3978,8 +4094,8 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims
*/
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -887,7 +1075,65 @@ index 0e9cd1d..4b0d67c 100644
uint8_t pll_lim_ver = 0, headerlen = 0, recordlen = 0, entries = 0;
uint32_t crystal_strap_mask, crystal_straps;
-@@ -4332,7 +4324,7 @@ static void parse_bios_version(struct drm_device *dev, struct nvbios *bios, uint
+@@ -4293,31 +4409,32 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims
+ break;
+ }
+
+-#if 0 /* for easy debugging */
+- ErrorF("pll.vco1.minfreq: %d\n", pll_lim->vco1.minfreq);
+- ErrorF("pll.vco1.maxfreq: %d\n", pll_lim->vco1.maxfreq);
+- ErrorF("pll.vco2.minfreq: %d\n", pll_lim->vco2.minfreq);
+- ErrorF("pll.vco2.maxfreq: %d\n", pll_lim->vco2.maxfreq);
+-
+- ErrorF("pll.vco1.min_inputfreq: %d\n", pll_lim->vco1.min_inputfreq);
+- ErrorF("pll.vco1.max_inputfreq: %d\n", pll_lim->vco1.max_inputfreq);
+- ErrorF("pll.vco2.min_inputfreq: %d\n", pll_lim->vco2.min_inputfreq);
+- ErrorF("pll.vco2.max_inputfreq: %d\n", pll_lim->vco2.max_inputfreq);
+-
+- ErrorF("pll.vco1.min_n: %d\n", pll_lim->vco1.min_n);
+- ErrorF("pll.vco1.max_n: %d\n", pll_lim->vco1.max_n);
+- ErrorF("pll.vco1.min_m: %d\n", pll_lim->vco1.min_m);
+- ErrorF("pll.vco1.max_m: %d\n", pll_lim->vco1.max_m);
+- ErrorF("pll.vco2.min_n: %d\n", pll_lim->vco2.min_n);
+- ErrorF("pll.vco2.max_n: %d\n", pll_lim->vco2.max_n);
+- ErrorF("pll.vco2.min_m: %d\n", pll_lim->vco2.min_m);
+- ErrorF("pll.vco2.max_m: %d\n", pll_lim->vco2.max_m);
+-
+- ErrorF("pll.max_log2p: %d\n", pll_lim->max_log2p);
+- ErrorF("pll.log2p_bias: %d\n", pll_lim->log2p_bias);
+-
+- ErrorF("pll.refclk: %d\n", pll_lim->refclk);
+-#endif
++ NV_DEBUG(dev, "pll.vco1.minfreq: %d\n", pll_lim->vco1.minfreq);
++ NV_DEBUG(dev, "pll.vco1.maxfreq: %d\n", pll_lim->vco1.maxfreq);
++ NV_DEBUG(dev, "pll.vco1.min_inputfreq: %d\n", pll_lim->vco1.min_inputfreq);
++ NV_DEBUG(dev, "pll.vco1.max_inputfreq: %d\n", pll_lim->vco1.max_inputfreq);
++ NV_DEBUG(dev, "pll.vco1.min_n: %d\n", pll_lim->vco1.min_n);
++ NV_DEBUG(dev, "pll.vco1.max_n: %d\n", pll_lim->vco1.max_n);
++ NV_DEBUG(dev, "pll.vco1.min_m: %d\n", pll_lim->vco1.min_m);
++ NV_DEBUG(dev, "pll.vco1.max_m: %d\n", pll_lim->vco1.max_m);
++ if (pll_lim->vco2.maxfreq) {
++ NV_DEBUG(dev, "pll.vco2.minfreq: %d\n", pll_lim->vco2.minfreq);
++ NV_DEBUG(dev, "pll.vco2.maxfreq: %d\n", pll_lim->vco2.maxfreq);
++ NV_DEBUG(dev, "pll.vco2.min_inputfreq: %d\n", pll_lim->vco2.min_inputfreq);
++ NV_DEBUG(dev, "pll.vco2.max_inputfreq: %d\n", pll_lim->vco2.max_inputfreq);
++ NV_DEBUG(dev, "pll.vco2.min_n: %d\n", pll_lim->vco2.min_n);
++ NV_DEBUG(dev, "pll.vco2.max_n: %d\n", pll_lim->vco2.max_n);
++ NV_DEBUG(dev, "pll.vco2.min_m: %d\n", pll_lim->vco2.min_m);
++ NV_DEBUG(dev, "pll.vco2.max_m: %d\n", pll_lim->vco2.max_m);
++ }
++ if (!pll_lim->max_p) {
++ NV_DEBUG(dev, "pll.max_log2p: %d\n", pll_lim->max_log2p);
++ NV_DEBUG(dev, "pll.log2p_bias: %d\n", pll_lim->log2p_bias);
++ } else {
++ NV_DEBUG(dev, "pll.min_p: %d\n", pll_lim->min_p);
++ NV_DEBUG(dev, "pll.max_p: %d\n", pll_lim->max_p);
++ }
++ NV_DEBUG(dev, "pll.refclk: %d\n", pll_lim->refclk);
+
+ return 0;
+ }
+@@ -4332,7 +4449,7 @@ static void parse_bios_version(struct drm_device *dev, struct nvbios *bios, uint
*/
bios->major_version = bios->data[offset + 3];
@@ -896,7 +1142,7 @@ index 0e9cd1d..4b0d67c 100644
NV_TRACE(dev, "Bios version %02x.%02x.%02x.%02x\n",
bios->data[offset + 3], bios->data[offset + 2],
bios->data[offset + 1], bios->data[offset]);
-@@ -4402,7 +4394,7 @@ static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, st
+@@ -4402,7 +4519,7 @@ static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, st
}
/* First entry is normal dac, 2nd tv-out perhaps? */
@@ -905,7 +1151,7 @@ index 0e9cd1d..4b0d67c 100644
return 0;
}
-@@ -4526,8 +4518,8 @@ static int parse_bit_i_tbl_entry(struct drm_device *dev, struct nvbios *bios, st
+@@ -4526,8 +4643,8 @@ static int parse_bit_i_tbl_entry(struct drm_device *dev, struct nvbios *bios, st
return -ENOSYS;
}
@@ -916,7 +1162,7 @@ index 0e9cd1d..4b0d67c 100644
return 0;
}
-@@ -4796,11 +4788,11 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi
+@@ -4796,11 +4913,11 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi
uint16_t legacy_scripts_offset, legacy_i2c_offset;
/* load needed defaults in case we can't parse this info */
@@ -933,7 +1179,7 @@ index 0e9cd1d..4b0d67c 100644
bios->fmaxvco = 256000;
bios->fminvco = 128000;
bios->fp.duallink_transition_clk = 90000;
-@@ -4907,10 +4899,10 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi
+@@ -4907,10 +5024,10 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi
bios->legacy.i2c_indices.crt = bios->data[legacy_i2c_offset];
bios->legacy.i2c_indices.tv = bios->data[legacy_i2c_offset + 1];
bios->legacy.i2c_indices.panel = bios->data[legacy_i2c_offset + 2];
@@ -948,7 +1194,7 @@ index 0e9cd1d..4b0d67c 100644
if (bmplength > 74) {
bios->fmaxvco = ROM32(bmp[67]);
-@@ -4984,7 +4976,8 @@ read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, i
+@@ -4984,7 +5101,8 @@ read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, i
else
NV_WARN(dev,
"DCB I2C table has more entries than indexable "
@@ -958,7 +1204,7 @@ index 0e9cd1d..4b0d67c 100644
entry_len = i2ctable[3];
/* [4] is i2c_default_indices, read in parse_dcb_table() */
}
-@@ -5000,8 +4993,8 @@ read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, i
+@@ -5000,8 +5118,8 @@ read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, i
if (index == 0xf)
return 0;
@@ -969,7 +1215,22 @@ index 0e9cd1d..4b0d67c 100644
index, i2ctable[2]);
return -ENOENT;
}
-@@ -5036,7 +5029,7 @@ read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, i
+@@ -5023,8 +5141,12 @@ read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, i
+ rdofs = wrofs = 0;
+ }
+
+- if (dcb_i2c_ver >= 0x40 && port_type != 5 && port_type != 6)
+- NV_WARN(dev, "DCB I2C table has port type %d\n", port_type);
++ if (dcb_i2c_ver >= 0x40) {
++ if (port_type != 5 && port_type != 6)
++ NV_WARN(dev, "DCB I2C table has port type %d\n", port_type);
++
++ i2c->entry = ROM32(i2ctable[headerlen + recordoffset + entry_len * index]);
++ }
+
+ i2c->port_type = port_type;
+ i2c->read = i2ctable[headerlen + recordoffset + rdofs + entry_len * index];
+@@ -5036,7 +5158,7 @@ read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, i
static struct dcb_gpio_entry *
new_gpio_entry(struct nvbios *bios)
{
@@ -978,7 +1239,7 @@ index 0e9cd1d..4b0d67c 100644
return &gpio->entry[gpio->entries++];
}
-@@ -5045,14 +5038,14 @@ struct dcb_gpio_entry *
+@@ -5045,14 +5167,14 @@ struct dcb_gpio_entry *
nouveau_bios_gpio_entry(struct drm_device *dev, enum dcb_gpio_tag tag)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -997,7 +1258,7 @@ index 0e9cd1d..4b0d67c 100644
}
return NULL;
-@@ -5075,32 +5068,32 @@ parse_dcb30_gpio_entry(struct nvbios *bios, uint16_t offset)
+@@ -5075,32 +5197,32 @@ parse_dcb30_gpio_entry(struct nvbios *bios, uint16_t offset)
gpio->tag = tag;
gpio->line = line;
gpio->invert = flags != 4;
@@ -1040,7 +1301,7 @@ index 0e9cd1d..4b0d67c 100644
uint8_t *gpio_table = &bios->data[gpio_table_ptr];
int header_len = gpio_table[1],
entries = gpio_table[2],
-@@ -5108,7 +5101,7 @@ parse_dcb_gpio_table(struct nvbios *bios)
+@@ -5108,7 +5230,7 @@ parse_dcb_gpio_table(struct nvbios *bios)
void (*parse_entry)(struct nvbios *, uint16_t) = NULL;
int i;
@@ -1049,7 +1310,7 @@ index 0e9cd1d..4b0d67c 100644
if (gpio_table_ptr && entry_len != 4) {
NV_WARN(dev, "Invalid DCB GPIO table entry length.\n");
return;
-@@ -5116,7 +5109,7 @@ parse_dcb_gpio_table(struct nvbios *bios)
+@@ -5116,7 +5238,7 @@ parse_dcb_gpio_table(struct nvbios *bios)
parse_entry = parse_dcb40_gpio_entry;
@@ -1058,7 +1319,7 @@ index 0e9cd1d..4b0d67c 100644
if (gpio_table_ptr && entry_len != 2) {
NV_WARN(dev, "Invalid DCB GPIO table entry length.\n");
return;
-@@ -5124,7 +5117,7 @@ parse_dcb_gpio_table(struct nvbios *bios)
+@@ -5124,7 +5246,7 @@ parse_dcb_gpio_table(struct nvbios *bios)
parse_entry = parse_dcb30_gpio_entry;
@@ -1067,7 +1328,7 @@ index 0e9cd1d..4b0d67c 100644
/*
* DCBs older than v3.0 don't really have a GPIO
* table, instead they keep some GPIO info at fixed
-@@ -5158,30 +5151,82 @@ struct dcb_connector_table_entry *
+@@ -5158,30 +5280,82 @@ struct dcb_connector_table_entry *
nouveau_bios_connector_entry(struct drm_device *dev, int index)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -1156,7 +1417,7 @@ index 0e9cd1d..4b0d67c 100644
NV_DEBUG_KMS(dev, "No DCB connector table present\n");
return;
}
-@@ -5199,12 +5244,14 @@ parse_dcb_connector_table(struct nvbios *bios)
+@@ -5199,12 +5373,14 @@ parse_dcb_connector_table(struct nvbios *bios)
entry = conntab + conntab[1];
cte = &ct->entry[0];
for (i = 0; i < conntab[2]; i++, entry += conntab[3], cte++) {
@@ -1172,7 +1433,7 @@ index 0e9cd1d..4b0d67c 100644
switch (cte->entry & 0x00033000) {
case 0x00001000:
cte->gpio_tag = 0x07;
-@@ -5226,12 +5273,43 @@ parse_dcb_connector_table(struct nvbios *bios)
+@@ -5226,12 +5402,43 @@ parse_dcb_connector_table(struct nvbios *bios)
if (cte->type == 0xff)
continue;
@@ -1217,7 +1478,7 @@ index 0e9cd1d..4b0d67c 100644
{
struct dcb_entry *entry = &dcb->entry[dcb->entries];
-@@ -5241,7 +5319,7 @@ static struct dcb_entry *new_dcb_entry(struct parsed_dcb *dcb)
+@@ -5241,7 +5448,7 @@ static struct dcb_entry *new_dcb_entry(struct parsed_dcb *dcb)
return entry;
}
@@ -1226,7 +1487,7 @@ index 0e9cd1d..4b0d67c 100644
{
struct dcb_entry *entry = new_dcb_entry(dcb);
-@@ -5252,7 +5330,7 @@ static void fabricate_vga_output(struct parsed_dcb *dcb, int i2c, int heads)
+@@ -5252,7 +5459,7 @@ static void fabricate_vga_output(struct parsed_dcb *dcb, int i2c, int heads)
/* "or" mostly unused in early gen crt modesetting, 0 is fine */
}
@@ -1235,7 +1496,7 @@ index 0e9cd1d..4b0d67c 100644
{
struct dcb_entry *entry = new_dcb_entry(dcb);
-@@ -5279,7 +5357,7 @@ static void fabricate_dvi_i_output(struct parsed_dcb *dcb, bool twoHeads)
+@@ -5279,7 +5486,7 @@ static void fabricate_dvi_i_output(struct parsed_dcb *dcb, bool twoHeads)
#endif
}
@@ -1244,7 +1505,7 @@ index 0e9cd1d..4b0d67c 100644
{
struct dcb_entry *entry = new_dcb_entry(dcb);
-@@ -5290,13 +5368,13 @@ static void fabricate_tv_output(struct parsed_dcb *dcb, bool twoHeads)
+@@ -5290,13 +5497,13 @@ static void fabricate_tv_output(struct parsed_dcb *dcb, bool twoHeads)
}
static bool
@@ -1260,7 +1521,7 @@ index 0e9cd1d..4b0d67c 100644
entry->connector = (conn >> 12) & 0xf;
entry->bus = (conn >> 16) & 0xf;
entry->location = (conn >> 20) & 0x3;
-@@ -5314,7 +5392,7 @@ parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
+@@ -5314,7 +5521,7 @@ parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
* Although the rest of a CRT conf dword is usually
* zeros, mac biosen have stuff there so we must mask
*/
@@ -1269,7 +1530,7 @@ index 0e9cd1d..4b0d67c 100644
(conf & 0xffff) * 10 :
(conf & 0xff) * 10000;
break;
-@@ -5323,7 +5401,7 @@ parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
+@@ -5323,7 +5530,7 @@ parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
uint32_t mask;
if (conf & 0x1)
entry->lvdsconf.use_straps_for_mode = true;
@@ -1278,7 +1539,7 @@ index 0e9cd1d..4b0d67c 100644
mask = ~0xd;
/*
* The laptop in bug 14567 lies and claims to not use
-@@ -5347,7 +5425,7 @@ parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
+@@ -5347,7 +5554,7 @@ parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
* Until we even try to use these on G8x, it's
* useless reporting unknown bits. They all are.
*/
@@ -1287,7 +1548,7 @@ index 0e9cd1d..4b0d67c 100644
break;
NV_ERROR(dev, "Unknown LVDS configuration bits, "
-@@ -5357,7 +5435,7 @@ parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
+@@ -5357,7 +5564,7 @@ parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
}
case OUTPUT_TV:
{
@@ -1296,7 +1557,7 @@ index 0e9cd1d..4b0d67c 100644
entry->tvconf.has_component_output = conf & (0x8 << 4);
else
entry->tvconf.has_component_output = false;
-@@ -5384,8 +5462,10 @@ parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
+@@ -5384,8 +5591,10 @@ parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
break;
case 0xe:
/* weird g80 mobile type that "nv" treats as a terminator */
@@ -1308,7 +1569,7 @@ index 0e9cd1d..4b0d67c 100644
}
/* unsure what DCB version introduces this, 3.0? */
-@@ -5396,7 +5476,7 @@ parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
+@@ -5396,7 +5605,7 @@ parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
}
static bool
@@ -1317,7 +1578,7 @@ index 0e9cd1d..4b0d67c 100644
uint32_t conn, uint32_t conf, struct dcb_entry *entry)
{
switch (conn & 0x0000000f) {
-@@ -5462,27 +5542,27 @@ parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb,
+@@ -5462,27 +5671,27 @@ parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb,
return true;
}
@@ -1353,7 +1614,7 @@ index 0e9cd1d..4b0d67c 100644
{
/*
* DCB v2.0 lists each output combination separately.
-@@ -5534,8 +5614,7 @@ static int
+@@ -5534,8 +5743,7 @@ static int
parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -1363,7 +1624,7 @@ index 0e9cd1d..4b0d67c 100644
uint16_t dcbptr = 0, i2ctabptr = 0;
uint8_t *dcbtable;
uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES;
-@@ -5543,9 +5622,6 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
+@@ -5543,9 +5751,6 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
int recordlength = 8, confofs = 4;
int i;
@@ -1373,7 +1634,7 @@ index 0e9cd1d..4b0d67c 100644
/* get the offset from 0x36 */
if (dev_priv->card_type > NV_04) {
dcbptr = ROM16(bios->data[0x36]);
-@@ -5567,21 +5643,21 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
+@@ -5567,21 +5772,21 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
dcbtable = &bios->data[dcbptr];
/* get DCB version */
@@ -1401,7 +1662,7 @@ index 0e9cd1d..4b0d67c 100644
} else {
i2ctabptr = ROM16(dcbtable[2]);
sig = ROM32(dcbtable[4]);
-@@ -5593,7 +5669,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
+@@ -5593,7 +5798,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
"signature (%08X)\n", sig);
return -EINVAL;
}
@@ -1410,7 +1671,7 @@ index 0e9cd1d..4b0d67c 100644
char sig[8] = { 0 };
strncpy(sig, (char *)&dcbtable[-7], 7);
-@@ -5641,14 +5717,11 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
+@@ -5641,14 +5846,11 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
if (!i2ctabptr)
NV_WARN(dev, "No pointer to DCB I2C port table\n");
else {
@@ -1428,7 +1689,7 @@ index 0e9cd1d..4b0d67c 100644
if (entries > DCB_MAX_NUM_ENTRIES)
entries = DCB_MAX_NUM_ENTRIES;
-@@ -5673,7 +5746,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
+@@ -5673,7 +5875,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
NV_TRACEWARN(dev, "Raw DCB entry %d: %08x %08x\n",
dcb->entries, connection, config);
@@ -1437,7 +1698,7 @@ index 0e9cd1d..4b0d67c 100644
break;
}
-@@ -5681,18 +5754,22 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
+@@ -5681,18 +5883,22 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
* apart for v2.1+ not being known for requiring merging, this
* guarantees dcbent->index is the index of the entry in the rom image
*/
@@ -1465,7 +1726,7 @@ index 0e9cd1d..4b0d67c 100644
/*
* DCB 3.0 also has the table in most cases, but there are some cards
-@@ -5700,9 +5777,11 @@ fixup_legacy_connector(struct nvbios *bios)
+@@ -5700,9 +5906,11 @@ fixup_legacy_connector(struct nvbios *bios)
* indices are all 0. We don't need the connector indices on pre-G80
* chips (yet?) so limit the use to DCB 4.0 and above.
*/
@@ -1478,7 +1739,7 @@ index 0e9cd1d..4b0d67c 100644
/*
* No known connector info before v3.0, so make it up. the rule here
* is: anything on the same i2c bus is considered to be on the same
-@@ -5710,37 +5789,38 @@ fixup_legacy_connector(struct nvbios *bios)
+@@ -5710,37 +5918,38 @@ fixup_legacy_connector(struct nvbios *bios)
* its own unique connector index.
*/
for (i = 0; i < dcb->entries; i++) {
@@ -1530,7 +1791,7 @@ index 0e9cd1d..4b0d67c 100644
int i;
for (i = 0; i < dcb->entries; i++) {
-@@ -5826,7 +5906,7 @@ static int load_nv17_hw_sequencer_ucode(struct drm_device *dev,
+@@ -5826,7 +6035,7 @@ static int load_nv17_hw_sequencer_ucode(struct drm_device *dev,
uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -1539,7 +1800,7 @@ index 0e9cd1d..4b0d67c 100644
const uint8_t edid_sig[] = {
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
uint16_t offset = 0;
-@@ -5859,7 +5939,7 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table,
+@@ -5859,7 +6068,7 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table,
struct dcb_entry *dcbent)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -1548,7 +1809,7 @@ index 0e9cd1d..4b0d67c 100644
struct init_exec iexec = { true, false };
mutex_lock(&bios->lock);
-@@ -5872,7 +5952,7 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table,
+@@ -5872,7 +6081,7 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table,
static bool NVInitVBIOS(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -1557,7 +1818,7 @@ index 0e9cd1d..4b0d67c 100644
memset(bios, 0, sizeof(struct nvbios));
mutex_init(&bios->lock);
-@@ -5888,7 +5968,7 @@ static bool NVInitVBIOS(struct drm_device *dev)
+@@ -5888,7 +6097,7 @@ static bool NVInitVBIOS(struct drm_device *dev)
static int nouveau_parse_vbios_struct(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -1566,7 +1827,7 @@ index 0e9cd1d..4b0d67c 100644
const uint8_t bit_signature[] = { 0xff, 0xb8, 'B', 'I', 'T' };
const uint8_t bmp_signature[] = { 0xff, 0x7f, 'N', 'V', 0x0 };
int offset;
-@@ -5915,7 +5995,7 @@ int
+@@ -5915,7 +6124,7 @@ int
nouveau_run_vbios_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -1575,7 +1836,7 @@ index 0e9cd1d..4b0d67c 100644
int i, ret = 0;
NVLockVgaCrtcs(dev, false);
-@@ -5946,9 +6026,9 @@ nouveau_run_vbios_init(struct drm_device *dev)
+@@ -5946,9 +6155,9 @@ nouveau_run_vbios_init(struct drm_device *dev)
}
if (dev_priv->card_type >= NV_50) {
@@ -1587,7 +1848,7 @@ index 0e9cd1d..4b0d67c 100644
0, 0);
}
}
-@@ -5962,11 +6042,11 @@ static void
+@@ -5962,11 +6171,11 @@ static void
nouveau_bios_i2c_devices_takedown(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -1601,7 +1862,7 @@ index 0e9cd1d..4b0d67c 100644
for (i = 0; i < DCB_MAX_NUM_I2C_ENTRIES; i++, entry++)
nouveau_i2c_fini(dev, entry);
}
-@@ -5975,13 +6055,11 @@ int
+@@ -5975,13 +6184,11 @@ int
nouveau_bios_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -1616,7 +1877,7 @@ index 0e9cd1d..4b0d67c 100644
if (!NVInitVBIOS(dev))
return -ENODEV;
-@@ -6023,10 +6101,8 @@ nouveau_bios_init(struct drm_device *dev)
+@@ -6023,10 +6230,8 @@ nouveau_bios_init(struct drm_device *dev)
bios_wr32(bios, NV_PEXTDEV_BOOT_0, saved_nv_pextdev_boot_0);
ret = nouveau_run_vbios_init(dev);
@@ -1629,14 +1890,15 @@ index 0e9cd1d..4b0d67c 100644
/* feature_byte on BMP is poor, but init always sets CR4B */
was_locked = NVLockVgaCrtcs(dev, false);
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h
-index fd94bd6..c0d7b0a 100644
+index fd94bd6..adf4ec2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.h
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.h
-@@ -34,9 +34,71 @@
+@@ -34,9 +34,72 @@
#define DCB_LOC_ON_CHIP 0
+struct dcb_i2c_entry {
++ uint32_t entry;
+ uint8_t port_type;
+ uint8_t read, write;
+ struct nouveau_i2c_chan *chan;
@@ -1705,7 +1967,7 @@ index fd94bd6..c0d7b0a 100644
uint8_t i2c_index;
uint8_t heads;
uint8_t connector;
-@@ -71,69 +133,22 @@ struct dcb_entry {
+@@ -71,69 +134,22 @@ struct dcb_entry {
bool i2c_upper_default;
};
@@ -1779,7 +2041,7 @@ index fd94bd6..c0d7b0a 100644
enum nouveau_or {
OUTPUT_A = (1 << 0),
OUTPUT_B = (1 << 1),
-@@ -190,8 +205,8 @@ struct pll_lims {
+@@ -190,8 +206,8 @@ struct pll_lims {
int refclk;
};
@@ -1790,7 +2052,7 @@ index fd94bd6..c0d7b0a 100644
uint8_t chip_version;
-@@ -199,11 +214,6 @@ struct nouveau_bios_info {
+@@ -199,11 +215,6 @@ struct nouveau_bios_info {
uint32_t tvdactestval;
uint8_t digital_min_front_porch;
bool fp_no_ddc;
@@ -1802,7 +2064,7 @@ index fd94bd6..c0d7b0a 100644
struct mutex lock;
-@@ -234,7 +244,7 @@ struct nvbios {
+@@ -234,7 +245,7 @@ struct nvbios {
uint16_t some_script_ptr; /* BIT I + 14 */
uint16_t init96_tbl_ptr; /* BIT I + 16 */
@@ -1811,7 +2073,7 @@ index fd94bd6..c0d7b0a 100644
struct {
int crtchead;
-@@ -260,7 +270,6 @@ struct nvbios {
+@@ -260,7 +271,6 @@ struct nvbios {
bool reset_after_pclk_change;
bool dual_link;
bool link_c_increment;
@@ -2484,7 +2746,7 @@ index da3b93b..60a709c 100644
struct nouveau_framebuffer *nouveau_fb;
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
-index 5be0cca..9e12c93 100644
+index 5be0cca..b908f77 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -76,6 +76,7 @@ struct nouveau_bo {
@@ -2647,7 +2909,7 @@ index 5be0cca..9e12c93 100644
extern u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index);
extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val);
extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index);
-@@ -1163,6 +1166,10 @@ extern int nouveau_gem_ioctl_info(struct drm_device *, void *,
+@@ -1163,6 +1166,16 @@ extern int nouveau_gem_ioctl_info(struct drm_device *, void *,
int nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
int nv17_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
@@ -2655,18 +2917,26 @@ index 5be0cca..9e12c93 100644
+int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
+int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
+
++/* nv50_calc. */
++int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk,
++ int *N1, int *M1, int *N2, int *M2, int *P);
++int nv50_calc_pll2(struct drm_device *, struct pll_lims *,
++ int clk, int *N, int *fN, int *M, int *P);
++
#ifndef ioread32_native
#ifdef __BIG_ENDIAN
#define ioread16_native ioread16be
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h
-index bc4a240..9f28b94 100644
+index bc4a240..e1df820 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
-@@ -47,6 +47,7 @@ struct nouveau_encoder {
+@@ -47,6 +47,9 @@ struct nouveau_encoder {
union {
struct {
+ int mc_unknown;
++ uint32_t unk0;
++ uint32_t unk1;
int dpcd_version;
int link_nr;
int link_bw;
@@ -2772,15 +3042,15 @@ index dc46792..7855b35 100644
if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 ||
cv >= 0x40) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c
-index 70e994d..88583e7 100644
+index 70e994d..316a3c7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_i2c.c
+++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c
-@@ -254,16 +254,16 @@ struct nouveau_i2c_chan *
+@@ -254,16 +254,27 @@ struct nouveau_i2c_chan *
nouveau_i2c_find(struct drm_device *dev, int index)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nvbios *bios = &dev_priv->VBIOS;
-+ struct nvbios *bios = &dev_priv->vbios;
++ struct dcb_i2c_entry *i2c = &dev_priv->vbios.dcb.i2c[index];
- if (index > DCB_MAX_NUM_I2C_ENTRIES)
+ if (index >= DCB_MAX_NUM_I2C_ENTRIES)
@@ -2788,13 +3058,25 @@ index 70e994d..88583e7 100644
- if (!bios->bdcb.dcb.i2c[index].chan) {
- if (nouveau_i2c_init(dev, &bios->bdcb.dcb.i2c[index], index))
-+ if (!bios->dcb.i2c[index].chan) {
-+ if (nouveau_i2c_init(dev, &bios->dcb.i2c[index], index))
- return NULL;
+- return NULL;
++ if (dev_priv->chipset >= NV_50 && (i2c->entry & 0x00000100)) {
++ uint32_t reg = 0xe500, val;
++
++ if (i2c->port_type == 6) {
++ reg += i2c->read * 0x50;
++ val = 0x2002;
++ } else {
++ reg += ((i2c->entry & 0x1e00) >> 9) * 0x50;
++ val = 0xe001;
++ }
++
++ nv_wr32(dev, reg, (nv_rd32(dev, reg) & ~0xf003) | val);
}
- return bios->bdcb.dcb.i2c[index].chan;
-+ return bios->dcb.i2c[index].chan;
++ if (!i2c->chan && nouveau_i2c_init(dev, i2c, index))
++ return NULL;
++ return i2c->chan;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c
@@ -3684,6 +3966,18 @@ index 2dc09db..775a701 100644
/* remove reserved space at end of vram from available amount */
dev_priv->fb_available_size -= dev_priv->ramin_rsvd_vram;
dev_priv->fb_aper_free = dev_priv->fb_available_size;
+diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h
+index aa9b310..6ca80a3 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_reg.h
++++ b/drivers/gpu/drm/nouveau/nouveau_reg.h
+@@ -826,6 +826,7 @@
+ #define NV50_SOR_DP_CTRL_TRAINING_PATTERN_2 0x02000000
+ #define NV50_SOR_DP_UNK118(i,l) (0x0061c118 + (i) * 0x800 + (l) * 0x80)
+ #define NV50_SOR_DP_UNK120(i,l) (0x0061c120 + (i) * 0x800 + (l) * 0x80)
++#define NV50_SOR_DP_UNK128(i,l) (0x0061c128 + (i) * 0x800 + (l) * 0x80)
+ #define NV50_SOR_DP_UNK130(i,l) (0x0061c130 + (i) * 0x800 + (l) * 0x80)
+
+ #define NV50_PDISPLAY_USER(i) ((i) * 0x1000 + 0x00640000)
diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
index ed15905..554fb45 100644
--- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c
@@ -4083,6 +4377,164 @@ index 53e8afe..0616c96 100644
/* Turn all the tiling regions off. */
for (i = 0; i < pfb->num_tiles; i++)
nv40_graph_set_region_tiling(dev, i, 0, 0, 0);
+diff --git a/drivers/gpu/drm/nouveau/nv50_calc.c b/drivers/gpu/drm/nouveau/nv50_calc.c
+new file mode 100644
+index 0000000..90f3f6b
+--- /dev/null
++++ b/drivers/gpu/drm/nouveau/nv50_calc.c
+@@ -0,0 +1,88 @@
++/*
++ * 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 "drmP.h"
++#include "drm_fixed.h"
++#include "nouveau_drv.h"
++#include "nouveau_hw.h"
++
++int
++nv50_calc_pll(struct drm_device *dev, struct pll_lims *pll, int clk,
++ int *N1, int *M1, int *N2, int *M2, int *P)
++{
++ struct nouveau_pll_vals pll_vals;
++ int ret;
++
++ ret = nouveau_calc_pll_mnp(dev, pll, clk, &pll_vals);
++ if (ret <= 0)
++ return ret;
++
++ *N1 = pll_vals.N1;
++ *M1 = pll_vals.M1;
++ *N2 = pll_vals.N2;
++ *M2 = pll_vals.M2;
++ *P = pll_vals.log2P;
++ return ret;
++}
++
++int
++nv50_calc_pll2(struct drm_device *dev, struct pll_lims *pll, int clk,
++ int *N, int *fN, int *M, int *P)
++{
++ fixed20_12 fb_div, a, b;
++
++ *P = pll->vco1.maxfreq / clk;
++ if (*P > pll->max_p)
++ *P = pll->max_p;
++ if (*P < pll->min_p)
++ *P = pll->min_p;
++
++ /* *M = ceil(refclk / pll->vco.max_inputfreq); */
++ a.full = dfixed_const(pll->refclk);
++ b.full = dfixed_const(pll->vco1.max_inputfreq);
++ a.full = dfixed_div(a, b);
++ a.full = dfixed_ceil(a);
++ *M = dfixed_trunc(a);
++
++ /* fb_div = (vco * *M) / refclk; */
++ fb_div.full = dfixed_const(clk * *P);
++ fb_div.full = dfixed_mul(fb_div, a);
++ a.full = dfixed_const(pll->refclk);
++ fb_div.full = dfixed_div(fb_div, a);
++
++ /* *N = floor(fb_div); */
++ a.full = dfixed_floor(fb_div);
++ *N = dfixed_trunc(fb_div);
++
++ /* *fN = (fmod(fb_div, 1.0) * 8192) - 4096; */
++ b.full = dfixed_const(8192);
++ a.full = dfixed_mul(a, b);
++ fb_div.full = dfixed_mul(fb_div, b);
++ fb_div.full = fb_div.full - a.full;
++ *fN = dfixed_trunc(fb_div) - 4096;
++ *fN &= 0xffff;
++
++ return clk;
++}
++
+diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c
+index d1a651e..03d0e41 100644
+--- a/drivers/gpu/drm/nouveau/nv50_crtc.c
++++ b/drivers/gpu/drm/nouveau/nv50_crtc.c
+@@ -264,32 +264,40 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update)
+ int
+ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk)
+ {
+- uint32_t pll_reg = NV50_PDISPLAY_CRTC_CLK_CTRL1(head);
+- struct nouveau_pll_vals pll;
+- struct pll_lims limits;
++ uint32_t reg = NV50_PDISPLAY_CRTC_CLK_CTRL1(head);
++ struct pll_lims pll;
+ uint32_t reg1, reg2;
+- int ret;
++ int ret, N1, M1, N2, M2, P;
+
+- ret = get_pll_limits(dev, pll_reg, &limits);
++ ret = get_pll_limits(dev, reg, &pll);
+ if (ret)
+ return ret;
+
+- ret = nouveau_calc_pll_mnp(dev, &limits, pclk, &pll);
+- if (ret <= 0)
+- return ret;
++ if (pll.vco2.maxfreq) {
++ ret = nv50_calc_pll(dev, &pll, pclk, &N1, &M1, &N2, &M2, &P);
++ if (ret <= 0)
++ return 0;
++
++ NV_DEBUG(dev, "pclk %d out %d NM1 %d %d NM2 %d %d P %d\n",
++ pclk, ret, N1, M1, N2, M2, P);
+
+- if (limits.vco2.maxfreq) {
+- reg1 = nv_rd32(dev, pll_reg + 4) & 0xff00ff00;
+- reg2 = nv_rd32(dev, pll_reg + 8) & 0x8000ff00;
+- nv_wr32(dev, pll_reg, 0x10000611);
+- nv_wr32(dev, pll_reg + 4, reg1 | (pll.M1 << 16) | pll.N1);
+- nv_wr32(dev, pll_reg + 8,
+- reg2 | (pll.log2P << 28) | (pll.M2 << 16) | pll.N2);
++ reg1 = nv_rd32(dev, reg + 4) & 0xff00ff00;
++ reg2 = nv_rd32(dev, reg + 8) & 0x8000ff00;
++ nv_wr32(dev, reg, 0x10000611);
++ nv_wr32(dev, reg + 4, reg1 | (M1 << 16) | N1);
++ nv_wr32(dev, reg + 8, reg2 | (P << 28) | (M2 << 16) | N2);
+ } else {
+- reg1 = nv_rd32(dev, pll_reg + 4) & 0xffc00000;
+- nv_wr32(dev, pll_reg, 0x50000610);
+- nv_wr32(dev, pll_reg + 4, reg1 |
+- (pll.log2P << 16) | (pll.M1 << 8) | pll.N1);
++ ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P);
++ if (ret <= 0)
++ return 0;
++
++ NV_DEBUG(dev, "pclk %d out %d N %d fN 0x%04x M %d P %d\n",
++ pclk, ret, N1, N2, M1, P);
++
++ reg1 = nv_rd32(dev, reg + 4) & 0xffc00000;
++ nv_wr32(dev, reg, 0x50000610);
++ nv_wr32(dev, reg + 4, reg1 | (P << 16) | (M1 << 8) | N1);
++ nv_wr32(dev, reg + 8, N2);
+ }
+
+ return 0;
diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c
index f08f042..1fd9537 100644
--- a/drivers/gpu/drm/nouveau/nv50_dac.c
@@ -4099,7 +4551,7 @@ index f08f042..1fd9537 100644
load_pattern);
} else {
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
-index 90f0bf5..649db4c 100644
+index 90f0bf5..2c2ec5f 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -143,7 +143,7 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan)
@@ -4227,7 +4679,54 @@ index 90f0bf5..649db4c 100644
if (bios->fp.dual_link)
script |= 0x0100;
if (bios->fp.if_is_24bit)
-@@ -919,10 +887,12 @@ nv50_display_error_handler(struct drm_device *dev)
+@@ -815,6 +783,37 @@ ack:
+ }
+
+ static void
++nv50_display_unk20_dp_hack(struct drm_device *dev, struct dcb_entry *dcb)
++{
++ int or = ffs(dcb->or) - 1, link = !(dcb->dpconf.sor.link & 1);
++ struct drm_encoder *encoder;
++ uint32_t tmp, unk0 = 0, unk1 = 0;
++
++ if (dcb->type != OUTPUT_DP)
++ return;
++
++ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
++ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
++
++ if (nv_encoder->dcb == dcb) {
++ unk0 = nv_encoder->dp.unk0;
++ unk1 = nv_encoder->dp.unk1;
++ break;
++ }
++ }
++
++ if (unk0 || unk1) {
++ tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
++ tmp &= 0xfffffe03;
++ nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp | unk0);
++
++ tmp = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link));
++ tmp &= 0xfef080c0;
++ nv_wr32(dev, NV50_SOR_DP_UNK128(or, link), tmp | unk1);
++ }
++}
++
++static void
+ nv50_display_unk20_handler(struct drm_device *dev)
+ {
+ struct dcb_entry *dcbent;
+@@ -837,6 +836,8 @@ nv50_display_unk20_handler(struct drm_device *dev)
+
+ nouveau_bios_run_display_table(dev, dcbent, script, pclk);
+
++ nv50_display_unk20_dp_hack(dev, dcbent);
++
+ tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head));
+ tmp &= ~0x000000f;
+ nv_wr32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head), tmp);
+@@ -919,10 +920,12 @@ nv50_display_error_handler(struct drm_device *dev)
nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR, 0x90000000);
}
@@ -4243,7 +4742,16 @@ index 90f0bf5..649db4c 100644
struct drm_connector *connector;
const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
uint32_t unplug_mask, plug_mask, change_mask;
-@@ -983,8 +953,10 @@ nv50_display_irq_handler(struct drm_device *dev)
+@@ -975,6 +978,8 @@ nv50_display_irq_hotplug(struct drm_device *dev)
+ nv_wr32(dev, 0xe054, nv_rd32(dev, 0xe054));
+ if (dev_priv->chipset >= 0x90)
+ nv_wr32(dev, 0xe074, nv_rd32(dev, 0xe074));
++
++ drm_sysfs_hotplug_event(dev);
+ }
+
+ void
+@@ -983,8 +988,10 @@ nv50_display_irq_handler(struct drm_device *dev)
struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t delayed = 0;
@@ -7102,7 +7610,7 @@ index f0dc4e3..5f21df3 100644
return -EINVAL;
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c
-index c2fff54..0c68698 100644
+index c2fff54..b11eaf9 100644
--- a/drivers/gpu/drm/nouveau/nv50_sor.c
+++ b/drivers/gpu/drm/nouveau/nv50_sor.c
@@ -211,7 +211,7 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
@@ -7122,23 +7630,28 @@ index c2fff54..0c68698 100644
struct nouveau_encoder *nv_encoder = NULL;
struct drm_encoder *encoder;
bool dum;
-@@ -319,5 +320,27 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
+@@ -319,5 +320,32 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
encoder->possible_crtcs = entry->heads;
encoder->possible_clones = 0;
+ if (nv_encoder->dcb->type == OUTPUT_DP) {
-+ uint32_t mc, or = nv_encoder->or;
++ int or = nv_encoder->or, link = !(entry->dpconf.sor.link & 1);
++ uint32_t tmp;
+
+ if (dev_priv->chipset < 0x90 ||
+ dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0)
-+ mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(or));
++ tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(or));
+ else
-+ mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(or));
++ tmp = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(or));
+
-+ switch ((mc & 0x00000f00) >> 8) {
++ switch ((tmp & 0x00000f00) >> 8) {
+ case 8:
+ case 9:
-+ nv_encoder->dp.mc_unknown = (mc & 0x000f0000) >> 16;
++ nv_encoder->dp.mc_unknown = (tmp & 0x000f0000) >> 16;
++ tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
++ nv_encoder->dp.unk0 = tmp & 0x000001fc;
++ tmp = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link));
++ nv_encoder->dp.unk1 = tmp & 0x010f7f3f;
+ break;
+ default:
+ break;
Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-13/kernel.spec,v
retrieving revision 1.2008
retrieving revision 1.2009
diff -u -p -r1.2008 -r1.2009
--- kernel.spec 28 Apr 2010 15:15:48 -0000 1.2008
+++ kernel.spec 29 Apr 2010 01:06:41 -0000 1.2009
@@ -734,6 +734,7 @@ Patch1815: drm-nouveau-abi16.patch
Patch1816: drm-nouveau-updates.patch
# requires code that hasn't been merged upstream yet
Patch1817: drm-nouveau-acpi-edid-fallback.patch
+Patch1818: drm-nouveau-drm-fixed-header.patch
# drm fixes
Patch1819: drm-intel-big-hammer.patch
@@ -1440,6 +1441,7 @@ ApplyPatch drm-radeon-ss-fix.patch
ApplyPatch drm-nouveau-abi16.patch
ApplyPatch drm-nouveau-updates.patch
ApplyPatch drm-nouveau-acpi-edid-fallback.patch
+ApplyPatch drm-nouveau-drm-fixed-header.patch
# pm broken on my thinkpad t60p - airlied
ApplyPatch drm-intel-big-hammer.patch
ApplyOptionalPatch drm-intel-next.patch
@@ -2166,6 +2168,12 @@ fi
# and build.
%changelog
+* Thu Apr 29 2010 Ben Skeggs <bskeggs at redhat.com> 2.6.33.3-73
+- nouveau: initial eDP support + DP suspend/resume fixes
+- nouveau: fix monitor detection on certain chipsets with DP support
+- nouveau: better CRTC PLL calculation on latest chipsets
+- nouveau: send hotplug events down to userspace
+
* Wed Apr 28 2010 John W. Linville <linville at redhat.com> 2.6.33.3-72
- Revert "ath9k: fix lockdep warning when unloading module"
More information about the scm-commits
mailing list