xref: /OK3568_Linux_fs/kernel/drivers/media/dvb-frontends/dvb-pll.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * descriptions + helper functions for simple dvb plls.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/slab.h>
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/idr.h>
13*4882a593Smuzhiyun #include <linux/dvb/frontend.h>
14*4882a593Smuzhiyun #include <asm/types.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include "dvb-pll.h"
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #define dprintk(fmt, arg...) \
19*4882a593Smuzhiyun 	printk(KERN_DEBUG pr_fmt("%s: " fmt), __func__, ##arg)
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun struct dvb_pll_priv {
22*4882a593Smuzhiyun 	/* pll number */
23*4882a593Smuzhiyun 	int nr;
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun 	/* i2c details */
26*4882a593Smuzhiyun 	int pll_i2c_address;
27*4882a593Smuzhiyun 	struct i2c_adapter *i2c;
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun 	/* the PLL descriptor */
30*4882a593Smuzhiyun 	const struct dvb_pll_desc *pll_desc;
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun 	/* cached frequency/bandwidth */
33*4882a593Smuzhiyun 	u32 frequency;
34*4882a593Smuzhiyun 	u32 bandwidth;
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #define DVB_PLL_MAX 64
38*4882a593Smuzhiyun static DEFINE_IDA(pll_ida);
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun static int debug;
41*4882a593Smuzhiyun module_param(debug, int, 0644);
42*4882a593Smuzhiyun MODULE_PARM_DESC(debug, "enable verbose debug messages");
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun static unsigned int id[DVB_PLL_MAX] =
45*4882a593Smuzhiyun 	{ [ 0 ... (DVB_PLL_MAX-1) ] = DVB_PLL_UNDEFINED };
46*4882a593Smuzhiyun module_param_array(id, int, NULL, 0644);
47*4882a593Smuzhiyun MODULE_PARM_DESC(id, "force pll id to use (DEBUG ONLY)");
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun /* ----------------------------------------------------------- */
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun struct dvb_pll_desc {
52*4882a593Smuzhiyun 	const char *name;
53*4882a593Smuzhiyun 	u32  min;
54*4882a593Smuzhiyun 	u32  max;
55*4882a593Smuzhiyun 	u32  iffreq;
56*4882a593Smuzhiyun 	void (*set)(struct dvb_frontend *fe, u8 *buf);
57*4882a593Smuzhiyun 	u8   *initdata;
58*4882a593Smuzhiyun 	u8   *initdata2;
59*4882a593Smuzhiyun 	u8   *sleepdata;
60*4882a593Smuzhiyun 	int  count;
61*4882a593Smuzhiyun 	struct {
62*4882a593Smuzhiyun 		u32 limit;
63*4882a593Smuzhiyun 		u32 stepsize;
64*4882a593Smuzhiyun 		u8  config;
65*4882a593Smuzhiyun 		u8  cb;
66*4882a593Smuzhiyun 	} entries[];
67*4882a593Smuzhiyun };
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun /* ----------------------------------------------------------- */
70*4882a593Smuzhiyun /* descriptions                                                */
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
73*4882a593Smuzhiyun 	.name  = "Thomson dtt7579",
74*4882a593Smuzhiyun 	.min   = 177 * MHz,
75*4882a593Smuzhiyun 	.max   = 858 * MHz,
76*4882a593Smuzhiyun 	.iffreq= 36166667,
77*4882a593Smuzhiyun 	.sleepdata = (u8[]){ 2, 0xb4, 0x03 },
78*4882a593Smuzhiyun 	.count = 4,
79*4882a593Smuzhiyun 	.entries = {
80*4882a593Smuzhiyun 		{  443250000, 166667, 0xb4, 0x02 },
81*4882a593Smuzhiyun 		{  542000000, 166667, 0xb4, 0x08 },
82*4882a593Smuzhiyun 		{  771000000, 166667, 0xbc, 0x08 },
83*4882a593Smuzhiyun 		{  999999999, 166667, 0xf4, 0x08 },
84*4882a593Smuzhiyun 	},
85*4882a593Smuzhiyun };
86*4882a593Smuzhiyun 
thomson_dtt759x_bw(struct dvb_frontend * fe,u8 * buf)87*4882a593Smuzhiyun static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun 	u32 bw = fe->dtv_property_cache.bandwidth_hz;
90*4882a593Smuzhiyun 	if (bw == 7000000)
91*4882a593Smuzhiyun 		buf[3] |= 0x10;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_thomson_dtt759x = {
95*4882a593Smuzhiyun 	.name  = "Thomson dtt759x",
96*4882a593Smuzhiyun 	.min   = 177 * MHz,
97*4882a593Smuzhiyun 	.max   = 896 * MHz,
98*4882a593Smuzhiyun 	.set   = thomson_dtt759x_bw,
99*4882a593Smuzhiyun 	.iffreq= 36166667,
100*4882a593Smuzhiyun 	.sleepdata = (u8[]){ 2, 0x84, 0x03 },
101*4882a593Smuzhiyun 	.count = 5,
102*4882a593Smuzhiyun 	.entries = {
103*4882a593Smuzhiyun 		{  264000000, 166667, 0xb4, 0x02 },
104*4882a593Smuzhiyun 		{  470000000, 166667, 0xbc, 0x02 },
105*4882a593Smuzhiyun 		{  735000000, 166667, 0xbc, 0x08 },
106*4882a593Smuzhiyun 		{  835000000, 166667, 0xf4, 0x08 },
107*4882a593Smuzhiyun 		{  999999999, 166667, 0xfc, 0x08 },
108*4882a593Smuzhiyun 	},
109*4882a593Smuzhiyun };
110*4882a593Smuzhiyun 
thomson_dtt7520x_bw(struct dvb_frontend * fe,u8 * buf)111*4882a593Smuzhiyun static void thomson_dtt7520x_bw(struct dvb_frontend *fe, u8 *buf)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun 	u32 bw = fe->dtv_property_cache.bandwidth_hz;
114*4882a593Smuzhiyun 	if (bw == 8000000)
115*4882a593Smuzhiyun 		buf[3] ^= 0x10;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_thomson_dtt7520x = {
119*4882a593Smuzhiyun 	.name  = "Thomson dtt7520x",
120*4882a593Smuzhiyun 	.min   = 185 * MHz,
121*4882a593Smuzhiyun 	.max   = 900 * MHz,
122*4882a593Smuzhiyun 	.set   = thomson_dtt7520x_bw,
123*4882a593Smuzhiyun 	.iffreq = 36166667,
124*4882a593Smuzhiyun 	.count = 7,
125*4882a593Smuzhiyun 	.entries = {
126*4882a593Smuzhiyun 		{  305000000, 166667, 0xb4, 0x12 },
127*4882a593Smuzhiyun 		{  405000000, 166667, 0xbc, 0x12 },
128*4882a593Smuzhiyun 		{  445000000, 166667, 0xbc, 0x12 },
129*4882a593Smuzhiyun 		{  465000000, 166667, 0xf4, 0x18 },
130*4882a593Smuzhiyun 		{  735000000, 166667, 0xfc, 0x18 },
131*4882a593Smuzhiyun 		{  835000000, 166667, 0xbc, 0x18 },
132*4882a593Smuzhiyun 		{  999999999, 166667, 0xfc, 0x18 },
133*4882a593Smuzhiyun 	},
134*4882a593Smuzhiyun };
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_lg_z201 = {
137*4882a593Smuzhiyun 	.name  = "LG z201",
138*4882a593Smuzhiyun 	.min   = 174 * MHz,
139*4882a593Smuzhiyun 	.max   = 862 * MHz,
140*4882a593Smuzhiyun 	.iffreq= 36166667,
141*4882a593Smuzhiyun 	.sleepdata = (u8[]){ 2, 0xbc, 0x03 },
142*4882a593Smuzhiyun 	.count = 5,
143*4882a593Smuzhiyun 	.entries = {
144*4882a593Smuzhiyun 		{  157500000, 166667, 0xbc, 0x01 },
145*4882a593Smuzhiyun 		{  443250000, 166667, 0xbc, 0x02 },
146*4882a593Smuzhiyun 		{  542000000, 166667, 0xbc, 0x04 },
147*4882a593Smuzhiyun 		{  830000000, 166667, 0xf4, 0x04 },
148*4882a593Smuzhiyun 		{  999999999, 166667, 0xfc, 0x04 },
149*4882a593Smuzhiyun 	},
150*4882a593Smuzhiyun };
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_unknown_1 = {
153*4882a593Smuzhiyun 	.name  = "unknown 1", /* used by dntv live dvb-t */
154*4882a593Smuzhiyun 	.min   = 174 * MHz,
155*4882a593Smuzhiyun 	.max   = 862 * MHz,
156*4882a593Smuzhiyun 	.iffreq= 36166667,
157*4882a593Smuzhiyun 	.count = 9,
158*4882a593Smuzhiyun 	.entries = {
159*4882a593Smuzhiyun 		{  150000000, 166667, 0xb4, 0x01 },
160*4882a593Smuzhiyun 		{  173000000, 166667, 0xbc, 0x01 },
161*4882a593Smuzhiyun 		{  250000000, 166667, 0xb4, 0x02 },
162*4882a593Smuzhiyun 		{  400000000, 166667, 0xbc, 0x02 },
163*4882a593Smuzhiyun 		{  420000000, 166667, 0xf4, 0x02 },
164*4882a593Smuzhiyun 		{  470000000, 166667, 0xfc, 0x02 },
165*4882a593Smuzhiyun 		{  600000000, 166667, 0xbc, 0x08 },
166*4882a593Smuzhiyun 		{  730000000, 166667, 0xf4, 0x08 },
167*4882a593Smuzhiyun 		{  999999999, 166667, 0xfc, 0x08 },
168*4882a593Smuzhiyun 	},
169*4882a593Smuzhiyun };
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun /* Infineon TUA6010XS
172*4882a593Smuzhiyun  * used in Thomson Cable Tuner
173*4882a593Smuzhiyun  */
174*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_tua6010xs = {
175*4882a593Smuzhiyun 	.name  = "Infineon TUA6010XS",
176*4882a593Smuzhiyun 	.min   = 44250 * kHz,
177*4882a593Smuzhiyun 	.max   = 858 * MHz,
178*4882a593Smuzhiyun 	.iffreq= 36125000,
179*4882a593Smuzhiyun 	.count = 3,
180*4882a593Smuzhiyun 	.entries = {
181*4882a593Smuzhiyun 		{  115750000, 62500, 0x8e, 0x03 },
182*4882a593Smuzhiyun 		{  403250000, 62500, 0x8e, 0x06 },
183*4882a593Smuzhiyun 		{  999999999, 62500, 0x8e, 0x85 },
184*4882a593Smuzhiyun 	},
185*4882a593Smuzhiyun };
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun /* Panasonic env57h1xd5 (some Philips PLL ?) */
188*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_env57h1xd5 = {
189*4882a593Smuzhiyun 	.name  = "Panasonic ENV57H1XD5",
190*4882a593Smuzhiyun 	.min   = 44250 * kHz,
191*4882a593Smuzhiyun 	.max   = 858 * MHz,
192*4882a593Smuzhiyun 	.iffreq= 36125000,
193*4882a593Smuzhiyun 	.count = 4,
194*4882a593Smuzhiyun 	.entries = {
195*4882a593Smuzhiyun 		{  153000000, 166667, 0xc2, 0x41 },
196*4882a593Smuzhiyun 		{  470000000, 166667, 0xc2, 0x42 },
197*4882a593Smuzhiyun 		{  526000000, 166667, 0xc2, 0x84 },
198*4882a593Smuzhiyun 		{  999999999, 166667, 0xc2, 0xa4 },
199*4882a593Smuzhiyun 	},
200*4882a593Smuzhiyun };
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun /* Philips TDA6650/TDA6651
203*4882a593Smuzhiyun  * used in Panasonic ENV77H11D5
204*4882a593Smuzhiyun  */
tda665x_bw(struct dvb_frontend * fe,u8 * buf)205*4882a593Smuzhiyun static void tda665x_bw(struct dvb_frontend *fe, u8 *buf)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun 	u32 bw = fe->dtv_property_cache.bandwidth_hz;
208*4882a593Smuzhiyun 	if (bw == 8000000)
209*4882a593Smuzhiyun 		buf[3] |= 0x08;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_tda665x = {
213*4882a593Smuzhiyun 	.name  = "Philips TDA6650/TDA6651",
214*4882a593Smuzhiyun 	.min   = 44250 * kHz,
215*4882a593Smuzhiyun 	.max   = 858 * MHz,
216*4882a593Smuzhiyun 	.set   = tda665x_bw,
217*4882a593Smuzhiyun 	.iffreq= 36166667,
218*4882a593Smuzhiyun 	.initdata = (u8[]){ 4, 0x0b, 0xf5, 0x85, 0xab },
219*4882a593Smuzhiyun 	.count = 12,
220*4882a593Smuzhiyun 	.entries = {
221*4882a593Smuzhiyun 		{   93834000, 166667, 0xca, 0x61 /* 011 0 0 0  01 */ },
222*4882a593Smuzhiyun 		{  123834000, 166667, 0xca, 0xa1 /* 101 0 0 0  01 */ },
223*4882a593Smuzhiyun 		{  161000000, 166667, 0xca, 0xa1 /* 101 0 0 0  01 */ },
224*4882a593Smuzhiyun 		{  163834000, 166667, 0xca, 0xc2 /* 110 0 0 0  10 */ },
225*4882a593Smuzhiyun 		{  253834000, 166667, 0xca, 0x62 /* 011 0 0 0  10 */ },
226*4882a593Smuzhiyun 		{  383834000, 166667, 0xca, 0xa2 /* 101 0 0 0  10 */ },
227*4882a593Smuzhiyun 		{  443834000, 166667, 0xca, 0xc2 /* 110 0 0 0  10 */ },
228*4882a593Smuzhiyun 		{  444000000, 166667, 0xca, 0xc4 /* 110 0 0 1  00 */ },
229*4882a593Smuzhiyun 		{  583834000, 166667, 0xca, 0x64 /* 011 0 0 1  00 */ },
230*4882a593Smuzhiyun 		{  793834000, 166667, 0xca, 0xa4 /* 101 0 0 1  00 */ },
231*4882a593Smuzhiyun 		{  444834000, 166667, 0xca, 0xc4 /* 110 0 0 1  00 */ },
232*4882a593Smuzhiyun 		{  861000000, 166667, 0xca, 0xe4 /* 111 0 0 1  00 */ },
233*4882a593Smuzhiyun 	}
234*4882a593Smuzhiyun };
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun /* Infineon TUA6034
237*4882a593Smuzhiyun  * used in LG TDTP E102P
238*4882a593Smuzhiyun  */
tua6034_bw(struct dvb_frontend * fe,u8 * buf)239*4882a593Smuzhiyun static void tua6034_bw(struct dvb_frontend *fe, u8 *buf)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun 	u32 bw = fe->dtv_property_cache.bandwidth_hz;
242*4882a593Smuzhiyun 	if (bw == 7000000)
243*4882a593Smuzhiyun 		buf[3] |= 0x08;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_tua6034 = {
247*4882a593Smuzhiyun 	.name  = "Infineon TUA6034",
248*4882a593Smuzhiyun 	.min   = 44250 * kHz,
249*4882a593Smuzhiyun 	.max   = 858 * MHz,
250*4882a593Smuzhiyun 	.iffreq= 36166667,
251*4882a593Smuzhiyun 	.count = 3,
252*4882a593Smuzhiyun 	.set   = tua6034_bw,
253*4882a593Smuzhiyun 	.entries = {
254*4882a593Smuzhiyun 		{  174500000, 62500, 0xce, 0x01 },
255*4882a593Smuzhiyun 		{  230000000, 62500, 0xce, 0x02 },
256*4882a593Smuzhiyun 		{  999999999, 62500, 0xce, 0x04 },
257*4882a593Smuzhiyun 	},
258*4882a593Smuzhiyun };
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun /* ALPS TDED4
261*4882a593Smuzhiyun  * used in Nebula-Cards and USB boxes
262*4882a593Smuzhiyun  */
tded4_bw(struct dvb_frontend * fe,u8 * buf)263*4882a593Smuzhiyun static void tded4_bw(struct dvb_frontend *fe, u8 *buf)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun 	u32 bw = fe->dtv_property_cache.bandwidth_hz;
266*4882a593Smuzhiyun 	if (bw == 8000000)
267*4882a593Smuzhiyun 		buf[3] |= 0x04;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_tded4 = {
271*4882a593Smuzhiyun 	.name = "ALPS TDED4",
272*4882a593Smuzhiyun 	.min =  47 * MHz,
273*4882a593Smuzhiyun 	.max = 863 * MHz,
274*4882a593Smuzhiyun 	.iffreq= 36166667,
275*4882a593Smuzhiyun 	.set   = tded4_bw,
276*4882a593Smuzhiyun 	.count = 4,
277*4882a593Smuzhiyun 	.entries = {
278*4882a593Smuzhiyun 		{ 153000000, 166667, 0x85, 0x01 },
279*4882a593Smuzhiyun 		{ 470000000, 166667, 0x85, 0x02 },
280*4882a593Smuzhiyun 		{ 823000000, 166667, 0x85, 0x08 },
281*4882a593Smuzhiyun 		{ 999999999, 166667, 0x85, 0x88 },
282*4882a593Smuzhiyun 	}
283*4882a593Smuzhiyun };
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun /* ALPS TDHU2
286*4882a593Smuzhiyun  * used in AverTVHD MCE A180
287*4882a593Smuzhiyun  */
288*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_tdhu2 = {
289*4882a593Smuzhiyun 	.name = "ALPS TDHU2",
290*4882a593Smuzhiyun 	.min =  54 * MHz,
291*4882a593Smuzhiyun 	.max = 864 * MHz,
292*4882a593Smuzhiyun 	.iffreq= 44000000,
293*4882a593Smuzhiyun 	.count = 4,
294*4882a593Smuzhiyun 	.entries = {
295*4882a593Smuzhiyun 		{ 162000000, 62500, 0x85, 0x01 },
296*4882a593Smuzhiyun 		{ 426000000, 62500, 0x85, 0x02 },
297*4882a593Smuzhiyun 		{ 782000000, 62500, 0x85, 0x08 },
298*4882a593Smuzhiyun 		{ 999999999, 62500, 0x85, 0x88 },
299*4882a593Smuzhiyun 	}
300*4882a593Smuzhiyun };
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun /* Samsung TBMV30111IN / TBMV30712IN1
303*4882a593Smuzhiyun  * used in Air2PC ATSC - 2nd generation (nxt2002)
304*4882a593Smuzhiyun  */
305*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_samsung_tbmv = {
306*4882a593Smuzhiyun 	.name = "Samsung TBMV30111IN / TBMV30712IN1",
307*4882a593Smuzhiyun 	.min =  54 * MHz,
308*4882a593Smuzhiyun 	.max = 860 * MHz,
309*4882a593Smuzhiyun 	.iffreq= 44000000,
310*4882a593Smuzhiyun 	.count = 6,
311*4882a593Smuzhiyun 	.entries = {
312*4882a593Smuzhiyun 		{ 172000000, 166667, 0xb4, 0x01 },
313*4882a593Smuzhiyun 		{ 214000000, 166667, 0xb4, 0x02 },
314*4882a593Smuzhiyun 		{ 467000000, 166667, 0xbc, 0x02 },
315*4882a593Smuzhiyun 		{ 721000000, 166667, 0xbc, 0x08 },
316*4882a593Smuzhiyun 		{ 841000000, 166667, 0xf4, 0x08 },
317*4882a593Smuzhiyun 		{ 999999999, 166667, 0xfc, 0x02 },
318*4882a593Smuzhiyun 	}
319*4882a593Smuzhiyun };
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun /*
322*4882a593Smuzhiyun  * Philips SD1878 Tuner.
323*4882a593Smuzhiyun  */
324*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
325*4882a593Smuzhiyun 	.name  = "Philips SD1878",
326*4882a593Smuzhiyun 	.min   =  950 * MHz,
327*4882a593Smuzhiyun 	.max   = 2150 * MHz,
328*4882a593Smuzhiyun 	.iffreq= 249, /* zero-IF, offset 249 is to round up */
329*4882a593Smuzhiyun 	.count = 4,
330*4882a593Smuzhiyun 	.entries = {
331*4882a593Smuzhiyun 		{ 1250000, 500, 0xc4, 0x00},
332*4882a593Smuzhiyun 		{ 1450000, 500, 0xc4, 0x40},
333*4882a593Smuzhiyun 		{ 2050000, 500, 0xc4, 0x80},
334*4882a593Smuzhiyun 		{ 2150000, 500, 0xc4, 0xc0},
335*4882a593Smuzhiyun 	},
336*4882a593Smuzhiyun };
337*4882a593Smuzhiyun 
opera1_bw(struct dvb_frontend * fe,u8 * buf)338*4882a593Smuzhiyun static void opera1_bw(struct dvb_frontend *fe, u8 *buf)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
341*4882a593Smuzhiyun 	struct dvb_pll_priv *priv = fe->tuner_priv;
342*4882a593Smuzhiyun 	u32 b_w  = (c->symbol_rate * 27) / 32000;
343*4882a593Smuzhiyun 	struct i2c_msg msg = {
344*4882a593Smuzhiyun 		.addr = priv->pll_i2c_address,
345*4882a593Smuzhiyun 		.flags = 0,
346*4882a593Smuzhiyun 		.buf = buf,
347*4882a593Smuzhiyun 		.len = 4
348*4882a593Smuzhiyun 	};
349*4882a593Smuzhiyun 	int result;
350*4882a593Smuzhiyun 	u8 lpf;
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	if (fe->ops.i2c_gate_ctrl)
353*4882a593Smuzhiyun 		fe->ops.i2c_gate_ctrl(fe, 1);
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	result = i2c_transfer(priv->i2c, &msg, 1);
356*4882a593Smuzhiyun 	if (result != 1)
357*4882a593Smuzhiyun 		pr_err("%s: i2c_transfer failed:%d",
358*4882a593Smuzhiyun 			__func__, result);
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	if (b_w <= 10000)
361*4882a593Smuzhiyun 		lpf = 0xc;
362*4882a593Smuzhiyun 	else if (b_w <= 12000)
363*4882a593Smuzhiyun 		lpf = 0x2;
364*4882a593Smuzhiyun 	else if (b_w <= 14000)
365*4882a593Smuzhiyun 		lpf = 0xa;
366*4882a593Smuzhiyun 	else if (b_w <= 16000)
367*4882a593Smuzhiyun 		lpf = 0x6;
368*4882a593Smuzhiyun 	else if (b_w <= 18000)
369*4882a593Smuzhiyun 		lpf = 0xe;
370*4882a593Smuzhiyun 	else if (b_w <= 20000)
371*4882a593Smuzhiyun 		lpf = 0x1;
372*4882a593Smuzhiyun 	else if (b_w <= 22000)
373*4882a593Smuzhiyun 		lpf = 0x9;
374*4882a593Smuzhiyun 	else if (b_w <= 24000)
375*4882a593Smuzhiyun 		lpf = 0x5;
376*4882a593Smuzhiyun 	else if (b_w <= 26000)
377*4882a593Smuzhiyun 		lpf = 0xd;
378*4882a593Smuzhiyun 	else if (b_w <= 28000)
379*4882a593Smuzhiyun 		lpf = 0x3;
380*4882a593Smuzhiyun 		else
381*4882a593Smuzhiyun 		lpf = 0xb;
382*4882a593Smuzhiyun 	buf[2] ^= 0x1c; /* Flip bits 3-5 */
383*4882a593Smuzhiyun 	/* Set lpf */
384*4882a593Smuzhiyun 	buf[2] |= ((lpf >> 2) & 0x3) << 3;
385*4882a593Smuzhiyun 	buf[3] |= (lpf & 0x3) << 2;
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	return;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_opera1 = {
391*4882a593Smuzhiyun 	.name  = "Opera Tuner",
392*4882a593Smuzhiyun 	.min   =  900 * MHz,
393*4882a593Smuzhiyun 	.max   = 2250 * MHz,
394*4882a593Smuzhiyun 	.initdata = (u8[]){ 4, 0x08, 0xe5, 0xe1, 0x00 },
395*4882a593Smuzhiyun 	.initdata2 = (u8[]){ 4, 0x08, 0xe5, 0xe5, 0x00 },
396*4882a593Smuzhiyun 	.iffreq= 0,
397*4882a593Smuzhiyun 	.set   = opera1_bw,
398*4882a593Smuzhiyun 	.count = 8,
399*4882a593Smuzhiyun 	.entries = {
400*4882a593Smuzhiyun 		{ 1064000, 500, 0xf9, 0xc2 },
401*4882a593Smuzhiyun 		{ 1169000, 500, 0xf9, 0xe2 },
402*4882a593Smuzhiyun 		{ 1299000, 500, 0xf9, 0x20 },
403*4882a593Smuzhiyun 		{ 1444000, 500, 0xf9, 0x40 },
404*4882a593Smuzhiyun 		{ 1606000, 500, 0xf9, 0x60 },
405*4882a593Smuzhiyun 		{ 1777000, 500, 0xf9, 0x80 },
406*4882a593Smuzhiyun 		{ 1941000, 500, 0xf9, 0xa0 },
407*4882a593Smuzhiyun 		{ 2250000, 500, 0xf9, 0xc0 },
408*4882a593Smuzhiyun 	}
409*4882a593Smuzhiyun };
410*4882a593Smuzhiyun 
samsung_dtos403ih102a_set(struct dvb_frontend * fe,u8 * buf)411*4882a593Smuzhiyun static void samsung_dtos403ih102a_set(struct dvb_frontend *fe, u8 *buf)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun 	struct dvb_pll_priv *priv = fe->tuner_priv;
414*4882a593Smuzhiyun 	struct i2c_msg msg = {
415*4882a593Smuzhiyun 		.addr = priv->pll_i2c_address,
416*4882a593Smuzhiyun 		.flags = 0,
417*4882a593Smuzhiyun 		.buf = buf,
418*4882a593Smuzhiyun 		.len = 4
419*4882a593Smuzhiyun 	};
420*4882a593Smuzhiyun 	int result;
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	if (fe->ops.i2c_gate_ctrl)
423*4882a593Smuzhiyun 		fe->ops.i2c_gate_ctrl(fe, 1);
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	result = i2c_transfer(priv->i2c, &msg, 1);
426*4882a593Smuzhiyun 	if (result != 1)
427*4882a593Smuzhiyun 		pr_err("%s: i2c_transfer failed:%d",
428*4882a593Smuzhiyun 			__func__, result);
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	buf[2] = 0x9e;
431*4882a593Smuzhiyun 	buf[3] = 0x90;
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	return;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun /* unknown pll used in Samsung DTOS403IH102A DVB-C tuner */
437*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {
438*4882a593Smuzhiyun 	.name   = "Samsung DTOS403IH102A",
439*4882a593Smuzhiyun 	.min    = 44250 * kHz,
440*4882a593Smuzhiyun 	.max    = 858 * MHz,
441*4882a593Smuzhiyun 	.iffreq =  36125000,
442*4882a593Smuzhiyun 	.count  = 8,
443*4882a593Smuzhiyun 	.set    = samsung_dtos403ih102a_set,
444*4882a593Smuzhiyun 	.entries = {
445*4882a593Smuzhiyun 		{ 135000000, 62500, 0xbe, 0x01 },
446*4882a593Smuzhiyun 		{ 177000000, 62500, 0xf6, 0x01 },
447*4882a593Smuzhiyun 		{ 370000000, 62500, 0xbe, 0x02 },
448*4882a593Smuzhiyun 		{ 450000000, 62500, 0xf6, 0x02 },
449*4882a593Smuzhiyun 		{ 466000000, 62500, 0xfe, 0x02 },
450*4882a593Smuzhiyun 		{ 538000000, 62500, 0xbe, 0x08 },
451*4882a593Smuzhiyun 		{ 826000000, 62500, 0xf6, 0x08 },
452*4882a593Smuzhiyun 		{ 999999999, 62500, 0xfe, 0x08 },
453*4882a593Smuzhiyun 	}
454*4882a593Smuzhiyun };
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun /* Samsung TDTC9251DH0 DVB-T NIM, as used on AirStar 2 */
457*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_samsung_tdtc9251dh0 = {
458*4882a593Smuzhiyun 	.name	= "Samsung TDTC9251DH0",
459*4882a593Smuzhiyun 	.min	=  48 * MHz,
460*4882a593Smuzhiyun 	.max	= 863 * MHz,
461*4882a593Smuzhiyun 	.iffreq	=  36166667,
462*4882a593Smuzhiyun 	.count	= 3,
463*4882a593Smuzhiyun 	.entries = {
464*4882a593Smuzhiyun 		{ 157500000, 166667, 0xcc, 0x09 },
465*4882a593Smuzhiyun 		{ 443000000, 166667, 0xcc, 0x0a },
466*4882a593Smuzhiyun 		{ 863000000, 166667, 0xcc, 0x08 },
467*4882a593Smuzhiyun 	}
468*4882a593Smuzhiyun };
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun /* Samsung TBDU18132 DVB-S NIM with TSA5059 PLL, used in SkyStar2 DVB-S 2.3 */
471*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_samsung_tbdu18132 = {
472*4882a593Smuzhiyun 	.name = "Samsung TBDU18132",
473*4882a593Smuzhiyun 	.min	=  950 * MHz,
474*4882a593Smuzhiyun 	.max	= 2150 * MHz, /* guesses */
475*4882a593Smuzhiyun 	.iffreq = 0,
476*4882a593Smuzhiyun 	.count = 2,
477*4882a593Smuzhiyun 	.entries = {
478*4882a593Smuzhiyun 		{ 1550000, 125, 0x84, 0x82 },
479*4882a593Smuzhiyun 		{ 4095937, 125, 0x84, 0x80 },
480*4882a593Smuzhiyun 	}
481*4882a593Smuzhiyun 	/* TSA5059 PLL has a 17 bit divisor rather than the 15 bits supported
482*4882a593Smuzhiyun 	 * by this driver.  The two extra bits are 0x60 in the third byte.  15
483*4882a593Smuzhiyun 	 * bits is enough for over 4 GHz, which is enough to cover the range
484*4882a593Smuzhiyun 	 * of this tuner.  We could use the additional divisor bits by adding
485*4882a593Smuzhiyun 	 * more entries, e.g.
486*4882a593Smuzhiyun 	 { 0x0ffff * 125 + 125/2, 125, 0x84 | 0x20, },
487*4882a593Smuzhiyun 	 { 0x17fff * 125 + 125/2, 125, 0x84 | 0x40, },
488*4882a593Smuzhiyun 	 { 0x1ffff * 125 + 125/2, 125, 0x84 | 0x60, }, */
489*4882a593Smuzhiyun };
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun /* Samsung TBMU24112 DVB-S NIM with SL1935 zero-IF tuner */
492*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_samsung_tbmu24112 = {
493*4882a593Smuzhiyun 	.name = "Samsung TBMU24112",
494*4882a593Smuzhiyun 	.min	=  950 * MHz,
495*4882a593Smuzhiyun 	.max	= 2150 * MHz, /* guesses */
496*4882a593Smuzhiyun 	.iffreq = 0,
497*4882a593Smuzhiyun 	.count = 2,
498*4882a593Smuzhiyun 	.entries = {
499*4882a593Smuzhiyun 		{ 1500000, 125, 0x84, 0x18 },
500*4882a593Smuzhiyun 		{ 9999999, 125, 0x84, 0x08 },
501*4882a593Smuzhiyun 	}
502*4882a593Smuzhiyun };
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun /* Alps TDEE4 DVB-C NIM, used on Cablestar 2 */
505*4882a593Smuzhiyun /* byte 4 : 1  *   *   AGD R3  R2  R1  R0
506*4882a593Smuzhiyun  * byte 5 : C1 *   RE  RTS BS4 BS3 BS2 BS1
507*4882a593Smuzhiyun  * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95
508*4882a593Smuzhiyun  * Range(MHz)  C1 *  RE RTS BS4 BS3 BS2 BS1  Byte 5
509*4882a593Smuzhiyun  *  47 - 153   0  *  0   0   0   0   0   1   0x01
510*4882a593Smuzhiyun  * 153 - 430   0  *  0   0   0   0   1   0   0x02
511*4882a593Smuzhiyun  * 430 - 822   0  *  0   0   1   0   0   0   0x08
512*4882a593Smuzhiyun  * 822 - 862   1  *  0   0   1   0   0   0   0x88 */
513*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_alps_tdee4 = {
514*4882a593Smuzhiyun 	.name = "ALPS TDEE4",
515*4882a593Smuzhiyun 	.min	=  47 * MHz,
516*4882a593Smuzhiyun 	.max	= 862 * MHz,
517*4882a593Smuzhiyun 	.iffreq	=  36125000,
518*4882a593Smuzhiyun 	.count = 4,
519*4882a593Smuzhiyun 	.entries = {
520*4882a593Smuzhiyun 		{ 153000000, 62500, 0x95, 0x01 },
521*4882a593Smuzhiyun 		{ 430000000, 62500, 0x95, 0x02 },
522*4882a593Smuzhiyun 		{ 822000000, 62500, 0x95, 0x08 },
523*4882a593Smuzhiyun 		{ 999999999, 62500, 0x95, 0x88 },
524*4882a593Smuzhiyun 	}
525*4882a593Smuzhiyun };
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun /* Infineon TUA6034 ISDB-T, used in Friio */
528*4882a593Smuzhiyun /* CP cur. 50uA, AGC takeover: 103dBuV, PORT3 on */
529*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_tua6034_friio = {
530*4882a593Smuzhiyun 	.name   = "Infineon TUA6034 ISDB-T (Friio)",
531*4882a593Smuzhiyun 	.min    =  90 * MHz,
532*4882a593Smuzhiyun 	.max    = 770 * MHz,
533*4882a593Smuzhiyun 	.iffreq =  57000000,
534*4882a593Smuzhiyun 	.initdata = (u8[]){ 4, 0x9a, 0x50, 0xb2, 0x08 },
535*4882a593Smuzhiyun 	.sleepdata = (u8[]){ 4, 0x9a, 0x70, 0xb3, 0x0b },
536*4882a593Smuzhiyun 	.count = 3,
537*4882a593Smuzhiyun 	.entries = {
538*4882a593Smuzhiyun 		{ 170000000, 142857, 0xba, 0x09 },
539*4882a593Smuzhiyun 		{ 470000000, 142857, 0xba, 0x0a },
540*4882a593Smuzhiyun 		{ 770000000, 142857, 0xb2, 0x08 },
541*4882a593Smuzhiyun 	}
542*4882a593Smuzhiyun };
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun /* Philips TDA6651 ISDB-T, used in Earthsoft PT1 */
545*4882a593Smuzhiyun static const struct dvb_pll_desc dvb_pll_tda665x_earth_pt1 = {
546*4882a593Smuzhiyun 	.name   = "Philips TDA6651 ISDB-T (EarthSoft PT1)",
547*4882a593Smuzhiyun 	.min    =  90 * MHz,
548*4882a593Smuzhiyun 	.max    = 770 * MHz,
549*4882a593Smuzhiyun 	.iffreq =  57000000,
550*4882a593Smuzhiyun 	.initdata = (u8[]){ 5, 0x0e, 0x7f, 0xc1, 0x80, 0x80 },
551*4882a593Smuzhiyun 	.count = 10,
552*4882a593Smuzhiyun 	.entries = {
553*4882a593Smuzhiyun 		{ 140000000, 142857, 0xc1, 0x81 },
554*4882a593Smuzhiyun 		{ 170000000, 142857, 0xc1, 0xa1 },
555*4882a593Smuzhiyun 		{ 220000000, 142857, 0xc1, 0x62 },
556*4882a593Smuzhiyun 		{ 330000000, 142857, 0xc1, 0xa2 },
557*4882a593Smuzhiyun 		{ 402000000, 142857, 0xc1, 0xe2 },
558*4882a593Smuzhiyun 		{ 450000000, 142857, 0xc1, 0x64 },
559*4882a593Smuzhiyun 		{ 550000000, 142857, 0xc1, 0x84 },
560*4882a593Smuzhiyun 		{ 600000000, 142857, 0xc1, 0xa4 },
561*4882a593Smuzhiyun 		{ 700000000, 142857, 0xc1, 0xc4 },
562*4882a593Smuzhiyun 		{ 770000000, 142857, 0xc1, 0xe4 },
563*4882a593Smuzhiyun 	}
564*4882a593Smuzhiyun };
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun /* ----------------------------------------------------------- */
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun static const struct dvb_pll_desc *pll_list[] = {
569*4882a593Smuzhiyun 	[DVB_PLL_UNDEFINED]              = NULL,
570*4882a593Smuzhiyun 	[DVB_PLL_THOMSON_DTT7579]        = &dvb_pll_thomson_dtt7579,
571*4882a593Smuzhiyun 	[DVB_PLL_THOMSON_DTT759X]        = &dvb_pll_thomson_dtt759x,
572*4882a593Smuzhiyun 	[DVB_PLL_THOMSON_DTT7520X]       = &dvb_pll_thomson_dtt7520x,
573*4882a593Smuzhiyun 	[DVB_PLL_LG_Z201]                = &dvb_pll_lg_z201,
574*4882a593Smuzhiyun 	[DVB_PLL_UNKNOWN_1]              = &dvb_pll_unknown_1,
575*4882a593Smuzhiyun 	[DVB_PLL_TUA6010XS]              = &dvb_pll_tua6010xs,
576*4882a593Smuzhiyun 	[DVB_PLL_ENV57H1XD5]             = &dvb_pll_env57h1xd5,
577*4882a593Smuzhiyun 	[DVB_PLL_TUA6034]                = &dvb_pll_tua6034,
578*4882a593Smuzhiyun 	[DVB_PLL_TDA665X]                = &dvb_pll_tda665x,
579*4882a593Smuzhiyun 	[DVB_PLL_TDED4]                  = &dvb_pll_tded4,
580*4882a593Smuzhiyun 	[DVB_PLL_TDEE4]                  = &dvb_pll_alps_tdee4,
581*4882a593Smuzhiyun 	[DVB_PLL_TDHU2]                  = &dvb_pll_tdhu2,
582*4882a593Smuzhiyun 	[DVB_PLL_SAMSUNG_TBMV]           = &dvb_pll_samsung_tbmv,
583*4882a593Smuzhiyun 	[DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261,
584*4882a593Smuzhiyun 	[DVB_PLL_OPERA1]                 = &dvb_pll_opera1,
585*4882a593Smuzhiyun 	[DVB_PLL_SAMSUNG_DTOS403IH102A]  = &dvb_pll_samsung_dtos403ih102a,
586*4882a593Smuzhiyun 	[DVB_PLL_SAMSUNG_TDTC9251DH0]    = &dvb_pll_samsung_tdtc9251dh0,
587*4882a593Smuzhiyun 	[DVB_PLL_SAMSUNG_TBDU18132]	 = &dvb_pll_samsung_tbdu18132,
588*4882a593Smuzhiyun 	[DVB_PLL_SAMSUNG_TBMU24112]      = &dvb_pll_samsung_tbmu24112,
589*4882a593Smuzhiyun 	[DVB_PLL_TUA6034_FRIIO]          = &dvb_pll_tua6034_friio,
590*4882a593Smuzhiyun 	[DVB_PLL_TDA665X_EARTH_PT1]      = &dvb_pll_tda665x_earth_pt1,
591*4882a593Smuzhiyun };
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun /* ----------------------------------------------------------- */
594*4882a593Smuzhiyun /* code                                                        */
595*4882a593Smuzhiyun 
dvb_pll_configure(struct dvb_frontend * fe,u8 * buf,const u32 frequency)596*4882a593Smuzhiyun static int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf,
597*4882a593Smuzhiyun 			     const u32 frequency)
598*4882a593Smuzhiyun {
599*4882a593Smuzhiyun 	struct dvb_pll_priv *priv = fe->tuner_priv;
600*4882a593Smuzhiyun 	const struct dvb_pll_desc *desc = priv->pll_desc;
601*4882a593Smuzhiyun 	u32 div;
602*4882a593Smuzhiyun 	int i;
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun 	for (i = 0; i < desc->count; i++) {
605*4882a593Smuzhiyun 		if (frequency > desc->entries[i].limit)
606*4882a593Smuzhiyun 			continue;
607*4882a593Smuzhiyun 		break;
608*4882a593Smuzhiyun 	}
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun 	if (debug)
611*4882a593Smuzhiyun 		dprintk("pll: %s: freq=%d | i=%d/%d\n", desc->name,
612*4882a593Smuzhiyun 		       frequency, i, desc->count);
613*4882a593Smuzhiyun 	if (i == desc->count)
614*4882a593Smuzhiyun 		return -EINVAL;
615*4882a593Smuzhiyun 
616*4882a593Smuzhiyun 	div = (frequency + desc->iffreq +
617*4882a593Smuzhiyun 	       desc->entries[i].stepsize/2) / desc->entries[i].stepsize;
618*4882a593Smuzhiyun 	buf[0] = div >> 8;
619*4882a593Smuzhiyun 	buf[1] = div & 0xff;
620*4882a593Smuzhiyun 	buf[2] = desc->entries[i].config;
621*4882a593Smuzhiyun 	buf[3] = desc->entries[i].cb;
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	if (desc->set)
624*4882a593Smuzhiyun 		desc->set(fe, buf);
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun 	if (debug)
627*4882a593Smuzhiyun 		dprintk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
628*4882a593Smuzhiyun 		       desc->name, div, buf[0], buf[1], buf[2], buf[3]);
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun 	// calculate the frequency we set it to
631*4882a593Smuzhiyun 	return (div * desc->entries[i].stepsize) - desc->iffreq;
632*4882a593Smuzhiyun }
633*4882a593Smuzhiyun 
dvb_pll_release(struct dvb_frontend * fe)634*4882a593Smuzhiyun static void dvb_pll_release(struct dvb_frontend *fe)
635*4882a593Smuzhiyun {
636*4882a593Smuzhiyun 	kfree(fe->tuner_priv);
637*4882a593Smuzhiyun 	fe->tuner_priv = NULL;
638*4882a593Smuzhiyun }
639*4882a593Smuzhiyun 
dvb_pll_sleep(struct dvb_frontend * fe)640*4882a593Smuzhiyun static int dvb_pll_sleep(struct dvb_frontend *fe)
641*4882a593Smuzhiyun {
642*4882a593Smuzhiyun 	struct dvb_pll_priv *priv = fe->tuner_priv;
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun 	if (priv->i2c == NULL)
645*4882a593Smuzhiyun 		return -EINVAL;
646*4882a593Smuzhiyun 
647*4882a593Smuzhiyun 	if (priv->pll_desc->sleepdata) {
648*4882a593Smuzhiyun 		struct i2c_msg msg = { .flags = 0,
649*4882a593Smuzhiyun 			.addr = priv->pll_i2c_address,
650*4882a593Smuzhiyun 			.buf = priv->pll_desc->sleepdata + 1,
651*4882a593Smuzhiyun 			.len = priv->pll_desc->sleepdata[0] };
652*4882a593Smuzhiyun 
653*4882a593Smuzhiyun 		int result;
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun 		if (fe->ops.i2c_gate_ctrl)
656*4882a593Smuzhiyun 			fe->ops.i2c_gate_ctrl(fe, 1);
657*4882a593Smuzhiyun 		if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
658*4882a593Smuzhiyun 			return result;
659*4882a593Smuzhiyun 		}
660*4882a593Smuzhiyun 		return 0;
661*4882a593Smuzhiyun 	}
662*4882a593Smuzhiyun 	/* Shouldn't be called when initdata is NULL, maybe BUG()? */
663*4882a593Smuzhiyun 	return -EINVAL;
664*4882a593Smuzhiyun }
665*4882a593Smuzhiyun 
dvb_pll_set_params(struct dvb_frontend * fe)666*4882a593Smuzhiyun static int dvb_pll_set_params(struct dvb_frontend *fe)
667*4882a593Smuzhiyun {
668*4882a593Smuzhiyun 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
669*4882a593Smuzhiyun 	struct dvb_pll_priv *priv = fe->tuner_priv;
670*4882a593Smuzhiyun 	u8 buf[4];
671*4882a593Smuzhiyun 	struct i2c_msg msg =
672*4882a593Smuzhiyun 		{ .addr = priv->pll_i2c_address, .flags = 0,
673*4882a593Smuzhiyun 		  .buf = buf, .len = sizeof(buf) };
674*4882a593Smuzhiyun 	int result;
675*4882a593Smuzhiyun 	u32 frequency = 0;
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun 	if (priv->i2c == NULL)
678*4882a593Smuzhiyun 		return -EINVAL;
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun 	result = dvb_pll_configure(fe, buf, c->frequency);
681*4882a593Smuzhiyun 	if (result < 0)
682*4882a593Smuzhiyun 		return result;
683*4882a593Smuzhiyun 	else
684*4882a593Smuzhiyun 		frequency = result;
685*4882a593Smuzhiyun 
686*4882a593Smuzhiyun 	if (fe->ops.i2c_gate_ctrl)
687*4882a593Smuzhiyun 		fe->ops.i2c_gate_ctrl(fe, 1);
688*4882a593Smuzhiyun 	if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
689*4882a593Smuzhiyun 		return result;
690*4882a593Smuzhiyun 	}
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 	priv->frequency = frequency;
693*4882a593Smuzhiyun 	priv->bandwidth = c->bandwidth_hz;
694*4882a593Smuzhiyun 
695*4882a593Smuzhiyun 	return 0;
696*4882a593Smuzhiyun }
697*4882a593Smuzhiyun 
dvb_pll_calc_regs(struct dvb_frontend * fe,u8 * buf,int buf_len)698*4882a593Smuzhiyun static int dvb_pll_calc_regs(struct dvb_frontend *fe,
699*4882a593Smuzhiyun 			     u8 *buf, int buf_len)
700*4882a593Smuzhiyun {
701*4882a593Smuzhiyun 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
702*4882a593Smuzhiyun 	struct dvb_pll_priv *priv = fe->tuner_priv;
703*4882a593Smuzhiyun 	int result;
704*4882a593Smuzhiyun 	u32 frequency = 0;
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun 	if (buf_len < 5)
707*4882a593Smuzhiyun 		return -EINVAL;
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 	result = dvb_pll_configure(fe, buf + 1, c->frequency);
710*4882a593Smuzhiyun 	if (result < 0)
711*4882a593Smuzhiyun 		return result;
712*4882a593Smuzhiyun 	else
713*4882a593Smuzhiyun 		frequency = result;
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun 	buf[0] = priv->pll_i2c_address;
716*4882a593Smuzhiyun 
717*4882a593Smuzhiyun 	priv->frequency = frequency;
718*4882a593Smuzhiyun 	priv->bandwidth = c->bandwidth_hz;
719*4882a593Smuzhiyun 
720*4882a593Smuzhiyun 	return 5;
721*4882a593Smuzhiyun }
722*4882a593Smuzhiyun 
dvb_pll_get_frequency(struct dvb_frontend * fe,u32 * frequency)723*4882a593Smuzhiyun static int dvb_pll_get_frequency(struct dvb_frontend *fe, u32 *frequency)
724*4882a593Smuzhiyun {
725*4882a593Smuzhiyun 	struct dvb_pll_priv *priv = fe->tuner_priv;
726*4882a593Smuzhiyun 	*frequency = priv->frequency;
727*4882a593Smuzhiyun 	return 0;
728*4882a593Smuzhiyun }
729*4882a593Smuzhiyun 
dvb_pll_get_bandwidth(struct dvb_frontend * fe,u32 * bandwidth)730*4882a593Smuzhiyun static int dvb_pll_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
731*4882a593Smuzhiyun {
732*4882a593Smuzhiyun 	struct dvb_pll_priv *priv = fe->tuner_priv;
733*4882a593Smuzhiyun 	*bandwidth = priv->bandwidth;
734*4882a593Smuzhiyun 	return 0;
735*4882a593Smuzhiyun }
736*4882a593Smuzhiyun 
dvb_pll_init(struct dvb_frontend * fe)737*4882a593Smuzhiyun static int dvb_pll_init(struct dvb_frontend *fe)
738*4882a593Smuzhiyun {
739*4882a593Smuzhiyun 	struct dvb_pll_priv *priv = fe->tuner_priv;
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun 	if (priv->i2c == NULL)
742*4882a593Smuzhiyun 		return -EINVAL;
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun 	if (priv->pll_desc->initdata) {
745*4882a593Smuzhiyun 		struct i2c_msg msg = { .flags = 0,
746*4882a593Smuzhiyun 			.addr = priv->pll_i2c_address,
747*4882a593Smuzhiyun 			.buf = priv->pll_desc->initdata + 1,
748*4882a593Smuzhiyun 			.len = priv->pll_desc->initdata[0] };
749*4882a593Smuzhiyun 
750*4882a593Smuzhiyun 		int result;
751*4882a593Smuzhiyun 		if (fe->ops.i2c_gate_ctrl)
752*4882a593Smuzhiyun 			fe->ops.i2c_gate_ctrl(fe, 1);
753*4882a593Smuzhiyun 		result = i2c_transfer(priv->i2c, &msg, 1);
754*4882a593Smuzhiyun 		if (result != 1)
755*4882a593Smuzhiyun 			return result;
756*4882a593Smuzhiyun 		if (priv->pll_desc->initdata2) {
757*4882a593Smuzhiyun 			msg.buf = priv->pll_desc->initdata2 + 1;
758*4882a593Smuzhiyun 			msg.len = priv->pll_desc->initdata2[0];
759*4882a593Smuzhiyun 			if (fe->ops.i2c_gate_ctrl)
760*4882a593Smuzhiyun 				fe->ops.i2c_gate_ctrl(fe, 1);
761*4882a593Smuzhiyun 			result = i2c_transfer(priv->i2c, &msg, 1);
762*4882a593Smuzhiyun 			if (result != 1)
763*4882a593Smuzhiyun 				return result;
764*4882a593Smuzhiyun 		}
765*4882a593Smuzhiyun 		return 0;
766*4882a593Smuzhiyun 	}
767*4882a593Smuzhiyun 	/* Shouldn't be called when initdata is NULL, maybe BUG()? */
768*4882a593Smuzhiyun 	return -EINVAL;
769*4882a593Smuzhiyun }
770*4882a593Smuzhiyun 
771*4882a593Smuzhiyun static const struct dvb_tuner_ops dvb_pll_tuner_ops = {
772*4882a593Smuzhiyun 	.release = dvb_pll_release,
773*4882a593Smuzhiyun 	.sleep = dvb_pll_sleep,
774*4882a593Smuzhiyun 	.init = dvb_pll_init,
775*4882a593Smuzhiyun 	.set_params = dvb_pll_set_params,
776*4882a593Smuzhiyun 	.calc_regs = dvb_pll_calc_regs,
777*4882a593Smuzhiyun 	.get_frequency = dvb_pll_get_frequency,
778*4882a593Smuzhiyun 	.get_bandwidth = dvb_pll_get_bandwidth,
779*4882a593Smuzhiyun };
780*4882a593Smuzhiyun 
dvb_pll_attach(struct dvb_frontend * fe,int pll_addr,struct i2c_adapter * i2c,unsigned int pll_desc_id)781*4882a593Smuzhiyun struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
782*4882a593Smuzhiyun 				    struct i2c_adapter *i2c,
783*4882a593Smuzhiyun 				    unsigned int pll_desc_id)
784*4882a593Smuzhiyun {
785*4882a593Smuzhiyun 	u8 *b1;
786*4882a593Smuzhiyun 	struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .len = 1 };
787*4882a593Smuzhiyun 	struct dvb_pll_priv *priv = NULL;
788*4882a593Smuzhiyun 	int ret;
789*4882a593Smuzhiyun 	const struct dvb_pll_desc *desc;
790*4882a593Smuzhiyun 	int nr;
791*4882a593Smuzhiyun 
792*4882a593Smuzhiyun 	b1 = kmalloc(1, GFP_KERNEL);
793*4882a593Smuzhiyun 	if (!b1)
794*4882a593Smuzhiyun 		return NULL;
795*4882a593Smuzhiyun 
796*4882a593Smuzhiyun 	b1[0] = 0;
797*4882a593Smuzhiyun 	msg.buf = b1;
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun 	nr = ida_simple_get(&pll_ida, 0, DVB_PLL_MAX, GFP_KERNEL);
800*4882a593Smuzhiyun 	if (nr < 0) {
801*4882a593Smuzhiyun 		kfree(b1);
802*4882a593Smuzhiyun 		return NULL;
803*4882a593Smuzhiyun 	}
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun 	if (id[nr] > DVB_PLL_UNDEFINED && id[nr] < ARRAY_SIZE(pll_list))
806*4882a593Smuzhiyun 		pll_desc_id = id[nr];
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun 	BUG_ON(pll_desc_id < 1 || pll_desc_id >= ARRAY_SIZE(pll_list));
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun 	desc = pll_list[pll_desc_id];
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun 	if (i2c != NULL) {
813*4882a593Smuzhiyun 		if (fe->ops.i2c_gate_ctrl)
814*4882a593Smuzhiyun 			fe->ops.i2c_gate_ctrl(fe, 1);
815*4882a593Smuzhiyun 
816*4882a593Smuzhiyun 		ret = i2c_transfer (i2c, &msg, 1);
817*4882a593Smuzhiyun 		if (ret != 1)
818*4882a593Smuzhiyun 			goto out;
819*4882a593Smuzhiyun 		if (fe->ops.i2c_gate_ctrl)
820*4882a593Smuzhiyun 			     fe->ops.i2c_gate_ctrl(fe, 0);
821*4882a593Smuzhiyun 	}
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun 	priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
824*4882a593Smuzhiyun 	if (!priv)
825*4882a593Smuzhiyun 		goto out;
826*4882a593Smuzhiyun 
827*4882a593Smuzhiyun 	priv->pll_i2c_address = pll_addr;
828*4882a593Smuzhiyun 	priv->i2c = i2c;
829*4882a593Smuzhiyun 	priv->pll_desc = desc;
830*4882a593Smuzhiyun 	priv->nr = nr;
831*4882a593Smuzhiyun 
832*4882a593Smuzhiyun 	memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops,
833*4882a593Smuzhiyun 	       sizeof(struct dvb_tuner_ops));
834*4882a593Smuzhiyun 
835*4882a593Smuzhiyun 	strscpy(fe->ops.tuner_ops.info.name, desc->name,
836*4882a593Smuzhiyun 		sizeof(fe->ops.tuner_ops.info.name));
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 	fe->ops.tuner_ops.info.frequency_min_hz = desc->min;
839*4882a593Smuzhiyun 	fe->ops.tuner_ops.info.frequency_max_hz = desc->max;
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun 	dprintk("%s tuner, frequency range: %u...%u\n",
842*4882a593Smuzhiyun 		desc->name, desc->min, desc->max);
843*4882a593Smuzhiyun 
844*4882a593Smuzhiyun 	if (!desc->initdata)
845*4882a593Smuzhiyun 		fe->ops.tuner_ops.init = NULL;
846*4882a593Smuzhiyun 	if (!desc->sleepdata)
847*4882a593Smuzhiyun 		fe->ops.tuner_ops.sleep = NULL;
848*4882a593Smuzhiyun 
849*4882a593Smuzhiyun 	fe->tuner_priv = priv;
850*4882a593Smuzhiyun 
851*4882a593Smuzhiyun 	if ((debug) || (id[priv->nr] == pll_desc_id)) {
852*4882a593Smuzhiyun 		dprintk("dvb-pll[%d]", priv->nr);
853*4882a593Smuzhiyun 		if (i2c != NULL)
854*4882a593Smuzhiyun 			pr_cont(" %d-%04x", i2c_adapter_id(i2c), pll_addr);
855*4882a593Smuzhiyun 		pr_cont(": id# %d (%s) attached, %s\n", pll_desc_id, desc->name,
856*4882a593Smuzhiyun 		       id[priv->nr] == pll_desc_id ?
857*4882a593Smuzhiyun 				"insmod option" : "autodetected");
858*4882a593Smuzhiyun 	}
859*4882a593Smuzhiyun 
860*4882a593Smuzhiyun 	kfree(b1);
861*4882a593Smuzhiyun 
862*4882a593Smuzhiyun 	return fe;
863*4882a593Smuzhiyun out:
864*4882a593Smuzhiyun 	kfree(b1);
865*4882a593Smuzhiyun 	ida_simple_remove(&pll_ida, nr);
866*4882a593Smuzhiyun 
867*4882a593Smuzhiyun 	return NULL;
868*4882a593Smuzhiyun }
869*4882a593Smuzhiyun EXPORT_SYMBOL(dvb_pll_attach);
870*4882a593Smuzhiyun 
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun static int
dvb_pll_probe(struct i2c_client * client,const struct i2c_device_id * id)873*4882a593Smuzhiyun dvb_pll_probe(struct i2c_client *client, const struct i2c_device_id *id)
874*4882a593Smuzhiyun {
875*4882a593Smuzhiyun 	struct dvb_pll_config *cfg;
876*4882a593Smuzhiyun 	struct dvb_frontend *fe;
877*4882a593Smuzhiyun 	unsigned int desc_id;
878*4882a593Smuzhiyun 
879*4882a593Smuzhiyun 	cfg = client->dev.platform_data;
880*4882a593Smuzhiyun 	fe = cfg->fe;
881*4882a593Smuzhiyun 	i2c_set_clientdata(client, fe);
882*4882a593Smuzhiyun 	desc_id = (unsigned int) id->driver_data;
883*4882a593Smuzhiyun 
884*4882a593Smuzhiyun 	if (!dvb_pll_attach(fe, client->addr, client->adapter, desc_id))
885*4882a593Smuzhiyun 		return -ENOMEM;
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 	/*
888*4882a593Smuzhiyun 	 * Unset tuner_ops.release (== dvb_pll_release)
889*4882a593Smuzhiyun 	 * which has been just set in the above dvb_pll_attach(),
890*4882a593Smuzhiyun 	 * because if tuner_ops.release was left defined,
891*4882a593Smuzhiyun 	 * this module would be 'put' twice on exit:
892*4882a593Smuzhiyun 	 * once by dvb_frontend_detach() and another by dvb_module_release().
893*4882a593Smuzhiyun 	 *
894*4882a593Smuzhiyun 	 * dvb_pll_release is instead executed in the i2c driver's .remove(),
895*4882a593Smuzhiyun 	 * keeping dvb_pll_attach untouched for legacy (dvb_attach) drivers.
896*4882a593Smuzhiyun 	 */
897*4882a593Smuzhiyun 	fe->ops.tuner_ops.release = NULL;
898*4882a593Smuzhiyun 	dev_info(&client->dev, "DVB Simple Tuner attached.\n");
899*4882a593Smuzhiyun 	return 0;
900*4882a593Smuzhiyun }
901*4882a593Smuzhiyun 
dvb_pll_remove(struct i2c_client * client)902*4882a593Smuzhiyun static int dvb_pll_remove(struct i2c_client *client)
903*4882a593Smuzhiyun {
904*4882a593Smuzhiyun 	struct dvb_frontend *fe = i2c_get_clientdata(client);
905*4882a593Smuzhiyun 	struct dvb_pll_priv *priv = fe->tuner_priv;
906*4882a593Smuzhiyun 
907*4882a593Smuzhiyun 	ida_simple_remove(&pll_ida, priv->nr);
908*4882a593Smuzhiyun 	dvb_pll_release(fe);
909*4882a593Smuzhiyun 	return 0;
910*4882a593Smuzhiyun }
911*4882a593Smuzhiyun 
912*4882a593Smuzhiyun 
913*4882a593Smuzhiyun static const struct i2c_device_id dvb_pll_id[] = {
914*4882a593Smuzhiyun 	{"dtt7579",		DVB_PLL_THOMSON_DTT7579},
915*4882a593Smuzhiyun 	{"dtt759x",		DVB_PLL_THOMSON_DTT759X},
916*4882a593Smuzhiyun 	{"z201",		DVB_PLL_LG_Z201},
917*4882a593Smuzhiyun 	{"unknown_1",		DVB_PLL_UNKNOWN_1},
918*4882a593Smuzhiyun 	{"tua6010xs",		DVB_PLL_TUA6010XS},
919*4882a593Smuzhiyun 	{"env57h1xd5",		DVB_PLL_ENV57H1XD5},
920*4882a593Smuzhiyun 	{"tua6034",		DVB_PLL_TUA6034},
921*4882a593Smuzhiyun 	{"tda665x",		DVB_PLL_TDA665X},
922*4882a593Smuzhiyun 	{"tded4",		DVB_PLL_TDED4},
923*4882a593Smuzhiyun 	{"tdhu2",		DVB_PLL_TDHU2},
924*4882a593Smuzhiyun 	{"tbmv",		DVB_PLL_SAMSUNG_TBMV},
925*4882a593Smuzhiyun 	{"sd1878_tda8261",	DVB_PLL_PHILIPS_SD1878_TDA8261},
926*4882a593Smuzhiyun 	{"opera1",		DVB_PLL_OPERA1},
927*4882a593Smuzhiyun 	{"dtos403ih102a",	DVB_PLL_SAMSUNG_DTOS403IH102A},
928*4882a593Smuzhiyun 	{"tdtc9251dh0",		DVB_PLL_SAMSUNG_TDTC9251DH0},
929*4882a593Smuzhiyun 	{"tbdu18132",		DVB_PLL_SAMSUNG_TBDU18132},
930*4882a593Smuzhiyun 	{"tbmu24112",		DVB_PLL_SAMSUNG_TBMU24112},
931*4882a593Smuzhiyun 	{"tdee4",		DVB_PLL_TDEE4},
932*4882a593Smuzhiyun 	{"dtt7520x",		DVB_PLL_THOMSON_DTT7520X},
933*4882a593Smuzhiyun 	{"tua6034_friio",	DVB_PLL_TUA6034_FRIIO},
934*4882a593Smuzhiyun 	{"tda665x_earthpt1",	DVB_PLL_TDA665X_EARTH_PT1},
935*4882a593Smuzhiyun 	{}
936*4882a593Smuzhiyun };
937*4882a593Smuzhiyun 
938*4882a593Smuzhiyun 
939*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, dvb_pll_id);
940*4882a593Smuzhiyun 
941*4882a593Smuzhiyun static struct i2c_driver dvb_pll_driver = {
942*4882a593Smuzhiyun 	.driver = {
943*4882a593Smuzhiyun 		.name = "dvb_pll",
944*4882a593Smuzhiyun 	},
945*4882a593Smuzhiyun 	.probe    = dvb_pll_probe,
946*4882a593Smuzhiyun 	.remove   = dvb_pll_remove,
947*4882a593Smuzhiyun 	.id_table = dvb_pll_id,
948*4882a593Smuzhiyun };
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun module_i2c_driver(dvb_pll_driver);
951*4882a593Smuzhiyun 
952*4882a593Smuzhiyun MODULE_DESCRIPTION("dvb pll library");
953*4882a593Smuzhiyun MODULE_AUTHOR("Gerd Knorr");
954*4882a593Smuzhiyun MODULE_LICENSE("GPL");
955