Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/dvb/pt1/va1j5jf8007t.c
15112 views
1
/*
2
* ISDB-T driver for VA1J5JF8007/VA1J5JF8011
3
*
4
* Copyright (C) 2009 HIRANO Takahito <[email protected]>
5
*
6
* based on pt1dvr - http://pt1dvr.sourceforge.jp/
7
* by Tomoaki Ishikawa <[email protected]>
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_read_snr(struct dvb_frontend *fe, u16 *snr)
50
{
51
struct va1j5jf8007t_state *state;
52
u8 addr;
53
int i;
54
u8 write_buf[1], read_buf[1];
55
struct i2c_msg msgs[2];
56
s32 word, x, y;
57
58
state = fe->demodulator_priv;
59
addr = state->config->demod_address;
60
61
word = 0;
62
for (i = 0; i < 3; i++) {
63
write_buf[0] = 0x8b + i;
64
65
msgs[0].addr = addr;
66
msgs[0].flags = 0;
67
msgs[0].len = sizeof(write_buf);
68
msgs[0].buf = write_buf;
69
70
msgs[1].addr = addr;
71
msgs[1].flags = I2C_M_RD;
72
msgs[1].len = sizeof(read_buf);
73
msgs[1].buf = read_buf;
74
75
if (i2c_transfer(state->adap, msgs, 2) != 2)
76
return -EREMOTEIO;
77
78
word <<= 8;
79
word |= read_buf[0];
80
}
81
82
if (!word)
83
return -EIO;
84
85
x = 10 * (intlog10(0x540000 * 100 / word) - (2 << 24));
86
y = (24ll << 46) / 1000000;
87
y = ((s64)y * x >> 30) - (16ll << 40) / 10000;
88
y = ((s64)y * x >> 29) + (398ll << 35) / 10000;
89
y = ((s64)y * x >> 30) + (5491ll << 29) / 10000;
90
y = ((s64)y * x >> 30) + (30965ll << 23) / 10000;
91
*snr = y >> 15;
92
return 0;
93
}
94
95
static int va1j5jf8007t_get_frontend_algo(struct dvb_frontend *fe)
96
{
97
return DVBFE_ALGO_HW;
98
}
99
100
static int
101
va1j5jf8007t_read_status(struct dvb_frontend *fe, fe_status_t *status)
102
{
103
struct va1j5jf8007t_state *state;
104
105
state = fe->demodulator_priv;
106
107
switch (state->tune_state) {
108
case VA1J5JF8007T_IDLE:
109
case VA1J5JF8007T_SET_FREQUENCY:
110
case VA1J5JF8007T_CHECK_FREQUENCY:
111
*status = 0;
112
return 0;
113
114
115
case VA1J5JF8007T_SET_MODULATION:
116
case VA1J5JF8007T_CHECK_MODULATION:
117
case VA1J5JF8007T_ABORT:
118
*status |= FE_HAS_SIGNAL;
119
return 0;
120
121
case VA1J5JF8007T_TRACK:
122
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
123
return 0;
124
}
125
126
BUG();
127
}
128
129
struct va1j5jf8007t_cb_map {
130
u32 frequency;
131
u8 cb;
132
};
133
134
static const struct va1j5jf8007t_cb_map va1j5jf8007t_cb_maps[] = {
135
{ 90000000, 0x80 },
136
{ 140000000, 0x81 },
137
{ 170000000, 0xa1 },
138
{ 220000000, 0x62 },
139
{ 330000000, 0xa2 },
140
{ 402000000, 0xe2 },
141
{ 450000000, 0x64 },
142
{ 550000000, 0x84 },
143
{ 600000000, 0xa4 },
144
{ 700000000, 0xc4 },
145
};
146
147
static u8 va1j5jf8007t_lookup_cb(u32 frequency)
148
{
149
int i;
150
const struct va1j5jf8007t_cb_map *map;
151
152
for (i = 0; i < ARRAY_SIZE(va1j5jf8007t_cb_maps); i++) {
153
map = &va1j5jf8007t_cb_maps[i];
154
if (frequency < map->frequency)
155
return map->cb;
156
}
157
return 0xe4;
158
}
159
160
static int va1j5jf8007t_set_frequency(struct va1j5jf8007t_state *state)
161
{
162
u32 frequency;
163
u16 word;
164
u8 buf[6];
165
struct i2c_msg msg;
166
167
frequency = state->fe.dtv_property_cache.frequency;
168
169
word = (frequency + 71428) / 142857 + 399;
170
buf[0] = 0xfe;
171
buf[1] = 0xc2;
172
buf[2] = word >> 8;
173
buf[3] = word;
174
buf[4] = 0x80;
175
buf[5] = va1j5jf8007t_lookup_cb(frequency);
176
177
msg.addr = state->config->demod_address;
178
msg.flags = 0;
179
msg.len = sizeof(buf);
180
msg.buf = buf;
181
182
if (i2c_transfer(state->adap, &msg, 1) != 1)
183
return -EREMOTEIO;
184
185
return 0;
186
}
187
188
static int
189
va1j5jf8007t_check_frequency(struct va1j5jf8007t_state *state, int *lock)
190
{
191
u8 addr;
192
u8 write_buf[2], read_buf[1];
193
struct i2c_msg msgs[2];
194
195
addr = state->config->demod_address;
196
197
write_buf[0] = 0xfe;
198
write_buf[1] = 0xc3;
199
200
msgs[0].addr = addr;
201
msgs[0].flags = 0;
202
msgs[0].len = sizeof(write_buf);
203
msgs[0].buf = write_buf;
204
205
msgs[1].addr = addr;
206
msgs[1].flags = I2C_M_RD;
207
msgs[1].len = sizeof(read_buf);
208
msgs[1].buf = read_buf;
209
210
if (i2c_transfer(state->adap, msgs, 2) != 2)
211
return -EREMOTEIO;
212
213
*lock = read_buf[0] & 0x40;
214
return 0;
215
}
216
217
static int va1j5jf8007t_set_modulation(struct va1j5jf8007t_state *state)
218
{
219
u8 buf[2];
220
struct i2c_msg msg;
221
222
buf[0] = 0x01;
223
buf[1] = 0x40;
224
225
msg.addr = state->config->demod_address;
226
msg.flags = 0;
227
msg.len = sizeof(buf);
228
msg.buf = buf;
229
230
if (i2c_transfer(state->adap, &msg, 1) != 1)
231
return -EREMOTEIO;
232
233
return 0;
234
}
235
236
static int va1j5jf8007t_check_modulation(struct va1j5jf8007t_state *state,
237
int *lock, int *retry)
238
{
239
u8 addr;
240
u8 write_buf[1], read_buf[1];
241
struct i2c_msg msgs[2];
242
243
addr = state->config->demod_address;
244
245
write_buf[0] = 0x80;
246
247
msgs[0].addr = addr;
248
msgs[0].flags = 0;
249
msgs[0].len = sizeof(write_buf);
250
msgs[0].buf = write_buf;
251
252
msgs[1].addr = addr;
253
msgs[1].flags = I2C_M_RD;
254
msgs[1].len = sizeof(read_buf);
255
msgs[1].buf = read_buf;
256
257
if (i2c_transfer(state->adap, msgs, 2) != 2)
258
return -EREMOTEIO;
259
260
*lock = !(read_buf[0] & 0x10);
261
*retry = read_buf[0] & 0x80;
262
return 0;
263
}
264
265
static int
266
va1j5jf8007t_tune(struct dvb_frontend *fe,
267
struct dvb_frontend_parameters *params,
268
unsigned int mode_flags, unsigned int *delay,
269
fe_status_t *status)
270
{
271
struct va1j5jf8007t_state *state;
272
int ret;
273
int lock = 0, retry = 0;
274
275
state = fe->demodulator_priv;
276
277
if (params != NULL)
278
state->tune_state = VA1J5JF8007T_SET_FREQUENCY;
279
280
switch (state->tune_state) {
281
case VA1J5JF8007T_IDLE:
282
*delay = 3 * HZ;
283
*status = 0;
284
return 0;
285
286
case VA1J5JF8007T_SET_FREQUENCY:
287
ret = va1j5jf8007t_set_frequency(state);
288
if (ret < 0)
289
return ret;
290
291
state->tune_state = VA1J5JF8007T_CHECK_FREQUENCY;
292
*delay = 0;
293
*status = 0;
294
return 0;
295
296
case VA1J5JF8007T_CHECK_FREQUENCY:
297
ret = va1j5jf8007t_check_frequency(state, &lock);
298
if (ret < 0)
299
return ret;
300
301
if (!lock) {
302
*delay = (HZ + 999) / 1000;
303
*status = 0;
304
return 0;
305
}
306
307
state->tune_state = VA1J5JF8007T_SET_MODULATION;
308
*delay = 0;
309
*status = FE_HAS_SIGNAL;
310
return 0;
311
312
case VA1J5JF8007T_SET_MODULATION:
313
ret = va1j5jf8007t_set_modulation(state);
314
if (ret < 0)
315
return ret;
316
317
state->tune_state = VA1J5JF8007T_CHECK_MODULATION;
318
*delay = 0;
319
*status = FE_HAS_SIGNAL;
320
return 0;
321
322
case VA1J5JF8007T_CHECK_MODULATION:
323
ret = va1j5jf8007t_check_modulation(state, &lock, &retry);
324
if (ret < 0)
325
return ret;
326
327
if (!lock) {
328
if (!retry) {
329
state->tune_state = VA1J5JF8007T_ABORT;
330
*delay = 3 * HZ;
331
*status = FE_HAS_SIGNAL;
332
return 0;
333
}
334
*delay = (HZ + 999) / 1000;
335
*status = FE_HAS_SIGNAL;
336
return 0;
337
}
338
339
state->tune_state = VA1J5JF8007T_TRACK;
340
/* fall through */
341
342
case VA1J5JF8007T_TRACK:
343
*delay = 3 * HZ;
344
*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
345
return 0;
346
347
case VA1J5JF8007T_ABORT:
348
*delay = 3 * HZ;
349
*status = FE_HAS_SIGNAL;
350
return 0;
351
}
352
353
BUG();
354
}
355
356
static int va1j5jf8007t_init_frequency(struct va1j5jf8007t_state *state)
357
{
358
u8 buf[7];
359
struct i2c_msg msg;
360
361
buf[0] = 0xfe;
362
buf[1] = 0xc2;
363
buf[2] = 0x01;
364
buf[3] = 0x8f;
365
buf[4] = 0xc1;
366
buf[5] = 0x80;
367
buf[6] = 0x80;
368
369
msg.addr = state->config->demod_address;
370
msg.flags = 0;
371
msg.len = sizeof(buf);
372
msg.buf = buf;
373
374
if (i2c_transfer(state->adap, &msg, 1) != 1)
375
return -EREMOTEIO;
376
377
return 0;
378
}
379
380
static int va1j5jf8007t_set_sleep(struct va1j5jf8007t_state *state, int sleep)
381
{
382
u8 buf[2];
383
struct i2c_msg msg;
384
385
buf[0] = 0x03;
386
buf[1] = sleep ? 0x90 : 0x80;
387
388
msg.addr = state->config->demod_address;
389
msg.flags = 0;
390
msg.len = sizeof(buf);
391
msg.buf = buf;
392
393
if (i2c_transfer(state->adap, &msg, 1) != 1)
394
return -EREMOTEIO;
395
396
return 0;
397
}
398
399
static int va1j5jf8007t_sleep(struct dvb_frontend *fe)
400
{
401
struct va1j5jf8007t_state *state;
402
int ret;
403
404
state = fe->demodulator_priv;
405
406
ret = va1j5jf8007t_init_frequency(state);
407
if (ret < 0)
408
return ret;
409
410
return va1j5jf8007t_set_sleep(state, 1);
411
}
412
413
static int va1j5jf8007t_init(struct dvb_frontend *fe)
414
{
415
struct va1j5jf8007t_state *state;
416
417
state = fe->demodulator_priv;
418
state->tune_state = VA1J5JF8007T_IDLE;
419
420
return va1j5jf8007t_set_sleep(state, 0);
421
}
422
423
static void va1j5jf8007t_release(struct dvb_frontend *fe)
424
{
425
struct va1j5jf8007t_state *state;
426
state = fe->demodulator_priv;
427
kfree(state);
428
}
429
430
static struct dvb_frontend_ops va1j5jf8007t_ops = {
431
.info = {
432
.name = "VA1J5JF8007/VA1J5JF8011 ISDB-T",
433
.type = FE_OFDM,
434
.frequency_min = 90000000,
435
.frequency_max = 770000000,
436
.frequency_stepsize = 142857,
437
.caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO |
438
FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
439
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
440
},
441
442
.read_snr = va1j5jf8007t_read_snr,
443
.get_frontend_algo = va1j5jf8007t_get_frontend_algo,
444
.read_status = va1j5jf8007t_read_status,
445
.tune = va1j5jf8007t_tune,
446
.sleep = va1j5jf8007t_sleep,
447
.init = va1j5jf8007t_init,
448
.release = va1j5jf8007t_release,
449
};
450
451
static const u8 va1j5jf8007t_20mhz_prepare_bufs[][2] = {
452
{0x03, 0x90}, {0x14, 0x8f}, {0x1c, 0x2a}, {0x1d, 0xa8}, {0x1e, 0xa2},
453
{0x22, 0x83}, {0x31, 0x0d}, {0x32, 0xe0}, {0x39, 0xd3}, {0x3a, 0x00},
454
{0x5c, 0x40}, {0x5f, 0x80}, {0x75, 0x02}, {0x76, 0x4e}, {0x77, 0x03},
455
{0xef, 0x01}
456
};
457
458
static const u8 va1j5jf8007t_25mhz_prepare_bufs[][2] = {
459
{0x03, 0x90}, {0x1c, 0x2a}, {0x1d, 0xa8}, {0x1e, 0xa2}, {0x22, 0x83},
460
{0x3a, 0x00}, {0x5c, 0x40}, {0x5f, 0x80}, {0x75, 0x0a}, {0x76, 0x4c},
461
{0x77, 0x03}, {0xef, 0x01}
462
};
463
464
int va1j5jf8007t_prepare(struct dvb_frontend *fe)
465
{
466
struct va1j5jf8007t_state *state;
467
const u8 (*bufs)[2];
468
int size;
469
u8 buf[2];
470
struct i2c_msg msg;
471
int i;
472
473
state = fe->demodulator_priv;
474
475
switch (state->config->frequency) {
476
case VA1J5JF8007T_20MHZ:
477
bufs = va1j5jf8007t_20mhz_prepare_bufs;
478
size = ARRAY_SIZE(va1j5jf8007t_20mhz_prepare_bufs);
479
break;
480
case VA1J5JF8007T_25MHZ:
481
bufs = va1j5jf8007t_25mhz_prepare_bufs;
482
size = ARRAY_SIZE(va1j5jf8007t_25mhz_prepare_bufs);
483
break;
484
default:
485
return -EINVAL;
486
}
487
488
msg.addr = state->config->demod_address;
489
msg.flags = 0;
490
msg.len = sizeof(buf);
491
msg.buf = buf;
492
493
for (i = 0; i < size; i++) {
494
memcpy(buf, bufs[i], sizeof(buf));
495
if (i2c_transfer(state->adap, &msg, 1) != 1)
496
return -EREMOTEIO;
497
}
498
499
return va1j5jf8007t_init_frequency(state);
500
}
501
502
struct dvb_frontend *
503
va1j5jf8007t_attach(const struct va1j5jf8007t_config *config,
504
struct i2c_adapter *adap)
505
{
506
struct va1j5jf8007t_state *state;
507
struct dvb_frontend *fe;
508
u8 buf[2];
509
struct i2c_msg msg;
510
511
state = kzalloc(sizeof(struct va1j5jf8007t_state), GFP_KERNEL);
512
if (!state)
513
return NULL;
514
515
state->config = config;
516
state->adap = adap;
517
518
fe = &state->fe;
519
memcpy(&fe->ops, &va1j5jf8007t_ops, sizeof(struct dvb_frontend_ops));
520
fe->demodulator_priv = state;
521
522
buf[0] = 0x01;
523
buf[1] = 0x80;
524
525
msg.addr = state->config->demod_address;
526
msg.flags = 0;
527
msg.len = sizeof(buf);
528
msg.buf = buf;
529
530
if (i2c_transfer(state->adap, &msg, 1) != 1) {
531
kfree(state);
532
return NULL;
533
}
534
535
return fe;
536
}
537
538