xref: /netbsd-src/sys/dev/usb/emdtv.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1 /* $NetBSD: emdtv.c,v 1.4 2011/08/09 01:42:24 jmcneill 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.4 2011/08/09 01:42:24 jmcneill 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/usbdevs.h>
42 
43 #include <dev/usb/emdtvvar.h>
44 #include <dev/usb/emdtvreg.h>
45 
46 static int	emdtv_match(device_t, cfdata_t, void *);
47 static void	emdtv_attach(device_t, device_t, void *);
48 static int	emdtv_detach(device_t, int);
49 static int	emdtv_rescan(device_t, const char *, const int *);
50 static void	emdtv_childdet(device_t, device_t);
51 static int	emdtv_activate(device_t, enum devact);
52 
53 static bool	emdtv_read_eeprom(struct emdtv_softc *);
54 static void	emdtv_board_setup(struct emdtv_softc *);
55 
56 static void	emdtv_default_board_init(struct emdtv_softc *);
57 
58 CFATTACH_DECL2_NEW(emdtv, sizeof(struct emdtv_softc),
59     emdtv_match, emdtv_attach, emdtv_detach, emdtv_activate,
60     emdtv_rescan, emdtv_childdet);
61 
62 static const struct usb_devno emdtv_devices[] = {
63 	{ USB_VENDOR_AMD,	USB_PRODUCT_AMD_TV_WONDER_600_USB },
64 	{ USB_VENDOR_PINNACLE,	USB_PRODUCT_PINNACLE_PCTV800E },
65 };
66 
67 int emdtv_debug_regs = 0;
68 
69 static int
70 emdtv_match(device_t parent, cfdata_t match, void *opaque)
71 {
72 	struct usb_attach_arg *uaa = opaque;
73 
74 	return usb_lookup(emdtv_devices, uaa->vendor, uaa->product) != NULL ?
75 	    UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
76 }
77 
78 static void
79 emdtv_attach(device_t parent, device_t self, void *opaque)
80 {
81 	struct emdtv_softc *sc = device_private(self);
82 	struct usb_attach_arg *uaa = opaque;
83 	usbd_device_handle dev = uaa->device;
84 	usbd_status status;
85 	char *devinfo;
86 
87 	devinfo = usbd_devinfo_alloc(dev, 0);
88 	aprint_naive("\n");
89 	aprint_normal(": %s\n", devinfo);
90 	usbd_devinfo_free(devinfo);
91 
92 	sc->sc_dev = self;
93 	sc->sc_udev = dev;
94 
95 	sc->sc_vendor = uaa->vendor;
96 	sc->sc_product = uaa->product;
97 
98 	emdtv_i2c_attach(sc);
99 
100 	emdtv_read_eeprom(sc);
101 
102 	sc->sc_board = emdtv_board_lookup(sc->sc_vendor, sc->sc_product);
103 	if (sc->sc_board == NULL) {
104 		aprint_error_dev(sc->sc_dev,
105 		    "unsupported board 0x%04x:0x%04x\n",
106 		    sc->sc_vendor, sc->sc_product);
107 		sc->sc_dying = true;
108 		return;
109 	}
110 
111 	emdtv_write_1(sc, 0x02, 0xa0, 0x23);
112 	if (emdtv_read_1(sc, UR_GET_STATUS, 0x05) != 0) {
113 		(void)emdtv_read_1(sc, 0x02, 0xa0);
114 		if (emdtv_read_1(sc, 0x02, 0xa0) & 0x08)
115 			aprint_debug_dev(sc->sc_dev,
116 			    "board requires manual gpio configuration\n");
117 	}
118 
119 	emdtv_board_setup(sc);
120 
121 	emdtv_gpio_ctl(sc, EMDTV_GPIO_ANALOG_ON, false);
122 	emdtv_gpio_ctl(sc, EMDTV_GPIO_TS1_ON, false);
123 	usbd_delay_ms(sc->sc_udev, 100);
124 	emdtv_gpio_ctl(sc, EMDTV_GPIO_ANALOG_ON, true);
125 	emdtv_gpio_ctl(sc, EMDTV_GPIO_TUNER1_ON, true);
126 	usbd_delay_ms(sc->sc_udev, 100);
127 
128 	status = usbd_set_config_no(sc->sc_udev, 1, 1);
129         if (status != USBD_NORMAL_COMPLETION) {
130 		aprint_error_dev(sc->sc_dev, "couldn't set config no\n");
131 		return;
132 	}
133 
134 	status = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface);
135 	if (status != USBD_NORMAL_COMPLETION) {
136 		aprint_error_dev(sc->sc_dev, "couldn't find iface handle\n");
137 		return;
138 	}
139 
140 	status = usbd_set_interface(sc->sc_iface, 1);
141 	if (status != USBD_NORMAL_COMPLETION) {
142 		aprint_error_dev(sc->sc_dev, "couldn't set interface\n");
143 		return;
144 	}
145 
146 	emdtv_dtv_attach(sc);
147 	emdtv_ir_attach(sc);
148 }
149 
150 static int
151 emdtv_detach(device_t self, int flags)
152 {
153 	struct emdtv_softc *sc = device_private(self);
154 	usbd_status status;
155 
156 	sc->sc_dying = true;
157 
158 	emdtv_ir_detach(sc, flags);
159 	emdtv_dtv_detach(sc, flags);
160 
161 	if (sc->sc_iface != NULL) {
162         	status = usbd_set_interface(sc->sc_iface, 0);
163 		if (status != USBD_NORMAL_COMPLETION)
164 			aprint_error_dev(sc->sc_dev,
165 			    "couldn't stop stream: %s\n", usbd_errstr(status));
166 	}
167 
168 	emdtv_i2c_detach(sc, flags);
169 
170 	return 0;
171 }
172 
173 int
174 emdtv_activate(device_t self, enum devact act)
175 {
176 	struct emdtv_softc *sc = device_private(self);
177 
178 	switch (act) {
179 	case DVACT_DEACTIVATE:
180 		sc->sc_dying = true;
181 		break;
182 	}
183 
184 	return 0;
185 }
186 
187 static int
188 emdtv_rescan(device_t self, const char *ifattr, const int *locs)
189 {
190 	struct emdtv_softc *sc = device_private(self);
191 
192 	emdtv_dtv_rescan(sc, ifattr, locs);
193 
194 	return 0;
195 }
196 
197 static void
198 emdtv_childdet(device_t self, device_t child)
199 {
200 	struct emdtv_softc *sc = device_private(self);
201 
202 	if (child == sc->sc_cirdev)
203 		sc->sc_cirdev = NULL;
204 	if (child == sc->sc_dtvdev)
205 		sc->sc_dtvdev = NULL;
206 }
207 
208 static bool
209 emdtv_read_eeprom(struct emdtv_softc *sc)
210 {
211 	i2c_addr_t ee = EM28XX_I2C_ADDR_EEPROM;
212 	uint8_t buf, *p = sc->sc_eeprom;
213 	struct emdtv_eeprom *eeprom = (struct emdtv_eeprom *)sc->sc_eeprom;
214 	int block, size = sizeof(sc->sc_eeprom);
215 
216 	if (iic_exec(&sc->sc_i2c, I2C_OP_READ, ee, NULL, 0, NULL, 0, 0))
217 		return false;
218 	buf = 0;
219 	if (iic_exec(&sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, ee, &buf, 1,
220 	    NULL, 0, 0))
221 		return false;
222 	while (size > 0) {
223 		block = min(size, 16);
224 		if (iic_exec(&sc->sc_i2c, I2C_OP_READ, ee, NULL, 0,
225 		    p, block, 0))
226 			return false;
227 		size -= block;
228 		p += block;
229 	}
230 
231 	aprint_normal_dev(sc->sc_dev,
232 	    "id 0x%08x vendor 0x%04x product 0x%04x\n",
233 	    eeprom->id, eeprom->vendor, eeprom->product);
234 
235 	sc->sc_vendor = eeprom->vendor;
236 	sc->sc_product = eeprom->product;
237 
238 	return true;
239 }
240 
241 static void
242 emdtv_board_setup(struct emdtv_softc *sc)
243 {
244 	switch (sc->sc_vendor) {
245 	case USB_VENDOR_EMPIA:
246 		switch (sc->sc_product) {
247 		case USB_PRODUCT_EMPIA_EM2883:
248 			emdtv_write_1(sc, UR_GET_STATUS, EM28XX_XCLK_REG, 0x97);
249 			emdtv_write_1(sc, UR_GET_STATUS, EM28XX_I2C_CLK_REG,
250 			    0x40);
251 			delay(10000);
252 			emdtv_write_1(sc, UR_GET_STATUS, 0x08, 0x2d);
253 			delay(10000);
254 			break;
255 		default:
256 			aprint_normal_dev(sc->sc_dev,
257 			    "unknown EMPIA board 0x%04x/0x%04x\n",
258 			    sc->sc_vendor, sc->sc_product);
259 			break;
260 		}
261 		break;
262 	case USB_VENDOR_AMD:
263 		switch (sc->sc_product) {
264 		case USB_PRODUCT_AMD_TV_WONDER_600_USB:
265 			emdtv_default_board_init(sc);
266 			break;
267 		default:
268 			aprint_normal_dev(sc->sc_dev,
269 			    "unknown AMD board 0x%04x/0x%04x\n",
270 			    sc->sc_vendor, sc->sc_product);
271 		}
272 		break;
273 	case USB_VENDOR_PINNACLE:
274 		switch (sc->sc_product) {
275 		case USB_PRODUCT_PINNACLE_PCTV800E:
276 			emdtv_default_board_init(sc);
277 			break;
278 		default:
279 			aprint_normal_dev(sc->sc_dev,
280 			    "unknown Pinnacle board 0x%04x/0x%04x\n",
281 			    sc->sc_vendor, sc->sc_product);
282 		}
283 		break;
284 	default:
285 		aprint_normal_dev(sc->sc_dev,
286 		    "unknown board 0x%04x:0x%04x\n",
287 		    sc->sc_vendor, sc->sc_product);
288 		break;
289 	}
290 }
291 
292 /*
293  * Register read/write
294  */
295 uint8_t
296 emdtv_read_1(struct emdtv_softc *sc, uint8_t req, uint16_t index)
297 {
298 	uint8_t val;
299 	emdtv_read_multi_1(sc, req, index, &val, 1);
300 	return val;
301 }
302 
303 void
304 emdtv_write_1(struct emdtv_softc *sc, uint8_t req, uint16_t index, uint8_t val)
305 {
306 	emdtv_write_multi_1(sc, req, index, &val, 1);
307 }
308 
309 void
310 emdtv_read_multi_1(struct emdtv_softc *sc, uint8_t req, uint16_t index,
311     uint8_t *datap, uint16_t count)
312 {
313 	usb_device_request_t request;
314 	usbd_status status;
315 
316 	request.bmRequestType = UT_READ_VENDOR_DEVICE;
317 	request.bRequest = req;
318 	USETW(request.wValue, 0x0000);
319 	USETW(request.wIndex, index);
320 	USETW(request.wLength, count);
321 
322 	status = usbd_do_request(sc->sc_udev, &request, datap);
323 	if (status != USBD_NORMAL_COMPLETION)
324 		aprint_error_dev(sc->sc_dev, "couldn't read %x/%x: %s\n",
325 		    req, index, usbd_errstr(status));
326 
327 	if (emdtv_debug_regs) {
328 		int i;
329 		printf("%s [%s] c0 %02x 00 00 %02x 00 01 00 <<<",
330 		    __func__, status == 0 ? " OK" : "NOK", req, index);
331 		for (i = 0; status == 0 && i < count; i++)
332 			printf(" %02x", datap[i]);
333 		printf("\n");
334 	}
335 }
336 
337 void
338 emdtv_write_multi_1(struct emdtv_softc *sc, uint8_t req, uint16_t index,
339     const uint8_t *datap, uint16_t count)
340 {
341 	usb_device_request_t request;
342 	usbd_status status;
343 
344 	request.bmRequestType = UT_WRITE_VENDOR_DEVICE;
345 	request.bRequest = req;
346 	USETW(request.wValue, 0x0000);
347 	USETW(request.wIndex, index);
348 	USETW(request.wLength, count);
349 
350 	status = usbd_do_request(sc->sc_udev, &request, __UNCONST(datap));
351 	if (status != USBD_NORMAL_COMPLETION)
352 		aprint_error_dev(sc->sc_dev, "couldn't read %x/%x: %s\n",
353 		    req, index, usbd_errstr(status));
354 
355 	if (emdtv_debug_regs) {
356 		int i;
357 		printf("%s [%s] 40 %02x 00 00 %02x 00 %02x 00 >>>",
358 		    __func__, status == 0 ? " OK" : "NOK",
359 		    req, index, count);
360 		for (i = 0; i < count; ++i)
361 			printf(" %02x", datap[i]);
362 		printf("\n");
363 	}
364 }
365 
366 bool
367 emdtv_gpio_ctl(struct emdtv_softc *sc, emdtv_gpio_reg_t gpioreg, bool onoff)
368 {
369 	const struct emdtv_board *eb = sc->sc_board;
370 	uint16_t gpio_value, reg;
371 	uint8_t gpio;
372 	uint8_t eeprom_offset = 0x3c;
373 	uint8_t val;
374 
375 	if (sc->sc_board->eb_manual_gpio == false) {
376 		val = eeprom_offset + gpioreg;
377 		emdtv_write_1(sc, 0x03, 0xa0, val);
378 		gpio_value = emdtv_read_1(sc, 0x02, 0xa0);
379 	} else {
380 		const struct emdtv_gpio_regs *r = &eb->eb_gpio_regs;
381 		switch (gpioreg) {
382 		case EMDTV_GPIO_TS1_ON:
383 			gpio_value = r->ts1_on;
384 			break;
385 		case EMDTV_GPIO_ANALOG_ON:
386 			gpio_value = r->a_on;
387 			break;
388 		case EMDTV_GPIO_TUNER1_ON:
389 			gpio_value = r->t1_on;
390 			break;
391 		case EMDTV_GPIO_TUNER1_RESET:
392 			gpio_value = r->t1_reset;
393 				break;
394 		case EMDTV_GPIO_DEMOD1_RESET:
395 			gpio_value = r->d1_reset;
396 			break;
397 		default:
398 			aprint_error_dev(sc->sc_dev,
399 			    "unknown gpio reg %d\n", gpioreg);
400 			return false;
401 		}
402 	}
403 
404 	if ((gpio_value & 0x80) == 0) {
405 		aprint_error_dev(sc->sc_dev,
406 		    "gpio reg %d not enabled\n", gpioreg);
407 		return false;
408 	}
409 
410 	reg = gpio_value & 0x10 ? 0x04 : 0x08;
411 	gpio = emdtv_read_1(sc, UR_GET_STATUS, reg);
412 	if ((gpio_value & 0x40) == 0) {
413 		gpio &= ~((uint8_t)(1 << (gpio_value & 7)));
414 
415 		if (onoff)
416 			gpio |= ((gpio_value >> 5) & 1) << (gpio_value & 7);
417 		else
418 			gpio |= (((gpio_value >> 5) & 1) ^ 1) <<
419 			    (gpio_value & 7);
420 		emdtv_write_1(sc, UR_GET_STATUS, reg, gpio);
421 	} else {
422 		gpio &= ~((uint8_t)(1 << (gpio_value & 0xf)));
423 
424 		gpio |= ((gpio_value >> 5) & 1) << (gpio_value & 7);
425 		emdtv_write_1(sc, UR_GET_STATUS, reg, gpio);
426 		usbd_delay_ms(sc->sc_udev, 100);
427 
428 		gpio &= ~((uint8_t)(1 << (gpio_value & 0xf)));
429 		gpio |= (((gpio_value >> 5) & 1) ^ 1) << (gpio_value & 7);
430 		emdtv_write_1(sc, UR_GET_STATUS, reg, gpio);
431 		usbd_delay_ms(sc->sc_udev, 100);
432 	}
433 
434 	return true;
435 }
436 
437 static void
438 emdtv_default_board_init(struct emdtv_softc *sc)
439 {
440 	emdtv_write_1(sc, UR_GET_STATUS, EM28XX_XCLK_REG, 0x27);
441 	emdtv_write_1(sc, UR_GET_STATUS, EM28XX_I2C_CLK_REG, 0x40);
442 	emdtv_write_1(sc, UR_GET_STATUS, 0x08, 0xff);
443 	emdtv_write_1(sc, UR_GET_STATUS, 0x04, 0x00);
444 	usbd_delay_ms(sc->sc_udev, 100);
445 	emdtv_write_1(sc, UR_GET_STATUS, 0x04, 0x08);
446 	usbd_delay_ms(sc->sc_udev, 100);
447 	emdtv_write_1(sc, UR_GET_STATUS, 0x08, 0xff);
448 	usbd_delay_ms(sc->sc_udev, 50);
449 	emdtv_write_1(sc, UR_GET_STATUS, 0x08, 0x2d);
450 	usbd_delay_ms(sc->sc_udev, 50);
451 	emdtv_write_1(sc, UR_GET_STATUS, 0x08, 0x3d);
452 	//emdtv_write_1(sc, UR_GET_STATUS, 0x0f, 0xa7);
453 	usbd_delay_ms(sc->sc_udev, 10);
454 }
455 
456 MODULE(MODULE_CLASS_DRIVER, emdtv, "cir,lg3303,xc3028");
457 
458 #ifdef _MODULE
459 #include "ioconf.c"
460 #endif
461 
462 static int
463 emdtv_modcmd(modcmd_t cmd, void *opaque)
464 {
465 	switch (cmd) {
466 	case MODULE_CMD_INIT:
467 #ifdef _MODULE
468 		return config_init_component(cfdriver_ioconf_emdtv,
469 		    cfattach_ioconf_emdtv, cfdata_ioconf_emdtv);
470 #else
471 		return 0;
472 #endif
473 	case MODULE_CMD_FINI:
474 #ifdef _MODULE
475 		return config_fini_component(cfdriver_ioconf_emdtv,
476 		    cfattach_ioconf_emdtv, cfdata_ioconf_emdtv);
477 #else
478 		return 0;
479 #endif
480 	default:
481 		return ENOTTY;
482 	}
483 }
484