V4L/DVB (12999): Add a driver for Earthsoft PT1
[safe/jmp/linux-2.6] / drivers / media / dvb / pt1 / va1j5jf8007t.c
1 /*
2  * ISDB-T driver for VA1J5JF8007
3  *
4  * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
5  *
6  * based on pt1dvr - http://pt1dvr.sourceforge.jp/
7  *      by Tomoaki Ishikawa <tomy@users.sourceforge.jp>
8  *
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.
13  *
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.
18  *
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.
22  */
23
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"
31
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,
40 };
41
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;
47 };
48
49 static int va1j5jf8007t_get_frontend_algo(struct dvb_frontend *fe)
50 {
51         return DVBFE_ALGO_HW;
52 }
53
54 static int
55 va1j5jf8007t_read_status(struct dvb_frontend *fe, fe_status_t *status)
56 {
57         struct va1j5jf8007t_state *state;
58
59         state = fe->demodulator_priv;
60
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;
67
68
69         case VA1J5JF8007T_SET_MODULATION:
70         case VA1J5JF8007T_CHECK_MODULATION:
71         case VA1J5JF8007T_ABORT:
72                 *status |= FE_HAS_SIGNAL;
73                 return 0;
74
75         case VA1J5JF8007T_TRACK:
76                 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
77                 return 0;
78         }
79
80         BUG();
81 }
82
83 struct va1j5jf8007t_cb_map {
84         u32 frequency;
85         u8 cb;
86 };
87
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 },
99 };
100
101 static u8 va1j5jf8007t_lookup_cb(u32 frequency)
102 {
103         int i;
104         const struct va1j5jf8007t_cb_map *map;
105
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;
110         }
111         return 0xe4;
112 }
113
114 static int va1j5jf8007t_set_frequency(struct va1j5jf8007t_state *state)
115 {
116         u32 frequency;
117         u16 word;
118         u8 buf[6];
119         struct i2c_msg msg;
120
121         frequency = state->fe.dtv_property_cache.frequency;
122
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);
130
131         msg.addr = state->config->demod_address;
132         msg.flags = 0;
133         msg.len = sizeof(buf);
134         msg.buf = buf;
135
136         if (i2c_transfer(state->adap, &msg, 1) != 1)
137                 return -EREMOTEIO;
138
139         return 0;
140 }
141
142 static int
143 va1j5jf8007t_check_frequency(struct va1j5jf8007t_state *state, int *lock)
144 {
145         u8 addr;
146         u8 write_buf[2], read_buf[1];
147         struct i2c_msg msgs[2];
148
149         addr = state->config->demod_address;
150
151         write_buf[0] = 0xfe;
152         write_buf[1] = 0xc3;
153
154         msgs[0].addr = addr;
155         msgs[0].flags = 0;
156         msgs[0].len = sizeof(write_buf);
157         msgs[0].buf = write_buf;
158
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;
163
164         if (i2c_transfer(state->adap, msgs, 2) != 2)
165                 return -EREMOTEIO;
166
167         *lock = read_buf[0] & 0x40;
168         return 0;
169 }
170
171 static int va1j5jf8007t_set_modulation(struct va1j5jf8007t_state *state)
172 {
173         u8 buf[2];
174         struct i2c_msg msg;
175
176         buf[0] = 0x01;
177         buf[1] = 0x40;
178
179         msg.addr = state->config->demod_address;
180         msg.flags = 0;
181         msg.len = sizeof(buf);
182         msg.buf = buf;
183
184         if (i2c_transfer(state->adap, &msg, 1) != 1)
185                 return -EREMOTEIO;
186
187         return 0;
188 }
189
190 static int va1j5jf8007t_check_modulation(struct va1j5jf8007t_state *state,
191                                          int *lock, int *retry)
192 {
193         u8 addr;
194         u8 write_buf[1], read_buf[1];
195         struct i2c_msg msgs[2];
196
197         addr = state->config->demod_address;
198
199         write_buf[0] = 0x80;
200
201         msgs[0].addr = addr;
202         msgs[0].flags = 0;
203         msgs[0].len = sizeof(write_buf);
204         msgs[0].buf = write_buf;
205
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;
210
211         if (i2c_transfer(state->adap, msgs, 2) != 2)
212                 return -EREMOTEIO;
213
214         *lock = !(read_buf[0] & 0x10);
215         *retry = read_buf[0] & 0x80;
216         return 0;
217 }
218
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)
224 {
225         struct va1j5jf8007t_state *state;
226         int ret;
227         int lock, retry;
228
229         state = fe->demodulator_priv;
230
231         if (params != NULL)
232                 state->tune_state = VA1J5JF8007T_SET_FREQUENCY;
233
234         switch (state->tune_state) {
235         case VA1J5JF8007T_IDLE:
236                 *delay = 3 * HZ;
237                 *status = 0;
238                 return 0;
239
240         case VA1J5JF8007T_SET_FREQUENCY:
241                 ret = va1j5jf8007t_set_frequency(state);
242                 if (ret < 0)
243                         return ret;
244
245                 state->tune_state = VA1J5JF8007T_CHECK_FREQUENCY;
246                 *delay = 0;
247                 *status = 0;
248                 return 0;
249
250         case VA1J5JF8007T_CHECK_FREQUENCY:
251                 ret = va1j5jf8007t_check_frequency(state, &lock);
252                 if (ret < 0)
253                         return ret;
254
255                 if (!lock)  {
256                         *delay = (HZ + 999) / 1000;
257                         *status = 0;
258                         return 0;
259                 }
260
261                 state->tune_state = VA1J5JF8007T_SET_MODULATION;
262                 *delay = 0;
263                 *status = FE_HAS_SIGNAL;
264                 return 0;
265
266         case VA1J5JF8007T_SET_MODULATION:
267                 ret = va1j5jf8007t_set_modulation(state);
268                 if (ret < 0)
269                         return ret;
270
271                 state->tune_state = VA1J5JF8007T_CHECK_MODULATION;
272                 *delay = 0;
273                 *status = FE_HAS_SIGNAL;
274                 return 0;
275
276         case VA1J5JF8007T_CHECK_MODULATION:
277                 ret = va1j5jf8007t_check_modulation(state, &lock, &retry);
278                 if (ret < 0)
279                         return ret;
280
281                 if (!lock)  {
282                         if (!retry)  {
283                                 state->tune_state = VA1J5JF8007T_ABORT;
284                                 *delay = 3 * HZ;
285                                 *status = FE_HAS_SIGNAL;
286                                 return 0;
287                         }
288                         *delay = (HZ + 999) / 1000;
289                         *status = FE_HAS_SIGNAL;
290                         return 0;
291                 }
292
293                 state->tune_state = VA1J5JF8007T_TRACK;
294                 /* fall through */
295
296         case VA1J5JF8007T_TRACK:
297                 *delay = 3 * HZ;
298                 *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
299                 return 0;
300
301         case VA1J5JF8007T_ABORT:
302                 *delay = 3 * HZ;
303                 *status = FE_HAS_SIGNAL;
304                 return 0;
305         }
306
307         BUG();
308 }
309
310 static int va1j5jf8007t_init_frequency(struct va1j5jf8007t_state *state)
311 {
312         u8 buf[7];
313         struct i2c_msg msg;
314
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;
322
323         msg.addr = state->config->demod_address;
324         msg.flags = 0;
325         msg.len = sizeof(buf);
326         msg.buf = buf;
327
328         if (i2c_transfer(state->adap, &msg, 1) != 1)
329                 return -EREMOTEIO;
330
331         return 0;
332 }
333
334 static int va1j5jf8007t_set_sleep(struct va1j5jf8007t_state *state, int sleep)
335 {
336         u8 buf[2];
337         struct i2c_msg msg;
338
339         buf[0] = 0x03;
340         buf[1] = sleep ? 0x90 : 0x80;
341
342         msg.addr = state->config->demod_address;
343         msg.flags = 0;
344         msg.len = sizeof(buf);
345         msg.buf = buf;
346
347         if (i2c_transfer(state->adap, &msg, 1) != 1)
348                 return -EREMOTEIO;
349
350         return 0;
351 }
352
353 static int va1j5jf8007t_sleep(struct dvb_frontend *fe)
354 {
355         struct va1j5jf8007t_state *state;
356         int ret;
357
358         state = fe->demodulator_priv;
359
360         ret = va1j5jf8007t_init_frequency(state);
361         if (ret < 0)
362                 return ret;
363
364         return va1j5jf8007t_set_sleep(state, 1);
365 }
366
367 static int va1j5jf8007t_init(struct dvb_frontend *fe)
368 {
369         struct va1j5jf8007t_state *state;
370
371         state = fe->demodulator_priv;
372         state->tune_state = VA1J5JF8007T_IDLE;
373
374         return va1j5jf8007t_set_sleep(state, 0);
375 }
376
377 static void va1j5jf8007t_release(struct dvb_frontend *fe)
378 {
379         struct va1j5jf8007t_state *state;
380         state = fe->demodulator_priv;
381         kfree(state);
382 }
383
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,
394         },
395
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,
402 };
403
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}
409 };
410
411 int va1j5jf8007t_prepare(struct dvb_frontend *fe)
412 {
413         struct va1j5jf8007t_state *state;
414         u8 buf[2];
415         struct i2c_msg msg;
416         int i;
417
418         state = fe->demodulator_priv;
419
420         msg.addr = state->config->demod_address;
421         msg.flags = 0;
422         msg.len = sizeof(buf);
423         msg.buf = buf;
424
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;
429         }
430
431         return va1j5jf8007t_init_frequency(state);
432 }
433
434 struct dvb_frontend *
435 va1j5jf8007t_attach(const struct va1j5jf8007t_config *config,
436                     struct i2c_adapter *adap)
437 {
438         struct va1j5jf8007t_state *state;
439         struct dvb_frontend *fe;
440         u8 buf[2];
441         struct i2c_msg msg;
442
443         state = kzalloc(sizeof(struct va1j5jf8007t_state), GFP_KERNEL);
444         if (!state)
445                 return NULL;
446
447         state->config = config;
448         state->adap = adap;
449
450         fe = &state->fe;
451         memcpy(&fe->ops, &va1j5jf8007t_ops, sizeof(struct dvb_frontend_ops));
452         fe->demodulator_priv = state;
453
454         buf[0] = 0x01;
455         buf[1] = 0x80;
456
457         msg.addr = state->config->demod_address;
458         msg.flags = 0;
459         msg.len = sizeof(buf);
460         msg.buf = buf;
461
462         if (i2c_transfer(state->adap, &msg, 1) != 1) {
463                 kfree(state);
464                 return NULL;
465         }
466
467         return fe;
468 }