diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-04-29 20:38:44 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-04-29 17:41:37 -0400 |
commit | 7c91f0624a9a2b8b9b122cf94fef34bc7f7347a6 (patch) | |
tree | e48220117475037125e86a3add48aa12cef7731f /drivers/media/common | |
parent | 5fe95e0b865060839449e1a61c1d5c67a4faab9a (diff) |
V4L/DVB(7767): Move tuners to common/tuners
There were several issues in the past, caused by the hybrid tuner design, since
now, the same tuner can be used by drivers/media/dvb and drivers/media/video.
Kconfig items were rearranged, to split V4L/DVB core from their drivers.
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/common')
29 files changed, 13196 insertions, 0 deletions
diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig new file mode 100644 index 000000000000..9a6a9022e970 --- /dev/null +++ b/drivers/media/common/tuners/Kconfig | |||
@@ -0,0 +1,118 @@ | |||
1 | config DVB_CORE_ATTACH | ||
2 | bool "Load and attach frontend driver modules as needed" | ||
3 | depends on DVB_CORE | ||
4 | depends on MODULES | ||
5 | help | ||
6 | Remove the static dependency of DVB card drivers on all | ||
7 | frontend modules for all possible card variants. Instead, | ||
8 | allow the card drivers to only load the frontend modules | ||
9 | they require. This saves several KBytes of memory. | ||
10 | |||
11 | Note: You will need module-init-tools v3.2 or later for this feature. | ||
12 | |||
13 | If unsure say Y. | ||
14 | |||
15 | config VIDEO_TUNER | ||
16 | tristate | ||
17 | default DVB_CORE || VIDEO_DEV | ||
18 | depends on DVB_CORE || VIDEO_DEV | ||
19 | select TUNER_XC2028 if !VIDEO_TUNER_CUSTOMIZE | ||
20 | select DVB_TUNER_XC5000 if !VIDEO_TUNER_CUSTOMIZE | ||
21 | select TUNER_MT20XX if !VIDEO_TUNER_CUSTOMIZE | ||
22 | select TUNER_TDA8290 if !VIDEO_TUNER_CUSTOMIZE | ||
23 | select TUNER_TEA5761 if !VIDEO_TUNER_CUSTOMIZE | ||
24 | select TUNER_TEA5767 if !VIDEO_TUNER_CUSTOMIZE | ||
25 | select TUNER_SIMPLE if !VIDEO_TUNER_CUSTOMIZE | ||
26 | select TUNER_TDA9887 if !VIDEO_TUNER_CUSTOMIZE | ||
27 | |||
28 | menuconfig VIDEO_TUNER_CUSTOMIZE | ||
29 | bool "Customize analog and hybrid tuner modules to build" | ||
30 | depends on VIDEO_TUNER | ||
31 | help | ||
32 | This allows the user to deselect tuner drivers unnecessary | ||
33 | for their hardware from the build. Use this option with care | ||
34 | as deselecting tuner drivers which are in fact necessary will | ||
35 | result in V4L/DVB devices which cannot be tuned due to lack of | ||
36 | driver support | ||
37 | |||
38 | If unsure say N. | ||
39 | |||
40 | if VIDEO_TUNER_CUSTOMIZE | ||
41 | |||
42 | config TUNER_SIMPLE | ||
43 | tristate "Simple tuner support" | ||
44 | depends on I2C | ||
45 | select TUNER_TDA9887 | ||
46 | default m if VIDEO_TUNER_CUSTOMIZE | ||
47 | help | ||
48 | Say Y here to include support for various simple tuners. | ||
49 | |||
50 | config TUNER_TDA8290 | ||
51 | tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo" | ||
52 | depends on I2C | ||
53 | select DVB_TDA827X | ||
54 | select DVB_TDA18271 | ||
55 | default m if VIDEO_TUNER_CUSTOMIZE | ||
56 | help | ||
57 | Say Y here to include support for Philips TDA8290+8275(a) tuner. | ||
58 | |||
59 | config DVB_TDA827X | ||
60 | tristate "Philips TDA827X silicon tuner" | ||
61 | depends on DVB_CORE && I2C | ||
62 | default m if DVB_FE_CUSTOMISE | ||
63 | help | ||
64 | A DVB-T silicon tuner module. Say Y when you want to support this tuner. | ||
65 | |||
66 | config DVB_TDA18271 | ||
67 | tristate "NXP TDA18271 silicon tuner" | ||
68 | depends on I2C | ||
69 | default m if DVB_FE_CUSTOMISE | ||
70 | help | ||
71 | A silicon tuner module. Say Y when you want to support this tuner. | ||
72 | |||
73 | config TUNER_TDA9887 | ||
74 | tristate "TDA 9885/6/7 analog IF demodulator" | ||
75 | depends on I2C | ||
76 | default m if VIDEO_TUNER_CUSTOMIZE | ||
77 | help | ||
78 | Say Y here to include support for Philips TDA9885/6/7 | ||
79 | analog IF demodulator. | ||
80 | |||
81 | config TUNER_TEA5761 | ||
82 | tristate "TEA 5761 radio tuner (EXPERIMENTAL)" | ||
83 | depends on I2C && EXPERIMENTAL | ||
84 | default m if VIDEO_TUNER_CUSTOMIZE | ||
85 | help | ||
86 | Say Y here to include support for the Philips TEA5761 radio tuner. | ||
87 | |||
88 | config TUNER_TEA5767 | ||
89 | tristate "TEA 5767 radio tuner" | ||
90 | depends on I2C | ||
91 | default m if VIDEO_TUNER_CUSTOMIZE | ||
92 | help | ||
93 | Say Y here to include support for the Philips TEA5767 radio tuner. | ||
94 | |||
95 | config TUNER_MT20XX | ||
96 | tristate "Microtune 2032 / 2050 tuners" | ||
97 | depends on I2C | ||
98 | default m if VIDEO_TUNER_CUSTOMIZE | ||
99 | help | ||
100 | Say Y here to include support for the MT2032 / MT2050 tuner. | ||
101 | |||
102 | config TUNER_XC2028 | ||
103 | tristate "XCeive xc2028/xc3028 tuners" | ||
104 | depends on I2C && FW_LOADER | ||
105 | default m if VIDEO_TUNER_CUSTOMIZE | ||
106 | help | ||
107 | Say Y here to include support for the xc2028/xc3028 tuners. | ||
108 | |||
109 | config DVB_TUNER_XC5000 | ||
110 | tristate "Xceive XC5000 silicon tuner" | ||
111 | depends on I2C | ||
112 | default m if DVB_FE_CUSTOMISE | ||
113 | help | ||
114 | A driver for the silicon tuner XC5000 from Xceive. | ||
115 | This device is only used inside a SiP called togther with a | ||
116 | demodulator for now. | ||
117 | |||
118 | endif # VIDEO_TUNER_CUSTOMIZE | ||
diff --git a/drivers/media/common/tuners/Makefile b/drivers/media/common/tuners/Makefile new file mode 100644 index 000000000000..685ae64fa3b8 --- /dev/null +++ b/drivers/media/common/tuners/Makefile | |||
@@ -0,0 +1,21 @@ | |||
1 | # | ||
2 | # Makefile for common V4L/DVB tuners | ||
3 | # | ||
4 | |||
5 | tda18271-objs := tda18271-maps.o tda18271-common.o tda18271-fe.o | ||
6 | |||
7 | obj-$(CONFIG_TUNER_XC2028) += tuner-xc2028.o | ||
8 | obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o | ||
9 | # tuner-types will be merged into tuner-simple, in the future | ||
10 | obj-$(CONFIG_TUNER_SIMPLE) += tuner-types.o | ||
11 | obj-$(CONFIG_TUNER_MT20XX) += mt20xx.o | ||
12 | obj-$(CONFIG_TUNER_TDA8290) += tda8290.o | ||
13 | obj-$(CONFIG_TUNER_TEA5767) += tea5767.o | ||
14 | obj-$(CONFIG_TUNER_TEA5761) += tea5761.o | ||
15 | obj-$(CONFIG_TUNER_TDA9887) += tda9887.o | ||
16 | obj-$(CONFIG_DVB_TDA827X) += tda827x.o | ||
17 | obj-$(CONFIG_DVB_TDA18271) += tda18271.o | ||
18 | obj-$(CONFIG_DVB_TUNER_XC5000) += xc5000.o | ||
19 | |||
20 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | ||
21 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | ||
diff --git a/drivers/media/common/tuners/mt20xx.c b/drivers/media/common/tuners/mt20xx.c new file mode 100644 index 000000000000..fbcb28233737 --- /dev/null +++ b/drivers/media/common/tuners/mt20xx.c | |||
@@ -0,0 +1,670 @@ | |||
1 | /* | ||
2 | * i2c tv tuner chip device driver | ||
3 | * controls microtune tuners, mt2032 + mt2050 at the moment. | ||
4 | * | ||
5 | * This "mt20xx" module was split apart from the original "tuner" module. | ||
6 | */ | ||
7 | #include <linux/delay.h> | ||
8 | #include <linux/i2c.h> | ||
9 | #include <linux/videodev.h> | ||
10 | #include "tuner-i2c.h" | ||
11 | #include "mt20xx.h" | ||
12 | |||
13 | static int debug; | ||
14 | module_param(debug, int, 0644); | ||
15 | MODULE_PARM_DESC(debug, "enable verbose debug messages"); | ||
16 | |||
17 | /* ---------------------------------------------------------------------- */ | ||
18 | |||
19 | static unsigned int optimize_vco = 1; | ||
20 | module_param(optimize_vco, int, 0644); | ||
21 | |||
22 | static unsigned int tv_antenna = 1; | ||
23 | module_param(tv_antenna, int, 0644); | ||
24 | |||
25 | static unsigned int radio_antenna; | ||
26 | module_param(radio_antenna, int, 0644); | ||
27 | |||
28 | /* ---------------------------------------------------------------------- */ | ||
29 | |||
30 | #define MT2032 0x04 | ||
31 | #define MT2030 0x06 | ||
32 | #define MT2040 0x07 | ||
33 | #define MT2050 0x42 | ||
34 | |||
35 | static char *microtune_part[] = { | ||
36 | [ MT2030 ] = "MT2030", | ||
37 | [ MT2032 ] = "MT2032", | ||
38 | [ MT2040 ] = "MT2040", | ||
39 | [ MT2050 ] = "MT2050", | ||
40 | }; | ||
41 | |||
42 | struct microtune_priv { | ||
43 | struct tuner_i2c_props i2c_props; | ||
44 | |||
45 | unsigned int xogc; | ||
46 | //unsigned int radio_if2; | ||
47 | |||
48 | u32 frequency; | ||
49 | }; | ||
50 | |||
51 | static int microtune_release(struct dvb_frontend *fe) | ||
52 | { | ||
53 | kfree(fe->tuner_priv); | ||
54 | fe->tuner_priv = NULL; | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | static int microtune_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
60 | { | ||
61 | struct microtune_priv *priv = fe->tuner_priv; | ||
62 | *frequency = priv->frequency; | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | // IsSpurInBand()? | ||
67 | static int mt2032_spurcheck(struct dvb_frontend *fe, | ||
68 | int f1, int f2, int spectrum_from,int spectrum_to) | ||
69 | { | ||
70 | struct microtune_priv *priv = fe->tuner_priv; | ||
71 | int n1=1,n2,f; | ||
72 | |||
73 | f1=f1/1000; //scale to kHz to avoid 32bit overflows | ||
74 | f2=f2/1000; | ||
75 | spectrum_from/=1000; | ||
76 | spectrum_to/=1000; | ||
77 | |||
78 | tuner_dbg("spurcheck f1=%d f2=%d from=%d to=%d\n", | ||
79 | f1,f2,spectrum_from,spectrum_to); | ||
80 | |||
81 | do { | ||
82 | n2=-n1; | ||
83 | f=n1*(f1-f2); | ||
84 | do { | ||
85 | n2--; | ||
86 | f=f-f2; | ||
87 | tuner_dbg("spurtest n1=%d n2=%d ftest=%d\n",n1,n2,f); | ||
88 | |||
89 | if( (f>spectrum_from) && (f<spectrum_to)) | ||
90 | tuner_dbg("mt2032 spurcheck triggered: %d\n",n1); | ||
91 | } while ( (f>(f2-spectrum_to)) || (n2>-5)); | ||
92 | n1++; | ||
93 | } while (n1<5); | ||
94 | |||
95 | return 1; | ||
96 | } | ||
97 | |||
98 | static int mt2032_compute_freq(struct dvb_frontend *fe, | ||
99 | unsigned int rfin, | ||
100 | unsigned int if1, unsigned int if2, | ||
101 | unsigned int spectrum_from, | ||
102 | unsigned int spectrum_to, | ||
103 | unsigned char *buf, | ||
104 | int *ret_sel, | ||
105 | unsigned int xogc) //all in Hz | ||
106 | { | ||
107 | struct microtune_priv *priv = fe->tuner_priv; | ||
108 | unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1, | ||
109 | desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq; | ||
110 | |||
111 | fref= 5250 *1000; //5.25MHz | ||
112 | desired_lo1=rfin+if1; | ||
113 | |||
114 | lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000); | ||
115 | lo1n=lo1/8; | ||
116 | lo1a=lo1-(lo1n*8); | ||
117 | |||
118 | s=rfin/1000/1000+1090; | ||
119 | |||
120 | if(optimize_vco) { | ||
121 | if(s>1890) sel=0; | ||
122 | else if(s>1720) sel=1; | ||
123 | else if(s>1530) sel=2; | ||
124 | else if(s>1370) sel=3; | ||
125 | else sel=4; // >1090 | ||
126 | } | ||
127 | else { | ||
128 | if(s>1790) sel=0; // <1958 | ||
129 | else if(s>1617) sel=1; | ||
130 | else if(s>1449) sel=2; | ||
131 | else if(s>1291) sel=3; | ||
132 | else sel=4; // >1090 | ||
133 | } | ||
134 | *ret_sel=sel; | ||
135 | |||
136 | lo1freq=(lo1a+8*lo1n)*fref; | ||
137 | |||
138 | tuner_dbg("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n", | ||
139 | rfin,lo1,lo1n,lo1a,sel,lo1freq); | ||
140 | |||
141 | desired_lo2=lo1freq-rfin-if2; | ||
142 | lo2=(desired_lo2)/fref; | ||
143 | lo2n=lo2/8; | ||
144 | lo2a=lo2-(lo2n*8); | ||
145 | lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith | ||
146 | lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000; | ||
147 | |||
148 | tuner_dbg("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n", | ||
149 | rfin,lo2,lo2n,lo2a,lo2num,lo2freq); | ||
150 | |||
151 | if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) { | ||
152 | tuner_info("mt2032: frequency parameters out of range: %d %d %d %d\n", | ||
153 | lo1a, lo1n, lo2a,lo2n); | ||
154 | return(-1); | ||
155 | } | ||
156 | |||
157 | mt2032_spurcheck(fe, lo1freq, desired_lo2, spectrum_from, spectrum_to); | ||
158 | // should recalculate lo1 (one step up/down) | ||
159 | |||
160 | // set up MT2032 register map for transfer over i2c | ||
161 | buf[0]=lo1n-1; | ||
162 | buf[1]=lo1a | (sel<<4); | ||
163 | buf[2]=0x86; // LOGC | ||
164 | buf[3]=0x0f; //reserved | ||
165 | buf[4]=0x1f; | ||
166 | buf[5]=(lo2n-1) | (lo2a<<5); | ||
167 | if(rfin >400*1000*1000) | ||
168 | buf[6]=0xe4; | ||
169 | else | ||
170 | buf[6]=0xf4; // set PKEN per rev 1.2 | ||
171 | buf[7]=8+xogc; | ||
172 | buf[8]=0xc3; //reserved | ||
173 | buf[9]=0x4e; //reserved | ||
174 | buf[10]=0xec; //reserved | ||
175 | buf[11]=(lo2num&0xff); | ||
176 | buf[12]=(lo2num>>8) |0x80; // Lo2RST | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | static int mt2032_check_lo_lock(struct dvb_frontend *fe) | ||
182 | { | ||
183 | struct microtune_priv *priv = fe->tuner_priv; | ||
184 | int try,lock=0; | ||
185 | unsigned char buf[2]; | ||
186 | |||
187 | for(try=0;try<10;try++) { | ||
188 | buf[0]=0x0e; | ||
189 | tuner_i2c_xfer_send(&priv->i2c_props,buf,1); | ||
190 | tuner_i2c_xfer_recv(&priv->i2c_props,buf,1); | ||
191 | tuner_dbg("mt2032 Reg.E=0x%02x\n",buf[0]); | ||
192 | lock=buf[0] &0x06; | ||
193 | |||
194 | if (lock==6) | ||
195 | break; | ||
196 | |||
197 | tuner_dbg("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]); | ||
198 | udelay(1000); | ||
199 | } | ||
200 | return lock; | ||
201 | } | ||
202 | |||
203 | static int mt2032_optimize_vco(struct dvb_frontend *fe,int sel,int lock) | ||
204 | { | ||
205 | struct microtune_priv *priv = fe->tuner_priv; | ||
206 | unsigned char buf[2]; | ||
207 | int tad1; | ||
208 | |||
209 | buf[0]=0x0f; | ||
210 | tuner_i2c_xfer_send(&priv->i2c_props,buf,1); | ||
211 | tuner_i2c_xfer_recv(&priv->i2c_props,buf,1); | ||
212 | tuner_dbg("mt2032 Reg.F=0x%02x\n",buf[0]); | ||
213 | tad1=buf[0]&0x07; | ||
214 | |||
215 | if(tad1 ==0) return lock; | ||
216 | if(tad1 ==1) return lock; | ||
217 | |||
218 | if(tad1==2) { | ||
219 | if(sel==0) | ||
220 | return lock; | ||
221 | else sel--; | ||
222 | } | ||
223 | else { | ||
224 | if(sel<4) | ||
225 | sel++; | ||
226 | else | ||
227 | return lock; | ||
228 | } | ||
229 | |||
230 | tuner_dbg("mt2032 optimize_vco: sel=%d\n",sel); | ||
231 | |||
232 | buf[0]=0x0f; | ||
233 | buf[1]=sel; | ||
234 | tuner_i2c_xfer_send(&priv->i2c_props,buf,2); | ||
235 | lock=mt2032_check_lo_lock(fe); | ||
236 | return lock; | ||
237 | } | ||
238 | |||
239 | |||
240 | static void mt2032_set_if_freq(struct dvb_frontend *fe, unsigned int rfin, | ||
241 | unsigned int if1, unsigned int if2, | ||
242 | unsigned int from, unsigned int to) | ||
243 | { | ||
244 | unsigned char buf[21]; | ||
245 | int lint_try,ret,sel,lock=0; | ||
246 | struct microtune_priv *priv = fe->tuner_priv; | ||
247 | |||
248 | tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n", | ||
249 | rfin,if1,if2,from,to); | ||
250 | |||
251 | buf[0]=0; | ||
252 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1); | ||
253 | tuner_i2c_xfer_recv(&priv->i2c_props,buf,21); | ||
254 | |||
255 | buf[0]=0; | ||
256 | ret=mt2032_compute_freq(fe,rfin,if1,if2,from,to,&buf[1],&sel,priv->xogc); | ||
257 | if (ret<0) | ||
258 | return; | ||
259 | |||
260 | // send only the relevant registers per Rev. 1.2 | ||
261 | buf[0]=0; | ||
262 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,4); | ||
263 | buf[5]=5; | ||
264 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,4); | ||
265 | buf[11]=11; | ||
266 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+11,3); | ||
267 | if(ret!=3) | ||
268 | tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret); | ||
269 | |||
270 | // wait for PLLs to lock (per manual), retry LINT if not. | ||
271 | for(lint_try=0; lint_try<2; lint_try++) { | ||
272 | lock=mt2032_check_lo_lock(fe); | ||
273 | |||
274 | if(optimize_vco) | ||
275 | lock=mt2032_optimize_vco(fe,sel,lock); | ||
276 | if(lock==6) break; | ||
277 | |||
278 | tuner_dbg("mt2032: re-init PLLs by LINT\n"); | ||
279 | buf[0]=7; | ||
280 | buf[1]=0x80 +8+priv->xogc; // set LINT to re-init PLLs | ||
281 | tuner_i2c_xfer_send(&priv->i2c_props,buf,2); | ||
282 | mdelay(10); | ||
283 | buf[1]=8+priv->xogc; | ||
284 | tuner_i2c_xfer_send(&priv->i2c_props,buf,2); | ||
285 | } | ||
286 | |||
287 | if (lock!=6) | ||
288 | tuner_warn("MT2032 Fatal Error: PLLs didn't lock.\n"); | ||
289 | |||
290 | buf[0]=2; | ||
291 | buf[1]=0x20; // LOGC for optimal phase noise | ||
292 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); | ||
293 | if (ret!=2) | ||
294 | tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret); | ||
295 | } | ||
296 | |||
297 | |||
298 | static int mt2032_set_tv_freq(struct dvb_frontend *fe, | ||
299 | struct analog_parameters *params) | ||
300 | { | ||
301 | int if2,from,to; | ||
302 | |||
303 | // signal bandwidth and picture carrier | ||
304 | if (params->std & V4L2_STD_525_60) { | ||
305 | // NTSC | ||
306 | from = 40750*1000; | ||
307 | to = 46750*1000; | ||
308 | if2 = 45750*1000; | ||
309 | } else { | ||
310 | // PAL | ||
311 | from = 32900*1000; | ||
312 | to = 39900*1000; | ||
313 | if2 = 38900*1000; | ||
314 | } | ||
315 | |||
316 | mt2032_set_if_freq(fe, params->frequency*62500, | ||
317 | 1090*1000*1000, if2, from, to); | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static int mt2032_set_radio_freq(struct dvb_frontend *fe, | ||
323 | struct analog_parameters *params) | ||
324 | { | ||
325 | struct microtune_priv *priv = fe->tuner_priv; | ||
326 | int if2; | ||
327 | |||
328 | if (params->std & V4L2_STD_525_60) { | ||
329 | tuner_dbg("pinnacle ntsc\n"); | ||
330 | if2 = 41300 * 1000; | ||
331 | } else { | ||
332 | tuner_dbg("pinnacle pal\n"); | ||
333 | if2 = 33300 * 1000; | ||
334 | } | ||
335 | |||
336 | // per Manual for FM tuning: first if center freq. 1085 MHz | ||
337 | mt2032_set_if_freq(fe, params->frequency * 125 / 2, | ||
338 | 1085*1000*1000,if2,if2,if2); | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static int mt2032_set_params(struct dvb_frontend *fe, | ||
344 | struct analog_parameters *params) | ||
345 | { | ||
346 | struct microtune_priv *priv = fe->tuner_priv; | ||
347 | int ret = -EINVAL; | ||
348 | |||
349 | switch (params->mode) { | ||
350 | case V4L2_TUNER_RADIO: | ||
351 | ret = mt2032_set_radio_freq(fe, params); | ||
352 | priv->frequency = params->frequency * 125 / 2; | ||
353 | break; | ||
354 | case V4L2_TUNER_ANALOG_TV: | ||
355 | case V4L2_TUNER_DIGITAL_TV: | ||
356 | ret = mt2032_set_tv_freq(fe, params); | ||
357 | priv->frequency = params->frequency * 62500; | ||
358 | break; | ||
359 | } | ||
360 | |||
361 | return ret; | ||
362 | } | ||
363 | |||
364 | static struct dvb_tuner_ops mt2032_tuner_ops = { | ||
365 | .set_analog_params = mt2032_set_params, | ||
366 | .release = microtune_release, | ||
367 | .get_frequency = microtune_get_frequency, | ||
368 | }; | ||
369 | |||
370 | // Initialization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001 | ||
371 | static int mt2032_init(struct dvb_frontend *fe) | ||
372 | { | ||
373 | struct microtune_priv *priv = fe->tuner_priv; | ||
374 | unsigned char buf[21]; | ||
375 | int ret,xogc,xok=0; | ||
376 | |||
377 | // Initialize Registers per spec. | ||
378 | buf[1]=2; // Index to register 2 | ||
379 | buf[2]=0xff; | ||
380 | buf[3]=0x0f; | ||
381 | buf[4]=0x1f; | ||
382 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+1,4); | ||
383 | |||
384 | buf[5]=6; // Index register 6 | ||
385 | buf[6]=0xe4; | ||
386 | buf[7]=0x8f; | ||
387 | buf[8]=0xc3; | ||
388 | buf[9]=0x4e; | ||
389 | buf[10]=0xec; | ||
390 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,6); | ||
391 | |||
392 | buf[12]=13; // Index register 13 | ||
393 | buf[13]=0x32; | ||
394 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+12,2); | ||
395 | |||
396 | // Adjust XOGC (register 7), wait for XOK | ||
397 | xogc=7; | ||
398 | do { | ||
399 | tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); | ||
400 | mdelay(10); | ||
401 | buf[0]=0x0e; | ||
402 | tuner_i2c_xfer_send(&priv->i2c_props,buf,1); | ||
403 | tuner_i2c_xfer_recv(&priv->i2c_props,buf,1); | ||
404 | xok=buf[0]&0x01; | ||
405 | tuner_dbg("mt2032: xok = 0x%02x\n",xok); | ||
406 | if (xok == 1) break; | ||
407 | |||
408 | xogc--; | ||
409 | tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); | ||
410 | if (xogc == 3) { | ||
411 | xogc=4; // min. 4 per spec | ||
412 | break; | ||
413 | } | ||
414 | buf[0]=0x07; | ||
415 | buf[1]=0x88 + xogc; | ||
416 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); | ||
417 | if (ret!=2) | ||
418 | tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret); | ||
419 | } while (xok != 1 ); | ||
420 | priv->xogc=xogc; | ||
421 | |||
422 | memcpy(&fe->ops.tuner_ops, &mt2032_tuner_ops, sizeof(struct dvb_tuner_ops)); | ||
423 | |||
424 | return(1); | ||
425 | } | ||
426 | |||
427 | static void mt2050_set_antenna(struct dvb_frontend *fe, unsigned char antenna) | ||
428 | { | ||
429 | struct microtune_priv *priv = fe->tuner_priv; | ||
430 | unsigned char buf[2]; | ||
431 | int ret; | ||
432 | |||
433 | buf[0] = 6; | ||
434 | buf[1] = antenna ? 0x11 : 0x10; | ||
435 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); | ||
436 | tuner_dbg("mt2050: enabled antenna connector %d\n", antenna); | ||
437 | } | ||
438 | |||
439 | static void mt2050_set_if_freq(struct dvb_frontend *fe,unsigned int freq, unsigned int if2) | ||
440 | { | ||
441 | struct microtune_priv *priv = fe->tuner_priv; | ||
442 | unsigned int if1=1218*1000*1000; | ||
443 | unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b; | ||
444 | int ret; | ||
445 | unsigned char buf[6]; | ||
446 | |||
447 | tuner_dbg("mt2050_set_if_freq freq=%d if1=%d if2=%d\n", | ||
448 | freq,if1,if2); | ||
449 | |||
450 | f_lo1=freq+if1; | ||
451 | f_lo1=(f_lo1/1000000)*1000000; | ||
452 | |||
453 | f_lo2=f_lo1-freq-if2; | ||
454 | f_lo2=(f_lo2/50000)*50000; | ||
455 | |||
456 | lo1=f_lo1/4000000; | ||
457 | lo2=f_lo2/4000000; | ||
458 | |||
459 | f_lo1_modulo= f_lo1-(lo1*4000000); | ||
460 | f_lo2_modulo= f_lo2-(lo2*4000000); | ||
461 | |||
462 | num1=4*f_lo1_modulo/4000000; | ||
463 | num2=4096*(f_lo2_modulo/1000)/4000; | ||
464 | |||
465 | // todo spurchecks | ||
466 | |||
467 | div1a=(lo1/12)-1; | ||
468 | div1b=lo1-(div1a+1)*12; | ||
469 | |||
470 | div2a=(lo2/8)-1; | ||
471 | div2b=lo2-(div2a+1)*8; | ||
472 | |||
473 | if (debug > 1) { | ||
474 | tuner_dbg("lo1 lo2 = %d %d\n", lo1, lo2); | ||
475 | tuner_dbg("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n", | ||
476 | num1,num2,div1a,div1b,div2a,div2b); | ||
477 | } | ||
478 | |||
479 | buf[0]=1; | ||
480 | buf[1]= 4*div1b + num1; | ||
481 | if(freq<275*1000*1000) buf[1] = buf[1]|0x80; | ||
482 | |||
483 | buf[2]=div1a; | ||
484 | buf[3]=32*div2b + num2/256; | ||
485 | buf[4]=num2-(num2/256)*256; | ||
486 | buf[5]=div2a; | ||
487 | if(num2!=0) buf[5]=buf[5]|0x40; | ||
488 | |||
489 | if (debug > 1) { | ||
490 | int i; | ||
491 | tuner_dbg("bufs is: "); | ||
492 | for(i=0;i<6;i++) | ||
493 | printk("%x ",buf[i]); | ||
494 | printk("\n"); | ||
495 | } | ||
496 | |||
497 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,6); | ||
498 | if (ret!=6) | ||
499 | tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret); | ||
500 | } | ||
501 | |||
502 | static int mt2050_set_tv_freq(struct dvb_frontend *fe, | ||
503 | struct analog_parameters *params) | ||
504 | { | ||
505 | unsigned int if2; | ||
506 | |||
507 | if (params->std & V4L2_STD_525_60) { | ||
508 | // NTSC | ||
509 | if2 = 45750*1000; | ||
510 | } else { | ||
511 | // PAL | ||
512 | if2 = 38900*1000; | ||
513 | } | ||
514 | if (V4L2_TUNER_DIGITAL_TV == params->mode) { | ||
515 | // DVB (pinnacle 300i) | ||
516 | if2 = 36150*1000; | ||
517 | } | ||
518 | mt2050_set_if_freq(fe, params->frequency*62500, if2); | ||
519 | mt2050_set_antenna(fe, tv_antenna); | ||
520 | |||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | static int mt2050_set_radio_freq(struct dvb_frontend *fe, | ||
525 | struct analog_parameters *params) | ||
526 | { | ||
527 | struct microtune_priv *priv = fe->tuner_priv; | ||
528 | int if2; | ||
529 | |||
530 | if (params->std & V4L2_STD_525_60) { | ||
531 | tuner_dbg("pinnacle ntsc\n"); | ||
532 | if2 = 41300 * 1000; | ||
533 | } else { | ||
534 | tuner_dbg("pinnacle pal\n"); | ||
535 | if2 = 33300 * 1000; | ||
536 | } | ||
537 | |||
538 | mt2050_set_if_freq(fe, params->frequency * 125 / 2, if2); | ||
539 | mt2050_set_antenna(fe, radio_antenna); | ||
540 | |||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | static int mt2050_set_params(struct dvb_frontend *fe, | ||
545 | struct analog_parameters *params) | ||
546 | { | ||
547 | struct microtune_priv *priv = fe->tuner_priv; | ||
548 | int ret = -EINVAL; | ||
549 | |||
550 | switch (params->mode) { | ||
551 | case V4L2_TUNER_RADIO: | ||
552 | ret = mt2050_set_radio_freq(fe, params); | ||
553 | priv->frequency = params->frequency * 125 / 2; | ||
554 | break; | ||
555 | case V4L2_TUNER_ANALOG_TV: | ||
556 | case V4L2_TUNER_DIGITAL_TV: | ||
557 | ret = mt2050_set_tv_freq(fe, params); | ||
558 | priv->frequency = params->frequency * 62500; | ||
559 | break; | ||
560 | } | ||
561 | |||
562 | return ret; | ||
563 | } | ||
564 | |||
565 | static struct dvb_tuner_ops mt2050_tuner_ops = { | ||
566 | .set_analog_params = mt2050_set_params, | ||
567 | .release = microtune_release, | ||
568 | .get_frequency = microtune_get_frequency, | ||
569 | }; | ||
570 | |||
571 | static int mt2050_init(struct dvb_frontend *fe) | ||
572 | { | ||
573 | struct microtune_priv *priv = fe->tuner_priv; | ||
574 | unsigned char buf[2]; | ||
575 | int ret; | ||
576 | |||
577 | buf[0]=6; | ||
578 | buf[1]=0x10; | ||
579 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // power | ||
580 | |||
581 | buf[0]=0x0f; | ||
582 | buf[1]=0x0f; | ||
583 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // m1lo | ||
584 | |||
585 | buf[0]=0x0d; | ||
586 | ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1); | ||
587 | tuner_i2c_xfer_recv(&priv->i2c_props,buf,1); | ||
588 | |||
589 | tuner_dbg("mt2050: sro is %x\n",buf[0]); | ||
590 | |||
591 | memcpy(&fe->ops.tuner_ops, &mt2050_tuner_ops, sizeof(struct dvb_tuner_ops)); | ||
592 | |||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | struct dvb_frontend *microtune_attach(struct dvb_frontend *fe, | ||
597 | struct i2c_adapter* i2c_adap, | ||
598 | u8 i2c_addr) | ||
599 | { | ||
600 | struct microtune_priv *priv = NULL; | ||
601 | char *name; | ||
602 | unsigned char buf[21]; | ||
603 | int company_code; | ||
604 | |||
605 | priv = kzalloc(sizeof(struct microtune_priv), GFP_KERNEL); | ||
606 | if (priv == NULL) | ||
607 | return NULL; | ||
608 | fe->tuner_priv = priv; | ||
609 | |||
610 | priv->i2c_props.addr = i2c_addr; | ||
611 | priv->i2c_props.adap = i2c_adap; | ||
612 | priv->i2c_props.name = "mt20xx"; | ||
613 | |||
614 | //priv->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */ | ||
615 | |||
616 | memset(buf,0,sizeof(buf)); | ||
617 | |||
618 | name = "unknown"; | ||
619 | |||
620 | tuner_i2c_xfer_send(&priv->i2c_props,buf,1); | ||
621 | tuner_i2c_xfer_recv(&priv->i2c_props,buf,21); | ||
622 | if (debug) { | ||
623 | int i; | ||
624 | tuner_dbg("MT20xx hexdump:"); | ||
625 | for(i=0;i<21;i++) { | ||
626 | printk(" %02x",buf[i]); | ||
627 | if(((i+1)%8)==0) printk(" "); | ||
628 | } | ||
629 | printk("\n"); | ||
630 | } | ||
631 | company_code = buf[0x11] << 8 | buf[0x12]; | ||
632 | tuner_info("microtune: companycode=%04x part=%02x rev=%02x\n", | ||
633 | company_code,buf[0x13],buf[0x14]); | ||
634 | |||
635 | |||
636 | if (buf[0x13] < ARRAY_SIZE(microtune_part) && | ||
637 | NULL != microtune_part[buf[0x13]]) | ||
638 | name = microtune_part[buf[0x13]]; | ||
639 | switch (buf[0x13]) { | ||
640 | case MT2032: | ||
641 | mt2032_init(fe); | ||
642 | break; | ||
643 | case MT2050: | ||
644 | mt2050_init(fe); | ||
645 | break; | ||
646 | default: | ||
647 | tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n", | ||
648 | name); | ||
649 | return NULL; | ||
650 | } | ||
651 | |||
652 | strlcpy(fe->ops.tuner_ops.info.name, name, | ||
653 | sizeof(fe->ops.tuner_ops.info.name)); | ||
654 | tuner_info("microtune %s found, OK\n",name); | ||
655 | return fe; | ||
656 | } | ||
657 | |||
658 | EXPORT_SYMBOL_GPL(microtune_attach); | ||
659 | |||
660 | MODULE_DESCRIPTION("Microtune tuner driver"); | ||
661 | MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); | ||
662 | MODULE_LICENSE("GPL"); | ||
663 | |||
664 | /* | ||
665 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
666 | * --------------------------------------------------------------------------- | ||
667 | * Local variables: | ||
668 | * c-basic-offset: 8 | ||
669 | * End: | ||
670 | */ | ||
diff --git a/drivers/media/common/tuners/mt20xx.h b/drivers/media/common/tuners/mt20xx.h new file mode 100644 index 000000000000..aa848e14ce5e --- /dev/null +++ b/drivers/media/common/tuners/mt20xx.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | This program is free software; you can redistribute it and/or modify | ||
3 | it under the terms of the GNU General Public License as published by | ||
4 | the Free Software Foundation; either version 2 of the License, or | ||
5 | (at your option) any later version. | ||
6 | |||
7 | This program is distributed in the hope that it will be useful, | ||
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | GNU General Public License for more details. | ||
11 | |||
12 | You should have received a copy of the GNU General Public License | ||
13 | along with this program; if not, write to the Free Software | ||
14 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
15 | */ | ||
16 | |||
17 | #ifndef __MT20XX_H__ | ||
18 | #define __MT20XX_H__ | ||
19 | |||
20 | #include <linux/i2c.h> | ||
21 | #include "dvb_frontend.h" | ||
22 | |||
23 | #if defined(CONFIG_TUNER_MT20XX) || (defined(CONFIG_TUNER_MT20XX_MODULE) && defined(MODULE)) | ||
24 | extern struct dvb_frontend *microtune_attach(struct dvb_frontend *fe, | ||
25 | struct i2c_adapter* i2c_adap, | ||
26 | u8 i2c_addr); | ||
27 | #else | ||
28 | static inline struct dvb_frontend *microtune_attach(struct dvb_frontend *fe, | ||
29 | struct i2c_adapter* i2c_adap, | ||
30 | u8 i2c_addr) | ||
31 | { | ||
32 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
33 | return NULL; | ||
34 | } | ||
35 | #endif | ||
36 | |||
37 | #endif /* __MT20XX_H__ */ | ||
diff --git a/drivers/media/common/tuners/tda18271-common.c b/drivers/media/common/tuners/tda18271-common.c new file mode 100644 index 000000000000..e27a7620a32f --- /dev/null +++ b/drivers/media/common/tuners/tda18271-common.c | |||
@@ -0,0 +1,666 @@ | |||
1 | /* | ||
2 | tda18271-common.c - driver for the Philips / NXP TDA18271 silicon tuner | ||
3 | |||
4 | Copyright (C) 2007, 2008 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 "tda18271-priv.h" | ||
22 | |||
23 | static int tda18271_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) | ||
24 | { | ||
25 | struct tda18271_priv *priv = fe->tuner_priv; | ||
26 | enum tda18271_i2c_gate gate; | ||
27 | int ret = 0; | ||
28 | |||
29 | switch (priv->gate) { | ||
30 | case TDA18271_GATE_DIGITAL: | ||
31 | case TDA18271_GATE_ANALOG: | ||
32 | gate = priv->gate; | ||
33 | break; | ||
34 | case TDA18271_GATE_AUTO: | ||
35 | default: | ||
36 | switch (priv->mode) { | ||
37 | case TDA18271_DIGITAL: | ||
38 | gate = TDA18271_GATE_DIGITAL; | ||
39 | break; | ||
40 | case TDA18271_ANALOG: | ||
41 | default: | ||
42 | gate = TDA18271_GATE_ANALOG; | ||
43 | break; | ||
44 | } | ||
45 | } | ||
46 | |||
47 | switch (gate) { | ||
48 | case TDA18271_GATE_ANALOG: | ||
49 | if (fe->ops.analog_ops.i2c_gate_ctrl) | ||
50 | ret = fe->ops.analog_ops.i2c_gate_ctrl(fe, enable); | ||
51 | break; | ||
52 | case TDA18271_GATE_DIGITAL: | ||
53 | if (fe->ops.i2c_gate_ctrl) | ||
54 | ret = fe->ops.i2c_gate_ctrl(fe, enable); | ||
55 | break; | ||
56 | default: | ||
57 | ret = -EINVAL; | ||
58 | break; | ||
59 | } | ||
60 | |||
61 | return ret; | ||
62 | }; | ||
63 | |||
64 | /*---------------------------------------------------------------------*/ | ||
65 | |||
66 | static void tda18271_dump_regs(struct dvb_frontend *fe, int extended) | ||
67 | { | ||
68 | struct tda18271_priv *priv = fe->tuner_priv; | ||
69 | unsigned char *regs = priv->tda18271_regs; | ||
70 | |||
71 | tda_reg("=== TDA18271 REG DUMP ===\n"); | ||
72 | tda_reg("ID_BYTE = 0x%02x\n", 0xff & regs[R_ID]); | ||
73 | tda_reg("THERMO_BYTE = 0x%02x\n", 0xff & regs[R_TM]); | ||
74 | tda_reg("POWER_LEVEL_BYTE = 0x%02x\n", 0xff & regs[R_PL]); | ||
75 | tda_reg("EASY_PROG_BYTE_1 = 0x%02x\n", 0xff & regs[R_EP1]); | ||
76 | tda_reg("EASY_PROG_BYTE_2 = 0x%02x\n", 0xff & regs[R_EP2]); | ||
77 | tda_reg("EASY_PROG_BYTE_3 = 0x%02x\n", 0xff & regs[R_EP3]); | ||
78 | tda_reg("EASY_PROG_BYTE_4 = 0x%02x\n", 0xff & regs[R_EP4]); | ||
79 | tda_reg("EASY_PROG_BYTE_5 = 0x%02x\n", 0xff & regs[R_EP5]); | ||
80 | tda_reg("CAL_POST_DIV_BYTE = 0x%02x\n", 0xff & regs[R_CPD]); | ||
81 | tda_reg("CAL_DIV_BYTE_1 = 0x%02x\n", 0xff & regs[R_CD1]); | ||
82 | tda_reg("CAL_DIV_BYTE_2 = 0x%02x\n", 0xff & regs[R_CD2]); | ||
83 | tda_reg("CAL_DIV_BYTE_3 = 0x%02x\n", 0xff & regs[R_CD3]); | ||
84 | tda_reg("MAIN_POST_DIV_BYTE = 0x%02x\n", 0xff & regs[R_MPD]); | ||
85 | tda_reg("MAIN_DIV_BYTE_1 = 0x%02x\n", 0xff & regs[R_MD1]); | ||
86 | tda_reg("MAIN_DIV_BYTE_2 = 0x%02x\n", 0xff & regs[R_MD2]); | ||
87 | tda_reg("MAIN_DIV_BYTE_3 = 0x%02x\n", 0xff & regs[R_MD3]); | ||
88 | |||
89 | /* only dump extended regs if DBG_ADV is set */ | ||
90 | if (!(tda18271_debug & DBG_ADV)) | ||
91 | return; | ||
92 | |||
93 | /* W indicates write-only registers. | ||
94 | * Register dump for write-only registers shows last value written. */ | ||
95 | |||
96 | tda_reg("EXTENDED_BYTE_1 = 0x%02x\n", 0xff & regs[R_EB1]); | ||
97 | tda_reg("EXTENDED_BYTE_2 = 0x%02x\n", 0xff & regs[R_EB2]); | ||
98 | tda_reg("EXTENDED_BYTE_3 = 0x%02x\n", 0xff & regs[R_EB3]); | ||
99 | tda_reg("EXTENDED_BYTE_4 = 0x%02x\n", 0xff & regs[R_EB4]); | ||
100 | tda_reg("EXTENDED_BYTE_5 = 0x%02x\n", 0xff & regs[R_EB5]); | ||
101 | tda_reg("EXTENDED_BYTE_6 = 0x%02x\n", 0xff & regs[R_EB6]); | ||
102 | tda_reg("EXTENDED_BYTE_7 = 0x%02x\n", 0xff & regs[R_EB7]); | ||
103 | tda_reg("EXTENDED_BYTE_8 = 0x%02x\n", 0xff & regs[R_EB8]); | ||
104 | tda_reg("EXTENDED_BYTE_9 W = 0x%02x\n", 0xff & regs[R_EB9]); | ||
105 | tda_reg("EXTENDED_BYTE_10 = 0x%02x\n", 0xff & regs[R_EB10]); | ||
106 | tda_reg("EXTENDED_BYTE_11 = 0x%02x\n", 0xff & regs[R_EB11]); | ||
107 | tda_reg("EXTENDED_BYTE_12 = 0x%02x\n", 0xff & regs[R_EB12]); | ||
108 | tda_reg("EXTENDED_BYTE_13 = 0x%02x\n", 0xff & regs[R_EB13]); | ||
109 | tda_reg("EXTENDED_BYTE_14 = 0x%02x\n", 0xff & regs[R_EB14]); | ||
110 | tda_reg("EXTENDED_BYTE_15 = 0x%02x\n", 0xff & regs[R_EB15]); | ||
111 | tda_reg("EXTENDED_BYTE_16 W = 0x%02x\n", 0xff & regs[R_EB16]); | ||
112 | tda_reg("EXTENDED_BYTE_17 W = 0x%02x\n", 0xff & regs[R_EB17]); | ||
113 | tda_reg("EXTENDED_BYTE_18 = 0x%02x\n", 0xff & regs[R_EB18]); | ||
114 | tda_reg("EXTENDED_BYTE_19 W = 0x%02x\n", 0xff & regs[R_EB19]); | ||
115 | tda_reg("EXTENDED_BYTE_20 W = 0x%02x\n", 0xff & regs[R_EB20]); | ||
116 | tda_reg("EXTENDED_BYTE_21 = 0x%02x\n", 0xff & regs[R_EB21]); | ||
117 | tda_reg("EXTENDED_BYTE_22 = 0x%02x\n", 0xff & regs[R_EB22]); | ||
118 | tda_reg("EXTENDED_BYTE_23 = 0x%02x\n", 0xff & regs[R_EB23]); | ||
119 | } | ||
120 | |||
121 | int tda18271_read_regs(struct dvb_frontend *fe) | ||
122 | { | ||
123 | struct tda18271_priv *priv = fe->tuner_priv; | ||
124 | unsigned char *regs = priv->tda18271_regs; | ||
125 | unsigned char buf = 0x00; | ||
126 | int ret; | ||
127 | struct i2c_msg msg[] = { | ||
128 | { .addr = priv->i2c_props.addr, .flags = 0, | ||
129 | .buf = &buf, .len = 1 }, | ||
130 | { .addr = priv->i2c_props.addr, .flags = I2C_M_RD, | ||
131 | .buf = regs, .len = 16 } | ||
132 | }; | ||
133 | |||
134 | tda18271_i2c_gate_ctrl(fe, 1); | ||
135 | |||
136 | /* read all registers */ | ||
137 | ret = i2c_transfer(priv->i2c_props.adap, msg, 2); | ||
138 | |||
139 | tda18271_i2c_gate_ctrl(fe, 0); | ||
140 | |||
141 | if (ret != 2) | ||
142 | tda_err("ERROR: i2c_transfer returned: %d\n", ret); | ||
143 | |||
144 | if (tda18271_debug & DBG_REG) | ||
145 | tda18271_dump_regs(fe, 0); | ||
146 | |||
147 | return (ret == 2 ? 0 : ret); | ||
148 | } | ||
149 | |||
150 | int tda18271_read_extended(struct dvb_frontend *fe) | ||
151 | { | ||
152 | struct tda18271_priv *priv = fe->tuner_priv; | ||
153 | unsigned char *regs = priv->tda18271_regs; | ||
154 | unsigned char regdump[TDA18271_NUM_REGS]; | ||
155 | unsigned char buf = 0x00; | ||
156 | int ret, i; | ||
157 | struct i2c_msg msg[] = { | ||
158 | { .addr = priv->i2c_props.addr, .flags = 0, | ||
159 | .buf = &buf, .len = 1 }, | ||
160 | { .addr = priv->i2c_props.addr, .flags = I2C_M_RD, | ||
161 | .buf = regdump, .len = TDA18271_NUM_REGS } | ||
162 | }; | ||
163 | |||
164 | tda18271_i2c_gate_ctrl(fe, 1); | ||
165 | |||
166 | /* read all registers */ | ||
167 | ret = i2c_transfer(priv->i2c_props.adap, msg, 2); | ||
168 | |||
169 | tda18271_i2c_gate_ctrl(fe, 0); | ||
170 | |||
171 | if (ret != 2) | ||
172 | tda_err("ERROR: i2c_transfer returned: %d\n", ret); | ||
173 | |||
174 | for (i = 0; i < TDA18271_NUM_REGS; i++) { | ||
175 | /* don't update write-only registers */ | ||
176 | if ((i != R_EB9) && | ||
177 | (i != R_EB16) && | ||
178 | (i != R_EB17) && | ||
179 | (i != R_EB19) && | ||
180 | (i != R_EB20)) | ||
181 | regs[i] = regdump[i]; | ||
182 | } | ||
183 | |||
184 | if (tda18271_debug & DBG_REG) | ||
185 | tda18271_dump_regs(fe, 1); | ||
186 | |||
187 | return (ret == 2 ? 0 : ret); | ||
188 | } | ||
189 | |||
190 | int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) | ||
191 | { | ||
192 | struct tda18271_priv *priv = fe->tuner_priv; | ||
193 | unsigned char *regs = priv->tda18271_regs; | ||
194 | unsigned char buf[TDA18271_NUM_REGS + 1]; | ||
195 | struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0, | ||
196 | .buf = buf, .len = len + 1 }; | ||
197 | int i, ret; | ||
198 | |||
199 | BUG_ON((len == 0) || (idx + len > sizeof(buf))); | ||
200 | |||
201 | buf[0] = idx; | ||
202 | for (i = 1; i <= len; i++) | ||
203 | buf[i] = regs[idx - 1 + i]; | ||
204 | |||
205 | tda18271_i2c_gate_ctrl(fe, 1); | ||
206 | |||
207 | /* write registers */ | ||
208 | ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); | ||
209 | |||
210 | tda18271_i2c_gate_ctrl(fe, 0); | ||
211 | |||
212 | if (ret != 1) | ||
213 | tda_err("ERROR: i2c_transfer returned: %d\n", ret); | ||
214 | |||
215 | return (ret == 1 ? 0 : ret); | ||
216 | } | ||
217 | |||
218 | /*---------------------------------------------------------------------*/ | ||
219 | |||
220 | int tda18271_charge_pump_source(struct dvb_frontend *fe, | ||
221 | enum tda18271_pll pll, int force) | ||
222 | { | ||
223 | struct tda18271_priv *priv = fe->tuner_priv; | ||
224 | unsigned char *regs = priv->tda18271_regs; | ||
225 | |||
226 | int r_cp = (pll == TDA18271_CAL_PLL) ? R_EB7 : R_EB4; | ||
227 | |||
228 | regs[r_cp] &= ~0x20; | ||
229 | regs[r_cp] |= ((force & 1) << 5); | ||
230 | tda18271_write_regs(fe, r_cp, 1); | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | int tda18271_init_regs(struct dvb_frontend *fe) | ||
236 | { | ||
237 | struct tda18271_priv *priv = fe->tuner_priv; | ||
238 | unsigned char *regs = priv->tda18271_regs; | ||
239 | |||
240 | tda_dbg("initializing registers for device @ %d-%04x\n", | ||
241 | i2c_adapter_id(priv->i2c_props.adap), | ||
242 | priv->i2c_props.addr); | ||
243 | |||
244 | /* initialize registers */ | ||
245 | switch (priv->id) { | ||
246 | case TDA18271HDC1: | ||
247 | regs[R_ID] = 0x83; | ||
248 | break; | ||
249 | case TDA18271HDC2: | ||
250 | regs[R_ID] = 0x84; | ||
251 | break; | ||
252 | }; | ||
253 | |||
254 | regs[R_TM] = 0x08; | ||
255 | regs[R_PL] = 0x80; | ||
256 | regs[R_EP1] = 0xc6; | ||
257 | regs[R_EP2] = 0xdf; | ||
258 | regs[R_EP3] = 0x16; | ||
259 | regs[R_EP4] = 0x60; | ||
260 | regs[R_EP5] = 0x80; | ||
261 | regs[R_CPD] = 0x80; | ||
262 | regs[R_CD1] = 0x00; | ||
263 | regs[R_CD2] = 0x00; | ||
264 | regs[R_CD3] = 0x00; | ||
265 | regs[R_MPD] = 0x00; | ||
266 | regs[R_MD1] = 0x00; | ||
267 | regs[R_MD2] = 0x00; | ||
268 | regs[R_MD3] = 0x00; | ||
269 | |||
270 | switch (priv->id) { | ||
271 | case TDA18271HDC1: | ||
272 | regs[R_EB1] = 0xff; | ||
273 | break; | ||
274 | case TDA18271HDC2: | ||
275 | regs[R_EB1] = 0xfc; | ||
276 | break; | ||
277 | }; | ||
278 | |||
279 | regs[R_EB2] = 0x01; | ||
280 | regs[R_EB3] = 0x84; | ||
281 | regs[R_EB4] = 0x41; | ||
282 | regs[R_EB5] = 0x01; | ||
283 | regs[R_EB6] = 0x84; | ||
284 | regs[R_EB7] = 0x40; | ||
285 | regs[R_EB8] = 0x07; | ||
286 | regs[R_EB9] = 0x00; | ||
287 | regs[R_EB10] = 0x00; | ||
288 | regs[R_EB11] = 0x96; | ||
289 | |||
290 | switch (priv->id) { | ||
291 | case TDA18271HDC1: | ||
292 | regs[R_EB12] = 0x0f; | ||
293 | break; | ||
294 | case TDA18271HDC2: | ||
295 | regs[R_EB12] = 0x33; | ||
296 | break; | ||
297 | }; | ||
298 | |||
299 | regs[R_EB13] = 0xc1; | ||
300 | regs[R_EB14] = 0x00; | ||
301 | regs[R_EB15] = 0x8f; | ||
302 | regs[R_EB16] = 0x00; | ||
303 | regs[R_EB17] = 0x00; | ||
304 | |||
305 | switch (priv->id) { | ||
306 | case TDA18271HDC1: | ||
307 | regs[R_EB18] = 0x00; | ||
308 | break; | ||
309 | case TDA18271HDC2: | ||
310 | regs[R_EB18] = 0x8c; | ||
311 | break; | ||
312 | }; | ||
313 | |||
314 | regs[R_EB19] = 0x00; | ||
315 | regs[R_EB20] = 0x20; | ||
316 | |||
317 | switch (priv->id) { | ||
318 | case TDA18271HDC1: | ||
319 | regs[R_EB21] = 0x33; | ||
320 | break; | ||
321 | case TDA18271HDC2: | ||
322 | regs[R_EB21] = 0xb3; | ||
323 | break; | ||
324 | }; | ||
325 | |||
326 | regs[R_EB22] = 0x48; | ||
327 | regs[R_EB23] = 0xb0; | ||
328 | |||
329 | if (priv->small_i2c) { | ||
330 | tda18271_write_regs(fe, 0x00, 0x10); | ||
331 | tda18271_write_regs(fe, 0x10, 0x10); | ||
332 | tda18271_write_regs(fe, 0x20, 0x07); | ||
333 | } else | ||
334 | tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS); | ||
335 | |||
336 | /* setup agc1 gain */ | ||
337 | regs[R_EB17] = 0x00; | ||
338 | tda18271_write_regs(fe, R_EB17, 1); | ||
339 | regs[R_EB17] = 0x03; | ||
340 | tda18271_write_regs(fe, R_EB17, 1); | ||
341 | regs[R_EB17] = 0x43; | ||
342 | tda18271_write_regs(fe, R_EB17, 1); | ||
343 | regs[R_EB17] = 0x4c; | ||
344 | tda18271_write_regs(fe, R_EB17, 1); | ||
345 | |||
346 | /* setup agc2 gain */ | ||
347 | if ((priv->id) == TDA18271HDC1) { | ||
348 | regs[R_EB20] = 0xa0; | ||
349 | tda18271_write_regs(fe, R_EB20, 1); | ||
350 | regs[R_EB20] = 0xa7; | ||
351 | tda18271_write_regs(fe, R_EB20, 1); | ||
352 | regs[R_EB20] = 0xe7; | ||
353 | tda18271_write_regs(fe, R_EB20, 1); | ||
354 | regs[R_EB20] = 0xec; | ||
355 | tda18271_write_regs(fe, R_EB20, 1); | ||
356 | } | ||
357 | |||
358 | /* image rejection calibration */ | ||
359 | |||
360 | /* low-band */ | ||
361 | regs[R_EP3] = 0x1f; | ||
362 | regs[R_EP4] = 0x66; | ||
363 | regs[R_EP5] = 0x81; | ||
364 | regs[R_CPD] = 0xcc; | ||
365 | regs[R_CD1] = 0x6c; | ||
366 | regs[R_CD2] = 0x00; | ||
367 | regs[R_CD3] = 0x00; | ||
368 | regs[R_MPD] = 0xcd; | ||
369 | regs[R_MD1] = 0x77; | ||
370 | regs[R_MD2] = 0x08; | ||
371 | regs[R_MD3] = 0x00; | ||
372 | |||
373 | tda18271_write_regs(fe, R_EP3, 11); | ||
374 | |||
375 | if ((priv->id) == TDA18271HDC2) { | ||
376 | /* main pll cp source on */ | ||
377 | tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1); | ||
378 | msleep(1); | ||
379 | |||
380 | /* main pll cp source off */ | ||
381 | tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0); | ||
382 | } | ||
383 | |||
384 | msleep(5); /* pll locking */ | ||
385 | |||
386 | /* launch detector */ | ||
387 | tda18271_write_regs(fe, R_EP1, 1); | ||
388 | msleep(5); /* wanted low measurement */ | ||
389 | |||
390 | regs[R_EP5] = 0x85; | ||
391 | regs[R_CPD] = 0xcb; | ||
392 | regs[R_CD1] = 0x66; | ||
393 | regs[R_CD2] = 0x70; | ||
394 | |||
395 | tda18271_write_regs(fe, R_EP3, 7); | ||
396 | msleep(5); /* pll locking */ | ||
397 | |||
398 | /* launch optimization algorithm */ | ||
399 | tda18271_write_regs(fe, R_EP2, 1); | ||
400 | msleep(30); /* image low optimization completion */ | ||
401 | |||
402 | /* mid-band */ | ||
403 | regs[R_EP5] = 0x82; | ||
404 | regs[R_CPD] = 0xa8; | ||
405 | regs[R_CD2] = 0x00; | ||
406 | regs[R_MPD] = 0xa9; | ||
407 | regs[R_MD1] = 0x73; | ||
408 | regs[R_MD2] = 0x1a; | ||
409 | |||
410 | tda18271_write_regs(fe, R_EP3, 11); | ||
411 | msleep(5); /* pll locking */ | ||
412 | |||
413 | /* launch detector */ | ||
414 | tda18271_write_regs(fe, R_EP1, 1); | ||
415 | msleep(5); /* wanted mid measurement */ | ||
416 | |||
417 | regs[R_EP5] = 0x86; | ||
418 | regs[R_CPD] = 0xa8; | ||
419 | regs[R_CD1] = 0x66; | ||
420 | regs[R_CD2] = 0xa0; | ||
421 | |||
422 | tda18271_write_regs(fe, R_EP3, 7); | ||
423 | msleep(5); /* pll locking */ | ||
424 | |||
425 | /* launch optimization algorithm */ | ||
426 | tda18271_write_regs(fe, R_EP2, 1); | ||
427 | msleep(30); /* image mid optimization completion */ | ||
428 | |||
429 | /* high-band */ | ||
430 | regs[R_EP5] = 0x83; | ||
431 | regs[R_CPD] = 0x98; | ||
432 | regs[R_CD1] = 0x65; | ||
433 | regs[R_CD2] = 0x00; | ||
434 | regs[R_MPD] = 0x99; | ||
435 | regs[R_MD1] = 0x71; | ||
436 | regs[R_MD2] = 0xcd; | ||
437 | |||
438 | tda18271_write_regs(fe, R_EP3, 11); | ||
439 | msleep(5); /* pll locking */ | ||
440 | |||
441 | /* launch detector */ | ||
442 | tda18271_write_regs(fe, R_EP1, 1); | ||
443 | msleep(5); /* wanted high measurement */ | ||
444 | |||
445 | regs[R_EP5] = 0x87; | ||
446 | regs[R_CD1] = 0x65; | ||
447 | regs[R_CD2] = 0x50; | ||
448 | |||
449 | tda18271_write_regs(fe, R_EP3, 7); | ||
450 | msleep(5); /* pll locking */ | ||
451 | |||
452 | /* launch optimization algorithm */ | ||
453 | tda18271_write_regs(fe, R_EP2, 1); | ||
454 | msleep(30); /* image high optimization completion */ | ||
455 | |||
456 | /* return to normal mode */ | ||
457 | regs[R_EP4] = 0x64; | ||
458 | tda18271_write_regs(fe, R_EP4, 1); | ||
459 | |||
460 | /* synchronize */ | ||
461 | tda18271_write_regs(fe, R_EP1, 1); | ||
462 | |||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | /*---------------------------------------------------------------------*/ | ||
467 | |||
468 | /* | ||
469 | * Standby modes, EP3 [7:5] | ||
470 | * | ||
471 | * | SM || SM_LT || SM_XT || mode description | ||
472 | * |=====\\=======\\=======\\=================================== | ||
473 | * | 0 || 0 || 0 || normal mode | ||
474 | * |-----||-------||-------||----------------------------------- | ||
475 | * | || || || standby mode w/ slave tuner output | ||
476 | * | 1 || 0 || 0 || & loop thru & xtal oscillator on | ||
477 | * |-----||-------||-------||----------------------------------- | ||
478 | * | 1 || 1 || 0 || standby mode w/ xtal oscillator on | ||
479 | * |-----||-------||-------||----------------------------------- | ||
480 | * | 1 || 1 || 1 || power off | ||
481 | * | ||
482 | */ | ||
483 | |||
484 | int tda18271_set_standby_mode(struct dvb_frontend *fe, | ||
485 | int sm, int sm_lt, int sm_xt) | ||
486 | { | ||
487 | struct tda18271_priv *priv = fe->tuner_priv; | ||
488 | unsigned char *regs = priv->tda18271_regs; | ||
489 | |||
490 | tda_dbg("sm = %d, sm_lt = %d, sm_xt = %d\n", sm, sm_lt, sm_xt); | ||
491 | |||
492 | regs[R_EP3] &= ~0xe0; /* clear sm, sm_lt, sm_xt */ | ||
493 | regs[R_EP3] |= sm ? (1 << 7) : 0 | | ||
494 | sm_lt ? (1 << 6) : 0 | | ||
495 | sm_xt ? (1 << 5) : 0; | ||
496 | |||
497 | tda18271_write_regs(fe, R_EP3, 1); | ||
498 | |||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | /*---------------------------------------------------------------------*/ | ||
503 | |||
504 | int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq) | ||
505 | { | ||
506 | /* sets main post divider & divider bytes, but does not write them */ | ||
507 | struct tda18271_priv *priv = fe->tuner_priv; | ||
508 | unsigned char *regs = priv->tda18271_regs; | ||
509 | u8 d, pd; | ||
510 | u32 div; | ||
511 | |||
512 | int ret = tda18271_lookup_pll_map(fe, MAIN_PLL, &freq, &pd, &d); | ||
513 | if (ret < 0) | ||
514 | goto fail; | ||
515 | |||
516 | regs[R_MPD] = (0x77 & pd); | ||
517 | |||
518 | switch (priv->mode) { | ||
519 | case TDA18271_ANALOG: | ||
520 | regs[R_MPD] &= ~0x08; | ||
521 | break; | ||
522 | case TDA18271_DIGITAL: | ||
523 | regs[R_MPD] |= 0x08; | ||
524 | break; | ||
525 | } | ||
526 | |||
527 | div = ((d * (freq / 1000)) << 7) / 125; | ||
528 | |||
529 | regs[R_MD1] = 0x7f & (div >> 16); | ||
530 | regs[R_MD2] = 0xff & (div >> 8); | ||
531 | regs[R_MD3] = 0xff & div; | ||
532 | fail: | ||
533 | return ret; | ||
534 | } | ||
535 | |||
536 | int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq) | ||
537 | { | ||
538 | /* sets cal post divider & divider bytes, but does not write them */ | ||
539 | struct tda18271_priv *priv = fe->tuner_priv; | ||
540 | unsigned char *regs = priv->tda18271_regs; | ||
541 | u8 d, pd; | ||
542 | u32 div; | ||
543 | |||
544 | int ret = tda18271_lookup_pll_map(fe, CAL_PLL, &freq, &pd, &d); | ||
545 | if (ret < 0) | ||
546 | goto fail; | ||
547 | |||
548 | regs[R_CPD] = pd; | ||
549 | |||
550 | div = ((d * (freq / 1000)) << 7) / 125; | ||
551 | |||
552 | regs[R_CD1] = 0x7f & (div >> 16); | ||
553 | regs[R_CD2] = 0xff & (div >> 8); | ||
554 | regs[R_CD3] = 0xff & div; | ||
555 | fail: | ||
556 | return ret; | ||
557 | } | ||
558 | |||
559 | /*---------------------------------------------------------------------*/ | ||
560 | |||
561 | int tda18271_calc_bp_filter(struct dvb_frontend *fe, u32 *freq) | ||
562 | { | ||
563 | /* sets bp filter bits, but does not write them */ | ||
564 | struct tda18271_priv *priv = fe->tuner_priv; | ||
565 | unsigned char *regs = priv->tda18271_regs; | ||
566 | u8 val; | ||
567 | |||
568 | int ret = tda18271_lookup_map(fe, BP_FILTER, freq, &val); | ||
569 | if (ret < 0) | ||
570 | goto fail; | ||
571 | |||
572 | regs[R_EP1] &= ~0x07; /* clear bp filter bits */ | ||
573 | regs[R_EP1] |= (0x07 & val); | ||
574 | fail: | ||
575 | return ret; | ||
576 | } | ||
577 | |||
578 | int tda18271_calc_km(struct dvb_frontend *fe, u32 *freq) | ||
579 | { | ||
580 | /* sets K & M bits, but does not write them */ | ||
581 | struct tda18271_priv *priv = fe->tuner_priv; | ||
582 | unsigned char *regs = priv->tda18271_regs; | ||
583 | u8 val; | ||
584 | |||
585 | int ret = tda18271_lookup_map(fe, RF_CAL_KMCO, freq, &val); | ||
586 | if (ret < 0) | ||
587 | goto fail; | ||
588 | |||
589 | regs[R_EB13] &= ~0x7c; /* clear k & m bits */ | ||
590 | regs[R_EB13] |= (0x7c & val); | ||
591 | fail: | ||
592 | return ret; | ||
593 | } | ||
594 | |||
595 | int tda18271_calc_rf_band(struct dvb_frontend *fe, u32 *freq) | ||
596 | { | ||
597 | /* sets rf band bits, but does not write them */ | ||
598 | struct tda18271_priv *priv = fe->tuner_priv; | ||
599 | unsigned char *regs = priv->tda18271_regs; | ||
600 | u8 val; | ||
601 | |||
602 | int ret = tda18271_lookup_map(fe, RF_BAND, freq, &val); | ||
603 | if (ret < 0) | ||
604 | goto fail; | ||
605 | |||
606 | regs[R_EP2] &= ~0xe0; /* clear rf band bits */ | ||
607 | regs[R_EP2] |= (0xe0 & (val << 5)); | ||
608 | fail: | ||
609 | return ret; | ||
610 | } | ||
611 | |||
612 | int tda18271_calc_gain_taper(struct dvb_frontend *fe, u32 *freq) | ||
613 | { | ||
614 | /* sets gain taper bits, but does not write them */ | ||
615 | struct tda18271_priv *priv = fe->tuner_priv; | ||
616 | unsigned char *regs = priv->tda18271_regs; | ||
617 | u8 val; | ||
618 | |||
619 | int ret = tda18271_lookup_map(fe, GAIN_TAPER, freq, &val); | ||
620 | if (ret < 0) | ||
621 | goto fail; | ||
622 | |||
623 | regs[R_EP2] &= ~0x1f; /* clear gain taper bits */ | ||
624 | regs[R_EP2] |= (0x1f & val); | ||
625 | fail: | ||
626 | return ret; | ||
627 | } | ||
628 | |||
629 | int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq) | ||
630 | { | ||
631 | /* sets IR Meas bits, but does not write them */ | ||
632 | struct tda18271_priv *priv = fe->tuner_priv; | ||
633 | unsigned char *regs = priv->tda18271_regs; | ||
634 | u8 val; | ||
635 | |||
636 | int ret = tda18271_lookup_map(fe, IR_MEASURE, freq, &val); | ||
637 | if (ret < 0) | ||
638 | goto fail; | ||
639 | |||
640 | regs[R_EP5] &= ~0x07; | ||
641 | regs[R_EP5] |= (0x07 & val); | ||
642 | fail: | ||
643 | return ret; | ||
644 | } | ||
645 | |||
646 | int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq) | ||
647 | { | ||
648 | /* sets rf cal byte (RFC_Cprog), but does not write it */ | ||
649 | struct tda18271_priv *priv = fe->tuner_priv; | ||
650 | unsigned char *regs = priv->tda18271_regs; | ||
651 | u8 val; | ||
652 | |||
653 | tda18271_lookup_map(fe, RF_CAL, freq, &val); | ||
654 | |||
655 | regs[R_EB14] = val; | ||
656 | |||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | /* | ||
661 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
662 | * --------------------------------------------------------------------------- | ||
663 | * Local variables: | ||
664 | * c-basic-offset: 8 | ||
665 | * End: | ||
666 | */ | ||
diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c new file mode 100644 index 000000000000..b262100ae897 --- /dev/null +++ b/drivers/media/common/tuners/tda18271-fe.c | |||
@@ -0,0 +1,1153 @@ | |||
1 | /* | ||
2 | tda18271-fe.c - driver for the Philips / NXP TDA18271 silicon tuner | ||
3 | |||
4 | Copyright (C) 2007, 2008 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/delay.h> | ||
22 | #include <linux/videodev2.h> | ||
23 | #include "tda18271-priv.h" | ||
24 | |||
25 | int tda18271_debug; | ||
26 | module_param_named(debug, tda18271_debug, int, 0644); | ||
27 | MODULE_PARM_DESC(debug, "set debug level " | ||
28 | "(info=1, map=2, reg=4, adv=8, cal=16 (or-able))"); | ||
29 | |||
30 | static int tda18271_cal_on_startup; | ||
31 | module_param_named(cal, tda18271_cal_on_startup, int, 0644); | ||
32 | MODULE_PARM_DESC(cal, "perform RF tracking filter calibration on startup"); | ||
33 | |||
34 | static DEFINE_MUTEX(tda18271_list_mutex); | ||
35 | static LIST_HEAD(hybrid_tuner_instance_list); | ||
36 | |||
37 | /*---------------------------------------------------------------------*/ | ||
38 | |||
39 | static inline int charge_pump_source(struct dvb_frontend *fe, int force) | ||
40 | { | ||
41 | struct tda18271_priv *priv = fe->tuner_priv; | ||
42 | return tda18271_charge_pump_source(fe, | ||
43 | (priv->role == TDA18271_SLAVE) ? | ||
44 | TDA18271_CAL_PLL : | ||
45 | TDA18271_MAIN_PLL, force); | ||
46 | } | ||
47 | |||
48 | static int tda18271_channel_configuration(struct dvb_frontend *fe, | ||
49 | struct tda18271_std_map_item *map, | ||
50 | u32 freq, u32 bw) | ||
51 | { | ||
52 | struct tda18271_priv *priv = fe->tuner_priv; | ||
53 | unsigned char *regs = priv->tda18271_regs; | ||
54 | u32 N; | ||
55 | |||
56 | /* update TV broadcast parameters */ | ||
57 | |||
58 | /* set standard */ | ||
59 | regs[R_EP3] &= ~0x1f; /* clear std bits */ | ||
60 | regs[R_EP3] |= (map->agc_mode << 3) | map->std; | ||
61 | |||
62 | /* set rfagc to high speed mode */ | ||
63 | regs[R_EP3] &= ~0x04; | ||
64 | |||
65 | /* set cal mode to normal */ | ||
66 | regs[R_EP4] &= ~0x03; | ||
67 | |||
68 | /* update IF output level & IF notch frequency */ | ||
69 | regs[R_EP4] &= ~0x1c; /* clear if level bits */ | ||
70 | regs[R_EP4] |= (map->if_lvl << 2); | ||
71 | |||
72 | switch (priv->mode) { | ||
73 | case TDA18271_ANALOG: | ||
74 | regs[R_MPD] &= ~0x80; /* IF notch = 0 */ | ||
75 | break; | ||
76 | case TDA18271_DIGITAL: | ||
77 | regs[R_MPD] |= 0x80; /* IF notch = 1 */ | ||
78 | break; | ||
79 | } | ||
80 | |||
81 | /* update FM_RFn */ | ||
82 | regs[R_EP4] &= ~0x80; | ||
83 | regs[R_EP4] |= map->fm_rfn << 7; | ||
84 | |||
85 | /* update rf top / if top */ | ||
86 | regs[R_EB22] = 0x00; | ||
87 | regs[R_EB22] |= map->rfagc_top; | ||
88 | tda18271_write_regs(fe, R_EB22, 1); | ||
89 | |||
90 | /* --------------------------------------------------------------- */ | ||
91 | |||
92 | /* disable Power Level Indicator */ | ||
93 | regs[R_EP1] |= 0x40; | ||
94 | |||
95 | /* frequency dependent parameters */ | ||
96 | |||
97 | tda18271_calc_ir_measure(fe, &freq); | ||
98 | |||
99 | tda18271_calc_bp_filter(fe, &freq); | ||
100 | |||
101 | tda18271_calc_rf_band(fe, &freq); | ||
102 | |||
103 | tda18271_calc_gain_taper(fe, &freq); | ||
104 | |||
105 | /* --------------------------------------------------------------- */ | ||
106 | |||
107 | /* dual tuner and agc1 extra configuration */ | ||
108 | |||
109 | switch (priv->role) { | ||
110 | case TDA18271_MASTER: | ||
111 | regs[R_EB1] |= 0x04; /* main vco */ | ||
112 | break; | ||
113 | case TDA18271_SLAVE: | ||
114 | regs[R_EB1] &= ~0x04; /* cal vco */ | ||
115 | break; | ||
116 | } | ||
117 | |||
118 | /* agc1 always active */ | ||
119 | regs[R_EB1] &= ~0x02; | ||
120 | |||
121 | /* agc1 has priority on agc2 */ | ||
122 | regs[R_EB1] &= ~0x01; | ||
123 | |||
124 | tda18271_write_regs(fe, R_EB1, 1); | ||
125 | |||
126 | /* --------------------------------------------------------------- */ | ||
127 | |||
128 | N = map->if_freq * 1000 + freq; | ||
129 | |||
130 | switch (priv->role) { | ||
131 | case TDA18271_MASTER: | ||
132 | tda18271_calc_main_pll(fe, N); | ||
133 | tda18271_write_regs(fe, R_MPD, 4); | ||
134 | break; | ||
135 | case TDA18271_SLAVE: | ||
136 | tda18271_calc_cal_pll(fe, N); | ||
137 | tda18271_write_regs(fe, R_CPD, 4); | ||
138 | |||
139 | regs[R_MPD] = regs[R_CPD] & 0x7f; | ||
140 | tda18271_write_regs(fe, R_MPD, 1); | ||
141 | break; | ||
142 | } | ||
143 | |||
144 | tda18271_write_regs(fe, R_TM, 7); | ||
145 | |||
146 | /* force charge pump source */ | ||
147 | charge_pump_source(fe, 1); | ||
148 | |||
149 | msleep(1); | ||
150 | |||
151 | /* return pll to normal operation */ | ||
152 | charge_pump_source(fe, 0); | ||
153 | |||
154 | msleep(20); | ||
155 | |||
156 | /* set rfagc to normal speed mode */ | ||
157 | if (map->fm_rfn) | ||
158 | regs[R_EP3] &= ~0x04; | ||
159 | else | ||
160 | regs[R_EP3] |= 0x04; | ||
161 | tda18271_write_regs(fe, R_EP3, 1); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static int tda18271_read_thermometer(struct dvb_frontend *fe) | ||
167 | { | ||
168 | struct tda18271_priv *priv = fe->tuner_priv; | ||
169 | unsigned char *regs = priv->tda18271_regs; | ||
170 | int tm; | ||
171 | |||
172 | /* switch thermometer on */ | ||
173 | regs[R_TM] |= 0x10; | ||
174 | tda18271_write_regs(fe, R_TM, 1); | ||
175 | |||
176 | /* read thermometer info */ | ||
177 | tda18271_read_regs(fe); | ||
178 | |||
179 | if ((((regs[R_TM] & 0x0f) == 0x00) && ((regs[R_TM] & 0x20) == 0x20)) || | ||
180 | (((regs[R_TM] & 0x0f) == 0x08) && ((regs[R_TM] & 0x20) == 0x00))) { | ||
181 | |||
182 | if ((regs[R_TM] & 0x20) == 0x20) | ||
183 | regs[R_TM] &= ~0x20; | ||
184 | else | ||
185 | regs[R_TM] |= 0x20; | ||
186 | |||
187 | tda18271_write_regs(fe, R_TM, 1); | ||
188 | |||
189 | msleep(10); /* temperature sensing */ | ||
190 | |||
191 | /* read thermometer info */ | ||
192 | tda18271_read_regs(fe); | ||
193 | } | ||
194 | |||
195 | tm = tda18271_lookup_thermometer(fe); | ||
196 | |||
197 | /* switch thermometer off */ | ||
198 | regs[R_TM] &= ~0x10; | ||
199 | tda18271_write_regs(fe, R_TM, 1); | ||
200 | |||
201 | /* set CAL mode to normal */ | ||
202 | regs[R_EP4] &= ~0x03; | ||
203 | tda18271_write_regs(fe, R_EP4, 1); | ||
204 | |||
205 | return tm; | ||
206 | } | ||
207 | |||
208 | /* ------------------------------------------------------------------ */ | ||
209 | |||
210 | static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe, | ||
211 | u32 freq) | ||
212 | { | ||
213 | struct tda18271_priv *priv = fe->tuner_priv; | ||
214 | struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state; | ||
215 | unsigned char *regs = priv->tda18271_regs; | ||
216 | int tm_current, rfcal_comp, approx, i; | ||
217 | u8 dc_over_dt, rf_tab; | ||
218 | |||
219 | /* power up */ | ||
220 | tda18271_set_standby_mode(fe, 0, 0, 0); | ||
221 | |||
222 | /* read die current temperature */ | ||
223 | tm_current = tda18271_read_thermometer(fe); | ||
224 | |||
225 | /* frequency dependent parameters */ | ||
226 | |||
227 | tda18271_calc_rf_cal(fe, &freq); | ||
228 | rf_tab = regs[R_EB14]; | ||
229 | |||
230 | i = tda18271_lookup_rf_band(fe, &freq, NULL); | ||
231 | if (i < 0) | ||
232 | return -EINVAL; | ||
233 | |||
234 | if ((0 == map[i].rf3) || (freq / 1000 < map[i].rf2)) { | ||
235 | approx = map[i].rf_a1 * | ||
236 | (freq / 1000 - map[i].rf1) + map[i].rf_b1 + rf_tab; | ||
237 | } else { | ||
238 | approx = map[i].rf_a2 * | ||
239 | (freq / 1000 - map[i].rf2) + map[i].rf_b2 + rf_tab; | ||
240 | } | ||
241 | |||
242 | if (approx < 0) | ||
243 | approx = 0; | ||
244 | if (approx > 255) | ||
245 | approx = 255; | ||
246 | |||
247 | tda18271_lookup_map(fe, RF_CAL_DC_OVER_DT, &freq, &dc_over_dt); | ||
248 | |||
249 | /* calculate temperature compensation */ | ||
250 | rfcal_comp = dc_over_dt * (tm_current - priv->tm_rfcal); | ||
251 | |||
252 | regs[R_EB14] = approx + rfcal_comp; | ||
253 | tda18271_write_regs(fe, R_EB14, 1); | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static int tda18271_por(struct dvb_frontend *fe) | ||
259 | { | ||
260 | struct tda18271_priv *priv = fe->tuner_priv; | ||
261 | unsigned char *regs = priv->tda18271_regs; | ||
262 | |||
263 | /* power up detector 1 */ | ||
264 | regs[R_EB12] &= ~0x20; | ||
265 | tda18271_write_regs(fe, R_EB12, 1); | ||
266 | |||
267 | regs[R_EB18] &= ~0x80; /* turn agc1 loop on */ | ||
268 | regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */ | ||
269 | tda18271_write_regs(fe, R_EB18, 1); | ||
270 | |||
271 | regs[R_EB21] |= 0x03; /* set agc2_gain to -6 dB */ | ||
272 | |||
273 | /* POR mode */ | ||
274 | tda18271_set_standby_mode(fe, 1, 0, 0); | ||
275 | |||
276 | /* disable 1.5 MHz low pass filter */ | ||
277 | regs[R_EB23] &= ~0x04; /* forcelp_fc2_en = 0 */ | ||
278 | regs[R_EB23] &= ~0x02; /* XXX: lp_fc[2] = 0 */ | ||
279 | tda18271_write_regs(fe, R_EB21, 3); | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq) | ||
285 | { | ||
286 | struct tda18271_priv *priv = fe->tuner_priv; | ||
287 | unsigned char *regs = priv->tda18271_regs; | ||
288 | u32 N; | ||
289 | |||
290 | /* set CAL mode to normal */ | ||
291 | regs[R_EP4] &= ~0x03; | ||
292 | tda18271_write_regs(fe, R_EP4, 1); | ||
293 | |||
294 | /* switch off agc1 */ | ||
295 | regs[R_EP3] |= 0x40; /* sm_lt = 1 */ | ||
296 | |||
297 | regs[R_EB18] |= 0x03; /* set agc1_gain to 15 dB */ | ||
298 | tda18271_write_regs(fe, R_EB18, 1); | ||
299 | |||
300 | /* frequency dependent parameters */ | ||
301 | |||
302 | tda18271_calc_bp_filter(fe, &freq); | ||
303 | tda18271_calc_gain_taper(fe, &freq); | ||
304 | tda18271_calc_rf_band(fe, &freq); | ||
305 | tda18271_calc_km(fe, &freq); | ||
306 | |||
307 | tda18271_write_regs(fe, R_EP1, 3); | ||
308 | tda18271_write_regs(fe, R_EB13, 1); | ||
309 | |||
310 | /* main pll charge pump source */ | ||
311 | tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1); | ||
312 | |||
313 | /* cal pll charge pump source */ | ||
314 | tda18271_charge_pump_source(fe, TDA18271_CAL_PLL, 1); | ||
315 | |||
316 | /* force dcdc converter to 0 V */ | ||
317 | regs[R_EB14] = 0x00; | ||
318 | tda18271_write_regs(fe, R_EB14, 1); | ||
319 | |||
320 | /* disable plls lock */ | ||
321 | regs[R_EB20] &= ~0x20; | ||
322 | tda18271_write_regs(fe, R_EB20, 1); | ||
323 | |||
324 | /* set CAL mode to RF tracking filter calibration */ | ||
325 | regs[R_EP4] |= 0x03; | ||
326 | tda18271_write_regs(fe, R_EP4, 2); | ||
327 | |||
328 | /* --------------------------------------------------------------- */ | ||
329 | |||
330 | /* set the internal calibration signal */ | ||
331 | N = freq; | ||
332 | |||
333 | tda18271_calc_cal_pll(fe, N); | ||
334 | tda18271_write_regs(fe, R_CPD, 4); | ||
335 | |||
336 | /* downconvert internal calibration */ | ||
337 | N += 1000000; | ||
338 | |||
339 | tda18271_calc_main_pll(fe, N); | ||
340 | tda18271_write_regs(fe, R_MPD, 4); | ||
341 | |||
342 | msleep(5); | ||
343 | |||
344 | tda18271_write_regs(fe, R_EP2, 1); | ||
345 | tda18271_write_regs(fe, R_EP1, 1); | ||
346 | tda18271_write_regs(fe, R_EP2, 1); | ||
347 | tda18271_write_regs(fe, R_EP1, 1); | ||
348 | |||
349 | /* --------------------------------------------------------------- */ | ||
350 | |||
351 | /* normal operation for the main pll */ | ||
352 | tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0); | ||
353 | |||
354 | /* normal operation for the cal pll */ | ||
355 | tda18271_charge_pump_source(fe, TDA18271_CAL_PLL, 0); | ||
356 | |||
357 | msleep(10); /* plls locking */ | ||
358 | |||
359 | /* launch the rf tracking filters calibration */ | ||
360 | regs[R_EB20] |= 0x20; | ||
361 | tda18271_write_regs(fe, R_EB20, 1); | ||
362 | |||
363 | msleep(60); /* calibration */ | ||
364 | |||
365 | /* --------------------------------------------------------------- */ | ||
366 | |||
367 | /* set CAL mode to normal */ | ||
368 | regs[R_EP4] &= ~0x03; | ||
369 | |||
370 | /* switch on agc1 */ | ||
371 | regs[R_EP3] &= ~0x40; /* sm_lt = 0 */ | ||
372 | |||
373 | regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */ | ||
374 | tda18271_write_regs(fe, R_EB18, 1); | ||
375 | |||
376 | tda18271_write_regs(fe, R_EP3, 2); | ||
377 | |||
378 | /* synchronization */ | ||
379 | tda18271_write_regs(fe, R_EP1, 1); | ||
380 | |||
381 | /* get calibration result */ | ||
382 | tda18271_read_extended(fe); | ||
383 | |||
384 | return regs[R_EB14]; | ||
385 | } | ||
386 | |||
387 | static int tda18271_powerscan(struct dvb_frontend *fe, | ||
388 | u32 *freq_in, u32 *freq_out) | ||
389 | { | ||
390 | struct tda18271_priv *priv = fe->tuner_priv; | ||
391 | unsigned char *regs = priv->tda18271_regs; | ||
392 | int sgn, bcal, count, wait; | ||
393 | u8 cid_target; | ||
394 | u16 count_limit; | ||
395 | u32 freq; | ||
396 | |||
397 | freq = *freq_in; | ||
398 | |||
399 | tda18271_calc_rf_band(fe, &freq); | ||
400 | tda18271_calc_rf_cal(fe, &freq); | ||
401 | tda18271_calc_gain_taper(fe, &freq); | ||
402 | tda18271_lookup_cid_target(fe, &freq, &cid_target, &count_limit); | ||
403 | |||
404 | tda18271_write_regs(fe, R_EP2, 1); | ||
405 | tda18271_write_regs(fe, R_EB14, 1); | ||
406 | |||
407 | /* downconvert frequency */ | ||
408 | freq += 1000000; | ||
409 | |||
410 | tda18271_calc_main_pll(fe, freq); | ||
411 | tda18271_write_regs(fe, R_MPD, 4); | ||
412 | |||
413 | msleep(5); /* pll locking */ | ||
414 | |||
415 | /* detection mode */ | ||
416 | regs[R_EP4] &= ~0x03; | ||
417 | regs[R_EP4] |= 0x01; | ||
418 | tda18271_write_regs(fe, R_EP4, 1); | ||
419 | |||
420 | /* launch power detection measurement */ | ||
421 | tda18271_write_regs(fe, R_EP2, 1); | ||
422 | |||
423 | /* read power detection info, stored in EB10 */ | ||
424 | tda18271_read_extended(fe); | ||
425 | |||
426 | /* algorithm initialization */ | ||
427 | sgn = 1; | ||
428 | *freq_out = *freq_in; | ||
429 | bcal = 0; | ||
430 | count = 0; | ||
431 | wait = false; | ||
432 | |||
433 | while ((regs[R_EB10] & 0x3f) < cid_target) { | ||
434 | /* downconvert updated freq to 1 MHz */ | ||
435 | freq = *freq_in + (sgn * count) + 1000000; | ||
436 | |||
437 | tda18271_calc_main_pll(fe, freq); | ||
438 | tda18271_write_regs(fe, R_MPD, 4); | ||
439 | |||
440 | if (wait) { | ||
441 | msleep(5); /* pll locking */ | ||
442 | wait = false; | ||
443 | } else | ||
444 | udelay(100); /* pll locking */ | ||
445 | |||
446 | /* launch power detection measurement */ | ||
447 | tda18271_write_regs(fe, R_EP2, 1); | ||
448 | |||
449 | /* read power detection info, stored in EB10 */ | ||
450 | tda18271_read_extended(fe); | ||
451 | |||
452 | count += 200; | ||
453 | |||
454 | if (count <= count_limit) | ||
455 | continue; | ||
456 | |||
457 | if (sgn <= 0) | ||
458 | break; | ||
459 | |||
460 | sgn = -1 * sgn; | ||
461 | count = 200; | ||
462 | wait = true; | ||
463 | } | ||
464 | |||
465 | if ((regs[R_EB10] & 0x3f) >= cid_target) { | ||
466 | bcal = 1; | ||
467 | *freq_out = freq - 1000000; | ||
468 | } else | ||
469 | bcal = 0; | ||
470 | |||
471 | tda_cal("bcal = %d, freq_in = %d, freq_out = %d (freq = %d)\n", | ||
472 | bcal, *freq_in, *freq_out, freq); | ||
473 | |||
474 | return bcal; | ||
475 | } | ||
476 | |||
477 | static int tda18271_powerscan_init(struct dvb_frontend *fe) | ||
478 | { | ||
479 | struct tda18271_priv *priv = fe->tuner_priv; | ||
480 | unsigned char *regs = priv->tda18271_regs; | ||
481 | |||
482 | /* set standard to digital */ | ||
483 | regs[R_EP3] &= ~0x1f; /* clear std bits */ | ||
484 | regs[R_EP3] |= 0x12; | ||
485 | |||
486 | /* set cal mode to normal */ | ||
487 | regs[R_EP4] &= ~0x03; | ||
488 | |||
489 | /* update IF output level & IF notch frequency */ | ||
490 | regs[R_EP4] &= ~0x1c; /* clear if level bits */ | ||
491 | |||
492 | tda18271_write_regs(fe, R_EP3, 2); | ||
493 | |||
494 | regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */ | ||
495 | tda18271_write_regs(fe, R_EB18, 1); | ||
496 | |||
497 | regs[R_EB21] &= ~0x03; /* set agc2_gain to -15 dB */ | ||
498 | |||
499 | /* 1.5 MHz low pass filter */ | ||
500 | regs[R_EB23] |= 0x04; /* forcelp_fc2_en = 1 */ | ||
501 | regs[R_EB23] |= 0x02; /* lp_fc[2] = 1 */ | ||
502 | |||
503 | tda18271_write_regs(fe, R_EB21, 3); | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq) | ||
509 | { | ||
510 | struct tda18271_priv *priv = fe->tuner_priv; | ||
511 | struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state; | ||
512 | unsigned char *regs = priv->tda18271_regs; | ||
513 | int bcal, rf, i; | ||
514 | #define RF1 0 | ||
515 | #define RF2 1 | ||
516 | #define RF3 2 | ||
517 | u32 rf_default[3]; | ||
518 | u32 rf_freq[3]; | ||
519 | u8 prog_cal[3]; | ||
520 | u8 prog_tab[3]; | ||
521 | |||
522 | i = tda18271_lookup_rf_band(fe, &freq, NULL); | ||
523 | |||
524 | if (i < 0) | ||
525 | return i; | ||
526 | |||
527 | rf_default[RF1] = 1000 * map[i].rf1_def; | ||
528 | rf_default[RF2] = 1000 * map[i].rf2_def; | ||
529 | rf_default[RF3] = 1000 * map[i].rf3_def; | ||
530 | |||
531 | for (rf = RF1; rf <= RF3; rf++) { | ||
532 | if (0 == rf_default[rf]) | ||
533 | return 0; | ||
534 | tda_cal("freq = %d, rf = %d\n", freq, rf); | ||
535 | |||
536 | /* look for optimized calibration frequency */ | ||
537 | bcal = tda18271_powerscan(fe, &rf_default[rf], &rf_freq[rf]); | ||
538 | |||
539 | tda18271_calc_rf_cal(fe, &rf_freq[rf]); | ||
540 | prog_tab[rf] = regs[R_EB14]; | ||
541 | |||
542 | if (1 == bcal) | ||
543 | prog_cal[rf] = tda18271_calibrate_rf(fe, rf_freq[rf]); | ||
544 | else | ||
545 | prog_cal[rf] = prog_tab[rf]; | ||
546 | |||
547 | switch (rf) { | ||
548 | case RF1: | ||
549 | map[i].rf_a1 = 0; | ||
550 | map[i].rf_b1 = prog_cal[RF1] - prog_tab[RF1]; | ||
551 | map[i].rf1 = rf_freq[RF1] / 1000; | ||
552 | break; | ||
553 | case RF2: | ||
554 | map[i].rf_a1 = (prog_cal[RF2] - prog_tab[RF2] - | ||
555 | prog_cal[RF1] + prog_tab[RF1]) / | ||
556 | ((rf_freq[RF2] - rf_freq[RF1]) / 1000); | ||
557 | map[i].rf2 = rf_freq[RF2] / 1000; | ||
558 | break; | ||
559 | case RF3: | ||
560 | map[i].rf_a2 = (prog_cal[RF3] - prog_tab[RF3] - | ||
561 | prog_cal[RF2] + prog_tab[RF2]) / | ||
562 | ((rf_freq[RF3] - rf_freq[RF2]) / 1000); | ||
563 | map[i].rf_b2 = prog_cal[RF2] - prog_tab[RF2]; | ||
564 | map[i].rf3 = rf_freq[RF3] / 1000; | ||
565 | break; | ||
566 | default: | ||
567 | BUG(); | ||
568 | } | ||
569 | } | ||
570 | |||
571 | return 0; | ||
572 | } | ||
573 | |||
574 | static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe) | ||
575 | { | ||
576 | struct tda18271_priv *priv = fe->tuner_priv; | ||
577 | unsigned int i; | ||
578 | |||
579 | tda_info("tda18271: performing RF tracking filter calibration\n"); | ||
580 | |||
581 | /* wait for die temperature stabilization */ | ||
582 | msleep(200); | ||
583 | |||
584 | tda18271_powerscan_init(fe); | ||
585 | |||
586 | /* rf band calibration */ | ||
587 | for (i = 0; priv->rf_cal_state[i].rfmax != 0; i++) | ||
588 | tda18271_rf_tracking_filters_init(fe, 1000 * | ||
589 | priv->rf_cal_state[i].rfmax); | ||
590 | |||
591 | priv->tm_rfcal = tda18271_read_thermometer(fe); | ||
592 | |||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | /* ------------------------------------------------------------------ */ | ||
597 | |||
598 | static int tda18271c2_rf_cal_init(struct dvb_frontend *fe) | ||
599 | { | ||
600 | struct tda18271_priv *priv = fe->tuner_priv; | ||
601 | unsigned char *regs = priv->tda18271_regs; | ||
602 | |||
603 | /* test RF_CAL_OK to see if we need init */ | ||
604 | if ((regs[R_EP1] & 0x10) == 0) | ||
605 | priv->cal_initialized = false; | ||
606 | |||
607 | if (priv->cal_initialized) | ||
608 | return 0; | ||
609 | |||
610 | tda18271_calc_rf_filter_curve(fe); | ||
611 | |||
612 | tda18271_por(fe); | ||
613 | |||
614 | tda_info("tda18271: RF tracking filter calibration complete\n"); | ||
615 | |||
616 | priv->cal_initialized = true; | ||
617 | |||
618 | return 0; | ||
619 | } | ||
620 | |||
621 | static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe, | ||
622 | u32 freq, u32 bw) | ||
623 | { | ||
624 | struct tda18271_priv *priv = fe->tuner_priv; | ||
625 | unsigned char *regs = priv->tda18271_regs; | ||
626 | u32 N = 0; | ||
627 | |||
628 | /* calculate bp filter */ | ||
629 | tda18271_calc_bp_filter(fe, &freq); | ||
630 | tda18271_write_regs(fe, R_EP1, 1); | ||
631 | |||
632 | regs[R_EB4] &= 0x07; | ||
633 | regs[R_EB4] |= 0x60; | ||
634 | tda18271_write_regs(fe, R_EB4, 1); | ||
635 | |||
636 | regs[R_EB7] = 0x60; | ||
637 | tda18271_write_regs(fe, R_EB7, 1); | ||
638 | |||
639 | regs[R_EB14] = 0x00; | ||
640 | tda18271_write_regs(fe, R_EB14, 1); | ||
641 | |||
642 | regs[R_EB20] = 0xcc; | ||
643 | tda18271_write_regs(fe, R_EB20, 1); | ||
644 | |||
645 | /* set cal mode to RF tracking filter calibration */ | ||
646 | regs[R_EP4] |= 0x03; | ||
647 | |||
648 | /* calculate cal pll */ | ||
649 | |||
650 | switch (priv->mode) { | ||
651 | case TDA18271_ANALOG: | ||
652 | N = freq - 1250000; | ||
653 | break; | ||
654 | case TDA18271_DIGITAL: | ||
655 | N = freq + bw / 2; | ||
656 | break; | ||
657 | } | ||
658 | |||
659 | tda18271_calc_cal_pll(fe, N); | ||
660 | |||
661 | /* calculate main pll */ | ||
662 | |||
663 | switch (priv->mode) { | ||
664 | case TDA18271_ANALOG: | ||
665 | N = freq - 250000; | ||
666 | break; | ||
667 | case TDA18271_DIGITAL: | ||
668 | N = freq + bw / 2 + 1000000; | ||
669 | break; | ||
670 | } | ||
671 | |||
672 | tda18271_calc_main_pll(fe, N); | ||
673 | |||
674 | tda18271_write_regs(fe, R_EP3, 11); | ||
675 | msleep(5); /* RF tracking filter calibration initialization */ | ||
676 | |||
677 | /* search for K,M,CO for RF calibration */ | ||
678 | tda18271_calc_km(fe, &freq); | ||
679 | tda18271_write_regs(fe, R_EB13, 1); | ||
680 | |||
681 | /* search for rf band */ | ||
682 | tda18271_calc_rf_band(fe, &freq); | ||
683 | |||
684 | /* search for gain taper */ | ||
685 | tda18271_calc_gain_taper(fe, &freq); | ||
686 | |||
687 | tda18271_write_regs(fe, R_EP2, 1); | ||
688 | tda18271_write_regs(fe, R_EP1, 1); | ||
689 | tda18271_write_regs(fe, R_EP2, 1); | ||
690 | tda18271_write_regs(fe, R_EP1, 1); | ||
691 | |||
692 | regs[R_EB4] &= 0x07; | ||
693 | regs[R_EB4] |= 0x40; | ||
694 | tda18271_write_regs(fe, R_EB4, 1); | ||
695 | |||
696 | regs[R_EB7] = 0x40; | ||
697 | tda18271_write_regs(fe, R_EB7, 1); | ||
698 | msleep(10); /* pll locking */ | ||
699 | |||
700 | regs[R_EB20] = 0xec; | ||
701 | tda18271_write_regs(fe, R_EB20, 1); | ||
702 | msleep(60); /* RF tracking filter calibration completion */ | ||
703 | |||
704 | regs[R_EP4] &= ~0x03; /* set cal mode to normal */ | ||
705 | tda18271_write_regs(fe, R_EP4, 1); | ||
706 | |||
707 | tda18271_write_regs(fe, R_EP1, 1); | ||
708 | |||
709 | /* RF tracking filter correction for VHF_Low band */ | ||
710 | if (0 == tda18271_calc_rf_cal(fe, &freq)) | ||
711 | tda18271_write_regs(fe, R_EB14, 1); | ||
712 | |||
713 | return 0; | ||
714 | } | ||
715 | |||
716 | /* ------------------------------------------------------------------ */ | ||
717 | |||
718 | static int tda18271_ir_cal_init(struct dvb_frontend *fe) | ||
719 | { | ||
720 | struct tda18271_priv *priv = fe->tuner_priv; | ||
721 | unsigned char *regs = priv->tda18271_regs; | ||
722 | |||
723 | tda18271_read_regs(fe); | ||
724 | |||
725 | /* test IR_CAL_OK to see if we need init */ | ||
726 | if ((regs[R_EP1] & 0x08) == 0) | ||
727 | tda18271_init_regs(fe); | ||
728 | |||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | static int tda18271_init(struct dvb_frontend *fe) | ||
733 | { | ||
734 | struct tda18271_priv *priv = fe->tuner_priv; | ||
735 | |||
736 | mutex_lock(&priv->lock); | ||
737 | |||
738 | /* power up */ | ||
739 | tda18271_set_standby_mode(fe, 0, 0, 0); | ||
740 | |||
741 | /* initialization */ | ||
742 | tda18271_ir_cal_init(fe); | ||
743 | |||
744 | if (priv->id == TDA18271HDC2) | ||
745 | tda18271c2_rf_cal_init(fe); | ||
746 | |||
747 | mutex_unlock(&priv->lock); | ||
748 | |||
749 | return 0; | ||
750 | } | ||
751 | |||
752 | static int tda18271_tune(struct dvb_frontend *fe, | ||
753 | struct tda18271_std_map_item *map, u32 freq, u32 bw) | ||
754 | { | ||
755 | struct tda18271_priv *priv = fe->tuner_priv; | ||
756 | |||
757 | tda_dbg("freq = %d, ifc = %d, bw = %d, agc_mode = %d, std = %d\n", | ||
758 | freq, map->if_freq, bw, map->agc_mode, map->std); | ||
759 | |||
760 | tda18271_init(fe); | ||
761 | |||
762 | mutex_lock(&priv->lock); | ||
763 | |||
764 | switch (priv->id) { | ||
765 | case TDA18271HDC1: | ||
766 | tda18271c1_rf_tracking_filter_calibration(fe, freq, bw); | ||
767 | break; | ||
768 | case TDA18271HDC2: | ||
769 | tda18271c2_rf_tracking_filters_correction(fe, freq); | ||
770 | break; | ||
771 | } | ||
772 | tda18271_channel_configuration(fe, map, freq, bw); | ||
773 | |||
774 | mutex_unlock(&priv->lock); | ||
775 | |||
776 | return 0; | ||
777 | } | ||
778 | |||
779 | /* ------------------------------------------------------------------ */ | ||
780 | |||
781 | static int tda18271_set_params(struct dvb_frontend *fe, | ||
782 | struct dvb_frontend_parameters *params) | ||
783 | { | ||
784 | struct tda18271_priv *priv = fe->tuner_priv; | ||
785 | struct tda18271_std_map *std_map = &priv->std; | ||
786 | struct tda18271_std_map_item *map; | ||
787 | int ret; | ||
788 | u32 bw, freq = params->frequency; | ||
789 | |||
790 | priv->mode = TDA18271_DIGITAL; | ||
791 | |||
792 | if (fe->ops.info.type == FE_ATSC) { | ||
793 | switch (params->u.vsb.modulation) { | ||
794 | case VSB_8: | ||
795 | case VSB_16: | ||
796 | map = &std_map->atsc_6; | ||
797 | break; | ||
798 | case QAM_64: | ||
799 | case QAM_256: | ||
800 | map = &std_map->qam_6; | ||
801 | break; | ||
802 | default: | ||
803 | tda_warn("modulation not set!\n"); | ||
804 | return -EINVAL; | ||
805 | } | ||
806 | #if 0 | ||
807 | /* userspace request is already center adjusted */ | ||
808 | freq += 1750000; /* Adjust to center (+1.75MHZ) */ | ||
809 | #endif | ||
810 | bw = 6000000; | ||
811 | } else if (fe->ops.info.type == FE_OFDM) { | ||
812 | switch (params->u.ofdm.bandwidth) { | ||
813 | case BANDWIDTH_6_MHZ: | ||
814 | bw = 6000000; | ||
815 | map = &std_map->dvbt_6; | ||
816 | break; | ||
817 | case BANDWIDTH_7_MHZ: | ||
818 | bw = 7000000; | ||
819 | map = &std_map->dvbt_7; | ||
820 | break; | ||
821 | case BANDWIDTH_8_MHZ: | ||
822 | bw = 8000000; | ||
823 | map = &std_map->dvbt_8; | ||
824 | break; | ||
825 | default: | ||
826 | tda_warn("bandwidth not set!\n"); | ||
827 | return -EINVAL; | ||
828 | } | ||
829 | } else { | ||
830 | tda_warn("modulation type not supported!\n"); | ||
831 | return -EINVAL; | ||
832 | } | ||
833 | |||
834 | /* When tuning digital, the analog demod must be tri-stated */ | ||
835 | if (fe->ops.analog_ops.standby) | ||
836 | fe->ops.analog_ops.standby(fe); | ||
837 | |||
838 | ret = tda18271_tune(fe, map, freq, bw); | ||
839 | |||
840 | if (ret < 0) | ||
841 | goto fail; | ||
842 | |||
843 | priv->frequency = freq; | ||
844 | priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? | ||
845 | params->u.ofdm.bandwidth : 0; | ||
846 | fail: | ||
847 | return ret; | ||
848 | } | ||
849 | |||
850 | static int tda18271_set_analog_params(struct dvb_frontend *fe, | ||
851 | struct analog_parameters *params) | ||
852 | { | ||
853 | struct tda18271_priv *priv = fe->tuner_priv; | ||
854 | struct tda18271_std_map *std_map = &priv->std; | ||
855 | struct tda18271_std_map_item *map; | ||
856 | char *mode; | ||
857 | int ret; | ||
858 | u32 freq = params->frequency * 62500; | ||
859 | |||
860 | priv->mode = TDA18271_ANALOG; | ||
861 | |||
862 | if (params->mode == V4L2_TUNER_RADIO) { | ||
863 | freq = freq / 1000; | ||
864 | map = &std_map->fm_radio; | ||
865 | mode = "fm"; | ||
866 | } else if (params->std & V4L2_STD_MN) { | ||
867 | map = &std_map->atv_mn; | ||
868 | mode = "MN"; | ||
869 | } else if (params->std & V4L2_STD_B) { | ||
870 | map = &std_map->atv_b; | ||
871 | mode = "B"; | ||
872 | } else if (params->std & V4L2_STD_GH) { | ||
873 | map = &std_map->atv_gh; | ||
874 | mode = "GH"; | ||
875 | } else if (params->std & V4L2_STD_PAL_I) { | ||
876 | map = &std_map->atv_i; | ||
877 | mode = "I"; | ||
878 | } else if (params->std & V4L2_STD_DK) { | ||
879 | map = &std_map->atv_dk; | ||
880 | mode = "DK"; | ||
881 | } else if (params->std & V4L2_STD_SECAM_L) { | ||
882 | map = &std_map->atv_l; | ||
883 | mode = "L"; | ||
884 | } else if (params->std & V4L2_STD_SECAM_LC) { | ||
885 | map = &std_map->atv_lc; | ||
886 | mode = "L'"; | ||
887 | } else { | ||
888 | map = &std_map->atv_i; | ||
889 | mode = "xx"; | ||
890 | } | ||
891 | |||
892 | tda_dbg("setting tda18271 to system %s\n", mode); | ||
893 | |||
894 | ret = tda18271_tune(fe, map, freq, 0); | ||
895 | |||
896 | if (ret < 0) | ||
897 | goto fail; | ||
898 | |||
899 | priv->frequency = freq; | ||
900 | priv->bandwidth = 0; | ||
901 | fail: | ||
902 | return ret; | ||
903 | } | ||
904 | |||
905 | static int tda18271_sleep(struct dvb_frontend *fe) | ||
906 | { | ||
907 | struct tda18271_priv *priv = fe->tuner_priv; | ||
908 | |||
909 | mutex_lock(&priv->lock); | ||
910 | |||
911 | /* standby mode w/ slave tuner output | ||
912 | * & loop thru & xtal oscillator on */ | ||
913 | tda18271_set_standby_mode(fe, 1, 0, 0); | ||
914 | |||
915 | mutex_unlock(&priv->lock); | ||
916 | |||
917 | return 0; | ||
918 | } | ||
919 | |||
920 | static int tda18271_release(struct dvb_frontend *fe) | ||
921 | { | ||
922 | struct tda18271_priv *priv = fe->tuner_priv; | ||
923 | |||
924 | mutex_lock(&tda18271_list_mutex); | ||
925 | |||
926 | if (priv) | ||
927 | hybrid_tuner_release_state(priv); | ||
928 | |||
929 | mutex_unlock(&tda18271_list_mutex); | ||
930 | |||
931 | fe->tuner_priv = NULL; | ||
932 | |||
933 | return 0; | ||
934 | } | ||
935 | |||
936 | static int tda18271_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
937 | { | ||
938 | struct tda18271_priv *priv = fe->tuner_priv; | ||
939 | *frequency = priv->frequency; | ||
940 | return 0; | ||
941 | } | ||
942 | |||
943 | static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) | ||
944 | { | ||
945 | struct tda18271_priv *priv = fe->tuner_priv; | ||
946 | *bandwidth = priv->bandwidth; | ||
947 | return 0; | ||
948 | } | ||
949 | |||
950 | /* ------------------------------------------------------------------ */ | ||
951 | |||
952 | #define tda18271_update_std(std_cfg, name) do { \ | ||
953 | if (map->std_cfg.if_freq + \ | ||
954 | map->std_cfg.agc_mode + map->std_cfg.std + \ | ||
955 | map->std_cfg.if_lvl + map->std_cfg.rfagc_top > 0) { \ | ||
956 | tda_dbg("Using custom std config for %s\n", name); \ | ||
957 | memcpy(&std->std_cfg, &map->std_cfg, \ | ||
958 | sizeof(struct tda18271_std_map_item)); \ | ||
959 | } } while (0) | ||
960 | |||
961 | #define tda18271_dump_std_item(std_cfg, name) do { \ | ||
962 | tda_dbg("(%s) if_freq = %d, agc_mode = %d, std = %d, " \ | ||
963 | "if_lvl = %d, rfagc_top = 0x%02x\n", \ | ||
964 | name, std->std_cfg.if_freq, \ | ||
965 | std->std_cfg.agc_mode, std->std_cfg.std, \ | ||
966 | std->std_cfg.if_lvl, std->std_cfg.rfagc_top); \ | ||
967 | } while (0) | ||
968 | |||
969 | static int tda18271_dump_std_map(struct dvb_frontend *fe) | ||
970 | { | ||
971 | struct tda18271_priv *priv = fe->tuner_priv; | ||
972 | struct tda18271_std_map *std = &priv->std; | ||
973 | |||
974 | tda_dbg("========== STANDARD MAP SETTINGS ==========\n"); | ||
975 | tda18271_dump_std_item(fm_radio, " fm "); | ||
976 | tda18271_dump_std_item(atv_b, "atv b "); | ||
977 | tda18271_dump_std_item(atv_dk, "atv dk"); | ||
978 | tda18271_dump_std_item(atv_gh, "atv gh"); | ||
979 | tda18271_dump_std_item(atv_i, "atv i "); | ||
980 | tda18271_dump_std_item(atv_l, "atv l "); | ||
981 | tda18271_dump_std_item(atv_lc, "atv l'"); | ||
982 | tda18271_dump_std_item(atv_mn, "atv mn"); | ||
983 | tda18271_dump_std_item(atsc_6, "atsc 6"); | ||
984 | tda18271_dump_std_item(dvbt_6, "dvbt 6"); | ||
985 | tda18271_dump_std_item(dvbt_7, "dvbt 7"); | ||
986 | tda18271_dump_std_item(dvbt_8, "dvbt 8"); | ||
987 | tda18271_dump_std_item(qam_6, "qam 6 "); | ||
988 | tda18271_dump_std_item(qam_8, "qam 8 "); | ||
989 | |||
990 | return 0; | ||
991 | } | ||
992 | |||
993 | static int tda18271_update_std_map(struct dvb_frontend *fe, | ||
994 | struct tda18271_std_map *map) | ||
995 | { | ||
996 | struct tda18271_priv *priv = fe->tuner_priv; | ||
997 | struct tda18271_std_map *std = &priv->std; | ||
998 | |||
999 | if (!map) | ||
1000 | return -EINVAL; | ||
1001 | |||
1002 | tda18271_update_std(fm_radio, "fm"); | ||
1003 | tda18271_update_std(atv_b, "atv b"); | ||
1004 | tda18271_update_std(atv_dk, "atv dk"); | ||
1005 | tda18271_update_std(atv_gh, "atv gh"); | ||
1006 | tda18271_update_std(atv_i, "atv i"); | ||
1007 | tda18271_update_std(atv_l, "atv l"); | ||
1008 | tda18271_update_std(atv_lc, "atv l'"); | ||
1009 | tda18271_update_std(atv_mn, "atv mn"); | ||
1010 | tda18271_update_std(atsc_6, "atsc 6"); | ||
1011 | tda18271_update_std(dvbt_6, "dvbt 6"); | ||
1012 | tda18271_update_std(dvbt_7, "dvbt 7"); | ||
1013 | tda18271_update_std(dvbt_8, "dvbt 8"); | ||
1014 | tda18271_update_std(qam_6, "qam 6"); | ||
1015 | tda18271_update_std(qam_8, "qam 8"); | ||
1016 | |||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
1020 | static int tda18271_get_id(struct dvb_frontend *fe) | ||
1021 | { | ||
1022 | struct tda18271_priv *priv = fe->tuner_priv; | ||
1023 | unsigned char *regs = priv->tda18271_regs; | ||
1024 | char *name; | ||
1025 | int ret = 0; | ||
1026 | |||
1027 | mutex_lock(&priv->lock); | ||
1028 | tda18271_read_regs(fe); | ||
1029 | mutex_unlock(&priv->lock); | ||
1030 | |||
1031 | switch (regs[R_ID] & 0x7f) { | ||
1032 | case 3: | ||
1033 | name = "TDA18271HD/C1"; | ||
1034 | priv->id = TDA18271HDC1; | ||
1035 | break; | ||
1036 | case 4: | ||
1037 | name = "TDA18271HD/C2"; | ||
1038 | priv->id = TDA18271HDC2; | ||
1039 | break; | ||
1040 | default: | ||
1041 | name = "Unknown device"; | ||
1042 | ret = -EINVAL; | ||
1043 | break; | ||
1044 | } | ||
1045 | |||
1046 | tda_info("%s detected @ %d-%04x%s\n", name, | ||
1047 | i2c_adapter_id(priv->i2c_props.adap), | ||
1048 | priv->i2c_props.addr, | ||
1049 | (0 == ret) ? "" : ", device not supported."); | ||
1050 | |||
1051 | return ret; | ||
1052 | } | ||
1053 | |||
1054 | static struct dvb_tuner_ops tda18271_tuner_ops = { | ||
1055 | .info = { | ||
1056 | .name = "NXP TDA18271HD", | ||
1057 | .frequency_min = 45000000, | ||
1058 | .frequency_max = 864000000, | ||
1059 | .frequency_step = 62500 | ||
1060 | }, | ||
1061 | .init = tda18271_init, | ||
1062 | .sleep = tda18271_sleep, | ||
1063 | .set_params = tda18271_set_params, | ||
1064 | .set_analog_params = tda18271_set_analog_params, | ||
1065 | .release = tda18271_release, | ||
1066 | .get_frequency = tda18271_get_frequency, | ||
1067 | .get_bandwidth = tda18271_get_bandwidth, | ||
1068 | }; | ||
1069 | |||
1070 | struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, | ||
1071 | struct i2c_adapter *i2c, | ||
1072 | struct tda18271_config *cfg) | ||
1073 | { | ||
1074 | struct tda18271_priv *priv = NULL; | ||
1075 | int instance; | ||
1076 | |||
1077 | mutex_lock(&tda18271_list_mutex); | ||
1078 | |||
1079 | instance = hybrid_tuner_request_state(struct tda18271_priv, priv, | ||
1080 | hybrid_tuner_instance_list, | ||
1081 | i2c, addr, "tda18271"); | ||
1082 | switch (instance) { | ||
1083 | case 0: | ||
1084 | goto fail; | ||
1085 | break; | ||
1086 | case 1: | ||
1087 | /* new tuner instance */ | ||
1088 | priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; | ||
1089 | priv->role = (cfg) ? cfg->role : TDA18271_MASTER; | ||
1090 | priv->cal_initialized = false; | ||
1091 | mutex_init(&priv->lock); | ||
1092 | |||
1093 | fe->tuner_priv = priv; | ||
1094 | |||
1095 | if (cfg) | ||
1096 | priv->small_i2c = cfg->small_i2c; | ||
1097 | |||
1098 | if (tda18271_get_id(fe) < 0) | ||
1099 | goto fail; | ||
1100 | |||
1101 | if (tda18271_assign_map_layout(fe) < 0) | ||
1102 | goto fail; | ||
1103 | |||
1104 | mutex_lock(&priv->lock); | ||
1105 | tda18271_init_regs(fe); | ||
1106 | |||
1107 | if ((tda18271_cal_on_startup) && (priv->id == TDA18271HDC2)) | ||
1108 | tda18271c2_rf_cal_init(fe); | ||
1109 | |||
1110 | mutex_unlock(&priv->lock); | ||
1111 | break; | ||
1112 | default: | ||
1113 | /* existing tuner instance */ | ||
1114 | fe->tuner_priv = priv; | ||
1115 | |||
1116 | /* allow dvb driver to override i2c gate setting */ | ||
1117 | if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG)) | ||
1118 | priv->gate = cfg->gate; | ||
1119 | break; | ||
1120 | } | ||
1121 | |||
1122 | /* override default std map with values in config struct */ | ||
1123 | if ((cfg) && (cfg->std_map)) | ||
1124 | tda18271_update_std_map(fe, cfg->std_map); | ||
1125 | |||
1126 | mutex_unlock(&tda18271_list_mutex); | ||
1127 | |||
1128 | memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops, | ||
1129 | sizeof(struct dvb_tuner_ops)); | ||
1130 | |||
1131 | if (tda18271_debug & (DBG_MAP | DBG_ADV)) | ||
1132 | tda18271_dump_std_map(fe); | ||
1133 | |||
1134 | return fe; | ||
1135 | fail: | ||
1136 | mutex_unlock(&tda18271_list_mutex); | ||
1137 | |||
1138 | tda18271_release(fe); | ||
1139 | return NULL; | ||
1140 | } | ||
1141 | EXPORT_SYMBOL_GPL(tda18271_attach); | ||
1142 | MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver"); | ||
1143 | MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>"); | ||
1144 | MODULE_LICENSE("GPL"); | ||
1145 | MODULE_VERSION("0.3"); | ||
1146 | |||
1147 | /* | ||
1148 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
1149 | * --------------------------------------------------------------------------- | ||
1150 | * Local variables: | ||
1151 | * c-basic-offset: 8 | ||
1152 | * End: | ||
1153 | */ | ||
diff --git a/drivers/media/common/tuners/tda18271-maps.c b/drivers/media/common/tuners/tda18271-maps.c new file mode 100644 index 000000000000..83e7561960c1 --- /dev/null +++ b/drivers/media/common/tuners/tda18271-maps.c | |||
@@ -0,0 +1,1313 @@ | |||
1 | /* | ||
2 | tda18271-tables.c - driver for the Philips / NXP TDA18271 silicon tuner | ||
3 | |||
4 | Copyright (C) 2007, 2008 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 "tda18271-priv.h" | ||
22 | |||
23 | struct tda18271_pll_map { | ||
24 | u32 lomax; | ||
25 | u8 pd; /* post div */ | ||
26 | u8 d; /* div */ | ||
27 | }; | ||
28 | |||
29 | struct tda18271_map { | ||
30 | u32 rfmax; | ||
31 | u8 val; | ||
32 | }; | ||
33 | |||
34 | /*---------------------------------------------------------------------*/ | ||
35 | |||
36 | static struct tda18271_pll_map tda18271c1_main_pll[] = { | ||
37 | { .lomax = 32000, .pd = 0x5f, .d = 0xf0 }, | ||
38 | { .lomax = 35000, .pd = 0x5e, .d = 0xe0 }, | ||
39 | { .lomax = 37000, .pd = 0x5d, .d = 0xd0 }, | ||
40 | { .lomax = 41000, .pd = 0x5c, .d = 0xc0 }, | ||
41 | { .lomax = 44000, .pd = 0x5b, .d = 0xb0 }, | ||
42 | { .lomax = 49000, .pd = 0x5a, .d = 0xa0 }, | ||
43 | { .lomax = 54000, .pd = 0x59, .d = 0x90 }, | ||
44 | { .lomax = 61000, .pd = 0x58, .d = 0x80 }, | ||
45 | { .lomax = 65000, .pd = 0x4f, .d = 0x78 }, | ||
46 | { .lomax = 70000, .pd = 0x4e, .d = 0x70 }, | ||
47 | { .lomax = 75000, .pd = 0x4d, .d = 0x68 }, | ||
48 | { .lomax = 82000, .pd = 0x4c, .d = 0x60 }, | ||
49 | { .lomax = 89000, .pd = 0x4b, .d = 0x58 }, | ||
50 | { .lomax = 98000, .pd = 0x4a, .d = 0x50 }, | ||
51 | { .lomax = 109000, .pd = 0x49, .d = 0x48 }, | ||
52 | { .lomax = 123000, .pd = 0x48, .d = 0x40 }, | ||
53 | { .lomax = 131000, .pd = 0x3f, .d = 0x3c }, | ||
54 | { .lomax = 141000, .pd = 0x3e, .d = 0x38 }, | ||
55 | { .lomax = 151000, .pd = 0x3d, .d = 0x34 }, | ||
56 | { .lomax = 164000, .pd = 0x3c, .d = 0x30 }, | ||
57 | { .lomax = 179000, .pd = 0x3b, .d = 0x2c }, | ||
58 | { .lomax = 197000, .pd = 0x3a, .d = 0x28 }, | ||
59 | { .lomax = 219000, .pd = 0x39, .d = 0x24 }, | ||
60 | { .lomax = 246000, .pd = 0x38, .d = 0x20 }, | ||
61 | { .lomax = 263000, .pd = 0x2f, .d = 0x1e }, | ||
62 | { .lomax = 282000, .pd = 0x2e, .d = 0x1c }, | ||
63 | { .lomax = 303000, .pd = 0x2d, .d = 0x1a }, | ||
64 | { .lomax = 329000, .pd = 0x2c, .d = 0x18 }, | ||
65 | { .lomax = 359000, .pd = 0x2b, .d = 0x16 }, | ||
66 | { .lomax = 395000, .pd = 0x2a, .d = 0x14 }, | ||
67 | { .lomax = 438000, .pd = 0x29, .d = 0x12 }, | ||
68 | { .lomax = 493000, .pd = 0x28, .d = 0x10 }, | ||
69 | { .lomax = 526000, .pd = 0x1f, .d = 0x0f }, | ||
70 | { .lomax = 564000, .pd = 0x1e, .d = 0x0e }, | ||
71 | { .lomax = 607000, .pd = 0x1d, .d = 0x0d }, | ||
72 | { .lomax = 658000, .pd = 0x1c, .d = 0x0c }, | ||
73 | { .lomax = 718000, .pd = 0x1b, .d = 0x0b }, | ||
74 | { .lomax = 790000, .pd = 0x1a, .d = 0x0a }, | ||
75 | { .lomax = 877000, .pd = 0x19, .d = 0x09 }, | ||
76 | { .lomax = 987000, .pd = 0x18, .d = 0x08 }, | ||
77 | { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */ | ||
78 | }; | ||
79 | |||
80 | static struct tda18271_pll_map tda18271c2_main_pll[] = { | ||
81 | { .lomax = 33125, .pd = 0x57, .d = 0xf0 }, | ||
82 | { .lomax = 35500, .pd = 0x56, .d = 0xe0 }, | ||
83 | { .lomax = 38188, .pd = 0x55, .d = 0xd0 }, | ||
84 | { .lomax = 41375, .pd = 0x54, .d = 0xc0 }, | ||
85 | { .lomax = 45125, .pd = 0x53, .d = 0xb0 }, | ||
86 | { .lomax = 49688, .pd = 0x52, .d = 0xa0 }, | ||
87 | { .lomax = 55188, .pd = 0x51, .d = 0x90 }, | ||
88 | { .lomax = 62125, .pd = 0x50, .d = 0x80 }, | ||
89 | { .lomax = 66250, .pd = 0x47, .d = 0x78 }, | ||
90 | { .lomax = 71000, .pd = 0x46, .d = 0x70 }, | ||
91 | { .lomax = 76375, .pd = 0x45, .d = 0x68 }, | ||
92 | { .lomax = 82750, .pd = 0x44, .d = 0x60 }, | ||
93 | { .lomax = 90250, .pd = 0x43, .d = 0x58 }, | ||
94 | { .lomax = 99375, .pd = 0x42, .d = 0x50 }, | ||
95 | { .lomax = 110375, .pd = 0x41, .d = 0x48 }, | ||
96 | { .lomax = 124250, .pd = 0x40, .d = 0x40 }, | ||
97 | { .lomax = 132500, .pd = 0x37, .d = 0x3c }, | ||
98 | { .lomax = 142000, .pd = 0x36, .d = 0x38 }, | ||
99 | { .lomax = 152750, .pd = 0x35, .d = 0x34 }, | ||
100 | { .lomax = 165500, .pd = 0x34, .d = 0x30 }, | ||
101 | { .lomax = 180500, .pd = 0x33, .d = 0x2c }, | ||
102 | { .lomax = 198750, .pd = 0x32, .d = 0x28 }, | ||
103 | { .lomax = 220750, .pd = 0x31, .d = 0x24 }, | ||
104 | { .lomax = 248500, .pd = 0x30, .d = 0x20 }, | ||
105 | { .lomax = 265000, .pd = 0x27, .d = 0x1e }, | ||
106 | { .lomax = 284000, .pd = 0x26, .d = 0x1c }, | ||
107 | { .lomax = 305500, .pd = 0x25, .d = 0x1a }, | ||
108 | { .lomax = 331000, .pd = 0x24, .d = 0x18 }, | ||
109 | { .lomax = 361000, .pd = 0x23, .d = 0x16 }, | ||
110 | { .lomax = 397500, .pd = 0x22, .d = 0x14 }, | ||
111 | { .lomax = 441500, .pd = 0x21, .d = 0x12 }, | ||
112 | { .lomax = 497000, .pd = 0x20, .d = 0x10 }, | ||
113 | { .lomax = 530000, .pd = 0x17, .d = 0x0f }, | ||
114 | { .lomax = 568000, .pd = 0x16, .d = 0x0e }, | ||
115 | { .lomax = 611000, .pd = 0x15, .d = 0x0d }, | ||
116 | { .lomax = 662000, .pd = 0x14, .d = 0x0c }, | ||
117 | { .lomax = 722000, .pd = 0x13, .d = 0x0b }, | ||
118 | { .lomax = 795000, .pd = 0x12, .d = 0x0a }, | ||
119 | { .lomax = 883000, .pd = 0x11, .d = 0x09 }, | ||
120 | { .lomax = 994000, .pd = 0x10, .d = 0x08 }, | ||
121 | { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */ | ||
122 | }; | ||
123 | |||
124 | static struct tda18271_pll_map tda18271c1_cal_pll[] = { | ||
125 | { .lomax = 33000, .pd = 0xdd, .d = 0xd0 }, | ||
126 | { .lomax = 36000, .pd = 0xdc, .d = 0xc0 }, | ||
127 | { .lomax = 40000, .pd = 0xdb, .d = 0xb0 }, | ||
128 | { .lomax = 44000, .pd = 0xda, .d = 0xa0 }, | ||
129 | { .lomax = 49000, .pd = 0xd9, .d = 0x90 }, | ||
130 | { .lomax = 55000, .pd = 0xd8, .d = 0x80 }, | ||
131 | { .lomax = 63000, .pd = 0xd3, .d = 0x70 }, | ||
132 | { .lomax = 67000, .pd = 0xcd, .d = 0x68 }, | ||
133 | { .lomax = 73000, .pd = 0xcc, .d = 0x60 }, | ||
134 | { .lomax = 80000, .pd = 0xcb, .d = 0x58 }, | ||
135 | { .lomax = 88000, .pd = 0xca, .d = 0x50 }, | ||
136 | { .lomax = 98000, .pd = 0xc9, .d = 0x48 }, | ||
137 | { .lomax = 110000, .pd = 0xc8, .d = 0x40 }, | ||
138 | { .lomax = 126000, .pd = 0xc3, .d = 0x38 }, | ||
139 | { .lomax = 135000, .pd = 0xbd, .d = 0x34 }, | ||
140 | { .lomax = 147000, .pd = 0xbc, .d = 0x30 }, | ||
141 | { .lomax = 160000, .pd = 0xbb, .d = 0x2c }, | ||
142 | { .lomax = 176000, .pd = 0xba, .d = 0x28 }, | ||
143 | { .lomax = 196000, .pd = 0xb9, .d = 0x24 }, | ||
144 | { .lomax = 220000, .pd = 0xb8, .d = 0x20 }, | ||
145 | { .lomax = 252000, .pd = 0xb3, .d = 0x1c }, | ||
146 | { .lomax = 271000, .pd = 0xad, .d = 0x1a }, | ||
147 | { .lomax = 294000, .pd = 0xac, .d = 0x18 }, | ||
148 | { .lomax = 321000, .pd = 0xab, .d = 0x16 }, | ||
149 | { .lomax = 353000, .pd = 0xaa, .d = 0x14 }, | ||
150 | { .lomax = 392000, .pd = 0xa9, .d = 0x12 }, | ||
151 | { .lomax = 441000, .pd = 0xa8, .d = 0x10 }, | ||
152 | { .lomax = 505000, .pd = 0xa3, .d = 0x0e }, | ||
153 | { .lomax = 543000, .pd = 0x9d, .d = 0x0d }, | ||
154 | { .lomax = 589000, .pd = 0x9c, .d = 0x0c }, | ||
155 | { .lomax = 642000, .pd = 0x9b, .d = 0x0b }, | ||
156 | { .lomax = 707000, .pd = 0x9a, .d = 0x0a }, | ||
157 | { .lomax = 785000, .pd = 0x99, .d = 0x09 }, | ||
158 | { .lomax = 883000, .pd = 0x98, .d = 0x08 }, | ||
159 | { .lomax = 1010000, .pd = 0x93, .d = 0x07 }, | ||
160 | { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */ | ||
161 | }; | ||
162 | |||
163 | static struct tda18271_pll_map tda18271c2_cal_pll[] = { | ||
164 | { .lomax = 33813, .pd = 0xdd, .d = 0xd0 }, | ||
165 | { .lomax = 36625, .pd = 0xdc, .d = 0xc0 }, | ||
166 | { .lomax = 39938, .pd = 0xdb, .d = 0xb0 }, | ||
167 | { .lomax = 43938, .pd = 0xda, .d = 0xa0 }, | ||
168 | { .lomax = 48813, .pd = 0xd9, .d = 0x90 }, | ||
169 | { .lomax = 54938, .pd = 0xd8, .d = 0x80 }, | ||
170 | { .lomax = 62813, .pd = 0xd3, .d = 0x70 }, | ||
171 | { .lomax = 67625, .pd = 0xcd, .d = 0x68 }, | ||
172 | { .lomax = 73250, .pd = 0xcc, .d = 0x60 }, | ||
173 | { .lomax = 79875, .pd = 0xcb, .d = 0x58 }, | ||
174 | { .lomax = 87875, .pd = 0xca, .d = 0x50 }, | ||
175 | { .lomax = 97625, .pd = 0xc9, .d = 0x48 }, | ||
176 | { .lomax = 109875, .pd = 0xc8, .d = 0x40 }, | ||
177 | { .lomax = 125625, .pd = 0xc3, .d = 0x38 }, | ||
178 | { .lomax = 135250, .pd = 0xbd, .d = 0x34 }, | ||
179 | { .lomax = 146500, .pd = 0xbc, .d = 0x30 }, | ||
180 | { .lomax = 159750, .pd = 0xbb, .d = 0x2c }, | ||
181 | { .lomax = 175750, .pd = 0xba, .d = 0x28 }, | ||
182 | { .lomax = 195250, .pd = 0xb9, .d = 0x24 }, | ||
183 | { .lomax = 219750, .pd = 0xb8, .d = 0x20 }, | ||
184 | { .lomax = 251250, .pd = 0xb3, .d = 0x1c }, | ||
185 | { .lomax = 270500, .pd = 0xad, .d = 0x1a }, | ||
186 | { .lomax = 293000, .pd = 0xac, .d = 0x18 }, | ||
187 | { .lomax = 319500, .pd = 0xab, .d = 0x16 }, | ||
188 | { .lomax = 351500, .pd = 0xaa, .d = 0x14 }, | ||
189 | { .lomax = 390500, .pd = 0xa9, .d = 0x12 }, | ||
190 | { .lomax = 439500, .pd = 0xa8, .d = 0x10 }, | ||
191 | { .lomax = 502500, .pd = 0xa3, .d = 0x0e }, | ||
192 | { .lomax = 541000, .pd = 0x9d, .d = 0x0d }, | ||
193 | { .lomax = 586000, .pd = 0x9c, .d = 0x0c }, | ||
194 | { .lomax = 639000, .pd = 0x9b, .d = 0x0b }, | ||
195 | { .lomax = 703000, .pd = 0x9a, .d = 0x0a }, | ||
196 | { .lomax = 781000, .pd = 0x99, .d = 0x09 }, | ||
197 | { .lomax = 879000, .pd = 0x98, .d = 0x08 }, | ||
198 | { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */ | ||
199 | }; | ||
200 | |||
201 | static struct tda18271_map tda18271_bp_filter[] = { | ||
202 | { .rfmax = 62000, .val = 0x00 }, | ||
203 | { .rfmax = 84000, .val = 0x01 }, | ||
204 | { .rfmax = 100000, .val = 0x02 }, | ||
205 | { .rfmax = 140000, .val = 0x03 }, | ||
206 | { .rfmax = 170000, .val = 0x04 }, | ||
207 | { .rfmax = 180000, .val = 0x05 }, | ||
208 | { .rfmax = 865000, .val = 0x06 }, | ||
209 | { .rfmax = 0, .val = 0x00 }, /* end */ | ||
210 | }; | ||
211 | |||
212 | static struct tda18271_map tda18271c1_km[] = { | ||
213 | { .rfmax = 61100, .val = 0x74 }, | ||
214 | { .rfmax = 350000, .val = 0x40 }, | ||
215 | { .rfmax = 720000, .val = 0x30 }, | ||
216 | { .rfmax = 865000, .val = 0x40 }, | ||
217 | { .rfmax = 0, .val = 0x00 }, /* end */ | ||
218 | }; | ||
219 | |||
220 | static struct tda18271_map tda18271c2_km[] = { | ||
221 | { .rfmax = 47900, .val = 0x38 }, | ||
222 | { .rfmax = 61100, .val = 0x44 }, | ||
223 | { .rfmax = 350000, .val = 0x30 }, | ||
224 | { .rfmax = 720000, .val = 0x24 }, | ||
225 | { .rfmax = 865000, .val = 0x3c }, | ||
226 | { .rfmax = 0, .val = 0x00 }, /* end */ | ||
227 | }; | ||
228 | |||
229 | static struct tda18271_map tda18271_rf_band[] = { | ||
230 | { .rfmax = 47900, .val = 0x00 }, | ||
231 | { .rfmax = 61100, .val = 0x01 }, | ||
232 | /* { .rfmax = 152600, .val = 0x02 }, */ | ||
233 | { .rfmax = 121200, .val = 0x02 }, | ||
234 | { .rfmax = 164700, .val = 0x03 }, | ||
235 | { .rfmax = 203500, .val = 0x04 }, | ||
236 | { .rfmax = 457800, .val = 0x05 }, | ||
237 | { .rfmax = 865000, .val = 0x06 }, | ||
238 | { .rfmax = 0, .val = 0x00 }, /* end */ | ||
239 | }; | ||
240 | |||
241 | static struct tda18271_map tda18271_gain_taper[] = { | ||
242 | { .rfmax = 45400, .val = 0x1f }, | ||
243 | { .rfmax = 45800, .val = 0x1e }, | ||
244 | { .rfmax = 46200, .val = 0x1d }, | ||
245 | { .rfmax = 46700, .val = 0x1c }, | ||
246 | { .rfmax = 47100, .val = 0x1b }, | ||
247 | { .rfmax = 47500, .val = 0x1a }, | ||
248 | { .rfmax = 47900, .val = 0x19 }, | ||
249 | { .rfmax = 49600, .val = 0x17 }, | ||
250 | { .rfmax = 51200, .val = 0x16 }, | ||
251 | { .rfmax = 52900, .val = 0x15 }, | ||
252 | { .rfmax = 54500, .val = 0x14 }, | ||
253 | { .rfmax = 56200, .val = 0x13 }, | ||
254 | { .rfmax = 57800, .val = 0x12 }, | ||
255 | { .rfmax = 59500, .val = 0x11 }, | ||
256 | { .rfmax = 61100, .val = 0x10 }, | ||
257 | { .rfmax = 67600, .val = 0x0d }, | ||
258 | { .rfmax = 74200, .val = 0x0c }, | ||
259 | { .rfmax = 80700, .val = 0x0b }, | ||
260 | { .rfmax = 87200, .val = 0x0a }, | ||
261 | { .rfmax = 93800, .val = 0x09 }, | ||
262 | { .rfmax = 100300, .val = 0x08 }, | ||
263 | { .rfmax = 106900, .val = 0x07 }, | ||
264 | { .rfmax = 113400, .val = 0x06 }, | ||
265 | { .rfmax = 119900, .val = 0x05 }, | ||
266 | { .rfmax = 126500, .val = 0x04 }, | ||
267 | { .rfmax = 133000, .val = 0x03 }, | ||
268 | { .rfmax = 139500, .val = 0x02 }, | ||
269 | { .rfmax = 146100, .val = 0x01 }, | ||
270 | { .rfmax = 152600, .val = 0x00 }, | ||
271 | { .rfmax = 154300, .val = 0x1f }, | ||
272 | { .rfmax = 156100, .val = 0x1e }, | ||
273 | { .rfmax = 157800, .val = 0x1d }, | ||
274 | { .rfmax = 159500, .val = 0x1c }, | ||
275 | { .rfmax = 161200, .val = 0x1b }, | ||
276 | { .rfmax = 163000, .val = 0x1a }, | ||
277 | { .rfmax = 164700, .val = 0x19 }, | ||
278 | { .rfmax = 170200, .val = 0x17 }, | ||
279 | { .rfmax = 175800, .val = 0x16 }, | ||
280 | { .rfmax = 181300, .val = 0x15 }, | ||
281 | { .rfmax = 186900, .val = 0x14 }, | ||
282 | { .rfmax = 192400, .val = 0x13 }, | ||
283 | { .rfmax = 198000, .val = 0x12 }, | ||
284 | { .rfmax = 203500, .val = 0x11 }, | ||
285 | { .rfmax = 216200, .val = 0x14 }, | ||
286 | { .rfmax = 228900, .val = 0x13 }, | ||
287 | { .rfmax = 241600, .val = 0x12 }, | ||
288 | { .rfmax = 254400, .val = 0x11 }, | ||
289 | { .rfmax = 267100, .val = 0x10 }, | ||
290 | { .rfmax = 279800, .val = 0x0f }, | ||
291 | { .rfmax = 292500, .val = 0x0e }, | ||
292 | { .rfmax = 305200, .val = 0x0d }, | ||
293 | { .rfmax = 317900, .val = 0x0c }, | ||
294 | { .rfmax = 330700, .val = 0x0b }, | ||
295 | { .rfmax = 343400, .val = 0x0a }, | ||
296 | { .rfmax = 356100, .val = 0x09 }, | ||
297 | { .rfmax = 368800, .val = 0x08 }, | ||
298 | { .rfmax = 381500, .val = 0x07 }, | ||
299 | { .rfmax = 394200, .val = 0x06 }, | ||
300 | { .rfmax = 406900, .val = 0x05 }, | ||
301 | { .rfmax = 419700, .val = 0x04 }, | ||
302 | { .rfmax = 432400, .val = 0x03 }, | ||
303 | { .rfmax = 445100, .val = 0x02 }, | ||
304 | { .rfmax = 457800, .val = 0x01 }, | ||
305 | { .rfmax = 476300, .val = 0x19 }, | ||
306 | { .rfmax = 494800, .val = 0x18 }, | ||
307 | { .rfmax = 513300, .val = 0x17 }, | ||
308 | { .rfmax = 531800, .val = 0x16 }, | ||
309 | { .rfmax = 550300, .val = 0x15 }, | ||
310 | { .rfmax = 568900, .val = 0x14 }, | ||
311 | { .rfmax = 587400, .val = 0x13 }, | ||
312 | { .rfmax = 605900, .val = 0x12 }, | ||
313 | { .rfmax = 624400, .val = 0x11 }, | ||
314 | { .rfmax = 642900, .val = 0x10 }, | ||
315 | { .rfmax = 661400, .val = 0x0f }, | ||
316 | { .rfmax = 679900, .val = 0x0e }, | ||
317 | { .rfmax = 698400, .val = 0x0d }, | ||
318 | { .rfmax = 716900, .val = 0x0c }, | ||
319 | { .rfmax = 735400, .val = 0x0b }, | ||
320 | { .rfmax = 753900, .val = 0x0a }, | ||
321 | { .rfmax = 772500, .val = 0x09 }, | ||
322 | { .rfmax = 791000, .val = 0x08 }, | ||
323 | { .rfmax = 809500, .val = 0x07 }, | ||
324 | { .rfmax = 828000, .val = 0x06 }, | ||
325 | { .rfmax = 846500, .val = 0x05 }, | ||
326 | { .rfmax = 865000, .val = 0x04 }, | ||
327 | { .rfmax = 0, .val = 0x00 }, /* end */ | ||
328 | }; | ||
329 | |||
330 | static struct tda18271_map tda18271c1_rf_cal[] = { | ||
331 | { .rfmax = 41000, .val = 0x1e }, | ||
332 | { .rfmax = 43000, .val = 0x30 }, | ||
333 | { .rfmax = 45000, .val = 0x43 }, | ||
334 | { .rfmax = 46000, .val = 0x4d }, | ||
335 | { .rfmax = 47000, .val = 0x54 }, | ||
336 | { .rfmax = 47900, .val = 0x64 }, | ||
337 | { .rfmax = 49100, .val = 0x20 }, | ||
338 | { .rfmax = 50000, .val = 0x22 }, | ||
339 | { .rfmax = 51000, .val = 0x2a }, | ||
340 | { .rfmax = 53000, .val = 0x32 }, | ||
341 | { .rfmax = 55000, .val = 0x35 }, | ||
342 | { .rfmax = 56000, .val = 0x3c }, | ||
343 | { .rfmax = 57000, .val = 0x3f }, | ||
344 | { .rfmax = 58000, .val = 0x48 }, | ||
345 | { .rfmax = 59000, .val = 0x4d }, | ||
346 | { .rfmax = 60000, .val = 0x58 }, | ||
347 | { .rfmax = 61100, .val = 0x5f }, | ||
348 | { .rfmax = 0, .val = 0x00 }, /* end */ | ||
349 | }; | ||
350 | |||
351 | static struct tda18271_map tda18271c2_rf_cal[] = { | ||
352 | { .rfmax = 41000, .val = 0x0f }, | ||
353 | { .rfmax = 43000, .val = 0x1c }, | ||
354 | { .rfmax = 45000, .val = 0x2f }, | ||
355 | { .rfmax = 46000, .val = 0x39 }, | ||
356 | { .rfmax = 47000, .val = 0x40 }, | ||
357 | { .rfmax = 47900, .val = 0x50 }, | ||
358 | { .rfmax = 49100, .val = 0x16 }, | ||
359 | { .rfmax = 50000, .val = 0x18 }, | ||
360 | { .rfmax = 51000, .val = 0x20 }, | ||
361 | { .rfmax = 53000, .val = 0x28 }, | ||
362 | { .rfmax = 55000, .val = 0x2b }, | ||
363 | { .rfmax = 56000, .val = 0x32 }, | ||
364 | { .rfmax = 57000, .val = 0x35 }, | ||
365 | { .rfmax = 58000, .val = 0x3e }, | ||
366 | { .rfmax = 59000, .val = 0x43 }, | ||
367 | { .rfmax = 60000, .val = 0x4e }, | ||
368 | { .rfmax = 61100, .val = 0x55 }, | ||
369 | { .rfmax = 63000, .val = 0x0f }, | ||
370 | { .rfmax = 64000, .val = 0x11 }, | ||
371 | { .rfmax = 65000, .val = 0x12 }, | ||
372 | { .rfmax = 66000, .val = 0x15 }, | ||
373 | { .rfmax = 67000, .val = 0x16 }, | ||
374 | { .rfmax = 68000, .val = 0x17 }, | ||
375 | { .rfmax = 70000, .val = 0x19 }, | ||
376 | { .rfmax = 71000, .val = 0x1c }, | ||
377 | { .rfmax = 72000, .val = 0x1d }, | ||
378 | { .rfmax = 73000, .val = 0x1f }, | ||
379 | { .rfmax = 74000, .val = 0x20 }, | ||
380 | { .rfmax = 75000, .val = 0x21 }, | ||
381 | { .rfmax = 76000, .val = 0x24 }, | ||
382 | { .rfmax = 77000, .val = 0x25 }, | ||
383 | { .rfmax = 78000, .val = 0x27 }, | ||
384 | { .rfmax = 80000, .val = 0x28 }, | ||
385 | { .rfmax = 81000, .val = 0x29 }, | ||
386 | { .rfmax = 82000, .val = 0x2d }, | ||
387 | { .rfmax = 83000, .val = 0x2e }, | ||
388 | { .rfmax = 84000, .val = 0x2f }, | ||
389 | { .rfmax = 85000, .val = 0x31 }, | ||
390 | { .rfmax = 86000, .val = 0x33 }, | ||
391 | { .rfmax = 87000, .val = 0x34 }, | ||
392 | { .rfmax = 88000, .val = 0x35 }, | ||
393 | { .rfmax = 89000, .val = 0x37 }, | ||
394 | { .rfmax = 90000, .val = 0x38 }, | ||
395 | { .rfmax = 91000, .val = 0x39 }, | ||
396 | { .rfmax = 93000, .val = 0x3c }, | ||
397 | { .rfmax = 94000, .val = 0x3e }, | ||
398 | { .rfmax = 95000, .val = 0x3f }, | ||
399 | { .rfmax = 96000, .val = 0x40 }, | ||
400 | { .rfmax = 97000, .val = 0x42 }, | ||
401 | { .rfmax = 99000, .val = 0x45 }, | ||
402 | { .rfmax = 100000, .val = 0x46 }, | ||
403 | { .rfmax = 102000, .val = 0x48 }, | ||
404 | { .rfmax = 103000, .val = 0x4a }, | ||
405 | { .rfmax = 105000, .val = 0x4d }, | ||
406 | { .rfmax = 106000, .val = 0x4e }, | ||
407 | { .rfmax = 107000, .val = 0x50 }, | ||
408 | { .rfmax = 108000, .val = 0x51 }, | ||
409 | { .rfmax = 110000, .val = 0x54 }, | ||
410 | { .rfmax = 111000, .val = 0x56 }, | ||
411 | { .rfmax = 112000, .val = 0x57 }, | ||
412 | { .rfmax = 113000, .val = 0x58 }, | ||
413 | { .rfmax = 114000, .val = 0x59 }, | ||
414 | { .rfmax = 115000, .val = 0x5c }, | ||
415 | { .rfmax = 116000, .val = 0x5d }, | ||
416 | { .rfmax = 117000, .val = 0x5f }, | ||
417 | { .rfmax = 119000, .val = 0x60 }, | ||
418 | { .rfmax = 120000, .val = 0x64 }, | ||
419 | { .rfmax = 121000, .val = 0x65 }, | ||
420 | { .rfmax = 122000, .val = 0x66 }, | ||
421 | { .rfmax = 123000, .val = 0x68 }, | ||
422 | { .rfmax = 124000, .val = 0x69 }, | ||
423 | { .rfmax = 125000, .val = 0x6c }, | ||
424 | { .rfmax = 126000, .val = 0x6d }, | ||
425 | { .rfmax = 127000, .val = 0x6e }, | ||
426 | { .rfmax = 128000, .val = 0x70 }, | ||
427 | { .rfmax = 129000, .val = 0x71 }, | ||
428 | { .rfmax = 130000, .val = 0x75 }, | ||
429 | { .rfmax = 131000, .val = 0x77 }, | ||
430 | { .rfmax = 132000, .val = 0x78 }, | ||
431 | { .rfmax = 133000, .val = 0x7b }, | ||
432 | { .rfmax = 134000, .val = 0x7e }, | ||
433 | { .rfmax = 135000, .val = 0x81 }, | ||
434 | { .rfmax = 136000, .val = 0x82 }, | ||
435 | { .rfmax = 137000, .val = 0x87 }, | ||
436 | { .rfmax = 138000, .val = 0x88 }, | ||
437 | { .rfmax = 139000, .val = 0x8d }, | ||
438 | { .rfmax = 140000, .val = 0x8e }, | ||
439 | { .rfmax = 141000, .val = 0x91 }, | ||
440 | { .rfmax = 142000, .val = 0x95 }, | ||
441 | { .rfmax = 143000, .val = 0x9a }, | ||
442 | { .rfmax = 144000, .val = 0x9d }, | ||
443 | { .rfmax = 145000, .val = 0xa1 }, | ||
444 | { .rfmax = 146000, .val = 0xa2 }, | ||
445 | { .rfmax = 147000, .val = 0xa4 }, | ||
446 | { .rfmax = 148000, .val = 0xa9 }, | ||
447 | { .rfmax = 149000, .val = 0xae }, | ||
448 | { .rfmax = 150000, .val = 0xb0 }, | ||
449 | { .rfmax = 151000, .val = 0xb1 }, | ||
450 | { .rfmax = 152000, .val = 0xb7 }, | ||
451 | { .rfmax = 153000, .val = 0xbd }, | ||
452 | { .rfmax = 154000, .val = 0x20 }, | ||
453 | { .rfmax = 155000, .val = 0x22 }, | ||
454 | { .rfmax = 156000, .val = 0x24 }, | ||
455 | { .rfmax = 157000, .val = 0x25 }, | ||
456 | { .rfmax = 158000, .val = 0x27 }, | ||
457 | { .rfmax = 159000, .val = 0x29 }, | ||
458 | { .rfmax = 160000, .val = 0x2c }, | ||
459 | { .rfmax = 161000, .val = 0x2d }, | ||
460 | { .rfmax = 163000, .val = 0x2e }, | ||
461 | { .rfmax = 164000, .val = 0x2f }, | ||
462 | { .rfmax = 165000, .val = 0x30 }, | ||
463 | { .rfmax = 166000, .val = 0x11 }, | ||
464 | { .rfmax = 167000, .val = 0x12 }, | ||
465 | { .rfmax = 168000, .val = 0x13 }, | ||
466 | { .rfmax = 169000, .val = 0x14 }, | ||
467 | { .rfmax = 170000, .val = 0x15 }, | ||
468 | { .rfmax = 172000, .val = 0x16 }, | ||
469 | { .rfmax = 173000, .val = 0x17 }, | ||
470 | { .rfmax = 174000, .val = 0x18 }, | ||
471 | { .rfmax = 175000, .val = 0x1a }, | ||
472 | { .rfmax = 176000, .val = 0x1b }, | ||
473 | { .rfmax = 178000, .val = 0x1d }, | ||
474 | { .rfmax = 179000, .val = 0x1e }, | ||
475 | { .rfmax = 180000, .val = 0x1f }, | ||
476 | { .rfmax = 181000, .val = 0x20 }, | ||
477 | { .rfmax = 182000, .val = 0x21 }, | ||
478 | { .rfmax = 183000, .val = 0x22 }, | ||
479 | { .rfmax = 184000, .val = 0x24 }, | ||
480 | { .rfmax = 185000, .val = 0x25 }, | ||
481 | { .rfmax = 186000, .val = 0x26 }, | ||
482 | { .rfmax = 187000, .val = 0x27 }, | ||
483 | { .rfmax = 188000, .val = 0x29 }, | ||
484 | { .rfmax = 189000, .val = 0x2a }, | ||
485 | { .rfmax = 190000, .val = 0x2c }, | ||
486 | { .rfmax = 191000, .val = 0x2d }, | ||
487 | { .rfmax = 192000, .val = 0x2e }, | ||
488 | { .rfmax = 193000, .val = 0x2f }, | ||
489 | { .rfmax = 194000, .val = 0x30 }, | ||
490 | { .rfmax = 195000, .val = 0x33 }, | ||
491 | { .rfmax = 196000, .val = 0x35 }, | ||
492 | { .rfmax = 198000, .val = 0x36 }, | ||
493 | { .rfmax = 200000, .val = 0x38 }, | ||
494 | { .rfmax = 201000, .val = 0x3c }, | ||
495 | { .rfmax = 202000, .val = 0x3d }, | ||
496 | { .rfmax = 203500, .val = 0x3e }, | ||
497 | { .rfmax = 206000, .val = 0x0e }, | ||
498 | { .rfmax = 208000, .val = 0x0f }, | ||
499 | { .rfmax = 212000, .val = 0x10 }, | ||
500 | { .rfmax = 216000, .val = 0x11 }, | ||
501 | { .rfmax = 217000, .val = 0x12 }, | ||
502 | { .rfmax = 218000, .val = 0x13 }, | ||
503 | { .rfmax = 220000, .val = 0x14 }, | ||
504 | { .rfmax = 222000, .val = 0x15 }, | ||
505 | { .rfmax = 225000, .val = 0x16 }, | ||
506 | { .rfmax = 228000, .val = 0x17 }, | ||
507 | { .rfmax = 231000, .val = 0x18 }, | ||
508 | { .rfmax = 234000, .val = 0x19 }, | ||
509 | { .rfmax = 235000, .val = 0x1a }, | ||
510 | { .rfmax = 236000, .val = 0x1b }, | ||
511 | { .rfmax = 237000, .val = 0x1c }, | ||
512 | { .rfmax = 240000, .val = 0x1d }, | ||
513 | { .rfmax = 242000, .val = 0x1f }, | ||
514 | { .rfmax = 247000, .val = 0x20 }, | ||
515 | { .rfmax = 249000, .val = 0x21 }, | ||
516 | { .rfmax = 252000, .val = 0x22 }, | ||
517 | { .rfmax = 253000, .val = 0x23 }, | ||
518 | { .rfmax = 254000, .val = 0x24 }, | ||
519 | { .rfmax = 256000, .val = 0x25 }, | ||
520 | { .rfmax = 259000, .val = 0x26 }, | ||
521 | { .rfmax = 262000, .val = 0x27 }, | ||
522 | { .rfmax = 264000, .val = 0x28 }, | ||
523 | { .rfmax = 267000, .val = 0x29 }, | ||
524 | { .rfmax = 269000, .val = 0x2a }, | ||
525 | { .rfmax = 271000, .val = 0x2b }, | ||
526 | { .rfmax = 273000, .val = 0x2c }, | ||
527 | { .rfmax = 275000, .val = 0x2d }, | ||
528 | { .rfmax = 277000, .val = 0x2e }, | ||
529 | { .rfmax = 279000, .val = 0x2f }, | ||
530 | { .rfmax = 282000, .val = 0x30 }, | ||
531 | { .rfmax = 284000, .val = 0x31 }, | ||
532 | { .rfmax = 286000, .val = 0x32 }, | ||
533 | { .rfmax = 287000, .val = 0x33 }, | ||
534 | { .rfmax = 290000, .val = 0x34 }, | ||
535 | { .rfmax = 293000, .val = 0x35 }, | ||
536 | { .rfmax = 295000, .val = 0x36 }, | ||
537 | { .rfmax = 297000, .val = 0x37 }, | ||
538 | { .rfmax = 300000, .val = 0x38 }, | ||
539 | { .rfmax = 303000, .val = 0x39 }, | ||
540 | { .rfmax = 305000, .val = 0x3a }, | ||
541 | { .rfmax = 306000, .val = 0x3b }, | ||
542 | { .rfmax = 307000, .val = 0x3c }, | ||
543 | { .rfmax = 310000, .val = 0x3d }, | ||
544 | { .rfmax = 312000, .val = 0x3e }, | ||
545 | { .rfmax = 315000, .val = 0x3f }, | ||
546 | { .rfmax = 318000, .val = 0x40 }, | ||
547 | { .rfmax = 320000, .val = 0x41 }, | ||
548 | { .rfmax = 323000, .val = 0x42 }, | ||
549 | { .rfmax = 324000, .val = 0x43 }, | ||
550 | { .rfmax = 325000, .val = 0x44 }, | ||
551 | { .rfmax = 327000, .val = 0x45 }, | ||
552 | { .rfmax = 331000, .val = 0x46 }, | ||
553 | { .rfmax = 334000, .val = 0x47 }, | ||
554 | { .rfmax = 337000, .val = 0x48 }, | ||
555 | { .rfmax = 339000, .val = 0x49 }, | ||
556 | { .rfmax = 340000, .val = 0x4a }, | ||
557 | { .rfmax = 341000, .val = 0x4b }, | ||
558 | { .rfmax = 343000, .val = 0x4c }, | ||
559 | { .rfmax = 345000, .val = 0x4d }, | ||
560 | { .rfmax = 349000, .val = 0x4e }, | ||
561 | { .rfmax = 352000, .val = 0x4f }, | ||
562 | { .rfmax = 353000, .val = 0x50 }, | ||
563 | { .rfmax = 355000, .val = 0x51 }, | ||
564 | { .rfmax = 357000, .val = 0x52 }, | ||
565 | { .rfmax = 359000, .val = 0x53 }, | ||
566 | { .rfmax = 361000, .val = 0x54 }, | ||
567 | { .rfmax = 362000, .val = 0x55 }, | ||
568 | { .rfmax = 364000, .val = 0x56 }, | ||
569 | { .rfmax = 368000, .val = 0x57 }, | ||
570 | { .rfmax = 370000, .val = 0x58 }, | ||
571 | { .rfmax = 372000, .val = 0x59 }, | ||
572 | { .rfmax = 375000, .val = 0x5a }, | ||
573 | { .rfmax = 376000, .val = 0x5b }, | ||
574 | { .rfmax = 377000, .val = 0x5c }, | ||
575 | { .rfmax = 379000, .val = 0x5d }, | ||
576 | { .rfmax = 382000, .val = 0x5e }, | ||
577 | { .rfmax = 384000, .val = 0x5f }, | ||
578 | { .rfmax = 385000, .val = 0x60 }, | ||
579 | { .rfmax = 386000, .val = 0x61 }, | ||
580 | { .rfmax = 388000, .val = 0x62 }, | ||
581 | { .rfmax = 390000, .val = 0x63 }, | ||
582 | { .rfmax = 393000, .val = 0x64 }, | ||
583 | { .rfmax = 394000, .val = 0x65 }, | ||
584 | { .rfmax = 396000, .val = 0x66 }, | ||
585 | { .rfmax = 397000, .val = 0x67 }, | ||
586 | { .rfmax = 398000, .val = 0x68 }, | ||
587 | { .rfmax = 400000, .val = 0x69 }, | ||
588 | { .rfmax = 402000, .val = 0x6a }, | ||
589 | { .rfmax = 403000, .val = 0x6b }, | ||
590 | { .rfmax = 407000, .val = 0x6c }, | ||
591 | { .rfmax = 408000, .val = 0x6d }, | ||
592 | { .rfmax = 409000, .val = 0x6e }, | ||
593 | { .rfmax = 410000, .val = 0x6f }, | ||
594 | { .rfmax = 411000, .val = 0x70 }, | ||
595 | { .rfmax = 412000, .val = 0x71 }, | ||
596 | { .rfmax = 413000, .val = 0x72 }, | ||
597 | { .rfmax = 414000, .val = 0x73 }, | ||
598 | { .rfmax = 417000, .val = 0x74 }, | ||
599 | { .rfmax = 418000, .val = 0x75 }, | ||
600 | { .rfmax = 420000, .val = 0x76 }, | ||
601 | { .rfmax = 422000, .val = 0x77 }, | ||
602 | { .rfmax = 423000, .val = 0x78 }, | ||
603 | { .rfmax = 424000, .val = 0x79 }, | ||
604 | { .rfmax = 427000, .val = 0x7a }, | ||
605 | { .rfmax = 428000, .val = 0x7b }, | ||
606 | { .rfmax = 429000, .val = 0x7d }, | ||
607 | { .rfmax = 432000, .val = 0x7f }, | ||
608 | { .rfmax = 434000, .val = 0x80 }, | ||
609 | { .rfmax = 435000, .val = 0x81 }, | ||
610 | { .rfmax = 436000, .val = 0x83 }, | ||
611 | { .rfmax = 437000, .val = 0x84 }, | ||
612 | { .rfmax = 438000, .val = 0x85 }, | ||
613 | { .rfmax = 439000, .val = 0x86 }, | ||
614 | { .rfmax = 440000, .val = 0x87 }, | ||
615 | { .rfmax = 441000, .val = 0x88 }, | ||
616 | { .rfmax = 442000, .val = 0x89 }, | ||
617 | { .rfmax = 445000, .val = 0x8a }, | ||
618 | { .rfmax = 446000, .val = 0x8b }, | ||
619 | { .rfmax = 447000, .val = 0x8c }, | ||
620 | { .rfmax = 448000, .val = 0x8e }, | ||
621 | { .rfmax = 449000, .val = 0x8f }, | ||
622 | { .rfmax = 450000, .val = 0x90 }, | ||
623 | { .rfmax = 452000, .val = 0x91 }, | ||
624 | { .rfmax = 453000, .val = 0x93 }, | ||
625 | { .rfmax = 454000, .val = 0x94 }, | ||
626 | { .rfmax = 456000, .val = 0x96 }, | ||
627 | { .rfmax = 457000, .val = 0x98 }, | ||
628 | { .rfmax = 461000, .val = 0x11 }, | ||
629 | { .rfmax = 468000, .val = 0x12 }, | ||
630 | { .rfmax = 472000, .val = 0x13 }, | ||
631 | { .rfmax = 473000, .val = 0x14 }, | ||
632 | { .rfmax = 474000, .val = 0x15 }, | ||
633 | { .rfmax = 481000, .val = 0x16 }, | ||
634 | { .rfmax = 486000, .val = 0x17 }, | ||
635 | { .rfmax = 491000, .val = 0x18 }, | ||
636 | { .rfmax = 498000, .val = 0x19 }, | ||
637 | { .rfmax = 499000, .val = 0x1a }, | ||
638 | { .rfmax = 501000, .val = 0x1b }, | ||
639 | { .rfmax = 506000, .val = 0x1c }, | ||
640 | { .rfmax = 511000, .val = 0x1d }, | ||
641 | { .rfmax = 516000, .val = 0x1e }, | ||
642 | { .rfmax = 520000, .val = 0x1f }, | ||
643 | { .rfmax = 521000, .val = 0x20 }, | ||
644 | { .rfmax = 525000, .val = 0x21 }, | ||
645 | { .rfmax = 529000, .val = 0x22 }, | ||
646 | { .rfmax = 533000, .val = 0x23 }, | ||
647 | { .rfmax = 539000, .val = 0x24 }, | ||
648 | { .rfmax = 541000, .val = 0x25 }, | ||
649 | { .rfmax = 547000, .val = 0x26 }, | ||
650 | { .rfmax = 549000, .val = 0x27 }, | ||
651 | { .rfmax = 551000, .val = 0x28 }, | ||
652 | { .rfmax = 556000, .val = 0x29 }, | ||
653 | { .rfmax = 561000, .val = 0x2a }, | ||
654 | { .rfmax = 563000, .val = 0x2b }, | ||
655 | { .rfmax = 565000, .val = 0x2c }, | ||
656 | { .rfmax = 569000, .val = 0x2d }, | ||
657 | { .rfmax = 571000, .val = 0x2e }, | ||
658 | { .rfmax = 577000, .val = 0x2f }, | ||
659 | { .rfmax = 580000, .val = 0x30 }, | ||
660 | { .rfmax = 582000, .val = 0x31 }, | ||
661 | { .rfmax = 584000, .val = 0x32 }, | ||
662 | { .rfmax = 588000, .val = 0x33 }, | ||
663 | { .rfmax = 591000, .val = 0x34 }, | ||
664 | { .rfmax = 596000, .val = 0x35 }, | ||
665 | { .rfmax = 598000, .val = 0x36 }, | ||
666 | { .rfmax = 603000, .val = 0x37 }, | ||
667 | { .rfmax = 604000, .val = 0x38 }, | ||
668 | { .rfmax = 606000, .val = 0x39 }, | ||
669 | { .rfmax = 612000, .val = 0x3a }, | ||
670 | { .rfmax = 615000, .val = 0x3b }, | ||
671 | { .rfmax = 617000, .val = 0x3c }, | ||
672 | { .rfmax = 621000, .val = 0x3d }, | ||
673 | { .rfmax = 622000, .val = 0x3e }, | ||
674 | { .rfmax = 625000, .val = 0x3f }, | ||
675 | { .rfmax = 632000, .val = 0x40 }, | ||
676 | { .rfmax = 633000, .val = 0x41 }, | ||
677 | { .rfmax = 634000, .val = 0x42 }, | ||
678 | { .rfmax = 642000, .val = 0x43 }, | ||
679 | { .rfmax = 643000, .val = 0x44 }, | ||
680 | { .rfmax = 647000, .val = 0x45 }, | ||
681 | { .rfmax = 650000, .val = 0x46 }, | ||
682 | { .rfmax = 652000, .val = 0x47 }, | ||
683 | { .rfmax = 657000, .val = 0x48 }, | ||
684 | { .rfmax = 661000, .val = 0x49 }, | ||
685 | { .rfmax = 662000, .val = 0x4a }, | ||
686 | { .rfmax = 665000, .val = 0x4b }, | ||
687 | { .rfmax = 667000, .val = 0x4c }, | ||
688 | { .rfmax = 670000, .val = 0x4d }, | ||
689 | { .rfmax = 673000, .val = 0x4e }, | ||
690 | { .rfmax = 676000, .val = 0x4f }, | ||
691 | { .rfmax = 677000, .val = 0x50 }, | ||
692 | { .rfmax = 681000, .val = 0x51 }, | ||
693 | { .rfmax = 683000, .val = 0x52 }, | ||
694 | { .rfmax = 686000, .val = 0x53 }, | ||
695 | { .rfmax = 688000, .val = 0x54 }, | ||
696 | { .rfmax = 689000, .val = 0x55 }, | ||
697 | { .rfmax = 691000, .val = 0x56 }, | ||
698 | { .rfmax = 695000, .val = 0x57 }, | ||
699 | { .rfmax = 698000, .val = 0x58 }, | ||
700 | { .rfmax = 703000, .val = 0x59 }, | ||
701 | { .rfmax = 704000, .val = 0x5a }, | ||
702 | { .rfmax = 705000, .val = 0x5b }, | ||
703 | { .rfmax = 707000, .val = 0x5c }, | ||
704 | { .rfmax = 710000, .val = 0x5d }, | ||
705 | { .rfmax = 712000, .val = 0x5e }, | ||
706 | { .rfmax = 717000, .val = 0x5f }, | ||
707 | { .rfmax = 718000, .val = 0x60 }, | ||
708 | { .rfmax = 721000, .val = 0x61 }, | ||
709 | { .rfmax = 722000, .val = 0x62 }, | ||
710 | { .rfmax = 723000, .val = 0x63 }, | ||
711 | { .rfmax = 725000, .val = 0x64 }, | ||
712 | { .rfmax = 727000, .val = 0x65 }, | ||
713 | { .rfmax = 730000, .val = 0x66 }, | ||
714 | { .rfmax = 732000, .val = 0x67 }, | ||
715 | { .rfmax = 735000, .val = 0x68 }, | ||
716 | { .rfmax = 740000, .val = 0x69 }, | ||
717 | { .rfmax = 741000, .val = 0x6a }, | ||
718 | { .rfmax = 742000, .val = 0x6b }, | ||
719 | { .rfmax = 743000, .val = 0x6c }, | ||
720 | { .rfmax = 745000, .val = 0x6d }, | ||
721 | { .rfmax = 747000, .val = 0x6e }, | ||
722 | { .rfmax = 748000, .val = 0x6f }, | ||
723 | { .rfmax = 750000, .val = 0x70 }, | ||
724 | { .rfmax = 752000, .val = 0x71 }, | ||
725 | { .rfmax = 754000, .val = 0x72 }, | ||
726 | { .rfmax = 757000, .val = 0x73 }, | ||
727 | { .rfmax = 758000, .val = 0x74 }, | ||
728 | { .rfmax = 760000, .val = 0x75 }, | ||
729 | { .rfmax = 763000, .val = 0x76 }, | ||
730 | { .rfmax = 764000, .val = 0x77 }, | ||
731 | { .rfmax = 766000, .val = 0x78 }, | ||
732 | { .rfmax = 767000, .val = 0x79 }, | ||
733 | { .rfmax = 768000, .val = 0x7a }, | ||
734 | { .rfmax = 773000, .val = 0x7b }, | ||
735 | { .rfmax = 774000, .val = 0x7c }, | ||
736 | { .rfmax = 776000, .val = 0x7d }, | ||
737 | { .rfmax = 777000, .val = 0x7e }, | ||
738 | { .rfmax = 778000, .val = 0x7f }, | ||
739 | { .rfmax = 779000, .val = 0x80 }, | ||
740 | { .rfmax = 781000, .val = 0x81 }, | ||
741 | { .rfmax = 783000, .val = 0x82 }, | ||
742 | { .rfmax = 784000, .val = 0x83 }, | ||
743 | { .rfmax = 785000, .val = 0x84 }, | ||
744 | { .rfmax = 786000, .val = 0x85 }, | ||
745 | { .rfmax = 793000, .val = 0x86 }, | ||
746 | { .rfmax = 794000, .val = 0x87 }, | ||
747 | { .rfmax = 795000, .val = 0x88 }, | ||
748 | { .rfmax = 797000, .val = 0x89 }, | ||
749 | { .rfmax = 799000, .val = 0x8a }, | ||
750 | { .rfmax = 801000, .val = 0x8b }, | ||
751 | { .rfmax = 802000, .val = 0x8c }, | ||
752 | { .rfmax = 803000, .val = 0x8d }, | ||
753 | { .rfmax = 804000, .val = 0x8e }, | ||
754 | { .rfmax = 810000, .val = 0x90 }, | ||
755 | { .rfmax = 811000, .val = 0x91 }, | ||
756 | { .rfmax = 812000, .val = 0x92 }, | ||
757 | { .rfmax = 814000, .val = 0x93 }, | ||
758 | { .rfmax = 816000, .val = 0x94 }, | ||
759 | { .rfmax = 817000, .val = 0x96 }, | ||
760 | { .rfmax = 818000, .val = 0x97 }, | ||
761 | { .rfmax = 820000, .val = 0x98 }, | ||
762 | { .rfmax = 821000, .val = 0x99 }, | ||
763 | { .rfmax = 822000, .val = 0x9a }, | ||
764 | { .rfmax = 828000, .val = 0x9b }, | ||
765 | { .rfmax = 829000, .val = 0x9d }, | ||
766 | { .rfmax = 830000, .val = 0x9f }, | ||
767 | { .rfmax = 831000, .val = 0xa0 }, | ||
768 | { .rfmax = 833000, .val = 0xa1 }, | ||
769 | { .rfmax = 835000, .val = 0xa2 }, | ||
770 | { .rfmax = 836000, .val = 0xa3 }, | ||
771 | { .rfmax = 837000, .val = 0xa4 }, | ||
772 | { .rfmax = 838000, .val = 0xa6 }, | ||
773 | { .rfmax = 840000, .val = 0xa8 }, | ||
774 | { .rfmax = 842000, .val = 0xa9 }, | ||
775 | { .rfmax = 845000, .val = 0xaa }, | ||
776 | { .rfmax = 846000, .val = 0xab }, | ||
777 | { .rfmax = 847000, .val = 0xad }, | ||
778 | { .rfmax = 848000, .val = 0xae }, | ||
779 | { .rfmax = 852000, .val = 0xaf }, | ||
780 | { .rfmax = 853000, .val = 0xb0 }, | ||
781 | { .rfmax = 858000, .val = 0xb1 }, | ||
782 | { .rfmax = 860000, .val = 0xb2 }, | ||
783 | { .rfmax = 861000, .val = 0xb3 }, | ||
784 | { .rfmax = 862000, .val = 0xb4 }, | ||
785 | { .rfmax = 863000, .val = 0xb6 }, | ||
786 | { .rfmax = 864000, .val = 0xb8 }, | ||
787 | { .rfmax = 865000, .val = 0xb9 }, | ||
788 | { .rfmax = 0, .val = 0x00 }, /* end */ | ||
789 | }; | ||
790 | |||
791 | static struct tda18271_map tda18271_ir_measure[] = { | ||
792 | { .rfmax = 30000, .val = 4 }, | ||
793 | { .rfmax = 200000, .val = 5 }, | ||
794 | { .rfmax = 600000, .val = 6 }, | ||
795 | { .rfmax = 865000, .val = 7 }, | ||
796 | { .rfmax = 0, .val = 0 }, /* end */ | ||
797 | }; | ||
798 | |||
799 | static struct tda18271_map tda18271_rf_cal_dc_over_dt[] = { | ||
800 | { .rfmax = 47900, .val = 0x00 }, | ||
801 | { .rfmax = 55000, .val = 0x00 }, | ||
802 | { .rfmax = 61100, .val = 0x0a }, | ||
803 | { .rfmax = 64000, .val = 0x0a }, | ||
804 | { .rfmax = 82000, .val = 0x14 }, | ||
805 | { .rfmax = 84000, .val = 0x19 }, | ||
806 | { .rfmax = 119000, .val = 0x1c }, | ||
807 | { .rfmax = 124000, .val = 0x20 }, | ||
808 | { .rfmax = 129000, .val = 0x2a }, | ||
809 | { .rfmax = 134000, .val = 0x32 }, | ||
810 | { .rfmax = 139000, .val = 0x39 }, | ||
811 | { .rfmax = 144000, .val = 0x3e }, | ||
812 | { .rfmax = 149000, .val = 0x3f }, | ||
813 | { .rfmax = 152600, .val = 0x40 }, | ||
814 | { .rfmax = 154000, .val = 0x40 }, | ||
815 | { .rfmax = 164700, .val = 0x41 }, | ||
816 | { .rfmax = 203500, .val = 0x32 }, | ||
817 | { .rfmax = 353000, .val = 0x19 }, | ||
818 | { .rfmax = 356000, .val = 0x1a }, | ||
819 | { .rfmax = 359000, .val = 0x1b }, | ||
820 | { .rfmax = 363000, .val = 0x1c }, | ||
821 | { .rfmax = 366000, .val = 0x1d }, | ||
822 | { .rfmax = 369000, .val = 0x1e }, | ||
823 | { .rfmax = 373000, .val = 0x1f }, | ||
824 | { .rfmax = 376000, .val = 0x20 }, | ||
825 | { .rfmax = 379000, .val = 0x21 }, | ||
826 | { .rfmax = 383000, .val = 0x22 }, | ||
827 | { .rfmax = 386000, .val = 0x23 }, | ||
828 | { .rfmax = 389000, .val = 0x24 }, | ||
829 | { .rfmax = 393000, .val = 0x25 }, | ||
830 | { .rfmax = 396000, .val = 0x26 }, | ||
831 | { .rfmax = 399000, .val = 0x27 }, | ||
832 | { .rfmax = 402000, .val = 0x28 }, | ||
833 | { .rfmax = 404000, .val = 0x29 }, | ||
834 | { .rfmax = 407000, .val = 0x2a }, | ||
835 | { .rfmax = 409000, .val = 0x2b }, | ||
836 | { .rfmax = 412000, .val = 0x2c }, | ||
837 | { .rfmax = 414000, .val = 0x2d }, | ||
838 | { .rfmax = 417000, .val = 0x2e }, | ||
839 | { .rfmax = 419000, .val = 0x2f }, | ||
840 | { .rfmax = 422000, .val = 0x30 }, | ||
841 | { .rfmax = 424000, .val = 0x31 }, | ||
842 | { .rfmax = 427000, .val = 0x32 }, | ||
843 | { .rfmax = 429000, .val = 0x33 }, | ||
844 | { .rfmax = 432000, .val = 0x34 }, | ||
845 | { .rfmax = 434000, .val = 0x35 }, | ||
846 | { .rfmax = 437000, .val = 0x36 }, | ||
847 | { .rfmax = 439000, .val = 0x37 }, | ||
848 | { .rfmax = 442000, .val = 0x38 }, | ||
849 | { .rfmax = 444000, .val = 0x39 }, | ||
850 | { .rfmax = 447000, .val = 0x3a }, | ||
851 | { .rfmax = 449000, .val = 0x3b }, | ||
852 | { .rfmax = 457800, .val = 0x3c }, | ||
853 | { .rfmax = 465000, .val = 0x0f }, | ||
854 | { .rfmax = 477000, .val = 0x12 }, | ||
855 | { .rfmax = 483000, .val = 0x14 }, | ||
856 | { .rfmax = 502000, .val = 0x19 }, | ||
857 | { .rfmax = 508000, .val = 0x1b }, | ||
858 | { .rfmax = 519000, .val = 0x1c }, | ||
859 | { .rfmax = 522000, .val = 0x1d }, | ||
860 | { .rfmax = 524000, .val = 0x1e }, | ||
861 | { .rfmax = 534000, .val = 0x1f }, | ||
862 | { .rfmax = 549000, .val = 0x20 }, | ||
863 | { .rfmax = 554000, .val = 0x22 }, | ||
864 | { .rfmax = 584000, .val = 0x24 }, | ||
865 | { .rfmax = 589000, .val = 0x26 }, | ||
866 | { .rfmax = 658000, .val = 0x27 }, | ||
867 | { .rfmax = 664000, .val = 0x2c }, | ||
868 | { .rfmax = 669000, .val = 0x2d }, | ||
869 | { .rfmax = 699000, .val = 0x2e }, | ||
870 | { .rfmax = 704000, .val = 0x30 }, | ||
871 | { .rfmax = 709000, .val = 0x31 }, | ||
872 | { .rfmax = 714000, .val = 0x32 }, | ||
873 | { .rfmax = 724000, .val = 0x33 }, | ||
874 | { .rfmax = 729000, .val = 0x36 }, | ||
875 | { .rfmax = 739000, .val = 0x38 }, | ||
876 | { .rfmax = 744000, .val = 0x39 }, | ||
877 | { .rfmax = 749000, .val = 0x3b }, | ||
878 | { .rfmax = 754000, .val = 0x3c }, | ||
879 | { .rfmax = 759000, .val = 0x3d }, | ||
880 | { .rfmax = 764000, .val = 0x3e }, | ||
881 | { .rfmax = 769000, .val = 0x3f }, | ||
882 | { .rfmax = 774000, .val = 0x40 }, | ||
883 | { .rfmax = 779000, .val = 0x41 }, | ||
884 | { .rfmax = 784000, .val = 0x43 }, | ||
885 | { .rfmax = 789000, .val = 0x46 }, | ||
886 | { .rfmax = 794000, .val = 0x48 }, | ||
887 | { .rfmax = 799000, .val = 0x4b }, | ||
888 | { .rfmax = 804000, .val = 0x4f }, | ||
889 | { .rfmax = 809000, .val = 0x54 }, | ||
890 | { .rfmax = 814000, .val = 0x59 }, | ||
891 | { .rfmax = 819000, .val = 0x5d }, | ||
892 | { .rfmax = 824000, .val = 0x61 }, | ||
893 | { .rfmax = 829000, .val = 0x68 }, | ||
894 | { .rfmax = 834000, .val = 0x6e }, | ||
895 | { .rfmax = 839000, .val = 0x75 }, | ||
896 | { .rfmax = 844000, .val = 0x7e }, | ||
897 | { .rfmax = 849000, .val = 0x82 }, | ||
898 | { .rfmax = 854000, .val = 0x84 }, | ||
899 | { .rfmax = 859000, .val = 0x8f }, | ||
900 | { .rfmax = 865000, .val = 0x9a }, | ||
901 | { .rfmax = 0, .val = 0x00 }, /* end */ | ||
902 | }; | ||
903 | |||
904 | /*---------------------------------------------------------------------*/ | ||
905 | |||
906 | struct tda18271_thermo_map { | ||
907 | u8 d; | ||
908 | u8 r0; | ||
909 | u8 r1; | ||
910 | }; | ||
911 | |||
912 | static struct tda18271_thermo_map tda18271_thermometer[] = { | ||
913 | { .d = 0x00, .r0 = 60, .r1 = 92 }, | ||
914 | { .d = 0x01, .r0 = 62, .r1 = 94 }, | ||
915 | { .d = 0x02, .r0 = 66, .r1 = 98 }, | ||
916 | { .d = 0x03, .r0 = 64, .r1 = 96 }, | ||
917 | { .d = 0x04, .r0 = 74, .r1 = 106 }, | ||
918 | { .d = 0x05, .r0 = 72, .r1 = 104 }, | ||
919 | { .d = 0x06, .r0 = 68, .r1 = 100 }, | ||
920 | { .d = 0x07, .r0 = 70, .r1 = 102 }, | ||
921 | { .d = 0x08, .r0 = 90, .r1 = 122 }, | ||
922 | { .d = 0x09, .r0 = 88, .r1 = 120 }, | ||
923 | { .d = 0x0a, .r0 = 84, .r1 = 116 }, | ||
924 | { .d = 0x0b, .r0 = 86, .r1 = 118 }, | ||
925 | { .d = 0x0c, .r0 = 76, .r1 = 108 }, | ||
926 | { .d = 0x0d, .r0 = 78, .r1 = 110 }, | ||
927 | { .d = 0x0e, .r0 = 82, .r1 = 114 }, | ||
928 | { .d = 0x0f, .r0 = 80, .r1 = 112 }, | ||
929 | { .d = 0x00, .r0 = 0, .r1 = 0 }, /* end */ | ||
930 | }; | ||
931 | |||
932 | int tda18271_lookup_thermometer(struct dvb_frontend *fe) | ||
933 | { | ||
934 | struct tda18271_priv *priv = fe->tuner_priv; | ||
935 | unsigned char *regs = priv->tda18271_regs; | ||
936 | int val, i = 0; | ||
937 | |||
938 | while (tda18271_thermometer[i].d < (regs[R_TM] & 0x0f)) { | ||
939 | if (tda18271_thermometer[i + 1].d == 0) | ||
940 | break; | ||
941 | i++; | ||
942 | } | ||
943 | |||
944 | if ((regs[R_TM] & 0x20) == 0x20) | ||
945 | val = tda18271_thermometer[i].r1; | ||
946 | else | ||
947 | val = tda18271_thermometer[i].r0; | ||
948 | |||
949 | tda_map("(%d) tm = %d\n", i, val); | ||
950 | |||
951 | return val; | ||
952 | } | ||
953 | |||
954 | /*---------------------------------------------------------------------*/ | ||
955 | |||
956 | struct tda18271_cid_target_map { | ||
957 | u32 rfmax; | ||
958 | u8 target; | ||
959 | u16 limit; | ||
960 | }; | ||
961 | |||
962 | static struct tda18271_cid_target_map tda18271_cid_target[] = { | ||
963 | { .rfmax = 46000, .target = 0x04, .limit = 1800 }, | ||
964 | { .rfmax = 52200, .target = 0x0a, .limit = 1500 }, | ||
965 | { .rfmax = 79100, .target = 0x01, .limit = 4000 }, | ||
966 | { .rfmax = 136800, .target = 0x18, .limit = 4000 }, | ||
967 | { .rfmax = 156700, .target = 0x18, .limit = 4000 }, | ||
968 | { .rfmax = 156700, .target = 0x18, .limit = 4000 }, | ||
969 | { .rfmax = 186250, .target = 0x0a, .limit = 4000 }, | ||
970 | { .rfmax = 230000, .target = 0x0a, .limit = 4000 }, | ||
971 | { .rfmax = 345000, .target = 0x18, .limit = 4000 }, | ||
972 | { .rfmax = 426000, .target = 0x0e, .limit = 4000 }, | ||
973 | { .rfmax = 489500, .target = 0x1e, .limit = 4000 }, | ||
974 | { .rfmax = 697500, .target = 0x32, .limit = 4000 }, | ||
975 | { .rfmax = 842000, .target = 0x3a, .limit = 4000 }, | ||
976 | { .rfmax = 0, .target = 0x00, .limit = 0 }, /* end */ | ||
977 | }; | ||
978 | |||
979 | int tda18271_lookup_cid_target(struct dvb_frontend *fe, | ||
980 | u32 *freq, u8 *cid_target, u16 *count_limit) | ||
981 | { | ||
982 | int i = 0; | ||
983 | |||
984 | while ((tda18271_cid_target[i].rfmax * 1000) < *freq) { | ||
985 | if (tda18271_cid_target[i + 1].rfmax == 0) | ||
986 | break; | ||
987 | i++; | ||
988 | } | ||
989 | *cid_target = tda18271_cid_target[i].target; | ||
990 | *count_limit = tda18271_cid_target[i].limit; | ||
991 | |||
992 | tda_map("(%d) cid_target = %02x, count_limit = %d\n", i, | ||
993 | tda18271_cid_target[i].target, tda18271_cid_target[i].limit); | ||
994 | |||
995 | return 0; | ||
996 | } | ||
997 | |||
998 | /*---------------------------------------------------------------------*/ | ||
999 | |||
1000 | static struct tda18271_rf_tracking_filter_cal tda18271_rf_band_template[] = { | ||
1001 | { .rfmax = 47900, .rfband = 0x00, | ||
1002 | .rf1_def = 46000, .rf2_def = 0, .rf3_def = 0 }, | ||
1003 | { .rfmax = 61100, .rfband = 0x01, | ||
1004 | .rf1_def = 52200, .rf2_def = 0, .rf3_def = 0 }, | ||
1005 | { .rfmax = 152600, .rfband = 0x02, | ||
1006 | .rf1_def = 70100, .rf2_def = 136800, .rf3_def = 0 }, | ||
1007 | { .rfmax = 164700, .rfband = 0x03, | ||
1008 | .rf1_def = 156700, .rf2_def = 0, .rf3_def = 0 }, | ||
1009 | { .rfmax = 203500, .rfband = 0x04, | ||
1010 | .rf1_def = 186250, .rf2_def = 0, .rf3_def = 0 }, | ||
1011 | { .rfmax = 457800, .rfband = 0x05, | ||
1012 | .rf1_def = 230000, .rf2_def = 345000, .rf3_def = 426000 }, | ||
1013 | { .rfmax = 865000, .rfband = 0x06, | ||
1014 | .rf1_def = 489500, .rf2_def = 697500, .rf3_def = 842000 }, | ||
1015 | { .rfmax = 0, .rfband = 0x00, | ||
1016 | .rf1_def = 0, .rf2_def = 0, .rf3_def = 0 }, /* end */ | ||
1017 | }; | ||
1018 | |||
1019 | int tda18271_lookup_rf_band(struct dvb_frontend *fe, u32 *freq, u8 *rf_band) | ||
1020 | { | ||
1021 | struct tda18271_priv *priv = fe->tuner_priv; | ||
1022 | struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state; | ||
1023 | int i = 0; | ||
1024 | |||
1025 | while ((map[i].rfmax * 1000) < *freq) { | ||
1026 | if (tda18271_debug & DBG_ADV) | ||
1027 | tda_map("(%d) rfmax = %d < freq = %d, " | ||
1028 | "rf1_def = %d, rf2_def = %d, rf3_def = %d, " | ||
1029 | "rf1 = %d, rf2 = %d, rf3 = %d, " | ||
1030 | "rf_a1 = %d, rf_a2 = %d, " | ||
1031 | "rf_b1 = %d, rf_b2 = %d\n", | ||
1032 | i, map[i].rfmax * 1000, *freq, | ||
1033 | map[i].rf1_def, map[i].rf2_def, map[i].rf3_def, | ||
1034 | map[i].rf1, map[i].rf2, map[i].rf3, | ||
1035 | map[i].rf_a1, map[i].rf_a2, | ||
1036 | map[i].rf_b1, map[i].rf_b2); | ||
1037 | if (map[i].rfmax == 0) | ||
1038 | return -EINVAL; | ||
1039 | i++; | ||
1040 | } | ||
1041 | if (rf_band) | ||
1042 | *rf_band = map[i].rfband; | ||
1043 | |||
1044 | tda_map("(%d) rf_band = %02x\n", i, map[i].rfband); | ||
1045 | |||
1046 | return i; | ||
1047 | } | ||
1048 | |||
1049 | /*---------------------------------------------------------------------*/ | ||
1050 | |||
1051 | struct tda18271_map_layout { | ||
1052 | struct tda18271_pll_map *main_pll; | ||
1053 | struct tda18271_pll_map *cal_pll; | ||
1054 | |||
1055 | struct tda18271_map *rf_cal; | ||
1056 | struct tda18271_map *rf_cal_kmco; | ||
1057 | struct tda18271_map *rf_cal_dc_over_dt; | ||
1058 | |||
1059 | struct tda18271_map *bp_filter; | ||
1060 | struct tda18271_map *rf_band; | ||
1061 | struct tda18271_map *gain_taper; | ||
1062 | struct tda18271_map *ir_measure; | ||
1063 | }; | ||
1064 | |||
1065 | /*---------------------------------------------------------------------*/ | ||
1066 | |||
1067 | int tda18271_lookup_pll_map(struct dvb_frontend *fe, | ||
1068 | enum tda18271_map_type map_type, | ||
1069 | u32 *freq, u8 *post_div, u8 *div) | ||
1070 | { | ||
1071 | struct tda18271_priv *priv = fe->tuner_priv; | ||
1072 | struct tda18271_pll_map *map = NULL; | ||
1073 | unsigned int i = 0; | ||
1074 | char *map_name; | ||
1075 | int ret = 0; | ||
1076 | |||
1077 | BUG_ON(!priv->maps); | ||
1078 | |||
1079 | switch (map_type) { | ||
1080 | case MAIN_PLL: | ||
1081 | map = priv->maps->main_pll; | ||
1082 | map_name = "main_pll"; | ||
1083 | break; | ||
1084 | case CAL_PLL: | ||
1085 | map = priv->maps->cal_pll; | ||
1086 | map_name = "cal_pll"; | ||
1087 | break; | ||
1088 | default: | ||
1089 | /* we should never get here */ | ||
1090 | map_name = "undefined"; | ||
1091 | break; | ||
1092 | } | ||
1093 | |||
1094 | if (!map) { | ||
1095 | tda_warn("%s map is not set!\n", map_name); | ||
1096 | ret = -EINVAL; | ||
1097 | goto fail; | ||
1098 | } | ||
1099 | |||
1100 | while ((map[i].lomax * 1000) < *freq) { | ||
1101 | if (map[i + 1].lomax == 0) { | ||
1102 | tda_map("%s: frequency (%d) out of range\n", | ||
1103 | map_name, *freq); | ||
1104 | ret = -ERANGE; | ||
1105 | break; | ||
1106 | } | ||
1107 | i++; | ||
1108 | } | ||
1109 | *post_div = map[i].pd; | ||
1110 | *div = map[i].d; | ||
1111 | |||
1112 | tda_map("(%d) %s: post div = 0x%02x, div = 0x%02x\n", | ||
1113 | i, map_name, *post_div, *div); | ||
1114 | fail: | ||
1115 | return ret; | ||
1116 | } | ||
1117 | |||
1118 | int tda18271_lookup_map(struct dvb_frontend *fe, | ||
1119 | enum tda18271_map_type map_type, | ||
1120 | u32 *freq, u8 *val) | ||
1121 | { | ||
1122 | struct tda18271_priv *priv = fe->tuner_priv; | ||
1123 | struct tda18271_map *map = NULL; | ||
1124 | unsigned int i = 0; | ||
1125 | char *map_name; | ||
1126 | int ret = 0; | ||
1127 | |||
1128 | BUG_ON(!priv->maps); | ||
1129 | |||
1130 | switch (map_type) { | ||
1131 | case BP_FILTER: | ||
1132 | map = priv->maps->bp_filter; | ||
1133 | map_name = "bp_filter"; | ||
1134 | break; | ||
1135 | case RF_CAL_KMCO: | ||
1136 | map = priv->maps->rf_cal_kmco; | ||
1137 | map_name = "km"; | ||
1138 | break; | ||
1139 | case RF_BAND: | ||
1140 | map = priv->maps->rf_band; | ||
1141 | map_name = "rf_band"; | ||
1142 | break; | ||
1143 | case GAIN_TAPER: | ||
1144 | map = priv->maps->gain_taper; | ||
1145 | map_name = "gain_taper"; | ||
1146 | break; | ||
1147 | case RF_CAL: | ||
1148 | map = priv->maps->rf_cal; | ||
1149 | map_name = "rf_cal"; | ||
1150 | break; | ||
1151 | case IR_MEASURE: | ||
1152 | map = priv->maps->ir_measure; | ||
1153 | map_name = "ir_measure"; | ||
1154 | break; | ||
1155 | case RF_CAL_DC_OVER_DT: | ||
1156 | map = priv->maps->rf_cal_dc_over_dt; | ||
1157 | map_name = "rf_cal_dc_over_dt"; | ||
1158 | break; | ||
1159 | default: | ||
1160 | /* we should never get here */ | ||
1161 | map_name = "undefined"; | ||
1162 | break; | ||
1163 | } | ||
1164 | |||
1165 | if (!map) { | ||
1166 | tda_warn("%s map is not set!\n", map_name); | ||
1167 | ret = -EINVAL; | ||
1168 | goto fail; | ||
1169 | } | ||
1170 | |||
1171 | while ((map[i].rfmax * 1000) < *freq) { | ||
1172 | if (map[i + 1].rfmax == 0) { | ||
1173 | tda_map("%s: frequency (%d) out of range\n", | ||
1174 | map_name, *freq); | ||
1175 | ret = -ERANGE; | ||
1176 | break; | ||
1177 | } | ||
1178 | i++; | ||
1179 | } | ||
1180 | *val = map[i].val; | ||
1181 | |||
1182 | tda_map("(%d) %s: 0x%02x\n", i, map_name, *val); | ||
1183 | fail: | ||
1184 | return ret; | ||
1185 | } | ||
1186 | |||
1187 | /*---------------------------------------------------------------------*/ | ||
1188 | |||
1189 | static struct tda18271_std_map tda18271c1_std_map = { | ||
1190 | .fm_radio = { .if_freq = 1250, .fm_rfn = 1, .agc_mode = 3, .std = 0, | ||
1191 | .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x18 */ | ||
1192 | .atv_b = { .if_freq = 6750, .fm_rfn = 0, .agc_mode = 1, .std = 6, | ||
1193 | .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */ | ||
1194 | .atv_dk = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7, | ||
1195 | .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */ | ||
1196 | .atv_gh = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7, | ||
1197 | .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */ | ||
1198 | .atv_i = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7, | ||
1199 | .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */ | ||
1200 | .atv_l = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7, | ||
1201 | .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */ | ||
1202 | .atv_lc = { .if_freq = 1250, .fm_rfn = 0, .agc_mode = 1, .std = 7, | ||
1203 | .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */ | ||
1204 | .atv_mn = { .if_freq = 5750, .fm_rfn = 0, .agc_mode = 1, .std = 5, | ||
1205 | .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0d */ | ||
1206 | .atsc_6 = { .if_freq = 3250, .fm_rfn = 0, .agc_mode = 3, .std = 4, | ||
1207 | .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */ | ||
1208 | .dvbt_6 = { .if_freq = 3300, .fm_rfn = 0, .agc_mode = 3, .std = 4, | ||
1209 | .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */ | ||
1210 | .dvbt_7 = { .if_freq = 3800, .fm_rfn = 0, .agc_mode = 3, .std = 5, | ||
1211 | .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */ | ||
1212 | .dvbt_8 = { .if_freq = 4300, .fm_rfn = 0, .agc_mode = 3, .std = 6, | ||
1213 | .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1e */ | ||
1214 | .qam_6 = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5, | ||
1215 | .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */ | ||
1216 | .qam_8 = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7, | ||
1217 | .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1f */ | ||
1218 | }; | ||
1219 | |||
1220 | static struct tda18271_std_map tda18271c2_std_map = { | ||
1221 | .fm_radio = { .if_freq = 1250, .fm_rfn = 1, .agc_mode = 3, .std = 0, | ||
1222 | .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x18 */ | ||
1223 | .atv_b = { .if_freq = 6000, .fm_rfn = 0, .agc_mode = 1, .std = 5, | ||
1224 | .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0d */ | ||
1225 | .atv_dk = { .if_freq = 6900, .fm_rfn = 0, .agc_mode = 1, .std = 6, | ||
1226 | .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */ | ||
1227 | .atv_gh = { .if_freq = 7100, .fm_rfn = 0, .agc_mode = 1, .std = 6, | ||
1228 | .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */ | ||
1229 | .atv_i = { .if_freq = 7250, .fm_rfn = 0, .agc_mode = 1, .std = 6, | ||
1230 | .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */ | ||
1231 | .atv_l = { .if_freq = 6900, .fm_rfn = 0, .agc_mode = 1, .std = 6, | ||
1232 | .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */ | ||
1233 | .atv_lc = { .if_freq = 1250, .fm_rfn = 0, .agc_mode = 1, .std = 6, | ||
1234 | .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */ | ||
1235 | .atv_mn = { .if_freq = 5400, .fm_rfn = 0, .agc_mode = 1, .std = 4, | ||
1236 | .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0c */ | ||
1237 | .atsc_6 = { .if_freq = 3250, .fm_rfn = 0, .agc_mode = 3, .std = 4, | ||
1238 | .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */ | ||
1239 | .dvbt_6 = { .if_freq = 3300, .fm_rfn = 0, .agc_mode = 3, .std = 4, | ||
1240 | .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */ | ||
1241 | .dvbt_7 = { .if_freq = 3500, .fm_rfn = 0, .agc_mode = 3, .std = 4, | ||
1242 | .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */ | ||
1243 | .dvbt_8 = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5, | ||
1244 | .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */ | ||
1245 | .qam_6 = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5, | ||
1246 | .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */ | ||
1247 | .qam_8 = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7, | ||
1248 | .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1f */ | ||
1249 | }; | ||
1250 | |||
1251 | /*---------------------------------------------------------------------*/ | ||
1252 | |||
1253 | static struct tda18271_map_layout tda18271c1_map_layout = { | ||
1254 | .main_pll = tda18271c1_main_pll, | ||
1255 | .cal_pll = tda18271c1_cal_pll, | ||
1256 | |||
1257 | .rf_cal = tda18271c1_rf_cal, | ||
1258 | .rf_cal_kmco = tda18271c1_km, | ||
1259 | |||
1260 | .bp_filter = tda18271_bp_filter, | ||
1261 | .rf_band = tda18271_rf_band, | ||
1262 | .gain_taper = tda18271_gain_taper, | ||
1263 | .ir_measure = tda18271_ir_measure, | ||
1264 | }; | ||
1265 | |||
1266 | static struct tda18271_map_layout tda18271c2_map_layout = { | ||
1267 | .main_pll = tda18271c2_main_pll, | ||
1268 | .cal_pll = tda18271c2_cal_pll, | ||
1269 | |||
1270 | .rf_cal = tda18271c2_rf_cal, | ||
1271 | .rf_cal_kmco = tda18271c2_km, | ||
1272 | |||
1273 | .rf_cal_dc_over_dt = tda18271_rf_cal_dc_over_dt, | ||
1274 | |||
1275 | .bp_filter = tda18271_bp_filter, | ||
1276 | .rf_band = tda18271_rf_band, | ||
1277 | .gain_taper = tda18271_gain_taper, | ||
1278 | .ir_measure = tda18271_ir_measure, | ||
1279 | }; | ||
1280 | |||
1281 | int tda18271_assign_map_layout(struct dvb_frontend *fe) | ||
1282 | { | ||
1283 | struct tda18271_priv *priv = fe->tuner_priv; | ||
1284 | int ret = 0; | ||
1285 | |||
1286 | switch (priv->id) { | ||
1287 | case TDA18271HDC1: | ||
1288 | priv->maps = &tda18271c1_map_layout; | ||
1289 | memcpy(&priv->std, &tda18271c1_std_map, | ||
1290 | sizeof(struct tda18271_std_map)); | ||
1291 | break; | ||
1292 | case TDA18271HDC2: | ||
1293 | priv->maps = &tda18271c2_map_layout; | ||
1294 | memcpy(&priv->std, &tda18271c2_std_map, | ||
1295 | sizeof(struct tda18271_std_map)); | ||
1296 | break; | ||
1297 | default: | ||
1298 | ret = -EINVAL; | ||
1299 | break; | ||
1300 | } | ||
1301 | memcpy(priv->rf_cal_state, &tda18271_rf_band_template, | ||
1302 | sizeof(tda18271_rf_band_template)); | ||
1303 | |||
1304 | return ret; | ||
1305 | } | ||
1306 | |||
1307 | /* | ||
1308 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
1309 | * --------------------------------------------------------------------------- | ||
1310 | * Local variables: | ||
1311 | * c-basic-offset: 8 | ||
1312 | * End: | ||
1313 | */ | ||
diff --git a/drivers/media/common/tuners/tda18271-priv.h b/drivers/media/common/tuners/tda18271-priv.h new file mode 100644 index 000000000000..2bc5eb368ea2 --- /dev/null +++ b/drivers/media/common/tuners/tda18271-priv.h | |||
@@ -0,0 +1,220 @@ | |||
1 | /* | ||
2 | tda18271-priv.h - private header for the NXP TDA18271 silicon tuner | ||
3 | |||
4 | Copyright (C) 2007, 2008 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 | #ifndef __TDA18271_PRIV_H__ | ||
22 | #define __TDA18271_PRIV_H__ | ||
23 | |||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/types.h> | ||
26 | #include <linux/mutex.h> | ||
27 | #include "tuner-i2c.h" | ||
28 | #include "tda18271.h" | ||
29 | |||
30 | #define R_ID 0x00 /* ID byte */ | ||
31 | #define R_TM 0x01 /* Thermo byte */ | ||
32 | #define R_PL 0x02 /* Power level byte */ | ||
33 | #define R_EP1 0x03 /* Easy Prog byte 1 */ | ||
34 | #define R_EP2 0x04 /* Easy Prog byte 2 */ | ||
35 | #define R_EP3 0x05 /* Easy Prog byte 3 */ | ||
36 | #define R_EP4 0x06 /* Easy Prog byte 4 */ | ||
37 | #define R_EP5 0x07 /* Easy Prog byte 5 */ | ||
38 | #define R_CPD 0x08 /* Cal Post-Divider byte */ | ||
39 | #define R_CD1 0x09 /* Cal Divider byte 1 */ | ||
40 | #define R_CD2 0x0a /* Cal Divider byte 2 */ | ||
41 | #define R_CD3 0x0b /* Cal Divider byte 3 */ | ||
42 | #define R_MPD 0x0c /* Main Post-Divider byte */ | ||
43 | #define R_MD1 0x0d /* Main Divider byte 1 */ | ||
44 | #define R_MD2 0x0e /* Main Divider byte 2 */ | ||
45 | #define R_MD3 0x0f /* Main Divider byte 3 */ | ||
46 | #define R_EB1 0x10 /* Extended byte 1 */ | ||
47 | #define R_EB2 0x11 /* Extended byte 2 */ | ||
48 | #define R_EB3 0x12 /* Extended byte 3 */ | ||
49 | #define R_EB4 0x13 /* Extended byte 4 */ | ||
50 | #define R_EB5 0x14 /* Extended byte 5 */ | ||
51 | #define R_EB6 0x15 /* Extended byte 6 */ | ||
52 | #define R_EB7 0x16 /* Extended byte 7 */ | ||
53 | #define R_EB8 0x17 /* Extended byte 8 */ | ||
54 | #define R_EB9 0x18 /* Extended byte 9 */ | ||
55 | #define R_EB10 0x19 /* Extended byte 10 */ | ||
56 | #define R_EB11 0x1a /* Extended byte 11 */ | ||
57 | #define R_EB12 0x1b /* Extended byte 12 */ | ||
58 | #define R_EB13 0x1c /* Extended byte 13 */ | ||
59 | #define R_EB14 0x1d /* Extended byte 14 */ | ||
60 | #define R_EB15 0x1e /* Extended byte 15 */ | ||
61 | #define R_EB16 0x1f /* Extended byte 16 */ | ||
62 | #define R_EB17 0x20 /* Extended byte 17 */ | ||
63 | #define R_EB18 0x21 /* Extended byte 18 */ | ||
64 | #define R_EB19 0x22 /* Extended byte 19 */ | ||
65 | #define R_EB20 0x23 /* Extended byte 20 */ | ||
66 | #define R_EB21 0x24 /* Extended byte 21 */ | ||
67 | #define R_EB22 0x25 /* Extended byte 22 */ | ||
68 | #define R_EB23 0x26 /* Extended byte 23 */ | ||
69 | |||
70 | #define TDA18271_NUM_REGS 39 | ||
71 | |||
72 | /*---------------------------------------------------------------------*/ | ||
73 | |||
74 | struct tda18271_rf_tracking_filter_cal { | ||
75 | u32 rfmax; | ||
76 | u8 rfband; | ||
77 | u32 rf1_def; | ||
78 | u32 rf2_def; | ||
79 | u32 rf3_def; | ||
80 | u32 rf1; | ||
81 | u32 rf2; | ||
82 | u32 rf3; | ||
83 | int rf_a1; | ||
84 | int rf_b1; | ||
85 | int rf_a2; | ||
86 | int rf_b2; | ||
87 | }; | ||
88 | |||
89 | enum tda18271_pll { | ||
90 | TDA18271_MAIN_PLL, | ||
91 | TDA18271_CAL_PLL, | ||
92 | }; | ||
93 | |||
94 | enum tda18271_mode { | ||
95 | TDA18271_ANALOG, | ||
96 | TDA18271_DIGITAL, | ||
97 | }; | ||
98 | |||
99 | struct tda18271_map_layout; | ||
100 | |||
101 | enum tda18271_ver { | ||
102 | TDA18271HDC1, | ||
103 | TDA18271HDC2, | ||
104 | }; | ||
105 | |||
106 | struct tda18271_priv { | ||
107 | unsigned char tda18271_regs[TDA18271_NUM_REGS]; | ||
108 | |||
109 | struct list_head hybrid_tuner_instance_list; | ||
110 | struct tuner_i2c_props i2c_props; | ||
111 | |||
112 | enum tda18271_mode mode; | ||
113 | enum tda18271_role role; | ||
114 | enum tda18271_i2c_gate gate; | ||
115 | enum tda18271_ver id; | ||
116 | |||
117 | unsigned int tm_rfcal; | ||
118 | unsigned int cal_initialized:1; | ||
119 | unsigned int small_i2c:1; | ||
120 | |||
121 | struct tda18271_map_layout *maps; | ||
122 | struct tda18271_std_map std; | ||
123 | struct tda18271_rf_tracking_filter_cal rf_cal_state[8]; | ||
124 | |||
125 | struct mutex lock; | ||
126 | |||
127 | u32 frequency; | ||
128 | u32 bandwidth; | ||
129 | }; | ||
130 | |||
131 | /*---------------------------------------------------------------------*/ | ||
132 | |||
133 | extern int tda18271_debug; | ||
134 | |||
135 | #define DBG_INFO 1 | ||
136 | #define DBG_MAP 2 | ||
137 | #define DBG_REG 4 | ||
138 | #define DBG_ADV 8 | ||
139 | #define DBG_CAL 16 | ||
140 | |||
141 | #define tda_printk(kern, fmt, arg...) \ | ||
142 | printk(kern "%s: " fmt, __func__, ##arg) | ||
143 | |||
144 | #define dprintk(kern, lvl, fmt, arg...) do {\ | ||
145 | if (tda18271_debug & lvl) \ | ||
146 | tda_printk(kern, fmt, ##arg); } while (0) | ||
147 | |||
148 | #define tda_info(fmt, arg...) printk(KERN_INFO fmt, ##arg) | ||
149 | #define tda_warn(fmt, arg...) tda_printk(KERN_WARNING, fmt, ##arg) | ||
150 | #define tda_err(fmt, arg...) tda_printk(KERN_ERR, fmt, ##arg) | ||
151 | #define tda_dbg(fmt, arg...) dprintk(KERN_DEBUG, DBG_INFO, fmt, ##arg) | ||
152 | #define tda_map(fmt, arg...) dprintk(KERN_DEBUG, DBG_MAP, fmt, ##arg) | ||
153 | #define tda_reg(fmt, arg...) dprintk(KERN_DEBUG, DBG_REG, fmt, ##arg) | ||
154 | #define tda_cal(fmt, arg...) dprintk(KERN_DEBUG, DBG_CAL, fmt, ##arg) | ||
155 | |||
156 | /*---------------------------------------------------------------------*/ | ||
157 | |||
158 | enum tda18271_map_type { | ||
159 | /* tda18271_pll_map */ | ||
160 | MAIN_PLL, | ||
161 | CAL_PLL, | ||
162 | /* tda18271_map */ | ||
163 | RF_CAL, | ||
164 | RF_CAL_KMCO, | ||
165 | RF_CAL_DC_OVER_DT, | ||
166 | BP_FILTER, | ||
167 | RF_BAND, | ||
168 | GAIN_TAPER, | ||
169 | IR_MEASURE, | ||
170 | }; | ||
171 | |||
172 | extern int tda18271_lookup_pll_map(struct dvb_frontend *fe, | ||
173 | enum tda18271_map_type map_type, | ||
174 | u32 *freq, u8 *post_div, u8 *div); | ||
175 | extern int tda18271_lookup_map(struct dvb_frontend *fe, | ||
176 | enum tda18271_map_type map_type, | ||
177 | u32 *freq, u8 *val); | ||
178 | |||
179 | extern int tda18271_lookup_thermometer(struct dvb_frontend *fe); | ||
180 | |||
181 | extern int tda18271_lookup_rf_band(struct dvb_frontend *fe, | ||
182 | u32 *freq, u8 *rf_band); | ||
183 | |||
184 | extern int tda18271_lookup_cid_target(struct dvb_frontend *fe, | ||
185 | u32 *freq, u8 *cid_target, | ||
186 | u16 *count_limit); | ||
187 | |||
188 | extern int tda18271_assign_map_layout(struct dvb_frontend *fe); | ||
189 | |||
190 | /*---------------------------------------------------------------------*/ | ||
191 | |||
192 | extern int tda18271_read_regs(struct dvb_frontend *fe); | ||
193 | extern int tda18271_read_extended(struct dvb_frontend *fe); | ||
194 | extern int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len); | ||
195 | extern int tda18271_init_regs(struct dvb_frontend *fe); | ||
196 | |||
197 | extern int tda18271_charge_pump_source(struct dvb_frontend *fe, | ||
198 | enum tda18271_pll pll, int force); | ||
199 | extern int tda18271_set_standby_mode(struct dvb_frontend *fe, | ||
200 | int sm, int sm_lt, int sm_xt); | ||
201 | |||
202 | extern int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq); | ||
203 | extern int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq); | ||
204 | |||
205 | extern int tda18271_calc_bp_filter(struct dvb_frontend *fe, u32 *freq); | ||
206 | extern int tda18271_calc_km(struct dvb_frontend *fe, u32 *freq); | ||
207 | extern int tda18271_calc_rf_band(struct dvb_frontend *fe, u32 *freq); | ||
208 | extern int tda18271_calc_gain_taper(struct dvb_frontend *fe, u32 *freq); | ||
209 | extern int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq); | ||
210 | extern int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq); | ||
211 | |||
212 | #endif /* __TDA18271_PRIV_H__ */ | ||
213 | |||
214 | /* | ||
215 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
216 | * --------------------------------------------------------------------------- | ||
217 | * Local variables: | ||
218 | * c-basic-offset: 8 | ||
219 | * End: | ||
220 | */ | ||
diff --git a/drivers/media/common/tuners/tda18271.h b/drivers/media/common/tuners/tda18271.h new file mode 100644 index 000000000000..0e7af8d05a38 --- /dev/null +++ b/drivers/media/common/tuners/tda18271.h | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | tda18271.h - header for the Philips / NXP TDA18271 silicon tuner | ||
3 | |||
4 | Copyright (C) 2007, 2008 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 | #ifndef __TDA18271_H__ | ||
22 | #define __TDA18271_H__ | ||
23 | |||
24 | #include <linux/i2c.h> | ||
25 | #include "dvb_frontend.h" | ||
26 | |||
27 | struct tda18271_std_map_item { | ||
28 | u16 if_freq; | ||
29 | |||
30 | /* EP3[4:3] */ | ||
31 | unsigned int agc_mode:2; | ||
32 | /* EP3[2:0] */ | ||
33 | unsigned int std:3; | ||
34 | /* EP4[7] */ | ||
35 | unsigned int fm_rfn:1; | ||
36 | /* EP4[4:2] */ | ||
37 | unsigned int if_lvl:3; | ||
38 | /* EB22[6:0] */ | ||
39 | unsigned int rfagc_top:7; | ||
40 | }; | ||
41 | |||
42 | struct tda18271_std_map { | ||
43 | struct tda18271_std_map_item fm_radio; | ||
44 | struct tda18271_std_map_item atv_b; | ||
45 | struct tda18271_std_map_item atv_dk; | ||
46 | struct tda18271_std_map_item atv_gh; | ||
47 | struct tda18271_std_map_item atv_i; | ||
48 | struct tda18271_std_map_item atv_l; | ||
49 | struct tda18271_std_map_item atv_lc; | ||
50 | struct tda18271_std_map_item atv_mn; | ||
51 | struct tda18271_std_map_item atsc_6; | ||
52 | struct tda18271_std_map_item dvbt_6; | ||
53 | struct tda18271_std_map_item dvbt_7; | ||
54 | struct tda18271_std_map_item dvbt_8; | ||
55 | struct tda18271_std_map_item qam_6; | ||
56 | struct tda18271_std_map_item qam_8; | ||
57 | }; | ||
58 | |||
59 | enum tda18271_role { | ||
60 | TDA18271_MASTER = 0, | ||
61 | TDA18271_SLAVE, | ||
62 | }; | ||
63 | |||
64 | enum tda18271_i2c_gate { | ||
65 | TDA18271_GATE_AUTO = 0, | ||
66 | TDA18271_GATE_ANALOG, | ||
67 | TDA18271_GATE_DIGITAL, | ||
68 | }; | ||
69 | |||
70 | struct tda18271_config { | ||
71 | /* override default if freq / std settings (optional) */ | ||
72 | struct tda18271_std_map *std_map; | ||
73 | |||
74 | /* master / slave tuner: master uses main pll, slave uses cal pll */ | ||
75 | enum tda18271_role role; | ||
76 | |||
77 | /* use i2c gate provided by analog or digital demod */ | ||
78 | enum tda18271_i2c_gate gate; | ||
79 | |||
80 | /* some i2c providers cant write all 39 registers at once */ | ||
81 | unsigned int small_i2c:1; | ||
82 | }; | ||
83 | |||
84 | #if defined(CONFIG_DVB_TDA18271) || (defined(CONFIG_DVB_TDA18271_MODULE) && defined(MODULE)) | ||
85 | extern struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, | ||
86 | struct i2c_adapter *i2c, | ||
87 | struct tda18271_config *cfg); | ||
88 | #else | ||
89 | static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, | ||
90 | u8 addr, | ||
91 | struct i2c_adapter *i2c, | ||
92 | struct tda18271_config *cfg) | ||
93 | { | ||
94 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
95 | return NULL; | ||
96 | } | ||
97 | #endif | ||
98 | |||
99 | #endif /* __TDA18271_H__ */ | ||
diff --git a/drivers/media/common/tuners/tda827x.c b/drivers/media/common/tuners/tda827x.c new file mode 100644 index 000000000000..d30d2c9094d9 --- /dev/null +++ b/drivers/media/common/tuners/tda827x.c | |||
@@ -0,0 +1,852 @@ | |||
1 | /* | ||
2 | * | ||
3 | * (c) 2005 Hartmut Hackmann | ||
4 | * (c) 2007 Michael Krufky | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <asm/types.h> | ||
23 | #include <linux/dvb/frontend.h> | ||
24 | #include <linux/videodev2.h> | ||
25 | |||
26 | #include "tda827x.h" | ||
27 | |||
28 | static int debug; | ||
29 | module_param(debug, int, 0644); | ||
30 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | ||
31 | |||
32 | #define dprintk(args...) \ | ||
33 | do { \ | ||
34 | if (debug) printk(KERN_DEBUG "tda827x: " args); \ | ||
35 | } while (0) | ||
36 | |||
37 | struct tda827x_priv { | ||
38 | int i2c_addr; | ||
39 | struct i2c_adapter *i2c_adap; | ||
40 | struct tda827x_config *cfg; | ||
41 | |||
42 | unsigned int sgIF; | ||
43 | unsigned char lpsel; | ||
44 | |||
45 | u32 frequency; | ||
46 | u32 bandwidth; | ||
47 | }; | ||
48 | |||
49 | static void tda827x_set_std(struct dvb_frontend *fe, | ||
50 | struct analog_parameters *params) | ||
51 | { | ||
52 | struct tda827x_priv *priv = fe->tuner_priv; | ||
53 | char *mode; | ||
54 | |||
55 | priv->lpsel = 0; | ||
56 | if (params->std & V4L2_STD_MN) { | ||
57 | priv->sgIF = 92; | ||
58 | priv->lpsel = 1; | ||
59 | mode = "MN"; | ||
60 | } else if (params->std & V4L2_STD_B) { | ||
61 | priv->sgIF = 108; | ||
62 | mode = "B"; | ||
63 | } else if (params->std & V4L2_STD_GH) { | ||
64 | priv->sgIF = 124; | ||
65 | mode = "GH"; | ||
66 | } else if (params->std & V4L2_STD_PAL_I) { | ||
67 | priv->sgIF = 124; | ||
68 | mode = "I"; | ||
69 | } else if (params->std & V4L2_STD_DK) { | ||
70 | priv->sgIF = 124; | ||
71 | mode = "DK"; | ||
72 | } else if (params->std & V4L2_STD_SECAM_L) { | ||
73 | priv->sgIF = 124; | ||
74 | mode = "L"; | ||
75 | } else if (params->std & V4L2_STD_SECAM_LC) { | ||
76 | priv->sgIF = 20; | ||
77 | mode = "LC"; | ||
78 | } else { | ||
79 | priv->sgIF = 124; | ||
80 | mode = "xx"; | ||
81 | } | ||
82 | |||
83 | if (params->mode == V4L2_TUNER_RADIO) | ||
84 | priv->sgIF = 88; /* if frequency is 5.5 MHz */ | ||
85 | |||
86 | dprintk("setting tda827x to system %s\n", mode); | ||
87 | } | ||
88 | |||
89 | |||
90 | /* ------------------------------------------------------------------ */ | ||
91 | |||
92 | struct tda827x_data { | ||
93 | u32 lomax; | ||
94 | u8 spd; | ||
95 | u8 bs; | ||
96 | u8 bp; | ||
97 | u8 cp; | ||
98 | u8 gc3; | ||
99 | u8 div1p5; | ||
100 | }; | ||
101 | |||
102 | static const struct tda827x_data tda827x_table[] = { | ||
103 | { .lomax = 62000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, | ||
104 | { .lomax = 66000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, | ||
105 | { .lomax = 76000000, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, | ||
106 | { .lomax = 84000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, | ||
107 | { .lomax = 93000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
108 | { .lomax = 98000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
109 | { .lomax = 109000000, .spd = 3, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
110 | { .lomax = 123000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1}, | ||
111 | { .lomax = 133000000, .spd = 2, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1}, | ||
112 | { .lomax = 151000000, .spd = 2, .bs = 1, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
113 | { .lomax = 154000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
114 | { .lomax = 181000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 0, .div1p5 = 0}, | ||
115 | { .lomax = 185000000, .spd = 2, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
116 | { .lomax = 217000000, .spd = 2, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
117 | { .lomax = 244000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1}, | ||
118 | { .lomax = 265000000, .spd = 1, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1}, | ||
119 | { .lomax = 302000000, .spd = 1, .bs = 1, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
120 | { .lomax = 324000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
121 | { .lomax = 370000000, .spd = 1, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
122 | { .lomax = 454000000, .spd = 1, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
123 | { .lomax = 493000000, .spd = 0, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1}, | ||
124 | { .lomax = 530000000, .spd = 0, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1}, | ||
125 | { .lomax = 554000000, .spd = 0, .bs = 1, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, | ||
126 | { .lomax = 604000000, .spd = 0, .bs = 1, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, | ||
127 | { .lomax = 696000000, .spd = 0, .bs = 2, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, | ||
128 | { .lomax = 740000000, .spd = 0, .bs = 2, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0}, | ||
129 | { .lomax = 820000000, .spd = 0, .bs = 3, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, | ||
130 | { .lomax = 865000000, .spd = 0, .bs = 3, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0}, | ||
131 | { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0} | ||
132 | }; | ||
133 | |||
134 | static int tda827xo_set_params(struct dvb_frontend *fe, | ||
135 | struct dvb_frontend_parameters *params) | ||
136 | { | ||
137 | struct tda827x_priv *priv = fe->tuner_priv; | ||
138 | u8 buf[14]; | ||
139 | |||
140 | struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, | ||
141 | .buf = buf, .len = sizeof(buf) }; | ||
142 | int i, tuner_freq, if_freq; | ||
143 | u32 N; | ||
144 | |||
145 | dprintk("%s:\n", __func__); | ||
146 | switch (params->u.ofdm.bandwidth) { | ||
147 | case BANDWIDTH_6_MHZ: | ||
148 | if_freq = 4000000; | ||
149 | break; | ||
150 | case BANDWIDTH_7_MHZ: | ||
151 | if_freq = 4500000; | ||
152 | break; | ||
153 | default: /* 8 MHz or Auto */ | ||
154 | if_freq = 5000000; | ||
155 | break; | ||
156 | } | ||
157 | tuner_freq = params->frequency + if_freq; | ||
158 | |||
159 | i = 0; | ||
160 | while (tda827x_table[i].lomax < tuner_freq) { | ||
161 | if (tda827x_table[i + 1].lomax == 0) | ||
162 | break; | ||
163 | i++; | ||
164 | } | ||
165 | |||
166 | N = ((tuner_freq + 125000) / 250000) << (tda827x_table[i].spd + 2); | ||
167 | buf[0] = 0; | ||
168 | buf[1] = (N>>8) | 0x40; | ||
169 | buf[2] = N & 0xff; | ||
170 | buf[3] = 0; | ||
171 | buf[4] = 0x52; | ||
172 | buf[5] = (tda827x_table[i].spd << 6) + (tda827x_table[i].div1p5 << 5) + | ||
173 | (tda827x_table[i].bs << 3) + | ||
174 | tda827x_table[i].bp; | ||
175 | buf[6] = (tda827x_table[i].gc3 << 4) + 0x8f; | ||
176 | buf[7] = 0xbf; | ||
177 | buf[8] = 0x2a; | ||
178 | buf[9] = 0x05; | ||
179 | buf[10] = 0xff; | ||
180 | buf[11] = 0x00; | ||
181 | buf[12] = 0x00; | ||
182 | buf[13] = 0x40; | ||
183 | |||
184 | msg.len = 14; | ||
185 | if (fe->ops.i2c_gate_ctrl) | ||
186 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
187 | if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) { | ||
188 | printk("%s: could not write to tuner at addr: 0x%02x\n", | ||
189 | __func__, priv->i2c_addr << 1); | ||
190 | return -EIO; | ||
191 | } | ||
192 | msleep(500); | ||
193 | /* correct CP value */ | ||
194 | buf[0] = 0x30; | ||
195 | buf[1] = 0x50 + tda827x_table[i].cp; | ||
196 | msg.len = 2; | ||
197 | |||
198 | if (fe->ops.i2c_gate_ctrl) | ||
199 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
200 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
201 | |||
202 | priv->frequency = tuner_freq - if_freq; // FIXME | ||
203 | priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0; | ||
204 | |||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static int tda827xo_sleep(struct dvb_frontend *fe) | ||
209 | { | ||
210 | struct tda827x_priv *priv = fe->tuner_priv; | ||
211 | static u8 buf[] = { 0x30, 0xd0 }; | ||
212 | struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, | ||
213 | .buf = buf, .len = sizeof(buf) }; | ||
214 | |||
215 | dprintk("%s:\n", __func__); | ||
216 | if (fe->ops.i2c_gate_ctrl) | ||
217 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
218 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
219 | |||
220 | if (priv->cfg && priv->cfg->sleep) | ||
221 | priv->cfg->sleep(fe); | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | /* ------------------------------------------------------------------ */ | ||
227 | |||
228 | static int tda827xo_set_analog_params(struct dvb_frontend *fe, | ||
229 | struct analog_parameters *params) | ||
230 | { | ||
231 | unsigned char tuner_reg[8]; | ||
232 | unsigned char reg2[2]; | ||
233 | u32 N; | ||
234 | int i; | ||
235 | struct tda827x_priv *priv = fe->tuner_priv; | ||
236 | struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0 }; | ||
237 | unsigned int freq = params->frequency; | ||
238 | |||
239 | tda827x_set_std(fe, params); | ||
240 | |||
241 | if (params->mode == V4L2_TUNER_RADIO) | ||
242 | freq = freq / 1000; | ||
243 | |||
244 | N = freq + priv->sgIF; | ||
245 | |||
246 | i = 0; | ||
247 | while (tda827x_table[i].lomax < N * 62500) { | ||
248 | if (tda827x_table[i + 1].lomax == 0) | ||
249 | break; | ||
250 | i++; | ||
251 | } | ||
252 | |||
253 | N = N << tda827x_table[i].spd; | ||
254 | |||
255 | tuner_reg[0] = 0; | ||
256 | tuner_reg[1] = (unsigned char)(N>>8); | ||
257 | tuner_reg[2] = (unsigned char) N; | ||
258 | tuner_reg[3] = 0x40; | ||
259 | tuner_reg[4] = 0x52 + (priv->lpsel << 5); | ||
260 | tuner_reg[5] = (tda827x_table[i].spd << 6) + | ||
261 | (tda827x_table[i].div1p5 << 5) + | ||
262 | (tda827x_table[i].bs << 3) + tda827x_table[i].bp; | ||
263 | tuner_reg[6] = 0x8f + (tda827x_table[i].gc3 << 4); | ||
264 | tuner_reg[7] = 0x8f; | ||
265 | |||
266 | msg.buf = tuner_reg; | ||
267 | msg.len = 8; | ||
268 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
269 | |||
270 | msg.buf = reg2; | ||
271 | msg.len = 2; | ||
272 | reg2[0] = 0x80; | ||
273 | reg2[1] = 0; | ||
274 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
275 | |||
276 | reg2[0] = 0x60; | ||
277 | reg2[1] = 0xbf; | ||
278 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
279 | |||
280 | reg2[0] = 0x30; | ||
281 | reg2[1] = tuner_reg[4] + 0x80; | ||
282 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
283 | |||
284 | msleep(1); | ||
285 | reg2[0] = 0x30; | ||
286 | reg2[1] = tuner_reg[4] + 4; | ||
287 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
288 | |||
289 | msleep(1); | ||
290 | reg2[0] = 0x30; | ||
291 | reg2[1] = tuner_reg[4]; | ||
292 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
293 | |||
294 | msleep(550); | ||
295 | reg2[0] = 0x30; | ||
296 | reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_table[i].cp; | ||
297 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
298 | |||
299 | reg2[0] = 0x60; | ||
300 | reg2[1] = 0x3f; | ||
301 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
302 | |||
303 | reg2[0] = 0x80; | ||
304 | reg2[1] = 0x08; /* Vsync en */ | ||
305 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
306 | |||
307 | priv->frequency = freq * 62500; | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static void tda827xo_agcf(struct dvb_frontend *fe) | ||
313 | { | ||
314 | struct tda827x_priv *priv = fe->tuner_priv; | ||
315 | unsigned char data[] = { 0x80, 0x0c }; | ||
316 | struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, | ||
317 | .buf = data, .len = 2}; | ||
318 | |||
319 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
320 | } | ||
321 | |||
322 | /* ------------------------------------------------------------------ */ | ||
323 | |||
324 | struct tda827xa_data { | ||
325 | u32 lomax; | ||
326 | u8 svco; | ||
327 | u8 spd; | ||
328 | u8 scr; | ||
329 | u8 sbs; | ||
330 | u8 gc3; | ||
331 | }; | ||
332 | |||
333 | static const struct tda827xa_data tda827xa_dvbt[] = { | ||
334 | { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1}, | ||
335 | { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, | ||
336 | { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, | ||
337 | { .lomax = 97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, | ||
338 | { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1}, | ||
339 | { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, | ||
340 | { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, | ||
341 | { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, | ||
342 | { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, | ||
343 | { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, | ||
344 | { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, | ||
345 | { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, | ||
346 | { .lomax = 290000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, | ||
347 | { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1}, | ||
348 | { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1}, | ||
349 | { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1}, | ||
350 | { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, | ||
351 | { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1}, | ||
352 | { .lomax = 550000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, | ||
353 | { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, | ||
354 | { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, | ||
355 | { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, | ||
356 | { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, | ||
357 | { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, | ||
358 | { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, | ||
359 | { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0}, | ||
360 | { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} | ||
361 | }; | ||
362 | |||
363 | static struct tda827xa_data tda827xa_analog[] = { | ||
364 | { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3}, | ||
365 | { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, | ||
366 | { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, | ||
367 | { .lomax = 97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, | ||
368 | { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1}, | ||
369 | { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, | ||
370 | { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, | ||
371 | { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, | ||
372 | { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, | ||
373 | { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, | ||
374 | { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 3}, | ||
375 | { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 3}, | ||
376 | { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, | ||
377 | { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3}, | ||
378 | { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3}, | ||
379 | { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, | ||
380 | { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1}, | ||
381 | { .lomax = 554000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, | ||
382 | { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, | ||
383 | { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, | ||
384 | { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, | ||
385 | { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, | ||
386 | { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, | ||
387 | { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, | ||
388 | { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0}, | ||
389 | { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} | ||
390 | }; | ||
391 | |||
392 | static int tda827xa_sleep(struct dvb_frontend *fe) | ||
393 | { | ||
394 | struct tda827x_priv *priv = fe->tuner_priv; | ||
395 | static u8 buf[] = { 0x30, 0x90 }; | ||
396 | struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, | ||
397 | .buf = buf, .len = sizeof(buf) }; | ||
398 | |||
399 | dprintk("%s:\n", __func__); | ||
400 | if (fe->ops.i2c_gate_ctrl) | ||
401 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
402 | |||
403 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
404 | |||
405 | if (fe->ops.i2c_gate_ctrl) | ||
406 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
407 | |||
408 | if (priv->cfg && priv->cfg->sleep) | ||
409 | priv->cfg->sleep(fe); | ||
410 | |||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | static void tda827xa_lna_gain(struct dvb_frontend *fe, int high, | ||
415 | struct analog_parameters *params) | ||
416 | { | ||
417 | struct tda827x_priv *priv = fe->tuner_priv; | ||
418 | unsigned char buf[] = {0x22, 0x01}; | ||
419 | int arg; | ||
420 | int gp_func; | ||
421 | struct i2c_msg msg = { .addr = priv->cfg->switch_addr, .flags = 0, | ||
422 | .buf = buf, .len = sizeof(buf) }; | ||
423 | |||
424 | if (NULL == priv->cfg) { | ||
425 | dprintk("tda827x_config not defined, cannot set LNA gain!\n"); | ||
426 | return; | ||
427 | } | ||
428 | if (priv->cfg->config) { | ||
429 | if (high) | ||
430 | dprintk("setting LNA to high gain\n"); | ||
431 | else | ||
432 | dprintk("setting LNA to low gain\n"); | ||
433 | } | ||
434 | switch (priv->cfg->config) { | ||
435 | case 0: /* no LNA */ | ||
436 | break; | ||
437 | case 1: /* switch is GPIO 0 of tda8290 */ | ||
438 | case 2: | ||
439 | if (params == NULL) { | ||
440 | gp_func = 0; | ||
441 | arg = 0; | ||
442 | } else { | ||
443 | /* turn Vsync on */ | ||
444 | gp_func = 1; | ||
445 | if (params->std & V4L2_STD_MN) | ||
446 | arg = 1; | ||
447 | else | ||
448 | arg = 0; | ||
449 | } | ||
450 | if (priv->cfg->tuner_callback) | ||
451 | priv->cfg->tuner_callback(priv->i2c_adap->algo_data, | ||
452 | gp_func, arg); | ||
453 | buf[1] = high ? 0 : 1; | ||
454 | if (priv->cfg->config == 2) | ||
455 | buf[1] = high ? 1 : 0; | ||
456 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
457 | break; | ||
458 | case 3: /* switch with GPIO of saa713x */ | ||
459 | if (priv->cfg->tuner_callback) | ||
460 | priv->cfg->tuner_callback(priv->i2c_adap->algo_data, 0, high); | ||
461 | break; | ||
462 | } | ||
463 | } | ||
464 | |||
465 | static int tda827xa_set_params(struct dvb_frontend *fe, | ||
466 | struct dvb_frontend_parameters *params) | ||
467 | { | ||
468 | struct tda827x_priv *priv = fe->tuner_priv; | ||
469 | u8 buf[11]; | ||
470 | |||
471 | struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, | ||
472 | .buf = buf, .len = sizeof(buf) }; | ||
473 | |||
474 | int i, tuner_freq, if_freq; | ||
475 | u32 N; | ||
476 | |||
477 | dprintk("%s:\n", __func__); | ||
478 | |||
479 | tda827xa_lna_gain(fe, 1, NULL); | ||
480 | msleep(20); | ||
481 | |||
482 | switch (params->u.ofdm.bandwidth) { | ||
483 | case BANDWIDTH_6_MHZ: | ||
484 | if_freq = 4000000; | ||
485 | break; | ||
486 | case BANDWIDTH_7_MHZ: | ||
487 | if_freq = 4500000; | ||
488 | break; | ||
489 | default: /* 8 MHz or Auto */ | ||
490 | if_freq = 5000000; | ||
491 | break; | ||
492 | } | ||
493 | tuner_freq = params->frequency + if_freq; | ||
494 | |||
495 | i = 0; | ||
496 | while (tda827xa_dvbt[i].lomax < tuner_freq) { | ||
497 | if(tda827xa_dvbt[i + 1].lomax == 0) | ||
498 | break; | ||
499 | i++; | ||
500 | } | ||
501 | |||
502 | N = ((tuner_freq + 31250) / 62500) << tda827xa_dvbt[i].spd; | ||
503 | buf[0] = 0; // subaddress | ||
504 | buf[1] = N >> 8; | ||
505 | buf[2] = N & 0xff; | ||
506 | buf[3] = 0; | ||
507 | buf[4] = 0x16; | ||
508 | buf[5] = (tda827xa_dvbt[i].spd << 5) + (tda827xa_dvbt[i].svco << 3) + | ||
509 | tda827xa_dvbt[i].sbs; | ||
510 | buf[6] = 0x4b + (tda827xa_dvbt[i].gc3 << 4); | ||
511 | buf[7] = 0x1c; | ||
512 | buf[8] = 0x06; | ||
513 | buf[9] = 0x24; | ||
514 | buf[10] = 0x00; | ||
515 | msg.len = 11; | ||
516 | if (fe->ops.i2c_gate_ctrl) | ||
517 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
518 | if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) { | ||
519 | printk("%s: could not write to tuner at addr: 0x%02x\n", | ||
520 | __func__, priv->i2c_addr << 1); | ||
521 | return -EIO; | ||
522 | } | ||
523 | buf[0] = 0x90; | ||
524 | buf[1] = 0xff; | ||
525 | buf[2] = 0x60; | ||
526 | buf[3] = 0x00; | ||
527 | buf[4] = 0x59; // lpsel, for 6MHz + 2 | ||
528 | msg.len = 5; | ||
529 | if (fe->ops.i2c_gate_ctrl) | ||
530 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
531 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
532 | |||
533 | buf[0] = 0xa0; | ||
534 | buf[1] = 0x40; | ||
535 | msg.len = 2; | ||
536 | if (fe->ops.i2c_gate_ctrl) | ||
537 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
538 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
539 | |||
540 | msleep(11); | ||
541 | msg.flags = I2C_M_RD; | ||
542 | if (fe->ops.i2c_gate_ctrl) | ||
543 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
544 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
545 | msg.flags = 0; | ||
546 | |||
547 | buf[1] >>= 4; | ||
548 | dprintk("tda8275a AGC2 gain is: %d\n", buf[1]); | ||
549 | if ((buf[1]) < 2) { | ||
550 | tda827xa_lna_gain(fe, 0, NULL); | ||
551 | buf[0] = 0x60; | ||
552 | buf[1] = 0x0c; | ||
553 | if (fe->ops.i2c_gate_ctrl) | ||
554 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
555 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
556 | } | ||
557 | |||
558 | buf[0] = 0xc0; | ||
559 | buf[1] = 0x99; // lpsel, for 6MHz + 2 | ||
560 | if (fe->ops.i2c_gate_ctrl) | ||
561 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
562 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
563 | |||
564 | buf[0] = 0x60; | ||
565 | buf[1] = 0x3c; | ||
566 | if (fe->ops.i2c_gate_ctrl) | ||
567 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
568 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
569 | |||
570 | /* correct CP value */ | ||
571 | buf[0] = 0x30; | ||
572 | buf[1] = 0x10 + tda827xa_dvbt[i].scr; | ||
573 | if (fe->ops.i2c_gate_ctrl) | ||
574 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
575 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
576 | |||
577 | msleep(163); | ||
578 | buf[0] = 0xc0; | ||
579 | buf[1] = 0x39; // lpsel, for 6MHz + 2 | ||
580 | if (fe->ops.i2c_gate_ctrl) | ||
581 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
582 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
583 | |||
584 | msleep(3); | ||
585 | /* freeze AGC1 */ | ||
586 | buf[0] = 0x50; | ||
587 | buf[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4); | ||
588 | if (fe->ops.i2c_gate_ctrl) | ||
589 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
590 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
591 | |||
592 | priv->frequency = tuner_freq - if_freq; // FIXME | ||
593 | priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0; | ||
594 | |||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | |||
599 | static int tda827xa_set_analog_params(struct dvb_frontend *fe, | ||
600 | struct analog_parameters *params) | ||
601 | { | ||
602 | unsigned char tuner_reg[11]; | ||
603 | u32 N; | ||
604 | int i; | ||
605 | struct tda827x_priv *priv = fe->tuner_priv; | ||
606 | struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, | ||
607 | .buf = tuner_reg, .len = sizeof(tuner_reg) }; | ||
608 | unsigned int freq = params->frequency; | ||
609 | |||
610 | tda827x_set_std(fe, params); | ||
611 | |||
612 | tda827xa_lna_gain(fe, 1, params); | ||
613 | msleep(10); | ||
614 | |||
615 | if (params->mode == V4L2_TUNER_RADIO) | ||
616 | freq = freq / 1000; | ||
617 | |||
618 | N = freq + priv->sgIF; | ||
619 | |||
620 | i = 0; | ||
621 | while (tda827xa_analog[i].lomax < N * 62500) { | ||
622 | if (tda827xa_analog[i + 1].lomax == 0) | ||
623 | break; | ||
624 | i++; | ||
625 | } | ||
626 | |||
627 | N = N << tda827xa_analog[i].spd; | ||
628 | |||
629 | tuner_reg[0] = 0; | ||
630 | tuner_reg[1] = (unsigned char)(N>>8); | ||
631 | tuner_reg[2] = (unsigned char) N; | ||
632 | tuner_reg[3] = 0; | ||
633 | tuner_reg[4] = 0x16; | ||
634 | tuner_reg[5] = (tda827xa_analog[i].spd << 5) + | ||
635 | (tda827xa_analog[i].svco << 3) + | ||
636 | tda827xa_analog[i].sbs; | ||
637 | tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4); | ||
638 | tuner_reg[7] = 0x1c; | ||
639 | tuner_reg[8] = 4; | ||
640 | tuner_reg[9] = 0x20; | ||
641 | tuner_reg[10] = 0x00; | ||
642 | msg.len = 11; | ||
643 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
644 | |||
645 | tuner_reg[0] = 0x90; | ||
646 | tuner_reg[1] = 0xff; | ||
647 | tuner_reg[2] = 0xe0; | ||
648 | tuner_reg[3] = 0; | ||
649 | tuner_reg[4] = 0x99 + (priv->lpsel << 1); | ||
650 | msg.len = 5; | ||
651 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
652 | |||
653 | tuner_reg[0] = 0xa0; | ||
654 | tuner_reg[1] = 0xc0; | ||
655 | msg.len = 2; | ||
656 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
657 | |||
658 | tuner_reg[0] = 0x30; | ||
659 | tuner_reg[1] = 0x10 + tda827xa_analog[i].scr; | ||
660 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
661 | |||
662 | msg.flags = I2C_M_RD; | ||
663 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
664 | msg.flags = 0; | ||
665 | tuner_reg[1] >>= 4; | ||
666 | dprintk("AGC2 gain is: %d\n", tuner_reg[1]); | ||
667 | if (tuner_reg[1] < 1) | ||
668 | tda827xa_lna_gain(fe, 0, params); | ||
669 | |||
670 | msleep(100); | ||
671 | tuner_reg[0] = 0x60; | ||
672 | tuner_reg[1] = 0x3c; | ||
673 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
674 | |||
675 | msleep(163); | ||
676 | tuner_reg[0] = 0x50; | ||
677 | tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4); | ||
678 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
679 | |||
680 | tuner_reg[0] = 0x80; | ||
681 | tuner_reg[1] = 0x28; | ||
682 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
683 | |||
684 | tuner_reg[0] = 0xb0; | ||
685 | tuner_reg[1] = 0x01; | ||
686 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
687 | |||
688 | tuner_reg[0] = 0xc0; | ||
689 | tuner_reg[1] = 0x19 + (priv->lpsel << 1); | ||
690 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
691 | |||
692 | priv->frequency = freq * 62500; | ||
693 | |||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | static void tda827xa_agcf(struct dvb_frontend *fe) | ||
698 | { | ||
699 | struct tda827x_priv *priv = fe->tuner_priv; | ||
700 | unsigned char data[] = {0x80, 0x2c}; | ||
701 | struct i2c_msg msg = {.addr = priv->i2c_addr, .flags = 0, | ||
702 | .buf = data, .len = 2}; | ||
703 | i2c_transfer(priv->i2c_adap, &msg, 1); | ||
704 | } | ||
705 | |||
706 | /* ------------------------------------------------------------------ */ | ||
707 | |||
708 | static int tda827x_release(struct dvb_frontend *fe) | ||
709 | { | ||
710 | kfree(fe->tuner_priv); | ||
711 | fe->tuner_priv = NULL; | ||
712 | return 0; | ||
713 | } | ||
714 | |||
715 | static int tda827x_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
716 | { | ||
717 | struct tda827x_priv *priv = fe->tuner_priv; | ||
718 | *frequency = priv->frequency; | ||
719 | return 0; | ||
720 | } | ||
721 | |||
722 | static int tda827x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) | ||
723 | { | ||
724 | struct tda827x_priv *priv = fe->tuner_priv; | ||
725 | *bandwidth = priv->bandwidth; | ||
726 | return 0; | ||
727 | } | ||
728 | |||
729 | static int tda827x_init(struct dvb_frontend *fe) | ||
730 | { | ||
731 | struct tda827x_priv *priv = fe->tuner_priv; | ||
732 | dprintk("%s:\n", __func__); | ||
733 | if (priv->cfg && priv->cfg->init) | ||
734 | priv->cfg->init(fe); | ||
735 | |||
736 | return 0; | ||
737 | } | ||
738 | |||
739 | static int tda827x_probe_version(struct dvb_frontend *fe); | ||
740 | |||
741 | static int tda827x_initial_init(struct dvb_frontend *fe) | ||
742 | { | ||
743 | int ret; | ||
744 | ret = tda827x_probe_version(fe); | ||
745 | if (ret) | ||
746 | return ret; | ||
747 | return fe->ops.tuner_ops.init(fe); | ||
748 | } | ||
749 | |||
750 | static int tda827x_initial_sleep(struct dvb_frontend *fe) | ||
751 | { | ||
752 | int ret; | ||
753 | ret = tda827x_probe_version(fe); | ||
754 | if (ret) | ||
755 | return ret; | ||
756 | return fe->ops.tuner_ops.sleep(fe); | ||
757 | } | ||
758 | |||
759 | static struct dvb_tuner_ops tda827xo_tuner_ops = { | ||
760 | .info = { | ||
761 | .name = "Philips TDA827X", | ||
762 | .frequency_min = 55000000, | ||
763 | .frequency_max = 860000000, | ||
764 | .frequency_step = 250000 | ||
765 | }, | ||
766 | .release = tda827x_release, | ||
767 | .init = tda827x_initial_init, | ||
768 | .sleep = tda827x_initial_sleep, | ||
769 | .set_params = tda827xo_set_params, | ||
770 | .set_analog_params = tda827xo_set_analog_params, | ||
771 | .get_frequency = tda827x_get_frequency, | ||
772 | .get_bandwidth = tda827x_get_bandwidth, | ||
773 | }; | ||
774 | |||
775 | static struct dvb_tuner_ops tda827xa_tuner_ops = { | ||
776 | .info = { | ||
777 | .name = "Philips TDA827XA", | ||
778 | .frequency_min = 44000000, | ||
779 | .frequency_max = 906000000, | ||
780 | .frequency_step = 62500 | ||
781 | }, | ||
782 | .release = tda827x_release, | ||
783 | .init = tda827x_init, | ||
784 | .sleep = tda827xa_sleep, | ||
785 | .set_params = tda827xa_set_params, | ||
786 | .set_analog_params = tda827xa_set_analog_params, | ||
787 | .get_frequency = tda827x_get_frequency, | ||
788 | .get_bandwidth = tda827x_get_bandwidth, | ||
789 | }; | ||
790 | |||
791 | static int tda827x_probe_version(struct dvb_frontend *fe) | ||
792 | { u8 data; | ||
793 | struct tda827x_priv *priv = fe->tuner_priv; | ||
794 | struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = I2C_M_RD, | ||
795 | .buf = &data, .len = 1 }; | ||
796 | if (fe->ops.i2c_gate_ctrl) | ||
797 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
798 | if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) { | ||
799 | printk("%s: could not read from tuner at addr: 0x%02x\n", | ||
800 | __func__, msg.addr << 1); | ||
801 | return -EIO; | ||
802 | } | ||
803 | if ((data & 0x3c) == 0) { | ||
804 | dprintk("tda827x tuner found\n"); | ||
805 | fe->ops.tuner_ops.init = tda827x_init; | ||
806 | fe->ops.tuner_ops.sleep = tda827xo_sleep; | ||
807 | if (priv->cfg) | ||
808 | priv->cfg->agcf = tda827xo_agcf; | ||
809 | } else { | ||
810 | dprintk("tda827xa tuner found\n"); | ||
811 | memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops)); | ||
812 | if (priv->cfg) | ||
813 | priv->cfg->agcf = tda827xa_agcf; | ||
814 | } | ||
815 | return 0; | ||
816 | } | ||
817 | |||
818 | struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr, | ||
819 | struct i2c_adapter *i2c, | ||
820 | struct tda827x_config *cfg) | ||
821 | { | ||
822 | struct tda827x_priv *priv = NULL; | ||
823 | |||
824 | dprintk("%s:\n", __func__); | ||
825 | priv = kzalloc(sizeof(struct tda827x_priv), GFP_KERNEL); | ||
826 | if (priv == NULL) | ||
827 | return NULL; | ||
828 | |||
829 | priv->i2c_addr = addr; | ||
830 | priv->i2c_adap = i2c; | ||
831 | priv->cfg = cfg; | ||
832 | memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops)); | ||
833 | fe->tuner_priv = priv; | ||
834 | |||
835 | dprintk("type set to %s\n", fe->ops.tuner_ops.info.name); | ||
836 | |||
837 | return fe; | ||
838 | } | ||
839 | EXPORT_SYMBOL_GPL(tda827x_attach); | ||
840 | |||
841 | MODULE_DESCRIPTION("DVB TDA827x driver"); | ||
842 | MODULE_AUTHOR("Hartmut Hackmann <hartmut.hackmann@t-online.de>"); | ||
843 | MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>"); | ||
844 | MODULE_LICENSE("GPL"); | ||
845 | |||
846 | /* | ||
847 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
848 | * --------------------------------------------------------------------------- | ||
849 | * Local variables: | ||
850 | * c-basic-offset: 8 | ||
851 | * End: | ||
852 | */ | ||
diff --git a/drivers/media/common/tuners/tda827x.h b/drivers/media/common/tuners/tda827x.h new file mode 100644 index 000000000000..b73c23570dab --- /dev/null +++ b/drivers/media/common/tuners/tda827x.h | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | DVB Driver for Philips tda827x / tda827xa Silicon tuners | ||
3 | |||
4 | (c) 2005 Hartmut Hackmann | ||
5 | (c) 2007 Michael Krufky | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | |||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | |||
22 | */ | ||
23 | |||
24 | #ifndef __DVB_TDA827X_H__ | ||
25 | #define __DVB_TDA827X_H__ | ||
26 | |||
27 | #include <linux/i2c.h> | ||
28 | #include "dvb_frontend.h" | ||
29 | |||
30 | struct tda827x_config | ||
31 | { | ||
32 | /* saa7134 - provided callbacks */ | ||
33 | int (*init) (struct dvb_frontend *fe); | ||
34 | int (*sleep) (struct dvb_frontend *fe); | ||
35 | |||
36 | /* interface to tda829x driver */ | ||
37 | unsigned int config; | ||
38 | int switch_addr; | ||
39 | int (*tuner_callback) (void *dev, int command, int arg); | ||
40 | |||
41 | void (*agcf)(struct dvb_frontend *fe); | ||
42 | }; | ||
43 | |||
44 | |||
45 | /** | ||
46 | * Attach a tda827x tuner to the supplied frontend structure. | ||
47 | * | ||
48 | * @param fe Frontend to attach to. | ||
49 | * @param addr i2c address of the tuner. | ||
50 | * @param i2c i2c adapter to use. | ||
51 | * @param cfg optional callback function pointers. | ||
52 | * @return FE pointer on success, NULL on failure. | ||
53 | */ | ||
54 | #if defined(CONFIG_DVB_TDA827X) || (defined(CONFIG_DVB_TDA827X_MODULE) && defined(MODULE)) | ||
55 | extern struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe, int addr, | ||
56 | struct i2c_adapter *i2c, | ||
57 | struct tda827x_config *cfg); | ||
58 | #else | ||
59 | static inline struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe, | ||
60 | int addr, | ||
61 | struct i2c_adapter *i2c, | ||
62 | struct tda827x_config *cfg) | ||
63 | { | ||
64 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
65 | return NULL; | ||
66 | } | ||
67 | #endif // CONFIG_DVB_TDA827X | ||
68 | |||
69 | #endif // __DVB_TDA827X_H__ | ||
diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c new file mode 100644 index 000000000000..0ebb5b525e57 --- /dev/null +++ b/drivers/media/common/tuners/tda8290.c | |||
@@ -0,0 +1,804 @@ | |||
1 | /* | ||
2 | |||
3 | i2c tv tuner chip device driver | ||
4 | controls the philips tda8290+75 tuner chip combo. | ||
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 | This "tda8290" module was split apart from the original "tuner" module. | ||
21 | */ | ||
22 | |||
23 | #include <linux/i2c.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/videodev.h> | ||
26 | #include "tuner-i2c.h" | ||
27 | #include "tda8290.h" | ||
28 | #include "tda827x.h" | ||
29 | #include "tda18271.h" | ||
30 | |||
31 | static int debug; | ||
32 | module_param(debug, int, 0644); | ||
33 | MODULE_PARM_DESC(debug, "enable verbose debug messages"); | ||
34 | |||
35 | /* ---------------------------------------------------------------------- */ | ||
36 | |||
37 | struct tda8290_priv { | ||
38 | struct tuner_i2c_props i2c_props; | ||
39 | |||
40 | unsigned char tda8290_easy_mode; | ||
41 | |||
42 | unsigned char tda827x_addr; | ||
43 | |||
44 | unsigned char ver; | ||
45 | #define TDA8290 1 | ||
46 | #define TDA8295 2 | ||
47 | #define TDA8275 4 | ||
48 | #define TDA8275A 8 | ||
49 | #define TDA18271 16 | ||
50 | |||
51 | struct tda827x_config cfg; | ||
52 | }; | ||
53 | |||
54 | /*---------------------------------------------------------------------*/ | ||
55 | |||
56 | static int tda8290_i2c_bridge(struct dvb_frontend *fe, int close) | ||
57 | { | ||
58 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
59 | |||
60 | unsigned char enable[2] = { 0x21, 0xC0 }; | ||
61 | unsigned char disable[2] = { 0x21, 0x00 }; | ||
62 | unsigned char *msg; | ||
63 | |||
64 | if (close) { | ||
65 | msg = enable; | ||
66 | tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); | ||
67 | /* let the bridge stabilize */ | ||
68 | msleep(20); | ||
69 | } else { | ||
70 | msg = disable; | ||
71 | tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); | ||
72 | } | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close) | ||
78 | { | ||
79 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
80 | |||
81 | unsigned char enable[2] = { 0x45, 0xc1 }; | ||
82 | unsigned char disable[2] = { 0x46, 0x00 }; | ||
83 | unsigned char buf[3] = { 0x45, 0x01, 0x00 }; | ||
84 | unsigned char *msg; | ||
85 | |||
86 | if (close) { | ||
87 | msg = enable; | ||
88 | tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); | ||
89 | /* let the bridge stabilize */ | ||
90 | msleep(20); | ||
91 | } else { | ||
92 | msg = disable; | ||
93 | tuner_i2c_xfer_send(&priv->i2c_props, msg, 1); | ||
94 | tuner_i2c_xfer_recv(&priv->i2c_props, &msg[1], 1); | ||
95 | |||
96 | buf[2] = msg[1]; | ||
97 | buf[2] &= ~0x04; | ||
98 | tuner_i2c_xfer_send(&priv->i2c_props, buf, 3); | ||
99 | msleep(5); | ||
100 | |||
101 | msg[1] |= 0x04; | ||
102 | tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); | ||
103 | } | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | /*---------------------------------------------------------------------*/ | ||
109 | |||
110 | static void set_audio(struct dvb_frontend *fe, | ||
111 | struct analog_parameters *params) | ||
112 | { | ||
113 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
114 | char* mode; | ||
115 | |||
116 | if (params->std & V4L2_STD_MN) { | ||
117 | priv->tda8290_easy_mode = 0x01; | ||
118 | mode = "MN"; | ||
119 | } else if (params->std & V4L2_STD_B) { | ||
120 | priv->tda8290_easy_mode = 0x02; | ||
121 | mode = "B"; | ||
122 | } else if (params->std & V4L2_STD_GH) { | ||
123 | priv->tda8290_easy_mode = 0x04; | ||
124 | mode = "GH"; | ||
125 | } else if (params->std & V4L2_STD_PAL_I) { | ||
126 | priv->tda8290_easy_mode = 0x08; | ||
127 | mode = "I"; | ||
128 | } else if (params->std & V4L2_STD_DK) { | ||
129 | priv->tda8290_easy_mode = 0x10; | ||
130 | mode = "DK"; | ||
131 | } else if (params->std & V4L2_STD_SECAM_L) { | ||
132 | priv->tda8290_easy_mode = 0x20; | ||
133 | mode = "L"; | ||
134 | } else if (params->std & V4L2_STD_SECAM_LC) { | ||
135 | priv->tda8290_easy_mode = 0x40; | ||
136 | mode = "LC"; | ||
137 | } else { | ||
138 | priv->tda8290_easy_mode = 0x10; | ||
139 | mode = "xx"; | ||
140 | } | ||
141 | |||
142 | tuner_dbg("setting tda829x to system %s\n", mode); | ||
143 | } | ||
144 | |||
145 | static void tda8290_set_params(struct dvb_frontend *fe, | ||
146 | struct analog_parameters *params) | ||
147 | { | ||
148 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
149 | |||
150 | unsigned char soft_reset[] = { 0x00, 0x00 }; | ||
151 | unsigned char easy_mode[] = { 0x01, priv->tda8290_easy_mode }; | ||
152 | unsigned char expert_mode[] = { 0x01, 0x80 }; | ||
153 | unsigned char agc_out_on[] = { 0x02, 0x00 }; | ||
154 | unsigned char gainset_off[] = { 0x28, 0x14 }; | ||
155 | unsigned char if_agc_spd[] = { 0x0f, 0x88 }; | ||
156 | unsigned char adc_head_6[] = { 0x05, 0x04 }; | ||
157 | unsigned char adc_head_9[] = { 0x05, 0x02 }; | ||
158 | unsigned char adc_head_12[] = { 0x05, 0x01 }; | ||
159 | unsigned char pll_bw_nom[] = { 0x0d, 0x47 }; | ||
160 | unsigned char pll_bw_low[] = { 0x0d, 0x27 }; | ||
161 | unsigned char gainset_2[] = { 0x28, 0x64 }; | ||
162 | unsigned char agc_rst_on[] = { 0x0e, 0x0b }; | ||
163 | unsigned char agc_rst_off[] = { 0x0e, 0x09 }; | ||
164 | unsigned char if_agc_set[] = { 0x0f, 0x81 }; | ||
165 | unsigned char addr_adc_sat = 0x1a; | ||
166 | unsigned char addr_agc_stat = 0x1d; | ||
167 | unsigned char addr_pll_stat = 0x1b; | ||
168 | unsigned char adc_sat, agc_stat, | ||
169 | pll_stat; | ||
170 | int i; | ||
171 | |||
172 | set_audio(fe, params); | ||
173 | |||
174 | if (priv->cfg.config) | ||
175 | tuner_dbg("tda827xa config is 0x%02x\n", priv->cfg.config); | ||
176 | tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2); | ||
177 | tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2); | ||
178 | tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2); | ||
179 | msleep(1); | ||
180 | |||
181 | expert_mode[1] = priv->tda8290_easy_mode + 0x80; | ||
182 | tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2); | ||
183 | tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2); | ||
184 | tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2); | ||
185 | if (priv->tda8290_easy_mode & 0x60) | ||
186 | tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2); | ||
187 | else | ||
188 | tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2); | ||
189 | tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2); | ||
190 | |||
191 | tda8290_i2c_bridge(fe, 1); | ||
192 | |||
193 | if (fe->ops.tuner_ops.set_analog_params) | ||
194 | fe->ops.tuner_ops.set_analog_params(fe, params); | ||
195 | |||
196 | for (i = 0; i < 3; i++) { | ||
197 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); | ||
198 | tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); | ||
199 | if (pll_stat & 0x80) { | ||
200 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1); | ||
201 | tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1); | ||
202 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); | ||
203 | tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); | ||
204 | tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat); | ||
205 | break; | ||
206 | } else { | ||
207 | tuner_dbg("tda8290 not locked, no signal?\n"); | ||
208 | msleep(100); | ||
209 | } | ||
210 | } | ||
211 | /* adjust headroom resp. gain */ | ||
212 | if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat < 20))) { | ||
213 | tuner_dbg("adjust gain, step 1. Agc: %d, ADC stat: %d, lock: %d\n", | ||
214 | agc_stat, adc_sat, pll_stat & 0x80); | ||
215 | tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2); | ||
216 | msleep(100); | ||
217 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); | ||
218 | tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); | ||
219 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); | ||
220 | tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); | ||
221 | if ((agc_stat > 115) || !(pll_stat & 0x80)) { | ||
222 | tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n", | ||
223 | agc_stat, pll_stat & 0x80); | ||
224 | if (priv->cfg.agcf) | ||
225 | priv->cfg.agcf(fe); | ||
226 | msleep(100); | ||
227 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); | ||
228 | tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); | ||
229 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); | ||
230 | tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); | ||
231 | if((agc_stat > 115) || !(pll_stat & 0x80)) { | ||
232 | tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat); | ||
233 | tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2); | ||
234 | tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_low, 2); | ||
235 | msleep(100); | ||
236 | } | ||
237 | } | ||
238 | } | ||
239 | |||
240 | /* l/ l' deadlock? */ | ||
241 | if(priv->tda8290_easy_mode & 0x60) { | ||
242 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1); | ||
243 | tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1); | ||
244 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); | ||
245 | tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); | ||
246 | if ((adc_sat > 20) || !(pll_stat & 0x80)) { | ||
247 | tuner_dbg("trying to resolve SECAM L deadlock\n"); | ||
248 | tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2); | ||
249 | msleep(40); | ||
250 | tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_off, 2); | ||
251 | } | ||
252 | } | ||
253 | |||
254 | tda8290_i2c_bridge(fe, 0); | ||
255 | tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2); | ||
256 | } | ||
257 | |||
258 | /*---------------------------------------------------------------------*/ | ||
259 | |||
260 | static void tda8295_power(struct dvb_frontend *fe, int enable) | ||
261 | { | ||
262 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
263 | unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */ | ||
264 | |||
265 | tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); | ||
266 | tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); | ||
267 | |||
268 | if (enable) | ||
269 | buf[1] = 0x01; | ||
270 | else | ||
271 | buf[1] = 0x03; | ||
272 | |||
273 | tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); | ||
274 | } | ||
275 | |||
276 | static void tda8295_set_easy_mode(struct dvb_frontend *fe, int enable) | ||
277 | { | ||
278 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
279 | unsigned char buf[] = { 0x01, 0x00 }; | ||
280 | |||
281 | tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); | ||
282 | tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); | ||
283 | |||
284 | if (enable) | ||
285 | buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */ | ||
286 | else | ||
287 | buf[1] = 0x00; /* reset active bit */ | ||
288 | |||
289 | tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); | ||
290 | } | ||
291 | |||
292 | static void tda8295_set_video_std(struct dvb_frontend *fe) | ||
293 | { | ||
294 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
295 | unsigned char buf[] = { 0x00, priv->tda8290_easy_mode }; | ||
296 | |||
297 | tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); | ||
298 | |||
299 | tda8295_set_easy_mode(fe, 1); | ||
300 | msleep(20); | ||
301 | tda8295_set_easy_mode(fe, 0); | ||
302 | } | ||
303 | |||
304 | /*---------------------------------------------------------------------*/ | ||
305 | |||
306 | static void tda8295_agc1_out(struct dvb_frontend *fe, int enable) | ||
307 | { | ||
308 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
309 | unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */ | ||
310 | |||
311 | tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); | ||
312 | tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); | ||
313 | |||
314 | if (enable) | ||
315 | buf[1] &= ~0x40; | ||
316 | else | ||
317 | buf[1] |= 0x40; | ||
318 | |||
319 | tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); | ||
320 | } | ||
321 | |||
322 | static void tda8295_agc2_out(struct dvb_frontend *fe, int enable) | ||
323 | { | ||
324 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
325 | unsigned char set_gpio_cf[] = { 0x44, 0x00 }; | ||
326 | unsigned char set_gpio_val[] = { 0x46, 0x00 }; | ||
327 | |||
328 | tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_cf[0], 1); | ||
329 | tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_cf[1], 1); | ||
330 | tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_val[0], 1); | ||
331 | tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_val[1], 1); | ||
332 | |||
333 | set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */ | ||
334 | |||
335 | if (enable) { | ||
336 | set_gpio_cf[1] |= 0x01; /* config GPIO_0 as Open Drain Out */ | ||
337 | set_gpio_val[1] &= 0xfe; /* set GPIO_0 pin low */ | ||
338 | } | ||
339 | tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_cf, 2); | ||
340 | tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2); | ||
341 | } | ||
342 | |||
343 | static int tda8295_has_signal(struct dvb_frontend *fe) | ||
344 | { | ||
345 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
346 | |||
347 | unsigned char hvpll_stat = 0x26; | ||
348 | unsigned char ret; | ||
349 | |||
350 | tuner_i2c_xfer_send(&priv->i2c_props, &hvpll_stat, 1); | ||
351 | tuner_i2c_xfer_recv(&priv->i2c_props, &ret, 1); | ||
352 | return (ret & 0x01) ? 65535 : 0; | ||
353 | } | ||
354 | |||
355 | /*---------------------------------------------------------------------*/ | ||
356 | |||
357 | static void tda8295_set_params(struct dvb_frontend *fe, | ||
358 | struct analog_parameters *params) | ||
359 | { | ||
360 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
361 | |||
362 | unsigned char blanking_mode[] = { 0x1d, 0x00 }; | ||
363 | |||
364 | set_audio(fe, params); | ||
365 | |||
366 | tuner_dbg("%s: freq = %d\n", __func__, params->frequency); | ||
367 | |||
368 | tda8295_power(fe, 1); | ||
369 | tda8295_agc1_out(fe, 1); | ||
370 | |||
371 | tuner_i2c_xfer_send(&priv->i2c_props, &blanking_mode[0], 1); | ||
372 | tuner_i2c_xfer_recv(&priv->i2c_props, &blanking_mode[1], 1); | ||
373 | |||
374 | tda8295_set_video_std(fe); | ||
375 | |||
376 | blanking_mode[1] = 0x03; | ||
377 | tuner_i2c_xfer_send(&priv->i2c_props, blanking_mode, 2); | ||
378 | msleep(20); | ||
379 | |||
380 | tda8295_i2c_bridge(fe, 1); | ||
381 | |||
382 | if (fe->ops.tuner_ops.set_analog_params) | ||
383 | fe->ops.tuner_ops.set_analog_params(fe, params); | ||
384 | |||
385 | if (priv->cfg.agcf) | ||
386 | priv->cfg.agcf(fe); | ||
387 | |||
388 | if (tda8295_has_signal(fe)) | ||
389 | tuner_dbg("tda8295 is locked\n"); | ||
390 | else | ||
391 | tuner_dbg("tda8295 not locked, no signal?\n"); | ||
392 | |||
393 | tda8295_i2c_bridge(fe, 0); | ||
394 | } | ||
395 | |||
396 | /*---------------------------------------------------------------------*/ | ||
397 | |||
398 | static int tda8290_has_signal(struct dvb_frontend *fe) | ||
399 | { | ||
400 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
401 | |||
402 | unsigned char i2c_get_afc[1] = { 0x1B }; | ||
403 | unsigned char afc = 0; | ||
404 | |||
405 | tuner_i2c_xfer_send(&priv->i2c_props, i2c_get_afc, ARRAY_SIZE(i2c_get_afc)); | ||
406 | tuner_i2c_xfer_recv(&priv->i2c_props, &afc, 1); | ||
407 | return (afc & 0x80)? 65535:0; | ||
408 | } | ||
409 | |||
410 | /*---------------------------------------------------------------------*/ | ||
411 | |||
412 | static void tda8290_standby(struct dvb_frontend *fe) | ||
413 | { | ||
414 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
415 | |||
416 | unsigned char cb1[] = { 0x30, 0xD0 }; | ||
417 | unsigned char tda8290_standby[] = { 0x00, 0x02 }; | ||
418 | unsigned char tda8290_agc_tri[] = { 0x02, 0x20 }; | ||
419 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2}; | ||
420 | |||
421 | tda8290_i2c_bridge(fe, 1); | ||
422 | if (priv->ver & TDA8275A) | ||
423 | cb1[1] = 0x90; | ||
424 | i2c_transfer(priv->i2c_props.adap, &msg, 1); | ||
425 | tda8290_i2c_bridge(fe, 0); | ||
426 | tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2); | ||
427 | tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2); | ||
428 | } | ||
429 | |||
430 | static void tda8295_standby(struct dvb_frontend *fe) | ||
431 | { | ||
432 | tda8295_agc1_out(fe, 0); /* Put AGC in tri-state */ | ||
433 | |||
434 | tda8295_power(fe, 0); | ||
435 | } | ||
436 | |||
437 | static void tda8290_init_if(struct dvb_frontend *fe) | ||
438 | { | ||
439 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
440 | |||
441 | unsigned char set_VS[] = { 0x30, 0x6F }; | ||
442 | unsigned char set_GP00_CF[] = { 0x20, 0x01 }; | ||
443 | unsigned char set_GP01_CF[] = { 0x20, 0x0B }; | ||
444 | |||
445 | if ((priv->cfg.config == 1) || (priv->cfg.config == 2)) | ||
446 | tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2); | ||
447 | else | ||
448 | tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2); | ||
449 | tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2); | ||
450 | } | ||
451 | |||
452 | static void tda8295_init_if(struct dvb_frontend *fe) | ||
453 | { | ||
454 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
455 | |||
456 | static unsigned char set_adc_ctl[] = { 0x33, 0x14 }; | ||
457 | static unsigned char set_adc_ctl2[] = { 0x34, 0x00 }; | ||
458 | static unsigned char set_pll_reg6[] = { 0x3e, 0x63 }; | ||
459 | static unsigned char set_pll_reg0[] = { 0x38, 0x23 }; | ||
460 | static unsigned char set_pll_reg7[] = { 0x3f, 0x01 }; | ||
461 | static unsigned char set_pll_reg10[] = { 0x42, 0x61 }; | ||
462 | static unsigned char set_gpio_reg0[] = { 0x44, 0x0b }; | ||
463 | |||
464 | tda8295_power(fe, 1); | ||
465 | |||
466 | tda8295_set_easy_mode(fe, 0); | ||
467 | tda8295_set_video_std(fe); | ||
468 | |||
469 | tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl, 2); | ||
470 | tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl2, 2); | ||
471 | tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg6, 2); | ||
472 | tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg0, 2); | ||
473 | tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg7, 2); | ||
474 | tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg10, 2); | ||
475 | tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_reg0, 2); | ||
476 | |||
477 | tda8295_agc1_out(fe, 0); | ||
478 | tda8295_agc2_out(fe, 0); | ||
479 | } | ||
480 | |||
481 | static void tda8290_init_tuner(struct dvb_frontend *fe) | ||
482 | { | ||
483 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
484 | unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf, | ||
485 | 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 }; | ||
486 | unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b, | ||
487 | 0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b }; | ||
488 | struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, | ||
489 | .buf=tda8275_init, .len = 14}; | ||
490 | if (priv->ver & TDA8275A) | ||
491 | msg.buf = tda8275a_init; | ||
492 | |||
493 | tda8290_i2c_bridge(fe, 1); | ||
494 | i2c_transfer(priv->i2c_props.adap, &msg, 1); | ||
495 | tda8290_i2c_bridge(fe, 0); | ||
496 | } | ||
497 | |||
498 | /*---------------------------------------------------------------------*/ | ||
499 | |||
500 | static void tda829x_release(struct dvb_frontend *fe) | ||
501 | { | ||
502 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
503 | |||
504 | /* only try to release the tuner if we've | ||
505 | * attached it from within this module */ | ||
506 | if (priv->ver & (TDA18271 | TDA8275 | TDA8275A)) | ||
507 | if (fe->ops.tuner_ops.release) | ||
508 | fe->ops.tuner_ops.release(fe); | ||
509 | |||
510 | kfree(fe->analog_demod_priv); | ||
511 | fe->analog_demod_priv = NULL; | ||
512 | } | ||
513 | |||
514 | static struct tda18271_config tda829x_tda18271_config = { | ||
515 | .gate = TDA18271_GATE_ANALOG, | ||
516 | }; | ||
517 | |||
518 | static int tda829x_find_tuner(struct dvb_frontend *fe) | ||
519 | { | ||
520 | struct tda8290_priv *priv = fe->analog_demod_priv; | ||
521 | struct analog_demod_ops *analog_ops = &fe->ops.analog_ops; | ||
522 | int i, ret, tuners_found; | ||
523 | u32 tuner_addrs; | ||
524 | u8 data; | ||
525 | struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 }; | ||
526 | |||
527 | if (NULL == analog_ops->i2c_gate_ctrl) | ||
528 | return -EINVAL; | ||
529 | |||
530 | analog_ops->i2c_gate_ctrl(fe, 1); | ||
531 | |||
532 | /* probe for tuner chip */ | ||
533 | tuners_found = 0; | ||
534 | tuner_addrs = 0; | ||
535 | for (i = 0x60; i <= 0x63; i++) { | ||
536 | msg.addr = i; | ||
537 | ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); | ||
538 | if (ret == 1) { | ||
539 | tuners_found++; | ||
540 | tuner_addrs = (tuner_addrs << 8) + i; | ||
541 | } | ||
542 | } | ||
543 | /* if there is more than one tuner, we expect the right one is | ||
544 | behind the bridge and we choose the highest address that doesn't | ||
545 | give a response now | ||
546 | */ | ||
547 | |||
548 | analog_ops->i2c_gate_ctrl(fe, 0); | ||
549 | |||
550 | if (tuners_found > 1) | ||
551 | for (i = 0; i < tuners_found; i++) { | ||
552 | msg.addr = tuner_addrs & 0xff; | ||
553 | ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); | ||
554 | if (ret == 1) | ||
555 | tuner_addrs = tuner_addrs >> 8; | ||
556 | else | ||
557 | break; | ||
558 | } | ||
559 | |||
560 | if (tuner_addrs == 0) { | ||
561 | tuner_addrs = 0x60; | ||
562 | tuner_info("could not clearly identify tuner address, " | ||
563 | "defaulting to %x\n", tuner_addrs); | ||
564 | } else { | ||
565 | tuner_addrs = tuner_addrs & 0xff; | ||
566 | tuner_info("setting tuner address to %x\n", tuner_addrs); | ||
567 | } | ||
568 | priv->tda827x_addr = tuner_addrs; | ||
569 | msg.addr = tuner_addrs; | ||
570 | |||
571 | analog_ops->i2c_gate_ctrl(fe, 1); | ||
572 | ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); | ||
573 | |||
574 | if (ret != 1) { | ||
575 | tuner_warn("tuner access failed!\n"); | ||
576 | return -EREMOTEIO; | ||
577 | } | ||
578 | |||
579 | if ((data == 0x83) || (data == 0x84)) { | ||
580 | priv->ver |= TDA18271; | ||
581 | tda18271_attach(fe, priv->tda827x_addr, | ||
582 | priv->i2c_props.adap, | ||
583 | &tda829x_tda18271_config); | ||
584 | } else { | ||
585 | if ((data & 0x3c) == 0) | ||
586 | priv->ver |= TDA8275; | ||
587 | else | ||
588 | priv->ver |= TDA8275A; | ||
589 | |||
590 | tda827x_attach(fe, priv->tda827x_addr, priv->i2c_props.adap, &priv->cfg); | ||
591 | priv->cfg.switch_addr = priv->i2c_props.addr; | ||
592 | } | ||
593 | if (fe->ops.tuner_ops.init) | ||
594 | fe->ops.tuner_ops.init(fe); | ||
595 | |||
596 | if (fe->ops.tuner_ops.sleep) | ||
597 | fe->ops.tuner_ops.sleep(fe); | ||
598 | |||
599 | analog_ops->i2c_gate_ctrl(fe, 0); | ||
600 | |||
601 | return 0; | ||
602 | } | ||
603 | |||
604 | static int tda8290_probe(struct tuner_i2c_props *i2c_props) | ||
605 | { | ||
606 | #define TDA8290_ID 0x89 | ||
607 | unsigned char tda8290_id[] = { 0x1f, 0x00 }; | ||
608 | |||
609 | /* detect tda8290 */ | ||
610 | tuner_i2c_xfer_send(i2c_props, &tda8290_id[0], 1); | ||
611 | tuner_i2c_xfer_recv(i2c_props, &tda8290_id[1], 1); | ||
612 | |||
613 | if (tda8290_id[1] == TDA8290_ID) { | ||
614 | if (debug) | ||
615 | printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n", | ||
616 | __func__, i2c_adapter_id(i2c_props->adap), | ||
617 | i2c_props->addr); | ||
618 | return 0; | ||
619 | } | ||
620 | |||
621 | return -ENODEV; | ||
622 | } | ||
623 | |||
624 | static int tda8295_probe(struct tuner_i2c_props *i2c_props) | ||
625 | { | ||
626 | #define TDA8295_ID 0x8a | ||
627 | unsigned char tda8295_id[] = { 0x2f, 0x00 }; | ||
628 | |||
629 | /* detect tda8295 */ | ||
630 | tuner_i2c_xfer_send(i2c_props, &tda8295_id[0], 1); | ||
631 | tuner_i2c_xfer_recv(i2c_props, &tda8295_id[1], 1); | ||
632 | |||
633 | if (tda8295_id[1] == TDA8295_ID) { | ||
634 | if (debug) | ||
635 | printk(KERN_DEBUG "%s: tda8295 detected @ %d-%04x\n", | ||
636 | __func__, i2c_adapter_id(i2c_props->adap), | ||
637 | i2c_props->addr); | ||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | return -ENODEV; | ||
642 | } | ||
643 | |||
644 | static struct analog_demod_ops tda8290_ops = { | ||
645 | .set_params = tda8290_set_params, | ||
646 | .has_signal = tda8290_has_signal, | ||
647 | .standby = tda8290_standby, | ||
648 | .release = tda829x_release, | ||
649 | .i2c_gate_ctrl = tda8290_i2c_bridge, | ||
650 | }; | ||
651 | |||
652 | static struct analog_demod_ops tda8295_ops = { | ||
653 | .set_params = tda8295_set_params, | ||
654 | .has_signal = tda8295_has_signal, | ||
655 | .standby = tda8295_standby, | ||
656 | .release = tda829x_release, | ||
657 | .i2c_gate_ctrl = tda8295_i2c_bridge, | ||
658 | }; | ||
659 | |||
660 | struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, | ||
661 | struct i2c_adapter *i2c_adap, u8 i2c_addr, | ||
662 | struct tda829x_config *cfg) | ||
663 | { | ||
664 | struct tda8290_priv *priv = NULL; | ||
665 | char *name; | ||
666 | |||
667 | priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); | ||
668 | if (priv == NULL) | ||
669 | return NULL; | ||
670 | fe->analog_demod_priv = priv; | ||
671 | |||
672 | priv->i2c_props.addr = i2c_addr; | ||
673 | priv->i2c_props.adap = i2c_adap; | ||
674 | priv->i2c_props.name = "tda829x"; | ||
675 | if (cfg) { | ||
676 | priv->cfg.config = cfg->lna_cfg; | ||
677 | priv->cfg.tuner_callback = cfg->tuner_callback; | ||
678 | } | ||
679 | |||
680 | if (tda8290_probe(&priv->i2c_props) == 0) { | ||
681 | priv->ver = TDA8290; | ||
682 | memcpy(&fe->ops.analog_ops, &tda8290_ops, | ||
683 | sizeof(struct analog_demod_ops)); | ||
684 | } | ||
685 | |||
686 | if (tda8295_probe(&priv->i2c_props) == 0) { | ||
687 | priv->ver = TDA8295; | ||
688 | memcpy(&fe->ops.analog_ops, &tda8295_ops, | ||
689 | sizeof(struct analog_demod_ops)); | ||
690 | } | ||
691 | |||
692 | if ((!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) && | ||
693 | (tda829x_find_tuner(fe) < 0)) | ||
694 | goto fail; | ||
695 | |||
696 | switch (priv->ver) { | ||
697 | case TDA8290: | ||
698 | name = "tda8290"; | ||
699 | break; | ||
700 | case TDA8295: | ||
701 | name = "tda8295"; | ||
702 | break; | ||
703 | case TDA8290 | TDA8275: | ||
704 | name = "tda8290+75"; | ||
705 | break; | ||
706 | case TDA8295 | TDA8275: | ||
707 | name = "tda8295+75"; | ||
708 | break; | ||
709 | case TDA8290 | TDA8275A: | ||
710 | name = "tda8290+75a"; | ||
711 | break; | ||
712 | case TDA8295 | TDA8275A: | ||
713 | name = "tda8295+75a"; | ||
714 | break; | ||
715 | case TDA8290 | TDA18271: | ||
716 | name = "tda8290+18271"; | ||
717 | break; | ||
718 | case TDA8295 | TDA18271: | ||
719 | name = "tda8295+18271"; | ||
720 | break; | ||
721 | default: | ||
722 | goto fail; | ||
723 | } | ||
724 | tuner_info("type set to %s\n", name); | ||
725 | |||
726 | fe->ops.analog_ops.info.name = name; | ||
727 | |||
728 | if (priv->ver & TDA8290) { | ||
729 | tda8290_init_tuner(fe); | ||
730 | tda8290_init_if(fe); | ||
731 | } else if (priv->ver & TDA8295) | ||
732 | tda8295_init_if(fe); | ||
733 | |||
734 | return fe; | ||
735 | |||
736 | fail: | ||
737 | tda829x_release(fe); | ||
738 | return NULL; | ||
739 | } | ||
740 | EXPORT_SYMBOL_GPL(tda829x_attach); | ||
741 | |||
742 | int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr) | ||
743 | { | ||
744 | struct tuner_i2c_props i2c_props = { | ||
745 | .adap = i2c_adap, | ||
746 | .addr = i2c_addr, | ||
747 | }; | ||
748 | |||
749 | unsigned char soft_reset[] = { 0x00, 0x00 }; | ||
750 | unsigned char easy_mode_b[] = { 0x01, 0x02 }; | ||
751 | unsigned char easy_mode_g[] = { 0x01, 0x04 }; | ||
752 | unsigned char restore_9886[] = { 0x00, 0xd6, 0x30 }; | ||
753 | unsigned char addr_dto_lsb = 0x07; | ||
754 | unsigned char data; | ||
755 | #define PROBE_BUFFER_SIZE 8 | ||
756 | unsigned char buf[PROBE_BUFFER_SIZE]; | ||
757 | int i; | ||
758 | |||
759 | /* rule out tda9887, which would return the same byte repeatedly */ | ||
760 | tuner_i2c_xfer_send(&i2c_props, soft_reset, 1); | ||
761 | tuner_i2c_xfer_recv(&i2c_props, buf, PROBE_BUFFER_SIZE); | ||
762 | for (i = 1; i < PROBE_BUFFER_SIZE; i++) { | ||
763 | if (buf[i] != buf[0]) | ||
764 | break; | ||
765 | } | ||
766 | |||
767 | /* all bytes are equal, not a tda829x - probably a tda9887 */ | ||
768 | if (i == PROBE_BUFFER_SIZE) | ||
769 | return -ENODEV; | ||
770 | |||
771 | if ((tda8290_probe(&i2c_props) == 0) || | ||
772 | (tda8295_probe(&i2c_props) == 0)) | ||
773 | return 0; | ||
774 | |||
775 | /* fall back to old probing method */ | ||
776 | tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2); | ||
777 | tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); | ||
778 | tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1); | ||
779 | tuner_i2c_xfer_recv(&i2c_props, &data, 1); | ||
780 | if (data == 0) { | ||
781 | tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2); | ||
782 | tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); | ||
783 | tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1); | ||
784 | tuner_i2c_xfer_recv(&i2c_props, &data, 1); | ||
785 | if (data == 0x7b) { | ||
786 | return 0; | ||
787 | } | ||
788 | } | ||
789 | tuner_i2c_xfer_send(&i2c_props, restore_9886, 3); | ||
790 | return -ENODEV; | ||
791 | } | ||
792 | EXPORT_SYMBOL_GPL(tda829x_probe); | ||
793 | |||
794 | MODULE_DESCRIPTION("Philips/NXP TDA8290/TDA8295 analog IF demodulator driver"); | ||
795 | MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky"); | ||
796 | MODULE_LICENSE("GPL"); | ||
797 | |||
798 | /* | ||
799 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
800 | * --------------------------------------------------------------------------- | ||
801 | * Local variables: | ||
802 | * c-basic-offset: 8 | ||
803 | * End: | ||
804 | */ | ||
diff --git a/drivers/media/common/tuners/tda8290.h b/drivers/media/common/tuners/tda8290.h new file mode 100644 index 000000000000..d3bbf276a469 --- /dev/null +++ b/drivers/media/common/tuners/tda8290.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | This program is free software; you can redistribute it and/or modify | ||
3 | it under the terms of the GNU General Public License as published by | ||
4 | the Free Software Foundation; either version 2 of the License, or | ||
5 | (at your option) any later version. | ||
6 | |||
7 | This program is distributed in the hope that it will be useful, | ||
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | GNU General Public License for more details. | ||
11 | |||
12 | You should have received a copy of the GNU General Public License | ||
13 | along with this program; if not, write to the Free Software | ||
14 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
15 | */ | ||
16 | |||
17 | #ifndef __TDA8290_H__ | ||
18 | #define __TDA8290_H__ | ||
19 | |||
20 | #include <linux/i2c.h> | ||
21 | #include "dvb_frontend.h" | ||
22 | |||
23 | struct tda829x_config { | ||
24 | unsigned int lna_cfg; | ||
25 | int (*tuner_callback) (void *dev, int command, int arg); | ||
26 | |||
27 | unsigned int probe_tuner:1; | ||
28 | #define TDA829X_PROBE_TUNER 0 | ||
29 | #define TDA829X_DONT_PROBE 1 | ||
30 | }; | ||
31 | |||
32 | #if defined(CONFIG_TUNER_TDA8290) || (defined(CONFIG_TUNER_TDA8290_MODULE) && defined(MODULE)) | ||
33 | extern int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr); | ||
34 | |||
35 | extern struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, | ||
36 | struct i2c_adapter *i2c_adap, | ||
37 | u8 i2c_addr, | ||
38 | struct tda829x_config *cfg); | ||
39 | #else | ||
40 | static inline int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr) | ||
41 | { | ||
42 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
43 | return -EINVAL; | ||
44 | } | ||
45 | |||
46 | static inline struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, | ||
47 | struct i2c_adapter *i2c_adap, | ||
48 | u8 i2c_addr, | ||
49 | struct tda829x_config *cfg) | ||
50 | { | ||
51 | printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", | ||
52 | __func__); | ||
53 | return NULL; | ||
54 | } | ||
55 | #endif | ||
56 | |||
57 | #endif /* __TDA8290_H__ */ | ||
diff --git a/drivers/media/common/tuners/tda9887.c b/drivers/media/common/tuners/tda9887.c new file mode 100644 index 000000000000..a0545ba957b0 --- /dev/null +++ b/drivers/media/common/tuners/tda9887.c | |||
@@ -0,0 +1,717 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/kernel.h> | ||
3 | #include <linux/i2c.h> | ||
4 | #include <linux/types.h> | ||
5 | #include <linux/init.h> | ||
6 | #include <linux/errno.h> | ||
7 | #include <linux/slab.h> | ||
8 | #include <linux/delay.h> | ||
9 | #include <linux/videodev.h> | ||
10 | #include <media/v4l2-common.h> | ||
11 | #include <media/tuner.h> | ||
12 | #include "tuner-i2c.h" | ||
13 | #include "tda9887.h" | ||
14 | |||
15 | |||
16 | /* Chips: | ||
17 | TDA9885 (PAL, NTSC) | ||
18 | TDA9886 (PAL, SECAM, NTSC) | ||
19 | TDA9887 (PAL, SECAM, NTSC, FM Radio) | ||
20 | |||
21 | Used as part of several tuners | ||
22 | */ | ||
23 | |||
24 | static int debug; | ||
25 | module_param(debug, int, 0644); | ||
26 | MODULE_PARM_DESC(debug, "enable verbose debug messages"); | ||
27 | |||
28 | static DEFINE_MUTEX(tda9887_list_mutex); | ||
29 | static LIST_HEAD(hybrid_tuner_instance_list); | ||
30 | |||
31 | struct tda9887_priv { | ||
32 | struct tuner_i2c_props i2c_props; | ||
33 | struct list_head hybrid_tuner_instance_list; | ||
34 | |||
35 | unsigned char data[4]; | ||
36 | unsigned int config; | ||
37 | unsigned int mode; | ||
38 | unsigned int audmode; | ||
39 | v4l2_std_id std; | ||
40 | }; | ||
41 | |||
42 | /* ---------------------------------------------------------------------- */ | ||
43 | |||
44 | #define UNSET (-1U) | ||
45 | |||
46 | struct tvnorm { | ||
47 | v4l2_std_id std; | ||
48 | char *name; | ||
49 | unsigned char b; | ||
50 | unsigned char c; | ||
51 | unsigned char e; | ||
52 | }; | ||
53 | |||
54 | /* ---------------------------------------------------------------------- */ | ||
55 | |||
56 | // | ||
57 | // TDA defines | ||
58 | // | ||
59 | |||
60 | //// first reg (b) | ||
61 | #define cVideoTrapBypassOFF 0x00 // bit b0 | ||
62 | #define cVideoTrapBypassON 0x01 // bit b0 | ||
63 | |||
64 | #define cAutoMuteFmInactive 0x00 // bit b1 | ||
65 | #define cAutoMuteFmActive 0x02 // bit b1 | ||
66 | |||
67 | #define cIntercarrier 0x00 // bit b2 | ||
68 | #define cQSS 0x04 // bit b2 | ||
69 | |||
70 | #define cPositiveAmTV 0x00 // bit b3:4 | ||
71 | #define cFmRadio 0x08 // bit b3:4 | ||
72 | #define cNegativeFmTV 0x10 // bit b3:4 | ||
73 | |||
74 | |||
75 | #define cForcedMuteAudioON 0x20 // bit b5 | ||
76 | #define cForcedMuteAudioOFF 0x00 // bit b5 | ||
77 | |||
78 | #define cOutputPort1Active 0x00 // bit b6 | ||
79 | #define cOutputPort1Inactive 0x40 // bit b6 | ||
80 | |||
81 | #define cOutputPort2Active 0x00 // bit b7 | ||
82 | #define cOutputPort2Inactive 0x80 // bit b7 | ||
83 | |||
84 | |||
85 | //// second reg (c) | ||
86 | #define cDeemphasisOFF 0x00 // bit c5 | ||
87 | #define cDeemphasisON 0x20 // bit c5 | ||
88 | |||
89 | #define cDeemphasis75 0x00 // bit c6 | ||
90 | #define cDeemphasis50 0x40 // bit c6 | ||
91 | |||
92 | #define cAudioGain0 0x00 // bit c7 | ||
93 | #define cAudioGain6 0x80 // bit c7 | ||
94 | |||
95 | #define cTopMask 0x1f // bit c0:4 | ||
96 | #define cTopDefault 0x10 // bit c0:4 | ||
97 | |||
98 | //// third reg (e) | ||
99 | #define cAudioIF_4_5 0x00 // bit e0:1 | ||
100 | #define cAudioIF_5_5 0x01 // bit e0:1 | ||
101 | #define cAudioIF_6_0 0x02 // bit e0:1 | ||
102 | #define cAudioIF_6_5 0x03 // bit e0:1 | ||
103 | |||
104 | |||
105 | #define cVideoIFMask 0x1c // bit e2:4 | ||
106 | /* Video IF selection in TV Mode (bit B3=0) */ | ||
107 | #define cVideoIF_58_75 0x00 // bit e2:4 | ||
108 | #define cVideoIF_45_75 0x04 // bit e2:4 | ||
109 | #define cVideoIF_38_90 0x08 // bit e2:4 | ||
110 | #define cVideoIF_38_00 0x0C // bit e2:4 | ||
111 | #define cVideoIF_33_90 0x10 // bit e2:4 | ||
112 | #define cVideoIF_33_40 0x14 // bit e2:4 | ||
113 | #define cRadioIF_45_75 0x18 // bit e2:4 | ||
114 | #define cRadioIF_38_90 0x1C // bit e2:4 | ||
115 | |||
116 | /* IF1 selection in Radio Mode (bit B3=1) */ | ||
117 | #define cRadioIF_33_30 0x00 // bit e2,4 (also 0x10,0x14) | ||
118 | #define cRadioIF_41_30 0x04 // bit e2,4 | ||
119 | |||
120 | /* Output of AFC pin in radio mode when bit E7=1 */ | ||
121 | #define cRadioAGC_SIF 0x00 // bit e3 | ||
122 | #define cRadioAGC_FM 0x08 // bit e3 | ||
123 | |||
124 | #define cTunerGainNormal 0x00 // bit e5 | ||
125 | #define cTunerGainLow 0x20 // bit e5 | ||
126 | |||
127 | #define cGating_18 0x00 // bit e6 | ||
128 | #define cGating_36 0x40 // bit e6 | ||
129 | |||
130 | #define cAgcOutON 0x80 // bit e7 | ||
131 | #define cAgcOutOFF 0x00 // bit e7 | ||
132 | |||
133 | /* ---------------------------------------------------------------------- */ | ||
134 | |||
135 | static struct tvnorm tvnorms[] = { | ||
136 | { | ||
137 | .std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N, | ||
138 | .name = "PAL-BGHN", | ||
139 | .b = ( cNegativeFmTV | | ||
140 | cQSS ), | ||
141 | .c = ( cDeemphasisON | | ||
142 | cDeemphasis50 | | ||
143 | cTopDefault), | ||
144 | .e = ( cGating_36 | | ||
145 | cAudioIF_5_5 | | ||
146 | cVideoIF_38_90 ), | ||
147 | },{ | ||
148 | .std = V4L2_STD_PAL_I, | ||
149 | .name = "PAL-I", | ||
150 | .b = ( cNegativeFmTV | | ||
151 | cQSS ), | ||
152 | .c = ( cDeemphasisON | | ||
153 | cDeemphasis50 | | ||
154 | cTopDefault), | ||
155 | .e = ( cGating_36 | | ||
156 | cAudioIF_6_0 | | ||
157 | cVideoIF_38_90 ), | ||
158 | },{ | ||
159 | .std = V4L2_STD_PAL_DK, | ||
160 | .name = "PAL-DK", | ||
161 | .b = ( cNegativeFmTV | | ||
162 | cQSS ), | ||
163 | .c = ( cDeemphasisON | | ||
164 | cDeemphasis50 | | ||
165 | cTopDefault), | ||
166 | .e = ( cGating_36 | | ||
167 | cAudioIF_6_5 | | ||
168 | cVideoIF_38_90 ), | ||
169 | },{ | ||
170 | .std = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc, | ||
171 | .name = "PAL-M/Nc", | ||
172 | .b = ( cNegativeFmTV | | ||
173 | cQSS ), | ||
174 | .c = ( cDeemphasisON | | ||
175 | cDeemphasis75 | | ||
176 | cTopDefault), | ||
177 | .e = ( cGating_36 | | ||
178 | cAudioIF_4_5 | | ||
179 | cVideoIF_45_75 ), | ||
180 | },{ | ||
181 | .std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H, | ||
182 | .name = "SECAM-BGH", | ||
183 | .b = ( cPositiveAmTV | | ||
184 | cQSS ), | ||
185 | .c = ( cTopDefault), | ||
186 | .e = ( cGating_36 | | ||
187 | cAudioIF_5_5 | | ||
188 | cVideoIF_38_90 ), | ||
189 | },{ | ||
190 | .std = V4L2_STD_SECAM_L, | ||
191 | .name = "SECAM-L", | ||
192 | .b = ( cPositiveAmTV | | ||
193 | cQSS ), | ||
194 | .c = ( cTopDefault), | ||
195 | .e = ( cGating_36 | | ||
196 | cAudioIF_6_5 | | ||
197 | cVideoIF_38_90 ), | ||
198 | },{ | ||
199 | .std = V4L2_STD_SECAM_LC, | ||
200 | .name = "SECAM-L'", | ||
201 | .b = ( cOutputPort2Inactive | | ||
202 | cPositiveAmTV | | ||
203 | cQSS ), | ||
204 | .c = ( cTopDefault), | ||
205 | .e = ( cGating_36 | | ||
206 | cAudioIF_6_5 | | ||
207 | cVideoIF_33_90 ), | ||
208 | },{ | ||
209 | .std = V4L2_STD_SECAM_DK, | ||
210 | .name = "SECAM-DK", | ||
211 | .b = ( cNegativeFmTV | | ||
212 | cQSS ), | ||
213 | .c = ( cDeemphasisON | | ||
214 | cDeemphasis50 | | ||
215 | cTopDefault), | ||
216 | .e = ( cGating_36 | | ||
217 | cAudioIF_6_5 | | ||
218 | cVideoIF_38_90 ), | ||
219 | },{ | ||
220 | .std = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR, | ||
221 | .name = "NTSC-M", | ||
222 | .b = ( cNegativeFmTV | | ||
223 | cQSS ), | ||
224 | .c = ( cDeemphasisON | | ||
225 | cDeemphasis75 | | ||
226 | cTopDefault), | ||
227 | .e = ( cGating_36 | | ||
228 | cAudioIF_4_5 | | ||
229 | cVideoIF_45_75 ), | ||
230 | },{ | ||
231 | .std = V4L2_STD_NTSC_M_JP, | ||
232 | .name = "NTSC-M-JP", | ||
233 | .b = ( cNegativeFmTV | | ||
234 | cQSS ), | ||
235 | .c = ( cDeemphasisON | | ||
236 | cDeemphasis50 | | ||
237 | cTopDefault), | ||
238 | .e = ( cGating_36 | | ||
239 | cAudioIF_4_5 | | ||
240 | cVideoIF_58_75 ), | ||
241 | } | ||
242 | }; | ||
243 | |||
244 | static struct tvnorm radio_stereo = { | ||
245 | .name = "Radio Stereo", | ||
246 | .b = ( cFmRadio | | ||
247 | cQSS ), | ||
248 | .c = ( cDeemphasisOFF | | ||
249 | cAudioGain6 | | ||
250 | cTopDefault), | ||
251 | .e = ( cTunerGainLow | | ||
252 | cAudioIF_5_5 | | ||
253 | cRadioIF_38_90 ), | ||
254 | }; | ||
255 | |||
256 | static struct tvnorm radio_mono = { | ||
257 | .name = "Radio Mono", | ||
258 | .b = ( cFmRadio | | ||
259 | cQSS ), | ||
260 | .c = ( cDeemphasisON | | ||
261 | cDeemphasis75 | | ||
262 | cTopDefault), | ||
263 | .e = ( cTunerGainLow | | ||
264 | cAudioIF_5_5 | | ||
265 | cRadioIF_38_90 ), | ||
266 | }; | ||
267 | |||
268 | /* ---------------------------------------------------------------------- */ | ||
269 | |||
270 | static void dump_read_message(struct dvb_frontend *fe, unsigned char *buf) | ||
271 | { | ||
272 | struct tda9887_priv *priv = fe->analog_demod_priv; | ||
273 | |||
274 | static char *afc[16] = { | ||
275 | "- 12.5 kHz", | ||
276 | "- 37.5 kHz", | ||
277 | "- 62.5 kHz", | ||
278 | "- 87.5 kHz", | ||
279 | "-112.5 kHz", | ||
280 | "-137.5 kHz", | ||
281 | "-162.5 kHz", | ||
282 | "-187.5 kHz [min]", | ||
283 | "+187.5 kHz [max]", | ||
284 | "+162.5 kHz", | ||
285 | "+137.5 kHz", | ||
286 | "+112.5 kHz", | ||
287 | "+ 87.5 kHz", | ||
288 | "+ 62.5 kHz", | ||
289 | "+ 37.5 kHz", | ||
290 | "+ 12.5 kHz", | ||
291 | }; | ||
292 | tuner_info("read: 0x%2x\n", buf[0]); | ||
293 | tuner_info(" after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no"); | ||
294 | tuner_info(" afc : %s\n", afc[(buf[0] >> 1) & 0x0f]); | ||
295 | tuner_info(" fmif level : %s\n", (buf[0] & 0x20) ? "high" : "low"); | ||
296 | tuner_info(" afc window : %s\n", (buf[0] & 0x40) ? "in" : "out"); | ||
297 | tuner_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low"); | ||
298 | } | ||
299 | |||
300 | static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf) | ||
301 | { | ||
302 | struct tda9887_priv *priv = fe->analog_demod_priv; | ||
303 | |||
304 | static char *sound[4] = { | ||
305 | "AM/TV", | ||
306 | "FM/radio", | ||
307 | "FM/TV", | ||
308 | "FM/radio" | ||
309 | }; | ||
310 | static char *adjust[32] = { | ||
311 | "-16", "-15", "-14", "-13", "-12", "-11", "-10", "-9", | ||
312 | "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1", | ||
313 | "0", "+1", "+2", "+3", "+4", "+5", "+6", "+7", | ||
314 | "+8", "+9", "+10", "+11", "+12", "+13", "+14", "+15" | ||
315 | }; | ||
316 | static char *deemph[4] = { | ||
317 | "no", "no", "75", "50" | ||
318 | }; | ||
319 | static char *carrier[4] = { | ||
320 | "4.5 MHz", | ||
321 | "5.5 MHz", | ||
322 | "6.0 MHz", | ||
323 | "6.5 MHz / AM" | ||
324 | }; | ||
325 | static char *vif[8] = { | ||
326 | "58.75 MHz", | ||
327 | "45.75 MHz", | ||
328 | "38.9 MHz", | ||
329 | "38.0 MHz", | ||
330 | "33.9 MHz", | ||
331 | "33.4 MHz", | ||
332 | "45.75 MHz + pin13", | ||
333 | "38.9 MHz + pin13", | ||
334 | }; | ||
335 | static char *rif[4] = { | ||
336 | "44 MHz", | ||
337 | "52 MHz", | ||
338 | "52 MHz", | ||
339 | "44 MHz", | ||
340 | }; | ||
341 | |||
342 | tuner_info("write: byte B 0x%02x\n", buf[1]); | ||
343 | tuner_info(" B0 video mode : %s\n", | ||
344 | (buf[1] & 0x01) ? "video trap" : "sound trap"); | ||
345 | tuner_info(" B1 auto mute fm : %s\n", | ||
346 | (buf[1] & 0x02) ? "yes" : "no"); | ||
347 | tuner_info(" B2 carrier mode : %s\n", | ||
348 | (buf[1] & 0x04) ? "QSS" : "Intercarrier"); | ||
349 | tuner_info(" B3-4 tv sound/radio : %s\n", | ||
350 | sound[(buf[1] & 0x18) >> 3]); | ||
351 | tuner_info(" B5 force mute audio: %s\n", | ||
352 | (buf[1] & 0x20) ? "yes" : "no"); | ||
353 | tuner_info(" B6 output port 1 : %s\n", | ||
354 | (buf[1] & 0x40) ? "high (inactive)" : "low (active)"); | ||
355 | tuner_info(" B7 output port 2 : %s\n", | ||
356 | (buf[1] & 0x80) ? "high (inactive)" : "low (active)"); | ||
357 | |||
358 | tuner_info("write: byte C 0x%02x\n", buf[2]); | ||
359 | tuner_info(" C0-4 top adjustment : %s dB\n", | ||
360 | adjust[buf[2] & 0x1f]); | ||
361 | tuner_info(" C5-6 de-emphasis : %s\n", | ||
362 | deemph[(buf[2] & 0x60) >> 5]); | ||
363 | tuner_info(" C7 audio gain : %s\n", | ||
364 | (buf[2] & 0x80) ? "-6" : "0"); | ||
365 | |||
366 | tuner_info("write: byte E 0x%02x\n", buf[3]); | ||
367 | tuner_info(" E0-1 sound carrier : %s\n", | ||
368 | carrier[(buf[3] & 0x03)]); | ||
369 | tuner_info(" E6 l pll gating : %s\n", | ||
370 | (buf[3] & 0x40) ? "36" : "13"); | ||
371 | |||
372 | if (buf[1] & 0x08) { | ||
373 | /* radio */ | ||
374 | tuner_info(" E2-4 video if : %s\n", | ||
375 | rif[(buf[3] & 0x0c) >> 2]); | ||
376 | tuner_info(" E7 vif agc output : %s\n", | ||
377 | (buf[3] & 0x80) | ||
378 | ? ((buf[3] & 0x10) ? "fm-agc radio" : | ||
379 | "sif-agc radio") | ||
380 | : "fm radio carrier afc"); | ||
381 | } else { | ||
382 | /* video */ | ||
383 | tuner_info(" E2-4 video if : %s\n", | ||
384 | vif[(buf[3] & 0x1c) >> 2]); | ||
385 | tuner_info(" E5 tuner gain : %s\n", | ||
386 | (buf[3] & 0x80) | ||
387 | ? ((buf[3] & 0x20) ? "external" : "normal") | ||
388 | : ((buf[3] & 0x20) ? "minimum" : "normal")); | ||
389 | tuner_info(" E7 vif agc output : %s\n", | ||
390 | (buf[3] & 0x80) ? ((buf[3] & 0x20) | ||
391 | ? "pin3 port, pin22 vif agc out" | ||
392 | : "pin22 port, pin3 vif acg ext in") | ||
393 | : "pin3+pin22 port"); | ||
394 | } | ||
395 | tuner_info("--\n"); | ||
396 | } | ||
397 | |||
398 | /* ---------------------------------------------------------------------- */ | ||
399 | |||
400 | static int tda9887_set_tvnorm(struct dvb_frontend *fe) | ||
401 | { | ||
402 | struct tda9887_priv *priv = fe->analog_demod_priv; | ||
403 | struct tvnorm *norm = NULL; | ||
404 | char *buf = priv->data; | ||
405 | int i; | ||
406 | |||
407 | if (priv->mode == V4L2_TUNER_RADIO) { | ||
408 | if (priv->audmode == V4L2_TUNER_MODE_MONO) | ||
409 | norm = &radio_mono; | ||
410 | else | ||
411 | norm = &radio_stereo; | ||
412 | } else { | ||
413 | for (i = 0; i < ARRAY_SIZE(tvnorms); i++) { | ||
414 | if (tvnorms[i].std & priv->std) { | ||
415 | norm = tvnorms+i; | ||
416 | break; | ||
417 | } | ||
418 | } | ||
419 | } | ||
420 | if (NULL == norm) { | ||
421 | tuner_dbg("Unsupported tvnorm entry - audio muted\n"); | ||
422 | return -1; | ||
423 | } | ||
424 | |||
425 | tuner_dbg("configure for: %s\n", norm->name); | ||
426 | buf[1] = norm->b; | ||
427 | buf[2] = norm->c; | ||
428 | buf[3] = norm->e; | ||
429 | return 0; | ||
430 | } | ||
431 | |||
432 | static unsigned int port1 = UNSET; | ||
433 | static unsigned int port2 = UNSET; | ||
434 | static unsigned int qss = UNSET; | ||
435 | static unsigned int adjust = UNSET; | ||
436 | |||
437 | module_param(port1, int, 0644); | ||
438 | module_param(port2, int, 0644); | ||
439 | module_param(qss, int, 0644); | ||
440 | module_param(adjust, int, 0644); | ||
441 | |||
442 | static int tda9887_set_insmod(struct dvb_frontend *fe) | ||
443 | { | ||
444 | struct tda9887_priv *priv = fe->analog_demod_priv; | ||
445 | char *buf = priv->data; | ||
446 | |||
447 | if (UNSET != port1) { | ||
448 | if (port1) | ||
449 | buf[1] |= cOutputPort1Inactive; | ||
450 | else | ||
451 | buf[1] &= ~cOutputPort1Inactive; | ||
452 | } | ||
453 | if (UNSET != port2) { | ||
454 | if (port2) | ||
455 | buf[1] |= cOutputPort2Inactive; | ||
456 | else | ||
457 | buf[1] &= ~cOutputPort2Inactive; | ||
458 | } | ||
459 | |||
460 | if (UNSET != qss) { | ||
461 | if (qss) | ||
462 | buf[1] |= cQSS; | ||
463 | else | ||
464 | buf[1] &= ~cQSS; | ||
465 | } | ||
466 | |||
467 | if (adjust >= 0x00 && adjust < 0x20) { | ||
468 | buf[2] &= ~cTopMask; | ||
469 | buf[2] |= adjust; | ||
470 | } | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | static int tda9887_do_config(struct dvb_frontend *fe) | ||
475 | { | ||
476 | struct tda9887_priv *priv = fe->analog_demod_priv; | ||
477 | char *buf = priv->data; | ||
478 | |||
479 | if (priv->config & TDA9887_PORT1_ACTIVE) | ||
480 | buf[1] &= ~cOutputPort1Inactive; | ||
481 | if (priv->config & TDA9887_PORT1_INACTIVE) | ||
482 | buf[1] |= cOutputPort1Inactive; | ||
483 | if (priv->config & TDA9887_PORT2_ACTIVE) | ||
484 | buf[1] &= ~cOutputPort2Inactive; | ||
485 | if (priv->config & TDA9887_PORT2_INACTIVE) | ||
486 | buf[1] |= cOutputPort2Inactive; | ||
487 | |||
488 | if (priv->config & TDA9887_QSS) | ||
489 | buf[1] |= cQSS; | ||
490 | if (priv->config & TDA9887_INTERCARRIER) | ||
491 | buf[1] &= ~cQSS; | ||
492 | |||
493 | if (priv->config & TDA9887_AUTOMUTE) | ||
494 | buf[1] |= cAutoMuteFmActive; | ||
495 | if (priv->config & TDA9887_DEEMPHASIS_MASK) { | ||
496 | buf[2] &= ~0x60; | ||
497 | switch (priv->config & TDA9887_DEEMPHASIS_MASK) { | ||
498 | case TDA9887_DEEMPHASIS_NONE: | ||
499 | buf[2] |= cDeemphasisOFF; | ||
500 | break; | ||
501 | case TDA9887_DEEMPHASIS_50: | ||
502 | buf[2] |= cDeemphasisON | cDeemphasis50; | ||
503 | break; | ||
504 | case TDA9887_DEEMPHASIS_75: | ||
505 | buf[2] |= cDeemphasisON | cDeemphasis75; | ||
506 | break; | ||
507 | } | ||
508 | } | ||
509 | if (priv->config & TDA9887_TOP_SET) { | ||
510 | buf[2] &= ~cTopMask; | ||
511 | buf[2] |= (priv->config >> 8) & cTopMask; | ||
512 | } | ||
513 | if ((priv->config & TDA9887_INTERCARRIER_NTSC) && | ||
514 | (priv->std & V4L2_STD_NTSC)) | ||
515 | buf[1] &= ~cQSS; | ||
516 | if (priv->config & TDA9887_GATING_18) | ||
517 | buf[3] &= ~cGating_36; | ||
518 | |||
519 | if (priv->mode == V4L2_TUNER_RADIO) { | ||
520 | if (priv->config & TDA9887_RIF_41_3) { | ||
521 | buf[3] &= ~cVideoIFMask; | ||
522 | buf[3] |= cRadioIF_41_30; | ||
523 | } | ||
524 | if (priv->config & TDA9887_GAIN_NORMAL) | ||
525 | buf[3] &= ~cTunerGainLow; | ||
526 | } | ||
527 | |||
528 | return 0; | ||
529 | } | ||
530 | |||
531 | /* ---------------------------------------------------------------------- */ | ||
532 | |||
533 | static int tda9887_status(struct dvb_frontend *fe) | ||
534 | { | ||
535 | struct tda9887_priv *priv = fe->analog_demod_priv; | ||
536 | unsigned char buf[1]; | ||
537 | int rc; | ||
538 | |||
539 | memset(buf,0,sizeof(buf)); | ||
540 | if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,buf,1))) | ||
541 | tuner_info("i2c i/o error: rc == %d (should be 1)\n", rc); | ||
542 | dump_read_message(fe, buf); | ||
543 | return 0; | ||
544 | } | ||
545 | |||
546 | static void tda9887_configure(struct dvb_frontend *fe) | ||
547 | { | ||
548 | struct tda9887_priv *priv = fe->analog_demod_priv; | ||
549 | int rc; | ||
550 | |||
551 | memset(priv->data,0,sizeof(priv->data)); | ||
552 | tda9887_set_tvnorm(fe); | ||
553 | |||
554 | /* A note on the port settings: | ||
555 | These settings tend to depend on the specifics of the board. | ||
556 | By default they are set to inactive (bit value 1) by this driver, | ||
557 | overwriting any changes made by the tvnorm. This means that it | ||
558 | is the responsibility of the module using the tda9887 to set | ||
559 | these values in case of changes in the tvnorm. | ||
560 | In many cases port 2 should be made active (0) when selecting | ||
561 | SECAM-L, and port 2 should remain inactive (1) for SECAM-L'. | ||
562 | |||
563 | For the other standards the tda9887 application note says that | ||
564 | the ports should be set to active (0), but, again, that may | ||
565 | differ depending on the precise hardware configuration. | ||
566 | */ | ||
567 | priv->data[1] |= cOutputPort1Inactive; | ||
568 | priv->data[1] |= cOutputPort2Inactive; | ||
569 | |||
570 | tda9887_do_config(fe); | ||
571 | tda9887_set_insmod(fe); | ||
572 | |||
573 | if (priv->mode == T_STANDBY) | ||
574 | priv->data[1] |= cForcedMuteAudioON; | ||
575 | |||
576 | tuner_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", | ||
577 | priv->data[1], priv->data[2], priv->data[3]); | ||
578 | if (debug > 1) | ||
579 | dump_write_message(fe, priv->data); | ||
580 | |||
581 | if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4))) | ||
582 | tuner_info("i2c i/o error: rc == %d (should be 4)\n", rc); | ||
583 | |||
584 | if (debug > 2) { | ||
585 | msleep_interruptible(1000); | ||
586 | tda9887_status(fe); | ||
587 | } | ||
588 | } | ||
589 | |||
590 | /* ---------------------------------------------------------------------- */ | ||
591 | |||
592 | static void tda9887_tuner_status(struct dvb_frontend *fe) | ||
593 | { | ||
594 | struct tda9887_priv *priv = fe->analog_demod_priv; | ||
595 | tuner_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", | ||
596 | priv->data[1], priv->data[2], priv->data[3]); | ||
597 | } | ||
598 | |||
599 | static int tda9887_get_afc(struct dvb_frontend *fe) | ||
600 | { | ||
601 | struct tda9887_priv *priv = fe->analog_demod_priv; | ||
602 | static int AFC_BITS_2_kHz[] = { | ||
603 | -12500, -37500, -62500, -97500, | ||
604 | -112500, -137500, -162500, -187500, | ||
605 | 187500, 162500, 137500, 112500, | ||
606 | 97500 , 62500, 37500 , 12500 | ||
607 | }; | ||
608 | int afc=0; | ||
609 | __u8 reg = 0; | ||
610 | |||
611 | if (1 == tuner_i2c_xfer_recv(&priv->i2c_props,®,1)) | ||
612 | afc = AFC_BITS_2_kHz[(reg>>1)&0x0f]; | ||
613 | |||
614 | return afc; | ||
615 | } | ||
616 | |||
617 | static void tda9887_standby(struct dvb_frontend *fe) | ||
618 | { | ||
619 | struct tda9887_priv *priv = fe->analog_demod_priv; | ||
620 | |||
621 | priv->mode = T_STANDBY; | ||
622 | |||
623 | tda9887_configure(fe); | ||
624 | } | ||
625 | |||
626 | static void tda9887_set_params(struct dvb_frontend *fe, | ||
627 | struct analog_parameters *params) | ||
628 | { | ||
629 | struct tda9887_priv *priv = fe->analog_demod_priv; | ||
630 | |||
631 | priv->mode = params->mode; | ||
632 | priv->audmode = params->audmode; | ||
633 | priv->std = params->std; | ||
634 | tda9887_configure(fe); | ||
635 | } | ||
636 | |||
637 | static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg) | ||
638 | { | ||
639 | struct tda9887_priv *priv = fe->analog_demod_priv; | ||
640 | |||
641 | priv->config = *(unsigned int *)priv_cfg; | ||
642 | tda9887_configure(fe); | ||
643 | |||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | static void tda9887_release(struct dvb_frontend *fe) | ||
648 | { | ||
649 | struct tda9887_priv *priv = fe->analog_demod_priv; | ||
650 | |||
651 | mutex_lock(&tda9887_list_mutex); | ||
652 | |||
653 | if (priv) | ||
654 | hybrid_tuner_release_state(priv); | ||
655 | |||
656 | mutex_unlock(&tda9887_list_mutex); | ||
657 | |||
658 | fe->analog_demod_priv = NULL; | ||
659 | } | ||
660 | |||
661 | static struct analog_demod_ops tda9887_ops = { | ||
662 | .info = { | ||
663 | .name = "tda9887", | ||
664 | }, | ||
665 | .set_params = tda9887_set_params, | ||
666 | .standby = tda9887_standby, | ||
667 | .tuner_status = tda9887_tuner_status, | ||
668 | .get_afc = tda9887_get_afc, | ||
669 | .release = tda9887_release, | ||
670 | .set_config = tda9887_set_config, | ||
671 | }; | ||
672 | |||
673 | struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, | ||
674 | struct i2c_adapter *i2c_adap, | ||
675 | u8 i2c_addr) | ||
676 | { | ||
677 | struct tda9887_priv *priv = NULL; | ||
678 | int instance; | ||
679 | |||
680 | mutex_lock(&tda9887_list_mutex); | ||
681 | |||
682 | instance = hybrid_tuner_request_state(struct tda9887_priv, priv, | ||
683 | hybrid_tuner_instance_list, | ||
684 | i2c_adap, i2c_addr, "tda9887"); | ||
685 | switch (instance) { | ||
686 | case 0: | ||
687 | mutex_unlock(&tda9887_list_mutex); | ||
688 | return NULL; | ||
689 | break; | ||
690 | case 1: | ||
691 | fe->analog_demod_priv = priv; | ||
692 | priv->mode = T_STANDBY; | ||
693 | tuner_info("tda988[5/6/7] found\n"); | ||
694 | break; | ||
695 | default: | ||
696 | fe->analog_demod_priv = priv; | ||
697 | break; | ||
698 | } | ||
699 | |||
700 | mutex_unlock(&tda9887_list_mutex); | ||
701 | |||
702 | memcpy(&fe->ops.analog_ops, &tda9887_ops, | ||
703 | sizeof(struct analog_demod_ops)); | ||
704 | |||
705 | return fe; | ||
706 | } | ||
707 | EXPORT_SYMBOL_GPL(tda9887_attach); | ||
708 | |||
709 | MODULE_LICENSE("GPL"); | ||
710 | |||
711 | /* | ||
712 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
713 | * --------------------------------------------------------------------------- | ||
714 | * Local variables: | ||
715 | * c-basic-offset: 8 | ||
716 | * End: | ||
717 | */ | ||
diff --git a/drivers/media/common/tuners/tda9887.h b/drivers/media/common/tuners/tda9887.h new file mode 100644 index 000000000000..be49dcbfc70e --- /dev/null +++ b/drivers/media/common/tuners/tda9887.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | This program is free software; you can redistribute it and/or modify | ||
3 | it under the terms of the GNU General Public License as published by | ||
4 | the Free Software Foundation; either version 2 of the License, or | ||
5 | (at your option) any later version. | ||
6 | |||
7 | This program is distributed in the hope that it will be useful, | ||
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | GNU General Public License for more details. | ||
11 | |||
12 | You should have received a copy of the GNU General Public License | ||
13 | along with this program; if not, write to the Free Software | ||
14 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
15 | */ | ||
16 | |||
17 | #ifndef __TDA9887_H__ | ||
18 | #define __TDA9887_H__ | ||
19 | |||
20 | #include <linux/i2c.h> | ||
21 | #include "dvb_frontend.h" | ||
22 | |||
23 | /* ------------------------------------------------------------------------ */ | ||
24 | #if defined(CONFIG_TUNER_TDA9887) || (defined(CONFIG_TUNER_TDA9887_MODULE) && defined(MODULE)) | ||
25 | extern struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, | ||
26 | struct i2c_adapter *i2c_adap, | ||
27 | u8 i2c_addr); | ||
28 | #else | ||
29 | static inline struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, | ||
30 | struct i2c_adapter *i2c_adap, | ||
31 | u8 i2c_addr) | ||
32 | { | ||
33 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
34 | return NULL; | ||
35 | } | ||
36 | #endif | ||
37 | |||
38 | #endif /* __TDA9887_H__ */ | ||
diff --git a/drivers/media/common/tuners/tea5761.c b/drivers/media/common/tuners/tea5761.c new file mode 100644 index 000000000000..b93cdef9ac73 --- /dev/null +++ b/drivers/media/common/tuners/tea5761.c | |||
@@ -0,0 +1,324 @@ | |||
1 | /* | ||
2 | * For Philips TEA5761 FM Chip | ||
3 | * I2C address is allways 0x20 (0x10 at 7-bit mode). | ||
4 | * | ||
5 | * Copyright (c) 2005-2007 Mauro Carvalho Chehab (mchehab@infradead.org) | ||
6 | * This code is placed under the terms of the GNUv2 General Public License | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <linux/i2c.h> | ||
11 | #include <linux/delay.h> | ||
12 | #include <linux/videodev.h> | ||
13 | #include <media/tuner.h> | ||
14 | #include "tuner-i2c.h" | ||
15 | #include "tea5761.h" | ||
16 | |||
17 | static int debug; | ||
18 | module_param(debug, int, 0644); | ||
19 | MODULE_PARM_DESC(debug, "enable verbose debug messages"); | ||
20 | |||
21 | struct tea5761_priv { | ||
22 | struct tuner_i2c_props i2c_props; | ||
23 | |||
24 | u32 frequency; | ||
25 | }; | ||
26 | |||
27 | /*****************************************************************************/ | ||
28 | |||
29 | /*************************** | ||
30 | * TEA5761HN I2C registers * | ||
31 | ***************************/ | ||
32 | |||
33 | /* INTREG - Read: bytes 0 and 1 / Write: byte 0 */ | ||
34 | |||
35 | /* first byte for reading */ | ||
36 | #define TEA5761_INTREG_IFFLAG 0x10 | ||
37 | #define TEA5761_INTREG_LEVFLAG 0x8 | ||
38 | #define TEA5761_INTREG_FRRFLAG 0x2 | ||
39 | #define TEA5761_INTREG_BLFLAG 0x1 | ||
40 | |||
41 | /* second byte for reading / byte for writing */ | ||
42 | #define TEA5761_INTREG_IFMSK 0x10 | ||
43 | #define TEA5761_INTREG_LEVMSK 0x8 | ||
44 | #define TEA5761_INTREG_FRMSK 0x2 | ||
45 | #define TEA5761_INTREG_BLMSK 0x1 | ||
46 | |||
47 | /* FRQSET - Read: bytes 2 and 3 / Write: byte 1 and 2 */ | ||
48 | |||
49 | /* First byte */ | ||
50 | #define TEA5761_FRQSET_SEARCH_UP 0x80 /* 1=Station search from botton to up */ | ||
51 | #define TEA5761_FRQSET_SEARCH_MODE 0x40 /* 1=Search mode */ | ||
52 | |||
53 | /* Bits 0-5 for divider MSB */ | ||
54 | |||
55 | /* Second byte */ | ||
56 | /* Bits 0-7 for divider LSB */ | ||
57 | |||
58 | /* TNCTRL - Read: bytes 4 and 5 / Write: Bytes 3 and 4 */ | ||
59 | |||
60 | /* first byte */ | ||
61 | |||
62 | #define TEA5761_TNCTRL_PUPD_0 0x40 /* Power UP/Power Down MSB */ | ||
63 | #define TEA5761_TNCTRL_BLIM 0X20 /* 1= Japan Frequencies, 0= European frequencies */ | ||
64 | #define TEA5761_TNCTRL_SWPM 0x10 /* 1= software port is FRRFLAG */ | ||
65 | #define TEA5761_TNCTRL_IFCTC 0x08 /* 1= IF count time 15.02 ms, 0= IF count time 2.02 ms */ | ||
66 | #define TEA5761_TNCTRL_AFM 0x04 | ||
67 | #define TEA5761_TNCTRL_SMUTE 0x02 /* 1= Soft mute */ | ||
68 | #define TEA5761_TNCTRL_SNC 0x01 | ||
69 | |||
70 | /* second byte */ | ||
71 | |||
72 | #define TEA5761_TNCTRL_MU 0x80 /* 1=Hard mute */ | ||
73 | #define TEA5761_TNCTRL_SSL_1 0x40 | ||
74 | #define TEA5761_TNCTRL_SSL_0 0x20 | ||
75 | #define TEA5761_TNCTRL_HLSI 0x10 | ||
76 | #define TEA5761_TNCTRL_MST 0x08 /* 1 = mono */ | ||
77 | #define TEA5761_TNCTRL_SWP 0x04 | ||
78 | #define TEA5761_TNCTRL_DTC 0x02 /* 1 = deemphasis 50 us, 0 = deemphasis 75 us */ | ||
79 | #define TEA5761_TNCTRL_AHLSI 0x01 | ||
80 | |||
81 | /* FRQCHECK - Read: bytes 6 and 7 */ | ||
82 | /* First byte */ | ||
83 | |||
84 | /* Bits 0-5 for divider MSB */ | ||
85 | |||
86 | /* Second byte */ | ||
87 | /* Bits 0-7 for divider LSB */ | ||
88 | |||
89 | /* TUNCHECK - Read: bytes 8 and 9 */ | ||
90 | |||
91 | /* First byte */ | ||
92 | #define TEA5761_TUNCHECK_IF_MASK 0x7e /* IF count */ | ||
93 | #define TEA5761_TUNCHECK_TUNTO 0x01 | ||
94 | |||
95 | /* Second byte */ | ||
96 | #define TEA5761_TUNCHECK_LEV_MASK 0xf0 /* Level Count */ | ||
97 | #define TEA5761_TUNCHECK_LD 0x08 | ||
98 | #define TEA5761_TUNCHECK_STEREO 0x04 | ||
99 | |||
100 | /* TESTREG - Read: bytes 10 and 11 / Write: bytes 5 and 6 */ | ||
101 | |||
102 | /* All zero = no test mode */ | ||
103 | |||
104 | /* MANID - Read: bytes 12 and 13 */ | ||
105 | |||
106 | /* First byte - should be 0x10 */ | ||
107 | #define TEA5767_MANID_VERSION_MASK 0xf0 /* Version = 1 */ | ||
108 | #define TEA5767_MANID_ID_MSB_MASK 0x0f /* Manufacurer ID - should be 0 */ | ||
109 | |||
110 | /* Second byte - Should be 0x2b */ | ||
111 | |||
112 | #define TEA5767_MANID_ID_LSB_MASK 0xfe /* Manufacturer ID - should be 0x15 */ | ||
113 | #define TEA5767_MANID_IDAV 0x01 /* 1 = Chip has ID, 0 = Chip has no ID */ | ||
114 | |||
115 | /* Chip ID - Read: bytes 14 and 15 */ | ||
116 | |||
117 | /* First byte - should be 0x57 */ | ||
118 | |||
119 | /* Second byte - should be 0x61 */ | ||
120 | |||
121 | /*****************************************************************************/ | ||
122 | |||
123 | #define FREQ_OFFSET 0 /* for TEA5767, it is 700 to give the right freq */ | ||
124 | static void tea5761_status_dump(unsigned char *buffer) | ||
125 | { | ||
126 | unsigned int div, frq; | ||
127 | |||
128 | div = ((buffer[2] & 0x3f) << 8) | buffer[3]; | ||
129 | |||
130 | frq = 1000 * (div * 32768 / 1000 + FREQ_OFFSET + 225) / 4; /* Freq in KHz */ | ||
131 | |||
132 | printk(KERN_INFO "tea5761: Frequency %d.%03d KHz (divider = 0x%04x)\n", | ||
133 | frq / 1000, frq % 1000, div); | ||
134 | } | ||
135 | |||
136 | /* Freq should be specifyed at 62.5 Hz */ | ||
137 | static int set_radio_freq(struct dvb_frontend *fe, | ||
138 | struct analog_parameters *params) | ||
139 | { | ||
140 | struct tea5761_priv *priv = fe->tuner_priv; | ||
141 | unsigned int frq = params->frequency; | ||
142 | unsigned char buffer[7] = {0, 0, 0, 0, 0, 0, 0 }; | ||
143 | unsigned div; | ||
144 | int rc; | ||
145 | |||
146 | tuner_dbg("radio freq counter %d\n", frq); | ||
147 | |||
148 | if (params->mode == T_STANDBY) { | ||
149 | tuner_dbg("TEA5761 set to standby mode\n"); | ||
150 | buffer[5] |= TEA5761_TNCTRL_MU; | ||
151 | } else { | ||
152 | buffer[4] |= TEA5761_TNCTRL_PUPD_0; | ||
153 | } | ||
154 | |||
155 | |||
156 | if (params->audmode == V4L2_TUNER_MODE_MONO) { | ||
157 | tuner_dbg("TEA5761 set to mono\n"); | ||
158 | buffer[5] |= TEA5761_TNCTRL_MST; | ||
159 | } else { | ||
160 | tuner_dbg("TEA5761 set to stereo\n"); | ||
161 | } | ||
162 | |||
163 | div = (1000 * (frq * 4 / 16 + 700 + 225) ) >> 15; | ||
164 | buffer[1] = (div >> 8) & 0x3f; | ||
165 | buffer[2] = div & 0xff; | ||
166 | |||
167 | if (debug) | ||
168 | tea5761_status_dump(buffer); | ||
169 | |||
170 | if (7 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 7))) | ||
171 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); | ||
172 | |||
173 | priv->frequency = frq * 125 / 2; | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static int tea5761_read_status(struct dvb_frontend *fe, char *buffer) | ||
179 | { | ||
180 | struct tea5761_priv *priv = fe->tuner_priv; | ||
181 | int rc; | ||
182 | |||
183 | memset(buffer, 0, 16); | ||
184 | if (16 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 16))) { | ||
185 | tuner_warn("i2c i/o error: rc == %d (should be 16)\n", rc); | ||
186 | return -EREMOTEIO; | ||
187 | } | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static inline int tea5761_signal(struct dvb_frontend *fe, const char *buffer) | ||
193 | { | ||
194 | struct tea5761_priv *priv = fe->tuner_priv; | ||
195 | |||
196 | int signal = ((buffer[9] & TEA5761_TUNCHECK_LEV_MASK) << (13 - 4)); | ||
197 | |||
198 | tuner_dbg("Signal strength: %d\n", signal); | ||
199 | |||
200 | return signal; | ||
201 | } | ||
202 | |||
203 | static inline int tea5761_stereo(struct dvb_frontend *fe, const char *buffer) | ||
204 | { | ||
205 | struct tea5761_priv *priv = fe->tuner_priv; | ||
206 | |||
207 | int stereo = buffer[9] & TEA5761_TUNCHECK_STEREO; | ||
208 | |||
209 | tuner_dbg("Radio ST GET = %02x\n", stereo); | ||
210 | |||
211 | return (stereo ? V4L2_TUNER_SUB_STEREO : 0); | ||
212 | } | ||
213 | |||
214 | static int tea5761_get_status(struct dvb_frontend *fe, u32 *status) | ||
215 | { | ||
216 | unsigned char buffer[16]; | ||
217 | |||
218 | *status = 0; | ||
219 | |||
220 | if (0 == tea5761_read_status(fe, buffer)) { | ||
221 | if (tea5761_signal(fe, buffer)) | ||
222 | *status = TUNER_STATUS_LOCKED; | ||
223 | if (tea5761_stereo(fe, buffer)) | ||
224 | *status |= TUNER_STATUS_STEREO; | ||
225 | } | ||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static int tea5761_get_rf_strength(struct dvb_frontend *fe, u16 *strength) | ||
231 | { | ||
232 | unsigned char buffer[16]; | ||
233 | |||
234 | *strength = 0; | ||
235 | |||
236 | if (0 == tea5761_read_status(fe, buffer)) | ||
237 | *strength = tea5761_signal(fe, buffer); | ||
238 | |||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr) | ||
243 | { | ||
244 | unsigned char buffer[16]; | ||
245 | int rc; | ||
246 | struct tuner_i2c_props i2c = { .adap = i2c_adap, .addr = i2c_addr }; | ||
247 | |||
248 | if (16 != (rc = tuner_i2c_xfer_recv(&i2c, buffer, 16))) { | ||
249 | printk(KERN_WARNING "it is not a TEA5761. Received %i chars.\n", rc); | ||
250 | return -EINVAL; | ||
251 | } | ||
252 | |||
253 | if ((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061)) { | ||
254 | printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x." | ||
255 | " It is not a TEA5761\n", | ||
256 | buffer[13], buffer[14], buffer[15]); | ||
257 | return -EINVAL; | ||
258 | } | ||
259 | printk(KERN_WARNING "tea5761: TEA%02x%02x detected. " | ||
260 | "Manufacturer ID= 0x%02x\n", | ||
261 | buffer[14], buffer[15], buffer[13]); | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static int tea5761_release(struct dvb_frontend *fe) | ||
267 | { | ||
268 | kfree(fe->tuner_priv); | ||
269 | fe->tuner_priv = NULL; | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static int tea5761_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
275 | { | ||
276 | struct tea5761_priv *priv = fe->tuner_priv; | ||
277 | *frequency = priv->frequency; | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static struct dvb_tuner_ops tea5761_tuner_ops = { | ||
282 | .info = { | ||
283 | .name = "tea5761", // Philips TEA5761HN FM Radio | ||
284 | }, | ||
285 | .set_analog_params = set_radio_freq, | ||
286 | .release = tea5761_release, | ||
287 | .get_frequency = tea5761_get_frequency, | ||
288 | .get_status = tea5761_get_status, | ||
289 | .get_rf_strength = tea5761_get_rf_strength, | ||
290 | }; | ||
291 | |||
292 | struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe, | ||
293 | struct i2c_adapter* i2c_adap, | ||
294 | u8 i2c_addr) | ||
295 | { | ||
296 | struct tea5761_priv *priv = NULL; | ||
297 | |||
298 | if (tea5761_autodetection(i2c_adap, i2c_addr) == EINVAL) | ||
299 | return NULL; | ||
300 | |||
301 | priv = kzalloc(sizeof(struct tea5761_priv), GFP_KERNEL); | ||
302 | if (priv == NULL) | ||
303 | return NULL; | ||
304 | fe->tuner_priv = priv; | ||
305 | |||
306 | priv->i2c_props.addr = i2c_addr; | ||
307 | priv->i2c_props.adap = i2c_adap; | ||
308 | priv->i2c_props.name = "tea5761"; | ||
309 | |||
310 | memcpy(&fe->ops.tuner_ops, &tea5761_tuner_ops, | ||
311 | sizeof(struct dvb_tuner_ops)); | ||
312 | |||
313 | tuner_info("type set to %s\n", "Philips TEA5761HN FM Radio"); | ||
314 | |||
315 | return fe; | ||
316 | } | ||
317 | |||
318 | |||
319 | EXPORT_SYMBOL_GPL(tea5761_attach); | ||
320 | EXPORT_SYMBOL_GPL(tea5761_autodetection); | ||
321 | |||
322 | MODULE_DESCRIPTION("Philips TEA5761 FM tuner driver"); | ||
323 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); | ||
324 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/common/tuners/tea5761.h b/drivers/media/common/tuners/tea5761.h new file mode 100644 index 000000000000..8eb62722b988 --- /dev/null +++ b/drivers/media/common/tuners/tea5761.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | This program is free software; you can redistribute it and/or modify | ||
3 | it under the terms of the GNU General Public License as published by | ||
4 | the Free Software Foundation; either version 2 of the License, or | ||
5 | (at your option) any later version. | ||
6 | |||
7 | This program is distributed in the hope that it will be useful, | ||
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | GNU General Public License for more details. | ||
11 | |||
12 | You should have received a copy of the GNU General Public License | ||
13 | along with this program; if not, write to the Free Software | ||
14 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
15 | */ | ||
16 | |||
17 | #ifndef __TEA5761_H__ | ||
18 | #define __TEA5761_H__ | ||
19 | |||
20 | #include <linux/i2c.h> | ||
21 | #include "dvb_frontend.h" | ||
22 | |||
23 | #if defined(CONFIG_TUNER_TEA5761) || (defined(CONFIG_TUNER_TEA5761_MODULE) && defined(MODULE)) | ||
24 | extern int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr); | ||
25 | |||
26 | extern struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe, | ||
27 | struct i2c_adapter* i2c_adap, | ||
28 | u8 i2c_addr); | ||
29 | #else | ||
30 | static inline int tea5761_autodetection(struct i2c_adapter* i2c_adap, | ||
31 | u8 i2c_addr) | ||
32 | { | ||
33 | printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", | ||
34 | __func__); | ||
35 | return -EINVAL; | ||
36 | } | ||
37 | |||
38 | static inline struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe, | ||
39 | struct i2c_adapter* i2c_adap, | ||
40 | u8 i2c_addr) | ||
41 | { | ||
42 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
43 | return NULL; | ||
44 | } | ||
45 | #endif | ||
46 | |||
47 | #endif /* __TEA5761_H__ */ | ||
diff --git a/drivers/media/common/tuners/tea5767.c b/drivers/media/common/tuners/tea5767.c new file mode 100644 index 000000000000..f6e7d7ad8424 --- /dev/null +++ b/drivers/media/common/tuners/tea5767.c | |||
@@ -0,0 +1,474 @@ | |||
1 | /* | ||
2 | * For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview | ||
3 | * I2C address is allways 0xC0. | ||
4 | * | ||
5 | * | ||
6 | * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@infradead.org) | ||
7 | * This code is placed under the terms of the GNU General Public License | ||
8 | * | ||
9 | * tea5767 autodetection thanks to Torsten Seeboth and Atsushi Nakagawa | ||
10 | * from their contributions on DScaler. | ||
11 | */ | ||
12 | |||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/videodev.h> | ||
16 | #include "tuner-i2c.h" | ||
17 | #include "tea5767.h" | ||
18 | |||
19 | static int debug; | ||
20 | module_param(debug, int, 0644); | ||
21 | MODULE_PARM_DESC(debug, "enable verbose debug messages"); | ||
22 | |||
23 | /*****************************************************************************/ | ||
24 | |||
25 | struct tea5767_priv { | ||
26 | struct tuner_i2c_props i2c_props; | ||
27 | u32 frequency; | ||
28 | struct tea5767_ctrl ctrl; | ||
29 | }; | ||
30 | |||
31 | /*****************************************************************************/ | ||
32 | |||
33 | /****************************** | ||
34 | * Write mode register values * | ||
35 | ******************************/ | ||
36 | |||
37 | /* First register */ | ||
38 | #define TEA5767_MUTE 0x80 /* Mutes output */ | ||
39 | #define TEA5767_SEARCH 0x40 /* Activates station search */ | ||
40 | /* Bits 0-5 for divider MSB */ | ||
41 | |||
42 | /* Second register */ | ||
43 | /* Bits 0-7 for divider LSB */ | ||
44 | |||
45 | /* Third register */ | ||
46 | |||
47 | /* Station search from botton to up */ | ||
48 | #define TEA5767_SEARCH_UP 0x80 | ||
49 | |||
50 | /* Searches with ADC output = 10 */ | ||
51 | #define TEA5767_SRCH_HIGH_LVL 0x60 | ||
52 | |||
53 | /* Searches with ADC output = 10 */ | ||
54 | #define TEA5767_SRCH_MID_LVL 0x40 | ||
55 | |||
56 | /* Searches with ADC output = 5 */ | ||
57 | #define TEA5767_SRCH_LOW_LVL 0x20 | ||
58 | |||
59 | /* if on, div=4*(Frf+Fif)/Fref otherwise, div=4*(Frf-Fif)/Freq) */ | ||
60 | #define TEA5767_HIGH_LO_INJECT 0x10 | ||
61 | |||
62 | /* Disable stereo */ | ||
63 | #define TEA5767_MONO 0x08 | ||
64 | |||
65 | /* Disable right channel and turns to mono */ | ||
66 | #define TEA5767_MUTE_RIGHT 0x04 | ||
67 | |||
68 | /* Disable left channel and turns to mono */ | ||
69 | #define TEA5767_MUTE_LEFT 0x02 | ||
70 | |||
71 | #define TEA5767_PORT1_HIGH 0x01 | ||
72 | |||
73 | /* Fourth register */ | ||
74 | #define TEA5767_PORT2_HIGH 0x80 | ||
75 | /* Chips stops working. Only I2C bus remains on */ | ||
76 | #define TEA5767_STDBY 0x40 | ||
77 | |||
78 | /* Japan freq (76-108 MHz. If disabled, 87.5-108 MHz */ | ||
79 | #define TEA5767_JAPAN_BAND 0x20 | ||
80 | |||
81 | /* Unselected means 32.768 KHz freq as reference. Otherwise Xtal at 13 MHz */ | ||
82 | #define TEA5767_XTAL_32768 0x10 | ||
83 | |||
84 | /* Cuts weak signals */ | ||
85 | #define TEA5767_SOFT_MUTE 0x08 | ||
86 | |||
87 | /* Activates high cut control */ | ||
88 | #define TEA5767_HIGH_CUT_CTRL 0x04 | ||
89 | |||
90 | /* Activates stereo noise control */ | ||
91 | #define TEA5767_ST_NOISE_CTL 0x02 | ||
92 | |||
93 | /* If activate PORT 1 indicates SEARCH or else it is used as PORT1 */ | ||
94 | #define TEA5767_SRCH_IND 0x01 | ||
95 | |||
96 | /* Fifth register */ | ||
97 | |||
98 | /* By activating, it will use Xtal at 13 MHz as reference for divider */ | ||
99 | #define TEA5767_PLLREF_ENABLE 0x80 | ||
100 | |||
101 | /* By activating, deemphasis=50, or else, deemphasis of 50us */ | ||
102 | #define TEA5767_DEEMPH_75 0X40 | ||
103 | |||
104 | /***************************** | ||
105 | * Read mode register values * | ||
106 | *****************************/ | ||
107 | |||
108 | /* First register */ | ||
109 | #define TEA5767_READY_FLAG_MASK 0x80 | ||
110 | #define TEA5767_BAND_LIMIT_MASK 0X40 | ||
111 | /* Bits 0-5 for divider MSB after search or preset */ | ||
112 | |||
113 | /* Second register */ | ||
114 | /* Bits 0-7 for divider LSB after search or preset */ | ||
115 | |||
116 | /* Third register */ | ||
117 | #define TEA5767_STEREO_MASK 0x80 | ||
118 | #define TEA5767_IF_CNTR_MASK 0x7f | ||
119 | |||
120 | /* Fourth register */ | ||
121 | #define TEA5767_ADC_LEVEL_MASK 0xf0 | ||
122 | |||
123 | /* should be 0 */ | ||
124 | #define TEA5767_CHIP_ID_MASK 0x0f | ||
125 | |||
126 | /* Fifth register */ | ||
127 | /* Reserved for future extensions */ | ||
128 | #define TEA5767_RESERVED_MASK 0xff | ||
129 | |||
130 | /*****************************************************************************/ | ||
131 | |||
132 | static void tea5767_status_dump(struct tea5767_priv *priv, | ||
133 | unsigned char *buffer) | ||
134 | { | ||
135 | unsigned int div, frq; | ||
136 | |||
137 | if (TEA5767_READY_FLAG_MASK & buffer[0]) | ||
138 | tuner_info("Ready Flag ON\n"); | ||
139 | else | ||
140 | tuner_info("Ready Flag OFF\n"); | ||
141 | |||
142 | if (TEA5767_BAND_LIMIT_MASK & buffer[0]) | ||
143 | tuner_info("Tuner at band limit\n"); | ||
144 | else | ||
145 | tuner_info("Tuner not at band limit\n"); | ||
146 | |||
147 | div = ((buffer[0] & 0x3f) << 8) | buffer[1]; | ||
148 | |||
149 | switch (priv->ctrl.xtal_freq) { | ||
150 | case TEA5767_HIGH_LO_13MHz: | ||
151 | frq = (div * 50000 - 700000 - 225000) / 4; /* Freq in KHz */ | ||
152 | break; | ||
153 | case TEA5767_LOW_LO_13MHz: | ||
154 | frq = (div * 50000 + 700000 + 225000) / 4; /* Freq in KHz */ | ||
155 | break; | ||
156 | case TEA5767_LOW_LO_32768: | ||
157 | frq = (div * 32768 + 700000 + 225000) / 4; /* Freq in KHz */ | ||
158 | break; | ||
159 | case TEA5767_HIGH_LO_32768: | ||
160 | default: | ||
161 | frq = (div * 32768 - 700000 - 225000) / 4; /* Freq in KHz */ | ||
162 | break; | ||
163 | } | ||
164 | buffer[0] = (div >> 8) & 0x3f; | ||
165 | buffer[1] = div & 0xff; | ||
166 | |||
167 | tuner_info("Frequency %d.%03d KHz (divider = 0x%04x)\n", | ||
168 | frq / 1000, frq % 1000, div); | ||
169 | |||
170 | if (TEA5767_STEREO_MASK & buffer[2]) | ||
171 | tuner_info("Stereo\n"); | ||
172 | else | ||
173 | tuner_info("Mono\n"); | ||
174 | |||
175 | tuner_info("IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK); | ||
176 | |||
177 | tuner_info("ADC Level = %d\n", | ||
178 | (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4); | ||
179 | |||
180 | tuner_info("Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK)); | ||
181 | |||
182 | tuner_info("Reserved = 0x%02x\n", | ||
183 | (buffer[4] & TEA5767_RESERVED_MASK)); | ||
184 | } | ||
185 | |||
186 | /* Freq should be specifyed at 62.5 Hz */ | ||
187 | static int set_radio_freq(struct dvb_frontend *fe, | ||
188 | struct analog_parameters *params) | ||
189 | { | ||
190 | struct tea5767_priv *priv = fe->tuner_priv; | ||
191 | unsigned int frq = params->frequency; | ||
192 | unsigned char buffer[5]; | ||
193 | unsigned div; | ||
194 | int rc; | ||
195 | |||
196 | tuner_dbg("radio freq = %d.%03d MHz\n", frq/16000,(frq/16)%1000); | ||
197 | |||
198 | buffer[2] = 0; | ||
199 | |||
200 | if (priv->ctrl.port1) | ||
201 | buffer[2] |= TEA5767_PORT1_HIGH; | ||
202 | |||
203 | if (params->audmode == V4L2_TUNER_MODE_MONO) { | ||
204 | tuner_dbg("TEA5767 set to mono\n"); | ||
205 | buffer[2] |= TEA5767_MONO; | ||
206 | } else { | ||
207 | tuner_dbg("TEA5767 set to stereo\n"); | ||
208 | } | ||
209 | |||
210 | |||
211 | buffer[3] = 0; | ||
212 | |||
213 | if (priv->ctrl.port2) | ||
214 | buffer[3] |= TEA5767_PORT2_HIGH; | ||
215 | |||
216 | if (priv->ctrl.high_cut) | ||
217 | buffer[3] |= TEA5767_HIGH_CUT_CTRL; | ||
218 | |||
219 | if (priv->ctrl.st_noise) | ||
220 | buffer[3] |= TEA5767_ST_NOISE_CTL; | ||
221 | |||
222 | if (priv->ctrl.soft_mute) | ||
223 | buffer[3] |= TEA5767_SOFT_MUTE; | ||
224 | |||
225 | if (priv->ctrl.japan_band) | ||
226 | buffer[3] |= TEA5767_JAPAN_BAND; | ||
227 | |||
228 | buffer[4] = 0; | ||
229 | |||
230 | if (priv->ctrl.deemph_75) | ||
231 | buffer[4] |= TEA5767_DEEMPH_75; | ||
232 | |||
233 | if (priv->ctrl.pllref) | ||
234 | buffer[4] |= TEA5767_PLLREF_ENABLE; | ||
235 | |||
236 | |||
237 | /* Rounds freq to next decimal value - for 62.5 KHz step */ | ||
238 | /* frq = 20*(frq/16)+radio_frq[frq%16]; */ | ||
239 | |||
240 | switch (priv->ctrl.xtal_freq) { | ||
241 | case TEA5767_HIGH_LO_13MHz: | ||
242 | tuner_dbg("radio HIGH LO inject xtal @ 13 MHz\n"); | ||
243 | buffer[2] |= TEA5767_HIGH_LO_INJECT; | ||
244 | div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000; | ||
245 | break; | ||
246 | case TEA5767_LOW_LO_13MHz: | ||
247 | tuner_dbg("radio LOW LO inject xtal @ 13 MHz\n"); | ||
248 | |||
249 | div = (frq * (4000 / 16) - 700000 - 225000 + 25000) / 50000; | ||
250 | break; | ||
251 | case TEA5767_LOW_LO_32768: | ||
252 | tuner_dbg("radio LOW LO inject xtal @ 32,768 MHz\n"); | ||
253 | buffer[3] |= TEA5767_XTAL_32768; | ||
254 | /* const 700=4000*175 Khz - to adjust freq to right value */ | ||
255 | div = ((frq * (4000 / 16) - 700000 - 225000) + 16384) >> 15; | ||
256 | break; | ||
257 | case TEA5767_HIGH_LO_32768: | ||
258 | default: | ||
259 | tuner_dbg("radio HIGH LO inject xtal @ 32,768 MHz\n"); | ||
260 | |||
261 | buffer[2] |= TEA5767_HIGH_LO_INJECT; | ||
262 | buffer[3] |= TEA5767_XTAL_32768; | ||
263 | div = ((frq * (4000 / 16) + 700000 + 225000) + 16384) >> 15; | ||
264 | break; | ||
265 | } | ||
266 | buffer[0] = (div >> 8) & 0x3f; | ||
267 | buffer[1] = div & 0xff; | ||
268 | |||
269 | if (5 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 5))) | ||
270 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); | ||
271 | |||
272 | if (debug) { | ||
273 | if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5))) | ||
274 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); | ||
275 | else | ||
276 | tea5767_status_dump(priv, buffer); | ||
277 | } | ||
278 | |||
279 | priv->frequency = frq * 125 / 2; | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int tea5767_read_status(struct dvb_frontend *fe, char *buffer) | ||
285 | { | ||
286 | struct tea5767_priv *priv = fe->tuner_priv; | ||
287 | int rc; | ||
288 | |||
289 | memset(buffer, 0, 5); | ||
290 | if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5))) { | ||
291 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); | ||
292 | return -EREMOTEIO; | ||
293 | } | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static inline int tea5767_signal(struct dvb_frontend *fe, const char *buffer) | ||
299 | { | ||
300 | struct tea5767_priv *priv = fe->tuner_priv; | ||
301 | |||
302 | int signal = ((buffer[3] & TEA5767_ADC_LEVEL_MASK) << 8); | ||
303 | |||
304 | tuner_dbg("Signal strength: %d\n", signal); | ||
305 | |||
306 | return signal; | ||
307 | } | ||
308 | |||
309 | static inline int tea5767_stereo(struct dvb_frontend *fe, const char *buffer) | ||
310 | { | ||
311 | struct tea5767_priv *priv = fe->tuner_priv; | ||
312 | |||
313 | int stereo = buffer[2] & TEA5767_STEREO_MASK; | ||
314 | |||
315 | tuner_dbg("Radio ST GET = %02x\n", stereo); | ||
316 | |||
317 | return (stereo ? V4L2_TUNER_SUB_STEREO : 0); | ||
318 | } | ||
319 | |||
320 | static int tea5767_get_status(struct dvb_frontend *fe, u32 *status) | ||
321 | { | ||
322 | unsigned char buffer[5]; | ||
323 | |||
324 | *status = 0; | ||
325 | |||
326 | if (0 == tea5767_read_status(fe, buffer)) { | ||
327 | if (tea5767_signal(fe, buffer)) | ||
328 | *status = TUNER_STATUS_LOCKED; | ||
329 | if (tea5767_stereo(fe, buffer)) | ||
330 | *status |= TUNER_STATUS_STEREO; | ||
331 | } | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static int tea5767_get_rf_strength(struct dvb_frontend *fe, u16 *strength) | ||
337 | { | ||
338 | unsigned char buffer[5]; | ||
339 | |||
340 | *strength = 0; | ||
341 | |||
342 | if (0 == tea5767_read_status(fe, buffer)) | ||
343 | *strength = tea5767_signal(fe, buffer); | ||
344 | |||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | static int tea5767_standby(struct dvb_frontend *fe) | ||
349 | { | ||
350 | unsigned char buffer[5]; | ||
351 | struct tea5767_priv *priv = fe->tuner_priv; | ||
352 | unsigned div, rc; | ||
353 | |||
354 | div = (87500 * 4 + 700 + 225 + 25) / 50; /* Set frequency to 87.5 MHz */ | ||
355 | buffer[0] = (div >> 8) & 0x3f; | ||
356 | buffer[1] = div & 0xff; | ||
357 | buffer[2] = TEA5767_PORT1_HIGH; | ||
358 | buffer[3] = TEA5767_PORT2_HIGH | TEA5767_HIGH_CUT_CTRL | | ||
359 | TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND | TEA5767_STDBY; | ||
360 | buffer[4] = 0; | ||
361 | |||
362 | if (5 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 5))) | ||
363 | tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); | ||
364 | |||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr) | ||
369 | { | ||
370 | struct tuner_i2c_props i2c = { .adap = i2c_adap, .addr = i2c_addr }; | ||
371 | unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
372 | int rc; | ||
373 | |||
374 | if ((rc = tuner_i2c_xfer_recv(&i2c, buffer, 7))< 5) { | ||
375 | printk(KERN_WARNING "It is not a TEA5767. Received %i bytes.\n", rc); | ||
376 | return EINVAL; | ||
377 | } | ||
378 | |||
379 | /* If all bytes are the same then it's a TV tuner and not a tea5767 */ | ||
380 | if (buffer[0] == buffer[1] && buffer[0] == buffer[2] && | ||
381 | buffer[0] == buffer[3] && buffer[0] == buffer[4]) { | ||
382 | printk(KERN_WARNING "All bytes are equal. It is not a TEA5767\n"); | ||
383 | return EINVAL; | ||
384 | } | ||
385 | |||
386 | /* Status bytes: | ||
387 | * Byte 4: bit 3:1 : CI (Chip Identification) == 0 | ||
388 | * bit 0 : internally set to 0 | ||
389 | * Byte 5: bit 7:0 : == 0 | ||
390 | */ | ||
391 | if (((buffer[3] & 0x0f) != 0x00) || (buffer[4] != 0x00)) { | ||
392 | printk(KERN_WARNING "Chip ID is not zero. It is not a TEA5767\n"); | ||
393 | return EINVAL; | ||
394 | } | ||
395 | |||
396 | |||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | static int tea5767_release(struct dvb_frontend *fe) | ||
401 | { | ||
402 | kfree(fe->tuner_priv); | ||
403 | fe->tuner_priv = NULL; | ||
404 | |||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | static int tea5767_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
409 | { | ||
410 | struct tea5767_priv *priv = fe->tuner_priv; | ||
411 | *frequency = priv->frequency; | ||
412 | |||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | static int tea5767_set_config (struct dvb_frontend *fe, void *priv_cfg) | ||
417 | { | ||
418 | struct tea5767_priv *priv = fe->tuner_priv; | ||
419 | |||
420 | memcpy(&priv->ctrl, priv_cfg, sizeof(priv->ctrl)); | ||
421 | |||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | static struct dvb_tuner_ops tea5767_tuner_ops = { | ||
426 | .info = { | ||
427 | .name = "tea5767", // Philips TEA5767HN FM Radio | ||
428 | }, | ||
429 | |||
430 | .set_analog_params = set_radio_freq, | ||
431 | .set_config = tea5767_set_config, | ||
432 | .sleep = tea5767_standby, | ||
433 | .release = tea5767_release, | ||
434 | .get_frequency = tea5767_get_frequency, | ||
435 | .get_status = tea5767_get_status, | ||
436 | .get_rf_strength = tea5767_get_rf_strength, | ||
437 | }; | ||
438 | |||
439 | struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe, | ||
440 | struct i2c_adapter* i2c_adap, | ||
441 | u8 i2c_addr) | ||
442 | { | ||
443 | struct tea5767_priv *priv = NULL; | ||
444 | |||
445 | priv = kzalloc(sizeof(struct tea5767_priv), GFP_KERNEL); | ||
446 | if (priv == NULL) | ||
447 | return NULL; | ||
448 | fe->tuner_priv = priv; | ||
449 | |||
450 | priv->i2c_props.addr = i2c_addr; | ||
451 | priv->i2c_props.adap = i2c_adap; | ||
452 | priv->i2c_props.name = "tea5767"; | ||
453 | |||
454 | priv->ctrl.xtal_freq = TEA5767_HIGH_LO_32768; | ||
455 | priv->ctrl.port1 = 1; | ||
456 | priv->ctrl.port2 = 1; | ||
457 | priv->ctrl.high_cut = 1; | ||
458 | priv->ctrl.st_noise = 1; | ||
459 | priv->ctrl.japan_band = 1; | ||
460 | |||
461 | memcpy(&fe->ops.tuner_ops, &tea5767_tuner_ops, | ||
462 | sizeof(struct dvb_tuner_ops)); | ||
463 | |||
464 | tuner_info("type set to %s\n", "Philips TEA5767HN FM Radio"); | ||
465 | |||
466 | return fe; | ||
467 | } | ||
468 | |||
469 | EXPORT_SYMBOL_GPL(tea5767_attach); | ||
470 | EXPORT_SYMBOL_GPL(tea5767_autodetection); | ||
471 | |||
472 | MODULE_DESCRIPTION("Philips TEA5767 FM tuner driver"); | ||
473 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); | ||
474 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/common/tuners/tea5767.h b/drivers/media/common/tuners/tea5767.h new file mode 100644 index 000000000000..7b547c092e25 --- /dev/null +++ b/drivers/media/common/tuners/tea5767.h | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | This program is free software; you can redistribute it and/or modify | ||
3 | it under the terms of the GNU General Public License as published by | ||
4 | the Free Software Foundation; either version 2 of the License, or | ||
5 | (at your option) any later version. | ||
6 | |||
7 | This program is distributed in the hope that it will be useful, | ||
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | GNU General Public License for more details. | ||
11 | |||
12 | You should have received a copy of the GNU General Public License | ||
13 | along with this program; if not, write to the Free Software | ||
14 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
15 | */ | ||
16 | |||
17 | #ifndef __TEA5767_H__ | ||
18 | #define __TEA5767_H__ | ||
19 | |||
20 | #include <linux/i2c.h> | ||
21 | #include "dvb_frontend.h" | ||
22 | |||
23 | enum tea5767_xtal { | ||
24 | TEA5767_LOW_LO_32768 = 0, | ||
25 | TEA5767_HIGH_LO_32768 = 1, | ||
26 | TEA5767_LOW_LO_13MHz = 2, | ||
27 | TEA5767_HIGH_LO_13MHz = 3, | ||
28 | }; | ||
29 | |||
30 | struct tea5767_ctrl { | ||
31 | unsigned int port1:1; | ||
32 | unsigned int port2:1; | ||
33 | unsigned int high_cut:1; | ||
34 | unsigned int st_noise:1; | ||
35 | unsigned int soft_mute:1; | ||
36 | unsigned int japan_band:1; | ||
37 | unsigned int deemph_75:1; | ||
38 | unsigned int pllref:1; | ||
39 | enum tea5767_xtal xtal_freq; | ||
40 | }; | ||
41 | |||
42 | #if defined(CONFIG_TUNER_TEA5767) || (defined(CONFIG_TUNER_TEA5767_MODULE) && defined(MODULE)) | ||
43 | extern int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr); | ||
44 | |||
45 | extern struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe, | ||
46 | struct i2c_adapter* i2c_adap, | ||
47 | u8 i2c_addr); | ||
48 | #else | ||
49 | static inline int tea5767_autodetection(struct i2c_adapter* i2c_adap, | ||
50 | u8 i2c_addr) | ||
51 | { | ||
52 | printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", | ||
53 | __func__); | ||
54 | return -EINVAL; | ||
55 | } | ||
56 | |||
57 | static inline struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe, | ||
58 | struct i2c_adapter* i2c_adap, | ||
59 | u8 i2c_addr) | ||
60 | { | ||
61 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
62 | return NULL; | ||
63 | } | ||
64 | #endif | ||
65 | |||
66 | #endif /* __TEA5767_H__ */ | ||
diff --git a/drivers/media/common/tuners/tuner-i2c.h b/drivers/media/common/tuners/tuner-i2c.h new file mode 100644 index 000000000000..3ad6c8e0b04c --- /dev/null +++ b/drivers/media/common/tuners/tuner-i2c.h | |||
@@ -0,0 +1,173 @@ | |||
1 | /* | ||
2 | tuner-i2c.h - i2c interface for different tuners | ||
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 | #ifndef __TUNER_I2C_H__ | ||
22 | #define __TUNER_I2C_H__ | ||
23 | |||
24 | #include <linux/i2c.h> | ||
25 | |||
26 | struct tuner_i2c_props { | ||
27 | u8 addr; | ||
28 | struct i2c_adapter *adap; | ||
29 | |||
30 | /* used for tuner instance management */ | ||
31 | int count; | ||
32 | char *name; | ||
33 | }; | ||
34 | |||
35 | static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, char *buf, int len) | ||
36 | { | ||
37 | struct i2c_msg msg = { .addr = props->addr, .flags = 0, | ||
38 | .buf = buf, .len = len }; | ||
39 | int ret = i2c_transfer(props->adap, &msg, 1); | ||
40 | |||
41 | return (ret == 1) ? len : ret; | ||
42 | } | ||
43 | |||
44 | static inline int tuner_i2c_xfer_recv(struct tuner_i2c_props *props, char *buf, int len) | ||
45 | { | ||
46 | struct i2c_msg msg = { .addr = props->addr, .flags = I2C_M_RD, | ||
47 | .buf = buf, .len = len }; | ||
48 | int ret = i2c_transfer(props->adap, &msg, 1); | ||
49 | |||
50 | return (ret == 1) ? len : ret; | ||
51 | } | ||
52 | |||
53 | static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props, | ||
54 | char *obuf, int olen, | ||
55 | char *ibuf, int ilen) | ||
56 | { | ||
57 | struct i2c_msg msg[2] = { { .addr = props->addr, .flags = 0, | ||
58 | .buf = obuf, .len = olen }, | ||
59 | { .addr = props->addr, .flags = I2C_M_RD, | ||
60 | .buf = ibuf, .len = ilen } }; | ||
61 | int ret = i2c_transfer(props->adap, msg, 2); | ||
62 | |||
63 | return (ret == 2) ? ilen : ret; | ||
64 | } | ||
65 | |||
66 | /* Callers must declare as a global for the module: | ||
67 | * | ||
68 | * static LIST_HEAD(hybrid_tuner_instance_list); | ||
69 | * | ||
70 | * hybrid_tuner_instance_list should be the third argument | ||
71 | * passed into hybrid_tuner_request_state(). | ||
72 | * | ||
73 | * state structure must contain the following: | ||
74 | * | ||
75 | * struct list_head hybrid_tuner_instance_list; | ||
76 | * struct tuner_i2c_props i2c_props; | ||
77 | * | ||
78 | * hybrid_tuner_instance_list (both within state structure and globally) | ||
79 | * is only required if the driver is using hybrid_tuner_request_state | ||
80 | * and hybrid_tuner_release_state to manage state sharing between | ||
81 | * multiple instances of hybrid tuners. | ||
82 | */ | ||
83 | |||
84 | #define tuner_printk(kernlvl, i2cprops, fmt, arg...) do { \ | ||
85 | printk(kernlvl "%s %d-%04x: " fmt, i2cprops.name, \ | ||
86 | i2cprops.adap ? \ | ||
87 | i2c_adapter_id(i2cprops.adap) : -1, \ | ||
88 | i2cprops.addr, ##arg); \ | ||
89 | } while (0) | ||
90 | |||
91 | /* TO DO: convert all callers of these macros to pass in | ||
92 | * struct tuner_i2c_props, then remove the macro wrappers */ | ||
93 | |||
94 | #define __tuner_warn(i2cprops, fmt, arg...) do { \ | ||
95 | tuner_printk(KERN_WARNING, i2cprops, fmt, ##arg); \ | ||
96 | } while (0) | ||
97 | |||
98 | #define __tuner_info(i2cprops, fmt, arg...) do { \ | ||
99 | tuner_printk(KERN_INFO, i2cprops, fmt, ##arg); \ | ||
100 | } while (0) | ||
101 | |||
102 | #define __tuner_err(i2cprops, fmt, arg...) do { \ | ||
103 | tuner_printk(KERN_ERR, i2cprops, fmt, ##arg); \ | ||
104 | } while (0) | ||
105 | |||
106 | #define __tuner_dbg(i2cprops, fmt, arg...) do { \ | ||
107 | if ((debug)) \ | ||
108 | tuner_printk(KERN_DEBUG, i2cprops, fmt, ##arg); \ | ||
109 | } while (0) | ||
110 | |||
111 | #define tuner_warn(fmt, arg...) __tuner_warn(priv->i2c_props, fmt, ##arg) | ||
112 | #define tuner_info(fmt, arg...) __tuner_info(priv->i2c_props, fmt, ##arg) | ||
113 | #define tuner_err(fmt, arg...) __tuner_err(priv->i2c_props, fmt, ##arg) | ||
114 | #define tuner_dbg(fmt, arg...) __tuner_dbg(priv->i2c_props, fmt, ##arg) | ||
115 | |||
116 | /****************************************************************************/ | ||
117 | |||
118 | /* The return value of hybrid_tuner_request_state indicates the number of | ||
119 | * instances using this tuner object. | ||
120 | * | ||
121 | * 0 - no instances, indicates an error - kzalloc must have failed | ||
122 | * | ||
123 | * 1 - one instance, indicates that the tuner object was created successfully | ||
124 | * | ||
125 | * 2 (or more) instances, indicates that an existing tuner object was found | ||
126 | */ | ||
127 | |||
128 | #define hybrid_tuner_request_state(type, state, list, i2cadap, i2caddr, devname)\ | ||
129 | ({ \ | ||
130 | int __ret = 0; \ | ||
131 | list_for_each_entry(state, &list, hybrid_tuner_instance_list) { \ | ||
132 | if (((i2cadap) && (state->i2c_props.adap)) && \ | ||
133 | ((i2c_adapter_id(state->i2c_props.adap) == \ | ||
134 | i2c_adapter_id(i2cadap)) && \ | ||
135 | (i2caddr == state->i2c_props.addr))) { \ | ||
136 | __tuner_info(state->i2c_props, \ | ||
137 | "attaching existing instance\n"); \ | ||
138 | state->i2c_props.count++; \ | ||
139 | __ret = state->i2c_props.count; \ | ||
140 | break; \ | ||
141 | } \ | ||
142 | } \ | ||
143 | if (0 == __ret) { \ | ||
144 | state = kzalloc(sizeof(type), GFP_KERNEL); \ | ||
145 | if (NULL == state) \ | ||
146 | goto __fail; \ | ||
147 | state->i2c_props.addr = i2caddr; \ | ||
148 | state->i2c_props.adap = i2cadap; \ | ||
149 | state->i2c_props.name = devname; \ | ||
150 | __tuner_info(state->i2c_props, \ | ||
151 | "creating new instance\n"); \ | ||
152 | list_add_tail(&state->hybrid_tuner_instance_list, &list);\ | ||
153 | state->i2c_props.count++; \ | ||
154 | __ret = state->i2c_props.count; \ | ||
155 | } \ | ||
156 | __fail: \ | ||
157 | __ret; \ | ||
158 | }) | ||
159 | |||
160 | #define hybrid_tuner_release_state(state) \ | ||
161 | ({ \ | ||
162 | int __ret; \ | ||
163 | state->i2c_props.count--; \ | ||
164 | __ret = state->i2c_props.count; \ | ||
165 | if (!state->i2c_props.count) { \ | ||
166 | __tuner_info(state->i2c_props, "destroying instance\n");\ | ||
167 | list_del(&state->hybrid_tuner_instance_list); \ | ||
168 | kfree(state); \ | ||
169 | } \ | ||
170 | __ret; \ | ||
171 | }) | ||
172 | |||
173 | #endif /* __TUNER_I2C_H__ */ | ||
diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c new file mode 100644 index 000000000000..be8d903171b7 --- /dev/null +++ b/drivers/media/common/tuners/tuner-simple.c | |||
@@ -0,0 +1,1093 @@ | |||
1 | /* | ||
2 | * i2c tv tuner chip device driver | ||
3 | * controls all those simple 4-control-bytes style tuners. | ||
4 | * | ||
5 | * This "tuner-simple" module was split apart from the original "tuner" module. | ||
6 | */ | ||
7 | #include <linux/delay.h> | ||
8 | #include <linux/i2c.h> | ||
9 | #include <linux/videodev.h> | ||
10 | #include <media/tuner.h> | ||
11 | #include <media/v4l2-common.h> | ||
12 | #include <media/tuner-types.h> | ||
13 | #include "tuner-i2c.h" | ||
14 | #include "tuner-simple.h" | ||
15 | |||
16 | static int debug; | ||
17 | module_param(debug, int, 0644); | ||
18 | MODULE_PARM_DESC(debug, "enable verbose debug messages"); | ||
19 | |||
20 | #define TUNER_SIMPLE_MAX 64 | ||
21 | static unsigned int simple_devcount; | ||
22 | |||
23 | static int offset; | ||
24 | module_param(offset, int, 0664); | ||
25 | MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner"); | ||
26 | |||
27 | static unsigned int atv_input[TUNER_SIMPLE_MAX] = \ | ||
28 | { [0 ... (TUNER_SIMPLE_MAX-1)] = 0 }; | ||
29 | static unsigned int dtv_input[TUNER_SIMPLE_MAX] = \ | ||
30 | { [0 ... (TUNER_SIMPLE_MAX-1)] = 0 }; | ||
31 | module_param_array(atv_input, int, NULL, 0644); | ||
32 | module_param_array(dtv_input, int, NULL, 0644); | ||
33 | MODULE_PARM_DESC(atv_input, "specify atv rf input, 0 for autoselect"); | ||
34 | MODULE_PARM_DESC(dtv_input, "specify dtv rf input, 0 for autoselect"); | ||
35 | |||
36 | /* ---------------------------------------------------------------------- */ | ||
37 | |||
38 | /* tv standard selection for Temic 4046 FM5 | ||
39 | this value takes the low bits of control byte 2 | ||
40 | from datasheet Rev.01, Feb.00 | ||
41 | standard BG I L L2 D | ||
42 | picture IF 38.9 38.9 38.9 33.95 38.9 | ||
43 | sound 1 33.4 32.9 32.4 40.45 32.4 | ||
44 | sound 2 33.16 | ||
45 | NICAM 33.05 32.348 33.05 33.05 | ||
46 | */ | ||
47 | #define TEMIC_SET_PAL_I 0x05 | ||
48 | #define TEMIC_SET_PAL_DK 0x09 | ||
49 | #define TEMIC_SET_PAL_L 0x0a /* SECAM ? */ | ||
50 | #define TEMIC_SET_PAL_L2 0x0b /* change IF ! */ | ||
51 | #define TEMIC_SET_PAL_BG 0x0c | ||
52 | |||
53 | /* tv tuner system standard selection for Philips FQ1216ME | ||
54 | this value takes the low bits of control byte 2 | ||
55 | from datasheet "1999 Nov 16" (supersedes "1999 Mar 23") | ||
56 | standard BG DK I L L` | ||
57 | picture carrier 38.90 38.90 38.90 38.90 33.95 | ||
58 | colour 34.47 34.47 34.47 34.47 38.38 | ||
59 | sound 1 33.40 32.40 32.90 32.40 40.45 | ||
60 | sound 2 33.16 - - - - | ||
61 | NICAM 33.05 33.05 32.35 33.05 39.80 | ||
62 | */ | ||
63 | #define PHILIPS_SET_PAL_I 0x01 /* Bit 2 always zero !*/ | ||
64 | #define PHILIPS_SET_PAL_BGDK 0x09 | ||
65 | #define PHILIPS_SET_PAL_L2 0x0a | ||
66 | #define PHILIPS_SET_PAL_L 0x0b | ||
67 | |||
68 | /* system switching for Philips FI1216MF MK2 | ||
69 | from datasheet "1996 Jul 09", | ||
70 | standard BG L L' | ||
71 | picture carrier 38.90 38.90 33.95 | ||
72 | colour 34.47 34.37 38.38 | ||
73 | sound 1 33.40 32.40 40.45 | ||
74 | sound 2 33.16 - - | ||
75 | NICAM 33.05 33.05 39.80 | ||
76 | */ | ||
77 | #define PHILIPS_MF_SET_STD_BG 0x01 /* Bit 2 must be zero, Bit 3 is system output */ | ||
78 | #define PHILIPS_MF_SET_STD_L 0x03 /* Used on Secam France */ | ||
79 | #define PHILIPS_MF_SET_STD_LC 0x02 /* Used on SECAM L' */ | ||
80 | |||
81 | /* Control byte */ | ||
82 | |||
83 | #define TUNER_RATIO_MASK 0x06 /* Bit cb1:cb2 */ | ||
84 | #define TUNER_RATIO_SELECT_50 0x00 | ||
85 | #define TUNER_RATIO_SELECT_32 0x02 | ||
86 | #define TUNER_RATIO_SELECT_166 0x04 | ||
87 | #define TUNER_RATIO_SELECT_62 0x06 | ||
88 | |||
89 | #define TUNER_CHARGE_PUMP 0x40 /* Bit cb6 */ | ||
90 | |||
91 | /* Status byte */ | ||
92 | |||
93 | #define TUNER_POR 0x80 | ||
94 | #define TUNER_FL 0x40 | ||
95 | #define TUNER_MODE 0x38 | ||
96 | #define TUNER_AFC 0x07 | ||
97 | #define TUNER_SIGNAL 0x07 | ||
98 | #define TUNER_STEREO 0x10 | ||
99 | |||
100 | #define TUNER_PLL_LOCKED 0x40 | ||
101 | #define TUNER_STEREO_MK3 0x04 | ||
102 | |||
103 | static DEFINE_MUTEX(tuner_simple_list_mutex); | ||
104 | static LIST_HEAD(hybrid_tuner_instance_list); | ||
105 | |||
106 | struct tuner_simple_priv { | ||
107 | unsigned int nr; | ||
108 | u16 last_div; | ||
109 | |||
110 | struct tuner_i2c_props i2c_props; | ||
111 | struct list_head hybrid_tuner_instance_list; | ||
112 | |||
113 | unsigned int type; | ||
114 | struct tunertype *tun; | ||
115 | |||
116 | u32 frequency; | ||
117 | u32 bandwidth; | ||
118 | }; | ||
119 | |||
120 | /* ---------------------------------------------------------------------- */ | ||
121 | |||
122 | static int tuner_read_status(struct dvb_frontend *fe) | ||
123 | { | ||
124 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
125 | unsigned char byte; | ||
126 | |||
127 | if (1 != tuner_i2c_xfer_recv(&priv->i2c_props, &byte, 1)) | ||
128 | return 0; | ||
129 | |||
130 | return byte; | ||
131 | } | ||
132 | |||
133 | static inline int tuner_signal(const int status) | ||
134 | { | ||
135 | return (status & TUNER_SIGNAL) << 13; | ||
136 | } | ||
137 | |||
138 | static inline int tuner_stereo(const int type, const int status) | ||
139 | { | ||
140 | switch (type) { | ||
141 | case TUNER_PHILIPS_FM1216ME_MK3: | ||
142 | case TUNER_PHILIPS_FM1236_MK3: | ||
143 | case TUNER_PHILIPS_FM1256_IH3: | ||
144 | case TUNER_LG_NTSC_TAPE: | ||
145 | return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); | ||
146 | default: | ||
147 | return status & TUNER_STEREO; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | static inline int tuner_islocked(const int status) | ||
152 | { | ||
153 | return (status & TUNER_FL); | ||
154 | } | ||
155 | |||
156 | static inline int tuner_afcstatus(const int status) | ||
157 | { | ||
158 | return (status & TUNER_AFC) - 2; | ||
159 | } | ||
160 | |||
161 | |||
162 | static int simple_get_status(struct dvb_frontend *fe, u32 *status) | ||
163 | { | ||
164 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
165 | int tuner_status; | ||
166 | |||
167 | if (priv->i2c_props.adap == NULL) | ||
168 | return -EINVAL; | ||
169 | |||
170 | tuner_status = tuner_read_status(fe); | ||
171 | |||
172 | *status = 0; | ||
173 | |||
174 | if (tuner_islocked(tuner_status)) | ||
175 | *status = TUNER_STATUS_LOCKED; | ||
176 | if (tuner_stereo(priv->type, tuner_status)) | ||
177 | *status |= TUNER_STATUS_STEREO; | ||
178 | |||
179 | tuner_dbg("AFC Status: %d\n", tuner_afcstatus(tuner_status)); | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength) | ||
185 | { | ||
186 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
187 | int signal; | ||
188 | |||
189 | if (priv->i2c_props.adap == NULL) | ||
190 | return -EINVAL; | ||
191 | |||
192 | signal = tuner_signal(tuner_read_status(fe)); | ||
193 | |||
194 | *strength = signal; | ||
195 | |||
196 | tuner_dbg("Signal strength: %d\n", signal); | ||
197 | |||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | /* ---------------------------------------------------------------------- */ | ||
202 | |||
203 | static inline char *tuner_param_name(enum param_type type) | ||
204 | { | ||
205 | char *name; | ||
206 | |||
207 | switch (type) { | ||
208 | case TUNER_PARAM_TYPE_RADIO: | ||
209 | name = "radio"; | ||
210 | break; | ||
211 | case TUNER_PARAM_TYPE_PAL: | ||
212 | name = "pal"; | ||
213 | break; | ||
214 | case TUNER_PARAM_TYPE_SECAM: | ||
215 | name = "secam"; | ||
216 | break; | ||
217 | case TUNER_PARAM_TYPE_NTSC: | ||
218 | name = "ntsc"; | ||
219 | break; | ||
220 | case TUNER_PARAM_TYPE_DIGITAL: | ||
221 | name = "digital"; | ||
222 | break; | ||
223 | default: | ||
224 | name = "unknown"; | ||
225 | break; | ||
226 | } | ||
227 | return name; | ||
228 | } | ||
229 | |||
230 | static struct tuner_params *simple_tuner_params(struct dvb_frontend *fe, | ||
231 | enum param_type desired_type) | ||
232 | { | ||
233 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
234 | struct tunertype *tun = priv->tun; | ||
235 | int i; | ||
236 | |||
237 | for (i = 0; i < tun->count; i++) | ||
238 | if (desired_type == tun->params[i].type) | ||
239 | break; | ||
240 | |||
241 | /* use default tuner params if desired_type not available */ | ||
242 | if (i == tun->count) { | ||
243 | tuner_dbg("desired params (%s) undefined for tuner %d\n", | ||
244 | tuner_param_name(desired_type), priv->type); | ||
245 | i = 0; | ||
246 | } | ||
247 | |||
248 | tuner_dbg("using tuner params #%d (%s)\n", i, | ||
249 | tuner_param_name(tun->params[i].type)); | ||
250 | |||
251 | return &tun->params[i]; | ||
252 | } | ||
253 | |||
254 | static int simple_config_lookup(struct dvb_frontend *fe, | ||
255 | struct tuner_params *t_params, | ||
256 | int *frequency, u8 *config, u8 *cb) | ||
257 | { | ||
258 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
259 | int i; | ||
260 | |||
261 | for (i = 0; i < t_params->count; i++) { | ||
262 | if (*frequency > t_params->ranges[i].limit) | ||
263 | continue; | ||
264 | break; | ||
265 | } | ||
266 | if (i == t_params->count) { | ||
267 | tuner_dbg("frequency out of range (%d > %d)\n", | ||
268 | *frequency, t_params->ranges[i - 1].limit); | ||
269 | *frequency = t_params->ranges[--i].limit; | ||
270 | } | ||
271 | *config = t_params->ranges[i].config; | ||
272 | *cb = t_params->ranges[i].cb; | ||
273 | |||
274 | tuner_dbg("freq = %d.%02d (%d), range = %d, " | ||
275 | "config = 0x%02x, cb = 0x%02x\n", | ||
276 | *frequency / 16, *frequency % 16 * 100 / 16, *frequency, | ||
277 | i, *config, *cb); | ||
278 | |||
279 | return i; | ||
280 | } | ||
281 | |||
282 | /* ---------------------------------------------------------------------- */ | ||
283 | |||
284 | static void simple_set_rf_input(struct dvb_frontend *fe, | ||
285 | u8 *config, u8 *cb, unsigned int rf) | ||
286 | { | ||
287 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
288 | |||
289 | switch (priv->type) { | ||
290 | case TUNER_PHILIPS_TUV1236D: | ||
291 | switch (rf) { | ||
292 | case 1: | ||
293 | *cb |= 0x08; | ||
294 | break; | ||
295 | default: | ||
296 | *cb &= ~0x08; | ||
297 | break; | ||
298 | } | ||
299 | break; | ||
300 | case TUNER_PHILIPS_FCV1236D: | ||
301 | switch (rf) { | ||
302 | case 1: | ||
303 | *cb |= 0x01; | ||
304 | break; | ||
305 | default: | ||
306 | *cb &= ~0x01; | ||
307 | break; | ||
308 | } | ||
309 | break; | ||
310 | default: | ||
311 | break; | ||
312 | } | ||
313 | } | ||
314 | |||
315 | static int simple_std_setup(struct dvb_frontend *fe, | ||
316 | struct analog_parameters *params, | ||
317 | u8 *config, u8 *cb) | ||
318 | { | ||
319 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
320 | u8 tuneraddr; | ||
321 | int rc; | ||
322 | |||
323 | /* tv norm specific stuff for multi-norm tuners */ | ||
324 | switch (priv->type) { | ||
325 | case TUNER_PHILIPS_SECAM: /* FI1216MF */ | ||
326 | /* 0x01 -> ??? no change ??? */ | ||
327 | /* 0x02 -> PAL BDGHI / SECAM L */ | ||
328 | /* 0x04 -> ??? PAL others / SECAM others ??? */ | ||
329 | *cb &= ~0x03; | ||
330 | if (params->std & V4L2_STD_SECAM_L) | ||
331 | /* also valid for V4L2_STD_SECAM */ | ||
332 | *cb |= PHILIPS_MF_SET_STD_L; | ||
333 | else if (params->std & V4L2_STD_SECAM_LC) | ||
334 | *cb |= PHILIPS_MF_SET_STD_LC; | ||
335 | else /* V4L2_STD_B|V4L2_STD_GH */ | ||
336 | *cb |= PHILIPS_MF_SET_STD_BG; | ||
337 | break; | ||
338 | |||
339 | case TUNER_TEMIC_4046FM5: | ||
340 | *cb &= ~0x0f; | ||
341 | |||
342 | if (params->std & V4L2_STD_PAL_BG) { | ||
343 | *cb |= TEMIC_SET_PAL_BG; | ||
344 | |||
345 | } else if (params->std & V4L2_STD_PAL_I) { | ||
346 | *cb |= TEMIC_SET_PAL_I; | ||
347 | |||
348 | } else if (params->std & V4L2_STD_PAL_DK) { | ||
349 | *cb |= TEMIC_SET_PAL_DK; | ||
350 | |||
351 | } else if (params->std & V4L2_STD_SECAM_L) { | ||
352 | *cb |= TEMIC_SET_PAL_L; | ||
353 | |||
354 | } | ||
355 | break; | ||
356 | |||
357 | case TUNER_PHILIPS_FQ1216ME: | ||
358 | *cb &= ~0x0f; | ||
359 | |||
360 | if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) { | ||
361 | *cb |= PHILIPS_SET_PAL_BGDK; | ||
362 | |||
363 | } else if (params->std & V4L2_STD_PAL_I) { | ||
364 | *cb |= PHILIPS_SET_PAL_I; | ||
365 | |||
366 | } else if (params->std & V4L2_STD_SECAM_L) { | ||
367 | *cb |= PHILIPS_SET_PAL_L; | ||
368 | |||
369 | } | ||
370 | break; | ||
371 | |||
372 | case TUNER_PHILIPS_FCV1236D: | ||
373 | /* 0x00 -> ATSC antenna input 1 */ | ||
374 | /* 0x01 -> ATSC antenna input 2 */ | ||
375 | /* 0x02 -> NTSC antenna input 1 */ | ||
376 | /* 0x03 -> NTSC antenna input 2 */ | ||
377 | *cb &= ~0x03; | ||
378 | if (!(params->std & V4L2_STD_ATSC)) | ||
379 | *cb |= 2; | ||
380 | break; | ||
381 | |||
382 | case TUNER_MICROTUNE_4042FI5: | ||
383 | /* Set the charge pump for fast tuning */ | ||
384 | *config |= TUNER_CHARGE_PUMP; | ||
385 | break; | ||
386 | |||
387 | case TUNER_PHILIPS_TUV1236D: | ||
388 | { | ||
389 | /* 0x40 -> ATSC antenna input 1 */ | ||
390 | /* 0x48 -> ATSC antenna input 2 */ | ||
391 | /* 0x00 -> NTSC antenna input 1 */ | ||
392 | /* 0x08 -> NTSC antenna input 2 */ | ||
393 | u8 buffer[4] = { 0x14, 0x00, 0x17, 0x00}; | ||
394 | *cb &= ~0x40; | ||
395 | if (params->std & V4L2_STD_ATSC) { | ||
396 | *cb |= 0x40; | ||
397 | buffer[1] = 0x04; | ||
398 | } | ||
399 | /* set to the correct mode (analog or digital) */ | ||
400 | tuneraddr = priv->i2c_props.addr; | ||
401 | priv->i2c_props.addr = 0x0a; | ||
402 | rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[0], 2); | ||
403 | if (2 != rc) | ||
404 | tuner_warn("i2c i/o error: rc == %d " | ||
405 | "(should be 2)\n", rc); | ||
406 | rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[2], 2); | ||
407 | if (2 != rc) | ||
408 | tuner_warn("i2c i/o error: rc == %d " | ||
409 | "(should be 2)\n", rc); | ||
410 | priv->i2c_props.addr = tuneraddr; | ||
411 | break; | ||
412 | } | ||
413 | } | ||
414 | if (atv_input[priv->nr]) | ||
415 | simple_set_rf_input(fe, config, cb, atv_input[priv->nr]); | ||
416 | |||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer, | ||
421 | u16 div, u8 config, u8 cb) | ||
422 | { | ||
423 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
424 | int rc; | ||
425 | |||
426 | switch (priv->type) { | ||
427 | case TUNER_LG_TDVS_H06XF: | ||
428 | /* Set the Auxiliary Byte. */ | ||
429 | buffer[0] = buffer[2]; | ||
430 | buffer[0] &= ~0x20; | ||
431 | buffer[0] |= 0x18; | ||
432 | buffer[1] = 0x20; | ||
433 | tuner_dbg("tv 0x%02x 0x%02x\n", buffer[0], buffer[1]); | ||
434 | |||
435 | rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2); | ||
436 | if (2 != rc) | ||
437 | tuner_warn("i2c i/o error: rc == %d " | ||
438 | "(should be 2)\n", rc); | ||
439 | break; | ||
440 | case TUNER_MICROTUNE_4042FI5: | ||
441 | { | ||
442 | /* FIXME - this may also work for other tuners */ | ||
443 | unsigned long timeout = jiffies + msecs_to_jiffies(1); | ||
444 | u8 status_byte = 0; | ||
445 | |||
446 | /* Wait until the PLL locks */ | ||
447 | for (;;) { | ||
448 | if (time_after(jiffies, timeout)) | ||
449 | return 0; | ||
450 | rc = tuner_i2c_xfer_recv(&priv->i2c_props, | ||
451 | &status_byte, 1); | ||
452 | if (1 != rc) { | ||
453 | tuner_warn("i2c i/o read error: rc == %d " | ||
454 | "(should be 1)\n", rc); | ||
455 | break; | ||
456 | } | ||
457 | if (status_byte & TUNER_PLL_LOCKED) | ||
458 | break; | ||
459 | udelay(10); | ||
460 | } | ||
461 | |||
462 | /* Set the charge pump for optimized phase noise figure */ | ||
463 | config &= ~TUNER_CHARGE_PUMP; | ||
464 | buffer[0] = (div>>8) & 0x7f; | ||
465 | buffer[1] = div & 0xff; | ||
466 | buffer[2] = config; | ||
467 | buffer[3] = cb; | ||
468 | tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
469 | buffer[0], buffer[1], buffer[2], buffer[3]); | ||
470 | |||
471 | rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4); | ||
472 | if (4 != rc) | ||
473 | tuner_warn("i2c i/o error: rc == %d " | ||
474 | "(should be 4)\n", rc); | ||
475 | break; | ||
476 | } | ||
477 | } | ||
478 | |||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer) | ||
483 | { | ||
484 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
485 | |||
486 | switch (priv->type) { | ||
487 | case TUNER_TENA_9533_DI: | ||
488 | case TUNER_YMEC_TVF_5533MF: | ||
489 | tuner_dbg("This tuner doesn't have FM. " | ||
490 | "Most cards have a TEA5767 for FM\n"); | ||
491 | return 0; | ||
492 | case TUNER_PHILIPS_FM1216ME_MK3: | ||
493 | case TUNER_PHILIPS_FM1236_MK3: | ||
494 | case TUNER_PHILIPS_FMD1216ME_MK3: | ||
495 | case TUNER_LG_NTSC_TAPE: | ||
496 | case TUNER_PHILIPS_FM1256_IH3: | ||
497 | buffer[3] = 0x19; | ||
498 | break; | ||
499 | case TUNER_TNF_5335MF: | ||
500 | buffer[3] = 0x11; | ||
501 | break; | ||
502 | case TUNER_LG_PAL_FM: | ||
503 | buffer[3] = 0xa5; | ||
504 | break; | ||
505 | case TUNER_THOMSON_DTT761X: | ||
506 | buffer[3] = 0x39; | ||
507 | break; | ||
508 | case TUNER_MICROTUNE_4049FM5: | ||
509 | default: | ||
510 | buffer[3] = 0xa4; | ||
511 | break; | ||
512 | } | ||
513 | |||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | /* ---------------------------------------------------------------------- */ | ||
518 | |||
519 | static int simple_set_tv_freq(struct dvb_frontend *fe, | ||
520 | struct analog_parameters *params) | ||
521 | { | ||
522 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
523 | u8 config, cb; | ||
524 | u16 div; | ||
525 | struct tunertype *tun; | ||
526 | u8 buffer[4]; | ||
527 | int rc, IFPCoff, i; | ||
528 | enum param_type desired_type; | ||
529 | struct tuner_params *t_params; | ||
530 | |||
531 | tun = priv->tun; | ||
532 | |||
533 | /* IFPCoff = Video Intermediate Frequency - Vif: | ||
534 | 940 =16*58.75 NTSC/J (Japan) | ||
535 | 732 =16*45.75 M/N STD | ||
536 | 704 =16*44 ATSC (at DVB code) | ||
537 | 632 =16*39.50 I U.K. | ||
538 | 622.4=16*38.90 B/G D/K I, L STD | ||
539 | 592 =16*37.00 D China | ||
540 | 590 =16.36.875 B Australia | ||
541 | 543.2=16*33.95 L' STD | ||
542 | 171.2=16*10.70 FM Radio (at set_radio_freq) | ||
543 | */ | ||
544 | |||
545 | if (params->std == V4L2_STD_NTSC_M_JP) { | ||
546 | IFPCoff = 940; | ||
547 | desired_type = TUNER_PARAM_TYPE_NTSC; | ||
548 | } else if ((params->std & V4L2_STD_MN) && | ||
549 | !(params->std & ~V4L2_STD_MN)) { | ||
550 | IFPCoff = 732; | ||
551 | desired_type = TUNER_PARAM_TYPE_NTSC; | ||
552 | } else if (params->std == V4L2_STD_SECAM_LC) { | ||
553 | IFPCoff = 543; | ||
554 | desired_type = TUNER_PARAM_TYPE_SECAM; | ||
555 | } else { | ||
556 | IFPCoff = 623; | ||
557 | desired_type = TUNER_PARAM_TYPE_PAL; | ||
558 | } | ||
559 | |||
560 | t_params = simple_tuner_params(fe, desired_type); | ||
561 | |||
562 | i = simple_config_lookup(fe, t_params, ¶ms->frequency, | ||
563 | &config, &cb); | ||
564 | |||
565 | div = params->frequency + IFPCoff + offset; | ||
566 | |||
567 | tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, " | ||
568 | "Offset=%d.%02d MHz, div=%0d\n", | ||
569 | params->frequency / 16, params->frequency % 16 * 100 / 16, | ||
570 | IFPCoff / 16, IFPCoff % 16 * 100 / 16, | ||
571 | offset / 16, offset % 16 * 100 / 16, div); | ||
572 | |||
573 | /* tv norm specific stuff for multi-norm tuners */ | ||
574 | simple_std_setup(fe, params, &config, &cb); | ||
575 | |||
576 | if (t_params->cb_first_if_lower_freq && div < priv->last_div) { | ||
577 | buffer[0] = config; | ||
578 | buffer[1] = cb; | ||
579 | buffer[2] = (div>>8) & 0x7f; | ||
580 | buffer[3] = div & 0xff; | ||
581 | } else { | ||
582 | buffer[0] = (div>>8) & 0x7f; | ||
583 | buffer[1] = div & 0xff; | ||
584 | buffer[2] = config; | ||
585 | buffer[3] = cb; | ||
586 | } | ||
587 | priv->last_div = div; | ||
588 | if (t_params->has_tda9887) { | ||
589 | struct v4l2_priv_tun_config tda9887_cfg; | ||
590 | int config = 0; | ||
591 | int is_secam_l = (params->std & (V4L2_STD_SECAM_L | | ||
592 | V4L2_STD_SECAM_LC)) && | ||
593 | !(params->std & ~(V4L2_STD_SECAM_L | | ||
594 | V4L2_STD_SECAM_LC)); | ||
595 | |||
596 | tda9887_cfg.tuner = TUNER_TDA9887; | ||
597 | tda9887_cfg.priv = &config; | ||
598 | |||
599 | if (params->std == V4L2_STD_SECAM_LC) { | ||
600 | if (t_params->port1_active ^ t_params->port1_invert_for_secam_lc) | ||
601 | config |= TDA9887_PORT1_ACTIVE; | ||
602 | if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc) | ||
603 | config |= TDA9887_PORT2_ACTIVE; | ||
604 | } else { | ||
605 | if (t_params->port1_active) | ||
606 | config |= TDA9887_PORT1_ACTIVE; | ||
607 | if (t_params->port2_active) | ||
608 | config |= TDA9887_PORT2_ACTIVE; | ||
609 | } | ||
610 | if (t_params->intercarrier_mode) | ||
611 | config |= TDA9887_INTERCARRIER; | ||
612 | if (is_secam_l) { | ||
613 | if (i == 0 && t_params->default_top_secam_low) | ||
614 | config |= TDA9887_TOP(t_params->default_top_secam_low); | ||
615 | else if (i == 1 && t_params->default_top_secam_mid) | ||
616 | config |= TDA9887_TOP(t_params->default_top_secam_mid); | ||
617 | else if (t_params->default_top_secam_high) | ||
618 | config |= TDA9887_TOP(t_params->default_top_secam_high); | ||
619 | } else { | ||
620 | if (i == 0 && t_params->default_top_low) | ||
621 | config |= TDA9887_TOP(t_params->default_top_low); | ||
622 | else if (i == 1 && t_params->default_top_mid) | ||
623 | config |= TDA9887_TOP(t_params->default_top_mid); | ||
624 | else if (t_params->default_top_high) | ||
625 | config |= TDA9887_TOP(t_params->default_top_high); | ||
626 | } | ||
627 | if (t_params->default_pll_gating_18) | ||
628 | config |= TDA9887_GATING_18; | ||
629 | i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG, | ||
630 | &tda9887_cfg); | ||
631 | } | ||
632 | tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
633 | buffer[0], buffer[1], buffer[2], buffer[3]); | ||
634 | |||
635 | rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4); | ||
636 | if (4 != rc) | ||
637 | tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc); | ||
638 | |||
639 | simple_post_tune(fe, &buffer[0], div, config, cb); | ||
640 | |||
641 | return 0; | ||
642 | } | ||
643 | |||
644 | static int simple_set_radio_freq(struct dvb_frontend *fe, | ||
645 | struct analog_parameters *params) | ||
646 | { | ||
647 | struct tunertype *tun; | ||
648 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
649 | u8 buffer[4]; | ||
650 | u16 div; | ||
651 | int rc, j; | ||
652 | struct tuner_params *t_params; | ||
653 | unsigned int freq = params->frequency; | ||
654 | |||
655 | tun = priv->tun; | ||
656 | |||
657 | for (j = tun->count-1; j > 0; j--) | ||
658 | if (tun->params[j].type == TUNER_PARAM_TYPE_RADIO) | ||
659 | break; | ||
660 | /* default t_params (j=0) will be used if desired type wasn't found */ | ||
661 | t_params = &tun->params[j]; | ||
662 | |||
663 | /* Select Radio 1st IF used */ | ||
664 | switch (t_params->radio_if) { | ||
665 | case 0: /* 10.7 MHz */ | ||
666 | freq += (unsigned int)(10.7*16000); | ||
667 | break; | ||
668 | case 1: /* 33.3 MHz */ | ||
669 | freq += (unsigned int)(33.3*16000); | ||
670 | break; | ||
671 | case 2: /* 41.3 MHz */ | ||
672 | freq += (unsigned int)(41.3*16000); | ||
673 | break; | ||
674 | default: | ||
675 | tuner_warn("Unsupported radio_if value %d\n", | ||
676 | t_params->radio_if); | ||
677 | return 0; | ||
678 | } | ||
679 | |||
680 | /* Bandswitch byte */ | ||
681 | simple_radio_bandswitch(fe, &buffer[0]); | ||
682 | |||
683 | buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) | | ||
684 | TUNER_RATIO_SELECT_50; /* 50 kHz step */ | ||
685 | |||
686 | /* Convert from 1/16 kHz V4L steps to 1/20 MHz (=50 kHz) PLL steps | ||
687 | freq * (1 Mhz / 16000 V4L steps) * (20 PLL steps / 1 MHz) = | ||
688 | freq * (1/800) */ | ||
689 | div = (freq + 400) / 800; | ||
690 | |||
691 | if (t_params->cb_first_if_lower_freq && div < priv->last_div) { | ||
692 | buffer[0] = buffer[2]; | ||
693 | buffer[1] = buffer[3]; | ||
694 | buffer[2] = (div>>8) & 0x7f; | ||
695 | buffer[3] = div & 0xff; | ||
696 | } else { | ||
697 | buffer[0] = (div>>8) & 0x7f; | ||
698 | buffer[1] = div & 0xff; | ||
699 | } | ||
700 | |||
701 | tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
702 | buffer[0], buffer[1], buffer[2], buffer[3]); | ||
703 | priv->last_div = div; | ||
704 | |||
705 | if (t_params->has_tda9887) { | ||
706 | int config = 0; | ||
707 | struct v4l2_priv_tun_config tda9887_cfg; | ||
708 | |||
709 | tda9887_cfg.tuner = TUNER_TDA9887; | ||
710 | tda9887_cfg.priv = &config; | ||
711 | |||
712 | if (t_params->port1_active && | ||
713 | !t_params->port1_fm_high_sensitivity) | ||
714 | config |= TDA9887_PORT1_ACTIVE; | ||
715 | if (t_params->port2_active && | ||
716 | !t_params->port2_fm_high_sensitivity) | ||
717 | config |= TDA9887_PORT2_ACTIVE; | ||
718 | if (t_params->intercarrier_mode) | ||
719 | config |= TDA9887_INTERCARRIER; | ||
720 | /* if (t_params->port1_set_for_fm_mono) | ||
721 | config &= ~TDA9887_PORT1_ACTIVE;*/ | ||
722 | if (t_params->fm_gain_normal) | ||
723 | config |= TDA9887_GAIN_NORMAL; | ||
724 | if (t_params->radio_if == 2) | ||
725 | config |= TDA9887_RIF_41_3; | ||
726 | i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG, | ||
727 | &tda9887_cfg); | ||
728 | } | ||
729 | rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4); | ||
730 | if (4 != rc) | ||
731 | tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc); | ||
732 | |||
733 | return 0; | ||
734 | } | ||
735 | |||
736 | static int simple_set_params(struct dvb_frontend *fe, | ||
737 | struct analog_parameters *params) | ||
738 | { | ||
739 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
740 | int ret = -EINVAL; | ||
741 | |||
742 | if (priv->i2c_props.adap == NULL) | ||
743 | return -EINVAL; | ||
744 | |||
745 | switch (params->mode) { | ||
746 | case V4L2_TUNER_RADIO: | ||
747 | ret = simple_set_radio_freq(fe, params); | ||
748 | priv->frequency = params->frequency * 125 / 2; | ||
749 | break; | ||
750 | case V4L2_TUNER_ANALOG_TV: | ||
751 | case V4L2_TUNER_DIGITAL_TV: | ||
752 | ret = simple_set_tv_freq(fe, params); | ||
753 | priv->frequency = params->frequency * 62500; | ||
754 | break; | ||
755 | } | ||
756 | priv->bandwidth = 0; | ||
757 | |||
758 | return ret; | ||
759 | } | ||
760 | |||
761 | static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf, | ||
762 | const struct dvb_frontend_parameters *params) | ||
763 | { | ||
764 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
765 | |||
766 | switch (priv->type) { | ||
767 | case TUNER_PHILIPS_FMD1216ME_MK3: | ||
768 | if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ && | ||
769 | params->frequency >= 158870000) | ||
770 | buf[3] |= 0x08; | ||
771 | break; | ||
772 | case TUNER_PHILIPS_TD1316: | ||
773 | /* determine band */ | ||
774 | buf[3] |= (params->frequency < 161000000) ? 1 : | ||
775 | (params->frequency < 444000000) ? 2 : 4; | ||
776 | |||
777 | /* setup PLL filter */ | ||
778 | if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) | ||
779 | buf[3] |= 1 << 3; | ||
780 | break; | ||
781 | case TUNER_PHILIPS_TUV1236D: | ||
782 | case TUNER_PHILIPS_FCV1236D: | ||
783 | { | ||
784 | unsigned int new_rf; | ||
785 | |||
786 | if (dtv_input[priv->nr]) | ||
787 | new_rf = dtv_input[priv->nr]; | ||
788 | else | ||
789 | switch (params->u.vsb.modulation) { | ||
790 | case QAM_64: | ||
791 | case QAM_256: | ||
792 | new_rf = 1; | ||
793 | break; | ||
794 | case VSB_8: | ||
795 | default: | ||
796 | new_rf = 0; | ||
797 | break; | ||
798 | } | ||
799 | simple_set_rf_input(fe, &buf[2], &buf[3], new_rf); | ||
800 | break; | ||
801 | } | ||
802 | default: | ||
803 | break; | ||
804 | } | ||
805 | } | ||
806 | |||
807 | static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf, | ||
808 | const struct dvb_frontend_parameters *params) | ||
809 | { | ||
810 | /* This function returns the tuned frequency on success, 0 on error */ | ||
811 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
812 | struct tunertype *tun = priv->tun; | ||
813 | static struct tuner_params *t_params; | ||
814 | u8 config, cb; | ||
815 | u32 div; | ||
816 | int ret, frequency = params->frequency / 62500; | ||
817 | |||
818 | t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL); | ||
819 | ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb); | ||
820 | if (ret < 0) | ||
821 | return 0; /* failure */ | ||
822 | |||
823 | div = ((frequency + t_params->iffreq) * 62500 + offset + | ||
824 | tun->stepsize/2) / tun->stepsize; | ||
825 | |||
826 | buf[0] = div >> 8; | ||
827 | buf[1] = div & 0xff; | ||
828 | buf[2] = config; | ||
829 | buf[3] = cb; | ||
830 | |||
831 | simple_set_dvb(fe, buf, params); | ||
832 | |||
833 | tuner_dbg("%s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n", | ||
834 | tun->name, div, buf[0], buf[1], buf[2], buf[3]); | ||
835 | |||
836 | /* calculate the frequency we set it to */ | ||
837 | return (div * tun->stepsize) - t_params->iffreq; | ||
838 | } | ||
839 | |||
840 | static int simple_dvb_calc_regs(struct dvb_frontend *fe, | ||
841 | struct dvb_frontend_parameters *params, | ||
842 | u8 *buf, int buf_len) | ||
843 | { | ||
844 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
845 | u32 frequency; | ||
846 | |||
847 | if (buf_len < 5) | ||
848 | return -EINVAL; | ||
849 | |||
850 | frequency = simple_dvb_configure(fe, buf+1, params); | ||
851 | if (frequency == 0) | ||
852 | return -EINVAL; | ||
853 | |||
854 | buf[0] = priv->i2c_props.addr; | ||
855 | |||
856 | priv->frequency = frequency; | ||
857 | priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? | ||
858 | params->u.ofdm.bandwidth : 0; | ||
859 | |||
860 | return 5; | ||
861 | } | ||
862 | |||
863 | static int simple_dvb_set_params(struct dvb_frontend *fe, | ||
864 | struct dvb_frontend_parameters *params) | ||
865 | { | ||
866 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
867 | u32 prev_freq, prev_bw; | ||
868 | int ret; | ||
869 | u8 buf[5]; | ||
870 | |||
871 | if (priv->i2c_props.adap == NULL) | ||
872 | return -EINVAL; | ||
873 | |||
874 | prev_freq = priv->frequency; | ||
875 | prev_bw = priv->bandwidth; | ||
876 | |||
877 | ret = simple_dvb_calc_regs(fe, params, buf, 5); | ||
878 | if (ret != 5) | ||
879 | goto fail; | ||
880 | |||
881 | /* put analog demod in standby when tuning digital */ | ||
882 | if (fe->ops.analog_ops.standby) | ||
883 | fe->ops.analog_ops.standby(fe); | ||
884 | |||
885 | if (fe->ops.i2c_gate_ctrl) | ||
886 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
887 | |||
888 | /* buf[0] contains the i2c address, but * | ||
889 | * we already have it in i2c_props.addr */ | ||
890 | ret = tuner_i2c_xfer_send(&priv->i2c_props, buf+1, 4); | ||
891 | if (ret != 4) | ||
892 | goto fail; | ||
893 | |||
894 | return 0; | ||
895 | fail: | ||
896 | /* calc_regs sets frequency and bandwidth. if we failed, unset them */ | ||
897 | priv->frequency = prev_freq; | ||
898 | priv->bandwidth = prev_bw; | ||
899 | |||
900 | return ret; | ||
901 | } | ||
902 | |||
903 | static int simple_init(struct dvb_frontend *fe) | ||
904 | { | ||
905 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
906 | |||
907 | if (priv->i2c_props.adap == NULL) | ||
908 | return -EINVAL; | ||
909 | |||
910 | if (priv->tun->initdata) { | ||
911 | int ret; | ||
912 | |||
913 | if (fe->ops.i2c_gate_ctrl) | ||
914 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
915 | |||
916 | ret = tuner_i2c_xfer_send(&priv->i2c_props, | ||
917 | priv->tun->initdata + 1, | ||
918 | priv->tun->initdata[0]); | ||
919 | if (ret != priv->tun->initdata[0]) | ||
920 | return ret; | ||
921 | } | ||
922 | |||
923 | return 0; | ||
924 | } | ||
925 | |||
926 | static int simple_sleep(struct dvb_frontend *fe) | ||
927 | { | ||
928 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
929 | |||
930 | if (priv->i2c_props.adap == NULL) | ||
931 | return -EINVAL; | ||
932 | |||
933 | if (priv->tun->sleepdata) { | ||
934 | int ret; | ||
935 | |||
936 | if (fe->ops.i2c_gate_ctrl) | ||
937 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
938 | |||
939 | ret = tuner_i2c_xfer_send(&priv->i2c_props, | ||
940 | priv->tun->sleepdata + 1, | ||
941 | priv->tun->sleepdata[0]); | ||
942 | if (ret != priv->tun->sleepdata[0]) | ||
943 | return ret; | ||
944 | } | ||
945 | |||
946 | return 0; | ||
947 | } | ||
948 | |||
949 | static int simple_release(struct dvb_frontend *fe) | ||
950 | { | ||
951 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
952 | |||
953 | mutex_lock(&tuner_simple_list_mutex); | ||
954 | |||
955 | if (priv) | ||
956 | hybrid_tuner_release_state(priv); | ||
957 | |||
958 | mutex_unlock(&tuner_simple_list_mutex); | ||
959 | |||
960 | fe->tuner_priv = NULL; | ||
961 | |||
962 | return 0; | ||
963 | } | ||
964 | |||
965 | static int simple_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
966 | { | ||
967 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
968 | *frequency = priv->frequency; | ||
969 | return 0; | ||
970 | } | ||
971 | |||
972 | static int simple_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) | ||
973 | { | ||
974 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
975 | *bandwidth = priv->bandwidth; | ||
976 | return 0; | ||
977 | } | ||
978 | |||
979 | static struct dvb_tuner_ops simple_tuner_ops = { | ||
980 | .init = simple_init, | ||
981 | .sleep = simple_sleep, | ||
982 | .set_analog_params = simple_set_params, | ||
983 | .set_params = simple_dvb_set_params, | ||
984 | .calc_regs = simple_dvb_calc_regs, | ||
985 | .release = simple_release, | ||
986 | .get_frequency = simple_get_frequency, | ||
987 | .get_bandwidth = simple_get_bandwidth, | ||
988 | .get_status = simple_get_status, | ||
989 | .get_rf_strength = simple_get_rf_strength, | ||
990 | }; | ||
991 | |||
992 | struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, | ||
993 | struct i2c_adapter *i2c_adap, | ||
994 | u8 i2c_addr, | ||
995 | unsigned int type) | ||
996 | { | ||
997 | struct tuner_simple_priv *priv = NULL; | ||
998 | int instance; | ||
999 | |||
1000 | if (type >= tuner_count) { | ||
1001 | printk(KERN_WARNING "%s: invalid tuner type: %d (max: %d)\n", | ||
1002 | __func__, type, tuner_count-1); | ||
1003 | return NULL; | ||
1004 | } | ||
1005 | |||
1006 | /* If i2c_adap is set, check that the tuner is at the correct address. | ||
1007 | * Otherwise, if i2c_adap is NULL, the tuner will be programmed directly | ||
1008 | * by the digital demod via calc_regs. | ||
1009 | */ | ||
1010 | if (i2c_adap != NULL) { | ||
1011 | u8 b[1]; | ||
1012 | struct i2c_msg msg = { | ||
1013 | .addr = i2c_addr, .flags = I2C_M_RD, | ||
1014 | .buf = b, .len = 1, | ||
1015 | }; | ||
1016 | |||
1017 | if (fe->ops.i2c_gate_ctrl) | ||
1018 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
1019 | |||
1020 | if (1 != i2c_transfer(i2c_adap, &msg, 1)) | ||
1021 | tuner_warn("unable to probe %s, proceeding anyway.", | ||
1022 | tuners[type].name); | ||
1023 | |||
1024 | if (fe->ops.i2c_gate_ctrl) | ||
1025 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
1026 | } | ||
1027 | |||
1028 | mutex_lock(&tuner_simple_list_mutex); | ||
1029 | |||
1030 | instance = hybrid_tuner_request_state(struct tuner_simple_priv, priv, | ||
1031 | hybrid_tuner_instance_list, | ||
1032 | i2c_adap, i2c_addr, | ||
1033 | "tuner-simple"); | ||
1034 | switch (instance) { | ||
1035 | case 0: | ||
1036 | mutex_unlock(&tuner_simple_list_mutex); | ||
1037 | return NULL; | ||
1038 | break; | ||
1039 | case 1: | ||
1040 | fe->tuner_priv = priv; | ||
1041 | |||
1042 | priv->type = type; | ||
1043 | priv->tun = &tuners[type]; | ||
1044 | priv->nr = simple_devcount++; | ||
1045 | break; | ||
1046 | default: | ||
1047 | fe->tuner_priv = priv; | ||
1048 | break; | ||
1049 | } | ||
1050 | |||
1051 | mutex_unlock(&tuner_simple_list_mutex); | ||
1052 | |||
1053 | memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, | ||
1054 | sizeof(struct dvb_tuner_ops)); | ||
1055 | |||
1056 | tuner_info("type set to %d (%s)\n", type, priv->tun->name); | ||
1057 | |||
1058 | if ((debug) || ((atv_input[priv->nr] > 0) || | ||
1059 | (dtv_input[priv->nr] > 0))) { | ||
1060 | if (0 == atv_input[priv->nr]) | ||
1061 | tuner_info("tuner %d atv rf input will be " | ||
1062 | "autoselected\n", priv->nr); | ||
1063 | else | ||
1064 | tuner_info("tuner %d atv rf input will be " | ||
1065 | "set to input %d (insmod option)\n", | ||
1066 | priv->nr, atv_input[priv->nr]); | ||
1067 | if (0 == dtv_input[priv->nr]) | ||
1068 | tuner_info("tuner %d dtv rf input will be " | ||
1069 | "autoselected\n", priv->nr); | ||
1070 | else | ||
1071 | tuner_info("tuner %d dtv rf input will be " | ||
1072 | "set to input %d (insmod option)\n", | ||
1073 | priv->nr, dtv_input[priv->nr]); | ||
1074 | } | ||
1075 | |||
1076 | strlcpy(fe->ops.tuner_ops.info.name, priv->tun->name, | ||
1077 | sizeof(fe->ops.tuner_ops.info.name)); | ||
1078 | |||
1079 | return fe; | ||
1080 | } | ||
1081 | EXPORT_SYMBOL_GPL(simple_tuner_attach); | ||
1082 | |||
1083 | MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver"); | ||
1084 | MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); | ||
1085 | MODULE_LICENSE("GPL"); | ||
1086 | |||
1087 | /* | ||
1088 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
1089 | * --------------------------------------------------------------------------- | ||
1090 | * Local variables: | ||
1091 | * c-basic-offset: 8 | ||
1092 | * End: | ||
1093 | */ | ||
diff --git a/drivers/media/common/tuners/tuner-simple.h b/drivers/media/common/tuners/tuner-simple.h new file mode 100644 index 000000000000..e46cf0121e03 --- /dev/null +++ b/drivers/media/common/tuners/tuner-simple.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | This program is free software; you can redistribute it and/or modify | ||
3 | it under the terms of the GNU General Public License as published by | ||
4 | the Free Software Foundation; either version 2 of the License, or | ||
5 | (at your option) any later version. | ||
6 | |||
7 | This program is distributed in the hope that it will be useful, | ||
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | GNU General Public License for more details. | ||
11 | |||
12 | You should have received a copy of the GNU General Public License | ||
13 | along with this program; if not, write to the Free Software | ||
14 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
15 | */ | ||
16 | |||
17 | #ifndef __TUNER_SIMPLE_H__ | ||
18 | #define __TUNER_SIMPLE_H__ | ||
19 | |||
20 | #include <linux/i2c.h> | ||
21 | #include "dvb_frontend.h" | ||
22 | |||
23 | #if defined(CONFIG_TUNER_SIMPLE) || (defined(CONFIG_TUNER_SIMPLE_MODULE) && defined(MODULE)) | ||
24 | extern struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, | ||
25 | struct i2c_adapter *i2c_adap, | ||
26 | u8 i2c_addr, | ||
27 | unsigned int type); | ||
28 | #else | ||
29 | static inline struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, | ||
30 | struct i2c_adapter *i2c_adap, | ||
31 | u8 i2c_addr, | ||
32 | unsigned int type) | ||
33 | { | ||
34 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
35 | return NULL; | ||
36 | } | ||
37 | #endif | ||
38 | |||
39 | #endif /* __TUNER_SIMPLE_H__ */ | ||
diff --git a/drivers/media/common/tuners/tuner-types.c b/drivers/media/common/tuners/tuner-types.c new file mode 100644 index 000000000000..10dddca8b5d1 --- /dev/null +++ b/drivers/media/common/tuners/tuner-types.c | |||
@@ -0,0 +1,1652 @@ | |||
1 | /* | ||
2 | * | ||
3 | * i2c tv tuner chip device type database. | ||
4 | * | ||
5 | */ | ||
6 | |||
7 | #include <linux/i2c.h> | ||
8 | #include <media/tuner.h> | ||
9 | #include <media/tuner-types.h> | ||
10 | |||
11 | /* ---------------------------------------------------------------------- */ | ||
12 | |||
13 | /* | ||
14 | * The floats in the tuner struct are computed at compile time | ||
15 | * by gcc and cast back to integers. Thus we don't violate the | ||
16 | * "no float in kernel" rule. | ||
17 | * | ||
18 | * A tuner_range may be referenced by multiple tuner_params structs. | ||
19 | * There are many duplicates in here. Reusing tuner_range structs, | ||
20 | * rather than defining new ones for each tuner, will cut down on | ||
21 | * memory usage, and is preferred when possible. | ||
22 | * | ||
23 | * Each tuner_params array may contain one or more elements, one | ||
24 | * for each video standard. | ||
25 | * | ||
26 | * FIXME: tuner_params struct contains an element, tda988x. We must | ||
27 | * set this for all tuners that contain a tda988x chip, and then we | ||
28 | * can remove this setting from the various card structs. | ||
29 | * | ||
30 | * FIXME: Right now, all tuners are using the first tuner_params[] | ||
31 | * array element for analog mode. In the future, we will be merging | ||
32 | * similar tuner definitions together, such that each tuner definition | ||
33 | * will have a tuner_params struct for each available video standard. | ||
34 | * At that point, the tuner_params[] array element will be chosen | ||
35 | * based on the video standard in use. | ||
36 | */ | ||
37 | |||
38 | /* The following was taken from dvb-pll.c: */ | ||
39 | |||
40 | /* Set AGC TOP value to 103 dBuV: | ||
41 | * 0x80 = Control Byte | ||
42 | * 0x40 = 250 uA charge pump (irrelevant) | ||
43 | * 0x18 = Aux Byte to follow | ||
44 | * 0x06 = 64.5 kHz divider (irrelevant) | ||
45 | * 0x01 = Disable Vt (aka sleep) | ||
46 | * | ||
47 | * 0x00 = AGC Time constant 2s Iagc = 300 nA (vs 0x80 = 9 nA) | ||
48 | * 0x50 = AGC Take over point = 103 dBuV | ||
49 | */ | ||
50 | static u8 tua603x_agc103[] = { 2, 0x80|0x40|0x18|0x06|0x01, 0x00|0x50 }; | ||
51 | |||
52 | /* 0x04 = 166.67 kHz divider | ||
53 | * | ||
54 | * 0x80 = AGC Time constant 50ms Iagc = 9 uA | ||
55 | * 0x20 = AGC Take over point = 112 dBuV | ||
56 | */ | ||
57 | static u8 tua603x_agc112[] = { 2, 0x80|0x40|0x18|0x04|0x01, 0x80|0x20 }; | ||
58 | |||
59 | /* 0-9 */ | ||
60 | /* ------------ TUNER_TEMIC_PAL - TEMIC PAL ------------ */ | ||
61 | |||
62 | static struct tuner_range tuner_temic_pal_ranges[] = { | ||
63 | { 16 * 140.25 /*MHz*/, 0x8e, 0x02, }, | ||
64 | { 16 * 463.25 /*MHz*/, 0x8e, 0x04, }, | ||
65 | { 16 * 999.99 , 0x8e, 0x01, }, | ||
66 | }; | ||
67 | |||
68 | static struct tuner_params tuner_temic_pal_params[] = { | ||
69 | { | ||
70 | .type = TUNER_PARAM_TYPE_PAL, | ||
71 | .ranges = tuner_temic_pal_ranges, | ||
72 | .count = ARRAY_SIZE(tuner_temic_pal_ranges), | ||
73 | }, | ||
74 | }; | ||
75 | |||
76 | /* ------------ TUNER_PHILIPS_PAL_I - Philips PAL_I ------------ */ | ||
77 | |||
78 | static struct tuner_range tuner_philips_pal_i_ranges[] = { | ||
79 | { 16 * 140.25 /*MHz*/, 0x8e, 0xa0, }, | ||
80 | { 16 * 463.25 /*MHz*/, 0x8e, 0x90, }, | ||
81 | { 16 * 999.99 , 0x8e, 0x30, }, | ||
82 | }; | ||
83 | |||
84 | static struct tuner_params tuner_philips_pal_i_params[] = { | ||
85 | { | ||
86 | .type = TUNER_PARAM_TYPE_PAL, | ||
87 | .ranges = tuner_philips_pal_i_ranges, | ||
88 | .count = ARRAY_SIZE(tuner_philips_pal_i_ranges), | ||
89 | }, | ||
90 | }; | ||
91 | |||
92 | /* ------------ TUNER_PHILIPS_NTSC - Philips NTSC ------------ */ | ||
93 | |||
94 | static struct tuner_range tuner_philips_ntsc_ranges[] = { | ||
95 | { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, }, | ||
96 | { 16 * 451.25 /*MHz*/, 0x8e, 0x90, }, | ||
97 | { 16 * 999.99 , 0x8e, 0x30, }, | ||
98 | }; | ||
99 | |||
100 | static struct tuner_params tuner_philips_ntsc_params[] = { | ||
101 | { | ||
102 | .type = TUNER_PARAM_TYPE_NTSC, | ||
103 | .ranges = tuner_philips_ntsc_ranges, | ||
104 | .count = ARRAY_SIZE(tuner_philips_ntsc_ranges), | ||
105 | .cb_first_if_lower_freq = 1, | ||
106 | }, | ||
107 | }; | ||
108 | |||
109 | /* ------------ TUNER_PHILIPS_SECAM - Philips SECAM ------------ */ | ||
110 | |||
111 | static struct tuner_range tuner_philips_secam_ranges[] = { | ||
112 | { 16 * 168.25 /*MHz*/, 0x8e, 0xa7, }, | ||
113 | { 16 * 447.25 /*MHz*/, 0x8e, 0x97, }, | ||
114 | { 16 * 999.99 , 0x8e, 0x37, }, | ||
115 | }; | ||
116 | |||
117 | static struct tuner_params tuner_philips_secam_params[] = { | ||
118 | { | ||
119 | .type = TUNER_PARAM_TYPE_SECAM, | ||
120 | .ranges = tuner_philips_secam_ranges, | ||
121 | .count = ARRAY_SIZE(tuner_philips_secam_ranges), | ||
122 | .cb_first_if_lower_freq = 1, | ||
123 | }, | ||
124 | }; | ||
125 | |||
126 | /* ------------ TUNER_PHILIPS_PAL - Philips PAL ------------ */ | ||
127 | |||
128 | static struct tuner_range tuner_philips_pal_ranges[] = { | ||
129 | { 16 * 168.25 /*MHz*/, 0x8e, 0xa0, }, | ||
130 | { 16 * 447.25 /*MHz*/, 0x8e, 0x90, }, | ||
131 | { 16 * 999.99 , 0x8e, 0x30, }, | ||
132 | }; | ||
133 | |||
134 | static struct tuner_params tuner_philips_pal_params[] = { | ||
135 | { | ||
136 | .type = TUNER_PARAM_TYPE_PAL, | ||
137 | .ranges = tuner_philips_pal_ranges, | ||
138 | .count = ARRAY_SIZE(tuner_philips_pal_ranges), | ||
139 | .cb_first_if_lower_freq = 1, | ||
140 | }, | ||
141 | }; | ||
142 | |||
143 | /* ------------ TUNER_TEMIC_NTSC - TEMIC NTSC ------------ */ | ||
144 | |||
145 | static struct tuner_range tuner_temic_ntsc_ranges[] = { | ||
146 | { 16 * 157.25 /*MHz*/, 0x8e, 0x02, }, | ||
147 | { 16 * 463.25 /*MHz*/, 0x8e, 0x04, }, | ||
148 | { 16 * 999.99 , 0x8e, 0x01, }, | ||
149 | }; | ||
150 | |||
151 | static struct tuner_params tuner_temic_ntsc_params[] = { | ||
152 | { | ||
153 | .type = TUNER_PARAM_TYPE_NTSC, | ||
154 | .ranges = tuner_temic_ntsc_ranges, | ||
155 | .count = ARRAY_SIZE(tuner_temic_ntsc_ranges), | ||
156 | }, | ||
157 | }; | ||
158 | |||
159 | /* ------------ TUNER_TEMIC_PAL_I - TEMIC PAL_I ------------ */ | ||
160 | |||
161 | static struct tuner_range tuner_temic_pal_i_ranges[] = { | ||
162 | { 16 * 170.00 /*MHz*/, 0x8e, 0x02, }, | ||
163 | { 16 * 450.00 /*MHz*/, 0x8e, 0x04, }, | ||
164 | { 16 * 999.99 , 0x8e, 0x01, }, | ||
165 | }; | ||
166 | |||
167 | static struct tuner_params tuner_temic_pal_i_params[] = { | ||
168 | { | ||
169 | .type = TUNER_PARAM_TYPE_PAL, | ||
170 | .ranges = tuner_temic_pal_i_ranges, | ||
171 | .count = ARRAY_SIZE(tuner_temic_pal_i_ranges), | ||
172 | }, | ||
173 | }; | ||
174 | |||
175 | /* ------------ TUNER_TEMIC_4036FY5_NTSC - TEMIC NTSC ------------ */ | ||
176 | |||
177 | static struct tuner_range tuner_temic_4036fy5_ntsc_ranges[] = { | ||
178 | { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, }, | ||
179 | { 16 * 463.25 /*MHz*/, 0x8e, 0x90, }, | ||
180 | { 16 * 999.99 , 0x8e, 0x30, }, | ||
181 | }; | ||
182 | |||
183 | static struct tuner_params tuner_temic_4036fy5_ntsc_params[] = { | ||
184 | { | ||
185 | .type = TUNER_PARAM_TYPE_NTSC, | ||
186 | .ranges = tuner_temic_4036fy5_ntsc_ranges, | ||
187 | .count = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_ranges), | ||
188 | }, | ||
189 | }; | ||
190 | |||
191 | /* ------------ TUNER_ALPS_TSBH1_NTSC - TEMIC NTSC ------------ */ | ||
192 | |||
193 | static struct tuner_range tuner_alps_tsb_1_ranges[] = { | ||
194 | { 16 * 137.25 /*MHz*/, 0x8e, 0x01, }, | ||
195 | { 16 * 385.25 /*MHz*/, 0x8e, 0x02, }, | ||
196 | { 16 * 999.99 , 0x8e, 0x08, }, | ||
197 | }; | ||
198 | |||
199 | static struct tuner_params tuner_alps_tsbh1_ntsc_params[] = { | ||
200 | { | ||
201 | .type = TUNER_PARAM_TYPE_NTSC, | ||
202 | .ranges = tuner_alps_tsb_1_ranges, | ||
203 | .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges), | ||
204 | }, | ||
205 | }; | ||
206 | |||
207 | /* 10-19 */ | ||
208 | /* ------------ TUNER_ALPS_TSBE1_PAL - TEMIC PAL ------------ */ | ||
209 | |||
210 | static struct tuner_params tuner_alps_tsb_1_params[] = { | ||
211 | { | ||
212 | .type = TUNER_PARAM_TYPE_PAL, | ||
213 | .ranges = tuner_alps_tsb_1_ranges, | ||
214 | .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges), | ||
215 | }, | ||
216 | }; | ||
217 | |||
218 | /* ------------ TUNER_ALPS_TSBB5_PAL_I - Alps PAL_I ------------ */ | ||
219 | |||
220 | static struct tuner_range tuner_alps_tsb_5_pal_ranges[] = { | ||
221 | { 16 * 133.25 /*MHz*/, 0x8e, 0x01, }, | ||
222 | { 16 * 351.25 /*MHz*/, 0x8e, 0x02, }, | ||
223 | { 16 * 999.99 , 0x8e, 0x08, }, | ||
224 | }; | ||
225 | |||
226 | static struct tuner_params tuner_alps_tsbb5_params[] = { | ||
227 | { | ||
228 | .type = TUNER_PARAM_TYPE_PAL, | ||
229 | .ranges = tuner_alps_tsb_5_pal_ranges, | ||
230 | .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges), | ||
231 | }, | ||
232 | }; | ||
233 | |||
234 | /* ------------ TUNER_ALPS_TSBE5_PAL - Alps PAL ------------ */ | ||
235 | |||
236 | static struct tuner_params tuner_alps_tsbe5_params[] = { | ||
237 | { | ||
238 | .type = TUNER_PARAM_TYPE_PAL, | ||
239 | .ranges = tuner_alps_tsb_5_pal_ranges, | ||
240 | .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges), | ||
241 | }, | ||
242 | }; | ||
243 | |||
244 | /* ------------ TUNER_ALPS_TSBC5_PAL - Alps PAL ------------ */ | ||
245 | |||
246 | static struct tuner_params tuner_alps_tsbc5_params[] = { | ||
247 | { | ||
248 | .type = TUNER_PARAM_TYPE_PAL, | ||
249 | .ranges = tuner_alps_tsb_5_pal_ranges, | ||
250 | .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges), | ||
251 | }, | ||
252 | }; | ||
253 | |||
254 | /* ------------ TUNER_TEMIC_4006FH5_PAL - TEMIC PAL ------------ */ | ||
255 | |||
256 | static struct tuner_range tuner_lg_pal_ranges[] = { | ||
257 | { 16 * 170.00 /*MHz*/, 0x8e, 0xa0, }, | ||
258 | { 16 * 450.00 /*MHz*/, 0x8e, 0x90, }, | ||
259 | { 16 * 999.99 , 0x8e, 0x30, }, | ||
260 | }; | ||
261 | |||
262 | static struct tuner_params tuner_temic_4006fh5_params[] = { | ||
263 | { | ||
264 | .type = TUNER_PARAM_TYPE_PAL, | ||
265 | .ranges = tuner_lg_pal_ranges, | ||
266 | .count = ARRAY_SIZE(tuner_lg_pal_ranges), | ||
267 | }, | ||
268 | }; | ||
269 | |||
270 | /* ------------ TUNER_ALPS_TSHC6_NTSC - Alps NTSC ------------ */ | ||
271 | |||
272 | static struct tuner_range tuner_alps_tshc6_ntsc_ranges[] = { | ||
273 | { 16 * 137.25 /*MHz*/, 0x8e, 0x14, }, | ||
274 | { 16 * 385.25 /*MHz*/, 0x8e, 0x12, }, | ||
275 | { 16 * 999.99 , 0x8e, 0x11, }, | ||
276 | }; | ||
277 | |||
278 | static struct tuner_params tuner_alps_tshc6_params[] = { | ||
279 | { | ||
280 | .type = TUNER_PARAM_TYPE_NTSC, | ||
281 | .ranges = tuner_alps_tshc6_ntsc_ranges, | ||
282 | .count = ARRAY_SIZE(tuner_alps_tshc6_ntsc_ranges), | ||
283 | }, | ||
284 | }; | ||
285 | |||
286 | /* ------------ TUNER_TEMIC_PAL_DK - TEMIC PAL ------------ */ | ||
287 | |||
288 | static struct tuner_range tuner_temic_pal_dk_ranges[] = { | ||
289 | { 16 * 168.25 /*MHz*/, 0x8e, 0xa0, }, | ||
290 | { 16 * 456.25 /*MHz*/, 0x8e, 0x90, }, | ||
291 | { 16 * 999.99 , 0x8e, 0x30, }, | ||
292 | }; | ||
293 | |||
294 | static struct tuner_params tuner_temic_pal_dk_params[] = { | ||
295 | { | ||
296 | .type = TUNER_PARAM_TYPE_PAL, | ||
297 | .ranges = tuner_temic_pal_dk_ranges, | ||
298 | .count = ARRAY_SIZE(tuner_temic_pal_dk_ranges), | ||
299 | }, | ||
300 | }; | ||
301 | |||
302 | /* ------------ TUNER_PHILIPS_NTSC_M - Philips NTSC ------------ */ | ||
303 | |||
304 | static struct tuner_range tuner_philips_ntsc_m_ranges[] = { | ||
305 | { 16 * 160.00 /*MHz*/, 0x8e, 0xa0, }, | ||
306 | { 16 * 454.00 /*MHz*/, 0x8e, 0x90, }, | ||
307 | { 16 * 999.99 , 0x8e, 0x30, }, | ||
308 | }; | ||
309 | |||
310 | static struct tuner_params tuner_philips_ntsc_m_params[] = { | ||
311 | { | ||
312 | .type = TUNER_PARAM_TYPE_NTSC, | ||
313 | .ranges = tuner_philips_ntsc_m_ranges, | ||
314 | .count = ARRAY_SIZE(tuner_philips_ntsc_m_ranges), | ||
315 | }, | ||
316 | }; | ||
317 | |||
318 | /* ------------ TUNER_TEMIC_4066FY5_PAL_I - TEMIC PAL_I ------------ */ | ||
319 | |||
320 | static struct tuner_range tuner_temic_40x6f_5_pal_ranges[] = { | ||
321 | { 16 * 169.00 /*MHz*/, 0x8e, 0xa0, }, | ||
322 | { 16 * 454.00 /*MHz*/, 0x8e, 0x90, }, | ||
323 | { 16 * 999.99 , 0x8e, 0x30, }, | ||
324 | }; | ||
325 | |||
326 | static struct tuner_params tuner_temic_4066fy5_pal_i_params[] = { | ||
327 | { | ||
328 | .type = TUNER_PARAM_TYPE_PAL, | ||
329 | .ranges = tuner_temic_40x6f_5_pal_ranges, | ||
330 | .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges), | ||
331 | }, | ||
332 | }; | ||
333 | |||
334 | /* ------------ TUNER_TEMIC_4006FN5_MULTI_PAL - TEMIC PAL ------------ */ | ||
335 | |||
336 | static struct tuner_params tuner_temic_4006fn5_multi_params[] = { | ||
337 | { | ||
338 | .type = TUNER_PARAM_TYPE_PAL, | ||
339 | .ranges = tuner_temic_40x6f_5_pal_ranges, | ||
340 | .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges), | ||
341 | }, | ||
342 | }; | ||
343 | |||
344 | /* 20-29 */ | ||
345 | /* ------------ TUNER_TEMIC_4009FR5_PAL - TEMIC PAL ------------ */ | ||
346 | |||
347 | static struct tuner_range tuner_temic_4009f_5_pal_ranges[] = { | ||
348 | { 16 * 141.00 /*MHz*/, 0x8e, 0xa0, }, | ||
349 | { 16 * 464.00 /*MHz*/, 0x8e, 0x90, }, | ||
350 | { 16 * 999.99 , 0x8e, 0x30, }, | ||
351 | }; | ||
352 | |||
353 | static struct tuner_params tuner_temic_4009f_5_params[] = { | ||
354 | { | ||
355 | .type = TUNER_PARAM_TYPE_PAL, | ||
356 | .ranges = tuner_temic_4009f_5_pal_ranges, | ||
357 | .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), | ||
358 | }, | ||
359 | }; | ||
360 | |||
361 | /* ------------ TUNER_TEMIC_4039FR5_NTSC - TEMIC NTSC ------------ */ | ||
362 | |||
363 | static struct tuner_range tuner_temic_4x3x_f_5_ntsc_ranges[] = { | ||
364 | { 16 * 158.00 /*MHz*/, 0x8e, 0xa0, }, | ||
365 | { 16 * 453.00 /*MHz*/, 0x8e, 0x90, }, | ||
366 | { 16 * 999.99 , 0x8e, 0x30, }, | ||
367 | }; | ||
368 | |||
369 | static struct tuner_params tuner_temic_4039fr5_params[] = { | ||
370 | { | ||
371 | .type = TUNER_PARAM_TYPE_NTSC, | ||
372 | .ranges = tuner_temic_4x3x_f_5_ntsc_ranges, | ||
373 | .count = ARRAY_SIZE(tuner_temic_4x3x_f_5_ntsc_ranges), | ||
374 | }, | ||
375 | }; | ||
376 | |||
377 | /* ------------ TUNER_TEMIC_4046FM5 - TEMIC PAL ------------ */ | ||
378 | |||
379 | static struct tuner_params tuner_temic_4046fm5_params[] = { | ||
380 | { | ||
381 | .type = TUNER_PARAM_TYPE_PAL, | ||
382 | .ranges = tuner_temic_40x6f_5_pal_ranges, | ||
383 | .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges), | ||
384 | }, | ||
385 | }; | ||
386 | |||
387 | /* ------------ TUNER_PHILIPS_PAL_DK - Philips PAL ------------ */ | ||
388 | |||
389 | static struct tuner_params tuner_philips_pal_dk_params[] = { | ||
390 | { | ||
391 | .type = TUNER_PARAM_TYPE_PAL, | ||
392 | .ranges = tuner_lg_pal_ranges, | ||
393 | .count = ARRAY_SIZE(tuner_lg_pal_ranges), | ||
394 | }, | ||
395 | }; | ||
396 | |||
397 | /* ------------ TUNER_PHILIPS_FQ1216ME - Philips PAL ------------ */ | ||
398 | |||
399 | static struct tuner_params tuner_philips_fq1216me_params[] = { | ||
400 | { | ||
401 | .type = TUNER_PARAM_TYPE_PAL, | ||
402 | .ranges = tuner_lg_pal_ranges, | ||
403 | .count = ARRAY_SIZE(tuner_lg_pal_ranges), | ||
404 | .has_tda9887 = 1, | ||
405 | .port1_active = 1, | ||
406 | .port2_active = 1, | ||
407 | .port2_invert_for_secam_lc = 1, | ||
408 | }, | ||
409 | }; | ||
410 | |||
411 | /* ------------ TUNER_LG_PAL_I_FM - LGINNOTEK PAL_I ------------ */ | ||
412 | |||
413 | static struct tuner_params tuner_lg_pal_i_fm_params[] = { | ||
414 | { | ||
415 | .type = TUNER_PARAM_TYPE_PAL, | ||
416 | .ranges = tuner_lg_pal_ranges, | ||
417 | .count = ARRAY_SIZE(tuner_lg_pal_ranges), | ||
418 | }, | ||
419 | }; | ||
420 | |||
421 | /* ------------ TUNER_LG_PAL_I - LGINNOTEK PAL_I ------------ */ | ||
422 | |||
423 | static struct tuner_params tuner_lg_pal_i_params[] = { | ||
424 | { | ||
425 | .type = TUNER_PARAM_TYPE_PAL, | ||
426 | .ranges = tuner_lg_pal_ranges, | ||
427 | .count = ARRAY_SIZE(tuner_lg_pal_ranges), | ||
428 | }, | ||
429 | }; | ||
430 | |||
431 | /* ------------ TUNER_LG_NTSC_FM - LGINNOTEK NTSC ------------ */ | ||
432 | |||
433 | static struct tuner_range tuner_lg_ntsc_fm_ranges[] = { | ||
434 | { 16 * 210.00 /*MHz*/, 0x8e, 0xa0, }, | ||
435 | { 16 * 497.00 /*MHz*/, 0x8e, 0x90, }, | ||
436 | { 16 * 999.99 , 0x8e, 0x30, }, | ||
437 | }; | ||
438 | |||
439 | static struct tuner_params tuner_lg_ntsc_fm_params[] = { | ||
440 | { | ||
441 | .type = TUNER_PARAM_TYPE_NTSC, | ||
442 | .ranges = tuner_lg_ntsc_fm_ranges, | ||
443 | .count = ARRAY_SIZE(tuner_lg_ntsc_fm_ranges), | ||
444 | }, | ||
445 | }; | ||
446 | |||
447 | /* ------------ TUNER_LG_PAL_FM - LGINNOTEK PAL ------------ */ | ||
448 | |||
449 | static struct tuner_params tuner_lg_pal_fm_params[] = { | ||
450 | { | ||
451 | .type = TUNER_PARAM_TYPE_PAL, | ||
452 | .ranges = tuner_lg_pal_ranges, | ||
453 | .count = ARRAY_SIZE(tuner_lg_pal_ranges), | ||
454 | }, | ||
455 | }; | ||
456 | |||
457 | /* ------------ TUNER_LG_PAL - LGINNOTEK PAL ------------ */ | ||
458 | |||
459 | static struct tuner_params tuner_lg_pal_params[] = { | ||
460 | { | ||
461 | .type = TUNER_PARAM_TYPE_PAL, | ||
462 | .ranges = tuner_lg_pal_ranges, | ||
463 | .count = ARRAY_SIZE(tuner_lg_pal_ranges), | ||
464 | }, | ||
465 | }; | ||
466 | |||
467 | /* 30-39 */ | ||
468 | /* ------------ TUNER_TEMIC_4009FN5_MULTI_PAL_FM - TEMIC PAL ------------ */ | ||
469 | |||
470 | static struct tuner_params tuner_temic_4009_fn5_multi_pal_fm_params[] = { | ||
471 | { | ||
472 | .type = TUNER_PARAM_TYPE_PAL, | ||
473 | .ranges = tuner_temic_4009f_5_pal_ranges, | ||
474 | .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), | ||
475 | }, | ||
476 | }; | ||
477 | |||
478 | /* ------------ TUNER_SHARP_2U5JF5540_NTSC - SHARP NTSC ------------ */ | ||
479 | |||
480 | static struct tuner_range tuner_sharp_2u5jf5540_ntsc_ranges[] = { | ||
481 | { 16 * 137.25 /*MHz*/, 0x8e, 0x01, }, | ||
482 | { 16 * 317.25 /*MHz*/, 0x8e, 0x02, }, | ||
483 | { 16 * 999.99 , 0x8e, 0x08, }, | ||
484 | }; | ||
485 | |||
486 | static struct tuner_params tuner_sharp_2u5jf5540_params[] = { | ||
487 | { | ||
488 | .type = TUNER_PARAM_TYPE_NTSC, | ||
489 | .ranges = tuner_sharp_2u5jf5540_ntsc_ranges, | ||
490 | .count = ARRAY_SIZE(tuner_sharp_2u5jf5540_ntsc_ranges), | ||
491 | }, | ||
492 | }; | ||
493 | |||
494 | /* ------------ TUNER_Samsung_PAL_TCPM9091PD27 - Samsung PAL ------------ */ | ||
495 | |||
496 | static struct tuner_range tuner_samsung_pal_tcpm9091pd27_ranges[] = { | ||
497 | { 16 * 169 /*MHz*/, 0x8e, 0xa0, }, | ||
498 | { 16 * 464 /*MHz*/, 0x8e, 0x90, }, | ||
499 | { 16 * 999.99 , 0x8e, 0x30, }, | ||
500 | }; | ||
501 | |||
502 | static struct tuner_params tuner_samsung_pal_tcpm9091pd27_params[] = { | ||
503 | { | ||
504 | .type = TUNER_PARAM_TYPE_PAL, | ||
505 | .ranges = tuner_samsung_pal_tcpm9091pd27_ranges, | ||
506 | .count = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_ranges), | ||
507 | }, | ||
508 | }; | ||
509 | |||
510 | /* ------------ TUNER_TEMIC_4106FH5 - TEMIC PAL ------------ */ | ||
511 | |||
512 | static struct tuner_params tuner_temic_4106fh5_params[] = { | ||
513 | { | ||
514 | .type = TUNER_PARAM_TYPE_PAL, | ||
515 | .ranges = tuner_temic_4009f_5_pal_ranges, | ||
516 | .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), | ||
517 | }, | ||
518 | }; | ||
519 | |||
520 | /* ------------ TUNER_TEMIC_4012FY5 - TEMIC PAL ------------ */ | ||
521 | |||
522 | static struct tuner_params tuner_temic_4012fy5_params[] = { | ||
523 | { | ||
524 | .type = TUNER_PARAM_TYPE_PAL, | ||
525 | .ranges = tuner_temic_pal_ranges, | ||
526 | .count = ARRAY_SIZE(tuner_temic_pal_ranges), | ||
527 | }, | ||
528 | }; | ||
529 | |||
530 | /* ------------ TUNER_TEMIC_4136FY5 - TEMIC NTSC ------------ */ | ||
531 | |||
532 | static struct tuner_params tuner_temic_4136_fy5_params[] = { | ||
533 | { | ||
534 | .type = TUNER_PARAM_TYPE_NTSC, | ||
535 | .ranges = tuner_temic_4x3x_f_5_ntsc_ranges, | ||
536 | .count = ARRAY_SIZE(tuner_temic_4x3x_f_5_ntsc_ranges), | ||
537 | }, | ||
538 | }; | ||
539 | |||
540 | /* ------------ TUNER_LG_PAL_NEW_TAPC - LGINNOTEK PAL ------------ */ | ||
541 | |||
542 | static struct tuner_range tuner_lg_new_tapc_ranges[] = { | ||
543 | { 16 * 170.00 /*MHz*/, 0x8e, 0x01, }, | ||
544 | { 16 * 450.00 /*MHz*/, 0x8e, 0x02, }, | ||
545 | { 16 * 999.99 , 0x8e, 0x08, }, | ||
546 | }; | ||
547 | |||
548 | static struct tuner_params tuner_lg_pal_new_tapc_params[] = { | ||
549 | { | ||
550 | .type = TUNER_PARAM_TYPE_PAL, | ||
551 | .ranges = tuner_lg_new_tapc_ranges, | ||
552 | .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges), | ||
553 | }, | ||
554 | }; | ||
555 | |||
556 | /* ------------ TUNER_PHILIPS_FM1216ME_MK3 - Philips PAL ------------ */ | ||
557 | |||
558 | static struct tuner_range tuner_fm1216me_mk3_pal_ranges[] = { | ||
559 | { 16 * 158.00 /*MHz*/, 0x8e, 0x01, }, | ||
560 | { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, | ||
561 | { 16 * 999.99 , 0x8e, 0x04, }, | ||
562 | }; | ||
563 | |||
564 | static struct tuner_params tuner_fm1216me_mk3_params[] = { | ||
565 | { | ||
566 | .type = TUNER_PARAM_TYPE_PAL, | ||
567 | .ranges = tuner_fm1216me_mk3_pal_ranges, | ||
568 | .count = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges), | ||
569 | .cb_first_if_lower_freq = 1, | ||
570 | .has_tda9887 = 1, | ||
571 | .port1_active = 1, | ||
572 | .port2_active = 1, | ||
573 | .port2_invert_for_secam_lc = 1, | ||
574 | .port1_fm_high_sensitivity = 1, | ||
575 | .default_top_mid = -2, | ||
576 | .default_top_secam_mid = -2, | ||
577 | .default_top_secam_high = -2, | ||
578 | }, | ||
579 | }; | ||
580 | |||
581 | /* ------------ TUNER_LG_NTSC_NEW_TAPC - LGINNOTEK NTSC ------------ */ | ||
582 | |||
583 | static struct tuner_params tuner_lg_ntsc_new_tapc_params[] = { | ||
584 | { | ||
585 | .type = TUNER_PARAM_TYPE_NTSC, | ||
586 | .ranges = tuner_lg_new_tapc_ranges, | ||
587 | .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges), | ||
588 | }, | ||
589 | }; | ||
590 | |||
591 | /* 40-49 */ | ||
592 | /* ------------ TUNER_HITACHI_NTSC - HITACHI NTSC ------------ */ | ||
593 | |||
594 | static struct tuner_params tuner_hitachi_ntsc_params[] = { | ||
595 | { | ||
596 | .type = TUNER_PARAM_TYPE_NTSC, | ||
597 | .ranges = tuner_lg_new_tapc_ranges, | ||
598 | .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges), | ||
599 | }, | ||
600 | }; | ||
601 | |||
602 | /* ------------ TUNER_PHILIPS_PAL_MK - Philips PAL ------------ */ | ||
603 | |||
604 | static struct tuner_range tuner_philips_pal_mk_pal_ranges[] = { | ||
605 | { 16 * 140.25 /*MHz*/, 0x8e, 0x01, }, | ||
606 | { 16 * 463.25 /*MHz*/, 0x8e, 0xc2, }, | ||
607 | { 16 * 999.99 , 0x8e, 0xcf, }, | ||
608 | }; | ||
609 | |||
610 | static struct tuner_params tuner_philips_pal_mk_params[] = { | ||
611 | { | ||
612 | .type = TUNER_PARAM_TYPE_PAL, | ||
613 | .ranges = tuner_philips_pal_mk_pal_ranges, | ||
614 | .count = ARRAY_SIZE(tuner_philips_pal_mk_pal_ranges), | ||
615 | }, | ||
616 | }; | ||
617 | |||
618 | /* ---- TUNER_PHILIPS_FCV1236D - Philips FCV1236D (ATSC/NTSC) ---- */ | ||
619 | |||
620 | static struct tuner_range tuner_philips_fcv1236d_ntsc_ranges[] = { | ||
621 | { 16 * 157.25 /*MHz*/, 0x8e, 0xa2, }, | ||
622 | { 16 * 451.25 /*MHz*/, 0x8e, 0x92, }, | ||
623 | { 16 * 999.99 , 0x8e, 0x32, }, | ||
624 | }; | ||
625 | |||
626 | static struct tuner_range tuner_philips_fcv1236d_atsc_ranges[] = { | ||
627 | { 16 * 159.00 /*MHz*/, 0x8e, 0xa0, }, | ||
628 | { 16 * 453.00 /*MHz*/, 0x8e, 0x90, }, | ||
629 | { 16 * 999.99 , 0x8e, 0x30, }, | ||
630 | }; | ||
631 | |||
632 | static struct tuner_params tuner_philips_fcv1236d_params[] = { | ||
633 | { | ||
634 | .type = TUNER_PARAM_TYPE_NTSC, | ||
635 | .ranges = tuner_philips_fcv1236d_ntsc_ranges, | ||
636 | .count = ARRAY_SIZE(tuner_philips_fcv1236d_ntsc_ranges), | ||
637 | }, | ||
638 | { | ||
639 | .type = TUNER_PARAM_TYPE_DIGITAL, | ||
640 | .ranges = tuner_philips_fcv1236d_atsc_ranges, | ||
641 | .count = ARRAY_SIZE(tuner_philips_fcv1236d_atsc_ranges), | ||
642 | .iffreq = 16 * 44.00, | ||
643 | }, | ||
644 | }; | ||
645 | |||
646 | /* ------------ TUNER_PHILIPS_FM1236_MK3 - Philips NTSC ------------ */ | ||
647 | |||
648 | static struct tuner_range tuner_fm1236_mk3_ntsc_ranges[] = { | ||
649 | { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, | ||
650 | { 16 * 442.00 /*MHz*/, 0x8e, 0x02, }, | ||
651 | { 16 * 999.99 , 0x8e, 0x04, }, | ||
652 | }; | ||
653 | |||
654 | static struct tuner_params tuner_fm1236_mk3_params[] = { | ||
655 | { | ||
656 | .type = TUNER_PARAM_TYPE_NTSC, | ||
657 | .ranges = tuner_fm1236_mk3_ntsc_ranges, | ||
658 | .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), | ||
659 | .cb_first_if_lower_freq = 1, | ||
660 | .has_tda9887 = 1, | ||
661 | .port1_active = 1, | ||
662 | .port2_active = 1, | ||
663 | .port1_fm_high_sensitivity = 1, | ||
664 | }, | ||
665 | }; | ||
666 | |||
667 | /* ------------ TUNER_PHILIPS_4IN1 - Philips NTSC ------------ */ | ||
668 | |||
669 | static struct tuner_params tuner_philips_4in1_params[] = { | ||
670 | { | ||
671 | .type = TUNER_PARAM_TYPE_NTSC, | ||
672 | .ranges = tuner_fm1236_mk3_ntsc_ranges, | ||
673 | .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), | ||
674 | }, | ||
675 | }; | ||
676 | |||
677 | /* ------------ TUNER_MICROTUNE_4049FM5 - Microtune PAL ------------ */ | ||
678 | |||
679 | static struct tuner_params tuner_microtune_4049_fm5_params[] = { | ||
680 | { | ||
681 | .type = TUNER_PARAM_TYPE_PAL, | ||
682 | .ranges = tuner_temic_4009f_5_pal_ranges, | ||
683 | .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges), | ||
684 | .has_tda9887 = 1, | ||
685 | .port1_invert_for_secam_lc = 1, | ||
686 | .default_pll_gating_18 = 1, | ||
687 | .fm_gain_normal=1, | ||
688 | .radio_if = 1, /* 33.3 MHz */ | ||
689 | }, | ||
690 | }; | ||
691 | |||
692 | /* ------------ TUNER_PANASONIC_VP27 - Panasonic NTSC ------------ */ | ||
693 | |||
694 | static struct tuner_range tuner_panasonic_vp27_ntsc_ranges[] = { | ||
695 | { 16 * 160.00 /*MHz*/, 0xce, 0x01, }, | ||
696 | { 16 * 454.00 /*MHz*/, 0xce, 0x02, }, | ||
697 | { 16 * 999.99 , 0xce, 0x08, }, | ||
698 | }; | ||
699 | |||
700 | static struct tuner_params tuner_panasonic_vp27_params[] = { | ||
701 | { | ||
702 | .type = TUNER_PARAM_TYPE_NTSC, | ||
703 | .ranges = tuner_panasonic_vp27_ntsc_ranges, | ||
704 | .count = ARRAY_SIZE(tuner_panasonic_vp27_ntsc_ranges), | ||
705 | .has_tda9887 = 1, | ||
706 | .intercarrier_mode = 1, | ||
707 | .default_top_low = -3, | ||
708 | .default_top_mid = -3, | ||
709 | .default_top_high = -3, | ||
710 | }, | ||
711 | }; | ||
712 | |||
713 | /* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */ | ||
714 | |||
715 | static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = { | ||
716 | { 16 * 161.25 /*MHz*/, 0x8e, 0xa0, }, | ||
717 | { 16 * 463.25 /*MHz*/, 0x8e, 0x90, }, | ||
718 | { 16 * 999.99 , 0x8e, 0x30, }, | ||
719 | }; | ||
720 | |||
721 | static struct tuner_params tuner_tnf_8831bgff_params[] = { | ||
722 | { | ||
723 | .type = TUNER_PARAM_TYPE_PAL, | ||
724 | .ranges = tuner_tnf_8831bgff_pal_ranges, | ||
725 | .count = ARRAY_SIZE(tuner_tnf_8831bgff_pal_ranges), | ||
726 | }, | ||
727 | }; | ||
728 | |||
729 | /* ------------ TUNER_MICROTUNE_4042FI5 - Microtune NTSC ------------ */ | ||
730 | |||
731 | static struct tuner_range tuner_microtune_4042fi5_ntsc_ranges[] = { | ||
732 | { 16 * 162.00 /*MHz*/, 0x8e, 0xa2, }, | ||
733 | { 16 * 457.00 /*MHz*/, 0x8e, 0x94, }, | ||
734 | { 16 * 999.99 , 0x8e, 0x31, }, | ||
735 | }; | ||
736 | |||
737 | static struct tuner_range tuner_microtune_4042fi5_atsc_ranges[] = { | ||
738 | { 16 * 162.00 /*MHz*/, 0x8e, 0xa1, }, | ||
739 | { 16 * 457.00 /*MHz*/, 0x8e, 0x91, }, | ||
740 | { 16 * 999.99 , 0x8e, 0x31, }, | ||
741 | }; | ||
742 | |||
743 | static struct tuner_params tuner_microtune_4042fi5_params[] = { | ||
744 | { | ||
745 | .type = TUNER_PARAM_TYPE_NTSC, | ||
746 | .ranges = tuner_microtune_4042fi5_ntsc_ranges, | ||
747 | .count = ARRAY_SIZE(tuner_microtune_4042fi5_ntsc_ranges), | ||
748 | }, | ||
749 | { | ||
750 | .type = TUNER_PARAM_TYPE_DIGITAL, | ||
751 | .ranges = tuner_microtune_4042fi5_atsc_ranges, | ||
752 | .count = ARRAY_SIZE(tuner_microtune_4042fi5_atsc_ranges), | ||
753 | .iffreq = 16 * 44.00 /*MHz*/, | ||
754 | }, | ||
755 | }; | ||
756 | |||
757 | /* 50-59 */ | ||
758 | /* ------------ TUNER_TCL_2002N - TCL NTSC ------------ */ | ||
759 | |||
760 | static struct tuner_range tuner_tcl_2002n_ntsc_ranges[] = { | ||
761 | { 16 * 172.00 /*MHz*/, 0x8e, 0x01, }, | ||
762 | { 16 * 448.00 /*MHz*/, 0x8e, 0x02, }, | ||
763 | { 16 * 999.99 , 0x8e, 0x08, }, | ||
764 | }; | ||
765 | |||
766 | static struct tuner_params tuner_tcl_2002n_params[] = { | ||
767 | { | ||
768 | .type = TUNER_PARAM_TYPE_NTSC, | ||
769 | .ranges = tuner_tcl_2002n_ntsc_ranges, | ||
770 | .count = ARRAY_SIZE(tuner_tcl_2002n_ntsc_ranges), | ||
771 | .cb_first_if_lower_freq = 1, | ||
772 | }, | ||
773 | }; | ||
774 | |||
775 | /* ------------ TUNER_PHILIPS_FM1256_IH3 - Philips PAL ------------ */ | ||
776 | |||
777 | static struct tuner_params tuner_philips_fm1256_ih3_params[] = { | ||
778 | { | ||
779 | .type = TUNER_PARAM_TYPE_PAL, | ||
780 | .ranges = tuner_fm1236_mk3_ntsc_ranges, | ||
781 | .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), | ||
782 | .radio_if = 1, /* 33.3 MHz */ | ||
783 | }, | ||
784 | }; | ||
785 | |||
786 | /* ------------ TUNER_THOMSON_DTT7610 - THOMSON ATSC ------------ */ | ||
787 | |||
788 | /* single range used for both ntsc and atsc */ | ||
789 | static struct tuner_range tuner_thomson_dtt7610_ntsc_ranges[] = { | ||
790 | { 16 * 157.25 /*MHz*/, 0x8e, 0x39, }, | ||
791 | { 16 * 454.00 /*MHz*/, 0x8e, 0x3a, }, | ||
792 | { 16 * 999.99 , 0x8e, 0x3c, }, | ||
793 | }; | ||
794 | |||
795 | static struct tuner_params tuner_thomson_dtt7610_params[] = { | ||
796 | { | ||
797 | .type = TUNER_PARAM_TYPE_NTSC, | ||
798 | .ranges = tuner_thomson_dtt7610_ntsc_ranges, | ||
799 | .count = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges), | ||
800 | }, | ||
801 | { | ||
802 | .type = TUNER_PARAM_TYPE_DIGITAL, | ||
803 | .ranges = tuner_thomson_dtt7610_ntsc_ranges, | ||
804 | .count = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges), | ||
805 | .iffreq = 16 * 44.00 /*MHz*/, | ||
806 | }, | ||
807 | }; | ||
808 | |||
809 | /* ------------ TUNER_PHILIPS_FQ1286 - Philips NTSC ------------ */ | ||
810 | |||
811 | static struct tuner_range tuner_philips_fq1286_ntsc_ranges[] = { | ||
812 | { 16 * 160.00 /*MHz*/, 0x8e, 0x41, }, | ||
813 | { 16 * 454.00 /*MHz*/, 0x8e, 0x42, }, | ||
814 | { 16 * 999.99 , 0x8e, 0x04, }, | ||
815 | }; | ||
816 | |||
817 | static struct tuner_params tuner_philips_fq1286_params[] = { | ||
818 | { | ||
819 | .type = TUNER_PARAM_TYPE_NTSC, | ||
820 | .ranges = tuner_philips_fq1286_ntsc_ranges, | ||
821 | .count = ARRAY_SIZE(tuner_philips_fq1286_ntsc_ranges), | ||
822 | }, | ||
823 | }; | ||
824 | |||
825 | /* ------------ TUNER_TCL_2002MB - TCL PAL ------------ */ | ||
826 | |||
827 | static struct tuner_range tuner_tcl_2002mb_pal_ranges[] = { | ||
828 | { 16 * 170.00 /*MHz*/, 0xce, 0x01, }, | ||
829 | { 16 * 450.00 /*MHz*/, 0xce, 0x02, }, | ||
830 | { 16 * 999.99 , 0xce, 0x08, }, | ||
831 | }; | ||
832 | |||
833 | static struct tuner_params tuner_tcl_2002mb_params[] = { | ||
834 | { | ||
835 | .type = TUNER_PARAM_TYPE_PAL, | ||
836 | .ranges = tuner_tcl_2002mb_pal_ranges, | ||
837 | .count = ARRAY_SIZE(tuner_tcl_2002mb_pal_ranges), | ||
838 | }, | ||
839 | }; | ||
840 | |||
841 | /* ------------ TUNER_PHILIPS_FQ1216AME_MK4 - Philips PAL ------------ */ | ||
842 | |||
843 | static struct tuner_range tuner_philips_fq12_6a___mk4_pal_ranges[] = { | ||
844 | { 16 * 160.00 /*MHz*/, 0xce, 0x01, }, | ||
845 | { 16 * 442.00 /*MHz*/, 0xce, 0x02, }, | ||
846 | { 16 * 999.99 , 0xce, 0x04, }, | ||
847 | }; | ||
848 | |||
849 | static struct tuner_params tuner_philips_fq1216ame_mk4_params[] = { | ||
850 | { | ||
851 | .type = TUNER_PARAM_TYPE_PAL, | ||
852 | .ranges = tuner_philips_fq12_6a___mk4_pal_ranges, | ||
853 | .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_pal_ranges), | ||
854 | .has_tda9887 = 1, | ||
855 | .port1_active = 1, | ||
856 | .port2_invert_for_secam_lc = 1, | ||
857 | .default_top_mid = -2, | ||
858 | .default_top_secam_low = -2, | ||
859 | .default_top_secam_mid = -2, | ||
860 | .default_top_secam_high = -2, | ||
861 | }, | ||
862 | }; | ||
863 | |||
864 | /* ------------ TUNER_PHILIPS_FQ1236A_MK4 - Philips NTSC ------------ */ | ||
865 | |||
866 | static struct tuner_params tuner_philips_fq1236a_mk4_params[] = { | ||
867 | { | ||
868 | .type = TUNER_PARAM_TYPE_NTSC, | ||
869 | .ranges = tuner_fm1236_mk3_ntsc_ranges, | ||
870 | .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges), | ||
871 | }, | ||
872 | }; | ||
873 | |||
874 | /* ------------ TUNER_YMEC_TVF_8531MF - Philips NTSC ------------ */ | ||
875 | |||
876 | static struct tuner_params tuner_ymec_tvf_8531mf_params[] = { | ||
877 | { | ||
878 | .type = TUNER_PARAM_TYPE_NTSC, | ||
879 | .ranges = tuner_philips_ntsc_m_ranges, | ||
880 | .count = ARRAY_SIZE(tuner_philips_ntsc_m_ranges), | ||
881 | }, | ||
882 | }; | ||
883 | |||
884 | /* ------------ TUNER_YMEC_TVF_5533MF - Philips NTSC ------------ */ | ||
885 | |||
886 | static struct tuner_range tuner_ymec_tvf_5533mf_ntsc_ranges[] = { | ||
887 | { 16 * 160.00 /*MHz*/, 0x8e, 0x01, }, | ||
888 | { 16 * 454.00 /*MHz*/, 0x8e, 0x02, }, | ||
889 | { 16 * 999.99 , 0x8e, 0x04, }, | ||
890 | }; | ||
891 | |||
892 | static struct tuner_params tuner_ymec_tvf_5533mf_params[] = { | ||
893 | { | ||
894 | .type = TUNER_PARAM_TYPE_NTSC, | ||
895 | .ranges = tuner_ymec_tvf_5533mf_ntsc_ranges, | ||
896 | .count = ARRAY_SIZE(tuner_ymec_tvf_5533mf_ntsc_ranges), | ||
897 | }, | ||
898 | }; | ||
899 | |||
900 | /* 60-69 */ | ||
901 | /* ------------ TUNER_THOMSON_DTT761X - THOMSON ATSC ------------ */ | ||
902 | /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */ | ||
903 | |||
904 | static struct tuner_range tuner_thomson_dtt761x_ntsc_ranges[] = { | ||
905 | { 16 * 145.25 /*MHz*/, 0x8e, 0x39, }, | ||
906 | { 16 * 415.25 /*MHz*/, 0x8e, 0x3a, }, | ||
907 | { 16 * 999.99 , 0x8e, 0x3c, }, | ||
908 | }; | ||
909 | |||
910 | static struct tuner_range tuner_thomson_dtt761x_atsc_ranges[] = { | ||
911 | { 16 * 147.00 /*MHz*/, 0x8e, 0x39, }, | ||
912 | { 16 * 417.00 /*MHz*/, 0x8e, 0x3a, }, | ||
913 | { 16 * 999.99 , 0x8e, 0x3c, }, | ||
914 | }; | ||
915 | |||
916 | static struct tuner_params tuner_thomson_dtt761x_params[] = { | ||
917 | { | ||
918 | .type = TUNER_PARAM_TYPE_NTSC, | ||
919 | .ranges = tuner_thomson_dtt761x_ntsc_ranges, | ||
920 | .count = ARRAY_SIZE(tuner_thomson_dtt761x_ntsc_ranges), | ||
921 | .has_tda9887 = 1, | ||
922 | .fm_gain_normal = 1, | ||
923 | .radio_if = 2, /* 41.3 MHz */ | ||
924 | }, | ||
925 | { | ||
926 | .type = TUNER_PARAM_TYPE_DIGITAL, | ||
927 | .ranges = tuner_thomson_dtt761x_atsc_ranges, | ||
928 | .count = ARRAY_SIZE(tuner_thomson_dtt761x_atsc_ranges), | ||
929 | .iffreq = 16 * 44.00, /*MHz*/ | ||
930 | }, | ||
931 | }; | ||
932 | |||
933 | /* ------------ TUNER_TENA_9533_DI - Philips PAL ------------ */ | ||
934 | |||
935 | static struct tuner_range tuner_tena_9533_di_pal_ranges[] = { | ||
936 | { 16 * 160.25 /*MHz*/, 0x8e, 0x01, }, | ||
937 | { 16 * 464.25 /*MHz*/, 0x8e, 0x02, }, | ||
938 | { 16 * 999.99 , 0x8e, 0x04, }, | ||
939 | }; | ||
940 | |||
941 | static struct tuner_params tuner_tena_9533_di_params[] = { | ||
942 | { | ||
943 | .type = TUNER_PARAM_TYPE_PAL, | ||
944 | .ranges = tuner_tena_9533_di_pal_ranges, | ||
945 | .count = ARRAY_SIZE(tuner_tena_9533_di_pal_ranges), | ||
946 | }, | ||
947 | }; | ||
948 | |||
949 | /* ------------ TUNER_PHILIPS_FMD1216ME_MK3 - Philips PAL ------------ */ | ||
950 | |||
951 | static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = { | ||
952 | { 16 * 160.00 /*MHz*/, 0x86, 0x51, }, | ||
953 | { 16 * 442.00 /*MHz*/, 0x86, 0x52, }, | ||
954 | { 16 * 999.99 , 0x86, 0x54, }, | ||
955 | }; | ||
956 | |||
957 | static struct tuner_range tuner_philips_fmd1216me_mk3_dvb_ranges[] = { | ||
958 | { 16 * 143.87 /*MHz*/, 0xbc, 0x41 }, | ||
959 | { 16 * 158.87 /*MHz*/, 0xf4, 0x41 }, | ||
960 | { 16 * 329.87 /*MHz*/, 0xbc, 0x42 }, | ||
961 | { 16 * 441.87 /*MHz*/, 0xf4, 0x42 }, | ||
962 | { 16 * 625.87 /*MHz*/, 0xbc, 0x44 }, | ||
963 | { 16 * 803.87 /*MHz*/, 0xf4, 0x44 }, | ||
964 | { 16 * 999.99 , 0xfc, 0x44 }, | ||
965 | }; | ||
966 | |||
967 | static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = { | ||
968 | { | ||
969 | .type = TUNER_PARAM_TYPE_PAL, | ||
970 | .ranges = tuner_philips_fmd1216me_mk3_pal_ranges, | ||
971 | .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_pal_ranges), | ||
972 | .has_tda9887 = 1, | ||
973 | .port1_active = 1, | ||
974 | .port2_active = 1, | ||
975 | .port2_fm_high_sensitivity = 1, | ||
976 | .port2_invert_for_secam_lc = 1, | ||
977 | .port1_set_for_fm_mono = 1, | ||
978 | }, | ||
979 | { | ||
980 | .type = TUNER_PARAM_TYPE_DIGITAL, | ||
981 | .ranges = tuner_philips_fmd1216me_mk3_dvb_ranges, | ||
982 | .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_dvb_ranges), | ||
983 | .iffreq = 16 * 36.125, /*MHz*/ | ||
984 | }, | ||
985 | }; | ||
986 | |||
987 | |||
988 | /* ------ TUNER_LG_TDVS_H06XF - LG INNOTEK / INFINEON ATSC ----- */ | ||
989 | |||
990 | static struct tuner_range tuner_tua6034_ntsc_ranges[] = { | ||
991 | { 16 * 165.00 /*MHz*/, 0x8e, 0x01 }, | ||
992 | { 16 * 450.00 /*MHz*/, 0x8e, 0x02 }, | ||
993 | { 16 * 999.99 , 0x8e, 0x04 }, | ||
994 | }; | ||
995 | |||
996 | static struct tuner_range tuner_tua6034_atsc_ranges[] = { | ||
997 | { 16 * 165.00 /*MHz*/, 0xce, 0x01 }, | ||
998 | { 16 * 450.00 /*MHz*/, 0xce, 0x02 }, | ||
999 | { 16 * 999.99 , 0xce, 0x04 }, | ||
1000 | }; | ||
1001 | |||
1002 | static struct tuner_params tuner_lg_tdvs_h06xf_params[] = { | ||
1003 | { | ||
1004 | .type = TUNER_PARAM_TYPE_NTSC, | ||
1005 | .ranges = tuner_tua6034_ntsc_ranges, | ||
1006 | .count = ARRAY_SIZE(tuner_tua6034_ntsc_ranges), | ||
1007 | }, | ||
1008 | { | ||
1009 | .type = TUNER_PARAM_TYPE_DIGITAL, | ||
1010 | .ranges = tuner_tua6034_atsc_ranges, | ||
1011 | .count = ARRAY_SIZE(tuner_tua6034_atsc_ranges), | ||
1012 | .iffreq = 16 * 44.00, | ||
1013 | }, | ||
1014 | }; | ||
1015 | |||
1016 | /* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */ | ||
1017 | |||
1018 | static struct tuner_range tuner_ymec_tvf66t5_b_dff_pal_ranges[] = { | ||
1019 | { 16 * 160.25 /*MHz*/, 0x8e, 0x01, }, | ||
1020 | { 16 * 464.25 /*MHz*/, 0x8e, 0x02, }, | ||
1021 | { 16 * 999.99 , 0x8e, 0x08, }, | ||
1022 | }; | ||
1023 | |||
1024 | static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = { | ||
1025 | { | ||
1026 | .type = TUNER_PARAM_TYPE_PAL, | ||
1027 | .ranges = tuner_ymec_tvf66t5_b_dff_pal_ranges, | ||
1028 | .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_pal_ranges), | ||
1029 | }, | ||
1030 | }; | ||
1031 | |||
1032 | /* ------------ TUNER_LG_NTSC_TALN_MINI - LGINNOTEK NTSC ------------ */ | ||
1033 | |||
1034 | static struct tuner_range tuner_lg_taln_ntsc_ranges[] = { | ||
1035 | { 16 * 137.25 /*MHz*/, 0x8e, 0x01, }, | ||
1036 | { 16 * 373.25 /*MHz*/, 0x8e, 0x02, }, | ||
1037 | { 16 * 999.99 , 0x8e, 0x08, }, | ||
1038 | }; | ||
1039 | |||
1040 | static struct tuner_range tuner_lg_taln_pal_secam_ranges[] = { | ||
1041 | { 16 * 150.00 /*MHz*/, 0x8e, 0x01, }, | ||
1042 | { 16 * 425.00 /*MHz*/, 0x8e, 0x02, }, | ||
1043 | { 16 * 999.99 , 0x8e, 0x08, }, | ||
1044 | }; | ||
1045 | |||
1046 | static struct tuner_params tuner_lg_taln_params[] = { | ||
1047 | { | ||
1048 | .type = TUNER_PARAM_TYPE_NTSC, | ||
1049 | .ranges = tuner_lg_taln_ntsc_ranges, | ||
1050 | .count = ARRAY_SIZE(tuner_lg_taln_ntsc_ranges), | ||
1051 | },{ | ||
1052 | .type = TUNER_PARAM_TYPE_PAL, | ||
1053 | .ranges = tuner_lg_taln_pal_secam_ranges, | ||
1054 | .count = ARRAY_SIZE(tuner_lg_taln_pal_secam_ranges), | ||
1055 | }, | ||
1056 | }; | ||
1057 | |||
1058 | /* ------------ TUNER_PHILIPS_TD1316 - Philips PAL ------------ */ | ||
1059 | |||
1060 | static struct tuner_range tuner_philips_td1316_pal_ranges[] = { | ||
1061 | { 16 * 160.00 /*MHz*/, 0xc8, 0xa1, }, | ||
1062 | { 16 * 442.00 /*MHz*/, 0xc8, 0xa2, }, | ||
1063 | { 16 * 999.99 , 0xc8, 0xa4, }, | ||
1064 | }; | ||
1065 | |||
1066 | static struct tuner_range tuner_philips_td1316_dvb_ranges[] = { | ||
1067 | { 16 * 93.834 /*MHz*/, 0xca, 0x60, }, | ||
1068 | { 16 * 123.834 /*MHz*/, 0xca, 0xa0, }, | ||
1069 | { 16 * 163.834 /*MHz*/, 0xca, 0xc0, }, | ||
1070 | { 16 * 253.834 /*MHz*/, 0xca, 0x60, }, | ||
1071 | { 16 * 383.834 /*MHz*/, 0xca, 0xa0, }, | ||
1072 | { 16 * 443.834 /*MHz*/, 0xca, 0xc0, }, | ||
1073 | { 16 * 583.834 /*MHz*/, 0xca, 0x60, }, | ||
1074 | { 16 * 793.834 /*MHz*/, 0xca, 0xa0, }, | ||
1075 | { 16 * 999.999 , 0xca, 0xe0, }, | ||
1076 | }; | ||
1077 | |||
1078 | static struct tuner_params tuner_philips_td1316_params[] = { | ||
1079 | { | ||
1080 | .type = TUNER_PARAM_TYPE_PAL, | ||
1081 | .ranges = tuner_philips_td1316_pal_ranges, | ||
1082 | .count = ARRAY_SIZE(tuner_philips_td1316_pal_ranges), | ||
1083 | }, | ||
1084 | { | ||
1085 | .type = TUNER_PARAM_TYPE_DIGITAL, | ||
1086 | .ranges = tuner_philips_td1316_dvb_ranges, | ||
1087 | .count = ARRAY_SIZE(tuner_philips_td1316_dvb_ranges), | ||
1088 | .iffreq = 16 * 36.166667 /*MHz*/, | ||
1089 | }, | ||
1090 | }; | ||
1091 | |||
1092 | /* ------------ TUNER_PHILIPS_TUV1236D - Philips ATSC ------------ */ | ||
1093 | |||
1094 | static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = { | ||
1095 | { 16 * 157.25 /*MHz*/, 0xce, 0x01, }, | ||
1096 | { 16 * 454.00 /*MHz*/, 0xce, 0x02, }, | ||
1097 | { 16 * 999.99 , 0xce, 0x04, }, | ||
1098 | }; | ||
1099 | |||
1100 | static struct tuner_range tuner_tuv1236d_atsc_ranges[] = { | ||
1101 | { 16 * 157.25 /*MHz*/, 0xc6, 0x41, }, | ||
1102 | { 16 * 454.00 /*MHz*/, 0xc6, 0x42, }, | ||
1103 | { 16 * 999.99 , 0xc6, 0x44, }, | ||
1104 | }; | ||
1105 | |||
1106 | static struct tuner_params tuner_tuv1236d_params[] = { | ||
1107 | { | ||
1108 | .type = TUNER_PARAM_TYPE_NTSC, | ||
1109 | .ranges = tuner_tuv1236d_ntsc_ranges, | ||
1110 | .count = ARRAY_SIZE(tuner_tuv1236d_ntsc_ranges), | ||
1111 | }, | ||
1112 | { | ||
1113 | .type = TUNER_PARAM_TYPE_DIGITAL, | ||
1114 | .ranges = tuner_tuv1236d_atsc_ranges, | ||
1115 | .count = ARRAY_SIZE(tuner_tuv1236d_atsc_ranges), | ||
1116 | .iffreq = 16 * 44.00, | ||
1117 | }, | ||
1118 | }; | ||
1119 | |||
1120 | /* ------------ TUNER_TNF_xxx5 - Texas Instruments--------- */ | ||
1121 | /* This is known to work with Tenna TVF58t5-MFF and TVF5835 MFF | ||
1122 | * but it is expected to work also with other Tenna/Ymec | ||
1123 | * models based on TI SN 761677 chip on both PAL and NTSC | ||
1124 | */ | ||
1125 | |||
1126 | static struct tuner_range tuner_tnf_5335_d_if_pal_ranges[] = { | ||
1127 | { 16 * 168.25 /*MHz*/, 0x8e, 0x01, }, | ||
1128 | { 16 * 471.25 /*MHz*/, 0x8e, 0x02, }, | ||
1129 | { 16 * 999.99 , 0x8e, 0x08, }, | ||
1130 | }; | ||
1131 | |||
1132 | static struct tuner_range tuner_tnf_5335mf_ntsc_ranges[] = { | ||
1133 | { 16 * 169.25 /*MHz*/, 0x8e, 0x01, }, | ||
1134 | { 16 * 469.25 /*MHz*/, 0x8e, 0x02, }, | ||
1135 | { 16 * 999.99 , 0x8e, 0x08, }, | ||
1136 | }; | ||
1137 | |||
1138 | static struct tuner_params tuner_tnf_5335mf_params[] = { | ||
1139 | { | ||
1140 | .type = TUNER_PARAM_TYPE_NTSC, | ||
1141 | .ranges = tuner_tnf_5335mf_ntsc_ranges, | ||
1142 | .count = ARRAY_SIZE(tuner_tnf_5335mf_ntsc_ranges), | ||
1143 | }, | ||
1144 | { | ||
1145 | .type = TUNER_PARAM_TYPE_PAL, | ||
1146 | .ranges = tuner_tnf_5335_d_if_pal_ranges, | ||
1147 | .count = ARRAY_SIZE(tuner_tnf_5335_d_if_pal_ranges), | ||
1148 | }, | ||
1149 | }; | ||
1150 | |||
1151 | /* 70-79 */ | ||
1152 | /* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */ | ||
1153 | |||
1154 | /* '+ 4' turns on the Low Noise Amplifier */ | ||
1155 | static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = { | ||
1156 | { 16 * 130.00 /*MHz*/, 0xce, 0x01 + 4, }, | ||
1157 | { 16 * 364.50 /*MHz*/, 0xce, 0x02 + 4, }, | ||
1158 | { 16 * 999.99 , 0xce, 0x08 + 4, }, | ||
1159 | }; | ||
1160 | |||
1161 | static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = { | ||
1162 | { | ||
1163 | .type = TUNER_PARAM_TYPE_NTSC, | ||
1164 | .ranges = tuner_samsung_tcpn_2121p30a_ntsc_ranges, | ||
1165 | .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_ntsc_ranges), | ||
1166 | }, | ||
1167 | }; | ||
1168 | |||
1169 | /* ------------ TUNER_THOMSON_FE6600 - DViCO Hybrid PAL ------------ */ | ||
1170 | |||
1171 | static struct tuner_range tuner_thomson_fe6600_pal_ranges[] = { | ||
1172 | { 16 * 160.00 /*MHz*/, 0xfe, 0x11, }, | ||
1173 | { 16 * 442.00 /*MHz*/, 0xf6, 0x12, }, | ||
1174 | { 16 * 999.99 , 0xf6, 0x18, }, | ||
1175 | }; | ||
1176 | |||
1177 | static struct tuner_range tuner_thomson_fe6600_dvb_ranges[] = { | ||
1178 | { 16 * 250.00 /*MHz*/, 0xb4, 0x12, }, | ||
1179 | { 16 * 455.00 /*MHz*/, 0xfe, 0x11, }, | ||
1180 | { 16 * 775.50 /*MHz*/, 0xbc, 0x18, }, | ||
1181 | { 16 * 999.99 , 0xf4, 0x18, }, | ||
1182 | }; | ||
1183 | |||
1184 | static struct tuner_params tuner_thomson_fe6600_params[] = { | ||
1185 | { | ||
1186 | .type = TUNER_PARAM_TYPE_PAL, | ||
1187 | .ranges = tuner_thomson_fe6600_pal_ranges, | ||
1188 | .count = ARRAY_SIZE(tuner_thomson_fe6600_pal_ranges), | ||
1189 | }, | ||
1190 | { | ||
1191 | .type = TUNER_PARAM_TYPE_DIGITAL, | ||
1192 | .ranges = tuner_thomson_fe6600_dvb_ranges, | ||
1193 | .count = ARRAY_SIZE(tuner_thomson_fe6600_dvb_ranges), | ||
1194 | .iffreq = 16 * 36.125 /*MHz*/, | ||
1195 | }, | ||
1196 | }; | ||
1197 | |||
1198 | /* ------------ TUNER_SAMSUNG_TCPG_6121P30A - Samsung PAL ------------ */ | ||
1199 | |||
1200 | /* '+ 4' turns on the Low Noise Amplifier */ | ||
1201 | static struct tuner_range tuner_samsung_tcpg_6121p30a_pal_ranges[] = { | ||
1202 | { 16 * 146.25 /*MHz*/, 0xce, 0x01 + 4, }, | ||
1203 | { 16 * 428.50 /*MHz*/, 0xce, 0x02 + 4, }, | ||
1204 | { 16 * 999.99 , 0xce, 0x08 + 4, }, | ||
1205 | }; | ||
1206 | |||
1207 | static struct tuner_params tuner_samsung_tcpg_6121p30a_params[] = { | ||
1208 | { | ||
1209 | .type = TUNER_PARAM_TYPE_PAL, | ||
1210 | .ranges = tuner_samsung_tcpg_6121p30a_pal_ranges, | ||
1211 | .count = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_pal_ranges), | ||
1212 | .has_tda9887 = 1, | ||
1213 | .port1_active = 1, | ||
1214 | .port2_active = 1, | ||
1215 | .port2_invert_for_secam_lc = 1, | ||
1216 | }, | ||
1217 | }; | ||
1218 | |||
1219 | /* --------------------------------------------------------------------- */ | ||
1220 | |||
1221 | struct tunertype tuners[] = { | ||
1222 | /* 0-9 */ | ||
1223 | [TUNER_TEMIC_PAL] = { /* TEMIC PAL */ | ||
1224 | .name = "Temic PAL (4002 FH5)", | ||
1225 | .params = tuner_temic_pal_params, | ||
1226 | .count = ARRAY_SIZE(tuner_temic_pal_params), | ||
1227 | }, | ||
1228 | [TUNER_PHILIPS_PAL_I] = { /* Philips PAL_I */ | ||
1229 | .name = "Philips PAL_I (FI1246 and compatibles)", | ||
1230 | .params = tuner_philips_pal_i_params, | ||
1231 | .count = ARRAY_SIZE(tuner_philips_pal_i_params), | ||
1232 | }, | ||
1233 | [TUNER_PHILIPS_NTSC] = { /* Philips NTSC */ | ||
1234 | .name = "Philips NTSC (FI1236,FM1236 and compatibles)", | ||
1235 | .params = tuner_philips_ntsc_params, | ||
1236 | .count = ARRAY_SIZE(tuner_philips_ntsc_params), | ||
1237 | }, | ||
1238 | [TUNER_PHILIPS_SECAM] = { /* Philips SECAM */ | ||
1239 | .name = "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)", | ||
1240 | .params = tuner_philips_secam_params, | ||
1241 | .count = ARRAY_SIZE(tuner_philips_secam_params), | ||
1242 | }, | ||
1243 | [TUNER_ABSENT] = { /* Tuner Absent */ | ||
1244 | .name = "NoTuner", | ||
1245 | }, | ||
1246 | [TUNER_PHILIPS_PAL] = { /* Philips PAL */ | ||
1247 | .name = "Philips PAL_BG (FI1216 and compatibles)", | ||
1248 | .params = tuner_philips_pal_params, | ||
1249 | .count = ARRAY_SIZE(tuner_philips_pal_params), | ||
1250 | }, | ||
1251 | [TUNER_TEMIC_NTSC] = { /* TEMIC NTSC */ | ||
1252 | .name = "Temic NTSC (4032 FY5)", | ||
1253 | .params = tuner_temic_ntsc_params, | ||
1254 | .count = ARRAY_SIZE(tuner_temic_ntsc_params), | ||
1255 | }, | ||
1256 | [TUNER_TEMIC_PAL_I] = { /* TEMIC PAL_I */ | ||
1257 | .name = "Temic PAL_I (4062 FY5)", | ||
1258 | .params = tuner_temic_pal_i_params, | ||
1259 | .count = ARRAY_SIZE(tuner_temic_pal_i_params), | ||
1260 | }, | ||
1261 | [TUNER_TEMIC_4036FY5_NTSC] = { /* TEMIC NTSC */ | ||
1262 | .name = "Temic NTSC (4036 FY5)", | ||
1263 | .params = tuner_temic_4036fy5_ntsc_params, | ||
1264 | .count = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_params), | ||
1265 | }, | ||
1266 | [TUNER_ALPS_TSBH1_NTSC] = { /* TEMIC NTSC */ | ||
1267 | .name = "Alps HSBH1", | ||
1268 | .params = tuner_alps_tsbh1_ntsc_params, | ||
1269 | .count = ARRAY_SIZE(tuner_alps_tsbh1_ntsc_params), | ||
1270 | }, | ||
1271 | |||
1272 | /* 10-19 */ | ||
1273 | [TUNER_ALPS_TSBE1_PAL] = { /* TEMIC PAL */ | ||
1274 | .name = "Alps TSBE1", | ||
1275 | .params = tuner_alps_tsb_1_params, | ||
1276 | .count = ARRAY_SIZE(tuner_alps_tsb_1_params), | ||
1277 | }, | ||
1278 | [TUNER_ALPS_TSBB5_PAL_I] = { /* Alps PAL_I */ | ||
1279 | .name = "Alps TSBB5", | ||
1280 | .params = tuner_alps_tsbb5_params, | ||
1281 | .count = ARRAY_SIZE(tuner_alps_tsbb5_params), | ||
1282 | }, | ||
1283 | [TUNER_ALPS_TSBE5_PAL] = { /* Alps PAL */ | ||
1284 | .name = "Alps TSBE5", | ||
1285 | .params = tuner_alps_tsbe5_params, | ||
1286 | .count = ARRAY_SIZE(tuner_alps_tsbe5_params), | ||
1287 | }, | ||
1288 | [TUNER_ALPS_TSBC5_PAL] = { /* Alps PAL */ | ||
1289 | .name = "Alps TSBC5", | ||
1290 | .params = tuner_alps_tsbc5_params, | ||
1291 | .count = ARRAY_SIZE(tuner_alps_tsbc5_params), | ||
1292 | }, | ||
1293 | [TUNER_TEMIC_4006FH5_PAL] = { /* TEMIC PAL */ | ||
1294 | .name = "Temic PAL_BG (4006FH5)", | ||
1295 | .params = tuner_temic_4006fh5_params, | ||
1296 | .count = ARRAY_SIZE(tuner_temic_4006fh5_params), | ||
1297 | }, | ||
1298 | [TUNER_ALPS_TSHC6_NTSC] = { /* Alps NTSC */ | ||
1299 | .name = "Alps TSCH6", | ||
1300 | .params = tuner_alps_tshc6_params, | ||
1301 | .count = ARRAY_SIZE(tuner_alps_tshc6_params), | ||
1302 | }, | ||
1303 | [TUNER_TEMIC_PAL_DK] = { /* TEMIC PAL */ | ||
1304 | .name = "Temic PAL_DK (4016 FY5)", | ||
1305 | .params = tuner_temic_pal_dk_params, | ||
1306 | .count = ARRAY_SIZE(tuner_temic_pal_dk_params), | ||
1307 | }, | ||
1308 | [TUNER_PHILIPS_NTSC_M] = { /* Philips NTSC */ | ||
1309 | .name = "Philips NTSC_M (MK2)", | ||
1310 | .params = tuner_philips_ntsc_m_params, | ||
1311 | .count = ARRAY_SIZE(tuner_philips_ntsc_m_params), | ||
1312 | }, | ||
1313 | [TUNER_TEMIC_4066FY5_PAL_I] = { /* TEMIC PAL_I */ | ||
1314 | .name = "Temic PAL_I (4066 FY5)", | ||
1315 | .params = tuner_temic_4066fy5_pal_i_params, | ||
1316 | .count = ARRAY_SIZE(tuner_temic_4066fy5_pal_i_params), | ||
1317 | }, | ||
1318 | [TUNER_TEMIC_4006FN5_MULTI_PAL] = { /* TEMIC PAL */ | ||
1319 | .name = "Temic PAL* auto (4006 FN5)", | ||
1320 | .params = tuner_temic_4006fn5_multi_params, | ||
1321 | .count = ARRAY_SIZE(tuner_temic_4006fn5_multi_params), | ||
1322 | }, | ||
1323 | |||
1324 | /* 20-29 */ | ||
1325 | [TUNER_TEMIC_4009FR5_PAL] = { /* TEMIC PAL */ | ||
1326 | .name = "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", | ||
1327 | .params = tuner_temic_4009f_5_params, | ||
1328 | .count = ARRAY_SIZE(tuner_temic_4009f_5_params), | ||
1329 | }, | ||
1330 | [TUNER_TEMIC_4039FR5_NTSC] = { /* TEMIC NTSC */ | ||
1331 | .name = "Temic NTSC (4039 FR5)", | ||
1332 | .params = tuner_temic_4039fr5_params, | ||
1333 | .count = ARRAY_SIZE(tuner_temic_4039fr5_params), | ||
1334 | }, | ||
1335 | [TUNER_TEMIC_4046FM5] = { /* TEMIC PAL */ | ||
1336 | .name = "Temic PAL/SECAM multi (4046 FM5)", | ||
1337 | .params = tuner_temic_4046fm5_params, | ||
1338 | .count = ARRAY_SIZE(tuner_temic_4046fm5_params), | ||
1339 | }, | ||
1340 | [TUNER_PHILIPS_PAL_DK] = { /* Philips PAL */ | ||
1341 | .name = "Philips PAL_DK (FI1256 and compatibles)", | ||
1342 | .params = tuner_philips_pal_dk_params, | ||
1343 | .count = ARRAY_SIZE(tuner_philips_pal_dk_params), | ||
1344 | }, | ||
1345 | [TUNER_PHILIPS_FQ1216ME] = { /* Philips PAL */ | ||
1346 | .name = "Philips PAL/SECAM multi (FQ1216ME)", | ||
1347 | .params = tuner_philips_fq1216me_params, | ||
1348 | .count = ARRAY_SIZE(tuner_philips_fq1216me_params), | ||
1349 | }, | ||
1350 | [TUNER_LG_PAL_I_FM] = { /* LGINNOTEK PAL_I */ | ||
1351 | .name = "LG PAL_I+FM (TAPC-I001D)", | ||
1352 | .params = tuner_lg_pal_i_fm_params, | ||
1353 | .count = ARRAY_SIZE(tuner_lg_pal_i_fm_params), | ||
1354 | }, | ||
1355 | [TUNER_LG_PAL_I] = { /* LGINNOTEK PAL_I */ | ||
1356 | .name = "LG PAL_I (TAPC-I701D)", | ||
1357 | .params = tuner_lg_pal_i_params, | ||
1358 | .count = ARRAY_SIZE(tuner_lg_pal_i_params), | ||
1359 | }, | ||
1360 | [TUNER_LG_NTSC_FM] = { /* LGINNOTEK NTSC */ | ||
1361 | .name = "LG NTSC+FM (TPI8NSR01F)", | ||
1362 | .params = tuner_lg_ntsc_fm_params, | ||
1363 | .count = ARRAY_SIZE(tuner_lg_ntsc_fm_params), | ||
1364 | }, | ||
1365 | [TUNER_LG_PAL_FM] = { /* LGINNOTEK PAL */ | ||
1366 | .name = "LG PAL_BG+FM (TPI8PSB01D)", | ||
1367 | .params = tuner_lg_pal_fm_params, | ||
1368 | .count = ARRAY_SIZE(tuner_lg_pal_fm_params), | ||
1369 | }, | ||
1370 | [TUNER_LG_PAL] = { /* LGINNOTEK PAL */ | ||
1371 | .name = "LG PAL_BG (TPI8PSB11D)", | ||
1372 | .params = tuner_lg_pal_params, | ||
1373 | .count = ARRAY_SIZE(tuner_lg_pal_params), | ||
1374 | }, | ||
1375 | |||
1376 | /* 30-39 */ | ||
1377 | [TUNER_TEMIC_4009FN5_MULTI_PAL_FM] = { /* TEMIC PAL */ | ||
1378 | .name = "Temic PAL* auto + FM (4009 FN5)", | ||
1379 | .params = tuner_temic_4009_fn5_multi_pal_fm_params, | ||
1380 | .count = ARRAY_SIZE(tuner_temic_4009_fn5_multi_pal_fm_params), | ||
1381 | }, | ||
1382 | [TUNER_SHARP_2U5JF5540_NTSC] = { /* SHARP NTSC */ | ||
1383 | .name = "SHARP NTSC_JP (2U5JF5540)", | ||
1384 | .params = tuner_sharp_2u5jf5540_params, | ||
1385 | .count = ARRAY_SIZE(tuner_sharp_2u5jf5540_params), | ||
1386 | }, | ||
1387 | [TUNER_Samsung_PAL_TCPM9091PD27] = { /* Samsung PAL */ | ||
1388 | .name = "Samsung PAL TCPM9091PD27", | ||
1389 | .params = tuner_samsung_pal_tcpm9091pd27_params, | ||
1390 | .count = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_params), | ||
1391 | }, | ||
1392 | [TUNER_MT2032] = { /* Microtune PAL|NTSC */ | ||
1393 | .name = "MT20xx universal", | ||
1394 | /* see mt20xx.c for details */ }, | ||
1395 | [TUNER_TEMIC_4106FH5] = { /* TEMIC PAL */ | ||
1396 | .name = "Temic PAL_BG (4106 FH5)", | ||
1397 | .params = tuner_temic_4106fh5_params, | ||
1398 | .count = ARRAY_SIZE(tuner_temic_4106fh5_params), | ||
1399 | }, | ||
1400 | [TUNER_TEMIC_4012FY5] = { /* TEMIC PAL */ | ||
1401 | .name = "Temic PAL_DK/SECAM_L (4012 FY5)", | ||
1402 | .params = tuner_temic_4012fy5_params, | ||
1403 | .count = ARRAY_SIZE(tuner_temic_4012fy5_params), | ||
1404 | }, | ||
1405 | [TUNER_TEMIC_4136FY5] = { /* TEMIC NTSC */ | ||
1406 | .name = "Temic NTSC (4136 FY5)", | ||
1407 | .params = tuner_temic_4136_fy5_params, | ||
1408 | .count = ARRAY_SIZE(tuner_temic_4136_fy5_params), | ||
1409 | }, | ||
1410 | [TUNER_LG_PAL_NEW_TAPC] = { /* LGINNOTEK PAL */ | ||
1411 | .name = "LG PAL (newer TAPC series)", | ||
1412 | .params = tuner_lg_pal_new_tapc_params, | ||
1413 | .count = ARRAY_SIZE(tuner_lg_pal_new_tapc_params), | ||
1414 | }, | ||
1415 | [TUNER_PHILIPS_FM1216ME_MK3] = { /* Philips PAL */ | ||
1416 | .name = "Philips PAL/SECAM multi (FM1216ME MK3)", | ||
1417 | .params = tuner_fm1216me_mk3_params, | ||
1418 | .count = ARRAY_SIZE(tuner_fm1216me_mk3_params), | ||
1419 | }, | ||
1420 | [TUNER_LG_NTSC_NEW_TAPC] = { /* LGINNOTEK NTSC */ | ||
1421 | .name = "LG NTSC (newer TAPC series)", | ||
1422 | .params = tuner_lg_ntsc_new_tapc_params, | ||
1423 | .count = ARRAY_SIZE(tuner_lg_ntsc_new_tapc_params), | ||
1424 | }, | ||
1425 | |||
1426 | /* 40-49 */ | ||
1427 | [TUNER_HITACHI_NTSC] = { /* HITACHI NTSC */ | ||
1428 | .name = "HITACHI V7-J180AT", | ||
1429 | .params = tuner_hitachi_ntsc_params, | ||
1430 | .count = ARRAY_SIZE(tuner_hitachi_ntsc_params), | ||
1431 | }, | ||
1432 | [TUNER_PHILIPS_PAL_MK] = { /* Philips PAL */ | ||
1433 | .name = "Philips PAL_MK (FI1216 MK)", | ||
1434 | .params = tuner_philips_pal_mk_params, | ||
1435 | .count = ARRAY_SIZE(tuner_philips_pal_mk_params), | ||
1436 | }, | ||
1437 | [TUNER_PHILIPS_FCV1236D] = { /* Philips ATSC */ | ||
1438 | .name = "Philips FCV1236D ATSC/NTSC dual in", | ||
1439 | .params = tuner_philips_fcv1236d_params, | ||
1440 | .count = ARRAY_SIZE(tuner_philips_fcv1236d_params), | ||
1441 | .min = 16 * 53.00, | ||
1442 | .max = 16 * 803.00, | ||
1443 | .stepsize = 62500, | ||
1444 | }, | ||
1445 | [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */ | ||
1446 | .name = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", | ||
1447 | .params = tuner_fm1236_mk3_params, | ||
1448 | .count = ARRAY_SIZE(tuner_fm1236_mk3_params), | ||
1449 | }, | ||
1450 | [TUNER_PHILIPS_4IN1] = { /* Philips NTSC */ | ||
1451 | .name = "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", | ||
1452 | .params = tuner_philips_4in1_params, | ||
1453 | .count = ARRAY_SIZE(tuner_philips_4in1_params), | ||
1454 | }, | ||
1455 | [TUNER_MICROTUNE_4049FM5] = { /* Microtune PAL */ | ||
1456 | .name = "Microtune 4049 FM5", | ||
1457 | .params = tuner_microtune_4049_fm5_params, | ||
1458 | .count = ARRAY_SIZE(tuner_microtune_4049_fm5_params), | ||
1459 | }, | ||
1460 | [TUNER_PANASONIC_VP27] = { /* Panasonic NTSC */ | ||
1461 | .name = "Panasonic VP27s/ENGE4324D", | ||
1462 | .params = tuner_panasonic_vp27_params, | ||
1463 | .count = ARRAY_SIZE(tuner_panasonic_vp27_params), | ||
1464 | }, | ||
1465 | [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */ | ||
1466 | .name = "LG NTSC (TAPE series)", | ||
1467 | .params = tuner_fm1236_mk3_params, | ||
1468 | .count = ARRAY_SIZE(tuner_fm1236_mk3_params), | ||
1469 | }, | ||
1470 | [TUNER_TNF_8831BGFF] = { /* Philips PAL */ | ||
1471 | .name = "Tenna TNF 8831 BGFF)", | ||
1472 | .params = tuner_tnf_8831bgff_params, | ||
1473 | .count = ARRAY_SIZE(tuner_tnf_8831bgff_params), | ||
1474 | }, | ||
1475 | [TUNER_MICROTUNE_4042FI5] = { /* Microtune NTSC */ | ||
1476 | .name = "Microtune 4042 FI5 ATSC/NTSC dual in", | ||
1477 | .params = tuner_microtune_4042fi5_params, | ||
1478 | .count = ARRAY_SIZE(tuner_microtune_4042fi5_params), | ||
1479 | .min = 16 * 57.00, | ||
1480 | .max = 16 * 858.00, | ||
1481 | .stepsize = 62500, | ||
1482 | }, | ||
1483 | |||
1484 | /* 50-59 */ | ||
1485 | [TUNER_TCL_2002N] = { /* TCL NTSC */ | ||
1486 | .name = "TCL 2002N", | ||
1487 | .params = tuner_tcl_2002n_params, | ||
1488 | .count = ARRAY_SIZE(tuner_tcl_2002n_params), | ||
1489 | }, | ||
1490 | [TUNER_PHILIPS_FM1256_IH3] = { /* Philips PAL */ | ||
1491 | .name = "Philips PAL/SECAM_D (FM 1256 I-H3)", | ||
1492 | .params = tuner_philips_fm1256_ih3_params, | ||
1493 | .count = ARRAY_SIZE(tuner_philips_fm1256_ih3_params), | ||
1494 | }, | ||
1495 | [TUNER_THOMSON_DTT7610] = { /* THOMSON ATSC */ | ||
1496 | .name = "Thomson DTT 7610 (ATSC/NTSC)", | ||
1497 | .params = tuner_thomson_dtt7610_params, | ||
1498 | .count = ARRAY_SIZE(tuner_thomson_dtt7610_params), | ||
1499 | .min = 16 * 44.00, | ||
1500 | .max = 16 * 958.00, | ||
1501 | .stepsize = 62500, | ||
1502 | }, | ||
1503 | [TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */ | ||
1504 | .name = "Philips FQ1286", | ||
1505 | .params = tuner_philips_fq1286_params, | ||
1506 | .count = ARRAY_SIZE(tuner_philips_fq1286_params), | ||
1507 | }, | ||
1508 | [TUNER_PHILIPS_TDA8290] = { /* Philips PAL|NTSC */ | ||
1509 | .name = "Philips/NXP TDA 8290/8295 + 8275/8275A/18271", | ||
1510 | /* see tda8290.c for details */ }, | ||
1511 | [TUNER_TCL_2002MB] = { /* TCL PAL */ | ||
1512 | .name = "TCL 2002MB", | ||
1513 | .params = tuner_tcl_2002mb_params, | ||
1514 | .count = ARRAY_SIZE(tuner_tcl_2002mb_params), | ||
1515 | }, | ||
1516 | [TUNER_PHILIPS_FQ1216AME_MK4] = { /* Philips PAL */ | ||
1517 | .name = "Philips PAL/SECAM multi (FQ1216AME MK4)", | ||
1518 | .params = tuner_philips_fq1216ame_mk4_params, | ||
1519 | .count = ARRAY_SIZE(tuner_philips_fq1216ame_mk4_params), | ||
1520 | }, | ||
1521 | [TUNER_PHILIPS_FQ1236A_MK4] = { /* Philips NTSC */ | ||
1522 | .name = "Philips FQ1236A MK4", | ||
1523 | .params = tuner_philips_fq1236a_mk4_params, | ||
1524 | .count = ARRAY_SIZE(tuner_philips_fq1236a_mk4_params), | ||
1525 | }, | ||
1526 | [TUNER_YMEC_TVF_8531MF] = { /* Philips NTSC */ | ||
1527 | .name = "Ymec TVision TVF-8531MF/8831MF/8731MF", | ||
1528 | .params = tuner_ymec_tvf_8531mf_params, | ||
1529 | .count = ARRAY_SIZE(tuner_ymec_tvf_8531mf_params), | ||
1530 | }, | ||
1531 | [TUNER_YMEC_TVF_5533MF] = { /* Philips NTSC */ | ||
1532 | .name = "Ymec TVision TVF-5533MF", | ||
1533 | .params = tuner_ymec_tvf_5533mf_params, | ||
1534 | .count = ARRAY_SIZE(tuner_ymec_tvf_5533mf_params), | ||
1535 | }, | ||
1536 | |||
1537 | /* 60-69 */ | ||
1538 | [TUNER_THOMSON_DTT761X] = { /* THOMSON ATSC */ | ||
1539 | /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */ | ||
1540 | .name = "Thomson DTT 761X (ATSC/NTSC)", | ||
1541 | .params = tuner_thomson_dtt761x_params, | ||
1542 | .count = ARRAY_SIZE(tuner_thomson_dtt761x_params), | ||
1543 | .min = 16 * 57.00, | ||
1544 | .max = 16 * 863.00, | ||
1545 | .stepsize = 62500, | ||
1546 | .initdata = tua603x_agc103, | ||
1547 | }, | ||
1548 | [TUNER_TENA_9533_DI] = { /* Philips PAL */ | ||
1549 | .name = "Tena TNF9533-D/IF/TNF9533-B/DF", | ||
1550 | .params = tuner_tena_9533_di_params, | ||
1551 | .count = ARRAY_SIZE(tuner_tena_9533_di_params), | ||
1552 | }, | ||
1553 | [TUNER_TEA5767] = { /* Philips RADIO */ | ||
1554 | .name = "Philips TEA5767HN FM Radio", | ||
1555 | /* see tea5767.c for details */ | ||
1556 | }, | ||
1557 | [TUNER_PHILIPS_FMD1216ME_MK3] = { /* Philips PAL */ | ||
1558 | .name = "Philips FMD1216ME MK3 Hybrid Tuner", | ||
1559 | .params = tuner_philips_fmd1216me_mk3_params, | ||
1560 | .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params), | ||
1561 | .min = 16 * 50.87, | ||
1562 | .max = 16 * 858.00, | ||
1563 | .stepsize = 166667, | ||
1564 | .initdata = tua603x_agc112, | ||
1565 | .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 }, | ||
1566 | }, | ||
1567 | [TUNER_LG_TDVS_H06XF] = { /* LGINNOTEK ATSC */ | ||
1568 | .name = "LG TDVS-H06xF", /* H061F, H062F & H064F */ | ||
1569 | .params = tuner_lg_tdvs_h06xf_params, | ||
1570 | .count = ARRAY_SIZE(tuner_lg_tdvs_h06xf_params), | ||
1571 | .min = 16 * 54.00, | ||
1572 | .max = 16 * 863.00, | ||
1573 | .stepsize = 62500, | ||
1574 | .initdata = tua603x_agc103, | ||
1575 | }, | ||
1576 | [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */ | ||
1577 | .name = "Ymec TVF66T5-B/DFF", | ||
1578 | .params = tuner_ymec_tvf66t5_b_dff_params, | ||
1579 | .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_params), | ||
1580 | }, | ||
1581 | [TUNER_LG_TALN] = { /* LGINNOTEK NTSC / PAL / SECAM */ | ||
1582 | .name = "LG TALN series", | ||
1583 | .params = tuner_lg_taln_params, | ||
1584 | .count = ARRAY_SIZE(tuner_lg_taln_params), | ||
1585 | }, | ||
1586 | [TUNER_PHILIPS_TD1316] = { /* Philips PAL */ | ||
1587 | .name = "Philips TD1316 Hybrid Tuner", | ||
1588 | .params = tuner_philips_td1316_params, | ||
1589 | .count = ARRAY_SIZE(tuner_philips_td1316_params), | ||
1590 | .min = 16 * 87.00, | ||
1591 | .max = 16 * 895.00, | ||
1592 | .stepsize = 166667, | ||
1593 | }, | ||
1594 | [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */ | ||
1595 | .name = "Philips TUV1236D ATSC/NTSC dual in", | ||
1596 | .params = tuner_tuv1236d_params, | ||
1597 | .count = ARRAY_SIZE(tuner_tuv1236d_params), | ||
1598 | .min = 16 * 54.00, | ||
1599 | .max = 16 * 864.00, | ||
1600 | .stepsize = 62500, | ||
1601 | }, | ||
1602 | [TUNER_TNF_5335MF] = { /* Tenna PAL/NTSC */ | ||
1603 | .name = "Tena TNF 5335 and similar models", | ||
1604 | .params = tuner_tnf_5335mf_params, | ||
1605 | .count = ARRAY_SIZE(tuner_tnf_5335mf_params), | ||
1606 | }, | ||
1607 | |||
1608 | /* 70-79 */ | ||
1609 | [TUNER_SAMSUNG_TCPN_2121P30A] = { /* Samsung NTSC */ | ||
1610 | .name = "Samsung TCPN 2121P30A", | ||
1611 | .params = tuner_samsung_tcpn_2121p30a_params, | ||
1612 | .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_params), | ||
1613 | }, | ||
1614 | [TUNER_XC2028] = { /* Xceive 2028 */ | ||
1615 | .name = "Xceive xc2028/xc3028 tuner", | ||
1616 | /* see tuner-xc2028.c for details */ | ||
1617 | }, | ||
1618 | [TUNER_THOMSON_FE6600] = { /* Thomson PAL / DVB-T */ | ||
1619 | .name = "Thomson FE6600", | ||
1620 | .params = tuner_thomson_fe6600_params, | ||
1621 | .count = ARRAY_SIZE(tuner_thomson_fe6600_params), | ||
1622 | .min = 16 * 44.25, | ||
1623 | .max = 16 * 858.00, | ||
1624 | .stepsize = 166667, | ||
1625 | }, | ||
1626 | [TUNER_SAMSUNG_TCPG_6121P30A] = { /* Samsung PAL */ | ||
1627 | .name = "Samsung TCPG 6121P30A", | ||
1628 | .params = tuner_samsung_tcpg_6121p30a_params, | ||
1629 | .count = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_params), | ||
1630 | }, | ||
1631 | [TUNER_TDA9887] = { /* Philips TDA 9887 IF PLL Demodulator. | ||
1632 | This chip is part of some modern tuners */ | ||
1633 | .name = "Philips TDA988[5,6,7] IF PLL Demodulator", | ||
1634 | /* see tda9887.c for details */ | ||
1635 | }, | ||
1636 | [TUNER_TEA5761] = { /* Philips RADIO */ | ||
1637 | .name = "Philips TEA5761 FM Radio", | ||
1638 | /* see tea5767.c for details */ | ||
1639 | }, | ||
1640 | [TUNER_XC5000] = { /* Xceive 5000 */ | ||
1641 | .name = "Xceive 5000 tuner", | ||
1642 | /* see xc5000.c for details */ | ||
1643 | }, | ||
1644 | }; | ||
1645 | EXPORT_SYMBOL(tuners); | ||
1646 | |||
1647 | unsigned const int tuner_count = ARRAY_SIZE(tuners); | ||
1648 | EXPORT_SYMBOL(tuner_count); | ||
1649 | |||
1650 | MODULE_DESCRIPTION("Simple tuner device type database"); | ||
1651 | MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); | ||
1652 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/common/tuners/tuner-xc2028-types.h b/drivers/media/common/tuners/tuner-xc2028-types.h new file mode 100644 index 000000000000..74dc46a71f64 --- /dev/null +++ b/drivers/media/common/tuners/tuner-xc2028-types.h | |||
@@ -0,0 +1,141 @@ | |||
1 | /* tuner-xc2028_types | ||
2 | * | ||
3 | * This file includes internal tipes to be used inside tuner-xc2028. | ||
4 | * Shouldn't be included outside tuner-xc2028 | ||
5 | * | ||
6 | * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org) | ||
7 | * This code is placed under the terms of the GNU General Public License v2 | ||
8 | */ | ||
9 | |||
10 | /* xc3028 firmware types */ | ||
11 | |||
12 | /* BASE firmware should be loaded before any other firmware */ | ||
13 | #define BASE (1<<0) | ||
14 | #define BASE_TYPES (BASE|F8MHZ|MTS|FM|INPUT1|INPUT2|INIT1) | ||
15 | |||
16 | /* F8MHZ marks BASE firmwares for 8 MHz Bandwidth */ | ||
17 | #define F8MHZ (1<<1) | ||
18 | |||
19 | /* Multichannel Television Sound (MTS) | ||
20 | Those firmwares are capable of using xc2038 DSP to decode audio and | ||
21 | produce a baseband audio output on some pins of the chip. | ||
22 | There are MTS firmwares for the most used video standards. It should be | ||
23 | required to use MTS firmwares, depending on the way audio is routed into | ||
24 | the bridge chip | ||
25 | */ | ||
26 | #define MTS (1<<2) | ||
27 | |||
28 | /* FIXME: I have no idea what's the difference between | ||
29 | D2620 and D2633 firmwares | ||
30 | */ | ||
31 | #define D2620 (1<<3) | ||
32 | #define D2633 (1<<4) | ||
33 | |||
34 | /* DTV firmwares for 6, 7 and 8 MHz | ||
35 | DTV6 - 6MHz - ATSC/DVB-C/DVB-T/ISDB-T/DOCSIS | ||
36 | DTV8 - 8MHz - DVB-C/DVB-T | ||
37 | */ | ||
38 | #define DTV6 (1 << 5) | ||
39 | #define QAM (1 << 6) | ||
40 | #define DTV7 (1<<7) | ||
41 | #define DTV78 (1<<8) | ||
42 | #define DTV8 (1<<9) | ||
43 | |||
44 | #define DTV_TYPES (D2620|D2633|DTV6|QAM|DTV7|DTV78|DTV8|ATSC) | ||
45 | |||
46 | /* There's a FM | BASE firmware + FM specific firmware (std=0) */ | ||
47 | #define FM (1<<10) | ||
48 | |||
49 | #define STD_SPECIFIC_TYPES (MTS|FM|LCD|NOGD) | ||
50 | |||
51 | /* Applies only for FM firmware | ||
52 | Makes it use RF input 1 (pin #2) instead of input 2 (pin #4) | ||
53 | */ | ||
54 | #define INPUT1 (1<<11) | ||
55 | |||
56 | |||
57 | /* LCD firmwares exist only for MTS STD/MN (PAL or NTSC/M) | ||
58 | and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr) | ||
59 | There are variants both with and without NOGD | ||
60 | Those firmwares produce better result with LCD displays | ||
61 | */ | ||
62 | #define LCD (1<<12) | ||
63 | |||
64 | /* NOGD firmwares exist only for MTS STD/MN (PAL or NTSC/M) | ||
65 | and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr) | ||
66 | The NOGD firmwares don't have group delay compensation filter | ||
67 | */ | ||
68 | #define NOGD (1<<13) | ||
69 | |||
70 | /* Old firmwares were broken into init0 and init1 */ | ||
71 | #define INIT1 (1<<14) | ||
72 | |||
73 | /* SCODE firmware selects particular behaviours */ | ||
74 | #define MONO (1 << 15) | ||
75 | #define ATSC (1 << 16) | ||
76 | #define IF (1 << 17) | ||
77 | #define LG60 (1 << 18) | ||
78 | #define ATI638 (1 << 19) | ||
79 | #define OREN538 (1 << 20) | ||
80 | #define OREN36 (1 << 21) | ||
81 | #define TOYOTA388 (1 << 22) | ||
82 | #define TOYOTA794 (1 << 23) | ||
83 | #define DIBCOM52 (1 << 24) | ||
84 | #define ZARLINK456 (1 << 25) | ||
85 | #define CHINA (1 << 26) | ||
86 | #define F6MHZ (1 << 27) | ||
87 | #define INPUT2 (1 << 28) | ||
88 | #define SCODE (1 << 29) | ||
89 | |||
90 | /* This flag identifies that the scode table has a new format */ | ||
91 | #define HAS_IF (1 << 30) | ||
92 | |||
93 | /* There are different scode tables for MTS and non-MTS. | ||
94 | The MTS firmwares support mono only | ||
95 | */ | ||
96 | #define SCODE_TYPES (SCODE | MTS) | ||
97 | |||
98 | |||
99 | /* Newer types not defined on videodev2.h. | ||
100 | The original idea were to move all those types to videodev2.h, but | ||
101 | it seemed overkill, since, with the exception of SECAM/K3, the other | ||
102 | types seem to be autodetected. | ||
103 | It is not clear where secam/k3 is used, nor we have a feedback of this | ||
104 | working or being autodetected by the standard secam firmware. | ||
105 | */ | ||
106 | |||
107 | #define V4L2_STD_SECAM_K3 (0x04000000) | ||
108 | |||
109 | /* Audio types */ | ||
110 | |||
111 | #define V4L2_STD_A2_A (1LL<<32) | ||
112 | #define V4L2_STD_A2_B (1LL<<33) | ||
113 | #define V4L2_STD_NICAM_A (1LL<<34) | ||
114 | #define V4L2_STD_NICAM_B (1LL<<35) | ||
115 | #define V4L2_STD_AM (1LL<<36) | ||
116 | #define V4L2_STD_BTSC (1LL<<37) | ||
117 | #define V4L2_STD_EIAJ (1LL<<38) | ||
118 | |||
119 | #define V4L2_STD_A2 (V4L2_STD_A2_A | V4L2_STD_A2_B) | ||
120 | #define V4L2_STD_NICAM (V4L2_STD_NICAM_A | V4L2_STD_NICAM_B) | ||
121 | |||
122 | /* To preserve backward compatibilty, | ||
123 | (std & V4L2_STD_AUDIO) = 0 means that ALL audio stds are supported | ||
124 | */ | ||
125 | |||
126 | #define V4L2_STD_AUDIO (V4L2_STD_A2 | \ | ||
127 | V4L2_STD_NICAM | \ | ||
128 | V4L2_STD_AM | \ | ||
129 | V4L2_STD_BTSC | \ | ||
130 | V4L2_STD_EIAJ) | ||
131 | |||
132 | /* Used standards with audio restrictions */ | ||
133 | |||
134 | #define V4L2_STD_PAL_BG_A2_A (V4L2_STD_PAL_BG | V4L2_STD_A2_A) | ||
135 | #define V4L2_STD_PAL_BG_A2_B (V4L2_STD_PAL_BG | V4L2_STD_A2_B) | ||
136 | #define V4L2_STD_PAL_BG_NICAM_A (V4L2_STD_PAL_BG | V4L2_STD_NICAM_A) | ||
137 | #define V4L2_STD_PAL_BG_NICAM_B (V4L2_STD_PAL_BG | V4L2_STD_NICAM_B) | ||
138 | #define V4L2_STD_PAL_DK_A2 (V4L2_STD_PAL_DK | V4L2_STD_A2) | ||
139 | #define V4L2_STD_PAL_DK_NICAM (V4L2_STD_PAL_DK | V4L2_STD_NICAM) | ||
140 | #define V4L2_STD_SECAM_L_NICAM (V4L2_STD_SECAM_L | V4L2_STD_NICAM) | ||
141 | #define V4L2_STD_SECAM_L_AM (V4L2_STD_SECAM_L | V4L2_STD_AM) | ||
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c new file mode 100644 index 000000000000..9e9003cffc7f --- /dev/null +++ b/drivers/media/common/tuners/tuner-xc2028.c | |||
@@ -0,0 +1,1227 @@ | |||
1 | /* tuner-xc2028 | ||
2 | * | ||
3 | * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org) | ||
4 | * | ||
5 | * Copyright (c) 2007 Michel Ludwig (michel.ludwig@gmail.com) | ||
6 | * - frontend interface | ||
7 | * | ||
8 | * This code is placed under the terms of the GNU General Public License v2 | ||
9 | */ | ||
10 | |||
11 | #include <linux/i2c.h> | ||
12 | #include <asm/div64.h> | ||
13 | #include <linux/firmware.h> | ||
14 | #include <linux/videodev2.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <media/tuner.h> | ||
17 | #include <linux/mutex.h> | ||
18 | #include "tuner-i2c.h" | ||
19 | #include "tuner-xc2028.h" | ||
20 | #include "tuner-xc2028-types.h" | ||
21 | |||
22 | #include <linux/dvb/frontend.h> | ||
23 | #include "dvb_frontend.h" | ||
24 | |||
25 | |||
26 | static int debug; | ||
27 | module_param(debug, int, 0644); | ||
28 | MODULE_PARM_DESC(debug, "enable verbose debug messages"); | ||
29 | |||
30 | static char audio_std[8]; | ||
31 | module_param_string(audio_std, audio_std, sizeof(audio_std), 0); | ||
32 | MODULE_PARM_DESC(audio_std, | ||
33 | "Audio standard. XC3028 audio decoder explicitly " | ||
34 | "needs to know what audio\n" | ||
35 | "standard is needed for some video standards with audio A2 or NICAM.\n" | ||
36 | "The valid values are:\n" | ||
37 | "A2\n" | ||
38 | "A2/A\n" | ||
39 | "A2/B\n" | ||
40 | "NICAM\n" | ||
41 | "NICAM/A\n" | ||
42 | "NICAM/B\n"); | ||
43 | |||
44 | static char firmware_name[FIRMWARE_NAME_MAX]; | ||
45 | module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0); | ||
46 | MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the " | ||
47 | "default firmware name\n"); | ||
48 | |||
49 | static LIST_HEAD(xc2028_list); | ||
50 | static DEFINE_MUTEX(xc2028_list_mutex); | ||
51 | |||
52 | /* struct for storing firmware table */ | ||
53 | struct firmware_description { | ||
54 | unsigned int type; | ||
55 | v4l2_std_id id; | ||
56 | __u16 int_freq; | ||
57 | unsigned char *ptr; | ||
58 | unsigned int size; | ||
59 | }; | ||
60 | |||
61 | struct firmware_properties { | ||
62 | unsigned int type; | ||
63 | v4l2_std_id id; | ||
64 | v4l2_std_id std_req; | ||
65 | __u16 int_freq; | ||
66 | unsigned int scode_table; | ||
67 | int scode_nr; | ||
68 | }; | ||
69 | |||
70 | struct xc2028_data { | ||
71 | struct list_head xc2028_list; | ||
72 | struct tuner_i2c_props i2c_props; | ||
73 | int (*tuner_callback) (void *dev, | ||
74 | int command, int arg); | ||
75 | void *video_dev; | ||
76 | int count; | ||
77 | __u32 frequency; | ||
78 | |||
79 | struct firmware_description *firm; | ||
80 | int firm_size; | ||
81 | __u16 firm_version; | ||
82 | |||
83 | __u16 hwmodel; | ||
84 | __u16 hwvers; | ||
85 | |||
86 | struct xc2028_ctrl ctrl; | ||
87 | |||
88 | struct firmware_properties cur_fw; | ||
89 | |||
90 | struct mutex lock; | ||
91 | }; | ||
92 | |||
93 | #define i2c_send(priv, buf, size) ({ \ | ||
94 | int _rc; \ | ||
95 | _rc = tuner_i2c_xfer_send(&priv->i2c_props, buf, size); \ | ||
96 | if (size != _rc) \ | ||
97 | tuner_info("i2c output error: rc = %d (should be %d)\n",\ | ||
98 | _rc, (int)size); \ | ||
99 | _rc; \ | ||
100 | }) | ||
101 | |||
102 | #define i2c_rcv(priv, buf, size) ({ \ | ||
103 | int _rc; \ | ||
104 | _rc = tuner_i2c_xfer_recv(&priv->i2c_props, buf, size); \ | ||
105 | if (size != _rc) \ | ||
106 | tuner_err("i2c input error: rc = %d (should be %d)\n", \ | ||
107 | _rc, (int)size); \ | ||
108 | _rc; \ | ||
109 | }) | ||
110 | |||
111 | #define i2c_send_recv(priv, obuf, osize, ibuf, isize) ({ \ | ||
112 | int _rc; \ | ||
113 | _rc = tuner_i2c_xfer_send_recv(&priv->i2c_props, obuf, osize, \ | ||
114 | ibuf, isize); \ | ||
115 | if (isize != _rc) \ | ||
116 | tuner_err("i2c input error: rc = %d (should be %d)\n", \ | ||
117 | _rc, (int)isize); \ | ||
118 | _rc; \ | ||
119 | }) | ||
120 | |||
121 | #define send_seq(priv, data...) ({ \ | ||
122 | static u8 _val[] = data; \ | ||
123 | int _rc; \ | ||
124 | if (sizeof(_val) != \ | ||
125 | (_rc = tuner_i2c_xfer_send(&priv->i2c_props, \ | ||
126 | _val, sizeof(_val)))) { \ | ||
127 | tuner_err("Error on line %d: %d\n", __LINE__, _rc); \ | ||
128 | } else \ | ||
129 | msleep(10); \ | ||
130 | _rc; \ | ||
131 | }) | ||
132 | |||
133 | static int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val) | ||
134 | { | ||
135 | unsigned char buf[2]; | ||
136 | unsigned char ibuf[2]; | ||
137 | |||
138 | tuner_dbg("%s %04x called\n", __func__, reg); | ||
139 | |||
140 | buf[0] = reg >> 8; | ||
141 | buf[1] = (unsigned char) reg; | ||
142 | |||
143 | if (i2c_send_recv(priv, buf, 2, ibuf, 2) != 2) | ||
144 | return -EIO; | ||
145 | |||
146 | *val = (ibuf[1]) | (ibuf[0] << 8); | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | #define dump_firm_type(t) dump_firm_type_and_int_freq(t, 0) | ||
151 | static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq) | ||
152 | { | ||
153 | if (type & BASE) | ||
154 | printk("BASE "); | ||
155 | if (type & INIT1) | ||
156 | printk("INIT1 "); | ||
157 | if (type & F8MHZ) | ||
158 | printk("F8MHZ "); | ||
159 | if (type & MTS) | ||
160 | printk("MTS "); | ||
161 | if (type & D2620) | ||
162 | printk("D2620 "); | ||
163 | if (type & D2633) | ||
164 | printk("D2633 "); | ||
165 | if (type & DTV6) | ||
166 | printk("DTV6 "); | ||
167 | if (type & QAM) | ||
168 | printk("QAM "); | ||
169 | if (type & DTV7) | ||
170 | printk("DTV7 "); | ||
171 | if (type & DTV78) | ||
172 | printk("DTV78 "); | ||
173 | if (type & DTV8) | ||
174 | printk("DTV8 "); | ||
175 | if (type & FM) | ||
176 | printk("FM "); | ||
177 | if (type & INPUT1) | ||
178 | printk("INPUT1 "); | ||
179 | if (type & LCD) | ||
180 | printk("LCD "); | ||
181 | if (type & NOGD) | ||
182 | printk("NOGD "); | ||
183 | if (type & MONO) | ||
184 | printk("MONO "); | ||
185 | if (type & ATSC) | ||
186 | printk("ATSC "); | ||
187 | if (type & IF) | ||
188 | printk("IF "); | ||
189 | if (type & LG60) | ||
190 | printk("LG60 "); | ||
191 | if (type & ATI638) | ||
192 | printk("ATI638 "); | ||
193 | if (type & OREN538) | ||
194 | printk("OREN538 "); | ||
195 | if (type & OREN36) | ||
196 | printk("OREN36 "); | ||
197 | if (type & TOYOTA388) | ||
198 | printk("TOYOTA388 "); | ||
199 | if (type & TOYOTA794) | ||
200 | printk("TOYOTA794 "); | ||
201 | if (type & DIBCOM52) | ||
202 | printk("DIBCOM52 "); | ||
203 | if (type & ZARLINK456) | ||
204 | printk("ZARLINK456 "); | ||
205 | if (type & CHINA) | ||
206 | printk("CHINA "); | ||
207 | if (type & F6MHZ) | ||
208 | printk("F6MHZ "); | ||
209 | if (type & INPUT2) | ||
210 | printk("INPUT2 "); | ||
211 | if (type & SCODE) | ||
212 | printk("SCODE "); | ||
213 | if (type & HAS_IF) | ||
214 | printk("HAS_IF_%d ", int_freq); | ||
215 | } | ||
216 | |||
217 | static v4l2_std_id parse_audio_std_option(void) | ||
218 | { | ||
219 | if (strcasecmp(audio_std, "A2") == 0) | ||
220 | return V4L2_STD_A2; | ||
221 | if (strcasecmp(audio_std, "A2/A") == 0) | ||
222 | return V4L2_STD_A2_A; | ||
223 | if (strcasecmp(audio_std, "A2/B") == 0) | ||
224 | return V4L2_STD_A2_B; | ||
225 | if (strcasecmp(audio_std, "NICAM") == 0) | ||
226 | return V4L2_STD_NICAM; | ||
227 | if (strcasecmp(audio_std, "NICAM/A") == 0) | ||
228 | return V4L2_STD_NICAM_A; | ||
229 | if (strcasecmp(audio_std, "NICAM/B") == 0) | ||
230 | return V4L2_STD_NICAM_B; | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static void free_firmware(struct xc2028_data *priv) | ||
236 | { | ||
237 | int i; | ||
238 | tuner_dbg("%s called\n", __func__); | ||
239 | |||
240 | if (!priv->firm) | ||
241 | return; | ||
242 | |||
243 | for (i = 0; i < priv->firm_size; i++) | ||
244 | kfree(priv->firm[i].ptr); | ||
245 | |||
246 | kfree(priv->firm); | ||
247 | |||
248 | priv->firm = NULL; | ||
249 | priv->firm_size = 0; | ||
250 | |||
251 | memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); | ||
252 | } | ||
253 | |||
254 | static int load_all_firmwares(struct dvb_frontend *fe) | ||
255 | { | ||
256 | struct xc2028_data *priv = fe->tuner_priv; | ||
257 | const struct firmware *fw = NULL; | ||
258 | unsigned char *p, *endp; | ||
259 | int rc = 0; | ||
260 | int n, n_array; | ||
261 | char name[33]; | ||
262 | char *fname; | ||
263 | |||
264 | tuner_dbg("%s called\n", __func__); | ||
265 | |||
266 | if (!firmware_name[0]) | ||
267 | fname = priv->ctrl.fname; | ||
268 | else | ||
269 | fname = firmware_name; | ||
270 | |||
271 | tuner_dbg("Reading firmware %s\n", fname); | ||
272 | rc = request_firmware(&fw, fname, &priv->i2c_props.adap->dev); | ||
273 | if (rc < 0) { | ||
274 | if (rc == -ENOENT) | ||
275 | tuner_err("Error: firmware %s not found.\n", | ||
276 | fname); | ||
277 | else | ||
278 | tuner_err("Error %d while requesting firmware %s \n", | ||
279 | rc, fname); | ||
280 | |||
281 | return rc; | ||
282 | } | ||
283 | p = fw->data; | ||
284 | endp = p + fw->size; | ||
285 | |||
286 | if (fw->size < sizeof(name) - 1 + 2 + 2) { | ||
287 | tuner_err("Error: firmware file %s has invalid size!\n", | ||
288 | fname); | ||
289 | goto corrupt; | ||
290 | } | ||
291 | |||
292 | memcpy(name, p, sizeof(name) - 1); | ||
293 | name[sizeof(name) - 1] = 0; | ||
294 | p += sizeof(name) - 1; | ||
295 | |||
296 | priv->firm_version = le16_to_cpu(*(__u16 *) p); | ||
297 | p += 2; | ||
298 | |||
299 | n_array = le16_to_cpu(*(__u16 *) p); | ||
300 | p += 2; | ||
301 | |||
302 | tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n", | ||
303 | n_array, fname, name, | ||
304 | priv->firm_version >> 8, priv->firm_version & 0xff); | ||
305 | |||
306 | priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL); | ||
307 | if (priv->firm == NULL) { | ||
308 | tuner_err("Not enough memory to load firmware file.\n"); | ||
309 | rc = -ENOMEM; | ||
310 | goto err; | ||
311 | } | ||
312 | priv->firm_size = n_array; | ||
313 | |||
314 | n = -1; | ||
315 | while (p < endp) { | ||
316 | __u32 type, size; | ||
317 | v4l2_std_id id; | ||
318 | __u16 int_freq = 0; | ||
319 | |||
320 | n++; | ||
321 | if (n >= n_array) { | ||
322 | tuner_err("More firmware images in file than " | ||
323 | "were expected!\n"); | ||
324 | goto corrupt; | ||
325 | } | ||
326 | |||
327 | /* Checks if there's enough bytes to read */ | ||
328 | if (p + sizeof(type) + sizeof(id) + sizeof(size) > endp) { | ||
329 | tuner_err("Firmware header is incomplete!\n"); | ||
330 | goto corrupt; | ||
331 | } | ||
332 | |||
333 | type = le32_to_cpu(*(__u32 *) p); | ||
334 | p += sizeof(type); | ||
335 | |||
336 | id = le64_to_cpu(*(v4l2_std_id *) p); | ||
337 | p += sizeof(id); | ||
338 | |||
339 | if (type & HAS_IF) { | ||
340 | int_freq = le16_to_cpu(*(__u16 *) p); | ||
341 | p += sizeof(int_freq); | ||
342 | } | ||
343 | |||
344 | size = le32_to_cpu(*(__u32 *) p); | ||
345 | p += sizeof(size); | ||
346 | |||
347 | if ((!size) || (size + p > endp)) { | ||
348 | tuner_err("Firmware type "); | ||
349 | dump_firm_type(type); | ||
350 | printk("(%x), id %llx is corrupted " | ||
351 | "(size=%d, expected %d)\n", | ||
352 | type, (unsigned long long)id, | ||
353 | (unsigned)(endp - p), size); | ||
354 | goto corrupt; | ||
355 | } | ||
356 | |||
357 | priv->firm[n].ptr = kzalloc(size, GFP_KERNEL); | ||
358 | if (priv->firm[n].ptr == NULL) { | ||
359 | tuner_err("Not enough memory to load firmware file.\n"); | ||
360 | rc = -ENOMEM; | ||
361 | goto err; | ||
362 | } | ||
363 | tuner_dbg("Reading firmware type "); | ||
364 | if (debug) { | ||
365 | dump_firm_type_and_int_freq(type, int_freq); | ||
366 | printk("(%x), id %llx, size=%d.\n", | ||
367 | type, (unsigned long long)id, size); | ||
368 | } | ||
369 | |||
370 | memcpy(priv->firm[n].ptr, p, size); | ||
371 | priv->firm[n].type = type; | ||
372 | priv->firm[n].id = id; | ||
373 | priv->firm[n].size = size; | ||
374 | priv->firm[n].int_freq = int_freq; | ||
375 | |||
376 | p += size; | ||
377 | } | ||
378 | |||
379 | if (n + 1 != priv->firm_size) { | ||
380 | tuner_err("Firmware file is incomplete!\n"); | ||
381 | goto corrupt; | ||
382 | } | ||
383 | |||
384 | goto done; | ||
385 | |||
386 | corrupt: | ||
387 | rc = -EINVAL; | ||
388 | tuner_err("Error: firmware file is corrupted!\n"); | ||
389 | |||
390 | err: | ||
391 | tuner_info("Releasing partially loaded firmware file.\n"); | ||
392 | free_firmware(priv); | ||
393 | |||
394 | done: | ||
395 | release_firmware(fw); | ||
396 | if (rc == 0) | ||
397 | tuner_dbg("Firmware files loaded.\n"); | ||
398 | |||
399 | return rc; | ||
400 | } | ||
401 | |||
402 | static int seek_firmware(struct dvb_frontend *fe, unsigned int type, | ||
403 | v4l2_std_id *id) | ||
404 | { | ||
405 | struct xc2028_data *priv = fe->tuner_priv; | ||
406 | int i, best_i = -1, best_nr_matches = 0; | ||
407 | unsigned int type_mask = 0; | ||
408 | |||
409 | tuner_dbg("%s called, want type=", __func__); | ||
410 | if (debug) { | ||
411 | dump_firm_type(type); | ||
412 | printk("(%x), id %016llx.\n", type, (unsigned long long)*id); | ||
413 | } | ||
414 | |||
415 | if (!priv->firm) { | ||
416 | tuner_err("Error! firmware not loaded\n"); | ||
417 | return -EINVAL; | ||
418 | } | ||
419 | |||
420 | if (((type & ~SCODE) == 0) && (*id == 0)) | ||
421 | *id = V4L2_STD_PAL; | ||
422 | |||
423 | if (type & BASE) | ||
424 | type_mask = BASE_TYPES; | ||
425 | else if (type & SCODE) { | ||
426 | type &= SCODE_TYPES; | ||
427 | type_mask = SCODE_TYPES & ~HAS_IF; | ||
428 | } else if (type & DTV_TYPES) | ||
429 | type_mask = DTV_TYPES; | ||
430 | else if (type & STD_SPECIFIC_TYPES) | ||
431 | type_mask = STD_SPECIFIC_TYPES; | ||
432 | |||
433 | type &= type_mask; | ||
434 | |||
435 | if (!(type & SCODE)) | ||
436 | type_mask = ~0; | ||
437 | |||
438 | /* Seek for exact match */ | ||
439 | for (i = 0; i < priv->firm_size; i++) { | ||
440 | if ((type == (priv->firm[i].type & type_mask)) && | ||
441 | (*id == priv->firm[i].id)) | ||
442 | goto found; | ||
443 | } | ||
444 | |||
445 | /* Seek for generic video standard match */ | ||
446 | for (i = 0; i < priv->firm_size; i++) { | ||
447 | v4l2_std_id match_mask; | ||
448 | int nr_matches; | ||
449 | |||
450 | if (type != (priv->firm[i].type & type_mask)) | ||
451 | continue; | ||
452 | |||
453 | match_mask = *id & priv->firm[i].id; | ||
454 | if (!match_mask) | ||
455 | continue; | ||
456 | |||
457 | if ((*id & match_mask) == *id) | ||
458 | goto found; /* Supports all the requested standards */ | ||
459 | |||
460 | nr_matches = hweight64(match_mask); | ||
461 | if (nr_matches > best_nr_matches) { | ||
462 | best_nr_matches = nr_matches; | ||
463 | best_i = i; | ||
464 | } | ||
465 | } | ||
466 | |||
467 | if (best_nr_matches > 0) { | ||
468 | tuner_dbg("Selecting best matching firmware (%d bits) for " | ||
469 | "type=", best_nr_matches); | ||
470 | dump_firm_type(type); | ||
471 | printk("(%x), id %016llx:\n", type, (unsigned long long)*id); | ||
472 | i = best_i; | ||
473 | goto found; | ||
474 | } | ||
475 | |||
476 | /*FIXME: Would make sense to seek for type "hint" match ? */ | ||
477 | |||
478 | i = -ENOENT; | ||
479 | goto ret; | ||
480 | |||
481 | found: | ||
482 | *id = priv->firm[i].id; | ||
483 | |||
484 | ret: | ||
485 | tuner_dbg("%s firmware for type=", (i < 0) ? "Can't find" : "Found"); | ||
486 | if (debug) { | ||
487 | dump_firm_type(type); | ||
488 | printk("(%x), id %016llx.\n", type, (unsigned long long)*id); | ||
489 | } | ||
490 | return i; | ||
491 | } | ||
492 | |||
493 | static int load_firmware(struct dvb_frontend *fe, unsigned int type, | ||
494 | v4l2_std_id *id) | ||
495 | { | ||
496 | struct xc2028_data *priv = fe->tuner_priv; | ||
497 | int pos, rc; | ||
498 | unsigned char *p, *endp, buf[priv->ctrl.max_len]; | ||
499 | |||
500 | tuner_dbg("%s called\n", __func__); | ||
501 | |||
502 | pos = seek_firmware(fe, type, id); | ||
503 | if (pos < 0) | ||
504 | return pos; | ||
505 | |||
506 | tuner_info("Loading firmware for type="); | ||
507 | dump_firm_type(priv->firm[pos].type); | ||
508 | printk("(%x), id %016llx.\n", priv->firm[pos].type, | ||
509 | (unsigned long long)*id); | ||
510 | |||
511 | p = priv->firm[pos].ptr; | ||
512 | endp = p + priv->firm[pos].size; | ||
513 | |||
514 | while (p < endp) { | ||
515 | __u16 size; | ||
516 | |||
517 | /* Checks if there's enough bytes to read */ | ||
518 | if (p + sizeof(size) > endp) { | ||
519 | tuner_err("Firmware chunk size is wrong\n"); | ||
520 | return -EINVAL; | ||
521 | } | ||
522 | |||
523 | size = le16_to_cpu(*(__u16 *) p); | ||
524 | p += sizeof(size); | ||
525 | |||
526 | if (size == 0xffff) | ||
527 | return 0; | ||
528 | |||
529 | if (!size) { | ||
530 | /* Special callback command received */ | ||
531 | rc = priv->tuner_callback(priv->video_dev, | ||
532 | XC2028_TUNER_RESET, 0); | ||
533 | if (rc < 0) { | ||
534 | tuner_err("Error at RESET code %d\n", | ||
535 | (*p) & 0x7f); | ||
536 | return -EINVAL; | ||
537 | } | ||
538 | continue; | ||
539 | } | ||
540 | if (size >= 0xff00) { | ||
541 | switch (size) { | ||
542 | case 0xff00: | ||
543 | rc = priv->tuner_callback(priv->video_dev, | ||
544 | XC2028_RESET_CLK, 0); | ||
545 | if (rc < 0) { | ||
546 | tuner_err("Error at RESET code %d\n", | ||
547 | (*p) & 0x7f); | ||
548 | return -EINVAL; | ||
549 | } | ||
550 | break; | ||
551 | default: | ||
552 | tuner_info("Invalid RESET code %d\n", | ||
553 | size & 0x7f); | ||
554 | return -EINVAL; | ||
555 | |||
556 | } | ||
557 | continue; | ||
558 | } | ||
559 | |||
560 | /* Checks for a sleep command */ | ||
561 | if (size & 0x8000) { | ||
562 | msleep(size & 0x7fff); | ||
563 | continue; | ||
564 | } | ||
565 | |||
566 | if ((size + p > endp)) { | ||
567 | tuner_err("missing bytes: need %d, have %d\n", | ||
568 | size, (int)(endp - p)); | ||
569 | return -EINVAL; | ||
570 | } | ||
571 | |||
572 | buf[0] = *p; | ||
573 | p++; | ||
574 | size--; | ||
575 | |||
576 | /* Sends message chunks */ | ||
577 | while (size > 0) { | ||
578 | int len = (size < priv->ctrl.max_len - 1) ? | ||
579 | size : priv->ctrl.max_len - 1; | ||
580 | |||
581 | memcpy(buf + 1, p, len); | ||
582 | |||
583 | rc = i2c_send(priv, buf, len + 1); | ||
584 | if (rc < 0) { | ||
585 | tuner_err("%d returned from send\n", rc); | ||
586 | return -EINVAL; | ||
587 | } | ||
588 | |||
589 | p += len; | ||
590 | size -= len; | ||
591 | } | ||
592 | } | ||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | static int load_scode(struct dvb_frontend *fe, unsigned int type, | ||
597 | v4l2_std_id *id, __u16 int_freq, int scode) | ||
598 | { | ||
599 | struct xc2028_data *priv = fe->tuner_priv; | ||
600 | int pos, rc; | ||
601 | unsigned char *p; | ||
602 | |||
603 | tuner_dbg("%s called\n", __func__); | ||
604 | |||
605 | if (!int_freq) { | ||
606 | pos = seek_firmware(fe, type, id); | ||
607 | if (pos < 0) | ||
608 | return pos; | ||
609 | } else { | ||
610 | for (pos = 0; pos < priv->firm_size; pos++) { | ||
611 | if ((priv->firm[pos].int_freq == int_freq) && | ||
612 | (priv->firm[pos].type & HAS_IF)) | ||
613 | break; | ||
614 | } | ||
615 | if (pos == priv->firm_size) | ||
616 | return -ENOENT; | ||
617 | } | ||
618 | |||
619 | p = priv->firm[pos].ptr; | ||
620 | |||
621 | if (priv->firm[pos].type & HAS_IF) { | ||
622 | if (priv->firm[pos].size != 12 * 16 || scode >= 16) | ||
623 | return -EINVAL; | ||
624 | p += 12 * scode; | ||
625 | } else { | ||
626 | /* 16 SCODE entries per file; each SCODE entry is 12 bytes and | ||
627 | * has a 2-byte size header in the firmware format. */ | ||
628 | if (priv->firm[pos].size != 14 * 16 || scode >= 16 || | ||
629 | le16_to_cpu(*(__u16 *)(p + 14 * scode)) != 12) | ||
630 | return -EINVAL; | ||
631 | p += 14 * scode + 2; | ||
632 | } | ||
633 | |||
634 | tuner_info("Loading SCODE for type="); | ||
635 | dump_firm_type_and_int_freq(priv->firm[pos].type, | ||
636 | priv->firm[pos].int_freq); | ||
637 | printk("(%x), id %016llx.\n", priv->firm[pos].type, | ||
638 | (unsigned long long)*id); | ||
639 | |||
640 | if (priv->firm_version < 0x0202) | ||
641 | rc = send_seq(priv, {0x20, 0x00, 0x00, 0x00}); | ||
642 | else | ||
643 | rc = send_seq(priv, {0xa0, 0x00, 0x00, 0x00}); | ||
644 | if (rc < 0) | ||
645 | return -EIO; | ||
646 | |||
647 | rc = i2c_send(priv, p, 12); | ||
648 | if (rc < 0) | ||
649 | return -EIO; | ||
650 | |||
651 | rc = send_seq(priv, {0x00, 0x8c}); | ||
652 | if (rc < 0) | ||
653 | return -EIO; | ||
654 | |||
655 | return 0; | ||
656 | } | ||
657 | |||
658 | static int check_firmware(struct dvb_frontend *fe, unsigned int type, | ||
659 | v4l2_std_id std, __u16 int_freq) | ||
660 | { | ||
661 | struct xc2028_data *priv = fe->tuner_priv; | ||
662 | struct firmware_properties new_fw; | ||
663 | int rc = 0, is_retry = 0; | ||
664 | u16 version, hwmodel; | ||
665 | v4l2_std_id std0; | ||
666 | |||
667 | tuner_dbg("%s called\n", __func__); | ||
668 | |||
669 | if (!priv->firm) { | ||
670 | if (!priv->ctrl.fname) { | ||
671 | tuner_info("xc2028/3028 firmware name not set!\n"); | ||
672 | return -EINVAL; | ||
673 | } | ||
674 | |||
675 | rc = load_all_firmwares(fe); | ||
676 | if (rc < 0) | ||
677 | return rc; | ||
678 | } | ||
679 | |||
680 | if (priv->ctrl.mts && !(type & FM)) | ||
681 | type |= MTS; | ||
682 | |||
683 | retry: | ||
684 | new_fw.type = type; | ||
685 | new_fw.id = std; | ||
686 | new_fw.std_req = std; | ||
687 | new_fw.scode_table = SCODE | priv->ctrl.scode_table; | ||
688 | new_fw.scode_nr = 0; | ||
689 | new_fw.int_freq = int_freq; | ||
690 | |||
691 | tuner_dbg("checking firmware, user requested type="); | ||
692 | if (debug) { | ||
693 | dump_firm_type(new_fw.type); | ||
694 | printk("(%x), id %016llx, ", new_fw.type, | ||
695 | (unsigned long long)new_fw.std_req); | ||
696 | if (!int_freq) { | ||
697 | printk("scode_tbl "); | ||
698 | dump_firm_type(priv->ctrl.scode_table); | ||
699 | printk("(%x), ", priv->ctrl.scode_table); | ||
700 | } else | ||
701 | printk("int_freq %d, ", new_fw.int_freq); | ||
702 | printk("scode_nr %d\n", new_fw.scode_nr); | ||
703 | } | ||
704 | |||
705 | /* No need to reload base firmware if it matches */ | ||
706 | if (((BASE | new_fw.type) & BASE_TYPES) == | ||
707 | (priv->cur_fw.type & BASE_TYPES)) { | ||
708 | tuner_dbg("BASE firmware not changed.\n"); | ||
709 | goto skip_base; | ||
710 | } | ||
711 | |||
712 | /* Updating BASE - forget about all currently loaded firmware */ | ||
713 | memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); | ||
714 | |||
715 | /* Reset is needed before loading firmware */ | ||
716 | rc = priv->tuner_callback(priv->video_dev, | ||
717 | XC2028_TUNER_RESET, 0); | ||
718 | if (rc < 0) | ||
719 | goto fail; | ||
720 | |||
721 | /* BASE firmwares are all std0 */ | ||
722 | std0 = 0; | ||
723 | rc = load_firmware(fe, BASE | new_fw.type, &std0); | ||
724 | if (rc < 0) { | ||
725 | tuner_err("Error %d while loading base firmware\n", | ||
726 | rc); | ||
727 | goto fail; | ||
728 | } | ||
729 | |||
730 | /* Load INIT1, if needed */ | ||
731 | tuner_dbg("Load init1 firmware, if exists\n"); | ||
732 | |||
733 | rc = load_firmware(fe, BASE | INIT1 | new_fw.type, &std0); | ||
734 | if (rc == -ENOENT) | ||
735 | rc = load_firmware(fe, (BASE | INIT1 | new_fw.type) & ~F8MHZ, | ||
736 | &std0); | ||
737 | if (rc < 0 && rc != -ENOENT) { | ||
738 | tuner_err("Error %d while loading init1 firmware\n", | ||
739 | rc); | ||
740 | goto fail; | ||
741 | } | ||
742 | |||
743 | skip_base: | ||
744 | /* | ||
745 | * No need to reload standard specific firmware if base firmware | ||
746 | * was not reloaded and requested video standards have not changed. | ||
747 | */ | ||
748 | if (priv->cur_fw.type == (BASE | new_fw.type) && | ||
749 | priv->cur_fw.std_req == std) { | ||
750 | tuner_dbg("Std-specific firmware already loaded.\n"); | ||
751 | goto skip_std_specific; | ||
752 | } | ||
753 | |||
754 | /* Reloading std-specific firmware forces a SCODE update */ | ||
755 | priv->cur_fw.scode_table = 0; | ||
756 | |||
757 | rc = load_firmware(fe, new_fw.type, &new_fw.id); | ||
758 | if (rc == -ENOENT) | ||
759 | rc = load_firmware(fe, new_fw.type & ~F8MHZ, &new_fw.id); | ||
760 | |||
761 | if (rc < 0) | ||
762 | goto fail; | ||
763 | |||
764 | skip_std_specific: | ||
765 | if (priv->cur_fw.scode_table == new_fw.scode_table && | ||
766 | priv->cur_fw.scode_nr == new_fw.scode_nr) { | ||
767 | tuner_dbg("SCODE firmware already loaded.\n"); | ||
768 | goto check_device; | ||
769 | } | ||
770 | |||
771 | if (new_fw.type & FM) | ||
772 | goto check_device; | ||
773 | |||
774 | /* Load SCODE firmware, if exists */ | ||
775 | tuner_dbg("Trying to load scode %d\n", new_fw.scode_nr); | ||
776 | |||
777 | rc = load_scode(fe, new_fw.type | new_fw.scode_table, &new_fw.id, | ||
778 | new_fw.int_freq, new_fw.scode_nr); | ||
779 | |||
780 | check_device: | ||
781 | if (xc2028_get_reg(priv, 0x0004, &version) < 0 || | ||
782 | xc2028_get_reg(priv, 0x0008, &hwmodel) < 0) { | ||
783 | tuner_err("Unable to read tuner registers.\n"); | ||
784 | goto fail; | ||
785 | } | ||
786 | |||
787 | tuner_dbg("Device is Xceive %d version %d.%d, " | ||
788 | "firmware version %d.%d\n", | ||
789 | hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8, | ||
790 | (version & 0xf0) >> 4, version & 0xf); | ||
791 | |||
792 | /* Check firmware version against what we downloaded. */ | ||
793 | if (priv->firm_version != ((version & 0xf0) << 4 | (version & 0x0f))) { | ||
794 | tuner_err("Incorrect readback of firmware version.\n"); | ||
795 | goto fail; | ||
796 | } | ||
797 | |||
798 | /* Check that the tuner hardware model remains consistent over time. */ | ||
799 | if (priv->hwmodel == 0 && (hwmodel == 2028 || hwmodel == 3028)) { | ||
800 | priv->hwmodel = hwmodel; | ||
801 | priv->hwvers = version & 0xff00; | ||
802 | } else if (priv->hwmodel == 0 || priv->hwmodel != hwmodel || | ||
803 | priv->hwvers != (version & 0xff00)) { | ||
804 | tuner_err("Read invalid device hardware information - tuner " | ||
805 | "hung?\n"); | ||
806 | goto fail; | ||
807 | } | ||
808 | |||
809 | memcpy(&priv->cur_fw, &new_fw, sizeof(priv->cur_fw)); | ||
810 | |||
811 | /* | ||
812 | * By setting BASE in cur_fw.type only after successfully loading all | ||
813 | * firmwares, we can: | ||
814 | * 1. Identify that BASE firmware with type=0 has been loaded; | ||
815 | * 2. Tell whether BASE firmware was just changed the next time through. | ||
816 | */ | ||
817 | priv->cur_fw.type |= BASE; | ||
818 | |||
819 | return 0; | ||
820 | |||
821 | fail: | ||
822 | memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); | ||
823 | if (!is_retry) { | ||
824 | msleep(50); | ||
825 | is_retry = 1; | ||
826 | tuner_dbg("Retrying firmware load\n"); | ||
827 | goto retry; | ||
828 | } | ||
829 | |||
830 | if (rc == -ENOENT) | ||
831 | rc = -EINVAL; | ||
832 | return rc; | ||
833 | } | ||
834 | |||
835 | static int xc2028_signal(struct dvb_frontend *fe, u16 *strength) | ||
836 | { | ||
837 | struct xc2028_data *priv = fe->tuner_priv; | ||
838 | u16 frq_lock, signal = 0; | ||
839 | int rc; | ||
840 | |||
841 | tuner_dbg("%s called\n", __func__); | ||
842 | |||
843 | mutex_lock(&priv->lock); | ||
844 | |||
845 | /* Sync Lock Indicator */ | ||
846 | rc = xc2028_get_reg(priv, 0x0002, &frq_lock); | ||
847 | if (rc < 0) | ||
848 | goto ret; | ||
849 | |||
850 | /* Frequency is locked */ | ||
851 | if (frq_lock == 1) | ||
852 | signal = 32768; | ||
853 | |||
854 | /* Get SNR of the video signal */ | ||
855 | rc = xc2028_get_reg(priv, 0x0040, &signal); | ||
856 | if (rc < 0) | ||
857 | goto ret; | ||
858 | |||
859 | /* Use both frq_lock and signal to generate the result */ | ||
860 | signal = signal || ((signal & 0x07) << 12); | ||
861 | |||
862 | ret: | ||
863 | mutex_unlock(&priv->lock); | ||
864 | |||
865 | *strength = signal; | ||
866 | |||
867 | tuner_dbg("signal strength is %d\n", signal); | ||
868 | |||
869 | return rc; | ||
870 | } | ||
871 | |||
872 | #define DIV 15625 | ||
873 | |||
874 | static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, | ||
875 | enum tuner_mode new_mode, | ||
876 | unsigned int type, | ||
877 | v4l2_std_id std, | ||
878 | u16 int_freq) | ||
879 | { | ||
880 | struct xc2028_data *priv = fe->tuner_priv; | ||
881 | int rc = -EINVAL; | ||
882 | unsigned char buf[4]; | ||
883 | u32 div, offset = 0; | ||
884 | |||
885 | tuner_dbg("%s called\n", __func__); | ||
886 | |||
887 | mutex_lock(&priv->lock); | ||
888 | |||
889 | tuner_dbg("should set frequency %d kHz\n", freq / 1000); | ||
890 | |||
891 | if (check_firmware(fe, type, std, int_freq) < 0) | ||
892 | goto ret; | ||
893 | |||
894 | /* On some cases xc2028 can disable video output, if | ||
895 | * very weak signals are received. By sending a soft | ||
896 | * reset, this is re-enabled. So, it is better to always | ||
897 | * send a soft reset before changing channels, to be sure | ||
898 | * that xc2028 will be in a safe state. | ||
899 | * Maybe this might also be needed for DTV. | ||
900 | */ | ||
901 | if (new_mode == T_ANALOG_TV) { | ||
902 | rc = send_seq(priv, {0x00, 0x00}); | ||
903 | } else if (priv->cur_fw.type & ATSC) { | ||
904 | offset = 1750000; | ||
905 | } else { | ||
906 | offset = 2750000; | ||
907 | /* | ||
908 | * We must adjust the offset by 500kHz in two cases in order | ||
909 | * to correctly center the IF output: | ||
910 | * 1) When the ZARLINK456 or DIBCOM52 tables were explicitly | ||
911 | * selected and a 7MHz channel is tuned; | ||
912 | * 2) When tuning a VHF channel with DTV78 firmware. | ||
913 | */ | ||
914 | if (((priv->cur_fw.type & DTV7) && | ||
915 | (priv->cur_fw.scode_table & (ZARLINK456 | DIBCOM52))) || | ||
916 | ((priv->cur_fw.type & DTV78) && freq < 470000000)) | ||
917 | offset -= 500000; | ||
918 | } | ||
919 | |||
920 | div = (freq - offset + DIV / 2) / DIV; | ||
921 | |||
922 | /* CMD= Set frequency */ | ||
923 | if (priv->firm_version < 0x0202) | ||
924 | rc = send_seq(priv, {0x00, 0x02, 0x00, 0x00}); | ||
925 | else | ||
926 | rc = send_seq(priv, {0x80, 0x02, 0x00, 0x00}); | ||
927 | if (rc < 0) | ||
928 | goto ret; | ||
929 | |||
930 | /* Return code shouldn't be checked. | ||
931 | The reset CLK is needed only with tm6000. | ||
932 | Driver should work fine even if this fails. | ||
933 | */ | ||
934 | priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1); | ||
935 | |||
936 | msleep(10); | ||
937 | |||
938 | buf[0] = 0xff & (div >> 24); | ||
939 | buf[1] = 0xff & (div >> 16); | ||
940 | buf[2] = 0xff & (div >> 8); | ||
941 | buf[3] = 0xff & (div); | ||
942 | |||
943 | rc = i2c_send(priv, buf, sizeof(buf)); | ||
944 | if (rc < 0) | ||
945 | goto ret; | ||
946 | msleep(100); | ||
947 | |||
948 | priv->frequency = freq; | ||
949 | |||
950 | tuner_dbg("divisor= %02x %02x %02x %02x (freq=%d.%03d)\n", | ||
951 | buf[0], buf[1], buf[2], buf[3], | ||
952 | freq / 1000000, (freq % 1000000) / 1000); | ||
953 | |||
954 | rc = 0; | ||
955 | |||
956 | ret: | ||
957 | mutex_unlock(&priv->lock); | ||
958 | |||
959 | return rc; | ||
960 | } | ||
961 | |||
962 | static int xc2028_set_analog_freq(struct dvb_frontend *fe, | ||
963 | struct analog_parameters *p) | ||
964 | { | ||
965 | struct xc2028_data *priv = fe->tuner_priv; | ||
966 | unsigned int type=0; | ||
967 | |||
968 | tuner_dbg("%s called\n", __func__); | ||
969 | |||
970 | if (p->mode == V4L2_TUNER_RADIO) { | ||
971 | type |= FM; | ||
972 | if (priv->ctrl.input1) | ||
973 | type |= INPUT1; | ||
974 | return generic_set_freq(fe, (625l * p->frequency) / 10, | ||
975 | T_ANALOG_TV, type, 0, 0); | ||
976 | } | ||
977 | |||
978 | /* if std is not defined, choose one */ | ||
979 | if (!p->std) | ||
980 | p->std = V4L2_STD_MN; | ||
981 | |||
982 | /* PAL/M, PAL/N, PAL/Nc and NTSC variants should use 6MHz firmware */ | ||
983 | if (!(p->std & V4L2_STD_MN)) | ||
984 | type |= F8MHZ; | ||
985 | |||
986 | /* Add audio hack to std mask */ | ||
987 | p->std |= parse_audio_std_option(); | ||
988 | |||
989 | return generic_set_freq(fe, 62500l * p->frequency, | ||
990 | T_ANALOG_TV, type, p->std, 0); | ||
991 | } | ||
992 | |||
993 | static int xc2028_set_params(struct dvb_frontend *fe, | ||
994 | struct dvb_frontend_parameters *p) | ||
995 | { | ||
996 | struct xc2028_data *priv = fe->tuner_priv; | ||
997 | unsigned int type=0; | ||
998 | fe_bandwidth_t bw = BANDWIDTH_8_MHZ; | ||
999 | u16 demod = 0; | ||
1000 | |||
1001 | tuner_dbg("%s called\n", __func__); | ||
1002 | |||
1003 | if (priv->ctrl.d2633) | ||
1004 | type |= D2633; | ||
1005 | else | ||
1006 | type |= D2620; | ||
1007 | |||
1008 | switch(fe->ops.info.type) { | ||
1009 | case FE_OFDM: | ||
1010 | bw = p->u.ofdm.bandwidth; | ||
1011 | break; | ||
1012 | case FE_QAM: | ||
1013 | tuner_info("WARN: There are some reports that " | ||
1014 | "QAM 6 MHz doesn't work.\n" | ||
1015 | "If this works for you, please report by " | ||
1016 | "e-mail to: v4l-dvb-maintainer@linuxtv.org\n"); | ||
1017 | bw = BANDWIDTH_6_MHZ; | ||
1018 | type |= QAM; | ||
1019 | break; | ||
1020 | case FE_ATSC: | ||
1021 | bw = BANDWIDTH_6_MHZ; | ||
1022 | /* The only ATSC firmware (at least on v2.7) is D2633, | ||
1023 | so overrides ctrl->d2633 */ | ||
1024 | type |= ATSC| D2633; | ||
1025 | type &= ~D2620; | ||
1026 | break; | ||
1027 | /* DVB-S is not supported */ | ||
1028 | default: | ||
1029 | return -EINVAL; | ||
1030 | } | ||
1031 | |||
1032 | switch (bw) { | ||
1033 | case BANDWIDTH_8_MHZ: | ||
1034 | if (p->frequency < 470000000) | ||
1035 | priv->ctrl.vhfbw7 = 0; | ||
1036 | else | ||
1037 | priv->ctrl.uhfbw8 = 1; | ||
1038 | type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV8; | ||
1039 | type |= F8MHZ; | ||
1040 | break; | ||
1041 | case BANDWIDTH_7_MHZ: | ||
1042 | if (p->frequency < 470000000) | ||
1043 | priv->ctrl.vhfbw7 = 1; | ||
1044 | else | ||
1045 | priv->ctrl.uhfbw8 = 0; | ||
1046 | type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV7; | ||
1047 | type |= F8MHZ; | ||
1048 | break; | ||
1049 | case BANDWIDTH_6_MHZ: | ||
1050 | type |= DTV6; | ||
1051 | priv->ctrl.vhfbw7 = 0; | ||
1052 | priv->ctrl.uhfbw8 = 0; | ||
1053 | break; | ||
1054 | default: | ||
1055 | tuner_err("error: bandwidth not supported.\n"); | ||
1056 | }; | ||
1057 | |||
1058 | /* All S-code tables need a 200kHz shift */ | ||
1059 | if (priv->ctrl.demod) | ||
1060 | demod = priv->ctrl.demod + 200; | ||
1061 | |||
1062 | return generic_set_freq(fe, p->frequency, | ||
1063 | T_DIGITAL_TV, type, 0, demod); | ||
1064 | } | ||
1065 | |||
1066 | |||
1067 | static int xc2028_dvb_release(struct dvb_frontend *fe) | ||
1068 | { | ||
1069 | struct xc2028_data *priv = fe->tuner_priv; | ||
1070 | |||
1071 | tuner_dbg("%s called\n", __func__); | ||
1072 | |||
1073 | mutex_lock(&xc2028_list_mutex); | ||
1074 | |||
1075 | priv->count--; | ||
1076 | |||
1077 | if (!priv->count) { | ||
1078 | list_del(&priv->xc2028_list); | ||
1079 | |||
1080 | kfree(priv->ctrl.fname); | ||
1081 | |||
1082 | free_firmware(priv); | ||
1083 | kfree(priv); | ||
1084 | fe->tuner_priv = NULL; | ||
1085 | } | ||
1086 | |||
1087 | mutex_unlock(&xc2028_list_mutex); | ||
1088 | |||
1089 | return 0; | ||
1090 | } | ||
1091 | |||
1092 | static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
1093 | { | ||
1094 | struct xc2028_data *priv = fe->tuner_priv; | ||
1095 | |||
1096 | tuner_dbg("%s called\n", __func__); | ||
1097 | |||
1098 | *frequency = priv->frequency; | ||
1099 | |||
1100 | return 0; | ||
1101 | } | ||
1102 | |||
1103 | static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) | ||
1104 | { | ||
1105 | struct xc2028_data *priv = fe->tuner_priv; | ||
1106 | struct xc2028_ctrl *p = priv_cfg; | ||
1107 | int rc = 0; | ||
1108 | |||
1109 | tuner_dbg("%s called\n", __func__); | ||
1110 | |||
1111 | mutex_lock(&priv->lock); | ||
1112 | |||
1113 | memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); | ||
1114 | if (priv->ctrl.max_len < 9) | ||
1115 | priv->ctrl.max_len = 13; | ||
1116 | |||
1117 | if (p->fname) { | ||
1118 | if (priv->ctrl.fname && strcmp(p->fname, priv->ctrl.fname)) { | ||
1119 | kfree(priv->ctrl.fname); | ||
1120 | free_firmware(priv); | ||
1121 | } | ||
1122 | |||
1123 | priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL); | ||
1124 | if (priv->ctrl.fname == NULL) | ||
1125 | rc = -ENOMEM; | ||
1126 | } | ||
1127 | |||
1128 | mutex_unlock(&priv->lock); | ||
1129 | |||
1130 | return rc; | ||
1131 | } | ||
1132 | |||
1133 | static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = { | ||
1134 | .info = { | ||
1135 | .name = "Xceive XC3028", | ||
1136 | .frequency_min = 42000000, | ||
1137 | .frequency_max = 864000000, | ||
1138 | .frequency_step = 50000, | ||
1139 | }, | ||
1140 | |||
1141 | .set_config = xc2028_set_config, | ||
1142 | .set_analog_params = xc2028_set_analog_freq, | ||
1143 | .release = xc2028_dvb_release, | ||
1144 | .get_frequency = xc2028_get_frequency, | ||
1145 | .get_rf_strength = xc2028_signal, | ||
1146 | .set_params = xc2028_set_params, | ||
1147 | }; | ||
1148 | |||
1149 | struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, | ||
1150 | struct xc2028_config *cfg) | ||
1151 | { | ||
1152 | struct xc2028_data *priv; | ||
1153 | void *video_dev; | ||
1154 | |||
1155 | if (debug) | ||
1156 | printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n"); | ||
1157 | |||
1158 | if (NULL == cfg) | ||
1159 | return NULL; | ||
1160 | |||
1161 | if (!fe) { | ||
1162 | printk(KERN_ERR "xc2028: No frontend!\n"); | ||
1163 | return NULL; | ||
1164 | } | ||
1165 | |||
1166 | video_dev = cfg->i2c_adap->algo_data; | ||
1167 | |||
1168 | if (debug) | ||
1169 | printk(KERN_DEBUG "xc2028: video_dev =%p\n", video_dev); | ||
1170 | |||
1171 | mutex_lock(&xc2028_list_mutex); | ||
1172 | |||
1173 | list_for_each_entry(priv, &xc2028_list, xc2028_list) { | ||
1174 | if (&priv->i2c_props.adap->dev == &cfg->i2c_adap->dev) { | ||
1175 | video_dev = NULL; | ||
1176 | if (debug) | ||
1177 | printk(KERN_DEBUG "xc2028: reusing device\n"); | ||
1178 | |||
1179 | break; | ||
1180 | } | ||
1181 | } | ||
1182 | |||
1183 | if (video_dev) { | ||
1184 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
1185 | if (priv == NULL) { | ||
1186 | mutex_unlock(&xc2028_list_mutex); | ||
1187 | return NULL; | ||
1188 | } | ||
1189 | |||
1190 | priv->i2c_props.addr = cfg->i2c_addr; | ||
1191 | priv->i2c_props.adap = cfg->i2c_adap; | ||
1192 | priv->i2c_props.name = "xc2028"; | ||
1193 | |||
1194 | priv->video_dev = video_dev; | ||
1195 | priv->tuner_callback = cfg->callback; | ||
1196 | priv->ctrl.max_len = 13; | ||
1197 | |||
1198 | mutex_init(&priv->lock); | ||
1199 | |||
1200 | list_add_tail(&priv->xc2028_list, &xc2028_list); | ||
1201 | } | ||
1202 | |||
1203 | fe->tuner_priv = priv; | ||
1204 | priv->count++; | ||
1205 | |||
1206 | if (debug) | ||
1207 | printk(KERN_DEBUG "xc2028: usage count is %i\n", priv->count); | ||
1208 | |||
1209 | memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops, | ||
1210 | sizeof(xc2028_dvb_tuner_ops)); | ||
1211 | |||
1212 | tuner_info("type set to %s\n", "XCeive xc2028/xc3028 tuner"); | ||
1213 | |||
1214 | if (cfg->ctrl) | ||
1215 | xc2028_set_config(fe, cfg->ctrl); | ||
1216 | |||
1217 | mutex_unlock(&xc2028_list_mutex); | ||
1218 | |||
1219 | return fe; | ||
1220 | } | ||
1221 | |||
1222 | EXPORT_SYMBOL(xc2028_attach); | ||
1223 | |||
1224 | MODULE_DESCRIPTION("Xceive xc2028/xc3028 tuner driver"); | ||
1225 | MODULE_AUTHOR("Michel Ludwig <michel.ludwig@gmail.com>"); | ||
1226 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); | ||
1227 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/common/tuners/tuner-xc2028.h b/drivers/media/common/tuners/tuner-xc2028.h new file mode 100644 index 000000000000..fc2f132a5541 --- /dev/null +++ b/drivers/media/common/tuners/tuner-xc2028.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* tuner-xc2028 | ||
2 | * | ||
3 | * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org) | ||
4 | * This code is placed under the terms of the GNU General Public License v2 | ||
5 | */ | ||
6 | |||
7 | #ifndef __TUNER_XC2028_H__ | ||
8 | #define __TUNER_XC2028_H__ | ||
9 | |||
10 | #include "dvb_frontend.h" | ||
11 | |||
12 | #define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw" | ||
13 | |||
14 | /* Dmoduler IF (kHz) */ | ||
15 | #define XC3028_FE_DEFAULT 0 /* Don't load SCODE */ | ||
16 | #define XC3028_FE_LG60 6000 | ||
17 | #define XC3028_FE_ATI638 6380 | ||
18 | #define XC3028_FE_OREN538 5380 | ||
19 | #define XC3028_FE_OREN36 3600 | ||
20 | #define XC3028_FE_TOYOTA388 3880 | ||
21 | #define XC3028_FE_TOYOTA794 7940 | ||
22 | #define XC3028_FE_DIBCOM52 5200 | ||
23 | #define XC3028_FE_ZARLINK456 4560 | ||
24 | #define XC3028_FE_CHINA 5200 | ||
25 | |||
26 | struct xc2028_ctrl { | ||
27 | char *fname; | ||
28 | int max_len; | ||
29 | unsigned int scode_table; | ||
30 | unsigned int mts :1; | ||
31 | unsigned int d2633 :1; | ||
32 | unsigned int input1:1; | ||
33 | unsigned int vhfbw7:1; | ||
34 | unsigned int uhfbw8:1; | ||
35 | unsigned int demod; | ||
36 | }; | ||
37 | |||
38 | struct xc2028_config { | ||
39 | struct i2c_adapter *i2c_adap; | ||
40 | u8 i2c_addr; | ||
41 | void *video_dev; | ||
42 | struct xc2028_ctrl *ctrl; | ||
43 | int (*callback) (void *dev, int command, int arg); | ||
44 | }; | ||
45 | |||
46 | /* xc2028 commands for callback */ | ||
47 | #define XC2028_TUNER_RESET 0 | ||
48 | #define XC2028_RESET_CLK 1 | ||
49 | |||
50 | #if defined(CONFIG_TUNER_XC2028) || (defined(CONFIG_TUNER_XC2028_MODULE) && defined(MODULE)) | ||
51 | extern struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, | ||
52 | struct xc2028_config *cfg); | ||
53 | #else | ||
54 | static inline struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, | ||
55 | struct xc2028_config *cfg) | ||
56 | { | ||
57 | printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", | ||
58 | __func__); | ||
59 | return NULL; | ||
60 | } | ||
61 | #endif | ||
62 | |||
63 | #endif /* __TUNER_XC2028_H__ */ | ||
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c new file mode 100644 index 000000000000..43d35bdb221f --- /dev/null +++ b/drivers/media/common/tuners/xc5000.c | |||
@@ -0,0 +1,964 @@ | |||
1 | /* | ||
2 | * Driver for Xceive XC5000 "QAM/8VSB single chip tuner" | ||
3 | * | ||
4 | * Copyright (c) 2007 Xceive Corporation | ||
5 | * Copyright (c) 2007 Steven Toth <stoth@hauppauge.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/moduleparam.h> | ||
25 | #include <linux/videodev2.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/dvb/frontend.h> | ||
28 | #include <linux/i2c.h> | ||
29 | |||
30 | #include "dvb_frontend.h" | ||
31 | |||
32 | #include "xc5000.h" | ||
33 | #include "xc5000_priv.h" | ||
34 | |||
35 | static int debug; | ||
36 | module_param(debug, int, 0644); | ||
37 | MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); | ||
38 | |||
39 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | ||
40 | printk(KERN_INFO "%s: " fmt, "xc5000", ## arg) | ||
41 | |||
42 | #define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw" | ||
43 | #define XC5000_DEFAULT_FIRMWARE_SIZE 12332 | ||
44 | |||
45 | /* Misc Defines */ | ||
46 | #define MAX_TV_STANDARD 23 | ||
47 | #define XC_MAX_I2C_WRITE_LENGTH 64 | ||
48 | |||
49 | /* Signal Types */ | ||
50 | #define XC_RF_MODE_AIR 0 | ||
51 | #define XC_RF_MODE_CABLE 1 | ||
52 | |||
53 | /* Result codes */ | ||
54 | #define XC_RESULT_SUCCESS 0 | ||
55 | #define XC_RESULT_RESET_FAILURE 1 | ||
56 | #define XC_RESULT_I2C_WRITE_FAILURE 2 | ||
57 | #define XC_RESULT_I2C_READ_FAILURE 3 | ||
58 | #define XC_RESULT_OUT_OF_RANGE 5 | ||
59 | |||
60 | /* Product id */ | ||
61 | #define XC_PRODUCT_ID_FW_NOT_LOADED 0x2000 | ||
62 | #define XC_PRODUCT_ID_FW_LOADED 0x1388 | ||
63 | |||
64 | /* Registers */ | ||
65 | #define XREG_INIT 0x00 | ||
66 | #define XREG_VIDEO_MODE 0x01 | ||
67 | #define XREG_AUDIO_MODE 0x02 | ||
68 | #define XREG_RF_FREQ 0x03 | ||
69 | #define XREG_D_CODE 0x04 | ||
70 | #define XREG_IF_OUT 0x05 | ||
71 | #define XREG_SEEK_MODE 0x07 | ||
72 | #define XREG_POWER_DOWN 0x0A | ||
73 | #define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */ | ||
74 | #define XREG_SMOOTHEDCVBS 0x0E | ||
75 | #define XREG_XTALFREQ 0x0F | ||
76 | #define XREG_FINERFFREQ 0x10 | ||
77 | #define XREG_DDIMODE 0x11 | ||
78 | |||
79 | #define XREG_ADC_ENV 0x00 | ||
80 | #define XREG_QUALITY 0x01 | ||
81 | #define XREG_FRAME_LINES 0x02 | ||
82 | #define XREG_HSYNC_FREQ 0x03 | ||
83 | #define XREG_LOCK 0x04 | ||
84 | #define XREG_FREQ_ERROR 0x05 | ||
85 | #define XREG_SNR 0x06 | ||
86 | #define XREG_VERSION 0x07 | ||
87 | #define XREG_PRODUCT_ID 0x08 | ||
88 | #define XREG_BUSY 0x09 | ||
89 | |||
90 | /* | ||
91 | Basic firmware description. This will remain with | ||
92 | the driver for documentation purposes. | ||
93 | |||
94 | This represents an I2C firmware file encoded as a | ||
95 | string of unsigned char. Format is as follows: | ||
96 | |||
97 | char[0 ]=len0_MSB -> len = len_MSB * 256 + len_LSB | ||
98 | char[1 ]=len0_LSB -> length of first write transaction | ||
99 | char[2 ]=data0 -> first byte to be sent | ||
100 | char[3 ]=data1 | ||
101 | char[4 ]=data2 | ||
102 | char[ ]=... | ||
103 | char[M ]=dataN -> last byte to be sent | ||
104 | char[M+1]=len1_MSB -> len = len_MSB * 256 + len_LSB | ||
105 | char[M+2]=len1_LSB -> length of second write transaction | ||
106 | char[M+3]=data0 | ||
107 | char[M+4]=data1 | ||
108 | ... | ||
109 | etc. | ||
110 | |||
111 | The [len] value should be interpreted as follows: | ||
112 | |||
113 | len= len_MSB _ len_LSB | ||
114 | len=1111_1111_1111_1111 : End of I2C_SEQUENCE | ||
115 | len=0000_0000_0000_0000 : Reset command: Do hardware reset | ||
116 | len=0NNN_NNNN_NNNN_NNNN : Normal transaction: number of bytes = {1:32767) | ||
117 | len=1WWW_WWWW_WWWW_WWWW : Wait command: wait for {1:32767} ms | ||
118 | |||
119 | For the RESET and WAIT commands, the two following bytes will contain | ||
120 | immediately the length of the following transaction. | ||
121 | |||
122 | */ | ||
123 | typedef struct { | ||
124 | char *Name; | ||
125 | u16 AudioMode; | ||
126 | u16 VideoMode; | ||
127 | } XC_TV_STANDARD; | ||
128 | |||
129 | /* Tuner standards */ | ||
130 | #define MN_NTSC_PAL_BTSC 0 | ||
131 | #define MN_NTSC_PAL_A2 1 | ||
132 | #define MN_NTSC_PAL_EIAJ 2 | ||
133 | #define MN_NTSC_PAL_Mono 3 | ||
134 | #define BG_PAL_A2 4 | ||
135 | #define BG_PAL_NICAM 5 | ||
136 | #define BG_PAL_MONO 6 | ||
137 | #define I_PAL_NICAM 7 | ||
138 | #define I_PAL_NICAM_MONO 8 | ||
139 | #define DK_PAL_A2 9 | ||
140 | #define DK_PAL_NICAM 10 | ||
141 | #define DK_PAL_MONO 11 | ||
142 | #define DK_SECAM_A2DK1 12 | ||
143 | #define DK_SECAM_A2LDK3 13 | ||
144 | #define DK_SECAM_A2MONO 14 | ||
145 | #define L_SECAM_NICAM 15 | ||
146 | #define LC_SECAM_NICAM 16 | ||
147 | #define DTV6 17 | ||
148 | #define DTV8 18 | ||
149 | #define DTV7_8 19 | ||
150 | #define DTV7 20 | ||
151 | #define FM_Radio_INPUT2 21 | ||
152 | #define FM_Radio_INPUT1 22 | ||
153 | |||
154 | static XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { | ||
155 | {"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020}, | ||
156 | {"M/N-NTSC/PAL-A2", 0x0600, 0x8020}, | ||
157 | {"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020}, | ||
158 | {"M/N-NTSC/PAL-Mono", 0x0478, 0x8020}, | ||
159 | {"B/G-PAL-A2", 0x0A00, 0x8049}, | ||
160 | {"B/G-PAL-NICAM", 0x0C04, 0x8049}, | ||
161 | {"B/G-PAL-MONO", 0x0878, 0x8059}, | ||
162 | {"I-PAL-NICAM", 0x1080, 0x8009}, | ||
163 | {"I-PAL-NICAM-MONO", 0x0E78, 0x8009}, | ||
164 | {"D/K-PAL-A2", 0x1600, 0x8009}, | ||
165 | {"D/K-PAL-NICAM", 0x0E80, 0x8009}, | ||
166 | {"D/K-PAL-MONO", 0x1478, 0x8009}, | ||
167 | {"D/K-SECAM-A2 DK1", 0x1200, 0x8009}, | ||
168 | {"D/K-SECAM-A2 L/DK3",0x0E00, 0x8009}, | ||
169 | {"D/K-SECAM-A2 MONO", 0x1478, 0x8009}, | ||
170 | {"L-SECAM-NICAM", 0x8E82, 0x0009}, | ||
171 | {"L'-SECAM-NICAM", 0x8E82, 0x4009}, | ||
172 | {"DTV6", 0x00C0, 0x8002}, | ||
173 | {"DTV8", 0x00C0, 0x800B}, | ||
174 | {"DTV7/8", 0x00C0, 0x801B}, | ||
175 | {"DTV7", 0x00C0, 0x8007}, | ||
176 | {"FM Radio-INPUT2", 0x9802, 0x9002}, | ||
177 | {"FM Radio-INPUT1", 0x0208, 0x9002} | ||
178 | }; | ||
179 | |||
180 | static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len); | ||
181 | static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len); | ||
182 | static void xc5000_TunerReset(struct dvb_frontend *fe); | ||
183 | |||
184 | static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len) | ||
185 | { | ||
186 | return xc5000_writeregs(priv, buf, len) | ||
187 | ? XC_RESULT_I2C_WRITE_FAILURE : XC_RESULT_SUCCESS; | ||
188 | } | ||
189 | |||
190 | static int xc_read_i2c_data(struct xc5000_priv *priv, u8 *buf, int len) | ||
191 | { | ||
192 | return xc5000_readregs(priv, buf, len) | ||
193 | ? XC_RESULT_I2C_READ_FAILURE : XC_RESULT_SUCCESS; | ||
194 | } | ||
195 | |||
196 | static int xc_reset(struct dvb_frontend *fe) | ||
197 | { | ||
198 | xc5000_TunerReset(fe); | ||
199 | return XC_RESULT_SUCCESS; | ||
200 | } | ||
201 | |||
202 | static void xc_wait(int wait_ms) | ||
203 | { | ||
204 | msleep(wait_ms); | ||
205 | } | ||
206 | |||
207 | static void xc5000_TunerReset(struct dvb_frontend *fe) | ||
208 | { | ||
209 | struct xc5000_priv *priv = fe->tuner_priv; | ||
210 | int ret; | ||
211 | |||
212 | dprintk(1, "%s()\n", __func__); | ||
213 | |||
214 | if (priv->cfg->tuner_callback) { | ||
215 | ret = priv->cfg->tuner_callback(priv->cfg->priv, | ||
216 | XC5000_TUNER_RESET, 0); | ||
217 | if (ret) | ||
218 | printk(KERN_ERR "xc5000: reset failed\n"); | ||
219 | } else | ||
220 | printk(KERN_ERR "xc5000: no tuner reset callback function, fatal\n"); | ||
221 | } | ||
222 | |||
223 | static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData) | ||
224 | { | ||
225 | u8 buf[4]; | ||
226 | int WatchDogTimer = 5; | ||
227 | int result; | ||
228 | |||
229 | buf[0] = (regAddr >> 8) & 0xFF; | ||
230 | buf[1] = regAddr & 0xFF; | ||
231 | buf[2] = (i2cData >> 8) & 0xFF; | ||
232 | buf[3] = i2cData & 0xFF; | ||
233 | result = xc_send_i2c_data(priv, buf, 4); | ||
234 | if (result == XC_RESULT_SUCCESS) { | ||
235 | /* wait for busy flag to clear */ | ||
236 | while ((WatchDogTimer > 0) && (result == XC_RESULT_SUCCESS)) { | ||
237 | buf[0] = 0; | ||
238 | buf[1] = XREG_BUSY; | ||
239 | |||
240 | result = xc_send_i2c_data(priv, buf, 2); | ||
241 | if (result == XC_RESULT_SUCCESS) { | ||
242 | result = xc_read_i2c_data(priv, buf, 2); | ||
243 | if (result == XC_RESULT_SUCCESS) { | ||
244 | if ((buf[0] == 0) && (buf[1] == 0)) { | ||
245 | /* busy flag cleared */ | ||
246 | break; | ||
247 | } else { | ||
248 | xc_wait(100); /* wait 5 ms */ | ||
249 | WatchDogTimer--; | ||
250 | } | ||
251 | } | ||
252 | } | ||
253 | } | ||
254 | } | ||
255 | if (WatchDogTimer < 0) | ||
256 | result = XC_RESULT_I2C_WRITE_FAILURE; | ||
257 | |||
258 | return result; | ||
259 | } | ||
260 | |||
261 | static int xc_read_reg(struct xc5000_priv *priv, u16 regAddr, u16 *i2cData) | ||
262 | { | ||
263 | u8 buf[2]; | ||
264 | int result; | ||
265 | |||
266 | buf[0] = (regAddr >> 8) & 0xFF; | ||
267 | buf[1] = regAddr & 0xFF; | ||
268 | result = xc_send_i2c_data(priv, buf, 2); | ||
269 | if (result != XC_RESULT_SUCCESS) | ||
270 | return result; | ||
271 | |||
272 | result = xc_read_i2c_data(priv, buf, 2); | ||
273 | if (result != XC_RESULT_SUCCESS) | ||
274 | return result; | ||
275 | |||
276 | *i2cData = buf[0] * 256 + buf[1]; | ||
277 | return result; | ||
278 | } | ||
279 | |||
280 | static int xc_load_i2c_sequence(struct dvb_frontend *fe, u8 i2c_sequence[]) | ||
281 | { | ||
282 | struct xc5000_priv *priv = fe->tuner_priv; | ||
283 | |||
284 | int i, nbytes_to_send, result; | ||
285 | unsigned int len, pos, index; | ||
286 | u8 buf[XC_MAX_I2C_WRITE_LENGTH]; | ||
287 | |||
288 | index=0; | ||
289 | while ((i2c_sequence[index]!=0xFF) || (i2c_sequence[index+1]!=0xFF)) { | ||
290 | len = i2c_sequence[index]* 256 + i2c_sequence[index+1]; | ||
291 | if (len == 0x0000) { | ||
292 | /* RESET command */ | ||
293 | result = xc_reset(fe); | ||
294 | index += 2; | ||
295 | if (result != XC_RESULT_SUCCESS) | ||
296 | return result; | ||
297 | } else if (len & 0x8000) { | ||
298 | /* WAIT command */ | ||
299 | xc_wait(len & 0x7FFF); | ||
300 | index += 2; | ||
301 | } else { | ||
302 | /* Send i2c data whilst ensuring individual transactions | ||
303 | * do not exceed XC_MAX_I2C_WRITE_LENGTH bytes. | ||
304 | */ | ||
305 | index += 2; | ||
306 | buf[0] = i2c_sequence[index]; | ||
307 | buf[1] = i2c_sequence[index + 1]; | ||
308 | pos = 2; | ||
309 | while (pos < len) { | ||
310 | if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2) { | ||
311 | nbytes_to_send = XC_MAX_I2C_WRITE_LENGTH; | ||
312 | } else { | ||
313 | nbytes_to_send = (len - pos + 2); | ||
314 | } | ||
315 | for (i=2; i<nbytes_to_send; i++) { | ||
316 | buf[i] = i2c_sequence[index + pos + i - 2]; | ||
317 | } | ||
318 | result = xc_send_i2c_data(priv, buf, nbytes_to_send); | ||
319 | |||
320 | if (result != XC_RESULT_SUCCESS) | ||
321 | return result; | ||
322 | |||
323 | pos += nbytes_to_send - 2; | ||
324 | } | ||
325 | index += len; | ||
326 | } | ||
327 | } | ||
328 | return XC_RESULT_SUCCESS; | ||
329 | } | ||
330 | |||
331 | static int xc_initialize(struct xc5000_priv *priv) | ||
332 | { | ||
333 | dprintk(1, "%s()\n", __func__); | ||
334 | return xc_write_reg(priv, XREG_INIT, 0); | ||
335 | } | ||
336 | |||
337 | static int xc_SetTVStandard(struct xc5000_priv *priv, | ||
338 | u16 VideoMode, u16 AudioMode) | ||
339 | { | ||
340 | int ret; | ||
341 | dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, VideoMode, AudioMode); | ||
342 | dprintk(1, "%s() Standard = %s\n", | ||
343 | __func__, | ||
344 | XC5000_Standard[priv->video_standard].Name); | ||
345 | |||
346 | ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode); | ||
347 | if (ret == XC_RESULT_SUCCESS) | ||
348 | ret = xc_write_reg(priv, XREG_AUDIO_MODE, AudioMode); | ||
349 | |||
350 | return ret; | ||
351 | } | ||
352 | |||
353 | static int xc_shutdown(struct xc5000_priv *priv) | ||
354 | { | ||
355 | return 0; | ||
356 | /* Fixme: cannot bring tuner back alive once shutdown | ||
357 | * without reloading the driver modules. | ||
358 | * return xc_write_reg(priv, XREG_POWER_DOWN, 0); | ||
359 | */ | ||
360 | } | ||
361 | |||
362 | static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode) | ||
363 | { | ||
364 | dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode, | ||
365 | rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE"); | ||
366 | |||
367 | if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE)) | ||
368 | { | ||
369 | rf_mode = XC_RF_MODE_CABLE; | ||
370 | printk(KERN_ERR | ||
371 | "%s(), Invalid mode, defaulting to CABLE", | ||
372 | __func__); | ||
373 | } | ||
374 | return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode); | ||
375 | } | ||
376 | |||
377 | static const struct dvb_tuner_ops xc5000_tuner_ops; | ||
378 | |||
379 | static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz) | ||
380 | { | ||
381 | u16 freq_code; | ||
382 | |||
383 | dprintk(1, "%s(%u)\n", __func__, freq_hz); | ||
384 | |||
385 | if ((freq_hz > xc5000_tuner_ops.info.frequency_max) || | ||
386 | (freq_hz < xc5000_tuner_ops.info.frequency_min)) | ||
387 | return XC_RESULT_OUT_OF_RANGE; | ||
388 | |||
389 | freq_code = (u16)(freq_hz / 15625); | ||
390 | |||
391 | return xc_write_reg(priv, XREG_RF_FREQ, freq_code); | ||
392 | } | ||
393 | |||
394 | |||
395 | static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz) | ||
396 | { | ||
397 | u32 freq_code = (freq_khz * 1024)/1000; | ||
398 | dprintk(1, "%s(freq_khz = %d) freq_code = 0x%x\n", | ||
399 | __func__, freq_khz, freq_code); | ||
400 | |||
401 | return xc_write_reg(priv, XREG_IF_OUT, freq_code); | ||
402 | } | ||
403 | |||
404 | |||
405 | static int xc_get_ADC_Envelope(struct xc5000_priv *priv, u16 *adc_envelope) | ||
406 | { | ||
407 | return xc_read_reg(priv, XREG_ADC_ENV, adc_envelope); | ||
408 | } | ||
409 | |||
410 | static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz) | ||
411 | { | ||
412 | int result; | ||
413 | u16 regData; | ||
414 | u32 tmp; | ||
415 | |||
416 | result = xc_read_reg(priv, XREG_FREQ_ERROR, ®Data); | ||
417 | if (result) | ||
418 | return result; | ||
419 | |||
420 | tmp = (u32)regData; | ||
421 | (*freq_error_hz) = (tmp * 15625) / 1000; | ||
422 | return result; | ||
423 | } | ||
424 | |||
425 | static int xc_get_lock_status(struct xc5000_priv *priv, u16 *lock_status) | ||
426 | { | ||
427 | return xc_read_reg(priv, XREG_LOCK, lock_status); | ||
428 | } | ||
429 | |||
430 | static int xc_get_version(struct xc5000_priv *priv, | ||
431 | u8 *hw_majorversion, u8 *hw_minorversion, | ||
432 | u8 *fw_majorversion, u8 *fw_minorversion) | ||
433 | { | ||
434 | u16 data; | ||
435 | int result; | ||
436 | |||
437 | result = xc_read_reg(priv, XREG_VERSION, &data); | ||
438 | if (result) | ||
439 | return result; | ||
440 | |||
441 | (*hw_majorversion) = (data >> 12) & 0x0F; | ||
442 | (*hw_minorversion) = (data >> 8) & 0x0F; | ||
443 | (*fw_majorversion) = (data >> 4) & 0x0F; | ||
444 | (*fw_minorversion) = data & 0x0F; | ||
445 | |||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz) | ||
450 | { | ||
451 | u16 regData; | ||
452 | int result; | ||
453 | |||
454 | result = xc_read_reg(priv, XREG_HSYNC_FREQ, ®Data); | ||
455 | if (result) | ||
456 | return result; | ||
457 | |||
458 | (*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100; | ||
459 | return result; | ||
460 | } | ||
461 | |||
462 | static int xc_get_frame_lines(struct xc5000_priv *priv, u16 *frame_lines) | ||
463 | { | ||
464 | return xc_read_reg(priv, XREG_FRAME_LINES, frame_lines); | ||
465 | } | ||
466 | |||
467 | static int xc_get_quality(struct xc5000_priv *priv, u16 *quality) | ||
468 | { | ||
469 | return xc_read_reg(priv, XREG_QUALITY, quality); | ||
470 | } | ||
471 | |||
472 | static u16 WaitForLock(struct xc5000_priv *priv) | ||
473 | { | ||
474 | u16 lockState = 0; | ||
475 | int watchDogCount = 40; | ||
476 | |||
477 | while ((lockState == 0) && (watchDogCount > 0)) { | ||
478 | xc_get_lock_status(priv, &lockState); | ||
479 | if (lockState != 1) { | ||
480 | xc_wait(5); | ||
481 | watchDogCount--; | ||
482 | } | ||
483 | } | ||
484 | return lockState; | ||
485 | } | ||
486 | |||
487 | static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz) | ||
488 | { | ||
489 | int found = 0; | ||
490 | |||
491 | dprintk(1, "%s(%u)\n", __func__, freq_hz); | ||
492 | |||
493 | if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS) | ||
494 | return 0; | ||
495 | |||
496 | if (WaitForLock(priv) == 1) | ||
497 | found = 1; | ||
498 | |||
499 | return found; | ||
500 | } | ||
501 | |||
502 | static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val) | ||
503 | { | ||
504 | u8 buf[2] = { reg >> 8, reg & 0xff }; | ||
505 | u8 bval[2] = { 0, 0 }; | ||
506 | struct i2c_msg msg[2] = { | ||
507 | { .addr = priv->cfg->i2c_address, | ||
508 | .flags = 0, .buf = &buf[0], .len = 2 }, | ||
509 | { .addr = priv->cfg->i2c_address, | ||
510 | .flags = I2C_M_RD, .buf = &bval[0], .len = 2 }, | ||
511 | }; | ||
512 | |||
513 | if (i2c_transfer(priv->i2c, msg, 2) != 2) { | ||
514 | printk(KERN_WARNING "xc5000: I2C read failed\n"); | ||
515 | return -EREMOTEIO; | ||
516 | } | ||
517 | |||
518 | *val = (bval[0] << 8) | bval[1]; | ||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len) | ||
523 | { | ||
524 | struct i2c_msg msg = { .addr = priv->cfg->i2c_address, | ||
525 | .flags = 0, .buf = buf, .len = len }; | ||
526 | |||
527 | if (i2c_transfer(priv->i2c, &msg, 1) != 1) { | ||
528 | printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", | ||
529 | (int)len); | ||
530 | return -EREMOTEIO; | ||
531 | } | ||
532 | return 0; | ||
533 | } | ||
534 | |||
535 | static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len) | ||
536 | { | ||
537 | struct i2c_msg msg = { .addr = priv->cfg->i2c_address, | ||
538 | .flags = I2C_M_RD, .buf = buf, .len = len }; | ||
539 | |||
540 | if (i2c_transfer(priv->i2c, &msg, 1) != 1) { | ||
541 | printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n",(int)len); | ||
542 | return -EREMOTEIO; | ||
543 | } | ||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | static int xc5000_fwupload(struct dvb_frontend* fe) | ||
548 | { | ||
549 | struct xc5000_priv *priv = fe->tuner_priv; | ||
550 | const struct firmware *fw; | ||
551 | int ret; | ||
552 | |||
553 | /* request the firmware, this will block and timeout */ | ||
554 | printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n", | ||
555 | XC5000_DEFAULT_FIRMWARE); | ||
556 | |||
557 | ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c->dev); | ||
558 | if (ret) { | ||
559 | printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n"); | ||
560 | ret = XC_RESULT_RESET_FAILURE; | ||
561 | goto out; | ||
562 | } else { | ||
563 | printk(KERN_INFO "xc5000: firmware read %Zu bytes.\n", | ||
564 | fw->size); | ||
565 | ret = XC_RESULT_SUCCESS; | ||
566 | } | ||
567 | |||
568 | if (fw->size != XC5000_DEFAULT_FIRMWARE_SIZE) { | ||
569 | printk(KERN_ERR "xc5000: firmware incorrect size\n"); | ||
570 | ret = XC_RESULT_RESET_FAILURE; | ||
571 | } else { | ||
572 | printk(KERN_INFO "xc5000: firmware upload\n"); | ||
573 | ret = xc_load_i2c_sequence(fe, fw->data ); | ||
574 | } | ||
575 | |||
576 | out: | ||
577 | release_firmware(fw); | ||
578 | return ret; | ||
579 | } | ||
580 | |||
581 | static void xc_debug_dump(struct xc5000_priv *priv) | ||
582 | { | ||
583 | u16 adc_envelope; | ||
584 | u32 freq_error_hz = 0; | ||
585 | u16 lock_status; | ||
586 | u32 hsync_freq_hz = 0; | ||
587 | u16 frame_lines; | ||
588 | u16 quality; | ||
589 | u8 hw_majorversion = 0, hw_minorversion = 0; | ||
590 | u8 fw_majorversion = 0, fw_minorversion = 0; | ||
591 | |||
592 | /* Wait for stats to stabilize. | ||
593 | * Frame Lines needs two frame times after initial lock | ||
594 | * before it is valid. | ||
595 | */ | ||
596 | xc_wait(100); | ||
597 | |||
598 | xc_get_ADC_Envelope(priv, &adc_envelope); | ||
599 | dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope); | ||
600 | |||
601 | xc_get_frequency_error(priv, &freq_error_hz); | ||
602 | dprintk(1, "*** Frequency error = %d Hz\n", freq_error_hz); | ||
603 | |||
604 | xc_get_lock_status(priv, &lock_status); | ||
605 | dprintk(1, "*** Lock status (0-Wait, 1-Locked, 2-No-signal) = %d\n", | ||
606 | lock_status); | ||
607 | |||
608 | xc_get_version(priv, &hw_majorversion, &hw_minorversion, | ||
609 | &fw_majorversion, &fw_minorversion); | ||
610 | dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x\n", | ||
611 | hw_majorversion, hw_minorversion, | ||
612 | fw_majorversion, fw_minorversion); | ||
613 | |||
614 | xc_get_hsync_freq(priv, &hsync_freq_hz); | ||
615 | dprintk(1, "*** Horizontal sync frequency = %d Hz\n", hsync_freq_hz); | ||
616 | |||
617 | xc_get_frame_lines(priv, &frame_lines); | ||
618 | dprintk(1, "*** Frame lines = %d\n", frame_lines); | ||
619 | |||
620 | xc_get_quality(priv, &quality); | ||
621 | dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality); | ||
622 | } | ||
623 | |||
624 | static int xc5000_set_params(struct dvb_frontend *fe, | ||
625 | struct dvb_frontend_parameters *params) | ||
626 | { | ||
627 | struct xc5000_priv *priv = fe->tuner_priv; | ||
628 | int ret; | ||
629 | |||
630 | dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency); | ||
631 | |||
632 | switch(params->u.vsb.modulation) { | ||
633 | case VSB_8: | ||
634 | case VSB_16: | ||
635 | dprintk(1, "%s() VSB modulation\n", __func__); | ||
636 | priv->rf_mode = XC_RF_MODE_AIR; | ||
637 | priv->freq_hz = params->frequency - 1750000; | ||
638 | priv->bandwidth = BANDWIDTH_6_MHZ; | ||
639 | priv->video_standard = DTV6; | ||
640 | break; | ||
641 | case QAM_64: | ||
642 | case QAM_256: | ||
643 | case QAM_AUTO: | ||
644 | dprintk(1, "%s() QAM modulation\n", __func__); | ||
645 | priv->rf_mode = XC_RF_MODE_CABLE; | ||
646 | priv->freq_hz = params->frequency - 1750000; | ||
647 | priv->bandwidth = BANDWIDTH_6_MHZ; | ||
648 | priv->video_standard = DTV6; | ||
649 | break; | ||
650 | default: | ||
651 | return -EINVAL; | ||
652 | } | ||
653 | |||
654 | dprintk(1, "%s() frequency=%d (compensated)\n", | ||
655 | __func__, priv->freq_hz); | ||
656 | |||
657 | ret = xc_SetSignalSource(priv, priv->rf_mode); | ||
658 | if (ret != XC_RESULT_SUCCESS) { | ||
659 | printk(KERN_ERR | ||
660 | "xc5000: xc_SetSignalSource(%d) failed\n", | ||
661 | priv->rf_mode); | ||
662 | return -EREMOTEIO; | ||
663 | } | ||
664 | |||
665 | ret = xc_SetTVStandard(priv, | ||
666 | XC5000_Standard[priv->video_standard].VideoMode, | ||
667 | XC5000_Standard[priv->video_standard].AudioMode); | ||
668 | if (ret != XC_RESULT_SUCCESS) { | ||
669 | printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n"); | ||
670 | return -EREMOTEIO; | ||
671 | } | ||
672 | |||
673 | ret = xc_set_IF_frequency(priv, priv->cfg->if_khz); | ||
674 | if (ret != XC_RESULT_SUCCESS) { | ||
675 | printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n", | ||
676 | priv->cfg->if_khz); | ||
677 | return -EIO; | ||
678 | } | ||
679 | |||
680 | xc_tune_channel(priv, priv->freq_hz); | ||
681 | |||
682 | if (debug) | ||
683 | xc_debug_dump(priv); | ||
684 | |||
685 | return 0; | ||
686 | } | ||
687 | |||
688 | static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe); | ||
689 | |||
690 | static int xc5000_set_analog_params(struct dvb_frontend *fe, | ||
691 | struct analog_parameters *params) | ||
692 | { | ||
693 | struct xc5000_priv *priv = fe->tuner_priv; | ||
694 | int ret; | ||
695 | |||
696 | if(priv->fwloaded == 0) | ||
697 | xc_load_fw_and_init_tuner(fe); | ||
698 | |||
699 | dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n", | ||
700 | __func__, params->frequency); | ||
701 | |||
702 | priv->rf_mode = XC_RF_MODE_CABLE; /* Fix me: it could be air. */ | ||
703 | |||
704 | /* params->frequency is in units of 62.5khz */ | ||
705 | priv->freq_hz = params->frequency * 62500; | ||
706 | |||
707 | /* FIX ME: Some video standards may have several possible audio | ||
708 | standards. We simply default to one of them here. | ||
709 | */ | ||
710 | if(params->std & V4L2_STD_MN) { | ||
711 | /* default to BTSC audio standard */ | ||
712 | priv->video_standard = MN_NTSC_PAL_BTSC; | ||
713 | goto tune_channel; | ||
714 | } | ||
715 | |||
716 | if(params->std & V4L2_STD_PAL_BG) { | ||
717 | /* default to NICAM audio standard */ | ||
718 | priv->video_standard = BG_PAL_NICAM; | ||
719 | goto tune_channel; | ||
720 | } | ||
721 | |||
722 | if(params->std & V4L2_STD_PAL_I) { | ||
723 | /* default to NICAM audio standard */ | ||
724 | priv->video_standard = I_PAL_NICAM; | ||
725 | goto tune_channel; | ||
726 | } | ||
727 | |||
728 | if(params->std & V4L2_STD_PAL_DK) { | ||
729 | /* default to NICAM audio standard */ | ||
730 | priv->video_standard = DK_PAL_NICAM; | ||
731 | goto tune_channel; | ||
732 | } | ||
733 | |||
734 | if(params->std & V4L2_STD_SECAM_DK) { | ||
735 | /* default to A2 DK1 audio standard */ | ||
736 | priv->video_standard = DK_SECAM_A2DK1; | ||
737 | goto tune_channel; | ||
738 | } | ||
739 | |||
740 | if(params->std & V4L2_STD_SECAM_L) { | ||
741 | priv->video_standard = L_SECAM_NICAM; | ||
742 | goto tune_channel; | ||
743 | } | ||
744 | |||
745 | if(params->std & V4L2_STD_SECAM_LC) { | ||
746 | priv->video_standard = LC_SECAM_NICAM; | ||
747 | goto tune_channel; | ||
748 | } | ||
749 | |||
750 | tune_channel: | ||
751 | ret = xc_SetSignalSource(priv, priv->rf_mode); | ||
752 | if (ret != XC_RESULT_SUCCESS) { | ||
753 | printk(KERN_ERR | ||
754 | "xc5000: xc_SetSignalSource(%d) failed\n", | ||
755 | priv->rf_mode); | ||
756 | return -EREMOTEIO; | ||
757 | } | ||
758 | |||
759 | ret = xc_SetTVStandard(priv, | ||
760 | XC5000_Standard[priv->video_standard].VideoMode, | ||
761 | XC5000_Standard[priv->video_standard].AudioMode); | ||
762 | if (ret != XC_RESULT_SUCCESS) { | ||
763 | printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n"); | ||
764 | return -EREMOTEIO; | ||
765 | } | ||
766 | |||
767 | xc_tune_channel(priv, priv->freq_hz); | ||
768 | |||
769 | if (debug) | ||
770 | xc_debug_dump(priv); | ||
771 | |||
772 | return 0; | ||
773 | } | ||
774 | |||
775 | static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq) | ||
776 | { | ||
777 | struct xc5000_priv *priv = fe->tuner_priv; | ||
778 | dprintk(1, "%s()\n", __func__); | ||
779 | *freq = priv->freq_hz; | ||
780 | return 0; | ||
781 | } | ||
782 | |||
783 | static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw) | ||
784 | { | ||
785 | struct xc5000_priv *priv = fe->tuner_priv; | ||
786 | dprintk(1, "%s()\n", __func__); | ||
787 | |||
788 | *bw = priv->bandwidth; | ||
789 | return 0; | ||
790 | } | ||
791 | |||
792 | static int xc5000_get_status(struct dvb_frontend *fe, u32 *status) | ||
793 | { | ||
794 | struct xc5000_priv *priv = fe->tuner_priv; | ||
795 | u16 lock_status = 0; | ||
796 | |||
797 | xc_get_lock_status(priv, &lock_status); | ||
798 | |||
799 | dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status); | ||
800 | |||
801 | *status = lock_status; | ||
802 | |||
803 | return 0; | ||
804 | } | ||
805 | |||
806 | static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe) | ||
807 | { | ||
808 | struct xc5000_priv *priv = fe->tuner_priv; | ||
809 | int ret = 0; | ||
810 | |||
811 | if (priv->fwloaded == 0) { | ||
812 | ret = xc5000_fwupload(fe); | ||
813 | if (ret != XC_RESULT_SUCCESS) | ||
814 | return ret; | ||
815 | priv->fwloaded = 1; | ||
816 | } | ||
817 | |||
818 | /* Start the tuner self-calibration process */ | ||
819 | ret |= xc_initialize(priv); | ||
820 | |||
821 | /* Wait for calibration to complete. | ||
822 | * We could continue but XC5000 will clock stretch subsequent | ||
823 | * I2C transactions until calibration is complete. This way we | ||
824 | * don't have to rely on clock stretching working. | ||
825 | */ | ||
826 | xc_wait( 100 ); | ||
827 | |||
828 | /* Default to "CABLE" mode */ | ||
829 | ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE); | ||
830 | |||
831 | return ret; | ||
832 | } | ||
833 | |||
834 | static int xc5000_sleep(struct dvb_frontend *fe) | ||
835 | { | ||
836 | struct xc5000_priv *priv = fe->tuner_priv; | ||
837 | int ret; | ||
838 | |||
839 | dprintk(1, "%s()\n", __func__); | ||
840 | |||
841 | /* On Pinnacle PCTV HD 800i, the tuner cannot be reinitialized | ||
842 | * once shutdown without reloading the driver. Maybe I am not | ||
843 | * doing something right. | ||
844 | * | ||
845 | */ | ||
846 | |||
847 | ret = xc_shutdown(priv); | ||
848 | if(ret != XC_RESULT_SUCCESS) { | ||
849 | printk(KERN_ERR | ||
850 | "xc5000: %s() unable to shutdown tuner\n", | ||
851 | __func__); | ||
852 | return -EREMOTEIO; | ||
853 | } | ||
854 | else { | ||
855 | /* priv->fwloaded = 0; */ | ||
856 | return XC_RESULT_SUCCESS; | ||
857 | } | ||
858 | } | ||
859 | |||
860 | static int xc5000_init(struct dvb_frontend *fe) | ||
861 | { | ||
862 | struct xc5000_priv *priv = fe->tuner_priv; | ||
863 | dprintk(1, "%s()\n", __func__); | ||
864 | |||
865 | if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) { | ||
866 | printk(KERN_ERR "xc5000: Unable to initialise tuner\n"); | ||
867 | return -EREMOTEIO; | ||
868 | } | ||
869 | |||
870 | if (debug) | ||
871 | xc_debug_dump(priv); | ||
872 | |||
873 | return 0; | ||
874 | } | ||
875 | |||
876 | static int xc5000_release(struct dvb_frontend *fe) | ||
877 | { | ||
878 | dprintk(1, "%s()\n", __func__); | ||
879 | kfree(fe->tuner_priv); | ||
880 | fe->tuner_priv = NULL; | ||
881 | return 0; | ||
882 | } | ||
883 | |||
884 | static const struct dvb_tuner_ops xc5000_tuner_ops = { | ||
885 | .info = { | ||
886 | .name = "Xceive XC5000", | ||
887 | .frequency_min = 1000000, | ||
888 | .frequency_max = 1023000000, | ||
889 | .frequency_step = 50000, | ||
890 | }, | ||
891 | |||
892 | .release = xc5000_release, | ||
893 | .init = xc5000_init, | ||
894 | .sleep = xc5000_sleep, | ||
895 | |||
896 | .set_params = xc5000_set_params, | ||
897 | .set_analog_params = xc5000_set_analog_params, | ||
898 | .get_frequency = xc5000_get_frequency, | ||
899 | .get_bandwidth = xc5000_get_bandwidth, | ||
900 | .get_status = xc5000_get_status | ||
901 | }; | ||
902 | |||
903 | struct dvb_frontend * xc5000_attach(struct dvb_frontend *fe, | ||
904 | struct i2c_adapter *i2c, | ||
905 | struct xc5000_config *cfg) | ||
906 | { | ||
907 | struct xc5000_priv *priv = NULL; | ||
908 | u16 id = 0; | ||
909 | |||
910 | dprintk(1, "%s()\n", __func__); | ||
911 | |||
912 | priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL); | ||
913 | if (priv == NULL) | ||
914 | return NULL; | ||
915 | |||
916 | priv->cfg = cfg; | ||
917 | priv->bandwidth = BANDWIDTH_6_MHZ; | ||
918 | priv->i2c = i2c; | ||
919 | |||
920 | /* Check if firmware has been loaded. It is possible that another | ||
921 | instance of the driver has loaded the firmware. | ||
922 | */ | ||
923 | if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) { | ||
924 | kfree(priv); | ||
925 | return NULL; | ||
926 | } | ||
927 | |||
928 | switch(id) { | ||
929 | case XC_PRODUCT_ID_FW_LOADED: | ||
930 | printk(KERN_INFO | ||
931 | "xc5000: Successfully identified at address 0x%02x\n", | ||
932 | cfg->i2c_address); | ||
933 | printk(KERN_INFO | ||
934 | "xc5000: Firmware has been loaded previously\n"); | ||
935 | priv->fwloaded = 1; | ||
936 | break; | ||
937 | case XC_PRODUCT_ID_FW_NOT_LOADED: | ||
938 | printk(KERN_INFO | ||
939 | "xc5000: Successfully identified at address 0x%02x\n", | ||
940 | cfg->i2c_address); | ||
941 | printk(KERN_INFO | ||
942 | "xc5000: Firmware has not been loaded previously\n"); | ||
943 | priv->fwloaded = 0; | ||
944 | break; | ||
945 | default: | ||
946 | printk(KERN_ERR | ||
947 | "xc5000: Device not found at addr 0x%02x (0x%x)\n", | ||
948 | cfg->i2c_address, id); | ||
949 | kfree(priv); | ||
950 | return NULL; | ||
951 | } | ||
952 | |||
953 | memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops, | ||
954 | sizeof(struct dvb_tuner_ops)); | ||
955 | |||
956 | fe->tuner_priv = priv; | ||
957 | |||
958 | return fe; | ||
959 | } | ||
960 | EXPORT_SYMBOL(xc5000_attach); | ||
961 | |||
962 | MODULE_AUTHOR("Steven Toth"); | ||
963 | MODULE_DESCRIPTION("Xceive xc5000 silicon tuner driver"); | ||
964 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/common/tuners/xc5000.h b/drivers/media/common/tuners/xc5000.h new file mode 100644 index 000000000000..b890883a0cdc --- /dev/null +++ b/drivers/media/common/tuners/xc5000.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * Driver for Xceive XC5000 "QAM/8VSB single chip tuner" | ||
3 | * | ||
4 | * Copyright (c) 2007 Steven Toth <stoth@hauppauge.com> | ||
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 | * | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef __XC5000_H__ | ||
23 | #define __XC5000_H__ | ||
24 | |||
25 | #include <linux/firmware.h> | ||
26 | |||
27 | struct dvb_frontend; | ||
28 | struct i2c_adapter; | ||
29 | |||
30 | struct xc5000_config { | ||
31 | u8 i2c_address; | ||
32 | u32 if_khz; | ||
33 | |||
34 | /* For each bridge framework, when it attaches either analog or digital, | ||
35 | * it has to store a reference back to its _core equivalent structure, | ||
36 | * so that it can service the hardware by steering gpio's etc. | ||
37 | * Each bridge implementation is different so cast priv accordingly. | ||
38 | * The xc5000 driver cares not for this value, other than ensuring | ||
39 | * it's passed back to a bridge during tuner_callback(). | ||
40 | */ | ||
41 | void *priv; | ||
42 | int (*tuner_callback) (void *priv, int command, int arg); | ||
43 | }; | ||
44 | |||
45 | /* xc5000 callback command */ | ||
46 | #define XC5000_TUNER_RESET 0 | ||
47 | |||
48 | #if defined(CONFIG_DVB_TUNER_XC5000) || \ | ||
49 | (defined(CONFIG_DVB_TUNER_XC5000_MODULE) && defined(MODULE)) | ||
50 | extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe, | ||
51 | struct i2c_adapter *i2c, | ||
52 | struct xc5000_config *cfg); | ||
53 | #else | ||
54 | static inline struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe, | ||
55 | struct i2c_adapter *i2c, | ||
56 | struct xc5000_config *cfg) | ||
57 | { | ||
58 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
59 | return NULL; | ||
60 | } | ||
61 | #endif // CONFIG_DVB_TUNER_XC5000 | ||
62 | |||
63 | #endif // __XC5000_H__ | ||
diff --git a/drivers/media/common/tuners/xc5000_priv.h b/drivers/media/common/tuners/xc5000_priv.h new file mode 100644 index 000000000000..13b2d19341da --- /dev/null +++ b/drivers/media/common/tuners/xc5000_priv.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * Driver for Xceive XC5000 "QAM/8VSB single chip tuner" | ||
3 | * | ||
4 | * Copyright (c) 2007 Steven Toth <stoth@hauppauge.com> | ||
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 | * | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef XC5000_PRIV_H | ||
23 | #define XC5000_PRIV_H | ||
24 | |||
25 | struct xc5000_priv { | ||
26 | struct xc5000_config *cfg; | ||
27 | struct i2c_adapter *i2c; | ||
28 | |||
29 | u32 freq_hz; | ||
30 | u32 bandwidth; | ||
31 | u8 video_standard; | ||
32 | u8 rf_mode; | ||
33 | u8 fwloaded; | ||
34 | }; | ||
35 | |||
36 | #endif | ||