Module Name: src
Committed By: jmcneill
Date: Sat Jul 9 15:00:45 UTC 2011
Modified Files:
src/sys/dev/i2c: au8522.c au8522var.h xc5k.c xc5kreg.h xc5kvar.h
src/sys/dev/usb: auvitek.c auvitek_board.c auvitek_i2c.c
auvitek_video.c auvitekvar.h
Added Files:
src/sys/dev/i2c: au8522mod.h au8522mod_8vsb.h au8522mod_qam256.h
au8522mod_qam64.h
src/sys/dev/usb: auvitek_dtv.c
Log Message:
add digital capture support
To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/i2c/au8522.c
cvs rdiff -u -r0 -r1.1 src/sys/dev/i2c/au8522mod.h \
src/sys/dev/i2c/au8522mod_8vsb.h src/sys/dev/i2c/au8522mod_qam256.h \
src/sys/dev/i2c/au8522mod_qam64.h
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/i2c/au8522var.h src/sys/dev/i2c/xc5k.c
cvs rdiff -u -r1.1 -r1.2 src/sys/dev/i2c/xc5kreg.h src/sys/dev/i2c/xc5kvar.h
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/usb/auvitek.c \
src/sys/dev/usb/auvitek_video.c
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/usb/auvitek_board.c \
src/sys/dev/usb/auvitekvar.h
cvs rdiff -u -r0 -r1.1 src/sys/dev/usb/auvitek_dtv.c
cvs rdiff -u -r1.1 -r1.2 src/sys/dev/usb/auvitek_i2c.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/i2c/au8522.c
diff -u src/sys/dev/i2c/au8522.c:1.3 src/sys/dev/i2c/au8522.c:1.4
--- src/sys/dev/i2c/au8522.c:1.3 Thu May 26 23:42:05 2011
+++ src/sys/dev/i2c/au8522.c Sat Jul 9 15:00:43 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: au8522.c,v 1.3 2011/05/26 23:42:05 jmcneill Exp $ */
+/* $NetBSD: au8522.c,v 1.4 2011/07/09 15:00:43 jmcneill Exp $ */
/*-
* Copyright (c) 2010 Jared D. McNeill <[email protected]>
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: au8522.c,v 1.3 2011/05/26 23:42:05 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: au8522.c,v 1.4 2011/07/09 15:00:43 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -41,10 +41,13 @@
#include <sys/kmem.h>
#include <sys/module.h>
+#include <dev/dtv/dtvio.h>
+
#include <dev/i2c/i2cvar.h>
#include <dev/i2c/au8522reg.h>
#include <dev/i2c/au8522var.h>
+#include <dev/i2c/au8522mod.h>
static int au8522_reset(struct au8522 *);
static int au8522_read_1(struct au8522 *, uint16_t, uint8_t *);
@@ -187,8 +190,31 @@
return 0;
}
+static int
+au8522_set_if(struct au8522 *au)
+{
+ uint8_t ifinit[3];
+ unsigned int n;
+
+ switch (au->if_freq) {
+ case 6000000: /* 6MHz */
+ ifinit[0] = 0xfb;
+ ifinit[1] = 0x8e;
+ ifinit[2] = 0x39;
+ break;
+ default:
+ aprint_error_dev(au->parent, "au8522: unsupported if freq %dHz\n", au->if_freq);
+ return EINVAL;
+ }
+
+ for (n = 0; n < __arraycount(ifinit); n++)
+ au8522_write_1(au, 0x80b5 + n, ifinit[n]);
+
+ return 0;
+}
+
struct au8522 *
-au8522_open(device_t parent, i2c_tag_t i2c, i2c_addr_t addr)
+au8522_open(device_t parent, i2c_tag_t i2c, i2c_addr_t addr, unsigned int if_freq)
{
struct au8522 *au;
@@ -198,6 +224,8 @@
au->parent = parent;
au->i2c = i2c;
au->i2c_addr = addr;
+ au->current_modulation = -1;
+ au->if_freq = if_freq;
if (au8522_reset(au))
goto failed;
@@ -271,6 +299,90 @@
}
}
+int
+au8522_set_modulation(struct au8522 *au, fe_modulation_t modulation)
+{
+ const struct au8522_modulation_table *modtab = NULL;
+ size_t modtablen;
+ unsigned int n;
+
+ switch (modulation) {
+ case VSB_8:
+ modtab = au8522_modulation_8vsb;
+ modtablen = __arraycount(au8522_modulation_8vsb);
+ break;
+ case QAM_64:
+ modtab = au8522_modulation_qam64;
+ modtablen = __arraycount(au8522_modulation_qam64);
+ break;
+ case QAM_256:
+ modtab = au8522_modulation_qam256;
+ modtablen = __arraycount(au8522_modulation_qam256);
+ break;
+ default:
+ return EINVAL;
+ }
+
+ for (n = 0; n < modtablen; n++)
+ au8522_write_1(au, modtab[n].reg, modtab[n].val);
+
+ au8522_set_if(au);
+
+ au->current_modulation = modulation;
+
+ return 0;
+}
+
+void
+au8522_set_gate(struct au8522 *au, bool onoff)
+{
+ au8522_write_1(au, AU8522_REG_TUNERCTL, onoff ? AU8522_TUNERCTL_EN : 0);
+}
+
+fe_status_t
+au8522_get_dtv_status(struct au8522 *au)
+{
+ fe_status_t status = 0;
+ uint8_t val;
+
+ //printf("%s: current_modulation = %d\n", __func__,
+ // au->current_modulation);
+
+ switch (au->current_modulation) {
+ case VSB_8:
+ if (au8522_read_1(au, 0x4088, &val))
+ return 0;
+ if ((val & 0x03) == 0x03) {
+ status |= FE_HAS_SIGNAL;
+ status |= FE_HAS_CARRIER;
+ status |= FE_HAS_VITERBI;
+ }
+ break;
+ case QAM_64:
+ case QAM_256:
+ if (au8522_read_1(au, 0x4541, &val))
+ return 0;
+ if (val & 0x80) {
+ status |= FE_HAS_VITERBI;
+ }
+ if (val & 0x20) {
+ status |= FE_HAS_SIGNAL;
+ status |= FE_HAS_CARRIER;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (status & FE_HAS_VITERBI) {
+ status |= FE_HAS_SYNC;
+ status |= FE_HAS_LOCK;
+ }
+
+ //printf("%s: status = 0x%x\n", __func__, status);
+ return status;
+}
+
MODULE(MODULE_CLASS_DRIVER, au8522, NULL);
static int
Index: src/sys/dev/i2c/au8522var.h
diff -u src/sys/dev/i2c/au8522var.h:1.2 src/sys/dev/i2c/au8522var.h:1.3
--- src/sys/dev/i2c/au8522var.h:1.2 Thu May 26 23:42:05 2011
+++ src/sys/dev/i2c/au8522var.h Sat Jul 9 15:00:44 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: au8522var.h,v 1.2 2011/05/26 23:42:05 jmcneill Exp $ */
+/* $NetBSD: au8522var.h,v 1.3 2011/07/09 15:00:44 jmcneill Exp $ */
/*-
* Copyright (c) 2010 Jared D. McNeill <[email protected]>
@@ -30,11 +30,16 @@
#define _AU8522VAR_H
#include <dev/i2c/i2cvar.h>
+#include <dev/dtv/dtvio.h>
struct au8522 {
device_t parent;
i2c_tag_t i2c;
i2c_addr_t i2c_addr;
+
+ unsigned int if_freq;
+
+ fe_modulation_t current_modulation;
};
typedef enum {
@@ -51,7 +56,7 @@
AU8522_AINPUT_SIF,
} au8522_ainput_t;
-struct au8522 * au8522_open(device_t, i2c_tag_t, i2c_addr_t);
+struct au8522 * au8522_open(device_t, i2c_tag_t, i2c_addr_t, unsigned int);
void au8522_close(struct au8522 *);
void au8522_enable(struct au8522 *, bool);
@@ -59,5 +64,8 @@
au8522_vinput_t, au8522_ainput_t);
int au8522_get_signal(struct au8522 *);
void au8522_set_audio(struct au8522 *, bool);
+int au8522_set_modulation(struct au8522 *, fe_modulation_t);
+void au8522_set_gate(struct au8522 *, bool);
+fe_status_t au8522_get_dtv_status(struct au8522 *);
#endif /* !_AU8522VAR_H */
Index: src/sys/dev/i2c/xc5k.c
diff -u src/sys/dev/i2c/xc5k.c:1.2 src/sys/dev/i2c/xc5k.c:1.3
--- src/sys/dev/i2c/xc5k.c:1.2 Tue Dec 28 00:11:50 2010
+++ src/sys/dev/i2c/xc5k.c Sat Jul 9 15:00:44 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: xc5k.c,v 1.2 2010/12/28 00:11:50 jmcneill Exp $ */
+/* $NetBSD: xc5k.c,v 1.3 2011/07/09 15:00:44 jmcneill Exp $ */
/*-
* Copyright (c) 2010 Jared D. McNeill <[email protected]>
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xc5k.c,v 1.2 2010/12/28 00:11:50 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xc5k.c,v 1.3 2011/07/09 15:00:44 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -51,6 +51,9 @@
#define XC5K_FIRMWARE_DRVNAME "xc5k"
#define XC5K_FIRMWARE_IMGNAME "dvb-fe-xc5000-1.6.114.fw"
+#define XC5K_FREQ_MIN 1000000
+#define XC5K_FREQ_MAX 1023000000
+
static kmutex_t xc5k_firmware_lock;
static int xc5k_reset(struct xc5k *);
@@ -126,7 +129,7 @@
xc5k_firmware_open(struct xc5k *xc)
{
firmware_handle_t fwh;
- uint16_t product_id;
+ uint16_t product_id, xcversion, xcbuild;
uint8_t *fw = NULL;
size_t fwlen;
int error;
@@ -156,6 +159,18 @@
aprint_normal_dev(xc->parent, "xc5k: loading firmware '%s/%s'\n",
XC5K_FIRMWARE_DRVNAME, XC5K_FIRMWARE_IMGNAME);
error = xc5k_firmware_upload(xc, fw, fwlen);
+ if (!error) {
+ xc5k_read_2(xc, XC5K_REG_VERSION, &xcversion);
+ xc5k_read_2(xc, XC5K_REG_BUILD, &xcbuild);
+ if (!error)
+ aprint_normal_dev(xc->parent,
+ "xc5k: hw %d.%d, fw %d.%d.%d\n",
+ (xcversion >> 12) & 0xf,
+ (xcversion >> 8) & 0xf,
+ (xcversion >> 4) & 0xf,
+ xcversion & 0xf,
+ xcbuild);
+ }
done:
if (fw)
@@ -228,7 +243,8 @@
struct xc5k *
xc5k_open(device_t parent, i2c_tag_t i2c, i2c_addr_t addr,
- xc5k_reset_cb reset, void *reset_priv)
+ xc5k_reset_cb reset, void *reset_priv, unsigned int if_freq,
+ fe_type_t fe_type)
{
struct xc5k *xc;
uint16_t product_id;
@@ -241,6 +257,8 @@
xc->i2c_addr = addr;
xc->reset = reset;
xc->reset_priv = reset_priv;
+ xc->if_freq = if_freq;
+ xc->fe_type = fe_type;
if (xc5k_read_2(xc, XC5K_REG_PRODUCT_ID, &product_id))
goto failed;
@@ -275,7 +293,7 @@
}
int
-xc5k_tune(struct xc5k *xc, struct xc5k_params *params)
+xc5k_tune_video(struct xc5k *xc, struct xc5k_params *params)
{
uint16_t amode, vmode;
uint16_t lock, freq;
@@ -298,9 +316,11 @@
return EIO;
if (xc5k_write_2(xc, XC5K_REG_AUDIO_MODE, amode))
return EIO;
+ if (xc5k_write_2(xc, XC5K_REG_OUTAMP, XC5K_OUTAMP_ANALOG))
+ return EIO;
freq = (params->frequency * 62500) / 15625;
#ifdef XC5K_DEBUG
- printf("xc5k_tune: frequency=%u (%u Hz)\n", params->frequency,
+ printf("xc5k_tune_video: frequency=%u (%u Hz)\n", params->frequency,
params->frequency * 62500);
printf(" freq=%u\n", freq);
#endif
@@ -312,7 +332,7 @@
if (xc5k_read_2(xc, XC5K_REG_LOCK, &lock))
return EIO;
#ifdef XC5K_DEBUG
- printf("xc5k_tune: lock=0x%04x\n", lock);
+ printf("xc5k_tune_video: lock=0x%04x\n", lock);
#endif
if (lock == 1)
break;
@@ -322,6 +342,98 @@
return 0;
}
+int
+xc5k_tune_dtv(struct xc5k *xc, const struct dvb_frontend_parameters *params)
+{
+ uint16_t amode, vmode;
+ uint32_t freq, ifout;
+ int signal_source;
+ fe_modulation_t modulation;
+
+ if (xc->fe_type == FE_ATSC)
+ modulation = params->u.vsb.modulation;
+ else if (xc->fe_type == FE_QAM)
+ modulation = params->u.qam.modulation;
+ else
+ return EINVAL;
+
+ switch (modulation) {
+ case VSB_8:
+ case VSB_16:
+ signal_source = XC5K_SIGNAL_SOURCE_AIR;
+ switch (xc->fe_type) {
+ case FE_ATSC:
+ amode = XC5K_AUDIO_MODE_DTV6;
+ vmode = XC5K_VIDEO_MODE_DTV6;
+ freq = params->frequency - 1750000;
+ break;
+ default:
+ return EINVAL;
+ }
+ break;
+ case QAM_16:
+ case QAM_32:
+ case QAM_64:
+ case QAM_128:
+ case QAM_256:
+ signal_source = XC5K_SIGNAL_SOURCE_CABLE;
+ switch (xc->fe_type) {
+ case FE_ATSC:
+ amode = XC5K_AUDIO_MODE_DTV6;
+ vmode = XC5K_VIDEO_MODE_DTV6;
+ freq = params->frequency - 1750000;
+ break;
+ case FE_QAM:
+ amode = XC5K_AUDIO_MODE_DTV78;
+ vmode = XC5K_VIDEO_MODE_DTV78;
+ freq = params->frequency - 2750000;
+ break;
+ default:
+ return EINVAL;
+ }
+ break;
+ default:
+ return EINVAL;
+ }
+
+ if (freq > XC5K_FREQ_MAX || freq < XC5K_FREQ_MIN)
+ return ERANGE;
+
+ if (xc5k_write_2(xc, XC5K_REG_SIGNAL_SOURCE, signal_source))
+ return EIO;
+ if (xc5k_write_2(xc, XC5K_REG_VIDEO_MODE, vmode))
+ return EIO;
+ if (xc5k_write_2(xc, XC5K_REG_AUDIO_MODE, amode))
+ return EIO;
+ ifout = ((xc->if_freq / 1000) * 1024) / 1000;
+ if (xc5k_write_2(xc, XC5K_REG_IF_OUT, ifout))
+ return EIO;
+ if (xc5k_write_2(xc, XC5K_REG_OUTAMP, XC5K_OUTAMP_DIGITAL))
+ return EIO;
+ freq = (uint16_t)(freq / 15625);
+ if (xc5k_write_2(xc, XC5K_REG_FINER_FREQ, freq))
+ return EIO;
+
+ return 0;
+}
+
+fe_status_t
+xc5k_get_status(struct xc5k *xc)
+{
+ uint16_t lock_status;
+ fe_status_t festatus = 0;
+
+ if (xc5k_read_2(xc, XC5K_REG_LOCK, &lock_status))
+ return 0;
+ if (lock_status & XC5K_LOCK_LOCKED) {
+ festatus |= FE_HAS_LOCK;
+ if ((lock_status & XC5K_LOCK_NOSIGNAL) == 0)
+ festatus |= FE_HAS_SIGNAL;
+ }
+
+ return festatus;
+}
+
MODULE(MODULE_CLASS_DRIVER, xc5k, NULL);
static int
@@ -329,7 +441,7 @@
{
switch (cmd) {
case MODULE_CMD_INIT:
- mutex_init(&xc5k_firmware_lock, MUTEX_DEFAULT, IPL_VM);
+ mutex_init(&xc5k_firmware_lock, MUTEX_DEFAULT, IPL_NONE);
return 0;
case MODULE_CMD_FINI:
mutex_destroy(&xc5k_firmware_lock);
Index: src/sys/dev/i2c/xc5kreg.h
diff -u src/sys/dev/i2c/xc5kreg.h:1.1 src/sys/dev/i2c/xc5kreg.h:1.2
--- src/sys/dev/i2c/xc5kreg.h:1.1 Mon Dec 27 15:42:11 2010
+++ src/sys/dev/i2c/xc5kreg.h Sat Jul 9 15:00:44 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: xc5kreg.h,v 1.1 2010/12/27 15:42:11 jmcneill Exp $ */
+/* $NetBSD: xc5kreg.h,v 1.2 2011/07/09 15:00:44 jmcneill Exp $ */
/*-
* Copyright (c) 2010 Jared D. McNeill <[email protected]>
@@ -33,13 +33,24 @@
#define XC5K_REG_INIT 0x00
#define XC5K_REG_VIDEO_MODE 0x01
#define XC5K_VIDEO_MODE_BTSC 0x8028
+#define XC5K_VIDEO_MODE_DTV6 0x8002
+#define XC5K_VIDEO_MODE_DTV7 0x8007
+#define XC5K_VIDEO_MODE_DTV8 0x800b
+#define XC5K_VIDEO_MODE_DTV78 0x801b
#define XC5K_REG_AUDIO_MODE 0x02
#define XC5K_AUDIO_MODE_BTSC 0x0400
+#define XC5K_AUDIO_MODE_DTV6 0x00c0
+#define XC5K_AUDIO_MODE_DTV7 0x00c0
+#define XC5K_AUDIO_MODE_DTV8 0x00c0
+#define XC5K_AUDIO_MODE_DTV78 0x00c0
#define XC5K_REG_RF_FREQ 0x03
#define XC5K_REG_D_CODE 0x04
#define XC5K_REG_IF_OUT 0x05
#define XC5K_REG_SEEK_MODE 0x07
#define XC5K_REG_POWER_DOWN 0x0a
+#define XC5K_REG_OUTAMP 0x0b
+#define XC5K_OUTAMP_DIGITAL 0x008a
+#define XC5K_OUTAMP_ANALOG 0x0009
#define XC5K_REG_SIGNAL_SOURCE 0x0d
#define XC5K_SIGNAL_SOURCE_AIR 0
#define XC5K_SIGNAL_SOURCE_CABLE 1
@@ -54,6 +65,8 @@
#define XC5K_REG_FRAME_LINES 0x02
#define XC5K_REG_HSYNC_FREQ 0x03
#define XC5K_REG_LOCK 0x04
+#define XC5K_LOCK_LOCKED 0x0001
+#define XC5K_LOCK_NOSIGNAL 0x0002
#define XC5K_REG_FREQ_ERR 0x05
#define XC5K_REG_SNR 0x06
#define XC5K_REG_VERSION 0x07
Index: src/sys/dev/i2c/xc5kvar.h
diff -u src/sys/dev/i2c/xc5kvar.h:1.1 src/sys/dev/i2c/xc5kvar.h:1.2
--- src/sys/dev/i2c/xc5kvar.h:1.1 Mon Dec 27 15:42:11 2010
+++ src/sys/dev/i2c/xc5kvar.h Sat Jul 9 15:00:44 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: xc5kvar.h,v 1.1 2010/12/27 15:42:11 jmcneill Exp $ */
+/* $NetBSD: xc5kvar.h,v 1.2 2011/07/09 15:00:44 jmcneill Exp $ */
/*-
* Copyright (c) 2010 Jared D. McNeill <[email protected]>
@@ -30,6 +30,7 @@
#define _XC5KVAR_H
#include <dev/i2c/i2cvar.h>
+#include <dev/dtv/dtvio.h>
#include <dev/video_if.h>
typedef int (*xc5k_reset_cb)(void *);
@@ -41,6 +42,9 @@
xc5k_reset_cb reset;
void *reset_priv;
+
+ unsigned int if_freq;
+ fe_type_t fe_type;
};
struct xc5k_params {
@@ -50,8 +54,10 @@
};
struct xc5k * xc5k_open(device_t, i2c_tag_t, i2c_addr_t,
- xc5k_reset_cb, void *);
+ xc5k_reset_cb, void *, unsigned int, fe_type_t);
void xc5k_close(struct xc5k *);
-int xc5k_tune(struct xc5k *, struct xc5k_params *);
+int xc5k_tune_video(struct xc5k *, struct xc5k_params *);
+int xc5k_tune_dtv(struct xc5k *, const struct dvb_frontend_parameters *);
+fe_status_t xc5k_get_status(struct xc5k *);
#endif /* !_XC5KVAR_H */
Index: src/sys/dev/usb/auvitek.c
diff -u src/sys/dev/usb/auvitek.c:1.3 src/sys/dev/usb/auvitek.c:1.4
--- src/sys/dev/usb/auvitek.c:1.3 Tue Dec 28 04:02:33 2010
+++ src/sys/dev/usb/auvitek.c Sat Jul 9 15:00:44 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: auvitek.c,v 1.3 2010/12/28 04:02:33 jmcneill Exp $ */
+/* $NetBSD: auvitek.c,v 1.4 2011/07/09 15:00:44 jmcneill Exp $ */
/*-
* Copyright (c) 2010 Jared D. McNeill <[email protected]>
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: auvitek.c,v 1.3 2010/12/28 04:02:33 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: auvitek.c,v 1.4 2011/07/09 15:00:44 jmcneill Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -115,7 +115,9 @@
sc->sc_dying = sc->sc_running = 0;
- mutex_init(&sc->sc_subdev_lock, MUTEX_DEFAULT, IPL_VM);
+ mutex_init(&sc->sc_subdev_lock, MUTEX_DEFAULT, IPL_NONE);
+ mutex_init(&sc->sc_ab.ab_lock, MUTEX_DEFAULT, IPL_USB);
+ cv_init(&sc->sc_ab.ab_cv, "auvitekbulk");
err = usbd_set_config_index(dev, 0, 1);
if (err) {
@@ -123,14 +125,23 @@
usbd_errstr(err));
return;
}
- err = usbd_device2interface_handle(dev, 0, &sc->sc_iface);
+ err = usbd_device2interface_handle(dev, 0, &sc->sc_isoc_iface);
+ if (err) {
+ aprint_error_dev(self, "couldn't get interface handle: %s\n",
+ usbd_errstr(err));
+ return;
+ }
+ err = usbd_device2interface_handle(dev, 3, &sc->sc_bulk_iface);
if (err) {
aprint_error_dev(self, "couldn't get interface handle: %s\n",
usbd_errstr(err));
return;
}
- err = usbd_set_interface(sc->sc_iface, AUVITEK_XFER_ALTNO);
+ sc->sc_ax.ax_sc = sc->sc_ab.ab_sc = sc;
+ sc->sc_ax.ax_endpt = sc->sc_ab.ab_endpt = -1;
+
+ err = usbd_set_interface(sc->sc_isoc_iface, AUVITEK_XFER_ALTNO);
if (err) {
aprint_error_dev(self, "couldn't set interface: %s\n",
usbd_errstr(err));
@@ -138,13 +149,11 @@
}
nep = 0;
- usbd_endpoint_count(sc->sc_iface, &nep);
- sc->sc_ax.ax_sc = sc;
- sc->sc_ax.ax_endpt = -1;
+ usbd_endpoint_count(sc->sc_isoc_iface, &nep);
for (i = 0; i < nep; i++) {
int dir, type;
- ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
+ ed = usbd_interface2endpoint_descriptor(sc->sc_isoc_iface, i);
if (ed == NULL) {
aprint_error_dev(self,
"couldn't read endpoint descriptor %d\n", i);
@@ -154,21 +163,22 @@
dir = UE_GET_DIR(ed->bEndpointAddress);
type = UE_GET_XFERTYPE(ed->bmAttributes);
- if (dir == UE_DIR_IN && type == UE_ISOCHRONOUS) {
+ if (dir == UE_DIR_IN && type == UE_ISOCHRONOUS &&
+ sc->sc_ax.ax_endpt == -1) {
sc->sc_ax.ax_endpt = ed->bEndpointAddress;
sc->sc_ax.ax_maxpktlen =
UE_GET_SIZE(UGETW(ed->wMaxPacketSize)) *
(UE_GET_TRANS(UGETW(ed->wMaxPacketSize)) + 1);
- break;
}
}
- err = usbd_set_interface(sc->sc_iface, 0);
+
+ err = usbd_set_interface(sc->sc_isoc_iface, 0);
if (err) {
aprint_error_dev(self, "couldn't set interface: %s\n",
usbd_errstr(err));
- sc->sc_dying = 1;
return;
}
+
if (sc->sc_ax.ax_endpt == -1) {
aprint_error_dev(self, "couldn't find isoc endpoint\n");
sc->sc_dying = 1;
@@ -183,11 +193,60 @@
aprint_debug_dev(self, "isoc endpoint 0x%02x size %d\n",
sc->sc_ax.ax_endpt, sc->sc_ax.ax_maxpktlen);
+ nep = 0;
+ usbd_endpoint_count(sc->sc_bulk_iface, &nep);
+ for (i = 0; i < nep; i++) {
+ int dir, type;
+
+ ed = usbd_interface2endpoint_descriptor(sc->sc_bulk_iface, i);
+ if (ed == NULL) {
+ aprint_error_dev(self,
+ "couldn't read endpoint descriptor %d\n", i);
+ continue;
+ }
+
+ dir = UE_GET_DIR(ed->bEndpointAddress);
+ type = UE_GET_XFERTYPE(ed->bmAttributes);
+
+ if (dir == UE_DIR_IN && type == UE_BULK &&
+ sc->sc_ab.ab_endpt == -1) {
+ sc->sc_ab.ab_endpt = ed->bEndpointAddress;
+ }
+ }
+
+ if (sc->sc_ab.ab_endpt == -1) {
+ aprint_error_dev(self, "couldn't find bulk endpoint\n");
+ sc->sc_dying = 1;
+ return;
+ }
+
+ for (i = 0; i < AUVITEK_NBULK_XFERS; i++) {
+ sc->sc_ab.ab_bx[i].bx_sc = sc;
+ sc->sc_ab.ab_bx[i].bx_xfer = usbd_alloc_xfer(sc->sc_udev);
+ if (sc->sc_ab.ab_bx[i].bx_xfer == NULL) {
+ aprint_error_dev(self, "couldn't allocate xfer\n");
+ sc->sc_dying = 1;
+ return;
+ }
+ sc->sc_ab.ab_bx[i].bx_buffer = usbd_alloc_buffer(
+ sc->sc_ab.ab_bx[i].bx_xfer, AUVITEK_BULK_BUFLEN);
+ if (sc->sc_ab.ab_bx[i].bx_buffer == NULL) {
+ aprint_error_dev(self,
+ "couldn't allocate xfer buffer\n");
+ sc->sc_dying = 1;
+ return;
+ }
+ }
+
+ aprint_debug_dev(self, "bulk endpoint 0x%02x size %d\n",
+ sc->sc_ab.ab_endpt, AUVITEK_BULK_BUFLEN);
+
auvitek_board_init(sc);
auvitek_i2c_attach(sc);
- sc->sc_au8522 = au8522_open(self, &sc->sc_i2c, 0x8e >> 1);
+ sc->sc_au8522 = au8522_open(self, &sc->sc_i2c, 0x8e >> 1,
+ auvitek_board_get_if_frequency(sc));
if (sc->sc_au8522 == NULL) {
aprint_error_dev(sc->sc_dev, "couldn't initialize decoder\n");
sc->sc_dying = 1;
@@ -196,17 +255,20 @@
auvitek_video_attach(sc);
auvitek_audio_attach(sc);
+ auvitek_dtv_attach(sc);
}
static int
auvitek_detach(device_t self, int flags)
{
struct auvitek_softc *sc = device_private(self);
+ unsigned int i;
sc->sc_dying = 1;
pmf_device_deregister(self);
+ auvitek_dtv_detach(sc, flags);
auvitek_audio_detach(sc, flags);
auvitek_video_detach(sc, flags);
@@ -219,6 +281,13 @@
mutex_destroy(&sc->sc_subdev_lock);
+ for (i = 0; i < AUVITEK_NBULK_XFERS; i++) {
+ if (sc->sc_ab.ab_bx[i].bx_xfer)
+ usbd_free_xfer(sc->sc_ab.ab_bx[i].bx_xfer);
+ }
+ cv_destroy(&sc->sc_ab.ab_cv);
+ mutex_destroy(&sc->sc_ab.ab_lock);
+
return 0;
}
@@ -242,6 +311,8 @@
struct auvitek_softc *sc = device_private(self);
auvitek_video_childdet(sc, child);
+ auvitek_audio_childdet(sc, child);
+ auvitek_dtv_childdet(sc, child);
}
uint8_t
@@ -287,7 +358,7 @@
usbd_errstr(err));
}
-MODULE(MODULE_CLASS_DRIVER, auvitek, "au8522,xc5k");
+MODULE(MODULE_CLASS_DRIVER, auvitek, "au8522,xc5k,dtv");
#ifdef _MODULE
#include "ioconf.c"
Index: src/sys/dev/usb/auvitek_video.c
diff -u src/sys/dev/usb/auvitek_video.c:1.3 src/sys/dev/usb/auvitek_video.c:1.4
--- src/sys/dev/usb/auvitek_video.c:1.3 Thu May 26 23:42:39 2011
+++ src/sys/dev/usb/auvitek_video.c Sat Jul 9 15:00:45 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: auvitek_video.c,v 1.3 2011/05/26 23:42:39 jmcneill Exp $ */
+/* $NetBSD: auvitek_video.c,v 1.4 2011/07/09 15:00:45 jmcneill Exp $ */
/*-
* Copyright (c) 2010 Jared D. McNeill <[email protected]>
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: auvitek_video.c,v 1.3 2011/05/26 23:42:39 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: auvitek_video.c,v 1.4 2011/07/09 15:00:45 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -100,9 +100,8 @@
uint8_t *, uint32_t);
static void auvitek_videobuf_weave(struct auvitek_softc *,
uint8_t *, uint32_t);
-static int auvitek_tuner_reset(void *);
-static const struct video_hw_if auvitek_hw_if = {
+static const struct video_hw_if auvitek_video_if = {
.open = auvitek_open,
.close = auvitek_close,
.get_devname = auvitek_get_devname,
@@ -133,7 +132,7 @@
{
snprintf(sc->sc_businfo, sizeof(sc->sc_businfo), "usb:%08x",
sc->sc_udev->cookie.cookie);
- sc->sc_videodev = video_attach_mi(&auvitek_hw_if, sc->sc_dev);
+ sc->sc_videodev = video_attach_mi(&auvitek_video_if, sc->sc_dev);
return (sc->sc_videodev != NULL);
}
@@ -167,7 +166,9 @@
mutex_enter(&sc->sc_subdev_lock);
if (sc->sc_xc5k == NULL) {
sc->sc_xc5k = xc5k_open(sc->sc_dev, &sc->sc_i2c, 0xc2 >> 1,
- auvitek_tuner_reset, sc);
+ auvitek_board_tuner_reset, sc,
+ auvitek_board_get_if_frequency(sc),
+ FE_ATSC);
}
mutex_exit(&sc->sc_subdev_lock);
@@ -525,7 +526,7 @@
params.frequency = vf->frequency;
if (sc->sc_au8522)
au8522_set_audio(sc->sc_au8522, false);
- error = xc5k_tune(sc->sc_xc5k, ¶ms);
+ error = xc5k_tune_video(sc->sc_xc5k, ¶ms);
if (sc->sc_au8522)
au8522_set_audio(sc->sc_au8522, true);
if (error)
@@ -548,7 +549,7 @@
usbd_status err;
int i;
- err = usbd_set_interface(sc->sc_iface, AUVITEK_XFER_ALTNO);
+ err = usbd_set_interface(sc->sc_isoc_iface, AUVITEK_XFER_ALTNO);
if (err != USBD_NORMAL_COMPLETION) {
aprint_error_dev(sc->sc_dev, "couldn't set altno %d: %s\n",
AUVITEK_XFER_ALTNO, usbd_errstr(err));
@@ -562,7 +563,7 @@
ax->ax_nframes = nframes;
ax->ax_uframe_len = uframe_len;
- for (i = 0; i < AUVITEK_NXFERS; i++) {
+ for (i = 0; i < AUVITEK_NISOC_XFERS; i++) {
struct auvitek_isoc *isoc = &ax->ax_i[i];
isoc->i_ax = ax;
isoc->i_frlengths =
@@ -570,7 +571,7 @@
KM_SLEEP);
}
- err = usbd_open_pipe(sc->sc_iface, ax->ax_endpt,
+ err = usbd_open_pipe(sc->sc_isoc_iface, ax->ax_endpt,
USBD_EXCLUSIVE_USE, &ax->ax_pipe);
if (err != USBD_NORMAL_COMPLETION) {
aprint_error_dev(sc->sc_dev, "couldn't open pipe: %s\n",
@@ -578,7 +579,7 @@
return EIO;
}
- for (i = 0; i < AUVITEK_NXFERS; i++) {
+ for (i = 0; i < AUVITEK_NISOC_XFERS; i++) {
struct auvitek_isoc *isoc = &ax->ax_i[i];
isoc->i_xfer = usbd_alloc_xfer(sc->sc_udev);
@@ -613,7 +614,7 @@
ax->ax_pipe = NULL;
}
- for (i = 0; i < AUVITEK_NXFERS; i++) {
+ for (i = 0; i < AUVITEK_NISOC_XFERS; i++) {
struct auvitek_isoc *isoc = &ax->ax_i[i];
if (isoc->i_xfer != NULL) {
usbd_free_buffer(isoc->i_xfer);
@@ -628,7 +629,7 @@
}
usbd_delay_ms(sc->sc_udev, 1000);
- err = usbd_set_interface(sc->sc_iface, 0);
+ err = usbd_set_interface(sc->sc_isoc_iface, 0);
if (err != USBD_NORMAL_COMPLETION) {
aprint_error_dev(sc->sc_dev,
"couldn't set zero bw interface: %s\n",
@@ -649,7 +650,7 @@
ax->ax_av.av_eb = ax->ax_av.av_ob = 0;
ax->ax_av.av_stride = 720 * 2;
- for (i = 0; i < AUVITEK_NXFERS; i++) {
+ for (i = 0; i < AUVITEK_NISOC_XFERS; i++) {
error = auvitek_isoc_start1(&ax->ax_i[i]);
if (error)
return error;
@@ -797,11 +798,3 @@
resid -= wlen;
}
}
-
-static int
-auvitek_tuner_reset(void *priv)
-{
- struct auvitek_softc *sc = priv;
-
- return auvitek_board_tuner_reset(sc);
-}
Index: src/sys/dev/usb/auvitek_board.c
diff -u src/sys/dev/usb/auvitek_board.c:1.2 src/sys/dev/usb/auvitek_board.c:1.3
--- src/sys/dev/usb/auvitek_board.c:1.2 Tue Dec 28 04:02:33 2010
+++ src/sys/dev/usb/auvitek_board.c Sat Jul 9 15:00:44 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: auvitek_board.c,v 1.2 2010/12/28 04:02:33 jmcneill Exp $ */
+/* $NetBSD: auvitek_board.c,v 1.3 2011/07/09 15:00:44 jmcneill Exp $ */
/*-
* Copyright (c) 2010 Jared D. McNeill <[email protected]>
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: auvitek_board.c,v 1.2 2010/12/28 04:02:33 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: auvitek_board.c,v 1.3 2011/07/09 15:00:44 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -97,8 +97,9 @@
}
int
-auvitek_board_tuner_reset(struct auvitek_softc *sc)
+auvitek_board_tuner_reset(void *priv)
{
+ struct auvitek_softc *sc = priv;
uint8_t val;
switch (sc->sc_board) {
@@ -117,3 +118,9 @@
return 0;
}
+
+unsigned int
+auvitek_board_get_if_frequency(struct auvitek_softc *sc)
+{
+ return 6000000; /* 6MHz */
+}
Index: src/sys/dev/usb/auvitekvar.h
diff -u src/sys/dev/usb/auvitekvar.h:1.2 src/sys/dev/usb/auvitekvar.h:1.3
--- src/sys/dev/usb/auvitekvar.h:1.2 Tue Dec 28 04:02:33 2010
+++ src/sys/dev/usb/auvitekvar.h Sat Jul 9 15:00:45 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: auvitekvar.h,v 1.2 2010/12/28 04:02:33 jmcneill Exp $ */
+/* $NetBSD: auvitekvar.h,v 1.3 2011/07/09 15:00:45 jmcneill Exp $ */
/*-
* Copyright (c) 2010 Jared D. McNeill <[email protected]>
@@ -30,6 +30,8 @@
#define _AUVITEKVAR_H
#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/kthread.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
@@ -47,8 +49,10 @@
AUVITEK_BOARD_HVR_950Q,
};
-#define AUVITEK_NXFERS 8
+#define AUVITEK_NISOC_XFERS 16
+#define AUVITEK_NBULK_XFERS 1
#define AUVITEK_XFER_ALTNO 5
+#define AUVITEK_BULK_BUFLEN 58658 /* BDA driver uses the same */
struct auvitek_isoc {
struct auvitek_xfer *i_ax;
@@ -69,7 +73,7 @@
int ax_endpt;
uint16_t ax_maxpktlen;
usbd_pipe_handle ax_pipe;
- struct auvitek_isoc ax_i[AUVITEK_NXFERS];
+ struct auvitek_isoc ax_i[AUVITEK_NISOC_XFERS];
uint32_t ax_nframes;
uint32_t ax_uframe_len;
uint8_t ax_frinfo;
@@ -77,15 +81,32 @@
struct auvitek_videobuf ax_av;
};
+struct auvitek_bulk_xfer {
+ struct auvitek_softc *bx_sc;
+ usbd_xfer_handle bx_xfer;
+ uint8_t *bx_buffer;
+};
+
+struct auvitek_bulk {
+ struct auvitek_softc *ab_sc;
+ int ab_endpt;
+ usbd_pipe_handle ab_pipe;
+ struct auvitek_bulk_xfer ab_bx[AUVITEK_NBULK_XFERS];
+ bool ab_running;
+ kmutex_t ab_lock;
+ kcondvar_t ab_cv;
+};
+
struct auvitek_softc {
device_t sc_dev;
- device_t sc_videodev, sc_audiodev;
+ device_t sc_videodev, sc_dtvdev, sc_audiodev;
struct i2c_controller sc_i2c;
kmutex_t sc_i2c_lock;
usbd_device_handle sc_udev;
int sc_uport;
- usbd_interface_handle sc_iface;
+ usbd_interface_handle sc_isoc_iface;
+ usbd_interface_handle sc_bulk_iface;
char sc_running;
char sc_dying;
@@ -102,6 +123,7 @@
uint32_t sc_curfreq;
struct auvitek_xfer sc_ax;
+ struct auvitek_bulk sc_ab;
char sc_businfo[32];
};
@@ -117,7 +139,8 @@
/* auvitek_board.c */
void auvitek_board_init(struct auvitek_softc *);
-int auvitek_board_tuner_reset(struct auvitek_softc *);
+int auvitek_board_tuner_reset(void *);
+unsigned int auvitek_board_get_if_frequency(struct auvitek_softc *);
/* auvitek_i2c.c */
int auvitek_i2c_attach(struct auvitek_softc *);
@@ -128,4 +151,9 @@
int auvitek_video_detach(struct auvitek_softc *, int);
void auvitek_video_childdet(struct auvitek_softc *, device_t);
+/* auvitek_dtv.c */
+int auvitek_dtv_attach(struct auvitek_softc *);
+int auvitek_dtv_detach(struct auvitek_softc *, int);
+void auvitek_dtv_childdet(struct auvitek_softc *, device_t);
+
#endif /* !_AUVITEKVAR_H */
Index: src/sys/dev/usb/auvitek_i2c.c
diff -u src/sys/dev/usb/auvitek_i2c.c:1.1 src/sys/dev/usb/auvitek_i2c.c:1.2
--- src/sys/dev/usb/auvitek_i2c.c:1.1 Mon Dec 27 15:42:11 2010
+++ src/sys/dev/usb/auvitek_i2c.c Sat Jul 9 15:00:45 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: auvitek_i2c.c,v 1.1 2010/12/27 15:42:11 jmcneill Exp $ */
+/* $NetBSD: auvitek_i2c.c,v 1.2 2011/07/09 15:00:45 jmcneill Exp $ */
/*-
* Copyright (c) 2010 Jared D. McNeill <[email protected]>
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: auvitek_i2c.c,v 1.1 2010/12/27 15:42:11 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: auvitek_i2c.c,v 1.2 2011/07/09 15:00:45 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -121,7 +121,7 @@
uint8_t v;
unsigned int i;
- KASSERT(mutex_owned(&sc->sc_i2c_lock));
+ //KASSERT(mutex_owned(&sc->sc_i2c_lock));
auvitek_write_1(sc, AU0828_REG_I2C_MBMODE, 1);
auvitek_write_1(sc, AU0828_REG_I2C_CLKDIV, sc->sc_i2c_clkdiv);
@@ -160,7 +160,7 @@
uint8_t v;
unsigned int i, fifolen;
- KASSERT(mutex_owned(&sc->sc_i2c_lock));
+ //KASSERT(mutex_owned(&sc->sc_i2c_lock));
auvitek_write_1(sc, AU0828_REG_I2C_MBMODE, 1);
auvitek_write_1(sc, AU0828_REG_I2C_CLKDIV, sc->sc_i2c_clkdiv);
Added files:
Index: src/sys/dev/i2c/au8522mod.h
diff -u /dev/null src/sys/dev/i2c/au8522mod.h:1.1
--- /dev/null Sat Jul 9 15:00:45 2011
+++ src/sys/dev/i2c/au8522mod.h Sat Jul 9 15:00:43 2011
@@ -0,0 +1,41 @@
+/* $NetBSD: au8522mod.h,v 1.1 2011/07/09 15:00:43 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2011 Jared D. McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _AU8522MOD_H
+#define _AU8522MOD_H
+
+struct au8522_modulation_table {
+ uint16_t reg;
+ uint8_t val;
+};
+
+#include <dev/i2c/au8522mod_8vsb.h>
+#include <dev/i2c/au8522mod_qam64.h>
+#include <dev/i2c/au8522mod_qam256.h>
+
+#endif /* !_AU8522MOD_H */
Index: src/sys/dev/i2c/au8522mod_8vsb.h
diff -u /dev/null src/sys/dev/i2c/au8522mod_8vsb.h:1.1
--- /dev/null Sat Jul 9 15:00:46 2011
+++ src/sys/dev/i2c/au8522mod_8vsb.h Sat Jul 9 15:00:43 2011
@@ -0,0 +1,57 @@
+/* $NetBSD: au8522mod_8vsb.h,v 1.1 2011/07/09 15:00:43 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2011 Jared D. McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+static const struct au8522_modulation_table au8522_modulation_8vsb[] = {
+ { 0x8090, 0x84 },
+ { 0x4092, 0x11 },
+ { 0x2005, 0x00 },
+ { 0x8091, 0x80 },
+ { 0x80a3, 0x0c },
+ { 0x80a4, 0xe8 },
+ { 0x8081, 0xc4 },
+ { 0x80a5, 0x40 },
+ { 0x80a7, 0x40 },
+ { 0x80a6, 0x67 },
+ { 0x8262, 0x20 },
+ { 0x821c, 0x30 },
+ { 0x80d8, 0x1a },
+ { 0x8227, 0xa0 },
+ { 0x8121, 0xff },
+ { 0x80a8, 0xf0 },
+ { 0x80a9, 0x05 },
+ { 0x80aa, 0x77 },
+ { 0x80ab, 0xf0 },
+ { 0x80ac, 0x05 },
+ { 0x80ad, 0x77 },
+ { 0x80ae, 0x41 },
+ { 0x80af, 0x66 },
+ { 0x821b, 0xcc },
+ { 0x821d, 0x80 },
+ { 0x80a4, 0xe8 },
+ { 0x8231, 0x13 },
+};
Index: src/sys/dev/i2c/au8522mod_qam256.h
diff -u /dev/null src/sys/dev/i2c/au8522mod_qam256.h:1.1
--- /dev/null Sat Jul 9 15:00:46 2011
+++ src/sys/dev/i2c/au8522mod_qam256.h Sat Jul 9 15:00:43 2011
@@ -0,0 +1,102 @@
+/* $NetBSD: au8522mod_qam256.h,v 1.1 2011/07/09 15:00:43 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2011 Jared D. McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+static const struct au8522_modulation_table au8522_modulation_qam256[] = {
+ { 0x80a3, 0x09 },
+ { 0x80a4, 0x00 },
+ { 0x8081, 0xc4 },
+ { 0x80a5, 0x40 },
+ { 0x80aa, 0x77 },
+ { 0x80ad, 0x77 },
+ { 0x80a6, 0x67 },
+ { 0x8262, 0x20 },
+ { 0x821c, 0x30 },
+ { 0x80b8, 0x3e },
+ { 0x80b9, 0xf0 },
+ { 0x80ba, 0x01 },
+ { 0x80bb, 0x18 },
+ { 0x80bc, 0x50 },
+ { 0x80bd, 0x00 },
+ { 0x80be, 0xea },
+ { 0x80bf, 0xef },
+ { 0x80c0, 0xfc },
+ { 0x80c1, 0xbd },
+ { 0x80c2, 0x1f },
+ { 0x80c3, 0xfc },
+ { 0x80c4, 0xdd },
+ { 0x80c5, 0xaf },
+ { 0x80c6, 0x00 },
+ { 0x80c7, 0x38 },
+ { 0x80c8, 0x30 },
+ { 0x80c9, 0x05 },
+ { 0x80ca, 0x4a },
+ { 0x80cb, 0xd0 },
+ { 0x80cc, 0x01 },
+ { 0x80cd, 0xd9 },
+ { 0x80ce, 0x6f },
+ { 0x80cf, 0xf9 },
+ { 0x80d0, 0x70 },
+ { 0x80d1, 0xdf },
+ { 0x80d2, 0xf7 },
+ { 0x80d3, 0xc2 },
+ { 0x80d4, 0xdf },
+ { 0x80d5, 0x02 },
+ { 0x80d6, 0x9a },
+ { 0x80d7, 0xd0 },
+ { 0x8250, 0x0d },
+ { 0x8251, 0xcd },
+ { 0x8252, 0xe0 },
+ { 0x8253, 0x05 },
+ { 0x8254, 0xa7 },
+ { 0x8255, 0xff },
+ { 0x8256, 0xed },
+ { 0x8257, 0x5b },
+ { 0x8258, 0xae },
+ { 0x8259, 0xe6 },
+ { 0x825a, 0x3d },
+ { 0x825b, 0x0f },
+ { 0x825c, 0x0d },
+ { 0x825d, 0xea },
+ { 0x825e, 0xf2 },
+ { 0x825f, 0x51 },
+ { 0x8260, 0xf5 },
+ { 0x8261, 0x06 },
+ { 0x821a, 0x00 },
+ { 0x8546, 0x40 },
+ { 0x8210, 0x26 },
+ { 0x8211, 0xf6 },
+ { 0x8212, 0x84 },
+ { 0x8213, 0x02 },
+ { 0x8502, 0x01 },
+ { 0x8121, 0x04 },
+ { 0x8122, 0x04 },
+ { 0x852e, 0x10 },
+ { 0x80a4, 0xca },
+ { 0x80a7, 0x40 },
+ { 0x8526, 0x01 },
+};
Index: src/sys/dev/i2c/au8522mod_qam64.h
diff -u /dev/null src/sys/dev/i2c/au8522mod_qam64.h:1.1
--- /dev/null Sat Jul 9 15:00:46 2011
+++ src/sys/dev/i2c/au8522mod_qam64.h Sat Jul 9 15:00:44 2011
@@ -0,0 +1,102 @@
+/* $NetBSD: au8522mod_qam64.h,v 1.1 2011/07/09 15:00:44 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2011 Jared D. McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+static const struct au8522_modulation_table au8522_modulation_qam64[] = {
+ { 0x00a3, 0x09 },
+ { 0x00a4, 0x00 },
+ { 0x0081, 0xc4 },
+ { 0x00a5, 0x40 },
+ { 0x00aa, 0x77 },
+ { 0x00ad, 0x77 },
+ { 0x00a6, 0x67 },
+ { 0x0262, 0x20 },
+ { 0x021c, 0x30 },
+ { 0x00b8, 0x3e },
+ { 0x00b9, 0xf0 },
+ { 0x00ba, 0x01 },
+ { 0x00bb, 0x18 },
+ { 0x00bc, 0x50 },
+ { 0x00bd, 0x00 },
+ { 0x00be, 0xea },
+ { 0x00bf, 0xef },
+ { 0x00c0, 0xfc },
+ { 0x00c1, 0xbd },
+ { 0x00c2, 0x1f },
+ { 0x00c3, 0xfc },
+ { 0x00c4, 0xdd },
+ { 0x00c5, 0xaf },
+ { 0x00c6, 0x00 },
+ { 0x00c7, 0x38 },
+ { 0x00c8, 0x30 },
+ { 0x00c9, 0x05 },
+ { 0x00ca, 0x4a },
+ { 0x00cb, 0xd0 },
+ { 0x00cc, 0x01 },
+ { 0x00cd, 0xd9 },
+ { 0x00ce, 0x6f },
+ { 0x00cf, 0xf9 },
+ { 0x00d0, 0x70 },
+ { 0x00d1, 0xdf },
+ { 0x00d2, 0xf7 },
+ { 0x00d3, 0xc2 },
+ { 0x00d4, 0xdf },
+ { 0x00d5, 0x02 },
+ { 0x00d6, 0x9a },
+ { 0x00d7, 0xd0 },
+ { 0x0250, 0x0d },
+ { 0x0251, 0xcd },
+ { 0x0252, 0xe0 },
+ { 0x0253, 0x05 },
+ { 0x0254, 0xa7 },
+ { 0x0255, 0xff },
+ { 0x0256, 0xed },
+ { 0x0257, 0x5b },
+ { 0x0258, 0xae },
+ { 0x0259, 0xe6 },
+ { 0x025a, 0x3d },
+ { 0x025b, 0x0f },
+ { 0x025c, 0x0d },
+ { 0x025d, 0xea },
+ { 0x025e, 0xf2 },
+ { 0x025f, 0x51 },
+ { 0x0260, 0xf5 },
+ { 0x0261, 0x06 },
+ { 0x021a, 0x00 },
+ { 0x0546, 0x40 },
+ { 0x0210, 0xc7 },
+ { 0x0211, 0xaa },
+ { 0x0212, 0xab },
+ { 0x0213, 0x02 },
+ { 0x0502, 0x00 },
+ { 0x0121, 0x04 },
+ { 0x0122, 0x04 },
+ { 0x052e, 0x10 },
+ { 0x00a4, 0xca },
+ { 0x00a7, 0x40 },
+ { 0x0526, 0x01 },
+};
Index: src/sys/dev/usb/auvitek_dtv.c
diff -u /dev/null src/sys/dev/usb/auvitek_dtv.c:1.1
--- /dev/null Sat Jul 9 15:00:46 2011
+++ src/sys/dev/usb/auvitek_dtv.c Sat Jul 9 15:00:44 2011
@@ -0,0 +1,345 @@
+/* $NetBSD: auvitek_dtv.c,v 1.1 2011/07/09 15:00:44 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2011 Jared D. McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Auvitek AU0828 USB controller (Digital TV function)
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: auvitek_dtv.c,v 1.1 2011/07/09 15:00:44 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/kmem.h>
+#include <sys/bus.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usbdevs.h>
+
+#include <dev/dtv/dtvif.h>
+
+#include <dev/usb/auvitekreg.h>
+#include <dev/usb/auvitekvar.h>
+
+static void auvitek_dtv_get_devinfo(void *,
+ struct dvb_frontend_info *);
+static int auvitek_dtv_open(void *, int);
+static void auvitek_dtv_close(void *);
+static int auvitek_dtv_set_tuner(void *,
+ const struct dvb_frontend_parameters *);
+static fe_status_t auvitek_dtv_get_status(void *);
+static uint16_t auvitek_dtv_get_signal_strength(void *);
+static uint16_t auvitek_dtv_get_snr(void *);
+static int auvitek_dtv_start_transfer(void *);
+static int auvitek_dtv_stop_transfer(void *);
+
+static int auvitek_dtv_init_pipes(struct auvitek_softc *);
+static int auvitek_dtv_close_pipes(struct auvitek_softc *);
+
+static int auvitek_dtv_bulk_start(struct auvitek_softc *);
+static int auvitek_dtv_bulk_start1(struct auvitek_bulk_xfer *);
+static void auvitek_dtv_bulk_cb(usbd_xfer_handle,
+ usbd_private_handle,
+ usbd_status);
+
+static const struct dtv_hw_if auvitek_dtv_if = {
+ .get_devinfo = auvitek_dtv_get_devinfo,
+ .open = auvitek_dtv_open,
+ .close = auvitek_dtv_close,
+ .set_tuner = auvitek_dtv_set_tuner,
+ .get_status = auvitek_dtv_get_status,
+ .get_signal_strength = auvitek_dtv_get_signal_strength,
+ .get_snr = auvitek_dtv_get_snr,
+ .start_transfer = auvitek_dtv_start_transfer,
+ .stop_transfer = auvitek_dtv_stop_transfer,
+};
+
+int
+auvitek_dtv_attach(struct auvitek_softc *sc)
+{
+ struct dtv_attach_args daa;
+
+ daa.hw = &auvitek_dtv_if;
+ daa.priv = sc;
+ sc->sc_dtvdev = config_found_ia(sc->sc_dev, "dtvbus", &daa, dtv_print);
+
+ return (sc->sc_dtvdev != NULL);
+}
+
+int
+auvitek_dtv_detach(struct auvitek_softc *sc, int flags)
+{
+ if (sc->sc_dtvdev != NULL) {
+ config_detach(sc->sc_dtvdev, flags);
+ sc->sc_dtvdev = NULL;
+ }
+
+ return 0;
+}
+
+void
+auvitek_dtv_childdet(struct auvitek_softc *sc, device_t child)
+{
+ if (sc->sc_dtvdev == child)
+ sc->sc_dtvdev = NULL;
+}
+
+static void
+auvitek_dtv_get_devinfo(void *priv, struct dvb_frontend_info *info)
+{
+ struct auvitek_softc *sc = priv;
+
+ memset(info, 0, sizeof(*info));
+ strlcpy(info->name, sc->sc_descr, sizeof(info->name));
+ info->type = FE_ATSC;
+ info->frequency_min = 54000000;
+ info->frequency_max = 858000000;
+ info->frequency_stepsize = 62500;
+ info->caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB;
+}
+
+static int
+auvitek_dtv_open(void *priv, int flags)
+{
+ struct auvitek_softc *sc = priv;
+
+ if (sc->sc_dying)
+ return EIO;
+
+ mutex_enter(&sc->sc_subdev_lock);
+ if (sc->sc_xc5k == NULL) {
+ sc->sc_xc5k = xc5k_open(sc->sc_dev, &sc->sc_i2c, 0xc2 >> 1,
+ auvitek_board_tuner_reset, sc,
+ auvitek_board_get_if_frequency(sc),
+ FE_ATSC);
+ }
+ mutex_exit(&sc->sc_subdev_lock);
+
+ if (sc->sc_xc5k == NULL)
+ return ENXIO;
+
+ return auvitek_dtv_init_pipes(sc);
+}
+
+static void
+auvitek_dtv_close(void *priv)
+{
+ struct auvitek_softc *sc = priv;
+
+ auvitek_dtv_stop_transfer(sc);
+ auvitek_dtv_close_pipes(sc);
+}
+
+static int
+auvitek_dtv_set_tuner(void *priv, const struct dvb_frontend_parameters *params)
+{
+ struct auvitek_softc *sc = priv;
+ int error;
+
+ error = au8522_set_modulation(sc->sc_au8522, params->u.vsb.modulation);
+ if (error)
+ return error;
+
+ delay(100000);
+
+ au8522_set_gate(sc->sc_au8522, true);
+ error = xc5k_tune_dtv(sc->sc_xc5k, params);
+ au8522_set_gate(sc->sc_au8522, false);
+
+ return error;
+}
+
+fe_status_t
+auvitek_dtv_get_status(void *priv)
+{
+ struct auvitek_softc *sc = priv;
+
+ return au8522_get_dtv_status(sc->sc_au8522);
+}
+
+uint16_t
+auvitek_dtv_get_signal_strength(void *priv)
+{
+ return 0; /* TODO */
+}
+
+uint16_t
+auvitek_dtv_get_snr(void *priv)
+{
+ return 0; /* TODO */
+}
+
+static int
+auvitek_dtv_start_transfer(void *priv)
+{
+ struct auvitek_softc *sc = priv;
+ int s;
+
+ if (sc->sc_ab.ab_running) {
+ return 0;
+ }
+
+ auvitek_write_1(sc, 0x608, 0x90);
+ auvitek_write_1(sc, 0x609, 0x72);
+ auvitek_write_1(sc, 0x60a, 0x71);
+ auvitek_write_1(sc, 0x60b, 0x01);
+
+ sc->sc_ab.ab_running = true;
+
+ s = splusb();
+ auvitek_dtv_bulk_start(sc);
+ splx(s);
+
+ return 0;
+}
+
+static int
+auvitek_dtv_stop_transfer(void *priv)
+{
+ struct auvitek_softc *sc = priv;
+
+ sc->sc_ab.ab_running = false;
+
+ auvitek_write_1(sc, 0x608, 0x00);
+ auvitek_write_1(sc, 0x609, 0x00);
+ auvitek_write_1(sc, 0x60a, 0x00);
+ auvitek_write_1(sc, 0x60b, 0x00);
+
+ return 0;
+}
+
+static int
+auvitek_dtv_init_pipes(struct auvitek_softc *sc)
+{
+ usbd_status err;
+
+ err = usbd_open_pipe(sc->sc_bulk_iface, sc->sc_ab.ab_endpt,
+ USBD_EXCLUSIVE_USE, &sc->sc_ab.ab_pipe);
+ if (err) {
+ aprint_error_dev(sc->sc_dev, "couldn't open bulk-in pipe: %s\n",
+ usbd_errstr(err));
+ return ENOMEM;
+ }
+
+ return 0;
+}
+
+static int
+auvitek_dtv_close_pipes(struct auvitek_softc *sc)
+{
+ if (sc->sc_ab.ab_pipe != NULL) {
+ usbd_abort_pipe(sc->sc_ab.ab_pipe);
+ usbd_close_pipe(sc->sc_ab.ab_pipe);
+ sc->sc_ab.ab_pipe = NULL;
+ }
+
+ return 0;
+}
+
+static void
+auvitek_dtv_bulk_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
+ usbd_status status)
+{
+ struct auvitek_bulk_xfer *bx = priv;
+ struct auvitek_softc *sc = bx->bx_sc;
+ struct auvitek_bulk *ab = &sc->sc_ab;
+ struct dtv_payload payload;
+ uint32_t xferlen;
+
+ if (ab->ab_running == false)
+ return;
+
+ usbd_get_xfer_status(xfer, NULL, NULL, &xferlen, NULL);
+
+ //printf("%s: status=%d xferlen=%u\n", __func__, status, xferlen);
+
+ if (status != USBD_NORMAL_COMPLETION) {
+ printf("%s: USB error (%s)\n", __func__, usbd_errstr(status));
+ if (status == USBD_STALLED) {
+ usbd_clear_endpoint_stall_async(ab->ab_pipe);
+ goto next;
+ }
+ if (status == USBD_SHORT_XFER) {
+ goto next;
+ }
+ return;
+ }
+
+ if (xferlen == 0) {
+ printf("%s: 0-length xfer\n", __func__);
+ goto next;
+ }
+
+ payload.data = bx->bx_buffer;
+ payload.size = xferlen;
+ dtv_submit_payload(sc->sc_dtvdev, &payload);
+
+next:
+ auvitek_dtv_bulk_start1(bx);
+}
+
+static int
+auvitek_dtv_bulk_start(struct auvitek_softc *sc)
+{
+ int i, error;
+
+ for (i = 0; i < AUVITEK_NBULK_XFERS; i++) {
+ error = auvitek_dtv_bulk_start1(&sc->sc_ab.ab_bx[i]);
+ if (error)
+ return error;
+ }
+
+ return 0;
+}
+
+static int
+auvitek_dtv_bulk_start1(struct auvitek_bulk_xfer *bx)
+{
+ struct auvitek_softc *sc = bx->bx_sc;
+ struct auvitek_bulk *ab = &sc->sc_ab;
+ int err;
+
+ usbd_setup_xfer(bx->bx_xfer, ab->ab_pipe, bx,
+ bx->bx_buffer, AUVITEK_BULK_BUFLEN,
+ //USBD_SHORT_XFER_OK|USBD_NO_COPY, USBD_NO_TIMEOUT,
+ USBD_NO_COPY, 100,
+ auvitek_dtv_bulk_cb);
+ err = usbd_transfer(bx->bx_xfer);
+ if (err != USBD_IN_PROGRESS) {
+ aprint_error_dev(sc->sc_dev, "USB error: %s\n",
+ usbd_errstr(err));
+ return ENODEV;
+ }
+
+ return 0;
+}