aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_bios.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_bios.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c904
1 files changed, 216 insertions, 688 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 5fc201b49d30..e5cbead85e50 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -27,6 +27,7 @@
#include "nouveau_drv.h"
#include "nouveau_hw.h"
#include "nouveau_encoder.h"
+#include "nouveau_gpio.h"
#include <linux/io-mapping.h>
@@ -34,9 +35,6 @@
#define NV_CIO_CRE_44_HEADA 0x0
#define NV_CIO_CRE_44_HEADB 0x3
#define FEATURE_MOBILE 0x10 /* also FEATURE_QUADRO for BMP */
-#define LEGACY_I2C_CRT 0x80
-#define LEGACY_I2C_PANEL 0x81
-#define LEGACY_I2C_TV 0x82
#define EDID1_LEN 128
@@ -723,115 +721,19 @@ static int dcb_entry_idx_from_crtchead(struct drm_device *dev)
return dcb_entry;
}
-static int
-read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, int index, struct dcb_i2c_entry *i2c)
-{
- uint8_t dcb_i2c_ver = dcb_version, headerlen = 0, entry_len = 4;
- int i2c_entries = DCB_MAX_NUM_I2C_ENTRIES;
- int recordoffset = 0, rdofs = 1, wrofs = 0;
- uint8_t port_type = 0;
-
- if (!i2ctable)
- return -EINVAL;
-
- if (dcb_version >= 0x30) {
- if (i2ctable[0] != dcb_version) /* necessary? */
- NV_WARN(dev,
- "DCB I2C table version mismatch (%02X vs %02X)\n",
- i2ctable[0], dcb_version);
- dcb_i2c_ver = i2ctable[0];
- headerlen = i2ctable[1];
- if (i2ctable[2] <= DCB_MAX_NUM_I2C_ENTRIES)
- i2c_entries = i2ctable[2];
- else
- NV_WARN(dev,
- "DCB I2C table has more entries than indexable "
- "(%d entries, max %d)\n", i2ctable[2],
- DCB_MAX_NUM_I2C_ENTRIES);
- entry_len = i2ctable[3];
- /* [4] is i2c_default_indices, read in parse_dcb_table() */
- }
- /*
- * It's your own fault if you call this function on a DCB 1.1 BIOS --
- * the test below is for DCB 1.2
- */
- if (dcb_version < 0x14) {
- recordoffset = 2;
- rdofs = 0;
- wrofs = 1;
- }
-
- if (index == 0xf)
- return 0;
- if (index >= i2c_entries) {
- NV_ERROR(dev, "DCB I2C index too big (%d >= %d)\n",
- index, i2ctable[2]);
- return -ENOENT;
- }
- if (i2ctable[headerlen + entry_len * index + 3] == 0xff) {
- NV_ERROR(dev, "DCB I2C entry invalid\n");
- return -EINVAL;
- }
-
- if (dcb_i2c_ver >= 0x30) {
- port_type = i2ctable[headerlen + recordoffset + 3 + entry_len * index];
-
- /*
- * Fixup for chips using same address offset for read and
- * write.
- */
- if (port_type == 4) /* seen on C51 */
- rdofs = wrofs = 1;
- if (port_type >= 5) /* G80+ */
- rdofs = wrofs = 0;
- }
-
- 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];
- i2c->write = i2ctable[headerlen + recordoffset + wrofs + entry_len * index];
-
- return 0;
-}
-
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;
- struct dcb_table *dcb = &dev_priv->vbios.dcb;
-
if (i2c_index == 0xff) {
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct dcb_table *dcb = &dev_priv->vbios.dcb;
/* note: dcb_entry_idx_from_crtchead needs pre-script set-up */
- int idx = dcb_entry_idx_from_crtchead(dev), shift = 0;
- int default_indices = dcb->i2c_default_indices;
+ int idx = dcb_entry_idx_from_crtchead(dev);
+ i2c_index = NV_I2C_DEFAULT(0);
if (idx != 0x7f && dcb->entry[idx].i2c_upper_default)
- shift = 4;
-
- i2c_index = (default_indices >> shift) & 0xf;
+ i2c_index = NV_I2C_DEFAULT(1);
}
- if (i2c_index == 0x80) /* g80+ */
- i2c_index = dcb->i2c_default_indices & 0xf;
- else
- if (i2c_index == 0x81)
- i2c_index = (dcb->i2c_default_indices & 0xf0) >> 4;
-
- if (i2c_index >= DCB_MAX_NUM_I2C_ENTRIES) {
- NV_ERROR(dev, "invalid i2c_index 0x%x\n", i2c_index);
- return NULL;
- }
-
- /* Make sure i2c table entry has been parsed, it may not
- * have been if this is a bus not referenced by a DCB encoder
- */
- read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table,
- i2c_index, &dcb->i2c[i2c_index]);
return nouveau_i2c_find(dev, i2c_index);
}
@@ -1199,13 +1101,9 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
switch (cond) {
case 0:
- {
- struct dcb_connector_table_entry *ent =
- &bios->dcb.connector.entry[dcb->connector];
-
- if (ent->type != DCB_CONNECTOR_eDP)
+ entry = dcb_conn(dev, dcb->connector);
+ if (!entry || entry[0] != DCB_CONNECTOR_eDP)
iexec->execute = false;
- }
break;
case 1:
case 2:
@@ -3227,49 +3125,6 @@ init_8d(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
return 1;
}
-static void
-init_gpio_unknv50(struct nvbios *bios, struct dcb_gpio_entry *gpio)
-{
- const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c };
- u32 r, s, v;
-
- /* Not a clue, needs de-magicing */
- r = nv50_gpio_ctl[gpio->line >> 4];
- s = (gpio->line & 0x0f);
- v = bios_rd32(bios, r) & ~(0x00010001 << s);
- switch ((gpio->entry & 0x06000000) >> 25) {
- case 1:
- v |= (0x00000001 << s);
- break;
- case 2:
- v |= (0x00010000 << s);
- break;
- default:
- break;
- }
-
- bios_wr32(bios, r, v);
-}
-
-static void
-init_gpio_unknvd0(struct nvbios *bios, struct dcb_gpio_entry *gpio)
-{
- u32 v, i;
-
- v = bios_rd32(bios, 0x00d610 + (gpio->line * 4));
- v &= 0xffffff00;
- v |= (gpio->entry & 0x00ff0000) >> 16;
- bios_wr32(bios, 0x00d610 + (gpio->line * 4), v);
-
- i = (gpio->entry & 0x1f000000) >> 24;
- if (i) {
- v = bios_rd32(bios, 0x00d640 + ((i - 1) * 4));
- v &= 0xffffff00;
- v |= gpio->line;
- bios_wr32(bios, 0x00d640 + ((i - 1) * 4), v);
- }
-}
-
static int
init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
{
@@ -3282,35 +3137,8 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
* each GPIO according to various values listed in each entry
*/
- struct drm_nouveau_private *dev_priv = bios->dev->dev_private;
- struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
- int i;
-
- if (dev_priv->card_type < NV_50) {
- NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n");
- return 1;
- }
-
- if (!iexec->execute)
- return 1;
-
- for (i = 0; i < bios->dcb.gpio.entries; i++) {
- struct dcb_gpio_entry *gpio = &bios->dcb.gpio.entry[i];
-
- BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry);
-
- BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n",
- offset, gpio->tag, gpio->state_default);
-
- if (!bios->execute)
- continue;
-
- pgpio->set(bios->dev, gpio->tag, gpio->state_default);
- if (dev_priv->card_type < NV_D0)
- init_gpio_unknv50(bios, gpio);
- else
- init_gpio_unknvd0(bios, gpio);
- }
+ if (iexec->execute && bios->execute)
+ nouveau_gpio_reset(bios->dev);
return 1;
}
@@ -4407,18 +4235,6 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b
break;
}
- /* Dell Latitude D620 reports a too-high value for the dual-link
- * transition freq, causing us to program the panel incorrectly.
- *
- * It doesn't appear the VBIOS actually uses its transition freq
- * (90000kHz), instead it uses the "Number of LVDS channels" field
- * out of the panel ID structure (http://www.spwg.org/).
- *
- * For the moment, a quirk will do :)
- */
- if (nv_match_device(dev, 0x01d7, 0x1028, 0x01c2))
- bios->fp.duallink_transition_clk = 80000;
-
/* 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);
@@ -4541,7 +4357,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk,
NV_DEBUG_KMS(dev, "Searching for output entry for %d %d %d\n",
dcbent->type, dcbent->location, dcbent->or);
for (i = 0; i < table[3]; i++) {
- otable = ROMPTR(bios, table[table[1] + (i * table[2])]);
+ otable = ROMPTR(dev, table[table[1] + (i * table[2])]);
if (otable && bios_encoder_match(dcbent, ROM32(otable[0])))
break;
}
@@ -4719,7 +4535,7 @@ static struct pll_mapping nv84_pll_mapping[] = {
{ PLL_CORE , 0x004028 },
{ PLL_SHADER, 0x004020 },
{ PLL_MEMORY, 0x004008 },
- { PLL_UNK05 , 0x004030 },
+ { PLL_VDEC , 0x004030 },
{ PLL_UNK41 , 0x00e818 },
{ PLL_VPLL0 , 0x614100 },
{ PLL_VPLL1 , 0x614900 },
@@ -5485,6 +5301,9 @@ bit_table(struct drm_device *dev, u8 id, struct bit_entry *bit)
struct nvbios *bios = &dev_priv->vbios;
u8 entries, *entry;
+ if (bios->type != NVBIOS_BIT)
+ return -ENODEV;
+
entries = bios->data[bios->offset + 10];
entry = &bios->data[bios->offset + 12];
while (entries--) {
@@ -5493,7 +5312,7 @@ bit_table(struct drm_device *dev, u8 id, struct bit_entry *bit)
bit->version = entry[1];
bit->length = ROM16(entry[2]);
bit->offset = ROM16(entry[4]);
- bit->data = ROMPTR(bios, entry[4]);
+ bit->data = ROMPTR(dev, entry[4]);
return 0;
}
@@ -5598,10 +5417,6 @@ 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 */
- bios->dcb.i2c[0].write = NV_CIO_CRE_DDC_WR__INDEX;
- bios->dcb.i2c[0].read = NV_CIO_CRE_DDC_STATUS__INDEX;
- bios->dcb.i2c[1].write = NV_CIO_CRE_DDC0_WR__INDEX;
- bios->dcb.i2c[1].read = NV_CIO_CRE_DDC0_STATUS__INDEX;
bios->digital_min_front_porch = 0x4b;
bios->fmaxvco = 256000;
bios->fminvco = 128000;
@@ -5709,14 +5524,6 @@ 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];
- if (bios->data[legacy_i2c_offset + 4])
- bios->dcb.i2c[0].write = bios->data[legacy_i2c_offset + 4];
- if (bios->data[legacy_i2c_offset + 5])
- bios->dcb.i2c[0].read = bios->data[legacy_i2c_offset + 5];
- if (bios->data[legacy_i2c_offset + 6])
- bios->dcb.i2c[1].write = bios->data[legacy_i2c_offset + 6];
- if (bios->data[legacy_i2c_offset + 7])
- bios->dcb.i2c[1].read = bios->data[legacy_i2c_offset + 7];
if (bmplength > 74) {
bios->fmaxvco = ROM32(bmp[67]);
@@ -5767,286 +5574,128 @@ static uint16_t findstr(uint8_t *data, int n, const uint8_t *str, int len)
return 0;
}
-static struct dcb_gpio_entry *
-new_gpio_entry(struct nvbios *bios)
-{
- struct drm_device *dev = bios->dev;
- struct dcb_gpio_table *gpio = &bios->dcb.gpio;
-
- if (gpio->entries >= DCB_MAX_NUM_GPIO_ENTRIES) {
- NV_ERROR(dev, "exceeded maximum number of gpio entries!!\n");
- return NULL;
- }
-
- return &gpio->entry[gpio->entries++];
-}
-
-struct dcb_gpio_entry *
-nouveau_bios_gpio_entry(struct drm_device *dev, enum dcb_gpio_tag tag)
+void *
+dcb_table(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nvbios *bios = &dev_priv->vbios;
- int i;
-
- for (i = 0; i < bios->dcb.gpio.entries; i++) {
- if (bios->dcb.gpio.entry[i].tag != tag)
- continue;
+ u8 *dcb = NULL;
- return &bios->dcb.gpio.entry[i];
+ if (dev_priv->card_type > NV_04)
+ dcb = ROMPTR(dev, dev_priv->vbios.data[0x36]);
+ if (!dcb) {
+ NV_WARNONCE(dev, "No DCB data found in VBIOS\n");
+ return NULL;
}
- return NULL;
-}
-
-static void
-parse_dcb_gpio_table(struct nvbios *bios)
-{
- struct drm_device *dev = bios->dev;
- struct dcb_gpio_entry *e;
- u8 headerlen, entries, recordlen;
- u8 *dcb, *gpio = NULL, *entry;
- int i;
-
- dcb = ROMPTR(bios, bios->data[0x36]);
+ if (dcb[0] >= 0x41) {
+ NV_WARNONCE(dev, "DCB version 0x%02x unknown\n", dcb[0]);
+ return NULL;
+ } else
if (dcb[0] >= 0x30) {
- gpio = ROMPTR(bios, dcb[10]);
- if (!gpio)
- goto no_table;
-
- headerlen = gpio[1];
- entries = gpio[2];
- recordlen = gpio[3];
+ if (ROM32(dcb[6]) == 0x4edcbdcb)
+ return dcb;
} else
- if (dcb[0] >= 0x22 && dcb[-1] >= 0x13) {
- gpio = ROMPTR(bios, dcb[-15]);
- if (!gpio)
- goto no_table;
-
- headerlen = 3;
- entries = gpio[2];
- recordlen = gpio[1];
+ if (dcb[0] >= 0x20) {
+ if (ROM32(dcb[4]) == 0x4edcbdcb)
+ return dcb;
} else
- if (dcb[0] >= 0x22) {
- /* No GPIO table present, parse the TVDAC GPIO data. */
- uint8_t *tvdac_gpio = &dcb[-5];
-
- if (tvdac_gpio[0] & 1) {
- e = new_gpio_entry(bios);
- e->tag = DCB_GPIO_TVDAC0;
- e->line = tvdac_gpio[1] >> 4;
- e->invert = tvdac_gpio[0] & 2;
- }
-
- goto no_table;
+ if (dcb[0] >= 0x15) {
+ if (!memcmp(&dcb[-7], "DEV_REC", 7))
+ return dcb;
} else {
- NV_DEBUG(dev, "no/unknown gpio table on DCB 0x%02x\n", dcb[0]);
- goto no_table;
- }
-
- entry = gpio + headerlen;
- for (i = 0; i < entries; i++, entry += recordlen) {
- e = new_gpio_entry(bios);
- if (!e)
- break;
-
- if (gpio[0] < 0x40) {
- e->entry = ROM16(entry[0]);
- e->tag = (e->entry & 0x07e0) >> 5;
- if (e->tag == 0x3f) {
- bios->dcb.gpio.entries--;
- continue;
- }
-
- e->line = (e->entry & 0x001f);
- e->invert = ((e->entry & 0xf800) >> 11) != 4;
- } else {
- e->entry = ROM32(entry[0]);
- e->tag = (e->entry & 0x0000ff00) >> 8;
- if (e->tag == 0xff) {
- bios->dcb.gpio.entries--;
- continue;
- }
-
- e->line = (e->entry & 0x0000001f) >> 0;
- if (gpio[0] == 0x40) {
- e->state_default = (e->entry & 0x01000000) >> 24;
- e->state[0] = (e->entry & 0x18000000) >> 27;
- e->state[1] = (e->entry & 0x60000000) >> 29;
- } else {
- e->state_default = (e->entry & 0x00000080) >> 7;
- e->state[0] = (entry[4] >> 4) & 3;
- e->state[1] = (entry[4] >> 6) & 3;
- }
- }
- }
-
-no_table:
- /* Apple iMac G4 NV18 */
- if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) {
- e = new_gpio_entry(bios);
- if (e) {
- e->tag = DCB_GPIO_TVDAC0;
- e->line = 4;
- }
- }
-}
-
-struct dcb_connector_table_entry *
-nouveau_bios_connector_entry(struct drm_device *dev, int index)
-{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nvbios *bios = &dev_priv->vbios;
- struct dcb_connector_table_entry *cte;
-
- if (index >= bios->dcb.connector.entries)
- return NULL;
-
- cte = &bios->dcb.connector.entry[index];
- if (cte->type == 0xff)
+ /*
+ * v1.4 (some NV15/16, NV11+) seems the same as v1.5, but
+ * always has the same single (crt) entry, even when tv-out
+ * present, so the conclusion is this version cannot really
+ * be used.
+ *
+ * v1.2 tables (some NV6/10, and NV15+) normally have the
+ * same 5 entries, which are not specific to the card and so
+ * no use.
+ *
+ * v1.2 does have an I2C table that read_dcb_i2c_table can
+ * handle, but cards exist (nv11 in #14821) with a bad i2c
+ * table pointer, so use the indices parsed in
+ * parse_bmp_structure.
+ *
+ * v1.1 (NV5+, maybe some NV4) is entirely unhelpful
+ */
+ NV_WARNONCE(dev, "No useful DCB data in VBIOS\n");
return NULL;
+ }
- return cte;
+ NV_WARNONCE(dev, "DCB header validation failed\n");
+ return NULL;
}
-static enum dcb_connector_type
-divine_connector_type(struct nvbios *bios, int index)
+void *
+dcb_outp(struct drm_device *dev, u8 idx)
{
- struct dcb_table *dcb = &bios->dcb;
- unsigned encoders = 0, type = DCB_CONNECTOR_NONE;
- int i;
-
- for (i = 0; i < dcb->entries; i++) {
- if (dcb->entry[i].connector == index)
- encoders |= (1 << dcb->entry[i].type);
- }
-
- if (encoders & (1 << OUTPUT_DP)) {
- if (encoders & (1 << OUTPUT_TMDS))
- type = DCB_CONNECTOR_DP;
- else
- type = DCB_CONNECTOR_eDP;
- } else
- if (encoders & (1 << OUTPUT_TMDS)) {
- if (encoders & (1 << OUTPUT_ANALOG))
- type = DCB_CONNECTOR_DVI_I;
- else
- type = DCB_CONNECTOR_DVI_D;
- } else
- if (encoders & (1 << OUTPUT_ANALOG)) {
- type = DCB_CONNECTOR_VGA;
+ u8 *dcb = dcb_table(dev);
+ if (dcb && dcb[0] >= 0x30) {
+ if (idx < dcb[2])
+ return dcb + dcb[1] + (idx * dcb[3]);
} else
- if (encoders & (1 << OUTPUT_LVDS)) {
- type = DCB_CONNECTOR_LVDS;
+ if (dcb && dcb[0] >= 0x20) {
+ u8 *i2c = ROMPTR(dev, dcb[2]);
+ u8 *ent = dcb + 8 + (idx * 8);
+ if (i2c && ent < i2c)
+ return ent;
} else
- if (encoders & (1 << OUTPUT_TV)) {
- type = DCB_CONNECTOR_TV_0;
+ if (dcb && dcb[0] >= 0x15) {
+ u8 *i2c = ROMPTR(dev, dcb[2]);
+ u8 *ent = dcb + 4 + (idx * 10);
+ if (i2c && ent < i2c)
+ return ent;
}
- return type;
+ return NULL;
}
-static void
-apply_dcb_connector_quirks(struct nvbios *bios, int idx)
-{
- struct dcb_connector_table_entry *cte = &bios->dcb.connector.entry[idx];
- struct drm_device *dev = bios->dev;
+int
+dcb_outp_foreach(struct drm_device *dev, void *data,
+ int (*exec)(struct drm_device *, void *, int idx, u8 *outp))
+{
+ int ret, idx = -1;
+ u8 *outp = NULL;
+ while ((outp = dcb_outp(dev, ++idx))) {
+ if (ROM32(outp[0]) == 0x00000000)
+ break; /* seen on an NV11 with DCB v1.5 */
+ if (ROM32(outp[0]) == 0xffffffff)
+ break; /* seen on an NV17 with DCB v2.0 */
+
+ if ((outp[0] & 0x0f) == OUTPUT_UNUSED)
+ continue;
+ if ((outp[0] & 0x0f) == OUTPUT_EOL)
+ break;
- /* Gigabyte NX85T */
- if (nv_match_device(dev, 0x0421, 0x1458, 0x344c)) {
- if (cte->type == DCB_CONNECTOR_HDMI_1)
- cte->type = DCB_CONNECTOR_DVI_I;
+ ret = exec(dev, data, idx, outp);
+ if (ret)
+ return ret;
}
- /* Gigabyte GV-NX86T512H */
- if (nv_match_device(dev, 0x0402, 0x1458, 0x3455)) {
- if (cte->type == DCB_CONNECTOR_HDMI_1)
- cte->type = DCB_CONNECTOR_DVI_I;
- }
+ return 0;
}
-static const u8 hpd_gpio[16] = {
- 0xff, 0x07, 0x08, 0xff, 0xff, 0x51, 0x52, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x5f, 0x60,
-};
-
-static void
-parse_dcb_connector_table(struct nvbios *bios)
+u8 *
+dcb_conntab(struct drm_device *dev)
{
- struct drm_device *dev = bios->dev;
- struct dcb_connector_table *ct = &bios->dcb.connector;
- struct dcb_connector_table_entry *cte;
- uint8_t *conntab = &bios->data[bios->dcb.connector_table_ptr];
- uint8_t *entry;
- int i;
-
- if (!bios->dcb.connector_table_ptr) {
- NV_DEBUG_KMS(dev, "No DCB connector table present\n");
- return;
- }
-
- NV_INFO(dev, "DCB connector table: VHER 0x%02x %d %d %d\n",
- conntab[0], conntab[1], conntab[2], conntab[3]);
- if ((conntab[0] != 0x30 && conntab[0] != 0x40) ||
- (conntab[3] != 2 && conntab[3] != 4)) {
- NV_ERROR(dev, " Unknown! Please report.\n");
- return;
+ u8 *dcb = dcb_table(dev);
+ if (dcb && dcb[0] >= 0x30 && dcb[1] >= 0x16) {
+ u8 *conntab = ROMPTR(dev, dcb[0x14]);
+ if (conntab && conntab[0] >= 0x30 && conntab[0] <= 0x40)
+ return conntab;
}
+ return NULL;
+}
- ct->entries = conntab[2];
-
- entry = conntab + conntab[1];
- cte = &ct->entry[0];
- for (i = 0; i < conntab[2]; i++, entry += conntab[3], cte++) {
- cte->index = i;
- if (conntab[3] == 2)
- cte->entry = ROM16(entry[0]);
- else
- cte->entry = ROM32(entry[0]);
-
- cte->type = (cte->entry & 0x000000ff) >> 0;
- cte->index2 = (cte->entry & 0x00000f00) >> 8;
-
- cte->gpio_tag = ffs((cte->entry & 0x07033000) >> 12);
- cte->gpio_tag = hpd_gpio[cte->gpio_tag];
-
- if (cte->type == 0xff)
- continue;
-
- apply_dcb_connector_quirks(bios, i);
-
- NV_INFO(dev, " %d: 0x%08x: type 0x%02x idx %d tag 0x%02x\n",
- i, cte->entry, cte->type, cte->index, cte->gpio_tag);
-
- /* check for known types, fallback to guessing the type
- * from attached encoders if we hit an unknown.
- */
- switch (cte->type) {
- case DCB_CONNECTOR_VGA:
- case DCB_CONNECTOR_TV_0:
- case DCB_CONNECTOR_TV_1:
- case DCB_CONNECTOR_TV_3:
- case DCB_CONNECTOR_DVI_I:
- case DCB_CONNECTOR_DVI_D:
- case DCB_CONNECTOR_LVDS:
- case DCB_CONNECTOR_LVDS_SPWG:
- case DCB_CONNECTOR_DP:
- case DCB_CONNECTOR_eDP:
- case DCB_CONNECTOR_HDMI_0:
- case DCB_CONNECTOR_HDMI_1:
- break;
- default:
- cte->type = divine_connector_type(bios, cte->index);
- NV_WARN(dev, "unknown type, using 0x%02x\n", cte->type);
- break;
- }
-
- if (nouveau_override_conntype) {
- int type = divine_connector_type(bios, cte->index);
- if (type != cte->type)
- NV_WARN(dev, " -> type 0x%02x\n", cte->type);
- }
-
- }
+u8 *
+dcb_conn(struct drm_device *dev, u8 idx)
+{
+ u8 *conntab = dcb_conntab(dev);
+ if (conntab && idx < conntab[2])
+ return conntab + conntab[1] + (idx * conntab[3]);
+ return NULL;
}
static struct dcb_entry *new_dcb_entry(struct dcb_table *dcb)
@@ -6079,8 +5728,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
entry->type = conn & 0xf;
entry->i2c_index = (conn >> 4) & 0xf;
entry->heads = (conn >> 8) & 0xf;
- if (dcb->version >= 0x40)
- entry->connector = (conn >> 12) & 0xf;
+ entry->connector = (conn >> 12) & 0xf;
entry->bus = (conn >> 16) & 0xf;
entry->location = (conn >> 20) & 0x3;
entry->or = (conn >> 24) & 0xf;
@@ -6252,25 +5900,6 @@ parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb,
return true;
}
-static bool parse_dcb_entry(struct drm_device *dev, struct dcb_table *dcb,
- uint32_t conn, uint32_t conf)
-{
- struct dcb_entry *entry = new_dcb_entry(dcb);
- bool ret;
-
- if (dcb->version >= 0x20)
- ret = parse_dcb20_entry(dev, dcb, conn, conf, entry);
- else
- ret = parse_dcb15_entry(dev, dcb, conn, conf, entry);
- if (!ret)
- return ret;
-
- read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table,
- entry->i2c_index, &dcb->i2c[entry->i2c_index]);
-
- return true;
-}
-
static
void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb)
{
@@ -6431,154 +6060,118 @@ fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios)
#endif
/* Make up some sane defaults */
- fabricate_dcb_output(dcb, OUTPUT_ANALOG, LEGACY_I2C_CRT, 1, 1);
+ fabricate_dcb_output(dcb, OUTPUT_ANALOG,
+ bios->legacy.i2c_indices.crt, 1, 1);
if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
- fabricate_dcb_output(dcb, OUTPUT_TV, LEGACY_I2C_TV,
+ fabricate_dcb_output(dcb, OUTPUT_TV,
+ bios->legacy.i2c_indices.tv,
all_heads, 0);
else if (bios->tmds.output0_script_ptr ||
bios->tmds.output1_script_ptr)
- fabricate_dcb_output(dcb, OUTPUT_TMDS, LEGACY_I2C_PANEL,
+ fabricate_dcb_output(dcb, OUTPUT_TMDS,
+ bios->legacy.i2c_indices.panel,
all_heads, 1);
}
static int
-parse_dcb_table(struct drm_device *dev, struct nvbios *bios)
+parse_dcb_entry(struct drm_device *dev, void *data, int idx, u8 *outp)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct dcb_table *dcb = &bios->dcb;
- uint16_t dcbptr = 0, i2ctabptr = 0;
- uint8_t *dcbtable;
- uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES;
- bool configblock = true;
- int recordlength = 8, confofs = 4;
- int i;
-
- /* get the offset from 0x36 */
- if (dev_priv->card_type > NV_04) {
- dcbptr = ROM16(bios->data[0x36]);
- if (dcbptr == 0x0000)
- NV_WARN(dev, "No output data (DCB) found in BIOS\n");
- }
-
- /* this situation likely means a really old card, pre DCB */
- if (dcbptr == 0x0) {
- fabricate_dcb_encoder_table(dev, bios);
- return 0;
- }
-
- dcbtable = &bios->data[dcbptr];
-
- /* get DCB version */
- dcb->version = dcbtable[0];
- NV_TRACE(dev, "Found Display Configuration Block version %d.%d\n",
- dcb->version >> 4, dcb->version & 0xf);
-
- if (dcb->version >= 0x20) { /* NV17+ */
- uint32_t sig;
+ struct dcb_table *dcb = &dev_priv->vbios.dcb;
+ u32 conf = (dcb->version >= 0x20) ? ROM32(outp[4]) : ROM32(outp[6]);
+ u32 conn = ROM32(outp[0]);
+ bool ret;
- if (dcb->version >= 0x30) { /* NV40+ */
- headerlen = dcbtable[1];
- entries = dcbtable[2];
- recordlength = dcbtable[3];
- i2ctabptr = ROM16(dcbtable[4]);
- sig = ROM32(dcbtable[6]);
- dcb->gpio_table_ptr = ROM16(dcbtable[10]);
- dcb->connector_table_ptr = ROM16(dcbtable[20]);
- } else {
- i2ctabptr = ROM16(dcbtable[2]);
- sig = ROM32(dcbtable[4]);
- headerlen = 8;
- }
+ if (apply_dcb_encoder_quirks(dev, idx, &conn, &conf)) {
+ struct dcb_entry *entry = new_dcb_entry(dcb);
- if (sig != 0x4edcbdcb) {
- NV_ERROR(dev, "Bad Display Configuration Block "
- "signature (%08X)\n", sig);
- return -EINVAL;
- }
- } else if (dcb->version >= 0x15) { /* some NV11 and NV20 */
- char sig[8] = { 0 };
+ NV_TRACEWARN(dev, "DCB outp %02d: %08x %08x\n", idx, conn, conf);
- strncpy(sig, (char *)&dcbtable[-7], 7);
- i2ctabptr = ROM16(dcbtable[2]);
- recordlength = 10;
- confofs = 6;
+ if (dcb->version >= 0x20)
+ ret = parse_dcb20_entry(dev, dcb, conn, conf, entry);
+ else
+ ret = parse_dcb15_entry(dev, dcb, conn, conf, entry);
+ if (!ret)
+ return 1; /* stop parsing */
- if (strcmp(sig, "DEV_REC")) {
- NV_ERROR(dev, "Bad Display Configuration Block "
- "signature (%s)\n", sig);
- return -EINVAL;
- }
- } else {
- /*
- * v1.4 (some NV15/16, NV11+) seems the same as v1.5, but always
- * has the same single (crt) entry, even when tv-out present, so
- * the conclusion is this version cannot really be used.
- * v1.2 tables (some NV6/10, and NV15+) normally have the same
- * 5 entries, which are not specific to the card and so no use.
- * v1.2 does have an I2C table that read_dcb_i2c_table can
- * handle, but cards exist (nv11 in #14821) with a bad i2c table
- * pointer, so use the indices parsed in parse_bmp_structure.
- * v1.1 (NV5+, maybe some NV4) is entirely unhelpful
+ /* Ignore the I2C index for on-chip TV-out, as there
+ * are cards with bogus values (nv31m in bug 23212),
+ * and it's otherwise useless.
*/
- NV_TRACEWARN(dev, "No useful information in BIOS output table; "
- "adding all possible outputs\n");
- fabricate_dcb_encoder_table(dev, bios);
- return 0;
+ if (entry->type == OUTPUT_TV &&
+ entry->location == DCB_LOC_ON_CHIP)
+ entry->i2c_index = 0x0f;
}
- if (!i2ctabptr)
- NV_WARN(dev, "No pointer to DCB I2C port table\n");
- else {
- dcb->i2c_table = &bios->data[i2ctabptr];
- if (dcb->version >= 0x30)
- dcb->i2c_default_indices = dcb->i2c_table[4];
+ return 0;
+}
- /*
- * Parse the "management" I2C bus, used for hardware
- * monitoring and some external TMDS transmitters.
- */
- if (dcb->version >= 0x22) {
- int idx = (dcb->version >= 0x40 ?
- dcb->i2c_default_indices & 0xf :
- 2);
+static void
+dcb_fake_connectors(struct nvbios *bios)
+{
+ struct dcb_table *dcbt = &bios->dcb;
+ u8 map[16] = { };
+ int i, idx = 0;
- read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table,
- idx, &dcb->i2c[idx]);
- }
+ /* heuristic: if we ever get a non-zero connector field, assume
+ * that all the indices are valid and we don't need fake them.
+ */
+ for (i = 0; i < dcbt->entries; i++) {
+ if (dcbt->entry[i].connector)
+ return;
}
- if (entries > DCB_MAX_NUM_ENTRIES)
- entries = DCB_MAX_NUM_ENTRIES;
-
- for (i = 0; i < entries; i++) {
- uint32_t connection, config = 0;
-
- connection = ROM32(dcbtable[headerlen + recordlength * i]);
- if (configblock)
- config = ROM32(dcbtable[headerlen + confofs + recordlength * i]);
-
- /* seen on an NV11 with DCB v1.5 */
- if (connection == 0x00000000)
- break;
+ /* no useful connector info available, we need to make it up
+ * ourselves. the rule here is: anything on the same i2c bus
+ * is considered to be on the same connector. any output
+ * without an associated i2c bus is assigned its own unique
+ * connector index.
+ */
+ for (i = 0; i < dcbt->entries; i++) {
+ u8 i2c = dcbt->entry[i].i2c_index;
+ if (i2c == 0x0f) {
+ dcbt->entry[i].connector = idx++;
+ } else {
+ if (!map[i2c])
+ map[i2c] = ++idx;
+ dcbt->entry[i].connector = map[i2c] - 1;
+ }
+ }
- /* seen on an NV17 with DCB v2.0 */
- if (connection == 0xffffffff)
- break;
+ /* if we created more than one connector, destroy the connector
+ * table - just in case it has random, rather than stub, entries.
+ */
+ if (i > 1) {
+ u8 *conntab = dcb_conntab(bios->dev);
+ if (conntab)
+ conntab[0] = 0x00;
+ }
+}
- if ((connection & 0x0000000f) == 0x0000000f)
- continue;
+static int
+parse_dcb_table(struct drm_device *dev, struct nvbios *bios)
+{
+ struct dcb_table *dcb = &bios->dcb;
+ u8 *dcbt, *conn;
+ int idx;
+
+ dcbt = dcb_table(dev);
+ if (!dcbt) {
+ /* handle pre-DCB boards */
+ if (bios->type == NVBIOS_BMP) {
+ fabricate_dcb_encoder_table(dev, bios);
+ return 0;
+ }
- if (!apply_dcb_encoder_quirks(dev, i, &connection, &config))
- continue;
+ return -EINVAL;
+ }
- NV_TRACEWARN(dev, "Raw DCB entry %d: %08x %08x\n",
- dcb->entries, connection, config);
+ NV_TRACE(dev, "DCB version %d.%d\n", dcbt[0] >> 4, dcbt[0] & 0xf);
- if (!parse_dcb_entry(dev, dcb, connection, config))
- break;
- }
+ dcb->version = dcbt[0];
+ dcb_outp_foreach(dev, NULL, parse_dcb_entry);
/*
* apart for v2.1+ not being known for requiring merging, this
@@ -6590,77 +6183,19 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios)
if (!dcb->entries)
return -ENXIO;
- parse_dcb_gpio_table(bios);
- parse_dcb_connector_table(bios);
- return 0;
-}
-
-static void
-fixup_legacy_connector(struct nvbios *bios)
-{
- struct dcb_table *dcb = &bios->dcb;
- int i, i2c, i2c_conn[DCB_MAX_NUM_I2C_ENTRIES] = { };
-
- /*
- * DCB 3.0 also has the table in most cases, but there are some cards
- * where the table is filled with stub entries, and the DCB entriy
- * 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.
- */
- if (dcb->version >= 0x40)
- return;
-
- dcb->connector.entries = 0;
-
- /*
- * 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
- * connector. any output without an associated i2c bus is assigned
- * its own unique connector index.
- */
- for (i = 0; i < dcb->entries; i++) {
- /*
- * Ignore the I2C index for on-chip TV-out, as there
- * are cards with bogus values (nv31m in bug 23212),
- * and it's otherwise useless.
- */
- if (dcb->entry[i].type == OUTPUT_TV &&
- dcb->entry[i].location == DCB_LOC_ON_CHIP)
- dcb->entry[i].i2c_index = 0xf;
- i2c = dcb->entry[i].i2c_index;
-
- if (i2c_conn[i2c]) {
- dcb->entry[i].connector = i2c_conn[i2c] - 1;
- continue;
+ /* dump connector table entries to log, if any exist */
+ idx = -1;
+ while ((conn = dcb_conn(dev, ++idx))) {
+ if (conn[0] != 0xff) {
+ NV_TRACE(dev, "DCB conn %02d: ", idx);
+ if (dcb_conntab(dev)[3] < 4)
+ printk("%04x\n", ROM16(conn[0]));
+ else
+ printk("%08x\n", ROM32(conn[0]));
}
-
- dcb->entry[i].connector = dcb->connector.entries++;
- if (i2c != 0xf)
- i2c_conn[i2c] = dcb->connector.entries;
- }
-
- /* Fake the connector table as well as just connector indices */
- for (i = 0; i < dcb->connector.entries; i++) {
- dcb->connector.entry[i].index = i;
- dcb->connector.entry[i].type = divine_connector_type(bios, i);
- dcb->connector.entry[i].gpio_tag = 0xff;
- }
-}
-
-static void
-fixup_legacy_i2c(struct nvbios *bios)
-{
- struct dcb_table *dcb = &bios->dcb;
- int i;
-
- for (i = 0; i < dcb->entries; i++) {
- if (dcb->entry[i].i2c_index == LEGACY_I2C_CRT)
- dcb->entry[i].i2c_index = bios->legacy.i2c_indices.crt;
- if (dcb->entry[i].i2c_index == LEGACY_I2C_PANEL)
- dcb->entry[i].i2c_index = bios->legacy.i2c_indices.panel;
- if (dcb->entry[i].i2c_index == LEGACY_I2C_TV)
- dcb->entry[i].i2c_index = bios->legacy.i2c_indices.tv;
}
+ dcb_fake_connectors(bios);
+ return 0;
}
static int load_nv17_hwsq_ucode_entry(struct drm_device *dev, struct nvbios *bios, uint16_t hwsq_offset, int entry)
@@ -6879,19 +6414,6 @@ nouveau_run_vbios_init(struct drm_device *dev)
return ret;
}
-static void
-nouveau_bios_i2c_devices_takedown(struct drm_device *dev)
-{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nvbios *bios = &dev_priv->vbios;
- struct dcb_i2c_entry *entry;
- int i;
-
- entry = &bios->dcb.i2c[0];
- for (i = 0; i < DCB_MAX_NUM_I2C_ENTRIES; i++, entry++)
- nouveau_i2c_fini(dev, entry);
-}
-
static bool
nouveau_bios_posted(struct drm_device *dev)
{
@@ -6928,12 +6450,17 @@ nouveau_bios_init(struct drm_device *dev)
if (ret)
return ret;
- ret = parse_dcb_table(dev, bios);
+ ret = nouveau_i2c_init(dev);
if (ret)
return ret;
- fixup_legacy_i2c(bios);
- fixup_legacy_connector(bios);
+ ret = nouveau_mxm_init(dev);
+ if (ret)
+ return ret;
+
+ ret = parse_dcb_table(dev, bios);
+ if (ret)
+ return ret;
if (!bios->major_version) /* we don't run version 0 bios */
return 0;
@@ -6971,5 +6498,6 @@ nouveau_bios_init(struct drm_device *dev)
void
nouveau_bios_takedown(struct drm_device *dev)
{
- nouveau_bios_i2c_devices_takedown(dev);
+ nouveau_mxm_fini(dev);
+ nouveau_i2c_fini(dev);
}