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