Rev 5097 | Rev 6084 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2351 | Serge | 1 | /* |
2 | * Copyright © 2006 Intel Corporation |
||
3 | * |
||
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
5 | * copy of this software and associated documentation files (the "Software"), |
||
6 | * to deal in the Software without restriction, including without limitation |
||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
8 | * and/or sell copies of the Software, and to permit persons to whom the |
||
9 | * Software is furnished to do so, subject to the following conditions: |
||
10 | * |
||
11 | * The above copyright notice and this permission notice (including the next |
||
12 | * paragraph) shall be included in all copies or substantial portions of the |
||
13 | * Software. |
||
14 | * |
||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||
21 | * SOFTWARE. |
||
22 | * |
||
23 | * Authors: |
||
24 | * Eric Anholt |
||
25 | * |
||
26 | */ |
||
5097 | serge | 27 | #include |
28 | #include |
||
5060 | serge | 29 | #include |
3031 | serge | 30 | #include |
2351 | Serge | 31 | #include "i915_drv.h" |
32 | #include "intel_bios.h" |
||
33 | |||
34 | #define SLAVE_ADDR1 0x70 |
||
35 | #define SLAVE_ADDR2 0x72 |
||
36 | |||
37 | static int panel_type; |
||
38 | |||
39 | static void * |
||
40 | find_section(struct bdb_header *bdb, int section_id) |
||
41 | { |
||
42 | u8 *base = (u8 *)bdb; |
||
43 | int index = 0; |
||
44 | u16 total, current_size; |
||
45 | u8 current_id; |
||
46 | |||
47 | /* skip to first section */ |
||
48 | index += bdb->header_size; |
||
49 | total = bdb->bdb_size; |
||
50 | |||
51 | /* walk the sections looking for section_id */ |
||
5060 | serge | 52 | while (index + 3 < total) { |
2351 | Serge | 53 | current_id = *(base + index); |
54 | index++; |
||
5060 | serge | 55 | |
2351 | Serge | 56 | current_size = *((u16 *)(base + index)); |
57 | index += 2; |
||
5060 | serge | 58 | |
59 | if (index + current_size > total) |
||
60 | return NULL; |
||
61 | |||
2351 | Serge | 62 | if (current_id == section_id) |
63 | return base + index; |
||
5060 | serge | 64 | |
2351 | Serge | 65 | index += current_size; |
66 | } |
||
67 | |||
68 | return NULL; |
||
69 | } |
||
70 | |||
71 | static u16 |
||
72 | get_blocksize(void *p) |
||
73 | { |
||
74 | u16 *block_ptr, block_size; |
||
75 | |||
76 | block_ptr = (u16 *)((char *)p - 2); |
||
77 | block_size = *block_ptr; |
||
78 | return block_size; |
||
79 | } |
||
80 | |||
81 | static void |
||
82 | fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, |
||
83 | const struct lvds_dvo_timing *dvo_timing) |
||
84 | { |
||
85 | panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | |
||
86 | dvo_timing->hactive_lo; |
||
87 | panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay + |
||
88 | ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo); |
||
89 | panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start + |
||
90 | dvo_timing->hsync_pulse_width; |
||
91 | panel_fixed_mode->htotal = panel_fixed_mode->hdisplay + |
||
92 | ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo); |
||
93 | |||
94 | panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) | |
||
95 | dvo_timing->vactive_lo; |
||
96 | panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay + |
||
97 | dvo_timing->vsync_off; |
||
98 | panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start + |
||
99 | dvo_timing->vsync_pulse_width; |
||
100 | panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay + |
||
101 | ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo); |
||
102 | panel_fixed_mode->clock = dvo_timing->clock * 10; |
||
103 | panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; |
||
104 | |||
105 | if (dvo_timing->hsync_positive) |
||
106 | panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC; |
||
107 | else |
||
108 | panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC; |
||
109 | |||
110 | if (dvo_timing->vsync_positive) |
||
111 | panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC; |
||
112 | else |
||
113 | panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC; |
||
114 | |||
115 | /* Some VBTs have bogus h/vtotal values */ |
||
116 | if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) |
||
117 | panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; |
||
118 | if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) |
||
119 | panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; |
||
120 | |||
121 | drm_mode_set_name(panel_fixed_mode); |
||
122 | } |
||
123 | |||
124 | static bool |
||
125 | lvds_dvo_timing_equal_size(const struct lvds_dvo_timing *a, |
||
126 | const struct lvds_dvo_timing *b) |
||
127 | { |
||
128 | if (a->hactive_hi != b->hactive_hi || |
||
129 | a->hactive_lo != b->hactive_lo) |
||
130 | return false; |
||
131 | |||
132 | if (a->hsync_off_hi != b->hsync_off_hi || |
||
133 | a->hsync_off_lo != b->hsync_off_lo) |
||
134 | return false; |
||
135 | |||
136 | if (a->hsync_pulse_width != b->hsync_pulse_width) |
||
137 | return false; |
||
138 | |||
139 | if (a->hblank_hi != b->hblank_hi || |
||
140 | a->hblank_lo != b->hblank_lo) |
||
141 | return false; |
||
142 | |||
143 | if (a->vactive_hi != b->vactive_hi || |
||
144 | a->vactive_lo != b->vactive_lo) |
||
145 | return false; |
||
146 | |||
147 | if (a->vsync_off != b->vsync_off) |
||
148 | return false; |
||
149 | |||
150 | if (a->vsync_pulse_width != b->vsync_pulse_width) |
||
151 | return false; |
||
152 | |||
153 | if (a->vblank_hi != b->vblank_hi || |
||
154 | a->vblank_lo != b->vblank_lo) |
||
155 | return false; |
||
156 | |||
157 | return true; |
||
158 | } |
||
159 | |||
160 | static const struct lvds_dvo_timing * |
||
161 | get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data, |
||
162 | const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs, |
||
163 | int index) |
||
164 | { |
||
165 | /* |
||
166 | * the size of fp_timing varies on the different platform. |
||
167 | * So calculate the DVO timing relative offset in LVDS data |
||
168 | * entry to get the DVO timing entry |
||
169 | */ |
||
170 | |||
171 | int lfp_data_size = |
||
172 | lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset - |
||
173 | lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset; |
||
174 | int dvo_timing_offset = |
||
175 | lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset - |
||
176 | lvds_lfp_data_ptrs->ptr[0].fp_timing_offset; |
||
177 | char *entry = (char *)lvds_lfp_data->data + lfp_data_size * index; |
||
178 | |||
179 | return (struct lvds_dvo_timing *)(entry + dvo_timing_offset); |
||
180 | } |
||
181 | |||
3031 | serge | 182 | /* get lvds_fp_timing entry |
183 | * this function may return NULL if the corresponding entry is invalid |
||
184 | */ |
||
185 | static const struct lvds_fp_timing * |
||
186 | get_lvds_fp_timing(const struct bdb_header *bdb, |
||
187 | const struct bdb_lvds_lfp_data *data, |
||
188 | const struct bdb_lvds_lfp_data_ptrs *ptrs, |
||
189 | int index) |
||
190 | { |
||
191 | size_t data_ofs = (const u8 *)data - (const u8 *)bdb; |
||
192 | u16 data_size = ((const u16 *)data)[-1]; /* stored in header */ |
||
193 | size_t ofs; |
||
194 | |||
195 | if (index >= ARRAY_SIZE(ptrs->ptr)) |
||
196 | return NULL; |
||
197 | ofs = ptrs->ptr[index].fp_timing_offset; |
||
198 | if (ofs < data_ofs || |
||
199 | ofs + sizeof(struct lvds_fp_timing) > data_ofs + data_size) |
||
200 | return NULL; |
||
201 | return (const struct lvds_fp_timing *)((const u8 *)bdb + ofs); |
||
202 | } |
||
203 | |||
2351 | Serge | 204 | /* Try to find integrated panel data */ |
205 | static void |
||
206 | parse_lfp_panel_data(struct drm_i915_private *dev_priv, |
||
207 | struct bdb_header *bdb) |
||
208 | { |
||
209 | const struct bdb_lvds_options *lvds_options; |
||
210 | const struct bdb_lvds_lfp_data *lvds_lfp_data; |
||
211 | const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; |
||
212 | const struct lvds_dvo_timing *panel_dvo_timing; |
||
3031 | serge | 213 | const struct lvds_fp_timing *fp_timing; |
2351 | Serge | 214 | struct drm_display_mode *panel_fixed_mode; |
5060 | serge | 215 | int i, downclock, drrs_mode; |
2351 | Serge | 216 | |
217 | lvds_options = find_section(bdb, BDB_LVDS_OPTIONS); |
||
218 | if (!lvds_options) |
||
219 | return; |
||
220 | |||
4104 | Serge | 221 | dev_priv->vbt.lvds_dither = lvds_options->pixel_dither; |
2351 | Serge | 222 | if (lvds_options->panel_type == 0xff) |
223 | return; |
||
224 | |||
225 | panel_type = lvds_options->panel_type; |
||
226 | |||
5060 | serge | 227 | drrs_mode = (lvds_options->dps_panel_type_bits |
228 | >> (panel_type * 2)) & MODE_MASK; |
||
229 | /* |
||
230 | * VBT has static DRRS = 0 and seamless DRRS = 2. |
||
231 | * The below piece of code is required to adjust vbt.drrs_type |
||
232 | * to match the enum drrs_support_type. |
||
233 | */ |
||
234 | switch (drrs_mode) { |
||
235 | case 0: |
||
236 | dev_priv->vbt.drrs_type = STATIC_DRRS_SUPPORT; |
||
237 | DRM_DEBUG_KMS("DRRS supported mode is static\n"); |
||
238 | break; |
||
239 | case 2: |
||
240 | dev_priv->vbt.drrs_type = SEAMLESS_DRRS_SUPPORT; |
||
241 | DRM_DEBUG_KMS("DRRS supported mode is seamless\n"); |
||
242 | break; |
||
243 | default: |
||
244 | dev_priv->vbt.drrs_type = DRRS_NOT_SUPPORTED; |
||
245 | DRM_DEBUG_KMS("DRRS not supported (VBT input)\n"); |
||
246 | break; |
||
247 | } |
||
248 | |||
2351 | Serge | 249 | lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); |
250 | if (!lvds_lfp_data) |
||
251 | return; |
||
252 | |||
253 | lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS); |
||
254 | if (!lvds_lfp_data_ptrs) |
||
255 | return; |
||
256 | |||
4104 | Serge | 257 | dev_priv->vbt.lvds_vbt = 1; |
2351 | Serge | 258 | |
259 | panel_dvo_timing = get_lvds_dvo_timing(lvds_lfp_data, |
||
260 | lvds_lfp_data_ptrs, |
||
261 | lvds_options->panel_type); |
||
262 | |||
263 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); |
||
264 | if (!panel_fixed_mode) |
||
265 | return; |
||
266 | |||
267 | fill_detail_timing_data(panel_fixed_mode, panel_dvo_timing); |
||
268 | |||
4104 | Serge | 269 | dev_priv->vbt.lfp_lvds_vbt_mode = panel_fixed_mode; |
2351 | Serge | 270 | |
271 | DRM_DEBUG_KMS("Found panel mode in BIOS VBT tables:\n"); |
||
272 | drm_mode_debug_printmodeline(panel_fixed_mode); |
||
273 | |||
274 | /* |
||
275 | * Iterate over the LVDS panel timing info to find the lowest clock |
||
276 | * for the native resolution. |
||
277 | */ |
||
278 | downclock = panel_dvo_timing->clock; |
||
279 | for (i = 0; i < 16; i++) { |
||
280 | const struct lvds_dvo_timing *dvo_timing; |
||
281 | |||
282 | dvo_timing = get_lvds_dvo_timing(lvds_lfp_data, |
||
283 | lvds_lfp_data_ptrs, |
||
284 | i); |
||
285 | if (lvds_dvo_timing_equal_size(dvo_timing, panel_dvo_timing) && |
||
286 | dvo_timing->clock < downclock) |
||
287 | downclock = dvo_timing->clock; |
||
288 | } |
||
289 | |||
5060 | serge | 290 | if (downclock < panel_dvo_timing->clock && i915.lvds_downclock) { |
2351 | Serge | 291 | dev_priv->lvds_downclock_avail = 1; |
292 | dev_priv->lvds_downclock = downclock * 10; |
||
293 | DRM_DEBUG_KMS("LVDS downclock is found in VBT. " |
||
294 | "Normal Clock %dKHz, downclock %dKHz\n", |
||
295 | panel_fixed_mode->clock, 10*downclock); |
||
296 | } |
||
3031 | serge | 297 | |
298 | fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data, |
||
299 | lvds_lfp_data_ptrs, |
||
300 | lvds_options->panel_type); |
||
301 | if (fp_timing) { |
||
302 | /* check the resolution, just to be sure */ |
||
303 | if (fp_timing->x_res == panel_fixed_mode->hdisplay && |
||
304 | fp_timing->y_res == panel_fixed_mode->vdisplay) { |
||
4104 | Serge | 305 | dev_priv->vbt.bios_lvds_val = fp_timing->lvds_reg_val; |
3031 | serge | 306 | DRM_DEBUG_KMS("VBT initial LVDS value %x\n", |
4104 | Serge | 307 | dev_priv->vbt.bios_lvds_val); |
3031 | serge | 308 | } |
309 | } |
||
2351 | Serge | 310 | } |
311 | |||
4560 | Serge | 312 | static void |
313 | parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb) |
||
314 | { |
||
315 | const struct bdb_lfp_backlight_data *backlight_data; |
||
316 | const struct bdb_lfp_backlight_data_entry *entry; |
||
317 | |||
318 | backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT); |
||
319 | if (!backlight_data) |
||
320 | return; |
||
321 | |||
322 | if (backlight_data->entry_size != sizeof(backlight_data->data[0])) { |
||
323 | DRM_DEBUG_KMS("Unsupported backlight data entry size %u\n", |
||
324 | backlight_data->entry_size); |
||
325 | return; |
||
326 | } |
||
327 | |||
328 | entry = &backlight_data->data[panel_type]; |
||
329 | |||
5060 | serge | 330 | dev_priv->vbt.backlight.present = entry->type == BDB_BACKLIGHT_TYPE_PWM; |
331 | if (!dev_priv->vbt.backlight.present) { |
||
332 | DRM_DEBUG_KMS("PWM backlight not present in VBT (type %u)\n", |
||
333 | entry->type); |
||
334 | return; |
||
335 | } |
||
336 | |||
4560 | Serge | 337 | dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz; |
338 | dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm; |
||
5060 | serge | 339 | dev_priv->vbt.backlight.min_brightness = entry->min_brightness; |
4560 | Serge | 340 | DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, " |
341 | "active %s, min brightness %u, level %u\n", |
||
342 | dev_priv->vbt.backlight.pwm_freq_hz, |
||
343 | dev_priv->vbt.backlight.active_low_pwm ? "low" : "high", |
||
5060 | serge | 344 | dev_priv->vbt.backlight.min_brightness, |
4560 | Serge | 345 | backlight_data->level[panel_type]); |
346 | } |
||
347 | |||
2351 | Serge | 348 | /* Try to find sdvo panel data */ |
349 | static void |
||
350 | parse_sdvo_panel_data(struct drm_i915_private *dev_priv, |
||
351 | struct bdb_header *bdb) |
||
352 | { |
||
353 | struct lvds_dvo_timing *dvo_timing; |
||
354 | struct drm_display_mode *panel_fixed_mode; |
||
355 | int index; |
||
356 | |||
5060 | serge | 357 | index = i915.vbt_sdvo_panel_type; |
3031 | serge | 358 | if (index == -2) { |
359 | DRM_DEBUG_KMS("Ignore SDVO panel mode from BIOS VBT tables.\n"); |
||
360 | return; |
||
361 | } |
||
362 | |||
2351 | Serge | 363 | if (index == -1) { |
364 | struct bdb_sdvo_lvds_options *sdvo_lvds_options; |
||
365 | |||
366 | sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); |
||
367 | if (!sdvo_lvds_options) |
||
368 | return; |
||
369 | |||
370 | index = sdvo_lvds_options->panel_type; |
||
371 | } |
||
372 | |||
373 | dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS); |
||
374 | if (!dvo_timing) |
||
375 | return; |
||
376 | |||
377 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); |
||
378 | if (!panel_fixed_mode) |
||
379 | return; |
||
380 | |||
381 | fill_detail_timing_data(panel_fixed_mode, dvo_timing + index); |
||
382 | |||
4104 | Serge | 383 | dev_priv->vbt.sdvo_lvds_vbt_mode = panel_fixed_mode; |
2351 | Serge | 384 | |
385 | DRM_DEBUG_KMS("Found SDVO panel mode in BIOS VBT tables:\n"); |
||
386 | drm_mode_debug_printmodeline(panel_fixed_mode); |
||
387 | } |
||
388 | |||
389 | static int intel_bios_ssc_frequency(struct drm_device *dev, |
||
390 | bool alternate) |
||
391 | { |
||
392 | switch (INTEL_INFO(dev)->gen) { |
||
393 | case 2: |
||
4560 | Serge | 394 | return alternate ? 66667 : 48000; |
2351 | Serge | 395 | case 3: |
396 | case 4: |
||
4560 | Serge | 397 | return alternate ? 100000 : 96000; |
2351 | Serge | 398 | default: |
4560 | Serge | 399 | return alternate ? 100000 : 120000; |
2351 | Serge | 400 | } |
401 | } |
||
402 | |||
403 | static void |
||
404 | parse_general_features(struct drm_i915_private *dev_priv, |
||
405 | struct bdb_header *bdb) |
||
406 | { |
||
407 | struct drm_device *dev = dev_priv->dev; |
||
408 | struct bdb_general_features *general; |
||
409 | |||
410 | general = find_section(bdb, BDB_GENERAL_FEATURES); |
||
411 | if (general) { |
||
4104 | Serge | 412 | dev_priv->vbt.int_tv_support = general->int_tv_support; |
413 | dev_priv->vbt.int_crt_support = general->int_crt_support; |
||
414 | dev_priv->vbt.lvds_use_ssc = general->enable_ssc; |
||
415 | dev_priv->vbt.lvds_ssc_freq = |
||
2351 | Serge | 416 | intel_bios_ssc_frequency(dev, general->ssc_freq); |
4104 | Serge | 417 | dev_priv->vbt.display_clock_mode = general->display_clock_mode; |
418 | dev_priv->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted; |
||
3746 | Serge | 419 | DRM_DEBUG_KMS("BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n", |
4104 | Serge | 420 | dev_priv->vbt.int_tv_support, |
421 | dev_priv->vbt.int_crt_support, |
||
422 | dev_priv->vbt.lvds_use_ssc, |
||
423 | dev_priv->vbt.lvds_ssc_freq, |
||
424 | dev_priv->vbt.display_clock_mode, |
||
425 | dev_priv->vbt.fdi_rx_polarity_inverted); |
||
2351 | Serge | 426 | } |
427 | } |
||
428 | |||
429 | static void |
||
430 | parse_general_definitions(struct drm_i915_private *dev_priv, |
||
431 | struct bdb_header *bdb) |
||
432 | { |
||
433 | struct bdb_general_definitions *general; |
||
434 | |||
435 | general = find_section(bdb, BDB_GENERAL_DEFINITIONS); |
||
436 | if (general) { |
||
437 | u16 block_size = get_blocksize(general); |
||
438 | if (block_size >= sizeof(*general)) { |
||
439 | int bus_pin = general->crt_ddc_gmbus_pin; |
||
440 | DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); |
||
3031 | serge | 441 | if (intel_gmbus_is_port_valid(bus_pin)) |
4104 | Serge | 442 | dev_priv->vbt.crt_ddc_pin = bus_pin; |
2351 | Serge | 443 | } else { |
444 | DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", |
||
445 | block_size); |
||
446 | } |
||
447 | } |
||
448 | } |
||
449 | |||
450 | static void |
||
451 | parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, |
||
452 | struct bdb_header *bdb) |
||
453 | { |
||
454 | struct sdvo_device_mapping *p_mapping; |
||
455 | struct bdb_general_definitions *p_defs; |
||
4560 | Serge | 456 | union child_device_config *p_child; |
2351 | Serge | 457 | int i, child_device_num, count; |
458 | u16 block_size; |
||
459 | |||
460 | p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); |
||
461 | if (!p_defs) { |
||
462 | DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n"); |
||
463 | return; |
||
464 | } |
||
465 | /* judge whether the size of child device meets the requirements. |
||
466 | * If the child device size obtained from general definition block |
||
467 | * is different with sizeof(struct child_device_config), skip the |
||
468 | * parsing of sdvo device info |
||
469 | */ |
||
470 | if (p_defs->child_dev_size != sizeof(*p_child)) { |
||
471 | /* different child dev size . Ignore it */ |
||
472 | DRM_DEBUG_KMS("different child size is found. Invalid.\n"); |
||
473 | return; |
||
474 | } |
||
475 | /* get the block size of general definitions */ |
||
476 | block_size = get_blocksize(p_defs); |
||
477 | /* get the number of child device */ |
||
478 | child_device_num = (block_size - sizeof(*p_defs)) / |
||
479 | sizeof(*p_child); |
||
480 | count = 0; |
||
481 | for (i = 0; i < child_device_num; i++) { |
||
482 | p_child = &(p_defs->devices[i]); |
||
4560 | Serge | 483 | if (!p_child->old.device_type) { |
2351 | Serge | 484 | /* skip the device block if device type is invalid */ |
485 | continue; |
||
486 | } |
||
4560 | Serge | 487 | if (p_child->old.slave_addr != SLAVE_ADDR1 && |
488 | p_child->old.slave_addr != SLAVE_ADDR2) { |
||
2351 | Serge | 489 | /* |
490 | * If the slave address is neither 0x70 nor 0x72, |
||
491 | * it is not a SDVO device. Skip it. |
||
492 | */ |
||
493 | continue; |
||
494 | } |
||
4560 | Serge | 495 | if (p_child->old.dvo_port != DEVICE_PORT_DVOB && |
496 | p_child->old.dvo_port != DEVICE_PORT_DVOC) { |
||
2351 | Serge | 497 | /* skip the incorrect SDVO port */ |
498 | DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n"); |
||
499 | continue; |
||
500 | } |
||
501 | DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on" |
||
502 | " %s port\n", |
||
4560 | Serge | 503 | p_child->old.slave_addr, |
504 | (p_child->old.dvo_port == DEVICE_PORT_DVOB) ? |
||
2351 | Serge | 505 | "SDVOB" : "SDVOC"); |
4560 | Serge | 506 | p_mapping = &(dev_priv->sdvo_mappings[p_child->old.dvo_port - 1]); |
2351 | Serge | 507 | if (!p_mapping->initialized) { |
4560 | Serge | 508 | p_mapping->dvo_port = p_child->old.dvo_port; |
509 | p_mapping->slave_addr = p_child->old.slave_addr; |
||
510 | p_mapping->dvo_wiring = p_child->old.dvo_wiring; |
||
511 | p_mapping->ddc_pin = p_child->old.ddc_pin; |
||
512 | p_mapping->i2c_pin = p_child->old.i2c_pin; |
||
2351 | Serge | 513 | p_mapping->initialized = 1; |
514 | DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n", |
||
515 | p_mapping->dvo_port, |
||
516 | p_mapping->slave_addr, |
||
517 | p_mapping->dvo_wiring, |
||
518 | p_mapping->ddc_pin, |
||
519 | p_mapping->i2c_pin); |
||
520 | } else { |
||
521 | DRM_DEBUG_KMS("Maybe one SDVO port is shared by " |
||
522 | "two SDVO device.\n"); |
||
523 | } |
||
4560 | Serge | 524 | if (p_child->old.slave2_addr) { |
2351 | Serge | 525 | /* Maybe this is a SDVO device with multiple inputs */ |
526 | /* And the mapping info is not added */ |
||
527 | DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this" |
||
528 | " is a SDVO device with multiple inputs.\n"); |
||
529 | } |
||
530 | count++; |
||
531 | } |
||
532 | |||
533 | if (!count) { |
||
534 | /* No SDVO device info is found */ |
||
535 | DRM_DEBUG_KMS("No SDVO device info is found in VBT\n"); |
||
536 | } |
||
537 | return; |
||
538 | } |
||
539 | |||
540 | static void |
||
541 | parse_driver_features(struct drm_i915_private *dev_priv, |
||
542 | struct bdb_header *bdb) |
||
543 | { |
||
544 | struct bdb_driver_features *driver; |
||
545 | |||
546 | driver = find_section(bdb, BDB_DRIVER_FEATURES); |
||
547 | if (!driver) |
||
548 | return; |
||
549 | |||
4560 | Serge | 550 | if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP) |
4104 | Serge | 551 | dev_priv->vbt.edp_support = 1; |
2351 | Serge | 552 | |
553 | if (driver->dual_frequency) |
||
554 | dev_priv->render_reclock_avail = true; |
||
5060 | serge | 555 | |
556 | DRM_DEBUG_KMS("DRRS State Enabled:%d\n", driver->drrs_enabled); |
||
557 | /* |
||
558 | * If DRRS is not supported, drrs_type has to be set to 0. |
||
559 | * This is because, VBT is configured in such a way that |
||
560 | * static DRRS is 0 and DRRS not supported is represented by |
||
561 | * driver->drrs_enabled=false |
||
562 | */ |
||
563 | if (!driver->drrs_enabled) |
||
564 | dev_priv->vbt.drrs_type = DRRS_NOT_SUPPORTED; |
||
2351 | Serge | 565 | } |
566 | |||
567 | static void |
||
568 | parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) |
||
569 | { |
||
570 | struct bdb_edp *edp; |
||
571 | struct edp_power_seq *edp_pps; |
||
572 | struct edp_link_params *edp_link_params; |
||
573 | |||
574 | edp = find_section(bdb, BDB_EDP); |
||
575 | if (!edp) { |
||
4560 | Serge | 576 | if (dev_priv->vbt.edp_support) |
3120 | serge | 577 | DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n"); |
2351 | Serge | 578 | return; |
579 | } |
||
580 | |||
581 | switch ((edp->color_depth >> (panel_type * 2)) & 3) { |
||
582 | case EDP_18BPP: |
||
4104 | Serge | 583 | dev_priv->vbt.edp_bpp = 18; |
2351 | Serge | 584 | break; |
585 | case EDP_24BPP: |
||
4104 | Serge | 586 | dev_priv->vbt.edp_bpp = 24; |
2351 | Serge | 587 | break; |
588 | case EDP_30BPP: |
||
4104 | Serge | 589 | dev_priv->vbt.edp_bpp = 30; |
2351 | Serge | 590 | break; |
591 | } |
||
592 | |||
593 | /* Get the eDP sequencing and link info */ |
||
594 | edp_pps = &edp->power_seqs[panel_type]; |
||
595 | edp_link_params = &edp->link_params[panel_type]; |
||
596 | |||
4104 | Serge | 597 | dev_priv->vbt.edp_pps = *edp_pps; |
2351 | Serge | 598 | |
5060 | serge | 599 | switch (edp_link_params->rate) { |
600 | case EDP_RATE_1_62: |
||
601 | dev_priv->vbt.edp_rate = DP_LINK_BW_1_62; |
||
602 | break; |
||
603 | case EDP_RATE_2_7: |
||
604 | dev_priv->vbt.edp_rate = DP_LINK_BW_2_7; |
||
605 | break; |
||
606 | default: |
||
607 | DRM_DEBUG_KMS("VBT has unknown eDP link rate value %u\n", |
||
608 | edp_link_params->rate); |
||
609 | break; |
||
610 | } |
||
611 | |||
2351 | Serge | 612 | switch (edp_link_params->lanes) { |
5060 | serge | 613 | case EDP_LANE_1: |
4104 | Serge | 614 | dev_priv->vbt.edp_lanes = 1; |
2351 | Serge | 615 | break; |
5060 | serge | 616 | case EDP_LANE_2: |
4104 | Serge | 617 | dev_priv->vbt.edp_lanes = 2; |
2351 | Serge | 618 | break; |
5060 | serge | 619 | case EDP_LANE_4: |
4104 | Serge | 620 | dev_priv->vbt.edp_lanes = 4; |
2351 | Serge | 621 | break; |
5060 | serge | 622 | default: |
623 | DRM_DEBUG_KMS("VBT has unknown eDP lane count value %u\n", |
||
624 | edp_link_params->lanes); |
||
625 | break; |
||
2351 | Serge | 626 | } |
5060 | serge | 627 | |
2351 | Serge | 628 | switch (edp_link_params->preemphasis) { |
5060 | serge | 629 | case EDP_PREEMPHASIS_NONE: |
5354 | serge | 630 | dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_0; |
2351 | Serge | 631 | break; |
5060 | serge | 632 | case EDP_PREEMPHASIS_3_5dB: |
5354 | serge | 633 | dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_1; |
2351 | Serge | 634 | break; |
5060 | serge | 635 | case EDP_PREEMPHASIS_6dB: |
5354 | serge | 636 | dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_2; |
2351 | Serge | 637 | break; |
5060 | serge | 638 | case EDP_PREEMPHASIS_9_5dB: |
5354 | serge | 639 | dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_3; |
2351 | Serge | 640 | break; |
5060 | serge | 641 | default: |
642 | DRM_DEBUG_KMS("VBT has unknown eDP pre-emphasis value %u\n", |
||
643 | edp_link_params->preemphasis); |
||
644 | break; |
||
2351 | Serge | 645 | } |
5060 | serge | 646 | |
2351 | Serge | 647 | switch (edp_link_params->vswing) { |
5060 | serge | 648 | case EDP_VSWING_0_4V: |
5354 | serge | 649 | dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_0; |
2351 | Serge | 650 | break; |
5060 | serge | 651 | case EDP_VSWING_0_6V: |
5354 | serge | 652 | dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_1; |
2351 | Serge | 653 | break; |
5060 | serge | 654 | case EDP_VSWING_0_8V: |
5354 | serge | 655 | dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_2; |
2351 | Serge | 656 | break; |
5060 | serge | 657 | case EDP_VSWING_1_2V: |
5354 | serge | 658 | dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_3; |
2351 | Serge | 659 | break; |
5060 | serge | 660 | default: |
661 | DRM_DEBUG_KMS("VBT has unknown eDP voltage swing value %u\n", |
||
662 | edp_link_params->vswing); |
||
663 | break; |
||
2351 | Serge | 664 | } |
665 | } |
||
666 | |||
5060 | serge | 667 | static u8 *goto_next_sequence(u8 *data, int *size) |
668 | { |
||
669 | u16 len; |
||
670 | int tmp = *size; |
||
671 | |||
672 | if (--tmp < 0) |
||
673 | return NULL; |
||
674 | |||
675 | /* goto first element */ |
||
676 | data++; |
||
677 | while (1) { |
||
678 | switch (*data) { |
||
679 | case MIPI_SEQ_ELEM_SEND_PKT: |
||
680 | /* |
||
681 | * skip by this element payload size |
||
682 | * skip elem id, command flag and data type |
||
683 | */ |
||
684 | tmp -= 5; |
||
685 | if (tmp < 0) |
||
686 | return NULL; |
||
687 | |||
688 | data += 3; |
||
689 | len = *((u16 *)data); |
||
690 | |||
691 | tmp -= len; |
||
692 | if (tmp < 0) |
||
693 | return NULL; |
||
694 | |||
695 | /* skip by len */ |
||
696 | data = data + 2 + len; |
||
697 | break; |
||
698 | case MIPI_SEQ_ELEM_DELAY: |
||
699 | /* skip by elem id, and delay is 4 bytes */ |
||
700 | tmp -= 5; |
||
701 | if (tmp < 0) |
||
702 | return NULL; |
||
703 | |||
704 | data += 5; |
||
705 | break; |
||
706 | case MIPI_SEQ_ELEM_GPIO: |
||
707 | tmp -= 3; |
||
708 | if (tmp < 0) |
||
709 | return NULL; |
||
710 | |||
711 | data += 3; |
||
712 | break; |
||
713 | default: |
||
714 | DRM_ERROR("Unknown element\n"); |
||
715 | return NULL; |
||
716 | } |
||
717 | |||
718 | /* end of sequence ? */ |
||
719 | if (*data == 0) |
||
720 | break; |
||
721 | } |
||
722 | |||
723 | /* goto next sequence or end of block byte */ |
||
724 | if (--tmp < 0) |
||
725 | return NULL; |
||
726 | |||
727 | data++; |
||
728 | |||
729 | /* update amount of data left for the sequence block to be parsed */ |
||
730 | *size = tmp; |
||
731 | return data; |
||
732 | } |
||
733 | |||
2351 | Serge | 734 | static void |
4560 | Serge | 735 | parse_mipi(struct drm_i915_private *dev_priv, struct bdb_header *bdb) |
736 | { |
||
5060 | serge | 737 | struct bdb_mipi_config *start; |
738 | struct bdb_mipi_sequence *sequence; |
||
739 | struct mipi_config *config; |
||
740 | struct mipi_pps_data *pps; |
||
741 | u8 *data, *seq_data; |
||
742 | int i, panel_id, seq_size; |
||
743 | u16 block_size; |
||
4560 | Serge | 744 | |
5060 | serge | 745 | /* parse MIPI blocks only if LFP type is MIPI */ |
746 | if (!dev_priv->vbt.has_mipi) |
||
4560 | Serge | 747 | return; |
5060 | serge | 748 | |
749 | /* Initialize this to undefined indicating no generic MIPI support */ |
||
750 | dev_priv->vbt.dsi.panel_id = MIPI_DSI_UNDEFINED_PANEL_ID; |
||
751 | |||
752 | /* Block #40 is already parsed and panel_fixed_mode is |
||
753 | * stored in dev_priv->lfp_lvds_vbt_mode |
||
754 | * resuse this when needed |
||
755 | */ |
||
756 | |||
757 | /* Parse #52 for panel index used from panel_type already |
||
758 | * parsed |
||
759 | */ |
||
760 | start = find_section(bdb, BDB_MIPI_CONFIG); |
||
761 | if (!start) { |
||
762 | DRM_DEBUG_KMS("No MIPI config BDB found"); |
||
763 | return; |
||
4560 | Serge | 764 | } |
765 | |||
5060 | serge | 766 | DRM_DEBUG_DRIVER("Found MIPI Config block, panel index = %d\n", |
767 | panel_type); |
||
768 | |||
769 | /* |
||
770 | * get hold of the correct configuration block and pps data as per |
||
771 | * the panel_type as index |
||
772 | */ |
||
773 | config = &start->config[panel_type]; |
||
774 | pps = &start->pps[panel_type]; |
||
775 | |||
776 | /* store as of now full data. Trim when we realise all is not needed */ |
||
777 | dev_priv->vbt.dsi.config = kmemdup(config, sizeof(struct mipi_config), GFP_KERNEL); |
||
778 | if (!dev_priv->vbt.dsi.config) |
||
779 | return; |
||
780 | |||
781 | dev_priv->vbt.dsi.pps = kmemdup(pps, sizeof(struct mipi_pps_data), GFP_KERNEL); |
||
782 | if (!dev_priv->vbt.dsi.pps) { |
||
783 | kfree(dev_priv->vbt.dsi.config); |
||
784 | return; |
||
785 | } |
||
786 | |||
787 | /* We have mandatory mipi config blocks. Initialize as generic panel */ |
||
788 | dev_priv->vbt.dsi.panel_id = MIPI_DSI_GENERIC_PANEL_ID; |
||
789 | |||
790 | /* Check if we have sequence block as well */ |
||
791 | sequence = find_section(bdb, BDB_MIPI_SEQUENCE); |
||
792 | if (!sequence) { |
||
793 | DRM_DEBUG_KMS("No MIPI Sequence found, parsing complete\n"); |
||
794 | return; |
||
795 | } |
||
796 | |||
797 | DRM_DEBUG_DRIVER("Found MIPI sequence block\n"); |
||
798 | |||
799 | block_size = get_blocksize(sequence); |
||
800 | |||
801 | /* |
||
802 | * parse the sequence block for individual sequences |
||
803 | */ |
||
804 | dev_priv->vbt.dsi.seq_version = sequence->version; |
||
805 | |||
806 | seq_data = &sequence->data[0]; |
||
807 | |||
808 | /* |
||
809 | * sequence block is variable length and hence we need to parse and |
||
810 | * get the sequence data for specific panel id |
||
811 | */ |
||
812 | for (i = 0; i < MAX_MIPI_CONFIGURATIONS; i++) { |
||
813 | panel_id = *seq_data; |
||
814 | seq_size = *((u16 *) (seq_data + 1)); |
||
815 | if (panel_id == panel_type) |
||
816 | break; |
||
817 | |||
818 | /* skip the sequence including seq header of 3 bytes */ |
||
819 | seq_data = seq_data + 3 + seq_size; |
||
820 | if ((seq_data - &sequence->data[0]) > block_size) { |
||
821 | DRM_ERROR("Sequence start is beyond sequence block size, corrupted sequence block\n"); |
||
822 | return; |
||
823 | } |
||
824 | } |
||
825 | |||
826 | if (i == MAX_MIPI_CONFIGURATIONS) { |
||
827 | DRM_ERROR("Sequence block detected but no valid configuration\n"); |
||
828 | return; |
||
829 | } |
||
830 | |||
831 | /* check if found sequence is completely within the sequence block |
||
832 | * just being paranoid */ |
||
833 | if (seq_size > block_size) { |
||
834 | DRM_ERROR("Corrupted sequence/size, bailing out\n"); |
||
835 | return; |
||
836 | } |
||
837 | |||
838 | /* skip the panel id(1 byte) and seq size(2 bytes) */ |
||
839 | dev_priv->vbt.dsi.data = kmemdup(seq_data + 3, seq_size, GFP_KERNEL); |
||
840 | if (!dev_priv->vbt.dsi.data) |
||
841 | return; |
||
842 | |||
843 | /* |
||
844 | * loop into the sequence data and split into multiple sequneces |
||
845 | * There are only 5 types of sequences as of now |
||
846 | */ |
||
847 | data = dev_priv->vbt.dsi.data; |
||
848 | dev_priv->vbt.dsi.size = seq_size; |
||
849 | |||
850 | /* two consecutive 0x00 indicate end of all sequences */ |
||
851 | while (1) { |
||
852 | int seq_id = *data; |
||
853 | if (MIPI_SEQ_MAX > seq_id && seq_id > MIPI_SEQ_UNDEFINED) { |
||
854 | dev_priv->vbt.dsi.sequence[seq_id] = data; |
||
855 | DRM_DEBUG_DRIVER("Found mipi sequence - %d\n", seq_id); |
||
856 | } else { |
||
857 | DRM_ERROR("undefined sequence\n"); |
||
858 | goto err; |
||
859 | } |
||
860 | |||
861 | /* partial parsing to skip elements */ |
||
862 | data = goto_next_sequence(data, &seq_size); |
||
863 | |||
864 | if (data == NULL) { |
||
865 | DRM_ERROR("Sequence elements going beyond block itself. Sequence block parsing failed\n"); |
||
866 | goto err; |
||
867 | } |
||
868 | |||
869 | if (*data == 0) |
||
870 | break; /* end of sequence reached */ |
||
871 | } |
||
872 | |||
873 | DRM_DEBUG_DRIVER("MIPI related vbt parsing complete\n"); |
||
874 | return; |
||
875 | err: |
||
876 | kfree(dev_priv->vbt.dsi.data); |
||
877 | dev_priv->vbt.dsi.data = NULL; |
||
878 | |||
879 | /* error during parsing so set all pointers to null |
||
880 | * because of partial parsing */ |
||
881 | memset(dev_priv->vbt.dsi.sequence, 0, sizeof(dev_priv->vbt.dsi.sequence)); |
||
4560 | Serge | 882 | } |
883 | |||
884 | static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, |
||
885 | struct bdb_header *bdb) |
||
886 | { |
||
887 | union child_device_config *it, *child = NULL; |
||
888 | struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port]; |
||
889 | uint8_t hdmi_level_shift; |
||
890 | int i, j; |
||
891 | bool is_dvi, is_hdmi, is_dp, is_edp, is_crt; |
||
892 | uint8_t aux_channel; |
||
893 | /* Each DDI port can have more than one value on the "DVO Port" field, |
||
894 | * so look for all the possible values for each port and abort if more |
||
895 | * than one is found. */ |
||
896 | int dvo_ports[][2] = { |
||
897 | {DVO_PORT_HDMIA, DVO_PORT_DPA}, |
||
898 | {DVO_PORT_HDMIB, DVO_PORT_DPB}, |
||
899 | {DVO_PORT_HDMIC, DVO_PORT_DPC}, |
||
900 | {DVO_PORT_HDMID, DVO_PORT_DPD}, |
||
901 | {DVO_PORT_CRT, -1 /* Port E can only be DVO_PORT_CRT */ }, |
||
902 | }; |
||
903 | |||
904 | /* Find the child device to use, abort if more than one found. */ |
||
905 | for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { |
||
906 | it = dev_priv->vbt.child_dev + i; |
||
907 | |||
908 | for (j = 0; j < 2; j++) { |
||
909 | if (dvo_ports[port][j] == -1) |
||
910 | break; |
||
911 | |||
912 | if (it->common.dvo_port == dvo_ports[port][j]) { |
||
913 | if (child) { |
||
914 | DRM_DEBUG_KMS("More than one child device for port %c in VBT.\n", |
||
915 | port_name(port)); |
||
916 | return; |
||
917 | } |
||
918 | child = it; |
||
919 | } |
||
920 | } |
||
921 | } |
||
922 | if (!child) |
||
923 | return; |
||
924 | |||
925 | aux_channel = child->raw[25]; |
||
926 | |||
927 | is_dvi = child->common.device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING; |
||
928 | is_dp = child->common.device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT; |
||
929 | is_crt = child->common.device_type & DEVICE_TYPE_ANALOG_OUTPUT; |
||
930 | is_hdmi = is_dvi && (child->common.device_type & DEVICE_TYPE_NOT_HDMI_OUTPUT) == 0; |
||
931 | is_edp = is_dp && (child->common.device_type & DEVICE_TYPE_INTERNAL_CONNECTOR); |
||
932 | |||
933 | info->supports_dvi = is_dvi; |
||
934 | info->supports_hdmi = is_hdmi; |
||
935 | info->supports_dp = is_dp; |
||
936 | |||
937 | DRM_DEBUG_KMS("Port %c VBT info: DP:%d HDMI:%d DVI:%d EDP:%d CRT:%d\n", |
||
938 | port_name(port), is_dp, is_hdmi, is_dvi, is_edp, is_crt); |
||
939 | |||
940 | if (is_edp && is_dvi) |
||
941 | DRM_DEBUG_KMS("Internal DP port %c is TMDS compatible\n", |
||
942 | port_name(port)); |
||
943 | if (is_crt && port != PORT_E) |
||
944 | DRM_DEBUG_KMS("Port %c is analog\n", port_name(port)); |
||
945 | if (is_crt && (is_dvi || is_dp)) |
||
946 | DRM_DEBUG_KMS("Analog port %c is also DP or TMDS compatible\n", |
||
947 | port_name(port)); |
||
948 | if (is_dvi && (port == PORT_A || port == PORT_E)) |
||
5354 | serge | 949 | DRM_DEBUG_KMS("Port %c is TMDS compatible\n", port_name(port)); |
4560 | Serge | 950 | if (!is_dvi && !is_dp && !is_crt) |
951 | DRM_DEBUG_KMS("Port %c is not DP/TMDS/CRT compatible\n", |
||
952 | port_name(port)); |
||
953 | if (is_edp && (port == PORT_B || port == PORT_C || port == PORT_E)) |
||
954 | DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port)); |
||
955 | |||
956 | if (is_dvi) { |
||
957 | if (child->common.ddc_pin == 0x05 && port != PORT_B) |
||
958 | DRM_DEBUG_KMS("Unexpected DDC pin for port B\n"); |
||
959 | if (child->common.ddc_pin == 0x04 && port != PORT_C) |
||
960 | DRM_DEBUG_KMS("Unexpected DDC pin for port C\n"); |
||
961 | if (child->common.ddc_pin == 0x06 && port != PORT_D) |
||
962 | DRM_DEBUG_KMS("Unexpected DDC pin for port D\n"); |
||
963 | } |
||
964 | |||
965 | if (is_dp) { |
||
966 | if (aux_channel == 0x40 && port != PORT_A) |
||
967 | DRM_DEBUG_KMS("Unexpected AUX channel for port A\n"); |
||
968 | if (aux_channel == 0x10 && port != PORT_B) |
||
969 | DRM_DEBUG_KMS("Unexpected AUX channel for port B\n"); |
||
970 | if (aux_channel == 0x20 && port != PORT_C) |
||
971 | DRM_DEBUG_KMS("Unexpected AUX channel for port C\n"); |
||
972 | if (aux_channel == 0x30 && port != PORT_D) |
||
973 | DRM_DEBUG_KMS("Unexpected AUX channel for port D\n"); |
||
974 | } |
||
975 | |||
976 | if (bdb->version >= 158) { |
||
977 | /* The VBT HDMI level shift values match the table we have. */ |
||
978 | hdmi_level_shift = child->raw[7] & 0xF; |
||
979 | DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n", |
||
980 | port_name(port), |
||
981 | hdmi_level_shift); |
||
982 | info->hdmi_level_shift = hdmi_level_shift; |
||
983 | } |
||
984 | } |
||
985 | |||
986 | static void parse_ddi_ports(struct drm_i915_private *dev_priv, |
||
987 | struct bdb_header *bdb) |
||
988 | { |
||
989 | struct drm_device *dev = dev_priv->dev; |
||
990 | enum port port; |
||
991 | |||
992 | if (!HAS_DDI(dev)) |
||
993 | return; |
||
994 | |||
995 | if (!dev_priv->vbt.child_dev_num) |
||
996 | return; |
||
997 | |||
998 | if (bdb->version < 155) |
||
999 | return; |
||
1000 | |||
1001 | for (port = PORT_A; port < I915_MAX_PORTS; port++) |
||
1002 | parse_ddi_port(dev_priv, port, bdb); |
||
1003 | } |
||
1004 | |||
1005 | static void |
||
2351 | Serge | 1006 | parse_device_mapping(struct drm_i915_private *dev_priv, |
1007 | struct bdb_header *bdb) |
||
1008 | { |
||
1009 | struct bdb_general_definitions *p_defs; |
||
4560 | Serge | 1010 | union child_device_config *p_child, *child_dev_ptr; |
2351 | Serge | 1011 | int i, child_device_num, count; |
1012 | u16 block_size; |
||
1013 | |||
1014 | p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); |
||
1015 | if (!p_defs) { |
||
1016 | DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n"); |
||
1017 | return; |
||
1018 | } |
||
1019 | /* judge whether the size of child device meets the requirements. |
||
1020 | * If the child device size obtained from general definition block |
||
1021 | * is different with sizeof(struct child_device_config), skip the |
||
1022 | * parsing of sdvo device info |
||
1023 | */ |
||
1024 | if (p_defs->child_dev_size != sizeof(*p_child)) { |
||
1025 | /* different child dev size . Ignore it */ |
||
1026 | DRM_DEBUG_KMS("different child size is found. Invalid.\n"); |
||
1027 | return; |
||
1028 | } |
||
1029 | /* get the block size of general definitions */ |
||
1030 | block_size = get_blocksize(p_defs); |
||
1031 | /* get the number of child device */ |
||
1032 | child_device_num = (block_size - sizeof(*p_defs)) / |
||
1033 | sizeof(*p_child); |
||
1034 | count = 0; |
||
1035 | /* get the number of child device that is present */ |
||
1036 | for (i = 0; i < child_device_num; i++) { |
||
1037 | p_child = &(p_defs->devices[i]); |
||
4560 | Serge | 1038 | if (!p_child->common.device_type) { |
2351 | Serge | 1039 | /* skip the device block if device type is invalid */ |
1040 | continue; |
||
1041 | } |
||
1042 | count++; |
||
1043 | } |
||
1044 | if (!count) { |
||
1045 | DRM_DEBUG_KMS("no child dev is parsed from VBT\n"); |
||
1046 | return; |
||
1047 | } |
||
4104 | Serge | 1048 | dev_priv->vbt.child_dev = kcalloc(count, sizeof(*p_child), GFP_KERNEL); |
1049 | if (!dev_priv->vbt.child_dev) { |
||
2351 | Serge | 1050 | DRM_DEBUG_KMS("No memory space for child device\n"); |
1051 | return; |
||
1052 | } |
||
1053 | |||
4104 | Serge | 1054 | dev_priv->vbt.child_dev_num = count; |
2351 | Serge | 1055 | count = 0; |
1056 | for (i = 0; i < child_device_num; i++) { |
||
1057 | p_child = &(p_defs->devices[i]); |
||
4560 | Serge | 1058 | if (!p_child->common.device_type) { |
2351 | Serge | 1059 | /* skip the device block if device type is invalid */ |
1060 | continue; |
||
1061 | } |
||
5060 | serge | 1062 | |
1063 | if (p_child->common.dvo_port >= DVO_PORT_MIPIA |
||
1064 | && p_child->common.dvo_port <= DVO_PORT_MIPID |
||
1065 | &&p_child->common.device_type & DEVICE_TYPE_MIPI_OUTPUT) { |
||
1066 | DRM_DEBUG_KMS("Found MIPI as LFP\n"); |
||
1067 | dev_priv->vbt.has_mipi = 1; |
||
1068 | dev_priv->vbt.dsi.port = p_child->common.dvo_port; |
||
1069 | } |
||
1070 | |||
4104 | Serge | 1071 | child_dev_ptr = dev_priv->vbt.child_dev + count; |
2351 | Serge | 1072 | count++; |
1073 | memcpy((void *)child_dev_ptr, (void *)p_child, |
||
1074 | sizeof(*p_child)); |
||
1075 | } |
||
1076 | return; |
||
1077 | } |
||
1078 | |||
1079 | static void |
||
1080 | init_vbt_defaults(struct drm_i915_private *dev_priv) |
||
1081 | { |
||
1082 | struct drm_device *dev = dev_priv->dev; |
||
4560 | Serge | 1083 | enum port port; |
2351 | Serge | 1084 | |
4104 | Serge | 1085 | dev_priv->vbt.crt_ddc_pin = GMBUS_PORT_VGADDC; |
2351 | Serge | 1086 | |
5060 | serge | 1087 | /* Default to having backlight */ |
1088 | dev_priv->vbt.backlight.present = true; |
||
1089 | |||
2351 | Serge | 1090 | /* LFP panel data */ |
4104 | Serge | 1091 | dev_priv->vbt.lvds_dither = 1; |
1092 | dev_priv->vbt.lvds_vbt = 0; |
||
2351 | Serge | 1093 | |
1094 | /* SDVO panel data */ |
||
4104 | Serge | 1095 | dev_priv->vbt.sdvo_lvds_vbt_mode = NULL; |
2351 | Serge | 1096 | |
1097 | /* general features */ |
||
4104 | Serge | 1098 | dev_priv->vbt.int_tv_support = 1; |
1099 | dev_priv->vbt.int_crt_support = 1; |
||
2351 | Serge | 1100 | |
1101 | /* Default to using SSC */ |
||
4104 | Serge | 1102 | dev_priv->vbt.lvds_use_ssc = 1; |
4560 | Serge | 1103 | /* |
1104 | * Core/SandyBridge/IvyBridge use alternative (120MHz) reference |
||
1105 | * clock for LVDS. |
||
1106 | */ |
||
1107 | dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev, |
||
1108 | !HAS_PCH_SPLIT(dev)); |
||
1109 | DRM_DEBUG_KMS("Set default to SSC at %d kHz\n", dev_priv->vbt.lvds_ssc_freq); |
||
1110 | |||
1111 | for (port = PORT_A; port < I915_MAX_PORTS; port++) { |
||
1112 | struct ddi_vbt_port_info *info = |
||
1113 | &dev_priv->vbt.ddi_port_info[port]; |
||
1114 | |||
5354 | serge | 1115 | info->hdmi_level_shift = HDMI_LEVEL_SHIFT_UNKNOWN; |
4560 | Serge | 1116 | |
1117 | info->supports_dvi = (port != PORT_A && port != PORT_E); |
||
1118 | info->supports_hdmi = info->supports_dvi; |
||
1119 | info->supports_dp = (port != PORT_E); |
||
1120 | } |
||
2351 | Serge | 1121 | } |
1122 | |||
5097 | serge | 1123 | static int intel_no_opregion_vbt_callback(const struct dmi_system_id *id) |
1124 | { |
||
1125 | DRM_DEBUG_KMS("Falling back to manually reading VBT from " |
||
1126 | "VBIOS ROM for %s\n", |
||
1127 | id->ident); |
||
1128 | return 1; |
||
1129 | } |
||
1130 | |||
1131 | static const struct dmi_system_id intel_no_opregion_vbt[] = { |
||
1132 | { |
||
1133 | .callback = intel_no_opregion_vbt_callback, |
||
1134 | .ident = "ThinkCentre A57", |
||
1135 | .matches = { |
||
1136 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
||
1137 | DMI_MATCH(DMI_PRODUCT_NAME, "97027RG"), |
||
1138 | }, |
||
1139 | }, |
||
1140 | { } |
||
1141 | }; |
||
1142 | |||
5060 | serge | 1143 | static struct bdb_header *validate_vbt(char *base, size_t size, |
1144 | struct vbt_header *vbt, |
||
1145 | const char *source) |
||
1146 | { |
||
1147 | size_t offset; |
||
1148 | struct bdb_header *bdb; |
||
3120 | serge | 1149 | |
5060 | serge | 1150 | if (vbt == NULL) { |
1151 | DRM_DEBUG_DRIVER("VBT signature missing\n"); |
||
1152 | return NULL; |
||
1153 | } |
||
1154 | |||
1155 | offset = (char *)vbt - base; |
||
1156 | if (offset + sizeof(struct vbt_header) > size) { |
||
1157 | DRM_DEBUG_DRIVER("VBT header incomplete\n"); |
||
1158 | return NULL; |
||
1159 | } |
||
1160 | |||
1161 | if (memcmp(vbt->signature, "$VBT", 4)) { |
||
1162 | DRM_DEBUG_DRIVER("VBT invalid signature\n"); |
||
1163 | return NULL; |
||
1164 | } |
||
1165 | |||
1166 | offset += vbt->bdb_offset; |
||
1167 | if (offset + sizeof(struct bdb_header) > size) { |
||
1168 | DRM_DEBUG_DRIVER("BDB header incomplete\n"); |
||
1169 | return NULL; |
||
1170 | } |
||
1171 | |||
1172 | bdb = (struct bdb_header *)(base + offset); |
||
1173 | if (offset + bdb->bdb_size > size) { |
||
1174 | DRM_DEBUG_DRIVER("BDB incomplete\n"); |
||
1175 | return NULL; |
||
1176 | } |
||
1177 | |||
1178 | DRM_DEBUG_KMS("Using VBT from %s: %20s\n", |
||
1179 | source, vbt->signature); |
||
1180 | return bdb; |
||
1181 | } |
||
1182 | |||
2351 | Serge | 1183 | /** |
1184 | * intel_parse_bios - find VBT and initialize settings from the BIOS |
||
1185 | * @dev: DRM device |
||
1186 | * |
||
1187 | * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers |
||
1188 | * to appropriate values. |
||
1189 | * |
||
1190 | * Returns 0 on success, nonzero on failure. |
||
1191 | */ |
||
3031 | serge | 1192 | int |
2351 | Serge | 1193 | intel_parse_bios(struct drm_device *dev) |
1194 | { |
||
1195 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
1196 | struct pci_dev *pdev = dev->pdev; |
||
1197 | struct bdb_header *bdb = NULL; |
||
1198 | u8 __iomem *bios = NULL; |
||
1199 | |||
3746 | Serge | 1200 | if (HAS_PCH_NOP(dev)) |
1201 | return -ENODEV; |
||
1202 | |||
2351 | Serge | 1203 | init_vbt_defaults(dev_priv); |
1204 | |||
1205 | /* XXX Should this validation be moved to intel_opregion.c? */ |
||
5097 | serge | 1206 | if (!dmi_check_system(intel_no_opregion_vbt) && dev_priv->opregion.vbt) |
5060 | serge | 1207 | bdb = validate_vbt((char *)dev_priv->opregion.header, OPREGION_SIZE, |
1208 | (struct vbt_header *)dev_priv->opregion.vbt, |
||
1209 | "OpRegion"); |
||
2351 | Serge | 1210 | |
1211 | if (bdb == NULL) { |
||
5060 | serge | 1212 | size_t i, size; |
2351 | Serge | 1213 | |
2360 | Serge | 1214 | bios = pci_map_rom(pdev, &size); |
2351 | Serge | 1215 | if (!bios) |
1216 | return -1; |
||
1217 | |||
1218 | /* Scour memory looking for the VBT signature */ |
||
1219 | for (i = 0; i + 4 < size; i++) { |
||
5060 | serge | 1220 | if (memcmp(bios + i, "$VBT", 4) == 0) { |
1221 | bdb = validate_vbt(bios, size, |
||
1222 | (struct vbt_header *)(bios + i), |
||
1223 | "PCI ROM"); |
||
2351 | Serge | 1224 | break; |
1225 | } |
||
1226 | } |
||
1227 | |||
5060 | serge | 1228 | if (!bdb) { |
2351 | Serge | 1229 | pci_unmap_rom(pdev, bios); |
1230 | return -1; |
||
1231 | } |
||
1232 | } |
||
1233 | |||
1234 | /* Grab useful general definitions */ |
||
1235 | parse_general_features(dev_priv, bdb); |
||
1236 | parse_general_definitions(dev_priv, bdb); |
||
1237 | parse_lfp_panel_data(dev_priv, bdb); |
||
4560 | Serge | 1238 | parse_lfp_backlight(dev_priv, bdb); |
2351 | Serge | 1239 | parse_sdvo_panel_data(dev_priv, bdb); |
1240 | parse_sdvo_device_mapping(dev_priv, bdb); |
||
1241 | parse_device_mapping(dev_priv, bdb); |
||
1242 | parse_driver_features(dev_priv, bdb); |
||
1243 | parse_edp(dev_priv, bdb); |
||
4560 | Serge | 1244 | parse_mipi(dev_priv, bdb); |
1245 | parse_ddi_ports(dev_priv, bdb); |
||
2351 | Serge | 1246 | |
1247 | if (bios) |
||
1248 | pci_unmap_rom(pdev, bios); |
||
1249 | |||
1250 | return 0; |
||
1251 | } |
||
1252 | |||
1253 | /* Ensure that vital registers have been initialised, even if the BIOS |
||
1254 | * is absent or just failing to do its job. |
||
1255 | */ |
||
1256 | void intel_setup_bios(struct drm_device *dev) |
||
1257 | { |
||
1258 | struct drm_i915_private *dev_priv = dev->dev_private; |
||
1259 | |||
1260 | /* Set the Panel Power On/Off timings if uninitialized. */ |
||
3243 | Serge | 1261 | if (!HAS_PCH_SPLIT(dev) && |
1262 | I915_READ(PP_ON_DELAYS) == 0 && I915_READ(PP_OFF_DELAYS) == 0) { |
||
2351 | Serge | 1263 | /* Set T2 to 40ms and T5 to 200ms */ |
1264 | I915_WRITE(PP_ON_DELAYS, 0x019007d0); |
||
1265 | |||
1266 | /* Set T3 to 35ms and Tx to 200ms */ |
||
1267 | I915_WRITE(PP_OFF_DELAYS, 0x015e07d0); |
||
1268 | } |
||
1269 | }>>=>>>>>>>>>>>>>>>>>>>><>><>><>><>><>> |