This source file includes following definitions.
- ivch_read
- ivch_write
- ivch_init
- ivch_detect
- ivch_mode_valid
- ivch_reset
- ivch_dpms
- ivch_get_hw_state
- ivch_mode_set
- ivch_dump_regs
- ivch_destroy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 #include "intel_display_types.h"
33 #include "intel_dvo_dev.h"
34
35
36
37
38
39
40
41
42
43
44
45 #define VR00 0x00
46 # define VR00_BASE_ADDRESS_MASK 0x007f
47
48
49
50
51 #define VR01 0x01
52
53
54
55
56 # define VR01_PANEL_FIT_ENABLE (1 << 3)
57
58
59
60
61
62 # define VR01_LCD_ENABLE (1 << 2)
63
64 # define VR01_DVO_BYPASS_ENABLE (1 << 1)
65
66 # define VR01_DVO_ENABLE (1 << 0)
67
68 # define VR01_DITHER_ENABLE (1 << 4)
69
70
71
72
73 #define VR10 0x10
74
75 # define VR10_LVDS_ENABLE (1 << 4)
76
77 # define VR10_INTERFACE_1X18 (0 << 2)
78
79 # define VR10_INTERFACE_1X24 (1 << 2)
80
81 # define VR10_INTERFACE_2X18 (2 << 2)
82
83 # define VR10_INTERFACE_2X24 (3 << 2)
84
85 # define VR10_INTERFACE_DEPTH_MASK (3 << 2)
86
87
88
89
90 #define VR20 0x20
91
92
93
94
95 #define VR21 0x21
96
97
98
99
100 #define VR30 0x30
101
102 # define VR30_PANEL_ON (1 << 15)
103
104 #define VR40 0x40
105 # define VR40_STALL_ENABLE (1 << 13)
106 # define VR40_VERTICAL_INTERP_ENABLE (1 << 12)
107 # define VR40_ENHANCED_PANEL_FITTING (1 << 11)
108 # define VR40_HORIZONTAL_INTERP_ENABLE (1 << 10)
109 # define VR40_AUTO_RATIO_ENABLE (1 << 9)
110 # define VR40_CLOCK_GATING_ENABLE (1 << 8)
111
112
113
114
115
116 #define VR41 0x41
117
118
119
120
121
122 #define VR42 0x42
123
124
125
126
127 #define VR43 0x43
128
129
130
131 #define VR80 0x80
132 #define VR81 0x81
133 #define VR82 0x82
134 #define VR83 0x83
135 #define VR84 0x84
136 #define VR85 0x85
137 #define VR86 0x86
138 #define VR87 0x87
139
140
141
142 #define VR88 0x88
143
144
145
146 #define VR8E 0x8E
147 # define VR8E_PANEL_TYPE_MASK (0xf << 0)
148 # define VR8E_PANEL_INTERFACE_CMOS (0 << 4)
149 # define VR8E_PANEL_INTERFACE_LVDS (1 << 4)
150 # define VR8E_FORCE_DEFAULT_PANEL (1 << 5)
151
152
153
154 #define VR8F 0x8F
155 # define VR8F_VCH_PRESENT (1 << 0)
156 # define VR8F_DISPLAY_CONN (1 << 1)
157 # define VR8F_POWER_MASK (0x3c)
158 # define VR8F_POWER_POS (2)
159
160
161
162
163
164
165 static const u16 backup_addresses[] = {
166 0x11, 0x12,
167 0x18, 0x19, 0x1a, 0x1f,
168 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
169 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
170 0x8e, 0x8f,
171 0x10
172 };
173
174
175 struct ivch_priv {
176 bool quiet;
177
178 u16 width, height;
179
180
181
182 u16 reg_backup[ARRAY_SIZE(backup_addresses)];
183 };
184
185
186 static void ivch_dump_regs(struct intel_dvo_device *dvo);
187
188
189
190
191
192 static bool ivch_read(struct intel_dvo_device *dvo, int addr, u16 *data)
193 {
194 struct ivch_priv *priv = dvo->dev_priv;
195 struct i2c_adapter *adapter = dvo->i2c_bus;
196 u8 out_buf[1];
197 u8 in_buf[2];
198
199 struct i2c_msg msgs[] = {
200 {
201 .addr = dvo->slave_addr,
202 .flags = I2C_M_RD,
203 .len = 0,
204 },
205 {
206 .addr = 0,
207 .flags = I2C_M_NOSTART,
208 .len = 1,
209 .buf = out_buf,
210 },
211 {
212 .addr = dvo->slave_addr,
213 .flags = I2C_M_RD | I2C_M_NOSTART,
214 .len = 2,
215 .buf = in_buf,
216 }
217 };
218
219 out_buf[0] = addr;
220
221 if (i2c_transfer(adapter, msgs, 3) == 3) {
222 *data = (in_buf[1] << 8) | in_buf[0];
223 return true;
224 }
225
226 if (!priv->quiet) {
227 DRM_DEBUG_KMS("Unable to read register 0x%02x from "
228 "%s:%02x.\n",
229 addr, adapter->name, dvo->slave_addr);
230 }
231 return false;
232 }
233
234
235 static bool ivch_write(struct intel_dvo_device *dvo, int addr, u16 data)
236 {
237 struct ivch_priv *priv = dvo->dev_priv;
238 struct i2c_adapter *adapter = dvo->i2c_bus;
239 u8 out_buf[3];
240 struct i2c_msg msg = {
241 .addr = dvo->slave_addr,
242 .flags = 0,
243 .len = 3,
244 .buf = out_buf,
245 };
246
247 out_buf[0] = addr;
248 out_buf[1] = data & 0xff;
249 out_buf[2] = data >> 8;
250
251 if (i2c_transfer(adapter, &msg, 1) == 1)
252 return true;
253
254 if (!priv->quiet) {
255 DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
256 addr, adapter->name, dvo->slave_addr);
257 }
258
259 return false;
260 }
261
262
263 static bool ivch_init(struct intel_dvo_device *dvo,
264 struct i2c_adapter *adapter)
265 {
266 struct ivch_priv *priv;
267 u16 temp;
268 int i;
269
270 priv = kzalloc(sizeof(struct ivch_priv), GFP_KERNEL);
271 if (priv == NULL)
272 return false;
273
274 dvo->i2c_bus = adapter;
275 dvo->dev_priv = priv;
276 priv->quiet = true;
277
278 if (!ivch_read(dvo, VR00, &temp))
279 goto out;
280 priv->quiet = false;
281
282
283
284
285
286 if ((temp & VR00_BASE_ADDRESS_MASK) != dvo->slave_addr) {
287 DRM_DEBUG_KMS("ivch detect failed due to address mismatch "
288 "(%d vs %d)\n",
289 (temp & VR00_BASE_ADDRESS_MASK), dvo->slave_addr);
290 goto out;
291 }
292
293 ivch_read(dvo, VR20, &priv->width);
294 ivch_read(dvo, VR21, &priv->height);
295
296
297
298
299 for (i = 0; i < ARRAY_SIZE(backup_addresses); i++)
300 ivch_read(dvo, backup_addresses[i], priv->reg_backup + i);
301
302 ivch_dump_regs(dvo);
303
304 return true;
305
306 out:
307 kfree(priv);
308 return false;
309 }
310
311 static enum drm_connector_status ivch_detect(struct intel_dvo_device *dvo)
312 {
313 return connector_status_connected;
314 }
315
316 static enum drm_mode_status ivch_mode_valid(struct intel_dvo_device *dvo,
317 struct drm_display_mode *mode)
318 {
319 if (mode->clock > 112000)
320 return MODE_CLOCK_HIGH;
321
322 return MODE_OK;
323 }
324
325
326
327
328
329 static void ivch_reset(struct intel_dvo_device *dvo)
330 {
331 struct ivch_priv *priv = dvo->dev_priv;
332 int i;
333
334 DRM_DEBUG_KMS("Resetting the IVCH registers\n");
335
336 ivch_write(dvo, VR10, 0x0000);
337
338 for (i = 0; i < ARRAY_SIZE(backup_addresses); i++)
339 ivch_write(dvo, backup_addresses[i], priv->reg_backup[i]);
340 }
341
342
343 static void ivch_dpms(struct intel_dvo_device *dvo, bool enable)
344 {
345 int i;
346 u16 vr01, vr30, backlight;
347
348 ivch_reset(dvo);
349
350
351 if (!ivch_read(dvo, VR01, &vr01))
352 return;
353
354 if (enable)
355 backlight = 1;
356 else
357 backlight = 0;
358
359 ivch_write(dvo, VR80, backlight);
360
361 if (enable)
362 vr01 |= VR01_LCD_ENABLE | VR01_DVO_ENABLE;
363 else
364 vr01 &= ~(VR01_LCD_ENABLE | VR01_DVO_ENABLE);
365
366 ivch_write(dvo, VR01, vr01);
367
368
369 for (i = 0; i < 100; i++) {
370 if (!ivch_read(dvo, VR30, &vr30))
371 break;
372
373 if (((vr30 & VR30_PANEL_ON) != 0) == enable)
374 break;
375 udelay(1000);
376 }
377
378 udelay(16 * 1000);
379 }
380
381 static bool ivch_get_hw_state(struct intel_dvo_device *dvo)
382 {
383 u16 vr01;
384
385 ivch_reset(dvo);
386
387
388 if (!ivch_read(dvo, VR01, &vr01))
389 return false;
390
391 if (vr01 & VR01_LCD_ENABLE)
392 return true;
393 else
394 return false;
395 }
396
397 static void ivch_mode_set(struct intel_dvo_device *dvo,
398 const struct drm_display_mode *mode,
399 const struct drm_display_mode *adjusted_mode)
400 {
401 struct ivch_priv *priv = dvo->dev_priv;
402 u16 vr40 = 0;
403 u16 vr01 = 0;
404 u16 vr10;
405
406 ivch_reset(dvo);
407
408 vr10 = priv->reg_backup[ARRAY_SIZE(backup_addresses) - 1];
409
410
411 vr10 &= VR10_INTERFACE_DEPTH_MASK;
412 if (vr10 == VR10_INTERFACE_2X18 || vr10 == VR10_INTERFACE_1X18)
413 vr01 = VR01_DITHER_ENABLE;
414
415 vr40 = (VR40_STALL_ENABLE | VR40_VERTICAL_INTERP_ENABLE |
416 VR40_HORIZONTAL_INTERP_ENABLE);
417
418 if (mode->hdisplay != adjusted_mode->crtc_hdisplay ||
419 mode->vdisplay != adjusted_mode->crtc_vdisplay) {
420 u16 x_ratio, y_ratio;
421
422 vr01 |= VR01_PANEL_FIT_ENABLE;
423 vr40 |= VR40_CLOCK_GATING_ENABLE;
424 x_ratio = (((mode->hdisplay - 1) << 16) /
425 (adjusted_mode->crtc_hdisplay - 1)) >> 2;
426 y_ratio = (((mode->vdisplay - 1) << 16) /
427 (adjusted_mode->crtc_vdisplay - 1)) >> 2;
428 ivch_write(dvo, VR42, x_ratio);
429 ivch_write(dvo, VR41, y_ratio);
430 } else {
431 vr01 &= ~VR01_PANEL_FIT_ENABLE;
432 vr40 &= ~VR40_CLOCK_GATING_ENABLE;
433 }
434 vr40 &= ~VR40_AUTO_RATIO_ENABLE;
435
436 ivch_write(dvo, VR01, vr01);
437 ivch_write(dvo, VR40, vr40);
438 }
439
440 static void ivch_dump_regs(struct intel_dvo_device *dvo)
441 {
442 u16 val;
443
444 ivch_read(dvo, VR00, &val);
445 DRM_DEBUG_KMS("VR00: 0x%04x\n", val);
446 ivch_read(dvo, VR01, &val);
447 DRM_DEBUG_KMS("VR01: 0x%04x\n", val);
448 ivch_read(dvo, VR10, &val);
449 DRM_DEBUG_KMS("VR10: 0x%04x\n", val);
450 ivch_read(dvo, VR30, &val);
451 DRM_DEBUG_KMS("VR30: 0x%04x\n", val);
452 ivch_read(dvo, VR40, &val);
453 DRM_DEBUG_KMS("VR40: 0x%04x\n", val);
454
455
456 ivch_read(dvo, VR80, &val);
457 DRM_DEBUG_KMS("VR80: 0x%04x\n", val);
458 ivch_read(dvo, VR81, &val);
459 DRM_DEBUG_KMS("VR81: 0x%04x\n", val);
460 ivch_read(dvo, VR82, &val);
461 DRM_DEBUG_KMS("VR82: 0x%04x\n", val);
462 ivch_read(dvo, VR83, &val);
463 DRM_DEBUG_KMS("VR83: 0x%04x\n", val);
464 ivch_read(dvo, VR84, &val);
465 DRM_DEBUG_KMS("VR84: 0x%04x\n", val);
466 ivch_read(dvo, VR85, &val);
467 DRM_DEBUG_KMS("VR85: 0x%04x\n", val);
468 ivch_read(dvo, VR86, &val);
469 DRM_DEBUG_KMS("VR86: 0x%04x\n", val);
470 ivch_read(dvo, VR87, &val);
471 DRM_DEBUG_KMS("VR87: 0x%04x\n", val);
472 ivch_read(dvo, VR88, &val);
473 DRM_DEBUG_KMS("VR88: 0x%04x\n", val);
474
475
476 ivch_read(dvo, VR8E, &val);
477 DRM_DEBUG_KMS("VR8E: 0x%04x\n", val);
478
479
480 ivch_read(dvo, VR8F, &val);
481 DRM_DEBUG_KMS("VR8F: 0x%04x\n", val);
482 }
483
484 static void ivch_destroy(struct intel_dvo_device *dvo)
485 {
486 struct ivch_priv *priv = dvo->dev_priv;
487
488 if (priv) {
489 kfree(priv);
490 dvo->dev_priv = NULL;
491 }
492 }
493
494 const struct intel_dvo_dev_ops ivch_ops = {
495 .init = ivch_init,
496 .dpms = ivch_dpms,
497 .get_hw_state = ivch_get_hw_state,
498 .mode_valid = ivch_mode_valid,
499 .mode_set = ivch_mode_set,
500 .detect = ivch_detect,
501 .dump_regs = ivch_dump_regs,
502 .destroy = ivch_destroy,
503 };