ec100.c revision 9a0bf528b4d66b605f02634236da085595c22101
1/*
2 * E3C EC100 demodulator driver
3 *
4 * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
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
22#include "dvb_frontend.h"
23#include "ec100_priv.h"
24#include "ec100.h"
25
26int ec100_debug;
27module_param_named(debug, ec100_debug, int, 0644);
28MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
29
30struct ec100_state {
31	struct i2c_adapter *i2c;
32	struct dvb_frontend frontend;
33	struct ec100_config config;
34
35	u16 ber;
36};
37
38/* write single register */
39static int ec100_write_reg(struct ec100_state *state, u8 reg, u8 val)
40{
41	u8 buf[2] = {reg, val};
42	struct i2c_msg msg = {
43		.addr = state->config.demod_address,
44		.flags = 0,
45		.len = 2,
46		.buf = buf};
47
48	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
49		warn("I2C write failed reg:%02x", reg);
50		return -EREMOTEIO;
51	}
52	return 0;
53}
54
55/* read single register */
56static int ec100_read_reg(struct ec100_state *state, u8 reg, u8 *val)
57{
58	struct i2c_msg msg[2] = {
59		{
60			.addr = state->config.demod_address,
61			.flags = 0,
62			.len = 1,
63			.buf = &reg
64		}, {
65			.addr = state->config.demod_address,
66			.flags = I2C_M_RD,
67			.len = 1,
68			.buf = val
69		}
70	};
71
72	if (i2c_transfer(state->i2c, msg, 2) != 2) {
73		warn("I2C read failed reg:%02x", reg);
74		return -EREMOTEIO;
75	}
76	return 0;
77}
78
79static int ec100_set_frontend(struct dvb_frontend *fe)
80{
81	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
82	struct ec100_state *state = fe->demodulator_priv;
83	int ret;
84	u8 tmp, tmp2;
85
86	deb_info("%s: freq:%d bw:%d\n", __func__, c->frequency,
87		c->bandwidth_hz);
88
89	/* program tuner */
90	if (fe->ops.tuner_ops.set_params)
91		fe->ops.tuner_ops.set_params(fe);
92
93	ret = ec100_write_reg(state, 0x04, 0x06);
94	if (ret)
95		goto error;
96	ret = ec100_write_reg(state, 0x67, 0x58);
97	if (ret)
98		goto error;
99	ret = ec100_write_reg(state, 0x05, 0x18);
100	if (ret)
101		goto error;
102
103	/* reg/bw |   6  |   7  |   8
104	   -------+------+------+------
105	   A 0x1b | 0xa1 | 0xe7 | 0x2c
106	   A 0x1c | 0x55 | 0x63 | 0x72
107	   -------+------+------+------
108	   B 0x1b | 0xb7 | 0x00 | 0x49
109	   B 0x1c | 0x55 | 0x64 | 0x72 */
110
111	switch (c->bandwidth_hz) {
112	case 6000000:
113		tmp = 0xb7;
114		tmp2 = 0x55;
115		break;
116	case 7000000:
117		tmp = 0x00;
118		tmp2 = 0x64;
119		break;
120	case 8000000:
121	default:
122		tmp = 0x49;
123		tmp2 = 0x72;
124	}
125
126	ret = ec100_write_reg(state, 0x1b, tmp);
127	if (ret)
128		goto error;
129	ret = ec100_write_reg(state, 0x1c, tmp2);
130	if (ret)
131		goto error;
132
133	ret = ec100_write_reg(state, 0x0c, 0xbb); /* if freq */
134	if (ret)
135		goto error;
136	ret = ec100_write_reg(state, 0x0d, 0x31); /* if freq */
137	if (ret)
138		goto error;
139
140	ret = ec100_write_reg(state, 0x08, 0x24);
141	if (ret)
142		goto error;
143
144	ret = ec100_write_reg(state, 0x00, 0x00); /* go */
145	if (ret)
146		goto error;
147	ret = ec100_write_reg(state, 0x00, 0x20); /* go */
148	if (ret)
149		goto error;
150
151	return ret;
152error:
153	deb_info("%s: failed:%d\n", __func__, ret);
154	return ret;
155}
156
157static int ec100_get_tune_settings(struct dvb_frontend *fe,
158	struct dvb_frontend_tune_settings *fesettings)
159{
160	fesettings->min_delay_ms = 300;
161	fesettings->step_size = 0;
162	fesettings->max_drift = 0;
163
164	return 0;
165}
166
167static int ec100_read_status(struct dvb_frontend *fe, fe_status_t *status)
168{
169	struct ec100_state *state = fe->demodulator_priv;
170	int ret;
171	u8 tmp;
172	*status = 0;
173
174	ret = ec100_read_reg(state, 0x42, &tmp);
175	if (ret)
176		goto error;
177
178	if (tmp & 0x80) {
179		/* bit7 set - have lock */
180		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
181			FE_HAS_SYNC | FE_HAS_LOCK;
182	} else {
183		ret = ec100_read_reg(state, 0x01, &tmp);
184		if (ret)
185			goto error;
186
187		if (tmp & 0x10) {
188			/* bit4 set - have signal */
189			*status |= FE_HAS_SIGNAL;
190			if (!(tmp & 0x01)) {
191				/* bit0 clear - have ~valid signal */
192				*status |= FE_HAS_CARRIER |  FE_HAS_VITERBI;
193			}
194		}
195	}
196
197	return ret;
198error:
199	deb_info("%s: failed:%d\n", __func__, ret);
200	return ret;
201}
202
203static int ec100_read_ber(struct dvb_frontend *fe, u32 *ber)
204{
205	struct ec100_state *state = fe->demodulator_priv;
206	int ret;
207	u8 tmp, tmp2;
208	u16 ber2;
209
210	*ber = 0;
211
212	ret = ec100_read_reg(state, 0x65, &tmp);
213	if (ret)
214		goto error;
215	ret = ec100_read_reg(state, 0x66, &tmp2);
216	if (ret)
217		goto error;
218
219	ber2 = (tmp2 << 8) | tmp;
220
221	/* if counter overflow or clear */
222	if (ber2 < state->ber)
223		*ber = ber2;
224	else
225		*ber = ber2 - state->ber;
226
227	state->ber = ber2;
228
229	return ret;
230error:
231	deb_info("%s: failed:%d\n", __func__, ret);
232	return ret;
233}
234
235static int ec100_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
236{
237	struct ec100_state *state = fe->demodulator_priv;
238	int ret;
239	u8 tmp;
240
241	ret = ec100_read_reg(state, 0x24, &tmp);
242	if (ret) {
243		*strength = 0;
244		goto error;
245	}
246
247	*strength = ((tmp << 8) | tmp);
248
249	return ret;
250error:
251	deb_info("%s: failed:%d\n", __func__, ret);
252	return ret;
253}
254
255static int ec100_read_snr(struct dvb_frontend *fe, u16 *snr)
256{
257	*snr = 0;
258	return 0;
259}
260
261static int ec100_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
262{
263	*ucblocks = 0;
264	return 0;
265}
266
267static void ec100_release(struct dvb_frontend *fe)
268{
269	struct ec100_state *state = fe->demodulator_priv;
270	kfree(state);
271}
272
273static struct dvb_frontend_ops ec100_ops;
274
275struct dvb_frontend *ec100_attach(const struct ec100_config *config,
276	struct i2c_adapter *i2c)
277{
278	int ret;
279	struct ec100_state *state = NULL;
280	u8 tmp;
281
282	/* allocate memory for the internal state */
283	state = kzalloc(sizeof(struct ec100_state), GFP_KERNEL);
284	if (state == NULL)
285		goto error;
286
287	/* setup the state */
288	state->i2c = i2c;
289	memcpy(&state->config, config, sizeof(struct ec100_config));
290
291	/* check if the demod is there */
292	ret = ec100_read_reg(state, 0x33, &tmp);
293	if (ret || tmp != 0x0b)
294		goto error;
295
296	/* create dvb_frontend */
297	memcpy(&state->frontend.ops, &ec100_ops,
298		sizeof(struct dvb_frontend_ops));
299	state->frontend.demodulator_priv = state;
300
301	return &state->frontend;
302error:
303	kfree(state);
304	return NULL;
305}
306EXPORT_SYMBOL(ec100_attach);
307
308static struct dvb_frontend_ops ec100_ops = {
309	.delsys = { SYS_DVBT },
310	.info = {
311		.name = "E3C EC100 DVB-T",
312		.caps =
313			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
314			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
315			FE_CAN_QPSK | FE_CAN_QAM_16 |
316			FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
317			FE_CAN_TRANSMISSION_MODE_AUTO |
318			FE_CAN_GUARD_INTERVAL_AUTO |
319			FE_CAN_HIERARCHY_AUTO |
320			FE_CAN_MUTE_TS
321	},
322
323	.release = ec100_release,
324	.set_frontend = ec100_set_frontend,
325	.get_tune_settings = ec100_get_tune_settings,
326	.read_status = ec100_read_status,
327	.read_ber = ec100_read_ber,
328	.read_signal_strength = ec100_read_signal_strength,
329	.read_snr = ec100_read_snr,
330	.read_ucblocks = ec100_read_ucblocks,
331};
332
333MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
334MODULE_DESCRIPTION("E3C EC100 DVB-T demodulator driver");
335MODULE_LICENSE("GPL");
336