| diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c |
| index 6b6c303..a81c738 100644 |
| |
| |
| @@ -3198,7 +3198,6 @@ static int run_lvds_table(struct drm_device *dev, struct dcb_entry *dcbent, int |
| struct nvbios *bios = &dev_priv->vbios; |
| unsigned int outputset = (dcbent->or == 4) ? 1 : 0; |
| uint16_t scriptptr = 0, clktable; |
| - uint8_t clktableptr = 0; |
| |
| /* |
| * For now we assume version 3.0 table - g80 support will need some |
| @@ -3217,26 +3216,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: |
| + clktable = bios->fp.lvdsmanufacturerpointer + 15; |
| + if (dcbent->or == 4) |
| + clktable += 8; |
| + |
| if (dcbent->lvdsconf.use_straps_for_mode) { |
| if (bios->fp.dual_link) |
| - clktableptr += 2; |
| - if (bios->fp.BITbit1) |
| - clktableptr++; |
| + clktable += 4; |
| + if (bios->fp.if_is_24bit) |
| + clktable += 2; |
| } else { |
| /* using EDID */ |
| - uint8_t fallback = bios->data[bios->fp.lvdsmanufacturerpointer + 4]; |
| - int fallbackcmpval = (dcbent->or == 4) ? 4 : 1; |
| + int cmpval_24bit = (dcbent->or == 4) ? 4 : 1; |
| |
| if (bios->fp.dual_link) { |
| - clktableptr += 2; |
| - fallbackcmpval *= 2; |
| + clktable += 4; |
| + cmpval_24bit <<= 1; |
| } |
| - if (fallbackcmpval & fallback) |
| - clktableptr++; |
| + |
| + if (bios->fp.strapless_is_24bit & cmpval_24bit) |
| + clktable += 2; |
| } |
| |
| - /* adding outputset * 8 may not be correct */ |
| - clktable = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 15 + clktableptr * 2 + outputset * 8]); |
| + clktable = ROM16(bios->data[clktable]); |
| if (!clktable) { |
| NV_ERROR(dev, "Pixel clock comparison table not found\n"); |
| return -ENOENT; |
| @@ -3638,37 +3640,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: |
| - /* |
| - * My money would be on there being a 24 bit interface bit in |
| - * this table, but I have no example of a laptop bios with a |
| - * 24 bit panel to confirm that. Hence we shout loudly if any |
| - * bit other than bit 0 is set (I've not even seen bit 1) |
| - */ |
| - if (bios->data[lvdsofs] > 1) |
| - NV_ERROR(dev, |
| - "You have a very unusual laptop display; please report it\n"); |
| + 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 BITbit1 isn't used |
| + * over-written, and if_is_24bit isn't used |
| */ |
| bios->fp.dual_link = bios->data[lvdsofs] & 1; |
| - bios->fp.BITbit1 = bios->data[lvdsofs] & 2; |
| - bios->fp.duallink_transition_clk = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 5]) * 10; |
| - break; |
| - case 0x40: |
| - 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; |
| } |
| |
| + /* 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 ((dev->pdev->device == 0x01d7) && |
| + (dev->pdev->subsystem_vendor == 0x1028) && |
| + (dev->pdev->subsystem_device == 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); |
| diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h |
| index 4f88e69..fd6274a 100644 |
| |
| |
| @@ -267,7 +267,6 @@ struct nvbios { |
| bool reset_after_pclk_change; |
| bool dual_link; |
| bool link_c_increment; |
| - bool BITbit1; |
| bool if_is_24bit; |
| int duallink_transition_clk; |
| uint8_t strapless_is_24bit; |