Rev 2360 | Rev 3120 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2360 | Rev 3031 | ||
---|---|---|---|
Line 23... | Line 23... | ||
23 | * Authors: |
23 | * Authors: |
24 | * Eric Anholt |
24 | * Eric Anholt |
25 | * |
25 | * |
26 | */ |
26 | */ |
27 | #include |
27 | #include |
28 | #include "drmP.h" |
28 | #include |
29 | #include "drm.h" |
- | |
30 | #include "i915_drm.h" |
29 | #include |
31 | #include "i915_drv.h" |
30 | #include "i915_drv.h" |
32 | #include "intel_bios.h" |
31 | #include "intel_bios.h" |
Line 33... | Line 32... | ||
33 | 32 | ||
34 | #define SLAVE_ADDR1 0x70 |
33 | #define SLAVE_ADDR1 0x70 |
Line 171... | Line 170... | ||
171 | char *entry = (char *)lvds_lfp_data->data + lfp_data_size * index; |
170 | char *entry = (char *)lvds_lfp_data->data + lfp_data_size * index; |
Line 172... | Line 171... | ||
172 | 171 | ||
173 | return (struct lvds_dvo_timing *)(entry + dvo_timing_offset); |
172 | return (struct lvds_dvo_timing *)(entry + dvo_timing_offset); |
Line -... | Line 173... | ||
- | 173 | } |
|
- | 174 | ||
- | 175 | /* get lvds_fp_timing entry |
|
- | 176 | * this function may return NULL if the corresponding entry is invalid |
|
- | 177 | */ |
|
- | 178 | static const struct lvds_fp_timing * |
|
- | 179 | get_lvds_fp_timing(const struct bdb_header *bdb, |
|
- | 180 | const struct bdb_lvds_lfp_data *data, |
|
- | 181 | const struct bdb_lvds_lfp_data_ptrs *ptrs, |
|
- | 182 | int index) |
|
- | 183 | { |
|
- | 184 | size_t data_ofs = (const u8 *)data - (const u8 *)bdb; |
|
- | 185 | u16 data_size = ((const u16 *)data)[-1]; /* stored in header */ |
|
- | 186 | size_t ofs; |
|
- | 187 | ||
- | 188 | if (index >= ARRAY_SIZE(ptrs->ptr)) |
|
- | 189 | return NULL; |
|
- | 190 | ofs = ptrs->ptr[index].fp_timing_offset; |
|
- | 191 | if (ofs < data_ofs || |
|
- | 192 | ofs + sizeof(struct lvds_fp_timing) > data_ofs + data_size) |
|
- | 193 | return NULL; |
|
- | 194 | return (const struct lvds_fp_timing *)((const u8 *)bdb + ofs); |
|
174 | } |
195 | } |
175 | 196 | ||
176 | /* Try to find integrated panel data */ |
197 | /* Try to find integrated panel data */ |
177 | static void |
198 | static void |
178 | parse_lfp_panel_data(struct drm_i915_private *dev_priv, |
199 | parse_lfp_panel_data(struct drm_i915_private *dev_priv, |
179 | struct bdb_header *bdb) |
200 | struct bdb_header *bdb) |
180 | { |
201 | { |
181 | const struct bdb_lvds_options *lvds_options; |
202 | const struct bdb_lvds_options *lvds_options; |
182 | const struct bdb_lvds_lfp_data *lvds_lfp_data; |
203 | const struct bdb_lvds_lfp_data *lvds_lfp_data; |
- | 204 | const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; |
|
183 | const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; |
205 | const struct lvds_dvo_timing *panel_dvo_timing; |
184 | const struct lvds_dvo_timing *panel_dvo_timing; |
206 | const struct lvds_fp_timing *fp_timing; |
Line 185... | Line 207... | ||
185 | struct drm_display_mode *panel_fixed_mode; |
207 | struct drm_display_mode *panel_fixed_mode; |
186 | int i, downclock; |
208 | int i, downclock; |
Line 241... | Line 263... | ||
241 | dev_priv->lvds_downclock = downclock * 10; |
263 | dev_priv->lvds_downclock = downclock * 10; |
242 | DRM_DEBUG_KMS("LVDS downclock is found in VBT. " |
264 | DRM_DEBUG_KMS("LVDS downclock is found in VBT. " |
243 | "Normal Clock %dKHz, downclock %dKHz\n", |
265 | "Normal Clock %dKHz, downclock %dKHz\n", |
244 | panel_fixed_mode->clock, 10*downclock); |
266 | panel_fixed_mode->clock, 10*downclock); |
245 | } |
267 | } |
- | 268 | ||
- | 269 | fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data, |
|
- | 270 | lvds_lfp_data_ptrs, |
|
- | 271 | lvds_options->panel_type); |
|
- | 272 | if (fp_timing) { |
|
- | 273 | /* check the resolution, just to be sure */ |
|
- | 274 | if (fp_timing->x_res == panel_fixed_mode->hdisplay && |
|
- | 275 | fp_timing->y_res == panel_fixed_mode->vdisplay) { |
|
- | 276 | dev_priv->bios_lvds_val = fp_timing->lvds_reg_val; |
|
- | 277 | DRM_DEBUG_KMS("VBT initial LVDS value %x\n", |
|
- | 278 | dev_priv->bios_lvds_val); |
|
- | 279 | } |
|
- | 280 | } |
|
246 | } |
281 | } |
Line 247... | Line 282... | ||
247 | 282 | ||
248 | /* Try to find sdvo panel data */ |
283 | /* Try to find sdvo panel data */ |
249 | static void |
284 | static void |
Line 253... | Line 288... | ||
253 | struct lvds_dvo_timing *dvo_timing; |
288 | struct lvds_dvo_timing *dvo_timing; |
254 | struct drm_display_mode *panel_fixed_mode; |
289 | struct drm_display_mode *panel_fixed_mode; |
255 | int index; |
290 | int index; |
Line 256... | Line 291... | ||
256 | 291 | ||
- | 292 | index = i915_vbt_sdvo_panel_type; |
|
- | 293 | if (index == -2) { |
|
- | 294 | DRM_DEBUG_KMS("Ignore SDVO panel mode from BIOS VBT tables.\n"); |
|
- | 295 | return; |
|
- | 296 | } |
|
257 | index = i915_vbt_sdvo_panel_type; |
297 | |
258 | if (index == -1) { |
298 | if (index == -1) { |
Line 259... | Line 299... | ||
259 | struct bdb_sdvo_lvds_options *sdvo_lvds_options; |
299 | struct bdb_sdvo_lvds_options *sdvo_lvds_options; |
260 | 300 | ||
Line 329... | Line 369... | ||
329 | if (general) { |
369 | if (general) { |
330 | u16 block_size = get_blocksize(general); |
370 | u16 block_size = get_blocksize(general); |
331 | if (block_size >= sizeof(*general)) { |
371 | if (block_size >= sizeof(*general)) { |
332 | int bus_pin = general->crt_ddc_gmbus_pin; |
372 | int bus_pin = general->crt_ddc_gmbus_pin; |
333 | DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); |
373 | DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); |
334 | if (bus_pin >= 1 && bus_pin <= 6) |
374 | if (intel_gmbus_is_port_valid(bus_pin)) |
335 | dev_priv->crt_ddc_pin = bus_pin; |
375 | dev_priv->crt_ddc_pin = bus_pin; |
336 | } else { |
376 | } else { |
337 | DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", |
377 | DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", |
338 | block_size); |
378 | block_size); |
339 | } |
379 | } |
Line 570... | Line 610... | ||
570 | } |
610 | } |
571 | if (!count) { |
611 | if (!count) { |
572 | DRM_DEBUG_KMS("no child dev is parsed from VBT\n"); |
612 | DRM_DEBUG_KMS("no child dev is parsed from VBT\n"); |
573 | return; |
613 | return; |
574 | } |
614 | } |
575 | dev_priv->child_dev = kzalloc(sizeof(*p_child) * count, GFP_KERNEL); |
615 | dev_priv->child_dev = kcalloc(count, sizeof(*p_child), GFP_KERNEL); |
576 | if (!dev_priv->child_dev) { |
616 | if (!dev_priv->child_dev) { |
577 | DRM_DEBUG_KMS("No memory space for child device\n"); |
617 | DRM_DEBUG_KMS("No memory space for child device\n"); |
578 | return; |
618 | return; |
579 | } |
619 | } |
Line 628... | Line 668... | ||
628 | * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers |
668 | * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers |
629 | * to appropriate values. |
669 | * to appropriate values. |
630 | * |
670 | * |
631 | * Returns 0 on success, nonzero on failure. |
671 | * Returns 0 on success, nonzero on failure. |
632 | */ |
672 | */ |
633 | bool |
673 | int |
634 | intel_parse_bios(struct drm_device *dev) |
674 | intel_parse_bios(struct drm_device *dev) |
635 | { |
675 | { |
636 | struct drm_i915_private *dev_priv = dev->dev_private; |
676 | struct drm_i915_private *dev_priv = dev->dev_private; |
637 | struct pci_dev *pdev = dev->pdev; |
677 | struct pci_dev *pdev = dev->pdev; |
638 | struct bdb_header *bdb = NULL; |
678 | struct bdb_header *bdb = NULL; |
Line 667... | Line 707... | ||
667 | break; |
707 | break; |
668 | } |
708 | } |
669 | } |
709 | } |
Line 670... | Line 710... | ||
670 | 710 | ||
671 | if (!vbt) { |
711 | if (!vbt) { |
672 | DRM_ERROR("VBT signature missing\n"); |
712 | DRM_DEBUG_DRIVER("VBT signature missing\n"); |
673 | pci_unmap_rom(pdev, bios); |
713 | pci_unmap_rom(pdev, bios); |
674 | return -1; |
714 | return -1; |
Line 675... | Line 715... | ||
675 | } |
715 | } |