aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/ngene
diff options
context:
space:
mode:
authorRalph Metzler <rmetzler@digitaldevices.de>2011-07-03 12:55:06 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-07-27 16:55:42 -0400
commit9ca9efb077505b5b717fc15eab33c44d17eb76f7 (patch)
treef6718f8aaab45032a4c6559274d7c27b2367fe60 /drivers/media/dvb/ngene
parentf9004df79ffd361312d4b5d237d56c2f64caa1a3 (diff)
[media] ngene: Support Digital Devices DuoFlex CT
Support Digital Devices DuoFlex CT with ngene. Signed-off-by: Ralph Metzler <rmetzler@digitaldevices.de> Signed-off-by: Oliver Endriss <o.endriss@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/ngene')
-rw-r--r--drivers/media/dvb/ngene/Kconfig2
-rw-r--r--drivers/media/dvb/ngene/ngene-cards.c176
-rw-r--r--drivers/media/dvb/ngene/ngene-core.c15
-rw-r--r--drivers/media/dvb/ngene/ngene.h3
4 files changed, 156 insertions, 40 deletions
diff --git a/drivers/media/dvb/ngene/Kconfig b/drivers/media/dvb/ngene/Kconfig
index cec242b7c00d..64c84702ba5c 100644
--- a/drivers/media/dvb/ngene/Kconfig
+++ b/drivers/media/dvb/ngene/Kconfig
@@ -5,6 +5,8 @@ config DVB_NGENE
5 select DVB_STV6110x if !DVB_FE_CUSTOMISE 5 select DVB_STV6110x if !DVB_FE_CUSTOMISE
6 select DVB_STV090x if !DVB_FE_CUSTOMISE 6 select DVB_STV090x if !DVB_FE_CUSTOMISE
7 select DVB_LGDT330X if !DVB_FE_CUSTOMISE 7 select DVB_LGDT330X if !DVB_FE_CUSTOMISE
8 select DVB_DRXK if !DVB_FE_CUSTOMISE
9 select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
8 select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE 10 select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
9 ---help--- 11 ---help---
10 Support for Micronas PCI express cards with nGene bridge. 12 Support for Micronas PCI express cards with nGene bridge.
diff --git a/drivers/media/dvb/ngene/ngene-cards.c b/drivers/media/dvb/ngene/ngene-cards.c
index fcf4be901ec8..ca2e146f1b8f 100644
--- a/drivers/media/dvb/ngene/ngene-cards.c
+++ b/drivers/media/dvb/ngene/ngene-cards.c
@@ -40,6 +40,7 @@
40#include "lnbh24.h" 40#include "lnbh24.h"
41#include "lgdt330x.h" 41#include "lgdt330x.h"
42#include "mt2131.h" 42#include "mt2131.h"
43#include "drxk.h"
43 44
44 45
45/****************************************************************************/ 46/****************************************************************************/
@@ -83,6 +84,52 @@ static int tuner_attach_stv6110(struct ngene_channel *chan)
83} 84}
84 85
85 86
87static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
88{
89 struct ngene_channel *chan = fe->sec_priv;
90 int status;
91
92 if (enable) {
93 down(&chan->dev->pll_mutex);
94 status = chan->gate_ctrl(fe, 1);
95 } else {
96 status = chan->gate_ctrl(fe, 0);
97 up(&chan->dev->pll_mutex);
98 }
99 return status;
100}
101
102struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
103 struct i2c_adapter *i2c, u8 adr);
104
105static int tuner_attach_tda18271(struct ngene_channel *chan)
106{
107 struct i2c_adapter *i2c;
108 struct dvb_frontend *fe;
109
110 i2c = &chan->dev->channel[0].i2c_adapter;
111 if (chan->fe->ops.i2c_gate_ctrl)
112 chan->fe->ops.i2c_gate_ctrl(chan->fe, 1);
113 fe = dvb_attach(tda18271c2dd_attach, chan->fe, i2c, 0x60);
114 if (chan->fe->ops.i2c_gate_ctrl)
115 chan->fe->ops.i2c_gate_ctrl(chan->fe, 0);
116 if (!fe) {
117 printk("No TDA18271 found!\n");
118 return -ENODEV;
119 }
120
121 return 0;
122}
123
124static int tuner_attach_probe(struct ngene_channel *chan)
125{
126 if (chan->demod_type == 0)
127 return tuner_attach_stv6110(chan);
128 if (chan->demod_type == 1)
129 return tuner_attach_tda18271(chan);
130 return -EINVAL;
131}
132
86static int demod_attach_stv0900(struct ngene_channel *chan) 133static int demod_attach_stv0900(struct ngene_channel *chan)
87{ 134{
88 struct i2c_adapter *i2c; 135 struct i2c_adapter *i2c;
@@ -130,6 +177,60 @@ static void cineS2_tuner_i2c_lock(struct dvb_frontend *fe, int lock)
130 up(&chan->dev->pll_mutex); 177 up(&chan->dev->pll_mutex);
131} 178}
132 179
180static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
181{
182 struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD,
183 .buf = val, .len = 1 }};
184 return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
185}
186
187static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
188 u16 reg, u8 *val)
189{
190 u8 msg[2] = {reg>>8, reg&0xff};
191 struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
192 .buf = msg, .len = 2},
193 {.addr = adr, .flags = I2C_M_RD,
194 .buf = val, .len = 1}};
195 return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
196}
197
198static int port_has_stv0900(struct i2c_adapter *i2c, int port)
199{
200 u8 val;
201 if (i2c_read_reg16(i2c, 0x68+port/2, 0xf100, &val) < 0)
202 return 0;
203 return 1;
204}
205
206static int port_has_drxk(struct i2c_adapter *i2c, int port)
207{
208 u8 val;
209
210 if (i2c_read(i2c, 0x29+port, &val) < 0)
211 return 0;
212 printk("DRXK@%02x\n", 0x29+port);
213 return 1;
214}
215
216static int demod_attach_drxk(struct ngene_channel *chan,
217 struct i2c_adapter *i2c)
218{
219 struct dvb_frontend *fe;
220
221 chan->fe = fe = dvb_attach(drxk_attach,
222 i2c, 0x29 + (chan->number^2),
223 &chan->fe2);
224 if (!chan->fe) {
225 printk("No DRXK found!\n");
226 return -ENODEV;
227 }
228 fe->sec_priv = chan;
229 chan->gate_ctrl = fe->ops.i2c_gate_ctrl;
230 fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
231 return 0;
232}
233
133static int cineS2_probe(struct ngene_channel *chan) 234static int cineS2_probe(struct ngene_channel *chan)
134{ 235{
135 struct i2c_adapter *i2c; 236 struct i2c_adapter *i2c;
@@ -144,43 +245,42 @@ static int cineS2_probe(struct ngene_channel *chan)
144 else 245 else
145 i2c = &chan->dev->channel[1].i2c_adapter; 246 i2c = &chan->dev->channel[1].i2c_adapter;
146 247
147 fe_conf = chan->dev->card_info->fe_config[chan->number]; 248 if (port_has_stv0900(i2c, chan->number)) {
148 i2c_msg.addr = fe_conf->address; 249 chan->demod_type=0;
149 250 fe_conf = chan->dev->card_info->fe_config[chan->number];
150 /* probe demod */ 251 /* demod found, attach it */
151 i2c_msg.len = 2; 252 rc = demod_attach_stv0900(chan);
152 buf[0] = 0xf1; 253 if (rc < 0 || chan->number < 2)
153 buf[1] = 0x00; 254 return rc;
154 rc = i2c_transfer(i2c, &i2c_msg, 1); 255
155 if (rc != 1) 256 /* demod #2: reprogram outputs DPN1 & DPN2 */
156 return -ENODEV; 257 i2c_msg.addr = fe_conf->address;
157 258 i2c_msg.len = 3;
158 /* demod found, attach it */ 259 buf[0] = 0xf1;
159 rc = demod_attach_stv0900(chan); 260 switch (chan->number)
160 if (rc < 0 || chan->number < 2) 261 {
161 return rc; 262 case 2:
162 263 buf[1] = 0x5c;
163 /* demod #2: reprogram outputs DPN1 & DPN2 */ 264 buf[2] = 0xc2;
164 i2c_msg.len = 3; 265 break;
165 buf[0] = 0xf1; 266 case 3:
166 switch (chan->number) { 267 buf[1] = 0x61;
167 case 2: 268 buf[2] = 0xcc;
168 buf[1] = 0x5c; 269 break;
169 buf[2] = 0xc2; 270 default:
170 break; 271 return -ENODEV;
171 case 3: 272 }
172 buf[1] = 0x61; 273 rc = i2c_transfer(i2c, &i2c_msg, 1);
173 buf[2] = 0xcc; 274 if (rc != 1) {
174 break; 275 printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n");
175 default: 276 return -EIO;
176 return -ENODEV; 277 }
278 } else if (port_has_drxk(i2c, chan->number^2)) {
279 chan->demod_type=1;
280 demod_attach_drxk(chan, i2c);
281 } else {
282 printk("No demod found on chan %d\n", chan->number);
177 } 283 }
178 rc = i2c_transfer(i2c, &i2c_msg, 1);
179 if (rc != 1) {
180 printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n");
181 return -EIO;
182 }
183
184 return 0; 284 return 0;
185} 285}
186 286
@@ -337,7 +437,7 @@ static struct ngene_info ngene_info_duoFlexS2 = {
337 .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, 437 .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
338 NGENE_IO_TSOUT}, 438 NGENE_IO_TSOUT},
339 .demod_attach = {cineS2_probe, cineS2_probe, cineS2_probe, cineS2_probe}, 439 .demod_attach = {cineS2_probe, cineS2_probe, cineS2_probe, cineS2_probe},
340 .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110}, 440 .tuner_attach = {tuner_attach_probe, tuner_attach_probe, tuner_attach_probe, tuner_attach_probe},
341 .fe_config = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2}, 441 .fe_config = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
342 .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1}, 442 .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
343 .lnb = {0x0a, 0x08, 0x0b, 0x09}, 443 .lnb = {0x0a, 0x08, 0x0b, 0x09},
@@ -397,7 +497,7 @@ MODULE_DEVICE_TABLE(pci, ngene_id_tbl);
397/****************************************************************************/ 497/****************************************************************************/
398 498
399static pci_ers_result_t ngene_error_detected(struct pci_dev *dev, 499static pci_ers_result_t ngene_error_detected(struct pci_dev *dev,
400 enum pci_channel_state state) 500 enum pci_channel_state state)
401{ 501{
402 printk(KERN_ERR DEVICE_NAME ": PCI error\n"); 502 printk(KERN_ERR DEVICE_NAME ": PCI error\n");
403 if (state == pci_channel_io_perm_failure) 503 if (state == pci_channel_io_perm_failure)
diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c
index 6927c726ce35..c59bf5057a40 100644
--- a/drivers/media/dvb/ngene/ngene-core.c
+++ b/drivers/media/dvb/ngene/ngene-core.c
@@ -41,7 +41,7 @@
41 41
42#include "ngene.h" 42#include "ngene.h"
43 43
44static int one_adapter = 1; 44static int one_adapter = 0;
45module_param(one_adapter, int, 0444); 45module_param(one_adapter, int, 0444);
46MODULE_PARM_DESC(one_adapter, "Use only one adapter."); 46MODULE_PARM_DESC(one_adapter, "Use only one adapter.");
47 47
@@ -461,7 +461,7 @@ static u8 TSFeatureDecoderSetup[8 * 5] = {
461 0x42, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, 461 0x42, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,
462 0x40, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXH */ 462 0x40, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXH */
463 0x71, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXHser */ 463 0x71, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXHser */
464 0x72, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* S2ser */ 464 0x72, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* S2ser */
465 0x40, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* LGDT3303 */ 465 0x40, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* LGDT3303 */
466}; 466};
467 467
@@ -1443,6 +1443,9 @@ static void release_channel(struct ngene_channel *chan)
1443 chan->ci_dev = NULL; 1443 chan->ci_dev = NULL;
1444 } 1444 }
1445 1445
1446 if (chan->fe2) {
1447 dvb_unregister_frontend(chan->fe2);
1448 }
1446 if (chan->fe) { 1449 if (chan->fe) {
1447 dvb_unregister_frontend(chan->fe); 1450 dvb_unregister_frontend(chan->fe);
1448 dvb_frontend_detach(chan->fe); 1451 dvb_frontend_detach(chan->fe);
@@ -1534,6 +1537,14 @@ static int init_channel(struct ngene_channel *chan)
1534 goto err; 1537 goto err;
1535 chan->has_demux = true; 1538 chan->has_demux = true;
1536 } 1539 }
1540 if (chan->fe2) {
1541 if (dvb_register_frontend(adapter, chan->fe2) < 0)
1542 goto err;
1543 chan->fe2->tuner_priv=chan->fe->tuner_priv;
1544 memcpy(&chan->fe2->ops.tuner_ops,
1545 &chan->fe->ops.tuner_ops,
1546 sizeof(struct dvb_tuner_ops));
1547 }
1537 1548
1538 if (chan->has_demux) { 1549 if (chan->has_demux) {
1539 ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux", 1550 ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
diff --git a/drivers/media/dvb/ngene/ngene.h b/drivers/media/dvb/ngene/ngene.h
index 40fce9e3ae66..e8cd93deba5a 100644
--- a/drivers/media/dvb/ngene/ngene.h
+++ b/drivers/media/dvb/ngene/ngene.h
@@ -641,8 +641,11 @@ struct ngene_channel {
641 int mode; 641 int mode;
642 bool has_adapter; 642 bool has_adapter;
643 bool has_demux; 643 bool has_demux;
644 int demod_type;
645 int (*gate_ctrl)(struct dvb_frontend *, int);
644 646
645 struct dvb_frontend *fe; 647 struct dvb_frontend *fe;
648 struct dvb_frontend *fe2;
646 struct dmxdev dmxdev; 649 struct dmxdev dmxdev;
647 struct dvb_demux demux; 650 struct dvb_demux demux;
648 struct dvb_net dvbnet; 651 struct dvb_net dvbnet;