Gentoo Archives: gentoo-commits

From: "Mike Pagano (mpagano)" <mpagano@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] linux-patches r2172 - genpatches-2.6/trunk/3.4
Date: Sun, 01 Jul 2012 21:27:50
Message-Id: 20120701212740.768AC2004B@flycatcher.gentoo.org
1 Author: mpagano
2 Date: 2012-07-01 21:27:39 +0000 (Sun, 01 Jul 2012)
3 New Revision: 2172
4
5 Added:
6 genpatches-2.6/trunk/3.4/2700_dual-channel-mode-vbios-check.patch
7 Modified:
8 genpatches-2.6/trunk/3.4/0000_README
9 Log:
10 Check VBIOS value for determining LVDS dual channel mode
11
12 Modified: genpatches-2.6/trunk/3.4/0000_README
13 ===================================================================
14 --- genpatches-2.6/trunk/3.4/0000_README 2012-06-23 18:47:58 UTC (rev 2171)
15 +++ genpatches-2.6/trunk/3.4/0000_README 2012-07-01 21:27:39 UTC (rev 2172)
16 @@ -63,6 +63,10 @@
17 From: Alexey Shvetsov <alexxy@g.o>
18 Desc: Zero copy for infiniband psm userspace driver
19
20 +Patch: 2700_dual-channel-mode-vbios-check.patch
21 +From: https://bugs.gentoo.org/show_bug.cgi?id=392549
22 +Desc: Check VBIOS value for determining LVDS dual channel mode
23 +
24 Patch: 4200_fbcondecor-0.9.6.patch
25 From: http://dev.gentoo.org/~spock
26 Desc: Bootsplash successor by Michal Januszewski ported by Alexxy
27
28 Added: genpatches-2.6/trunk/3.4/2700_dual-channel-mode-vbios-check.patch
29 ===================================================================
30 --- genpatches-2.6/trunk/3.4/2700_dual-channel-mode-vbios-check.patch (rev 0)
31 +++ genpatches-2.6/trunk/3.4/2700_dual-channel-mode-vbios-check.patch 2012-07-01 21:27:39 UTC (rev 2172)
32 @@ -0,0 +1,163 @@
33 +From: Takashi Iwai <tiwai@××××.de>
34 +Date: Tue, 20 Mar 2012 12:07:05 +0000 (+0100)
35 +Subject: drm/i915: Check VBIOS value for determining LVDS dual channel mode, too
36 +X-Git-Tag: v3.5-rc1~83^2~140^2~83
37 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux.git;a=commitdiff_plain;h=b03543857fd75876b96e10d4320b775e95041bb7
38 +
39 +drm/i915: Check VBIOS value for determining LVDS dual channel mode, too
40 +
41 +Currently i915 driver checks [PCH_]LVDS register bits to decide
42 +whether to set up the dual-link or the single-link mode. This relies
43 +implicitly on that BIOS initializes the register properly at boot.
44 +However, BIOS doesn't initialize it always. When the machine is
45 +booted with the closed lid, BIOS skips the LVDS reg initialization.
46 +This ends up in blank output on a machine with a dual-link LVDS when
47 +you open the lid after the boot.
48 +
49 +This patch adds a workaround for that problem by checking the initial
50 +LVDS register value in VBT.
51 +
52 +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=37742
53 +Tested-By: Paulo Zanoni <paulo.r.zanoni@×××××.com>
54 +Reviewed-by: Rodrigo Vivi <rodrigo.vivi@×××××.com>
55 +Reviewed-by: Adam Jackson <ajax@××××××.com>
56 +Signed-off-by: Takashi Iwai <tiwai@××××.de>
57 +Signed-off-by: Daniel Vetter <daniel.vetter@×××××.ch>
58 +---
59 +
60 +diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
61 +index b6098b0..4cbed7f 100644
62 +--- a/drivers/gpu/drm/i915/i915_drv.h
63 ++++ b/drivers/gpu/drm/i915/i915_drv.h
64 +@@ -406,6 +406,8 @@ typedef struct drm_i915_private {
65 + unsigned int lvds_use_ssc:1;
66 + unsigned int display_clock_mode:1;
67 + int lvds_ssc_freq;
68 ++ unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
69 ++ unsigned int lvds_val; /* used for checking LVDS channel mode */
70 + struct {
71 + int rate;
72 + int lanes;
73 +diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
74 +index 0ae76d6..e4317da 100644
75 +--- a/drivers/gpu/drm/i915/intel_bios.c
76 ++++ b/drivers/gpu/drm/i915/intel_bios.c
77 +@@ -173,6 +173,28 @@ get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data,
78 + return (struct lvds_dvo_timing *)(entry + dvo_timing_offset);
79 + }
80 +
81 ++/* get lvds_fp_timing entry
82 ++ * this function may return NULL if the corresponding entry is invalid
83 ++ */
84 ++static const struct lvds_fp_timing *
85 ++get_lvds_fp_timing(const struct bdb_header *bdb,
86 ++ const struct bdb_lvds_lfp_data *data,
87 ++ const struct bdb_lvds_lfp_data_ptrs *ptrs,
88 ++ int index)
89 ++{
90 ++ size_t data_ofs = (const u8 *)data - (const u8 *)bdb;
91 ++ u16 data_size = ((const u16 *)data)[-1]; /* stored in header */
92 ++ size_t ofs;
93 ++
94 ++ if (index >= ARRAY_SIZE(ptrs->ptr))
95 ++ return NULL;
96 ++ ofs = ptrs->ptr[index].fp_timing_offset;
97 ++ if (ofs < data_ofs ||
98 ++ ofs + sizeof(struct lvds_fp_timing) > data_ofs + data_size)
99 ++ return NULL;
100 ++ return (const struct lvds_fp_timing *)((const u8 *)bdb + ofs);
101 ++}
102 ++
103 + /* Try to find integrated panel data */
104 + static void
105 + parse_lfp_panel_data(struct drm_i915_private *dev_priv,
106 +@@ -182,6 +204,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
107 + const struct bdb_lvds_lfp_data *lvds_lfp_data;
108 + const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
109 + const struct lvds_dvo_timing *panel_dvo_timing;
110 ++ const struct lvds_fp_timing *fp_timing;
111 + struct drm_display_mode *panel_fixed_mode;
112 + int i, downclock;
113 +
114 +@@ -243,6 +266,19 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
115 + "Normal Clock %dKHz, downclock %dKHz\n",
116 + panel_fixed_mode->clock, 10*downclock);
117 + }
118 ++
119 ++ fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data,
120 ++ lvds_lfp_data_ptrs,
121 ++ lvds_options->panel_type);
122 ++ if (fp_timing) {
123 ++ /* check the resolution, just to be sure */
124 ++ if (fp_timing->x_res == panel_fixed_mode->hdisplay &&
125 ++ fp_timing->y_res == panel_fixed_mode->vdisplay) {
126 ++ dev_priv->bios_lvds_val = fp_timing->lvds_reg_val;
127 ++ DRM_DEBUG_KMS("VBT initial LVDS value %x\n",
128 ++ dev_priv->bios_lvds_val);
129 ++ }
130 ++ }
131 + }
132 +
133 + /* Try to find sdvo panel data */
134 +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
135 +index 683002fb..a76ac2e 100644
136 +--- a/drivers/gpu/drm/i915/intel_display.c
137 ++++ b/drivers/gpu/drm/i915/intel_display.c
138 +@@ -360,6 +360,27 @@ static const intel_limit_t intel_limits_ironlake_display_port = {
139 + .find_pll = intel_find_pll_ironlake_dp,
140 + };
141 +
142 ++static bool is_dual_link_lvds(struct drm_i915_private *dev_priv,
143 ++ unsigned int reg)
144 ++{
145 ++ unsigned int val;
146 ++
147 ++ if (dev_priv->lvds_val)
148 ++ val = dev_priv->lvds_val;
149 ++ else {
150 ++ /* BIOS should set the proper LVDS register value at boot, but
151 ++ * in reality, it doesn't set the value when the lid is closed;
152 ++ * we need to check "the value to be set" in VBT when LVDS
153 ++ * register is uninitialized.
154 ++ */
155 ++ val = I915_READ(reg);
156 ++ if (!(val & ~LVDS_DETECTED))
157 ++ val = dev_priv->bios_lvds_val;
158 ++ dev_priv->lvds_val = val;
159 ++ }
160 ++ return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;
161 ++}
162 ++
163 + static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
164 + int refclk)
165 + {
166 +@@ -368,8 +389,7 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
167 + const intel_limit_t *limit;
168 +
169 + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
170 +- if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) ==
171 +- LVDS_CLKB_POWER_UP) {
172 ++ if (is_dual_link_lvds(dev_priv, PCH_LVDS)) {
173 + /* LVDS dual channel */
174 + if (refclk == 100000)
175 + limit = &intel_limits_ironlake_dual_lvds_100m;
176 +@@ -397,8 +417,7 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc)
177 + const intel_limit_t *limit;
178 +
179 + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
180 +- if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
181 +- LVDS_CLKB_POWER_UP)
182 ++ if (is_dual_link_lvds(dev_priv, LVDS))
183 + /* LVDS with dual channel */
184 + limit = &intel_limits_g4x_dual_channel_lvds;
185 + else
186 +@@ -536,8 +555,7 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
187 + * reliably set up different single/dual channel state, if we
188 + * even can.
189 + */
190 +- if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
191 +- LVDS_CLKB_POWER_UP)
192 ++ if (is_dual_link_lvds(dev_priv, LVDS))
193 + clock.p2 = limit->p2.p2_fast;
194 + else
195 + clock.p2 = limit->p2.p2_slow;