blob: 9c59f4306883a6de666052c613896b850313b8d0 [file] [log] [blame]
Johannes Stezenbach2add87a2005-05-16 21:54:10 -07001/*
Patrick Boettcherd66b94b2009-05-20 05:08:26 -03002 * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
3 * flexcop-fe-tuner.c - methods for frontend attachment and DiSEqC controlling
4 * see flexcop.c for copyright information
Johannes Stezenbach2add87a2005-05-16 21:54:10 -07005 */
Michael Krufky827855d2008-04-22 14:46:16 -03006#include <media/tuner.h>
Johannes Stezenbach2add87a2005-05-16 21:54:10 -07007#include "flexcop.h"
Johannes Stezenbach2add87a2005-05-16 21:54:10 -07008#include "mt312.h"
Patrick Boettcherd66b94b2009-05-20 05:08:26 -03009#include "stv0299.h"
Patrick Boettcherca19aaa2008-04-13 15:49:22 -030010#include "s5h1420.h"
11#include "itd1000.h"
Patrick Boettcherc9dd82c2008-03-29 21:28:07 -030012#include "cx24113.h"
Patrick Boettcherd66b94b2009-05-20 05:08:26 -030013#include "cx24123.h"
Patrick Boettcherc9dd82c2008-03-29 21:28:07 -030014#include "isl6421.h"
Jemma Denson5afc9a22015-04-14 09:04:50 -030015#include "cx24120.h"
Patrick Boettcherd66b94b2009-05-20 05:08:26 -030016#include "mt352.h"
17#include "bcm3510.h"
18#include "nxt200x.h"
19#include "dvb-pll.h"
20#include "lgdt330x.h"
21#include "tuner-simple.h"
22#include "stv0297.h"
Patrick Boettcherc9dd82c2008-03-29 21:28:07 -030023
Trent Piepho68b7f762009-06-11 19:31:22 -030024
25/* Can we use the specified front-end? Remember that if we are compiled
26 * into the kernel we can't call code that's in modules. */
27#define FE_SUPPORTED(fe) (defined(CONFIG_DVB_##fe) || \
28 (defined(CONFIG_DVB_##fe##_MODULE) && defined(MODULE)))
29
Jemma Denson4b7574f2015-05-21 06:29:23 -030030#if FE_SUPPORTED(BCM3510) || (FE_SUPPORTED(CX24120) && FE_SUPPORTED(ISL6421))
Jemma Denson5afc9a22015-04-14 09:04:50 -030031static int flexcop_fe_request_firmware(struct dvb_frontend *fe,
32 const struct firmware **fw, char *name)
33{
34 struct flexcop_device *fc = fe->dvb->priv;
35
36 return request_firmware(fw, name, fc->dev);
37}
38#endif
39
Johannes Stezenbach2add87a2005-05-16 21:54:10 -070040/* lnb control */
Trent Piepho68b7f762009-06-11 19:31:22 -030041#if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299)
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -030042static int flexcop_set_voltage(struct dvb_frontend *fe,
43 enum fe_sec_voltage voltage)
Johannes Stezenbach2add87a2005-05-16 21:54:10 -070044{
45 struct flexcop_device *fc = fe->dvb->priv;
46 flexcop_ibi_value v;
47 deb_tuner("polarity/voltage = %u\n", voltage);
48
49 v = fc->read_ibi_reg(fc, misc_204);
50 switch (voltage) {
Patrick Boettcherd66b94b2009-05-20 05:08:26 -030051 case SEC_VOLTAGE_OFF:
52 v.misc_204.ACPI1_sig = 1;
53 break;
54 case SEC_VOLTAGE_13:
55 v.misc_204.ACPI1_sig = 0;
56 v.misc_204.LNB_L_H_sig = 0;
57 break;
58 case SEC_VOLTAGE_18:
59 v.misc_204.ACPI1_sig = 0;
60 v.misc_204.LNB_L_H_sig = 1;
61 break;
62 default:
63 err("unknown SEC_VOLTAGE value");
64 return -EINVAL;
Johannes Stezenbach2add87a2005-05-16 21:54:10 -070065 }
66 return fc->write_ibi_reg(fc, misc_204, v);
67}
Patrick Boettcherd66b94b2009-05-20 05:08:26 -030068#endif
Johannes Stezenbach2add87a2005-05-16 21:54:10 -070069
Trent Piepho68b7f762009-06-11 19:31:22 -030070#if FE_SUPPORTED(S5H1420) || FE_SUPPORTED(STV0299) || FE_SUPPORTED(MT312)
Johannes Stezenbach2add87a2005-05-16 21:54:10 -070071static int flexcop_sleep(struct dvb_frontend* fe)
72{
73 struct flexcop_device *fc = fe->dvb->priv;
Johannes Stezenbach2add87a2005-05-16 21:54:10 -070074 if (fc->fe_sleep)
75 return fc->fe_sleep(fe);
Johannes Stezenbach2add87a2005-05-16 21:54:10 -070076 return 0;
77}
Patrick Boettcherd66b94b2009-05-20 05:08:26 -030078#endif
Johannes Stezenbach2add87a2005-05-16 21:54:10 -070079
Patrick Boettcherd66b94b2009-05-20 05:08:26 -030080/* SkyStar2 DVB-S rev 2.3 */
Trent Piepho016e53d2009-06-11 19:31:22 -030081#if FE_SUPPORTED(MT312) && FE_SUPPORTED(PLL)
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -030082static int flexcop_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
Johannes Stezenbach2add87a2005-05-16 21:54:10 -070083{
Patrick Boettcherd66b94b2009-05-20 05:08:26 -030084/* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */
Johannes Stezenbach2add87a2005-05-16 21:54:10 -070085 struct flexcop_device *fc = fe->dvb->priv;
86 flexcop_ibi_value v;
87 u16 ax;
88 v.raw = 0;
Johannes Stezenbach2add87a2005-05-16 21:54:10 -070089 deb_tuner("tone = %u\n",tone);
90
91 switch (tone) {
Patrick Boettcherd66b94b2009-05-20 05:08:26 -030092 case SEC_TONE_ON:
93 ax = 0x01ff;
94 break;
95 case SEC_TONE_OFF:
96 ax = 0;
97 break;
98 default:
99 err("unknown SEC_TONE value");
100 return -EINVAL;
Johannes Stezenbach2add87a2005-05-16 21:54:10 -0700101 }
102
103 v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */
Johannes Stezenbach958706c2005-05-16 21:54:19 -0700104 v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax;
105 v.lnb_switch_freq_200.LNB_CTLLowCount_sig = ax == 0 ? 0x1ff : ax;
Johannes Stezenbach2add87a2005-05-16 21:54:10 -0700106 return fc->write_ibi_reg(fc,lnb_switch_freq_200,v);
107}
108
109static void flexcop_diseqc_send_bit(struct dvb_frontend* fe, int data)
110{
111 flexcop_set_tone(fe, SEC_TONE_ON);
112 udelay(data ? 500 : 1000);
113 flexcop_set_tone(fe, SEC_TONE_OFF);
114 udelay(data ? 1000 : 500);
115}
116
117static void flexcop_diseqc_send_byte(struct dvb_frontend* fe, int data)
118{
119 int i, par = 1, d;
Johannes Stezenbach2add87a2005-05-16 21:54:10 -0700120 for (i = 7; i >= 0; i--) {
121 d = (data >> i) & 1;
122 par ^= d;
123 flexcop_diseqc_send_bit(fe, d);
124 }
Johannes Stezenbach2add87a2005-05-16 21:54:10 -0700125 flexcop_diseqc_send_bit(fe, par);
126}
127
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300128static int flexcop_send_diseqc_msg(struct dvb_frontend *fe,
129 int len, u8 *msg, unsigned long burst)
Johannes Stezenbach2add87a2005-05-16 21:54:10 -0700130{
131 int i;
132
133 flexcop_set_tone(fe, SEC_TONE_OFF);
134 mdelay(16);
135
136 for (i = 0; i < len; i++)
137 flexcop_diseqc_send_byte(fe,msg[i]);
Johannes Stezenbach2add87a2005-05-16 21:54:10 -0700138 mdelay(16);
139
140 if (burst != -1) {
141 if (burst)
142 flexcop_diseqc_send_byte(fe, 0xff);
143 else {
144 flexcop_set_tone(fe, SEC_TONE_ON);
Thierry MERLEc4e3fd92008-09-01 17:32:10 -0300145 mdelay(12);
146 udelay(500);
Johannes Stezenbach2add87a2005-05-16 21:54:10 -0700147 flexcop_set_tone(fe, SEC_TONE_OFF);
148 }
149 msleep(20);
150 }
151 return 0;
152}
153
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300154static int flexcop_diseqc_send_master_cmd(struct dvb_frontend *fe,
155 struct dvb_diseqc_master_cmd *cmd)
Johannes Stezenbach2add87a2005-05-16 21:54:10 -0700156{
157 return flexcop_send_diseqc_msg(fe, cmd->msg_len, cmd->msg, 0);
158}
159
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300160static int flexcop_diseqc_send_burst(struct dvb_frontend *fe,
Mauro Carvalho Chehab0df289a2015-06-07 14:53:52 -0300161 enum fe_sec_mini_cmd minicmd)
Johannes Stezenbach2add87a2005-05-16 21:54:10 -0700162{
163 return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd);
164}
165
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300166static struct mt312_config skystar23_samsung_tbdu18132_config = {
167 .demod_address = 0x0e,
168};
Johannes Stezenbach2add87a2005-05-16 21:54:10 -0700169
Trent Piephoeccd15a2009-06-11 05:33:00 -0300170static int skystar2_rev23_attach(struct flexcop_device *fc,
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300171 struct i2c_adapter *i2c)
172{
Trent Piepho016e53d2009-06-11 19:31:22 -0300173 struct dvb_frontend_ops *ops;
174
Trent Piephoeccd15a2009-06-11 05:33:00 -0300175 fc->fe = dvb_attach(mt312_attach, &skystar23_samsung_tbdu18132_config, i2c);
Trent Piepho016e53d2009-06-11 19:31:22 -0300176 if (!fc->fe)
177 return 0;
178
179 if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, i2c,
180 DVB_PLL_SAMSUNG_TBDU18132))
181 return 0;
182
183 ops = &fc->fe->ops;
184 ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
185 ops->diseqc_send_burst = flexcop_diseqc_send_burst;
186 ops->set_tone = flexcop_set_tone;
187 ops->set_voltage = flexcop_set_voltage;
188 fc->fe_sleep = ops->sleep;
189 ops->sleep = flexcop_sleep;
190 return 1;
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300191}
Trent Piepho68b7f762009-06-11 19:31:22 -0300192#else
193#define skystar2_rev23_attach NULL
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300194#endif
Johannes Stezenbach2add87a2005-05-16 21:54:10 -0700195
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300196/* SkyStar2 DVB-S rev 2.6 */
Trent Piepho016e53d2009-06-11 19:31:22 -0300197#if FE_SUPPORTED(STV0299) && FE_SUPPORTED(PLL)
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300198static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe,
199 u32 srate, u32 ratio)
200{
201 u8 aclk = 0;
202 u8 bclk = 0;
203
204 if (srate < 1500000) {
205 aclk = 0xb7; bclk = 0x47;
206 } else if (srate < 3000000) {
207 aclk = 0xb7; bclk = 0x4b;
208 } else if (srate < 7000000) {
209 aclk = 0xb7; bclk = 0x4f;
210 } else if (srate < 14000000) {
211 aclk = 0xb7; bclk = 0x53;
212 } else if (srate < 30000000) {
213 aclk = 0xb6; bclk = 0x53;
214 } else if (srate < 45000000) {
215 aclk = 0xb4; bclk = 0x51;
216 }
217
218 stv0299_writereg(fe, 0x13, aclk);
219 stv0299_writereg(fe, 0x14, bclk);
220 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
221 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
222 stv0299_writereg(fe, 0x21, ratio & 0xf0);
223 return 0;
224}
225
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300226static u8 samsung_tbmu24112_inittab[] = {
227 0x01, 0x15,
228 0x02, 0x30,
229 0x03, 0x00,
230 0x04, 0x7D,
231 0x05, 0x35,
232 0x06, 0x02,
233 0x07, 0x00,
234 0x08, 0xC3,
235 0x0C, 0x00,
236 0x0D, 0x81,
237 0x0E, 0x23,
238 0x0F, 0x12,
239 0x10, 0x7E,
240 0x11, 0x84,
241 0x12, 0xB9,
242 0x13, 0x88,
243 0x14, 0x89,
244 0x15, 0xC9,
245 0x16, 0x00,
246 0x17, 0x5C,
247 0x18, 0x00,
248 0x19, 0x00,
249 0x1A, 0x00,
250 0x1C, 0x00,
251 0x1D, 0x00,
252 0x1E, 0x00,
253 0x1F, 0x3A,
254 0x20, 0x2E,
255 0x21, 0x80,
256 0x22, 0xFF,
257 0x23, 0xC1,
258 0x28, 0x00,
259 0x29, 0x1E,
260 0x2A, 0x14,
261 0x2B, 0x0F,
262 0x2C, 0x09,
263 0x2D, 0x05,
264 0x31, 0x1F,
265 0x32, 0x19,
266 0x33, 0xFE,
267 0x34, 0x93,
268 0xff, 0xff,
Johannes Stezenbach2add87a2005-05-16 21:54:10 -0700269};
270
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300271static struct stv0299_config samsung_tbmu24112_config = {
272 .demod_address = 0x68,
273 .inittab = samsung_tbmu24112_inittab,
274 .mclk = 88000000UL,
275 .invert = 0,
276 .skip_reinit = 0,
277 .lock_output = STV0299_LOCKOUTPUT_LK,
278 .volt13_op0_op1 = STV0299_VOLT13_OP1,
279 .min_delay_ms = 100,
280 .set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
281};
282
Trent Piephoeccd15a2009-06-11 05:33:00 -0300283static int skystar2_rev26_attach(struct flexcop_device *fc,
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300284 struct i2c_adapter *i2c)
285{
286 fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c);
Trent Piepho016e53d2009-06-11 19:31:22 -0300287 if (!fc->fe)
288 return 0;
289
290 if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, i2c,
291 DVB_PLL_SAMSUNG_TBMU24112))
292 return 0;
293
294 fc->fe->ops.set_voltage = flexcop_set_voltage;
295 fc->fe_sleep = fc->fe->ops.sleep;
296 fc->fe->ops.sleep = flexcop_sleep;
297 return 1;
298
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300299}
Trent Piepho68b7f762009-06-11 19:31:22 -0300300#else
301#define skystar2_rev26_attach NULL
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300302#endif
303
304/* SkyStar2 DVB-S rev 2.7 */
Trent Piepho68b7f762009-06-11 19:31:22 -0300305#if FE_SUPPORTED(S5H1420) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_ITD1000)
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300306static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
307 .demod_address = 0x53,
308 .invert = 1,
309 .repeated_start_workaround = 1,
310 .serial_mpeg = 1,
311};
312
313static struct itd1000_config skystar2_rev2_7_itd1000_config = {
314 .i2c_address = 0x61,
315};
316
Trent Piephoeccd15a2009-06-11 05:33:00 -0300317static int skystar2_rev27_attach(struct flexcop_device *fc,
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300318 struct i2c_adapter *i2c)
319{
Trent Piephoeccd15a2009-06-11 05:33:00 -0300320 flexcop_ibi_value r108;
321 struct i2c_adapter *i2c_tuner;
322
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300323 /* enable no_base_addr - no repeated start when reading */
324 fc->fc_i2c_adap[0].no_base_addr = 1;
Trent Piephoeccd15a2009-06-11 05:33:00 -0300325 fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config,
326 i2c);
327 if (!fc->fe)
328 goto fail;
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300329
Trent Piephoeccd15a2009-06-11 05:33:00 -0300330 i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe);
331 if (!i2c_tuner)
332 goto fail;
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300333
Trent Piephoeccd15a2009-06-11 05:33:00 -0300334 fc->fe_sleep = fc->fe->ops.sleep;
335 fc->fe->ops.sleep = flexcop_sleep;
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300336
Trent Piephoeccd15a2009-06-11 05:33:00 -0300337 /* enable no_base_addr - no repeated start when reading */
338 fc->fc_i2c_adap[2].no_base_addr = 1;
339 if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
Mauro Carvalho Chehab48a8a032013-04-05 12:18:54 -0300340 0x08, 1, 1, false)) {
Trent Piephoeccd15a2009-06-11 05:33:00 -0300341 err("ISL6421 could NOT be attached");
342 goto fail_isl;
343 }
344 info("ISL6421 successfully attached");
345
346 /* the ITD1000 requires a lower i2c clock - is it a problem ? */
347 r108.raw = 0x00000506;
348 fc->write_ibi_reg(fc, tw_sm_c_108, r108);
349 if (!dvb_attach(itd1000_attach, fc->fe, i2c_tuner,
350 &skystar2_rev2_7_itd1000_config)) {
351 err("ITD1000 could NOT be attached");
352 /* Should i2c clock be restored? */
353 goto fail_isl;
354 }
355 info("ITD1000 successfully attached");
356
357 return 1;
358
359fail_isl:
360 fc->fc_i2c_adap[2].no_base_addr = 0;
361fail:
362 /* for the next devices we need it again */
363 fc->fc_i2c_adap[0].no_base_addr = 0;
364 return 0;
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300365}
Trent Piepho68b7f762009-06-11 19:31:22 -0300366#else
367#define skystar2_rev27_attach NULL
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300368#endif
369
370/* SkyStar2 rev 2.8 */
Trent Piepho68b7f762009-06-11 19:31:22 -0300371#if FE_SUPPORTED(CX24123) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_CX24113)
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300372static struct cx24123_config skystar2_rev2_8_cx24123_config = {
373 .demod_address = 0x55,
374 .dont_use_pll = 1,
375 .agc_callback = cx24113_agc_callback,
376};
377
378static const struct cx24113_config skystar2_rev2_8_cx24113_config = {
379 .i2c_addr = 0x54,
380 .xtal_khz = 10111,
381};
382
Trent Piephoeccd15a2009-06-11 05:33:00 -0300383static int skystar2_rev28_attach(struct flexcop_device *fc,
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300384 struct i2c_adapter *i2c)
385{
Trent Piephoeccd15a2009-06-11 05:33:00 -0300386 struct i2c_adapter *i2c_tuner;
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300387
Trent Piephoeccd15a2009-06-11 05:33:00 -0300388 fc->fe = dvb_attach(cx24123_attach, &skystar2_rev2_8_cx24123_config,
389 i2c);
390 if (!fc->fe)
391 return 0;
392
Joe Perches1ebcad72009-07-02 15:57:09 -0300393 i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);
Trent Piephoeccd15a2009-06-11 05:33:00 -0300394 if (!i2c_tuner)
395 return 0;
396
397 if (!dvb_attach(cx24113_attach, fc->fe, &skystar2_rev2_8_cx24113_config,
398 i2c_tuner)) {
399 err("CX24113 could NOT be attached");
400 return 0;
401 }
402 info("CX24113 successfully attached");
403
404 fc->fc_i2c_adap[2].no_base_addr = 1;
405 if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
Mauro Carvalho Chehab48a8a032013-04-05 12:18:54 -0300406 0x08, 0, 0, false)) {
Trent Piephoeccd15a2009-06-11 05:33:00 -0300407 err("ISL6421 could NOT be attached");
408 fc->fc_i2c_adap[2].no_base_addr = 0;
409 return 0;
410 }
411 info("ISL6421 successfully attached");
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300412 /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an
413 * IR-receiver (PIC16F818) - but the card has no input for that ??? */
Trent Piephoeccd15a2009-06-11 05:33:00 -0300414 return 1;
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300415}
Trent Piepho68b7f762009-06-11 19:31:22 -0300416#else
417#define skystar2_rev28_attach NULL
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300418#endif
419
420/* AirStar DVB-T */
Trent Piepho6d67c972009-06-11 19:31:22 -0300421#if FE_SUPPORTED(MT352) && FE_SUPPORTED(PLL)
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300422static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe)
423{
424 static u8 mt352_clock_config[] = { 0x89, 0x18, 0x2d };
425 static u8 mt352_reset[] = { 0x50, 0x80 };
426 static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 };
427 static u8 mt352_agc_cfg[] = { 0x67, 0x28, 0xa1 };
428 static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
429
430 mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
431 udelay(2000);
432 mt352_write(fe, mt352_reset, sizeof(mt352_reset));
433 mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
434 mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
435 mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
436 return 0;
437}
438
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300439static struct mt352_config samsung_tdtc9251dh0_config = {
440 .demod_address = 0x0f,
441 .demod_init = samsung_tdtc9251dh0_demod_init,
442};
443
Trent Piephoeccd15a2009-06-11 05:33:00 -0300444static int airstar_dvbt_attach(struct flexcop_device *fc,
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300445 struct i2c_adapter *i2c)
446{
447 fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
Trent Piepho6d67c972009-06-11 19:31:22 -0300448 if (!fc->fe)
449 return 0;
450
451 return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL,
452 DVB_PLL_SAMSUNG_TDTC9251DH0);
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300453}
Trent Piepho68b7f762009-06-11 19:31:22 -0300454#else
455#define airstar_dvbt_attach NULL
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300456#endif
457
458/* AirStar ATSC 1st generation */
Trent Piepho68b7f762009-06-11 19:31:22 -0300459#if FE_SUPPORTED(BCM3510)
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300460static struct bcm3510_config air2pc_atsc_first_gen_config = {
461 .demod_address = 0x0f,
462 .request_firmware = flexcop_fe_request_firmware,
463};
464
Trent Piephoeccd15a2009-06-11 05:33:00 -0300465static int airstar_atsc1_attach(struct flexcop_device *fc,
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300466 struct i2c_adapter *i2c)
467{
468 fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
Trent Piephoeccd15a2009-06-11 05:33:00 -0300469 return fc->fe != NULL;
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300470}
Trent Piepho68b7f762009-06-11 19:31:22 -0300471#else
472#define airstar_atsc1_attach NULL
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300473#endif
474
475/* AirStar ATSC 2nd generation */
Trent Piepho68b7f762009-06-11 19:31:22 -0300476#if FE_SUPPORTED(NXT200X) && FE_SUPPORTED(PLL)
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300477static struct nxt200x_config samsung_tbmv_config = {
478 .demod_address = 0x0a,
479};
480
Trent Piephoeccd15a2009-06-11 05:33:00 -0300481static int airstar_atsc2_attach(struct flexcop_device *fc,
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300482 struct i2c_adapter *i2c)
483{
484 fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c);
Trent Piephoeccd15a2009-06-11 05:33:00 -0300485 if (!fc->fe)
486 return 0;
487
488 return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL,
489 DVB_PLL_SAMSUNG_TBMV);
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300490}
Trent Piepho68b7f762009-06-11 19:31:22 -0300491#else
492#define airstar_atsc2_attach NULL
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300493#endif
494
495/* AirStar ATSC 3rd generation */
Trent Piepho68b7f762009-06-11 19:31:22 -0300496#if FE_SUPPORTED(LGDT330X)
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300497static struct lgdt330x_config air2pc_atsc_hd5000_config = {
498 .demod_address = 0x59,
499 .demod_chip = LGDT3303,
500 .serial_mpeg = 0x04,
501 .clock_polarity_flip = 1,
502};
503
Trent Piephoeccd15a2009-06-11 05:33:00 -0300504static int airstar_atsc3_attach(struct flexcop_device *fc,
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300505 struct i2c_adapter *i2c)
506{
507 fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c);
Trent Piephoeccd15a2009-06-11 05:33:00 -0300508 if (!fc->fe)
509 return 0;
510
511 return !!dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
512 TUNER_LG_TDVS_H06XF);
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300513}
Trent Piepho68b7f762009-06-11 19:31:22 -0300514#else
515#define airstar_atsc3_attach NULL
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300516#endif
517
518/* CableStar2 DVB-C */
Trent Piepho7a6fbd82009-06-11 19:31:22 -0300519#if FE_SUPPORTED(STV0297) && FE_SUPPORTED(PLL)
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700520static u8 alps_tdee4_stv0297_inittab[] = {
521 0x80, 0x01,
522 0x80, 0x00,
523 0x81, 0x01,
524 0x81, 0x00,
Antti Seppälä9d85d772006-12-20 11:10:35 -0300525 0x00, 0x48,
526 0x01, 0x58,
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700527 0x03, 0x00,
528 0x04, 0x00,
529 0x07, 0x00,
530 0x08, 0x00,
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700531 0x30, 0xff,
Antti Seppälä9d85d772006-12-20 11:10:35 -0300532 0x31, 0x9d,
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700533 0x32, 0xff,
534 0x33, 0x00,
Antti Seppälä9d85d772006-12-20 11:10:35 -0300535 0x34, 0x29,
536 0x35, 0x55,
537 0x36, 0x80,
538 0x37, 0x6e,
539 0x38, 0x9c,
540 0x40, 0x1a,
541 0x41, 0xfe,
542 0x42, 0x33,
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700543 0x43, 0x00,
544 0x44, 0xff,
545 0x45, 0x00,
546 0x46, 0x00,
547 0x49, 0x04,
Antti Seppälä9d85d772006-12-20 11:10:35 -0300548 0x4a, 0x51,
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700549 0x4b, 0xf8,
550 0x52, 0x30,
Antti Seppälä9d85d772006-12-20 11:10:35 -0300551 0x53, 0x06,
552 0x59, 0x06,
553 0x5a, 0x5e,
554 0x5b, 0x04,
555 0x61, 0x49,
556 0x62, 0x0a,
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700557 0x70, 0xff,
Antti Seppälä9d85d772006-12-20 11:10:35 -0300558 0x71, 0x04,
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700559 0x72, 0x00,
560 0x73, 0x00,
561 0x74, 0x0c,
Antti Seppälä9d85d772006-12-20 11:10:35 -0300562 0x80, 0x20,
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700563 0x81, 0x00,
Antti Seppälä9d85d772006-12-20 11:10:35 -0300564 0x82, 0x30,
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700565 0x83, 0x00,
566 0x84, 0x04,
Antti Seppälä9d85d772006-12-20 11:10:35 -0300567 0x85, 0x22,
568 0x86, 0x08,
569 0x87, 0x1b,
570 0x88, 0x00,
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700571 0x89, 0x00,
Antti Seppälä9d85d772006-12-20 11:10:35 -0300572 0x90, 0x00,
573 0x91, 0x04,
574 0xa0, 0x86,
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700575 0xa1, 0x00,
576 0xa2, 0x00,
577 0xb0, 0x91,
578 0xb1, 0x0b,
Antti Seppälä9d85d772006-12-20 11:10:35 -0300579 0xc0, 0x5b,
580 0xc1, 0x10,
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700581 0xc2, 0x12,
Antti Seppälä9d85d772006-12-20 11:10:35 -0300582 0xd0, 0x02,
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700583 0xd1, 0x00,
584 0xd2, 0x00,
585 0xd3, 0x00,
Antti Seppälä9d85d772006-12-20 11:10:35 -0300586 0xd4, 0x02,
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700587 0xd5, 0x00,
588 0xde, 0x00,
Antti Seppälä9d85d772006-12-20 11:10:35 -0300589 0xdf, 0x01,
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700590 0xff, 0xff,
591};
592
Johannes Stezenbach2add87a2005-05-16 21:54:10 -0700593static struct stv0297_config alps_tdee4_stv0297_config = {
594 .demod_address = 0x1c,
Andrew de Quinceydc27a162005-09-09 13:03:07 -0700595 .inittab = alps_tdee4_stv0297_inittab,
Johannes Stezenbach2add87a2005-05-16 21:54:10 -0700596};
597
Trent Piephoeccd15a2009-06-11 05:33:00 -0300598static int cablestar2_attach(struct flexcop_device *fc,
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300599 struct i2c_adapter *i2c)
Johannes Stezenbach2add87a2005-05-16 21:54:10 -0700600{
Antti Seppälä11c6c7f2008-12-01 06:59:37 -0300601 fc->fc_i2c_adap[0].no_base_addr = 1;
Patrick Boettcher6394cf52008-03-29 20:49:57 -0300602 fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c);
Trent Piepho7a6fbd82009-06-11 19:31:22 -0300603 if (!fc->fe)
604 goto fail;
605
606 /* This tuner doesn't use the stv0297's I2C gate, but instead the
607 * tuner is connected to a different flexcop I2C adapter. */
608 if (fc->fe->ops.i2c_gate_ctrl)
609 fc->fe->ops.i2c_gate_ctrl(fc->fe, 0);
610 fc->fe->ops.i2c_gate_ctrl = NULL;
611
612 if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61,
613 &fc->fc_i2c_adap[2].i2c_adap, DVB_PLL_TDEE4))
614 goto fail;
615
Trent Piephoeccd15a2009-06-11 05:33:00 -0300616 return 1;
Trent Piepho7a6fbd82009-06-11 19:31:22 -0300617
618fail:
619 /* Reset for next frontend to try */
620 fc->fc_i2c_adap[0].no_base_addr = 0;
621 return 0;
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300622}
Trent Piepho68b7f762009-06-11 19:31:22 -0300623#else
624#define cablestar2_attach NULL
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300625#endif
626
Jemma Denson5afc9a22015-04-14 09:04:50 -0300627/* SkyStar S2 PCI DVB-S/S2 card based on Conexant cx24120/cx24118 */
628#if FE_SUPPORTED(CX24120) && FE_SUPPORTED(ISL6421)
629static const struct cx24120_config skystar2_rev3_3_cx24120_config = {
630 .i2c_addr = 0x55,
631 .xtal_khz = 10111,
632 .initial_mpeg_config = { 0xa1, 0x76, 0x07 },
633 .request_firmware = flexcop_fe_request_firmware,
Patrick Boettcherf7a77eb2015-04-28 02:47:42 -0300634 .i2c_wr_max = 4,
Jemma Denson5afc9a22015-04-14 09:04:50 -0300635};
636
637static int skystarS2_rev33_attach(struct flexcop_device *fc,
638 struct i2c_adapter *i2c)
639{
640 fc->fe = dvb_attach(cx24120_attach,
Jemma Densoncf4f8112015-05-15 15:40:29 -0300641 &skystar2_rev3_3_cx24120_config, i2c);
642 if (!fc->fe)
Jemma Denson5afc9a22015-04-14 09:04:50 -0300643 return 0;
644
645 fc->dev_type = FC_SKYS2_REV33;
646 fc->fc_i2c_adap[2].no_base_addr = 1;
Jemma Densoncf4f8112015-05-15 15:40:29 -0300647 if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
648 0x08, 0, 0, false)) {
Jemma Denson5afc9a22015-04-14 09:04:50 -0300649 err("ISL6421 could NOT be attached!");
Jemma Densoncf4f8112015-05-15 15:40:29 -0300650 fc->fc_i2c_adap[2].no_base_addr = 0;
Jemma Denson5afc9a22015-04-14 09:04:50 -0300651 return 0;
652 }
653 info("ISL6421 successfully attached.");
654
Jemma Densond3525b62015-05-30 15:10:06 -0300655 if (fc->has_32_hw_pid_filter)
656 fc->skip_6_hw_pid_filter = 1;
657
Jemma Denson5afc9a22015-04-14 09:04:50 -0300658 return 1;
659}
660#else
661#define skystarS2_rev33_attach NULL
662#endif
663
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300664static struct {
665 flexcop_device_type_t type;
Trent Piephoeccd15a2009-06-11 05:33:00 -0300666 int (*attach)(struct flexcop_device *, struct i2c_adapter *);
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300667} flexcop_frontends[] = {
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300668 { FC_SKY_REV27, skystar2_rev27_attach },
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300669 { FC_SKY_REV28, skystar2_rev28_attach },
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300670 { FC_SKY_REV26, skystar2_rev26_attach },
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300671 { FC_AIR_DVBT, airstar_dvbt_attach },
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300672 { FC_AIR_ATSC2, airstar_atsc2_attach },
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300673 { FC_AIR_ATSC3, airstar_atsc3_attach },
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300674 { FC_AIR_ATSC1, airstar_atsc1_attach },
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300675 { FC_CABLE, cablestar2_attach },
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300676 { FC_SKY_REV23, skystar2_rev23_attach },
Jemma Denson5afc9a22015-04-14 09:04:50 -0300677 { FC_SKYS2_REV33, skystarS2_rev33_attach },
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300678};
679
680/* try to figure out the frontend */
681int flexcop_frontend_init(struct flexcop_device *fc)
682{
683 int i;
684 for (i = 0; i < ARRAY_SIZE(flexcop_frontends); i++) {
Trent Piepho68b7f762009-06-11 19:31:22 -0300685 if (!flexcop_frontends[i].attach)
686 continue;
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300687 /* type needs to be set before, because of some workarounds
688 * done based on the probed card type */
689 fc->dev_type = flexcop_frontends[i].type;
Trent Piephoeccd15a2009-06-11 05:33:00 -0300690 if (flexcop_frontends[i].attach(fc, &fc->fc_i2c_adap[0].i2c_adap))
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300691 goto fe_found;
Trent Piephoeccd15a2009-06-11 05:33:00 -0300692 /* Clean up partially attached frontend */
693 if (fc->fe) {
694 dvb_frontend_detach(fc->fe);
695 fc->fe = NULL;
696 }
Patrick Boettcher6394cf52008-03-29 20:49:57 -0300697 }
Patrick Boettcherd66b94b2009-05-20 05:08:26 -0300698 fc->dev_type = FC_UNK;
Patrick Boettcher6394cf52008-03-29 20:49:57 -0300699 err("no frontend driver found for this B2C2/FlexCop adapter");
700 return -ENODEV;
701
702fe_found:
703 info("found '%s' .", fc->fe->ops.info.name);
704 if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
705 err("frontend registration failed!");
Trent Piephoeccd15a2009-06-11 05:33:00 -0300706 dvb_frontend_detach(fc->fe);
Patrick Boettcher6394cf52008-03-29 20:49:57 -0300707 fc->fe = NULL;
708 return -EINVAL;
Johannes Stezenbach2add87a2005-05-16 21:54:10 -0700709 }
710 fc->init_state |= FC_STATE_FE_INIT;
711 return 0;
712}
713
714void flexcop_frontend_exit(struct flexcop_device *fc)
715{
Andrew de Quincey2bfe0312006-08-08 09:10:08 -0300716 if (fc->init_state & FC_STATE_FE_INIT) {
Johannes Stezenbach2add87a2005-05-16 21:54:10 -0700717 dvb_unregister_frontend(fc->fe);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -0300718 dvb_frontend_detach(fc->fe);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -0300719 }
Johannes Stezenbach2add87a2005-05-16 21:54:10 -0700720 fc->init_state &= ~FC_STATE_FE_INIT;
721}