PageRenderTime 30ms CodeModel.GetById 21ms app.highlight 7ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/media/dvb/frontends/stb6000.c

https://bitbucket.org/ndreys/linux-sunxi
C | 256 lines | 192 code | 41 blank | 23 comment | 37 complexity | 7a97aed77972f9eedb2419bf4d84c344 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1  /*
  2     Driver for ST STB6000 DVBS Silicon tuner
  3
  4     Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
  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
 23#include <linux/slab.h>
 24#include <linux/module.h>
 25#include <linux/dvb/frontend.h>
 26#include <asm/types.h>
 27
 28#include "stb6000.h"
 29
 30static int debug;
 31#define dprintk(args...) \
 32	do { \
 33		if (debug) \
 34			printk(KERN_DEBUG "stb6000: " args); \
 35	} while (0)
 36
 37struct stb6000_priv {
 38	/* i2c details */
 39	int i2c_address;
 40	struct i2c_adapter *i2c;
 41	u32 frequency;
 42};
 43
 44static int stb6000_release(struct dvb_frontend *fe)
 45{
 46	kfree(fe->tuner_priv);
 47	fe->tuner_priv = NULL;
 48	return 0;
 49}
 50
 51static int stb6000_sleep(struct dvb_frontend *fe)
 52{
 53	struct stb6000_priv *priv = fe->tuner_priv;
 54	int ret;
 55	u8 buf[] = { 10, 0 };
 56	struct i2c_msg msg = {
 57		.addr = priv->i2c_address,
 58		.flags = 0,
 59		.buf = buf,
 60		.len = 2
 61	};
 62
 63	dprintk("%s:\n", __func__);
 64
 65	if (fe->ops.i2c_gate_ctrl)
 66		fe->ops.i2c_gate_ctrl(fe, 1);
 67
 68	ret = i2c_transfer(priv->i2c, &msg, 1);
 69	if (ret != 1)
 70		dprintk("%s: i2c error\n", __func__);
 71
 72	if (fe->ops.i2c_gate_ctrl)
 73		fe->ops.i2c_gate_ctrl(fe, 0);
 74
 75	return (ret == 1) ? 0 : ret;
 76}
 77
 78static int stb6000_set_params(struct dvb_frontend *fe,
 79				struct dvb_frontend_parameters *params)
 80{
 81	struct stb6000_priv *priv = fe->tuner_priv;
 82	unsigned int n, m;
 83	int ret;
 84	u32 freq_mhz;
 85	int bandwidth;
 86	u8 buf[12];
 87	struct i2c_msg msg = {
 88		.addr = priv->i2c_address,
 89		.flags = 0,
 90		.buf = buf,
 91		.len = 12
 92	};
 93
 94	dprintk("%s:\n", __func__);
 95
 96	freq_mhz = params->frequency / 1000;
 97	bandwidth = params->u.qpsk.symbol_rate / 1000000;
 98
 99	if (bandwidth > 31)
100		bandwidth = 31;
101
102	if ((freq_mhz > 949) && (freq_mhz < 2151)) {
103		buf[0] = 0x01;
104		buf[1] = 0xac;
105		if (freq_mhz < 1950)
106			buf[1] = 0xaa;
107		if (freq_mhz < 1800)
108			buf[1] = 0xa8;
109		if (freq_mhz < 1650)
110			buf[1] = 0xa6;
111		if (freq_mhz < 1530)
112			buf[1] = 0xa5;
113		if (freq_mhz < 1470)
114			buf[1] = 0xa4;
115		if (freq_mhz < 1370)
116			buf[1] = 0xa2;
117		if (freq_mhz < 1300)
118			buf[1] = 0xa1;
119		if (freq_mhz < 1200)
120			buf[1] = 0xa0;
121		if (freq_mhz < 1075)
122			buf[1] = 0xbc;
123		if (freq_mhz < 1000)
124			buf[1] = 0xba;
125		if (freq_mhz < 1075) {
126			n = freq_mhz / 8; /* vco=lo*4 */
127			m = 2;
128		} else {
129			n = freq_mhz / 16; /* vco=lo*2 */
130			m = 1;
131		}
132		buf[2] = n >> 1;
133		buf[3] = (unsigned char)(((n & 1) << 7) |
134					(m * freq_mhz - n * 16) | 0x60);
135		buf[4] = 0x04;
136		buf[5] = 0x0e;
137
138		buf[6] = (unsigned char)(bandwidth);
139
140		buf[7] = 0xd8;
141		buf[8] = 0xd0;
142		buf[9] = 0x50;
143		buf[10] = 0xeb;
144		buf[11] = 0x4f;
145
146		if (fe->ops.i2c_gate_ctrl)
147			fe->ops.i2c_gate_ctrl(fe, 1);
148
149		ret = i2c_transfer(priv->i2c, &msg, 1);
150		if (ret != 1)
151			dprintk("%s: i2c error\n", __func__);
152
153		udelay(10);
154		if (fe->ops.i2c_gate_ctrl)
155			fe->ops.i2c_gate_ctrl(fe, 0);
156
157		buf[0] = 0x07;
158		buf[1] = 0xdf;
159		buf[2] = 0xd0;
160		buf[3] = 0x50;
161		buf[4] = 0xfb;
162		msg.len = 5;
163
164		if (fe->ops.i2c_gate_ctrl)
165			fe->ops.i2c_gate_ctrl(fe, 1);
166
167		ret = i2c_transfer(priv->i2c, &msg, 1);
168		if (ret != 1)
169			dprintk("%s: i2c error\n", __func__);
170
171		udelay(10);
172		if (fe->ops.i2c_gate_ctrl)
173			fe->ops.i2c_gate_ctrl(fe, 0);
174
175		priv->frequency = freq_mhz * 1000;
176
177		return (ret == 1) ? 0 : ret;
178	}
179	return -1;
180}
181
182static int stb6000_get_frequency(struct dvb_frontend *fe, u32 *frequency)
183{
184	struct stb6000_priv *priv = fe->tuner_priv;
185	*frequency = priv->frequency;
186	return 0;
187}
188
189static struct dvb_tuner_ops stb6000_tuner_ops = {
190	.info = {
191		.name = "ST STB6000",
192		.frequency_min = 950000,
193		.frequency_max = 2150000
194	},
195	.release = stb6000_release,
196	.sleep = stb6000_sleep,
197	.set_params = stb6000_set_params,
198	.get_frequency = stb6000_get_frequency,
199};
200
201struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr,
202						struct i2c_adapter *i2c)
203{
204	struct stb6000_priv *priv = NULL;
205	u8 b0[] = { 0 };
206	u8 b1[] = { 0, 0 };
207	struct i2c_msg msg[2] = {
208		{
209			.addr = addr,
210			.flags = 0,
211			.buf = b0,
212			.len = 0
213		}, {
214			.addr = addr,
215			.flags = I2C_M_RD,
216			.buf = b1,
217			.len = 2
218		}
219	};
220	int ret;
221
222	dprintk("%s:\n", __func__);
223
224	if (fe->ops.i2c_gate_ctrl)
225		fe->ops.i2c_gate_ctrl(fe, 1);
226
227	/* is some i2c device here ? */
228	ret = i2c_transfer(i2c, msg, 2);
229	if (fe->ops.i2c_gate_ctrl)
230		fe->ops.i2c_gate_ctrl(fe, 0);
231
232	if (ret != 2)
233		return NULL;
234
235	priv = kzalloc(sizeof(struct stb6000_priv), GFP_KERNEL);
236	if (priv == NULL)
237		return NULL;
238
239	priv->i2c_address = addr;
240	priv->i2c = i2c;
241
242	memcpy(&fe->ops.tuner_ops, &stb6000_tuner_ops,
243				sizeof(struct dvb_tuner_ops));
244
245	fe->tuner_priv = priv;
246
247	return fe;
248}
249EXPORT_SYMBOL(stb6000_attach);
250
251module_param(debug, int, 0644);
252MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
253
254MODULE_DESCRIPTION("DVB STB6000 driver");
255MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>");
256MODULE_LICENSE("GPL");