diff options
| -rw-r--r-- | drivers/media/video/cx18/cx18-cards.c | 4 | ||||
| -rw-r--r-- | drivers/media/video/cx18/cx18-dvb.c | 160 |
2 files changed, 162 insertions, 2 deletions
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index 80ee7bd64e24..36f2d76006fd 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c | |||
| @@ -204,8 +204,8 @@ static const struct cx18_card cx18_card_mpc718 = { | |||
| 204 | .v4l2_capabilities = CX18_CAP_ENCODER, | 204 | .v4l2_capabilities = CX18_CAP_ENCODER, |
| 205 | .hw_audio_ctrl = CX18_HW_418_AV, | 205 | .hw_audio_ctrl = CX18_HW_418_AV, |
| 206 | .hw_muxer = CX18_HW_GPIO_MUX, | 206 | .hw_muxer = CX18_HW_GPIO_MUX, |
| 207 | .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX | | 207 | .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | |
| 208 | CX18_HW_GPIO_RESET_CTRL, | 208 | CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL, |
| 209 | .video_inputs = { | 209 | .video_inputs = { |
| 210 | { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, | 210 | { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, |
| 211 | { CX18_CARD_INPUT_SVIDEO1, 1, | 211 | { CX18_CARD_INPUT_SVIDEO1, 1, |
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 6ea3fe623ef4..51a0c33b25b7 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c | |||
| @@ -30,6 +30,10 @@ | |||
| 30 | #include "s5h1409.h" | 30 | #include "s5h1409.h" |
| 31 | #include "mxl5005s.h" | 31 | #include "mxl5005s.h" |
| 32 | #include "zl10353.h" | 32 | #include "zl10353.h" |
| 33 | |||
| 34 | #include <linux/firmware.h> | ||
| 35 | #include "mt352.h" | ||
| 36 | #include "mt352_priv.h" | ||
| 33 | #include "tuner-xc2028.h" | 37 | #include "tuner-xc2028.h" |
| 34 | 38 | ||
| 35 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 39 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
| @@ -38,6 +42,11 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | |||
| 38 | #define CX18_CLOCK_ENABLE2 0xc71024 | 42 | #define CX18_CLOCK_ENABLE2 0xc71024 |
| 39 | #define CX18_DMUX_CLK_MASK 0x0080 | 43 | #define CX18_DMUX_CLK_MASK 0x0080 |
| 40 | 44 | ||
| 45 | /* | ||
| 46 | * CX18_CARD_HVR_1600_ESMT | ||
| 47 | * CX18_CARD_HVR_1600_SAMSUNG | ||
| 48 | */ | ||
| 49 | |||
| 41 | static struct mxl5005s_config hauppauge_hvr1600_tuner = { | 50 | static struct mxl5005s_config hauppauge_hvr1600_tuner = { |
| 42 | .i2c_address = 0xC6 >> 1, | 51 | .i2c_address = 0xC6 >> 1, |
| 43 | .if_freq = IF_FREQ_5380000HZ, | 52 | .if_freq = IF_FREQ_5380000HZ, |
| @@ -65,6 +74,9 @@ static struct s5h1409_config hauppauge_hvr1600_config = { | |||
| 65 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK | 74 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK |
| 66 | }; | 75 | }; |
| 67 | 76 | ||
| 77 | /* | ||
| 78 | * CX18_CARD_LEADTEK_DVR3100H | ||
| 79 | */ | ||
| 68 | /* Information/confirmation of proper config values provided by Terry Wu */ | 80 | /* Information/confirmation of proper config values provided by Terry Wu */ |
| 69 | static struct zl10353_config leadtek_dvr3100h_demod = { | 81 | static struct zl10353_config leadtek_dvr3100h_demod = { |
| 70 | .demod_address = 0x1e >> 1, /* Datasheet suggested straps */ | 82 | .demod_address = 0x1e >> 1, /* Datasheet suggested straps */ |
| @@ -74,6 +86,121 @@ static struct zl10353_config leadtek_dvr3100h_demod = { | |||
| 74 | .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ | 86 | .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ |
| 75 | }; | 87 | }; |
| 76 | 88 | ||
| 89 | /* | ||
| 90 | * CX18_CARD_YUAN_MPC718 | ||
| 91 | */ | ||
| 92 | /* | ||
| 93 | * Due to | ||
| 94 | * | ||
| 95 | * 1. an absence of information on how to prgram the MT352 | ||
| 96 | * 2. the Linux mt352 module pushing MT352 initialzation off onto us here | ||
| 97 | * | ||
| 98 | * We have to use an init sequence that *you* must extract from the Windows | ||
| 99 | * driver (yuanrap.sys) and which we load as a firmware. | ||
| 100 | * | ||
| 101 | * If someone can provide me with a Zarlink MT352 (Intel CE6352?) Design Manual | ||
| 102 | * with chip programming details, then I can remove this annoyance. | ||
| 103 | */ | ||
| 104 | static int yuan_mpc718_mt352_reqfw(struct cx18_stream *stream, | ||
| 105 | const struct firmware **fw) | ||
| 106 | { | ||
| 107 | struct cx18 *cx = stream->cx; | ||
| 108 | const char *fn = "dvb-cx18-mpc718-mt352.fw"; | ||
| 109 | int ret; | ||
| 110 | |||
| 111 | ret = request_firmware(fw, fn, &cx->pci_dev->dev); | ||
| 112 | if (ret) | ||
| 113 | CX18_ERR("Unable to open firmware file %s\n", fn); | ||
| 114 | else { | ||
| 115 | size_t sz = (*fw)->size; | ||
| 116 | if (sz < 2 || sz > 64 || (sz % 2) != 0) { | ||
| 117 | CX18_ERR("Firmware %s has a bad size: %lu bytes\n", | ||
| 118 | fn, (unsigned long) sz); | ||
| 119 | ret = -EILSEQ; | ||
| 120 | release_firmware(*fw); | ||
| 121 | *fw = NULL; | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | if (ret) { | ||
| 126 | CX18_ERR("The MPC718 board variant with the MT352 DVB-T" | ||
| 127 | "demodualtor will not work without it\n"); | ||
| 128 | CX18_ERR("Run 'linux/Documentation/dvb/get_dvb_firmware " | ||
| 129 | "mpc718' if you need the firmware\n"); | ||
| 130 | } | ||
| 131 | return ret; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int yuan_mpc718_mt352_init(struct dvb_frontend *fe) | ||
| 135 | { | ||
| 136 | struct cx18_dvb *dvb = container_of(fe->dvb, | ||
| 137 | struct cx18_dvb, dvb_adapter); | ||
| 138 | struct cx18_stream *stream = container_of(dvb, struct cx18_stream, dvb); | ||
| 139 | const struct firmware *fw = NULL; | ||
| 140 | int ret; | ||
| 141 | int i; | ||
| 142 | u8 buf[3]; | ||
| 143 | |||
| 144 | ret = yuan_mpc718_mt352_reqfw(stream, &fw); | ||
| 145 | if (ret) | ||
| 146 | return ret; | ||
| 147 | |||
| 148 | /* Loop through all the register-value pairs in the firmware file */ | ||
| 149 | for (i = 0; i < fw->size; i += 2) { | ||
| 150 | buf[0] = fw->data[i]; | ||
| 151 | /* Intercept a few registers we want to set ourselves */ | ||
| 152 | switch (buf[0]) { | ||
| 153 | case TRL_NOMINAL_RATE_0: | ||
| 154 | /* Set our custom OFDM bandwidth in the case below */ | ||
| 155 | break; | ||
| 156 | case TRL_NOMINAL_RATE_1: | ||
| 157 | /* 6 MHz: 64/7 * 6/8 / 20.48 * 2^16 = 0x55b6.db6 */ | ||
| 158 | /* 7 MHz: 64/7 * 7/8 / 20.48 * 2^16 = 0x6400 */ | ||
| 159 | /* 8 MHz: 64/7 * 8/8 / 20.48 * 2^16 = 0x7249.249 */ | ||
| 160 | buf[1] = 0x72; | ||
| 161 | buf[2] = 0x49; | ||
| 162 | mt352_write(fe, buf, 3); | ||
| 163 | break; | ||
| 164 | case INPUT_FREQ_0: | ||
| 165 | /* Set our custom IF in the case below */ | ||
| 166 | break; | ||
| 167 | case INPUT_FREQ_1: | ||
| 168 | /* 4.56 MHz IF: (20.48 - 4.56)/20.48 * 2^14 = 0x31c0 */ | ||
| 169 | buf[1] = 0x31; | ||
| 170 | buf[2] = 0xc0; | ||
| 171 | mt352_write(fe, buf, 3); | ||
| 172 | break; | ||
| 173 | default: | ||
| 174 | /* Pass through the register-value pair from the fw */ | ||
| 175 | buf[1] = fw->data[i+1]; | ||
| 176 | mt352_write(fe, buf, 2); | ||
| 177 | break; | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | buf[0] = (u8) TUNER_GO; | ||
| 182 | buf[1] = 0x01; /* Go */ | ||
| 183 | mt352_write(fe, buf, 2); | ||
| 184 | release_firmware(fw); | ||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | static struct mt352_config yuan_mpc718_mt352_demod = { | ||
| 189 | .demod_address = 0x1e >> 1, | ||
| 190 | .adc_clock = 20480, /* 20.480 MHz */ | ||
| 191 | .if2 = 4560, /* 4.560 MHz */ | ||
| 192 | .no_tuner = 1, /* XC3028 is not behind the gate */ | ||
| 193 | .demod_init = yuan_mpc718_mt352_init, | ||
| 194 | }; | ||
| 195 | |||
| 196 | static struct zl10353_config yuan_mpc718_zl10353_demod = { | ||
| 197 | .demod_address = 0x1e >> 1, /* Datasheet suggested straps */ | ||
| 198 | .if2 = 45600, /* 4.560 MHz IF from the XC3028 */ | ||
| 199 | .parallel_ts = 1, /* Not a serial TS */ | ||
| 200 | .no_tuner = 1, /* XC3028 is not behind the gate */ | ||
| 201 | .disable_i2c_gate_ctrl = 1, /* Disable the I2C gate */ | ||
| 202 | }; | ||
| 203 | |||
| 77 | static int dvb_register(struct cx18_stream *stream); | 204 | static int dvb_register(struct cx18_stream *stream); |
| 78 | 205 | ||
| 79 | /* Kernel DVB framework calls this when the feed needs to start. | 206 | /* Kernel DVB framework calls this when the feed needs to start. |
| @@ -113,6 +240,7 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) | |||
| 113 | break; | 240 | break; |
| 114 | 241 | ||
| 115 | case CX18_CARD_LEADTEK_DVR3100H: | 242 | case CX18_CARD_LEADTEK_DVR3100H: |
| 243 | case CX18_CARD_YUAN_MPC718: | ||
| 116 | default: | 244 | default: |
| 117 | /* Assumption - Parallel transport - Signalling | 245 | /* Assumption - Parallel transport - Signalling |
| 118 | * undefined or default. | 246 | * undefined or default. |
| @@ -326,6 +454,38 @@ static int dvb_register(struct cx18_stream *stream) | |||
| 326 | fe->ops.tuner_ops.set_config(fe, &ctrl); | 454 | fe->ops.tuner_ops.set_config(fe, &ctrl); |
| 327 | } | 455 | } |
| 328 | break; | 456 | break; |
| 457 | case CX18_CARD_YUAN_MPC718: | ||
| 458 | /* | ||
| 459 | * TODO | ||
| 460 | * Apparently, these cards also could instead have a | ||
| 461 | * DiBcom demod supported by one of the db7000 drivers | ||
| 462 | */ | ||
| 463 | dvb->fe = dvb_attach(mt352_attach, | ||
| 464 | &yuan_mpc718_mt352_demod, | ||
| 465 | &cx->i2c_adap[1]); | ||
| 466 | if (dvb->fe == NULL) | ||
| 467 | dvb->fe = dvb_attach(zl10353_attach, | ||
| 468 | &yuan_mpc718_zl10353_demod, | ||
| 469 | &cx->i2c_adap[1]); | ||
| 470 | if (dvb->fe != NULL) { | ||
| 471 | struct dvb_frontend *fe; | ||
| 472 | struct xc2028_config cfg = { | ||
| 473 | .i2c_adap = &cx->i2c_adap[1], | ||
| 474 | .i2c_addr = 0xc2 >> 1, | ||
| 475 | .ctrl = NULL, | ||
| 476 | }; | ||
| 477 | static struct xc2028_ctrl ctrl = { | ||
| 478 | .fname = XC2028_DEFAULT_FIRMWARE, | ||
| 479 | .max_len = 64, | ||
| 480 | .demod = XC3028_FE_ZARLINK456, | ||
| 481 | .type = XC2028_AUTO, | ||
| 482 | }; | ||
| 483 | |||
| 484 | fe = dvb_attach(xc2028_attach, dvb->fe, &cfg); | ||
| 485 | if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) | ||
| 486 | fe->ops.tuner_ops.set_config(fe, &ctrl); | ||
| 487 | } | ||
| 488 | break; | ||
| 329 | default: | 489 | default: |
| 330 | /* No Digital Tv Support */ | 490 | /* No Digital Tv Support */ |
| 331 | break; | 491 | break; |
