diff options
Diffstat (limited to 'drivers/media/usb/cx231xx/cx231xx-dvb.c')
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-dvb.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c index dd600b994e69..610d5675bde6 100644 --- a/drivers/media/usb/cx231xx/cx231xx-dvb.c +++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include "si2165.h" | 34 | #include "si2165.h" |
35 | #include "mb86a20s.h" | 35 | #include "mb86a20s.h" |
36 | #include "si2157.h" | 36 | #include "si2157.h" |
37 | #include "lgdt3306a.h" | ||
37 | 38 | ||
38 | MODULE_DESCRIPTION("driver for cx231xx based DVB cards"); | 39 | MODULE_DESCRIPTION("driver for cx231xx based DVB cards"); |
39 | MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>"); | 40 | MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>"); |
@@ -160,6 +161,18 @@ static const struct si2165_config pctv_quatro_stick_1114xx_si2165_config = { | |||
160 | .ref_freq_Hz = 24000000, | 161 | .ref_freq_Hz = 24000000, |
161 | }; | 162 | }; |
162 | 163 | ||
164 | static struct lgdt3306a_config hauppauge_955q_lgdt3306a_config = { | ||
165 | .i2c_addr = 0x59, | ||
166 | .qam_if_khz = 4000, | ||
167 | .vsb_if_khz = 3250, | ||
168 | .deny_i2c_rptr = 1, | ||
169 | .spectral_inversion = 1, | ||
170 | .mpeg_mode = LGDT3306A_MPEG_SERIAL, | ||
171 | .tpclk_edge = LGDT3306A_TPCLK_RISING_EDGE, | ||
172 | .tpvalid_polarity = LGDT3306A_TP_VALID_HIGH, | ||
173 | .xtalMHz = 25, | ||
174 | }; | ||
175 | |||
163 | static inline void print_err_status(struct cx231xx *dev, int packet, int status) | 176 | static inline void print_err_status(struct cx231xx *dev, int packet, int status) |
164 | { | 177 | { |
165 | char *errmsg = "Unknown"; | 178 | char *errmsg = "Unknown"; |
@@ -455,6 +468,7 @@ static int register_dvb(struct cx231xx_dvb *dvb, | |||
455 | 468 | ||
456 | mutex_init(&dvb->lock); | 469 | mutex_init(&dvb->lock); |
457 | 470 | ||
471 | |||
458 | /* register adapter */ | 472 | /* register adapter */ |
459 | result = dvb_register_adapter(&dvb->adapter, dev->name, module, device, | 473 | result = dvb_register_adapter(&dvb->adapter, dev->name, module, device, |
460 | adapter_nr); | 474 | adapter_nr); |
@@ -464,6 +478,7 @@ static int register_dvb(struct cx231xx_dvb *dvb, | |||
464 | dev->name, result); | 478 | dev->name, result); |
465 | goto fail_adapter; | 479 | goto fail_adapter; |
466 | } | 480 | } |
481 | dvb_register_media_controller(&dvb->adapter, dev->media_dev); | ||
467 | 482 | ||
468 | /* Ensure all frontends negotiate bus access */ | 483 | /* Ensure all frontends negotiate bus access */ |
469 | dvb->frontend->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl; | 484 | dvb->frontend->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl; |
@@ -536,6 +551,8 @@ static int register_dvb(struct cx231xx_dvb *dvb, | |||
536 | 551 | ||
537 | /* register network adapter */ | 552 | /* register network adapter */ |
538 | dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); | 553 | dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); |
554 | dvb_create_media_graph(&dvb->adapter); | ||
555 | |||
539 | return 0; | 556 | return 0; |
540 | 557 | ||
541 | fail_fe_conn: | 558 | fail_fe_conn: |
@@ -807,7 +824,61 @@ static int dvb_init(struct cx231xx *dev) | |||
807 | dev->dvb->i2c_client_tuner = client; | 824 | dev->dvb->i2c_client_tuner = client; |
808 | break; | 825 | break; |
809 | } | 826 | } |
827 | case CX231XX_BOARD_HAUPPAUGE_955Q: | ||
828 | { | ||
829 | struct i2c_client *client; | ||
830 | struct i2c_board_info info; | ||
831 | struct si2157_config si2157_config; | ||
832 | |||
833 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
834 | |||
835 | dev->dvb->frontend = dvb_attach(lgdt3306a_attach, | ||
836 | &hauppauge_955q_lgdt3306a_config, | ||
837 | tuner_i2c | ||
838 | ); | ||
839 | |||
840 | if (dev->dvb->frontend == NULL) { | ||
841 | dev_err(dev->dev, | ||
842 | "Failed to attach LGDT3306A frontend.\n"); | ||
843 | result = -EINVAL; | ||
844 | goto out_free; | ||
845 | } | ||
846 | |||
847 | dev->dvb->frontend->ops.i2c_gate_ctrl = NULL; | ||
848 | |||
849 | /* define general-purpose callback pointer */ | ||
850 | dvb->frontend->callback = cx231xx_tuner_callback; | ||
851 | |||
852 | /* attach tuner */ | ||
853 | memset(&si2157_config, 0, sizeof(si2157_config)); | ||
854 | si2157_config.fe = dev->dvb->frontend; | ||
855 | si2157_config.inversion = true; | ||
856 | strlcpy(info.type, "si2157", I2C_NAME_SIZE); | ||
857 | info.addr = 0x60; | ||
858 | info.platform_data = &si2157_config; | ||
859 | request_module("si2157"); | ||
810 | 860 | ||
861 | client = i2c_new_device( | ||
862 | tuner_i2c, | ||
863 | &info); | ||
864 | if (client == NULL || client->dev.driver == NULL) { | ||
865 | dvb_frontend_detach(dev->dvb->frontend); | ||
866 | result = -ENODEV; | ||
867 | goto out_free; | ||
868 | } | ||
869 | |||
870 | if (!try_module_get(client->dev.driver->owner)) { | ||
871 | i2c_unregister_device(client); | ||
872 | dvb_frontend_detach(dev->dvb->frontend); | ||
873 | result = -ENODEV; | ||
874 | goto out_free; | ||
875 | } | ||
876 | |||
877 | dev->cx231xx_reset_analog_tuner = NULL; | ||
878 | |||
879 | dev->dvb->i2c_client_tuner = client; | ||
880 | break; | ||
881 | } | ||
811 | case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: | 882 | case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: |
812 | case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID: | 883 | case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID: |
813 | 884 | ||