blob: 6de1aea02d5148f4c1b340141305eed68170c191 [file] [log] [blame]
Michael Krufky8ce47da2007-04-27 12:31:14 -03001/*
2 *
3 * (c) 2005 Hartmut Hackmann
4 * (c) 2007 Michael Krufky
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#include <linux/module.h>
Michael Krufky8ce47da2007-04-27 12:31:14 -030022#include <asm/types.h>
Michael Krufky746d97322007-08-25 19:08:45 -030023#include <linux/dvb/frontend.h>
24#include <linux/videodev2.h>
Michael Krufky8ce47da2007-04-27 12:31:14 -030025
26#include "tda827x.h"
27
28static int debug = 0;
Michael Krufky746d97322007-08-25 19:08:45 -030029module_param(debug, int, 0644);
30MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
31
Michael Krufky8ce47da2007-04-27 12:31:14 -030032#define dprintk(args...) \
33 do { \
34 if (debug) printk(KERN_DEBUG "tda827x: " args); \
35 } while (0)
36
37struct tda827x_priv {
38 int i2c_addr;
39 struct i2c_adapter *i2c_adap;
40 struct tda827x_config *cfg;
41 u32 frequency;
42 u32 bandwidth;
43};
44
45struct tda827x_data {
46 u32 lomax;
47 u8 spd;
48 u8 bs;
49 u8 bp;
50 u8 cp;
51 u8 gc3;
52 u8 div1p5;
53};
54
Michael Krufky746d97322007-08-25 19:08:45 -030055static const struct tda827x_data tda827x_table[] = {
Michael Krufky8ce47da2007-04-27 12:31:14 -030056 { .lomax = 62000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
57 { .lomax = 66000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
58 { .lomax = 76000000, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
59 { .lomax = 84000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
60 { .lomax = 93000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0},
61 { .lomax = 98000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0},
62 { .lomax = 109000000, .spd = 3, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
63 { .lomax = 123000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1},
64 { .lomax = 133000000, .spd = 2, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1},
65 { .lomax = 151000000, .spd = 2, .bs = 1, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
66 { .lomax = 154000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
67 { .lomax = 181000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 0, .div1p5 = 0},
68 { .lomax = 185000000, .spd = 2, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
69 { .lomax = 217000000, .spd = 2, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
70 { .lomax = 244000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1},
71 { .lomax = 265000000, .spd = 1, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1},
72 { .lomax = 302000000, .spd = 1, .bs = 1, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
73 { .lomax = 324000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
74 { .lomax = 370000000, .spd = 1, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
75 { .lomax = 454000000, .spd = 1, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
76 { .lomax = 493000000, .spd = 0, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1},
77 { .lomax = 530000000, .spd = 0, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1},
78 { .lomax = 554000000, .spd = 0, .bs = 1, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
79 { .lomax = 604000000, .spd = 0, .bs = 1, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
80 { .lomax = 696000000, .spd = 0, .bs = 2, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
81 { .lomax = 740000000, .spd = 0, .bs = 2, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0},
82 { .lomax = 820000000, .spd = 0, .bs = 3, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
83 { .lomax = 865000000, .spd = 0, .bs = 3, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0},
84 { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0}
85};
86
87static int tda827xo_set_params(struct dvb_frontend *fe,
88 struct dvb_frontend_parameters *params)
89{
90 struct tda827x_priv *priv = fe->tuner_priv;
91 u8 buf[14];
92
93 struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
94 .buf = buf, .len = sizeof(buf) };
95 int i, tuner_freq, if_freq;
96 u32 N;
97
Hartmut Hackmann9971f4f2007-03-23 21:00:07 -030098 dprintk("%s:\n", __FUNCTION__);
Michael Krufky8ce47da2007-04-27 12:31:14 -030099 switch (params->u.ofdm.bandwidth) {
100 case BANDWIDTH_6_MHZ:
101 if_freq = 4000000;
102 break;
103 case BANDWIDTH_7_MHZ:
104 if_freq = 4500000;
105 break;
106 default: /* 8 MHz or Auto */
107 if_freq = 5000000;
108 break;
109 }
110 tuner_freq = params->frequency + if_freq;
111
112 i = 0;
Michael Krufky746d97322007-08-25 19:08:45 -0300113 while (tda827x_table[i].lomax < tuner_freq) {
114 if (tda827x_table[i + 1].lomax == 0)
Michael Krufky8ce47da2007-04-27 12:31:14 -0300115 break;
116 i++;
117 }
118
Michael Krufky746d97322007-08-25 19:08:45 -0300119 N = ((tuner_freq + 125000) / 250000) << (tda827x_table[i].spd + 2);
Michael Krufky8ce47da2007-04-27 12:31:14 -0300120 buf[0] = 0;
121 buf[1] = (N>>8) | 0x40;
122 buf[2] = N & 0xff;
123 buf[3] = 0;
124 buf[4] = 0x52;
Michael Krufky746d97322007-08-25 19:08:45 -0300125 buf[5] = (tda827x_table[i].spd << 6) + (tda827x_table[i].div1p5 << 5) +
126 (tda827x_table[i].bs << 3) +
127 tda827x_table[i].bp;
128 buf[6] = (tda827x_table[i].gc3 << 4) + 0x8f;
Michael Krufky8ce47da2007-04-27 12:31:14 -0300129 buf[7] = 0xbf;
130 buf[8] = 0x2a;
131 buf[9] = 0x05;
132 buf[10] = 0xff;
133 buf[11] = 0x00;
134 buf[12] = 0x00;
135 buf[13] = 0x40;
136
137 msg.len = 14;
138 if (fe->ops.i2c_gate_ctrl)
139 fe->ops.i2c_gate_ctrl(fe, 1);
140 if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
141 printk("%s: could not write to tuner at addr: 0x%02x\n",
142 __FUNCTION__, priv->i2c_addr << 1);
143 return -EIO;
144 }
145 msleep(500);
146 /* correct CP value */
147 buf[0] = 0x30;
Michael Krufky746d97322007-08-25 19:08:45 -0300148 buf[1] = 0x50 + tda827x_table[i].cp;
Michael Krufky8ce47da2007-04-27 12:31:14 -0300149 msg.len = 2;
150
151 if (fe->ops.i2c_gate_ctrl)
152 fe->ops.i2c_gate_ctrl(fe, 1);
153 i2c_transfer(priv->i2c_adap, &msg, 1);
154
155 priv->frequency = tuner_freq - if_freq; // FIXME
156 priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
157
158 return 0;
159}
160
161static int tda827xo_sleep(struct dvb_frontend *fe)
162{
163 struct tda827x_priv *priv = fe->tuner_priv;
164 static u8 buf[] = { 0x30, 0xd0 };
165 struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
166 .buf = buf, .len = sizeof(buf) };
167
Hartmut Hackmann9971f4f2007-03-23 21:00:07 -0300168 dprintk("%s:\n", __FUNCTION__);
Michael Krufky8ce47da2007-04-27 12:31:14 -0300169 if (fe->ops.i2c_gate_ctrl)
170 fe->ops.i2c_gate_ctrl(fe, 1);
171 i2c_transfer(priv->i2c_adap, &msg, 1);
172
173 if (priv->cfg && priv->cfg->sleep)
174 priv->cfg->sleep(fe);
175
176 return 0;
177}
178
179/* ------------------------------------------------------------------ */
180
Michael Krufky746d97322007-08-25 19:08:45 -0300181static int tda827xo_set_analog_params(struct dvb_frontend *fe,
182 struct analog_parameters *params)
183{
184 unsigned char tuner_reg[8];
185 unsigned char reg2[2];
186 u32 N;
187 int i;
188 struct tda827x_priv *priv = fe->tuner_priv;
189 struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0 };
190 unsigned int freq = params->frequency;
191
192 if (params->mode == V4L2_TUNER_RADIO)
193 freq = freq / 1000;
194
195 N = freq + priv->cfg->sgIF;
196
197 i = 0;
198 while (tda827x_table[i].lomax < N * 62500) {
199 if (tda827x_table[i + 1].lomax == 0)
200 break;
201 i++;
202 }
203
204 N = N << tda827x_table[i].spd;
205
206 tuner_reg[0] = 0;
207 tuner_reg[1] = (unsigned char)(N>>8);
208 tuner_reg[2] = (unsigned char) N;
209 tuner_reg[3] = 0x40;
210 tuner_reg[4] = 0x52 + (priv->cfg->tda827x_lpsel << 5);
211 tuner_reg[5] = (tda827x_table[i].spd << 6) +
212 (tda827x_table[i].div1p5 << 5) +
213 (tda827x_table[i].bs << 3) + tda827x_table[i].bp;
214 tuner_reg[6] = 0x8f + (tda827x_table[i].gc3 << 4);
215 tuner_reg[7] = 0x8f;
216
217 msg.buf = tuner_reg;
218 msg.len = 8;
219 i2c_transfer(priv->i2c_adap, &msg, 1);
220
221 msg.buf = reg2;
222 msg.len = 2;
223 reg2[0] = 0x80;
224 reg2[1] = 0;
225 i2c_transfer(priv->i2c_adap, &msg, 1);
226
227 reg2[0] = 0x60;
228 reg2[1] = 0xbf;
229 i2c_transfer(priv->i2c_adap, &msg, 1);
230
231 reg2[0] = 0x30;
232 reg2[1] = tuner_reg[4] + 0x80;
233 i2c_transfer(priv->i2c_adap, &msg, 1);
234
235 msleep(1);
236 reg2[0] = 0x30;
237 reg2[1] = tuner_reg[4] + 4;
238 i2c_transfer(priv->i2c_adap, &msg, 1);
239
240 msleep(1);
241 reg2[0] = 0x30;
242 reg2[1] = tuner_reg[4];
243 i2c_transfer(priv->i2c_adap, &msg, 1);
244
245 msleep(550);
246 reg2[0] = 0x30;
247 reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_table[i].cp;
248 i2c_transfer(priv->i2c_adap, &msg, 1);
249
250 reg2[0] = 0x60;
251 reg2[1] = 0x3f;
252 i2c_transfer(priv->i2c_adap, &msg, 1);
253
254 reg2[0] = 0x80;
255 reg2[1] = 0x08; /* Vsync en */
256 i2c_transfer(priv->i2c_adap, &msg, 1);
257
258 priv->frequency = freq * 62500;
259
260 return 0;
261}
262
263static void tda827xo_agcf(struct dvb_frontend *fe)
264{
265 struct tda827x_priv *priv = fe->tuner_priv;
266 unsigned char data[] = { 0x80, 0x0c };
267 struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
268 .buf = data, .len = 2};
269
270 i2c_transfer(priv->i2c_adap, &msg, 1);
271}
272
273/* ------------------------------------------------------------------ */
274
Michael Krufky8ce47da2007-04-27 12:31:14 -0300275struct tda827xa_data {
276 u32 lomax;
277 u8 svco;
278 u8 spd;
279 u8 scr;
280 u8 sbs;
281 u8 gc3;
282};
283
284static const struct tda827xa_data tda827xa_dvbt[] = {
285 { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1},
286 { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
287 { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
288 { .lomax = 97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
289 { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
290 { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
291 { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
292 { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
293 { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
294 { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
295 { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
296 { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
297 { .lomax = 290000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
298 { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
299 { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
300 { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
301 { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
302 { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
303 { .lomax = 550000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
304 { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
305 { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
306 { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
307 { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
308 { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
309 { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
310 { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
311 { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
312};
313
Michael Krufky746d97322007-08-25 19:08:45 -0300314static struct tda827xa_data tda827xa_analog[] = {
315 { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3},
316 { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
317 { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
318 { .lomax = 97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
319 { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
320 { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
321 { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
322 { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
323 { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
324 { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
325 { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 3},
326 { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 3},
327 { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
328 { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
329 { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
330 { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
331 { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
332 { .lomax = 554000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
333 { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
334 { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
335 { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
336 { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
337 { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
338 { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
339 { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
340 { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
341};
342
Michael Krufky8ce47da2007-04-27 12:31:14 -0300343static int tda827xa_set_params(struct dvb_frontend *fe,
344 struct dvb_frontend_parameters *params)
345{
346 struct tda827x_priv *priv = fe->tuner_priv;
Hartmut Hackmannede22002007-04-27 12:31:32 -0300347 u8 buf[11];
Michael Krufky8ce47da2007-04-27 12:31:14 -0300348
349 struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
350 .buf = buf, .len = sizeof(buf) };
351
352 int i, tuner_freq, if_freq;
353 u32 N;
354
Hartmut Hackmann9971f4f2007-03-23 21:00:07 -0300355 dprintk("%s:\n", __FUNCTION__);
Michael Krufky8ce47da2007-04-27 12:31:14 -0300356 if (priv->cfg && priv->cfg->lna_gain)
357 priv->cfg->lna_gain(fe, 1);
358 msleep(20);
359
360 switch (params->u.ofdm.bandwidth) {
361 case BANDWIDTH_6_MHZ:
362 if_freq = 4000000;
363 break;
364 case BANDWIDTH_7_MHZ:
365 if_freq = 4500000;
366 break;
367 default: /* 8 MHz or Auto */
368 if_freq = 5000000;
369 break;
370 }
371 tuner_freq = params->frequency + if_freq;
372
373 i = 0;
374 while (tda827xa_dvbt[i].lomax < tuner_freq) {
375 if(tda827xa_dvbt[i + 1].lomax == 0)
376 break;
377 i++;
378 }
379
380 N = ((tuner_freq + 31250) / 62500) << tda827xa_dvbt[i].spd;
381 buf[0] = 0; // subaddress
382 buf[1] = N >> 8;
383 buf[2] = N & 0xff;
384 buf[3] = 0;
385 buf[4] = 0x16;
386 buf[5] = (tda827xa_dvbt[i].spd << 5) + (tda827xa_dvbt[i].svco << 3) +
387 tda827xa_dvbt[i].sbs;
388 buf[6] = 0x4b + (tda827xa_dvbt[i].gc3 << 4);
389 buf[7] = 0x1c;
390 buf[8] = 0x06;
391 buf[9] = 0x24;
392 buf[10] = 0x00;
393 msg.len = 11;
394 if (fe->ops.i2c_gate_ctrl)
395 fe->ops.i2c_gate_ctrl(fe, 1);
396 if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
397 printk("%s: could not write to tuner at addr: 0x%02x\n",
398 __FUNCTION__, priv->i2c_addr << 1);
399 return -EIO;
400 }
401 buf[0] = 0x90;
402 buf[1] = 0xff;
403 buf[2] = 0x60;
404 buf[3] = 0x00;
405 buf[4] = 0x59; // lpsel, for 6MHz + 2
406 msg.len = 5;
407 if (fe->ops.i2c_gate_ctrl)
408 fe->ops.i2c_gate_ctrl(fe, 1);
409 i2c_transfer(priv->i2c_adap, &msg, 1);
410
411 buf[0] = 0xa0;
412 buf[1] = 0x40;
413 msg.len = 2;
414 if (fe->ops.i2c_gate_ctrl)
415 fe->ops.i2c_gate_ctrl(fe, 1);
416 i2c_transfer(priv->i2c_adap, &msg, 1);
417
418 msleep(11);
419 msg.flags = I2C_M_RD;
420 if (fe->ops.i2c_gate_ctrl)
421 fe->ops.i2c_gate_ctrl(fe, 1);
422 i2c_transfer(priv->i2c_adap, &msg, 1);
423 msg.flags = 0;
424
425 buf[1] >>= 4;
426 dprintk("tda8275a AGC2 gain is: %d\n", buf[1]);
427 if ((buf[1]) < 2) {
428 if (priv->cfg && priv->cfg->lna_gain)
429 priv->cfg->lna_gain(fe, 0);
430 buf[0] = 0x60;
431 buf[1] = 0x0c;
432 if (fe->ops.i2c_gate_ctrl)
433 fe->ops.i2c_gate_ctrl(fe, 1);
434 i2c_transfer(priv->i2c_adap, &msg, 1);
435 }
436
437 buf[0] = 0xc0;
438 buf[1] = 0x99; // lpsel, for 6MHz + 2
439 if (fe->ops.i2c_gate_ctrl)
440 fe->ops.i2c_gate_ctrl(fe, 1);
441 i2c_transfer(priv->i2c_adap, &msg, 1);
442
443 buf[0] = 0x60;
444 buf[1] = 0x3c;
445 if (fe->ops.i2c_gate_ctrl)
446 fe->ops.i2c_gate_ctrl(fe, 1);
447 i2c_transfer(priv->i2c_adap, &msg, 1);
448
449 /* correct CP value */
450 buf[0] = 0x30;
451 buf[1] = 0x10 + tda827xa_dvbt[i].scr;
452 if (fe->ops.i2c_gate_ctrl)
453 fe->ops.i2c_gate_ctrl(fe, 1);
454 i2c_transfer(priv->i2c_adap, &msg, 1);
455
456 msleep(163);
457 buf[0] = 0xc0;
458 buf[1] = 0x39; // lpsel, for 6MHz + 2
459 if (fe->ops.i2c_gate_ctrl)
460 fe->ops.i2c_gate_ctrl(fe, 1);
461 i2c_transfer(priv->i2c_adap, &msg, 1);
462
463 msleep(3);
464 /* freeze AGC1 */
465 buf[0] = 0x50;
466 buf[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4);
467 if (fe->ops.i2c_gate_ctrl)
468 fe->ops.i2c_gate_ctrl(fe, 1);
469 i2c_transfer(priv->i2c_adap, &msg, 1);
470
471 priv->frequency = tuner_freq - if_freq; // FIXME
472 priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
473
474 return 0;
475}
476
477static int tda827xa_sleep(struct dvb_frontend *fe)
478{
479 struct tda827x_priv *priv = fe->tuner_priv;
480 static u8 buf[] = { 0x30, 0x90 };
481 struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
482 .buf = buf, .len = sizeof(buf) };
483
Hartmut Hackmann9971f4f2007-03-23 21:00:07 -0300484 dprintk("%s:\n", __FUNCTION__);
Michael Krufky8ce47da2007-04-27 12:31:14 -0300485 if (fe->ops.i2c_gate_ctrl)
486 fe->ops.i2c_gate_ctrl(fe, 1);
487
488 i2c_transfer(priv->i2c_adap, &msg, 1);
489
490 if (fe->ops.i2c_gate_ctrl)
491 fe->ops.i2c_gate_ctrl(fe, 0);
492
493 if (priv->cfg && priv->cfg->sleep)
494 priv->cfg->sleep(fe);
495
496 return 0;
497}
498
Michael Krufky746d97322007-08-25 19:08:45 -0300499/* ------------------------------------------------------------------ */
500
501static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
502 struct analog_parameters *params)
503{
504 struct tda827x_priv *priv = fe->tuner_priv;
505 unsigned char buf[] = {0x22, 0x01};
506 int arg;
507 struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
508 .buf = buf, .len = sizeof(buf) };
509
510 if (priv->cfg->config) {
511 if (high)
512 dprintk("setting LNA to high gain\n");
513 else
514 dprintk("setting LNA to low gain\n");
515 }
516 switch (*priv->cfg->config) {
517 case 0: /* no LNA */
518 break;
519 case 1: /* switch is GPIO 0 of tda8290 */
520 case 2:
521 /* turn Vsync on */
522 if (params->std & V4L2_STD_MN)
523 arg = 1;
524 else
525 arg = 0;
526 if (priv->cfg->tuner_callback)
527 priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
528 1, arg);
529 buf[1] = high ? 0 : 1;
530 if (*priv->cfg->config == 2)
531 buf[1] = high ? 1 : 0;
532 i2c_transfer(priv->i2c_adap, &msg, 1);
533 break;
534 case 3: /* switch with GPIO of saa713x */
535 if (priv->cfg->tuner_callback)
536 priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
537 0, high);
538 break;
539 }
540}
541
542static int tda827xa_set_analog_params(struct dvb_frontend *fe,
543 struct analog_parameters *params)
544{
545 unsigned char tuner_reg[11];
546 u32 N;
547 int i;
548 struct tda827x_priv *priv = fe->tuner_priv;
549 struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
550 .buf = tuner_reg, .len = sizeof(tuner_reg) };
551 unsigned int freq = params->frequency;
552
553 tda827xa_lna_gain(fe, 1, params);
554 msleep(10);
555
556 if (params->mode == V4L2_TUNER_RADIO)
557 freq = freq / 1000;
558
559 N = freq + priv->cfg->sgIF;
560
561 i = 0;
562 while (tda827xa_analog[i].lomax < N * 62500) {
563 if (tda827xa_analog[i + 1].lomax == 0)
564 break;
565 i++;
566 }
567
568 N = N << tda827xa_analog[i].spd;
569
570 tuner_reg[0] = 0;
571 tuner_reg[1] = (unsigned char)(N>>8);
572 tuner_reg[2] = (unsigned char) N;
573 tuner_reg[3] = 0;
574 tuner_reg[4] = 0x16;
575 tuner_reg[5] = (tda827xa_analog[i].spd << 5) +
576 (tda827xa_analog[i].svco << 3) +
577 tda827xa_analog[i].sbs;
578 tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4);
579 tuner_reg[7] = 0x1c;
580 tuner_reg[8] = 4;
581 tuner_reg[9] = 0x20;
582 tuner_reg[10] = 0x00;
583 msg.len = 11;
584 i2c_transfer(priv->i2c_adap, &msg, 1);
585
586 tuner_reg[0] = 0x90;
587 tuner_reg[1] = 0xff;
588 tuner_reg[2] = 0xe0;
589 tuner_reg[3] = 0;
590 tuner_reg[4] = 0x99 + (priv->cfg->tda827x_lpsel << 1);
591 msg.len = 5;
592 i2c_transfer(priv->i2c_adap, &msg, 1);
593
594 tuner_reg[0] = 0xa0;
595 tuner_reg[1] = 0xc0;
596 msg.len = 2;
597 i2c_transfer(priv->i2c_adap, &msg, 1);
598
599 tuner_reg[0] = 0x30;
600 tuner_reg[1] = 0x10 + tda827xa_analog[i].scr;
601 i2c_transfer(priv->i2c_adap, &msg, 1);
602
603 msg.flags = I2C_M_RD;
604 i2c_transfer(priv->i2c_adap, &msg, 1);
605 msg.flags = 0;
606 tuner_reg[1] >>= 4;
607 dprintk("AGC2 gain is: %d\n", tuner_reg[1]);
608 if (tuner_reg[1] < 1)
609 tda827xa_lna_gain(fe, 0, params);
610
611 msleep(100);
612 tuner_reg[0] = 0x60;
613 tuner_reg[1] = 0x3c;
614 i2c_transfer(priv->i2c_adap, &msg, 1);
615
616 msleep(163);
617 tuner_reg[0] = 0x50;
618 tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4);
619 i2c_transfer(priv->i2c_adap, &msg, 1);
620
621 tuner_reg[0] = 0x80;
622 tuner_reg[1] = 0x28;
623 i2c_transfer(priv->i2c_adap, &msg, 1);
624
625 tuner_reg[0] = 0xb0;
626 tuner_reg[1] = 0x01;
627 i2c_transfer(priv->i2c_adap, &msg, 1);
628
629 tuner_reg[0] = 0xc0;
630 tuner_reg[1] = 0x19 + (priv->cfg->tda827x_lpsel << 1);
631 i2c_transfer(priv->i2c_adap, &msg, 1);
632
633 priv->frequency = freq * 62500;
634
635 return 0;
636}
637
638static void tda827xa_agcf(struct dvb_frontend *fe)
639{
640 struct tda827x_priv *priv = fe->tuner_priv;
641 unsigned char data[] = {0x80, 0x2c};
642 struct i2c_msg msg = {.addr = priv->i2c_addr, .flags = 0,
643 .buf = data, .len = 2};
644 i2c_transfer(priv->i2c_adap, &msg, 1);
645}
646
647/* ------------------------------------------------------------------ */
648
Michael Krufky8ce47da2007-04-27 12:31:14 -0300649static int tda827x_release(struct dvb_frontend *fe)
650{
651 kfree(fe->tuner_priv);
652 fe->tuner_priv = NULL;
653 return 0;
654}
655
656static int tda827x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
657{
658 struct tda827x_priv *priv = fe->tuner_priv;
659 *frequency = priv->frequency;
660 return 0;
661}
662
663static int tda827x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
664{
665 struct tda827x_priv *priv = fe->tuner_priv;
666 *bandwidth = priv->bandwidth;
667 return 0;
668}
669
670static int tda827x_init(struct dvb_frontend *fe)
671{
672 struct tda827x_priv *priv = fe->tuner_priv;
Hartmut Hackmann9971f4f2007-03-23 21:00:07 -0300673 dprintk("%s:\n", __FUNCTION__);
Michael Krufky8ce47da2007-04-27 12:31:14 -0300674 if (priv->cfg && priv->cfg->init)
675 priv->cfg->init(fe);
676
677 return 0;
678}
679
Hartmut Hackmann9971f4f2007-03-23 21:00:07 -0300680static int tda827x_probe_version(struct dvb_frontend *fe);
681
682static int tda827x_initial_init(struct dvb_frontend *fe)
683{
684 int ret;
685 ret = tda827x_probe_version(fe);
686 if (ret)
687 return ret;
688 return fe->ops.tuner_ops.init(fe);
689}
690
691static int tda827x_initial_sleep(struct dvb_frontend *fe)
692{
693 int ret;
694 ret = tda827x_probe_version(fe);
695 if (ret)
696 return ret;
697 return fe->ops.tuner_ops.sleep(fe);
698}
Michael Krufky8ce47da2007-04-27 12:31:14 -0300699
700static struct dvb_tuner_ops tda827xo_tuner_ops = {
701 .info = {
702 .name = "Philips TDA827X",
Hartmut Hackmann11f65102007-04-27 12:31:15 -0300703 .frequency_min = 55000000,
704 .frequency_max = 860000000,
705 .frequency_step = 250000
Michael Krufky8ce47da2007-04-27 12:31:14 -0300706 },
707 .release = tda827x_release,
Hartmut Hackmann9971f4f2007-03-23 21:00:07 -0300708 .init = tda827x_initial_init,
709 .sleep = tda827x_initial_sleep,
Michael Krufky8ce47da2007-04-27 12:31:14 -0300710 .set_params = tda827xo_set_params,
Michael Krufky746d97322007-08-25 19:08:45 -0300711 .set_analog_params = tda827xo_set_analog_params,
Michael Krufky8ce47da2007-04-27 12:31:14 -0300712 .get_frequency = tda827x_get_frequency,
713 .get_bandwidth = tda827x_get_bandwidth,
714};
715
716static struct dvb_tuner_ops tda827xa_tuner_ops = {
717 .info = {
718 .name = "Philips TDA827XA",
Hartmut Hackmann11f65102007-04-27 12:31:15 -0300719 .frequency_min = 44000000,
720 .frequency_max = 906000000,
721 .frequency_step = 62500
Michael Krufky8ce47da2007-04-27 12:31:14 -0300722 },
723 .release = tda827x_release,
724 .init = tda827x_init,
725 .sleep = tda827xa_sleep,
726 .set_params = tda827xa_set_params,
Michael Krufky746d97322007-08-25 19:08:45 -0300727 .set_analog_params = tda827xa_set_analog_params,
Michael Krufky8ce47da2007-04-27 12:31:14 -0300728 .get_frequency = tda827x_get_frequency,
729 .get_bandwidth = tda827x_get_bandwidth,
730};
731
Hartmut Hackmann9971f4f2007-03-23 21:00:07 -0300732static int tda827x_probe_version(struct dvb_frontend *fe)
733{ u8 data;
734 struct tda827x_priv *priv = fe->tuner_priv;
735 struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = I2C_M_RD,
736 .buf = &data, .len = 1 };
737 if (fe->ops.i2c_gate_ctrl)
738 fe->ops.i2c_gate_ctrl(fe, 1);
739 if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
740 printk("%s: could not read from tuner at addr: 0x%02x\n",
741 __FUNCTION__, msg.addr << 1);
742 return -EIO;
743 }
744 if ((data & 0x3c) == 0) {
745 dprintk("tda827x tuner found\n");
746 fe->ops.tuner_ops.init = tda827x_init;
747 fe->ops.tuner_ops.sleep = tda827xo_sleep;
Michael Krufky746d97322007-08-25 19:08:45 -0300748 priv->cfg->agcf = tda827xo_agcf;
Hartmut Hackmann9971f4f2007-03-23 21:00:07 -0300749 } else {
750 dprintk("tda827xa tuner found\n");
751 memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops));
Michael Krufky746d97322007-08-25 19:08:45 -0300752 priv->cfg->agcf = tda827xa_agcf;
Hartmut Hackmann9971f4f2007-03-23 21:00:07 -0300753 }
754 return 0;
755}
756
Michael Krufky8ce47da2007-04-27 12:31:14 -0300757struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr,
758 struct i2c_adapter *i2c,
759 struct tda827x_config *cfg)
760{
761 struct tda827x_priv *priv = NULL;
Hartmut Hackmann9971f4f2007-03-23 21:00:07 -0300762
Michael Krufky8ce47da2007-04-27 12:31:14 -0300763 dprintk("%s:\n", __FUNCTION__);
Michael Krufky8ce47da2007-04-27 12:31:14 -0300764 priv = kzalloc(sizeof(struct tda827x_priv), GFP_KERNEL);
765 if (priv == NULL)
766 return NULL;
767
768 priv->i2c_addr = addr;
769 priv->i2c_adap = i2c;
770 priv->cfg = cfg;
Hartmut Hackmann9971f4f2007-03-23 21:00:07 -0300771 memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops));
Michael Krufky8ce47da2007-04-27 12:31:14 -0300772 fe->tuner_priv = priv;
Hartmut Hackmann9971f4f2007-03-23 21:00:07 -0300773
Michael Krufky746d97322007-08-25 19:08:45 -0300774 dprintk("type set to %s\n", fe->ops.tuner_ops.info.name);
775
Michael Krufky8ce47da2007-04-27 12:31:14 -0300776 return fe;
777}
Michael Krufkyce1f8bd2007-10-22 00:28:50 -0300778EXPORT_SYMBOL_GPL(tda827x_attach);
Michael Krufky8ce47da2007-04-27 12:31:14 -0300779
Michael Krufky8ce47da2007-04-27 12:31:14 -0300780MODULE_DESCRIPTION("DVB TDA827x driver");
Hartmut Hackmann11f65102007-04-27 12:31:15 -0300781MODULE_AUTHOR("Hartmut Hackmann <hartmut.hackmann@t-online.de>");
782MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
Michael Krufky8ce47da2007-04-27 12:31:14 -0300783MODULE_LICENSE("GPL");
784
785/*
786 * Overrides for Emacs so that we follow Linus's tabbing style.
787 * ---------------------------------------------------------------------------
788 * Local variables:
789 * c-basic-offset: 8
790 * End:
791 */