xref: /openbmc/linux/drivers/media/dvb-frontends/stv6110.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1  // SPDX-License-Identifier: GPL-2.0-or-later
2  /*
3   * stv6110.c
4   *
5   * Driver for ST STV6110 satellite tuner IC.
6   *
7   * Copyright (C) 2009 NetUP Inc.
8   * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
9   */
10  
11  #include <linux/slab.h>
12  #include <linux/module.h>
13  #include <linux/dvb/frontend.h>
14  
15  #include <linux/types.h>
16  
17  #include "stv6110.h"
18  
19  /* Max transfer size done by I2C transfer functions */
20  #define MAX_XFER_SIZE  64
21  
22  static int debug;
23  
24  struct stv6110_priv {
25  	int i2c_address;
26  	struct i2c_adapter *i2c;
27  
28  	u32 mclk;
29  	u8 clk_div;
30  	u8 gain;
31  	u8 regs[8];
32  };
33  
34  #define dprintk(args...) \
35  	do { \
36  		if (debug) \
37  			printk(KERN_DEBUG args); \
38  	} while (0)
39  
abssub(s32 a,s32 b)40  static s32 abssub(s32 a, s32 b)
41  {
42  	if (a > b)
43  		return a - b;
44  	else
45  		return b - a;
46  };
47  
stv6110_release(struct dvb_frontend * fe)48  static void stv6110_release(struct dvb_frontend *fe)
49  {
50  	kfree(fe->tuner_priv);
51  	fe->tuner_priv = NULL;
52  }
53  
stv6110_write_regs(struct dvb_frontend * fe,u8 buf[],int start,int len)54  static int stv6110_write_regs(struct dvb_frontend *fe, u8 buf[],
55  							int start, int len)
56  {
57  	struct stv6110_priv *priv = fe->tuner_priv;
58  	int rc;
59  	u8 cmdbuf[MAX_XFER_SIZE];
60  	struct i2c_msg msg = {
61  		.addr	= priv->i2c_address,
62  		.flags	= 0,
63  		.buf	= cmdbuf,
64  		.len	= len + 1
65  	};
66  
67  	dprintk("%s\n", __func__);
68  
69  	if (1 + len > sizeof(cmdbuf)) {
70  		printk(KERN_WARNING
71  		       "%s: i2c wr: len=%d is too big!\n",
72  		       KBUILD_MODNAME, len);
73  		return -EINVAL;
74  	}
75  
76  	if (start + len > 8)
77  		return -EINVAL;
78  
79  	memcpy(&cmdbuf[1], buf, len);
80  	cmdbuf[0] = start;
81  
82  	if (fe->ops.i2c_gate_ctrl)
83  		fe->ops.i2c_gate_ctrl(fe, 1);
84  
85  	rc = i2c_transfer(priv->i2c, &msg, 1);
86  	if (rc != 1)
87  		dprintk("%s: i2c error\n", __func__);
88  
89  	if (fe->ops.i2c_gate_ctrl)
90  		fe->ops.i2c_gate_ctrl(fe, 0);
91  
92  	return 0;
93  }
94  
stv6110_read_regs(struct dvb_frontend * fe,u8 regs[],int start,int len)95  static int stv6110_read_regs(struct dvb_frontend *fe, u8 regs[],
96  							int start, int len)
97  {
98  	struct stv6110_priv *priv = fe->tuner_priv;
99  	int rc;
100  	u8 reg[] = { start };
101  	struct i2c_msg msg[] = {
102  		{
103  			.addr	= priv->i2c_address,
104  			.flags	= 0,
105  			.buf	= reg,
106  			.len	= 1,
107  		}, {
108  			.addr	= priv->i2c_address,
109  			.flags	= I2C_M_RD,
110  			.buf	= regs,
111  			.len	= len,
112  		},
113  	};
114  
115  	if (fe->ops.i2c_gate_ctrl)
116  		fe->ops.i2c_gate_ctrl(fe, 1);
117  
118  	rc = i2c_transfer(priv->i2c, msg, 2);
119  	if (rc != 2)
120  		dprintk("%s: i2c error\n", __func__);
121  
122  	if (fe->ops.i2c_gate_ctrl)
123  		fe->ops.i2c_gate_ctrl(fe, 0);
124  
125  	memcpy(&priv->regs[start], regs, len);
126  
127  	return 0;
128  }
129  
stv6110_read_reg(struct dvb_frontend * fe,int start)130  static int stv6110_read_reg(struct dvb_frontend *fe, int start)
131  {
132  	u8 buf[] = { 0 };
133  	stv6110_read_regs(fe, buf, start, 1);
134  
135  	return buf[0];
136  }
137  
stv6110_sleep(struct dvb_frontend * fe)138  static int stv6110_sleep(struct dvb_frontend *fe)
139  {
140  	u8 reg[] = { 0 };
141  	stv6110_write_regs(fe, reg, 0, 1);
142  
143  	return 0;
144  }
145  
carrier_width(u32 symbol_rate,enum fe_rolloff rolloff)146  static u32 carrier_width(u32 symbol_rate, enum fe_rolloff rolloff)
147  {
148  	u32 rlf;
149  
150  	switch (rolloff) {
151  	case ROLLOFF_20:
152  		rlf = 20;
153  		break;
154  	case ROLLOFF_25:
155  		rlf = 25;
156  		break;
157  	default:
158  		rlf = 35;
159  		break;
160  	}
161  
162  	return symbol_rate  + ((symbol_rate * rlf) / 100);
163  }
164  
stv6110_set_bandwidth(struct dvb_frontend * fe,u32 bandwidth)165  static int stv6110_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
166  {
167  	struct stv6110_priv *priv = fe->tuner_priv;
168  	u8 r8, ret = 0x04;
169  	int i;
170  
171  	if ((bandwidth / 2) > 36000000) /*BW/2 max=31+5=36 mhz for r8=31*/
172  		r8 = 31;
173  	else if ((bandwidth / 2) < 5000000) /* BW/2 min=5Mhz for F=0 */
174  		r8 = 0;
175  	else /*if 5 < BW/2 < 36*/
176  		r8 = (bandwidth / 2) / 1000000 - 5;
177  
178  	/* ctrl3, RCCLKOFF = 0 Activate the calibration Clock */
179  	/* ctrl3, CF = r8 Set the LPF value */
180  	priv->regs[RSTV6110_CTRL3] &= ~((1 << 6) | 0x1f);
181  	priv->regs[RSTV6110_CTRL3] |= (r8 & 0x1f);
182  	stv6110_write_regs(fe, &priv->regs[RSTV6110_CTRL3], RSTV6110_CTRL3, 1);
183  	/* stat1, CALRCSTRT = 1 Start LPF auto calibration*/
184  	priv->regs[RSTV6110_STAT1] |= 0x02;
185  	stv6110_write_regs(fe, &priv->regs[RSTV6110_STAT1], RSTV6110_STAT1, 1);
186  
187  	i = 0;
188  	/* Wait for CALRCSTRT == 0 */
189  	while ((i < 10) && (ret != 0)) {
190  		ret = ((stv6110_read_reg(fe, RSTV6110_STAT1)) & 0x02);
191  		mdelay(1);	/* wait for LPF auto calibration */
192  		i++;
193  	}
194  
195  	/* RCCLKOFF = 1 calibration done, deactivate the calibration Clock */
196  	priv->regs[RSTV6110_CTRL3] |= (1 << 6);
197  	stv6110_write_regs(fe, &priv->regs[RSTV6110_CTRL3], RSTV6110_CTRL3, 1);
198  	return 0;
199  }
200  
stv6110_init(struct dvb_frontend * fe)201  static int stv6110_init(struct dvb_frontend *fe)
202  {
203  	struct stv6110_priv *priv = fe->tuner_priv;
204  	u8 buf0[] = { 0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e };
205  
206  	memcpy(priv->regs, buf0, 8);
207  	/* K = (Reference / 1000000) - 16 */
208  	priv->regs[RSTV6110_CTRL1] &= ~(0x1f << 3);
209  	priv->regs[RSTV6110_CTRL1] |=
210  				((((priv->mclk / 1000000) - 16) & 0x1f) << 3);
211  
212  	/* divisor value for the output clock */
213  	priv->regs[RSTV6110_CTRL2] &= ~0xc0;
214  	priv->regs[RSTV6110_CTRL2] |= (priv->clk_div << 6);
215  
216  	stv6110_write_regs(fe, &priv->regs[RSTV6110_CTRL1], RSTV6110_CTRL1, 8);
217  	msleep(1);
218  	stv6110_set_bandwidth(fe, 72000000);
219  
220  	return 0;
221  }
222  
stv6110_get_frequency(struct dvb_frontend * fe,u32 * frequency)223  static int stv6110_get_frequency(struct dvb_frontend *fe, u32 *frequency)
224  {
225  	struct stv6110_priv *priv = fe->tuner_priv;
226  	u32 nbsteps, divider, psd2, freq;
227  	u8 regs[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
228  
229  	stv6110_read_regs(fe, regs, 0, 8);
230  	/*N*/
231  	divider = (priv->regs[RSTV6110_TUNING2] & 0x0f) << 8;
232  	divider += priv->regs[RSTV6110_TUNING1];
233  
234  	/*R*/
235  	nbsteps  = (priv->regs[RSTV6110_TUNING2] >> 6) & 3;
236  	/*p*/
237  	psd2  = (priv->regs[RSTV6110_TUNING2] >> 4) & 1;
238  
239  	freq = divider * (priv->mclk / 1000);
240  	freq /= (1 << (nbsteps + psd2));
241  	freq /= 4;
242  
243  	*frequency = freq;
244  
245  	return 0;
246  }
247  
stv6110_set_frequency(struct dvb_frontend * fe,u32 frequency)248  static int stv6110_set_frequency(struct dvb_frontend *fe, u32 frequency)
249  {
250  	struct stv6110_priv *priv = fe->tuner_priv;
251  	u8 ret = 0x04;
252  	u32 divider, ref, p, presc, i, result_freq, vco_freq;
253  	s32 p_calc, p_calc_opt = 1000, r_div, r_div_opt = 0, p_val;
254  
255  	dprintk("%s, freq=%d kHz, mclk=%d Hz\n", __func__,
256  						frequency, priv->mclk);
257  
258  	/* K = (Reference / 1000000) - 16 */
259  	priv->regs[RSTV6110_CTRL1] &= ~(0x1f << 3);
260  	priv->regs[RSTV6110_CTRL1] |=
261  				((((priv->mclk / 1000000) - 16) & 0x1f) << 3);
262  
263  	/* BB_GAIN = db/2 */
264  	priv->regs[RSTV6110_CTRL2] &= ~0x0f;
265  	priv->regs[RSTV6110_CTRL2] |= (priv->gain & 0x0f);
266  
267  	if (frequency <= 1023000) {
268  		p = 1;
269  		presc = 0;
270  	} else if (frequency <= 1300000) {
271  		p = 1;
272  		presc = 1;
273  	} else if (frequency <= 2046000) {
274  		p = 0;
275  		presc = 0;
276  	} else {
277  		p = 0;
278  		presc = 1;
279  	}
280  	/* DIV4SEL = p*/
281  	priv->regs[RSTV6110_TUNING2] &= ~(1 << 4);
282  	priv->regs[RSTV6110_TUNING2] |= (p << 4);
283  
284  	/* PRESC32ON = presc */
285  	priv->regs[RSTV6110_TUNING2] &= ~(1 << 5);
286  	priv->regs[RSTV6110_TUNING2] |= (presc << 5);
287  
288  	p_val = (int)(1 << (p + 1)) * 10;/* P = 2 or P = 4 */
289  	for (r_div = 0; r_div <= 3; r_div++) {
290  		p_calc = (priv->mclk / 100000);
291  		p_calc /= (1 << (r_div + 1));
292  		if ((abssub(p_calc, p_val)) < (abssub(p_calc_opt, p_val)))
293  			r_div_opt = r_div;
294  
295  		p_calc_opt = (priv->mclk / 100000);
296  		p_calc_opt /= (1 << (r_div_opt + 1));
297  	}
298  
299  	ref = priv->mclk / ((1 << (r_div_opt + 1))  * (1 << (p + 1)));
300  	divider = (((frequency * 1000) + (ref >> 1)) / ref);
301  
302  	/* RDIV = r_div_opt */
303  	priv->regs[RSTV6110_TUNING2] &= ~(3 << 6);
304  	priv->regs[RSTV6110_TUNING2] |= (((r_div_opt) & 3) << 6);
305  
306  	/* NDIV_MSB = MSB(divider) */
307  	priv->regs[RSTV6110_TUNING2] &= ~0x0f;
308  	priv->regs[RSTV6110_TUNING2] |= (((divider) >> 8) & 0x0f);
309  
310  	/* NDIV_LSB, LSB(divider) */
311  	priv->regs[RSTV6110_TUNING1] = (divider & 0xff);
312  
313  	/* CALVCOSTRT = 1 VCO Auto Calibration */
314  	priv->regs[RSTV6110_STAT1] |= 0x04;
315  	stv6110_write_regs(fe, &priv->regs[RSTV6110_CTRL1],
316  						RSTV6110_CTRL1, 8);
317  
318  	i = 0;
319  	/* Wait for CALVCOSTRT == 0 */
320  	while ((i < 10) && (ret != 0)) {
321  		ret = ((stv6110_read_reg(fe, RSTV6110_STAT1)) & 0x04);
322  		msleep(1); /* wait for VCO auto calibration */
323  		i++;
324  	}
325  
326  	ret = stv6110_read_reg(fe, RSTV6110_STAT1);
327  	stv6110_get_frequency(fe, &result_freq);
328  
329  	vco_freq = divider * ((priv->mclk / 1000) / ((1 << (r_div_opt + 1))));
330  	dprintk("%s, stat1=%x, lo_freq=%d kHz, vco_frec=%d kHz\n", __func__,
331  						ret, result_freq, vco_freq);
332  
333  	return 0;
334  }
335  
stv6110_set_params(struct dvb_frontend * fe)336  static int stv6110_set_params(struct dvb_frontend *fe)
337  {
338  	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
339  	u32 bandwidth = carrier_width(c->symbol_rate, c->rolloff);
340  
341  	stv6110_set_frequency(fe, c->frequency);
342  	stv6110_set_bandwidth(fe, bandwidth);
343  
344  	return 0;
345  }
346  
stv6110_get_bandwidth(struct dvb_frontend * fe,u32 * bandwidth)347  static int stv6110_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
348  {
349  	struct stv6110_priv *priv = fe->tuner_priv;
350  	u8 r8 = 0;
351  	u8 regs[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
352  	stv6110_read_regs(fe, regs, 0, 8);
353  
354  	/* CF */
355  	r8 = priv->regs[RSTV6110_CTRL3] & 0x1f;
356  	*bandwidth = (r8 + 5) * 2000000;/* x2 for ZIF tuner BW/2 = F+5 Mhz */
357  
358  	return 0;
359  }
360  
361  static const struct dvb_tuner_ops stv6110_tuner_ops = {
362  	.info = {
363  		.name = "ST STV6110",
364  		.frequency_min_hz  =  950 * MHz,
365  		.frequency_max_hz  = 2150 * MHz,
366  		.frequency_step_hz =    1 * MHz,
367  	},
368  	.init = stv6110_init,
369  	.release = stv6110_release,
370  	.sleep = stv6110_sleep,
371  	.set_params = stv6110_set_params,
372  	.get_frequency = stv6110_get_frequency,
373  	.set_frequency = stv6110_set_frequency,
374  	.get_bandwidth = stv6110_get_bandwidth,
375  	.set_bandwidth = stv6110_set_bandwidth,
376  
377  };
378  
stv6110_attach(struct dvb_frontend * fe,const struct stv6110_config * config,struct i2c_adapter * i2c)379  struct dvb_frontend *stv6110_attach(struct dvb_frontend *fe,
380  					const struct stv6110_config *config,
381  					struct i2c_adapter *i2c)
382  {
383  	struct stv6110_priv *priv = NULL;
384  	u8 reg0[] = { 0x00, 0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e };
385  
386  	struct i2c_msg msg[] = {
387  		{
388  			.addr = config->i2c_address,
389  			.flags = 0,
390  			.buf = reg0,
391  			.len = 9
392  		}
393  	};
394  	int ret;
395  
396  	/* divisor value for the output clock */
397  	reg0[2] &= ~0xc0;
398  	reg0[2] |= (config->clk_div << 6);
399  
400  	if (fe->ops.i2c_gate_ctrl)
401  		fe->ops.i2c_gate_ctrl(fe, 1);
402  
403  	ret = i2c_transfer(i2c, msg, 1);
404  
405  	if (fe->ops.i2c_gate_ctrl)
406  		fe->ops.i2c_gate_ctrl(fe, 0);
407  
408  	if (ret != 1)
409  		return NULL;
410  
411  	priv = kzalloc(sizeof(struct stv6110_priv), GFP_KERNEL);
412  	if (priv == NULL)
413  		return NULL;
414  
415  	priv->i2c_address = config->i2c_address;
416  	priv->i2c = i2c;
417  	priv->mclk = config->mclk;
418  	priv->clk_div = config->clk_div;
419  	priv->gain = config->gain;
420  
421  	memcpy(&priv->regs, &reg0[1], 8);
422  
423  	memcpy(&fe->ops.tuner_ops, &stv6110_tuner_ops,
424  				sizeof(struct dvb_tuner_ops));
425  	fe->tuner_priv = priv;
426  	printk(KERN_INFO "STV6110 attached on addr=%x!\n", priv->i2c_address);
427  
428  	return fe;
429  }
430  EXPORT_SYMBOL_GPL(stv6110_attach);
431  
432  module_param(debug, int, 0644);
433  MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
434  
435  MODULE_DESCRIPTION("ST STV6110 driver");
436  MODULE_AUTHOR("Igor M. Liplianin");
437  MODULE_LICENSE("GPL");
438