Commit | Line | Data |
---|---|---|
5bea1cd3 MK |
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 | */ |