Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
1da177e4 LT |
2 | * |
3 | * i2c tv tuner chip device driver | |
4 | * controls all those simple 4-control-bytes style tuners. | |
5 | */ | |
6 | #include <linux/delay.h> | |
7 | #include <linux/i2c.h> | |
8 | #include <linux/videodev.h> | |
9 | #include <media/tuner.h> | |
ba8fc399 | 10 | #include <media/v4l2-common.h> |
8218b0b2 MK |
11 | #include <media/tuner-types.h> |
12 | #include "tuner-driver.h" | |
1da177e4 | 13 | |
5c07db0c | 14 | static int offset = 0; |
4d98816b | 15 | module_param(offset, int, 0664); |
5c07db0c MCC |
16 | MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner"); |
17 | ||
1da177e4 LT |
18 | /* ---------------------------------------------------------------------- */ |
19 | ||
20 | /* tv standard selection for Temic 4046 FM5 | |
21 | this value takes the low bits of control byte 2 | |
22 | from datasheet Rev.01, Feb.00 | |
23 | standard BG I L L2 D | |
24 | picture IF 38.9 38.9 38.9 33.95 38.9 | |
25 | sound 1 33.4 32.9 32.4 40.45 32.4 | |
26 | sound 2 33.16 | |
27 | NICAM 33.05 32.348 33.05 33.05 | |
28 | */ | |
29 | #define TEMIC_SET_PAL_I 0x05 | |
30 | #define TEMIC_SET_PAL_DK 0x09 | |
31 | #define TEMIC_SET_PAL_L 0x0a // SECAM ? | |
32 | #define TEMIC_SET_PAL_L2 0x0b // change IF ! | |
33 | #define TEMIC_SET_PAL_BG 0x0c | |
34 | ||
35 | /* tv tuner system standard selection for Philips FQ1216ME | |
36 | this value takes the low bits of control byte 2 | |
37 | from datasheet "1999 Nov 16" (supersedes "1999 Mar 23") | |
38 | standard BG DK I L L` | |
39 | picture carrier 38.90 38.90 38.90 38.90 33.95 | |
40 | colour 34.47 34.47 34.47 34.47 38.38 | |
41 | sound 1 33.40 32.40 32.90 32.40 40.45 | |
42 | sound 2 33.16 - - - - | |
43 | NICAM 33.05 33.05 32.35 33.05 39.80 | |
44 | */ | |
45 | #define PHILIPS_SET_PAL_I 0x01 /* Bit 2 always zero !*/ | |
46 | #define PHILIPS_SET_PAL_BGDK 0x09 | |
47 | #define PHILIPS_SET_PAL_L2 0x0a | |
48 | #define PHILIPS_SET_PAL_L 0x0b | |
49 | ||
50 | /* system switching for Philips FI1216MF MK2 | |
51 | from datasheet "1996 Jul 09", | |
52 | standard BG L L' | |
53 | picture carrier 38.90 38.90 33.95 | |
54 | colour 34.47 34.37 38.38 | |
55 | sound 1 33.40 32.40 40.45 | |
56 | sound 2 33.16 - - | |
57 | NICAM 33.05 33.05 39.80 | |
58 | */ | |
c57032de MCC |
59 | #define PHILIPS_MF_SET_STD_BG 0x01 /* Bit 2 must be zero, Bit 3 is system output */ |
60 | #define PHILIPS_MF_SET_STD_L 0x03 /* Used on Secam France */ | |
61 | #define PHILIPS_MF_SET_STD_LC 0x02 /* Used on SECAM L' */ | |
1da177e4 | 62 | |
f7ce3cc6 MCC |
63 | /* Control byte */ |
64 | ||
65 | #define TUNER_RATIO_MASK 0x06 /* Bit cb1:cb2 */ | |
66 | #define TUNER_RATIO_SELECT_50 0x00 | |
67 | #define TUNER_RATIO_SELECT_32 0x02 | |
68 | #define TUNER_RATIO_SELECT_166 0x04 | |
69 | #define TUNER_RATIO_SELECT_62 0x06 | |
70 | ||
71 | #define TUNER_CHARGE_PUMP 0x40 /* Bit cb6 */ | |
72 | ||
73 | /* Status byte */ | |
74 | ||
75 | #define TUNER_POR 0x80 | |
76 | #define TUNER_FL 0x40 | |
77 | #define TUNER_MODE 0x38 | |
78 | #define TUNER_AFC 0x07 | |
79 | #define TUNER_SIGNAL 0x07 | |
80 | #define TUNER_STEREO 0x10 | |
81 | ||
82 | #define TUNER_PLL_LOCKED 0x40 | |
83 | #define TUNER_STEREO_MK3 0x04 | |
1da177e4 | 84 | |
1da177e4 LT |
85 | /* ---------------------------------------------------------------------- */ |
86 | ||
87 | static int tuner_getstatus(struct i2c_client *c) | |
88 | { | |
89 | unsigned char byte; | |
90 | ||
91 | if (1 != i2c_master_recv(c,&byte,1)) | |
92 | return 0; | |
56fc08ca | 93 | |
1da177e4 LT |
94 | return byte; |
95 | } | |
96 | ||
1da177e4 LT |
97 | static int tuner_signal(struct i2c_client *c) |
98 | { | |
56fc08ca | 99 | return (tuner_getstatus(c) & TUNER_SIGNAL) << 13; |
1da177e4 LT |
100 | } |
101 | ||
102 | static int tuner_stereo(struct i2c_client *c) | |
103 | { | |
56fc08ca MCC |
104 | int stereo, status; |
105 | struct tuner *t = i2c_get_clientdata(c); | |
106 | ||
107 | status = tuner_getstatus (c); | |
108 | ||
109 | switch (t->type) { | |
4ac97914 | 110 | case TUNER_PHILIPS_FM1216ME_MK3: |
657de3cd | 111 | case TUNER_PHILIPS_FM1236_MK3: |
56fc08ca | 112 | case TUNER_PHILIPS_FM1256_IH3: |
122b5dbe | 113 | case TUNER_LG_NTSC_TAPE: |
56fc08ca MCC |
114 | stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); |
115 | break; | |
116 | default: | |
117 | stereo = status & TUNER_STEREO; | |
118 | } | |
119 | ||
120 | return stereo; | |
1da177e4 LT |
121 | } |
122 | ||
1da177e4 LT |
123 | |
124 | /* ---------------------------------------------------------------------- */ | |
125 | ||
126 | static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) | |
127 | { | |
128 | struct tuner *t = i2c_get_clientdata(c); | |
3fc46d35 | 129 | u8 config, cb, tuneraddr; |
1da177e4 LT |
130 | u16 div; |
131 | struct tunertype *tun; | |
27487d44 | 132 | u8 buffer[4]; |
7b0ac9cd | 133 | int rc, IFPCoff, i, j; |
476d63d0 | 134 | enum param_type desired_type; |
ba8fc399 | 135 | struct tuner_params *params; |
1da177e4 LT |
136 | |
137 | tun = &tuners[t->type]; | |
7b0ac9cd | 138 | |
5f594187 MK |
139 | /* IFPCoff = Video Intermediate Frequency - Vif: |
140 | 940 =16*58.75 NTSC/J (Japan) | |
141 | 732 =16*45.75 M/N STD | |
142 | 704 =16*44 ATSC (at DVB code) | |
143 | 632 =16*39.50 I U.K. | |
144 | 622.4=16*38.90 B/G D/K I, L STD | |
145 | 592 =16*37.00 D China | |
146 | 590 =16.36.875 B Australia | |
147 | 543.2=16*33.95 L' STD | |
148 | 171.2=16*10.70 FM Radio (at set_radio_freq) | |
149 | */ | |
150 | ||
151 | if (t->std == V4L2_STD_NTSC_M_JP) { | |
476d63d0 MK |
152 | IFPCoff = 940; |
153 | desired_type = TUNER_PARAM_TYPE_NTSC; | |
5f594187 MK |
154 | } else if ((t->std & V4L2_STD_MN) && |
155 | !(t->std & ~V4L2_STD_MN)) { | |
476d63d0 MK |
156 | IFPCoff = 732; |
157 | desired_type = TUNER_PARAM_TYPE_NTSC; | |
5f594187 | 158 | } else if (t->std == V4L2_STD_SECAM_LC) { |
476d63d0 MK |
159 | IFPCoff = 543; |
160 | desired_type = TUNER_PARAM_TYPE_SECAM; | |
5f594187 | 161 | } else { |
476d63d0 MK |
162 | IFPCoff = 623; |
163 | desired_type = TUNER_PARAM_TYPE_PAL; | |
5f594187 MK |
164 | } |
165 | ||
476d63d0 MK |
166 | for (j = 0; j < tun->count-1; j++) { |
167 | if (desired_type != tun->params[j].type) | |
168 | continue; | |
169 | break; | |
170 | } | |
8f1a58d0 | 171 | /* use default tuner_params if desired_type not available */ |
15207b2e MK |
172 | if (desired_type != tun->params[j].type) { |
173 | tuner_dbg("IFPCoff = %d: tuner_params undefined for tuner %d\n", | |
174 | IFPCoff,t->type); | |
8f1a58d0 | 175 | j = 0; |
15207b2e | 176 | } |
ba8fc399 | 177 | params = &tun->params[j]; |
8f1a58d0 | 178 | |
ba8fc399 HV |
179 | for (i = 0; i < params->count; i++) { |
180 | if (freq > params->ranges[i].limit) | |
90200d2b MK |
181 | continue; |
182 | break; | |
1da177e4 | 183 | } |
ba8fc399 | 184 | if (i == params->count) { |
27487d44 | 185 | tuner_dbg("TV frequency out of range (%d > %d)", |
ba8fc399 HV |
186 | freq, params->ranges[i - 1].limit); |
187 | freq = params->ranges[--i].limit; | |
27487d44 | 188 | } |
ba8fc399 HV |
189 | config = params->ranges[i].config; |
190 | cb = params->ranges[i].cb; | |
5f594187 MK |
191 | /* i == 0 -> VHF_LO |
192 | * i == 1 -> VHF_HI | |
193 | * i == 2 -> UHF */ | |
bd0d0f59 | 194 | tuner_dbg("tv: param %d, range %d\n",j,i); |
1da177e4 | 195 | |
5f594187 MK |
196 | div=freq + IFPCoff + offset; |
197 | ||
198 | tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n", | |
199 | freq / 16, freq % 16 * 100 / 16, | |
200 | IFPCoff / 16, IFPCoff % 16 * 100 / 16, | |
201 | offset / 16, offset % 16 * 100 / 16, | |
202 | div); | |
203 | ||
1da177e4 LT |
204 | /* tv norm specific stuff for multi-norm tuners */ |
205 | switch (t->type) { | |
206 | case TUNER_PHILIPS_SECAM: // FI1216MF | |
207 | /* 0x01 -> ??? no change ??? */ | |
208 | /* 0x02 -> PAL BDGHI / SECAM L */ | |
209 | /* 0x04 -> ??? PAL others / SECAM others ??? */ | |
82c01d3d | 210 | cb &= ~0x03; |
211 | if (t->std & V4L2_STD_SECAM_L) //also valid for V4L2_STD_SECAM | |
c57032de | 212 | cb |= PHILIPS_MF_SET_STD_L; |
82c01d3d | 213 | else if (t->std & V4L2_STD_SECAM_LC) |
c57032de | 214 | cb |= PHILIPS_MF_SET_STD_LC; |
82c01d3d | 215 | else /* V4L2_STD_B|V4L2_STD_GH */ |
c57032de | 216 | cb |= PHILIPS_MF_SET_STD_BG; |
1da177e4 LT |
217 | break; |
218 | ||
219 | case TUNER_TEMIC_4046FM5: | |
ab66b22f | 220 | cb &= ~0x0f; |
1da177e4 LT |
221 | |
222 | if (t->std & V4L2_STD_PAL_BG) { | |
ab66b22f | 223 | cb |= TEMIC_SET_PAL_BG; |
1da177e4 LT |
224 | |
225 | } else if (t->std & V4L2_STD_PAL_I) { | |
ab66b22f | 226 | cb |= TEMIC_SET_PAL_I; |
1da177e4 LT |
227 | |
228 | } else if (t->std & V4L2_STD_PAL_DK) { | |
ab66b22f | 229 | cb |= TEMIC_SET_PAL_DK; |
1da177e4 LT |
230 | |
231 | } else if (t->std & V4L2_STD_SECAM_L) { | |
ab66b22f | 232 | cb |= TEMIC_SET_PAL_L; |
1da177e4 LT |
233 | |
234 | } | |
235 | break; | |
236 | ||
237 | case TUNER_PHILIPS_FQ1216ME: | |
ab66b22f | 238 | cb &= ~0x0f; |
1da177e4 LT |
239 | |
240 | if (t->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) { | |
ab66b22f | 241 | cb |= PHILIPS_SET_PAL_BGDK; |
1da177e4 LT |
242 | |
243 | } else if (t->std & V4L2_STD_PAL_I) { | |
ab66b22f | 244 | cb |= PHILIPS_SET_PAL_I; |
1da177e4 LT |
245 | |
246 | } else if (t->std & V4L2_STD_SECAM_L) { | |
ab66b22f | 247 | cb |= PHILIPS_SET_PAL_L; |
1da177e4 LT |
248 | |
249 | } | |
250 | break; | |
251 | ||
252 | case TUNER_PHILIPS_ATSC: | |
253 | /* 0x00 -> ATSC antenna input 1 */ | |
254 | /* 0x01 -> ATSC antenna input 2 */ | |
255 | /* 0x02 -> NTSC antenna input 1 */ | |
256 | /* 0x03 -> NTSC antenna input 2 */ | |
ab66b22f | 257 | cb &= ~0x03; |
1da177e4 | 258 | if (!(t->std & V4L2_STD_ATSC)) |
ab66b22f | 259 | cb |= 2; |
1da177e4 LT |
260 | /* FIXME: input */ |
261 | break; | |
262 | ||
263 | case TUNER_MICROTUNE_4042FI5: | |
264 | /* Set the charge pump for fast tuning */ | |
3fc46d35 | 265 | config |= TUNER_CHARGE_PUMP; |
1da177e4 | 266 | break; |
e976f937 KL |
267 | |
268 | case TUNER_PHILIPS_TUV1236D: | |
269 | /* 0x40 -> ATSC antenna input 1 */ | |
270 | /* 0x48 -> ATSC antenna input 2 */ | |
271 | /* 0x00 -> NTSC antenna input 1 */ | |
272 | /* 0x08 -> NTSC antenna input 2 */ | |
fde6d31e KL |
273 | buffer[0] = 0x14; |
274 | buffer[1] = 0x00; | |
275 | buffer[2] = 0x17; | |
276 | buffer[3] = 0x00; | |
ab66b22f | 277 | cb &= ~0x40; |
fde6d31e | 278 | if (t->std & V4L2_STD_ATSC) { |
ab66b22f | 279 | cb |= 0x40; |
fde6d31e KL |
280 | buffer[1] = 0x04; |
281 | } | |
282 | /* set to the correct mode (analog or digital) */ | |
fde6d31e KL |
283 | tuneraddr = c->addr; |
284 | c->addr = 0x0a; | |
285 | if (2 != (rc = i2c_master_send(c,&buffer[0],2))) | |
286 | tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); | |
287 | if (2 != (rc = i2c_master_send(c,&buffer[2],2))) | |
288 | tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); | |
289 | c->addr = tuneraddr; | |
e976f937 KL |
290 | /* FIXME: input */ |
291 | break; | |
1da177e4 LT |
292 | } |
293 | ||
ba8fc399 | 294 | if (params->cb_first_if_lower_freq && div < t->last_div) { |
3fc46d35 | 295 | buffer[0] = config; |
ab66b22f | 296 | buffer[1] = cb; |
1da177e4 LT |
297 | buffer[2] = (div>>8) & 0x7f; |
298 | buffer[3] = div & 0xff; | |
299 | } else { | |
300 | buffer[0] = (div>>8) & 0x7f; | |
301 | buffer[1] = div & 0xff; | |
3fc46d35 | 302 | buffer[2] = config; |
ab66b22f | 303 | buffer[3] = cb; |
1da177e4 | 304 | } |
27487d44 | 305 | t->last_div = div; |
ba8fc399 HV |
306 | if (params->has_tda9887) { |
307 | int config = 0; | |
308 | int is_secam_l = (t->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) && | |
309 | !(t->std & ~(V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)); | |
310 | ||
311 | if (t->std == V4L2_STD_SECAM_LC) { | |
312 | if (params->port1_active ^ params->port1_invert_for_secam_lc) | |
313 | config |= TDA9887_PORT1_ACTIVE; | |
314 | if (params->port2_active ^ params->port2_invert_for_secam_lc) | |
315 | config |= TDA9887_PORT2_ACTIVE; | |
316 | } | |
317 | else { | |
318 | if (params->port1_active) | |
319 | config |= TDA9887_PORT1_ACTIVE; | |
320 | if (params->port2_active) | |
321 | config |= TDA9887_PORT2_ACTIVE; | |
322 | } | |
323 | if (params->intercarrier_mode) | |
324 | config |= TDA9887_INTERCARRIER; | |
325 | if (is_secam_l) { | |
326 | if (i == 0 && params->default_top_secam_low) | |
327 | config |= TDA9887_TOP(params->default_top_secam_low); | |
328 | else if (i == 1 && params->default_top_secam_mid) | |
329 | config |= TDA9887_TOP(params->default_top_secam_mid); | |
330 | else if (params->default_top_secam_high) | |
331 | config |= TDA9887_TOP(params->default_top_secam_high); | |
332 | } | |
333 | else { | |
334 | if (i == 0 && params->default_top_low) | |
335 | config |= TDA9887_TOP(params->default_top_low); | |
336 | else if (i == 1 && params->default_top_mid) | |
337 | config |= TDA9887_TOP(params->default_top_mid); | |
338 | else if (params->default_top_high) | |
339 | config |= TDA9887_TOP(params->default_top_high); | |
340 | } | |
d7304dee TP |
341 | if (params->default_pll_gating_18) |
342 | config |= TDA9887_GATING_18; | |
ba8fc399 HV |
343 | i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config); |
344 | } | |
1da177e4 LT |
345 | tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", |
346 | buffer[0],buffer[1],buffer[2],buffer[3]); | |
347 | ||
4ac97914 | 348 | if (4 != (rc = i2c_master_send(c,buffer,4))) |
1da177e4 LT |
349 | tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); |
350 | ||
d9cd2d9b MK |
351 | switch (t->type) { |
352 | case TUNER_LG_TDVS_H06XF: | |
353 | /* Set the Auxiliary Byte. */ | |
354 | buffer[0] = buffer[2]; | |
355 | buffer[0] &= ~0x20; | |
356 | buffer[0] |= 0x18; | |
357 | buffer[1] = 0x20; | |
358 | tuner_dbg("tv 0x%02x 0x%02x\n",buffer[0],buffer[1]); | |
359 | ||
360 | if (2 != (rc = i2c_master_send(c,buffer,2))) | |
361 | tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); | |
362 | break; | |
363 | case TUNER_MICROTUNE_4042FI5: | |
364 | { | |
1da177e4 LT |
365 | // FIXME - this may also work for other tuners |
366 | unsigned long timeout = jiffies + msecs_to_jiffies(1); | |
367 | u8 status_byte = 0; | |
368 | ||
369 | /* Wait until the PLL locks */ | |
370 | for (;;) { | |
371 | if (time_after(jiffies,timeout)) | |
372 | return; | |
373 | if (1 != (rc = i2c_master_recv(c,&status_byte,1))) { | |
374 | tuner_warn("i2c i/o read error: rc == %d (should be 1)\n",rc); | |
375 | break; | |
376 | } | |
f7ce3cc6 | 377 | if (status_byte & TUNER_PLL_LOCKED) |
1da177e4 LT |
378 | break; |
379 | udelay(10); | |
380 | } | |
381 | ||
382 | /* Set the charge pump for optimized phase noise figure */ | |
3fc46d35 | 383 | config &= ~TUNER_CHARGE_PUMP; |
1da177e4 LT |
384 | buffer[0] = (div>>8) & 0x7f; |
385 | buffer[1] = div & 0xff; | |
3fc46d35 | 386 | buffer[2] = config; |
ab66b22f | 387 | buffer[3] = cb; |
1da177e4 | 388 | tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", |
d9cd2d9b | 389 | buffer[0],buffer[1],buffer[2],buffer[3]); |
1da177e4 LT |
390 | |
391 | if (4 != (rc = i2c_master_send(c,buffer,4))) | |
392 | tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); | |
d9cd2d9b MK |
393 | break; |
394 | } | |
1da177e4 LT |
395 | } |
396 | } | |
397 | ||
398 | static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) | |
399 | { | |
400 | struct tunertype *tun; | |
401 | struct tuner *t = i2c_get_clientdata(c); | |
27487d44 HV |
402 | u8 buffer[4]; |
403 | u16 div; | |
7b0ac9cd | 404 | int rc, j; |
476d63d0 | 405 | enum param_type desired_type = TUNER_PARAM_TYPE_RADIO; |
ba8fc399 | 406 | struct tuner_params *params; |
1da177e4 | 407 | |
f7ce3cc6 | 408 | tun = &tuners[t->type]; |
476d63d0 MK |
409 | |
410 | for (j = 0; j < tun->count-1; j++) { | |
411 | if (desired_type != tun->params[j].type) | |
412 | continue; | |
413 | break; | |
414 | } | |
8f1a58d0 MK |
415 | /* use default tuner_params if desired_type not available */ |
416 | if (desired_type != tun->params[j].type) | |
417 | j = 0; | |
7b0ac9cd | 418 | |
f7ce3cc6 | 419 | div = (20 * freq / 16000) + (int)(20*10.7); /* IF 10.7 MHz */ |
ba8fc399 HV |
420 | params = &tun->params[j]; |
421 | buffer[2] = (params->ranges[0].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */ | |
1da177e4 LT |
422 | |
423 | switch (t->type) { | |
56fc08ca | 424 | case TUNER_TENA_9533_DI: |
391cd727 | 425 | case TUNER_YMEC_TVF_5533MF: |
f7ce3cc6 MCC |
426 | tuner_dbg ("This tuner doesn't have FM. Most cards has a TEA5767 for FM\n"); |
427 | return; | |
1da177e4 LT |
428 | case TUNER_PHILIPS_FM1216ME_MK3: |
429 | case TUNER_PHILIPS_FM1236_MK3: | |
586b0cab | 430 | case TUNER_PHILIPS_FMD1216ME_MK3: |
122b5dbe | 431 | case TUNER_LG_NTSC_TAPE: |
1da177e4 LT |
432 | buffer[3] = 0x19; |
433 | break; | |
efcf55cb MCC |
434 | case TUNER_TNF_5335MF: |
435 | buffer[3] = 0x11; | |
436 | break; | |
1da177e4 | 437 | case TUNER_PHILIPS_FM1256_IH3: |
f7ce3cc6 | 438 | div = (20 * freq) / 16000 + (int)(33.3 * 20); /* IF 33.3 MHz */ |
1da177e4 LT |
439 | buffer[3] = 0x19; |
440 | break; | |
441 | case TUNER_LG_PAL_FM: | |
442 | buffer[3] = 0xa5; | |
443 | break; | |
33ac6b52 MCC |
444 | case TUNER_MICROTUNE_4049FM5: |
445 | div = (20 * freq) / 16000 + (int)(33.3 * 20); /* IF 33.3 MHz */ | |
446 | buffer[3] = 0xa4; | |
447 | break; | |
1da177e4 LT |
448 | default: |
449 | buffer[3] = 0xa4; | |
450 | break; | |
451 | } | |
ba8fc399 | 452 | if (params->cb_first_if_lower_freq && div < t->last_div) { |
27487d44 HV |
453 | buffer[0] = buffer[2]; |
454 | buffer[1] = buffer[3]; | |
455 | buffer[2] = (div>>8) & 0x7f; | |
456 | buffer[3] = div & 0xff; | |
457 | } else { | |
458 | buffer[0] = (div>>8) & 0x7f; | |
459 | buffer[1] = div & 0xff; | |
460 | } | |
1da177e4 LT |
461 | |
462 | tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n", | |
463 | buffer[0],buffer[1],buffer[2],buffer[3]); | |
27487d44 | 464 | t->last_div = div; |
1da177e4 | 465 | |
ba8fc399 HV |
466 | if (params->has_tda9887) { |
467 | int config = 0; | |
468 | if (params->port1_active && !params->port1_fm_high_sensitivity) | |
469 | config |= TDA9887_PORT1_ACTIVE; | |
470 | if (params->port2_active && !params->port2_fm_high_sensitivity) | |
471 | config |= TDA9887_PORT2_ACTIVE; | |
472 | if (params->intercarrier_mode) | |
473 | config |= TDA9887_INTERCARRIER; | |
474 | /* if (params->port1_set_for_fm_mono) | |
475 | config &= ~TDA9887_PORT1_ACTIVE;*/ | |
483deb0f MCC |
476 | if (params->fm_gain_normal) |
477 | config |= TDA9887_GAIN_NORMAL; | |
ba8fc399 HV |
478 | i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config); |
479 | } | |
4ac97914 | 480 | if (4 != (rc = i2c_master_send(c,buffer,4))) |
1da177e4 LT |
481 | tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); |
482 | } | |
483 | ||
5d807c9f MK |
484 | static struct tuner_operations simple_tuner_ops = { |
485 | .set_tv_freq = default_set_tv_freq, | |
486 | .set_radio_freq = default_set_radio_freq, | |
487 | .has_signal = tuner_signal, | |
488 | .is_stereo = tuner_stereo, | |
489 | }; | |
490 | ||
1da177e4 LT |
491 | int default_tuner_init(struct i2c_client *c) |
492 | { | |
493 | struct tuner *t = i2c_get_clientdata(c); | |
494 | ||
495 | tuner_info("type set to %d (%s)\n", | |
496 | t->type, tuners[t->type].name); | |
497 | strlcpy(c->name, tuners[t->type].name, sizeof(c->name)); | |
498 | ||
5d807c9f | 499 | memcpy(&t->ops, &simple_tuner_ops, sizeof(struct tuner_operations)); |
586b0cab | 500 | |
1da177e4 LT |
501 | return 0; |
502 | } | |
503 | ||
504 | /* | |
505 | * Overrides for Emacs so that we follow Linus's tabbing style. | |
506 | * --------------------------------------------------------------------------- | |
507 | * Local variables: | |
508 | * c-basic-offset: 8 | |
509 | * End: | |
510 | */ |