aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick Boettcher <pb@linuxtv.org>2009-05-20 04:08:26 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-06-16 17:21:09 -0400
commitd66b94b4aa2f40e134f8c07c58ae74ef3d523ee0 (patch)
tree697b3a45c678df570ca1be56426c3b4b84874b05
parent302e8acc4137821cd30514da3d91ac109b461c7d (diff)
V4L/DVB (11829): Rewrote frontend-attach mechanism to gain noise-less deactivation of submodules
This patch is reorganizing the frontend-attach mechanism in order to gain noise-less (superflous prints) deactivation of submodules. Credits go to Uwe Bugla for helping to clean and test the code. Signed-off-by: Uwe Bugla <uwe.bugla@gmx.de> Signed-off-by: Patrick Boettcher <pb@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/dvb/b2c2/flexcop-common.h8
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c760
2 files changed, 413 insertions, 355 deletions
diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h
index 3e1c472092ab..9e2148a19967 100644
--- a/drivers/media/dvb/b2c2/flexcop-common.h
+++ b/drivers/media/dvb/b2c2/flexcop-common.h
@@ -1,9 +1,7 @@
1/* 1/*
2 * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III 2 * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
3 * 3 * flexcop-common.h - common header file for device-specific source files
4 * flexcop-common.h - common header file for device-specific source files also. 4 * see flexcop.c for copyright information
5 *
6 * see flexcop.c for copyright information.
7 */ 5 */
8#ifndef __FLEXCOP_COMMON_H__ 6#ifndef __FLEXCOP_COMMON_H__
9#define __FLEXCOP_COMMON_H__ 7#define __FLEXCOP_COMMON_H__
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index f7afab5944cf..3f485bf13121 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -1,34 +1,27 @@
1/* 1/*
2 * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III 2 * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
3 * 3 * flexcop-fe-tuner.c - methods for frontend attachment and DiSEqC controlling
4 * flexcop-fe-tuner.c - methods for attaching a frontend and controlling DiSEqC. 4 * see flexcop.c for copyright information
5 *
6 * see flexcop.c for copyright information.
7 */ 5 */
8#include <media/tuner.h> 6#include <media/tuner.h>
9
10#include "flexcop.h" 7#include "flexcop.h"
11
12#include "stv0299.h"
13#include "mt352.h"
14#include "nxt200x.h"
15#include "bcm3510.h"
16#include "stv0297.h"
17#include "mt312.h" 8#include "mt312.h"
18#include "lgdt330x.h" 9#include "stv0299.h"
19#include "dvb-pll.h"
20#include "tuner-simple.h"
21
22#include "s5h1420.h" 10#include "s5h1420.h"
23#include "itd1000.h" 11#include "itd1000.h"
24
25#include "cx24123.h"
26#include "cx24113.h" 12#include "cx24113.h"
27 13#include "cx24123.h"
28#include "isl6421.h" 14#include "isl6421.h"
15#include "mt352.h"
16#include "bcm3510.h"
17#include "nxt200x.h"
18#include "dvb-pll.h"
19#include "lgdt330x.h"
20#include "tuner-simple.h"
21#include "stv0297.h"
29 22
30/* lnb control */ 23/* lnb control */
31 24#if defined(CONFIG_DVB_MT312_MODULE) || defined(CONFIG_DVB_STV0299_MODULE)
32static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) 25static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
33{ 26{
34 struct flexcop_device *fc = fe->dvb->priv; 27 struct flexcop_device *fc = fe->dvb->priv;
@@ -37,65 +30,62 @@ static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage
37 30
38 v = fc->read_ibi_reg(fc, misc_204); 31 v = fc->read_ibi_reg(fc, misc_204);
39 switch (voltage) { 32 switch (voltage) {
40 case SEC_VOLTAGE_OFF: 33 case SEC_VOLTAGE_OFF:
41 v.misc_204.ACPI1_sig = 1; 34 v.misc_204.ACPI1_sig = 1;
42 break; 35 break;
43 case SEC_VOLTAGE_13: 36 case SEC_VOLTAGE_13:
44 v.misc_204.ACPI1_sig = 0; 37 v.misc_204.ACPI1_sig = 0;
45 v.misc_204.LNB_L_H_sig = 0; 38 v.misc_204.LNB_L_H_sig = 0;
46 break; 39 break;
47 case SEC_VOLTAGE_18: 40 case SEC_VOLTAGE_18:
48 v.misc_204.ACPI1_sig = 0; 41 v.misc_204.ACPI1_sig = 0;
49 v.misc_204.LNB_L_H_sig = 1; 42 v.misc_204.LNB_L_H_sig = 1;
50 break; 43 break;
51 default: 44 default:
52 err("unknown SEC_VOLTAGE value"); 45 err("unknown SEC_VOLTAGE value");
53 return -EINVAL; 46 return -EINVAL;
54 } 47 }
55 return fc->write_ibi_reg(fc, misc_204, v); 48 return fc->write_ibi_reg(fc, misc_204, v);
56} 49}
50#endif
57 51
52#if defined(CONFIG_DVB_S5H1420_MODULE) || defined(CONFIG_DVB_STV0299_MODULE) \
53 || defined(CONFIG_DVB_MT312_MODULE)
58static int flexcop_sleep(struct dvb_frontend* fe) 54static int flexcop_sleep(struct dvb_frontend* fe)
59{ 55{
60 struct flexcop_device *fc = fe->dvb->priv; 56 struct flexcop_device *fc = fe->dvb->priv;
61/* flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204); */
62
63 if (fc->fe_sleep) 57 if (fc->fe_sleep)
64 return fc->fe_sleep(fe); 58 return fc->fe_sleep(fe);
65
66/* v.misc_204.ACPI3_sig = 1;
67 fc->write_ibi_reg(fc,misc_204,v);*/
68
69 return 0; 59 return 0;
70} 60}
61#endif
71 62
63/* SkyStar2 DVB-S rev 2.3 */
64#if defined(CONFIG_DVB_MT312_MODULE)
72static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) 65static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
73{ 66{
74 /* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */ 67/* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */
75 struct flexcop_device *fc = fe->dvb->priv; 68 struct flexcop_device *fc = fe->dvb->priv;
76 flexcop_ibi_value v; 69 flexcop_ibi_value v;
77 u16 ax; 70 u16 ax;
78 v.raw = 0; 71 v.raw = 0;
79
80 deb_tuner("tone = %u\n",tone); 72 deb_tuner("tone = %u\n",tone);
81 73
82 switch (tone) { 74 switch (tone) {
83 case SEC_TONE_ON: 75 case SEC_TONE_ON:
84 ax = 0x01ff; 76 ax = 0x01ff;
85 break; 77 break;
86 case SEC_TONE_OFF: 78 case SEC_TONE_OFF:
87 ax = 0; 79 ax = 0;
88 break; 80 break;
89 default: 81 default:
90 err("unknown SEC_TONE value"); 82 err("unknown SEC_TONE value");
91 return -EINVAL; 83 return -EINVAL;
92 } 84 }
93 85
94 v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */ 86 v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */
95
96 v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax; 87 v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax;
97 v.lnb_switch_freq_200.LNB_CTLLowCount_sig = ax == 0 ? 0x1ff : ax; 88 v.lnb_switch_freq_200.LNB_CTLLowCount_sig = ax == 0 ? 0x1ff : ax;
98
99 return fc->write_ibi_reg(fc,lnb_switch_freq_200,v); 89 return fc->write_ibi_reg(fc,lnb_switch_freq_200,v);
100} 90}
101 91
@@ -110,17 +100,16 @@ static void flexcop_diseqc_send_bit(struct dvb_frontend* fe, int data)
110static void flexcop_diseqc_send_byte(struct dvb_frontend* fe, int data) 100static void flexcop_diseqc_send_byte(struct dvb_frontend* fe, int data)
111{ 101{
112 int i, par = 1, d; 102 int i, par = 1, d;
113
114 for (i = 7; i >= 0; i--) { 103 for (i = 7; i >= 0; i--) {
115 d = (data >> i) & 1; 104 d = (data >> i) & 1;
116 par ^= d; 105 par ^= d;
117 flexcop_diseqc_send_bit(fe, d); 106 flexcop_diseqc_send_bit(fe, d);
118 } 107 }
119
120 flexcop_diseqc_send_bit(fe, par); 108 flexcop_diseqc_send_bit(fe, par);
121} 109}
122 110
123static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, unsigned long burst) 111static int flexcop_send_diseqc_msg(struct dvb_frontend *fe,
112 int len, u8 *msg, unsigned long burst)
124{ 113{
125 int i; 114 int i;
126 115
@@ -129,7 +118,6 @@ static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, un
129 118
130 for (i = 0; i < len; i++) 119 for (i = 0; i < len; i++)
131 flexcop_diseqc_send_byte(fe,msg[i]); 120 flexcop_diseqc_send_byte(fe,msg[i]);
132
133 mdelay(16); 121 mdelay(16);
134 122
135 if (burst != -1) { 123 if (burst != -1) {
@@ -146,50 +134,110 @@ static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, un
146 return 0; 134 return 0;
147} 135}
148 136
149static int flexcop_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) 137static int flexcop_diseqc_send_master_cmd(struct dvb_frontend *fe,
138 struct dvb_diseqc_master_cmd *cmd)
150{ 139{
151 return flexcop_send_diseqc_msg(fe, cmd->msg_len, cmd->msg, 0); 140 return flexcop_send_diseqc_msg(fe, cmd->msg_len, cmd->msg, 0);
152} 141}
153 142
154static int flexcop_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) 143static int flexcop_diseqc_send_burst(struct dvb_frontend *fe,
144 fe_sec_mini_cmd_t minicmd)
155{ 145{
156 return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd); 146 return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd);
157} 147}
158 148
159/* dvb-s stv0299 */ 149static struct mt312_config skystar23_samsung_tbdu18132_config = {
160static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) 150 .demod_address = 0x0e,
151};
152
153static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend *fe,
154 struct dvb_frontend_parameters *params)
155{
156 u8 buf[4];
157 u32 div;
158 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf,
159 .len = sizeof(buf) };
160 struct flexcop_device *fc = fe->dvb->priv;
161 div = (params->frequency + (125/2)) / 125;
162
163 buf[0] = (div >> 8) & 0x7f;
164 buf[1] = (div >> 0) & 0xff;
165 buf[2] = 0x84 | ((div >> 10) & 0x60);
166 buf[3] = 0x80;
167
168 if (params->frequency < 1550000)
169 buf[3] |= 0x02;
170
171 if (fe->ops.i2c_gate_ctrl)
172 fe->ops.i2c_gate_ctrl(fe, 1);
173 if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
174 return -EIO;
175 return 0;
176}
177
178static void skystar2_rev23_attach(struct flexcop_device *fc,
179 struct i2c_adapter *i2c)
180{
181 fc->fe = dvb_attach(mt312_attach,
182 &skystar23_samsung_tbdu18132_config, i2c);
183 if (fc->fe != NULL) {
184 struct dvb_frontend_ops *ops = &fc->fe->ops;
185 ops->tuner_ops.set_params \
186 = skystar23_samsung_tbdu18132_tuner_set_params;
187 ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
188 ops->diseqc_send_burst = flexcop_diseqc_send_burst;
189 ops->set_tone = flexcop_set_tone;
190 ops->set_voltage = flexcop_set_voltage;
191 fc->fe_sleep = ops->sleep;
192 ops->sleep = flexcop_sleep;
193 fc->dev_type = FC_SKY_REV23;
194 }
195}
196#endif
197
198/* SkyStar2 DVB-S rev 2.6 */
199#if defined(CONFIG_DVB_STV0299_MODULE)
200static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe,
201 u32 srate, u32 ratio)
161{ 202{
162 u8 aclk = 0; 203 u8 aclk = 0;
163 u8 bclk = 0; 204 u8 bclk = 0;
164 205
165 if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } 206 if (srate < 1500000) {
166 else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } 207 aclk = 0xb7; bclk = 0x47;
167 else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } 208 } else if (srate < 3000000) {
168 else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } 209 aclk = 0xb7; bclk = 0x4b;
169 else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } 210 } else if (srate < 7000000) {
170 else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } 211 aclk = 0xb7; bclk = 0x4f;
171 212 } else if (srate < 14000000) {
172 stv0299_writereg (fe, 0x13, aclk); 213 aclk = 0xb7; bclk = 0x53;
173 stv0299_writereg (fe, 0x14, bclk); 214 } else if (srate < 30000000) {
174 stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); 215 aclk = 0xb6; bclk = 0x53;
175 stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); 216 } else if (srate < 45000000) {
176 stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); 217 aclk = 0xb4; bclk = 0x51;
218 }
177 219
220 stv0299_writereg(fe, 0x13, aclk);
221 stv0299_writereg(fe, 0x14, bclk);
222 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
223 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
224 stv0299_writereg(fe, 0x21, ratio & 0xf0);
178 return 0; 225 return 0;
179} 226}
180 227
181static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) 228static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend *fe,
229 struct dvb_frontend_parameters *params)
182{ 230{
183 u8 buf[4]; 231 u8 buf[4];
184 u32 div; 232 u32 div;
185 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; 233 struct i2c_msg msg = {
234 .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
186 struct flexcop_device *fc = fe->dvb->priv; 235 struct flexcop_device *fc = fe->dvb->priv;
187
188 div = params->frequency / 125; 236 div = params->frequency / 125;
189 237
190 buf[0] = (div >> 8) & 0x7f; 238 buf[0] = (div >> 8) & 0x7f;
191 buf[1] = div & 0xff; 239 buf[1] = div & 0xff;
192 buf[2] = 0x84; /* 0xC4 */ 240 buf[2] = 0x84; /* 0xC4 */
193 buf[3] = 0x08; 241 buf[3] = 0x08;
194 242
195 if (params->frequency < 1500000) 243 if (params->frequency < 1500000)
@@ -203,48 +251,48 @@ static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dv
203} 251}
204 252
205static u8 samsung_tbmu24112_inittab[] = { 253static u8 samsung_tbmu24112_inittab[] = {
206 0x01, 0x15, 254 0x01, 0x15,
207 0x02, 0x30, 255 0x02, 0x30,
208 0x03, 0x00, 256 0x03, 0x00,
209 0x04, 0x7D, 257 0x04, 0x7D,
210 0x05, 0x35, 258 0x05, 0x35,
211 0x06, 0x02, 259 0x06, 0x02,
212 0x07, 0x00, 260 0x07, 0x00,
213 0x08, 0xC3, 261 0x08, 0xC3,
214 0x0C, 0x00, 262 0x0C, 0x00,
215 0x0D, 0x81, 263 0x0D, 0x81,
216 0x0E, 0x23, 264 0x0E, 0x23,
217 0x0F, 0x12, 265 0x0F, 0x12,
218 0x10, 0x7E, 266 0x10, 0x7E,
219 0x11, 0x84, 267 0x11, 0x84,
220 0x12, 0xB9, 268 0x12, 0xB9,
221 0x13, 0x88, 269 0x13, 0x88,
222 0x14, 0x89, 270 0x14, 0x89,
223 0x15, 0xC9, 271 0x15, 0xC9,
224 0x16, 0x00, 272 0x16, 0x00,
225 0x17, 0x5C, 273 0x17, 0x5C,
226 0x18, 0x00, 274 0x18, 0x00,
227 0x19, 0x00, 275 0x19, 0x00,
228 0x1A, 0x00, 276 0x1A, 0x00,
229 0x1C, 0x00, 277 0x1C, 0x00,
230 0x1D, 0x00, 278 0x1D, 0x00,
231 0x1E, 0x00, 279 0x1E, 0x00,
232 0x1F, 0x3A, 280 0x1F, 0x3A,
233 0x20, 0x2E, 281 0x20, 0x2E,
234 0x21, 0x80, 282 0x21, 0x80,
235 0x22, 0xFF, 283 0x22, 0xFF,
236 0x23, 0xC1, 284 0x23, 0xC1,
237 0x28, 0x00, 285 0x28, 0x00,
238 0x29, 0x1E, 286 0x29, 0x1E,
239 0x2A, 0x14, 287 0x2A, 0x14,
240 0x2B, 0x0F, 288 0x2B, 0x0F,
241 0x2C, 0x09, 289 0x2C, 0x09,
242 0x2D, 0x05, 290 0x2D, 0x05,
243 0x31, 0x1F, 291 0x31, 0x1F,
244 0x32, 0x19, 292 0x32, 0x19,
245 0x33, 0xFE, 293 0x33, 0xFE,
246 0x34, 0x93, 294 0x34, 0x93,
247 0xff, 0xff, 295 0xff, 0xff,
248}; 296};
249 297
250static struct stv0299_config samsung_tbmu24112_config = { 298static struct stv0299_config samsung_tbmu24112_config = {
@@ -259,27 +307,136 @@ static struct stv0299_config samsung_tbmu24112_config = {
259 .set_symbol_rate = samsung_tbmu24112_set_symbol_rate, 307 .set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
260}; 308};
261 309
262/* dvb-t mt352 */ 310static void skystar2_rev26_attach(struct flexcop_device *fc,
263static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe) 311 struct i2c_adapter *i2c)
264{ 312{
265 static u8 mt352_clock_config [] = { 0x89, 0x18, 0x2d }; 313 fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c);
266 static u8 mt352_reset [] = { 0x50, 0x80 }; 314 if (fc->fe != NULL) {
267 static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 }; 315 struct dvb_frontend_ops *ops = &fc->fe->ops;
268 static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0xa1 }; 316 ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
317 ops->set_voltage = flexcop_set_voltage;
318 fc->fe_sleep = ops->sleep;
319 ops->sleep = flexcop_sleep;
320 }
321}
322#endif
323
324/* SkyStar2 DVB-S rev 2.7 */
325#if defined(CONFIG_DVB_S5H1420_MODULE)
326static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
327 .demod_address = 0x53,
328 .invert = 1,
329 .repeated_start_workaround = 1,
330 .serial_mpeg = 1,
331};
332
333static struct itd1000_config skystar2_rev2_7_itd1000_config = {
334 .i2c_address = 0x61,
335};
336
337static void skystar2_rev27_attach(struct flexcop_device *fc,
338 struct i2c_adapter *i2c)
339{
340 /* enable no_base_addr - no repeated start when reading */
341 fc->fc_i2c_adap[0].no_base_addr = 1;
342 fc->fe = dvb_attach(s5h1420_attach,
343 &skystar2_rev2_7_s5h1420_config, i2c);
344 if (fc->fe != NULL) {
345 flexcop_ibi_value r108;
346 struct i2c_adapter *i2c_tuner \
347 = s5h1420_get_tuner_i2c_adapter(fc->fe);
348 struct dvb_frontend_ops *ops = &fc->fe->ops;
349
350 fc->fe_sleep = ops->sleep;
351 ops->sleep = flexcop_sleep;
352
353 /* enable no_base_addr - no repeated start when reading */
354 fc->fc_i2c_adap[2].no_base_addr = 1;
355 if (dvb_attach(isl6421_attach, fc->fe,
356 &fc->fc_i2c_adap[2].i2c_adap, 0x08, 1, 1) == NULL)
357 err("ISL6421 could NOT be attached");
358 else
359 info("ISL6421 successfully attached");
360
361 /* the ITD1000 requires a lower i2c clock - is it a problem ? */
362 r108.raw = 0x00000506;
363 fc->write_ibi_reg(fc, tw_sm_c_108, r108);
364 if (i2c_tuner) {
365 if (dvb_attach(itd1000_attach, fc->fe, i2c_tuner,
366 &skystar2_rev2_7_itd1000_config) == NULL)
367 err("ITD1000 could NOT be attached");
368 else
369 info("ITD1000 successfully attached");
370 }
371 } else
372 fc->fc_i2c_adap[0].no_base_addr = 0;
373 /* for the next devices we need it again */
374}
375#endif
376
377/* SkyStar2 rev 2.8 */
378#if defined(CONFIG_DVB_CX24123_MODULE)
379static struct cx24123_config skystar2_rev2_8_cx24123_config = {
380 .demod_address = 0x55,
381 .dont_use_pll = 1,
382 .agc_callback = cx24113_agc_callback,
383};
384
385static const struct cx24113_config skystar2_rev2_8_cx24113_config = {
386 .i2c_addr = 0x54,
387 .xtal_khz = 10111,
388};
389
390static void skystar2_rev28_attach(struct flexcop_device *fc,
391 struct i2c_adapter *i2c)
392{
393 fc->fe = dvb_attach(cx24123_attach,
394 &skystar2_rev2_8_cx24123_config, i2c);
395 if (fc->fe != NULL) {
396 struct i2c_adapter *i2c_tuner \
397 = cx24123_get_tuner_i2c_adapter(fc->fe);
398 if (i2c_tuner != NULL) {
399 if (dvb_attach(cx24113_attach, fc->fe,
400 &skystar2_rev2_8_cx24113_config,
401 i2c_tuner) == NULL)
402 err("CX24113 could NOT be attached");
403 else
404 info("CX24113 successfully attached");
405 }
406
407 fc->fc_i2c_adap[2].no_base_addr = 1;
408 if (dvb_attach(isl6421_attach, fc->fe,
409 &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0) == NULL)
410 err("ISL6421 could NOT be attached");
411 else
412 info("ISL6421 successfully attached");
413 /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an
414 * IR-receiver (PIC16F818) - but the card has no input for that ??? */
415 }
416}
417#endif
418
419/* AirStar DVB-T */
420#if defined(CONFIG_DVB_MT352_MODULE)
421static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe)
422{
423 static u8 mt352_clock_config[] = { 0x89, 0x18, 0x2d };
424 static u8 mt352_reset[] = { 0x50, 0x80 };
425 static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 };
426 static u8 mt352_agc_cfg[] = { 0x67, 0x28, 0xa1 };
269 static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 }; 427 static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
270 428
271 mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); 429 mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
272 udelay(2000); 430 udelay(2000);
273 mt352_write(fe, mt352_reset, sizeof(mt352_reset)); 431 mt352_write(fe, mt352_reset, sizeof(mt352_reset));
274 mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); 432 mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
275
276 mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); 433 mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
277 mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg)); 434 mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
278
279 return 0; 435 return 0;
280} 436}
281 437
282static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len) 438static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend *fe,
439 struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len)
283{ 440{
284 u32 div; 441 u32 div;
285 unsigned char bs = 0; 442 unsigned char bs = 0;
@@ -287,19 +444,20 @@ static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend* fe, struct dvb_fro
287 if (buf_len < 5) 444 if (buf_len < 5)
288 return -EINVAL; 445 return -EINVAL;
289 446
290 #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ 447#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
291 div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; 448 div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
292 449 if (params->frequency >= 48000000 && params->frequency <= 154000000) \
293 if (params->frequency >= 48000000 && params->frequency <= 154000000) bs = 0x09; 450 bs = 0x09;
294 if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a; 451 if (params->frequency >= 161000000 && params->frequency <= 439000000) \
295 if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08; 452 bs = 0x0a;
453 if (params->frequency >= 447000000 && params->frequency <= 863000000) \
454 bs = 0x08;
296 455
297 pllbuf[0] = 0x61; 456 pllbuf[0] = 0x61;
298 pllbuf[1] = div >> 8; 457 pllbuf[1] = div >> 8;
299 pllbuf[2] = div & 0xff; 458 pllbuf[2] = div & 0xff;
300 pllbuf[3] = 0xcc; 459 pllbuf[3] = 0xcc;
301 pllbuf[4] = bs; 460 pllbuf[4] = bs;
302
303 return 5; 461 return 5;
304} 462}
305 463
@@ -308,70 +466,88 @@ static struct mt352_config samsung_tdtc9251dh0_config = {
308 .demod_init = samsung_tdtc9251dh0_demod_init, 466 .demod_init = samsung_tdtc9251dh0_demod_init,
309}; 467};
310 468
311static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) 469static void airstar_dvbt_attach(struct flexcop_device *fc,
470 struct i2c_adapter *i2c)
471{
472 fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
473 if (fc->fe != NULL)
474 fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
475}
476#endif
477
478/* AirStar ATSC 1st generation */
479#if defined(CONFIG_DVB_BCM3510_MODULE)
480static int flexcop_fe_request_firmware(struct dvb_frontend *fe,
481 const struct firmware **fw, char* name)
312{ 482{
313 struct flexcop_device *fc = fe->dvb->priv; 483 struct flexcop_device *fc = fe->dvb->priv;
314 return request_firmware(fw, name, fc->dev); 484 return request_firmware(fw, name, fc->dev);
315} 485}
316 486
317static struct lgdt330x_config air2pc_atsc_hd5000_config = {
318 .demod_address = 0x59,
319 .demod_chip = LGDT3303,
320 .serial_mpeg = 0x04,
321 .clock_polarity_flip = 1,
322};
323
324static struct nxt200x_config samsung_tbmv_config = {
325 .demod_address = 0x0a,
326};
327
328static struct bcm3510_config air2pc_atsc_first_gen_config = { 487static struct bcm3510_config air2pc_atsc_first_gen_config = {
329 .demod_address = 0x0f, 488 .demod_address = 0x0f,
330 .request_firmware = flexcop_fe_request_firmware, 489 .request_firmware = flexcop_fe_request_firmware,
331}; 490};
332 491
333static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) 492static void airstar_atsc1_attach(struct flexcop_device *fc,
493 struct i2c_adapter *i2c)
334{ 494{
335 u8 buf[4]; 495 fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
336 u32 div; 496}
337 struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; 497#endif
338 struct flexcop_device *fc = fe->dvb->priv;
339
340 div = (params->frequency + (125/2)) / 125;
341
342 buf[0] = (div >> 8) & 0x7f;
343 buf[1] = (div >> 0) & 0xff;
344 buf[2] = 0x84 | ((div >> 10) & 0x60);
345 buf[3] = 0x80;
346 498
347 if (params->frequency < 1550000) 499/* AirStar ATSC 2nd generation */
348 buf[3] |= 0x02; 500#if defined(CONFIG_DVB_NXT200X_MODULE)
501static struct nxt200x_config samsung_tbmv_config = {
502 .demod_address = 0x0a,
503};
349 504
350 if (fe->ops.i2c_gate_ctrl) 505static void airstar_atsc2_attach(struct flexcop_device *fc,
351 fe->ops.i2c_gate_ctrl(fe, 1); 506 struct i2c_adapter *i2c)
352 if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1) 507{
353 return -EIO; 508 fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c);
354 return 0; 509 if (fc->fe != NULL)
510 dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL,
511 DVB_PLL_SAMSUNG_TBMV);
355} 512}
513#endif
356 514
357static struct mt312_config skystar23_samsung_tbdu18132_config = { 515/* AirStar ATSC 3rd generation */
358 516#if defined(CONFIG_DVB_LGDT330X_MODULE)
359 .demod_address = 0x0e, 517static struct lgdt330x_config air2pc_atsc_hd5000_config = {
518 .demod_address = 0x59,
519 .demod_chip = LGDT3303,
520 .serial_mpeg = 0x04,
521 .clock_polarity_flip = 1,
360}; 522};
361 523
524static void airstar_atsc3_attach(struct flexcop_device *fc,
525 struct i2c_adapter *i2c)
526{
527 fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c);
528 if (fc->fe != NULL) {
529 dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
530 TUNER_LG_TDVS_H06XF);
531 }
532}
533#endif
534
535/* CableStar2 DVB-C */
536#if defined(CONFIG_DVB_STV0297_MODULE)
362static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe, 537static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
363 struct dvb_frontend_parameters *fep) 538 struct dvb_frontend_parameters *fep)
364{ 539{
365 struct flexcop_device *fc = fe->dvb->priv; 540 struct flexcop_device *fc = fe->dvb->priv;
366 u8 buf[4]; 541 u8 buf[4];
367 u16 div; 542 u16 div;
368 int ret; 543 int ret;
369 544
370/* 62.5 kHz * 10 */ 545/* 62.5 kHz * 10 */
371#define REF_FREQ 625 546#define REF_FREQ 625
372#define FREQ_OFFSET 36125 547#define FREQ_OFFSET 36125
373 548
374 div = ((fep->frequency/1000 + FREQ_OFFSET ) * 10) / REF_FREQ; // 4 MHz = 4000 KHz 549 div = ((fep->frequency/1000 + FREQ_OFFSET) * 10) / REF_FREQ;
550/* 4 MHz = 4000 KHz */
375 551
376 buf[0] = (u8)( div >> 8) & 0x7f; 552 buf[0] = (u8)( div >> 8) & 0x7f;
377 buf[1] = (u8) div & 0xff; 553 buf[1] = (u8) div & 0xff;
@@ -384,11 +560,11 @@ static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
384 * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95 */ 560 * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95 */
385 buf[2] = 0x95; 561 buf[2] = 0x95;
386 562
387// Range(MHz) C1 * RE RTS BS4 BS3 BS2 BS1 Byte 5 563/* Range(MHz) C1 * RE RTS BS4 BS3 BS2 BS1 Byte 5
388// 47 - 153 0 * 0 0 0 0 0 1 0x01 564 * 47 - 153 0 * 0 0 0 0 0 1 0x01
389// 153 - 430 0 * 0 0 0 0 1 0 0x02 565 * 153 - 430 0 * 0 0 0 0 1 0 0x02
390// 430 - 822 0 * 0 0 1 0 0 0 0x08 566 * 430 - 822 0 * 0 0 1 0 0 0 0x08
391// 822 - 862 1 * 0 0 1 0 0 0 0x88 567 * 822 - 862 1 * 0 0 1 0 0 0 0x88 */
392 568
393 if (fep->frequency <= 153000000) buf[3] = 0x01; 569 if (fep->frequency <= 153000000) buf[3] = 0x01;
394 else if (fep->frequency <= 430000000) buf[3] = 0x02; 570 else if (fep->frequency <= 430000000) buf[3] = 0x02;
@@ -397,11 +573,11 @@ static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
397 573
398 if (fe->ops.i2c_gate_ctrl) 574 if (fe->ops.i2c_gate_ctrl)
399 fe->ops.i2c_gate_ctrl(fe, 0); 575 fe->ops.i2c_gate_ctrl(fe, 0);
400 deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]); 576 deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n", fep->frequency,
577 buf[0], buf[1], buf[2], buf[3]);
401 ret = fc->i2c_request(&fc->fc_i2c_adap[2], 578 ret = fc->i2c_request(&fc->fc_i2c_adap[2],
402 FC_WRITE, 0x61, buf[0], &buf[1], 3); 579 FC_WRITE, 0x61, buf[0], &buf[1], 3);
403 deb_tuner("tuner write returned: %d\n",ret); 580 deb_tuner("tuner write returned: %d\n",ret);
404
405 return ret; 581 return ret;
406} 582}
407 583
@@ -481,190 +657,75 @@ static u8 alps_tdee4_stv0297_inittab[] = {
481static struct stv0297_config alps_tdee4_stv0297_config = { 657static struct stv0297_config alps_tdee4_stv0297_config = {
482 .demod_address = 0x1c, 658 .demod_address = 0x1c,
483 .inittab = alps_tdee4_stv0297_inittab, 659 .inittab = alps_tdee4_stv0297_inittab,
484// .invert = 1,
485// .pll_set = alps_tdee4_stv0297_pll_set,
486}; 660};
487 661
488 662static void cablestar2_attach(struct flexcop_device *fc,
489/* SkyStar2 rev2.7 (a/u) */ 663 struct i2c_adapter *i2c)
490static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
491 .demod_address = 0x53,
492 .invert = 1,
493 .repeated_start_workaround = 1,
494 .serial_mpeg = 1,
495};
496
497static struct itd1000_config skystar2_rev2_7_itd1000_config = {
498 .i2c_address = 0x61,
499};
500
501/* SkyStar2 rev2.8 */
502static struct cx24123_config skystar2_rev2_8_cx24123_config = {
503 .demod_address = 0x55,
504 .dont_use_pll = 1,
505 .agc_callback = cx24113_agc_callback,
506};
507
508static const struct cx24113_config skystar2_rev2_8_cx24113_config = {
509 .i2c_addr = 0x54,
510 .xtal_khz = 10111,
511};
512
513/* try to figure out the frontend, each card/box can have on of the following list */
514int flexcop_frontend_init(struct flexcop_device *fc)
515{ 664{
516 struct dvb_frontend_ops *ops;
517 struct i2c_adapter *i2c = &fc->fc_i2c_adap[0].i2c_adap;
518 struct i2c_adapter *i2c_tuner;
519
520 /* enable no_base_addr - no repeated start when reading */
521 fc->fc_i2c_adap[0].no_base_addr = 1;
522 fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config, i2c);
523 if (fc->fe != NULL) {
524 flexcop_ibi_value r108;
525 i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe);
526 ops = &fc->fe->ops;
527
528 fc->fe_sleep = ops->sleep;
529 ops->sleep = flexcop_sleep;
530
531 fc->dev_type = FC_SKY_REV27;
532
533 /* enable no_base_addr - no repeated start when reading */
534 fc->fc_i2c_adap[2].no_base_addr = 1;
535 if (dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, 0x08, 1, 1) == NULL)
536 err("ISL6421 could NOT be attached");
537 else
538 info("ISL6421 successfully attached");
539
540 /* the ITD1000 requires a lower i2c clock - it slows down the stuff for everyone - but is it a problem ? */
541 r108.raw = 0x00000506;
542 fc->write_ibi_reg(fc, tw_sm_c_108, r108);
543 if (i2c_tuner) {
544 if (dvb_attach(itd1000_attach, fc->fe, i2c_tuner, &skystar2_rev2_7_itd1000_config) == NULL)
545 err("ITD1000 could NOT be attached");
546 else
547 info("ITD1000 successfully attached");
548 }
549 goto fe_found;
550 }
551 fc->fc_i2c_adap[0].no_base_addr = 0; /* for the next devices we need it again */
552
553 /* try the sky v2.8 (cx24123, isl6421) */
554 fc->fe = dvb_attach(cx24123_attach,
555 &skystar2_rev2_8_cx24123_config, i2c);
556 if (fc->fe != NULL) {
557 i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);
558 if (i2c_tuner != NULL) {
559 if (dvb_attach(cx24113_attach, fc->fe,
560 &skystar2_rev2_8_cx24113_config,
561 i2c_tuner) == NULL)
562 err("CX24113 could NOT be attached");
563 else
564 info("CX24113 successfully attached");
565 }
566
567 fc->dev_type = FC_SKY_REV28;
568
569 fc->fc_i2c_adap[2].no_base_addr = 1;
570 if (dvb_attach(isl6421_attach, fc->fe,
571 &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0) == NULL)
572 err("ISL6421 could NOT be attached");
573 else
574 info("ISL6421 successfully attached");
575
576 /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an
577 * IR-receiver (PIC16F818) - but the card has no input for
578 * that ??? */
579
580 goto fe_found;
581 }
582
583 /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
584 fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c);
585 if (fc->fe != NULL) {
586 ops = &fc->fe->ops;
587
588 ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
589
590 ops->set_voltage = flexcop_set_voltage;
591
592 fc->fe_sleep = ops->sleep;
593 ops->sleep = flexcop_sleep;
594
595 fc->dev_type = FC_SKY_REV26;
596 goto fe_found;
597 }
598
599 /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
600 fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
601 if (fc->fe != NULL) {
602 fc->dev_type = FC_AIR_DVBT;
603 fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
604 goto fe_found;
605 }
606
607 /* try the air atsc 2nd generation (nxt2002) */
608 fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c);
609 if (fc->fe != NULL) {
610 fc->dev_type = FC_AIR_ATSC2;
611 dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, DVB_PLL_SAMSUNG_TBMV);
612 goto fe_found;
613 }
614
615 fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c);
616 if (fc->fe != NULL) {
617 fc->dev_type = FC_AIR_ATSC3;
618 dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
619 TUNER_LG_TDVS_H06XF);
620 goto fe_found;
621 }
622
623 /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
624 fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
625 if (fc->fe != NULL) {
626 fc->dev_type = FC_AIR_ATSC1;
627 goto fe_found;
628 }
629
630 /* try the cable dvb (stv0297) */
631 fc->fc_i2c_adap[0].no_base_addr = 1; 665 fc->fc_i2c_adap[0].no_base_addr = 1;
632 fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c); 666 fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c);
633 if (fc->fe != NULL) { 667 if (fc->fe != NULL)
634 fc->dev_type = FC_CABLE; 668 fc->fe->ops.tuner_ops.set_params \
635 fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params; 669 = alps_tdee4_stv0297_tuner_set_params;
636 goto fe_found; 670 else
637 } 671 fc->fc_i2c_adap[0].no_base_addr = 0;
638 fc->fc_i2c_adap[0].no_base_addr = 0; 672}
639 673#endif
640 /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */ 674
641 fc->fe = dvb_attach(mt312_attach, 675static struct {
642 &skystar23_samsung_tbdu18132_config, i2c); 676 flexcop_device_type_t type;
643 if (fc->fe != NULL) { 677 void (*attach)(struct flexcop_device *, struct i2c_adapter *);
644 ops = &fc->fe->ops; 678} flexcop_frontends[] = {
645 679#if defined(CONFIG_DVB_S5H1420_MODULE)
646 ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params; 680 { FC_SKY_REV27, skystar2_rev27_attach },
647 681#endif
648 ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; 682#if defined(CONFIG_DVB_CX24123_MODULE)
649 ops->diseqc_send_burst = flexcop_diseqc_send_burst; 683 { FC_SKY_REV28, skystar2_rev28_attach },
650 ops->set_tone = flexcop_set_tone; 684#endif
651 ops->set_voltage = flexcop_set_voltage; 685#if defined(CONFIG_DVB_STV0299_MODULE)
652 686 { FC_SKY_REV26, skystar2_rev26_attach },
653 fc->fe_sleep = ops->sleep; 687#endif
654 ops->sleep = flexcop_sleep; 688#if defined(CONFIG_DVB_MT352_MODULE)
689 { FC_AIR_DVBT, airstar_dvbt_attach },
690#endif
691#if defined(CONFIG_DVB_NXT200X_MODULE)
692 { FC_AIR_ATSC2, airstar_atsc2_attach },
693#endif
694#if defined(CONFIG_DVB_LGDT330X_MODULE)
695 { FC_AIR_ATSC3, airstar_atsc3_attach },
696#endif
697#if defined(CONFIG_DVB_BCM3510_MODULE)
698 { FC_AIR_ATSC1, airstar_atsc1_attach },
699#endif
700#if defined(CONFIG_DVB_STV0297_MODULE)
701 { FC_CABLE, cablestar2_attach },
702#endif
703#if defined(CONFIG_DVB_MT312_MODULE)
704 { FC_SKY_REV23, skystar2_rev23_attach },
705#endif
706};
655 707
656 fc->dev_type = FC_SKY_REV23; 708/* try to figure out the frontend */
657 goto fe_found; 709int flexcop_frontend_init(struct flexcop_device *fc)
710{
711 int i;
712 for (i = 0; i < ARRAY_SIZE(flexcop_frontends); i++) {
713 /* type needs to be set before, because of some workarounds
714 * done based on the probed card type */
715 fc->dev_type = flexcop_frontends[i].type;
716 flexcop_frontends[i].attach(fc, &fc->fc_i2c_adap[0].i2c_adap);
717 if (fc->fe != NULL)
718 goto fe_found;
658 } 719 }
659 720 fc->dev_type = FC_UNK;
660 err("no frontend driver found for this B2C2/FlexCop adapter"); 721 err("no frontend driver found for this B2C2/FlexCop adapter");
661 return -ENODEV; 722 return -ENODEV;
662 723
663fe_found: 724fe_found:
664 info("found '%s' .", fc->fe->ops.info.name); 725 info("found '%s' .", fc->fe->ops.info.name);
665 if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) { 726 if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
727 struct dvb_frontend_ops *ops = &fc->fe->ops;
666 err("frontend registration failed!"); 728 err("frontend registration failed!");
667 ops = &fc->fe->ops;
668 if (ops->release != NULL) 729 if (ops->release != NULL)
669 ops->release(fc->fe); 730 ops->release(fc->fe);
670 fc->fe = NULL; 731 fc->fe = NULL;
@@ -680,6 +741,5 @@ void flexcop_frontend_exit(struct flexcop_device *fc)
680 dvb_unregister_frontend(fc->fe); 741 dvb_unregister_frontend(fc->fe);
681 dvb_frontend_detach(fc->fe); 742 dvb_frontend_detach(fc->fe);
682 } 743 }
683
684 fc->init_state &= ~FC_STATE_FE_INIT; 744 fc->init_state &= ~FC_STATE_FE_INIT;
685} 745}