diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_bios.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_bios.c | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 9d78cff33b24..754dd22fdd77 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include "i915_drv.h" | 30 | #include "i915_drv.h" |
31 | #include "intel_bios.h" | 31 | #include "intel_bios.h" |
32 | 32 | ||
33 | #define SLAVE_ADDR1 0x70 | ||
34 | #define SLAVE_ADDR2 0x72 | ||
33 | 35 | ||
34 | static void * | 36 | static void * |
35 | find_section(struct bdb_header *bdb, int section_id) | 37 | find_section(struct bdb_header *bdb, int section_id) |
@@ -193,6 +195,88 @@ parse_general_features(struct drm_i915_private *dev_priv, | |||
193 | } | 195 | } |
194 | } | 196 | } |
195 | 197 | ||
198 | static void | ||
199 | parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, | ||
200 | struct bdb_header *bdb) | ||
201 | { | ||
202 | struct sdvo_device_mapping *p_mapping; | ||
203 | struct bdb_general_definitions *p_defs; | ||
204 | struct child_device_config *p_child; | ||
205 | int i, child_device_num, count; | ||
206 | u16 block_size, *block_ptr; | ||
207 | |||
208 | p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); | ||
209 | if (!p_defs) { | ||
210 | DRM_DEBUG("No general definition block is found\n"); | ||
211 | return; | ||
212 | } | ||
213 | /* judge whether the size of child device meets the requirements. | ||
214 | * If the child device size obtained from general definition block | ||
215 | * is different with sizeof(struct child_device_config), skip the | ||
216 | * parsing of sdvo device info | ||
217 | */ | ||
218 | if (p_defs->child_dev_size != sizeof(*p_child)) { | ||
219 | /* different child dev size . Ignore it */ | ||
220 | DRM_DEBUG("different child size is found. Invalid.\n"); | ||
221 | return; | ||
222 | } | ||
223 | /* get the block size of general definitions */ | ||
224 | block_ptr = (u16 *)((char *)p_defs - 2); | ||
225 | block_size = *block_ptr; | ||
226 | /* get the number of child device */ | ||
227 | child_device_num = (block_size - sizeof(*p_defs)) / | ||
228 | sizeof(*p_child); | ||
229 | count = 0; | ||
230 | for (i = 0; i < child_device_num; i++) { | ||
231 | p_child = &(p_defs->devices[i]); | ||
232 | if (!p_child->device_type) { | ||
233 | /* skip the device block if device type is invalid */ | ||
234 | continue; | ||
235 | } | ||
236 | if (p_child->slave_addr != SLAVE_ADDR1 && | ||
237 | p_child->slave_addr != SLAVE_ADDR2) { | ||
238 | /* | ||
239 | * If the slave address is neither 0x70 nor 0x72, | ||
240 | * it is not a SDVO device. Skip it. | ||
241 | */ | ||
242 | continue; | ||
243 | } | ||
244 | if (p_child->dvo_port != DEVICE_PORT_DVOB && | ||
245 | p_child->dvo_port != DEVICE_PORT_DVOC) { | ||
246 | /* skip the incorrect SDVO port */ | ||
247 | DRM_DEBUG("Incorrect SDVO port. Skip it \n"); | ||
248 | continue; | ||
249 | } | ||
250 | DRM_DEBUG("the SDVO device with slave addr %2x is found on " | ||
251 | "%s port\n", | ||
252 | p_child->slave_addr, | ||
253 | (p_child->dvo_port == DEVICE_PORT_DVOB) ? | ||
254 | "SDVOB" : "SDVOC"); | ||
255 | p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]); | ||
256 | if (!p_mapping->initialized) { | ||
257 | p_mapping->dvo_port = p_child->dvo_port; | ||
258 | p_mapping->slave_addr = p_child->slave_addr; | ||
259 | p_mapping->dvo_wiring = p_child->dvo_wiring; | ||
260 | p_mapping->initialized = 1; | ||
261 | } else { | ||
262 | DRM_DEBUG("Maybe one SDVO port is shared by " | ||
263 | "two SDVO device.\n"); | ||
264 | } | ||
265 | if (p_child->slave2_addr) { | ||
266 | /* Maybe this is a SDVO device with multiple inputs */ | ||
267 | /* And the mapping info is not added */ | ||
268 | DRM_DEBUG("there exists the slave2_addr. Maybe this " | ||
269 | "is a SDVO device with multiple inputs.\n"); | ||
270 | } | ||
271 | count++; | ||
272 | } | ||
273 | |||
274 | if (!count) { | ||
275 | /* No SDVO device info is found */ | ||
276 | DRM_DEBUG("No SDVO device info is found in VBT\n"); | ||
277 | } | ||
278 | return; | ||
279 | } | ||
196 | /** | 280 | /** |
197 | * intel_init_bios - initialize VBIOS settings & find VBT | 281 | * intel_init_bios - initialize VBIOS settings & find VBT |
198 | * @dev: DRM device | 282 | * @dev: DRM device |
@@ -242,7 +326,7 @@ intel_init_bios(struct drm_device *dev) | |||
242 | parse_general_features(dev_priv, bdb); | 326 | parse_general_features(dev_priv, bdb); |
243 | parse_lfp_panel_data(dev_priv, bdb); | 327 | parse_lfp_panel_data(dev_priv, bdb); |
244 | parse_sdvo_panel_data(dev_priv, bdb); | 328 | parse_sdvo_panel_data(dev_priv, bdb); |
245 | 329 | parse_sdvo_device_mapping(dev_priv, bdb); | |
246 | pci_unmap_rom(pdev, bios); | 330 | pci_unmap_rom(pdev, bios); |
247 | 331 | ||
248 | return 0; | 332 | return 0; |