blob: 1d719cce89959e3da71eff79c3d071b5773f5530 [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
2412u32 dib8000_wait_lock(struct dib8000_state *state, u32 internal, u32 wait0_ms, u32 wait1_ms, u32 wait2_ms)
2413{
2414 u32 value;
2415 u16 reg = 11; /* P_search_end0 start addr */
2416
2417 for (reg = 11; reg < 16; reg += 2) {
2418 if (reg == 11) {
2419 if (state->revision == 0x8090)
2420 value = internal * wait1_ms; /* P_search_end0 wait time */
2421 else
2422 value = internal * wait0_ms; /* P_search_end0 wait time */
2423 } else if (reg == 13)
2424 value = internal * wait1_ms; /* P_search_end0 wait time */
2425 else if (reg == 15)
2426 value = internal * wait2_ms; /* P_search_end0 wait time */
2427 dib8000_write_word(state, reg, (u16)((value >> 16) & 0xffff));
2428 dib8000_write_word(state, (reg + 1), (u16)(value & 0xffff));
2429 }
2430 return value;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002431}
2432
2433static int dib8000_autosearch_start(struct dvb_frontend *fe)
2434{
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002435 struct dib8000_state *state = fe->demodulator_priv;
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002436 u8 slist = 0;
2437 u32 value, internal = state->cfg.pll->internal;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002438
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002439 if (state->revision == 0x8090)
2440 internal = dib8000_read32(state, 23) / 1000;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002441
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002442 if (state->autosearch_state == AS_SEARCHING_FFT) {
2443 dib8000_write_word(state, 37, 0x0065); /* P_ctrl_pha_off_max default values */
2444 dib8000_write_word(state, 116, 0x0000); /* P_ana_gain to 0 */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002445
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002446 dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x1fff) | (0 << 13) | (1 << 15)); /* P_mode = 0, P_restart_search=1 */
2447 dib8000_write_word(state, 1, (dib8000_read_word(state, 1) & 0xfffc) | 0); /* P_guard = 0 */
2448 dib8000_write_word(state, 6, 0); /* P_lock0_mask = 0 */
2449 dib8000_write_word(state, 7, 0); /* P_lock1_mask = 0 */
2450 dib8000_write_word(state, 8, 0); /* P_lock2_mask = 0 */
2451 dib8000_write_word(state, 10, (dib8000_read_word(state, 10) & 0x200) | (16 << 4) | (0 << 0)); /* P_search_list=16, P_search_maxtrial=0 */
2452
2453 if (state->revision == 0x8090)
2454 value = dib8000_wait_lock(state, internal, 10, 10, 10); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
2455 else
2456 value = dib8000_wait_lock(state, internal, 20, 20, 20); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
2457
2458 dib8000_write_word(state, 17, 0);
2459 dib8000_write_word(state, 18, 200); /* P_search_rstst = 200 */
2460 dib8000_write_word(state, 19, 0);
2461 dib8000_write_word(state, 20, 400); /* P_search_rstend = 400 */
2462 dib8000_write_word(state, 21, (value >> 16) & 0xffff); /* P_search_checkst */
2463 dib8000_write_word(state, 22, value & 0xffff);
2464
2465 if (state->revision == 0x8090)
2466 dib8000_write_word(state, 32, (dib8000_read_word(state, 32) & 0xf0ff) | (0 << 8)); /* P_corm_alpha = 0 */
2467 else
2468 dib8000_write_word(state, 32, (dib8000_read_word(state, 32) & 0xf0ff) | (9 << 8)); /* P_corm_alpha = 3 */
2469 dib8000_write_word(state, 355, 2); /* P_search_param_max = 2 */
2470
2471 /* P_search_param_select = (1 | 1<<4 | 1 << 8) */
2472 dib8000_write_word(state, 356, 0);
2473 dib8000_write_word(state, 357, 0x111);
2474
2475 dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (1 << 13)); /* P_restart_ccg = 1 */
2476 dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (0 << 13)); /* P_restart_ccg = 0 */
2477 dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x7ff) | (0 << 15) | (1 << 13)); /* P_restart_search = 0; */
2478 } else if (state->autosearch_state == AS_SEARCHING_GUARD) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03002479 state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
2480 state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002481 state->fe[0]->dtv_property_cache.inversion = 0;
2482 state->fe[0]->dtv_property_cache.layer[0].modulation = QAM_64;
2483 state->fe[0]->dtv_property_cache.layer[0].fec = FEC_2_3;
2484 state->fe[0]->dtv_property_cache.layer[0].interleaving = 0;
2485 state->fe[0]->dtv_property_cache.layer[0].segment_count = 13;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002486
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002487 slist = 16;
2488 state->fe[0]->dtv_property_cache.transmission_mode = state->found_nfft;
Patrick Boettcher78f3bc62009-08-17 12:53:51 -03002489
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002490 dib8000_set_isdbt_common_channel(state, slist, 1);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002491
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002492 /* set lock_mask values */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002493 dib8000_write_word(state, 6, 0x4);
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002494 if (state->revision == 0x8090)
2495 dib8000_write_word(state, 7, ((1 << 12) | (1 << 11) | (1 << 10)));/* tmcc_dec_lock, tmcc_sync_lock, tmcc_data_lock, tmcc_bch_uncor */
2496 else
2497 dib8000_write_word(state, 7, 0x8);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002498 dib8000_write_word(state, 8, 0x1000);
2499
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002500 /* set lock_mask wait time values */
2501 if (state->revision == 0x8090)
2502 dib8000_wait_lock(state, internal, 50, 100, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
2503 else
2504 dib8000_wait_lock(state, internal, 50, 200, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
2505
2506 dib8000_write_word(state, 355, 3); /* P_search_param_max = 3 */
2507
2508 /* P_search_param_select = 0xf; look for the 4 different guard intervals */
2509 dib8000_write_word(state, 356, 0);
2510 dib8000_write_word(state, 357, 0xf);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002511
2512 value = dib8000_read_word(state, 0);
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002513 dib8000_write_word(state, 0, (u16)((1 << 15) | value));
2514 dib8000_read_word(state, 1284); /* reset the INT. n_irq_pending */
2515 dib8000_write_word(state, 0, (u16)value);
2516 } else {
2517 state->fe[0]->dtv_property_cache.inversion = 0;
2518 state->fe[0]->dtv_property_cache.layer[0].modulation = QAM_64;
2519 state->fe[0]->dtv_property_cache.layer[0].fec = FEC_2_3;
2520 state->fe[0]->dtv_property_cache.layer[0].interleaving = 0;
2521 state->fe[0]->dtv_property_cache.layer[0].segment_count = 13;
2522 if (!state->fe[0]->dtv_property_cache.isdbt_sb_mode)
2523 state->fe[0]->dtv_property_cache.layer[0].segment_count = 13;
Patrick Boettcher78f3bc62009-08-17 12:53:51 -03002524
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002525 /* choose the right list, in sb, always do everything */
2526 if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
2527 slist = 7;
2528 dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));
2529 } else {
2530 if (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) {
2531 if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) {
2532 state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
2533 state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
2534 slist = 7;
2535 dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); /* P_mode = 1 to have autosearch start ok with mode2 */
2536 } else {
2537 state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
2538 slist = 3;
2539 }
2540 } else {
2541 if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) {
2542 state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
2543 slist = 2;
2544 dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); /* P_mode = 1 */
2545 } else
2546 slist = 0;
2547 }
2548 }
2549 dprintk("Using list for autosearch : %d", slist);
2550
2551 dib8000_set_isdbt_common_channel(state, slist, 1);
2552
2553 /* set lock_mask values */
2554 dib8000_write_word(state, 6, 0x4);
2555 if (state->revision == 0x8090)
2556 dib8000_write_word(state, 7, (1 << 12) | (1 << 11) | (1 << 10));
2557 else
2558 dib8000_write_word(state, 7, 0x8);
2559 dib8000_write_word(state, 8, 0x1000);
2560
2561 /* set lock_mask wait time values */
2562 if (state->revision == 0x8090)
2563 dib8000_wait_lock(state, internal, 50, 200, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
2564 else
2565 dib8000_wait_lock(state, internal, 50, 100, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
2566
2567 value = dib8000_read_word(state, 0);
2568 dib8000_write_word(state, 0, (u16)((1 << 15) | value));
2569 dib8000_read_word(state, 1284); /* reset the INT. n_irq_pending */
2570 dib8000_write_word(state, 0, (u16)value);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002571 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002572 return 0;
2573}
2574
2575static int dib8000_autosearch_irq(struct dvb_frontend *fe)
2576{
2577 struct dib8000_state *state = fe->demodulator_priv;
2578 u16 irq_pending = dib8000_read_word(state, 1284);
2579
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002580 if (state->autosearch_state == AS_SEARCHING_FFT) {
2581 if (irq_pending & 0x1) {
2582 dprintk("dib8000_autosearch_irq: max correlation result available");
2583 return 3;
2584 }
2585 } else {
2586 if (irq_pending & 0x1) { /* failed */
2587 dprintk("dib8000_autosearch_irq failed");
2588 return 1;
2589 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002590
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002591 if (irq_pending & 0x2) { /* succeeded */
2592 dprintk("dib8000_autosearch_irq succeeded");
2593 return 2;
2594 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002595 }
2596
2597 return 0; // still pending
2598}
2599
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002600static void dib8000_viterbi_state(struct dib8000_state *state, u8 onoff)
2601{
2602 u16 tmp;
2603
2604 tmp = dib8000_read_word(state, 771);
2605 if (onoff) /* start P_restart_chd : channel_decoder */
2606 dib8000_write_word(state, 771, tmp & 0xfffd);
2607 else /* stop P_restart_chd : channel_decoder */
2608 dib8000_write_word(state, 771, tmp | (1<<1));
2609}
2610
2611static void dib8000_set_dds(struct dib8000_state *state, s32 offset_khz)
2612{
2613 s16 unit_khz_dds_val;
2614 u32 abs_offset_khz = ABS(offset_khz);
2615 u32 dds = state->cfg.pll->ifreq & 0x1ffffff;
2616 u8 invert = !!(state->cfg.pll->ifreq & (1 << 25));
2617 u8 ratio;
2618
2619 if (state->revision == 0x8090) {
2620 ratio = 4;
2621 unit_khz_dds_val = (1<<26) / (dib8000_read32(state, 23) / 1000);
2622 if (offset_khz < 0)
2623 dds = (1 << 26) - (abs_offset_khz * unit_khz_dds_val);
2624 else
2625 dds = (abs_offset_khz * unit_khz_dds_val);
2626
2627 if (invert)
2628 dds = (1<<26) - dds;
2629 } else {
2630 ratio = 2;
2631 unit_khz_dds_val = (u16) (67108864 / state->cfg.pll->internal);
2632
2633 if (offset_khz < 0)
2634 unit_khz_dds_val *= -1;
2635
2636 /* IF tuner */
2637 if (invert)
2638 dds -= abs_offset_khz * unit_khz_dds_val;
2639 else
2640 dds += abs_offset_khz * unit_khz_dds_val;
2641 }
2642
2643 dprintk("setting a DDS frequency offset of %c%dkHz", invert ? '-' : ' ', dds / unit_khz_dds_val);
2644
2645 if (abs_offset_khz <= (state->cfg.pll->internal / ratio)) {
2646 /* Max dds offset is the half of the demod freq */
2647 dib8000_write_word(state, 26, invert);
2648 dib8000_write_word(state, 27, (u16)(dds >> 16) & 0x1ff);
2649 dib8000_write_word(state, 28, (u16)(dds & 0xffff));
2650 }
2651}
2652
2653static void dib8000_set_frequency_offset(struct dib8000_state *state)
2654{
2655 int i;
2656 u32 current_rf;
2657 int total_dds_offset_khz;
2658
2659 if (state->fe[0]->ops.tuner_ops.get_frequency)
2660 state->fe[0]->ops.tuner_ops.get_frequency(state->fe[0], &current_rf);
2661 else
2662 current_rf = state->fe[0]->dtv_property_cache.frequency;
2663 current_rf /= 1000;
2664 total_dds_offset_khz = (int)current_rf - (int)state->fe[0]->dtv_property_cache.frequency / 1000;
2665
2666 if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
2667 state->subchannel = state->fe[0]->dtv_property_cache.isdbt_sb_subchannel;
2668
2669 i = dib8000_read_word(state, 26) & 1; /* P_dds_invspec */
2670 dib8000_write_word(state, 26, state->fe[0]->dtv_property_cache.inversion ^ i);
2671
2672 if (state->cfg.pll->ifreq == 0) { /* low if tuner */
2673 if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0)
2674 dib8000_write_word(state, 26, dib8000_read_word(state, 26) | 1);
2675 } else {
2676 if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0)
2677 total_dds_offset_khz *= -1;
2678 }
2679 }
2680
2681 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);
2682
2683 /* apply dds offset now */
2684 dib8000_set_dds(state, total_dds_offset_khz);
2685}
2686
2687static u16 LUT_isdbt_symbol_duration[4] = { 26, 101, 63 };
2688u32 dib8000_get_symbol_duration(struct dib8000_state *state)
2689{
2690 u16 i;
2691
2692 switch (state->fe[0]->dtv_property_cache.transmission_mode) {
2693 case TRANSMISSION_MODE_2K:
2694 i = 0;
2695 break;
2696 case TRANSMISSION_MODE_4K:
2697 i = 2;
2698 break;
2699 default:
2700 case TRANSMISSION_MODE_AUTO:
2701 case TRANSMISSION_MODE_8K:
2702 i = 1;
2703 break;
2704 }
2705
2706 return (LUT_isdbt_symbol_duration[i] / (state->fe[0]->dtv_property_cache.bandwidth_hz / 1000)) + 1;
2707}
2708
2709static void dib8000_set_isdbt_loop_params(struct dib8000_state *state, enum param_loop_step loop_step)
2710{
2711 u16 reg_32 = 0, reg_37 = 0;
2712
2713 switch (loop_step) {
2714 case LOOP_TUNE_1:
2715 if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
2716 if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
2717 reg_32 = ((11 - state->mode) << 12) | (6 << 8) | 0x40; /* P_timf_alpha = (11-P_mode), P_corm_alpha=6, P_corm_thres=0x40 */
2718 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) */
2719 } else { /* Sound Broadcasting mode 3 seg */
2720 reg_32 = ((10 - state->mode) << 12) | (6 << 8) | 0x60; /* P_timf_alpha = (10-P_mode), P_corm_alpha=6, P_corm_thres=0x60 */
2721 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) */
2722 }
2723 } else { /* 13-seg start conf offset loop parameters */
2724 reg_32 = ((9 - state->mode) << 12) | (6 << 8) | 0x80; /* P_timf_alpha = (9-P_mode, P_corm_alpha=6, P_corm_thres=0x80 */
2725 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 */
2726 }
2727 break;
2728 case LOOP_TUNE_2:
2729 if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
2730 if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) { /* Sound Broadcasting mode 1 seg */
2731 reg_32 = ((13-state->mode) << 12) | (6 << 8) | 0x40; /* P_timf_alpha = (13-P_mode) , P_corm_alpha=6, P_corm_thres=0x40*/
2732 reg_37 = (12-state->mode) | ((5 + state->mode) << 5);
2733 } else { /* Sound Broadcasting mode 3 seg */
2734 reg_32 = ((12-state->mode) << 12) | (6 << 8) | 0x60; /* P_timf_alpha = (12-P_mode) , P_corm_alpha=6, P_corm_thres=0x60 */
2735 reg_37 = (11-state->mode) | ((5 + state->mode) << 5);
2736 }
2737 } else { /* 13 seg */
2738 reg_32 = ((11-state->mode) << 12) | (6 << 8) | 0x80; /* P_timf_alpha = 8 , P_corm_alpha=6, P_corm_thres=0x80 */
2739 reg_37 = ((5+state->mode) << 5) | (10 - state->mode);
2740 }
2741 break;
2742 }
2743 dib8000_write_word(state, 32, reg_32);
2744 dib8000_write_word(state, 37, reg_37);
2745}
2746
2747static void dib8000_demod_restart(struct dib8000_state *state)
2748{
2749 dib8000_write_word(state, 770, 0x4000);
2750 dib8000_write_word(state, 770, 0x0000);
2751 return;
2752}
2753
2754static void dib8000_set_sync_wait(struct dib8000_state *state)
2755{
2756 u16 sync_wait = 64;
2757
2758 /* P_dvsy_sync_wait - reuse mode */
2759 switch (state->fe[0]->dtv_property_cache.transmission_mode) {
2760 case TRANSMISSION_MODE_8K:
2761 sync_wait = 256;
2762 break;
2763 case TRANSMISSION_MODE_4K:
2764 sync_wait = 128;
2765 break;
2766 default:
2767 case TRANSMISSION_MODE_2K:
2768 sync_wait = 64;
2769 break;
2770 }
2771
2772 if (state->cfg.diversity_delay == 0)
2773 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 */
2774 else
2775 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 */
2776
2777 dib8000_write_word(state, 273, (dib8000_read_word(state, 273) & 0x000f) | (sync_wait << 4));
2778}
2779
2780static u32 dib8000_get_timeout(struct dib8000_state *state, u32 delay, enum timeout_mode mode)
2781{
2782 if (mode == SYMBOL_DEPENDENT_ON)
2783 return systime() + (delay * state->symbol_duration);
2784 else
2785 return systime() + delay;
2786}
2787
2788static s32 dib8000_get_status(struct dvb_frontend *fe)
2789{
2790 struct dib8000_state *state = fe->demodulator_priv;
2791 return state->status;
2792}
2793
2794enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
2795{
2796 struct dib8000_state *state = fe->demodulator_priv;
2797 return state->tune_state;
2798}
2799EXPORT_SYMBOL(dib8000_get_tune_state);
2800
2801int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
2802{
2803 struct dib8000_state *state = fe->demodulator_priv;
2804
2805 state->tune_state = tune_state;
2806 return 0;
2807}
2808EXPORT_SYMBOL(dib8000_set_tune_state);
2809
2810static int dib8000_tune_restart_from_demod(struct dvb_frontend *fe)
2811{
2812 struct dib8000_state *state = fe->demodulator_priv;
2813
2814 state->status = FE_STATUS_TUNE_PENDING;
2815 state->tune_state = CT_DEMOD_START;
2816 return 0;
2817}
2818
2819static u16 dib8000_read_lock(struct dvb_frontend *fe)
2820{
2821 struct dib8000_state *state = fe->demodulator_priv;
2822
2823 if (state->revision == 0x8090)
2824 return dib8000_read_word(state, 570);
2825 return dib8000_read_word(state, 568);
2826}
2827
2828static int dib8090p_init_sdram(struct dib8000_state *state)
2829{
2830 u16 reg = 0;
2831 dprintk("init sdram");
2832
2833 reg = dib8000_read_word(state, 274) & 0xfff0;
2834 dib8000_write_word(state, 274, reg | 0x7); /* P_dintlv_delay_ram = 7 because of MobileSdram */
2835
2836 dib8000_write_word(state, 1803, (7 << 2));
2837
2838 reg = dib8000_read_word(state, 1280);
2839 dib8000_write_word(state, 1280, reg | (1 << 2)); /* force restart P_restart_sdram */
2840 dib8000_write_word(state, 1280, reg); /* release restart P_restart_sdram */
2841
2842 return 0;
2843}
2844
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002845static int dib8000_tune(struct dvb_frontend *fe)
2846{
2847 struct dib8000_state *state = fe->demodulator_priv;
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002848 enum frontend_tune_state *tune_state = &state->tune_state;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002849
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002850 u16 locks, deeper_interleaver = 0, i;
2851 int ret = 1; /* 1 symbol duration (in 100us unit) delay most of the time */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002852
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002853 u32 *timeout = &state->timeout;
2854 u32 now = systime();
2855#ifdef DIB8000_AGC_FREEZE
2856 u16 agc1, agc2;
2857#endif
Dan Carpentere04f4b22012-07-20 07:11:57 -03002858
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002859 u32 corm[4] = {0, 0, 0, 0};
2860 u8 find_index, max_value;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002861
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002862#if 0
2863 if (*tune_state < CT_DEMOD_STOP)
2864 dprintk("IN: context status = %d, TUNE_STATE %d autosearch step = %u systime = %u", state->channel_parameters_set, *tune_state, state->autosearch_state, now);
2865#endif
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002866
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002867 switch (*tune_state) {
2868 case CT_DEMOD_START: /* 30 */
2869 if (state->revision == 0x8090)
2870 dib8090p_init_sdram(state);
2871 state->status = FE_STATUS_TUNE_PENDING;
2872 if ((state->fe[0]->dtv_property_cache.delivery_system != SYS_ISDBT) ||
2873 (state->fe[0]->dtv_property_cache.inversion == INVERSION_AUTO) ||
2874 (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) ||
2875 (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) ||
2876 (((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) != 0) &&
2877 (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0xff) &&
2878 (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0) &&
2879 ((state->fe[0]->dtv_property_cache.layer[0].modulation == QAM_AUTO) ||
2880 (state->fe[0]->dtv_property_cache.layer[0].fec == FEC_AUTO))) ||
2881 (((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 1)) != 0) &&
2882 (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0xff) &&
2883 (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0) &&
2884 ((state->fe[0]->dtv_property_cache.layer[1].modulation == QAM_AUTO) ||
2885 (state->fe[0]->dtv_property_cache.layer[1].fec == FEC_AUTO))) ||
2886 (((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 2)) != 0) &&
2887 (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0xff) &&
2888 (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0) &&
2889 ((state->fe[0]->dtv_property_cache.layer[2].modulation == QAM_AUTO) ||
2890 (state->fe[0]->dtv_property_cache.layer[2].fec == FEC_AUTO))) ||
2891 (((state->fe[0]->dtv_property_cache.layer[0].segment_count == 0) ||
2892 ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) == 0)) &&
2893 ((state->fe[0]->dtv_property_cache.layer[1].segment_count == 0) ||
2894 ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (2 << 0)) == 0)) &&
2895 ((state->fe[0]->dtv_property_cache.layer[2].segment_count == 0) || ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (3 << 0)) == 0))))
2896 state->channel_parameters_set = 0; /* auto search */
2897 else
2898 state->channel_parameters_set = 1; /* channel parameters are known */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002899
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002900 dib8000_viterbi_state(state, 0); /* force chan dec in restart */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002901
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002902 /* Layer monit */
2903 dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002904
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002905 dib8000_set_frequency_offset(state);
2906 dib8000_set_bandwidth(fe, state->fe[0]->dtv_property_cache.bandwidth_hz / 1000);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002907
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002908 if (state->channel_parameters_set == 0) { /* The channel struct is unknown, search it ! */
2909#ifdef DIB8000_AGC_FREEZE
2910 if (state->revision != 0x8090) {
2911 state->agc1_max = dib8000_read_word(state, 108);
2912 state->agc1_min = dib8000_read_word(state, 109);
2913 state->agc2_max = dib8000_read_word(state, 110);
2914 state->agc2_min = dib8000_read_word(state, 111);
2915 agc1 = dib8000_read_word(state, 388);
2916 agc2 = dib8000_read_word(state, 389);
2917 dib8000_write_word(state, 108, agc1);
2918 dib8000_write_word(state, 109, agc1);
2919 dib8000_write_word(state, 110, agc2);
2920 dib8000_write_word(state, 111, agc2);
2921 }
2922#endif
2923 state->autosearch_state = AS_SEARCHING_FFT;
2924 state->found_nfft = TRANSMISSION_MODE_AUTO;
2925 state->found_guard = GUARD_INTERVAL_AUTO;
2926 *tune_state = CT_DEMOD_SEARCH_NEXT;
2927 } else { /* we already know the channel struct so TUNE only ! */
2928 state->autosearch_state = AS_DONE;
2929 *tune_state = CT_DEMOD_STEP_3;
2930 }
2931 state->symbol_duration = dib8000_get_symbol_duration(state);
2932 break;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002933
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002934 case CT_DEMOD_SEARCH_NEXT: /* 51 */
2935 dib8000_autosearch_start(fe);
2936 if (state->revision == 0x8090)
2937 ret = 50;
2938 else
2939 ret = 15;
2940 *tune_state = CT_DEMOD_STEP_1;
2941 break;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002942
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002943 case CT_DEMOD_STEP_1: /* 31 */
2944 switch (dib8000_autosearch_irq(fe)) {
2945 case 1: /* fail */
2946 state->status = FE_STATUS_TUNE_FAILED;
2947 state->autosearch_state = AS_DONE;
2948 *tune_state = CT_DEMOD_STOP; /* else we are done here */
2949 break;
2950 case 2: /* Succes */
2951 state->status = FE_STATUS_FFT_SUCCESS; /* signal to the upper layer, that there was a channel found and the parameters can be read */
2952 *tune_state = CT_DEMOD_STEP_3;
2953 if (state->autosearch_state == AS_SEARCHING_GUARD)
2954 *tune_state = CT_DEMOD_STEP_2;
2955 else
2956 state->autosearch_state = AS_DONE;
2957 break;
2958 case 3: /* Autosearch FFT max correlation endded */
2959 *tune_state = CT_DEMOD_STEP_2;
2960 break;
2961 }
2962 break;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002963
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002964 case CT_DEMOD_STEP_2:
2965 switch (state->autosearch_state) {
2966 case AS_SEARCHING_FFT:
2967 /* searching for the correct FFT */
2968 if (state->revision == 0x8090) {
2969 corm[2] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
2970 corm[1] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
2971 corm[0] = (dib8000_read_word(state, 600) << 16) | (dib8000_read_word(state, 601));
2972 } else {
2973 corm[2] = (dib8000_read_word(state, 594) << 16) | (dib8000_read_word(state, 595));
2974 corm[1] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
2975 corm[0] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
2976 }
2977 /* dprintk("corm fft: %u %u %u", corm[0], corm[1], corm[2]); */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002978
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002979 max_value = 0;
2980 for (find_index = 1 ; find_index < 3 ; find_index++) {
2981 if (corm[max_value] < corm[find_index])
2982 max_value = find_index ;
2983 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03002984
Patrick Boettcher173a64c2013-04-22 12:45:52 -03002985 switch (max_value) {
2986 case 0:
2987 state->found_nfft = TRANSMISSION_MODE_2K;
2988 break;
2989 case 1:
2990 state->found_nfft = TRANSMISSION_MODE_4K;
2991 break;
2992 case 2:
2993 default:
2994 state->found_nfft = TRANSMISSION_MODE_8K;
2995 break;
2996 }
2997 /* dprintk("Autosearch FFT has found Mode %d", max_value + 1); */
2998
2999 *tune_state = CT_DEMOD_SEARCH_NEXT;
3000 state->autosearch_state = AS_SEARCHING_GUARD;
3001 if (state->revision == 0x8090)
3002 ret = 50;
3003 else
3004 ret = 10;
3005 break;
3006 case AS_SEARCHING_GUARD:
3007 /* searching for the correct guard interval */
3008 if (state->revision == 0x8090)
3009 state->found_guard = dib8000_read_word(state, 572) & 0x3;
3010 else
3011 state->found_guard = dib8000_read_word(state, 570) & 0x3;
3012 /* dprintk("guard interval found=%i", state->found_guard); */
3013
3014 *tune_state = CT_DEMOD_STEP_3;
3015 break;
3016 default:
3017 /* the demod should never be in this state */
3018 state->status = FE_STATUS_TUNE_FAILED;
3019 state->autosearch_state = AS_DONE;
3020 *tune_state = CT_DEMOD_STOP; /* else we are done here */
3021 break;
3022 }
3023 break;
3024
3025 case CT_DEMOD_STEP_3: /* 33 */
3026 state->symbol_duration = dib8000_get_symbol_duration(state);
3027 dib8000_set_isdbt_loop_params(state, LOOP_TUNE_1);
3028 dib8000_set_isdbt_common_channel(state, 0, 0);/* setting the known channel parameters here */
3029 *tune_state = CT_DEMOD_STEP_4;
3030 break;
3031
3032 case CT_DEMOD_STEP_4: /* (34) */
3033 dib8000_demod_restart(state);
3034
3035 dib8000_set_sync_wait(state);
3036 dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
3037
3038 locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */
3039 /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this lenght to lock */
3040 *timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON);
3041 *tune_state = CT_DEMOD_STEP_5;
3042 break;
3043
3044 case CT_DEMOD_STEP_5: /* (35) */
3045 locks = dib8000_read_lock(fe);
3046 if (locks & (0x3 << 11)) { /* coff-lock and off_cpil_lock achieved */
3047 dib8000_update_timf(state); /* we achieved a coff_cpil_lock - it's time to update the timf */
3048 if (!state->differential_constellation) {
3049 /* 2 times lmod4_win_len + 10 symbols (pipe delay after coff + nb to compute a 1st correlation) */
3050 *timeout = dib8000_get_timeout(state, (20 * ((dib8000_read_word(state, 188)>>5)&0x1f)), SYMBOL_DEPENDENT_ON);
3051 *tune_state = CT_DEMOD_STEP_7;
3052 } else {
3053 *tune_state = CT_DEMOD_STEP_8;
3054 }
3055 } else if (now > *timeout) {
3056 *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
3057 }
3058 break;
3059
3060 case CT_DEMOD_STEP_6: /* (36) if there is an input (diversity) */
3061 if ((state->fe[1] != NULL) && (state->output_mode != OUTMODE_DIVERSITY)) {
3062 /* 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 */
3063 if (dib8000_get_status(state->fe[1]) <= FE_STATUS_STD_SUCCESS) /* Something is locked on the input fe */
3064 *tune_state = CT_DEMOD_STEP_8; /* go for mpeg */
3065 else if (dib8000_get_status(state->fe[1]) >= FE_STATUS_TUNE_TIME_TOO_SHORT) { /* fe in input failled also, break the current one */
3066 *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
3067 dib8000_viterbi_state(state, 1); /* start viterbi chandec */
3068 dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
3069 state->status = FE_STATUS_TUNE_FAILED;
3070 }
3071 } else {
3072 dib8000_viterbi_state(state, 1); /* start viterbi chandec */
3073 dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
3074 *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
3075 state->status = FE_STATUS_TUNE_FAILED;
3076 }
3077 break;
3078
3079 case CT_DEMOD_STEP_7: /* 37 */
3080 locks = dib8000_read_lock(fe);
3081 if (locks & (1<<10)) { /* lmod4_lock */
3082 ret = 14; /* wait for 14 symbols */
3083 *tune_state = CT_DEMOD_STEP_8;
3084 } else if (now > *timeout)
3085 *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
3086 break;
3087
3088 case CT_DEMOD_STEP_8: /* 38 */
3089 dib8000_viterbi_state(state, 1); /* start viterbi chandec */
3090 dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
3091
3092 /* mpeg will never lock on this condition because init_prbs is not set : search for it !*/
3093 if (state->fe[0]->dtv_property_cache.isdbt_sb_mode && state->fe[0]->dtv_property_cache.isdbt_sb_subchannel == -1 && !state->differential_constellation) {
3094 state->subchannel = 0;
3095 *tune_state = CT_DEMOD_STEP_11;
3096 } else {
3097 *tune_state = CT_DEMOD_STEP_9;
3098 state->status = FE_STATUS_LOCKED;
3099 }
3100 break;
3101
3102 case CT_DEMOD_STEP_9: /* 39 */
3103 if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */
3104 /* defines timeout for mpeg lock depending on interleaver lenght of longest layer */
3105 for (i = 0; i < 3; i++) {
3106 if (state->fe[0]->dtv_property_cache.layer[i].interleaving >= deeper_interleaver) {
3107 dprintk("layer%i: time interleaver = %d ", i, state->fe[0]->dtv_property_cache.layer[i].interleaving);
3108 if (state->fe[0]->dtv_property_cache.layer[i].segment_count > 0) { /* valid layer */
3109 deeper_interleaver = state->fe[0]->dtv_property_cache.layer[0].interleaving;
3110 state->longest_intlv_layer = i;
3111 }
3112 }
3113 }
3114
3115 if (deeper_interleaver == 0)
3116 locks = 2; /* locks is the tmp local variable name */
3117 else if (deeper_interleaver == 3)
3118 locks = 8;
3119 else
3120 locks = 2 * deeper_interleaver;
3121
3122 if (state->diversity_onoff != 0) /* because of diversity sync */
3123 locks *= 2;
3124
3125 *timeout = now + (2000 * locks); /* give the mpeg lock 800ms if sram is present */
3126 dprintk("Deeper interleaver mode = %d on layer %d : timeout mult factor = %d => will use timeout = %d", deeper_interleaver, state->longest_intlv_layer, locks, *timeout);
3127
3128 *tune_state = CT_DEMOD_STEP_10;
3129 } else
3130 *tune_state = CT_DEMOD_STOP;
3131 break;
3132
3133 case CT_DEMOD_STEP_10: /* 40 */
3134 locks = dib8000_read_lock(fe);
3135 if (locks&(1<<(7-state->longest_intlv_layer))) { /* mpeg lock : check the longest one */
3136 dprintk("Mpeg locks [ L0 : %d | L1 : %d | L2 : %d ]", (locks>>7)&0x1, (locks>>6)&0x1, (locks>>5)&0x1);
3137 if (state->fe[0]->dtv_property_cache.isdbt_sb_mode && state->fe[0]->dtv_property_cache.isdbt_sb_subchannel == -1 && !state->differential_constellation)
3138 /* signal to the upper layer, that there was a channel found and the parameters can be read */
3139 state->status = FE_STATUS_DEMOD_SUCCESS;
3140 else
3141 state->status = FE_STATUS_DATA_LOCKED;
3142 *tune_state = CT_DEMOD_STOP;
3143 } else if (now > *timeout) {
3144 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 */
3145 state->subchannel += 3;
3146 *tune_state = CT_DEMOD_STEP_11;
3147 } 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 */
3148 if (locks & (0x7<<5)) {
3149 dprintk("Mpeg locks [ L0 : %d | L1 : %d | L2 : %d ]", (locks>>7)&0x1, (locks>>6)&0x1, (locks>>5)&0x1);
3150 state->status = FE_STATUS_DATA_LOCKED;
3151 } else
3152 state->status = FE_STATUS_TUNE_FAILED;
3153 *tune_state = CT_DEMOD_STOP;
3154 }
3155 }
3156 break;
3157
3158 case CT_DEMOD_STEP_11: /* 41 : init prbs autosearch */
3159 if (state->subchannel <= 41) {
3160 dib8000_set_subchannel_prbs(state, dib8000_get_init_prbs(state, state->subchannel));
3161 *tune_state = CT_DEMOD_STEP_9;
3162 } else {
3163 *tune_state = CT_DEMOD_STOP;
3164 state->status = FE_STATUS_TUNE_FAILED;
3165 }
3166 break;
3167
3168 default:
3169 break;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003170 }
3171
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003172 /* tuning is finished - cleanup the demod */
3173 switch (*tune_state) {
3174 case CT_DEMOD_STOP: /* (42) */
3175#ifdef DIB8000_AGC_FREEZE
3176 if ((state->revision != 0x8090) && (state->agc1_max != 0)) {
3177 dib8000_write_word(state, 108, state->agc1_max);
3178 dib8000_write_word(state, 109, state->agc1_min);
3179 dib8000_write_word(state, 110, state->agc2_max);
3180 dib8000_write_word(state, 111, state->agc2_min);
3181 state->agc1_max = 0;
3182 state->agc1_min = 0;
3183 state->agc2_max = 0;
3184 state->agc2_min = 0;
3185 }
3186#endif
3187 ret = FE_CALLBACK_TIME_NEVER;
3188 break;
3189 default:
3190 break;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003191 }
3192
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003193 if ((ret > 0) && (*tune_state > CT_DEMOD_STEP_3))
3194 return ret * state->symbol_duration;
3195 if ((ret > 0) && (ret < state->symbol_duration))
3196 return state->symbol_duration; /* at least one symbol */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003197 return ret;
3198}
3199
3200static int dib8000_wakeup(struct dvb_frontend *fe)
3201{
3202 struct dib8000_state *state = fe->demodulator_priv;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003203 u8 index_frontend;
3204 int ret;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003205
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003206 dib8000_set_power_mode(state, DIB8000_POWER_ALL);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003207 dib8000_set_adc_state(state, DIBX000_ADC_ON);
3208 if (dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
3209 dprintk("could not start Slow ADC");
3210
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003211 if (state->revision == 0x8090)
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003212 dib8000_sad_calib(state);
3213
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003214 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003215 ret = state->fe[index_frontend]->ops.init(state->fe[index_frontend]);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003216 if (ret < 0)
Olivier Grenie4c70e072011-01-03 15:33:37 -03003217 return ret;
3218 }
3219
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003220 return 0;
3221}
3222
3223static int dib8000_sleep(struct dvb_frontend *fe)
3224{
Olivier Grenie4c70e072011-01-03 15:33:37 -03003225 struct dib8000_state *state = fe->demodulator_priv;
3226 u8 index_frontend;
3227 int ret;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003228
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003229 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003230 ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]);
3231 if (ret < 0)
3232 return ret;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003233 }
Olivier Grenie4c70e072011-01-03 15:33:37 -03003234
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003235 if (state->revision != 0x8090)
3236 dib8000_set_output_mode(fe, OUTMODE_HIGH_Z);
3237 dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY);
Olivier Grenie4c70e072011-01-03 15:33:37 -03003238 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 -03003239}
3240
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -03003241static int dib8000_get_frontend(struct dvb_frontend *fe)
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003242{
3243 struct dib8000_state *state = fe->demodulator_priv;
3244 u16 i, val = 0;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003245 fe_status_t stat;
3246 u8 index_frontend, sub_index_frontend;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003247
3248 fe->dtv_property_cache.bandwidth_hz = 6000000;
3249
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003250 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003251 state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
3252 if (stat&FE_HAS_SYNC) {
3253 dprintk("TMCC lock on the slave%i", index_frontend);
3254 /* synchronize the cache with the other frontends */
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -03003255 state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003256 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 -03003257 if (sub_index_frontend != index_frontend) {
3258 state->fe[sub_index_frontend]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode;
3259 state->fe[sub_index_frontend]->dtv_property_cache.inversion = state->fe[index_frontend]->dtv_property_cache.inversion;
3260 state->fe[sub_index_frontend]->dtv_property_cache.transmission_mode = state->fe[index_frontend]->dtv_property_cache.transmission_mode;
3261 state->fe[sub_index_frontend]->dtv_property_cache.guard_interval = state->fe[index_frontend]->dtv_property_cache.guard_interval;
3262 state->fe[sub_index_frontend]->dtv_property_cache.isdbt_partial_reception = state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception;
3263 for (i = 0; i < 3; i++) {
3264 state->fe[sub_index_frontend]->dtv_property_cache.layer[i].segment_count = state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count;
3265 state->fe[sub_index_frontend]->dtv_property_cache.layer[i].interleaving = state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving;
3266 state->fe[sub_index_frontend]->dtv_property_cache.layer[i].fec = state->fe[index_frontend]->dtv_property_cache.layer[i].fec;
3267 state->fe[sub_index_frontend]->dtv_property_cache.layer[i].modulation = state->fe[index_frontend]->dtv_property_cache.layer[i].modulation;
3268 }
3269 }
3270 }
3271 return 0;
3272 }
3273 }
3274
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003275 fe->dtv_property_cache.isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1;
3276
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003277 if (state->revision == 0x8090)
3278 val = dib8000_read_word(state, 572);
3279 else
3280 val = dib8000_read_word(state, 570);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003281 fe->dtv_property_cache.inversion = (val & 0x40) >> 6;
3282 switch ((val & 0x30) >> 4) {
3283 case 1:
3284 fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
3285 break;
3286 case 3:
3287 default:
3288 fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
3289 break;
3290 }
3291
3292 switch (val & 0x3) {
3293 case 0:
3294 fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
3295 dprintk("dib8000_get_frontend GI = 1/32 ");
3296 break;
3297 case 1:
3298 fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16;
3299 dprintk("dib8000_get_frontend GI = 1/16 ");
3300 break;
3301 case 2:
3302 dprintk("dib8000_get_frontend GI = 1/8 ");
3303 fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
3304 break;
3305 case 3:
3306 dprintk("dib8000_get_frontend GI = 1/4 ");
3307 fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4;
3308 break;
3309 }
3310
3311 val = dib8000_read_word(state, 505);
3312 fe->dtv_property_cache.isdbt_partial_reception = val & 1;
3313 dprintk("dib8000_get_frontend : partial_reception = %d ", fe->dtv_property_cache.isdbt_partial_reception);
3314
3315 for (i = 0; i < 3; i++) {
3316 val = dib8000_read_word(state, 493 + i);
3317 fe->dtv_property_cache.layer[i].segment_count = val & 0x0F;
3318 dprintk("dib8000_get_frontend : Layer %d segments = %d ", i, fe->dtv_property_cache.layer[i].segment_count);
3319
3320 val = dib8000_read_word(state, 499 + i);
3321 fe->dtv_property_cache.layer[i].interleaving = val & 0x3;
3322 dprintk("dib8000_get_frontend : Layer %d time_intlv = %d ", i, fe->dtv_property_cache.layer[i].interleaving);
3323
3324 val = dib8000_read_word(state, 481 + i);
3325 switch (val & 0x7) {
3326 case 1:
3327 fe->dtv_property_cache.layer[i].fec = FEC_1_2;
3328 dprintk("dib8000_get_frontend : Layer %d Code Rate = 1/2 ", i);
3329 break;
3330 case 2:
3331 fe->dtv_property_cache.layer[i].fec = FEC_2_3;
3332 dprintk("dib8000_get_frontend : Layer %d Code Rate = 2/3 ", i);
3333 break;
3334 case 3:
3335 fe->dtv_property_cache.layer[i].fec = FEC_3_4;
3336 dprintk("dib8000_get_frontend : Layer %d Code Rate = 3/4 ", i);
3337 break;
3338 case 5:
3339 fe->dtv_property_cache.layer[i].fec = FEC_5_6;
3340 dprintk("dib8000_get_frontend : Layer %d Code Rate = 5/6 ", i);
3341 break;
3342 default:
3343 fe->dtv_property_cache.layer[i].fec = FEC_7_8;
3344 dprintk("dib8000_get_frontend : Layer %d Code Rate = 7/8 ", i);
3345 break;
3346 }
3347
3348 val = dib8000_read_word(state, 487 + i);
3349 switch (val & 0x3) {
3350 case 0:
3351 dprintk("dib8000_get_frontend : Layer %d DQPSK ", i);
3352 fe->dtv_property_cache.layer[i].modulation = DQPSK;
3353 break;
3354 case 1:
3355 fe->dtv_property_cache.layer[i].modulation = QPSK;
3356 dprintk("dib8000_get_frontend : Layer %d QPSK ", i);
3357 break;
3358 case 2:
3359 fe->dtv_property_cache.layer[i].modulation = QAM_16;
3360 dprintk("dib8000_get_frontend : Layer %d QAM16 ", i);
3361 break;
3362 case 3:
3363 default:
3364 dprintk("dib8000_get_frontend : Layer %d QAM64 ", i);
3365 fe->dtv_property_cache.layer[i].modulation = QAM_64;
3366 break;
3367 }
3368 }
Olivier Grenie4c70e072011-01-03 15:33:37 -03003369
3370 /* synchronize the cache with the other frontends */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003371 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003372 state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode = fe->dtv_property_cache.isdbt_sb_mode;
3373 state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion;
3374 state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode;
3375 state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval;
3376 state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception = fe->dtv_property_cache.isdbt_partial_reception;
3377 for (i = 0; i < 3; i++) {
3378 state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count = fe->dtv_property_cache.layer[i].segment_count;
3379 state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving = fe->dtv_property_cache.layer[i].interleaving;
3380 state->fe[index_frontend]->dtv_property_cache.layer[i].fec = fe->dtv_property_cache.layer[i].fec;
3381 state->fe[index_frontend]->dtv_property_cache.layer[i].modulation = fe->dtv_property_cache.layer[i].modulation;
3382 }
3383 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003384 return 0;
3385}
3386
Mauro Carvalho Chehab490ecd62011-12-22 20:38:27 -03003387static int dib8000_set_frontend(struct dvb_frontend *fe)
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003388{
3389 struct dib8000_state *state = fe->demodulator_priv;
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003390 int l, i, active, time, ret, time_slave = FE_CALLBACK_TIME_NEVER;
3391 u8 exit_condition, index_frontend;
3392 u32 delay, callback_time;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003393
Olivier Grenie4c70e072011-01-03 15:33:37 -03003394 if (state->fe[0]->dtv_property_cache.frequency == 0) {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003395 dprintk("dib8000: must at least specify frequency ");
3396 return 0;
3397 }
3398
Olivier Grenie4c70e072011-01-03 15:33:37 -03003399 if (state->fe[0]->dtv_property_cache.bandwidth_hz == 0) {
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003400 dprintk("dib8000: no bandwidth specified, set to default ");
Olivier Grenie4c70e072011-01-03 15:33:37 -03003401 state->fe[0]->dtv_property_cache.bandwidth_hz = 6000000;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003402 }
3403
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003404 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003405 /* synchronization of the cache */
3406 state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_ISDBT;
3407 memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties));
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003408
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003409 /* set output mode and diversity input */
3410 if (state->revision != 0x8090) {
3411 dib8000_set_diversity_in(state->fe[index_frontend], 1);
3412 if (index_frontend != 0)
3413 dib8000_set_output_mode(state->fe[index_frontend],
3414 OUTMODE_DIVERSITY);
3415 else
3416 dib8000_set_output_mode(state->fe[0], OUTMODE_HIGH_Z);
3417 } else {
3418 dib8096p_set_diversity_in(state->fe[index_frontend], 1);
3419 if (index_frontend != 0)
3420 dib8096p_set_output_mode(state->fe[index_frontend],
3421 OUTMODE_DIVERSITY);
3422 else
3423 dib8096p_set_output_mode(state->fe[0], OUTMODE_HIGH_Z);
3424 }
3425
3426 /* tune the tuner */
Olivier Grenie4c70e072011-01-03 15:33:37 -03003427 if (state->fe[index_frontend]->ops.tuner_ops.set_params)
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03003428 state->fe[index_frontend]->ops.tuner_ops.set_params(state->fe[index_frontend]);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003429
Olivier Grenie4c70e072011-01-03 15:33:37 -03003430 dib8000_set_tune_state(state->fe[index_frontend], CT_AGC_START);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003431 }
3432
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003433 /* turn off the diversity of the last chip */
3434 if (state->revision != 0x8090)
3435 dib8000_set_diversity_in(state->fe[index_frontend - 1], 0);
3436 else
3437 dib8096p_set_diversity_in(state->fe[index_frontend - 1], 0);
3438
Olivier Grenie4c70e072011-01-03 15:33:37 -03003439 /* start up the AGC */
3440 do {
3441 time = dib8000_agc_startup(state->fe[0]);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003442 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003443 time_slave = dib8000_agc_startup(state->fe[index_frontend]);
3444 if (time == FE_CALLBACK_TIME_NEVER)
3445 time = time_slave;
3446 else if ((time_slave != FE_CALLBACK_TIME_NEVER) && (time_slave > time))
3447 time = time_slave;
3448 }
3449 if (time != FE_CALLBACK_TIME_NEVER)
3450 msleep(time / 10);
3451 else
3452 break;
3453 exit_condition = 1;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003454 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003455 if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_AGC_STOP) {
3456 exit_condition = 0;
3457 break;
3458 }
3459 }
3460 } while (exit_condition == 0);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003461
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003462 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
Olivier Grenie4c70e072011-01-03 15:33:37 -03003463 dib8000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
3464
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003465 active = 1;
3466 do {
3467 callback_time = FE_CALLBACK_TIME_NEVER;
Mauro Carvalho Chehab2c2c4412011-01-16 13:02:52 -02003468 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003469 delay = dib8000_tune(state->fe[index_frontend]);
3470 if (delay != FE_CALLBACK_TIME_NEVER)
3471 delay += systime();
Olivier Grenie4c70e072011-01-03 15:33:37 -03003472
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003473 /* we are in autosearch */
3474 if (state->channel_parameters_set == 0) { /* searching */
3475 if ((dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_DEMOD_SUCCESS) || (dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_FFT_SUCCESS)) {
3476 dprintk("autosearch succeeded on fe%i", index_frontend);
3477 dib8000_get_frontend(state->fe[index_frontend]); /* we read the channel parameters from the frontend which was successful */
3478 state->channel_parameters_set = 1;
3479
3480 for (l = 0; (l < MAX_NUMBER_OF_FRONTENDS) && (state->fe[l] != NULL); l++) {
3481 if (l != index_frontend) { /* and for all frontend except the successful one */
3482 dib8000_tune_restart_from_demod(state->fe[l]);
3483
3484 state->fe[l]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode;
3485 state->fe[l]->dtv_property_cache.inversion = state->fe[index_frontend]->dtv_property_cache.inversion;
3486 state->fe[l]->dtv_property_cache.transmission_mode = state->fe[index_frontend]->dtv_property_cache.transmission_mode;
3487 state->fe[l]->dtv_property_cache.guard_interval = state->fe[index_frontend]->dtv_property_cache.guard_interval;
3488 state->fe[l]->dtv_property_cache.isdbt_partial_reception = state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception;
3489 for (i = 0; i < 3; i++) {
3490 state->fe[l]->dtv_property_cache.layer[i].segment_count = state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count;
3491 state->fe[l]->dtv_property_cache.layer[i].interleaving = state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving;
3492 state->fe[l]->dtv_property_cache.layer[i].fec = state->fe[index_frontend]->dtv_property_cache.layer[i].fec;
3493 state->fe[l]->dtv_property_cache.layer[i].modulation = state->fe[index_frontend]->dtv_property_cache.layer[i].modulation;
3494 }
3495
3496 }
Mauro Carvalho Chehab2c2c4412011-01-16 13:02:52 -02003497 }
3498 }
3499 }
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003500 if (delay < callback_time)
3501 callback_time = delay;
3502 }
3503 /* tuning is done when the master frontend is done (failed or success) */
3504 if (dib8000_get_status(state->fe[0]) == FE_STATUS_TUNE_FAILED ||
3505 dib8000_get_status(state->fe[0]) == FE_STATUS_LOCKED ||
3506 dib8000_get_status(state->fe[0]) == FE_STATUS_DATA_LOCKED) {
3507 active = 0;
3508 /* we need to wait for all frontends to be finished */
3509 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
3510 if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_DEMOD_STOP)
3511 active = 1;
3512 }
3513 if (active == 0)
3514 dprintk("tuning done with status %d", dib8000_get_status(state->fe[0]));
Mauro Carvalho Chehab2c2c4412011-01-16 13:02:52 -02003515 }
Olivier Grenie4c70e072011-01-03 15:33:37 -03003516
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003517 if ((active == 1) && (callback_time == FE_CALLBACK_TIME_NEVER)) {
3518 dprintk("strange callback time something went wrong");
3519 active = 0;
3520 }
Olivier Grenie4c70e072011-01-03 15:33:37 -03003521
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003522 while ((active == 1) && (systime() < callback_time))
3523 msleep(100);
3524 } while (active);
Olivier Grenie4c70e072011-01-03 15:33:37 -03003525
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003526 /* set output mode */
3527 if (state->revision != 0x8090)
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003528 dib8000_set_output_mode(state->fe[0], state->cfg.output_mode);
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003529 else {
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003530 dib8096p_set_output_mode(state->fe[0], state->cfg.output_mode);
3531 if (state->cfg.enMpegOutput == 0) {
3532 dib8096p_setDibTxMux(state, MPEG_ON_DIBTX);
3533 dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
3534 }
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003535 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003536
3537 return ret;
3538}
3539
3540static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
3541{
3542 struct dib8000_state *state = fe->demodulator_priv;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003543 u16 lock_slave = 0, lock;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003544 u8 index_frontend;
3545
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003546 lock = dib8000_read_lock(fe);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003547 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
Olivier Grenie4c70e072011-01-03 15:33:37 -03003548 lock_slave |= dib8000_read_lock(state->fe[index_frontend]);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003549
3550 *stat = 0;
3551
Olivier Grenie4c70e072011-01-03 15:33:37 -03003552 if (((lock >> 13) & 1) || ((lock_slave >> 13) & 1))
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003553 *stat |= FE_HAS_SIGNAL;
3554
Olivier Grenie4c70e072011-01-03 15:33:37 -03003555 if (((lock >> 8) & 1) || ((lock_slave >> 8) & 1)) /* Equal */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003556 *stat |= FE_HAS_CARRIER;
3557
Olivier Grenie4c70e072011-01-03 15:33:37 -03003558 if ((((lock >> 1) & 0xf) == 0xf) || (((lock_slave >> 1) & 0xf) == 0xf)) /* TMCC_SYNC */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003559 *stat |= FE_HAS_SYNC;
3560
Olivier Grenie4c70e072011-01-03 15:33:37 -03003561 if ((((lock >> 12) & 1) || ((lock_slave >> 12) & 1)) && ((lock >> 5) & 7)) /* FEC MPEG */
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003562 *stat |= FE_HAS_LOCK;
3563
Olivier Grenie4c70e072011-01-03 15:33:37 -03003564 if (((lock >> 12) & 1) || ((lock_slave >> 12) & 1)) {
Olivier Grenie89dfc552009-11-30 06:38:49 -03003565 lock = dib8000_read_word(state, 554); /* Viterbi Layer A */
3566 if (lock & 0x01)
3567 *stat |= FE_HAS_VITERBI;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003568
Olivier Grenie89dfc552009-11-30 06:38:49 -03003569 lock = dib8000_read_word(state, 555); /* Viterbi Layer B */
3570 if (lock & 0x01)
3571 *stat |= FE_HAS_VITERBI;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003572
Olivier Grenie89dfc552009-11-30 06:38:49 -03003573 lock = dib8000_read_word(state, 556); /* Viterbi Layer C */
3574 if (lock & 0x01)
3575 *stat |= FE_HAS_VITERBI;
3576 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003577
3578 return 0;
3579}
3580
3581static int dib8000_read_ber(struct dvb_frontend *fe, u32 * ber)
3582{
3583 struct dib8000_state *state = fe->demodulator_priv;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003584
3585 /* 13 segments */
3586 if (state->revision == 0x8090)
3587 *ber = (dib8000_read_word(state, 562) << 16) |
3588 dib8000_read_word(state, 563);
3589 else
3590 *ber = (dib8000_read_word(state, 560) << 16) |
3591 dib8000_read_word(state, 561);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003592 return 0;
3593}
3594
3595static int dib8000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
3596{
3597 struct dib8000_state *state = fe->demodulator_priv;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003598
3599 /* packet error on 13 seg */
3600 if (state->revision == 0x8090)
3601 *unc = dib8000_read_word(state, 567);
3602 else
3603 *unc = dib8000_read_word(state, 565);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003604 return 0;
3605}
3606
3607static int dib8000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
3608{
3609 struct dib8000_state *state = fe->demodulator_priv;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003610 u8 index_frontend;
3611 u16 val;
3612
3613 *strength = 0;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003614 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003615 state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val);
3616 if (val > 65535 - *strength)
3617 *strength = 65535;
3618 else
3619 *strength += val;
3620 }
3621
3622 val = 65535 - dib8000_read_word(state, 390);
3623 if (val > 65535 - *strength)
3624 *strength = 65535;
3625 else
3626 *strength += val;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003627 return 0;
3628}
3629
Olivier Grenie4c70e072011-01-03 15:33:37 -03003630static u32 dib8000_get_snr(struct dvb_frontend *fe)
3631{
3632 struct dib8000_state *state = fe->demodulator_priv;
3633 u32 n, s, exp;
3634 u16 val;
3635
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003636 if (state->revision != 0x8090)
3637 val = dib8000_read_word(state, 542);
3638 else
3639 val = dib8000_read_word(state, 544);
Olivier Grenie4c70e072011-01-03 15:33:37 -03003640 n = (val >> 6) & 0xff;
3641 exp = (val & 0x3f);
3642 if ((exp & 0x20) != 0)
3643 exp -= 0x40;
3644 n <<= exp+16;
3645
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003646 if (state->revision != 0x8090)
3647 val = dib8000_read_word(state, 543);
3648 else
3649 val = dib8000_read_word(state, 545);
Olivier Grenie4c70e072011-01-03 15:33:37 -03003650 s = (val >> 6) & 0xff;
3651 exp = (val & 0x3f);
3652 if ((exp & 0x20) != 0)
3653 exp -= 0x40;
3654 s <<= exp+16;
3655
3656 if (n > 0) {
3657 u32 t = (s/n) << 16;
3658 return t + ((s << 16) - n*t) / n;
3659 }
3660 return 0xffffffff;
3661}
3662
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003663static int dib8000_read_snr(struct dvb_frontend *fe, u16 * snr)
3664{
3665 struct dib8000_state *state = fe->demodulator_priv;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003666 u8 index_frontend;
3667 u32 snr_master;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003668
Olivier Grenie4c70e072011-01-03 15:33:37 -03003669 snr_master = dib8000_get_snr(fe);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003670 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
Olivier Grenie4c70e072011-01-03 15:33:37 -03003671 snr_master += dib8000_get_snr(state->fe[index_frontend]);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003672
Olivier Grenie1f6bfcc2011-07-04 12:33:54 -03003673 if ((snr_master >> 16) != 0) {
Olivier Grenie4c70e072011-01-03 15:33:37 -03003674 snr_master = 10*intlog10(snr_master>>16);
3675 *snr = snr_master / ((1 << 24) / 10);
3676 }
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003677 else
Olivier Grenie4c70e072011-01-03 15:33:37 -03003678 *snr = 0;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003679
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003680 return 0;
3681}
3682
Olivier Grenie4c70e072011-01-03 15:33:37 -03003683int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
3684{
3685 struct dib8000_state *state = fe->demodulator_priv;
3686 u8 index_frontend = 1;
3687
3688 while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
3689 index_frontend++;
3690 if (index_frontend < MAX_NUMBER_OF_FRONTENDS) {
3691 dprintk("set slave fe %p to index %i", fe_slave, index_frontend);
3692 state->fe[index_frontend] = fe_slave;
3693 return 0;
3694 }
3695
3696 dprintk("too many slave frontend");
3697 return -ENOMEM;
3698}
3699EXPORT_SYMBOL(dib8000_set_slave_frontend);
3700
3701int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
3702{
3703 struct dib8000_state *state = fe->demodulator_priv;
3704 u8 index_frontend = 1;
3705
3706 while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
3707 index_frontend++;
3708 if (index_frontend != 1) {
3709 dprintk("remove slave fe %p (index %i)", state->fe[index_frontend-1], index_frontend-1);
3710 state->fe[index_frontend] = NULL;
3711 return 0;
3712 }
3713
3714 dprintk("no frontend to be removed");
3715 return -ENODEV;
3716}
3717EXPORT_SYMBOL(dib8000_remove_slave_frontend);
3718
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003719struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
Olivier Grenie4c70e072011-01-03 15:33:37 -03003720{
3721 struct dib8000_state *state = fe->demodulator_priv;
3722
3723 if (slave_index >= MAX_NUMBER_OF_FRONTENDS)
3724 return NULL;
3725 return state->fe[slave_index];
3726}
3727EXPORT_SYMBOL(dib8000_get_slave_frontend);
3728
3729
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003730int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
3731 u8 default_addr, u8 first_addr, u8 is_dib8096p)
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003732{
Olivier Grenie5a0deee2011-05-03 12:27:33 -03003733 int k = 0, ret = 0;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003734 u8 new_addr = 0;
3735 struct i2c_device client = {.adap = host };
3736
Olivier Grenie5a0deee2011-05-03 12:27:33 -03003737 client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
3738 if (!client.i2c_write_buffer) {
3739 dprintk("%s: not enough memory", __func__);
3740 return -ENOMEM;
3741 }
3742 client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
3743 if (!client.i2c_read_buffer) {
3744 dprintk("%s: not enough memory", __func__);
3745 ret = -ENOMEM;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03003746 goto error_memory_read;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03003747 }
Patrick Boettcher79fcce32011-08-03 12:08:21 -03003748 client.i2c_buffer_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL);
3749 if (!client.i2c_buffer_lock) {
3750 dprintk("%s: not enough memory", __func__);
3751 ret = -ENOMEM;
3752 goto error_memory_lock;
3753 }
3754 mutex_init(client.i2c_buffer_lock);
Olivier Grenie5a0deee2011-05-03 12:27:33 -03003755
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003756 for (k = no_of_demods - 1; k >= 0; k--) {
3757 /* designated i2c address */
3758 new_addr = first_addr + (k << 1);
3759
3760 client.addr = new_addr;
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003761 if (!is_dib8096p)
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003762 dib8000_i2c_write16(&client, 1287, 0x0003); /* sram lead in, rdy */
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003763 if (dib8000_identify(&client) == 0) {
3764 /* sram lead in, rdy */
3765 if (!is_dib8096p)
3766 dib8000_i2c_write16(&client, 1287, 0x0003);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003767 client.addr = default_addr;
3768 if (dib8000_identify(&client) == 0) {
3769 dprintk("#%d: not identified", k);
Olivier Grenie5a0deee2011-05-03 12:27:33 -03003770 ret = -EINVAL;
3771 goto error;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003772 }
3773 }
3774
3775 /* start diversity to pull_down div_str - just for i2c-enumeration */
3776 dib8000_i2c_write16(&client, 1286, (1 << 10) | (4 << 6));
3777
3778 /* set new i2c address and force divstart */
3779 dib8000_i2c_write16(&client, 1285, (new_addr << 2) | 0x2);
3780 client.addr = new_addr;
3781 dib8000_identify(&client);
3782
3783 dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
3784 }
3785
3786 for (k = 0; k < no_of_demods; k++) {
3787 new_addr = first_addr | (k << 1);
3788 client.addr = new_addr;
3789
3790 // unforce divstr
3791 dib8000_i2c_write16(&client, 1285, new_addr << 2);
3792
3793 /* deactivate div - it was just for i2c-enumeration */
3794 dib8000_i2c_write16(&client, 1286, 0);
3795 }
3796
Olivier Grenie5a0deee2011-05-03 12:27:33 -03003797error:
Patrick Boettcher79fcce32011-08-03 12:08:21 -03003798 kfree(client.i2c_buffer_lock);
3799error_memory_lock:
Olivier Grenie5a0deee2011-05-03 12:27:33 -03003800 kfree(client.i2c_read_buffer);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03003801error_memory_read:
Olivier Grenie5a0deee2011-05-03 12:27:33 -03003802 kfree(client.i2c_write_buffer);
3803
3804 return ret;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003805}
3806
3807EXPORT_SYMBOL(dib8000_i2c_enumeration);
3808static int dib8000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
3809{
3810 tune->min_delay_ms = 1000;
3811 tune->step_size = 0;
3812 tune->max_drift = 0;
3813 return 0;
3814}
3815
3816static void dib8000_release(struct dvb_frontend *fe)
3817{
3818 struct dib8000_state *st = fe->demodulator_priv;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003819 u8 index_frontend;
3820
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03003821 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (st->fe[index_frontend] != NULL); index_frontend++)
Olivier Grenie4c70e072011-01-03 15:33:37 -03003822 dvb_frontend_detach(st->fe[index_frontend]);
3823
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003824 dibx000_exit_i2c_master(&st->i2c_master);
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003825 i2c_del_adapter(&st->dib8096p_tuner_adap);
Olivier Grenie4c70e072011-01-03 15:33:37 -03003826 kfree(st->fe[0]);
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003827 kfree(st);
3828}
3829
3830struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
3831{
3832 struct dib8000_state *st = fe->demodulator_priv;
3833 return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
3834}
3835
3836EXPORT_SYMBOL(dib8000_get_i2c_master);
3837
Olivier Grenief8731f42009-09-18 04:08:43 -03003838int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
3839{
3840 struct dib8000_state *st = fe->demodulator_priv;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003841 u16 val = dib8000_read_word(st, 299) & 0xffef;
3842 val |= (onoff & 0x1) << 4;
Olivier Grenief8731f42009-09-18 04:08:43 -03003843
Olivier Grenie4c70e072011-01-03 15:33:37 -03003844 dprintk("pid filter enabled %d", onoff);
3845 return dib8000_write_word(st, 299, val);
Olivier Grenief8731f42009-09-18 04:08:43 -03003846}
3847EXPORT_SYMBOL(dib8000_pid_filter_ctrl);
3848
3849int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
3850{
3851 struct dib8000_state *st = fe->demodulator_priv;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003852 dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
3853 return dib8000_write_word(st, 305 + id, onoff ? (1 << 13) | pid : 0);
Olivier Grenief8731f42009-09-18 04:08:43 -03003854}
3855EXPORT_SYMBOL(dib8000_pid_filter);
3856
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003857static const struct dvb_frontend_ops dib8000_ops = {
Mauro Carvalho Chehab490ecd62011-12-22 20:38:27 -03003858 .delsys = { SYS_ISDBT },
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003859 .info = {
3860 .name = "DiBcom 8000 ISDB-T",
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003861 .frequency_min = 44250000,
3862 .frequency_max = 867250000,
3863 .frequency_stepsize = 62500,
3864 .caps = FE_CAN_INVERSION_AUTO |
3865 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
3866 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
3867 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
3868 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
3869 },
3870
3871 .release = dib8000_release,
3872
3873 .init = dib8000_wakeup,
3874 .sleep = dib8000_sleep,
3875
Mauro Carvalho Chehab490ecd62011-12-22 20:38:27 -03003876 .set_frontend = dib8000_set_frontend,
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003877 .get_tune_settings = dib8000_fe_get_tune_settings,
Mauro Carvalho Chehab490ecd62011-12-22 20:38:27 -03003878 .get_frontend = dib8000_get_frontend,
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003879
3880 .read_status = dib8000_read_status,
3881 .read_ber = dib8000_read_ber,
3882 .read_signal_strength = dib8000_read_signal_strength,
3883 .read_snr = dib8000_read_snr,
3884 .read_ucblocks = dib8000_read_unc_blocks,
3885};
3886
3887struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
3888{
3889 struct dvb_frontend *fe;
3890 struct dib8000_state *state;
3891
3892 dprintk("dib8000_attach");
3893
3894 state = kzalloc(sizeof(struct dib8000_state), GFP_KERNEL);
3895 if (state == NULL)
3896 return NULL;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003897 fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL);
3898 if (fe == NULL)
Dan Carpentered54c0e2011-01-19 11:27:58 -03003899 goto error;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003900
3901 memcpy(&state->cfg, cfg, sizeof(struct dib8000_config));
3902 state->i2c.adap = i2c_adap;
3903 state->i2c.addr = i2c_addr;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03003904 state->i2c.i2c_write_buffer = state->i2c_write_buffer;
3905 state->i2c.i2c_read_buffer = state->i2c_read_buffer;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03003906 mutex_init(&state->i2c_buffer_lock);
3907 state->i2c.i2c_buffer_lock = &state->i2c_buffer_lock;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003908 state->gpio_val = cfg->gpio_val;
3909 state->gpio_dir = cfg->gpio_dir;
3910
3911 /* Ensure the output mode remains at the previous default if it's
3912 * not specifically set by the caller.
3913 */
3914 if ((state->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (state->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
3915 state->cfg.output_mode = OUTMODE_MPEG2_FIFO;
3916
Olivier Grenie4c70e072011-01-03 15:33:37 -03003917 state->fe[0] = fe;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003918 fe->demodulator_priv = state;
Olivier Grenie4c70e072011-01-03 15:33:37 -03003919 memcpy(&state->fe[0]->ops, &dib8000_ops, sizeof(struct dvb_frontend_ops));
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003920
3921 state->timf_default = cfg->pll->timf;
3922
3923 if (dib8000_identify(&state->i2c) == 0)
3924 goto error;
3925
3926 dibx000_init_i2c_master(&state->i2c_master, DIB8000, state->i2c.adap, state->i2c.addr);
3927
Olivier Grenie0c32dbd2011-08-10 05:17:18 -03003928 /* init 8096p tuner adapter */
3929 strncpy(state->dib8096p_tuner_adap.name, "DiB8096P tuner interface",
3930 sizeof(state->dib8096p_tuner_adap.name));
3931 state->dib8096p_tuner_adap.algo = &dib8096p_tuner_xfer_algo;
3932 state->dib8096p_tuner_adap.algo_data = NULL;
3933 state->dib8096p_tuner_adap.dev.parent = state->i2c.adap->dev.parent;
3934 i2c_set_adapdata(&state->dib8096p_tuner_adap, state);
3935 i2c_add_adapter(&state->dib8096p_tuner_adap);
3936
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003937 dib8000_reset(fe);
3938
3939 dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5)); /* ber_rs_len = 3 */
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003940 state->current_demod_bw = 6000;
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003941
3942 return fe;
3943
Patrick Boettcher173a64c2013-04-22 12:45:52 -03003944error:
Patrick Boettcher77e2c0f2009-08-17 07:01:10 -03003945 kfree(state);
3946 return NULL;
3947}
3948
3949EXPORT_SYMBOL(dib8000_attach);
3950
3951MODULE_AUTHOR("Olivier Grenie <Olivier.Grenie@dibcom.fr, " "Patrick Boettcher <pboettcher@dibcom.fr>");
3952MODULE_DESCRIPTION("Driver for the DiBcom 8000 ISDB-T demodulator");
3953MODULE_LICENSE("GPL");