diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_bios.c | 102 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_bios.h | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 4 |
4 files changed, 93 insertions, 33 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9b149fe824c3..c431fa54bbb5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -180,7 +180,8 @@ typedef struct drm_i915_private { | |||
180 | int backlight_duty_cycle; /* restore backlight to this value */ | 180 | int backlight_duty_cycle; /* restore backlight to this value */ |
181 | bool panel_wants_dither; | 181 | bool panel_wants_dither; |
182 | struct drm_display_mode *panel_fixed_mode; | 182 | struct drm_display_mode *panel_fixed_mode; |
183 | struct drm_display_mode *vbt_mode; /* if any */ | 183 | struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */ |
184 | struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ | ||
184 | 185 | ||
185 | /* Feature bits from the VBIOS */ | 186 | /* Feature bits from the VBIOS */ |
186 | unsigned int int_tv_support:1; | 187 | unsigned int int_tv_support:1; |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index fc28e2bbd542..9d78cff33b24 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
@@ -57,9 +57,43 @@ find_section(struct bdb_header *bdb, int section_id) | |||
57 | return NULL; | 57 | return NULL; |
58 | } | 58 | } |
59 | 59 | ||
60 | /* Try to find panel data */ | ||
61 | static void | 60 | static void |
62 | parse_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb) | 61 | fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, |
62 | struct lvds_dvo_timing *dvo_timing) | ||
63 | { | ||
64 | panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | | ||
65 | dvo_timing->hactive_lo; | ||
66 | panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay + | ||
67 | ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo); | ||
68 | panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start + | ||
69 | dvo_timing->hsync_pulse_width; | ||
70 | panel_fixed_mode->htotal = panel_fixed_mode->hdisplay + | ||
71 | ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo); | ||
72 | |||
73 | panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) | | ||
74 | dvo_timing->vactive_lo; | ||
75 | panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay + | ||
76 | dvo_timing->vsync_off; | ||
77 | panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start + | ||
78 | dvo_timing->vsync_pulse_width; | ||
79 | panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay + | ||
80 | ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo); | ||
81 | panel_fixed_mode->clock = dvo_timing->clock * 10; | ||
82 | panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; | ||
83 | |||
84 | /* Some VBTs have bogus h/vtotal values */ | ||
85 | if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) | ||
86 | panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; | ||
87 | if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) | ||
88 | panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; | ||
89 | |||
90 | drm_mode_set_name(panel_fixed_mode); | ||
91 | } | ||
92 | |||
93 | /* Try to find integrated panel data */ | ||
94 | static void | ||
95 | parse_lfp_panel_data(struct drm_i915_private *dev_priv, | ||
96 | struct bdb_header *bdb) | ||
63 | { | 97 | { |
64 | struct bdb_lvds_options *lvds_options; | 98 | struct bdb_lvds_options *lvds_options; |
65 | struct bdb_lvds_lfp_data *lvds_lfp_data; | 99 | struct bdb_lvds_lfp_data *lvds_lfp_data; |
@@ -91,38 +125,45 @@ parse_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb) | |||
91 | panel_fixed_mode = drm_calloc(1, sizeof(*panel_fixed_mode), | 125 | panel_fixed_mode = drm_calloc(1, sizeof(*panel_fixed_mode), |
92 | DRM_MEM_DRIVER); | 126 | DRM_MEM_DRIVER); |
93 | 127 | ||
94 | panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | | 128 | fill_detail_timing_data(panel_fixed_mode, dvo_timing); |
95 | dvo_timing->hactive_lo; | ||
96 | panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay + | ||
97 | ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo); | ||
98 | panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start + | ||
99 | dvo_timing->hsync_pulse_width; | ||
100 | panel_fixed_mode->htotal = panel_fixed_mode->hdisplay + | ||
101 | ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo); | ||
102 | 129 | ||
103 | panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) | | 130 | dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode; |
104 | dvo_timing->vactive_lo; | ||
105 | panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay + | ||
106 | dvo_timing->vsync_off; | ||
107 | panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start + | ||
108 | dvo_timing->vsync_pulse_width; | ||
109 | panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay + | ||
110 | ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo); | ||
111 | panel_fixed_mode->clock = dvo_timing->clock * 10; | ||
112 | panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; | ||
113 | 131 | ||
114 | /* Some VBTs have bogus h/vtotal values */ | 132 | DRM_DEBUG("Found panel mode in BIOS VBT tables:\n"); |
115 | if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) | 133 | drm_mode_debug_printmodeline(panel_fixed_mode); |
116 | panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; | ||
117 | if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) | ||
118 | panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; | ||
119 | 134 | ||
120 | drm_mode_set_name(panel_fixed_mode); | 135 | return; |
136 | } | ||
137 | |||
138 | /* Try to find sdvo panel data */ | ||
139 | static void | ||
140 | parse_sdvo_panel_data(struct drm_i915_private *dev_priv, | ||
141 | struct bdb_header *bdb) | ||
142 | { | ||
143 | struct bdb_sdvo_lvds_options *sdvo_lvds_options; | ||
144 | struct lvds_dvo_timing *dvo_timing; | ||
145 | struct drm_display_mode *panel_fixed_mode; | ||
121 | 146 | ||
122 | dev_priv->vbt_mode = panel_fixed_mode; | 147 | dev_priv->sdvo_lvds_vbt_mode = NULL; |
123 | 148 | ||
124 | DRM_DEBUG("Found panel mode in BIOS VBT tables:\n"); | 149 | sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); |
125 | drm_mode_debug_printmodeline(panel_fixed_mode); | 150 | if (!sdvo_lvds_options) |
151 | return; | ||
152 | |||
153 | dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS); | ||
154 | if (!dvo_timing) | ||
155 | return; | ||
156 | |||
157 | panel_fixed_mode = drm_calloc(1, sizeof(*panel_fixed_mode), | ||
158 | DRM_MEM_DRIVER); | ||
159 | |||
160 | if (!panel_fixed_mode) | ||
161 | return; | ||
162 | |||
163 | fill_detail_timing_data(panel_fixed_mode, | ||
164 | dvo_timing + sdvo_lvds_options->panel_type); | ||
165 | |||
166 | dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode; | ||
126 | 167 | ||
127 | return; | 168 | return; |
128 | } | 169 | } |
@@ -199,7 +240,8 @@ intel_init_bios(struct drm_device *dev) | |||
199 | 240 | ||
200 | /* Grab useful general definitions */ | 241 | /* Grab useful general definitions */ |
201 | parse_general_features(dev_priv, bdb); | 242 | parse_general_features(dev_priv, bdb); |
202 | parse_panel_data(dev_priv, bdb); | 243 | parse_lfp_panel_data(dev_priv, bdb); |
244 | parse_sdvo_panel_data(dev_priv, bdb); | ||
203 | 245 | ||
204 | pci_unmap_rom(pdev, bios); | 246 | pci_unmap_rom(pdev, bios); |
205 | 247 | ||
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index de621aad85b5..8ca2cde15804 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h | |||
@@ -279,6 +279,23 @@ struct vch_bdb_22 { | |||
279 | struct vch_panel_data panels[16]; | 279 | struct vch_panel_data panels[16]; |
280 | } __attribute__((packed)); | 280 | } __attribute__((packed)); |
281 | 281 | ||
282 | struct bdb_sdvo_lvds_options { | ||
283 | u8 panel_backlight; | ||
284 | u8 h40_set_panel_type; | ||
285 | u8 panel_type; | ||
286 | u8 ssc_clk_freq; | ||
287 | u16 als_low_trip; | ||
288 | u16 als_high_trip; | ||
289 | u8 sclalarcoeff_tab_row_num; | ||
290 | u8 sclalarcoeff_tab_row_size; | ||
291 | u8 coefficient[8]; | ||
292 | u8 panel_misc_bits_1; | ||
293 | u8 panel_misc_bits_2; | ||
294 | u8 panel_misc_bits_3; | ||
295 | u8 panel_misc_bits_4; | ||
296 | } __attribute__((packed)); | ||
297 | |||
298 | |||
282 | bool intel_init_bios(struct drm_device *dev); | 299 | bool intel_init_bios(struct drm_device *dev); |
283 | 300 | ||
284 | /* | 301 | /* |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 439a86514993..53731f0ffcb5 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
@@ -511,10 +511,10 @@ void intel_lvds_init(struct drm_device *dev) | |||
511 | } | 511 | } |
512 | 512 | ||
513 | /* Failed to get EDID, what about VBT? */ | 513 | /* Failed to get EDID, what about VBT? */ |
514 | if (dev_priv->vbt_mode) { | 514 | if (dev_priv->lfp_lvds_vbt_mode) { |
515 | mutex_lock(&dev->mode_config.mutex); | 515 | mutex_lock(&dev->mode_config.mutex); |
516 | dev_priv->panel_fixed_mode = | 516 | dev_priv->panel_fixed_mode = |
517 | drm_mode_duplicate(dev, dev_priv->vbt_mode); | 517 | drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); |
518 | mutex_unlock(&dev->mode_config.mutex); | 518 | mutex_unlock(&dev->mode_config.mutex); |
519 | if (dev_priv->panel_fixed_mode) { | 519 | if (dev_priv->panel_fixed_mode) { |
520 | dev_priv->panel_fixed_mode->type |= | 520 | dev_priv->panel_fixed_mode->type |= |