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