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#include "dvo.h"
30
31#define CH7xxx_REG_VID 0x4a
32#define CH7xxx_REG_DID 0x4b
33
34#define CH7011_VID 0x83
35#define CH7009A_VID 0x84
36#define CH7009B_VID 0x85
37#define CH7301_VID 0x95
38
39#define CH7xxx_VID 0x84
40#define CH7xxx_DID 0x17
41
42#define CH7xxx_NUM_REGS 0x4c
43
44#define CH7xxx_CM 0x1c
45#define CH7xxx_CM_XCM (1<<0)
46#define CH7xxx_CM_MCP (1<<2)
47#define CH7xxx_INPUT_CLOCK 0x1d
48#define CH7xxx_GPIO 0x1e
49#define CH7xxx_GPIO_HPIR (1<<3)
50#define CH7xxx_IDF 0x1f
51
52#define CH7xxx_IDF_HSP (1<<3)
53#define CH7xxx_IDF_VSP (1<<4)
54
55#define CH7xxx_CONNECTION_DETECT 0x20
56#define CH7xxx_CDET_DVI (1<<5)
57
58#define CH7301_DAC_CNTL 0x21
59#define CH7301_HOTPLUG 0x23
60#define CH7xxx_TCTL 0x31
61#define CH7xxx_TVCO 0x32
62#define CH7xxx_TPCP 0x33
63#define CH7xxx_TPD 0x34
64#define CH7xxx_TPVT 0x35
65#define CH7xxx_TLPF 0x36
66#define CH7xxx_TCT 0x37
67#define CH7301_TEST_PATTERN 0x48
68
69#define CH7xxx_PM 0x49
70#define CH7xxx_PM_FPD (1<<0)
71#define CH7301_PM_DACPD0 (1<<1)
72#define CH7301_PM_DACPD1 (1<<2)
73#define CH7301_PM_DACPD2 (1<<3)
74#define CH7xxx_PM_DVIL (1<<6)
75#define CH7xxx_PM_DVIP (1<<7)
76
77#define CH7301_SYNC_POLARITY 0x56
78#define CH7301_SYNC_RGB_YUV (1<<0)
79#define CH7301_SYNC_POL_DVI (1<<5)
80
81
82
83
84
85static struct ch7xxx_id_struct {
86 uint8_t vid;
87 char *name;
88} ch7xxx_ids[] = {
89 { CH7011_VID, "CH7011" },
90 { CH7009A_VID, "CH7009A" },
91 { CH7009B_VID, "CH7009B" },
92 { CH7301_VID, "CH7301" },
93};
94
95struct ch7xxx_reg_state {
96 uint8_t regs[CH7xxx_NUM_REGS];
97};
98
99struct ch7xxx_priv {
100 bool quiet;
101
102 struct ch7xxx_reg_state save_reg;
103 struct ch7xxx_reg_state mode_reg;
104 uint8_t save_TCTL, save_TPCP, save_TPD, save_TPVT;
105 uint8_t save_TLPF, save_TCT, save_PM, save_IDF;
106};
107
108static void ch7xxx_save(struct intel_dvo_device *dvo);
109
110static char *ch7xxx_get_id(uint8_t vid)
111{
112 int i;
113
114 for (i = 0; i < ARRAY_SIZE(ch7xxx_ids); i++) {
115 if (ch7xxx_ids[i].vid == vid)
116 return ch7xxx_ids[i].name;
117 }
118
119 return NULL;
120}
121
122
123static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
124{
125 struct ch7xxx_priv *ch7xxx= dvo->dev_priv;
126 struct i2c_adapter *adapter = dvo->i2c_bus;
127 struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
128 u8 out_buf[2];
129 u8 in_buf[2];
130
131 struct i2c_msg msgs[] = {
132 {
133 .addr = dvo->slave_addr,
134 .flags = 0,
135 .len = 1,
136 .buf = out_buf,
137 },
138 {
139 .addr = dvo->slave_addr,
140 .flags = I2C_M_RD,
141 .len = 1,
142 .buf = in_buf,
143 }
144 };
145
146 out_buf[0] = addr;
147 out_buf[1] = 0;
148
149 if (i2c_transfer(&i2cbus->adapter, msgs, 2) == 2) {
150 *ch = in_buf[0];
151 return true;
152 };
153
154 if (!ch7xxx->quiet) {
155 DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n",
156 addr, i2cbus->adapter.name, dvo->slave_addr);
157 }
158 return false;
159}
160
161
162static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
163{
164 struct ch7xxx_priv *ch7xxx = dvo->dev_priv;
165 struct i2c_adapter *adapter = dvo->i2c_bus;
166 struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
167 uint8_t out_buf[2];
168 struct i2c_msg msg = {
169 .addr = dvo->slave_addr,
170 .flags = 0,
171 .len = 2,
172 .buf = out_buf,
173 };
174
175 out_buf[0] = addr;
176 out_buf[1] = ch;
177
178 if (i2c_transfer(&i2cbus->adapter, &msg, 1) == 1)
179 return true;
180
181 if (!ch7xxx->quiet) {
182 DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n",
183 addr, i2cbus->adapter.name, dvo->slave_addr);
184 }
185
186 return false;
187}
188
189static bool ch7xxx_init(struct intel_dvo_device *dvo,
190 struct i2c_adapter *adapter)
191{
192
193 struct ch7xxx_priv *ch7xxx;
194 uint8_t vendor, device;
195 char *name;
196
197 ch7xxx = kzalloc(sizeof(struct ch7xxx_priv), GFP_KERNEL);
198 if (ch7xxx == NULL)
199 return false;
200
201 dvo->i2c_bus = adapter;
202 dvo->dev_priv = ch7xxx;
203 ch7xxx->quiet = true;
204
205 if (!ch7xxx_readb(dvo, CH7xxx_REG_VID, &vendor))
206 goto out;
207
208 name = ch7xxx_get_id(vendor);
209 if (!name) {
210 DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n",
211 vendor, adapter->name, dvo->slave_addr);
212 goto out;
213 }
214
215
216 if (!ch7xxx_readb(dvo, CH7xxx_REG_DID, &device))
217 goto out;
218
219 if (device != CH7xxx_DID) {
220 DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n",
221 vendor, adapter->name, dvo->slave_addr);
222 goto out;
223 }
224
225 ch7xxx->quiet = false;
226 DRM_DEBUG("Detected %s chipset, vendor/device ID 0x%02x/0x%02x\n",
227 name, vendor, device);
228 return true;
229out:
230 kfree(ch7xxx);
231 return false;
232}
233
234static enum drm_connector_status ch7xxx_detect(struct intel_dvo_device *dvo)
235{
236 uint8_t cdet, orig_pm, pm;
237
238 ch7xxx_readb(dvo, CH7xxx_PM, &orig_pm);
239
240 pm = orig_pm;
241 pm &= ~CH7xxx_PM_FPD;
242 pm |= CH7xxx_PM_DVIL | CH7xxx_PM_DVIP;
243
244 ch7xxx_writeb(dvo, CH7xxx_PM, pm);
245
246 ch7xxx_readb(dvo, CH7xxx_CONNECTION_DETECT, &cdet);
247
248 ch7xxx_writeb(dvo, CH7xxx_PM, orig_pm);
249
250 if (cdet & CH7xxx_CDET_DVI)
251 return connector_status_connected;
252 return connector_status_disconnected;
253}
254
255static enum drm_mode_status ch7xxx_mode_valid(struct intel_dvo_device *dvo,
256 struct drm_display_mode *mode)
257{
258 if (mode->clock > 165000)
259 return MODE_CLOCK_HIGH;
260
261 return MODE_OK;
262}
263
264static void ch7xxx_mode_set(struct intel_dvo_device *dvo,
265 struct drm_display_mode *mode,
266 struct drm_display_mode *adjusted_mode)
267{
268 uint8_t tvco, tpcp, tpd, tlpf, idf;
269
270 if (mode->clock <= 65000) {
271 tvco = 0x23;
272 tpcp = 0x08;
273 tpd = 0x16;
274 tlpf = 0x60;
275 } else {
276 tvco = 0x2d;
277 tpcp = 0x06;
278 tpd = 0x26;
279 tlpf = 0xa0;
280 }
281
282 ch7xxx_writeb(dvo, CH7xxx_TCTL, 0x00);
283 ch7xxx_writeb(dvo, CH7xxx_TVCO, tvco);
284 ch7xxx_writeb(dvo, CH7xxx_TPCP, tpcp);
285 ch7xxx_writeb(dvo, CH7xxx_TPD, tpd);
286 ch7xxx_writeb(dvo, CH7xxx_TPVT, 0x30);
287 ch7xxx_writeb(dvo, CH7xxx_TLPF, tlpf);
288 ch7xxx_writeb(dvo, CH7xxx_TCT, 0x00);
289
290 ch7xxx_readb(dvo, CH7xxx_IDF, &idf);
291
292 idf &= ~(CH7xxx_IDF_HSP | CH7xxx_IDF_VSP);
293 if (mode->flags & DRM_MODE_FLAG_PHSYNC)
294 idf |= CH7xxx_IDF_HSP;
295
296 if (mode->flags & DRM_MODE_FLAG_PVSYNC)
297 idf |= CH7xxx_IDF_HSP;
298
299 ch7xxx_writeb(dvo, CH7xxx_IDF, idf);
300}
301
302
303static void ch7xxx_dpms(struct intel_dvo_device *dvo, int mode)
304{
305 if (mode == DRM_MODE_DPMS_ON)
306 ch7xxx_writeb(dvo, CH7xxx_PM, CH7xxx_PM_DVIL | CH7xxx_PM_DVIP);
307 else
308 ch7xxx_writeb(dvo, CH7xxx_PM, CH7xxx_PM_FPD);
309}
310
311static void ch7xxx_dump_regs(struct intel_dvo_device *dvo)
312{
313 struct ch7xxx_priv *ch7xxx = dvo->dev_priv;
314 int i;
315
316 for (i = 0; i < CH7xxx_NUM_REGS; i++) {
317 if ((i % 8) == 0 )
318 DRM_DEBUG("\n %02X: ", i);
319 DRM_DEBUG("%02X ", ch7xxx->mode_reg.regs[i]);
320 }
321}
322
323static void ch7xxx_save(struct intel_dvo_device *dvo)
324{
325 struct ch7xxx_priv *ch7xxx= dvo->dev_priv;
326
327 ch7xxx_readb(dvo, CH7xxx_TCTL, &ch7xxx->save_TCTL);
328 ch7xxx_readb(dvo, CH7xxx_TPCP, &ch7xxx->save_TPCP);
329 ch7xxx_readb(dvo, CH7xxx_TPD, &ch7xxx->save_TPD);
330 ch7xxx_readb(dvo, CH7xxx_TPVT, &ch7xxx->save_TPVT);
331 ch7xxx_readb(dvo, CH7xxx_TLPF, &ch7xxx->save_TLPF);
332 ch7xxx_readb(dvo, CH7xxx_PM, &ch7xxx->save_PM);
333 ch7xxx_readb(dvo, CH7xxx_IDF, &ch7xxx->save_IDF);
334}
335
336static void ch7xxx_restore(struct intel_dvo_device *dvo)
337{
338 struct ch7xxx_priv *ch7xxx = dvo->dev_priv;
339
340 ch7xxx_writeb(dvo, CH7xxx_TCTL, ch7xxx->save_TCTL);
341 ch7xxx_writeb(dvo, CH7xxx_TPCP, ch7xxx->save_TPCP);
342 ch7xxx_writeb(dvo, CH7xxx_TPD, ch7xxx->save_TPD);
343 ch7xxx_writeb(dvo, CH7xxx_TPVT, ch7xxx->save_TPVT);
344 ch7xxx_writeb(dvo, CH7xxx_TLPF, ch7xxx->save_TLPF);
345 ch7xxx_writeb(dvo, CH7xxx_IDF, ch7xxx->save_IDF);
346 ch7xxx_writeb(dvo, CH7xxx_PM, ch7xxx->save_PM);
347}
348
349static void ch7xxx_destroy(struct intel_dvo_device *dvo)
350{
351 struct ch7xxx_priv *ch7xxx = dvo->dev_priv;
352
353 if (ch7xxx) {
354 kfree(ch7xxx);
355 dvo->dev_priv = NULL;
356 }
357}
358
359struct intel_dvo_dev_ops ch7xxx_ops = {
360 .init = ch7xxx_init,
361 .detect = ch7xxx_detect,
362 .mode_valid = ch7xxx_mode_valid,
363 .mode_set = ch7xxx_mode_set,
364 .dpms = ch7xxx_dpms,
365 .dump_regs = ch7xxx_dump_regs,
366 .save = ch7xxx_save,
367 .restore = ch7xxx_restore,
368 .destroy = ch7xxx_destroy,
369};
370