Rev 5060 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5060 | Rev 6084 | ||
---|---|---|---|
Line 20... | Line 20... | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
21 | * DEALINGS IN THE SOFTWARE. |
21 | * DEALINGS IN THE SOFTWARE. |
22 | * |
22 | * |
23 | * Authors: |
23 | * Authors: |
24 | * Eric Anholt |
24 | * Eric Anholt |
- | 25 | * Thomas Richter |
|
- | 26 | * |
|
- | 27 | * Minor modifications (Dithering enable): |
|
- | 28 | * Thomas Richter |
|
25 | * |
29 | * |
26 | */ |
30 | */ |
Line 27... | Line 31... | ||
27 | 31 | ||
Line 57... | Line 61... | ||
57 | # define VR01_LCD_ENABLE (1 << 2) |
61 | # define VR01_LCD_ENABLE (1 << 2) |
58 | /** Enables the DVO repeater. */ |
62 | /** Enables the DVO repeater. */ |
59 | # define VR01_DVO_BYPASS_ENABLE (1 << 1) |
63 | # define VR01_DVO_BYPASS_ENABLE (1 << 1) |
60 | /** Enables the DVO clock */ |
64 | /** Enables the DVO clock */ |
61 | # define VR01_DVO_ENABLE (1 << 0) |
65 | # define VR01_DVO_ENABLE (1 << 0) |
- | 66 | /** Enable dithering for 18bpp panels. Not documented. */ |
|
- | 67 | # define VR01_DITHER_ENABLE (1 << 4) |
|
Line 62... | Line 68... | ||
62 | 68 | ||
63 | /* |
69 | /* |
64 | * LCD Interface Format |
70 | * LCD Interface Format |
65 | */ |
71 | */ |
Line 72... | Line 78... | ||
72 | # define VR10_INTERFACE_1X24 (1 << 2) |
78 | # define VR10_INTERFACE_1X24 (1 << 2) |
73 | /** Enables 2x18-bit LVDS or CMOS output. */ |
79 | /** Enables 2x18-bit LVDS or CMOS output. */ |
74 | # define VR10_INTERFACE_2X18 (2 << 2) |
80 | # define VR10_INTERFACE_2X18 (2 << 2) |
75 | /** Enables 2x24-bit LVDS output */ |
81 | /** Enables 2x24-bit LVDS output */ |
76 | # define VR10_INTERFACE_2X24 (3 << 2) |
82 | # define VR10_INTERFACE_2X24 (3 << 2) |
- | 83 | /** Mask that defines the depth of the pipeline */ |
|
- | 84 | # define VR10_INTERFACE_DEPTH_MASK (3 << 2) |
|
Line 77... | Line 85... | ||
77 | 85 | ||
78 | /* |
86 | /* |
79 | * VR20 LCD Horizontal Display Size |
87 | * VR20 LCD Horizontal Display Size |
80 | */ |
88 | */ |
Line 81... | Line 89... | ||
81 | #define VR20 0x20 |
89 | #define VR20 0x20 |
82 | 90 | ||
83 | /* |
91 | /* |
84 | * LCD Vertical Display Size |
92 | * LCD Vertical Display Size |
Line 85... | Line 93... | ||
85 | */ |
93 | */ |
86 | #define VR21 0x20 |
94 | #define VR21 0x21 |
87 | 95 | ||
88 | /* |
96 | /* |
Line 146... | Line 154... | ||
146 | # define VR8F_VCH_PRESENT (1 << 0) |
154 | # define VR8F_VCH_PRESENT (1 << 0) |
147 | # define VR8F_DISPLAY_CONN (1 << 1) |
155 | # define VR8F_DISPLAY_CONN (1 << 1) |
148 | # define VR8F_POWER_MASK (0x3c) |
156 | # define VR8F_POWER_MASK (0x3c) |
149 | # define VR8F_POWER_POS (2) |
157 | # define VR8F_POWER_POS (2) |
Line -... | Line 158... | ||
- | 158 | ||
- | 159 | /* Some Bios implementations do not restore the DVO state upon |
|
- | 160 | * resume from standby. Thus, this driver has to handle it |
|
- | 161 | * instead. The following list contains all registers that |
|
- | 162 | * require saving. |
|
- | 163 | */ |
|
- | 164 | static const uint16_t backup_addresses[] = { |
|
- | 165 | 0x11, 0x12, |
|
- | 166 | 0x18, 0x19, 0x1a, 0x1f, |
|
- | 167 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, |
|
- | 168 | 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, |
|
- | 169 | 0x8e, 0x8f, |
|
- | 170 | 0x10 /* this must come last */ |
|
- | 171 | }; |
|
Line 150... | Line 172... | ||
150 | 172 | ||
151 | 173 | ||
Line 152... | Line 174... | ||
152 | struct ivch_priv { |
174 | struct ivch_priv { |
- | 175 | bool quiet; |
|
- | 176 | ||
- | 177 | uint16_t width, height; |
|
- | 178 | ||
153 | bool quiet; |
179 | /* Register backup */ |
Line 154... | Line 180... | ||
154 | 180 | ||
155 | uint16_t width, height; |
- | |
156 | }; |
181 | uint16_t reg_backup[ARRAY_SIZE(backup_addresses)]; |
157 | 182 | }; |
|
158 | 183 | ||
159 | static void ivch_dump_regs(struct intel_dvo_device *dvo); |
184 | |
160 | 185 | static void ivch_dump_regs(struct intel_dvo_device *dvo); |
|
Line 237... | Line 262... | ||
237 | static bool ivch_init(struct intel_dvo_device *dvo, |
262 | static bool ivch_init(struct intel_dvo_device *dvo, |
238 | struct i2c_adapter *adapter) |
263 | struct i2c_adapter *adapter) |
239 | { |
264 | { |
240 | struct ivch_priv *priv; |
265 | struct ivch_priv *priv; |
241 | uint16_t temp; |
266 | uint16_t temp; |
- | 267 | int i; |
|
Line 242... | Line 268... | ||
242 | 268 | ||
243 | priv = kzalloc(sizeof(struct ivch_priv), GFP_KERNEL); |
269 | priv = kzalloc(sizeof(struct ivch_priv), GFP_KERNEL); |
244 | if (priv == NULL) |
270 | if (priv == NULL) |
Line 264... | Line 290... | ||
264 | } |
290 | } |
Line 265... | Line 291... | ||
265 | 291 | ||
266 | ivch_read(dvo, VR20, &priv->width); |
292 | ivch_read(dvo, VR20, &priv->width); |
Line -... | Line 293... | ||
- | 293 | ivch_read(dvo, VR21, &priv->height); |
|
- | 294 | ||
- | 295 | /* Make a backup of the registers to be able to restore them |
|
- | 296 | * upon suspend. |
|
- | 297 | */ |
|
- | 298 | for (i = 0; i < ARRAY_SIZE(backup_addresses); i++) |
|
- | 299 | ivch_read(dvo, backup_addresses[i], priv->reg_backup + i); |
|
- | 300 | ||
267 | ivch_read(dvo, VR21, &priv->height); |
301 | ivch_dump_regs(dvo); |
Line 268... | Line 302... | ||
268 | 302 | ||
269 | return true; |
303 | return true; |
270 | 304 | ||
Line 285... | Line 319... | ||
285 | return MODE_CLOCK_HIGH; |
319 | return MODE_CLOCK_HIGH; |
Line 286... | Line 320... | ||
286 | 320 | ||
287 | return MODE_OK; |
321 | return MODE_OK; |
Line -... | Line 322... | ||
- | 322 | } |
|
- | 323 | ||
- | 324 | /* Restore the DVO registers after a resume |
|
- | 325 | * from RAM. Registers have been saved during |
|
- | 326 | * the initialization. |
|
- | 327 | */ |
|
- | 328 | static void ivch_reset(struct intel_dvo_device *dvo) |
|
- | 329 | { |
|
- | 330 | struct ivch_priv *priv = dvo->dev_priv; |
|
- | 331 | int i; |
|
- | 332 | ||
- | 333 | DRM_DEBUG_KMS("Resetting the IVCH registers\n"); |
|
- | 334 | ||
- | 335 | ivch_write(dvo, VR10, 0x0000); |
|
- | 336 | ||
- | 337 | for (i = 0; i < ARRAY_SIZE(backup_addresses); i++) |
|
- | 338 | ivch_write(dvo, backup_addresses[i], priv->reg_backup[i]); |
|
288 | } |
339 | } |
289 | 340 | ||
290 | /** Sets the power state of the panel connected to the ivch */ |
341 | /** Sets the power state of the panel connected to the ivch */ |
291 | static void ivch_dpms(struct intel_dvo_device *dvo, bool enable) |
342 | static void ivch_dpms(struct intel_dvo_device *dvo, bool enable) |
292 | { |
343 | { |
Line -... | Line 344... | ||
- | 344 | int i; |
|
- | 345 | uint16_t vr01, vr30, backlight; |
|
293 | int i; |
346 | |
294 | uint16_t vr01, vr30, backlight; |
347 | ivch_reset(dvo); |
295 | 348 | ||
Line 296... | Line 349... | ||
296 | /* Set the new power state of the panel. */ |
349 | /* Set the new power state of the panel. */ |
297 | if (!ivch_read(dvo, VR01, &vr01)) |
350 | if (!ivch_read(dvo, VR01, &vr01)) |
298 | return; |
351 | return; |
299 | 352 | ||
- | 353 | if (enable) |
|
300 | if (enable) |
354 | backlight = 1; |
Line 301... | Line 355... | ||
301 | backlight = 1; |
355 | else |
302 | else |
356 | backlight = 0; |
303 | backlight = 0; |
357 | |
Line 325... | Line 379... | ||
325 | 379 | ||
326 | static bool ivch_get_hw_state(struct intel_dvo_device *dvo) |
380 | static bool ivch_get_hw_state(struct intel_dvo_device *dvo) |
327 | { |
381 | { |
Line -... | Line 382... | ||
- | 382 | uint16_t vr01; |
|
- | 383 | ||
328 | uint16_t vr01; |
384 | ivch_reset(dvo); |
329 | 385 | ||
330 | /* Set the new power state of the panel. */ |
386 | /* Set the new power state of the panel. */ |
Line 331... | Line 387... | ||
331 | if (!ivch_read(dvo, VR01, &vr01)) |
387 | if (!ivch_read(dvo, VR01, &vr01)) |
Line 336... | Line 392... | ||
336 | else |
392 | else |
337 | return false; |
393 | return false; |
338 | } |
394 | } |
Line 339... | Line 395... | ||
339 | 395 | ||
340 | static void ivch_mode_set(struct intel_dvo_device *dvo, |
396 | static void ivch_mode_set(struct intel_dvo_device *dvo, |
341 | struct drm_display_mode *mode, |
397 | const struct drm_display_mode *mode, |
342 | struct drm_display_mode *adjusted_mode) |
398 | const struct drm_display_mode *adjusted_mode) |
- | 399 | { |
|
343 | { |
400 | struct ivch_priv *priv = dvo->dev_priv; |
- | 401 | uint16_t vr40 = 0; |
|
344 | uint16_t vr40 = 0; |
402 | uint16_t vr01 = 0; |
- | 403 | uint16_t vr10; |
|
- | 404 | ||
- | 405 | ivch_reset(dvo); |
|
- | 406 | ||
- | 407 | vr10 = priv->reg_backup[ARRAY_SIZE(backup_addresses) - 1]; |
|
- | 408 | ||
- | 409 | /* Enable dithering for 18 bpp pipelines */ |
|
- | 410 | vr10 &= VR10_INTERFACE_DEPTH_MASK; |
|
- | 411 | if (vr10 == VR10_INTERFACE_2X18 || vr10 == VR10_INTERFACE_1X18) |
|
Line 345... | Line -... | ||
345 | uint16_t vr01; |
- | |
346 | 412 | vr01 = VR01_DITHER_ENABLE; |
|
347 | vr01 = 0; |
413 | |
Line 348... | Line 414... | ||
348 | vr40 = (VR40_STALL_ENABLE | VR40_VERTICAL_INTERP_ENABLE | |
414 | vr40 = (VR40_STALL_ENABLE | VR40_VERTICAL_INTERP_ENABLE | |
349 | VR40_HORIZONTAL_INTERP_ENABLE); |
415 | VR40_HORIZONTAL_INTERP_ENABLE); |
350 | 416 | ||
Line 351... | Line 417... | ||
351 | if (mode->hdisplay != adjusted_mode->hdisplay || |
417 | if (mode->hdisplay != adjusted_mode->crtc_hdisplay || |
352 | mode->vdisplay != adjusted_mode->vdisplay) { |
418 | mode->vdisplay != adjusted_mode->crtc_vdisplay) { |
353 | uint16_t x_ratio, y_ratio; |
419 | uint16_t x_ratio, y_ratio; |
354 | 420 | ||
355 | vr01 |= VR01_PANEL_FIT_ENABLE; |
421 | vr01 |= VR01_PANEL_FIT_ENABLE; |
356 | vr40 |= VR40_CLOCK_GATING_ENABLE; |
422 | vr40 |= VR40_CLOCK_GATING_ENABLE; |
357 | x_ratio = (((mode->hdisplay - 1) << 16) / |
423 | x_ratio = (((mode->hdisplay - 1) << 16) / |
358 | (adjusted_mode->hdisplay - 1)) >> 2; |
424 | (adjusted_mode->crtc_hdisplay - 1)) >> 2; |
359 | y_ratio = (((mode->vdisplay - 1) << 16) / |
425 | y_ratio = (((mode->vdisplay - 1) << 16) / |
360 | (adjusted_mode->vdisplay - 1)) >> 2; |
426 | (adjusted_mode->crtc_vdisplay - 1)) >> 2; |
361 | ivch_write(dvo, VR42, x_ratio); |
427 | ivch_write(dvo, VR42, x_ratio); |
362 | ivch_write(dvo, VR41, y_ratio); |
428 | ivch_write(dvo, VR41, y_ratio); |
363 | } else { |
429 | } else { |
Line 364... | Line 430... | ||
364 | vr01 &= ~VR01_PANEL_FIT_ENABLE; |
430 | vr01 &= ~VR01_PANEL_FIT_ENABLE; |
365 | vr40 &= ~VR40_CLOCK_GATING_ENABLE; |
431 | vr40 &= ~VR40_CLOCK_GATING_ENABLE; |
366 | } |
- | |
367 | vr40 &= ~VR40_AUTO_RATIO_ENABLE; |
- | |
368 | 432 | } |
|
Line 369... | Line 433... | ||
369 | ivch_write(dvo, VR01, vr01); |
433 | vr40 &= ~VR40_AUTO_RATIO_ENABLE; |
370 | ivch_write(dvo, VR40, vr40); |
434 | |
371 | 435 | ivch_write(dvo, VR01, vr01); |
|
Line 372... | Line 436... | ||
372 | ivch_dump_regs(dvo); |
436 | ivch_write(dvo, VR40, vr40); |
373 | } |
437 | } |
374 | 438 | ||
375 | static void ivch_dump_regs(struct intel_dvo_device *dvo) |
439 | static void ivch_dump_regs(struct intel_dvo_device *dvo) |
- | 440 | { |
|
- | 441 | uint16_t val; |
|
376 | { |
442 | |
377 | uint16_t val; |
443 | ivch_read(dvo, VR00, &val); |
378 | 444 | DRM_DEBUG_KMS("VR00: 0x%04x\n", val); |
|
379 | ivch_read(dvo, VR00, &val); |
445 | ivch_read(dvo, VR01, &val); |