Merge tag 'reset-for-v5.3' of git://git.pengutronix.de/git/pza/linux into arm/drivers
[sfrench/cifs-2.6.git] / drivers / media / tuners / mt2131.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
4  *
5  *  Copyright (c) 2006 Steven Toth <stoth@linuxtv.org>
6  */
7
8 #include <linux/module.h>
9 #include <linux/delay.h>
10 #include <linux/dvb/frontend.h>
11 #include <linux/i2c.h>
12 #include <linux/slab.h>
13
14 #include <media/dvb_frontend.h>
15
16 #include "mt2131.h"
17 #include "mt2131_priv.h"
18
19 static int debug;
20 module_param(debug, int, 0644);
21 MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
22
23 #define dprintk(level,fmt, arg...) if (debug >= level) \
24         printk(KERN_INFO "%s: " fmt, "mt2131", ## arg)
25
26 static u8 mt2131_config1[] = {
27         0x01,
28         0x50, 0x00, 0x50, 0x80, 0x00, 0x49, 0xfa, 0x88,
29         0x08, 0x77, 0x41, 0x04, 0x00, 0x00, 0x00, 0x32,
30         0x7f, 0xda, 0x4c, 0x00, 0x10, 0xaa, 0x78, 0x80,
31         0xff, 0x68, 0xa0, 0xff, 0xdd, 0x00, 0x00
32 };
33
34 static u8 mt2131_config2[] = {
35         0x10,
36         0x7f, 0xc8, 0x0a, 0x5f, 0x00, 0x04
37 };
38
39 static int mt2131_readreg(struct mt2131_priv *priv, u8 reg, u8 *val)
40 {
41         struct i2c_msg msg[2] = {
42                 { .addr = priv->cfg->i2c_address, .flags = 0,
43                   .buf = &reg, .len = 1 },
44                 { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD,
45                   .buf = val,  .len = 1 },
46         };
47
48         if (i2c_transfer(priv->i2c, msg, 2) != 2) {
49                 printk(KERN_WARNING "mt2131 I2C read failed\n");
50                 return -EREMOTEIO;
51         }
52         return 0;
53 }
54
55 static int mt2131_writereg(struct mt2131_priv *priv, u8 reg, u8 val)
56 {
57         u8 buf[2] = { reg, val };
58         struct i2c_msg msg = { .addr = priv->cfg->i2c_address, .flags = 0,
59                                .buf = buf, .len = 2 };
60
61         if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
62                 printk(KERN_WARNING "mt2131 I2C write failed\n");
63                 return -EREMOTEIO;
64         }
65         return 0;
66 }
67
68 static int mt2131_writeregs(struct mt2131_priv *priv,u8 *buf, u8 len)
69 {
70         struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
71                                .flags = 0, .buf = buf, .len = len };
72
73         if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
74                 printk(KERN_WARNING "mt2131 I2C write failed (len=%i)\n",
75                        (int)len);
76                 return -EREMOTEIO;
77         }
78         return 0;
79 }
80
81 static int mt2131_set_params(struct dvb_frontend *fe)
82 {
83         struct dtv_frontend_properties *c = &fe->dtv_property_cache;
84         struct mt2131_priv *priv;
85         int ret=0, i;
86         u32 freq;
87         u8  if_band_center;
88         u32 f_lo1, f_lo2;
89         u32 div1, num1, div2, num2;
90         u8  b[8];
91         u8 lockval = 0;
92
93         priv = fe->tuner_priv;
94
95         freq = c->frequency / 1000;  /* Hz -> kHz */
96         dprintk(1, "%s() freq=%d\n", __func__, freq);
97
98         f_lo1 = freq + MT2131_IF1 * 1000;
99         f_lo1 = (f_lo1 / 250) * 250;
100         f_lo2 = f_lo1 - freq - MT2131_IF2;
101
102         priv->frequency =  (f_lo1 - f_lo2 - MT2131_IF2) * 1000;
103
104         /* Frequency LO1 = 16MHz * (DIV1 + NUM1/8192 ) */
105         num1 = f_lo1 * 64 / (MT2131_FREF / 128);
106         div1 = num1 / 8192;
107         num1 &= 0x1fff;
108
109         /* Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 ) */
110         num2 = f_lo2 * 64 / (MT2131_FREF / 128);
111         div2 = num2 / 8192;
112         num2 &= 0x1fff;
113
114         if (freq <=   82500) if_band_center = 0x00; else
115         if (freq <=  137500) if_band_center = 0x01; else
116         if (freq <=  192500) if_band_center = 0x02; else
117         if (freq <=  247500) if_band_center = 0x03; else
118         if (freq <=  302500) if_band_center = 0x04; else
119         if (freq <=  357500) if_band_center = 0x05; else
120         if (freq <=  412500) if_band_center = 0x06; else
121         if (freq <=  467500) if_band_center = 0x07; else
122         if (freq <=  522500) if_band_center = 0x08; else
123         if (freq <=  577500) if_band_center = 0x09; else
124         if (freq <=  632500) if_band_center = 0x0A; else
125         if (freq <=  687500) if_band_center = 0x0B; else
126         if (freq <=  742500) if_band_center = 0x0C; else
127         if (freq <=  797500) if_band_center = 0x0D; else
128         if (freq <=  852500) if_band_center = 0x0E; else
129         if (freq <=  907500) if_band_center = 0x0F; else
130         if (freq <=  962500) if_band_center = 0x10; else
131         if (freq <= 1017500) if_band_center = 0x11; else
132         if (freq <= 1072500) if_band_center = 0x12; else if_band_center = 0x13;
133
134         b[0] = 1;
135         b[1] = (num1 >> 5) & 0xFF;
136         b[2] = (num1 & 0x1F);
137         b[3] = div1;
138         b[4] = (num2 >> 5) & 0xFF;
139         b[5] = num2 & 0x1F;
140         b[6] = div2;
141
142         dprintk(1, "IF1: %dMHz IF2: %dMHz\n", MT2131_IF1, MT2131_IF2);
143         dprintk(1, "PLL freq=%dkHz  band=%d\n", (int)freq, (int)if_band_center);
144         dprintk(1, "PLL f_lo1=%dkHz  f_lo2=%dkHz\n", (int)f_lo1, (int)f_lo2);
145         dprintk(1, "PLL div1=%d  num1=%d  div2=%d  num2=%d\n",
146                 (int)div1, (int)num1, (int)div2, (int)num2);
147         dprintk(1, "PLL [1..6]: %2x %2x %2x %2x %2x %2x\n",
148                 (int)b[1], (int)b[2], (int)b[3], (int)b[4], (int)b[5],
149                 (int)b[6]);
150
151         ret = mt2131_writeregs(priv,b,7);
152         if (ret < 0)
153                 return ret;
154
155         mt2131_writereg(priv, 0x0b, if_band_center);
156
157         /* Wait for lock */
158         i = 0;
159         do {
160                 mt2131_readreg(priv, 0x08, &lockval);
161                 if ((lockval & 0x88) == 0x88)
162                         break;
163                 msleep(4);
164                 i++;
165         } while (i < 10);
166
167         return ret;
168 }
169
170 static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
171 {
172         struct mt2131_priv *priv = fe->tuner_priv;
173         dprintk(1, "%s()\n", __func__);
174         *frequency = priv->frequency;
175         return 0;
176 }
177
178 static int mt2131_get_status(struct dvb_frontend *fe, u32 *status)
179 {
180         struct mt2131_priv *priv = fe->tuner_priv;
181         u8 lock_status = 0;
182         u8 afc_status = 0;
183
184         *status = 0;
185
186         mt2131_readreg(priv, 0x08, &lock_status);
187         if ((lock_status & 0x88) == 0x88)
188                 *status = TUNER_STATUS_LOCKED;
189
190         mt2131_readreg(priv, 0x09, &afc_status);
191         dprintk(1, "%s() - LO Status = 0x%x, AFC Status = 0x%x\n",
192                 __func__, lock_status, afc_status);
193
194         return 0;
195 }
196
197 static int mt2131_init(struct dvb_frontend *fe)
198 {
199         struct mt2131_priv *priv = fe->tuner_priv;
200         int ret;
201         dprintk(1, "%s()\n", __func__);
202
203         if ((ret = mt2131_writeregs(priv, mt2131_config1,
204                                     sizeof(mt2131_config1))) < 0)
205                 return ret;
206
207         mt2131_writereg(priv, 0x0b, 0x09);
208         mt2131_writereg(priv, 0x15, 0x47);
209         mt2131_writereg(priv, 0x07, 0xf2);
210         mt2131_writereg(priv, 0x0b, 0x01);
211
212         if ((ret = mt2131_writeregs(priv, mt2131_config2,
213                                     sizeof(mt2131_config2))) < 0)
214                 return ret;
215
216         return ret;
217 }
218
219 static void mt2131_release(struct dvb_frontend *fe)
220 {
221         dprintk(1, "%s()\n", __func__);
222         kfree(fe->tuner_priv);
223         fe->tuner_priv = NULL;
224 }
225
226 static const struct dvb_tuner_ops mt2131_tuner_ops = {
227         .info = {
228                 .name              = "Microtune MT2131",
229                 .frequency_min_hz  =  48 * MHz,
230                 .frequency_max_hz  = 860 * MHz,
231                 .frequency_step_hz =  50 * kHz,
232         },
233
234         .release       = mt2131_release,
235         .init          = mt2131_init,
236
237         .set_params    = mt2131_set_params,
238         .get_frequency = mt2131_get_frequency,
239         .get_status    = mt2131_get_status
240 };
241
242 struct dvb_frontend * mt2131_attach(struct dvb_frontend *fe,
243                                     struct i2c_adapter *i2c,
244                                     struct mt2131_config *cfg, u16 if1)
245 {
246         struct mt2131_priv *priv = NULL;
247         u8 id = 0;
248
249         dprintk(1, "%s()\n", __func__);
250
251         priv = kzalloc(sizeof(struct mt2131_priv), GFP_KERNEL);
252         if (priv == NULL)
253                 return NULL;
254
255         priv->cfg = cfg;
256         priv->i2c = i2c;
257
258         if (mt2131_readreg(priv, 0, &id) != 0) {
259                 kfree(priv);
260                 return NULL;
261         }
262         if ( (id != 0x3E) && (id != 0x3F) ) {
263                 printk(KERN_ERR "MT2131: Device not found at addr 0x%02x\n",
264                        cfg->i2c_address);
265                 kfree(priv);
266                 return NULL;
267         }
268
269         printk(KERN_INFO "MT2131: successfully identified at address 0x%02x\n",
270                cfg->i2c_address);
271         memcpy(&fe->ops.tuner_ops, &mt2131_tuner_ops,
272                sizeof(struct dvb_tuner_ops));
273
274         fe->tuner_priv = priv;
275         return fe;
276 }
277 EXPORT_SYMBOL(mt2131_attach);
278
279 MODULE_AUTHOR("Steven Toth");
280 MODULE_DESCRIPTION("Microtune MT2131 silicon tuner driver");
281 MODULE_LICENSE("GPL");