diff options
author | yakui_zhao <yakui.zhao@intel.com> | 2009-05-31 05:17:17 -0400 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2009-06-05 10:13:05 -0400 |
commit | 9b9d172d06b0f2d51cc9431e2c6c3055f0cf10ef (patch) | |
tree | 64721f8599a6cb39706cc9c48ce04c17f7377911 /drivers/gpu | |
parent | 59a036cfbd29aadf40d2b754cfebee2a96268752 (diff) |
drm/i915: parse VBT general definition block to get the SDVO device info
The general definition block contains the child device tables, which include
the SDVO device info. For example: device slave address, device dvo port,
device type.
We will get the info of SDVO device by parsing the general definition blocks.
Only when a valid slave address is found, it is regarded as the SDVO device.
And the info of DVO port and slave address is recorded.
http://bugs.freedesktop.org/show_bug.cgi?id=20429
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_bios.c | 86 |
2 files changed, 93 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ded9e786883e..db81f5513daa 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -126,6 +126,13 @@ struct drm_i915_fence_reg { | |||
126 | struct drm_gem_object *obj; | 126 | struct drm_gem_object *obj; |
127 | }; | 127 | }; |
128 | 128 | ||
129 | struct sdvo_device_mapping { | ||
130 | u8 dvo_port; | ||
131 | u8 slave_addr; | ||
132 | u8 dvo_wiring; | ||
133 | u8 initialized; | ||
134 | }; | ||
135 | |||
129 | typedef struct drm_i915_private { | 136 | typedef struct drm_i915_private { |
130 | struct drm_device *dev; | 137 | struct drm_device *dev; |
131 | 138 | ||
@@ -389,6 +396,7 @@ typedef struct drm_i915_private { | |||
389 | /* storage for physical objects */ | 396 | /* storage for physical objects */ |
390 | struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT]; | 397 | struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT]; |
391 | } mm; | 398 | } mm; |
399 | struct sdvo_device_mapping sdvo_mappings[2]; | ||
392 | } drm_i915_private_t; | 400 | } drm_i915_private_t; |
393 | 401 | ||
394 | /** driver private structure attached to each drm_gem_object */ | 402 | /** driver private structure attached to each drm_gem_object */ |
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; |