xref: /dragonfly/sys/dev/drm/i915/dvo_ns2501.c (revision 279dd846)
1 /*
2  *
3  * Copyright (c) 2012 Gilles Dartiguelongue, Thomas Richter
4  *
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sub license, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice (including the
16  * next paragraph) shall be included in all copies or substantial portions
17  * of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
23  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  *
27  */
28 
29 #include "dvo.h"
30 #include "i915_reg.h"
31 #include "i915_drv.h"
32 
33 #define NS2501_VID 0x1305
34 #define NS2501_DID 0x6726
35 
36 #define NS2501_VID_LO 0x00
37 #define NS2501_VID_HI 0x01
38 #define NS2501_DID_LO 0x02
39 #define NS2501_DID_HI 0x03
40 #define NS2501_REV 0x04
41 #define NS2501_RSVD 0x05
42 #define NS2501_FREQ_LO 0x06
43 #define NS2501_FREQ_HI 0x07
44 
45 #define NS2501_REG8 0x08
46 #define NS2501_8_VEN (1<<5)
47 #define NS2501_8_HEN (1<<4)
48 #define NS2501_8_DSEL (1<<3)
49 #define NS2501_8_BPAS (1<<2)
50 #define NS2501_8_RSVD (1<<1)
51 #define NS2501_8_PD (1<<0)
52 
53 #define NS2501_REG9 0x09
54 #define NS2501_9_VLOW (1<<7)
55 #define NS2501_9_MSEL_MASK (0x7<<4)
56 #define NS2501_9_TSEL (1<<3)
57 #define NS2501_9_RSEN (1<<2)
58 #define NS2501_9_RSVD (1<<1)
59 #define NS2501_9_MDI (1<<0)
60 
61 #define NS2501_REGC 0x0c
62 
63 struct ns2501_priv {
64 	//I2CDevRec d;
65 	bool quiet;
66 	int reg_8_shadow;
67 	int reg_8_set;
68 	// Shadow registers for i915
69 	int dvoc;
70 	int pll_a;
71 	int srcdim;
72 	int fw_blc;
73 };
74 
75 #define NSPTR(d) ((NS2501Ptr)(d->DriverPrivate.ptr))
76 
77 /*
78  * For reasons unclear to me, the ns2501 at least on the Fujitsu/Siemens
79  * laptops does not react on the i2c bus unless
80  * both the PLL is running and the display is configured in its native
81  * resolution.
82  * This function forces the DVO on, and stores the registers it touches.
83  * Afterwards, registers are restored to regular values.
84  *
85  * This is pretty much a hack, though it works.
86  * Without that, ns2501_readb and ns2501_writeb fail
87  * when switching the resolution.
88  */
89 
90 /*
91 ** Read a register from the ns2501.
92 ** Returns true if successful, false otherwise.
93 ** If it returns false, it might be wise to enable the
94 ** DVO with the above function.
95 */
96 static bool ns2501_readb(struct intel_dvo_device *dvo, int addr, uint8_t * ch)
97 {
98 	struct intel_iic_softc *sc;
99 	struct ns2501_priv *ns = dvo->dev_priv;
100 	struct i2c_adapter *adapter = dvo->i2c_bus;
101 	u8 out_buf[2];
102 	u8 in_buf[2];
103 
104 	struct i2c_msg msgs[] = {
105 		{
106 		 .slave = dvo->slave_addr << 1,
107 		 .flags = 0,
108 		 .len = 1,
109 		 .buf = out_buf,
110 		 },
111 		{
112 		 .slave = dvo->slave_addr << 1,
113 		 .flags = I2C_M_RD,
114 		 .len = 1,
115 		 .buf = in_buf,
116 		 }
117 	};
118 
119 	out_buf[0] = addr;
120 	out_buf[1] = 0;
121 
122 	sc = device_get_softc(adapter);
123 
124 	if (iicbus_transfer(adapter, msgs, 2) == 0) {
125 		*ch = in_buf[0];
126 		return true;
127 	}
128 
129 	if (!ns->quiet) {
130 		DRM_DEBUG_KMS
131 		    ("Unable to read register 0x%02x from %s:0x%02x.\n", addr,
132 		     sc->name, dvo->slave_addr);
133 	}
134 
135 	return false;
136 }
137 
138 /*
139 ** Write a register to the ns2501.
140 ** Returns true if successful, false otherwise.
141 ** If it returns false, it might be wise to enable the
142 ** DVO with the above function.
143 */
144 static bool ns2501_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
145 {
146 	struct intel_iic_softc *sc;
147 	struct ns2501_priv *ns = dvo->dev_priv;
148 	struct i2c_adapter *adapter = dvo->i2c_bus;
149 	uint8_t out_buf[2];
150 
151 	struct i2c_msg msg = {
152 		.slave = dvo->slave_addr << 1,
153 		.flags = 0,
154 		.len = 2,
155 		.buf = out_buf,
156 	};
157 
158 	out_buf[0] = addr;
159 	out_buf[1] = ch;
160 
161 	sc = device_get_softc(adapter);
162 
163 	if (iicbus_transfer(adapter, &msg, 1) == 0) {
164 		return true;
165 	}
166 
167 	if (!ns->quiet) {
168 		DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d\n",
169 			      addr, sc->name, dvo->slave_addr);
170 	}
171 
172 	return false;
173 }
174 
175 /* National Semiconductor 2501 driver for chip on i2c bus
176  * scan for the chip on the bus.
177  * Hope the VBIOS initialized the PLL correctly so we can
178  * talk to it. If not, it will not be seen and not detected.
179  * Bummer!
180  */
181 static bool ns2501_init(struct intel_dvo_device *dvo,
182 			struct i2c_adapter *adapter)
183 {
184 	struct intel_iic_softc *sc;
185 	/* this will detect the NS2501 chip on the specified i2c bus */
186 	struct ns2501_priv *ns;
187 	unsigned char ch;
188 
189 	sc = device_get_softc(adapter);
190 
191 	ns = kzalloc(sizeof(struct ns2501_priv), GFP_KERNEL);
192 	if (ns == NULL)
193 		return false;
194 
195 	dvo->i2c_bus = adapter;
196 	dvo->dev_priv = ns;
197 	ns->quiet = true;
198 
199 	if (!ns2501_readb(dvo, NS2501_VID_LO, &ch))
200 		goto out;
201 
202 	if (ch != (NS2501_VID & 0xff)) {
203 		DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
204 			      ch, sc->name, dvo->slave_addr);
205 		goto out;
206 	}
207 
208 	if (!ns2501_readb(dvo, NS2501_DID_LO, &ch))
209 		goto out;
210 
211 	if (ch != (NS2501_DID & 0xff)) {
212 		DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
213 			      ch, sc->name, dvo->slave_addr);
214 		goto out;
215 	}
216 	ns->quiet = false;
217 	ns->reg_8_set = 0;
218 	ns->reg_8_shadow =
219 	    NS2501_8_PD | NS2501_8_BPAS | NS2501_8_VEN | NS2501_8_HEN;
220 
221 	DRM_DEBUG_KMS("init ns2501 dvo controller successfully!\n");
222 	return true;
223 
224 out:
225 	kfree(ns);
226 	return false;
227 }
228 
229 static enum drm_connector_status ns2501_detect(struct intel_dvo_device *dvo)
230 {
231 	/*
232 	 * This is a Laptop display, it doesn't have hotplugging.
233 	 * Even if not, the detection bit of the 2501 is unreliable as
234 	 * it only works for some display types.
235 	 * It is even more unreliable as the PLL must be active for
236 	 * allowing reading from the chiop.
237 	 */
238 	return connector_status_connected;
239 }
240 
241 static enum drm_mode_status ns2501_mode_valid(struct intel_dvo_device *dvo,
242 					      struct drm_display_mode *mode)
243 {
244 	DRM_DEBUG_KMS
245 	    ("is mode valid (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d)\n",
246 	     mode->hdisplay, mode->htotal, mode->vdisplay, mode->vtotal);
247 
248 	/*
249 	 * Currently, these are all the modes I have data from.
250 	 * More might exist. Unclear how to find the native resolution
251 	 * of the panel in here so we could always accept it
252 	 * by disabling the scaler.
253 	 */
254 	if ((mode->hdisplay == 800 && mode->vdisplay == 600) ||
255 	    (mode->hdisplay == 640 && mode->vdisplay == 480) ||
256 	    (mode->hdisplay == 1024 && mode->vdisplay == 768)) {
257 		return MODE_OK;
258 	} else {
259 		return MODE_ONE_SIZE;	/* Is this a reasonable error? */
260 	}
261 }
262 
263 static void ns2501_mode_set(struct intel_dvo_device *dvo,
264 			    struct drm_display_mode *mode,
265 			    struct drm_display_mode *adjusted_mode)
266 {
267 	bool ok;
268 	int retries = 10;
269 	struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
270 
271 	DRM_DEBUG_KMS
272 	    ("set mode (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d).\n",
273 	     mode->hdisplay, mode->htotal, mode->vdisplay, mode->vtotal);
274 
275 	/*
276 	 * Where do I find the native resolution for which scaling is not required???
277 	 *
278 	 * First trigger the DVO on as otherwise the chip does not appear on the i2c
279 	 * bus.
280 	 */
281 	do {
282 		ok = true;
283 
284 		if (mode->hdisplay == 800 && mode->vdisplay == 600) {
285 			/* mode 277 */
286 			ns->reg_8_shadow &= ~NS2501_8_BPAS;
287 			DRM_DEBUG_KMS("switching to 800x600\n");
288 
289 			/*
290 			 * No, I do not know where this data comes from.
291 			 * It is just what the video bios left in the DVO, so
292 			 * I'm just copying it here over.
293 			 * This also means that I cannot support any other modes
294 			 * except the ones supported by the bios.
295 			 */
296 			ok &= ns2501_writeb(dvo, 0x11, 0xc8);	// 0xc7 also works.
297 			ok &= ns2501_writeb(dvo, 0x1b, 0x19);
298 			ok &= ns2501_writeb(dvo, 0x1c, 0x62);	// VBIOS left 0x64 here, but 0x62 works nicer
299 			ok &= ns2501_writeb(dvo, 0x1d, 0x02);
300 
301 			ok &= ns2501_writeb(dvo, 0x34, 0x03);
302 			ok &= ns2501_writeb(dvo, 0x35, 0xff);
303 
304 			ok &= ns2501_writeb(dvo, 0x80, 0x27);
305 			ok &= ns2501_writeb(dvo, 0x81, 0x03);
306 			ok &= ns2501_writeb(dvo, 0x82, 0x41);
307 			ok &= ns2501_writeb(dvo, 0x83, 0x05);
308 
309 			ok &= ns2501_writeb(dvo, 0x8d, 0x02);
310 			ok &= ns2501_writeb(dvo, 0x8e, 0x04);
311 			ok &= ns2501_writeb(dvo, 0x8f, 0x00);
312 
313 			ok &= ns2501_writeb(dvo, 0x90, 0xfe);	/* vertical. VBIOS left 0xff here, but 0xfe works better */
314 			ok &= ns2501_writeb(dvo, 0x91, 0x07);
315 			ok &= ns2501_writeb(dvo, 0x94, 0x00);
316 			ok &= ns2501_writeb(dvo, 0x95, 0x00);
317 
318 			ok &= ns2501_writeb(dvo, 0x96, 0x00);
319 
320 			ok &= ns2501_writeb(dvo, 0x99, 0x00);
321 			ok &= ns2501_writeb(dvo, 0x9a, 0x88);
322 
323 			ok &= ns2501_writeb(dvo, 0x9c, 0x23);	/* Looks like first and last line of the image. */
324 			ok &= ns2501_writeb(dvo, 0x9d, 0x00);
325 			ok &= ns2501_writeb(dvo, 0x9e, 0x25);
326 			ok &= ns2501_writeb(dvo, 0x9f, 0x03);
327 
328 			ok &= ns2501_writeb(dvo, 0xa4, 0x80);
329 
330 			ok &= ns2501_writeb(dvo, 0xb6, 0x00);
331 
332 			ok &= ns2501_writeb(dvo, 0xb9, 0xc8);	/* horizontal? */
333 			ok &= ns2501_writeb(dvo, 0xba, 0x00);	/* horizontal? */
334 
335 			ok &= ns2501_writeb(dvo, 0xc0, 0x05);	/* horizontal? */
336 			ok &= ns2501_writeb(dvo, 0xc1, 0xd7);
337 
338 			ok &= ns2501_writeb(dvo, 0xc2, 0x00);
339 			ok &= ns2501_writeb(dvo, 0xc3, 0xf8);
340 
341 			ok &= ns2501_writeb(dvo, 0xc4, 0x03);
342 			ok &= ns2501_writeb(dvo, 0xc5, 0x1a);
343 
344 			ok &= ns2501_writeb(dvo, 0xc6, 0x00);
345 			ok &= ns2501_writeb(dvo, 0xc7, 0x73);
346 			ok &= ns2501_writeb(dvo, 0xc8, 0x02);
347 
348 		} else if (mode->hdisplay == 640 && mode->vdisplay == 480) {
349 			/* mode 274 */
350 			DRM_DEBUG_KMS("switching to 640x480\n");
351 			/*
352 			 * No, I do not know where this data comes from.
353 			 * It is just what the video bios left in the DVO, so
354 			 * I'm just copying it here over.
355 			 * This also means that I cannot support any other modes
356 			 * except the ones supported by the bios.
357 			 */
358 			ns->reg_8_shadow &= ~NS2501_8_BPAS;
359 
360 			ok &= ns2501_writeb(dvo, 0x11, 0xa0);
361 			ok &= ns2501_writeb(dvo, 0x1b, 0x11);
362 			ok &= ns2501_writeb(dvo, 0x1c, 0x54);
363 			ok &= ns2501_writeb(dvo, 0x1d, 0x03);
364 
365 			ok &= ns2501_writeb(dvo, 0x34, 0x03);
366 			ok &= ns2501_writeb(dvo, 0x35, 0xff);
367 
368 			ok &= ns2501_writeb(dvo, 0x80, 0xff);
369 			ok &= ns2501_writeb(dvo, 0x81, 0x07);
370 			ok &= ns2501_writeb(dvo, 0x82, 0x3d);
371 			ok &= ns2501_writeb(dvo, 0x83, 0x05);
372 
373 			ok &= ns2501_writeb(dvo, 0x8d, 0x02);
374 			ok &= ns2501_writeb(dvo, 0x8e, 0x10);
375 			ok &= ns2501_writeb(dvo, 0x8f, 0x00);
376 
377 			ok &= ns2501_writeb(dvo, 0x90, 0xff);	/* vertical */
378 			ok &= ns2501_writeb(dvo, 0x91, 0x07);
379 			ok &= ns2501_writeb(dvo, 0x94, 0x00);
380 			ok &= ns2501_writeb(dvo, 0x95, 0x00);
381 
382 			ok &= ns2501_writeb(dvo, 0x96, 0x05);
383 
384 			ok &= ns2501_writeb(dvo, 0x99, 0x00);
385 			ok &= ns2501_writeb(dvo, 0x9a, 0x88);
386 
387 			ok &= ns2501_writeb(dvo, 0x9c, 0x24);
388 			ok &= ns2501_writeb(dvo, 0x9d, 0x00);
389 			ok &= ns2501_writeb(dvo, 0x9e, 0x25);
390 			ok &= ns2501_writeb(dvo, 0x9f, 0x03);
391 
392 			ok &= ns2501_writeb(dvo, 0xa4, 0x84);
393 
394 			ok &= ns2501_writeb(dvo, 0xb6, 0x09);
395 
396 			ok &= ns2501_writeb(dvo, 0xb9, 0xa0);	/* horizontal? */
397 			ok &= ns2501_writeb(dvo, 0xba, 0x00);	/* horizontal? */
398 
399 			ok &= ns2501_writeb(dvo, 0xc0, 0x05);	/* horizontal? */
400 			ok &= ns2501_writeb(dvo, 0xc1, 0x90);
401 
402 			ok &= ns2501_writeb(dvo, 0xc2, 0x00);
403 			ok &= ns2501_writeb(dvo, 0xc3, 0x0f);
404 
405 			ok &= ns2501_writeb(dvo, 0xc4, 0x03);
406 			ok &= ns2501_writeb(dvo, 0xc5, 0x16);
407 
408 			ok &= ns2501_writeb(dvo, 0xc6, 0x00);
409 			ok &= ns2501_writeb(dvo, 0xc7, 0x02);
410 			ok &= ns2501_writeb(dvo, 0xc8, 0x02);
411 
412 		} else if (mode->hdisplay == 1024 && mode->vdisplay == 768) {
413 			/* mode 280 */
414 			DRM_DEBUG_KMS("switching to 1024x768\n");
415 			/*
416 			 * This might or might not work, actually. I'm silently
417 			 * assuming here that the native panel resolution is
418 			 * 1024x768. If not, then this leaves the scaler disabled
419 			 * generating a picture that is likely not the expected.
420 			 *
421 			 * Problem is that I do not know where to take the panel
422 			 * dimensions from.
423 			 *
424 			 * Enable the bypass, scaling not required.
425 			 *
426 			 * The scaler registers are irrelevant here....
427 			 *
428 			 */
429 			ns->reg_8_shadow |= NS2501_8_BPAS;
430 			ok &= ns2501_writeb(dvo, 0x37, 0x44);
431 		} else {
432 			/*
433 			 * Data not known. Bummer!
434 			 * Hopefully, the code should not go here
435 			 * as mode_OK delivered no other modes.
436 			 */
437 			ns->reg_8_shadow |= NS2501_8_BPAS;
438 		}
439 		ok &= ns2501_writeb(dvo, NS2501_REG8, ns->reg_8_shadow);
440 	} while (!ok && retries--);
441 }
442 
443 /* set the NS2501 power state */
444 static bool ns2501_get_hw_state(struct intel_dvo_device *dvo)
445 {
446 	unsigned char ch;
447 
448 	if (!ns2501_readb(dvo, NS2501_REG8, &ch))
449 		return false;
450 
451 	if (ch & NS2501_8_PD)
452 		return true;
453 	else
454 		return false;
455 }
456 
457 /* set the NS2501 power state */
458 static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable)
459 {
460 	bool ok;
461 	int retries = 10;
462 	struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
463 	unsigned char ch;
464 
465 	DRM_DEBUG_KMS("Trying set the dpms of the DVO to %i\n", enable);
466 
467 	ch = ns->reg_8_shadow;
468 
469 	if (enable)
470 		ch |= NS2501_8_PD;
471 	else
472 		ch &= ~NS2501_8_PD;
473 
474 	if (ns->reg_8_set == 0 || ns->reg_8_shadow != ch) {
475 		ns->reg_8_set = 1;
476 		ns->reg_8_shadow = ch;
477 
478 		do {
479 			ok = true;
480 			ok &= ns2501_writeb(dvo, NS2501_REG8, ch);
481 			ok &=
482 			    ns2501_writeb(dvo, 0x34,
483 					  enable ? 0x03 : 0x00);
484 			ok &=
485 			    ns2501_writeb(dvo, 0x35,
486 					  enable ? 0xff : 0x00);
487 		} while (!ok && retries--);
488 	}
489 }
490 
491 static void ns2501_dump_regs(struct intel_dvo_device *dvo)
492 {
493 	uint8_t val;
494 
495 	ns2501_readb(dvo, NS2501_FREQ_LO, &val);
496 	DRM_DEBUG_KMS("NS2501_FREQ_LO: 0x%02x\n", val);
497 	ns2501_readb(dvo, NS2501_FREQ_HI, &val);
498 	DRM_DEBUG_KMS("NS2501_FREQ_HI: 0x%02x\n", val);
499 	ns2501_readb(dvo, NS2501_REG8, &val);
500 	DRM_DEBUG_KMS("NS2501_REG8: 0x%02x\n", val);
501 	ns2501_readb(dvo, NS2501_REG9, &val);
502 	DRM_DEBUG_KMS("NS2501_REG9: 0x%02x\n", val);
503 	ns2501_readb(dvo, NS2501_REGC, &val);
504 	DRM_DEBUG_KMS("NS2501_REGC: 0x%02x\n", val);
505 }
506 
507 static void ns2501_destroy(struct intel_dvo_device *dvo)
508 {
509 	struct ns2501_priv *ns = dvo->dev_priv;
510 
511 	if (ns) {
512 		kfree(ns);
513 		dvo->dev_priv = NULL;
514 	}
515 }
516 
517 struct intel_dvo_dev_ops ns2501_ops = {
518 	.init = ns2501_init,
519 	.detect = ns2501_detect,
520 	.mode_valid = ns2501_mode_valid,
521 	.mode_set = ns2501_mode_set,
522 	.dpms = ns2501_dpms,
523 	.get_hw_state = ns2501_get_hw_state,
524 	.dump_regs = ns2501_dump_regs,
525 	.destroy = ns2501_destroy,
526 };
527