diff options
author | Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us> | 2008-06-28 04:01:30 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-07-20 06:14:14 -0400 |
commit | f5376adacc693155c24e4e7be3777bdd0eeb99f7 (patch) | |
tree | cb083d0f5d62b24a88df53b91cfcd604645a0a1f | |
parent | c0f4c0adfdb10747045fcc757a3e60ae1e1558f3 (diff) |
V4L/DVB (8147): cxusb: add initial support for AVerTVHD Volar
Add initial support for this device. The AGC and tracking filter
settings for the mxl5003 are known to be wrong, but it generally works.
Signed-off-by: Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r-- | drivers/media/dvb/dvb-usb/cxusb.c | 146 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/cxusb.h | 3 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 5 |
3 files changed, 150 insertions, 4 deletions
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 0286156704f2..578afce6884c 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include "zl10353.h" | 35 | #include "zl10353.h" |
36 | #include "tuner-xc2028.h" | 36 | #include "tuner-xc2028.h" |
37 | #include "tuner-simple.h" | 37 | #include "tuner-simple.h" |
38 | #include "mxl5005s.h" | ||
38 | 39 | ||
39 | /* debug */ | 40 | /* debug */ |
40 | static int dvb_usb_cxusb_debug; | 41 | static int dvb_usb_cxusb_debug; |
@@ -43,9 +44,8 @@ MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_ST | |||
43 | 44 | ||
44 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 45 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
45 | 46 | ||
46 | #define deb_info(args...) dprintk(dvb_usb_cxusb_debug,0x01,args) | 47 | #define deb_info(args...) dprintk(dvb_usb_cxusb_debug, 0x03, args) |
47 | #define deb_i2c(args...) if (d->udev->descriptor.idVendor == USB_VID_MEDION) \ | 48 | #define deb_i2c(args...) dprintk(dvb_usb_cxusb_debug, 0x02, args) |
48 | dprintk(dvb_usb_cxusb_debug,0x01,args) | ||
49 | 49 | ||
50 | static int cxusb_ctrl_msg(struct dvb_usb_device *d, | 50 | static int cxusb_ctrl_msg(struct dvb_usb_device *d, |
51 | u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) | 51 | u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) |
@@ -202,6 +202,46 @@ static int cxusb_power_ctrl(struct dvb_usb_device *d, int onoff) | |||
202 | return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0); | 202 | return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0); |
203 | } | 203 | } |
204 | 204 | ||
205 | static int cxusb_aver_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
206 | { | ||
207 | int ret; | ||
208 | if (!onoff) | ||
209 | return cxusb_ctrl_msg(d, CMD_POWER_OFF, NULL, 0, NULL, 0); | ||
210 | if (d->state == DVB_USB_STATE_INIT && | ||
211 | usb_set_interface(d->udev, 0, 0) < 0) | ||
212 | err("set interface failed"); | ||
213 | do; while (!(ret = cxusb_ctrl_msg(d, CMD_POWER_ON, NULL, 0, NULL, 0)) && | ||
214 | !(ret = cxusb_ctrl_msg(d, 0x15, NULL, 0, NULL, 0)) && | ||
215 | !(ret = cxusb_ctrl_msg(d, 0x17, NULL, 0, NULL, 0)) && 0); | ||
216 | if (!ret) { | ||
217 | /* FIXME: We don't know why, but we need to configure the | ||
218 | * lgdt3303 with the register settings below on resume */ | ||
219 | int i; | ||
220 | u8 buf, bufs[] = { | ||
221 | 0x0e, 0x2, 0x00, 0x7f, | ||
222 | 0x0e, 0x2, 0x02, 0xfe, | ||
223 | 0x0e, 0x2, 0x02, 0x01, | ||
224 | 0x0e, 0x2, 0x00, 0x03, | ||
225 | 0x0e, 0x2, 0x0d, 0x40, | ||
226 | 0x0e, 0x2, 0x0e, 0x87, | ||
227 | 0x0e, 0x2, 0x0f, 0x8e, | ||
228 | 0x0e, 0x2, 0x10, 0x01, | ||
229 | 0x0e, 0x2, 0x14, 0xd7, | ||
230 | 0x0e, 0x2, 0x47, 0x88, | ||
231 | }; | ||
232 | msleep(20); | ||
233 | for (i = 0; i < sizeof(bufs)/sizeof(u8); i += 4/sizeof(u8)) { | ||
234 | ret = cxusb_ctrl_msg(d, CMD_I2C_WRITE, | ||
235 | bufs+i, 4, &buf, 1); | ||
236 | if (ret) | ||
237 | break; | ||
238 | if (buf != 0x8) | ||
239 | return -EREMOTEIO; | ||
240 | } | ||
241 | } | ||
242 | return ret; | ||
243 | } | ||
244 | |||
205 | static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff) | 245 | static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff) |
206 | { | 246 | { |
207 | u8 b = 0; | 247 | u8 b = 0; |
@@ -233,6 +273,16 @@ static int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | |||
233 | return 0; | 273 | return 0; |
234 | } | 274 | } |
235 | 275 | ||
276 | static int cxusb_aver_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
277 | { | ||
278 | if (onoff) | ||
279 | cxusb_ctrl_msg(adap->dev, CMD_AVER_STREAM_ON, NULL, 0, NULL, 0); | ||
280 | else | ||
281 | cxusb_ctrl_msg(adap->dev, CMD_AVER_STREAM_OFF, | ||
282 | NULL, 0, NULL, 0); | ||
283 | return 0; | ||
284 | } | ||
285 | |||
236 | static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | 286 | static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) |
237 | { | 287 | { |
238 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; | 288 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; |
@@ -423,6 +473,12 @@ static struct lgdt330x_config cxusb_lgdt3303_config = { | |||
423 | .demod_chip = LGDT3303, | 473 | .demod_chip = LGDT3303, |
424 | }; | 474 | }; |
425 | 475 | ||
476 | static struct lgdt330x_config cxusb_aver_lgdt3303_config = { | ||
477 | .demod_address = 0x0e, | ||
478 | .demod_chip = LGDT3303, | ||
479 | .clock_polarity_flip = 2, | ||
480 | }; | ||
481 | |||
426 | static struct mt352_config cxusb_dee1601_config = { | 482 | static struct mt352_config cxusb_dee1601_config = { |
427 | .demod_address = 0x0f, | 483 | .demod_address = 0x0f, |
428 | .demod_init = cxusb_dee1601_demod_init, | 484 | .demod_init = cxusb_dee1601_demod_init, |
@@ -453,6 +509,24 @@ static struct mt352_config cxusb_mt352_xc3028_config = { | |||
453 | .demod_init = cxusb_mt352_demod_init, | 509 | .demod_init = cxusb_mt352_demod_init, |
454 | }; | 510 | }; |
455 | 511 | ||
512 | /* FIXME: needs tweaking */ | ||
513 | static struct mxl5005s_config aver_a868r_tuner = { | ||
514 | .i2c_address = 0x63, | ||
515 | .if_freq = 6000000UL, | ||
516 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
517 | .agc_mode = MXL_SINGLE_AGC, | ||
518 | .tracking_filter = MXL_TF_C, | ||
519 | .rssi_enable = MXL_RSSI_ENABLE, | ||
520 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
521 | .div_out = MXL_DIV_OUT_4, | ||
522 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
523 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
524 | .top = MXL5005S_TOP_25P2, | ||
525 | .mod_mode = MXL_DIGITAL_MODE, | ||
526 | .if_mode = MXL_ZERO_IF, | ||
527 | .AgcMasterByte = 0x00, | ||
528 | }; | ||
529 | |||
456 | /* Callbacks for DVB USB */ | 530 | /* Callbacks for DVB USB */ |
457 | static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) | 531 | static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) |
458 | { | 532 | { |
@@ -533,6 +607,13 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap) | |||
533 | return 0; | 607 | return 0; |
534 | } | 608 | } |
535 | 609 | ||
610 | static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap) | ||
611 | { | ||
612 | dvb_attach(mxl5005s_attach, adap->fe, | ||
613 | &adap->dev->i2c_adap, &aver_a868r_tuner); | ||
614 | return 0; | ||
615 | } | ||
616 | |||
536 | static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap) | 617 | static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap) |
537 | { | 618 | { |
538 | u8 b; | 619 | u8 b; |
@@ -562,6 +643,16 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap) | |||
562 | return -EIO; | 643 | return -EIO; |
563 | } | 644 | } |
564 | 645 | ||
646 | static int cxusb_aver_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap) | ||
647 | { | ||
648 | adap->fe = dvb_attach(lgdt330x_attach, &cxusb_aver_lgdt3303_config, | ||
649 | &adap->dev->i2c_adap); | ||
650 | if (adap->fe != NULL) | ||
651 | return 0; | ||
652 | |||
653 | return -EIO; | ||
654 | } | ||
655 | |||
565 | static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap) | 656 | static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap) |
566 | { | 657 | { |
567 | /* used in both lgz201 and th7579 */ | 658 | /* used in both lgz201 and th7579 */ |
@@ -736,6 +827,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties; | |||
736 | static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties; | 827 | static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties; |
737 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties; | 828 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties; |
738 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties; | 829 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties; |
830 | static struct dvb_usb_device_properties cxusb_aver_a868r_properties; | ||
739 | 831 | ||
740 | static int cxusb_probe(struct usb_interface *intf, | 832 | static int cxusb_probe(struct usb_interface *intf, |
741 | const struct usb_device_id *id) | 833 | const struct usb_device_id *id) |
@@ -756,7 +848,10 @@ static int cxusb_probe(struct usb_interface *intf, | |||
756 | THIS_MODULE, NULL, adapter_nr) || | 848 | THIS_MODULE, NULL, adapter_nr) || |
757 | 0 == dvb_usb_device_init(intf, | 849 | 0 == dvb_usb_device_init(intf, |
758 | &cxusb_bluebird_nano2_needsfirmware_properties, | 850 | &cxusb_bluebird_nano2_needsfirmware_properties, |
759 | THIS_MODULE, NULL, adapter_nr)) | 851 | THIS_MODULE, NULL, adapter_nr) || |
852 | 0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties, | ||
853 | THIS_MODULE, NULL, adapter_nr) || | ||
854 | 0) | ||
760 | return 0; | 855 | return 0; |
761 | 856 | ||
762 | return -EINVAL; | 857 | return -EINVAL; |
@@ -779,6 +874,7 @@ static struct usb_device_id cxusb_table [] = { | |||
779 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) }, | 874 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) }, |
780 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) }, | 875 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) }, |
781 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) }, | 876 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) }, |
877 | { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R) }, | ||
782 | {} /* Terminating entry */ | 878 | {} /* Terminating entry */ |
783 | }; | 879 | }; |
784 | MODULE_DEVICE_TABLE (usb, cxusb_table); | 880 | MODULE_DEVICE_TABLE (usb, cxusb_table); |
@@ -1182,6 +1278,48 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope | |||
1182 | } | 1278 | } |
1183 | }; | 1279 | }; |
1184 | 1280 | ||
1281 | static struct dvb_usb_device_properties cxusb_aver_a868r_properties = { | ||
1282 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
1283 | |||
1284 | .usb_ctrl = CYPRESS_FX2, | ||
1285 | |||
1286 | .size_of_priv = sizeof(struct cxusb_state), | ||
1287 | |||
1288 | .num_adapters = 1, | ||
1289 | .adapter = { | ||
1290 | { | ||
1291 | .streaming_ctrl = cxusb_aver_streaming_ctrl, | ||
1292 | .frontend_attach = cxusb_aver_lgdt3303_frontend_attach, | ||
1293 | .tuner_attach = cxusb_mxl5003s_tuner_attach, | ||
1294 | /* parameter for the MPEG2-data transfer */ | ||
1295 | .stream = { | ||
1296 | .type = USB_BULK, | ||
1297 | .count = 5, | ||
1298 | .endpoint = 0x04, | ||
1299 | .u = { | ||
1300 | .bulk = { | ||
1301 | .buffersize = 8192, | ||
1302 | } | ||
1303 | } | ||
1304 | }, | ||
1305 | |||
1306 | }, | ||
1307 | }, | ||
1308 | .power_ctrl = cxusb_aver_power_ctrl, | ||
1309 | |||
1310 | .i2c_algo = &cxusb_i2c_algo, | ||
1311 | |||
1312 | .generic_bulk_ctrl_endpoint = 0x01, | ||
1313 | |||
1314 | .num_device_descs = 1, | ||
1315 | .devices = { | ||
1316 | { "AVerMedia AVerTVHD Volar (A868R)", | ||
1317 | { NULL }, | ||
1318 | { &cxusb_table[16], NULL }, | ||
1319 | }, | ||
1320 | } | ||
1321 | }; | ||
1322 | |||
1185 | static struct usb_driver cxusb_driver = { | 1323 | static struct usb_driver cxusb_driver = { |
1186 | .name = "dvb_usb_cxusb", | 1324 | .name = "dvb_usb_cxusb", |
1187 | .probe = cxusb_probe, | 1325 | .probe = cxusb_probe, |
diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h index 4768a2c35517..1a51eafd31b9 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.h +++ b/drivers/media/dvb/dvb-usb/cxusb.h | |||
@@ -20,6 +20,9 @@ | |||
20 | #define CMD_STREAMING_ON 0x36 | 20 | #define CMD_STREAMING_ON 0x36 |
21 | #define CMD_STREAMING_OFF 0x37 | 21 | #define CMD_STREAMING_OFF 0x37 |
22 | 22 | ||
23 | #define CMD_AVER_STREAM_ON 0x18 | ||
24 | #define CMD_AVER_STREAM_OFF 0x19 | ||
25 | |||
23 | #define CMD_GET_IR_CODE 0x47 | 26 | #define CMD_GET_IR_CODE 0x47 |
24 | 27 | ||
25 | #define CMD_ANALOG 0x50 | 28 | #define CMD_ANALOG 0x50 |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index e6b43fb3a148..75ec9caa1421 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
@@ -137,6 +137,11 @@ | |||
137 | #define USB_PID_AVERMEDIA_EXPRESS 0xb568 | 137 | #define USB_PID_AVERMEDIA_EXPRESS 0xb568 |
138 | #define USB_PID_AVERMEDIA_VOLAR 0xa807 | 138 | #define USB_PID_AVERMEDIA_VOLAR 0xa807 |
139 | #define USB_PID_AVERMEDIA_VOLAR_2 0xb808 | 139 | #define USB_PID_AVERMEDIA_VOLAR_2 0xb808 |
140 | #define USB_PID_AVERMEDIA_VOLAR_A868R 0xa868 | ||
141 | #define USB_PID_AVERMEDIA_MCE_USB_M038 0x1228 | ||
142 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R 0x0039 | ||
143 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_ATSC 0x1039 | ||
144 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_DVBT 0x2039 | ||
140 | #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 | 145 | #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 |
141 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a | 146 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a |
142 | #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 | 147 | #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 |