diff options
author | Patrick Boettcher <pb@linuxtv.org> | 2006-09-19 12:51:43 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-10-03 15:12:40 -0300 |
commit | 0540c4961fcc6d69b8a3314c330c376890715eee (patch) | |
tree | 8babf9a7a6d10f4ebc5990009ad64328daf044a5 /drivers/media/dvb/dvb-usb/vp702x.c | |
parent | 6958effedb0dc709966c22e7fd0e8210b5401b84 (diff) | |
download | kernel_samsung_aries-0540c4961fcc6d69b8a3314c330c376890715eee.zip kernel_samsung_aries-0540c4961fcc6d69b8a3314c330c376890715eee.tar.gz kernel_samsung_aries-0540c4961fcc6d69b8a3314c330c376890715eee.tar.bz2 |
V4L/DVB (4649): Merged VP702x support to dvb-usb multi input
The fixed support for the VP70x (supports only StarBox2) is now in sync with
latest changes in the dvb-usb framework.
Signed-off-by: Patrick Boettcher <pb@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/dvb/dvb-usb/vp702x.c')
-rw-r--r-- | drivers/media/dvb/dvb-usb/vp702x.c | 173 |
1 files changed, 113 insertions, 60 deletions
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c index fdab256..02bd61a 100644 --- a/drivers/media/dvb/dvb-usb/vp702x.c +++ b/drivers/media/dvb/dvb-usb/vp702x.c @@ -22,50 +22,54 @@ module_param_named(debug,dvb_usb_vp702x_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); struct vp702x_state { - u8 pid_table[17]; /* [16] controls the pid_table state */ + int pid_filter_count; + int pid_filter_can_bypass; + u8 pid_filter_state; +}; + +struct vp702x_device_state { + u8 power_state; }; /* check for mutex FIXME */ int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) { - int ret = 0,try = 0; + int ret = -1; - while (ret >= 0 && ret != blen && try < 3) { ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev,0), req, USB_TYPE_VENDOR | USB_DIR_IN, value,index,b,blen, 2000); - deb_info("reading number %d (ret: %d)\n",try,ret); - try++; - } - if (ret < 0 || ret != blen) { - warn("usb in operation failed."); + if (ret < 0) { + warn("usb in operation failed. (%d)", ret); ret = -EIO; } else ret = 0; - deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index); + + deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); debug_dump(b,blen,deb_xfer); return ret; } -static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, +int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) { - deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index); + int ret; + deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); debug_dump(b,blen,deb_xfer); - if (usb_control_msg(d->udev, + if ((ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev,0), req, USB_TYPE_VENDOR | USB_DIR_OUT, value,index,b,blen, - 2000) != blen) { - warn("usb out operation failed."); + 2000)) != blen) { + warn("usb out operation failed. (%d)",ret); return -EIO; } else return 0; @@ -78,12 +82,10 @@ int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int il if ((ret = mutex_lock_interruptible(&d->usb_mutex))) return ret; - if ((ret = vp702x_usb_out_op(d,REQUEST_OUT,0,0,o,olen)) < 0) - goto unlock; + ret = vp702x_usb_out_op(d,REQUEST_OUT,0,0,o,olen); msleep(msec); ret = vp702x_usb_in_op(d,REQUEST_IN,0,0,i,ilen); -unlock: mutex_unlock(&d->usb_mutex); return ret; @@ -108,29 +110,65 @@ static int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, return ret; } -static int vp702x_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) +static int vp702x_set_pld_mode(struct dvb_usb_adapter *adap, u8 bypass) +{ + u8 buf[16] = { 0 }; + return vp702x_usb_in_op(adap->dev, 0xe0, (bypass << 8) | 0x0e, 0, buf, 16); +} + +static int vp702x_set_pld_state(struct dvb_usb_adapter *adap, u8 state) +{ + u8 buf[16] = { 0 }; + return vp702x_usb_in_op(adap->dev, 0xe0, (state << 8) | 0x0f, 0, buf, 16); +} + +static int vp702x_set_pid(struct dvb_usb_adapter *adap, u16 pid, u8 id, int onoff) { struct vp702x_state *st = adap->priv; - u8 buf[9]; - - if (onoff) { - st->pid_table[16] |= 1 << index; - st->pid_table[index*2] = (pid >> 8) & 0xff; - st->pid_table[index*2+1] = pid & 0xff; - } else { - st->pid_table[16] &= ~(1 << index); - st->pid_table[index*2] = st->pid_table[index*2+1] = 0; + u8 buf[16] = { 0 }; + + if (onoff) + st->pid_filter_state |= (1 << id); + else { + st->pid_filter_state &= ~(1 << id); + pid = 0xffff; } - return vp702x_usb_inout_cmd(adap->dev,SET_PID_FILTER,st->pid_table,17,buf,9,10); + id = 0x10 + id*2; + + vp702x_set_pld_state(adap, st->pid_filter_state); + vp702x_usb_in_op(adap->dev, 0xe0, (((pid >> 8) & 0xff) << 8) | (id), 0, buf, 16); + vp702x_usb_in_op(adap->dev, 0xe0, (((pid ) & 0xff) << 8) | (id+1), 0, buf, 16); + return 0; } -static int vp702x_power_ctrl(struct dvb_usb_device *d, int onoff) + +static int vp702x_init_pid_filter(struct dvb_usb_adapter *adap) { - vp702x_usb_in_op(d,RESET_TUNER,0,0,NULL,0); + struct vp702x_state *st = adap->priv; + int i; + u8 b[10] = { 0 }; - vp702x_usb_in_op(d,SET_TUNER_POWER_REQ,0,onoff,NULL,0); - return vp702x_usb_in_op(d,SET_TUNER_POWER_REQ,0,onoff,NULL,0); + st->pid_filter_count = 8; + st->pid_filter_can_bypass = 1; + st->pid_filter_state = 0x00; + + vp702x_set_pld_mode(adap, 1); // bypass + + for (i = 0; i < st->pid_filter_count; i++) + vp702x_set_pid(adap, 0xffff, i, 1); + + vp702x_usb_in_op(adap->dev, 0xb5, 3, 0, b, 10); + vp702x_usb_in_op(adap->dev, 0xb5, 0, 0, b, 10); + vp702x_usb_in_op(adap->dev, 0xb5, 1, 0, b, 10); + + //vp702x_set_pld_mode(d, 0); // filter + return 0; +} + +static int vp702x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) +{ + return 0; } /* keys for the enclosed remote control */ @@ -166,26 +204,45 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) return 0; } +int vp702x_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + struct vp702x_device_state *st = d->priv; + + if (st->power_state == 0 && onoff) + vp702x_usb_out_op(d, SET_TUNER_POWER_REQ, 1, 7, NULL, 0); + else if (st->power_state == 1 && onoff == 0) + vp702x_usb_out_op(d, SET_TUNER_POWER_REQ, 0, 7, NULL, 0); + + st->power_state = onoff; + + return 0; +} + static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6]) { - u8 macb[9]; - if (vp702x_usb_inout_cmd(d, GET_MAC_ADDRESS, NULL, 0, macb, 9, 10)) - return -EIO; - memcpy(mac,&macb[3],6); + u8 i; + for (i = 6; i < 12; i++) + vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &mac[i - 6], 1); return 0; } static int vp702x_frontend_attach(struct dvb_usb_adapter *adap) { - u8 buf[9] = { 0 }; + u8 buf[10] = { 0 }; + + vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 0, 7, NULL, 0); - if (vp702x_usb_inout_cmd(adap->dev, GET_SYSTEM_STRING, NULL, 0, buf, 9, 10)) + if (vp702x_usb_inout_cmd(adap->dev, GET_SYSTEM_STRING, NULL, 0, buf, 10, 10)) return -EIO; - buf[8] = '\0'; + buf[9] = '\0'; info("system string: %s",&buf[1]); + vp702x_init_pid_filter(adap); + adap->fe = vp702x_fe_attach(adap->dev); + vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 1, 7, NULL, 0); + return 0; } @@ -194,39 +251,36 @@ static struct dvb_usb_device_properties vp702x_properties; static int vp702x_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - struct usb_device *udev = interface_to_usbdev(intf); - - usb_clear_halt(udev,usb_sndctrlpipe(udev,0)); - usb_clear_halt(udev,usb_rcvctrlpipe(udev,0)); - return dvb_usb_device_init(intf,&vp702x_properties,THIS_MODULE,NULL); } static struct usb_device_id vp702x_usb_table [] = { { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7021_COLD) }, - { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7021_WARM) }, - { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_COLD) }, - { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_WARM) }, +// { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_COLD) }, +// { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_WARM) }, { 0 }, }; MODULE_DEVICE_TABLE(usb, vp702x_usb_table); static struct dvb_usb_device_properties vp702x_properties = { .usb_ctrl = CYPRESS_FX2, - .firmware = "dvb-usb-vp702x-01.fw", + .firmware = "dvb-usb-vp702x-02.fw", + .no_reconnect = 1, + + .size_of_priv = sizeof(struct vp702x_device_state), .num_adapters = 1, .adapter = { { - .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, - .pid_filter_count = 8, /* !!! */ + .caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS, - .pid_filter = vp702x_pid_filter, + .streaming_ctrl = vp702x_streaming_ctrl, .frontend_attach = vp702x_frontend_attach, + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, + .count = 10, .endpoint = 0x02, .u = { .bulk = { @@ -235,9 +289,8 @@ static struct dvb_usb_device_properties vp702x_properties = { } }, .size_of_priv = sizeof(struct vp702x_state), + } }, - }, - .power_ctrl = vp702x_power_ctrl, .read_mac_address = vp702x_read_mac_addr, .rc_key_map = vp702x_rc_keys, @@ -245,23 +298,23 @@ static struct dvb_usb_device_properties vp702x_properties = { .rc_interval = 400, .rc_query = vp702x_rc_query, - .num_device_descs = 2, + .num_device_descs = 1, .devices = { { .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7021)", .cold_ids = { &vp702x_usb_table[0], NULL }, - .warm_ids = { &vp702x_usb_table[1], NULL }, + .warm_ids = { NULL }, }, - { .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7020)", +/* { .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7020)", .cold_ids = { &vp702x_usb_table[2], NULL }, .warm_ids = { &vp702x_usb_table[3], NULL }, }, - { 0 }, +*/ { NULL }, } }; /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver vp702x_usb_driver = { - .name = "dvb-usb-vp702x", + .name = "dvb_usb_vp702x", .probe = vp702x_usb_probe, .disconnect = dvb_usb_device_exit, .id_table = vp702x_usb_table, @@ -290,5 +343,5 @@ module_exit(vp702x_usb_module_exit); MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); MODULE_DESCRIPTION("Driver for Twinhan StarBox DVB-S USB2.0 and clones"); -MODULE_VERSION("1.0-alpha"); +MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); |