1 1.17 riastrad /* $NetBSD: emdtv_dtv.c,v 1.17 2022/03/29 09:08:44 riastradh Exp $ */ 2 1.1 jmcneill 3 1.1 jmcneill /*- 4 1.1 jmcneill * Copyright (c) 2008, 2011 Jared D. McNeill <jmcneill (at) invisible.ca> 5 1.1 jmcneill * All rights reserved. 6 1.1 jmcneill * 7 1.1 jmcneill * Redistribution and use in source and binary forms, with or without 8 1.1 jmcneill * modification, are permitted provided that the following conditions 9 1.1 jmcneill * are met: 10 1.1 jmcneill * 1. Redistributions of source code must retain the above copyright 11 1.1 jmcneill * notice, this list of conditions and the following disclaimer. 12 1.1 jmcneill * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 jmcneill * notice, this list of conditions and the following disclaimer in the 14 1.1 jmcneill * documentation and/or other materials provided with the distribution. 15 1.1 jmcneill * 16 1.1 jmcneill * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 1.1 jmcneill * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 1.1 jmcneill * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 1.1 jmcneill * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 1.1 jmcneill * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 1.1 jmcneill * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 1.1 jmcneill * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 1.1 jmcneill * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 1.1 jmcneill * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 1.1 jmcneill * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 1.1 jmcneill * POSSIBILITY OF SUCH DAMAGE. 27 1.1 jmcneill */ 28 1.1 jmcneill 29 1.1 jmcneill #include <sys/cdefs.h> 30 1.17 riastrad __KERNEL_RCSID(0, "$NetBSD: emdtv_dtv.c,v 1.17 2022/03/29 09:08:44 riastradh Exp $"); 31 1.1 jmcneill 32 1.1 jmcneill #include <sys/param.h> 33 1.1 jmcneill #include <sys/systm.h> 34 1.1 jmcneill #include <sys/device.h> 35 1.11 skrll #include <sys/lwp.h> 36 1.1 jmcneill #include <sys/conf.h> 37 1.1 jmcneill 38 1.1 jmcneill #include <dev/usb/usb.h> 39 1.1 jmcneill #include <dev/usb/usbdi.h> 40 1.1 jmcneill #include <dev/usb/usbdi_util.h> 41 1.9 mrg #include <dev/usb/usbdivar.h> 42 1.1 jmcneill #include <dev/usb/usbdevs.h> 43 1.1 jmcneill 44 1.1 jmcneill #include <dev/i2c/i2cvar.h> 45 1.1 jmcneill 46 1.1 jmcneill #include <dev/usb/emdtvvar.h> 47 1.1 jmcneill #include <dev/usb/emdtvreg.h> 48 1.1 jmcneill 49 1.1 jmcneill static void emdtv_dtv_get_devinfo(void *, 50 1.1 jmcneill struct dvb_frontend_info *); 51 1.1 jmcneill static int emdtv_dtv_open(void *, int); 52 1.1 jmcneill static void emdtv_dtv_close(void *); 53 1.1 jmcneill static int emdtv_dtv_set_tuner(void *, 54 1.1 jmcneill const struct dvb_frontend_parameters *); 55 1.1 jmcneill static fe_status_t emdtv_dtv_get_status(void *); 56 1.1 jmcneill static uint16_t emdtv_dtv_get_signal_strength(void *); 57 1.1 jmcneill static uint16_t emdtv_dtv_get_snr(void *); 58 1.5 jmcneill static int emdtv_dtv_start_transfer(void *, 59 1.5 jmcneill void (*)(void *, const struct dtv_payload *), 60 1.5 jmcneill void *); 61 1.1 jmcneill static int emdtv_dtv_stop_transfer(void *); 62 1.1 jmcneill 63 1.1 jmcneill static int emdtv_dtv_tuner_reset(void *); 64 1.1 jmcneill 65 1.1 jmcneill static void emdtv_dtv_isoc_startall(struct emdtv_softc *); 66 1.1 jmcneill static int emdtv_dtv_isoc_start(struct emdtv_softc *, 67 1.1 jmcneill struct emdtv_isoc_xfer *); 68 1.12 skrll static void emdtv_dtv_isoc(struct usbd_xfer *, void *, 69 1.1 jmcneill usbd_status); 70 1.1 jmcneill 71 1.1 jmcneill static const struct dtv_hw_if emdtv_dtv_if = { 72 1.1 jmcneill .get_devinfo = emdtv_dtv_get_devinfo, 73 1.1 jmcneill .open = emdtv_dtv_open, 74 1.1 jmcneill .close = emdtv_dtv_close, 75 1.1 jmcneill .set_tuner = emdtv_dtv_set_tuner, 76 1.1 jmcneill .get_status = emdtv_dtv_get_status, 77 1.1 jmcneill .get_signal_strength = emdtv_dtv_get_signal_strength, 78 1.1 jmcneill .get_snr = emdtv_dtv_get_snr, 79 1.1 jmcneill .start_transfer = emdtv_dtv_start_transfer, 80 1.1 jmcneill .stop_transfer = emdtv_dtv_stop_transfer, 81 1.1 jmcneill }; 82 1.1 jmcneill 83 1.1 jmcneill void 84 1.1 jmcneill emdtv_dtv_attach(struct emdtv_softc *sc) 85 1.1 jmcneill { 86 1.1 jmcneill usb_endpoint_descriptor_t *ed; 87 1.1 jmcneill usbd_status status; 88 1.1 jmcneill int i; 89 1.1 jmcneill 90 1.1 jmcneill for (i = 0; i < EMDTV_NXFERS; i++) { 91 1.1 jmcneill sc->sc_ix[i].ix_altix = (i & 1) ? 92 1.1 jmcneill &sc->sc_ix[i - 1] : &sc->sc_ix[i + 1]; 93 1.1 jmcneill sc->sc_ix[i].ix_sc = sc; 94 1.1 jmcneill } 95 1.1 jmcneill 96 1.1 jmcneill ed = usbd_interface2endpoint_descriptor(sc->sc_iface, 3); 97 1.1 jmcneill if (ed == NULL) { 98 1.1 jmcneill aprint_error_dev(sc->sc_dev, "couldn't find endpoint 3\n"); 99 1.1 jmcneill return; 100 1.1 jmcneill } 101 1.1 jmcneill sc->sc_isoc_maxpacketsize = UGETW(ed->wMaxPacketSize); 102 1.1 jmcneill sc->sc_isoc_buflen = sc->sc_isoc_maxpacketsize * EMDTV_NFRAMES; 103 1.1 jmcneill 104 1.14 christos aprint_debug_dev(sc->sc_dev, "calling usbd_open_pipe, ep 0x%02x\n", 105 1.1 jmcneill ed->bEndpointAddress); 106 1.12 skrll status = usbd_open_pipe(sc->sc_iface, 107 1.10 jmcneill ed->bEndpointAddress, USBD_EXCLUSIVE_USE|USBD_MPSAFE, 108 1.1 jmcneill &sc->sc_isoc_pipe); 109 1.1 jmcneill if (status != USBD_NORMAL_COMPLETION) { 110 1.1 jmcneill aprint_error_dev(sc->sc_dev, "couldn't open isoc pipe\n"); 111 1.1 jmcneill usbd_set_interface(sc->sc_iface, 0); 112 1.1 jmcneill return; 113 1.1 jmcneill } 114 1.1 jmcneill 115 1.1 jmcneill emdtv_write_1(sc, UR_GET_STATUS, 0x48, 0x00); 116 1.1 jmcneill emdtv_write_1(sc, UR_GET_STATUS, 0x12, 0x77); 117 1.1 jmcneill usbd_delay_ms(sc->sc_udev, 6); 118 1.1 jmcneill 119 1.1 jmcneill emdtv_gpio_ctl(sc, EMDTV_GPIO_ANALOG_ON, false); 120 1.1 jmcneill emdtv_gpio_ctl(sc, EMDTV_GPIO_TS1_ON, true); 121 1.1 jmcneill emdtv_gpio_ctl(sc, EMDTV_GPIO_TUNER1_ON, true); 122 1.1 jmcneill emdtv_gpio_ctl(sc, EMDTV_GPIO_DEMOD1_RESET, true); 123 1.1 jmcneill usbd_delay_ms(sc->sc_udev, 100); 124 1.1 jmcneill 125 1.5 jmcneill emdtv_dtv_rescan(sc, NULL, NULL); 126 1.1 jmcneill } 127 1.1 jmcneill 128 1.12 skrll static void 129 1.12 skrll emdtv_dtv_free_xfers(struct emdtv_softc *sc) 130 1.12 skrll { 131 1.12 skrll 132 1.12 skrll for (size_t i = 0; i < EMDTV_NXFERS; i++) 133 1.12 skrll if (sc->sc_ix[i].ix_xfer) { 134 1.12 skrll usbd_destroy_xfer(sc->sc_ix[i].ix_xfer); 135 1.12 skrll sc->sc_ix[i].ix_xfer = NULL; 136 1.12 skrll sc->sc_ix[i].ix_buf = NULL; 137 1.12 skrll } 138 1.12 skrll 139 1.12 skrll return; 140 1.12 skrll } 141 1.12 skrll 142 1.1 jmcneill void 143 1.1 jmcneill emdtv_dtv_detach(struct emdtv_softc *sc, int flags) 144 1.1 jmcneill { 145 1.17 riastrad 146 1.1 jmcneill sc->sc_streaming = false; 147 1.1 jmcneill 148 1.1 jmcneill if (sc->sc_xc3028) 149 1.1 jmcneill xc3028_close(sc->sc_xc3028); 150 1.1 jmcneill if (sc->sc_lg3303) 151 1.1 jmcneill lg3303_close(sc->sc_lg3303); 152 1.1 jmcneill 153 1.1 jmcneill if (sc->sc_isoc_pipe) { 154 1.1 jmcneill usbd_abort_pipe(sc->sc_isoc_pipe); 155 1.12 skrll emdtv_dtv_free_xfers(sc); 156 1.1 jmcneill usbd_close_pipe(sc->sc_isoc_pipe); 157 1.1 jmcneill sc->sc_isoc_pipe = NULL; 158 1.1 jmcneill } 159 1.1 jmcneill } 160 1.1 jmcneill 161 1.5 jmcneill void 162 1.5 jmcneill emdtv_dtv_rescan(struct emdtv_softc *sc, const char *ifattr, const int *locs) 163 1.5 jmcneill { 164 1.5 jmcneill struct dtv_attach_args daa; 165 1.5 jmcneill 166 1.5 jmcneill daa.hw = &emdtv_dtv_if; 167 1.5 jmcneill daa.priv = sc; 168 1.5 jmcneill 169 1.5 jmcneill if (ifattr_match(ifattr, "dtvbus") && sc->sc_dtvdev == NULL) 170 1.15 thorpej sc->sc_dtvdev = config_found(sc->sc_dev, &daa, dtv_print, 171 1.16 thorpej CFARGS(.iattr = "dtvbus")); 172 1.5 jmcneill } 173 1.5 jmcneill 174 1.1 jmcneill static void 175 1.1 jmcneill emdtv_dtv_get_devinfo(void *priv, struct dvb_frontend_info *info) 176 1.1 jmcneill { 177 1.1 jmcneill struct emdtv_softc *sc = priv; 178 1.1 jmcneill 179 1.1 jmcneill memset(info, 0, sizeof(*info)); 180 1.1 jmcneill strlcpy(info->name, sc->sc_board->eb_name, sizeof(info->name)); 181 1.1 jmcneill info->type = FE_ATSC; 182 1.1 jmcneill info->frequency_min = 54000000; 183 1.1 jmcneill info->frequency_max = 858000000; 184 1.1 jmcneill info->frequency_stepsize = 62500; 185 1.1 jmcneill info->caps = FE_CAN_8VSB; 186 1.1 jmcneill } 187 1.1 jmcneill 188 1.1 jmcneill static int 189 1.1 jmcneill emdtv_dtv_open(void *priv, int flags) 190 1.1 jmcneill { 191 1.1 jmcneill struct emdtv_softc *sc = priv; 192 1.1 jmcneill 193 1.1 jmcneill if (sc->sc_dying) 194 1.1 jmcneill return ENXIO; 195 1.1 jmcneill 196 1.12 skrll aprint_debug_dev(sc->sc_dev, "allocating isoc xfers (pktsz %d)\n", 197 1.12 skrll sc->sc_isoc_maxpacketsize); 198 1.12 skrll 199 1.12 skrll for (size_t i = 0; i < EMDTV_NXFERS; i++) { 200 1.12 skrll int error = usbd_create_xfer(sc->sc_isoc_pipe, 201 1.12 skrll sc->sc_isoc_buflen, USBD_SHORT_XFER_OK, EMDTV_NFRAMES, 202 1.12 skrll &sc->sc_ix[i].ix_xfer); 203 1.12 skrll if (error) 204 1.12 skrll return error; 205 1.12 skrll sc->sc_ix[i].ix_buf = usbd_get_buffer(sc->sc_ix[i].ix_xfer); 206 1.12 skrll aprint_debug_dev(sc->sc_dev, " ix[%zu] xfer %p buf %p\n", 207 1.12 skrll i, sc->sc_ix[i].ix_xfer, sc->sc_ix[i].ix_buf); 208 1.12 skrll } 209 1.12 skrll 210 1.1 jmcneill switch (sc->sc_board->eb_tuner) { 211 1.2 jakllsch case EMDTV_TUNER_XC3028: 212 1.2 jakllsch if (sc->sc_xc3028 == NULL) { 213 1.2 jakllsch sc->sc_xc3028 = xc3028_open(sc->sc_dev, 214 1.2 jakllsch &sc->sc_i2c, 0x61 << 1, emdtv_dtv_tuner_reset, sc, 215 1.2 jakllsch XC3028); 216 1.2 jakllsch } 217 1.2 jakllsch if (sc->sc_xc3028 == NULL) { 218 1.2 jakllsch aprint_error_dev(sc->sc_dev, "couldn't open xc3028\n"); 219 1.2 jakllsch return ENXIO; 220 1.2 jakllsch } 221 1.2 jakllsch break; 222 1.1 jmcneill case EMDTV_TUNER_XC3028L: 223 1.1 jmcneill if (sc->sc_xc3028 == NULL) { 224 1.1 jmcneill sc->sc_xc3028 = xc3028_open(sc->sc_dev, 225 1.1 jmcneill &sc->sc_i2c, 0x61 << 1, emdtv_dtv_tuner_reset, sc, 226 1.1 jmcneill XC3028L); 227 1.1 jmcneill } 228 1.1 jmcneill if (sc->sc_xc3028 == NULL) { 229 1.1 jmcneill aprint_error_dev(sc->sc_dev, "couldn't open xc3028l\n"); 230 1.1 jmcneill return ENXIO; 231 1.1 jmcneill } 232 1.1 jmcneill break; 233 1.1 jmcneill default: 234 1.1 jmcneill aprint_error_dev(sc->sc_dev, "unsupported tuner (%d)\n", 235 1.1 jmcneill sc->sc_board->eb_tuner); 236 1.1 jmcneill return EIO; 237 1.1 jmcneill } 238 1.1 jmcneill 239 1.1 jmcneill switch (sc->sc_board->eb_demod) { 240 1.1 jmcneill case EMDTV_DEMOD_LG3303: 241 1.1 jmcneill if (sc->sc_lg3303 == NULL) { 242 1.1 jmcneill sc->sc_lg3303 = lg3303_open(sc->sc_dev, 243 1.3 jmcneill &sc->sc_i2c, 0x1c, 0); 244 1.1 jmcneill } 245 1.1 jmcneill if (sc->sc_lg3303 == NULL) { 246 1.1 jmcneill aprint_error_dev(sc->sc_dev, "couldn't open lg3303\n"); 247 1.1 jmcneill return ENXIO; 248 1.1 jmcneill } 249 1.1 jmcneill break; 250 1.1 jmcneill default: 251 1.1 jmcneill aprint_error_dev(sc->sc_dev, "unsupported demod (%d)\n", 252 1.1 jmcneill sc->sc_board->eb_demod); 253 1.1 jmcneill return EIO; 254 1.1 jmcneill } 255 1.1 jmcneill 256 1.1 jmcneill return 0; 257 1.1 jmcneill } 258 1.1 jmcneill 259 1.1 jmcneill static void 260 1.1 jmcneill emdtv_dtv_close(void *priv) 261 1.1 jmcneill { 262 1.12 skrll struct emdtv_softc *sc = priv; 263 1.12 skrll 264 1.12 skrll emdtv_dtv_free_xfers(sc); 265 1.1 jmcneill } 266 1.1 jmcneill 267 1.1 jmcneill static int 268 1.1 jmcneill emdtv_dtv_set_tuner(void *priv, const struct dvb_frontend_parameters *params) 269 1.1 jmcneill { 270 1.1 jmcneill struct emdtv_softc *sc = priv; 271 1.1 jmcneill int error; 272 1.1 jmcneill 273 1.1 jmcneill /* Setup demod */ 274 1.1 jmcneill error = ENXIO; 275 1.1 jmcneill if (sc->sc_lg3303) 276 1.1 jmcneill error = lg3303_set_modulation(sc->sc_lg3303, 277 1.1 jmcneill params->u.vsb.modulation); 278 1.1 jmcneill if (error) 279 1.1 jmcneill return error; 280 1.1 jmcneill 281 1.1 jmcneill /* Setup tuner */ 282 1.1 jmcneill error = ENXIO; 283 1.1 jmcneill if (sc->sc_xc3028) 284 1.1 jmcneill error = xc3028_tune_dtv(sc->sc_xc3028, params); 285 1.1 jmcneill 286 1.1 jmcneill return error; 287 1.1 jmcneill } 288 1.1 jmcneill 289 1.1 jmcneill static fe_status_t 290 1.1 jmcneill emdtv_dtv_get_status(void *priv) 291 1.1 jmcneill { 292 1.1 jmcneill struct emdtv_softc *sc = priv; 293 1.1 jmcneill 294 1.1 jmcneill if (sc->sc_lg3303) 295 1.1 jmcneill return lg3303_get_dtv_status(sc->sc_lg3303); 296 1.1 jmcneill 297 1.1 jmcneill return 0; 298 1.1 jmcneill } 299 1.1 jmcneill 300 1.1 jmcneill uint16_t 301 1.1 jmcneill emdtv_dtv_get_signal_strength(void *priv) 302 1.1 jmcneill { 303 1.4 jmcneill struct emdtv_softc *sc = priv; 304 1.4 jmcneill 305 1.4 jmcneill if (sc->sc_lg3303) 306 1.4 jmcneill return lg3303_get_signal_strength(sc->sc_lg3303); 307 1.4 jmcneill 308 1.1 jmcneill return 0; 309 1.1 jmcneill } 310 1.1 jmcneill 311 1.1 jmcneill uint16_t 312 1.1 jmcneill emdtv_dtv_get_snr(void *priv) 313 1.1 jmcneill { 314 1.4 jmcneill struct emdtv_softc *sc = priv; 315 1.4 jmcneill 316 1.4 jmcneill if (sc->sc_lg3303) 317 1.4 jmcneill return lg3303_get_snr(sc->sc_lg3303); 318 1.4 jmcneill 319 1.1 jmcneill return 0; 320 1.1 jmcneill } 321 1.1 jmcneill 322 1.1 jmcneill static int 323 1.5 jmcneill emdtv_dtv_start_transfer(void *priv, 324 1.5 jmcneill void (*cb)(void *, const struct dtv_payload *), void *arg) 325 1.1 jmcneill { 326 1.1 jmcneill struct emdtv_softc *sc = priv; 327 1.12 skrll int s; 328 1.1 jmcneill 329 1.1 jmcneill s = splusb(); 330 1.1 jmcneill 331 1.1 jmcneill sc->sc_streaming = true; 332 1.5 jmcneill sc->sc_dtvsubmitcb = cb; 333 1.5 jmcneill sc->sc_dtvsubmitarg = arg; 334 1.1 jmcneill 335 1.1 jmcneill aprint_debug_dev(sc->sc_dev, "starting isoc transactions\n"); 336 1.1 jmcneill 337 1.1 jmcneill emdtv_dtv_isoc_startall(sc); 338 1.1 jmcneill splx(s); 339 1.1 jmcneill 340 1.1 jmcneill return 0; 341 1.1 jmcneill } 342 1.1 jmcneill 343 1.1 jmcneill static int 344 1.1 jmcneill emdtv_dtv_stop_transfer(void *priv) 345 1.1 jmcneill { 346 1.1 jmcneill struct emdtv_softc *sc = priv; 347 1.1 jmcneill 348 1.1 jmcneill aprint_debug_dev(sc->sc_dev, "stopping stream\n"); 349 1.1 jmcneill 350 1.1 jmcneill sc->sc_streaming = false; 351 1.1 jmcneill 352 1.8 jmcneill KERNEL_LOCK(1, curlwp); 353 1.1 jmcneill if (sc->sc_isoc_pipe != NULL) 354 1.1 jmcneill usbd_abort_pipe(sc->sc_isoc_pipe); 355 1.8 jmcneill KERNEL_UNLOCK_ONE(curlwp); 356 1.1 jmcneill 357 1.5 jmcneill sc->sc_dtvsubmitcb = NULL; 358 1.5 jmcneill sc->sc_dtvsubmitarg = NULL; 359 1.5 jmcneill 360 1.1 jmcneill return 0; 361 1.1 jmcneill } 362 1.1 jmcneill 363 1.1 jmcneill static void 364 1.1 jmcneill emdtv_dtv_isoc_startall(struct emdtv_softc *sc) 365 1.1 jmcneill { 366 1.1 jmcneill int i; 367 1.1 jmcneill 368 1.1 jmcneill if (sc->sc_streaming == false || sc->sc_dying == true) 369 1.1 jmcneill return; 370 1.1 jmcneill 371 1.1 jmcneill for (i = 0; i < EMDTV_NXFERS; i += 2) 372 1.1 jmcneill emdtv_dtv_isoc_start(sc, &sc->sc_ix[i]); 373 1.1 jmcneill } 374 1.1 jmcneill 375 1.1 jmcneill static int 376 1.1 jmcneill emdtv_dtv_isoc_start(struct emdtv_softc *sc, struct emdtv_isoc_xfer *ix) 377 1.1 jmcneill { 378 1.1 jmcneill int i; 379 1.1 jmcneill 380 1.1 jmcneill if (sc->sc_isoc_pipe == NULL) 381 1.1 jmcneill return EIO; 382 1.1 jmcneill 383 1.1 jmcneill for (i = 0; i < EMDTV_NFRAMES; i++) 384 1.1 jmcneill ix->ix_frlengths[i] = sc->sc_isoc_maxpacketsize; 385 1.1 jmcneill 386 1.1 jmcneill usbd_setup_isoc_xfer(ix->ix_xfer, 387 1.1 jmcneill ix, 388 1.1 jmcneill ix->ix_frlengths, 389 1.1 jmcneill EMDTV_NFRAMES, 390 1.12 skrll USBD_SHORT_XFER_OK, 391 1.1 jmcneill emdtv_dtv_isoc); 392 1.8 jmcneill 393 1.8 jmcneill KERNEL_LOCK(1, curlwp); 394 1.1 jmcneill usbd_transfer(ix->ix_xfer); 395 1.8 jmcneill KERNEL_UNLOCK_ONE(curlwp); 396 1.1 jmcneill 397 1.1 jmcneill return 0; 398 1.1 jmcneill } 399 1.1 jmcneill 400 1.1 jmcneill static void 401 1.12 skrll emdtv_dtv_isoc(struct usbd_xfer *xfer, void * priv, 402 1.1 jmcneill usbd_status err) 403 1.1 jmcneill { 404 1.1 jmcneill struct emdtv_isoc_xfer *ix = priv; 405 1.1 jmcneill struct emdtv_softc *sc = ix->ix_sc; 406 1.1 jmcneill struct dtv_payload payload; 407 1.12 skrll struct usbd_pipe *isoc = sc->sc_isoc_pipe; 408 1.1 jmcneill uint32_t len; 409 1.1 jmcneill uint8_t *buf; 410 1.1 jmcneill int i; 411 1.1 jmcneill 412 1.1 jmcneill KASSERT(xfer == ix->ix_xfer); 413 1.1 jmcneill 414 1.5 jmcneill if (sc->sc_dying || sc->sc_dtvsubmitcb == NULL) 415 1.1 jmcneill return; 416 1.1 jmcneill 417 1.1 jmcneill if (err) { 418 1.1 jmcneill if (err == USBD_STALLED) { 419 1.1 jmcneill usbd_clear_endpoint_stall_async(isoc); 420 1.1 jmcneill goto resched; 421 1.1 jmcneill } 422 1.1 jmcneill return; 423 1.1 jmcneill } 424 1.1 jmcneill 425 1.1 jmcneill usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL); 426 1.1 jmcneill 427 1.1 jmcneill if (len == 0) 428 1.1 jmcneill goto resched; 429 1.1 jmcneill 430 1.1 jmcneill buf = usbd_get_buffer(xfer); 431 1.1 jmcneill if (buf == NULL) 432 1.1 jmcneill goto resched; 433 1.1 jmcneill 434 1.1 jmcneill for (i = 0; i < EMDTV_NFRAMES; i++, buf += sc->sc_isoc_maxpacketsize) { 435 1.1 jmcneill if (ix->ix_frlengths[i] == 0) 436 1.1 jmcneill continue; 437 1.1 jmcneill payload.data = buf; 438 1.1 jmcneill payload.size = ix->ix_frlengths[i]; 439 1.5 jmcneill sc->sc_dtvsubmitcb(sc->sc_dtvsubmitarg, &payload); 440 1.1 jmcneill } 441 1.1 jmcneill 442 1.1 jmcneill resched: 443 1.1 jmcneill emdtv_dtv_isoc_start(sc, ix->ix_altix); 444 1.1 jmcneill } 445 1.1 jmcneill 446 1.1 jmcneill static int 447 1.1 jmcneill emdtv_dtv_tuner_reset(void *opaque) 448 1.1 jmcneill { 449 1.1 jmcneill struct emdtv_softc *sc = opaque; 450 1.1 jmcneill emdtv_gpio_ctl(sc, EMDTV_GPIO_TUNER1_RESET, true); 451 1.1 jmcneill return 0; 452 1.1 jmcneill } 453