blob: d065a72e0bb7e27a07b189af5aa9ca517baaafa3 [file] [log] [blame]
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001/*
2 * Linux-DVB Driver for DiBcom's DiB8000 chip (ISDB-T).
3 *
4 * Copyright (C) 2009 DiBcom (http://www.dibcom.fr/)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2.
9 */
10#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090011#include <linux/slab.h>
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -030012#include <linux/i2c.h>
Patrick Boettcher79fcce32011-08-03 12:08:21 -030013#include <linux/mutex.h>
14
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -030015#include "dvb_math.h"
16
17#include "dvb_frontend.h"
18
19#include "dib8000.h"
20
21#define LAYER_ALL -1
22#define LAYER_A 1
23#define LAYER_B 2
24#define LAYER_C 3
25
Olivier Grenie4c70e072011-01-03 15:33:37 -030026#define MAX_NUMBER_OF_FRONTENDS 6
Patrick Boettcher173a64c2013-04-22 12:45:52 -030027/* #define DIB8000_AGC_FREEZE */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -030028
Patrick Boettcher78f3bc62009-08-17 12:53:51 -030029static int debug;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -030030module_param(debug, int, 0644);
31MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
32
33#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0)
34
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -030035struct i2c_device {
36 struct i2c_adapter *adap;
37 u8 addr;
Olivier Grenie5a0deee2011-05-03 12:27:33 -030038 u8 *i2c_write_buffer;
39 u8 *i2c_read_buffer;
Patrick Boettcher79fcce32011-08-03 12:08:21 -030040 struct mutex *i2c_buffer_lock;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -030041};
42
Patrick Boettcher173a64c2013-04-22 12:45:52 -030043enum param_loop_step {
44 LOOP_TUNE_1,
45 LOOP_TUNE_2
46};
47
48enum dib8000_autosearch_step {
49 AS_START = 0,
50 AS_SEARCHING_FFT,
51 AS_SEARCHING_GUARD,
52 AS_DONE = 100,
53};
54
55enum timeout_mode {
56 SYMBOL_DEPENDENT_OFF = 0,
57 SYMBOL_DEPENDENT_ON,
58};
59
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -030060struct dib8000_state {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -030061 struct dib8000_config cfg;
62
63 struct i2c_device i2c;
64
65 struct dibx000_i2c_master i2c_master;
66
67 u16 wbd_ref;
68
69 u8 current_band;
70 u32 current_bandwidth;
71 struct dibx000_agc_config *current_agc;
72 u32 timf;
73 u32 timf_default;
74
75 u8 div_force_off:1;
76 u8 div_state:1;
77 u16 div_sync_wait;
78
79 u8 agc_state;
80 u8 differential_constellation;
81 u8 diversity_onoff;
82
83 s16 ber_monitored_layer;
84 u16 gpio_dir;
85 u16 gpio_val;
86
87 u16 revision;
88 u8 isdbt_cfg_loaded;
89 enum frontend_tune_state tune_state;
Patrick Boettcher173a64c2013-04-22 12:45:52 -030090 s32 status;
Olivier Grenie4c70e072011-01-03 15:33:37 -030091
92 struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
Olivier Grenie5a0deee2011-05-03 12:27:33 -030093
94 /* for the I2C transfer */
95 struct i2c_msg msg[2];
96 u8 i2c_write_buffer[4];
97 u8 i2c_read_buffer[2];
Patrick Boettcher79fcce32011-08-03 12:08:21 -030098 struct mutex i2c_buffer_lock;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -030099 u8 input_mode_mpeg;
100
101 u16 tuner_enable;
102 struct i2c_adapter dib8096p_tuner_adap;
Patrick Boettcher173a64c2013-04-22 12:45:52 -0300103 u16 current_demod_bw;
104
105 u16 seg_mask;
106 u16 seg_diff_mask;
107 u16 mode;
108 u8 layer_b_nb_seg;
109 u8 layer_c_nb_seg;
110
111 u8 channel_parameters_set;
112 u16 autosearch_state;
113 u16 found_nfft;
114 u16 found_guard;
115 u8 subchannel;
116 u8 symbol_duration;
117 u32 timeout;
118 u8 longest_intlv_layer;
119 u16 output_mode;
120
121#ifdef DIB8000_AGC_FREEZE
122 u16 agc1_max;
123 u16 agc1_min;
124 u16 agc2_max;
125 u16 agc2_min;
126#endif
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300127};
128
129enum dib8000_power_mode {
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300130 DIB8000_POWER_ALL = 0,
131 DIB8000_POWER_INTERFACE_ONLY,
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300132};
133
134static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg)
135{
Patrick Boettcher79fcce32011-08-03 12:08:21 -0300136 u16 ret;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300137 struct i2c_msg msg[2] = {
Patrick Boettcher79fcce32011-08-03 12:08:21 -0300138 {.addr = i2c->addr >> 1, .flags = 0, .len = 2},
139 {.addr = i2c->addr >> 1, .flags = I2C_M_RD, .len = 2},
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300140 };
141
Patrick Boettcher79fcce32011-08-03 12:08:21 -0300142 if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
143 dprintk("could not acquire lock");
144 return 0;
145 }
146
147 msg[0].buf = i2c->i2c_write_buffer;
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300148 msg[0].buf[0] = reg >> 8;
149 msg[0].buf[1] = reg & 0xff;
Patrick Boettcher79fcce32011-08-03 12:08:21 -0300150 msg[1].buf = i2c->i2c_read_buffer;
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300151
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300152 if (i2c_transfer(i2c->adap, msg, 2) != 2)
153 dprintk("i2c read error on %d", reg);
154
Patrick Boettcher79fcce32011-08-03 12:08:21 -0300155 ret = (msg[1].buf[0] << 8) | msg[1].buf[1];
156 mutex_unlock(i2c->i2c_buffer_lock);
157 return ret;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300158}
159
160static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
161{
Patrick Boettcher79fcce32011-08-03 12:08:21 -0300162 u16 ret;
163
164 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
165 dprintk("could not acquire lock");
166 return 0;
167 }
168
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300169 state->i2c_write_buffer[0] = reg >> 8;
170 state->i2c_write_buffer[1] = reg & 0xff;
171
172 memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
173 state->msg[0].addr = state->i2c.addr >> 1;
174 state->msg[0].flags = 0;
175 state->msg[0].buf = state->i2c_write_buffer;
176 state->msg[0].len = 2;
177 state->msg[1].addr = state->i2c.addr >> 1;
178 state->msg[1].flags = I2C_M_RD;
179 state->msg[1].buf = state->i2c_read_buffer;
180 state->msg[1].len = 2;
181
182 if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2)
183 dprintk("i2c read error on %d", reg);
184
Patrick Boettcher79fcce32011-08-03 12:08:21 -0300185 ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
186 mutex_unlock(&state->i2c_buffer_lock);
187
188 return ret;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300189}
190
191static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
192{
193 u16 rw[2];
194
195 rw[0] = dib8000_read_word(state, reg + 0);
196 rw[1] = dib8000_read_word(state, reg + 1);
197
198 return ((rw[0] << 16) | (rw[1]));
199}
200
201static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
202{
Patrick Boettcher79fcce32011-08-03 12:08:21 -0300203 struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, .len = 4};
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300204 int ret = 0;
205
Patrick Boettcher79fcce32011-08-03 12:08:21 -0300206 if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
207 dprintk("could not acquire lock");
208 return -EINVAL;
209 }
210
211 msg.buf = i2c->i2c_write_buffer;
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300212 msg.buf[0] = (reg >> 8) & 0xff;
213 msg.buf[1] = reg & 0xff;
214 msg.buf[2] = (val >> 8) & 0xff;
215 msg.buf[3] = val & 0xff;
216
217 ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
Patrick Boettcher79fcce32011-08-03 12:08:21 -0300218 mutex_unlock(i2c->i2c_buffer_lock);
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300219
220 return ret;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300221}
222
223static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val)
224{
Patrick Boettcher79fcce32011-08-03 12:08:21 -0300225 int ret;
226
227 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
228 dprintk("could not acquire lock");
229 return -EINVAL;
230 }
231
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300232 state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
233 state->i2c_write_buffer[1] = reg & 0xff;
234 state->i2c_write_buffer[2] = (val >> 8) & 0xff;
235 state->i2c_write_buffer[3] = val & 0xff;
236
237 memset(&state->msg[0], 0, sizeof(struct i2c_msg));
238 state->msg[0].addr = state->i2c.addr >> 1;
239 state->msg[0].flags = 0;
240 state->msg[0].buf = state->i2c_write_buffer;
241 state->msg[0].len = 4;
242
Patrick Boettcher79fcce32011-08-03 12:08:21 -0300243 ret = (i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ?
244 -EREMOTEIO : 0);
245 mutex_unlock(&state->i2c_buffer_lock);
246
247 return ret;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300248}
249
Olivier Grenie4c70e072011-01-03 15:33:37 -0300250static const s16 coeff_2k_sb_1seg_dqpsk[8] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300251 (769 << 5) | 0x0a, (745 << 5) | 0x03, (595 << 5) | 0x0d, (769 << 5) | 0x0a, (920 << 5) | 0x09, (784 << 5) | 0x02, (519 << 5) | 0x0c,
Olivier Grenie4c70e072011-01-03 15:33:37 -0300252 (920 << 5) | 0x09
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300253};
254
Olivier Grenie4c70e072011-01-03 15:33:37 -0300255static const s16 coeff_2k_sb_1seg[8] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300256 (692 << 5) | 0x0b, (683 << 5) | 0x01, (519 << 5) | 0x09, (692 << 5) | 0x0b, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f
257};
258
Olivier Grenie4c70e072011-01-03 15:33:37 -0300259static const s16 coeff_2k_sb_3seg_0dqpsk_1dqpsk[8] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300260 (832 << 5) | 0x10, (912 << 5) | 0x05, (900 << 5) | 0x12, (832 << 5) | 0x10, (-931 << 5) | 0x0f, (912 << 5) | 0x04, (807 << 5) | 0x11,
Olivier Grenie4c70e072011-01-03 15:33:37 -0300261 (-931 << 5) | 0x0f
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300262};
263
Olivier Grenie4c70e072011-01-03 15:33:37 -0300264static const s16 coeff_2k_sb_3seg_0dqpsk[8] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300265 (622 << 5) | 0x0c, (941 << 5) | 0x04, (796 << 5) | 0x10, (622 << 5) | 0x0c, (982 << 5) | 0x0c, (519 << 5) | 0x02, (572 << 5) | 0x0e,
Olivier Grenie4c70e072011-01-03 15:33:37 -0300266 (982 << 5) | 0x0c
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300267};
268
Olivier Grenie4c70e072011-01-03 15:33:37 -0300269static const s16 coeff_2k_sb_3seg_1dqpsk[8] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300270 (699 << 5) | 0x14, (607 << 5) | 0x04, (944 << 5) | 0x13, (699 << 5) | 0x14, (-720 << 5) | 0x0d, (640 << 5) | 0x03, (866 << 5) | 0x12,
Olivier Grenie4c70e072011-01-03 15:33:37 -0300271 (-720 << 5) | 0x0d
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300272};
273
Olivier Grenie4c70e072011-01-03 15:33:37 -0300274static const s16 coeff_2k_sb_3seg[8] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300275 (664 << 5) | 0x0c, (925 << 5) | 0x03, (937 << 5) | 0x10, (664 << 5) | 0x0c, (-610 << 5) | 0x0a, (697 << 5) | 0x01, (836 << 5) | 0x0e,
Olivier Grenie4c70e072011-01-03 15:33:37 -0300276 (-610 << 5) | 0x0a
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300277};
278
Olivier Grenie4c70e072011-01-03 15:33:37 -0300279static const s16 coeff_4k_sb_1seg_dqpsk[8] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300280 (-955 << 5) | 0x0e, (687 << 5) | 0x04, (818 << 5) | 0x10, (-955 << 5) | 0x0e, (-922 << 5) | 0x0d, (750 << 5) | 0x03, (665 << 5) | 0x0f,
Olivier Grenie4c70e072011-01-03 15:33:37 -0300281 (-922 << 5) | 0x0d
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300282};
283
Olivier Grenie4c70e072011-01-03 15:33:37 -0300284static const s16 coeff_4k_sb_1seg[8] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300285 (638 << 5) | 0x0d, (683 << 5) | 0x02, (638 << 5) | 0x0d, (638 << 5) | 0x0d, (-655 << 5) | 0x0a, (517 << 5) | 0x00, (698 << 5) | 0x0d,
Olivier Grenie4c70e072011-01-03 15:33:37 -0300286 (-655 << 5) | 0x0a
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300287};
288
Olivier Grenie4c70e072011-01-03 15:33:37 -0300289static const s16 coeff_4k_sb_3seg_0dqpsk_1dqpsk[8] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300290 (-707 << 5) | 0x14, (910 << 5) | 0x06, (889 << 5) | 0x16, (-707 << 5) | 0x14, (-958 << 5) | 0x13, (993 << 5) | 0x05, (523 << 5) | 0x14,
Olivier Grenie4c70e072011-01-03 15:33:37 -0300291 (-958 << 5) | 0x13
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300292};
293
Olivier Grenie4c70e072011-01-03 15:33:37 -0300294static const s16 coeff_4k_sb_3seg_0dqpsk[8] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300295 (-723 << 5) | 0x13, (910 << 5) | 0x05, (777 << 5) | 0x14, (-723 << 5) | 0x13, (-568 << 5) | 0x0f, (547 << 5) | 0x03, (696 << 5) | 0x12,
Olivier Grenie4c70e072011-01-03 15:33:37 -0300296 (-568 << 5) | 0x0f
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300297};
298
Olivier Grenie4c70e072011-01-03 15:33:37 -0300299static const s16 coeff_4k_sb_3seg_1dqpsk[8] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300300 (-940 << 5) | 0x15, (607 << 5) | 0x05, (915 << 5) | 0x16, (-940 << 5) | 0x15, (-848 << 5) | 0x13, (683 << 5) | 0x04, (543 << 5) | 0x14,
Olivier Grenie4c70e072011-01-03 15:33:37 -0300301 (-848 << 5) | 0x13
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300302};
303
Olivier Grenie4c70e072011-01-03 15:33:37 -0300304static const s16 coeff_4k_sb_3seg[8] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300305 (612 << 5) | 0x12, (910 << 5) | 0x04, (864 << 5) | 0x14, (612 << 5) | 0x12, (-869 << 5) | 0x13, (683 << 5) | 0x02, (869 << 5) | 0x12,
Olivier Grenie4c70e072011-01-03 15:33:37 -0300306 (-869 << 5) | 0x13
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300307};
308
Olivier Grenie4c70e072011-01-03 15:33:37 -0300309static const s16 coeff_8k_sb_1seg_dqpsk[8] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300310 (-835 << 5) | 0x12, (684 << 5) | 0x05, (735 << 5) | 0x14, (-835 << 5) | 0x12, (-598 << 5) | 0x10, (781 << 5) | 0x04, (739 << 5) | 0x13,
Olivier Grenie4c70e072011-01-03 15:33:37 -0300311 (-598 << 5) | 0x10
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300312};
313
Olivier Grenie4c70e072011-01-03 15:33:37 -0300314static const s16 coeff_8k_sb_1seg[8] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300315 (673 << 5) | 0x0f, (683 << 5) | 0x03, (808 << 5) | 0x12, (673 << 5) | 0x0f, (585 << 5) | 0x0f, (512 << 5) | 0x01, (780 << 5) | 0x0f,
Olivier Grenie4c70e072011-01-03 15:33:37 -0300316 (585 << 5) | 0x0f
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300317};
318
Olivier Grenie4c70e072011-01-03 15:33:37 -0300319static const s16 coeff_8k_sb_3seg_0dqpsk_1dqpsk[8] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300320 (863 << 5) | 0x17, (930 << 5) | 0x07, (878 << 5) | 0x19, (863 << 5) | 0x17, (0 << 5) | 0x14, (521 << 5) | 0x05, (980 << 5) | 0x18,
Olivier Grenie4c70e072011-01-03 15:33:37 -0300321 (0 << 5) | 0x14
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300322};
323
Olivier Grenie4c70e072011-01-03 15:33:37 -0300324static const s16 coeff_8k_sb_3seg_0dqpsk[8] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300325 (-924 << 5) | 0x17, (910 << 5) | 0x06, (774 << 5) | 0x17, (-924 << 5) | 0x17, (-877 << 5) | 0x15, (565 << 5) | 0x04, (553 << 5) | 0x15,
Olivier Grenie4c70e072011-01-03 15:33:37 -0300326 (-877 << 5) | 0x15
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300327};
328
Olivier Grenie4c70e072011-01-03 15:33:37 -0300329static const s16 coeff_8k_sb_3seg_1dqpsk[8] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300330 (-921 << 5) | 0x19, (607 << 5) | 0x06, (881 << 5) | 0x19, (-921 << 5) | 0x19, (-921 << 5) | 0x14, (713 << 5) | 0x05, (1018 << 5) | 0x18,
Olivier Grenie4c70e072011-01-03 15:33:37 -0300331 (-921 << 5) | 0x14
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300332};
333
Olivier Grenie4c70e072011-01-03 15:33:37 -0300334static const s16 coeff_8k_sb_3seg[8] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300335 (514 << 5) | 0x14, (910 << 5) | 0x05, (861 << 5) | 0x17, (514 << 5) | 0x14, (690 << 5) | 0x14, (683 << 5) | 0x03, (662 << 5) | 0x15,
Olivier Grenie4c70e072011-01-03 15:33:37 -0300336 (690 << 5) | 0x14
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300337};
338
Olivier Grenie4c70e072011-01-03 15:33:37 -0300339static const s16 ana_fe_coeff_3seg[24] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300340 81, 80, 78, 74, 68, 61, 54, 45, 37, 28, 19, 11, 4, 1022, 1017, 1013, 1010, 1008, 1008, 1008, 1008, 1010, 1014, 1017
341};
342
Olivier Grenie4c70e072011-01-03 15:33:37 -0300343static const s16 ana_fe_coeff_1seg[24] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300344 249, 226, 164, 82, 5, 981, 970, 988, 1018, 20, 31, 26, 8, 1012, 1000, 1018, 1012, 8, 15, 14, 9, 3, 1017, 1003
345};
346
Olivier Grenie4c70e072011-01-03 15:33:37 -0300347static const s16 ana_fe_coeff_13seg[24] = {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300348 396, 305, 105, -51, -77, -12, 41, 31, -11, -30, -11, 14, 15, -2, -13, -7, 5, 8, 1, -6, -7, -3, 0, 1
349};
350
351static u16 fft_to_mode(struct dib8000_state *state)
352{
353 u16 mode;
Olivier Grenie4c70e072011-01-03 15:33:37 -0300354 switch (state->fe[0]->dtv_property_cache.transmission_mode) {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300355 case TRANSMISSION_MODE_2K:
356 mode = 1;
357 break;
358 case TRANSMISSION_MODE_4K:
359 mode = 2;
360 break;
361 default:
362 case TRANSMISSION_MODE_AUTO:
363 case TRANSMISSION_MODE_8K:
364 mode = 3;
365 break;
366 }
367 return mode;
368}
369
370static void dib8000_set_acquisition_mode(struct dib8000_state *state)
371{
372 u16 nud = dib8000_read_word(state, 298);
373 nud |= (1 << 3) | (1 << 0);
374 dprintk("acquisition mode activated");
375 dib8000_write_word(state, 298, nud);
376}
Olivier Grenie4c70e072011-01-03 15:33:37 -0300377static int dib8000_set_output_mode(struct dvb_frontend *fe, int mode)
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300378{
Olivier Grenie4c70e072011-01-03 15:33:37 -0300379 struct dib8000_state *state = fe->demodulator_priv;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300380 u16 outreg, fifo_threshold, smo_mode, sram = 0x0205; /* by default SDRAM deintlv is enabled */
381
Patrick Boettcher173a64c2013-04-22 12:45:52 -0300382 state->output_mode = mode;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300383 outreg = 0;
384 fifo_threshold = 1792;
385 smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1);
386
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300387 dprintk("-I- Setting output mode for demod %p to %d",
388 &state->fe[0], mode);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300389
390 switch (mode) {
391 case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock
392 outreg = (1 << 10); /* 0x0400 */
393 break;
394 case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock
395 outreg = (1 << 10) | (1 << 6); /* 0x0440 */
396 break;
397 case OUTMODE_MPEG2_SERIAL: // STBs with serial input
398 outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */
399 break;
400 case OUTMODE_DIVERSITY:
401 if (state->cfg.hostbus_diversity) {
402 outreg = (1 << 10) | (4 << 6); /* 0x0500 */
403 sram &= 0xfdff;
404 } else
405 sram |= 0x0c00;
406 break;
407 case OUTMODE_MPEG2_FIFO: // e.g. USB feeding
408 smo_mode |= (3 << 1);
409 fifo_threshold = 512;
410 outreg = (1 << 10) | (5 << 6);
411 break;
412 case OUTMODE_HIGH_Z: // disable
413 outreg = 0;
414 break;
415
416 case OUTMODE_ANALOG_ADC:
417 outreg = (1 << 10) | (3 << 6);
418 dib8000_set_acquisition_mode(state);
419 break;
420
421 default:
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300422 dprintk("Unhandled output_mode passed to be set for demod %p",
423 &state->fe[0]);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300424 return -EINVAL;
425 }
426
427 if (state->cfg.output_mpeg2_in_188_bytes)
428 smo_mode |= (1 << 5);
429
430 dib8000_write_word(state, 299, smo_mode);
431 dib8000_write_word(state, 300, fifo_threshold); /* synchronous fread */
432 dib8000_write_word(state, 1286, outreg);
433 dib8000_write_word(state, 1291, sram);
434
435 return 0;
436}
437
438static int dib8000_set_diversity_in(struct dvb_frontend *fe, int onoff)
439{
440 struct dib8000_state *state = fe->demodulator_priv;
Patrick Boettcher173a64c2013-04-22 12:45:52 -0300441 u16 tmp, sync_wait = dib8000_read_word(state, 273) & 0xfff0;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300442
Patrick Boettcher173a64c2013-04-22 12:45:52 -0300443 dprintk("set diversity input to %i", onoff);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300444 if (!state->differential_constellation) {
445 dib8000_write_word(state, 272, 1 << 9); //dvsy_off_lmod4 = 1
446 dib8000_write_word(state, 273, sync_wait | (1 << 2) | 2); // sync_enable = 1; comb_mode = 2
447 } else {
448 dib8000_write_word(state, 272, 0); //dvsy_off_lmod4 = 0
449 dib8000_write_word(state, 273, sync_wait); // sync_enable = 0; comb_mode = 0
450 }
451 state->diversity_onoff = onoff;
452
453 switch (onoff) {
454 case 0: /* only use the internal way - not the diversity input */
455 dib8000_write_word(state, 270, 1);
456 dib8000_write_word(state, 271, 0);
457 break;
458 case 1: /* both ways */
459 dib8000_write_word(state, 270, 6);
460 dib8000_write_word(state, 271, 6);
461 break;
462 case 2: /* only the diversity input */
463 dib8000_write_word(state, 270, 0);
464 dib8000_write_word(state, 271, 1);
465 break;
466 }
Patrick Boettcher173a64c2013-04-22 12:45:52 -0300467
468 if (state->revision == 0x8002) {
469 tmp = dib8000_read_word(state, 903);
470 dib8000_write_word(state, 903, tmp & ~(1 << 3));
471 msleep(30);
472 dib8000_write_word(state, 903, tmp | (1 << 3));
473 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300474 return 0;
475}
476
477static void dib8000_set_power_mode(struct dib8000_state *state, enum dib8000_power_mode mode)
478{
479 /* by default everything is going to be powered off */
480 u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0xffff,
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300481 reg_900 = (dib8000_read_word(state, 900) & 0xfffc) | 0x3,
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300482 reg_1280;
483
484 if (state->revision != 0x8090)
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300485 reg_1280 = (dib8000_read_word(state, 1280) & 0x00ff) | 0xff00;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300486 else
487 reg_1280 = (dib8000_read_word(state, 1280) & 0x707f) | 0x8f80;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300488
489 /* now, depending on the requested mode, we power on */
490 switch (mode) {
491 /* power up everything in the demod */
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300492 case DIB8000_POWER_ALL:
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300493 reg_774 = 0x0000;
494 reg_775 = 0x0000;
495 reg_776 = 0x0000;
496 reg_900 &= 0xfffc;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300497 if (state->revision != 0x8090)
498 reg_1280 &= 0x00ff;
499 else
500 reg_1280 &= 0x707f;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300501 break;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300502 case DIB8000_POWER_INTERFACE_ONLY:
503 if (state->revision != 0x8090)
504 reg_1280 &= 0x00ff;
505 else
506 reg_1280 &= 0xfa7b;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300507 break;
508 }
509
510 dprintk("powermode : 774 : %x ; 775 : %x; 776 : %x ; 900 : %x; 1280 : %x", reg_774, reg_775, reg_776, reg_900, reg_1280);
511 dib8000_write_word(state, 774, reg_774);
512 dib8000_write_word(state, 775, reg_775);
513 dib8000_write_word(state, 776, reg_776);
514 dib8000_write_word(state, 900, reg_900);
515 dib8000_write_word(state, 1280, reg_1280);
516}
517
518static int dib8000_set_adc_state(struct dib8000_state *state, enum dibx000_adc_states no)
519{
520 int ret = 0;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300521 u16 reg, reg_907 = dib8000_read_word(state, 907);
522 u16 reg_908 = dib8000_read_word(state, 908);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300523
524 switch (no) {
525 case DIBX000_SLOW_ADC_ON:
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300526 if (state->revision != 0x8090) {
527 reg_908 |= (1 << 1) | (1 << 0);
528 ret |= dib8000_write_word(state, 908, reg_908);
529 reg_908 &= ~(1 << 1);
530 } else {
531 reg = dib8000_read_word(state, 1925);
532 /* en_slowAdc = 1 & reset_sladc = 1 */
533 dib8000_write_word(state, 1925, reg |
534 (1<<4) | (1<<2));
535
536 /* read acces to make it works... strange ... */
537 reg = dib8000_read_word(state, 1925);
538 msleep(20);
539 /* en_slowAdc = 1 & reset_sladc = 0 */
540 dib8000_write_word(state, 1925, reg & ~(1<<4));
541
542 reg = dib8000_read_word(state, 921) & ~((0x3 << 14)
543 | (0x3 << 12));
544 /* ref = Vin1 => Vbg ; sel = Vin0 or Vin3 ;
545 (Vin2 = Vcm) */
546 dib8000_write_word(state, 921, reg | (1 << 14)
547 | (3 << 12));
548 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300549 break;
550
551 case DIBX000_SLOW_ADC_OFF:
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300552 if (state->revision == 0x8090) {
553 reg = dib8000_read_word(state, 1925);
554 /* reset_sladc = 1 en_slowAdc = 0 */
555 dib8000_write_word(state, 1925,
556 (reg & ~(1<<2)) | (1<<4));
557 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300558 reg_908 |= (1 << 1) | (1 << 0);
559 break;
560
561 case DIBX000_ADC_ON:
562 reg_907 &= 0x0fff;
563 reg_908 &= 0x0003;
564 break;
565
566 case DIBX000_ADC_OFF: // leave the VBG voltage on
567 reg_907 |= (1 << 14) | (1 << 13) | (1 << 12);
568 reg_908 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
569 break;
570
571 case DIBX000_VBG_ENABLE:
572 reg_907 &= ~(1 << 15);
573 break;
574
575 case DIBX000_VBG_DISABLE:
576 reg_907 |= (1 << 15);
577 break;
578
579 default:
580 break;
581 }
582
583 ret |= dib8000_write_word(state, 907, reg_907);
584 ret |= dib8000_write_word(state, 908, reg_908);
585
586 return ret;
587}
588
Olivier Grenie4c70e072011-01-03 15:33:37 -0300589static int dib8000_set_bandwidth(struct dvb_frontend *fe, u32 bw)
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300590{
Olivier Grenie4c70e072011-01-03 15:33:37 -0300591 struct dib8000_state *state = fe->demodulator_priv;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300592 u32 timf;
593
594 if (bw == 0)
595 bw = 6000;
596
597 if (state->timf == 0) {
598 dprintk("using default timf");
599 timf = state->timf_default;
600 } else {
601 dprintk("using updated timf");
602 timf = state->timf;
603 }
604
605 dib8000_write_word(state, 29, (u16) ((timf >> 16) & 0xffff));
606 dib8000_write_word(state, 30, (u16) ((timf) & 0xffff));
607
608 return 0;
609}
610
611static int dib8000_sad_calib(struct dib8000_state *state)
612{
Patrick Boettcher173a64c2013-04-22 12:45:52 -0300613 u8 sad_sel = 3;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300614
Patrick Boettcher173a64c2013-04-22 12:45:52 -0300615 if (state->revision == 0x8090) {
616 dib8000_write_word(state, 922, (sad_sel << 2));
617 dib8000_write_word(state, 923, 2048);
618
619 dib8000_write_word(state, 922, (sad_sel << 2) | 0x1);
620 dib8000_write_word(state, 922, (sad_sel << 2));
621 } else {
622 /* internal */
623 dib8000_write_word(state, 923, (0 << 1) | (0 << 0));
624 dib8000_write_word(state, 924, 776);
625
626 /* do the calibration */
627 dib8000_write_word(state, 923, (1 << 0));
628 dib8000_write_word(state, 923, (0 << 0));
629 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300630
631 msleep(1);
632 return 0;
633}
634
635int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
636{
637 struct dib8000_state *state = fe->demodulator_priv;
638 if (value > 4095)
639 value = 4095;
640 state->wbd_ref = value;
641 return dib8000_write_word(state, 106, value);
642}
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300643EXPORT_SYMBOL(dib8000_set_wbd_ref);
Patrick Boettcher173a64c2013-04-22 12:45:52 -0300644
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300645static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw)
646{
647 dprintk("ifreq: %d %x, inversion: %d", bw->ifreq, bw->ifreq, bw->ifreq >> 25);
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300648 if (state->revision != 0x8090) {
649 dib8000_write_word(state, 23,
650 (u16) (((bw->internal * 1000) >> 16) & 0xffff));
651 dib8000_write_word(state, 24,
652 (u16) ((bw->internal * 1000) & 0xffff));
653 } else {
654 dib8000_write_word(state, 23, (u16) (((bw->internal / 2 * 1000) >> 16) & 0xffff));
655 dib8000_write_word(state, 24,
656 (u16) ((bw->internal / 2 * 1000) & 0xffff));
657 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300658 dib8000_write_word(state, 27, (u16) ((bw->ifreq >> 16) & 0x01ff));
659 dib8000_write_word(state, 28, (u16) (bw->ifreq & 0xffff));
660 dib8000_write_word(state, 26, (u16) ((bw->ifreq >> 25) & 0x0003));
661
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300662 if (state->revision != 0x8090)
663 dib8000_write_word(state, 922, bw->sad_cfg);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300664}
665
666static void dib8000_reset_pll(struct dib8000_state *state)
667{
668 const struct dibx000_bandwidth_config *pll = state->cfg.pll;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300669 u16 clk_cfg1, reg;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300670
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300671 if (state->revision != 0x8090) {
672 dib8000_write_word(state, 901,
673 (pll->pll_prediv << 8) | (pll->pll_ratio << 0));
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300674
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300675 clk_cfg1 = (1 << 10) | (0 << 9) | (pll->IO_CLK_en_core << 8) |
676 (pll->bypclk_div << 5) | (pll->enable_refdiv << 4) |
677 (1 << 3) | (pll->pll_range << 1) |
678 (pll->pll_reset << 0);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300679
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300680 dib8000_write_word(state, 902, clk_cfg1);
681 clk_cfg1 = (clk_cfg1 & 0xfff7) | (pll->pll_bypass << 3);
682 dib8000_write_word(state, 902, clk_cfg1);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300683
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300684 dprintk("clk_cfg1: 0x%04x", clk_cfg1);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300685
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300686 /* smpl_cfg: P_refclksel=2, P_ensmplsel=1 nodivsmpl=1 */
687 if (state->cfg.pll->ADClkSrc == 0)
688 dib8000_write_word(state, 904,
689 (0 << 15) | (0 << 12) | (0 << 10) |
690 (pll->modulo << 8) |
691 (pll->ADClkSrc << 7) | (0 << 1));
692 else if (state->cfg.refclksel != 0)
693 dib8000_write_word(state, 904, (0 << 15) | (1 << 12) |
694 ((state->cfg.refclksel & 0x3) << 10) |
695 (pll->modulo << 8) |
696 (pll->ADClkSrc << 7) | (0 << 1));
697 else
698 dib8000_write_word(state, 904, (0 << 15) | (1 << 12) |
699 (3 << 10) | (pll->modulo << 8) |
700 (pll->ADClkSrc << 7) | (0 << 1));
701 } else {
702 dib8000_write_word(state, 1856, (!pll->pll_reset<<13) |
703 (pll->pll_range<<12) | (pll->pll_ratio<<6) |
704 (pll->pll_prediv));
705
706 reg = dib8000_read_word(state, 1857);
707 dib8000_write_word(state, 1857, reg|(!pll->pll_bypass<<15));
708
709 reg = dib8000_read_word(state, 1858); /* Force clk out pll /2 */
710 dib8000_write_word(state, 1858, reg | 1);
711
712 dib8000_write_word(state, 904, (pll->modulo << 8));
713 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300714
715 dib8000_reset_pll_common(state, pll);
716}
717
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300718int dib8000_update_pll(struct dvb_frontend *fe,
Patrick Boettcher173a64c2013-04-22 12:45:52 -0300719 struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio)
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300720{
721 struct dib8000_state *state = fe->demodulator_priv;
722 u16 reg_1857, reg_1856 = dib8000_read_word(state, 1856);
Patrick Boettcher173a64c2013-04-22 12:45:52 -0300723 u8 loopdiv, prediv, oldprediv = state->cfg.pll->pll_prediv ;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300724 u32 internal, xtal;
725
726 /* get back old values */
727 prediv = reg_1856 & 0x3f;
728 loopdiv = (reg_1856 >> 6) & 0x3f;
729
Patrick Boettcher173a64c2013-04-22 12:45:52 -0300730 if ((pll == NULL) || (pll->pll_prediv == prediv &&
731 pll->pll_ratio == loopdiv))
732 return -EINVAL;
733
734 dprintk("Updating pll (prediv: old = %d new = %d ; loopdiv : old = %d new = %d)", prediv, pll->pll_prediv, loopdiv, pll->pll_ratio);
735 if (state->revision == 0x8090) {
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300736 reg_1856 &= 0xf000;
737 reg_1857 = dib8000_read_word(state, 1857);
738 /* disable PLL */
739 dib8000_write_word(state, 1857, reg_1857 & ~(1 << 15));
740
741 dib8000_write_word(state, 1856, reg_1856 |
742 ((pll->pll_ratio & 0x3f) << 6) |
743 (pll->pll_prediv & 0x3f));
744
745 /* write new system clk into P_sec_len */
746 internal = dib8000_read32(state, 23) / 1000;
747 dprintk("Old Internal = %d", internal);
748 xtal = 2 * (internal / loopdiv) * prediv;
749 internal = 1000 * (xtal/pll->pll_prediv) * pll->pll_ratio;
750 dprintk("Xtal = %d , New Fmem = %d New Fdemod = %d, New Fsampling = %d", xtal, internal/1000, internal/2000, internal/8000);
751 dprintk("New Internal = %d", internal);
752
753 dib8000_write_word(state, 23,
754 (u16) (((internal / 2) >> 16) & 0xffff));
755 dib8000_write_word(state, 24, (u16) ((internal / 2) & 0xffff));
756 /* enable PLL */
757 dib8000_write_word(state, 1857, reg_1857 | (1 << 15));
758
759 while (((dib8000_read_word(state, 1856)>>15)&0x1) != 1)
760 dprintk("Waiting for PLL to lock");
761
762 /* verify */
763 reg_1856 = dib8000_read_word(state, 1856);
764 dprintk("PLL Updated with prediv = %d and loopdiv = %d",
765 reg_1856&0x3f, (reg_1856>>6)&0x3f);
Patrick Boettcher173a64c2013-04-22 12:45:52 -0300766 } else {
767 if (bw != state->current_demod_bw) {
768 /** Bandwidth change => force PLL update **/
769 dprintk("PLL: Bandwidth Change %d MHz -> %d MHz (prediv: %d->%d)", state->current_demod_bw / 1000, bw / 1000, oldprediv, state->cfg.pll->pll_prediv);
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300770
Patrick Boettcher173a64c2013-04-22 12:45:52 -0300771 if (state->cfg.pll->pll_prediv != oldprediv) {
772 /** Full PLL change only if prediv is changed **/
773
774 /** full update => bypass and reconfigure **/
775 dprintk("PLL: New Setting for %d MHz Bandwidth (prediv: %d, ratio: %d)", bw/1000, state->cfg.pll->pll_prediv, state->cfg.pll->pll_ratio);
776 dib8000_write_word(state, 902, dib8000_read_word(state, 902) | (1<<3)); /* bypass PLL */
777 dib8000_reset_pll(state);
778 dib8000_write_word(state, 898, 0x0004); /* sad */
779 } else
780 ratio = state->cfg.pll->pll_ratio;
781
782 state->current_demod_bw = bw;
783 }
784
785 if (ratio != 0) {
786 /** ratio update => only change ratio **/
787 dprintk("PLL: Update ratio (prediv: %d, ratio: %d)", state->cfg.pll->pll_prediv, ratio);
788 dib8000_write_word(state, 901, (state->cfg.pll->pll_prediv << 8) | (ratio << 0)); /* only the PLL ratio is updated. */
789 }
790}
791
792 return 0;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300793}
794EXPORT_SYMBOL(dib8000_update_pll);
795
796
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300797static int dib8000_reset_gpio(struct dib8000_state *st)
798{
799 /* reset the GPIOs */
800 dib8000_write_word(st, 1029, st->cfg.gpio_dir);
801 dib8000_write_word(st, 1030, st->cfg.gpio_val);
802
803 /* TODO 782 is P_gpio_od */
804
805 dib8000_write_word(st, 1032, st->cfg.gpio_pwm_pos);
806
807 dib8000_write_word(st, 1037, st->cfg.pwm_freq_div);
808 return 0;
809}
810
811static int dib8000_cfg_gpio(struct dib8000_state *st, u8 num, u8 dir, u8 val)
812{
813 st->cfg.gpio_dir = dib8000_read_word(st, 1029);
814 st->cfg.gpio_dir &= ~(1 << num); /* reset the direction bit */
815 st->cfg.gpio_dir |= (dir & 0x1) << num; /* set the new direction */
816 dib8000_write_word(st, 1029, st->cfg.gpio_dir);
817
818 st->cfg.gpio_val = dib8000_read_word(st, 1030);
819 st->cfg.gpio_val &= ~(1 << num); /* reset the direction bit */
820 st->cfg.gpio_val |= (val & 0x01) << num; /* set the new value */
821 dib8000_write_word(st, 1030, st->cfg.gpio_val);
822
823 dprintk("gpio dir: %x: gpio val: %x", st->cfg.gpio_dir, st->cfg.gpio_val);
824
825 return 0;
826}
827
828int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
829{
830 struct dib8000_state *state = fe->demodulator_priv;
831 return dib8000_cfg_gpio(state, num, dir, val);
832}
833
834EXPORT_SYMBOL(dib8000_set_gpio);
835static const u16 dib8000_defaults[] = {
836 /* auto search configuration - lock0 by default waiting
837 * for cpil_lock; lock1 cpil_lock; lock2 tmcc_sync_lock */
838 3, 7,
839 0x0004,
840 0x0400,
841 0x0814,
842
843 12, 11,
844 0x001b,
845 0x7740,
846 0x005b,
847 0x8d80,
848 0x01c9,
849 0xc380,
850 0x0000,
851 0x0080,
852 0x0000,
853 0x0090,
854 0x0001,
855 0xd4c0,
856
857 /*1, 32,
Olivier Grenie4c70e072011-01-03 15:33:37 -0300858 0x6680 // P_corm_thres Lock algorithms configuration */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300859
860 11, 80, /* set ADC level to -16 */
861 (1 << 13) - 825 - 117,
862 (1 << 13) - 837 - 117,
863 (1 << 13) - 811 - 117,
864 (1 << 13) - 766 - 117,
865 (1 << 13) - 737 - 117,
866 (1 << 13) - 693 - 117,
867 (1 << 13) - 648 - 117,
868 (1 << 13) - 619 - 117,
869 (1 << 13) - 575 - 117,
870 (1 << 13) - 531 - 117,
871 (1 << 13) - 501 - 117,
872
873 4, 108,
874 0,
875 0,
876 0,
877 0,
878
879 1, 175,
880 0x0410,
881 1, 179,
882 8192, // P_fft_nb_to_cut
883
884 6, 181,
885 0x2800, // P_coff_corthres_ ( 2k 4k 8k ) 0x2800
886 0x2800,
887 0x2800,
888 0x2800, // P_coff_cpilthres_ ( 2k 4k 8k ) 0x2800
889 0x2800,
890 0x2800,
891
892 2, 193,
893 0x0666, // P_pha3_thres
894 0x0000, // P_cti_use_cpe, P_cti_use_prog
895
896 2, 205,
897 0x200f, // P_cspu_regul, P_cspu_win_cut
898 0x000f, // P_des_shift_work
899
900 5, 215,
901 0x023d, // P_adp_regul_cnt
902 0x00a4, // P_adp_noise_cnt
903 0x00a4, // P_adp_regul_ext
904 0x7ff0, // P_adp_noise_ext
905 0x3ccc, // P_adp_fil
906
907 1, 230,
908 0x0000, // P_2d_byp_ti_num
909
910 1, 263,
911 0x800, //P_equal_thres_wgn
912
913 1, 268,
914 (2 << 9) | 39, // P_equal_ctrl_synchro, P_equal_speedmode
915
916 1, 270,
917 0x0001, // P_div_lock0_wait
918 1, 285,
919 0x0020, //p_fec_
920 1, 299,
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300921 0x0062, /* P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300922
923 1, 338,
924 (1 << 12) | // P_ctrl_corm_thres4pre_freq_inh=1
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300925 (1 << 10) |
926 (0 << 9) | /* P_ctrl_pre_freq_inh=0 */
927 (3 << 5) | /* P_ctrl_pre_freq_step=3 */
928 (1 << 0), /* P_pre_freq_win_len=1 */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300929
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300930 0,
931};
932
933static u16 dib8000_identify(struct i2c_device *client)
934{
935 u16 value;
936
937 //because of glitches sometimes
938 value = dib8000_i2c_read16(client, 896);
939
940 if ((value = dib8000_i2c_read16(client, 896)) != 0x01b3) {
941 dprintk("wrong Vendor ID (read=0x%x)", value);
942 return 0;
943 }
944
945 value = dib8000_i2c_read16(client, 897);
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300946 if (value != 0x8000 && value != 0x8001 &&
947 value != 0x8002 && value != 0x8090) {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300948 dprintk("wrong Device ID (%x)", value);
949 return 0;
950 }
951
952 switch (value) {
953 case 0x8000:
954 dprintk("found DiB8000A");
955 break;
956 case 0x8001:
957 dprintk("found DiB8000B");
958 break;
959 case 0x8002:
960 dprintk("found DiB8000C");
961 break;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300962 case 0x8090:
963 dprintk("found DiB8096P");
964 break;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300965 }
966 return value;
967}
968
969static int dib8000_reset(struct dvb_frontend *fe)
970{
971 struct dib8000_state *state = fe->demodulator_priv;
972
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300973 if ((state->revision = dib8000_identify(&state->i2c)) == 0)
974 return -EINVAL;
975
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300976 /* sram lead in, rdy */
977 if (state->revision != 0x8090)
978 dib8000_write_word(state, 1287, 0x0003);
979
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300980 if (state->revision == 0x8000)
981 dprintk("error : dib8000 MA not supported");
982
983 dibx000_reset_i2c_master(&state->i2c_master);
984
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300985 dib8000_set_power_mode(state, DIB8000_POWER_ALL);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300986
987 /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */
Patrick Boettcher173a64c2013-04-22 12:45:52 -0300988 dib8000_set_adc_state(state, DIBX000_ADC_OFF);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300989
990 /* restart all parts */
991 dib8000_write_word(state, 770, 0xffff);
992 dib8000_write_word(state, 771, 0xffff);
993 dib8000_write_word(state, 772, 0xfffc);
Olivier Grenie0c32dbd2011-08-10 05:17:18 -0300994 if (state->revision == 0x8090)
995 dib8000_write_word(state, 1280, 0x0045);
996 else
997 dib8000_write_word(state, 1280, 0x004d);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -0300998 dib8000_write_word(state, 1281, 0x000c);
999
1000 dib8000_write_word(state, 770, 0x0000);
1001 dib8000_write_word(state, 771, 0x0000);
1002 dib8000_write_word(state, 772, 0x0000);
1003 dib8000_write_word(state, 898, 0x0004); // sad
1004 dib8000_write_word(state, 1280, 0x0000);
1005 dib8000_write_word(state, 1281, 0x0000);
1006
1007 /* drives */
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03001008 if (state->revision != 0x8090) {
1009 if (state->cfg.drives)
1010 dib8000_write_word(state, 906, state->cfg.drives);
1011 else {
1012 dprintk("using standard PAD-drive-settings, please adjust settings in config-struct to be optimal.");
1013 /* min drive SDRAM - not optimal - adjust */
1014 dib8000_write_word(state, 906, 0x2d98);
1015 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001016 }
1017
1018 dib8000_reset_pll(state);
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03001019 if (state->revision != 0x8090)
1020 dib8000_write_word(state, 898, 0x0004);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001021
1022 if (dib8000_reset_gpio(state) != 0)
1023 dprintk("GPIO reset was not successful.");
1024
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03001025 if ((state->revision != 0x8090) &&
1026 (dib8000_set_output_mode(fe, OUTMODE_HIGH_Z) != 0))
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001027 dprintk("OUTPUT_MODE could not be resetted.");
1028
1029 state->current_agc = NULL;
1030
1031 // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ...
1032 /* P_iqc_ca2 = 0; P_iqc_impnc_on = 0; P_iqc_mode = 0; */
1033 if (state->cfg.pll->ifreq == 0)
1034 dib8000_write_word(state, 40, 0x0755); /* P_iqc_corr_inh = 0 enable IQcorr block */
1035 else
1036 dib8000_write_word(state, 40, 0x1f55); /* P_iqc_corr_inh = 1 disable IQcorr block */
1037
1038 {
1039 u16 l = 0, r;
1040 const u16 *n;
1041 n = dib8000_defaults;
1042 l = *n++;
1043 while (l) {
1044 r = *n++;
1045 do {
1046 dib8000_write_word(state, r, *n++);
1047 r++;
1048 } while (--l);
1049 l = *n++;
1050 }
1051 }
Patrick Boettcher173a64c2013-04-22 12:45:52 -03001052
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001053 state->isdbt_cfg_loaded = 0;
1054
1055 //div_cfg override for special configs
Patrick Boettcher173a64c2013-04-22 12:45:52 -03001056 if ((state->revision != 8090) && (state->cfg.div_cfg != 0))
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001057 dib8000_write_word(state, 903, state->cfg.div_cfg);
1058
1059 /* unforce divstr regardless whether i2c enumeration was done or not */
1060 dib8000_write_word(state, 1285, dib8000_read_word(state, 1285) & ~(1 << 1));
1061
Olivier Grenie4c70e072011-01-03 15:33:37 -03001062 dib8000_set_bandwidth(fe, 6000);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001063
1064 dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON);
Patrick Boettcher173a64c2013-04-22 12:45:52 -03001065 dib8000_sad_calib(state);
1066 if (state->revision != 0x8090)
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03001067 dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
Patrick Boettcher173a64c2013-04-22 12:45:52 -03001068
1069 /* ber_rs_len = 3 */
1070 dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5));
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001071
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03001072 dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001073
1074 return 0;
1075}
1076
1077static void dib8000_restart_agc(struct dib8000_state *state)
1078{
1079 // P_restart_iqc & P_restart_agc
1080 dib8000_write_word(state, 770, 0x0a00);
1081 dib8000_write_word(state, 770, 0x0000);
1082}
1083
1084static int dib8000_update_lna(struct dib8000_state *state)
1085{
1086 u16 dyn_gain;
1087
1088 if (state->cfg.update_lna) {
1089 // read dyn_gain here (because it is demod-dependent and not tuner)
1090 dyn_gain = dib8000_read_word(state, 390);
1091
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001092 if (state->cfg.update_lna(state->fe[0], dyn_gain)) {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001093 dib8000_restart_agc(state);
1094 return 1;
1095 }
1096 }
1097 return 0;
1098}
1099
1100static int dib8000_set_agc_config(struct dib8000_state *state, u8 band)
1101{
1102 struct dibx000_agc_config *agc = NULL;
1103 int i;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03001104 u16 reg;
1105
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001106 if (state->current_band == band && state->current_agc != NULL)
1107 return 0;
1108 state->current_band = band;
1109
1110 for (i = 0; i < state->cfg.agc_config_count; i++)
1111 if (state->cfg.agc[i].band_caps & band) {
1112 agc = &state->cfg.agc[i];
1113 break;
1114 }
1115
1116 if (agc == NULL) {
1117 dprintk("no valid AGC configuration found for band 0x%02x", band);
1118 return -EINVAL;
1119 }
1120
1121 state->current_agc = agc;
1122
1123 /* AGC */
1124 dib8000_write_word(state, 76, agc->setup);
1125 dib8000_write_word(state, 77, agc->inv_gain);
1126 dib8000_write_word(state, 78, agc->time_stabiliz);
1127 dib8000_write_word(state, 101, (agc->alpha_level << 12) | agc->thlock);
1128
1129 // Demod AGC loop configuration
1130 dib8000_write_word(state, 102, (agc->alpha_mant << 5) | agc->alpha_exp);
1131 dib8000_write_word(state, 103, (agc->beta_mant << 6) | agc->beta_exp);
1132
1133 dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d",
1134 state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
1135
1136 /* AGC continued */
1137 if (state->wbd_ref != 0)
1138 dib8000_write_word(state, 106, state->wbd_ref);
1139 else // use default
1140 dib8000_write_word(state, 106, agc->wbd_ref);
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03001141
1142 if (state->revision == 0x8090) {
1143 reg = dib8000_read_word(state, 922) & (0x3 << 2);
1144 dib8000_write_word(state, 922, reg | (agc->wbd_sel << 2));
1145 }
1146
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001147 dib8000_write_word(state, 107, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8));
1148 dib8000_write_word(state, 108, agc->agc1_max);
1149 dib8000_write_word(state, 109, agc->agc1_min);
1150 dib8000_write_word(state, 110, agc->agc2_max);
1151 dib8000_write_word(state, 111, agc->agc2_min);
1152 dib8000_write_word(state, 112, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
1153 dib8000_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
1154 dib8000_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
1155 dib8000_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
1156
1157 dib8000_write_word(state, 75, agc->agc1_pt3);
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03001158 if (state->revision != 0x8090)
1159 dib8000_write_word(state, 923,
1160 (dib8000_read_word(state, 923) & 0xffe3) |
1161 (agc->wbd_inv << 4) | (agc->wbd_sel << 2));
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001162
1163 return 0;
1164}
1165
Olivier Grenie03245a52009-12-04 13:27:57 -03001166void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
1167{
1168 struct dib8000_state *state = fe->demodulator_priv;
1169 dib8000_set_adc_state(state, DIBX000_ADC_ON);
1170 dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000)));
1171}
1172EXPORT_SYMBOL(dib8000_pwm_agc_reset);
1173
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001174static int dib8000_agc_soft_split(struct dib8000_state *state)
1175{
1176 u16 agc, split_offset;
1177
1178 if (!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0)
1179 return FE_CALLBACK_TIME_NEVER;
1180
1181 // n_agc_global
1182 agc = dib8000_read_word(state, 390);
1183
1184 if (agc > state->current_agc->split.min_thres)
1185 split_offset = state->current_agc->split.min;
1186 else if (agc < state->current_agc->split.max_thres)
1187 split_offset = state->current_agc->split.max;
1188 else
1189 split_offset = state->current_agc->split.max *
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001190 (agc - state->current_agc->split.min_thres) /
1191 (state->current_agc->split.max_thres - state->current_agc->split.min_thres);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001192
1193 dprintk("AGC split_offset: %d", split_offset);
1194
1195 // P_agc_force_split and P_agc_split_offset
1196 dib8000_write_word(state, 107, (dib8000_read_word(state, 107) & 0xff00) | split_offset);
1197 return 5000;
1198}
1199
1200static int dib8000_agc_startup(struct dvb_frontend *fe)
1201{
1202 struct dib8000_state *state = fe->demodulator_priv;
1203 enum frontend_tune_state *tune_state = &state->tune_state;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001204 int ret = 0;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03001205 u16 reg, upd_demod_gain_period = 0x8000;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001206
1207 switch (*tune_state) {
1208 case CT_AGC_START:
1209 // set power-up level: interf+analog+AGC
1210
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03001211 if (state->revision != 0x8090)
1212 dib8000_set_adc_state(state, DIBX000_ADC_ON);
1213 else {
1214 dib8000_set_power_mode(state, DIB8000_POWER_ALL);
1215
1216 reg = dib8000_read_word(state, 1947)&0xff00;
1217 dib8000_write_word(state, 1946,
1218 upd_demod_gain_period & 0xFFFF);
1219 /* bit 14 = enDemodGain */
1220 dib8000_write_word(state, 1947, reg | (1<<14) |
1221 ((upd_demod_gain_period >> 16) & 0xFF));
1222
1223 /* enable adc i & q */
1224 reg = dib8000_read_word(state, 1920);
1225 dib8000_write_word(state, 1920, (reg | 0x3) &
1226 (~(1 << 7)));
1227 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001228
1229 if (dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000))) != 0) {
1230 *tune_state = CT_AGC_STOP;
1231 state->status = FE_STATUS_TUNE_FAILED;
1232 break;
1233 }
1234
1235 ret = 70;
1236 *tune_state = CT_AGC_STEP_0;
1237 break;
1238
1239 case CT_AGC_STEP_0:
1240 //AGC initialization
1241 if (state->cfg.agc_control)
Olivier Grenie4c70e072011-01-03 15:33:37 -03001242 state->cfg.agc_control(fe, 1);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001243
1244 dib8000_restart_agc(state);
1245
1246 // wait AGC rough lock time
1247 ret = 50;
1248 *tune_state = CT_AGC_STEP_1;
1249 break;
1250
1251 case CT_AGC_STEP_1:
1252 // wait AGC accurate lock time
1253 ret = 70;
1254
1255 if (dib8000_update_lna(state))
1256 // wait only AGC rough lock time
1257 ret = 50;
1258 else
1259 *tune_state = CT_AGC_STEP_2;
1260 break;
1261
1262 case CT_AGC_STEP_2:
1263 dib8000_agc_soft_split(state);
1264
1265 if (state->cfg.agc_control)
Olivier Grenie4c70e072011-01-03 15:33:37 -03001266 state->cfg.agc_control(fe, 0);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001267
1268 *tune_state = CT_AGC_STOP;
1269 break;
1270 default:
1271 ret = dib8000_agc_soft_split(state);
1272 break;
1273 }
1274 return ret;
1275
1276}
1277
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03001278static void dib8096p_host_bus_drive(struct dib8000_state *state, u8 drive)
1279{
1280 u16 reg;
1281
1282 drive &= 0x7;
1283
1284 /* drive host bus 2, 3, 4 */
1285 reg = dib8000_read_word(state, 1798) &
1286 ~(0x7 | (0x7 << 6) | (0x7 << 12));
1287 reg |= (drive<<12) | (drive<<6) | drive;
1288 dib8000_write_word(state, 1798, reg);
1289
1290 /* drive host bus 5,6 */
1291 reg = dib8000_read_word(state, 1799) & ~((0x7 << 2) | (0x7 << 8));
1292 reg |= (drive<<8) | (drive<<2);
1293 dib8000_write_word(state, 1799, reg);
1294
1295 /* drive host bus 7, 8, 9 */
1296 reg = dib8000_read_word(state, 1800) &
1297 ~(0x7 | (0x7 << 6) | (0x7 << 12));
1298 reg |= (drive<<12) | (drive<<6) | drive;
1299 dib8000_write_word(state, 1800, reg);
1300
1301 /* drive host bus 10, 11 */
1302 reg = dib8000_read_word(state, 1801) & ~((0x7 << 2) | (0x7 << 8));
1303 reg |= (drive<<8) | (drive<<2);
1304 dib8000_write_word(state, 1801, reg);
1305
1306 /* drive host bus 12, 13, 14 */
1307 reg = dib8000_read_word(state, 1802) &
1308 ~(0x7 | (0x7 << 6) | (0x7 << 12));
1309 reg |= (drive<<12) | (drive<<6) | drive;
1310 dib8000_write_word(state, 1802, reg);
1311}
1312
1313static u32 dib8096p_calcSyncFreq(u32 P_Kin, u32 P_Kout,
1314 u32 insertExtSynchro, u32 syncSize)
1315{
1316 u32 quantif = 3;
1317 u32 nom = (insertExtSynchro * P_Kin+syncSize);
1318 u32 denom = P_Kout;
1319 u32 syncFreq = ((nom << quantif) / denom);
1320
1321 if ((syncFreq & ((1 << quantif) - 1)) != 0)
1322 syncFreq = (syncFreq >> quantif) + 1;
1323 else
1324 syncFreq = (syncFreq >> quantif);
1325
1326 if (syncFreq != 0)
1327 syncFreq = syncFreq - 1;
1328
1329 return syncFreq;
1330}
1331
1332static void dib8096p_cfg_DibTx(struct dib8000_state *state, u32 P_Kin,
1333 u32 P_Kout, u32 insertExtSynchro, u32 synchroMode,
1334 u32 syncWord, u32 syncSize)
1335{
1336 dprintk("Configure DibStream Tx");
1337
1338 dib8000_write_word(state, 1615, 1);
1339 dib8000_write_word(state, 1603, P_Kin);
1340 dib8000_write_word(state, 1605, P_Kout);
1341 dib8000_write_word(state, 1606, insertExtSynchro);
1342 dib8000_write_word(state, 1608, synchroMode);
1343 dib8000_write_word(state, 1609, (syncWord >> 16) & 0xffff);
1344 dib8000_write_word(state, 1610, syncWord & 0xffff);
1345 dib8000_write_word(state, 1612, syncSize);
1346 dib8000_write_word(state, 1615, 0);
1347}
1348
1349static void dib8096p_cfg_DibRx(struct dib8000_state *state, u32 P_Kin,
1350 u32 P_Kout, u32 synchroMode, u32 insertExtSynchro,
1351 u32 syncWord, u32 syncSize, u32 dataOutRate)
1352{
1353 u32 syncFreq;
1354
1355 dprintk("Configure DibStream Rx synchroMode = %d", synchroMode);
1356
1357 if ((P_Kin != 0) && (P_Kout != 0)) {
1358 syncFreq = dib8096p_calcSyncFreq(P_Kin, P_Kout,
1359 insertExtSynchro, syncSize);
1360 dib8000_write_word(state, 1542, syncFreq);
1361 }
1362
1363 dib8000_write_word(state, 1554, 1);
1364 dib8000_write_word(state, 1536, P_Kin);
1365 dib8000_write_word(state, 1537, P_Kout);
1366 dib8000_write_word(state, 1539, synchroMode);
1367 dib8000_write_word(state, 1540, (syncWord >> 16) & 0xffff);
1368 dib8000_write_word(state, 1541, syncWord & 0xffff);
1369 dib8000_write_word(state, 1543, syncSize);
1370 dib8000_write_word(state, 1544, dataOutRate);
1371 dib8000_write_word(state, 1554, 0);
1372}
1373
1374static void dib8096p_enMpegMux(struct dib8000_state *state, int onoff)
1375{
1376 u16 reg_1287;
1377
1378 reg_1287 = dib8000_read_word(state, 1287);
1379
1380 switch (onoff) {
1381 case 1:
1382 reg_1287 &= ~(1 << 8);
1383 break;
1384 case 0:
1385 reg_1287 |= (1 << 8);
1386 break;
1387 }
1388
1389 dib8000_write_word(state, 1287, reg_1287);
1390}
1391
1392static void dib8096p_configMpegMux(struct dib8000_state *state,
1393 u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2)
1394{
1395 u16 reg_1287;
1396
1397 dprintk("Enable Mpeg mux");
1398
1399 dib8096p_enMpegMux(state, 0);
1400
1401 /* If the input mode is MPEG do not divide the serial clock */
1402 if ((enSerialMode == 1) && (state->input_mode_mpeg == 1))
1403 enSerialClkDiv2 = 0;
1404
1405 reg_1287 = ((pulseWidth & 0x1f) << 3) |
1406 ((enSerialMode & 0x1) << 2) | (enSerialClkDiv2 & 0x1);
1407 dib8000_write_word(state, 1287, reg_1287);
1408
1409 dib8096p_enMpegMux(state, 1);
1410}
1411
1412static void dib8096p_setDibTxMux(struct dib8000_state *state, int mode)
1413{
1414 u16 reg_1288 = dib8000_read_word(state, 1288) & ~(0x7 << 7);
1415
1416 switch (mode) {
1417 case MPEG_ON_DIBTX:
1418 dprintk("SET MPEG ON DIBSTREAM TX");
1419 dib8096p_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
1420 reg_1288 |= (1 << 9); break;
1421 case DIV_ON_DIBTX:
1422 dprintk("SET DIV_OUT ON DIBSTREAM TX");
1423 dib8096p_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
1424 reg_1288 |= (1 << 8); break;
1425 case ADC_ON_DIBTX:
1426 dprintk("SET ADC_OUT ON DIBSTREAM TX");
1427 dib8096p_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
1428 reg_1288 |= (1 << 7); break;
1429 default:
1430 break;
1431 }
1432 dib8000_write_word(state, 1288, reg_1288);
1433}
1434
1435static void dib8096p_setHostBusMux(struct dib8000_state *state, int mode)
1436{
1437 u16 reg_1288 = dib8000_read_word(state, 1288) & ~(0x7 << 4);
1438
1439 switch (mode) {
1440 case DEMOUT_ON_HOSTBUS:
1441 dprintk("SET DEM OUT OLD INTERF ON HOST BUS");
1442 dib8096p_enMpegMux(state, 0);
1443 reg_1288 |= (1 << 6);
1444 break;
1445 case DIBTX_ON_HOSTBUS:
1446 dprintk("SET DIBSTREAM TX ON HOST BUS");
1447 dib8096p_enMpegMux(state, 0);
1448 reg_1288 |= (1 << 5);
1449 break;
1450 case MPEG_ON_HOSTBUS:
1451 dprintk("SET MPEG MUX ON HOST BUS");
1452 reg_1288 |= (1 << 4);
1453 break;
1454 default:
1455 break;
1456 }
1457 dib8000_write_word(state, 1288, reg_1288);
1458}
1459
1460static int dib8096p_set_diversity_in(struct dvb_frontend *fe, int onoff)
1461{
1462 struct dib8000_state *state = fe->demodulator_priv;
1463 u16 reg_1287;
1464
1465 switch (onoff) {
1466 case 0: /* only use the internal way - not the diversity input */
1467 dprintk("%s mode OFF : by default Enable Mpeg INPUT",
1468 __func__);
1469 /* outputRate = 8 */
1470 dib8096p_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0);
1471
1472 /* Do not divide the serial clock of MPEG MUX in
1473 SERIAL MODE in case input mode MPEG is used */
1474 reg_1287 = dib8000_read_word(state, 1287);
1475 /* enSerialClkDiv2 == 1 ? */
1476 if ((reg_1287 & 0x1) == 1) {
1477 /* force enSerialClkDiv2 = 0 */
1478 reg_1287 &= ~0x1;
1479 dib8000_write_word(state, 1287, reg_1287);
1480 }
1481 state->input_mode_mpeg = 1;
1482 break;
1483 case 1: /* both ways */
1484 case 2: /* only the diversity input */
1485 dprintk("%s ON : Enable diversity INPUT", __func__);
1486 dib8096p_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
1487 state->input_mode_mpeg = 0;
1488 break;
1489 }
1490
1491 dib8000_set_diversity_in(state->fe[0], onoff);
1492 return 0;
1493}
1494
1495static int dib8096p_set_output_mode(struct dvb_frontend *fe, int mode)
1496{
1497 struct dib8000_state *state = fe->demodulator_priv;
1498 u16 outreg, smo_mode, fifo_threshold;
1499 u8 prefer_mpeg_mux_use = 1;
1500 int ret = 0;
1501
Patrick Boettcher173a64c2013-04-22 12:45:52 -03001502 state->output_mode = mode;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03001503 dib8096p_host_bus_drive(state, 1);
1504
1505 fifo_threshold = 1792;
1506 smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1);
1507 outreg = dib8000_read_word(state, 1286) &
1508 ~((1 << 10) | (0x7 << 6) | (1 << 1));
1509
1510 switch (mode) {
1511 case OUTMODE_HIGH_Z:
1512 outreg = 0;
1513 break;
1514
1515 case OUTMODE_MPEG2_SERIAL:
1516 if (prefer_mpeg_mux_use) {
1517 dprintk("dib8096P setting output mode TS_SERIAL using Mpeg Mux");
1518 dib8096p_configMpegMux(state, 3, 1, 1);
1519 dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS);
1520 } else {/* Use Smooth block */
1521 dprintk("dib8096P setting output mode TS_SERIAL using Smooth bloc");
1522 dib8096p_setHostBusMux(state,
1523 DEMOUT_ON_HOSTBUS);
1524 outreg |= (2 << 6) | (0 << 1);
1525 }
1526 break;
1527
1528 case OUTMODE_MPEG2_PAR_GATED_CLK:
1529 if (prefer_mpeg_mux_use) {
1530 dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Mpeg Mux");
1531 dib8096p_configMpegMux(state, 2, 0, 0);
1532 dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS);
1533 } else { /* Use Smooth block */
1534 dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Smooth block");
1535 dib8096p_setHostBusMux(state,
1536 DEMOUT_ON_HOSTBUS);
1537 outreg |= (0 << 6);
1538 }
1539 break;
1540
1541 case OUTMODE_MPEG2_PAR_CONT_CLK: /* Using Smooth block only */
1542 dprintk("dib8096P setting output mode TS_PARALLEL_CONT using Smooth block");
1543 dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
1544 outreg |= (1 << 6);
1545 break;
1546
1547 case OUTMODE_MPEG2_FIFO:
1548 /* Using Smooth block because not supported
1549 by new Mpeg Mux bloc */
1550 dprintk("dib8096P setting output mode TS_FIFO using Smooth block");
1551 dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
1552 outreg |= (5 << 6);
1553 smo_mode |= (3 << 1);
1554 fifo_threshold = 512;
1555 break;
1556
1557 case OUTMODE_DIVERSITY:
1558 dprintk("dib8096P setting output mode MODE_DIVERSITY");
1559 dib8096p_setDibTxMux(state, DIV_ON_DIBTX);
1560 dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
1561 break;
1562
1563 case OUTMODE_ANALOG_ADC:
1564 dprintk("dib8096P setting output mode MODE_ANALOG_ADC");
1565 dib8096p_setDibTxMux(state, ADC_ON_DIBTX);
1566 dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
1567 break;
1568 }
1569
1570 if (mode != OUTMODE_HIGH_Z)
1571 outreg |= (1<<10);
1572
1573 dprintk("output_mpeg2_in_188_bytes = %d",
1574 state->cfg.output_mpeg2_in_188_bytes);
1575 if (state->cfg.output_mpeg2_in_188_bytes)
1576 smo_mode |= (1 << 5);
1577
1578 ret |= dib8000_write_word(state, 299, smo_mode);
1579 /* synchronous fread */
1580 ret |= dib8000_write_word(state, 299 + 1, fifo_threshold);
1581 ret |= dib8000_write_word(state, 1286, outreg);
1582
1583 return ret;
1584}
1585
1586static int map_addr_to_serpar_number(struct i2c_msg *msg)
1587{
1588 if (msg->buf[0] <= 15)
1589 msg->buf[0] -= 1;
1590 else if (msg->buf[0] == 17)
1591 msg->buf[0] = 15;
1592 else if (msg->buf[0] == 16)
1593 msg->buf[0] = 17;
1594 else if (msg->buf[0] == 19)
1595 msg->buf[0] = 16;
1596 else if (msg->buf[0] >= 21 && msg->buf[0] <= 25)
1597 msg->buf[0] -= 3;
1598 else if (msg->buf[0] == 28)
1599 msg->buf[0] = 23;
1600 else if (msg->buf[0] == 99)
1601 msg->buf[0] = 99;
1602 else
1603 return -EINVAL;
1604 return 0;
1605}
1606
1607static int dib8096p_tuner_write_serpar(struct i2c_adapter *i2c_adap,
1608 struct i2c_msg msg[], int num)
1609{
1610 struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
1611 u8 n_overflow = 1;
1612 u16 i = 1000;
1613 u16 serpar_num = msg[0].buf[0];
1614
1615 while (n_overflow == 1 && i) {
1616 n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1;
1617 i--;
1618 if (i == 0)
1619 dprintk("Tuner ITF: write busy (overflow)");
1620 }
1621 dib8000_write_word(state, 1985, (1 << 6) | (serpar_num & 0x3f));
1622 dib8000_write_word(state, 1986, (msg[0].buf[1] << 8) | msg[0].buf[2]);
1623
1624 return num;
1625}
1626
1627static int dib8096p_tuner_read_serpar(struct i2c_adapter *i2c_adap,
1628 struct i2c_msg msg[], int num)
1629{
1630 struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
1631 u8 n_overflow = 1, n_empty = 1;
1632 u16 i = 1000;
1633 u16 serpar_num = msg[0].buf[0];
1634 u16 read_word;
1635
1636 while (n_overflow == 1 && i) {
1637 n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1;
1638 i--;
1639 if (i == 0)
1640 dprintk("TunerITF: read busy (overflow)");
1641 }
1642 dib8000_write_word(state, 1985, (0<<6) | (serpar_num&0x3f));
1643
1644 i = 1000;
1645 while (n_empty == 1 && i) {
1646 n_empty = dib8000_read_word(state, 1984)&0x1;
1647 i--;
1648 if (i == 0)
1649 dprintk("TunerITF: read busy (empty)");
1650 }
1651
1652 read_word = dib8000_read_word(state, 1987);
1653 msg[1].buf[0] = (read_word >> 8) & 0xff;
1654 msg[1].buf[1] = (read_word) & 0xff;
1655
1656 return num;
1657}
1658
1659static int dib8096p_tuner_rw_serpar(struct i2c_adapter *i2c_adap,
1660 struct i2c_msg msg[], int num)
1661{
1662 if (map_addr_to_serpar_number(&msg[0]) == 0) {
1663 if (num == 1) /* write */
1664 return dib8096p_tuner_write_serpar(i2c_adap, msg, 1);
1665 else /* read */
1666 return dib8096p_tuner_read_serpar(i2c_adap, msg, 2);
1667 }
1668 return num;
1669}
1670
1671static int dib8096p_rw_on_apb(struct i2c_adapter *i2c_adap,
1672 struct i2c_msg msg[], int num, u16 apb_address)
1673{
1674 struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
1675 u16 word;
1676
1677 if (num == 1) { /* write */
1678 dib8000_write_word(state, apb_address,
1679 ((msg[0].buf[1] << 8) | (msg[0].buf[2])));
1680 } else {
1681 word = dib8000_read_word(state, apb_address);
1682 msg[1].buf[0] = (word >> 8) & 0xff;
1683 msg[1].buf[1] = (word) & 0xff;
1684 }
1685 return num;
1686}
1687
1688static int dib8096p_tuner_xfer(struct i2c_adapter *i2c_adap,
1689 struct i2c_msg msg[], int num)
1690{
1691 struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
1692 u16 apb_address = 0, word;
1693 int i = 0;
1694
1695 switch (msg[0].buf[0]) {
1696 case 0x12:
1697 apb_address = 1920;
1698 break;
1699 case 0x14:
1700 apb_address = 1921;
1701 break;
1702 case 0x24:
1703 apb_address = 1922;
1704 break;
1705 case 0x1a:
1706 apb_address = 1923;
1707 break;
1708 case 0x22:
1709 apb_address = 1924;
1710 break;
1711 case 0x33:
1712 apb_address = 1926;
1713 break;
1714 case 0x34:
1715 apb_address = 1927;
1716 break;
1717 case 0x35:
1718 apb_address = 1928;
1719 break;
1720 case 0x36:
1721 apb_address = 1929;
1722 break;
1723 case 0x37:
1724 apb_address = 1930;
1725 break;
1726 case 0x38:
1727 apb_address = 1931;
1728 break;
1729 case 0x39:
1730 apb_address = 1932;
1731 break;
1732 case 0x2a:
1733 apb_address = 1935;
1734 break;
1735 case 0x2b:
1736 apb_address = 1936;
1737 break;
1738 case 0x2c:
1739 apb_address = 1937;
1740 break;
1741 case 0x2d:
1742 apb_address = 1938;
1743 break;
1744 case 0x2e:
1745 apb_address = 1939;
1746 break;
1747 case 0x2f:
1748 apb_address = 1940;
1749 break;
1750 case 0x30:
1751 apb_address = 1941;
1752 break;
1753 case 0x31:
1754 apb_address = 1942;
1755 break;
1756 case 0x32:
1757 apb_address = 1943;
1758 break;
1759 case 0x3e:
1760 apb_address = 1944;
1761 break;
1762 case 0x3f:
1763 apb_address = 1945;
1764 break;
1765 case 0x40:
1766 apb_address = 1948;
1767 break;
1768 case 0x25:
1769 apb_address = 936;
1770 break;
1771 case 0x26:
1772 apb_address = 937;
1773 break;
1774 case 0x27:
1775 apb_address = 938;
1776 break;
1777 case 0x28:
1778 apb_address = 939;
1779 break;
1780 case 0x1d:
1781 /* get sad sel request */
1782 i = ((dib8000_read_word(state, 921) >> 12)&0x3);
1783 word = dib8000_read_word(state, 924+i);
1784 msg[1].buf[0] = (word >> 8) & 0xff;
1785 msg[1].buf[1] = (word) & 0xff;
1786 return num;
1787 case 0x1f:
1788 if (num == 1) { /* write */
1789 word = (u16) ((msg[0].buf[1] << 8) |
1790 msg[0].buf[2]);
1791 /* in the VGAMODE Sel are located on bit 0/1 */
1792 word &= 0x3;
1793 word = (dib8000_read_word(state, 921) &
1794 ~(3<<12)) | (word<<12);
1795 /* Set the proper input */
1796 dib8000_write_word(state, 921, word);
1797 return num;
1798 }
1799 }
1800
1801 if (apb_address != 0) /* R/W acces via APB */
1802 return dib8096p_rw_on_apb(i2c_adap, msg, num, apb_address);
1803 else /* R/W access via SERPAR */
1804 return dib8096p_tuner_rw_serpar(i2c_adap, msg, num);
1805
1806 return 0;
1807}
1808
1809static u32 dib8096p_i2c_func(struct i2c_adapter *adapter)
1810{
1811 return I2C_FUNC_I2C;
1812}
1813
1814static struct i2c_algorithm dib8096p_tuner_xfer_algo = {
1815 .master_xfer = dib8096p_tuner_xfer,
1816 .functionality = dib8096p_i2c_func,
1817};
1818
1819struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
1820{
1821 struct dib8000_state *st = fe->demodulator_priv;
1822 return &st->dib8096p_tuner_adap;
1823}
1824EXPORT_SYMBOL(dib8096p_get_i2c_tuner);
1825
1826int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
1827{
1828 struct dib8000_state *state = fe->demodulator_priv;
1829 u16 en_cur_state;
1830
1831 dprintk("sleep dib8096p: %d", onoff);
1832
1833 en_cur_state = dib8000_read_word(state, 1922);
1834
1835 /* LNAs and MIX are ON and therefore it is a valid configuration */
1836 if (en_cur_state > 0xff)
1837 state->tuner_enable = en_cur_state ;
1838
1839 if (onoff)
1840 en_cur_state &= 0x00ff;
1841 else {
1842 if (state->tuner_enable != 0)
1843 en_cur_state = state->tuner_enable;
1844 }
1845
1846 dib8000_write_word(state, 1922, en_cur_state);
1847
1848 return 0;
1849}
1850EXPORT_SYMBOL(dib8096p_tuner_sleep);
1851
Olivier Grenie4c70e072011-01-03 15:33:37 -03001852static const s32 lut_1000ln_mant[] =
Olivier Grenie03245a52009-12-04 13:27:57 -03001853{
Olivier Grenie9c783032009-12-07 07:49:40 -03001854 908, 7003, 7090, 7170, 7244, 7313, 7377, 7438, 7495, 7549, 7600
Olivier Grenie03245a52009-12-04 13:27:57 -03001855};
1856
Olivier Grenie4c70e072011-01-03 15:33:37 -03001857s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
Olivier Grenie03245a52009-12-04 13:27:57 -03001858{
Olivier Grenie4c70e072011-01-03 15:33:37 -03001859 struct dib8000_state *state = fe->demodulator_priv;
1860 u32 ix = 0, tmp_val = 0, exp = 0, mant = 0;
1861 s32 val;
Olivier Grenie03245a52009-12-04 13:27:57 -03001862
Olivier Grenie4c70e072011-01-03 15:33:37 -03001863 val = dib8000_read32(state, 384);
Olivier Grenie4c70e072011-01-03 15:33:37 -03001864 if (mode) {
1865 tmp_val = val;
1866 while (tmp_val >>= 1)
1867 exp++;
1868 mant = (val * 1000 / (1<<exp));
1869 ix = (u8)((mant-1000)/100); /* index of the LUT */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001870 val = (lut_1000ln_mant[ix] + 693*(exp-20) - 6908);
Olivier Grenie4c70e072011-01-03 15:33:37 -03001871 val = (val*256)/1000;
1872 }
1873 return val;
Olivier Grenie03245a52009-12-04 13:27:57 -03001874}
1875EXPORT_SYMBOL(dib8000_get_adc_power);
1876
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03001877int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
1878{
1879 struct dib8000_state *state = fe->demodulator_priv;
1880 int val = 0;
1881
1882 switch (IQ) {
1883 case 1:
1884 val = dib8000_read_word(state, 403);
1885 break;
1886 case 0:
1887 val = dib8000_read_word(state, 404);
1888 break;
1889 }
1890 if (val & 0x200)
1891 val -= 1024;
1892
1893 return val;
1894}
1895EXPORT_SYMBOL(dib8090p_get_dc_power);
1896
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001897static void dib8000_update_timf(struct dib8000_state *state)
1898{
1899 u32 timf = state->timf = dib8000_read32(state, 435);
1900
1901 dib8000_write_word(state, 29, (u16) (timf >> 16));
1902 dib8000_write_word(state, 30, (u16) (timf & 0xffff));
1903 dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default);
1904}
1905
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03001906u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf)
1907{
1908 struct dib8000_state *state = fe->demodulator_priv;
1909
1910 switch (op) {
1911 case DEMOD_TIMF_SET:
1912 state->timf = timf;
1913 break;
1914 case DEMOD_TIMF_UPDATE:
1915 dib8000_update_timf(state);
1916 break;
1917 case DEMOD_TIMF_GET:
1918 break;
1919 }
1920 dib8000_set_bandwidth(state->fe[0], 6000);
1921
1922 return state->timf;
1923}
1924EXPORT_SYMBOL(dib8000_ctrl_timf);
1925
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001926static const u16 adc_target_16dB[11] = {
1927 (1 << 13) - 825 - 117,
1928 (1 << 13) - 837 - 117,
1929 (1 << 13) - 811 - 117,
1930 (1 << 13) - 766 - 117,
1931 (1 << 13) - 737 - 117,
1932 (1 << 13) - 693 - 117,
1933 (1 << 13) - 648 - 117,
1934 (1 << 13) - 619 - 117,
1935 (1 << 13) - 575 - 117,
1936 (1 << 13) - 531 - 117,
1937 (1 << 13) - 501 - 117
1938};
1939static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 };
1940
Patrick Boettcher173a64c2013-04-22 12:45:52 -03001941static u16 dib8000_set_layer(struct dib8000_state *state, u8 layer_index, u16 max_constellation)
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001942{
Patrick Boettcher173a64c2013-04-22 12:45:52 -03001943 u8 cr, constellation, time_intlv;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001944
Patrick Boettcher173a64c2013-04-22 12:45:52 -03001945 switch (state->fe[0]->dtv_property_cache.layer[layer_index].modulation) {
1946 case DQPSK:
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001947 constellation = 0;
1948 break;
Patrick Boettcher173a64c2013-04-22 12:45:52 -03001949 case QPSK:
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001950 constellation = 1;
1951 break;
Patrick Boettcher173a64c2013-04-22 12:45:52 -03001952 case QAM_16:
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001953 constellation = 2;
1954 break;
Patrick Boettcher173a64c2013-04-22 12:45:52 -03001955 case QAM_64:
1956 default:
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001957 constellation = 3;
1958 break;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001959 }
1960
Patrick Boettcher173a64c2013-04-22 12:45:52 -03001961 switch (state->fe[0]->dtv_property_cache.layer[layer_index].fec) {
1962 case FEC_1_2:
1963 cr = 1;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001964 break;
Patrick Boettcher173a64c2013-04-22 12:45:52 -03001965 case FEC_2_3:
1966 cr = 2;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001967 break;
Patrick Boettcher173a64c2013-04-22 12:45:52 -03001968 case FEC_3_4:
1969 cr = 3;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001970 break;
Patrick Boettcher173a64c2013-04-22 12:45:52 -03001971 case FEC_5_6:
1972 cr = 5;
1973 break;
1974 case FEC_7_8:
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001975 default:
Patrick Boettcher173a64c2013-04-22 12:45:52 -03001976 cr = 7;
1977 break;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001978 }
Patrick Boettcher173a64c2013-04-22 12:45:52 -03001979
1980 if ((state->fe[0]->dtv_property_cache.layer[layer_index].interleaving > 0) && ((state->fe[0]->dtv_property_cache.layer[layer_index].interleaving <= 3) || (state->fe[0]->dtv_property_cache.layer[layer_index].interleaving == 4 && state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1)))
1981 time_intlv = state->fe[0]->dtv_property_cache.layer[layer_index].interleaving;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03001982 else
Patrick Boettcher173a64c2013-04-22 12:45:52 -03001983 time_intlv = 0;
1984
1985 dib8000_write_word(state, 2 + layer_index, (constellation << 10) | ((state->fe[0]->dtv_property_cache.layer[layer_index].segment_count & 0xf) << 6) | (cr << 3) | time_intlv);
1986 if (state->fe[0]->dtv_property_cache.layer[layer_index].segment_count > 0) {
1987 switch (max_constellation) {
1988 case DQPSK:
1989 case QPSK:
1990 if (state->fe[0]->dtv_property_cache.layer[layer_index].modulation == QAM_16 || state->fe[0]->dtv_property_cache.layer[layer_index].modulation == QAM_64)
1991 max_constellation = state->fe[0]->dtv_property_cache.layer[layer_index].modulation;
1992 break;
1993 case QAM_16:
1994 if (state->fe[0]->dtv_property_cache.layer[layer_index].modulation == QAM_64)
1995 max_constellation = state->fe[0]->dtv_property_cache.layer[layer_index].modulation;
1996 break;
1997 }
1998 }
1999
2000 return max_constellation;
2001}
2002
2003static const u16 adp_Q64[4] = {0x0148, 0xfff0, 0x00a4, 0xfff8}; /* P_adp_regul_cnt 0.04, P_adp_noise_cnt -0.002, P_adp_regul_ext 0.02, P_adp_noise_ext -0.001 */
2004static const u16 adp_Q16[4] = {0x023d, 0xffdf, 0x00a4, 0xfff0}; /* P_adp_regul_cnt 0.07, P_adp_noise_cnt -0.004, P_adp_regul_ext 0.02, P_adp_noise_ext -0.002 */
2005static const u16 adp_Qdefault[4] = {0x099a, 0xffae, 0x0333, 0xfff8}; /* P_adp_regul_cnt 0.3, P_adp_noise_cnt -0.01, P_adp_regul_ext 0.1, P_adp_noise_ext -0.002 */
2006static u16 dib8000_adp_fine_tune(struct dib8000_state *state, u16 max_constellation)
2007{
2008 u16 i, ana_gain = 0;
2009 const u16 *adp;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002010
2011 /* channel estimation fine configuration */
2012 switch (max_constellation) {
2013 case QAM_64:
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002014 ana_gain = 0x7;
2015 adp = &adp_Q64[0];
2016 break;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002017 case QAM_16:
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002018 ana_gain = 0x7;
2019 adp = &adp_Q16[0];
2020 break;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002021 default:
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002022 ana_gain = 0;
2023 adp = &adp_Qdefault[0];
2024 break;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002025 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002026
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002027 for (i = 0; i < 4; i++)
2028 dib8000_write_word(state, 215 + i, adp[i]);
2029
2030 return ana_gain;
2031}
2032
2033static void dib8000_update_ana_gain(struct dib8000_state *state, u16 ana_gain)
2034{
2035 u16 i;
2036
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002037 dib8000_write_word(state, 116, ana_gain);
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002038
2039 /* update ADC target depending on ana_gain */
2040 if (ana_gain) { /* set -16dB ADC target for ana_gain=-1 */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002041 for (i = 0; i < 10; i++)
2042 dib8000_write_word(state, 80 + i, adc_target_16dB[i]);
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002043 } else { /* set -22dB ADC target for ana_gain=0 */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002044 for (i = 0; i < 10; i++)
2045 dib8000_write_word(state, 80 + i, adc_target_16dB[i] - 355);
2046 }
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002047}
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002048
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002049static void dib8000_load_ana_fe_coefs(struct dib8000_state *state, const s16 *ana_fe)
2050{
2051 u16 mode = 0;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002052
2053 if (state->isdbt_cfg_loaded == 0)
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002054 for (mode = 0; mode < 24; mode++)
2055 dib8000_write_word(state, 117 + mode, ana_fe[mode]);
2056}
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002057
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002058static const u16 lut_prbs_2k[14] = {
2059 0, 0x423, 0x009, 0x5C7, 0x7A6, 0x3D8, 0x527, 0x7FF, 0x79B, 0x3D6, 0x3A2, 0x53B, 0x2F4, 0x213
2060};
2061static const u16 lut_prbs_4k[14] = {
2062 0, 0x208, 0x0C3, 0x7B9, 0x423, 0x5C7, 0x3D8, 0x7FF, 0x3D6, 0x53B, 0x213, 0x029, 0x0D0, 0x48E
2063};
2064static const u16 lut_prbs_8k[14] = {
2065 0, 0x740, 0x069, 0x7DD, 0x208, 0x7B9, 0x5C7, 0x7FF, 0x53B, 0x029, 0x48E, 0x4C4, 0x367, 0x684
2066};
2067
2068static u16 dib8000_get_init_prbs(struct dib8000_state *state, u16 subchannel)
2069{
2070 int sub_channel_prbs_group = 0;
2071
2072 sub_channel_prbs_group = (subchannel / 3) + 1;
2073 dprintk("sub_channel_prbs_group = %d , subchannel =%d prbs = 0x%04x", sub_channel_prbs_group, subchannel, lut_prbs_8k[sub_channel_prbs_group]);
2074
2075 switch (state->fe[0]->dtv_property_cache.transmission_mode) {
2076 case TRANSMISSION_MODE_2K:
2077 return lut_prbs_2k[sub_channel_prbs_group];
2078 case TRANSMISSION_MODE_4K:
2079 return lut_prbs_4k[sub_channel_prbs_group];
2080 default:
2081 case TRANSMISSION_MODE_8K:
2082 return lut_prbs_8k[sub_channel_prbs_group];
2083 }
2084}
2085
2086static void dib8000_set_13seg_channel(struct dib8000_state *state)
2087{
2088 u16 i;
2089 u16 coff_pow = 0x2800;
2090
2091 state->seg_mask = 0x1fff; /* All 13 segments enabled */
2092
2093 /* ---- COFF ---- Carloff, the most robust --- */
2094 if (state->isdbt_cfg_loaded == 0) { /* if not Sound Broadcasting mode : put default values for 13 segments */
2095 dib8000_write_word(state, 180, (16 << 6) | 9);
2096 dib8000_write_word(state, 187, (4 << 12) | (8 << 5) | 0x2);
2097 coff_pow = 0x2800;
2098 for (i = 0; i < 6; i++)
2099 dib8000_write_word(state, 181+i, coff_pow);
2100
2101 /* P_ctrl_corm_thres4pre_freq_inh=1, P_ctrl_pre_freq_mode_sat=1 */
2102 /* P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 3, P_pre_freq_win_len=1 */
2103 dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (3 << 5) | 1);
2104
2105 /* P_ctrl_pre_freq_win_len=8, P_ctrl_pre_freq_thres_lockin=6 */
2106 dib8000_write_word(state, 340, (8 << 6) | (6 << 0));
2107 /* P_ctrl_pre_freq_thres_lockout=4, P_small_use_tmcc/ac/cp=1 */
2108 dib8000_write_word(state, 341, (4 << 3) | (1 << 2) | (1 << 1) | (1 << 0));
2109
2110 dib8000_write_word(state, 228, 0); /* default value */
2111 dib8000_write_word(state, 265, 31); /* default value */
2112 dib8000_write_word(state, 205, 0x200f); /* init value */
2113 }
2114
2115 /*
2116 * make the cpil_coff_lock more robust but slower p_coff_winlen
2117 * 6bits; p_coff_thres_lock 6bits (for coff lock if needed)
2118 */
2119
2120 if (state->cfg.pll->ifreq == 0)
2121 dib8000_write_word(state, 266, ~state->seg_mask | state->seg_diff_mask | 0x40); /* P_equal_noise_seg_inh */
2122
2123 dib8000_load_ana_fe_coefs(state, ana_fe_coeff_13seg);
2124}
2125
2126static void dib8000_set_subchannel_prbs(struct dib8000_state *state, u16 init_prbs)
2127{
2128 u16 reg_1;
2129
2130 reg_1 = dib8000_read_word(state, 1);
2131 dib8000_write_word(state, 1, (init_prbs << 2) | (reg_1 & 0x3)); /* ADDR 1 */
2132}
2133
2134static void dib8000_small_fine_tune(struct dib8000_state *state)
2135{
2136 u16 i;
2137 const s16 *ncoeff;
2138
2139 dib8000_write_word(state, 352, state->seg_diff_mask);
2140 dib8000_write_word(state, 353, state->seg_mask);
2141
2142 /* P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5 */
2143 dib8000_write_word(state, 351, (state->fe[0]->dtv_property_cache.isdbt_sb_mode << 9) | (state->fe[0]->dtv_property_cache.isdbt_sb_mode << 8) | (13 << 4) | 5);
2144
2145 if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
2146 /* ---- SMALL ---- */
2147 switch (state->fe[0]->dtv_property_cache.transmission_mode) {
2148 case TRANSMISSION_MODE_2K:
2149 if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { /* 1-seg */
2150 if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) /* DQPSK */
2151 ncoeff = coeff_2k_sb_1seg_dqpsk;
2152 else /* QPSK or QAM */
2153 ncoeff = coeff_2k_sb_1seg;
2154 } else { /* 3-segments */
2155 if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) { /* DQPSK on central segment */
2156 if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) /* DQPSK on external segments */
2157 ncoeff = coeff_2k_sb_3seg_0dqpsk_1dqpsk;
2158 else /* QPSK or QAM on external segments */
2159 ncoeff = coeff_2k_sb_3seg_0dqpsk;
2160 } else { /* QPSK or QAM on central segment */
2161 if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) /* DQPSK on external segments */
2162 ncoeff = coeff_2k_sb_3seg_1dqpsk;
2163 else /* QPSK or QAM on external segments */
2164 ncoeff = coeff_2k_sb_3seg;
2165 }
2166 }
2167 break;
2168 case TRANSMISSION_MODE_4K:
2169 if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { /* 1-seg */
2170 if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) /* DQPSK */
2171 ncoeff = coeff_4k_sb_1seg_dqpsk;
2172 else /* QPSK or QAM */
2173 ncoeff = coeff_4k_sb_1seg;
2174 } else { /* 3-segments */
2175 if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) { /* DQPSK on central segment */
2176 if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) /* DQPSK on external segments */
2177 ncoeff = coeff_4k_sb_3seg_0dqpsk_1dqpsk;
2178 else /* QPSK or QAM on external segments */
2179 ncoeff = coeff_4k_sb_3seg_0dqpsk;
2180 } else { /* QPSK or QAM on central segment */
2181 if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) /* DQPSK on external segments */
2182 ncoeff = coeff_4k_sb_3seg_1dqpsk;
2183 else /* QPSK or QAM on external segments */
2184 ncoeff = coeff_4k_sb_3seg;
2185 }
2186 }
2187 break;
2188 case TRANSMISSION_MODE_AUTO:
2189 case TRANSMISSION_MODE_8K:
2190 default:
2191 if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { /* 1-seg */
2192 if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) /* DQPSK */
2193 ncoeff = coeff_8k_sb_1seg_dqpsk;
2194 else /* QPSK or QAM */
2195 ncoeff = coeff_8k_sb_1seg;
2196 } else { /* 3-segments */
2197 if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) { /* DQPSK on central segment */
2198 if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) /* DQPSK on external segments */
2199 ncoeff = coeff_8k_sb_3seg_0dqpsk_1dqpsk;
2200 else /* QPSK or QAM on external segments */
2201 ncoeff = coeff_8k_sb_3seg_0dqpsk;
2202 } else { /* QPSK or QAM on central segment */
2203 if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) /* DQPSK on external segments */
2204 ncoeff = coeff_8k_sb_3seg_1dqpsk;
2205 else /* QPSK or QAM on external segments */
2206 ncoeff = coeff_8k_sb_3seg;
2207 }
2208 }
2209 break;
2210 }
2211
2212 for (i = 0; i < 8; i++)
2213 dib8000_write_word(state, 343 + i, ncoeff[i]);
2214 }
2215}
2216
2217static const u16 coff_thres_1seg[3] = {300, 150, 80};
2218static const u16 coff_thres_3seg[3] = {350, 300, 250};
2219static void dib8000_set_sb_channel(struct dib8000_state *state)
2220{
2221 const u16 *coff;
2222 u16 i;
2223
2224 if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K || state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_4K) {
2225 dib8000_write_word(state, 219, dib8000_read_word(state, 219) | 0x1); /* adp_pass =1 */
2226 dib8000_write_word(state, 190, dib8000_read_word(state, 190) | (0x1 << 14)); /* pha3_force_pha_shift = 1 */
2227 } else {
2228 dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); /* adp_pass =0 */
2229 dib8000_write_word(state, 190, dib8000_read_word(state, 190) & 0xbfff); /* pha3_force_pha_shift = 0 */
2230 }
2231
2232 if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1) /* 3-segments */
2233 state->seg_mask = 0x00E0;
2234 else /* 1-segment */
2235 state->seg_mask = 0x0040;
2236
2237 dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200);
2238
2239 /* ---- COFF ---- Carloff, the most robust --- */
2240 /* P_coff_cpil_alpha=4, P_coff_inh=0, P_coff_cpil_winlen=64, P_coff_narrow_band=1, P_coff_square_val=1, P_coff_one_seg=~partial_rcpt, P_coff_use_tmcc=1, P_coff_use_ac=1 */
2241 dib8000_write_word(state, 187, (4 << 12) | (0 << 11) | (63 << 5) | (0x3 << 3) | ((~state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 2) | 0x3);
2242
2243 dib8000_write_word(state, 340, (16 << 6) | (8 << 0)); /* P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8 */
2244 dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0));/* P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1 */
2245
2246 /* Sound Broadcasting mode 1 seg */
2247 if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
2248 /* P_coff_winlen=63, P_coff_thres_lock=15, P_coff_one_seg_width = (P_mode == 3) , P_coff_one_seg_sym = (P_mode-1) */
2249 if (state->mode == 3)
2250 dib8000_write_word(state, 180, 0x1fcf | ((state->mode - 1) << 14));
2251 else
2252 dib8000_write_word(state, 180, 0x0fcf | ((state->mode - 1) << 14));
2253
2254 /* P_ctrl_corm_thres4pre_freq_inh=1,P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 5, P_pre_freq_win_len=4 */
2255 dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (5 << 5) | 4);
2256 coff = &coff_thres_1seg[0];
2257 } else { /* Sound Broadcasting mode 3 seg */
2258 dib8000_write_word(state, 180, 0x1fcf | (1 << 14));
2259 /* P_ctrl_corm_thres4pre_freq_inh = 1, P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 4, P_pre_freq_win_len=4 */
2260 dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (4 << 5) | 4);
2261 coff = &coff_thres_3seg[0];
2262 }
2263
2264 dib8000_write_word(state, 228, 1); /* P_2d_mode_byp=1 */
2265 dib8000_write_word(state, 205, dib8000_read_word(state, 205) & 0xfff0); /* P_cspu_win_cut = 0 */
2266
2267 if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0 && state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K)
2268 dib8000_write_word(state, 265, 15); /* P_equal_noise_sel = 15 */
2269
2270 /* Write COFF thres */
2271 for (i = 0 ; i < 3; i++) {
2272 dib8000_write_word(state, 181+i, coff[i]);
2273 dib8000_write_word(state, 184+i, coff[i]);
2274 }
2275
2276 /*
2277 * make the cpil_coff_lock more robust but slower p_coff_winlen
2278 * 6bits; p_coff_thres_lock 6bits (for coff lock if needed)
2279 */
2280
2281 dib8000_write_word(state, 266, ~state->seg_mask | state->seg_diff_mask); /* P_equal_noise_seg_inh */
2282
2283 if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0)
2284 dib8000_write_word(state, 178, 64); /* P_fft_powrange = 64 */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002285 else
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002286 dib8000_write_word(state, 178, 32); /* P_fft_powrange = 32 */
2287}
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002288
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002289static void dib8000_set_isdbt_common_channel(struct dib8000_state *state, u8 seq, u8 autosearching)
2290{
2291 u16 p_cfr_left_edge = 0, p_cfr_right_edge = 0;
2292 u16 tmcc_pow = 0, ana_gain = 0, tmp = 0, i = 0, nbseg_diff = 0 ;
2293 u16 max_constellation = DQPSK;
2294 int init_prbs;
2295
2296 /* P_mode */
2297 dib8000_write_word(state, 10, (seq << 4));
2298
2299 /* init mode */
2300 state->mode = fft_to_mode(state);
2301
2302 /* set guard */
2303 tmp = dib8000_read_word(state, 1);
2304 dib8000_write_word(state, 1, (tmp&0xfffc) | (state->fe[0]->dtv_property_cache.guard_interval & 0x3));
2305
2306 dib8000_write_word(state, 274, (dib8000_read_word(state, 274) & 0xffcf) | ((state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 5) | ((state->fe[0]->dtv_property_cache.isdbt_sb_mode & 1) << 4));
2307
2308 /* signal optimization parameter */
2309 if (state->fe[0]->dtv_property_cache.isdbt_partial_reception) {
2310 state->seg_diff_mask = (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) << permu_seg[0];
2311 for (i = 1; i < 3; i++)
2312 nbseg_diff += (state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count;
2313 for (i = 0; i < nbseg_diff; i++)
2314 state->seg_diff_mask |= 1 << permu_seg[i+1];
2315 } else {
2316 for (i = 0; i < 3; i++)
2317 nbseg_diff += (state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count;
2318 for (i = 0; i < nbseg_diff; i++)
2319 state->seg_diff_mask |= 1 << permu_seg[i];
2320 }
2321
2322 if (state->seg_diff_mask)
2323 dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200);
2324 else
2325 dib8000_write_word(state, 268, (2 << 9) | 39); /*init value */
2326
2327 for (i = 0; i < 3; i++)
2328 max_constellation = dib8000_set_layer(state, i, max_constellation);
2329 if (autosearching == 0) {
2330 state->layer_b_nb_seg = state->fe[0]->dtv_property_cache.layer[1].segment_count;
2331 state->layer_c_nb_seg = state->fe[0]->dtv_property_cache.layer[2].segment_count;
2332 }
2333
2334 /* WRITE: Mode & Diff mask */
2335 dib8000_write_word(state, 0, (state->mode << 13) | state->seg_diff_mask);
2336
2337 state->differential_constellation = (state->seg_diff_mask != 0);
2338
2339 /* channel estimation fine configuration */
2340 ana_gain = dib8000_adp_fine_tune(state, max_constellation);
2341
2342 /* update ana_gain depending on max constellation */
2343 dib8000_update_ana_gain(state, ana_gain);
2344
2345 /* ---- ANA_FE ---- */
2346 if (state->fe[0]->dtv_property_cache.isdbt_partial_reception) /* 3-segments */
2347 dib8000_load_ana_fe_coefs(state, ana_fe_coeff_3seg);
2348 else
2349 dib8000_load_ana_fe_coefs(state, ana_fe_coeff_1seg); /* 1-segment */
2350
2351 /* TSB or ISDBT ? apply it now */
2352 if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
2353 dib8000_set_sb_channel(state);
2354 if (state->fe[0]->dtv_property_cache.isdbt_sb_subchannel != -1)
2355 init_prbs = dib8000_get_init_prbs(state, state->fe[0]->dtv_property_cache.isdbt_sb_subchannel);
2356 else
2357 init_prbs = 0;
2358 } else {
2359 dib8000_set_13seg_channel(state);
2360 init_prbs = 0xfff;
2361 }
2362
2363 /* SMALL */
2364 dib8000_small_fine_tune(state);
2365
2366 dib8000_set_subchannel_prbs(state, init_prbs);
2367
2368 /* ---- CHAN_BLK ---- */
2369 for (i = 0; i < 13; i++) {
2370 if ((((~state->seg_diff_mask) >> i) & 1) == 1) {
2371 p_cfr_left_edge += (1 << i) * ((i == 0) || ((((state->seg_mask & (~state->seg_diff_mask)) >> (i - 1)) & 1) == 0));
2372 p_cfr_right_edge += (1 << i) * ((i == 12) || ((((state->seg_mask & (~state->seg_diff_mask)) >> (i + 1)) & 1) == 0));
2373 }
2374 }
2375 dib8000_write_word(state, 222, p_cfr_left_edge); /* p_cfr_left_edge */
2376 dib8000_write_word(state, 223, p_cfr_right_edge); /* p_cfr_right_edge */
2377 /* "P_cspu_left_edge" & "P_cspu_right_edge" not used => do not care */
2378
2379 dib8000_write_word(state, 189, ~state->seg_mask | state->seg_diff_mask); /* P_lmod4_seg_inh */
2380 dib8000_write_word(state, 192, ~state->seg_mask | state->seg_diff_mask); /* P_pha3_seg_inh */
2381 dib8000_write_word(state, 225, ~state->seg_mask | state->seg_diff_mask); /* P_tac_seg_inh */
2382
2383 if (!autosearching)
2384 dib8000_write_word(state, 288, (~state->seg_mask | state->seg_diff_mask) & 0x1fff); /* P_tmcc_seg_eq_inh */
2385 else
2386 dib8000_write_word(state, 288, 0x1fff); /*disable equalisation of the tmcc when autosearch to be able to find the DQPSK channels. */
2387
2388 dib8000_write_word(state, 211, state->seg_mask & (~state->seg_diff_mask)); /* P_des_seg_enabled */
2389 dib8000_write_word(state, 287, ~state->seg_mask | 0x1000); /* P_tmcc_seg_inh */
2390
2391 dib8000_write_word(state, 178, 32); /* P_fft_powrange = 32 */
2392
2393 /* ---- TMCC ---- */
2394 for (i = 0; i < 3; i++)
2395 tmcc_pow += (((state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * 4 + 1) * state->fe[0]->dtv_property_cache.layer[i].segment_count) ;
2396
2397 /* Quantif of "P_tmcc_dec_thres_?k" is (0, 5+mode, 9); */
2398 /* Threshold is set at 1/4 of max power. */
2399 tmcc_pow *= (1 << (9-2));
2400 dib8000_write_word(state, 290, tmcc_pow); /* P_tmcc_dec_thres_2k */
2401 dib8000_write_word(state, 291, tmcc_pow); /* P_tmcc_dec_thres_4k */
2402 dib8000_write_word(state, 292, tmcc_pow); /* P_tmcc_dec_thres_8k */
2403 /*dib8000_write_word(state, 287, (1 << 13) | 0x1000 ); */
2404
2405 /* ---- PHA3 ---- */
2406 if (state->isdbt_cfg_loaded == 0)
2407 dib8000_write_word(state, 250, 3285); /* p_2d_hspeed_thr0 */
2408
2409 state->isdbt_cfg_loaded = 0;
2410}
2411
Mauro Carvalho Chehab6f7ee06f2013-04-25 10:36:56 -03002412static u32 dib8000_wait_lock(struct dib8000_state *state, u32 internal,
2413 u32 wait0_ms, u32 wait1_ms, u32 wait2_ms)
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002414{
2415 u32 value;
2416 u16 reg = 11; /* P_search_end0 start addr */
2417
2418 for (reg = 11; reg < 16; reg += 2) {
2419 if (reg == 11) {
2420 if (state->revision == 0x8090)
2421 value = internal * wait1_ms; /* P_search_end0 wait time */
2422 else
2423 value = internal * wait0_ms; /* P_search_end0 wait time */
2424 } else if (reg == 13)
2425 value = internal * wait1_ms; /* P_search_end0 wait time */
2426 else if (reg == 15)
2427 value = internal * wait2_ms; /* P_search_end0 wait time */
2428 dib8000_write_word(state, reg, (u16)((value >> 16) & 0xffff));
2429 dib8000_write_word(state, (reg + 1), (u16)(value & 0xffff));
2430 }
2431 return value;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002432}
2433
2434static int dib8000_autosearch_start(struct dvb_frontend *fe)
2435{
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002436 struct dib8000_state *state = fe->demodulator_priv;
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002437 u8 slist = 0;
2438 u32 value, internal = state->cfg.pll->internal;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002439
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002440 if (state->revision == 0x8090)
2441 internal = dib8000_read32(state, 23) / 1000;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002442
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002443 if (state->autosearch_state == AS_SEARCHING_FFT) {
2444 dib8000_write_word(state, 37, 0x0065); /* P_ctrl_pha_off_max default values */
2445 dib8000_write_word(state, 116, 0x0000); /* P_ana_gain to 0 */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002446
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002447 dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x1fff) | (0 << 13) | (1 << 15)); /* P_mode = 0, P_restart_search=1 */
2448 dib8000_write_word(state, 1, (dib8000_read_word(state, 1) & 0xfffc) | 0); /* P_guard = 0 */
2449 dib8000_write_word(state, 6, 0); /* P_lock0_mask = 0 */
2450 dib8000_write_word(state, 7, 0); /* P_lock1_mask = 0 */
2451 dib8000_write_word(state, 8, 0); /* P_lock2_mask = 0 */
2452 dib8000_write_word(state, 10, (dib8000_read_word(state, 10) & 0x200) | (16 << 4) | (0 << 0)); /* P_search_list=16, P_search_maxtrial=0 */
2453
2454 if (state->revision == 0x8090)
2455 value = dib8000_wait_lock(state, internal, 10, 10, 10); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
2456 else
2457 value = dib8000_wait_lock(state, internal, 20, 20, 20); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
2458
2459 dib8000_write_word(state, 17, 0);
2460 dib8000_write_word(state, 18, 200); /* P_search_rstst = 200 */
2461 dib8000_write_word(state, 19, 0);
2462 dib8000_write_word(state, 20, 400); /* P_search_rstend = 400 */
2463 dib8000_write_word(state, 21, (value >> 16) & 0xffff); /* P_search_checkst */
2464 dib8000_write_word(state, 22, value & 0xffff);
2465
2466 if (state->revision == 0x8090)
2467 dib8000_write_word(state, 32, (dib8000_read_word(state, 32) & 0xf0ff) | (0 << 8)); /* P_corm_alpha = 0 */
2468 else
2469 dib8000_write_word(state, 32, (dib8000_read_word(state, 32) & 0xf0ff) | (9 << 8)); /* P_corm_alpha = 3 */
2470 dib8000_write_word(state, 355, 2); /* P_search_param_max = 2 */
2471
2472 /* P_search_param_select = (1 | 1<<4 | 1 << 8) */
2473 dib8000_write_word(state, 356, 0);
2474 dib8000_write_word(state, 357, 0x111);
2475
2476 dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (1 << 13)); /* P_restart_ccg = 1 */
2477 dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (0 << 13)); /* P_restart_ccg = 0 */
2478 dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x7ff) | (0 << 15) | (1 << 13)); /* P_restart_search = 0; */
2479 } else if (state->autosearch_state == AS_SEARCHING_GUARD) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03002480 state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
2481 state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002482 state->fe[0]->dtv_property_cache.inversion = 0;
2483 state->fe[0]->dtv_property_cache.layer[0].modulation = QAM_64;
2484 state->fe[0]->dtv_property_cache.layer[0].fec = FEC_2_3;
2485 state->fe[0]->dtv_property_cache.layer[0].interleaving = 0;
2486 state->fe[0]->dtv_property_cache.layer[0].segment_count = 13;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002487
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002488 slist = 16;
2489 state->fe[0]->dtv_property_cache.transmission_mode = state->found_nfft;
Patrick Boettcher78f3bc62009-08-17 12:53:51 -03002490
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002491 dib8000_set_isdbt_common_channel(state, slist, 1);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002492
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002493 /* set lock_mask values */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002494 dib8000_write_word(state, 6, 0x4);
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002495 if (state->revision == 0x8090)
2496 dib8000_write_word(state, 7, ((1 << 12) | (1 << 11) | (1 << 10)));/* tmcc_dec_lock, tmcc_sync_lock, tmcc_data_lock, tmcc_bch_uncor */
2497 else
2498 dib8000_write_word(state, 7, 0x8);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002499 dib8000_write_word(state, 8, 0x1000);
2500
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002501 /* set lock_mask wait time values */
2502 if (state->revision == 0x8090)
2503 dib8000_wait_lock(state, internal, 50, 100, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
2504 else
2505 dib8000_wait_lock(state, internal, 50, 200, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
2506
2507 dib8000_write_word(state, 355, 3); /* P_search_param_max = 3 */
2508
2509 /* P_search_param_select = 0xf; look for the 4 different guard intervals */
2510 dib8000_write_word(state, 356, 0);
2511 dib8000_write_word(state, 357, 0xf);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002512
2513 value = dib8000_read_word(state, 0);
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002514 dib8000_write_word(state, 0, (u16)((1 << 15) | value));
2515 dib8000_read_word(state, 1284); /* reset the INT. n_irq_pending */
2516 dib8000_write_word(state, 0, (u16)value);
2517 } else {
2518 state->fe[0]->dtv_property_cache.inversion = 0;
2519 state->fe[0]->dtv_property_cache.layer[0].modulation = QAM_64;
2520 state->fe[0]->dtv_property_cache.layer[0].fec = FEC_2_3;
2521 state->fe[0]->dtv_property_cache.layer[0].interleaving = 0;
2522 state->fe[0]->dtv_property_cache.layer[0].segment_count = 13;
2523 if (!state->fe[0]->dtv_property_cache.isdbt_sb_mode)
2524 state->fe[0]->dtv_property_cache.layer[0].segment_count = 13;
Patrick Boettcher78f3bc62009-08-17 12:53:51 -03002525
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002526 /* choose the right list, in sb, always do everything */
2527 if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
2528 slist = 7;
2529 dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));
2530 } else {
2531 if (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) {
2532 if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) {
2533 state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
2534 state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
2535 slist = 7;
2536 dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); /* P_mode = 1 to have autosearch start ok with mode2 */
2537 } else {
2538 state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
2539 slist = 3;
2540 }
2541 } else {
2542 if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) {
2543 state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
2544 slist = 2;
2545 dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); /* P_mode = 1 */
2546 } else
2547 slist = 0;
2548 }
2549 }
2550 dprintk("Using list for autosearch : %d", slist);
2551
2552 dib8000_set_isdbt_common_channel(state, slist, 1);
2553
2554 /* set lock_mask values */
2555 dib8000_write_word(state, 6, 0x4);
2556 if (state->revision == 0x8090)
2557 dib8000_write_word(state, 7, (1 << 12) | (1 << 11) | (1 << 10));
2558 else
2559 dib8000_write_word(state, 7, 0x8);
2560 dib8000_write_word(state, 8, 0x1000);
2561
2562 /* set lock_mask wait time values */
2563 if (state->revision == 0x8090)
2564 dib8000_wait_lock(state, internal, 50, 200, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
2565 else
2566 dib8000_wait_lock(state, internal, 50, 100, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
2567
2568 value = dib8000_read_word(state, 0);
2569 dib8000_write_word(state, 0, (u16)((1 << 15) | value));
2570 dib8000_read_word(state, 1284); /* reset the INT. n_irq_pending */
2571 dib8000_write_word(state, 0, (u16)value);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002572 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002573 return 0;
2574}
2575
2576static int dib8000_autosearch_irq(struct dvb_frontend *fe)
2577{
2578 struct dib8000_state *state = fe->demodulator_priv;
2579 u16 irq_pending = dib8000_read_word(state, 1284);
2580
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002581 if (state->autosearch_state == AS_SEARCHING_FFT) {
2582 if (irq_pending & 0x1) {
2583 dprintk("dib8000_autosearch_irq: max correlation result available");
2584 return 3;
2585 }
2586 } else {
2587 if (irq_pending & 0x1) { /* failed */
2588 dprintk("dib8000_autosearch_irq failed");
2589 return 1;
2590 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002591
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002592 if (irq_pending & 0x2) { /* succeeded */
2593 dprintk("dib8000_autosearch_irq succeeded");
2594 return 2;
2595 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002596 }
2597
2598 return 0; // still pending
2599}
2600
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002601static void dib8000_viterbi_state(struct dib8000_state *state, u8 onoff)
2602{
2603 u16 tmp;
2604
2605 tmp = dib8000_read_word(state, 771);
2606 if (onoff) /* start P_restart_chd : channel_decoder */
2607 dib8000_write_word(state, 771, tmp & 0xfffd);
2608 else /* stop P_restart_chd : channel_decoder */
2609 dib8000_write_word(state, 771, tmp | (1<<1));
2610}
2611
2612static void dib8000_set_dds(struct dib8000_state *state, s32 offset_khz)
2613{
2614 s16 unit_khz_dds_val;
2615 u32 abs_offset_khz = ABS(offset_khz);
2616 u32 dds = state->cfg.pll->ifreq & 0x1ffffff;
2617 u8 invert = !!(state->cfg.pll->ifreq & (1 << 25));
2618 u8 ratio;
2619
2620 if (state->revision == 0x8090) {
2621 ratio = 4;
2622 unit_khz_dds_val = (1<<26) / (dib8000_read32(state, 23) / 1000);
2623 if (offset_khz < 0)
2624 dds = (1 << 26) - (abs_offset_khz * unit_khz_dds_val);
2625 else
2626 dds = (abs_offset_khz * unit_khz_dds_val);
2627
2628 if (invert)
2629 dds = (1<<26) - dds;
2630 } else {
2631 ratio = 2;
2632 unit_khz_dds_val = (u16) (67108864 / state->cfg.pll->internal);
2633
2634 if (offset_khz < 0)
2635 unit_khz_dds_val *= -1;
2636
2637 /* IF tuner */
2638 if (invert)
2639 dds -= abs_offset_khz * unit_khz_dds_val;
2640 else
2641 dds += abs_offset_khz * unit_khz_dds_val;
2642 }
2643
2644 dprintk("setting a DDS frequency offset of %c%dkHz", invert ? '-' : ' ', dds / unit_khz_dds_val);
2645
2646 if (abs_offset_khz <= (state->cfg.pll->internal / ratio)) {
2647 /* Max dds offset is the half of the demod freq */
2648 dib8000_write_word(state, 26, invert);
2649 dib8000_write_word(state, 27, (u16)(dds >> 16) & 0x1ff);
2650 dib8000_write_word(state, 28, (u16)(dds & 0xffff));
2651 }
2652}
2653
2654static void dib8000_set_frequency_offset(struct dib8000_state *state)
2655{
2656 int i;
2657 u32 current_rf;
2658 int total_dds_offset_khz;
2659
2660 if (state->fe[0]->ops.tuner_ops.get_frequency)
2661 state->fe[0]->ops.tuner_ops.get_frequency(state->fe[0], &current_rf);
2662 else
2663 current_rf = state->fe[0]->dtv_property_cache.frequency;
2664 current_rf /= 1000;
2665 total_dds_offset_khz = (int)current_rf - (int)state->fe[0]->dtv_property_cache.frequency / 1000;
2666
2667 if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
2668 state->subchannel = state->fe[0]->dtv_property_cache.isdbt_sb_subchannel;
2669
2670 i = dib8000_read_word(state, 26) & 1; /* P_dds_invspec */
2671 dib8000_write_word(state, 26, state->fe[0]->dtv_property_cache.inversion ^ i);
2672
2673 if (state->cfg.pll->ifreq == 0) { /* low if tuner */
2674 if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0)
2675 dib8000_write_word(state, 26, dib8000_read_word(state, 26) | 1);
2676 } else {
2677 if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0)
2678 total_dds_offset_khz *= -1;
2679 }
2680 }
2681
2682 dprintk("%dkhz tuner offset (frequency = %dHz & current_rf = %dHz) total_dds_offset_hz = %d", state->fe[0]->dtv_property_cache.frequency - current_rf, state->fe[0]->dtv_property_cache.frequency, current_rf, total_dds_offset_khz);
2683
2684 /* apply dds offset now */
2685 dib8000_set_dds(state, total_dds_offset_khz);
2686}
2687
2688static u16 LUT_isdbt_symbol_duration[4] = { 26, 101, 63 };
Mauro Carvalho Chehab6f7ee06f2013-04-25 10:36:56 -03002689
2690static u32 dib8000_get_symbol_duration(struct dib8000_state *state)
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002691{
2692 u16 i;
2693
2694 switch (state->fe[0]->dtv_property_cache.transmission_mode) {
2695 case TRANSMISSION_MODE_2K:
2696 i = 0;
2697 break;
2698 case TRANSMISSION_MODE_4K:
2699 i = 2;
2700 break;
2701 default:
2702 case TRANSMISSION_MODE_AUTO:
2703 case TRANSMISSION_MODE_8K:
2704 i = 1;
2705 break;
2706 }
2707
2708 return (LUT_isdbt_symbol_duration[i] / (state->fe[0]->dtv_property_cache.bandwidth_hz / 1000)) + 1;
2709}
2710
2711static void dib8000_set_isdbt_loop_params(struct dib8000_state *state, enum param_loop_step loop_step)
2712{
2713 u16 reg_32 = 0, reg_37 = 0;
2714
2715 switch (loop_step) {
2716 case LOOP_TUNE_1:
2717 if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
2718 if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
2719 reg_32 = ((11 - state->mode) << 12) | (6 << 8) | 0x40; /* P_timf_alpha = (11-P_mode), P_corm_alpha=6, P_corm_thres=0x40 */
2720 reg_37 = (3 << 5) | (0 << 4) | (10 - state->mode); /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = (10-P_mode) */
2721 } else { /* Sound Broadcasting mode 3 seg */
2722 reg_32 = ((10 - state->mode) << 12) | (6 << 8) | 0x60; /* P_timf_alpha = (10-P_mode), P_corm_alpha=6, P_corm_thres=0x60 */
2723 reg_37 = (3 << 5) | (0 << 4) | (9 - state->mode); /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = (9-P_mode) */
2724 }
2725 } else { /* 13-seg start conf offset loop parameters */
2726 reg_32 = ((9 - state->mode) << 12) | (6 << 8) | 0x80; /* P_timf_alpha = (9-P_mode, P_corm_alpha=6, P_corm_thres=0x80 */
2727 reg_37 = (3 << 5) | (0 << 4) | (8 - state->mode); /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = 9 */
2728 }
2729 break;
2730 case LOOP_TUNE_2:
2731 if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
2732 if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { /* Sound Broadcasting mode 1 seg */
2733 reg_32 = ((13-state->mode) << 12) | (6 << 8) | 0x40; /* P_timf_alpha = (13-P_mode) , P_corm_alpha=6, P_corm_thres=0x40*/
2734 reg_37 = (12-state->mode) | ((5 + state->mode) << 5);
2735 } else { /* Sound Broadcasting mode 3 seg */
2736 reg_32 = ((12-state->mode) << 12) | (6 << 8) | 0x60; /* P_timf_alpha = (12-P_mode) , P_corm_alpha=6, P_corm_thres=0x60 */
2737 reg_37 = (11-state->mode) | ((5 + state->mode) << 5);
2738 }
2739 } else { /* 13 seg */
2740 reg_32 = ((11-state->mode) << 12) | (6 << 8) | 0x80; /* P_timf_alpha = 8 , P_corm_alpha=6, P_corm_thres=0x80 */
2741 reg_37 = ((5+state->mode) << 5) | (10 - state->mode);
2742 }
2743 break;
2744 }
2745 dib8000_write_word(state, 32, reg_32);
2746 dib8000_write_word(state, 37, reg_37);
2747}
2748
2749static void dib8000_demod_restart(struct dib8000_state *state)
2750{
2751 dib8000_write_word(state, 770, 0x4000);
2752 dib8000_write_word(state, 770, 0x0000);
2753 return;
2754}
2755
2756static void dib8000_set_sync_wait(struct dib8000_state *state)
2757{
2758 u16 sync_wait = 64;
2759
2760 /* P_dvsy_sync_wait - reuse mode */
2761 switch (state->fe[0]->dtv_property_cache.transmission_mode) {
2762 case TRANSMISSION_MODE_8K:
2763 sync_wait = 256;
2764 break;
2765 case TRANSMISSION_MODE_4K:
2766 sync_wait = 128;
2767 break;
2768 default:
2769 case TRANSMISSION_MODE_2K:
2770 sync_wait = 64;
2771 break;
2772 }
2773
2774 if (state->cfg.diversity_delay == 0)
2775 sync_wait = (sync_wait * (1 << (state->fe[0]->dtv_property_cache.guard_interval)) * 3) / 2 + 48; /* add 50% SFN margin + compensate for one DVSY-fifo */
2776 else
2777 sync_wait = (sync_wait * (1 << (state->fe[0]->dtv_property_cache.guard_interval)) * 3) / 2 + state->cfg.diversity_delay; /* add 50% SFN margin + compensate for DVSY-fifo */
2778
2779 dib8000_write_word(state, 273, (dib8000_read_word(state, 273) & 0x000f) | (sync_wait << 4));
2780}
2781
2782static u32 dib8000_get_timeout(struct dib8000_state *state, u32 delay, enum timeout_mode mode)
2783{
2784 if (mode == SYMBOL_DEPENDENT_ON)
2785 return systime() + (delay * state->symbol_duration);
2786 else
2787 return systime() + delay;
2788}
2789
2790static s32 dib8000_get_status(struct dvb_frontend *fe)
2791{
2792 struct dib8000_state *state = fe->demodulator_priv;
2793 return state->status;
2794}
2795
2796enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
2797{
2798 struct dib8000_state *state = fe->demodulator_priv;
2799 return state->tune_state;
2800}
2801EXPORT_SYMBOL(dib8000_get_tune_state);
2802
2803int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
2804{
2805 struct dib8000_state *state = fe->demodulator_priv;
2806
2807 state->tune_state = tune_state;
2808 return 0;
2809}
2810EXPORT_SYMBOL(dib8000_set_tune_state);
2811
2812static int dib8000_tune_restart_from_demod(struct dvb_frontend *fe)
2813{
2814 struct dib8000_state *state = fe->demodulator_priv;
2815
2816 state->status = FE_STATUS_TUNE_PENDING;
2817 state->tune_state = CT_DEMOD_START;
2818 return 0;
2819}
2820
2821static u16 dib8000_read_lock(struct dvb_frontend *fe)
2822{
2823 struct dib8000_state *state = fe->demodulator_priv;
2824
2825 if (state->revision == 0x8090)
2826 return dib8000_read_word(state, 570);
2827 return dib8000_read_word(state, 568);
2828}
2829
2830static int dib8090p_init_sdram(struct dib8000_state *state)
2831{
2832 u16 reg = 0;
2833 dprintk("init sdram");
2834
2835 reg = dib8000_read_word(state, 274) & 0xfff0;
2836 dib8000_write_word(state, 274, reg | 0x7); /* P_dintlv_delay_ram = 7 because of MobileSdram */
2837
2838 dib8000_write_word(state, 1803, (7 << 2));
2839
2840 reg = dib8000_read_word(state, 1280);
2841 dib8000_write_word(state, 1280, reg | (1 << 2)); /* force restart P_restart_sdram */
2842 dib8000_write_word(state, 1280, reg); /* release restart P_restart_sdram */
2843
2844 return 0;
2845}
2846
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002847static int dib8000_tune(struct dvb_frontend *fe)
2848{
2849 struct dib8000_state *state = fe->demodulator_priv;
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002850 enum frontend_tune_state *tune_state = &state->tune_state;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002851
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002852 u16 locks, deeper_interleaver = 0, i;
2853 int ret = 1; /* 1 symbol duration (in 100us unit) delay most of the time */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002854
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002855 u32 *timeout = &state->timeout;
2856 u32 now = systime();
2857#ifdef DIB8000_AGC_FREEZE
2858 u16 agc1, agc2;
2859#endif
Dan Carpentere04f4b22012-07-20 07:11:57 -03002860
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002861 u32 corm[4] = {0, 0, 0, 0};
2862 u8 find_index, max_value;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002863
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002864#if 0
2865 if (*tune_state < CT_DEMOD_STOP)
2866 dprintk("IN: context status = %d, TUNE_STATE %d autosearch step = %u systime = %u", state->channel_parameters_set, *tune_state, state->autosearch_state, now);
2867#endif
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002868
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002869 switch (*tune_state) {
2870 case CT_DEMOD_START: /* 30 */
2871 if (state->revision == 0x8090)
2872 dib8090p_init_sdram(state);
2873 state->status = FE_STATUS_TUNE_PENDING;
2874 if ((state->fe[0]->dtv_property_cache.delivery_system != SYS_ISDBT) ||
2875 (state->fe[0]->dtv_property_cache.inversion == INVERSION_AUTO) ||
2876 (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) ||
2877 (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) ||
2878 (((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) != 0) &&
2879 (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0xff) &&
2880 (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0) &&
2881 ((state->fe[0]->dtv_property_cache.layer[0].modulation == QAM_AUTO) ||
2882 (state->fe[0]->dtv_property_cache.layer[0].fec == FEC_AUTO))) ||
2883 (((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 1)) != 0) &&
2884 (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0xff) &&
2885 (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0) &&
2886 ((state->fe[0]->dtv_property_cache.layer[1].modulation == QAM_AUTO) ||
2887 (state->fe[0]->dtv_property_cache.layer[1].fec == FEC_AUTO))) ||
2888 (((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 2)) != 0) &&
2889 (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0xff) &&
2890 (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0) &&
2891 ((state->fe[0]->dtv_property_cache.layer[2].modulation == QAM_AUTO) ||
2892 (state->fe[0]->dtv_property_cache.layer[2].fec == FEC_AUTO))) ||
2893 (((state->fe[0]->dtv_property_cache.layer[0].segment_count == 0) ||
2894 ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) == 0)) &&
2895 ((state->fe[0]->dtv_property_cache.layer[1].segment_count == 0) ||
2896 ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (2 << 0)) == 0)) &&
2897 ((state->fe[0]->dtv_property_cache.layer[2].segment_count == 0) || ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (3 << 0)) == 0))))
2898 state->channel_parameters_set = 0; /* auto search */
2899 else
2900 state->channel_parameters_set = 1; /* channel parameters are known */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002901
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002902 dib8000_viterbi_state(state, 0); /* force chan dec in restart */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002903
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002904 /* Layer monit */
2905 dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002906
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002907 dib8000_set_frequency_offset(state);
2908 dib8000_set_bandwidth(fe, state->fe[0]->dtv_property_cache.bandwidth_hz / 1000);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002909
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002910 if (state->channel_parameters_set == 0) { /* The channel struct is unknown, search it ! */
2911#ifdef DIB8000_AGC_FREEZE
2912 if (state->revision != 0x8090) {
2913 state->agc1_max = dib8000_read_word(state, 108);
2914 state->agc1_min = dib8000_read_word(state, 109);
2915 state->agc2_max = dib8000_read_word(state, 110);
2916 state->agc2_min = dib8000_read_word(state, 111);
2917 agc1 = dib8000_read_word(state, 388);
2918 agc2 = dib8000_read_word(state, 389);
2919 dib8000_write_word(state, 108, agc1);
2920 dib8000_write_word(state, 109, agc1);
2921 dib8000_write_word(state, 110, agc2);
2922 dib8000_write_word(state, 111, agc2);
2923 }
2924#endif
2925 state->autosearch_state = AS_SEARCHING_FFT;
2926 state->found_nfft = TRANSMISSION_MODE_AUTO;
2927 state->found_guard = GUARD_INTERVAL_AUTO;
2928 *tune_state = CT_DEMOD_SEARCH_NEXT;
2929 } else { /* we already know the channel struct so TUNE only ! */
2930 state->autosearch_state = AS_DONE;
2931 *tune_state = CT_DEMOD_STEP_3;
2932 }
2933 state->symbol_duration = dib8000_get_symbol_duration(state);
2934 break;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002935
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002936 case CT_DEMOD_SEARCH_NEXT: /* 51 */
2937 dib8000_autosearch_start(fe);
2938 if (state->revision == 0x8090)
2939 ret = 50;
2940 else
2941 ret = 15;
2942 *tune_state = CT_DEMOD_STEP_1;
2943 break;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002944
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002945 case CT_DEMOD_STEP_1: /* 31 */
2946 switch (dib8000_autosearch_irq(fe)) {
2947 case 1: /* fail */
2948 state->status = FE_STATUS_TUNE_FAILED;
2949 state->autosearch_state = AS_DONE;
2950 *tune_state = CT_DEMOD_STOP; /* else we are done here */
2951 break;
2952 case 2: /* Succes */
2953 state->status = FE_STATUS_FFT_SUCCESS; /* signal to the upper layer, that there was a channel found and the parameters can be read */
2954 *tune_state = CT_DEMOD_STEP_3;
2955 if (state->autosearch_state == AS_SEARCHING_GUARD)
2956 *tune_state = CT_DEMOD_STEP_2;
2957 else
2958 state->autosearch_state = AS_DONE;
2959 break;
2960 case 3: /* Autosearch FFT max correlation endded */
2961 *tune_state = CT_DEMOD_STEP_2;
2962 break;
2963 }
2964 break;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002965
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002966 case CT_DEMOD_STEP_2:
2967 switch (state->autosearch_state) {
2968 case AS_SEARCHING_FFT:
2969 /* searching for the correct FFT */
2970 if (state->revision == 0x8090) {
2971 corm[2] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
2972 corm[1] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
2973 corm[0] = (dib8000_read_word(state, 600) << 16) | (dib8000_read_word(state, 601));
2974 } else {
2975 corm[2] = (dib8000_read_word(state, 594) << 16) | (dib8000_read_word(state, 595));
2976 corm[1] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
2977 corm[0] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
2978 }
2979 /* dprintk("corm fft: %u %u %u", corm[0], corm[1], corm[2]); */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002980
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002981 max_value = 0;
2982 for (find_index = 1 ; find_index < 3 ; find_index++) {
2983 if (corm[max_value] < corm[find_index])
2984 max_value = find_index ;
2985 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002986
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002987 switch (max_value) {
2988 case 0:
2989 state->found_nfft = TRANSMISSION_MODE_2K;
2990 break;
2991 case 1:
2992 state->found_nfft = TRANSMISSION_MODE_4K;
2993 break;
2994 case 2:
2995 default:
2996 state->found_nfft = TRANSMISSION_MODE_8K;
2997 break;
2998 }
2999 /* dprintk("Autosearch FFT has found Mode %d", max_value + 1); */
3000
3001 *tune_state = CT_DEMOD_SEARCH_NEXT;
3002 state->autosearch_state = AS_SEARCHING_GUARD;
3003 if (state->revision == 0x8090)
3004 ret = 50;
3005 else
3006 ret = 10;
3007 break;
3008 case AS_SEARCHING_GUARD:
3009 /* searching for the correct guard interval */
3010 if (state->revision == 0x8090)
3011 state->found_guard = dib8000_read_word(state, 572) & 0x3;
3012 else
3013 state->found_guard = dib8000_read_word(state, 570) & 0x3;
3014 /* dprintk("guard interval found=%i", state->found_guard); */
3015
3016 *tune_state = CT_DEMOD_STEP_3;
3017 break;
3018 default:
3019 /* the demod should never be in this state */
3020 state->status = FE_STATUS_TUNE_FAILED;
3021 state->autosearch_state = AS_DONE;
3022 *tune_state = CT_DEMOD_STOP; /* else we are done here */
3023 break;
3024 }
3025 break;
3026
3027 case CT_DEMOD_STEP_3: /* 33 */
3028 state->symbol_duration = dib8000_get_symbol_duration(state);
3029 dib8000_set_isdbt_loop_params(state, LOOP_TUNE_1);
3030 dib8000_set_isdbt_common_channel(state, 0, 0);/* setting the known channel parameters here */
3031 *tune_state = CT_DEMOD_STEP_4;
3032 break;
3033
3034 case CT_DEMOD_STEP_4: /* (34) */
3035 dib8000_demod_restart(state);
3036
3037 dib8000_set_sync_wait(state);
3038 dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
3039
3040 locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */
3041 /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this lenght to lock */
3042 *timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON);
3043 *tune_state = CT_DEMOD_STEP_5;
3044 break;
3045
3046 case CT_DEMOD_STEP_5: /* (35) */
3047 locks = dib8000_read_lock(fe);
3048 if (locks & (0x3 << 11)) { /* coff-lock and off_cpil_lock achieved */
3049 dib8000_update_timf(state); /* we achieved a coff_cpil_lock - it's time to update the timf */
3050 if (!state->differential_constellation) {
3051 /* 2 times lmod4_win_len + 10 symbols (pipe delay after coff + nb to compute a 1st correlation) */
3052 *timeout = dib8000_get_timeout(state, (20 * ((dib8000_read_word(state, 188)>>5)&0x1f)), SYMBOL_DEPENDENT_ON);
3053 *tune_state = CT_DEMOD_STEP_7;
3054 } else {
3055 *tune_state = CT_DEMOD_STEP_8;
3056 }
3057 } else if (now > *timeout) {
3058 *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
3059 }
3060 break;
3061
3062 case CT_DEMOD_STEP_6: /* (36) if there is an input (diversity) */
3063 if ((state->fe[1] != NULL) && (state->output_mode != OUTMODE_DIVERSITY)) {
3064 /* if there is a diversity fe in input and this fe is has not already failled : wait here until this this fe has succedeed or failled */
3065 if (dib8000_get_status(state->fe[1]) <= FE_STATUS_STD_SUCCESS) /* Something is locked on the input fe */
3066 *tune_state = CT_DEMOD_STEP_8; /* go for mpeg */
3067 else if (dib8000_get_status(state->fe[1]) >= FE_STATUS_TUNE_TIME_TOO_SHORT) { /* fe in input failled also, break the current one */
3068 *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
3069 dib8000_viterbi_state(state, 1); /* start viterbi chandec */
3070 dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
3071 state->status = FE_STATUS_TUNE_FAILED;
3072 }
3073 } else {
3074 dib8000_viterbi_state(state, 1); /* start viterbi chandec */
3075 dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
3076 *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
3077 state->status = FE_STATUS_TUNE_FAILED;
3078 }
3079 break;
3080
3081 case CT_DEMOD_STEP_7: /* 37 */
3082 locks = dib8000_read_lock(fe);
3083 if (locks & (1<<10)) { /* lmod4_lock */
3084 ret = 14; /* wait for 14 symbols */
3085 *tune_state = CT_DEMOD_STEP_8;
3086 } else if (now > *timeout)
3087 *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
3088 break;
3089
3090 case CT_DEMOD_STEP_8: /* 38 */
3091 dib8000_viterbi_state(state, 1); /* start viterbi chandec */
3092 dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
3093
3094 /* mpeg will never lock on this condition because init_prbs is not set : search for it !*/
3095 if (state->fe[0]->dtv_property_cache.isdbt_sb_mode && state->fe[0]->dtv_property_cache.isdbt_sb_subchannel == -1 && !state->differential_constellation) {
3096 state->subchannel = 0;
3097 *tune_state = CT_DEMOD_STEP_11;
3098 } else {
3099 *tune_state = CT_DEMOD_STEP_9;
3100 state->status = FE_STATUS_LOCKED;
3101 }
3102 break;
3103
3104 case CT_DEMOD_STEP_9: /* 39 */
3105 if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */
3106 /* defines timeout for mpeg lock depending on interleaver lenght of longest layer */
3107 for (i = 0; i < 3; i++) {
3108 if (state->fe[0]->dtv_property_cache.layer[i].interleaving >= deeper_interleaver) {
3109 dprintk("layer%i: time interleaver = %d ", i, state->fe[0]->dtv_property_cache.layer[i].interleaving);
3110 if (state->fe[0]->dtv_property_cache.layer[i].segment_count > 0) { /* valid layer */
3111 deeper_interleaver = state->fe[0]->dtv_property_cache.layer[0].interleaving;
3112 state->longest_intlv_layer = i;
3113 }
3114 }
3115 }
3116
3117 if (deeper_interleaver == 0)
3118 locks = 2; /* locks is the tmp local variable name */
3119 else if (deeper_interleaver == 3)
3120 locks = 8;
3121 else
3122 locks = 2 * deeper_interleaver;
3123
3124 if (state->diversity_onoff != 0) /* because of diversity sync */
3125 locks *= 2;
3126
3127 *timeout = now + (2000 * locks); /* give the mpeg lock 800ms if sram is present */
3128 dprintk("Deeper interleaver mode = %d on layer %d : timeout mult factor = %d => will use timeout = %d", deeper_interleaver, state->longest_intlv_layer, locks, *timeout);
3129
3130 *tune_state = CT_DEMOD_STEP_10;
3131 } else
3132 *tune_state = CT_DEMOD_STOP;
3133 break;
3134
3135 case CT_DEMOD_STEP_10: /* 40 */
3136 locks = dib8000_read_lock(fe);
3137 if (locks&(1<<(7-state->longest_intlv_layer))) { /* mpeg lock : check the longest one */
3138 dprintk("Mpeg locks [ L0 : %d | L1 : %d | L2 : %d ]", (locks>>7)&0x1, (locks>>6)&0x1, (locks>>5)&0x1);
3139 if (state->fe[0]->dtv_property_cache.isdbt_sb_mode && state->fe[0]->dtv_property_cache.isdbt_sb_subchannel == -1 && !state->differential_constellation)
3140 /* signal to the upper layer, that there was a channel found and the parameters can be read */
3141 state->status = FE_STATUS_DEMOD_SUCCESS;
3142 else
3143 state->status = FE_STATUS_DATA_LOCKED;
3144 *tune_state = CT_DEMOD_STOP;
3145 } else if (now > *timeout) {
3146 if (state->fe[0]->dtv_property_cache.isdbt_sb_mode && state->fe[0]->dtv_property_cache.isdbt_sb_subchannel == -1 && !state->differential_constellation) { /* continue to try init prbs autosearch */
3147 state->subchannel += 3;
3148 *tune_state = CT_DEMOD_STEP_11;
3149 } else { /* we are done mpeg of the longest interleaver xas not locking but let's try if an other layer has locked in the same time */
3150 if (locks & (0x7<<5)) {
3151 dprintk("Mpeg locks [ L0 : %d | L1 : %d | L2 : %d ]", (locks>>7)&0x1, (locks>>6)&0x1, (locks>>5)&0x1);
3152 state->status = FE_STATUS_DATA_LOCKED;
3153 } else
3154 state->status = FE_STATUS_TUNE_FAILED;
3155 *tune_state = CT_DEMOD_STOP;
3156 }
3157 }
3158 break;
3159
3160 case CT_DEMOD_STEP_11: /* 41 : init prbs autosearch */
3161 if (state->subchannel <= 41) {
3162 dib8000_set_subchannel_prbs(state, dib8000_get_init_prbs(state, state->subchannel));
3163 *tune_state = CT_DEMOD_STEP_9;
3164 } else {
3165 *tune_state = CT_DEMOD_STOP;
3166 state->status = FE_STATUS_TUNE_FAILED;
3167 }
3168 break;
3169
3170 default:
3171 break;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003172 }
3173
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003174 /* tuning is finished - cleanup the demod */
3175 switch (*tune_state) {
3176 case CT_DEMOD_STOP: /* (42) */
3177#ifdef DIB8000_AGC_FREEZE
3178 if ((state->revision != 0x8090) && (state->agc1_max != 0)) {
3179 dib8000_write_word(state, 108, state->agc1_max);
3180 dib8000_write_word(state, 109, state->agc1_min);
3181 dib8000_write_word(state, 110, state->agc2_max);
3182 dib8000_write_word(state, 111, state->agc2_min);
3183 state->agc1_max = 0;
3184 state->agc1_min = 0;
3185 state->agc2_max = 0;
3186 state->agc2_min = 0;
3187 }
3188#endif
3189 ret = FE_CALLBACK_TIME_NEVER;
3190 break;
3191 default:
3192 break;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003193 }
3194
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003195 if ((ret > 0) && (*tune_state > CT_DEMOD_STEP_3))
3196 return ret * state->symbol_duration;
3197 if ((ret > 0) && (ret < state->symbol_duration))
3198 return state->symbol_duration; /* at least one symbol */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003199 return ret;
3200}
3201
3202static int dib8000_wakeup(struct dvb_frontend *fe)
3203{
3204 struct dib8000_state *state = fe->demodulator_priv;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003205 u8 index_frontend;
3206 int ret;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003207
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003208 dib8000_set_power_mode(state, DIB8000_POWER_ALL);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003209 dib8000_set_adc_state(state, DIBX000_ADC_ON);
3210 if (dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
3211 dprintk("could not start Slow ADC");
3212
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003213 if (state->revision == 0x8090)
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003214 dib8000_sad_calib(state);
3215
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003216 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003217 ret = state->fe[index_frontend]->ops.init(state->fe[index_frontend]);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003218 if (ret < 0)
Olivier Grenie4c70e072011-01-03 15:33:37 -03003219 return ret;
3220 }
3221
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003222 return 0;
3223}
3224
3225static int dib8000_sleep(struct dvb_frontend *fe)
3226{
Olivier Grenie4c70e072011-01-03 15:33:37 -03003227 struct dib8000_state *state = fe->demodulator_priv;
3228 u8 index_frontend;
3229 int ret;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003230
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003231 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003232 ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]);
3233 if (ret < 0)
3234 return ret;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003235 }
Olivier Grenie4c70e072011-01-03 15:33:37 -03003236
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003237 if (state->revision != 0x8090)
3238 dib8000_set_output_mode(fe, OUTMODE_HIGH_Z);
3239 dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY);
Olivier Grenie4c70e072011-01-03 15:33:37 -03003240 return dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(state, DIBX000_ADC_OFF);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003241}
3242
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -03003243static int dib8000_get_frontend(struct dvb_frontend *fe)
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003244{
3245 struct dib8000_state *state = fe->demodulator_priv;
3246 u16 i, val = 0;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003247 fe_status_t stat;
3248 u8 index_frontend, sub_index_frontend;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003249
3250 fe->dtv_property_cache.bandwidth_hz = 6000000;
3251
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003252 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003253 state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
3254 if (stat&FE_HAS_SYNC) {
3255 dprintk("TMCC lock on the slave%i", index_frontend);
3256 /* synchronize the cache with the other frontends */
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -03003257 state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003258 for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL); sub_index_frontend++) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003259 if (sub_index_frontend != index_frontend) {
3260 state->fe[sub_index_frontend]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode;
3261 state->fe[sub_index_frontend]->dtv_property_cache.inversion = state->fe[index_frontend]->dtv_property_cache.inversion;
3262 state->fe[sub_index_frontend]->dtv_property_cache.transmission_mode = state->fe[index_frontend]->dtv_property_cache.transmission_mode;
3263 state->fe[sub_index_frontend]->dtv_property_cache.guard_interval = state->fe[index_frontend]->dtv_property_cache.guard_interval;
3264 state->fe[sub_index_frontend]->dtv_property_cache.isdbt_partial_reception = state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception;
3265 for (i = 0; i < 3; i++) {
3266 state->fe[sub_index_frontend]->dtv_property_cache.layer[i].segment_count = state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count;
3267 state->fe[sub_index_frontend]->dtv_property_cache.layer[i].interleaving = state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving;
3268 state->fe[sub_index_frontend]->dtv_property_cache.layer[i].fec = state->fe[index_frontend]->dtv_property_cache.layer[i].fec;
3269 state->fe[sub_index_frontend]->dtv_property_cache.layer[i].modulation = state->fe[index_frontend]->dtv_property_cache.layer[i].modulation;
3270 }
3271 }
3272 }
3273 return 0;
3274 }
3275 }
3276
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003277 fe->dtv_property_cache.isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1;
3278
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003279 if (state->revision == 0x8090)
3280 val = dib8000_read_word(state, 572);
3281 else
3282 val = dib8000_read_word(state, 570);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003283 fe->dtv_property_cache.inversion = (val & 0x40) >> 6;
3284 switch ((val & 0x30) >> 4) {
3285 case 1:
3286 fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
3287 break;
3288 case 3:
3289 default:
3290 fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
3291 break;
3292 }
3293
3294 switch (val & 0x3) {
3295 case 0:
3296 fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
3297 dprintk("dib8000_get_frontend GI = 1/32 ");
3298 break;
3299 case 1:
3300 fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16;
3301 dprintk("dib8000_get_frontend GI = 1/16 ");
3302 break;
3303 case 2:
3304 dprintk("dib8000_get_frontend GI = 1/8 ");
3305 fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
3306 break;
3307 case 3:
3308 dprintk("dib8000_get_frontend GI = 1/4 ");
3309 fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4;
3310 break;
3311 }
3312
3313 val = dib8000_read_word(state, 505);
3314 fe->dtv_property_cache.isdbt_partial_reception = val & 1;
3315 dprintk("dib8000_get_frontend : partial_reception = %d ", fe->dtv_property_cache.isdbt_partial_reception);
3316
3317 for (i = 0; i < 3; i++) {
3318 val = dib8000_read_word(state, 493 + i);
3319 fe->dtv_property_cache.layer[i].segment_count = val & 0x0F;
3320 dprintk("dib8000_get_frontend : Layer %d segments = %d ", i, fe->dtv_property_cache.layer[i].segment_count);
3321
3322 val = dib8000_read_word(state, 499 + i);
3323 fe->dtv_property_cache.layer[i].interleaving = val & 0x3;
3324 dprintk("dib8000_get_frontend : Layer %d time_intlv = %d ", i, fe->dtv_property_cache.layer[i].interleaving);
3325
3326 val = dib8000_read_word(state, 481 + i);
3327 switch (val & 0x7) {
3328 case 1:
3329 fe->dtv_property_cache.layer[i].fec = FEC_1_2;
3330 dprintk("dib8000_get_frontend : Layer %d Code Rate = 1/2 ", i);
3331 break;
3332 case 2:
3333 fe->dtv_property_cache.layer[i].fec = FEC_2_3;
3334 dprintk("dib8000_get_frontend : Layer %d Code Rate = 2/3 ", i);
3335 break;
3336 case 3:
3337 fe->dtv_property_cache.layer[i].fec = FEC_3_4;
3338 dprintk("dib8000_get_frontend : Layer %d Code Rate = 3/4 ", i);
3339 break;
3340 case 5:
3341 fe->dtv_property_cache.layer[i].fec = FEC_5_6;
3342 dprintk("dib8000_get_frontend : Layer %d Code Rate = 5/6 ", i);
3343 break;
3344 default:
3345 fe->dtv_property_cache.layer[i].fec = FEC_7_8;
3346 dprintk("dib8000_get_frontend : Layer %d Code Rate = 7/8 ", i);
3347 break;
3348 }
3349
3350 val = dib8000_read_word(state, 487 + i);
3351 switch (val & 0x3) {
3352 case 0:
3353 dprintk("dib8000_get_frontend : Layer %d DQPSK ", i);
3354 fe->dtv_property_cache.layer[i].modulation = DQPSK;
3355 break;
3356 case 1:
3357 fe->dtv_property_cache.layer[i].modulation = QPSK;
3358 dprintk("dib8000_get_frontend : Layer %d QPSK ", i);
3359 break;
3360 case 2:
3361 fe->dtv_property_cache.layer[i].modulation = QAM_16;
3362 dprintk("dib8000_get_frontend : Layer %d QAM16 ", i);
3363 break;
3364 case 3:
3365 default:
3366 dprintk("dib8000_get_frontend : Layer %d QAM64 ", i);
3367 fe->dtv_property_cache.layer[i].modulation = QAM_64;
3368 break;
3369 }
3370 }
Olivier Grenie4c70e072011-01-03 15:33:37 -03003371
3372 /* synchronize the cache with the other frontends */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003373 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003374 state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode = fe->dtv_property_cache.isdbt_sb_mode;
3375 state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion;
3376 state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode;
3377 state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval;
3378 state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception = fe->dtv_property_cache.isdbt_partial_reception;
3379 for (i = 0; i < 3; i++) {
3380 state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count = fe->dtv_property_cache.layer[i].segment_count;
3381 state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving = fe->dtv_property_cache.layer[i].interleaving;
3382 state->fe[index_frontend]->dtv_property_cache.layer[i].fec = fe->dtv_property_cache.layer[i].fec;
3383 state->fe[index_frontend]->dtv_property_cache.layer[i].modulation = fe->dtv_property_cache.layer[i].modulation;
3384 }
3385 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003386 return 0;
3387}
3388
Mauro Carvalho Chehab490ecd62011-12-22 20:38:27 -03003389static int dib8000_set_frontend(struct dvb_frontend *fe)
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003390{
3391 struct dib8000_state *state = fe->demodulator_priv;
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003392 int l, i, active, time, ret, time_slave = FE_CALLBACK_TIME_NEVER;
3393 u8 exit_condition, index_frontend;
3394 u32 delay, callback_time;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003395
Olivier Grenie4c70e072011-01-03 15:33:37 -03003396 if (state->fe[0]->dtv_property_cache.frequency == 0) {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003397 dprintk("dib8000: must at least specify frequency ");
3398 return 0;
3399 }
3400
Olivier Grenie4c70e072011-01-03 15:33:37 -03003401 if (state->fe[0]->dtv_property_cache.bandwidth_hz == 0) {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003402 dprintk("dib8000: no bandwidth specified, set to default ");
Olivier Grenie4c70e072011-01-03 15:33:37 -03003403 state->fe[0]->dtv_property_cache.bandwidth_hz = 6000000;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003404 }
3405
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003406 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003407 /* synchronization of the cache */
3408 state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_ISDBT;
3409 memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties));
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003410
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003411 /* set output mode and diversity input */
3412 if (state->revision != 0x8090) {
3413 dib8000_set_diversity_in(state->fe[index_frontend], 1);
3414 if (index_frontend != 0)
3415 dib8000_set_output_mode(state->fe[index_frontend],
3416 OUTMODE_DIVERSITY);
3417 else
3418 dib8000_set_output_mode(state->fe[0], OUTMODE_HIGH_Z);
3419 } else {
3420 dib8096p_set_diversity_in(state->fe[index_frontend], 1);
3421 if (index_frontend != 0)
3422 dib8096p_set_output_mode(state->fe[index_frontend],
3423 OUTMODE_DIVERSITY);
3424 else
3425 dib8096p_set_output_mode(state->fe[0], OUTMODE_HIGH_Z);
3426 }
3427
3428 /* tune the tuner */
Olivier Grenie4c70e072011-01-03 15:33:37 -03003429 if (state->fe[index_frontend]->ops.tuner_ops.set_params)
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03003430 state->fe[index_frontend]->ops.tuner_ops.set_params(state->fe[index_frontend]);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003431
Olivier Grenie4c70e072011-01-03 15:33:37 -03003432 dib8000_set_tune_state(state->fe[index_frontend], CT_AGC_START);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003433 }
3434
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003435 /* turn off the diversity of the last chip */
3436 if (state->revision != 0x8090)
3437 dib8000_set_diversity_in(state->fe[index_frontend - 1], 0);
3438 else
3439 dib8096p_set_diversity_in(state->fe[index_frontend - 1], 0);
3440
Olivier Grenie4c70e072011-01-03 15:33:37 -03003441 /* start up the AGC */
3442 do {
3443 time = dib8000_agc_startup(state->fe[0]);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003444 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003445 time_slave = dib8000_agc_startup(state->fe[index_frontend]);
3446 if (time == FE_CALLBACK_TIME_NEVER)
3447 time = time_slave;
3448 else if ((time_slave != FE_CALLBACK_TIME_NEVER) && (time_slave > time))
3449 time = time_slave;
3450 }
3451 if (time != FE_CALLBACK_TIME_NEVER)
3452 msleep(time / 10);
3453 else
3454 break;
3455 exit_condition = 1;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003456 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003457 if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_AGC_STOP) {
3458 exit_condition = 0;
3459 break;
3460 }
3461 }
3462 } while (exit_condition == 0);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003463
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003464 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
Olivier Grenie4c70e072011-01-03 15:33:37 -03003465 dib8000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
3466
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003467 active = 1;
3468 do {
3469 callback_time = FE_CALLBACK_TIME_NEVER;
Mauro Carvalho Chehab2c2c4412011-01-16 13:02:52 -02003470 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003471 delay = dib8000_tune(state->fe[index_frontend]);
3472 if (delay != FE_CALLBACK_TIME_NEVER)
3473 delay += systime();
Olivier Grenie4c70e072011-01-03 15:33:37 -03003474
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003475 /* we are in autosearch */
3476 if (state->channel_parameters_set == 0) { /* searching */
3477 if ((dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_DEMOD_SUCCESS) || (dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_FFT_SUCCESS)) {
3478 dprintk("autosearch succeeded on fe%i", index_frontend);
3479 dib8000_get_frontend(state->fe[index_frontend]); /* we read the channel parameters from the frontend which was successful */
3480 state->channel_parameters_set = 1;
3481
3482 for (l = 0; (l < MAX_NUMBER_OF_FRONTENDS) && (state->fe[l] != NULL); l++) {
3483 if (l != index_frontend) { /* and for all frontend except the successful one */
3484 dib8000_tune_restart_from_demod(state->fe[l]);
3485
3486 state->fe[l]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode;
3487 state->fe[l]->dtv_property_cache.inversion = state->fe[index_frontend]->dtv_property_cache.inversion;
3488 state->fe[l]->dtv_property_cache.transmission_mode = state->fe[index_frontend]->dtv_property_cache.transmission_mode;
3489 state->fe[l]->dtv_property_cache.guard_interval = state->fe[index_frontend]->dtv_property_cache.guard_interval;
3490 state->fe[l]->dtv_property_cache.isdbt_partial_reception = state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception;
3491 for (i = 0; i < 3; i++) {
3492 state->fe[l]->dtv_property_cache.layer[i].segment_count = state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count;
3493 state->fe[l]->dtv_property_cache.layer[i].interleaving = state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving;
3494 state->fe[l]->dtv_property_cache.layer[i].fec = state->fe[index_frontend]->dtv_property_cache.layer[i].fec;
3495 state->fe[l]->dtv_property_cache.layer[i].modulation = state->fe[index_frontend]->dtv_property_cache.layer[i].modulation;
3496 }
3497
3498 }
Mauro Carvalho Chehab2c2c4412011-01-16 13:02:52 -02003499 }
3500 }
3501 }
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003502 if (delay < callback_time)
3503 callback_time = delay;
3504 }
3505 /* tuning is done when the master frontend is done (failed or success) */
3506 if (dib8000_get_status(state->fe[0]) == FE_STATUS_TUNE_FAILED ||
3507 dib8000_get_status(state->fe[0]) == FE_STATUS_LOCKED ||
3508 dib8000_get_status(state->fe[0]) == FE_STATUS_DATA_LOCKED) {
3509 active = 0;
3510 /* we need to wait for all frontends to be finished */
3511 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
3512 if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_DEMOD_STOP)
3513 active = 1;
3514 }
3515 if (active == 0)
3516 dprintk("tuning done with status %d", dib8000_get_status(state->fe[0]));
Mauro Carvalho Chehab2c2c4412011-01-16 13:02:52 -02003517 }
Olivier Grenie4c70e072011-01-03 15:33:37 -03003518
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003519 if ((active == 1) && (callback_time == FE_CALLBACK_TIME_NEVER)) {
3520 dprintk("strange callback time something went wrong");
3521 active = 0;
3522 }
Olivier Grenie4c70e072011-01-03 15:33:37 -03003523
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003524 while ((active == 1) && (systime() < callback_time))
3525 msleep(100);
3526 } while (active);
Olivier Grenie4c70e072011-01-03 15:33:37 -03003527
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003528 /* set output mode */
3529 if (state->revision != 0x8090)
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003530 dib8000_set_output_mode(state->fe[0], state->cfg.output_mode);
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003531 else {
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003532 dib8096p_set_output_mode(state->fe[0], state->cfg.output_mode);
3533 if (state->cfg.enMpegOutput == 0) {
3534 dib8096p_setDibTxMux(state, MPEG_ON_DIBTX);
3535 dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
3536 }
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003537 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003538
3539 return ret;
3540}
3541
3542static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
3543{
3544 struct dib8000_state *state = fe->demodulator_priv;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003545 u16 lock_slave = 0, lock;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003546 u8 index_frontend;
3547
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003548 lock = dib8000_read_lock(fe);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003549 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
Olivier Grenie4c70e072011-01-03 15:33:37 -03003550 lock_slave |= dib8000_read_lock(state->fe[index_frontend]);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003551
3552 *stat = 0;
3553
Olivier Grenie4c70e072011-01-03 15:33:37 -03003554 if (((lock >> 13) & 1) || ((lock_slave >> 13) & 1))
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003555 *stat |= FE_HAS_SIGNAL;
3556
Olivier Grenie4c70e072011-01-03 15:33:37 -03003557 if (((lock >> 8) & 1) || ((lock_slave >> 8) & 1)) /* Equal */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003558 *stat |= FE_HAS_CARRIER;
3559
Olivier Grenie4c70e072011-01-03 15:33:37 -03003560 if ((((lock >> 1) & 0xf) == 0xf) || (((lock_slave >> 1) & 0xf) == 0xf)) /* TMCC_SYNC */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003561 *stat |= FE_HAS_SYNC;
3562
Olivier Grenie4c70e072011-01-03 15:33:37 -03003563 if ((((lock >> 12) & 1) || ((lock_slave >> 12) & 1)) && ((lock >> 5) & 7)) /* FEC MPEG */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003564 *stat |= FE_HAS_LOCK;
3565
Olivier Grenie4c70e072011-01-03 15:33:37 -03003566 if (((lock >> 12) & 1) || ((lock_slave >> 12) & 1)) {
Olivier Grenie89dfc552009-11-30 06:38:49 -03003567 lock = dib8000_read_word(state, 554); /* Viterbi Layer A */
3568 if (lock & 0x01)
3569 *stat |= FE_HAS_VITERBI;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003570
Olivier Grenie89dfc552009-11-30 06:38:49 -03003571 lock = dib8000_read_word(state, 555); /* Viterbi Layer B */
3572 if (lock & 0x01)
3573 *stat |= FE_HAS_VITERBI;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003574
Olivier Grenie89dfc552009-11-30 06:38:49 -03003575 lock = dib8000_read_word(state, 556); /* Viterbi Layer C */
3576 if (lock & 0x01)
3577 *stat |= FE_HAS_VITERBI;
3578 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003579
3580 return 0;
3581}
3582
3583static int dib8000_read_ber(struct dvb_frontend *fe, u32 * ber)
3584{
3585 struct dib8000_state *state = fe->demodulator_priv;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003586
3587 /* 13 segments */
3588 if (state->revision == 0x8090)
3589 *ber = (dib8000_read_word(state, 562) << 16) |
3590 dib8000_read_word(state, 563);
3591 else
3592 *ber = (dib8000_read_word(state, 560) << 16) |
3593 dib8000_read_word(state, 561);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003594 return 0;
3595}
3596
3597static int dib8000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
3598{
3599 struct dib8000_state *state = fe->demodulator_priv;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003600
3601 /* packet error on 13 seg */
3602 if (state->revision == 0x8090)
3603 *unc = dib8000_read_word(state, 567);
3604 else
3605 *unc = dib8000_read_word(state, 565);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003606 return 0;
3607}
3608
3609static int dib8000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
3610{
3611 struct dib8000_state *state = fe->demodulator_priv;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003612 u8 index_frontend;
3613 u16 val;
3614
3615 *strength = 0;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003616 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003617 state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val);
3618 if (val > 65535 - *strength)
3619 *strength = 65535;
3620 else
3621 *strength += val;
3622 }
3623
3624 val = 65535 - dib8000_read_word(state, 390);
3625 if (val > 65535 - *strength)
3626 *strength = 65535;
3627 else
3628 *strength += val;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003629 return 0;
3630}
3631
Olivier Grenie4c70e072011-01-03 15:33:37 -03003632static u32 dib8000_get_snr(struct dvb_frontend *fe)
3633{
3634 struct dib8000_state *state = fe->demodulator_priv;
3635 u32 n, s, exp;
3636 u16 val;
3637
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003638 if (state->revision != 0x8090)
3639 val = dib8000_read_word(state, 542);
3640 else
3641 val = dib8000_read_word(state, 544);
Olivier Grenie4c70e072011-01-03 15:33:37 -03003642 n = (val >> 6) & 0xff;
3643 exp = (val & 0x3f);
3644 if ((exp & 0x20) != 0)
3645 exp -= 0x40;
3646 n <<= exp+16;
3647
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003648 if (state->revision != 0x8090)
3649 val = dib8000_read_word(state, 543);
3650 else
3651 val = dib8000_read_word(state, 545);
Olivier Grenie4c70e072011-01-03 15:33:37 -03003652 s = (val >> 6) & 0xff;
3653 exp = (val & 0x3f);
3654 if ((exp & 0x20) != 0)
3655 exp -= 0x40;
3656 s <<= exp+16;
3657
3658 if (n > 0) {
3659 u32 t = (s/n) << 16;
3660 return t + ((s << 16) - n*t) / n;
3661 }
3662 return 0xffffffff;
3663}
3664
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003665static int dib8000_read_snr(struct dvb_frontend *fe, u16 * snr)
3666{
3667 struct dib8000_state *state = fe->demodulator_priv;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003668 u8 index_frontend;
3669 u32 snr_master;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003670
Olivier Grenie4c70e072011-01-03 15:33:37 -03003671 snr_master = dib8000_get_snr(fe);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003672 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
Olivier Grenie4c70e072011-01-03 15:33:37 -03003673 snr_master += dib8000_get_snr(state->fe[index_frontend]);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003674
Olivier Grenie1f6bfcc2011-07-04 12:33:54 -03003675 if ((snr_master >> 16) != 0) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003676 snr_master = 10*intlog10(snr_master>>16);
3677 *snr = snr_master / ((1 << 24) / 10);
3678 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003679 else
Olivier Grenie4c70e072011-01-03 15:33:37 -03003680 *snr = 0;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003681
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003682 return 0;
3683}
3684
Olivier Grenie4c70e072011-01-03 15:33:37 -03003685int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
3686{
3687 struct dib8000_state *state = fe->demodulator_priv;
3688 u8 index_frontend = 1;
3689
3690 while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
3691 index_frontend++;
3692 if (index_frontend < MAX_NUMBER_OF_FRONTENDS) {
3693 dprintk("set slave fe %p to index %i", fe_slave, index_frontend);
3694 state->fe[index_frontend] = fe_slave;
3695 return 0;
3696 }
3697
3698 dprintk("too many slave frontend");
3699 return -ENOMEM;
3700}
3701EXPORT_SYMBOL(dib8000_set_slave_frontend);
3702
3703int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
3704{
3705 struct dib8000_state *state = fe->demodulator_priv;
3706 u8 index_frontend = 1;
3707
3708 while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
3709 index_frontend++;
3710 if (index_frontend != 1) {
3711 dprintk("remove slave fe %p (index %i)", state->fe[index_frontend-1], index_frontend-1);
3712 state->fe[index_frontend] = NULL;
3713 return 0;
3714 }
3715
3716 dprintk("no frontend to be removed");
3717 return -ENODEV;
3718}
3719EXPORT_SYMBOL(dib8000_remove_slave_frontend);
3720
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003721struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
Olivier Grenie4c70e072011-01-03 15:33:37 -03003722{
3723 struct dib8000_state *state = fe->demodulator_priv;
3724
3725 if (slave_index >= MAX_NUMBER_OF_FRONTENDS)
3726 return NULL;
3727 return state->fe[slave_index];
3728}
3729EXPORT_SYMBOL(dib8000_get_slave_frontend);
3730
3731
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003732int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
3733 u8 default_addr, u8 first_addr, u8 is_dib8096p)
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003734{
Olivier Grenie5a0deee2011-05-03 12:27:33 -03003735 int k = 0, ret = 0;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003736 u8 new_addr = 0;
3737 struct i2c_device client = {.adap = host };
3738
Olivier Grenie5a0deee2011-05-03 12:27:33 -03003739 client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
3740 if (!client.i2c_write_buffer) {
3741 dprintk("%s: not enough memory", __func__);
3742 return -ENOMEM;
3743 }
3744 client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
3745 if (!client.i2c_read_buffer) {
3746 dprintk("%s: not enough memory", __func__);
3747 ret = -ENOMEM;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03003748 goto error_memory_read;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03003749 }
Patrick Boettcher79fcce32011-08-03 12:08:21 -03003750 client.i2c_buffer_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL);
3751 if (!client.i2c_buffer_lock) {
3752 dprintk("%s: not enough memory", __func__);
3753 ret = -ENOMEM;
3754 goto error_memory_lock;
3755 }
3756 mutex_init(client.i2c_buffer_lock);
Olivier Grenie5a0deee2011-05-03 12:27:33 -03003757
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003758 for (k = no_of_demods - 1; k >= 0; k--) {
3759 /* designated i2c address */
3760 new_addr = first_addr + (k << 1);
3761
3762 client.addr = new_addr;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003763 if (!is_dib8096p)
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003764 dib8000_i2c_write16(&client, 1287, 0x0003); /* sram lead in, rdy */
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003765 if (dib8000_identify(&client) == 0) {
3766 /* sram lead in, rdy */
3767 if (!is_dib8096p)
3768 dib8000_i2c_write16(&client, 1287, 0x0003);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003769 client.addr = default_addr;
3770 if (dib8000_identify(&client) == 0) {
3771 dprintk("#%d: not identified", k);
Olivier Grenie5a0deee2011-05-03 12:27:33 -03003772 ret = -EINVAL;
3773 goto error;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003774 }
3775 }
3776
3777 /* start diversity to pull_down div_str - just for i2c-enumeration */
3778 dib8000_i2c_write16(&client, 1286, (1 << 10) | (4 << 6));
3779
3780 /* set new i2c address and force divstart */
3781 dib8000_i2c_write16(&client, 1285, (new_addr << 2) | 0x2);
3782 client.addr = new_addr;
3783 dib8000_identify(&client);
3784
3785 dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
3786 }
3787
3788 for (k = 0; k < no_of_demods; k++) {
3789 new_addr = first_addr | (k << 1);
3790 client.addr = new_addr;
3791
3792 // unforce divstr
3793 dib8000_i2c_write16(&client, 1285, new_addr << 2);
3794
3795 /* deactivate div - it was just for i2c-enumeration */
3796 dib8000_i2c_write16(&client, 1286, 0);
3797 }
3798
Olivier Grenie5a0deee2011-05-03 12:27:33 -03003799error:
Patrick Boettcher79fcce32011-08-03 12:08:21 -03003800 kfree(client.i2c_buffer_lock);
3801error_memory_lock:
Olivier Grenie5a0deee2011-05-03 12:27:33 -03003802 kfree(client.i2c_read_buffer);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03003803error_memory_read:
Olivier Grenie5a0deee2011-05-03 12:27:33 -03003804 kfree(client.i2c_write_buffer);
3805
3806 return ret;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003807}
3808
3809EXPORT_SYMBOL(dib8000_i2c_enumeration);
3810static int dib8000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
3811{
3812 tune->min_delay_ms = 1000;
3813 tune->step_size = 0;
3814 tune->max_drift = 0;
3815 return 0;
3816}
3817
3818static void dib8000_release(struct dvb_frontend *fe)
3819{
3820 struct dib8000_state *st = fe->demodulator_priv;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003821 u8 index_frontend;
3822
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003823 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (st->fe[index_frontend] != NULL); index_frontend++)
Olivier Grenie4c70e072011-01-03 15:33:37 -03003824 dvb_frontend_detach(st->fe[index_frontend]);
3825
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003826 dibx000_exit_i2c_master(&st->i2c_master);
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003827 i2c_del_adapter(&st->dib8096p_tuner_adap);
Olivier Grenie4c70e072011-01-03 15:33:37 -03003828 kfree(st->fe[0]);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003829 kfree(st);
3830}
3831
3832struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
3833{
3834 struct dib8000_state *st = fe->demodulator_priv;
3835 return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
3836}
3837
3838EXPORT_SYMBOL(dib8000_get_i2c_master);
3839
Olivier Grenief8731f42009-09-18 04:08:43 -03003840int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
3841{
3842 struct dib8000_state *st = fe->demodulator_priv;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003843 u16 val = dib8000_read_word(st, 299) & 0xffef;
3844 val |= (onoff & 0x1) << 4;
Olivier Grenief8731f42009-09-18 04:08:43 -03003845
Olivier Grenie4c70e072011-01-03 15:33:37 -03003846 dprintk("pid filter enabled %d", onoff);
3847 return dib8000_write_word(st, 299, val);
Olivier Grenief8731f42009-09-18 04:08:43 -03003848}
3849EXPORT_SYMBOL(dib8000_pid_filter_ctrl);
3850
3851int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
3852{
3853 struct dib8000_state *st = fe->demodulator_priv;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003854 dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
3855 return dib8000_write_word(st, 305 + id, onoff ? (1 << 13) | pid : 0);
Olivier Grenief8731f42009-09-18 04:08:43 -03003856}
3857EXPORT_SYMBOL(dib8000_pid_filter);
3858
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003859static const struct dvb_frontend_ops dib8000_ops = {
Mauro Carvalho Chehab490ecd62011-12-22 20:38:27 -03003860 .delsys = { SYS_ISDBT },
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003861 .info = {
3862 .name = "DiBcom 8000 ISDB-T",
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003863 .frequency_min = 44250000,
3864 .frequency_max = 867250000,
3865 .frequency_stepsize = 62500,
3866 .caps = FE_CAN_INVERSION_AUTO |
3867 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
3868 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
3869 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
3870 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
3871 },
3872
3873 .release = dib8000_release,
3874
3875 .init = dib8000_wakeup,
3876 .sleep = dib8000_sleep,
3877
Mauro Carvalho Chehab490ecd62011-12-22 20:38:27 -03003878 .set_frontend = dib8000_set_frontend,
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003879 .get_tune_settings = dib8000_fe_get_tune_settings,
Mauro Carvalho Chehab490ecd62011-12-22 20:38:27 -03003880 .get_frontend = dib8000_get_frontend,
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003881
3882 .read_status = dib8000_read_status,
3883 .read_ber = dib8000_read_ber,
3884 .read_signal_strength = dib8000_read_signal_strength,
3885 .read_snr = dib8000_read_snr,
3886 .read_ucblocks = dib8000_read_unc_blocks,
3887};
3888
3889struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
3890{
3891 struct dvb_frontend *fe;
3892 struct dib8000_state *state;
3893
3894 dprintk("dib8000_attach");
3895
3896 state = kzalloc(sizeof(struct dib8000_state), GFP_KERNEL);
3897 if (state == NULL)
3898 return NULL;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003899 fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL);
3900 if (fe == NULL)
Dan Carpentered54c0e2011-01-19 11:27:58 -03003901 goto error;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003902
3903 memcpy(&state->cfg, cfg, sizeof(struct dib8000_config));
3904 state->i2c.adap = i2c_adap;
3905 state->i2c.addr = i2c_addr;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03003906 state->i2c.i2c_write_buffer = state->i2c_write_buffer;
3907 state->i2c.i2c_read_buffer = state->i2c_read_buffer;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03003908 mutex_init(&state->i2c_buffer_lock);
3909 state->i2c.i2c_buffer_lock = &state->i2c_buffer_lock;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003910 state->gpio_val = cfg->gpio_val;
3911 state->gpio_dir = cfg->gpio_dir;
3912
3913 /* Ensure the output mode remains at the previous default if it's
3914 * not specifically set by the caller.
3915 */
3916 if ((state->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (state->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
3917 state->cfg.output_mode = OUTMODE_MPEG2_FIFO;
3918
Olivier Grenie4c70e072011-01-03 15:33:37 -03003919 state->fe[0] = fe;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003920 fe->demodulator_priv = state;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003921 memcpy(&state->fe[0]->ops, &dib8000_ops, sizeof(struct dvb_frontend_ops));
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003922
3923 state->timf_default = cfg->pll->timf;
3924
3925 if (dib8000_identify(&state->i2c) == 0)
3926 goto error;
3927
3928 dibx000_init_i2c_master(&state->i2c_master, DIB8000, state->i2c.adap, state->i2c.addr);
3929
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003930 /* init 8096p tuner adapter */
3931 strncpy(state->dib8096p_tuner_adap.name, "DiB8096P tuner interface",
3932 sizeof(state->dib8096p_tuner_adap.name));
3933 state->dib8096p_tuner_adap.algo = &dib8096p_tuner_xfer_algo;
3934 state->dib8096p_tuner_adap.algo_data = NULL;
3935 state->dib8096p_tuner_adap.dev.parent = state->i2c.adap->dev.parent;
3936 i2c_set_adapdata(&state->dib8096p_tuner_adap, state);
3937 i2c_add_adapter(&state->dib8096p_tuner_adap);
3938
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003939 dib8000_reset(fe);
3940
3941 dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5)); /* ber_rs_len = 3 */
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003942 state->current_demod_bw = 6000;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003943
3944 return fe;
3945
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003946error:
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003947 kfree(state);
3948 return NULL;
3949}
3950
3951EXPORT_SYMBOL(dib8000_attach);
3952
3953MODULE_AUTHOR("Olivier Grenie <Olivier.Grenie@dibcom.fr, " "Patrick Boettcher <pboettcher@dibcom.fr>");
3954MODULE_DESCRIPTION("Driver for the DiBcom 8000 ISDB-T demodulator");
3955MODULE_LICENSE("GPL");