diff options
Diffstat (limited to 'drivers/media/dvb/frontends/tda18271.c')
-rw-r--r-- | drivers/media/dvb/frontends/tda18271.c | 1054 |
1 files changed, 1054 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/tda18271.c b/drivers/media/dvb/frontends/tda18271.c new file mode 100644 index 000000000000..3395f2bda498 --- /dev/null +++ b/drivers/media/dvb/frontends/tda18271.c | |||
@@ -0,0 +1,1054 @@ | |||
1 | /* | ||
2 | tda18271.c - driver for the Philips / NXP TDA18271 silicon tuner | ||
3 | |||
4 | Copyright (C) 2007 Michael Krufky (mkrufky@linuxtv.org) | ||
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/i2c.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/videodev2.h> | ||
24 | |||
25 | #include "tda18271.h" | ||
26 | |||
27 | static int debug; | ||
28 | module_param(debug, int, 0644); | ||
29 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | ||
30 | |||
31 | #define tuner_dbg(fmt, arg...) do {\ | ||
32 | if (debug > 0) \ | ||
33 | printk(KERN_DEBUG fmt, ##arg); } while (0) | ||
34 | |||
35 | #define tuner_extra_dbg(fmt, arg...) do {\ | ||
36 | if (debug > 1) \ | ||
37 | printk(KERN_DEBUG fmt, ##arg); } while (0) | ||
38 | |||
39 | #define R_ID 0x00 /* ID byte */ | ||
40 | #define R_TM 0x01 /* Thermo byte */ | ||
41 | #define R_PL 0x02 /* Power level byte */ | ||
42 | #define R_EP1 0x03 /* Easy Prog byte 1 */ | ||
43 | #define R_EP2 0x04 /* Easy Prog byte 2 */ | ||
44 | #define R_EP3 0x05 /* Easy Prog byte 3 */ | ||
45 | #define R_EP4 0x06 /* Easy Prog byte 4 */ | ||
46 | #define R_EP5 0x07 /* Easy Prog byte 5 */ | ||
47 | #define R_CPD 0x08 /* Cal Post-Divider byte */ | ||
48 | #define R_CD1 0x09 /* Cal Divider byte 1 */ | ||
49 | #define R_CD2 0x0a /* Cal Divider byte 2 */ | ||
50 | #define R_CD3 0x0b /* Cal Divider byte 3 */ | ||
51 | #define R_MPD 0x0c /* Main Post-Divider byte */ | ||
52 | #define R_MD1 0x0d /* Main Divider byte 1 */ | ||
53 | #define R_MD2 0x0e /* Main Divider byte 2 */ | ||
54 | #define R_MD3 0x0f /* Main Divider byte 3 */ | ||
55 | #define R_EB1 0x10 /* Extended byte 1 */ | ||
56 | #define R_EB2 0x11 /* Extended byte 2 */ | ||
57 | #define R_EB3 0x12 /* Extended byte 3 */ | ||
58 | #define R_EB4 0x13 /* Extended byte 4 */ | ||
59 | #define R_EB5 0x14 /* Extended byte 5 */ | ||
60 | #define R_EB6 0x15 /* Extended byte 6 */ | ||
61 | #define R_EB7 0x16 /* Extended byte 7 */ | ||
62 | #define R_EB8 0x17 /* Extended byte 8 */ | ||
63 | #define R_EB9 0x18 /* Extended byte 9 */ | ||
64 | #define R_EB10 0x19 /* Extended byte 10 */ | ||
65 | #define R_EB11 0x1a /* Extended byte 11 */ | ||
66 | #define R_EB12 0x1b /* Extended byte 12 */ | ||
67 | #define R_EB13 0x1c /* Extended byte 13 */ | ||
68 | #define R_EB14 0x1d /* Extended byte 14 */ | ||
69 | #define R_EB15 0x1e /* Extended byte 15 */ | ||
70 | #define R_EB16 0x1f /* Extended byte 16 */ | ||
71 | #define R_EB17 0x20 /* Extended byte 17 */ | ||
72 | #define R_EB18 0x21 /* Extended byte 18 */ | ||
73 | #define R_EB19 0x22 /* Extended byte 19 */ | ||
74 | #define R_EB20 0x23 /* Extended byte 20 */ | ||
75 | #define R_EB21 0x24 /* Extended byte 21 */ | ||
76 | #define R_EB22 0x25 /* Extended byte 22 */ | ||
77 | #define R_EB23 0x26 /* Extended byte 23 */ | ||
78 | |||
79 | struct tda18271_pll_map { | ||
80 | u32 lomax; | ||
81 | u8 pd; /* post div */ | ||
82 | u8 d; /* div */ | ||
83 | }; | ||
84 | |||
85 | static struct tda18271_pll_map tda18271_main_pll[] = { | ||
86 | { .lomax = 32000, .pd = 0x5f, .d = 0xf0 }, | ||
87 | { .lomax = 35000, .pd = 0x5e, .d = 0xe0 }, | ||
88 | { .lomax = 37000, .pd = 0x5d, .d = 0xd0 }, | ||
89 | { .lomax = 41000, .pd = 0x5c, .d = 0xc0 }, | ||
90 | { .lomax = 44000, .pd = 0x5b, .d = 0xb0 }, | ||
91 | { .lomax = 49000, .pd = 0x5a, .d = 0xa0 }, | ||
92 | { .lomax = 54000, .pd = 0x59, .d = 0x90 }, | ||
93 | { .lomax = 61000, .pd = 0x58, .d = 0x80 }, | ||
94 | { .lomax = 65000, .pd = 0x4f, .d = 0x78 }, | ||
95 | { .lomax = 70000, .pd = 0x4e, .d = 0x70 }, | ||
96 | { .lomax = 75000, .pd = 0x4d, .d = 0x68 }, | ||
97 | { .lomax = 82000, .pd = 0x4c, .d = 0x60 }, | ||
98 | { .lomax = 89000, .pd = 0x4b, .d = 0x58 }, | ||
99 | { .lomax = 98000, .pd = 0x4a, .d = 0x50 }, | ||
100 | { .lomax = 109000, .pd = 0x49, .d = 0x48 }, | ||
101 | { .lomax = 123000, .pd = 0x48, .d = 0x40 }, | ||
102 | { .lomax = 131000, .pd = 0x3f, .d = 0x3c }, | ||
103 | { .lomax = 141000, .pd = 0x3e, .d = 0x38 }, | ||
104 | { .lomax = 151000, .pd = 0x3d, .d = 0x34 }, | ||
105 | { .lomax = 164000, .pd = 0x3c, .d = 0x30 }, | ||
106 | { .lomax = 179000, .pd = 0x3b, .d = 0x2c }, | ||
107 | { .lomax = 197000, .pd = 0x3a, .d = 0x28 }, | ||
108 | { .lomax = 219000, .pd = 0x39, .d = 0x24 }, | ||
109 | { .lomax = 246000, .pd = 0x38, .d = 0x20 }, | ||
110 | { .lomax = 263000, .pd = 0x2f, .d = 0x1e }, | ||
111 | { .lomax = 282000, .pd = 0x2e, .d = 0x1c }, | ||
112 | { .lomax = 303000, .pd = 0x2d, .d = 0x1a }, | ||
113 | { .lomax = 329000, .pd = 0x2c, .d = 0x18 }, | ||
114 | { .lomax = 359000, .pd = 0x2b, .d = 0x16 }, | ||
115 | { .lomax = 395000, .pd = 0x2a, .d = 0x14 }, | ||
116 | { .lomax = 438000, .pd = 0x29, .d = 0x12 }, | ||
117 | { .lomax = 493000, .pd = 0x28, .d = 0x10 }, | ||
118 | { .lomax = 526000, .pd = 0x1f, .d = 0x0f }, | ||
119 | { .lomax = 564000, .pd = 0x1e, .d = 0x0e }, | ||
120 | { .lomax = 607000, .pd = 0x1d, .d = 0x0d }, | ||
121 | { .lomax = 658000, .pd = 0x1c, .d = 0x0c }, | ||
122 | { .lomax = 718000, .pd = 0x1b, .d = 0x0b }, | ||
123 | { .lomax = 790000, .pd = 0x1a, .d = 0x0a }, | ||
124 | { .lomax = 877000, .pd = 0x19, .d = 0x09 }, | ||
125 | { .lomax = 987000, .pd = 0x18, .d = 0x08 }, | ||
126 | { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */ | ||
127 | }; | ||
128 | |||
129 | static struct tda18271_pll_map tda18271_cal_pll[] = { | ||
130 | { .lomax = 33000, .pd = 0xdd, .d = 0xd0 }, | ||
131 | { .lomax = 36000, .pd = 0xdc, .d = 0xc0 }, | ||
132 | { .lomax = 40000, .pd = 0xdb, .d = 0xb0 }, | ||
133 | { .lomax = 44000, .pd = 0xda, .d = 0xa0 }, | ||
134 | { .lomax = 49000, .pd = 0xd9, .d = 0x90 }, | ||
135 | { .lomax = 55000, .pd = 0xd8, .d = 0x80 }, | ||
136 | { .lomax = 63000, .pd = 0xd3, .d = 0x70 }, | ||
137 | { .lomax = 67000, .pd = 0xcd, .d = 0x68 }, | ||
138 | { .lomax = 73000, .pd = 0xcc, .d = 0x60 }, | ||
139 | { .lomax = 80000, .pd = 0xcb, .d = 0x58 }, | ||
140 | { .lomax = 88000, .pd = 0xca, .d = 0x50 }, | ||
141 | { .lomax = 98000, .pd = 0xc9, .d = 0x48 }, | ||
142 | { .lomax = 110000, .pd = 0xc8, .d = 0x40 }, | ||
143 | { .lomax = 126000, .pd = 0xc3, .d = 0x38 }, | ||
144 | { .lomax = 135000, .pd = 0xbd, .d = 0x34 }, | ||
145 | { .lomax = 147000, .pd = 0xbc, .d = 0x30 }, | ||
146 | { .lomax = 160000, .pd = 0xbb, .d = 0x2c }, | ||
147 | { .lomax = 176000, .pd = 0xba, .d = 0x28 }, | ||
148 | { .lomax = 196000, .pd = 0xb9, .d = 0x24 }, | ||
149 | { .lomax = 220000, .pd = 0xb8, .d = 0x20 }, | ||
150 | { .lomax = 252000, .pd = 0xb3, .d = 0x1c }, | ||
151 | { .lomax = 271000, .pd = 0xad, .d = 0x1a }, | ||
152 | { .lomax = 294000, .pd = 0xac, .d = 0x18 }, | ||
153 | { .lomax = 321000, .pd = 0xab, .d = 0x16 }, | ||
154 | { .lomax = 353000, .pd = 0xaa, .d = 0x14 }, | ||
155 | { .lomax = 392000, .pd = 0xa9, .d = 0x12 }, | ||
156 | { .lomax = 441000, .pd = 0xa8, .d = 0x10 }, | ||
157 | { .lomax = 505000, .pd = 0xa3, .d = 0x0e }, | ||
158 | { .lomax = 543000, .pd = 0x9d, .d = 0x0d }, | ||
159 | { .lomax = 589000, .pd = 0x9c, .d = 0x0c }, | ||
160 | { .lomax = 642000, .pd = 0x9b, .d = 0x0b }, | ||
161 | { .lomax = 707000, .pd = 0x9a, .d = 0x0a }, | ||
162 | { .lomax = 785000, .pd = 0x99, .d = 0x09 }, | ||
163 | { .lomax = 883000, .pd = 0x98, .d = 0x08 }, | ||
164 | { .lomax = 1010000, .pd = 0x93, .d = 0x07 }, | ||
165 | { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */ | ||
166 | }; | ||
167 | |||
168 | struct tda18271_map { | ||
169 | u32 rfmax; | ||
170 | u8 val; | ||
171 | }; | ||
172 | |||
173 | static struct tda18271_map tda18271_bp_filter[] = { | ||
174 | { .rfmax = 62000, .val = 0x00 }, | ||
175 | { .rfmax = 84000, .val = 0x01 }, | ||
176 | { .rfmax = 100000, .val = 0x02 }, | ||
177 | { .rfmax = 140000, .val = 0x03 }, | ||
178 | { .rfmax = 170000, .val = 0x04 }, | ||
179 | { .rfmax = 180000, .val = 0x05 }, | ||
180 | { .rfmax = 865000, .val = 0x06 }, | ||
181 | { .rfmax = 0, .val = 0x00 }, /* end */ | ||
182 | }; | ||
183 | |||
184 | static struct tda18271_map tda18271_km[] = { | ||
185 | { .rfmax = 61100, .val = 0x74 }, | ||
186 | { .rfmax = 350000, .val = 0x40 }, | ||
187 | { .rfmax = 720000, .val = 0x30 }, | ||
188 | { .rfmax = 865000, .val = 0x40 }, | ||
189 | { .rfmax = 0, .val = 0x00 }, /* end */ | ||
190 | }; | ||
191 | |||
192 | static struct tda18271_map tda18271_rf_band[] = { | ||
193 | { .rfmax = 47900, .val = 0x00 }, | ||
194 | { .rfmax = 61100, .val = 0x01 }, | ||
195 | /* { .rfmax = 152600, .val = 0x02 }, */ | ||
196 | { .rfmax = 121200, .val = 0x02 }, | ||
197 | { .rfmax = 164700, .val = 0x03 }, | ||
198 | { .rfmax = 203500, .val = 0x04 }, | ||
199 | { .rfmax = 457800, .val = 0x05 }, | ||
200 | { .rfmax = 865000, .val = 0x06 }, | ||
201 | { .rfmax = 0, .val = 0x00 }, /* end */ | ||
202 | }; | ||
203 | |||
204 | static struct tda18271_map tda18271_gain_taper[] = { | ||
205 | { .rfmax = 45400, .val = 0x1f }, | ||
206 | { .rfmax = 45800, .val = 0x1e }, | ||
207 | { .rfmax = 46200, .val = 0x1d }, | ||
208 | { .rfmax = 46700, .val = 0x1c }, | ||
209 | { .rfmax = 47100, .val = 0x1b }, | ||
210 | { .rfmax = 47500, .val = 0x1a }, | ||
211 | { .rfmax = 47900, .val = 0x19 }, | ||
212 | { .rfmax = 49600, .val = 0x17 }, | ||
213 | { .rfmax = 51200, .val = 0x16 }, | ||
214 | { .rfmax = 52900, .val = 0x15 }, | ||
215 | { .rfmax = 54500, .val = 0x14 }, | ||
216 | { .rfmax = 56200, .val = 0x13 }, | ||
217 | { .rfmax = 57800, .val = 0x12 }, | ||
218 | { .rfmax = 59500, .val = 0x11 }, | ||
219 | { .rfmax = 61100, .val = 0x10 }, | ||
220 | { .rfmax = 67600, .val = 0x0d }, | ||
221 | { .rfmax = 74200, .val = 0x0c }, | ||
222 | { .rfmax = 80700, .val = 0x0b }, | ||
223 | { .rfmax = 87200, .val = 0x0a }, | ||
224 | { .rfmax = 93800, .val = 0x09 }, | ||
225 | { .rfmax = 100300, .val = 0x08 }, | ||
226 | { .rfmax = 106900, .val = 0x07 }, | ||
227 | { .rfmax = 113400, .val = 0x06 }, | ||
228 | { .rfmax = 119900, .val = 0x05 }, | ||
229 | { .rfmax = 126500, .val = 0x04 }, | ||
230 | { .rfmax = 133000, .val = 0x03 }, | ||
231 | { .rfmax = 139500, .val = 0x02 }, | ||
232 | { .rfmax = 146100, .val = 0x01 }, | ||
233 | { .rfmax = 152600, .val = 0x00 }, | ||
234 | { .rfmax = 154300, .val = 0x1f }, | ||
235 | { .rfmax = 156100, .val = 0x1e }, | ||
236 | { .rfmax = 157800, .val = 0x1d }, | ||
237 | { .rfmax = 159500, .val = 0x1c }, | ||
238 | { .rfmax = 161200, .val = 0x1b }, | ||
239 | { .rfmax = 163000, .val = 0x1a }, | ||
240 | { .rfmax = 164700, .val = 0x19 }, | ||
241 | { .rfmax = 170200, .val = 0x17 }, | ||
242 | { .rfmax = 175800, .val = 0x16 }, | ||
243 | { .rfmax = 181300, .val = 0x15 }, | ||
244 | { .rfmax = 186900, .val = 0x14 }, | ||
245 | { .rfmax = 192400, .val = 0x13 }, | ||
246 | { .rfmax = 198000, .val = 0x12 }, | ||
247 | { .rfmax = 203500, .val = 0x11 }, | ||
248 | { .rfmax = 216200, .val = 0x14 }, | ||
249 | { .rfmax = 228900, .val = 0x13 }, | ||
250 | { .rfmax = 241600, .val = 0x12 }, | ||
251 | { .rfmax = 254400, .val = 0x11 }, | ||
252 | { .rfmax = 267100, .val = 0x10 }, | ||
253 | { .rfmax = 279800, .val = 0x0f }, | ||
254 | { .rfmax = 292500, .val = 0x0e }, | ||
255 | { .rfmax = 305200, .val = 0x0d }, | ||
256 | { .rfmax = 317900, .val = 0x0c }, | ||
257 | { .rfmax = 330700, .val = 0x0b }, | ||
258 | { .rfmax = 343400, .val = 0x0a }, | ||
259 | { .rfmax = 356100, .val = 0x09 }, | ||
260 | { .rfmax = 368800, .val = 0x08 }, | ||
261 | { .rfmax = 381500, .val = 0x07 }, | ||
262 | { .rfmax = 394200, .val = 0x06 }, | ||
263 | { .rfmax = 406900, .val = 0x05 }, | ||
264 | { .rfmax = 419700, .val = 0x04 }, | ||
265 | { .rfmax = 432400, .val = 0x03 }, | ||
266 | { .rfmax = 445100, .val = 0x02 }, | ||
267 | { .rfmax = 457800, .val = 0x01 }, | ||
268 | { .rfmax = 476300, .val = 0x19 }, | ||
269 | { .rfmax = 494800, .val = 0x18 }, | ||
270 | { .rfmax = 513300, .val = 0x17 }, | ||
271 | { .rfmax = 531800, .val = 0x16 }, | ||
272 | { .rfmax = 550300, .val = 0x15 }, | ||
273 | { .rfmax = 568900, .val = 0x14 }, | ||
274 | { .rfmax = 587400, .val = 0x13 }, | ||
275 | { .rfmax = 605900, .val = 0x12 }, | ||
276 | { .rfmax = 624400, .val = 0x11 }, | ||
277 | { .rfmax = 642900, .val = 0x10 }, | ||
278 | { .rfmax = 661400, .val = 0x0f }, | ||
279 | { .rfmax = 679900, .val = 0x0e }, | ||
280 | { .rfmax = 698400, .val = 0x0d }, | ||
281 | { .rfmax = 716900, .val = 0x0c }, | ||
282 | { .rfmax = 735400, .val = 0x0b }, | ||
283 | { .rfmax = 753900, .val = 0x0a }, | ||
284 | { .rfmax = 772500, .val = 0x09 }, | ||
285 | { .rfmax = 791000, .val = 0x08 }, | ||
286 | { .rfmax = 809500, .val = 0x07 }, | ||
287 | { .rfmax = 828000, .val = 0x06 }, | ||
288 | { .rfmax = 846500, .val = 0x05 }, | ||
289 | { .rfmax = 865000, .val = 0x04 }, | ||
290 | { .rfmax = 0, .val = 0x00 }, /* end */ | ||
291 | }; | ||
292 | |||
293 | static struct tda18271_map tda18271_rf_cal[] = { | ||
294 | { .rfmax = 41000, .val = 0x1e }, | ||
295 | { .rfmax = 43000, .val = 0x30 }, | ||
296 | { .rfmax = 45000, .val = 0x43 }, | ||
297 | { .rfmax = 46000, .val = 0x4d }, | ||
298 | { .rfmax = 47000, .val = 0x54 }, | ||
299 | { .rfmax = 47900, .val = 0x64 }, | ||
300 | { .rfmax = 49100, .val = 0x20 }, | ||
301 | { .rfmax = 50000, .val = 0x22 }, | ||
302 | { .rfmax = 51000, .val = 0x2a }, | ||
303 | { .rfmax = 53000, .val = 0x32 }, | ||
304 | { .rfmax = 55000, .val = 0x35 }, | ||
305 | { .rfmax = 56000, .val = 0x3c }, | ||
306 | { .rfmax = 57000, .val = 0x3f }, | ||
307 | { .rfmax = 58000, .val = 0x48 }, | ||
308 | { .rfmax = 59000, .val = 0x4d }, | ||
309 | { .rfmax = 60000, .val = 0x58 }, | ||
310 | { .rfmax = 61100, .val = 0x5f }, | ||
311 | { .rfmax = 0, .val = 0x00 }, /* end */ | ||
312 | }; | ||
313 | |||
314 | /*---------------------------------------------------------------------*/ | ||
315 | |||
316 | #define TDA18271_NUM_REGS 39 | ||
317 | |||
318 | #define TDA18271_ANALOG 0 | ||
319 | #define TDA18271_DIGITAL 1 | ||
320 | |||
321 | struct tda18271_priv { | ||
322 | u8 i2c_addr; | ||
323 | struct i2c_adapter *i2c_adap; | ||
324 | unsigned char tda18271_regs[TDA18271_NUM_REGS]; | ||
325 | int mode; | ||
326 | |||
327 | u32 frequency; | ||
328 | u32 bandwidth; | ||
329 | }; | ||
330 | |||
331 | /*---------------------------------------------------------------------*/ | ||
332 | |||
333 | static void tda18271_dump_regs(struct dvb_frontend *fe) | ||
334 | { | ||
335 | struct tda18271_priv *priv = fe->tuner_priv; | ||
336 | unsigned char *regs = priv->tda18271_regs; | ||
337 | |||
338 | tuner_dbg("=== TDA18271 REG DUMP ===\n"); | ||
339 | tuner_dbg("ID_BYTE = 0x%x\n", 0xff & regs[R_ID]); | ||
340 | tuner_dbg("THERMO_BYTE = 0x%x\n", 0xff & regs[R_TM]); | ||
341 | tuner_dbg("POWER_LEVEL_BYTE = 0x%x\n", 0xff & regs[R_PL]); | ||
342 | tuner_dbg("EASY_PROG_BYTE_1 = 0x%x\n", 0xff & regs[R_EP1]); | ||
343 | tuner_dbg("EASY_PROG_BYTE_2 = 0x%x\n", 0xff & regs[R_EP2]); | ||
344 | tuner_dbg("EASY_PROG_BYTE_3 = 0x%x\n", 0xff & regs[R_EP3]); | ||
345 | tuner_dbg("EASY_PROG_BYTE_4 = 0x%x\n", 0xff & regs[R_EP4]); | ||
346 | tuner_dbg("EASY_PROG_BYTE_5 = 0x%x\n", 0xff & regs[R_EP5]); | ||
347 | tuner_dbg("CAL_POST_DIV_BYTE = 0x%x\n", 0xff & regs[R_CPD]); | ||
348 | tuner_dbg("CAL_DIV_BYTE_1 = 0x%x\n", 0xff & regs[R_CD1]); | ||
349 | tuner_dbg("CAL_DIV_BYTE_2 = 0x%x\n", 0xff & regs[R_CD2]); | ||
350 | tuner_dbg("CAL_DIV_BYTE_3 = 0x%x\n", 0xff & regs[R_CD3]); | ||
351 | tuner_dbg("MAIN_POST_DIV_BYTE = 0x%x\n", 0xff & regs[R_MPD]); | ||
352 | tuner_dbg("MAIN_DIV_BYTE_1 = 0x%x\n", 0xff & regs[R_MD1]); | ||
353 | tuner_dbg("MAIN_DIV_BYTE_2 = 0x%x\n", 0xff & regs[R_MD2]); | ||
354 | tuner_dbg("MAIN_DIV_BYTE_3 = 0x%x\n", 0xff & regs[R_MD3]); | ||
355 | } | ||
356 | |||
357 | static void tda18271_read_regs(struct dvb_frontend *fe) | ||
358 | { | ||
359 | struct tda18271_priv *priv = fe->tuner_priv; | ||
360 | unsigned char *regs = priv->tda18271_regs; | ||
361 | unsigned char buf = 0x00; | ||
362 | int ret; | ||
363 | struct i2c_msg msg[] = { | ||
364 | { .addr = priv->i2c_addr, .flags = 0, | ||
365 | .buf = &buf, .len = 1 }, | ||
366 | { .addr = priv->i2c_addr, .flags = I2C_M_RD, | ||
367 | .buf = regs, .len = 16 } | ||
368 | }; | ||
369 | |||
370 | if (fe->ops.i2c_gate_ctrl) | ||
371 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
372 | |||
373 | /* read all registers */ | ||
374 | ret = i2c_transfer(priv->i2c_adap, msg, 2); | ||
375 | |||
376 | if (fe->ops.i2c_gate_ctrl) | ||
377 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
378 | |||
379 | if (ret != 2) | ||
380 | printk("ERROR: %s: i2c_transfer returned: %d\n", | ||
381 | __FUNCTION__, ret); | ||
382 | |||
383 | if (debug > 1) | ||
384 | tda18271_dump_regs(fe); | ||
385 | } | ||
386 | |||
387 | static void tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) | ||
388 | { | ||
389 | struct tda18271_priv *priv = fe->tuner_priv; | ||
390 | unsigned char *regs = priv->tda18271_regs; | ||
391 | unsigned char buf[TDA18271_NUM_REGS+1]; | ||
392 | struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, | ||
393 | .buf = buf, .len = len+1 }; | ||
394 | int i, ret; | ||
395 | |||
396 | BUG_ON((len == 0) || (idx+len > sizeof(buf))); | ||
397 | |||
398 | buf[0] = idx; | ||
399 | for (i = 1; i <= len; i++) { | ||
400 | buf[i] = regs[idx-1+i]; | ||
401 | } | ||
402 | |||
403 | if (fe->ops.i2c_gate_ctrl) | ||
404 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
405 | |||
406 | /* write registers */ | ||
407 | ret = i2c_transfer(priv->i2c_adap, &msg, 1); | ||
408 | |||
409 | if (fe->ops.i2c_gate_ctrl) | ||
410 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
411 | |||
412 | if (ret != 1) | ||
413 | printk(KERN_WARNING "ERROR: %s: i2c_transfer returned: %d\n", | ||
414 | __FUNCTION__, ret); | ||
415 | } | ||
416 | |||
417 | /*---------------------------------------------------------------------*/ | ||
418 | |||
419 | static void tda18271_init_regs(struct dvb_frontend *fe) | ||
420 | { | ||
421 | struct tda18271_priv *priv = fe->tuner_priv; | ||
422 | unsigned char *regs = priv->tda18271_regs; | ||
423 | |||
424 | tda18271_read_regs(fe); | ||
425 | |||
426 | /* test IR_CAL_OK to see if we need init */ | ||
427 | if ((regs[R_EP1] & 0x08) != 0) | ||
428 | return; | ||
429 | |||
430 | printk(KERN_INFO "tda18271: initializing registers\n"); | ||
431 | |||
432 | /* initialize registers */ | ||
433 | regs[R_ID] = 0x83; | ||
434 | regs[R_TM] = 0x08; | ||
435 | regs[R_PL] = 0x80; | ||
436 | regs[R_EP1] = 0xc6; | ||
437 | regs[R_EP2] = 0xdf; | ||
438 | regs[R_EP3] = 0x16; | ||
439 | regs[R_EP4] = 0x60; | ||
440 | regs[R_EP5] = 0x80; | ||
441 | regs[R_CPD] = 0x80; | ||
442 | regs[R_CD1] = 0x00; | ||
443 | regs[R_CD2] = 0x00; | ||
444 | regs[R_CD3] = 0x00; | ||
445 | regs[R_MPD] = 0x00; | ||
446 | regs[R_MD1] = 0x00; | ||
447 | regs[R_MD2] = 0x00; | ||
448 | regs[R_MD3] = 0x00; | ||
449 | regs[R_EB1] = 0xff; | ||
450 | regs[R_EB2] = 0x01; | ||
451 | regs[R_EB3] = 0x84; | ||
452 | regs[R_EB4] = 0x41; | ||
453 | regs[R_EB5] = 0x01; | ||
454 | regs[R_EB6] = 0x84; | ||
455 | regs[R_EB7] = 0x40; | ||
456 | regs[R_EB8] = 0x07; | ||
457 | regs[R_EB9] = 0x00; | ||
458 | regs[R_EB10] = 0x00; | ||
459 | regs[R_EB11] = 0x96; | ||
460 | regs[R_EB12] = 0x0f; | ||
461 | regs[R_EB13] = 0xc1; | ||
462 | regs[R_EB14] = 0x00; | ||
463 | regs[R_EB15] = 0x8f; | ||
464 | regs[R_EB16] = 0x00; | ||
465 | regs[R_EB17] = 0x00; | ||
466 | regs[R_EB18] = 0x00; | ||
467 | regs[R_EB19] = 0x00; | ||
468 | regs[R_EB20] = 0x20; | ||
469 | regs[R_EB21] = 0x33; | ||
470 | regs[R_EB22] = 0x48; | ||
471 | regs[R_EB23] = 0xb0; | ||
472 | |||
473 | tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS); | ||
474 | /* setup AGC1 & AGC2 */ | ||
475 | regs[R_EB17] = 0x00; | ||
476 | tda18271_write_regs(fe, R_EB17, 1); | ||
477 | regs[R_EB17] = 0x03; | ||
478 | tda18271_write_regs(fe, R_EB17, 1); | ||
479 | regs[R_EB17] = 0x43; | ||
480 | tda18271_write_regs(fe, R_EB17, 1); | ||
481 | regs[R_EB17] = 0x4c; | ||
482 | tda18271_write_regs(fe, R_EB17, 1); | ||
483 | |||
484 | regs[R_EB20] = 0xa0; | ||
485 | tda18271_write_regs(fe, R_EB20, 1); | ||
486 | regs[R_EB20] = 0xa7; | ||
487 | tda18271_write_regs(fe, R_EB20, 1); | ||
488 | regs[R_EB20] = 0xe7; | ||
489 | tda18271_write_regs(fe, R_EB20, 1); | ||
490 | regs[R_EB20] = 0xec; | ||
491 | tda18271_write_regs(fe, R_EB20, 1); | ||
492 | |||
493 | /* image rejection calibration */ | ||
494 | |||
495 | /* low-band */ | ||
496 | regs[R_EP3] = 0x1f; | ||
497 | regs[R_EP4] = 0x66; | ||
498 | regs[R_EP5] = 0x81; | ||
499 | regs[R_CPD] = 0xcc; | ||
500 | regs[R_CD1] = 0x6c; | ||
501 | regs[R_CD2] = 0x00; | ||
502 | regs[R_CD3] = 0x00; | ||
503 | regs[R_MPD] = 0xcd; | ||
504 | regs[R_MD1] = 0x77; | ||
505 | regs[R_MD2] = 0x08; | ||
506 | regs[R_MD3] = 0x00; | ||
507 | |||
508 | tda18271_write_regs(fe, R_EP3, 11); | ||
509 | msleep(5); /* pll locking */ | ||
510 | |||
511 | regs[R_EP1] = 0xc6; | ||
512 | tda18271_write_regs(fe, R_EP1, 1); | ||
513 | msleep(5); /* wanted low measurement */ | ||
514 | |||
515 | regs[R_EP3] = 0x1f; | ||
516 | regs[R_EP4] = 0x66; | ||
517 | regs[R_EP5] = 0x85; | ||
518 | regs[R_CPD] = 0xcb; | ||
519 | regs[R_CD1] = 0x66; | ||
520 | regs[R_CD2] = 0x70; | ||
521 | regs[R_CD3] = 0x00; | ||
522 | |||
523 | tda18271_write_regs(fe, R_EP3, 7); | ||
524 | msleep(5); /* pll locking */ | ||
525 | |||
526 | regs[R_EP2] = 0xdf; | ||
527 | tda18271_write_regs(fe, R_EP2, 1); | ||
528 | msleep(30); /* image low optimization completion */ | ||
529 | |||
530 | /* mid-band */ | ||
531 | regs[R_EP3] = 0x1f; | ||
532 | regs[R_EP4] = 0x66; | ||
533 | regs[R_EP5] = 0x82; | ||
534 | regs[R_CPD] = 0xa8; | ||
535 | regs[R_CD1] = 0x66; | ||
536 | regs[R_CD2] = 0x00; | ||
537 | regs[R_CD3] = 0x00; | ||
538 | regs[R_MPD] = 0xa9; | ||
539 | regs[R_MD1] = 0x73; | ||
540 | regs[R_MD2] = 0x1a; | ||
541 | regs[R_MD3] = 0x00; | ||
542 | |||
543 | tda18271_write_regs(fe, R_EP3, 11); | ||
544 | msleep(5); /* pll locking */ | ||
545 | |||
546 | regs[R_EP1] = 0xc6; | ||
547 | tda18271_write_regs(fe, R_EP1, 1); | ||
548 | msleep(5); /* wanted mid measurement */ | ||
549 | |||
550 | regs[R_EP3] = 0x1f; | ||
551 | regs[R_EP4] = 0x66; | ||
552 | regs[R_EP5] = 0x86; | ||
553 | regs[R_CPD] = 0xa8; | ||
554 | regs[R_CD1] = 0x66; | ||
555 | regs[R_CD2] = 0xa0; | ||
556 | regs[R_CD3] = 0x00; | ||
557 | |||
558 | tda18271_write_regs(fe, R_EP3, 7); | ||
559 | msleep(5); /* pll locking */ | ||
560 | |||
561 | regs[R_EP2] = 0xdf; | ||
562 | tda18271_write_regs(fe, R_EP2, 1); | ||
563 | msleep(30); /* image mid optimization completion */ | ||
564 | |||
565 | /* high-band */ | ||
566 | regs[R_EP3] = 0x1f; | ||
567 | regs[R_EP4] = 0x66; | ||
568 | regs[R_EP5] = 0x83; | ||
569 | regs[R_CPD] = 0x98; | ||
570 | regs[R_CD1] = 0x65; | ||
571 | regs[R_CD2] = 0x00; | ||
572 | regs[R_CD3] = 0x00; | ||
573 | regs[R_MPD] = 0x99; | ||
574 | regs[R_MD1] = 0x71; | ||
575 | regs[R_MD2] = 0xcd; | ||
576 | regs[R_MD3] = 0x00; | ||
577 | |||
578 | tda18271_write_regs(fe, R_EP3, 11); | ||
579 | msleep(5); /* pll locking */ | ||
580 | |||
581 | regs[R_EP1] = 0xc6; | ||
582 | tda18271_write_regs(fe, R_EP1, 1); | ||
583 | msleep(5); /* wanted high measurement */ | ||
584 | |||
585 | regs[R_EP3] = 0x1f; | ||
586 | regs[R_EP4] = 0x66; | ||
587 | regs[R_EP5] = 0x87; | ||
588 | regs[R_CPD] = 0x98; | ||
589 | regs[R_CD1] = 0x65; | ||
590 | regs[R_CD2] = 0x50; | ||
591 | regs[R_CD3] = 0x00; | ||
592 | |||
593 | tda18271_write_regs(fe, R_EP3, 7); | ||
594 | msleep(5); /* pll locking */ | ||
595 | |||
596 | regs[R_EP2] = 0xdf; | ||
597 | |||
598 | tda18271_write_regs(fe, R_EP2, 1); | ||
599 | msleep(30); /* image high optimization completion */ | ||
600 | |||
601 | regs[R_EP4] = 0x64; | ||
602 | tda18271_write_regs(fe, R_EP4, 1); | ||
603 | |||
604 | regs[R_EP1] = 0xc6; | ||
605 | tda18271_write_regs(fe, R_EP1, 1); | ||
606 | } | ||
607 | |||
608 | static int tda18271_tune(struct dvb_frontend *fe, | ||
609 | u32 ifc, u32 freq, u32 bw, u8 std) | ||
610 | { | ||
611 | struct tda18271_priv *priv = fe->tuner_priv; | ||
612 | unsigned char *regs = priv->tda18271_regs; | ||
613 | u32 div, N = 0; | ||
614 | int i; | ||
615 | |||
616 | |||
617 | tuner_dbg("%s: freq = %d, ifc = %d\n", __FUNCTION__, freq, ifc); | ||
618 | |||
619 | tda18271_init_regs(fe); | ||
620 | /* RF tracking filter calibration */ | ||
621 | |||
622 | /* calculate BP_Filter */ | ||
623 | i = 0; | ||
624 | while ((tda18271_bp_filter[i].rfmax * 1000) < freq) { | ||
625 | if (tda18271_bp_filter[i + 1].rfmax == 0) | ||
626 | break; | ||
627 | i++; | ||
628 | } | ||
629 | tuner_extra_dbg("bp filter = 0x%x, i = %d\n", | ||
630 | tda18271_bp_filter[i].val, i); | ||
631 | |||
632 | regs[R_EP1] &= ~0x07; /* clear bp filter bits */ | ||
633 | regs[R_EP1] |= tda18271_bp_filter[i].val; | ||
634 | tda18271_write_regs(fe, R_EP1, 1); | ||
635 | |||
636 | regs[R_EB4] &= 0x07; | ||
637 | regs[R_EB4] |= 0x60; | ||
638 | tda18271_write_regs(fe, R_EB4, 1); | ||
639 | |||
640 | regs[R_EB7] = 0x60; | ||
641 | tda18271_write_regs(fe, R_EB7, 1); | ||
642 | |||
643 | regs[R_EB14] = 0x00; | ||
644 | tda18271_write_regs(fe, R_EB14, 1); | ||
645 | |||
646 | regs[R_EB20] = 0xcc; | ||
647 | tda18271_write_regs(fe, R_EB20, 1); | ||
648 | |||
649 | /* set CAL mode to RF tracking filter calibration */ | ||
650 | regs[R_EB4] |= 0x03; | ||
651 | |||
652 | /* calculate CAL PLL */ | ||
653 | |||
654 | switch (priv->mode) { | ||
655 | case TDA18271_ANALOG: | ||
656 | N = freq - 1250000; | ||
657 | break; | ||
658 | case TDA18271_DIGITAL: | ||
659 | N = freq + bw / 2; | ||
660 | break; | ||
661 | } | ||
662 | |||
663 | i = 0; | ||
664 | while ((tda18271_cal_pll[i].lomax * 1000) < N) { | ||
665 | if (tda18271_cal_pll[i + 1].lomax == 0) | ||
666 | break; | ||
667 | i++; | ||
668 | } | ||
669 | tuner_extra_dbg("cal pll, pd = 0x%x, d = 0x%x, i = %d\n", | ||
670 | tda18271_cal_pll[i].pd, tda18271_cal_pll[i].d, i); | ||
671 | |||
672 | regs[R_CPD] = tda18271_cal_pll[i].pd; | ||
673 | |||
674 | div = ((tda18271_cal_pll[i].d * (N / 1000)) << 7) / 125; | ||
675 | regs[R_CD1] = 0xff & (div >> 16); | ||
676 | regs[R_CD2] = 0xff & (div >> 8); | ||
677 | regs[R_CD3] = 0xff & div; | ||
678 | |||
679 | /* calculate MAIN PLL */ | ||
680 | |||
681 | switch (priv->mode) { | ||
682 | case TDA18271_ANALOG: | ||
683 | N = freq - 250000; | ||
684 | break; | ||
685 | case TDA18271_DIGITAL: | ||
686 | N = freq + bw / 2 + 1000000; | ||
687 | break; | ||
688 | } | ||
689 | |||
690 | i = 0; | ||
691 | while ((tda18271_main_pll[i].lomax * 1000) < N) { | ||
692 | if (tda18271_main_pll[i + 1].lomax == 0) | ||
693 | break; | ||
694 | i++; | ||
695 | } | ||
696 | tuner_extra_dbg("main pll, pd = 0x%x, d = 0x%x, i = %d\n", | ||
697 | tda18271_main_pll[i].pd, tda18271_main_pll[i].d, i); | ||
698 | |||
699 | regs[R_MPD] = (0x7f & tda18271_main_pll[i].pd); | ||
700 | |||
701 | switch (priv->mode) { | ||
702 | case TDA18271_ANALOG: | ||
703 | regs[R_MPD] &= ~0x08; | ||
704 | break; | ||
705 | case TDA18271_DIGITAL: | ||
706 | regs[R_MPD] |= 0x08; | ||
707 | break; | ||
708 | } | ||
709 | |||
710 | div = ((tda18271_main_pll[i].d * (N / 1000)) << 7) / 125; | ||
711 | regs[R_MD1] = 0xff & (div >> 16); | ||
712 | regs[R_MD2] = 0xff & (div >> 8); | ||
713 | regs[R_MD3] = 0xff & div; | ||
714 | |||
715 | tda18271_write_regs(fe, R_EP3, 11); | ||
716 | msleep(5); /* RF tracking filter calibration initialization */ | ||
717 | |||
718 | /* search for K,M,CO for RF Calibration */ | ||
719 | i = 0; | ||
720 | while ((tda18271_km[i].rfmax * 1000) < freq) { | ||
721 | if (tda18271_km[i + 1].rfmax == 0) | ||
722 | break; | ||
723 | i++; | ||
724 | } | ||
725 | tuner_extra_dbg("km = 0x%x, i = %d\n", tda18271_km[i].val, i); | ||
726 | |||
727 | regs[R_EB13] &= 0x83; | ||
728 | regs[R_EB13] |= tda18271_km[i].val; | ||
729 | tda18271_write_regs(fe, R_EB13, 1); | ||
730 | |||
731 | /* search for RF_BAND */ | ||
732 | i = 0; | ||
733 | while ((tda18271_rf_band[i].rfmax * 1000) < freq) { | ||
734 | if (tda18271_rf_band[i + 1].rfmax == 0) | ||
735 | break; | ||
736 | i++; | ||
737 | } | ||
738 | tuner_extra_dbg("rf band = 0x%x, i = %d\n", | ||
739 | tda18271_rf_band[i].val, i); | ||
740 | |||
741 | regs[R_EP2] &= ~0xe0; /* clear rf band bits */ | ||
742 | regs[R_EP2] |= (tda18271_rf_band[i].val << 5); | ||
743 | |||
744 | /* search for Gain_Taper */ | ||
745 | i = 0; | ||
746 | while ((tda18271_gain_taper[i].rfmax * 1000) < freq) { | ||
747 | if (tda18271_gain_taper[i + 1].rfmax == 0) | ||
748 | break; | ||
749 | i++; | ||
750 | } | ||
751 | tuner_extra_dbg("gain taper = 0x%x, i = %d\n", | ||
752 | tda18271_gain_taper[i].val, i); | ||
753 | |||
754 | regs[R_EP2] &= ~0x1f; /* clear gain taper bits */ | ||
755 | regs[R_EP2] |= tda18271_gain_taper[i].val; | ||
756 | |||
757 | tda18271_write_regs(fe, R_EP2, 1); | ||
758 | tda18271_write_regs(fe, R_EP1, 1); | ||
759 | tda18271_write_regs(fe, R_EP2, 1); | ||
760 | tda18271_write_regs(fe, R_EP1, 1); | ||
761 | |||
762 | regs[R_EB4] &= 0x07; | ||
763 | regs[R_EB4] |= 0x40; | ||
764 | tda18271_write_regs(fe, R_EB4, 1); | ||
765 | |||
766 | regs[R_EB7] = 0x40; | ||
767 | tda18271_write_regs(fe, R_EB7, 1); | ||
768 | msleep(10); | ||
769 | |||
770 | regs[R_EB20] = 0xec; | ||
771 | tda18271_write_regs(fe, R_EB20, 1); | ||
772 | msleep(60); /* RF tracking filter calibration completion */ | ||
773 | |||
774 | regs[R_EP4] &= ~0x03; /* set cal mode to normal */ | ||
775 | tda18271_write_regs(fe, R_EP4, 1); | ||
776 | |||
777 | tda18271_write_regs(fe, R_EP1, 1); | ||
778 | |||
779 | /* RF tracking filer correction for VHF_Low band */ | ||
780 | i = 0; | ||
781 | while ((tda18271_rf_cal[i].rfmax * 1000) < freq) { | ||
782 | if (tda18271_rf_cal[i].rfmax == 0) | ||
783 | break; | ||
784 | i++; | ||
785 | } | ||
786 | tuner_extra_dbg("rf cal = 0x%x, i = %d\n", tda18271_rf_cal[i].val, i); | ||
787 | |||
788 | /* VHF_Low band only */ | ||
789 | if (tda18271_rf_cal[i].rfmax != 0) { | ||
790 | regs[R_EB14] = tda18271_rf_cal[i].val; | ||
791 | tda18271_write_regs(fe, R_EB14, 1); | ||
792 | } | ||
793 | |||
794 | /* Channel Configuration */ | ||
795 | |||
796 | switch (priv->mode) { | ||
797 | case TDA18271_ANALOG: | ||
798 | regs[R_EB22] = 0x2c; | ||
799 | break; | ||
800 | case TDA18271_DIGITAL: | ||
801 | regs[R_EB22] = 0x37; | ||
802 | break; | ||
803 | } | ||
804 | tda18271_write_regs(fe, R_EB22, 1); | ||
805 | |||
806 | regs[R_EP1] |= 0x40; /* set dis power level on */ | ||
807 | |||
808 | /* set standard */ | ||
809 | regs[R_EP3] &= ~0x1f; /* clear std bits */ | ||
810 | |||
811 | /* see table 22 */ | ||
812 | regs[R_EP3] |= std; | ||
813 | |||
814 | /* TO DO: * | ||
815 | * ================ * | ||
816 | * FM radio, 0x18 * | ||
817 | * ATSC 6MHz, 0x1c * | ||
818 | * DVB-T 6MHz, 0x1c * | ||
819 | * DVB-T 7MHz, 0x1d * | ||
820 | * DVB-T 8MHz, 0x1e * | ||
821 | * QAM 6MHz, 0x1d * | ||
822 | * QAM 8MHz, 0x1f */ | ||
823 | |||
824 | regs[R_EP4] &= ~0x03; /* set cal mode to normal */ | ||
825 | |||
826 | regs[R_EP4] &= ~0x1c; /* clear if level bits */ | ||
827 | switch (priv->mode) { | ||
828 | case TDA18271_ANALOG: | ||
829 | regs[R_MPD] &= ~0x80; /* IF notch = 0 */ | ||
830 | break; | ||
831 | case TDA18271_DIGITAL: | ||
832 | regs[R_EP4] |= 0x04; | ||
833 | regs[R_MPD] |= 0x80; | ||
834 | break; | ||
835 | } | ||
836 | |||
837 | regs[R_EP4] &= ~0x80; /* turn this bit on only for fm */ | ||
838 | |||
839 | /* FIXME: image rejection validity EP5[2:0] */ | ||
840 | |||
841 | /* calculate MAIN PLL */ | ||
842 | N = freq + ifc; | ||
843 | |||
844 | i = 0; | ||
845 | while ((tda18271_main_pll[i].lomax * 1000) < N) { | ||
846 | if (tda18271_main_pll[i + 1].lomax == 0) | ||
847 | break; | ||
848 | i++; | ||
849 | } | ||
850 | tuner_extra_dbg("main pll, pd = 0x%x, d = 0x%x, i = %d\n", | ||
851 | tda18271_main_pll[i].pd, tda18271_main_pll[i].d, i); | ||
852 | |||
853 | regs[R_MPD] = (0x7f & tda18271_main_pll[i].pd); | ||
854 | switch (priv->mode) { | ||
855 | case TDA18271_ANALOG: | ||
856 | regs[R_MPD] &= ~0x08; | ||
857 | break; | ||
858 | case TDA18271_DIGITAL: | ||
859 | regs[R_MPD] |= 0x08; | ||
860 | break; | ||
861 | } | ||
862 | |||
863 | div = ((tda18271_main_pll[i].d * (N / 1000)) << 7) / 125; | ||
864 | regs[R_MD1] = 0xff & (div >> 16); | ||
865 | regs[R_MD2] = 0xff & (div >> 8); | ||
866 | regs[R_MD3] = 0xff & div; | ||
867 | |||
868 | tda18271_write_regs(fe, R_TM, 15); | ||
869 | msleep(5); | ||
870 | return 0; | ||
871 | } | ||
872 | |||
873 | /* ------------------------------------------------------------------ */ | ||
874 | |||
875 | static int tda18271_set_params(struct dvb_frontend *fe, | ||
876 | struct dvb_frontend_parameters *params) | ||
877 | { | ||
878 | struct tda18271_priv *priv = fe->tuner_priv; | ||
879 | u8 std; | ||
880 | u32 bw, sgIF = 0; | ||
881 | |||
882 | u32 freq = params->frequency; | ||
883 | |||
884 | priv->mode = TDA18271_DIGITAL; | ||
885 | |||
886 | /* see table 22 */ | ||
887 | if (fe->ops.info.type == FE_ATSC) { | ||
888 | switch (params->u.vsb.modulation) { | ||
889 | case VSB_8: | ||
890 | case VSB_16: | ||
891 | std = 0x1b; /* device-specific (spec says 0x1c) */ | ||
892 | sgIF = 5380000; | ||
893 | break; | ||
894 | case QAM_64: | ||
895 | case QAM_256: | ||
896 | std = 0x18; /* device-specific (spec says 0x1d) */ | ||
897 | sgIF = 4000000; | ||
898 | break; | ||
899 | default: | ||
900 | printk(KERN_WARNING "%s: modulation not set!\n", | ||
901 | __FUNCTION__); | ||
902 | return -EINVAL; | ||
903 | } | ||
904 | freq += 1750000; /* Adjust to center (+1.75MHZ) */ | ||
905 | bw = 6000000; | ||
906 | } else if (fe->ops.info.type == FE_OFDM) { | ||
907 | switch (params->u.ofdm.bandwidth) { | ||
908 | case BANDWIDTH_6_MHZ: | ||
909 | std = 0x1c; | ||
910 | bw = 6000000; | ||
911 | break; | ||
912 | case BANDWIDTH_7_MHZ: | ||
913 | std = 0x1d; | ||
914 | bw = 7000000; | ||
915 | break; | ||
916 | case BANDWIDTH_8_MHZ: | ||
917 | std = 0x1e; | ||
918 | bw = 8000000; | ||
919 | break; | ||
920 | default: | ||
921 | printk(KERN_WARNING "%s: bandwidth not set!\n", | ||
922 | __FUNCTION__); | ||
923 | return -EINVAL; | ||
924 | } | ||
925 | } else { | ||
926 | printk(KERN_WARNING "%s: modulation type not supported!\n", | ||
927 | __FUNCTION__); | ||
928 | return -EINVAL; | ||
929 | } | ||
930 | |||
931 | return tda18271_tune(fe, sgIF, freq, bw, std); | ||
932 | } | ||
933 | |||
934 | static int tda18271_set_analog_params(struct dvb_frontend *fe, | ||
935 | struct analog_parameters *params) | ||
936 | { | ||
937 | struct tda18271_priv *priv = fe->tuner_priv; | ||
938 | u8 std; | ||
939 | unsigned int sgIF; | ||
940 | char *mode; | ||
941 | |||
942 | priv->mode = TDA18271_ANALOG; | ||
943 | |||
944 | /* see table 22 */ | ||
945 | if (params->std & V4L2_STD_MN) { | ||
946 | std = 0x0d; | ||
947 | sgIF = 92; | ||
948 | mode = "MN"; | ||
949 | } else if (params->std & V4L2_STD_B) { | ||
950 | std = 0x0e; | ||
951 | sgIF = 108; | ||
952 | mode = "B"; | ||
953 | } else if (params->std & V4L2_STD_GH) { | ||
954 | std = 0x0f; | ||
955 | sgIF = 124; | ||
956 | mode = "GH"; | ||
957 | } else if (params->std & V4L2_STD_PAL_I) { | ||
958 | std = 0x0f; | ||
959 | sgIF = 124; | ||
960 | mode = "I"; | ||
961 | } else if (params->std & V4L2_STD_DK) { | ||
962 | std = 0x0f; | ||
963 | sgIF = 124; | ||
964 | mode = "DK"; | ||
965 | } else if (params->std & V4L2_STD_SECAM_L) { | ||
966 | std = 0x0f; | ||
967 | sgIF = 124; | ||
968 | mode = "L"; | ||
969 | } else if (params->std & V4L2_STD_SECAM_LC) { | ||
970 | std = 0x0f; | ||
971 | sgIF = 20; | ||
972 | mode = "LC"; | ||
973 | } else { | ||
974 | std = 0x0f; | ||
975 | sgIF = 124; | ||
976 | mode = "xx"; | ||
977 | } | ||
978 | |||
979 | if (params->mode == V4L2_TUNER_RADIO) | ||
980 | sgIF = 88; /* if frequency is 5.5 MHz */ | ||
981 | |||
982 | tuner_dbg("setting tda18271 to system %s\n", mode); | ||
983 | |||
984 | return tda18271_tune(fe, sgIF * 62500, params->frequency * 62500, | ||
985 | 0, std); | ||
986 | } | ||
987 | |||
988 | static int tda18271_release(struct dvb_frontend *fe) | ||
989 | { | ||
990 | kfree(fe->tuner_priv); | ||
991 | fe->tuner_priv = NULL; | ||
992 | return 0; | ||
993 | } | ||
994 | |||
995 | static int tda18271_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
996 | { | ||
997 | struct tda18271_priv *priv = fe->tuner_priv; | ||
998 | *frequency = priv->frequency; | ||
999 | return 0; | ||
1000 | } | ||
1001 | |||
1002 | static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) | ||
1003 | { | ||
1004 | struct tda18271_priv *priv = fe->tuner_priv; | ||
1005 | *bandwidth = priv->bandwidth; | ||
1006 | return 0; | ||
1007 | } | ||
1008 | |||
1009 | static struct dvb_tuner_ops tda18271_tuner_ops = { | ||
1010 | .info = { | ||
1011 | .name = "NXP TDA18271HD", | ||
1012 | .frequency_min = 45000000, | ||
1013 | .frequency_max = 864000000, | ||
1014 | .frequency_step = 62500 | ||
1015 | }, | ||
1016 | .set_params = tda18271_set_params, | ||
1017 | .set_analog_params = tda18271_set_analog_params, | ||
1018 | .release = tda18271_release, | ||
1019 | .get_frequency = tda18271_get_frequency, | ||
1020 | .get_bandwidth = tda18271_get_bandwidth, | ||
1021 | }; | ||
1022 | |||
1023 | struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, | ||
1024 | struct i2c_adapter *i2c) | ||
1025 | { | ||
1026 | struct tda18271_priv *priv = NULL; | ||
1027 | |||
1028 | tuner_dbg("%s:\n", __FUNCTION__); | ||
1029 | priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL); | ||
1030 | if (priv == NULL) | ||
1031 | return NULL; | ||
1032 | |||
1033 | priv->i2c_addr = addr; | ||
1034 | priv->i2c_adap = i2c; | ||
1035 | |||
1036 | memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops, | ||
1037 | sizeof(struct dvb_tuner_ops)); | ||
1038 | |||
1039 | fe->tuner_priv = priv; | ||
1040 | |||
1041 | return fe; | ||
1042 | } | ||
1043 | EXPORT_SYMBOL_GPL(tda18271_attach); | ||
1044 | MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver"); | ||
1045 | MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>"); | ||
1046 | MODULE_LICENSE("GPL"); | ||
1047 | |||
1048 | /* | ||
1049 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
1050 | * --------------------------------------------------------------------------- | ||
1051 | * Local variables: | ||
1052 | * c-basic-offset: 8 | ||
1053 | * End: | ||
1054 | */ | ||