diff options
author | Oliver Endriss <o.endriss@gmx.de> | 2011-01-10 04:36:13 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-03-21 19:31:44 -0400 |
commit | 5fec18574fec3eaffcab596c1a4e943e2d413cc3 (patch) | |
tree | 0e694ed67a65e339d835dac9e6dfd119cfc667fc | |
parent | ac9725d224544954a8d3413a2a66bdf49f735d8b (diff) |
[media] ngene: Support up to 4 tuners
Support up to 4 tuners for cineS2 v5, duoflex & mystique v2.
Signed-off-by: Oliver Endriss <o.endriss@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/dvb/ngene/ngene-cards.c | 174 |
1 files changed, 143 insertions, 31 deletions
diff --git a/drivers/media/dvb/ngene/ngene-cards.c b/drivers/media/dvb/ngene/ngene-cards.c index 4692a41ad95..5e6b85c3c0f 100644 --- a/drivers/media/dvb/ngene/ngene-cards.c +++ b/drivers/media/dvb/ngene/ngene-cards.c | |||
@@ -48,20 +48,27 @@ | |||
48 | 48 | ||
49 | static int tuner_attach_stv6110(struct ngene_channel *chan) | 49 | static int tuner_attach_stv6110(struct ngene_channel *chan) |
50 | { | 50 | { |
51 | struct i2c_adapter *i2c; | ||
51 | struct stv090x_config *feconf = (struct stv090x_config *) | 52 | struct stv090x_config *feconf = (struct stv090x_config *) |
52 | chan->dev->card_info->fe_config[chan->number]; | 53 | chan->dev->card_info->fe_config[chan->number]; |
53 | struct stv6110x_config *tunerconf = (struct stv6110x_config *) | 54 | struct stv6110x_config *tunerconf = (struct stv6110x_config *) |
54 | chan->dev->card_info->tuner_config[chan->number]; | 55 | chan->dev->card_info->tuner_config[chan->number]; |
55 | struct stv6110x_devctl *ctl; | 56 | struct stv6110x_devctl *ctl; |
56 | 57 | ||
57 | ctl = dvb_attach(stv6110x_attach, chan->fe, tunerconf, | 58 | /* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */ |
58 | &chan->i2c_adapter); | 59 | if (chan->number < 2) |
60 | i2c = &chan->dev->channel[0].i2c_adapter; | ||
61 | else | ||
62 | i2c = &chan->dev->channel[1].i2c_adapter; | ||
63 | |||
64 | ctl = dvb_attach(stv6110x_attach, chan->fe, tunerconf, i2c); | ||
59 | if (ctl == NULL) { | 65 | if (ctl == NULL) { |
60 | printk(KERN_ERR DEVICE_NAME ": No STV6110X found!\n"); | 66 | printk(KERN_ERR DEVICE_NAME ": No STV6110X found!\n"); |
61 | return -ENODEV; | 67 | return -ENODEV; |
62 | } | 68 | } |
63 | 69 | ||
64 | feconf->tuner_init = ctl->tuner_init; | 70 | feconf->tuner_init = ctl->tuner_init; |
71 | feconf->tuner_sleep = ctl->tuner_sleep; | ||
65 | feconf->tuner_set_mode = ctl->tuner_set_mode; | 72 | feconf->tuner_set_mode = ctl->tuner_set_mode; |
66 | feconf->tuner_set_frequency = ctl->tuner_set_frequency; | 73 | feconf->tuner_set_frequency = ctl->tuner_set_frequency; |
67 | feconf->tuner_get_frequency = ctl->tuner_get_frequency; | 74 | feconf->tuner_get_frequency = ctl->tuner_get_frequency; |
@@ -78,20 +85,31 @@ static int tuner_attach_stv6110(struct ngene_channel *chan) | |||
78 | 85 | ||
79 | static int demod_attach_stv0900(struct ngene_channel *chan) | 86 | static int demod_attach_stv0900(struct ngene_channel *chan) |
80 | { | 87 | { |
88 | struct i2c_adapter *i2c; | ||
81 | struct stv090x_config *feconf = (struct stv090x_config *) | 89 | struct stv090x_config *feconf = (struct stv090x_config *) |
82 | chan->dev->card_info->fe_config[chan->number]; | 90 | chan->dev->card_info->fe_config[chan->number]; |
83 | 91 | ||
84 | chan->fe = dvb_attach(stv090x_attach, | 92 | /* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */ |
85 | feconf, | 93 | /* Note: Both adapters share the same i2c bus, but the demod */ |
86 | &chan->i2c_adapter, | 94 | /* driver requires that each demod has its own i2c adapter */ |
87 | chan->number == 0 ? STV090x_DEMODULATOR_0 : | 95 | if (chan->number < 2) |
88 | STV090x_DEMODULATOR_1); | 96 | i2c = &chan->dev->channel[0].i2c_adapter; |
97 | else | ||
98 | i2c = &chan->dev->channel[1].i2c_adapter; | ||
99 | |||
100 | chan->fe = dvb_attach(stv090x_attach, feconf, i2c, | ||
101 | (chan->number & 1) == 0 ? STV090x_DEMODULATOR_0 | ||
102 | : STV090x_DEMODULATOR_1); | ||
89 | if (chan->fe == NULL) { | 103 | if (chan->fe == NULL) { |
90 | printk(KERN_ERR DEVICE_NAME ": No STV0900 found!\n"); | 104 | printk(KERN_ERR DEVICE_NAME ": No STV0900 found!\n"); |
91 | return -ENODEV; | 105 | return -ENODEV; |
92 | } | 106 | } |
93 | 107 | ||
94 | if (!dvb_attach(lnbh24_attach, chan->fe, &chan->i2c_adapter, 0, | 108 | /* store channel info */ |
109 | if (feconf->tuner_i2c_lock) | ||
110 | chan->fe->analog_demod_priv = chan; | ||
111 | |||
112 | if (!dvb_attach(lnbh24_attach, chan->fe, i2c, 0, | ||
95 | 0, chan->dev->card_info->lnb[chan->number])) { | 113 | 0, chan->dev->card_info->lnb[chan->number])) { |
96 | printk(KERN_ERR DEVICE_NAME ": No LNBH24 found!\n"); | 114 | printk(KERN_ERR DEVICE_NAME ": No LNBH24 found!\n"); |
97 | dvb_frontend_detach(chan->fe); | 115 | dvb_frontend_detach(chan->fe); |
@@ -101,6 +119,71 @@ static int demod_attach_stv0900(struct ngene_channel *chan) | |||
101 | return 0; | 119 | return 0; |
102 | } | 120 | } |
103 | 121 | ||
122 | static void cineS2_tuner_i2c_lock(struct dvb_frontend *fe, int lock) | ||
123 | { | ||
124 | struct ngene_channel *chan = fe->analog_demod_priv; | ||
125 | |||
126 | if (lock) | ||
127 | down(&chan->dev->pll_mutex); | ||
128 | else | ||
129 | up(&chan->dev->pll_mutex); | ||
130 | } | ||
131 | |||
132 | static int cineS2_probe(struct ngene_channel *chan) | ||
133 | { | ||
134 | struct i2c_adapter *i2c; | ||
135 | struct stv090x_config *fe_conf; | ||
136 | u8 buf[3]; | ||
137 | struct i2c_msg i2c_msg = { .flags = 0, .buf = buf }; | ||
138 | int rc; | ||
139 | |||
140 | /* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */ | ||
141 | if (chan->number < 2) | ||
142 | i2c = &chan->dev->channel[0].i2c_adapter; | ||
143 | else | ||
144 | i2c = &chan->dev->channel[1].i2c_adapter; | ||
145 | |||
146 | fe_conf = chan->dev->card_info->fe_config[chan->number]; | ||
147 | i2c_msg.addr = fe_conf->address; | ||
148 | |||
149 | /* probe demod */ | ||
150 | i2c_msg.len = 2; | ||
151 | buf[0] = 0xf1; | ||
152 | buf[1] = 0x00; | ||
153 | rc = i2c_transfer(i2c, &i2c_msg, 1); | ||
154 | if (rc != 1) | ||
155 | return -ENODEV; | ||
156 | |||
157 | /* demod found, attach it */ | ||
158 | rc = demod_attach_stv0900(chan); | ||
159 | if (rc < 0 || chan->number < 2) | ||
160 | return rc; | ||
161 | |||
162 | /* demod #2: reprogram outputs DPN1 & DPN2 */ | ||
163 | i2c_msg.len = 3; | ||
164 | buf[0] = 0xf1; | ||
165 | switch (chan->number) { | ||
166 | case 2: | ||
167 | buf[1] = 0x5c; | ||
168 | buf[2] = 0xc2; | ||
169 | break; | ||
170 | case 3: | ||
171 | buf[1] = 0x61; | ||
172 | buf[2] = 0xcc; | ||
173 | break; | ||
174 | default: | ||
175 | return -ENODEV; | ||
176 | } | ||
177 | rc = i2c_transfer(i2c, &i2c_msg, 1); | ||
178 | if (rc != 1) { | ||
179 | printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n"); | ||
180 | return -EIO; | ||
181 | } | ||
182 | |||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | |||
104 | static struct lgdt330x_config aver_m780 = { | 187 | static struct lgdt330x_config aver_m780 = { |
105 | .demod_address = 0xb2 >> 1, | 188 | .demod_address = 0xb2 >> 1, |
106 | .demod_chip = LGDT3303, | 189 | .demod_chip = LGDT3303, |
@@ -151,6 +234,29 @@ static struct stv090x_config fe_cineS2 = { | |||
151 | .adc2_range = STV090x_ADC_1Vpp, | 234 | .adc2_range = STV090x_ADC_1Vpp, |
152 | 235 | ||
153 | .diseqc_envelope_mode = true, | 236 | .diseqc_envelope_mode = true, |
237 | |||
238 | .tuner_i2c_lock = cineS2_tuner_i2c_lock, | ||
239 | }; | ||
240 | |||
241 | static struct stv090x_config fe_cineS2_2 = { | ||
242 | .device = STV0900, | ||
243 | .demod_mode = STV090x_DUAL, | ||
244 | .clk_mode = STV090x_CLK_EXT, | ||
245 | |||
246 | .xtal = 27000000, | ||
247 | .address = 0x69, | ||
248 | |||
249 | .ts1_mode = STV090x_TSMODE_SERIAL_PUNCTURED, | ||
250 | .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, | ||
251 | |||
252 | .repeater_level = STV090x_RPTLEVEL_16, | ||
253 | |||
254 | .adc1_range = STV090x_ADC_1Vpp, | ||
255 | .adc2_range = STV090x_ADC_1Vpp, | ||
256 | |||
257 | .diseqc_envelope_mode = true, | ||
258 | |||
259 | .tuner_i2c_lock = cineS2_tuner_i2c_lock, | ||
154 | }; | 260 | }; |
155 | 261 | ||
156 | static struct stv6110x_config tuner_cineS2_0 = { | 262 | static struct stv6110x_config tuner_cineS2_0 = { |
@@ -175,7 +281,8 @@ static struct ngene_info ngene_info_cineS2 = { | |||
175 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, | 281 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, |
176 | .lnb = {0x0b, 0x08}, | 282 | .lnb = {0x0b, 0x08}, |
177 | .tsf = {3, 3}, | 283 | .tsf = {3, 3}, |
178 | .fw_version = 15, | 284 | .fw_version = 18, |
285 | .msi_supported = true, | ||
179 | }; | 286 | }; |
180 | 287 | ||
181 | static struct ngene_info ngene_info_satixS2 = { | 288 | static struct ngene_info ngene_info_satixS2 = { |
@@ -188,46 +295,51 @@ static struct ngene_info ngene_info_satixS2 = { | |||
188 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, | 295 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, |
189 | .lnb = {0x0b, 0x08}, | 296 | .lnb = {0x0b, 0x08}, |
190 | .tsf = {3, 3}, | 297 | .tsf = {3, 3}, |
191 | .fw_version = 15, | 298 | .fw_version = 18, |
299 | .msi_supported = true, | ||
192 | }; | 300 | }; |
193 | 301 | ||
194 | static struct ngene_info ngene_info_satixS2v2 = { | 302 | static struct ngene_info ngene_info_satixS2v2 = { |
195 | .type = NGENE_SIDEWINDER, | 303 | .type = NGENE_SIDEWINDER, |
196 | .name = "Mystique SaTiX-S2 Dual (v2)", | 304 | .name = "Mystique SaTiX-S2 Dual (v2)", |
197 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, | 305 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN}, |
198 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, | 306 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe}, |
199 | .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, | 307 | .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110}, |
200 | .fe_config = {&fe_cineS2, &fe_cineS2}, | 308 | .fe_config = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2}, |
201 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, | 309 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1}, |
202 | .lnb = {0x0a, 0x08}, | 310 | .lnb = {0x0a, 0x08, 0x0b, 0x09}, |
203 | .tsf = {3, 3}, | 311 | .tsf = {3, 3}, |
204 | .fw_version = 15, | 312 | .fw_version = 18, |
313 | .msi_supported = true, | ||
205 | }; | 314 | }; |
206 | 315 | ||
207 | static struct ngene_info ngene_info_cineS2v5 = { | 316 | static struct ngene_info ngene_info_cineS2v5 = { |
208 | .type = NGENE_SIDEWINDER, | 317 | .type = NGENE_SIDEWINDER, |
209 | .name = "Linux4Media cineS2 DVB-S2 Twin Tuner (v5)", | 318 | .name = "Linux4Media cineS2 DVB-S2 Twin Tuner (v5)", |
210 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, | 319 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN}, |
211 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, | 320 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe}, |
212 | .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, | 321 | .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110}, |
213 | .fe_config = {&fe_cineS2, &fe_cineS2}, | 322 | .fe_config = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2}, |
214 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, | 323 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1}, |
215 | .lnb = {0x0a, 0x08}, | 324 | .lnb = {0x0a, 0x08, 0x0b, 0x09}, |
216 | .tsf = {3, 3}, | 325 | .tsf = {3, 3}, |
217 | .fw_version = 15, | 326 | .fw_version = 18, |
327 | .msi_supported = true, | ||
218 | }; | 328 | }; |
219 | 329 | ||
330 | |||
220 | static struct ngene_info ngene_info_duoFlexS2 = { | 331 | static struct ngene_info ngene_info_duoFlexS2 = { |
221 | .type = NGENE_SIDEWINDER, | 332 | .type = NGENE_SIDEWINDER, |
222 | .name = "Digital Devices DuoFlex S2 miniPCIe", | 333 | .name = "Digital Devices DuoFlex S2 miniPCIe", |
223 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, | 334 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN}, |
224 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, | 335 | .demod_attach = {cineS2_probe, cineS2_probe, cineS2_probe, cineS2_probe}, |
225 | .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, | 336 | .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110}, |
226 | .fe_config = {&fe_cineS2, &fe_cineS2}, | 337 | .fe_config = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2}, |
227 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, | 338 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1}, |
228 | .lnb = {0x0a, 0x08}, | 339 | .lnb = {0x0a, 0x08, 0x0b, 0x09}, |
229 | .tsf = {3, 3}, | 340 | .tsf = {3, 3}, |
230 | .fw_version = 15, | 341 | .fw_version = 18, |
342 | .msi_supported = true, | ||
231 | }; | 343 | }; |
232 | 344 | ||
233 | static struct ngene_info ngene_info_m780 = { | 345 | static struct ngene_info ngene_info_m780 = { |