diff options
Diffstat (limited to 'linux/drivers')
55 files changed, 1078 insertions, 275 deletions
diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index f1d172a3f..9c2494168 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -104,6 +104,56 @@ IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE] = { EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt); +/* Mauro Carvalho Chehab <mchehab@infradead.org> */ +IR_KEYTAB_TYPE ir_codes_avermedia_m135a[IR_KEYTAB_SIZE] = { + [0x00] = KEY_POWER2, + [0x2e] = KEY_DOT, /* '.' */ + [0x01] = KEY_MODE, /* TV/FM */ + + [0x05] = KEY_1, + [0x06] = KEY_2, + [0x07] = KEY_3, + [0x09] = KEY_4, + [0x0a] = KEY_5, + [0x0b] = KEY_6, + [0x0d] = KEY_7, + [0x0e] = KEY_8, + [0x0f] = KEY_9, + [0x11] = KEY_0, + + [0x13] = KEY_RIGHT, /* -> */ + [0x12] = KEY_LEFT, /* <- */ + + [0x17] = KEY_SLEEP, /* Capturar Imagem */ + [0x10] = KEY_SHUFFLE, /* Amostra */ + + /* FIXME: The keys bellow aren't ok */ + + [0x43] = KEY_CHANNELUP, + [0x42] = KEY_CHANNELDOWN, + [0x1f] = KEY_VOLUMEUP, + [0x1e] = KEY_VOLUMEDOWN, + [0x0c] = KEY_ENTER, + + [0x14] = KEY_MUTE, + [0x08] = KEY_AUDIO, + + [0x03] = KEY_TEXT, + [0x04] = KEY_EPG, + [0x2b] = KEY_TV2, /* TV2 */ + + [0x1d] = KEY_RED, + [0x1c] = KEY_YELLOW, + [0x41] = KEY_GREEN, + [0x40] = KEY_BLUE, + + [0x1a] = KEY_PLAYPAUSE, + [0x19] = KEY_RECORD, + [0x18] = KEY_PLAY, + [0x1b] = KEY_STOP, +}; +EXPORT_SYMBOL_GPL(ir_codes_avermedia_m135a); + /* Attila Kondoros <attila.kondoros@chello.hu> */ IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { @@ -2338,3 +2388,86 @@ IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE] = { [0x2a] = KEY_MENU, }; EXPORT_SYMBOL_GPL(ir_codes_avermedia_a16d); + +/* Encore ENLTV-FM v5.3 + Mauro Carvalho Chehab <mchehab@infradead.org> + */ +IR_KEYTAB_TYPE ir_codes_encore_enltv_fm53[IR_KEYTAB_SIZE] = { + [0x10] = KEY_POWER2, + [0x06] = KEY_MUTE, + + [0x09] = KEY_1, + [0x1d] = KEY_2, + [0x1f] = KEY_3, + [0x19] = KEY_4, + [0x1b] = KEY_5, + [0x11] = KEY_6, + [0x17] = KEY_7, + [0x12] = KEY_8, + [0x16] = KEY_9, + [0x48] = KEY_0, + + [0x04] = KEY_LIST, /* -/-- */ + [0x40] = KEY_LAST, /* recall */ + + [0x02] = KEY_MODE, /* TV/AV */ + [0x05] = KEY_SHUFFLE, /* SNAPSHOT */ + + [0x4c] = KEY_CHANNELUP, /* UP */ + [0x00] = KEY_CHANNELDOWN, /* DOWN */ + [0x0d] = KEY_VOLUMEUP, /* RIGHT */ + [0x15] = KEY_VOLUMEDOWN, /* LEFT */ + [0x49] = KEY_ENTER, /* OK */ + + [0x54] = KEY_RECORD, + [0x4d] = KEY_PLAY, /* pause */ + + [0x1e] = KEY_UP, /* video setting */ + [0x0e] = KEY_RIGHT, /* <- */ + [0x1a] = KEY_LEFT, /* -> */ + + [0x0a] = KEY_DOWN, /* video default */ + [0x0c] = KEY_ZOOM, /* hide pannel */ + [0x47] = KEY_SLEEP, /* shutdown */ +}; +EXPORT_SYMBOL_GPL(ir_codes_encore_enltv_fm53); + +/* Zogis Real Audio 220 - 32 keys IR */ +IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE] = { + [0x1c] = KEY_RADIO, + [0x12] = KEY_POWER2, + + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + [0x00] = KEY_0, + + [0x0c] = KEY_VOLUMEUP, + [0x18] = KEY_VOLUMEDOWN, + [0x0b] = KEY_CHANNELUP, + [0x15] = KEY_CHANNELDOWN, + [0x16] = KEY_ENTER, + + [0x11] = KEY_LIST, /* Source */ + [0x0d] = KEY_AUDIO, /* stereo */ + + [0x0f] = KEY_PREVIOUS, /* Prev */ + [0x1b] = KEY_PAUSE, /* Timeshift */ + [0x1a] = KEY_NEXT, /* Next */ + + [0x0e] = KEY_STOP, + [0x1f] = KEY_PLAY, + [0x1e] = KEY_PLAYPAUSE, /* Pause */ + + [0x1d] = KEY_RECORD, + [0x13] = KEY_MUTE, + [0x19] = KEY_SHUFFLE, /* Snapshot */ + +}; +EXPORT_SYMBOL_GPL(ir_codes_real_audio_220_32_keys); diff --git a/linux/drivers/media/common/tuners/tda827x.c b/linux/drivers/media/common/tuners/tda827x.c index 763b0dd95..83a017c53 100644 --- a/linux/drivers/media/common/tuners/tda827x.c +++ b/linux/drivers/media/common/tuners/tda827x.c @@ -448,17 +448,19 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high, else arg = 0; } - if (priv->cfg->tuner_callback) - priv->cfg->tuner_callback(priv->i2c_adap->algo_data, - gp_func, arg); + if (fe->callback) + fe->callback(priv->i2c_adap->algo_data, + DVB_FRONTEND_COMPONENT_TUNER, + gp_func, arg); buf[1] = high ? 0 : 1; if (priv->cfg->config == 2) buf[1] = high ? 1 : 0; i2c_transfer(priv->i2c_adap, &msg, 1); break; case 3: /* switch with GPIO of saa713x */ - if (priv->cfg->tuner_callback) - priv->cfg->tuner_callback(priv->i2c_adap->algo_data, 0, high); + if (fe->callback) + fe->callback(priv->i2c_adap->algo_data, + DVB_FRONTEND_COMPONENT_TUNER, 0, high); break; } } diff --git a/linux/drivers/media/common/tuners/tda827x.h b/linux/drivers/media/common/tuners/tda827x.h index 7850a9a1d..7d72ce0a0 100644 --- a/linux/drivers/media/common/tuners/tda827x.h +++ b/linux/drivers/media/common/tuners/tda827x.h @@ -36,7 +36,6 @@ struct tda827x_config /* interface to tda829x driver */ unsigned int config; int switch_addr; - int (*tuner_callback) (void *dev, int command, int arg); void (*agcf)(struct dvb_frontend *fe); }; diff --git a/linux/drivers/media/common/tuners/tda8290.c b/linux/drivers/media/common/tuners/tda8290.c index 751845554..637849ec8 100644 --- a/linux/drivers/media/common/tuners/tda8290.c +++ b/linux/drivers/media/common/tuners/tda8290.c @@ -695,10 +695,8 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, priv->i2c_props.addr = i2c_addr; priv->i2c_props.adap = i2c_adap; priv->i2c_props.name = "tda829x"; - if (cfg) { + if (cfg) priv->cfg.config = cfg->lna_cfg; - priv->cfg.tuner_callback = cfg->tuner_callback; - } if (tda8290_probe(&priv->i2c_props) == 0) { priv->ver = TDA8290; diff --git a/linux/drivers/media/common/tuners/tda8290.h b/linux/drivers/media/common/tuners/tda8290.h index aa074f3f0..7e288b26f 100644 --- a/linux/drivers/media/common/tuners/tda8290.h +++ b/linux/drivers/media/common/tuners/tda8290.h @@ -22,7 +22,6 @@ struct tda829x_config { unsigned int lna_cfg; - int (*tuner_callback) (void *dev, int command, int arg); unsigned int probe_tuner:1; #define TDA829X_PROBE_TUNER 0 diff --git a/linux/drivers/media/common/tuners/tuner-xc2028.c b/linux/drivers/media/common/tuners/tuner-xc2028.c index a3272e81e..7f43272ca 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.c +++ b/linux/drivers/media/common/tuners/tuner-xc2028.c @@ -75,9 +75,6 @@ struct firmware_properties { struct xc2028_data { struct list_head hybrid_tuner_instance_list; struct tuner_i2c_props i2c_props; - int (*tuner_callback) (void *dev, - int command, int arg); - void *video_dev; __u32 frequency; struct firmware_description *firm; @@ -496,6 +493,23 @@ ret: return i; } +static inline int do_tuner_callback(struct dvb_frontend *fe, int cmd, int arg) +{ + struct xc2028_data *priv = fe->tuner_priv; + + /* analog side (tuner-core) uses i2c_adap->algo_data. + * digital side is not guaranteed to have algo_data defined. + * + * digital side will always have fe->dvb defined. + * analog side (tuner-core) doesn't (yet) define fe->dvb. + */ + + return (!fe->callback) ? -EINVAL : + fe->callback(((fe->dvb) && (fe->dvb->priv)) ? + fe->dvb->priv : priv->i2c_props.adap->algo_data, + DVB_FRONTEND_COMPONENT_TUNER, cmd, arg); +} + static int load_firmware(struct dvb_frontend *fe, unsigned int type, v4l2_std_id *id) { @@ -534,8 +548,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type, if (!size) { /* Special callback command received */ - rc = priv->tuner_callback(priv->video_dev, - XC2028_TUNER_RESET, 0); + rc = do_tuner_callback(fe, XC2028_TUNER_RESET, 0); if (rc < 0) { tuner_err("Error at RESET code %d\n", (*p) & 0x7f); @@ -546,8 +559,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type, if (size >= 0xff00) { switch (size) { case 0xff00: - rc = priv->tuner_callback(priv->video_dev, - XC2028_RESET_CLK, 0); + rc = do_tuner_callback(fe, XC2028_RESET_CLK, 0); if (rc < 0) { tuner_err("Error at RESET code %d\n", (*p) & 0x7f); @@ -719,8 +731,7 @@ retry: memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); /* Reset is needed before loading firmware */ - rc = priv->tuner_callback(priv->video_dev, - XC2028_TUNER_RESET, 0); + rc = do_tuner_callback(fe, XC2028_TUNER_RESET, 0); if (rc < 0) goto fail; @@ -937,7 +948,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, The reset CLK is needed only with tm6000. Driver should work fine even if this fails. */ - priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1); + do_tuner_callback(fe, XC2028_RESET_CLK, 1); msleep(10); @@ -1006,11 +1017,6 @@ static int xc2028_set_params(struct dvb_frontend *fe, tuner_dbg("%s called\n", __func__); - if (priv->ctrl.d2633) - type |= D2633; - else - type |= D2620; - switch(fe->ops.info.type) { case FE_OFDM: bw = p->u.ofdm.bandwidth; @@ -1025,10 +1031,8 @@ static int xc2028_set_params(struct dvb_frontend *fe, break; case FE_ATSC: bw = BANDWIDTH_6_MHZ; - /* The only ATSC firmware (at least on v2.7) is D2633, - so overrides ctrl->d2633 */ - type |= ATSC| D2633; - type &= ~D2620; + /* The only ATSC firmware (at least on v2.7) is D2633 */ + type |= ATSC | D2633; break; /* DVB-S is not supported */ default: @@ -1061,6 +1065,28 @@ static int xc2028_set_params(struct dvb_frontend *fe, tuner_err("error: bandwidth not supported.\n"); }; + /* + Selects between D2633 or D2620 firmware. + It doesn't make sense for ATSC, since it should be D2633 on all cases + */ + if (fe->ops.info.type != FE_ATSC) { + switch (priv->ctrl.type) { + case XC2028_D2633: + type |= D2633; + break; + case XC2028_D2620: + type |= D2620; + break; + case XC2028_AUTO: + default: + /* Zarlink seems to need D2633 */ + if (priv->ctrl.demod == XC3028_FE_ZARLINK456) + type |= D2633; + else + type |= D2620; + } + } + /* All S-code tables need a 200kHz shift */ if (priv->ctrl.demod) demod = priv->ctrl.demod + 200; @@ -1213,20 +1239,10 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, break; case 1: /* new tuner instance */ - priv->tuner_callback = cfg->callback; priv->ctrl.max_len = 13; mutex_init(&priv->lock); - /* analog side (tuner-core) uses i2c_adap->algo_data. - * digital side is not guaranteed to have algo_data defined. - * - * digital side will always have fe->dvb defined. - * analog side (tuner-core) doesn't (yet) define fe->dvb. - */ - priv->video_dev = ((fe->dvb) && (fe->dvb->priv)) ? - fe->dvb->priv : cfg->i2c_adap->algo_data; - fe->tuner_priv = priv; break; case 2: diff --git a/linux/drivers/media/common/tuners/tuner-xc2028.h b/linux/drivers/media/common/tuners/tuner-xc2028.h index 2c5b6282b..19de7928a 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.h +++ b/linux/drivers/media/common/tuners/tuner-xc2028.h @@ -24,24 +24,28 @@ #define XC3028_FE_ZARLINK456 4560 #define XC3028_FE_CHINA 5200 +enum firmware_type { + XC2028_AUTO = 0, /* By default, auto-detects */ + XC2028_D2633, + XC2028_D2620, +}; + struct xc2028_ctrl { char *fname; int max_len; unsigned int scode_table; unsigned int mts :1; - unsigned int d2633 :1; unsigned int input1:1; unsigned int vhfbw7:1; unsigned int uhfbw8:1; unsigned int demod; + enum firmware_type type:2; }; struct xc2028_config { struct i2c_adapter *i2c_adap; u8 i2c_addr; - void *video_dev; struct xc2028_ctrl *ctrl; - int (*callback) (void *dev, int command, int arg); }; /* xc2028 commands for callback */ diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c index 7d4d82d23..f3a3c47fe 100644 --- a/linux/drivers/media/common/tuners/xc5000.c +++ b/linux/drivers/media/common/tuners/xc5000.c @@ -58,8 +58,6 @@ struct xc5000_priv { u32 bandwidth; u8 video_standard; u8 rf_mode; - - int (*tuner_callback) (void *priv, int command, int arg); }; /* Misc Defines */ @@ -232,10 +230,11 @@ static void xc5000_TunerReset(struct dvb_frontend *fe) dprintk(1, "%s()\n", __func__); - if (priv->tuner_callback) { - ret = priv->tuner_callback(((fe->dvb) && (fe->dvb->priv)) ? + if (fe->callback) { + ret = fe->callback(((fe->dvb) && (fe->dvb->priv)) ? fe->dvb->priv : priv->i2c_props.adap->algo_data, + DVB_FRONTEND_COMPONENT_TUNER, XC5000_TUNER_RESET, 0); if (ret) printk(KERN_ERR "xc5000: reset failed\n"); @@ -994,7 +993,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, /* new tuner instance */ priv->bandwidth = BANDWIDTH_6_MHZ; priv->if_khz = cfg->if_khz; - priv->tuner_callback = cfg->tuner_callback; fe->tuner_priv = priv; break; diff --git a/linux/drivers/media/common/tuners/xc5000.h b/linux/drivers/media/common/tuners/xc5000.h index fa0321cfd..cf1a558e0 100644 --- a/linux/drivers/media/common/tuners/xc5000.h +++ b/linux/drivers/media/common/tuners/xc5000.h @@ -30,8 +30,6 @@ struct i2c_adapter; struct xc5000_config { u8 i2c_address; u32 if_khz; - - int (*tuner_callback) (void *priv, int command, int arg); }; /* xc5000 callback command */ diff --git a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 4eed783f4..a127a4175 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -491,6 +491,7 @@ static struct s5h1420_config skystar2_rev2_7_s5h1420_config = { .demod_address = 0x53, .invert = 1, .repeated_start_workaround = 1, + .serial_mpeg = 1, }; static struct itd1000_config skystar2_rev2_7_itd1000_config = { diff --git a/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c index f6016feab..19965a055 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c @@ -94,6 +94,9 @@ struct dvb_ca_slot { /* current state of the CAM */ int slot_state; + /* mutex used for serializing access to one CI slot */ + struct mutex slot_lock; + /* Number of CAMCHANGES that have occurred since last processing */ atomic_t camchange_count; @@ -712,14 +715,20 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * b dprintk("%s\n", __func__); - // sanity check + /* sanity check */ if (bytes_write > ca->slot_info[slot].link_buf_size) return -EINVAL; - /* check if interface is actually waiting for us to read from it, or if a read is in progress */ + /* it is possible we are dealing with a single buffer implementation, + thus if there is data available for read or if there is even a read + already in progress, we do nothing but awake the kernel thread to + process the data if necessary. */ if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exitnowrite; if (status & (STATUSREG_DA | STATUSREG_RE)) { + if (status & STATUSREG_DA) + dvb_ca_en50221_thread_wakeup(ca); + status = -EAGAIN; goto exitnowrite; } @@ -988,6 +997,8 @@ static int dvb_ca_en50221_thread(void *data) /* go through all the slots processing them */ for (slot = 0; slot < ca->slot_count; slot++) { + mutex_lock(&ca->slot_info[slot].slot_lock); + // check the cam status + deal with CAMCHANGEs while (dvb_ca_en50221_check_camstatus(ca, slot)) { /* clear down an old CI slot if necessary */ @@ -1123,7 +1134,7 @@ static int dvb_ca_en50221_thread(void *data) case DVB_CA_SLOTSTATE_RUNNING: if (!ca->open) - continue; + break; // poll slots for data pktcount = 0; @@ -1147,6 +1158,8 @@ static int dvb_ca_en50221_thread(void *data) } break; } + + mutex_unlock(&ca->slot_info[slot].slot_lock); } } @@ -1182,6 +1195,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file, switch (cmd) { case CA_RESET: for (slot = 0; slot < ca->slot_count; slot++) { + mutex_lock(&ca->slot_info[slot].slot_lock); if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) { dvb_ca_en50221_slot_shutdown(ca, slot); if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) @@ -1189,6 +1203,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file, slot, DVB_CA_EN50221_CAMCHANGE_INSERTED); } + mutex_unlock(&ca->slot_info[slot].slot_lock); } ca->next_read_slot = 0; dvb_ca_en50221_thread_wakeup(ca); @@ -1309,7 +1324,9 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file, goto exit; } + mutex_lock(&ca->slot_info[slot].slot_lock); status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen + 2); + mutex_unlock(&ca->slot_info[slot].slot_lock); if (status == (fraglen + 2)) { written = 1; break; @@ -1665,6 +1682,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE; atomic_set(&ca->slot_info[i].camchange_count, 0); ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED; + mutex_init(&ca->slot_info[i].slot_lock); } if (signal_pending(current)) { diff --git a/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.h b/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.h index 8467e63dd..7df2e1411 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.h +++ b/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.h @@ -45,8 +45,10 @@ struct dvb_ca_en50221 { /* the module owning this structure */ struct module* owner; - /* NOTE: the read_*, write_* and poll_slot_status functions must use locks as - * they may be called from several threads at once */ + /* NOTE: the read_*, write_* and poll_slot_status functions will be + * called for different slots concurrently and need to use locks where + * and if appropriate. There will be no concurrent access to one slot. + */ /* functions for accessing attribute memory on the CAM */ int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address); diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h index 1207f29f2..a0c591b3b 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -234,6 +234,8 @@ struct dvb_frontend { void *sec_priv; void *analog_demod_priv; struct dtv_frontend_properties dtv_property_cache; +#define DVB_FRONTEND_COMPONENT_TUNER 0 + int (*callback)(void *adapter_priv, int component, int cmd, int arg); }; extern int dvb_register_frontend(struct dvb_adapter *dvb, diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index 0131424e1..241c9ab54 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -72,9 +72,11 @@ config DVB_USB_DIB0700 select DVB_DIB7000P select DVB_DIB7000M select DVB_DIB3000MC + select DVB_S5H1411 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE + select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE select DVB_TUNER_DIB0070 help Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The diff --git a/linux/drivers/media/dvb/dvb-usb/cxusb.c b/linux/drivers/media/dvb/dvb-usb/cxusb.c index 1a746127c..406d7fba3 100644 --- a/linux/drivers/media/dvb/dvb-usb/cxusb.c +++ b/linux/drivers/media/dvb/dvb-usb/cxusb.c @@ -742,7 +742,8 @@ static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap) return 0; } -static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg) +static int dvico_bluebird_xc2028_callback(void *ptr, int component, + int command, int arg) { struct dvb_usb_adapter *adap = ptr; struct dvb_usb_device *d = adap->dev; @@ -770,7 +771,6 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap) struct xc2028_config cfg = { .i2c_adap = &adap->dev->i2c_adap, .i2c_addr = 0x61, - .callback = dvico_bluebird_xc2028_callback, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, @@ -778,6 +778,9 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap) .demod = XC3028_FE_ZARLINK456, }; + /* FIXME: generalize & move to common area */ + adap->fe->callback = dvico_bluebird_xc2028_callback; + fe = dvb_attach(xc2028_attach, adap->fe, &cfg); if (fe == NULL || fe->ops.tuner_ops.set_config == NULL) return -EIO; diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700.h b/linux/drivers/media/dvb/dvb-usb/dib0700.h index 66d4dc6ba..739193943 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700.h +++ b/linux/drivers/media/dvb/dvb-usb/dib0700.h @@ -31,6 +31,8 @@ extern int dvb_usb_dib0700_debug; // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) #define REQUEST_SET_RC 0x11 +#define REQUEST_NEW_I2C_READ 0x12 +#define REQUEST_NEW_I2C_WRITE 0x13 #define REQUEST_GET_VERSION 0x15 struct dib0700_state { @@ -39,6 +41,8 @@ struct dib0700_state { u8 rc_toggle; u8 rc_counter; u8 is_dib7000pc; + u8 fw_use_new_i2c_api; + u8 disable_streaming_master_mode; }; extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_core.c b/linux/drivers/media/dvb/dvb-usb/dib0700_core.c index a2162fda5..3c7bdef28 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -82,9 +82,98 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_ } /* - * I2C master xfer function + * I2C master xfer function (supported in 1.20 firmware) */ -static int dib0700_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num) +static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, + int num) +{ + /* The new i2c firmware messages are more reliable and in particular + properly support i2c read calls not preceded by a write */ + + struct dvb_usb_device *d = i2c_get_adapdata(adap); + uint8_t bus_mode = 1; /* 0=eeprom bus, 1=frontend bus */ + uint8_t gen_mode = 0; /* 0=master i2c, 1=gpio i2c */ + uint8_t en_start = 0; + uint8_t en_stop = 0; + uint8_t buf[255]; /* TBV: malloc ? */ + int result, i; + + /* Ensure nobody else hits the i2c bus while we're sending our + sequence of messages, (such as the remote control thread) */ + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + for (i = 0; i < num; i++) { + if (i == 0) { + /* First message in the transaction */ + en_start = 1; + } else if (!(msg[i].flags & I2C_M_NOSTART)) { + /* Device supports repeated-start */ + en_start = 1; + } else { + /* Not the first packet and device doesn't support + repeated start */ + en_start = 0; + } + if (i == (num - 1)) { + /* Last message in the transaction */ + en_stop = 1; + } + + if (msg[i].flags & I2C_M_RD) { + /* Read request */ + u16 index, value; + uint8_t i2c_dest; + + i2c_dest = (msg[i].addr << 1); + value = ((en_start << 7) | (en_stop << 6) | + (msg[i].len & 0x3F)) << 8 | i2c_dest; + /* I2C ctrl + FE bus; */ + index = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30); + + result = usb_control_msg(d->udev, + usb_rcvctrlpipe(d->udev, 0), + REQUEST_NEW_I2C_READ, + USB_TYPE_VENDOR | USB_DIR_IN, + value, index, msg[i].buf, + msg[i].len, + USB_CTRL_GET_TIMEOUT); + if (result < 0) { + err("i2c read error (status = %d)\n", result); + break; + } + } else { + /* Write request */ + buf[0] = REQUEST_NEW_I2C_WRITE; + buf[1] = (msg[i].addr << 1); + buf[2] = (en_start << 7) | (en_stop << 6) | + (msg[i].len & 0x3F); + /* I2C ctrl + FE bus; */ + buf[3] = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30); + /* The Actual i2c payload */ + memcpy(&buf[4], msg[i].buf, msg[i].len); + + result = usb_control_msg(d->udev, + usb_sndctrlpipe(d->udev, 0), + REQUEST_NEW_I2C_WRITE, + USB_TYPE_VENDOR | USB_DIR_OUT, + 0, 0, buf, msg[i].len + 4, + USB_CTRL_GET_TIMEOUT); + if (result < 0) { + err("i2c write error (status = %d)\n", result); + break; + } + } + } + mutex_unlock(&d->i2c_mutex); + return i; +} + +/* + * I2C master xfer function (pre-1.20 firmware) + */ +static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, + struct i2c_msg *msg, int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); int i,len; @@ -124,6 +213,21 @@ static int dib0700_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num return i; } +static int dib0700_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, + int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + struct dib0700_state *st = d->priv; + + if (st->fw_use_new_i2c_api == 1) { + /* User running at least fw 1.20 */ + return dib0700_i2c_xfer_new(adap, msg, num); + } else { + /* Use legacy calls */ + return dib0700_i2c_xfer_legacy(adap, msg, num); + } +} + static u32 dib0700_i2c_func(struct i2c_adapter *adapter) { return I2C_FUNC_I2C; @@ -246,7 +350,12 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) b[0] = REQUEST_ENABLE_VIDEO; b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */ - b[2] = (0x01 << 4); /* Master mode */ + + if (st->disable_streaming_master_mode == 1) + b[2] = 0x00; + else + b[2] = (0x01 << 4); /* Master mode */ + b[3] = 0x00; deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id); diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c index 6c0e5c5f4..9891ca092 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -14,6 +14,8 @@ #include "mt2060.h" #include "mt2266.h" #include "tuner-xc2028.h" +#include "xc5000.h" +#include "s5h1411.h" #include "dib0070.h" static int force_lna_activation; @@ -366,7 +368,8 @@ static struct dib7000p_config stk7700ph_dib7700_xc3028_config = { .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, }; -static int stk7700ph_xc3028_callback(void *ptr, int command, int arg) +static int stk7700ph_xc3028_callback(void *ptr, int component, + int command, int arg) { struct dvb_usb_adapter *adap = ptr; @@ -394,7 +397,6 @@ static struct xc2028_ctrl stk7700ph_xc3028_ctrl = { static struct xc2028_config stk7700ph_xc3028_config = { .i2c_addr = 0x61, - .callback = stk7700ph_xc3028_callback, .ctrl = &stk7700ph_xc3028_ctrl, }; @@ -435,7 +437,9 @@ static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap) DIBX000_I2C_INTERFACE_TUNER, 1); stk7700ph_xc3028_config.i2c_adap = tun_i2c; - stk7700ph_xc3028_config.video_dev = adap; + + /* FIXME: generalize & move to common area */ + adap->fe->callback = stk7700ph_xc3028_callback; return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config) == NULL ? -ENODEV : 0; @@ -677,6 +681,43 @@ static struct dvb_usb_rc_key dib0700_rc_keys[] = { { 0x01, 0x7d, KEY_VOLUMEDOWN }, { 0x02, 0x42, KEY_CHANNELUP }, { 0x00, 0x7d, KEY_CHANNELDOWN }, + + /* Key codes for Nova-TD "credit card" remote control. */ + { 0x1d, 0x00, KEY_0 }, + { 0x1d, 0x01, KEY_1 }, + { 0x1d, 0x02, KEY_2 }, + { 0x1d, 0x03, KEY_3 }, + { 0x1d, 0x04, KEY_4 }, + { 0x1d, 0x05, KEY_5 }, + { 0x1d, 0x06, KEY_6 }, + { 0x1d, 0x07, KEY_7 }, + { 0x1d, 0x08, KEY_8 }, + { 0x1d, 0x09, KEY_9 }, + { 0x1d, 0x0a, KEY_TEXT }, + { 0x1d, 0x0d, KEY_MENU }, + { 0x1d, 0x0f, KEY_MUTE }, + { 0x1d, 0x10, KEY_VOLUMEUP }, + { 0x1d, 0x11, KEY_VOLUMEDOWN }, + { 0x1d, 0x12, KEY_CHANNEL }, + { 0x1d, 0x14, KEY_UP }, + { 0x1d, 0x15, KEY_DOWN }, + { 0x1d, 0x16, KEY_LEFT }, + { 0x1d, 0x17, KEY_RIGHT }, + { 0x1d, 0x1c, KEY_TV }, + { 0x1d, 0x1e, KEY_NEXT }, + { 0x1d, 0x1f, KEY_BACK }, + { 0x1d, 0x20, KEY_CHANNELUP }, + { 0x1d, 0x21, KEY_CHANNELDOWN }, + { 0x1d, 0x24, KEY_LAST }, + { 0x1d, 0x25, KEY_OK }, + { 0x1d, 0x30, KEY_PAUSE }, + { 0x1d, 0x32, KEY_REWIND }, + { 0x1d, 0x34, KEY_FASTFORWARD }, + { 0x1d, 0x35, KEY_PLAY }, + { 0x1d, 0x36, KEY_STOP }, + { 0x1d, 0x37, KEY_RECORD }, + { 0x1d, 0x3b, KEY_GOTO }, + { 0x1d, 0x3d, KEY_POWER }, }; /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ @@ -1078,6 +1119,92 @@ static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap) return adap->fe == NULL ? -ENODEV : 0; } +/* S5H1411 */ +static struct s5h1411_config pinnacle_801e_config = { + .output_mode = S5H1411_PARALLEL_OUTPUT, + .gpio = S5H1411_GPIO_OFF, + .mpeg_timing = S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK, + .qam_if = S5H1411_IF_44000, + .vsb_if = S5H1411_IF_44000, + .inversion = S5H1411_INVERSION_OFF, + .status_mode = S5H1411_DEMODLOCKING +}; + +/* Pinnacle PCTV HD Pro 801e GPIOs map: + GPIO0 - currently unknown + GPIO1 - xc5000 tuner reset + GPIO2 - CX25843 sleep + GPIO3 - currently unknown + GPIO4 - currently unknown + GPIO6 - currently unknown + GPIO7 - currently unknown + GPIO9 - currently unknown + GPIO10 - CX25843 reset + */ +static int s5h1411_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct dib0700_state *st = adap->dev->priv; + + /* Make use of the new i2c functions from FW 1.20 */ + st->fw_use_new_i2c_api = 1; + + /* The s5h1411 requires the dib0700 to not be in master mode */ + st->disable_streaming_master_mode = 1; + + /* All msleep values taken from Windows USB trace */ + dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 0); + dib0700_set_gpio(adap->dev, GPIO3, GPIO_OUT, 0); + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); + msleep(400); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); + msleep(60); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); + msleep(30); + dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 0); + msleep(30); + + /* Put the CX25843 to sleep for now since we're in digital mode */ + dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 1); + + /* GPIOs are initialized, do the attach */ + adap->fe = dvb_attach(s5h1411_attach, &pinnacle_801e_config, + &adap->dev->i2c_adap); + return adap->fe == NULL ? -ENODEV : 0; +} + +static int dib0700_xc5000_tuner_callback(void *priv, int component, + int command, int arg) +{ + struct dvb_usb_adapter *adap = priv; + + /* Reset the tuner */ + dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 0); + msleep(330); /* from Windows USB trace */ + dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 1); + msleep(330); /* from Windows USB trace */ + + return 0; +} + +static struct xc5000_config s5h1411_xc5000_tunerconfig = { + .i2c_address = 0x64, + .if_khz = 5380, +}; + +static int xc5000_tuner_attach(struct dvb_usb_adapter *adap) +{ + return dvb_attach(xc5000_attach, adap->fe, &adap->dev->i2c_adap, + &s5h1411_xc5000_tunerconfig) + == NULL ? -ENODEV : 0; + + /* FIXME: generalize & move to common area */ + adap->fe->callback = dib0700_xc5000_tuner_callback; +} + /* DVB-USB and USB stuff follows */ struct usb_device_id dib0700_usb_id_table[] = { /* 0 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, @@ -1119,6 +1246,11 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) }, /* 35 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) }, { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_3) }, + { USB_DEVICE(USB_VID_GIGABYTE, USB_PID_GIGABYTE_U8000) }, + { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700PH) }, + { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000H) }, +/* 40 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E) }, + { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E_SE) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1126,7 +1258,7 @@ MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); #define DIB0700_DEFAULT_DEVICE_PROPERTIES \ .caps = DVB_USB_IS_AN_I2C_ADAPTER, \ .usb_ctrl = DEVICE_SPECIFIC, \ - .firmware = "dvb-usb-dib0700-1.10.fw", \ + .firmware = "dvb-usb-dib0700-1.20.fw", \ .download_firmware = dib0700_download_firmware, \ .no_reconnect = 1, \ .size_of_priv = sizeof(struct dib0700_state), \ @@ -1293,7 +1425,12 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[31], NULL }, { NULL }, } - } + }, + + .rc_interval = DEFAULT_RC_INTERVAL, + .rc_key_map = dib0700_rc_keys, + .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), + .rc_query = dib0700_rc_query }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, .num_adapters = 1, @@ -1408,7 +1545,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 3, + .num_device_descs = 5, .devices = { { "Terratec Cinergy HT USB XE", { &dib0700_usb_id_table[27], NULL }, @@ -1422,6 +1559,47 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[32], NULL }, { NULL }, }, + { "Gigabyte U8000-RH", + { &dib0700_usb_id_table[37], NULL }, + { NULL }, + }, + { "YUAN High-Tech STK7700PH", + { &dib0700_usb_id_table[38], NULL }, + { NULL }, + }, + { "Asus My Cinema-U3000Hybrid", + { &dib0700_usb_id_table[39], NULL }, + { NULL }, + }, + }, + .rc_interval = DEFAULT_RC_INTERVAL, + .rc_key_map = dib0700_rc_keys, + .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), + .rc_query = dib0700_rc_query + }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, + .num_adapters = 1, + .adapter = { + { + .frontend_attach = s5h1411_frontend_attach, + .tuner_attach = xc5000_tuner_attach, + + DIB0700_DEFAULT_STREAMING_CONFIG(0x02), + + .size_of_priv = sizeof(struct + dib0700_adapter_state), + }, + }, + + .num_device_descs = 2, + .devices = { + { "Pinnacle PCTV HD Pro USB Stick", + { &dib0700_usb_id_table[40], NULL }, + { NULL }, + }, + { "Pinnacle PCTV HD USB Stick", + { &dib0700_usb_id_table[41], NULL }, + { NULL }, + }, }, .rc_interval = DEFAULT_RC_INTERVAL, .rc_key_map = dib0700_rc_keys, diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 7ae262e08..dfaf1d257 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -171,6 +171,8 @@ #define USB_PID_PINNACLE_PCTV71E 0x022b #define USB_PID_PINNACLE_PCTV72E 0x0236 #define USB_PID_PINNACLE_PCTV73E 0x0237 +#define USB_PID_PINNACLE_PCTV801E 0x023a +#define USB_PID_PINNACLE_PCTV801E_SE 0x023b #define USB_PID_PCTV_200E 0x020e #define USB_PID_PCTV_400E 0x020f #define USB_PID_PCTV_450E 0x0222 @@ -221,9 +223,12 @@ #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514 #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513 #define USB_PID_GIGABYTE_U7000 0x7001 +#define USB_PID_GIGABYTE_U8000 0x7002 #define USB_PID_ASUS_U3000 0x171f +#define USB_PID_ASUS_U3000H 0x1736 #define USB_PID_ASUS_U3100 0x173f #define USB_PID_YUAN_EC372S 0x1edc +#define USB_PID_YUAN_STK7700PH 0x1f08 #define USB_PID_DW2102 0x2102 #define USB_PID_XTENSIONS_XD_380 0x0381 #define USB_PID_TELESTAR_STARSTICK_2 0x8000 diff --git a/linux/drivers/media/dvb/frontends/s5h1420.c b/linux/drivers/media/dvb/frontends/s5h1420.c index b768da972..46d55e393 100644 --- a/linux/drivers/media/dvb/frontends/s5h1420.c +++ b/linux/drivers/media/dvb/frontends/s5h1420.c @@ -59,7 +59,7 @@ struct s5h1420_state { * it does not support repeated-start, workaround: write addr-1 * and then read */ - u8 shadow[255]; + u8 shadow[256]; }; static u32 s5h1420_getsymbolrate(struct s5h1420_state* state); @@ -94,8 +94,11 @@ static u8 s5h1420_readreg(struct s5h1420_state *state, u8 reg) if (ret != 3) return ret; } else { - ret = i2c_transfer(state->i2c, &msg[1], 2); - if (ret != 2) + ret = i2c_transfer(state->i2c, &msg[1], 1); + if (ret != 1) + return ret; + ret = i2c_transfer(state->i2c, &msg[2], 1); + if (ret != 1) return ret; } @@ -854,7 +857,7 @@ static int s5h1420_init (struct dvb_frontend* fe) struct s5h1420_state* state = fe->demodulator_priv; /* disable power down and do reset */ - state->CON_1_val = 0x10; + state->CON_1_val = state->config->serial_mpeg << 4; s5h1420_writereg(state, 0x02, state->CON_1_val); msleep(10); s5h1420_reset(state); diff --git a/linux/drivers/media/dvb/frontends/s5h1420.h b/linux/drivers/media/dvb/frontends/s5h1420.h index 4c913f142..ff308136d 100644 --- a/linux/drivers/media/dvb/frontends/s5h1420.h +++ b/linux/drivers/media/dvb/frontends/s5h1420.h @@ -32,10 +32,12 @@ struct s5h1420_config u8 demod_address; /* does the inversion require inversion? */ - u8 invert : 1; + u8 invert:1; - u8 repeated_start_workaround : 1; - u8 cdclk_polarity : 1; /* 1 == falling edge, 0 == raising edge */ + u8 repeated_start_workaround:1; + u8 cdclk_polarity:1; /* 1 == falling edge, 0 == raising edge */ + + u8 serial_mpeg:1; }; #if defined(CONFIG_DVB_S5H1420) || (defined(CONFIG_DVB_S5H1420_MODULE) && defined(MODULE)) diff --git a/linux/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/linux/drivers/media/dvb/ttusb-dec/ttusbdecfe.c index 443af2409..21260aad1 100644 --- a/linux/drivers/media/dvb/ttusb-dec/ttusbdecfe.c +++ b/linux/drivers/media/dvb/ttusb-dec/ttusbdecfe.c @@ -38,7 +38,17 @@ struct ttusbdecfe_state { }; -static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status) +static int ttusbdecfe_dvbs_read_status(struct dvb_frontend *fe, + fe_status_t *status) +{ + *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | + FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK; + return 0; +} + + +static int ttusbdecfe_dvbt_read_status(struct dvb_frontend *fe, + fe_status_t *status) { struct ttusbdecfe_state* state = fe->demodulator_priv; u8 b[] = { 0x00, 0x00, 0x00, 0x00, @@ -251,7 +261,7 @@ static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = { .get_tune_settings = ttusbdecfe_dvbt_get_tune_settings, - .read_status = ttusbdecfe_read_status, + .read_status = ttusbdecfe_dvbt_read_status, }; static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = { @@ -273,7 +283,7 @@ static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = { .set_frontend = ttusbdecfe_dvbs_set_frontend, - .read_status = ttusbdecfe_read_status, + .read_status = ttusbdecfe_dvbs_read_status, .diseqc_send_master_cmd = ttusbdecfe_dvbs_diseqc_send_master_cmd, .set_voltage = ttusbdecfe_dvbs_set_voltage, diff --git a/linux/drivers/media/video/au0828/au0828-cards.c b/linux/drivers/media/video/au0828/au0828-cards.c index ed48908a9..5f07a8a07 100644 --- a/linux/drivers/media/video/au0828/au0828-cards.c +++ b/linux/drivers/media/video/au0828/au0828-cards.c @@ -46,7 +46,7 @@ struct au0828_board au0828_boards[] = { /* Tuner callback function for au0828 boards. Currently only needed * for HVR1500Q, which has an xc5000 tuner. */ -int au0828_tuner_callback(void *priv, int command, int arg) +int au0828_tuner_callback(void *priv, int component, int command, int arg) { struct au0828_dev *dev = priv; diff --git a/linux/drivers/media/video/au0828/au0828-dvb.c b/linux/drivers/media/video/au0828/au0828-dvb.c index 24160ca59..82474a4a8 100644 --- a/linux/drivers/media/video/au0828/au0828-dvb.c +++ b/linux/drivers/media/video/au0828/au0828-dvb.c @@ -54,7 +54,6 @@ static struct au8522_config hauppauge_woodbury_config = { static struct xc5000_config hauppauge_hvr950q_tunerconfig = { .i2c_address = 0x61, .if_khz = 6000, - .tuner_callback = au0828_tuner_callback }; static struct mxl5007t_config mxl5007t_hvr950q_config = { @@ -394,6 +393,8 @@ int au0828_dvb_register(struct au0828_dev *dev) __func__); return -1; } + /* define general-purpose callback pointer */ + dvb->frontend->callback = au0828_tuner_callback; /* register everything */ ret = dvb_register(dev); diff --git a/linux/drivers/media/video/au0828/au0828.h b/linux/drivers/media/video/au0828/au0828.h index 4f10ff300..9d6a1161d 100644 --- a/linux/drivers/media/video/au0828/au0828.h +++ b/linux/drivers/media/video/au0828/au0828.h @@ -103,7 +103,8 @@ extern int au0828_debug; extern struct au0828_board au0828_boards[]; extern struct usb_device_id au0828_usb_id_table[]; extern void au0828_gpio_setup(struct au0828_dev *dev); -extern int au0828_tuner_callback(void *priv, int command, int arg); +extern int au0828_tuner_callback(void *priv, int component, + int command, int arg); extern void au0828_card_setup(struct au0828_dev *dev); /* ----------------------------------------------------------- */ diff --git a/linux/drivers/media/video/cx18/cx18-gpio.c b/linux/drivers/media/video/cx18/cx18-gpio.c index 3bdffbf7a..0e5604219 100644 --- a/linux/drivers/media/video/cx18/cx18-gpio.c +++ b/linux/drivers/media/video/cx18/cx18-gpio.c @@ -152,7 +152,7 @@ void cx18_gpio_init(struct cx18 *cx) } /* Xceive tuner reset function */ -int cx18_reset_tuner_gpio(void *dev, int cmd, int value) +int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value) { struct i2c_algo_bit_data *algo = dev; struct cx18_i2c_algo_callback_data *cb_data = algo->data; diff --git a/linux/drivers/media/video/cx18/cx18-gpio.h b/linux/drivers/media/video/cx18/cx18-gpio.h index 22cd7ddf8..beb7424b9 100644 --- a/linux/drivers/media/video/cx18/cx18-gpio.h +++ b/linux/drivers/media/video/cx18/cx18-gpio.h @@ -23,5 +23,5 @@ void cx18_gpio_init(struct cx18 *cx); void cx18_reset_i2c_slaves_gpio(struct cx18 *cx); void cx18_reset_ir_gpio(void *data); -int cx18_reset_tuner_gpio(void *dev, int cmd, int value); +int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value); int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg); diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index be9a6d8ec..2b497b28b 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -338,7 +338,7 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) dev->name, tv.model); } -int cx23885_tuner_callback(void *priv, int command, int arg) +int cx23885_tuner_callback(void *priv, int component, int command, int arg) { struct cx23885_tsport *port = priv; struct cx23885_dev *dev = port->dev; diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index c84688aba..1909ef6e3 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -190,13 +190,11 @@ static struct s5h1411_config dvico_s5h1411_config = { static struct xc5000_config hauppauge_hvr1500q_tunerconfig = { .i2c_address = 0x61, .if_khz = 5380, - .tuner_callback = cx23885_tuner_callback, }; static struct xc5000_config dvico_xc5000_tunerconfig = { .i2c_address = 0x64, .if_khz = 5380, - .tuner_callback = cx23885_tuner_callback, }; static struct tda829x_config tda829x_no_probe = { @@ -404,8 +402,6 @@ static int dvb_register(struct cx23885_tsport *port) struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, .i2c_addr = 0x61, - .video_dev = port, - .callback = cx23885_tuner_callback, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, @@ -444,14 +440,13 @@ static int dvb_register(struct cx23885_tsport *port) struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, .i2c_addr = 0x64, - .video_dev = port, - .callback = cx23885_tuner_callback, }; static struct xc2028_ctrl ctl = { .fname = XC3028L_DEFAULT_FIRMWARE, .max_len = 64, .demod = 5000, - .d2633 = 1 + /* This is true for all demods with v36 firmware? */ + .type = XC2028_D2633, }; fe = dvb_attach(xc2028_attach, @@ -486,8 +481,6 @@ static int dvb_register(struct cx23885_tsport *port) struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, .i2c_addr = 0x61, - .video_dev = port, - .callback = cx23885_tuner_callback, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, @@ -513,8 +506,6 @@ static int dvb_register(struct cx23885_tsport *port) struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, .i2c_addr = 0x61, - .video_dev = port, - .callback = cx23885_tuner_callback, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, @@ -537,6 +528,8 @@ static int dvb_register(struct cx23885_tsport *port) printk("%s: frontend initialization failed\n", dev->name); return -1; } + /* define general-purpose callback pointer */ + port->dvb.frontend->callback = cx23885_tuner_callback; /* Put the analog decoder in standby to keep it quiet */ cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL); diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index 49e3eaec7..dea1798f7 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -412,7 +412,7 @@ extern const unsigned int cx23885_bcount; extern struct cx23885_subid cx23885_subids[]; extern const unsigned int cx23885_idcount; -extern int cx23885_tuner_callback(void *priv, int command, int arg); +extern int cx23885_tuner_callback(void *priv, int component, int command, int arg); extern void cx23885_card_list(struct cx23885_dev *dev); extern int cx23885_ir_init(struct cx23885_dev *dev); extern void cx23885_gpio_setup(struct cx23885_dev *dev); diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index 95b2ff5d9..215a724ce 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -1482,15 +1482,26 @@ static const struct cx88_board cx88_boards[] = { .name = "Pinnacle Hybrid PCTV", .tuner_type = TUNER_XC2028, .tuner_addr = 0x61, + .radio_type = TUNER_XC2028, + .radio_addr = 0x61, .input = { { .type = CX88_VMUX_TELEVISION, .vmux = 0, + .gpio0 = 0x004ff, + .gpio1 = 0x010ff, + .gpio2 = 0x00001, }, { .type = CX88_VMUX_COMPOSITE1, .vmux = 1, + .gpio0 = 0x004fb, + .gpio1 = 0x010ef, + .audioroute = 1, }, { .type = CX88_VMUX_SVIDEO, .vmux = 2, + .gpio0 = 0x004fb, + .gpio1 = 0x010ef, + .audioroute = 1, } }, .radio = { .type = CX88_RADIO, @@ -1498,10 +1509,7 @@ static const struct cx88_board cx88_boards[] = { .gpio1 = 0x010ff, .gpio2 = 0x0ff, }, -#if 0 - /* needs some more GPIO work */ .mpeg = CX88_MPEG_DVB, -#endif }, [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = { .name = "Winfast TV2000 XP Global", @@ -1665,6 +1673,36 @@ static const struct cx88_board cx88_boards[] = { .gpio2 = 0x0cfb, }, }, + [CX88_BOARD_PROLINK_PV_GLOBAL_XTREME] = { + .name = "Prolink Pixelview Global Extreme", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x04fb, + .gpio1 = 0x04080, + .gpio2 = 0x0cf7, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x04fb, + .gpio1 = 0x04080, + .gpio2 = 0x0cfb, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x04fb, + .gpio1 = 0x04080, + .gpio2 = 0x0cfb, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x04ff, + .gpio1 = 0x04080, + .gpio2 = 0x0cf7, + }, + }, /* Both radio, analog and ATSC work with this board. However, for analog to work, s5h1409 gate should be open, otherwise, tuner-xc3028 won't be detected. @@ -2163,6 +2201,10 @@ static const struct cx88_subid cx88_subids[] = { .subdevice = 0x4935, .card = CX88_BOARD_PROLINK_PV_8000GT, }, { + .subvendor = 0x1554, + .subdevice = 0x4976, + .card = CX88_BOARD_PROLINK_PV_GLOBAL_XTREME, + }, { .subvendor = 0x17de, .subdevice = 0x08c1, .card = CX88_BOARD_KWORLD_ATSC_120, @@ -2345,9 +2387,21 @@ static int cx88_dvico_xc2028_callback(struct cx88_core *core, { switch (command) { case XC2028_TUNER_RESET: - cx_write(MO_GP0_IO, 0x101000); - mdelay(5); - cx_set(MO_GP0_IO, 0x101010); + switch (core->boardnr) { + case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: + /* GPIO-4 xc3028 tuner */ + + cx_set(MO_GP0_IO, 0x00001000); + cx_clear(MO_GP0_IO, 0x00000010); + msleep(100); + cx_set(MO_GP0_IO, 0x00000010); + msleep(100); + break; + default: + cx_write(MO_GP0_IO, 0x101000); + mdelay(5); + cx_set(MO_GP0_IO, 0x101010); + } break; default: return -EINVAL; @@ -2454,8 +2508,10 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core, return cx88_xc3028_geniatech_tuner_callback(core, command, arg); case CX88_BOARD_PROLINK_PV_8000GT: + case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: return cx88_pv_8000gt_callback(core, command, arg); case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: + case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: return cx88_dvico_xc2028_callback(core, command, arg); } @@ -2523,7 +2579,7 @@ static int cx88_xc5000_tuner_callback(struct cx88_core *core, return 0; /* Should never be here */ } -int cx88_tuner_callback(void *priv, int command, int arg) +int cx88_tuner_callback(void *priv, int component, int command, int arg) { struct i2c_algo_bit_data *i2c_algo = priv; struct cx88_core *core; @@ -2540,6 +2596,9 @@ int cx88_tuner_callback(void *priv, int command, int arg) return -EINVAL; } + if (component != DVB_FRONTEND_COMPONENT_TUNER) + return -EINVAL; + switch (core->board.tuner_type) { case TUNER_XC2028: info_printk(core, "Calling XC2028/3028 callback\n"); @@ -2603,6 +2662,7 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) udelay(1000); break; + case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: case CX88_BOARD_PROLINK_PV_8000GT: cx_write(MO_GP2_IO, 0xcf7); mdelay(50); @@ -2650,11 +2710,16 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: ctl->demod = XC3028_FE_OREN538; break; + case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: case CX88_BOARD_PROLINK_PV_8000GT: /* - * This board uses non-MTS firmware + * Those boards uses non-MTS firmware */ break; + case CX88_BOARD_PINNACLE_HYBRID_PCTV: + ctl->demod = XC3028_FE_ZARLINK456; + ctl->mts = 1; + break; default: ctl->demod = XC3028_FE_OREN538; ctl->mts = 1; diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index 64c799500..da1ad2b6b 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -406,40 +406,6 @@ static int tevii_dvbs_set_voltage(struct dvb_frontend *fe, return 0; } -static int cx88_pci_nano_callback(void *ptr, int command, int arg) -{ - struct cx88_core *core = ptr; - - switch (command) { - case XC2028_TUNER_RESET: - /* Send the tuner in then out of reset */ - dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg); - - switch (core->boardnr) { - case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: - /* GPIO-4 xc3028 tuner */ - - cx_set(MO_GP0_IO, 0x00001000); - cx_clear(MO_GP0_IO, 0x00000010); - msleep(100); - cx_set(MO_GP0_IO, 0x00000010); - msleep(100); - break; - } - - break; - case XC2028_RESET_CLK: - dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg); - break; - default: - dprintk(1, "%s: unknown command %d, arg %d\n", __func__, - command, arg); - return -EINVAL; - } - - return 0; -} - static struct cx24123_config geniatech_dvbs_config = { .demod_address = 0x55, .set_ts_params = cx24123_set_ts_param, @@ -487,7 +453,12 @@ static struct s5h1409_config kworld_atsc_120_config = { static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { .i2c_address = 0x64, .if_khz = 5380, - .tuner_callback = cx88_tuner_callback, +}; + +static struct zl10353_config cx88_pinnacle_hybrid_pctv = { + .demod_address = (0x1e >> 1), + .no_tuner = 1, + .if2 = 45600, }; static struct zl10353_config cx88_geniatech_x8000_mt = { @@ -514,7 +485,6 @@ static struct s5h1411_config dvico_fusionhdtv7_config = { static struct xc5000_config dvico_fusionhdtv7_tuner_config = { .i2c_address = 0xc2 >> 1, .if_khz = 5380, - .tuner_callback = cx88_tuner_callback, }; static int attach_xc3028(u8 addr, struct cx8802_dev *dev) @@ -525,7 +495,6 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) .i2c_adap = &dev->core->i2c_adap, .i2c_addr = addr, .ctrl = &ctl, - .callback = cx88_tuner_callback, }; if (!dev->dvb.frontend) { @@ -919,7 +888,6 @@ static int dvb_register(struct cx8802_dev *dev) struct xc2028_config cfg = { .i2c_adap = &core->i2c_adap, .i2c_addr = 0x61, - .callback = cx88_pci_nano_callback, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, @@ -935,10 +903,13 @@ static int dvb_register(struct cx8802_dev *dev) break; case CX88_BOARD_PINNACLE_HYBRID_PCTV: dev->dvb.frontend = dvb_attach(zl10353_attach, - &cx88_geniatech_x8000_mt, + &cx88_pinnacle_hybrid_pctv, &core->i2c_adap); - if (attach_xc3028(0x61, dev) < 0) - goto frontend_detach; + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.i2c_gate_ctrl = NULL; + if (attach_xc3028(0x61, dev) < 0) + goto frontend_detach; + } break; case CX88_BOARD_GENIATECH_X8000_MT: dev->ts_gen_cntrl = 0x00; @@ -1042,6 +1013,8 @@ static int dvb_register(struct cx8802_dev *dev) core->name); return -EINVAL; } + /* define general-purpose callback pointer */ + dev->dvb.frontend->callback = cx88_tuner_callback; /* Ensure all frontends negotiate bus access */ dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; diff --git a/linux/drivers/media/video/cx88/cx88-input.c b/linux/drivers/media/video/cx88/cx88-input.c index 3cdc473de..bcecb5bbd 100644 --- a/linux/drivers/media/video/cx88/cx88-input.c +++ b/linux/drivers/media/video/cx88/cx88-input.c @@ -274,6 +274,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->polling = 1; /* ms */ break; case CX88_BOARD_PROLINK_PV_8000GT: + case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: ir_codes = ir_codes_pixelview_new; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x3f; diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 38702eb4f..e42ce0016 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -228,6 +228,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_OMICOM_SS4_PCI 71 #define CX88_BOARD_TBS_8920 72 #define CX88_BOARD_TEVII_S420 73 +#define CX88_BOARD_PROLINK_PV_GLOBAL_XTREME 74 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, @@ -629,7 +630,7 @@ extern void cx88_call_i2c_clients(struct cx88_core *core, /* ----------------------------------------------------------- */ /* cx88-cards.c */ -extern int cx88_tuner_callback(void *dev, int command, int arg); +extern int cx88_tuner_callback(void *dev, int component, int command, int arg); extern int cx88_get_resources(const struct cx88_core *core, struct pci_dev *pci); extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr); diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 5abdefdf0..38874e024 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1273,7 +1273,7 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = { {0x1ba50080, EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA, TUNER_ABSENT}, }; -int em28xx_tuner_callback(void *ptr, int command, int arg) +int em28xx_tuner_callback(void *ptr, int component, int command, int arg) { int rc = 0; struct em28xx *dev = ptr; diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index 79c11b1d0..03c212e5a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -250,7 +250,6 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) memset(&cfg, 0, sizeof(cfg)); cfg.i2c_adap = &dev->i2c_adap; cfg.i2c_addr = addr; - cfg.callback = em28xx_tuner_callback; if (!dev->dvb->frontend) { printk(KERN_ERR "%s/2: dvb frontend not attached. " @@ -466,6 +465,8 @@ static int dvb_init(struct em28xx *dev) result = -EINVAL; goto out_free; } + /* define general-purpose callback pointer */ + dvb->frontend->callback = em28xx_tuner_callback; /* register everything */ result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 4bdff9619..d73b8c983 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -541,7 +541,7 @@ extern struct em28xx_board em28xx_boards[]; extern struct usb_device_id em28xx_id_table[]; extern const unsigned int em28xx_bcount; void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir); -int em28xx_tuner_callback(void *ptr, int command, int arg); +int em28xx_tuner_callback(void *ptr, int component, int command, int arg); /* Provided by em28xx-input.c */ /* TODO: Check if the standard get_key handlers on ir-common can be used */ diff --git a/linux/drivers/media/video/gspca/spca561.c b/linux/drivers/media/video/gspca/spca561.c index b1329a149..0250ee96d 100644 --- a/linux/drivers/media/video/gspca/spca561.c +++ b/linux/drivers/media/video/gspca/spca561.c @@ -1078,7 +1078,7 @@ static struct ctrl sd_ctrls_12a[] = { { .id = V4L2_CID_DO_WHITE_BALANCE, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "While Balance", + .name = "White Balance", .minimum = WHITE_MIN, .maximum = WHITE_MAX, .step = 1, diff --git a/linux/drivers/media/video/ivtv/ivtv-gpio.c b/linux/drivers/media/video/ivtv/ivtv-gpio.c index bc22905ea..74a44844c 100644 --- a/linux/drivers/media/video/ivtv/ivtv-gpio.c +++ b/linux/drivers/media/video/ivtv/ivtv-gpio.c @@ -124,7 +124,7 @@ void ivtv_reset_ir_gpio(struct ivtv *itv) } /* Xceive tuner reset function */ -int ivtv_reset_tuner_gpio(void *dev, int cmd, int value) +int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value) { struct i2c_algo_bit_data *algo = dev; struct ivtv *itv = algo->data; diff --git a/linux/drivers/media/video/ivtv/ivtv-gpio.h b/linux/drivers/media/video/ivtv/ivtv-gpio.h index 964a265d9..48b629161 100644 --- a/linux/drivers/media/video/ivtv/ivtv-gpio.h +++ b/linux/drivers/media/video/ivtv/ivtv-gpio.h @@ -24,7 +24,7 @@ /* GPIO stuff */ void ivtv_gpio_init(struct ivtv *itv); void ivtv_reset_ir_gpio(struct ivtv *itv); -int ivtv_reset_tuner_gpio(void *dev, int cmd, int value); +int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value); int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg); #endif diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 3fbf9dfc7..135250cf5 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -3299,6 +3299,7 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_HAUPPAUGE_HVR1110] = { /* Thomas Genty <tomlohave@gmail.com> */ + /* David Bentham <db260179@hotmail.com> */ .name = "Hauppauge WinTV-HVR1110 DVB-T/Hybrid", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_TDA8290, @@ -3307,23 +3308,26 @@ struct saa7134_board saa7134_boards[] = { .radio_addr = ADDR_UNSET, .tuner_config = 1, .mpeg = SAA7134_MPEG_DVB, + .gpiomask = 0x0200100, .inputs = {{ .name = name_tv, .vmux = 1, .amux = TV, .tv = 1, - },{ - .name = name_comp1, - .vmux = 3, - .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */ - },{ - .name = name_svideo, - .vmux = 8, - .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */ - }}, + .gpio = 0x0000100, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, .radio = { .name = name_radio, - .amux = TV, + .amux = TV, + .gpio = 0x0200100, }, }, [SAA7134_BOARD_CINERGY_HT_PCMCIA] = { @@ -3427,6 +3431,42 @@ struct saa7134_board saa7134_boards[] = { .amux = 0, }, }, + [SAA7134_BOARD_ENCORE_ENLTV_FM53] = { + .name = "Encore ENLTV-FM v5.3", + .audio_clock = 0x00200000, + .tuner_type = TUNER_TNF_5335MF, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask = 0x7000, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = 1, + .tv = 1, + .gpio = 0x50000, + }, { + .name = name_comp1, + .vmux = 3, + .amux = 2, + .gpio = 0x2000, + }, { + .name = name_svideo, + .vmux = 8, + .amux = 2, + .gpio = 0x2000, + } }, + .radio = { + .name = name_radio, + .vmux = 1, + .amux = 1, + }, + .mute = { + .name = name_mute, + .gpio = 0xf000, + .amux = 0, + }, + }, [SAA7134_BOARD_CINERGY_HT_PCI] = { .name = "Terratec Cinergy HT PCI", .audio_clock = 0x00187de7, @@ -3670,6 +3710,40 @@ struct saa7134_board saa7134_boards[] = { .tv = 1, }}, }, + [SAA7134_BOARD_AVERMEDIA_M135A] = { + .name = "Avermedia PCI pure analog (M135A)", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tuner_config = 2, + .gpiomask = 0x020200000, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x00200000, + }, + .mute = { + .name = name_mute, + .amux = TV, + .gpio = 0x01, + }, + }, [SAA7134_BOARD_BEHOLD_401] = { /* Beholder Intl. Ltd. 2008 */ /*Dmitry Belimov <d.belimov@gmail.com> */ @@ -4478,6 +4552,65 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x0200000, }, }, + [SAA7134_BOARD_REAL_ANGEL_220] = { + .name = "Zogis Real Angel 220", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_TNF_5335MF, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask = 0x801a8087, + .inputs = { { + .name = name_tv, + .vmux = 3, + .amux = LINE2, + .tv = 1, + .gpio = 0x624000, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE1, + .gpio = 0x624000, + }, { + .name = name_svideo, + .vmux = 1, + .amux = LINE1, + .gpio = 0x624000, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + .gpio = 0x624001, + }, + .mute = { + .name = name_mute, + .amux = TV, + }, + }, + [SAA7134_BOARD_ADS_INSTANT_HDTV_PCI] = { + .name = "ADS Tech Instant HDTV", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TUV1236D, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .mpeg = SAA7134_MPEG_DVB, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp, + .vmux = 4, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -4846,6 +4979,12 @@ struct pci_device_id saa7134_pci_tbl[] = { },{ .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xf11d, + .driver_data = SAA7134_BOARD_AVERMEDIA_M135A, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, .subvendor = PCI_VENDOR_ID_PHILIPS, .subdevice = 0x2004, @@ -5226,6 +5365,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM, },{ .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = 0x1a7f, + .subdevice = 0x2008, + .driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM53, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x153b, .subdevice = 0x1175, @@ -5484,6 +5629,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .driver_data = SAA7134_BOARD_VIDEOMATE_T750, }, { .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */ + .subvendor = 0x1421, + .subdevice = 0x0380, + .driver_data = SAA7134_BOARD_ADS_INSTANT_HDTV_PCI, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x5169, .subdevice = 0x1502, @@ -5671,7 +5822,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev, return 0; } -int saa7134_tuner_callback(void *priv, int command, int arg) +int saa7134_tuner_callback(void *priv, int component, int command, int arg) { struct saa7134_dev *dev = priv; if (dev != NULL) { @@ -5755,6 +5906,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_STUDIO_507: case SAA7134_BOARD_AVERMEDIA_GO_007_FM: case SAA7134_BOARD_AVERMEDIA_777: + case SAA7134_BOARD_AVERMEDIA_M135A: /* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */ case SAA7134_BOARD_VIDEOMATE_TV_PVR: case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: @@ -5779,6 +5931,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_A16AR: case SAA7134_BOARD_ENCORE_ENLTV: case SAA7134_BOARD_ENCORE_ENLTV_FM: + case SAA7134_BOARD_ENCORE_ENLTV_FM53: case SAA7134_BOARD_10MOONSTVMASTER3: case SAA7134_BOARD_BEHOLD_401: case SAA7134_BOARD_BEHOLD_403: @@ -5791,6 +5944,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_505FM: case SAA7134_BOARD_BEHOLD_507_9FM: case SAA7134_BOARD_GENIUS_TVGO_A11MCE: + case SAA7134_BOARD_REAL_ANGEL_220: dev->has_remote = SAA7134_REMOTE_GPIO; break; case SAA7134_BOARD_FLYDVBS_LR300: @@ -6174,6 +6328,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) i2c_transfer(&dev->i2c_adap, &msg, 1); break; } + case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI: case SAA7134_BOARD_KWORLD_ATSC110: { /* enable tuner */ diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index ce8bcc967..c839114a0 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -760,6 +760,10 @@ static int saa7134_hw_enable2(struct saa7134_dev *dev) irq2_mask |= SAA7134_IRQ2_INTE_GPIO18A; } + if (dev->has_remote == SAA7134_REMOTE_I2C) { + request_module("ir-kbd-i2c"); + } + saa_writel(SAA7134_IRQ1, 0); saa_writel(SAA7134_IRQ2, irq2_mask); diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c index d61ab4e10..5222f1728 100644 --- a/linux/drivers/media/video/saa7134/saa7134-dvb.c +++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c @@ -553,7 +553,6 @@ static int configure_tda827x_fe(struct saa7134_dev *dev, /* ------------------------------------------------------------------ */ static struct tda827x_config tda827x_cfg_0 = { - .tuner_callback = saa7134_tuner_callback, .init = philips_tda827x_tuner_init, .sleep = philips_tda827x_tuner_sleep, .config = 0, @@ -561,7 +560,6 @@ static struct tda827x_config tda827x_cfg_0 = { }; static struct tda827x_config tda827x_cfg_1 = { - .tuner_callback = saa7134_tuner_callback, .init = philips_tda827x_tuner_init, .sleep = philips_tda827x_tuner_sleep, .config = 1, @@ -569,7 +567,6 @@ static struct tda827x_config tda827x_cfg_1 = { }; static struct tda827x_config tda827x_cfg_2 = { - .tuner_callback = saa7134_tuner_callback, .init = philips_tda827x_tuner_init, .sleep = philips_tda827x_tuner_sleep, .config = 2, @@ -577,7 +574,6 @@ static struct tda827x_config tda827x_cfg_2 = { }; static struct tda827x_config tda827x_cfg_2_sw42 = { - .tuner_callback = saa7134_tuner_callback, .init = philips_tda827x_tuner_init, .sleep = philips_tda827x_tuner_sleep, .config = 2, @@ -836,7 +832,6 @@ static int ads_duo_tuner_sleep(struct dvb_frontend *fe) } static struct tda827x_config ads_duo_cfg = { - .tuner_callback = saa7134_tuner_callback, .init = ads_duo_tuner_init, .sleep = ads_duo_tuner_sleep, .config = 0 @@ -1161,6 +1156,7 @@ static int dvb_init(struct saa7134_dev *dev) dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, NULL, DVB_PLL_TDHU2); break; + case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI: case SAA7134_BOARD_KWORLD_ATSC110: dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110, &dev->i2c_adap); @@ -1370,6 +1366,8 @@ static int dvb_init(struct saa7134_dev *dev) printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name); return -1; } + /* define general-purpose callback pointer */ + dev->dvb.frontend->callback = saa7134_tuner_callback; /* register everything else */ ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev, diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index a9f6df2dd..cb93661fb 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -401,6 +401,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPMODE0, 0x4); saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); break; + case SAA7134_BOARD_AVERMEDIA_M135A: + ir_codes = ir_codes_avermedia_m135a; + mask_keydown = 0x0040000; + mask_keycode = 0x00013f; + nec_gpio = 1; + break; case SAA7134_BOARD_AVERMEDIA_777: case SAA7134_BOARD_AVERMEDIA_A16AR: ir_codes = ir_codes_avermedia; @@ -509,6 +515,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x040000; polling = 50; // ms break; + case SAA7134_BOARD_ENCORE_ENLTV_FM53: + ir_codes = ir_codes_encore_enltv_fm53; + mask_keydown = 0x0040000; + mask_keycode = 0x00007f; + nec_gpio = 1; + break; case SAA7134_BOARD_10MOONSTVMASTER3: ir_codes = ir_codes_encore_enltv; mask_keycode = 0x5f80000; @@ -521,6 +533,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keydown = 0xf00000; polling = 50; /* ms */ break; + case SAA7134_BOARD_REAL_ANGEL_220: + ir_codes = ir_codes_real_audio_220_32_keys; + mask_keycode = 0x3f00; + mask_keyup = 0x4000; + polling = 50; /* ms */ + break; } if (NULL == ir_codes) { printk("%s: Oops: IR config error [card=%d]\n", diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 168cc7dfd..b704b5f40 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -271,6 +271,10 @@ struct saa7134_format { #define SAA7134_BOARD_AVERMEDIA_M103 145 #define SAA7134_BOARD_ASUSTeK_P7131_ANALOG 146 #define SAA7134_BOARD_ASUSTeK_TIGER_3IN1 147 +#define SAA7134_BOARD_ENCORE_ENLTV_FM53 148 +#define SAA7134_BOARD_AVERMEDIA_M135A 149 +#define SAA7134_BOARD_REAL_ANGEL_220 150 +#define SAA7134_BOARD_ADS_INSTANT_HDTV_PCI 151 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 @@ -658,7 +662,7 @@ extern struct pci_device_id __devinitdata saa7134_pci_tbl[]; extern int saa7134_board_init1(struct saa7134_dev *dev); extern int saa7134_board_init2(struct saa7134_dev *dev); -int saa7134_tuner_callback(void *priv, int command, int arg); +int saa7134_tuner_callback(void *priv, int component, int command, int arg); /* ----------------------------------------------------------- */ diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c index 055e92549..8c1817a47 100644 --- a/linux/drivers/media/video/stk-webcam.c +++ b/linux/drivers/media/video/stk-webcam.c @@ -66,22 +66,6 @@ static struct usb_device_id stkwebcam_table[] = { }; MODULE_DEVICE_TABLE(usb, stkwebcam_table); -static void stk_camera_cleanup(struct kref *kref) -{ - struct stk_camera *dev = to_stk_camera(kref); - - STK_INFO("Syntek USB2.0 Camera release resources" - " video device /dev/video%d\n", dev->vdev.minor); - video_unregister_device(&dev->vdev); - video_set_drvdata(&dev->vdev, NULL); - - if (dev->sio_bufs != NULL || dev->isobufs != NULL) - STK_ERROR("We are leaking memory\n"); - usb_put_intf(dev->interface); - kfree(dev); -} - - /* * Basic stuff */ @@ -695,8 +679,7 @@ static int v4l_stk_open(struct inode *inode, struct file *fp) unlock_kernel(); return -ENXIO; } - fp->private_data = vdev; - kref_get(&dev->kref); + fp->private_data = dev; usb_autopm_get_interface(dev->interface); unlock_kernel(); @@ -705,23 +688,10 @@ static int v4l_stk_open(struct inode *inode, struct file *fp) static int v4l_stk_release(struct inode *inode, struct file *fp) { - struct stk_camera *dev; - struct video_device *vdev; - - vdev = video_devdata(fp); - if (vdev == NULL) { - STK_ERROR("v4l_release called w/o video devdata\n"); - return -EFAULT; - } - dev = vdev_to_camera(vdev); - if (dev == NULL) { - STK_ERROR("v4l_release called on removed device\n"); - return -ENODEV; - } + struct stk_camera *dev = fp->private_data; if (dev->owner != fp) { usb_autopm_put_interface(dev->interface); - kref_put(&dev->kref, stk_camera_cleanup); return 0; } @@ -732,7 +702,6 @@ static int v4l_stk_release(struct inode *inode, struct file *fp) dev->owner = NULL; usb_autopm_put_interface(dev->interface); - kref_put(&dev->kref, stk_camera_cleanup); return 0; } @@ -743,14 +712,8 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf, int i; int ret; unsigned long flags; - struct stk_camera *dev; - struct video_device *vdev; struct stk_sio_buffer *sbuf; - - vdev = video_devdata(fp); - if (vdev == NULL) - return -EFAULT; - dev = vdev_to_camera(vdev); + struct stk_camera *dev = fp->private_data; if (dev == NULL) return -EIO; @@ -809,15 +772,8 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf, static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait) { - struct stk_camera *dev; - struct video_device *vdev; - - vdev = video_devdata(fp); - - if (vdev == NULL) - return -EFAULT; + struct stk_camera *dev = fp->private_data; - dev = vdev_to_camera(vdev); if (dev == NULL) return -ENODEV; @@ -855,16 +811,12 @@ static int v4l_stk_mmap(struct file *fp, struct vm_area_struct *vma) unsigned int i; int ret; unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; - struct stk_camera *dev; - struct video_device *vdev; + struct stk_camera *dev = fp->private_data; struct stk_sio_buffer *sbuf = NULL; if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) return -EINVAL; - vdev = video_devdata(fp); - dev = vdev_to_camera(vdev); - for (i = 0; i < dev->n_sbufs; i++) { if (dev->sio_bufs[i].v4lbuf.m.offset == offset) { sbuf = dev->sio_bufs + i; @@ -1360,6 +1312,12 @@ static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = { static void stk_v4l_dev_release(struct video_device *vd) { + struct stk_camera *dev = vdev_to_camera(vd); + + if (dev->sio_bufs != NULL || dev->isobufs != NULL) + STK_ERROR("We are leaking memory\n"); + usb_put_intf(dev->interface); + kfree(dev); } static struct video_device stk_v4l_data = { @@ -1380,7 +1338,6 @@ static int stk_register_video_device(struct stk_camera *dev) dev->vdev = stk_v4l_data; dev->vdev.debug = debug; dev->vdev.parent = &dev->interface->dev; - video_set_drvdata(&dev->vdev, dev); err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); if (err) STK_ERROR("v4l registration failed\n"); @@ -1397,7 +1354,7 @@ static int stk_camera_probe(struct usb_interface *interface, const struct usb_device_id *id) { int i; - int err; + int err = 0; struct stk_camera *dev = NULL; struct usb_device *udev = interface_to_usbdev(interface); @@ -1410,7 +1367,6 @@ static int stk_camera_probe(struct usb_interface *interface, return -ENOMEM; } - kref_init(&dev->kref); spin_lock_init(&dev->spinlock); init_waitqueue_head(&dev->wait_frame); @@ -1443,8 +1399,8 @@ static int stk_camera_probe(struct usb_interface *interface, } if (!dev->isoc_ep) { STK_ERROR("Could not find isoc-in endpoint"); - kref_put(&dev->kref, stk_camera_cleanup); - return -ENODEV; + err = -ENODEV; + goto error; } dev->vsettings.brightness = 0x7fff; dev->vsettings.palette = V4L2_PIX_FMT_RGB565; @@ -1458,14 +1414,17 @@ static int stk_camera_probe(struct usb_interface *interface, err = stk_register_video_device(dev); if (err) { - kref_put(&dev->kref, stk_camera_cleanup); - return err; + goto error; } stk_create_sysfs_files(&dev->vdev); usb_autopm_enable(dev->interface); return 0; + +error: + kfree(dev); + return err; } static void stk_camera_disconnect(struct usb_interface *interface) @@ -1478,7 +1437,10 @@ static void stk_camera_disconnect(struct usb_interface *interface) wake_up_interruptible(&dev->wait_frame); stk_remove_sysfs_files(&dev->vdev); - kref_put(&dev->kref, stk_camera_cleanup); + STK_INFO("Syntek USB2.0 Camera release resources" + "video device /dev/video%d\n", dev->vdev.minor); + + video_unregister_device(&dev->vdev); } #ifdef CONFIG_PM diff --git a/linux/drivers/media/video/stk-webcam.h b/linux/drivers/media/video/stk-webcam.h index df4dfefc5..084a85bdd 100644 --- a/linux/drivers/media/video/stk-webcam.h +++ b/linux/drivers/media/video/stk-webcam.h @@ -99,7 +99,6 @@ struct stk_camera { u8 isoc_ep; - struct kref kref; /* Not sure if this is right */ atomic_t urbs_used; @@ -121,7 +120,6 @@ struct stk_camera { unsigned sequence; }; -#define to_stk_camera(d) container_of(d, struct stk_camera, kref) #define vdev_to_camera(d) container_of(d, struct stk_camera, vdev) void stk_camera_delete(struct kref *); diff --git a/linux/drivers/media/video/tda9840.c b/linux/drivers/media/video/tda9840.c index 72adcb450..31dde7516 100644 --- a/linux/drivers/media/video/tda9840.c +++ b/linux/drivers/media/video/tda9840.c @@ -72,7 +72,6 @@ static void tda9840_write(struct i2c_client *client, u8 reg, u8 val) static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) { - int result = 0; int byte = *(int *)arg; switch (cmd) { @@ -177,9 +176,6 @@ static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) return -ENOIOCTLCMD; } - if (result) - return -EIO; - return 0; } diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index d6ce6f6a5..5dd4bd660 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -93,7 +93,6 @@ struct tuner { unsigned int type; /* chip type id */ unsigned int config; - int (*tuner_callback) (void *dev, int command, int arg); const char *name; }; @@ -347,7 +346,7 @@ static struct xc5000_config xc5000_cfg; static void set_type(struct i2c_client *c, unsigned int type, unsigned int new_mode_mask, unsigned int new_config, - int (*tuner_callback) (void *dev, int command,int arg)) + int (*tuner_callback) (void *dev, int component, int cmd, int arg)) { struct tuner *t = i2c_get_clientdata(c); struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; @@ -363,7 +362,7 @@ static void set_type(struct i2c_client *c, unsigned int type, t->config = new_config; if (tuner_callback != NULL) { tuner_dbg("defining GPIO callback\n"); - t->tuner_callback = tuner_callback; + t->fe.callback = tuner_callback; } if (t->mode == T_UNINITIALIZED) { @@ -386,7 +385,6 @@ static void set_type(struct i2c_client *c, unsigned int type, { struct tda829x_config cfg = { .lna_cfg = t->config, - .tuner_callback = t->tuner_callback, }; if (!dvb_attach(tda829x_attach, &t->fe, t->i2c->adapter, t->i2c->addr, &cfg)) @@ -434,7 +432,6 @@ static void set_type(struct i2c_client *c, unsigned int type, struct xc2028_config cfg = { .i2c_adap = t->i2c->adapter, .i2c_addr = t->i2c->addr, - .callback = t->tuner_callback, }; if (!dvb_attach(xc2028_attach, &t->fe, &cfg)) goto attach_failed; @@ -451,7 +448,6 @@ static void set_type(struct i2c_client *c, unsigned int type, xc5000_cfg.i2c_address = t->i2c->addr; xc5000_cfg.if_khz = 5380; - xc5000_cfg.tuner_callback = t->tuner_callback; if (!dvb_attach(xc5000_attach, &t->fe, t->i2c->adapter, &xc5000_cfg)) goto attach_failed; @@ -1234,7 +1230,7 @@ register_client: } else { t->mode = V4L2_TUNER_DIGITAL_TV; } - set_type(client, t->type, t->mode_mask, t->config, t->tuner_callback); + set_type(client, t->type, t->mode_mask, t->config, t->fe.callback); list_add_tail(&t->list, &tuner_list); return 0; } diff --git a/linux/drivers/media/video/uvc/uvc_ctrl.c b/linux/drivers/media/video/uvc/uvc_ctrl.c index 6ef3e5297..f16aafe9c 100644 --- a/linux/drivers/media/video/uvc/uvc_ctrl.c +++ b/linux/drivers/media/video/uvc/uvc_ctrl.c @@ -83,6 +83,22 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_WHITE_BALANCE_TEMPERATURE_CONTROL, + .index = 6, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, + .index = 7, + .size = 4, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, .selector = PU_BACKLIGHT_COMPENSATION_CONTROL, .index = 8, .size = 2, @@ -114,6 +130,60 @@ static struct uvc_control_info uvc_ctrls[] = { | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, }, { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, + .index = 12, + .size = 1, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR + | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, + .index = 13, + .size = 1, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR + | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_DIGITAL_MULTIPLIER_CONTROL, + .index = 14, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL, + .index = 15, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_ANALOG_VIDEO_STANDARD_CONTROL, + .index = 16, + .size = 1, + .flags = UVC_CONTROL_GET_CUR, + }, + { + .entity = UVC_GUID_UVC_PROCESSING, + .selector = PU_ANALOG_LOCK_STATUS_CONTROL, + .index = 17, + .size = 1, + .flags = UVC_CONTROL_GET_CUR, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_SCANNING_MODE_CONTROL, + .index = 0, + .size = 1, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR + | UVC_CONTROL_RESTORE, + }, + { .entity = UVC_GUID_UVC_CAMERA, .selector = CT_AE_MODE_CONTROL, .index = 1, @@ -140,6 +210,14 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_EXPOSURE_TIME_RELATIVE_CONTROL, + .index = 4, + .size = 1, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR + | UVC_CONTROL_RESTORE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, .selector = CT_FOCUS_ABSOLUTE_CONTROL, .index = 5, .size = 2, @@ -148,42 +226,90 @@ static struct uvc_control_info uvc_ctrls[] = { }, { .entity = UVC_GUID_UVC_CAMERA, - .selector = CT_FOCUS_AUTO_CONTROL, - .index = 17, - .size = 1, - .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR - | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, + .selector = CT_FOCUS_RELATIVE_CONTROL, + .index = 6, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_AUTO_UPDATE, }, { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, - .index = 12, + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_IRIS_ABSOLUTE_CONTROL, + .index = 7, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_IRIS_RELATIVE_CONTROL, + .index = 8, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR - | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, + | UVC_CONTROL_AUTO_UPDATE, }, { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_TEMPERATURE_CONTROL, - .index = 6, + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_ZOOM_ABSOLUTE_CONTROL, + .index = 9, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, }, { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_ZOOM_RELATIVE_CONTROL, + .index = 10, + .size = 3, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_PANTILT_ABSOLUTE_CONTROL, + .index = 11, + .size = 8, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_PANTILT_RELATIVE_CONTROL, + .index = 12, + .size = 4, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_ROLL_ABSOLUTE_CONTROL, .index = 13, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_ROLL_RELATIVE_CONTROL, + .index = 14, + .size = 2, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + | UVC_CONTROL_AUTO_UPDATE, + }, + { + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_FOCUS_AUTO_CONTROL, + .index = 17, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, }, { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, - .index = 7, - .size = 4, - .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE + .entity = UVC_GUID_UVC_CAMERA, + .selector = CT_PRIVACY_CONTROL, + .index = 18, + .size = 1, + .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, }, }; @@ -592,7 +718,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, if (ctrl == NULL) return -EINVAL; - data = kmalloc(8, GFP_KERNEL); + data = kmalloc(ctrl->info->size, GFP_KERNEL); if (data == NULL) return -ENOMEM; @@ -711,7 +837,17 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev, for (i = 0; i < entity->ncontrols; ++i) { ctrl = &entity->controls[i]; - if (ctrl->info == NULL || !ctrl->dirty) + if (ctrl->info == NULL) + continue; + + /* Reset the loaded flag for auto-update controls that were + * marked as loaded in uvc_ctrl_get/uvc_ctrl_set to prevent + * uvc_ctrl_get from using the cached value. + */ + if (ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) + ctrl->loaded = 0; + + if (!ctrl->dirty) continue; if (!rollback) @@ -727,9 +863,6 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev, uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), ctrl->info->size); - if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) - ctrl->loaded = 0; - ctrl->dirty = 0; if (ret < 0) @@ -787,8 +920,7 @@ int uvc_ctrl_get(struct uvc_video_device *video, if (ret < 0) return ret; - if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0) - ctrl->loaded = 1; + ctrl->loaded = 1; } xctrl->value = uvc_get_le_value( @@ -839,8 +971,7 @@ int uvc_ctrl_set(struct uvc_video_device *video, return ret; } - if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0) - ctrl->loaded = 1; + ctrl->loaded = 1; } if (!ctrl->dirty) { diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index b2482502a..5364417de 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1941,6 +1941,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_MINMAX }, + /* Advent 4211 - Bison Electronics */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x5986, + .idProduct = 0x0203, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_MINMAX }, /* Bison Electronics */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, diff --git a/linux/drivers/media/video/uvc/uvc_status.c b/linux/drivers/media/video/uvc/uvc_status.c index 75e678ac5..5d60b264d 100644 --- a/linux/drivers/media/video/uvc/uvc_status.c +++ b/linux/drivers/media/video/uvc/uvc_status.c @@ -177,9 +177,15 @@ int uvc_status_init(struct uvc_device *dev) uvc_input_init(dev); + dev->status = kzalloc(UVC_MAX_STATUS_SIZE, GFP_KERNEL); + if (dev->status == NULL) + return -ENOMEM; + dev->int_urb = usb_alloc_urb(0, GFP_KERNEL); - if (dev->int_urb == NULL) + if (dev->int_urb == NULL) { + kfree(dev->status); return -ENOMEM; + } pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress); @@ -192,7 +198,7 @@ int uvc_status_init(struct uvc_device *dev) interval = fls(interval) - 1; usb_fill_int_urb(dev->int_urb, dev->udev, pipe, - dev->status, sizeof dev->status, uvc_status_complete, + dev->status, UVC_MAX_STATUS_SIZE, uvc_status_complete, dev, interval); return usb_submit_urb(dev->int_urb, GFP_KERNEL); @@ -202,6 +208,7 @@ void uvc_status_cleanup(struct uvc_device *dev) { usb_kill_urb(dev->int_urb); usb_free_urb(dev->int_urb); + kfree(dev->status); uvc_input_cleanup(dev); } diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c index d4758c8e1..78e4c4e09 100644 --- a/linux/drivers/media/video/uvc/uvc_v4l2.c +++ b/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -842,10 +842,6 @@ static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file, if (ret < 0) return ret; - if (!(video->streaming->cur_format->flags & - UVC_FMT_FLAG_COMPRESSED)) - video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE; - rb->count = ret; ret = 0; break; diff --git a/linux/drivers/media/video/uvc/uvc_video.c b/linux/drivers/media/video/uvc/uvc_video.c index 593aebffe..b7bb23820 100644 --- a/linux/drivers/media/video/uvc/uvc_video.c +++ b/linux/drivers/media/video/uvc/uvc_video.c @@ -971,6 +971,11 @@ int uvc_video_enable(struct uvc_video_device *video, int enable) return 0; } + if (video->streaming->cur_format->flags & UVC_FMT_FLAG_COMPRESSED) + video->queue.flags &= ~UVC_QUEUE_DROP_INCOMPLETE; + else + video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE; + if ((ret = uvc_queue_enable(&video->queue, 1)) < 0) return ret; diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index bafe3406e..9a6bc1aaf 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -303,6 +303,8 @@ struct uvc_xu_control { #define UVC_MAX_FRAME_SIZE (16*1024*1024) /* Maximum number of video buffers. */ #define UVC_MAX_VIDEO_BUFFERS 32 +/* Maximum status buffer size in bytes of interrupt URB. */ +#define UVC_MAX_STATUS_SIZE 16 #define UVC_CTRL_CONTROL_TIMEOUT 300 #define UVC_CTRL_STREAMING_TIMEOUT 1000 @@ -634,7 +636,7 @@ struct uvc_device { /* Status Interrupt Endpoint */ struct usb_host_endpoint *int_ep; struct urb *int_urb; - __u8 status[16]; + __u8 *status; struct input_dev *input; /* Video Streaming interfaces */ |