/* * Copyright 2005-2006 Erik Waling * Copyright 2006 Stephane Marchesin * Copyright 2007-2009 Stuart Bennett * * 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 AUTHORS 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.
*/
/* these defines are made up */ #define NV_CIO_CRE_44_HEADA 0x0 #define NV_CIO_CRE_44_HEADB 0x3 #define FEATURE_MOBILE 0x10 /* also FEATURE_QUADRO for BMP */
staticbool nv_cksum(const uint8_t *data, unsignedint length)
{ /* * There's a few checksums in the BIOS, so here's a generic checking * function.
*/ int i;
uint8_t sum = 0;
for (i = 0; i < length; i++)
sum += data[i];
if (sum) returntrue;
returnfalse;
}
static uint16_t clkcmptable(struct nvbios *bios, uint16_t clktable, int pxclk)
{ int compare_record_len, i = 0;
uint16_t compareclk, scriptptr = 0;
if (bios->major_version < 5) /* pre BIT */
compare_record_len = 3; else
compare_record_len = 4;
if (script == LVDS_PANEL_OFF) { /* off-on delay in ms */
mdelay(ROM16(bios->data[bios->fp.xlated_entry + 7]));
} #ifdef __powerpc__ /* Powerbook specific quirks */ if (script == LVDS_RESET &&
(pdev->device == 0x0179 || pdev->device == 0x0189 ||
pdev->device == 0x0329))
nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72); #endif
return 0;
}
staticint run_lvds_table(struct drm_device *dev, struct dcb_output *dcbent, int head, enum LVDS_script script, int pxclk)
{ /* * The BIT LVDS table's header has the information to setup the * necessary registers. Following the standard 4 byte header are: * A bitmask byte and a dual-link transition pxclk value for use in * selecting the init script when not using straps; 4 script pointers * for panel power, selected by output and on/off; and 8 table pointers * for panel init, the needed one determined by output, and bits in the * conf byte. These tables are similar to the TMDS tables, consisting * of a list of pxclks and script pointers.
*/ struct nouveau_drm *drm = nouveau_drm(dev); struct nvbios *bios = &drm->vbios; unsignedint outputset = (dcbent->or == 4) ? 1 : 0;
uint16_t scriptptr = 0, clktable;
/* * For now we assume version 3.0 table - g80 support will need some * changes
*/
switch (script) { case LVDS_INIT: return -ENOSYS; case LVDS_BACKLIGHT_ON: case LVDS_PANEL_ON:
scriptptr = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 7 + outputset * 2]); break; case LVDS_BACKLIGHT_OFF: case LVDS_PANEL_OFF:
scriptptr = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 11 + outputset * 2]); break; case LVDS_RESET:
clktable = bios->fp.lvdsmanufacturerpointer + 15; if (dcbent->or == 4)
clktable += 8;
if (dcbent->lvdsconf.use_straps_for_mode) { if (bios->fp.dual_link)
clktable += 4; if (bios->fp.if_is_24bit)
clktable += 2;
} else { /* using EDID */ int cmpval_24bit = (dcbent->or == 4) ? 4 : 1;
if (bios->fp.dual_link) {
clktable += 4;
cmpval_24bit <<= 1;
}
if (bios->fp.strapless_is_24bit & cmpval_24bit)
clktable += 2;
}
if (!scriptptr) {
NV_ERROR(drm, "LVDS output init script not found\n"); return -ENOENT;
}
run_digital_op_script(dev, scriptptr, dcbent, head, bios->fp.dual_link);
return 0;
}
int call_lvds_script(struct drm_device *dev, struct dcb_output *dcbent, int head, enum LVDS_script script, int pxclk)
{ /* * LVDS operations are multiplexed in an effort to present a single API * which works with two vastly differing underlying structures. * This acts as the demux
*/
sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000;
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding); /* some scripts set a value in NV_PBUS_POWERCTRL_2 and break video overlay */
nvif_wr32(device, NV_PBUS_POWERCTRL_2, 0);
staticint parse_lvds_manufacturer_table_header(struct drm_device *dev, struct nvbios *bios, struct lvdstableheader *lth)
{ /* * BMP version (0xa) LVDS table has a simple header of version and * record length. The BIT LVDS table has the typical BIT table header: * version byte, header length byte, record length byte, and a byte for * the maximum number of records that can be held in the table.
*/
/* * The fp strap is normally dictated by the "User Strap" in * PEXTDEV_BOOT_0[20:16], but on BMP cards when bit 2 of the * Internal_Flags struct at 0x48 is set, the user strap gets overriden * by the PCI subsystem ID during POST, but not before the previous user * strap has been committed to CR58 for CR57=0xf on head A, which may be * read and used instead
*/
if (bios->fp.fptablepointer == 0x0) { /* Most laptop cards lack an fp table. They use DDC. */
NV_DEBUG(drm, "Pointer to flat panel table invalid\n");
bios->digital_min_front_porch = 0x4b; return 0;
}
switch (fptable_ver) { /* * BMP version 0x5.0x11 BIOSen have version 1 like tables, but no * version field, and miss one of the spread spectrum/PWM bytes. * This could affect early GF2Go parts (not seen any appropriate ROMs * though). Here we assume that a version of 0x05 matches this case * (combining with a BMP version check would be better), as the * common case for the panel type field is 0x0005, and that is in * fact what we are reading the first byte of.
*/ case 0x05: /* some NV10, 11, 15, 16 */
recordlen = 42;
ofs = -1; break; case 0x10: /* some NV15/16, and NV11+ */
recordlen = 44;
ofs = 0; break; case 0x20: /* NV40+ */
headerlen = fptable[1];
recordlen = fptable[2];
fpentries = fptable[3]; /* * fptable[4] is the minimum * RAMDAC_FP_HCRTC -> RAMDAC_FP_HSYNC_START gap
*/
bios->digital_min_front_porch = fptable[4];
ofs = -7; break; default:
NV_ERROR(drm, "FP table revision %d.%d not currently supported\n",
fptable_ver >> 4, fptable_ver & 0xf); return -ENOSYS;
}
if (!bios->is_mobile) /* !mobile only needs digital_min_front_porch */ return 0;
ret = parse_lvds_manufacturer_table_header(dev, bios, <h); if (ret) return ret;
/* nv4x cards need both a strap value and fpindex of 0xf to use DDC */ if (lth.lvds_ver > 0x10)
bios->fp_no_ddc = fpstrapping != 0xf || fpindex != 0xf;
/* * If either the strap or xlated fpindex value are 0xf there is no * panel using a strap-derived bios mode present. this condition * includes, but is different from, the DDC panel indicator above
*/ if (fpstrapping == 0xf || fpindex == 0xf) return 0;
int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, bool *if_is_24bit)
{ /* * The LVDS table header is (mostly) described in * parse_lvds_manufacturer_table_header(): the BIT header additionally * contains the dual-link transition pxclk (in 10s kHz), at byte 5 - if * straps are not being used for the panel, this specifies the frequency * at which modes should be set up in the dual link style. * * Following the header, the BMP (ver 0xa) table has several records, * indexed by a separate xlat table, indexed in turn by the fp strap in * EXTDEV_BOOT. Each record had a config byte, followed by 6 script * numbers for use by INIT_SUB which controlled panel init and power, * and finally a dword of ms to sleep between power off and on * operations. * * In the BIT versions, the table following the header serves as an * integrated config and xlat table: the records in the table are * indexed by the FP strap nibble in EXTDEV_BOOT, and each record has * two bytes - the first as a config byte, the second for indexing the * fp mode table pointed to by the BIT 'D' table * * DDC is not used until after card init, so selecting the correct table * entry and setting the dual link flag for EDID equipped panels, * requiring tests against the native-mode pixel clock, cannot be done * until later, when this function should be called with non-zero pxclk
*/ struct nouveau_drm *drm = nouveau_drm(dev); struct nvbios *bios = &drm->vbios; int fpstrapping = get_fp_strap(dev, bios), lvdsmanufacturerindex = 0; struct lvdstableheader lth;
uint16_t lvdsofs; int ret, chip_version = bios->chip_version;
ret = parse_lvds_manufacturer_table_header(dev, bios, <h); if (ret) return ret;
switch (lth.lvds_ver) { case 0x0a: /* pre NV40 */
lvdsmanufacturerindex = bios->data[
bios->fp.fpxlatemanufacturertableptr +
fpstrapping];
/* we're done if this isn't the EDID panel case */ if (!pxclk) break;
if (chip_version < 0x25) { /* nv17 behaviour * * It seems the old style lvds script pointer is reused * to select 18/24 bit colour depth for EDID panels.
*/
lvdsmanufacturerindex =
(bios->legacy.lvds_single_a_script_ptr & 1) ?
2 : 0; if (pxclk >= bios->fp.duallink_transition_clk)
lvdsmanufacturerindex++;
} elseif (chip_version < 0x30) { /* nv28 behaviour (off-chip encoder) * * nv28 does a complex dance of first using byte 121 of * the EDID to choose the lvdsmanufacturerindex, then * later attempting to match the EDID manufacturer and * product IDs in a table (signature 'pidt' (panel id * table?)), setting an lvdsmanufacturerindex of 0 and * an fp strap of the match index (or 0xf if none)
*/
lvdsmanufacturerindex = 0;
} else { /* nv31, nv34 behaviour */
lvdsmanufacturerindex = 0; if (pxclk >= bios->fp.duallink_transition_clk)
lvdsmanufacturerindex = 2; if (pxclk >= 140000)
lvdsmanufacturerindex = 3;
}
/* * nvidia set the high nibble of (cr57=f, cr58) to * lvdsmanufacturerindex in this case; we don't
*/ break; case 0x30: /* NV4x */ case 0x40: /* G80/G90 */
lvdsmanufacturerindex = fpstrapping; break; default:
NV_ERROR(drm, "LVDS table revision not currently supported\n"); return -ENOSYS;
}
lvdsofs = bios->fp.xlated_entry = bios->fp.lvdsmanufacturerpointer + lth.headerlen + lth.recordlen * lvdsmanufacturerindex; switch (lth.lvds_ver) { case 0x0a:
bios->fp.power_off_for_reset = bios->data[lvdsofs] & 1;
bios->fp.reset_after_pclk_change = bios->data[lvdsofs] & 2;
bios->fp.dual_link = bios->data[lvdsofs] & 4;
bios->fp.link_c_increment = bios->data[lvdsofs] & 8;
*if_is_24bit = bios->data[lvdsofs] & 16; break; case 0x30: case 0x40: /* * No sign of the "power off for reset" or "reset for panel * on" bits, but it's safer to assume we should
*/
bios->fp.power_off_for_reset = true;
bios->fp.reset_after_pclk_change = true;
/* * It's ok lvdsofs is wrong for nv4x edid case; dual_link is * over-written, and if_is_24bit isn't used
*/
bios->fp.dual_link = bios->data[lvdsofs] & 1;
bios->fp.if_is_24bit = bios->data[lvdsofs] & 2;
bios->fp.strapless_is_24bit = bios->data[bios->fp.lvdsmanufacturerpointer + 4];
bios->fp.duallink_transition_clk = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 5]) * 10; break;
}
/* 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);
*dl = bios->fp.dual_link;
return 0;
}
int run_tmds_table(struct drm_device *dev, struct dcb_output *dcbent, int head, int pxclk)
{ /* * the pxclk parameter is in kHz * * This runs the TMDS regs setting code found on BIT bios cards * * For ffs(or) == 1 use the first table, for ffs(or) == 2 and * ffs(or) == 3, use the second.
*/
if (bitentry->length < 6) {
NV_ERROR(drm, "BIT i table too short for needed information\n"); return -EINVAL;
}
/* * bit 4 seems to indicate a mobile bios (doesn't suffer from BMP's * Quadro identity crisis), other bits possibly as for BMP feature byte
*/
bios->feature_byte = bios->data[bitentry->offset + 5];
bios->is_mobile = bios->feature_byte & FEATURE_MOBILE;
if (bitentry->length < 15) {
NV_WARN(drm, "BIT i table not long enough for DAC load " "detection comparison table\n"); return -EINVAL;
}
staticint parse_bit_lvds_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
{ /* * Parses the LVDS table segment that the bit entry points to. * Starting at bitentry->offset: * * offset + 0 (16 bits): LVDS strap xlate table pointer
*/
struct nouveau_drm *drm = nouveau_drm(dev);
if (bitentry->length != 2) {
NV_ERROR(drm, "Do not understand BIT LVDS table\n"); return -EINVAL;
}
/* * No idea if it's still called the LVDS manufacturer table, but * the concept's close enough.
*/
bios->fp.lvdsmanufacturerpointer = ROM16(bios->data[bitentry->offset]);
return 0;
}
staticint
parse_bit_M_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
{ /* * offset + 2 (8 bits): number of options in an * INIT_RAM_RESTRICT_ZM_REG_GROUP opcode option set * offset + 3 (16 bits): pointer to strap xlate table for RAM * restrict option selection * * There's a bunch of bits in this table other than the RAM restrict * stuff that we don't use - their use currently unknown
*/
/* * Older bios versions don't have a sufficiently long table for * what we want
*/ if (bitentry->length < 0x5) return 0;
staticint parse_bit_tmds_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
{ /* * Parses the pointer to the TMDS table * * Starting at bitentry->offset: * * offset + 0 (16 bits): TMDS table pointer * * The TMDS table is typically found just before the DCB table, with a * characteristic signature of 0x11,0x13 (1.1 being version, 0x13 being * length?) * * At offset +7 is a pointer to a script, which I don't know how to * run yet. * At offset +9 is a pointer to another script, likewise * Offset +11 has a pointer to a table where the first word is a pxclk * frequency and the second word a pointer to a script, which should be * run if the comparison pxclk frequency is less than the pxclk desired. * This repeats for decreasing comparison frequencies * Offset +13 has a pointer to a similar table * The selection of table (and possibly +7/+9 script) is dictated by * "or" from the DCB.
*/
/* nv50+ has v2.0, but we don't parse it atm */ if (bios->data[tmdstableptr] != 0x11) return -ENOSYS;
/* * These two scripts are odd: they don't seem to get run even when * they are not stubbed.
*/
script1 = ROM16(bios->data[tmdstableptr + 7]);
script2 = ROM16(bios->data[tmdstableptr + 9]); if (bios->data[script1] != 'q' || bios->data[script2] != 'q')
NV_WARN(drm, "TMDS table script pointers not stubbed\n");
if (bit_table(dev, table->id, &bitentry) == 0) return table->parse_fn(dev, bios, &bitentry);
NV_INFO(drm, "BIT table '%c' not found\n", table->id); return -ENOSYS;
}
staticint
parse_bit_structure(struct nvbios *bios, const uint16_t bitoffset)
{ int ret;
/* * The only restriction on parsing order currently is having 'i' first * for use of bios->*_version or bios->feature_byte while parsing; * functions shouldn't be actually *doing* anything apart from pulling * data from the image into the bios struct, thus no interdependencies
*/
ret = parse_bit_table(bios, bitoffset, &BIT_TABLE('i', i)); if (ret) /* info? */ return ret; if (bios->major_version >= 0x60) /* g80+ */
parse_bit_table(bios, bitoffset, &BIT_TABLE('A', A));
parse_bit_table(bios, bitoffset, &BIT_TABLE('D', display));
ret = parse_bit_table(bios, bitoffset, &BIT_TABLE('I', init)); if (ret) return ret;
parse_bit_table(bios, bitoffset, &BIT_TABLE('M', M)); /* memory? */
parse_bit_table(bios, bitoffset, &BIT_TABLE('L', lvds));
parse_bit_table(bios, bitoffset, &BIT_TABLE('T', tmds));
return 0;
}
staticint parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsignedint offset)
{ /* * Parses the BMP structure for useful things, but does not act on them * * offset + 5: BMP major version * offset + 6: BMP minor version * offset + 9: BMP feature byte * offset + 10: BCD encoded BIOS version * * offset + 18: init script table pointer (for bios versions < 5.10h) * offset + 20: extra init script table pointer (for bios * versions < 5.10h) * * offset + 24: memory init table pointer (used on early bios versions) * offset + 26: SDR memory sequencing setup data table * offset + 28: DDR memory sequencing setup data table * * offset + 54: index of I2C CRTC pair to use for CRT output * offset + 55: index of I2C CRTC pair to use for TV output * offset + 56: index of I2C CRTC pair to use for flat panel output * offset + 58: write CRTC index for I2C pair 0 * offset + 59: read CRTC index for I2C pair 0 * offset + 60: write CRTC index for I2C pair 1 * offset + 61: read CRTC index for I2C pair 1 * * offset + 67: maximum internal PLL frequency (single stage PLL) * offset + 71: minimum internal PLL frequency (single stage PLL) * * offset + 75: script table pointers, as described in * parse_script_table_pointers * * offset + 89: TMDS single link output A table pointer * offset + 91: TMDS single link output B table pointer * offset + 95: LVDS single link output A table pointer * offset + 105: flat panel timings table pointer * offset + 107: flat panel strapping translation table pointer * offset + 117: LVDS manufacturer panel config table pointer * offset + 119: LVDS manufacturer strapping translation table pointer * * offset + 142: PLL limits table pointer * * offset + 156: minimum pixel clock for LVDS dual link
*/
/* load needed defaults in case we can't parse this info */
bios->digital_min_front_porch = 0x4b;
bios->fmaxvco = 256000;
bios->fminvco = 128000;
bios->fp.duallink_transition_clk = 90000;
NV_INFO(drm, "BMP version %d.%d\n",
bmp_version_major, bmp_version_minor);
/* * Make sure that 0x36 is blank and can't be mistaken for a DCB * pointer on early versions
*/ if (bmp_version_major < 5)
*(uint16_t *)&bios->data[0x36] = 0;
/* * Seems that the minor version was 1 for all major versions prior * to 5. Version 6 could theoretically exist, but I suspect BIT * happened instead.
*/ if ((bmp_version_major < 5 && bmp_version_minor != 1) || bmp_version_major > 5) {
NV_ERROR(drm, "You have an unsupported BMP version. " "Please send in your bios\n"); return -ENOSYS;
}
if (bmp_version_major == 0) /* nothing that's currently useful in this version */ return 0; elseif (bmp_version_major == 1)
bmplength = 44; /* exact for 1.01 */ elseif (bmp_version_major == 2)
bmplength = 48; /* exact for 2.01 */ elseif (bmp_version_major == 3)
bmplength = 54; /* guessed - mem init tables added in this version */ elseif (bmp_version_major == 4 || bmp_version_minor < 0x1) /* don't know if 5.0 exists... */
bmplength = 62; /* guessed - BMP I2C indices added in version 4*/ elseif (bmp_version_minor < 0x6)
bmplength = 67; /* exact for 5.01 */ elseif (bmp_version_minor < 0x10)
bmplength = 75; /* exact for 5.06 */ elseif (bmp_version_minor == 0x10)
bmplength = 89; /* exact for 5.10h */ elseif (bmp_version_minor < 0x14)
bmplength = 118; /* exact for 5.11h */ elseif (bmp_version_minor < 0x24) /* * Not sure of version where pll limits came in; * certainly exist by 0x24 though.
*/ /* length not exact: this is long enough to get lvds members */
bmplength = 123; elseif (bmp_version_minor < 0x27) /* * Length not exact: this is long enough to get pll limit * member
*/
bmplength = 144; else /* * Length not exact: this is long enough to get dual link * transition clock.
*/
bmplength = 158;
/* * Bit 4 seems to indicate either a mobile bios or a quadro card -- * mobile behaviour consistent (nv11+), quadro only seen nv18gl-nv36gl * (not nv10gl), bit 5 that the flat panel tables are present, and * bit 6 a tv bios.
*/
bios->feature_byte = bmp[9];
if (drm->client.device.info.family > NV_DEVICE_INFO_V0_TNT)
dcb = ROMPTR(dev, drm->vbios.data[0x36]); if (!dcb) {
NV_WARN(drm, "No DCB data found in VBIOS\n"); return NULL;
}
if (dcb[0] >= 0x42) {
NV_WARN(drm, "DCB version 0x%02x unknown\n", dcb[0]); return NULL;
} else if (dcb[0] >= 0x30) { if (ROM32(dcb[6]) == 0x4edcbdcb) return dcb;
} else if (dcb[0] >= 0x20) { if (ROM32(dcb[4]) == 0x4edcbdcb) return dcb;
} else if (dcb[0] >= 0x15) { if (!memcmp(&dcb[-7], "DEV_REC", 7)) return dcb;
} 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
*/
NV_WARN(drm, "No useful DCB data in VBIOS\n"); return NULL;
}
int
olddcb_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 = olddcb_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) == DCB_OUTPUT_UNUSED) continue; if ((outp[0] & 0x0f) == DCB_OUTPUT_EOL) break;
ret = exec(dev, data, idx, outp); if (ret) return ret;
}
switch (entry->type) { case DCB_OUTPUT_ANALOG: /* * Although the rest of a CRT conf dword is usually * zeros, mac biosen have stuff there so we must mask
*/
entry->crtconf.maxfreq = (dcb->version < 0x30) ?
(conf & 0xffff) * 10 :
(conf & 0xff) * 10000; break; case DCB_OUTPUT_LVDS:
{
uint32_t mask; if (conf & 0x1)
entry->lvdsconf.use_straps_for_mode = true; if (dcb->version < 0x22) {
mask = ~0xd; /* * The laptop in bug 14567 lies and claims to not use * straps when it does, so assume all DCB 2.0 laptops * use straps, until a broken EDID using one is produced
*/
entry->lvdsconf.use_straps_for_mode = true; /* * Both 0x4 and 0x8 show up in v2.0 tables; assume they * mean the same thing (probably wrong, but might work)
*/ if (conf & 0x4 || conf & 0x8)
entry->lvdsconf.use_power_scripts = true;
} else {
mask = ~0x7; if (conf & 0x2)
entry->lvdsconf.use_acpi_for_edid = true; if (conf & 0x4)
entry->lvdsconf.use_power_scripts = true;
entry->lvdsconf.sor.link = (conf & 0x00000030) >> 4;
link = entry->lvdsconf.sor.link;
} if (conf & mask) { /* * Until we even try to use these on G8x, it's * useless reporting unknown bits. They all are.
*/ if (dcb->version >= 0x40) break;
break;
} case DCB_OUTPUT_DP:
entry->dpconf.sor.link = (conf & 0x00000030) >> 4;
entry->extdev = (conf & 0x0000ff00) >> 8; switch ((conf & 0x00e00000) >> 21) { case 0:
entry->dpconf.link_bw = 162000; break; case 1:
entry->dpconf.link_bw = 270000; break; case 2:
entry->dpconf.link_bw = 540000; break; case 3: default:
entry->dpconf.link_bw = 810000; break;
} switch ((conf & 0x0f000000) >> 24) { case 0xf: case 0x4:
entry->dpconf.link_nr = 4; break; case 0x3: case 0x2:
entry->dpconf.link_nr = 2; break; default:
entry->dpconf.link_nr = 1; break;
}
link = entry->dpconf.sor.link; break; case DCB_OUTPUT_TMDS: if (dcb->version >= 0x40) {
entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4;
entry->extdev = (conf & 0x0000ff00) >> 8;
link = entry->tmdsconf.sor.link;
} elseif (dcb->version >= 0x30)
entry->tmdsconf.slave_addr = (conf & 0x00000700) >> 8; elseif (dcb->version >= 0x22)
entry->tmdsconf.slave_addr = (conf & 0x00000070) >> 4; break; case DCB_OUTPUT_EOL: /* weird g80 mobile type that "nv" treats as a terminator */
dcb->entries--; returnfalse; default: break;
}
if (dcb->version < 0x40) { /* Normal entries consist of a single bit, but dual link has * the next most significant bit set too
*/
entry->duallink_possible =
((1 << (ffs(entry->or) - 1)) * 3 == entry->or);
} else {
entry->duallink_possible = (entry->sorconf.link == 3);
}
/* unsure what DCB version introduces this, 3.0? */ if (conf & 0x100000)
entry->i2c_upper_default = true;
switch (entry->type) { case DCB_OUTPUT_ANALOG:
entry->crtconf.maxfreq = (conf & 0xffff) * 10; break; case DCB_OUTPUT_TV:
entry->tvconf.has_component_output = false; break; case DCB_OUTPUT_LVDS: if ((conn & 0x00003f00) >> 8 != 0x10)
entry->lvdsconf.use_straps_for_mode = true;
entry->lvdsconf.use_power_scripts = true; break; default: break;
}
returntrue;
}
static void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb)
{ /* * DCB v2.0 lists each output combination separately. * Here we merge compatible entries to have fewer outputs, with * more options
*/
struct nouveau_drm *drm = nouveau_drm(dev); int i, newentries = 0;
for (i = 0; i < dcb->entries; i++) { struct dcb_output *ient = &dcb->entry[i]; int j;
for (j = i + 1; j < dcb->entries; j++) { struct dcb_output *jent = &dcb->entry[j];
if (jent->type == 100) /* already merged entry */ continue;
/* merge heads field when all other fields the same */ if (jent->i2c_index == ient->i2c_index &&
jent->type == ient->type &&
jent->location == ient->location &&
jent->or == ient->or) {
NV_INFO(drm, "Merging DCB entries %d and %d\n",
i, j);
ient->heads |= jent->heads;
jent->type = 100; /* dummy value */
}
}
}
/* Compact entries merged into others out of dcb */ for (i = 0; i < dcb->entries; i++) { if (dcb->entry[i].type == 100) continue;
/* Dell Precision M6300 * DCB entry 2: 02025312 00000010 * DCB entry 3: 02026312 00000020 * * Identical, except apparently a different connector on a * different SOR link. Not a clue how we're supposed to know * which one is in use if it even shares an i2c line... * * Ignore the connector on the second SOR link to prevent * nasty problems until this is sorted (assuming it's not a * VBIOS bug).
*/ if (nv_match_device(dev, 0x040d, 0x1028, 0x019b)) { if (*conn == 0x02026312 && *conf == 0x00000020) returnfalse;
}
/* GeForce3 Ti 200 * * DCB reports an LVDS output that should be TMDS: * DCB entry 1: f2005014 ffffffff
*/ if (nv_match_device(dev, 0x0201, 0x1462, 0x8851)) { if (*conn == 0xf2005014 && *conf == 0xffffffff) {
fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, DCB_OUTPUT_B); returnfalse;
}
}
if (dcb->version >= 0x20)
ret = parse_dcb20_entry(dev, dcb, conn, conf, entry); else
ret = parse_dcb15_entry(dev, dcb, conn, conf, entry);
entry->id = idx;
if (!ret) return 1; /* stop parsing */
/* 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 (entry->type == DCB_OUTPUT_TV &&
entry->location == DCB_LOC_ON_CHIP)
entry->i2c_index = 0x0f;
}
return 0;
}
staticvoid
dcb_fake_connectors(struct nvbios *bios)
{ struct dcb_table *dcbt = &bios->dcb;
u8 map[16] = { }; int i, idx = 0;
/* heuristic: if we ever get a non-zero connector field, assume * that all the indices are valid and we don't need fake them. * * and, as usual, a blacklist of boards with bad bios data..
*/ if (!nv_match_device(bios->dev, 0x0392, 0x107d, 0x20a2)) { for (i = 0; i < dcbt->entries; i++) { if (dcbt->entry[i].connector) return;
}
}
/* 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;
}
}
/* 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 = olddcb_conntab(bios->dev); if (conntab)
conntab[0] = 0x00;
}
}
/* * apart for v2.1+ not being known for requiring merging, this * guarantees dcbent->index is the index of the entry in the rom image
*/ if (dcb->version < 0x21)
merge_like_dcb_entries(dev, dcb);
/* dump connector table entries to log, if any exist */
idx = -1; while ((conn = olddcb_conn(dev, ++idx))) { if (conn[0] != 0xff) { if (olddcb_conntab(dev)[3] < 4)
NV_INFO(drm, "DCB conn %02d: %04x\n",
idx, ROM16(conn[0])); else
NV_INFO(drm, "DCB conn %02d: %08x\n",
idx, ROM32(conn[0]));
}
}
dcb_fake_connectors(bios); return 0;
}
staticint load_nv17_hwsq_ucode_entry(struct drm_device *dev, struct nvbios *bios, uint16_t hwsq_offset, int entry)
{ /* * The header following the "HWSQ" signature has the number of entries, * and the entry size * * An entry consists of a dword to write to the sequencer control reg * (0x00001304), followed by the ucode bytes, written sequentially, * starting at reg 0x00001400
*/
staticint load_nv17_hw_sequencer_ucode(struct drm_device *dev, struct nvbios *bios)
{ /* * BMP based cards, from NV17, need a microcode loading to correctly * control the GPIO etc for LVDS panels * * BIT based cards seem to do this directly in the init scripts * * The microcode entries are found by the "HWSQ" signature.
*/
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.