Full support for Ginger Console
[linux-ginger.git] / drivers / media / dvb / pt1 / va1j5jf8007t.c
blob71117f4ca7e6dac447f3c29215244ae2070554fb
1 /*
2 * ISDB-T driver for VA1J5JF8007
4 * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
6 * based on pt1dvr - http://pt1dvr.sourceforge.jp/
7 * by Tomoaki Ishikawa <tomy@users.sourceforge.jp>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/slab.h>
27 #include <linux/i2c.h>
28 #include "dvb_frontend.h"
29 #include "dvb_math.h"
30 #include "va1j5jf8007t.h"
32 enum va1j5jf8007t_tune_state {
33 VA1J5JF8007T_IDLE,
34 VA1J5JF8007T_SET_FREQUENCY,
35 VA1J5JF8007T_CHECK_FREQUENCY,
36 VA1J5JF8007T_SET_MODULATION,
37 VA1J5JF8007T_CHECK_MODULATION,
38 VA1J5JF8007T_TRACK,
39 VA1J5JF8007T_ABORT,
42 struct va1j5jf8007t_state {
43 const struct va1j5jf8007t_config *config;
44 struct i2c_adapter *adap;
45 struct dvb_frontend fe;
46 enum va1j5jf8007t_tune_state tune_state;
49 static int va1j5jf8007t_get_frontend_algo(struct dvb_frontend *fe)
51 return DVBFE_ALGO_HW;
54 static int
55 va1j5jf8007t_read_status(struct dvb_frontend *fe, fe_status_t *status)
57 struct va1j5jf8007t_state *state;
59 state = fe->demodulator_priv;
61 switch (state->tune_state) {
62 case VA1J5JF8007T_IDLE:
63 case VA1J5JF8007T_SET_FREQUENCY:
64 case VA1J5JF8007T_CHECK_FREQUENCY:
65 *status = 0;
66 return 0;
69 case VA1J5JF8007T_SET_MODULATION:
70 case VA1J5JF8007T_CHECK_MODULATION:
71 case VA1J5JF8007T_ABORT:
72 *status |= FE_HAS_SIGNAL;
73 return 0;
75 case VA1J5JF8007T_TRACK:
76 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
77 return 0;
80 BUG();
83 struct va1j5jf8007t_cb_map {
84 u32 frequency;
85 u8 cb;
88 static const struct va1j5jf8007t_cb_map va1j5jf8007t_cb_maps[] = {
89 { 90000000, 0x80 },
90 { 140000000, 0x81 },
91 { 170000000, 0xa1 },
92 { 220000000, 0x62 },
93 { 330000000, 0xa2 },
94 { 402000000, 0xe2 },
95 { 450000000, 0x64 },
96 { 550000000, 0x84 },
97 { 600000000, 0xa4 },
98 { 700000000, 0xc4 },
101 static u8 va1j5jf8007t_lookup_cb(u32 frequency)
103 int i;
104 const struct va1j5jf8007t_cb_map *map;
106 for (i = 0; i < ARRAY_SIZE(va1j5jf8007t_cb_maps); i++) {
107 map = &va1j5jf8007t_cb_maps[i];
108 if (frequency < map->frequency)
109 return map->cb;
111 return 0xe4;
114 static int va1j5jf8007t_set_frequency(struct va1j5jf8007t_state *state)
116 u32 frequency;
117 u16 word;
118 u8 buf[6];
119 struct i2c_msg msg;
121 frequency = state->fe.dtv_property_cache.frequency;
123 word = (frequency + 71428) / 142857 + 399;
124 buf[0] = 0xfe;
125 buf[1] = 0xc2;
126 buf[2] = word >> 8;
127 buf[3] = word;
128 buf[4] = 0x80;
129 buf[5] = va1j5jf8007t_lookup_cb(frequency);
131 msg.addr = state->config->demod_address;
132 msg.flags = 0;
133 msg.len = sizeof(buf);
134 msg.buf = buf;
136 if (i2c_transfer(state->adap, &msg, 1) != 1)
137 return -EREMOTEIO;
139 return 0;
142 static int
143 va1j5jf8007t_check_frequency(struct va1j5jf8007t_state *state, int *lock)
145 u8 addr;
146 u8 write_buf[2], read_buf[1];
147 struct i2c_msg msgs[2];
149 addr = state->config->demod_address;
151 write_buf[0] = 0xfe;
152 write_buf[1] = 0xc3;
154 msgs[0].addr = addr;
155 msgs[0].flags = 0;
156 msgs[0].len = sizeof(write_buf);
157 msgs[0].buf = write_buf;
159 msgs[1].addr = addr;
160 msgs[1].flags = I2C_M_RD;
161 msgs[1].len = sizeof(read_buf);
162 msgs[1].buf = read_buf;
164 if (i2c_transfer(state->adap, msgs, 2) != 2)
165 return -EREMOTEIO;
167 *lock = read_buf[0] & 0x40;
168 return 0;
171 static int va1j5jf8007t_set_modulation(struct va1j5jf8007t_state *state)
173 u8 buf[2];
174 struct i2c_msg msg;
176 buf[0] = 0x01;
177 buf[1] = 0x40;
179 msg.addr = state->config->demod_address;
180 msg.flags = 0;
181 msg.len = sizeof(buf);
182 msg.buf = buf;
184 if (i2c_transfer(state->adap, &msg, 1) != 1)
185 return -EREMOTEIO;
187 return 0;
190 static int va1j5jf8007t_check_modulation(struct va1j5jf8007t_state *state,
191 int *lock, int *retry)
193 u8 addr;
194 u8 write_buf[1], read_buf[1];
195 struct i2c_msg msgs[2];
197 addr = state->config->demod_address;
199 write_buf[0] = 0x80;
201 msgs[0].addr = addr;
202 msgs[0].flags = 0;
203 msgs[0].len = sizeof(write_buf);
204 msgs[0].buf = write_buf;
206 msgs[1].addr = addr;
207 msgs[1].flags = I2C_M_RD;
208 msgs[1].len = sizeof(read_buf);
209 msgs[1].buf = read_buf;
211 if (i2c_transfer(state->adap, msgs, 2) != 2)
212 return -EREMOTEIO;
214 *lock = !(read_buf[0] & 0x10);
215 *retry = read_buf[0] & 0x80;
216 return 0;
219 static int
220 va1j5jf8007t_tune(struct dvb_frontend *fe,
221 struct dvb_frontend_parameters *params,
222 unsigned int mode_flags, unsigned int *delay,
223 fe_status_t *status)
225 struct va1j5jf8007t_state *state;
226 int ret;
227 int lock, retry;
229 state = fe->demodulator_priv;
231 if (params != NULL)
232 state->tune_state = VA1J5JF8007T_SET_FREQUENCY;
234 switch (state->tune_state) {
235 case VA1J5JF8007T_IDLE:
236 *delay = 3 * HZ;
237 *status = 0;
238 return 0;
240 case VA1J5JF8007T_SET_FREQUENCY:
241 ret = va1j5jf8007t_set_frequency(state);
242 if (ret < 0)
243 return ret;
245 state->tune_state = VA1J5JF8007T_CHECK_FREQUENCY;
246 *delay = 0;
247 *status = 0;
248 return 0;
250 case VA1J5JF8007T_CHECK_FREQUENCY:
251 ret = va1j5jf8007t_check_frequency(state, &lock);
252 if (ret < 0)
253 return ret;
255 if (!lock) {
256 *delay = (HZ + 999) / 1000;
257 *status = 0;
258 return 0;
261 state->tune_state = VA1J5JF8007T_SET_MODULATION;
262 *delay = 0;
263 *status = FE_HAS_SIGNAL;
264 return 0;
266 case VA1J5JF8007T_SET_MODULATION:
267 ret = va1j5jf8007t_set_modulation(state);
268 if (ret < 0)
269 return ret;
271 state->tune_state = VA1J5JF8007T_CHECK_MODULATION;
272 *delay = 0;
273 *status = FE_HAS_SIGNAL;
274 return 0;
276 case VA1J5JF8007T_CHECK_MODULATION:
277 ret = va1j5jf8007t_check_modulation(state, &lock, &retry);
278 if (ret < 0)
279 return ret;
281 if (!lock) {
282 if (!retry) {
283 state->tune_state = VA1J5JF8007T_ABORT;
284 *delay = 3 * HZ;
285 *status = FE_HAS_SIGNAL;
286 return 0;
288 *delay = (HZ + 999) / 1000;
289 *status = FE_HAS_SIGNAL;
290 return 0;
293 state->tune_state = VA1J5JF8007T_TRACK;
294 /* fall through */
296 case VA1J5JF8007T_TRACK:
297 *delay = 3 * HZ;
298 *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
299 return 0;
301 case VA1J5JF8007T_ABORT:
302 *delay = 3 * HZ;
303 *status = FE_HAS_SIGNAL;
304 return 0;
307 BUG();
310 static int va1j5jf8007t_init_frequency(struct va1j5jf8007t_state *state)
312 u8 buf[7];
313 struct i2c_msg msg;
315 buf[0] = 0xfe;
316 buf[1] = 0xc2;
317 buf[2] = 0x01;
318 buf[3] = 0x8f;
319 buf[4] = 0xc1;
320 buf[5] = 0x80;
321 buf[6] = 0x80;
323 msg.addr = state->config->demod_address;
324 msg.flags = 0;
325 msg.len = sizeof(buf);
326 msg.buf = buf;
328 if (i2c_transfer(state->adap, &msg, 1) != 1)
329 return -EREMOTEIO;
331 return 0;
334 static int va1j5jf8007t_set_sleep(struct va1j5jf8007t_state *state, int sleep)
336 u8 buf[2];
337 struct i2c_msg msg;
339 buf[0] = 0x03;
340 buf[1] = sleep ? 0x90 : 0x80;
342 msg.addr = state->config->demod_address;
343 msg.flags = 0;
344 msg.len = sizeof(buf);
345 msg.buf = buf;
347 if (i2c_transfer(state->adap, &msg, 1) != 1)
348 return -EREMOTEIO;
350 return 0;
353 static int va1j5jf8007t_sleep(struct dvb_frontend *fe)
355 struct va1j5jf8007t_state *state;
356 int ret;
358 state = fe->demodulator_priv;
360 ret = va1j5jf8007t_init_frequency(state);
361 if (ret < 0)
362 return ret;
364 return va1j5jf8007t_set_sleep(state, 1);
367 static int va1j5jf8007t_init(struct dvb_frontend *fe)
369 struct va1j5jf8007t_state *state;
371 state = fe->demodulator_priv;
372 state->tune_state = VA1J5JF8007T_IDLE;
374 return va1j5jf8007t_set_sleep(state, 0);
377 static void va1j5jf8007t_release(struct dvb_frontend *fe)
379 struct va1j5jf8007t_state *state;
380 state = fe->demodulator_priv;
381 kfree(state);
384 static struct dvb_frontend_ops va1j5jf8007t_ops = {
385 .info = {
386 .name = "VA1J5JF8007 ISDB-T",
387 .type = FE_OFDM,
388 .frequency_min = 90000000,
389 .frequency_max = 770000000,
390 .frequency_stepsize = 142857,
391 .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO |
392 FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
393 FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
396 .get_frontend_algo = va1j5jf8007t_get_frontend_algo,
397 .read_status = va1j5jf8007t_read_status,
398 .tune = va1j5jf8007t_tune,
399 .sleep = va1j5jf8007t_sleep,
400 .init = va1j5jf8007t_init,
401 .release = va1j5jf8007t_release,
404 static const u8 va1j5jf8007t_prepare_bufs[][2] = {
405 {0x03, 0x90}, {0x14, 0x8f}, {0x1c, 0x2a}, {0x1d, 0xa8}, {0x1e, 0xa2},
406 {0x22, 0x83}, {0x31, 0x0d}, {0x32, 0xe0}, {0x39, 0xd3}, {0x3a, 0x00},
407 {0x5c, 0x40}, {0x5f, 0x80}, {0x75, 0x02}, {0x76, 0x4e}, {0x77, 0x03},
408 {0xef, 0x01}
411 int va1j5jf8007t_prepare(struct dvb_frontend *fe)
413 struct va1j5jf8007t_state *state;
414 u8 buf[2];
415 struct i2c_msg msg;
416 int i;
418 state = fe->demodulator_priv;
420 msg.addr = state->config->demod_address;
421 msg.flags = 0;
422 msg.len = sizeof(buf);
423 msg.buf = buf;
425 for (i = 0; i < ARRAY_SIZE(va1j5jf8007t_prepare_bufs); i++) {
426 memcpy(buf, va1j5jf8007t_prepare_bufs[i], sizeof(buf));
427 if (i2c_transfer(state->adap, &msg, 1) != 1)
428 return -EREMOTEIO;
431 return va1j5jf8007t_init_frequency(state);
434 struct dvb_frontend *
435 va1j5jf8007t_attach(const struct va1j5jf8007t_config *config,
436 struct i2c_adapter *adap)
438 struct va1j5jf8007t_state *state;
439 struct dvb_frontend *fe;
440 u8 buf[2];
441 struct i2c_msg msg;
443 state = kzalloc(sizeof(struct va1j5jf8007t_state), GFP_KERNEL);
444 if (!state)
445 return NULL;
447 state->config = config;
448 state->adap = adap;
450 fe = &state->fe;
451 memcpy(&fe->ops, &va1j5jf8007t_ops, sizeof(struct dvb_frontend_ops));
452 fe->demodulator_priv = state;
454 buf[0] = 0x01;
455 buf[1] = 0x80;
457 msg.addr = state->config->demod_address;
458 msg.flags = 0;
459 msg.len = sizeof(buf);
460 msg.buf = buf;
462 if (i2c_transfer(state->adap, &msg, 1) != 1) {
463 kfree(state);
464 return NULL;
467 return fe;