xref: /netbsd-src/sys/dev/usb/emdtv.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /* $NetBSD: emdtv.c,v 1.9 2012/12/27 16:42:32 skrll Exp $ */
2 
3 /*-
4  * Copyright (c) 2008, 2011 Jared D. McNeill <jmcneill@invisible.ca>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: emdtv.c,v 1.9 2012/12/27 16:42:32 skrll Exp $");
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/device.h>
35 #include <sys/module.h>
36 #include <sys/conf.h>
37 
38 #include <dev/usb/usb.h>
39 #include <dev/usb/usbdi.h>
40 #include <dev/usb/usbdi_util.h>
41 #include <dev/usb/usbdivar.h>
42 #include <dev/usb/usbdevs.h>
43 
44 #include <dev/usb/emdtvvar.h>
45 #include <dev/usb/emdtvreg.h>
46 
47 static int	emdtv_match(device_t, cfdata_t, void *);
48 static void	emdtv_attach(device_t, device_t, void *);
49 static int	emdtv_detach(device_t, int);
50 static int	emdtv_rescan(device_t, const char *, const int *);
51 static void	emdtv_childdet(device_t, device_t);
52 static int	emdtv_activate(device_t, enum devact);
53 
54 static bool	emdtv_read_eeprom(struct emdtv_softc *);
55 static void	emdtv_board_setup(struct emdtv_softc *);
56 
57 static void	emdtv_default_board_init(struct emdtv_softc *);
58 
59 CFATTACH_DECL2_NEW(emdtv, sizeof(struct emdtv_softc),
60     emdtv_match, emdtv_attach, emdtv_detach, emdtv_activate,
61     emdtv_rescan, emdtv_childdet);
62 
63 static const struct usb_devno emdtv_devices[] = {
64 	{ USB_VENDOR_AMD,	USB_PRODUCT_AMD_TV_WONDER_600_USB },
65 	{ USB_VENDOR_PINNACLE,	USB_PRODUCT_PINNACLE_PCTV800E },
66 };
67 
68 int emdtv_debug_regs = 0;
69 
70 static int
71 emdtv_match(device_t parent, cfdata_t match, void *opaque)
72 {
73 	struct usb_attach_arg *uaa = opaque;
74 
75 	return usb_lookup(emdtv_devices, uaa->vendor, uaa->product) != NULL ?
76 	    UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
77 }
78 
79 static void
80 emdtv_attach(device_t parent, device_t self, void *opaque)
81 {
82 	struct emdtv_softc *sc = device_private(self);
83 	struct usb_attach_arg *uaa = opaque;
84 	usbd_device_handle dev = uaa->device;
85 	usbd_status status;
86 	char *devinfo;
87 
88 	devinfo = usbd_devinfo_alloc(dev, 0);
89 	aprint_naive("\n");
90 	aprint_normal(": %s\n", devinfo);
91 	usbd_devinfo_free(devinfo);
92 
93 	sc->sc_dev = self;
94 	sc->sc_udev = dev;
95 
96 	sc->sc_vendor = uaa->vendor;
97 	sc->sc_product = uaa->product;
98 
99 	emdtv_i2c_attach(sc);
100 
101 	emdtv_read_eeprom(sc);
102 
103 	sc->sc_board = emdtv_board_lookup(sc->sc_vendor, sc->sc_product);
104 	if (sc->sc_board == NULL) {
105 		aprint_error_dev(sc->sc_dev,
106 		    "unsupported board 0x%04x:0x%04x\n",
107 		    sc->sc_vendor, sc->sc_product);
108 		sc->sc_dying = true;
109 		return;
110 	}
111 
112 	emdtv_write_1(sc, 0x02, 0xa0, 0x23);
113 	if (emdtv_read_1(sc, UR_GET_STATUS, 0x05) != 0) {
114 		(void)emdtv_read_1(sc, 0x02, 0xa0);
115 		if (emdtv_read_1(sc, 0x02, 0xa0) & 0x08)
116 			aprint_debug_dev(sc->sc_dev,
117 			    "board requires manual gpio configuration\n");
118 	}
119 
120 	emdtv_board_setup(sc);
121 
122 	emdtv_gpio_ctl(sc, EMDTV_GPIO_ANALOG_ON, false);
123 	emdtv_gpio_ctl(sc, EMDTV_GPIO_TS1_ON, false);
124 	usbd_delay_ms(sc->sc_udev, 100);
125 	emdtv_gpio_ctl(sc, EMDTV_GPIO_ANALOG_ON, true);
126 	emdtv_gpio_ctl(sc, EMDTV_GPIO_TUNER1_ON, true);
127 	usbd_delay_ms(sc->sc_udev, 100);
128 
129 	status = usbd_set_config_no(sc->sc_udev, 1, 1);
130         if (status != USBD_NORMAL_COMPLETION) {
131 		aprint_error_dev(sc->sc_dev, "failed to set configuration"
132 		    ", err=%s\n", usbd_errstr(status));
133 		return;
134 	}
135 
136 	status = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface);
137 	if (status != USBD_NORMAL_COMPLETION) {
138 		aprint_error_dev(sc->sc_dev, "couldn't find iface handle\n");
139 		return;
140 	}
141 
142 	status = usbd_set_interface(sc->sc_iface, 1);
143 	if (status != USBD_NORMAL_COMPLETION) {
144 		aprint_error_dev(sc->sc_dev, "couldn't set interface\n");
145 		return;
146 	}
147 
148 	emdtv_dtv_attach(sc);
149 	emdtv_ir_attach(sc);
150 }
151 
152 static int
153 emdtv_detach(device_t self, int flags)
154 {
155 	struct emdtv_softc *sc = device_private(self);
156 	usbd_status status;
157 
158 	sc->sc_dying = true;
159 
160 	emdtv_ir_detach(sc, flags);
161 	emdtv_dtv_detach(sc, flags);
162 
163 	if (sc->sc_iface != NULL) {
164         	status = usbd_set_interface(sc->sc_iface, 0);
165 		if (status != USBD_NORMAL_COMPLETION)
166 			aprint_error_dev(sc->sc_dev,
167 			    "couldn't stop stream: %s\n", usbd_errstr(status));
168 	}
169 
170 	emdtv_i2c_detach(sc, flags);
171 
172 	return 0;
173 }
174 
175 int
176 emdtv_activate(device_t self, enum devact act)
177 {
178 	struct emdtv_softc *sc = device_private(self);
179 
180 	switch (act) {
181 	case DVACT_DEACTIVATE:
182 		sc->sc_dying = true;
183 		break;
184 	}
185 
186 	return 0;
187 }
188 
189 static int
190 emdtv_rescan(device_t self, const char *ifattr, const int *locs)
191 {
192 	struct emdtv_softc *sc = device_private(self);
193 
194 	emdtv_dtv_rescan(sc, ifattr, locs);
195 
196 	return 0;
197 }
198 
199 static void
200 emdtv_childdet(device_t self, device_t child)
201 {
202 	struct emdtv_softc *sc = device_private(self);
203 
204 	if (child == sc->sc_cirdev)
205 		sc->sc_cirdev = NULL;
206 	if (child == sc->sc_dtvdev)
207 		sc->sc_dtvdev = NULL;
208 }
209 
210 static bool
211 emdtv_read_eeprom(struct emdtv_softc *sc)
212 {
213 	i2c_addr_t ee = EM28XX_I2C_ADDR_EEPROM;
214 	uint8_t buf, *p = sc->sc_eeprom;
215 	struct emdtv_eeprom *eeprom = (struct emdtv_eeprom *)sc->sc_eeprom;
216 	int block, size = sizeof(sc->sc_eeprom);
217 
218 	if (iic_exec(&sc->sc_i2c, I2C_OP_READ, ee, NULL, 0, NULL, 0, 0))
219 		return false;
220 	buf = 0;
221 	if (iic_exec(&sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, ee, &buf, 1,
222 	    NULL, 0, 0))
223 		return false;
224 	while (size > 0) {
225 		block = min(size, 16);
226 		if (iic_exec(&sc->sc_i2c, I2C_OP_READ, ee, NULL, 0,
227 		    p, block, 0))
228 			return false;
229 		size -= block;
230 		p += block;
231 	}
232 
233 	aprint_normal_dev(sc->sc_dev,
234 	    "id 0x%08x vendor 0x%04x product 0x%04x\n",
235 	    eeprom->id, eeprom->vendor, eeprom->product);
236 
237 	sc->sc_vendor = eeprom->vendor;
238 	sc->sc_product = eeprom->product;
239 
240 	return true;
241 }
242 
243 static void
244 emdtv_board_setup(struct emdtv_softc *sc)
245 {
246 	switch (sc->sc_vendor) {
247 	case USB_VENDOR_EMPIA:
248 		switch (sc->sc_product) {
249 		case USB_PRODUCT_EMPIA_EM2883:
250 			emdtv_write_1(sc, UR_GET_STATUS, EM28XX_XCLK_REG, 0x97);
251 			emdtv_write_1(sc, UR_GET_STATUS, EM28XX_I2C_CLK_REG,
252 			    0x40);
253 			delay(10000);
254 			emdtv_write_1(sc, UR_GET_STATUS, 0x08, 0x2d);
255 			delay(10000);
256 			break;
257 		default:
258 			aprint_normal_dev(sc->sc_dev,
259 			    "unknown EMPIA board 0x%04x/0x%04x\n",
260 			    sc->sc_vendor, sc->sc_product);
261 			break;
262 		}
263 		break;
264 	case USB_VENDOR_AMD:
265 		switch (sc->sc_product) {
266 		case USB_PRODUCT_AMD_TV_WONDER_600_USB:
267 			emdtv_default_board_init(sc);
268 			break;
269 		default:
270 			aprint_normal_dev(sc->sc_dev,
271 			    "unknown AMD board 0x%04x/0x%04x\n",
272 			    sc->sc_vendor, sc->sc_product);
273 		}
274 		break;
275 	case USB_VENDOR_PINNACLE:
276 		switch (sc->sc_product) {
277 		case USB_PRODUCT_PINNACLE_PCTV800E:
278 			emdtv_default_board_init(sc);
279 			break;
280 		default:
281 			aprint_normal_dev(sc->sc_dev,
282 			    "unknown Pinnacle board 0x%04x/0x%04x\n",
283 			    sc->sc_vendor, sc->sc_product);
284 		}
285 		break;
286 	default:
287 		aprint_normal_dev(sc->sc_dev,
288 		    "unknown board 0x%04x:0x%04x\n",
289 		    sc->sc_vendor, sc->sc_product);
290 		break;
291 	}
292 }
293 
294 /*
295  * Register read/write
296  */
297 uint8_t
298 emdtv_read_1(struct emdtv_softc *sc, uint8_t req, uint16_t index)
299 {
300 	uint8_t val;
301 	emdtv_read_multi_1(sc, req, index, &val, 1);
302 	return val;
303 }
304 
305 void
306 emdtv_write_1(struct emdtv_softc *sc, uint8_t req, uint16_t index, uint8_t val)
307 {
308 	emdtv_write_multi_1(sc, req, index, &val, 1);
309 }
310 
311 void
312 emdtv_read_multi_1(struct emdtv_softc *sc, uint8_t req, uint16_t index,
313     uint8_t *datap, uint16_t count)
314 {
315 	usb_device_request_t request;
316 	usbd_status status;
317 
318 	request.bmRequestType = UT_READ_VENDOR_DEVICE;
319 	request.bRequest = req;
320 	USETW(request.wValue, 0x0000);
321 	USETW(request.wIndex, index);
322 	USETW(request.wLength, count);
323 
324 	KERNEL_LOCK(1, curlwp);
325 	status = usbd_do_request(sc->sc_udev, &request, datap);
326 	KERNEL_UNLOCK_ONE(curlwp);
327 
328 	if (status != USBD_NORMAL_COMPLETION)
329 		aprint_error_dev(sc->sc_dev, "couldn't read %x/%x: %s\n",
330 		    req, index, usbd_errstr(status));
331 
332 	if (emdtv_debug_regs) {
333 		int i;
334 		printf("%s [%s] c0 %02x 00 00 %02x 00 01 00 <<<",
335 		    __func__, status == 0 ? " OK" : "NOK", req, index);
336 		for (i = 0; status == 0 && i < count; i++)
337 			printf(" %02x", datap[i]);
338 		printf("\n");
339 	}
340 }
341 
342 void
343 emdtv_write_multi_1(struct emdtv_softc *sc, uint8_t req, uint16_t index,
344     const uint8_t *datap, uint16_t count)
345 {
346 	usb_device_request_t request;
347 	usbd_status status;
348 
349 	request.bmRequestType = UT_WRITE_VENDOR_DEVICE;
350 	request.bRequest = req;
351 	USETW(request.wValue, 0x0000);
352 	USETW(request.wIndex, index);
353 	USETW(request.wLength, count);
354 
355 	KERNEL_LOCK(1, curlwp);
356 	status = usbd_do_request(sc->sc_udev, &request, __UNCONST(datap));
357 	KERNEL_UNLOCK_ONE(curlwp);
358 
359 	if (status != USBD_NORMAL_COMPLETION)
360 		aprint_error_dev(sc->sc_dev, "couldn't read %x/%x: %s\n",
361 		    req, index, usbd_errstr(status));
362 
363 	if (emdtv_debug_regs) {
364 		int i;
365 		printf("%s [%s] 40 %02x 00 00 %02x 00 %02x 00 >>>",
366 		    __func__, status == 0 ? " OK" : "NOK",
367 		    req, index, count);
368 		for (i = 0; i < count; ++i)
369 			printf(" %02x", datap[i]);
370 		printf("\n");
371 	}
372 }
373 
374 bool
375 emdtv_gpio_ctl(struct emdtv_softc *sc, emdtv_gpio_reg_t gpioreg, bool onoff)
376 {
377 	const struct emdtv_board *eb = sc->sc_board;
378 	uint16_t gpio_value, reg;
379 	uint8_t gpio;
380 	uint8_t eeprom_offset = 0x3c;
381 	uint8_t val;
382 
383 	if (sc->sc_board->eb_manual_gpio == false) {
384 		val = eeprom_offset + gpioreg;
385 		emdtv_write_1(sc, 0x03, 0xa0, val);
386 		gpio_value = emdtv_read_1(sc, 0x02, 0xa0);
387 	} else {
388 		const struct emdtv_gpio_regs *r = &eb->eb_gpio_regs;
389 		switch (gpioreg) {
390 		case EMDTV_GPIO_TS1_ON:
391 			gpio_value = r->ts1_on;
392 			break;
393 		case EMDTV_GPIO_ANALOG_ON:
394 			gpio_value = r->a_on;
395 			break;
396 		case EMDTV_GPIO_TUNER1_ON:
397 			gpio_value = r->t1_on;
398 			break;
399 		case EMDTV_GPIO_TUNER1_RESET:
400 			gpio_value = r->t1_reset;
401 				break;
402 		case EMDTV_GPIO_DEMOD1_RESET:
403 			gpio_value = r->d1_reset;
404 			break;
405 		default:
406 			aprint_error_dev(sc->sc_dev,
407 			    "unknown gpio reg %d\n", gpioreg);
408 			return false;
409 		}
410 	}
411 
412 	if ((gpio_value & 0x80) == 0) {
413 		aprint_error_dev(sc->sc_dev,
414 		    "gpio reg %d not enabled\n", gpioreg);
415 		return false;
416 	}
417 
418 	reg = gpio_value & 0x10 ? 0x04 : 0x08;
419 	gpio = emdtv_read_1(sc, UR_GET_STATUS, reg);
420 	if ((gpio_value & 0x40) == 0) {
421 		gpio &= ~((uint8_t)(1 << (gpio_value & 7)));
422 
423 		if (onoff)
424 			gpio |= ((gpio_value >> 5) & 1) << (gpio_value & 7);
425 		else
426 			gpio |= (((gpio_value >> 5) & 1) ^ 1) <<
427 			    (gpio_value & 7);
428 		emdtv_write_1(sc, UR_GET_STATUS, reg, gpio);
429 	} else {
430 		gpio &= ~((uint8_t)(1 << (gpio_value & 0xf)));
431 
432 		gpio |= ((gpio_value >> 5) & 1) << (gpio_value & 7);
433 		emdtv_write_1(sc, UR_GET_STATUS, reg, gpio);
434 		usbd_delay_ms(sc->sc_udev, 100);
435 
436 		gpio &= ~((uint8_t)(1 << (gpio_value & 0xf)));
437 		gpio |= (((gpio_value >> 5) & 1) ^ 1) << (gpio_value & 7);
438 		emdtv_write_1(sc, UR_GET_STATUS, reg, gpio);
439 		usbd_delay_ms(sc->sc_udev, 100);
440 	}
441 
442 	return true;
443 }
444 
445 static void
446 emdtv_default_board_init(struct emdtv_softc *sc)
447 {
448 	emdtv_write_1(sc, UR_GET_STATUS, EM28XX_XCLK_REG, 0x27);
449 	emdtv_write_1(sc, UR_GET_STATUS, EM28XX_I2C_CLK_REG, 0x40);
450 	emdtv_write_1(sc, UR_GET_STATUS, 0x08, 0xff);
451 	emdtv_write_1(sc, UR_GET_STATUS, 0x04, 0x00);
452 	usbd_delay_ms(sc->sc_udev, 100);
453 	emdtv_write_1(sc, UR_GET_STATUS, 0x04, 0x08);
454 	usbd_delay_ms(sc->sc_udev, 100);
455 	emdtv_write_1(sc, UR_GET_STATUS, 0x08, 0xff);
456 	usbd_delay_ms(sc->sc_udev, 50);
457 	emdtv_write_1(sc, UR_GET_STATUS, 0x08, 0x2d);
458 	usbd_delay_ms(sc->sc_udev, 50);
459 	emdtv_write_1(sc, UR_GET_STATUS, 0x08, 0x3d);
460 	//emdtv_write_1(sc, UR_GET_STATUS, 0x0f, 0xa7);
461 	usbd_delay_ms(sc->sc_udev, 10);
462 }
463 
464 MODULE(MODULE_CLASS_DRIVER, emdtv, "cir,lg3303,xc3028");
465 
466 #ifdef _MODULE
467 #include "ioconf.c"
468 #endif
469 
470 static int
471 emdtv_modcmd(modcmd_t cmd, void *opaque)
472 {
473 	switch (cmd) {
474 	case MODULE_CMD_INIT:
475 #ifdef _MODULE
476 		return config_init_component(cfdriver_ioconf_emdtv,
477 		    cfattach_ioconf_emdtv, cfdata_ioconf_emdtv);
478 #else
479 		return 0;
480 #endif
481 	case MODULE_CMD_FINI:
482 #ifdef _MODULE
483 		return config_fini_component(cfdriver_ioconf_emdtv,
484 		    cfattach_ioconf_emdtv, cfdata_ioconf_emdtv);
485 #else
486 		return 0;
487 #endif
488 	default:
489 		return ENOTTY;
490 	}
491 }
492