blob: 974c2b7dc20167bd093159adb6a087319e5f6ff3 [file] [log] [blame]
Olivier Greniedd316c62011-01-04 04:28:59 -03001/*
2 * Linux-DVB Driver for DiBcom's DiB9000 and demodulator-family.
3 *
4 * Copyright (C) 2005-10 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>
11#include <linux/i2c.h>
12#include <linux/mutex.h>
13
14#include "dvb_math.h"
15#include "dvb_frontend.h"
16
17#include "dib9000.h"
18#include "dibx000_common.h"
19
20static int debug;
21module_param(debug, int, 0644);
22MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
23
24#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB9000: "); printk(args); printk("\n"); } } while (0)
25#define MAX_NUMBER_OF_FRONTENDS 6
26
27struct i2c_device {
28 struct i2c_adapter *i2c_adap;
29 u8 i2c_addr;
Olivier Grenie5a0deee2011-05-03 12:27:33 -030030 u8 *i2c_read_buffer;
31 u8 *i2c_write_buffer;
Olivier Greniedd316c62011-01-04 04:28:59 -030032};
33
34/* lock */
35#define DIB_LOCK struct mutex
Olivier Grenieb4d6046e2011-01-04 13:08:14 -030036#define DibAcquireLock(lock) do { if (mutex_lock_interruptible(lock) < 0) dprintk("could not get the lock"); } while (0)
Olivier Greniedd316c62011-01-04 04:28:59 -030037#define DibReleaseLock(lock) mutex_unlock(lock)
38#define DibInitLock(lock) mutex_init(lock)
39#define DibFreeLock(lock)
40
Patrick Boettcher79fcce32011-08-03 12:08:21 -030041struct dib9000_pid_ctrl {
42#define DIB9000_PID_FILTER_CTRL 0
43#define DIB9000_PID_FILTER 1
44 u8 cmd;
45 u8 id;
46 u16 pid;
47 u8 onoff;
48};
49
Olivier Greniedd316c62011-01-04 04:28:59 -030050struct dib9000_state {
51 struct i2c_device i2c;
52
53 struct dibx000_i2c_master i2c_master;
54 struct i2c_adapter tuner_adap;
55 struct i2c_adapter component_bus;
56
57 u16 revision;
58 u8 reg_offs;
59
60 enum frontend_tune_state tune_state;
61 u32 status;
62 struct dvb_frontend_parametersContext channel_status;
63
64 u8 fe_id;
65
66#define DIB9000_GPIO_DEFAULT_DIRECTIONS 0xffff
67 u16 gpio_dir;
68#define DIB9000_GPIO_DEFAULT_VALUES 0x0000
69 u16 gpio_val;
70#define DIB9000_GPIO_DEFAULT_PWM_POS 0xffff
71 u16 gpio_pwm_pos;
72
73 union { /* common for all chips */
74 struct {
75 u8 mobile_mode:1;
76 } host;
77
78 struct {
79 struct dib9000_fe_memory_map {
80 u16 addr;
81 u16 size;
82 } fe_mm[18];
83 u8 memcmd;
84
85 DIB_LOCK mbx_if_lock; /* to protect read/write operations */
86 DIB_LOCK mbx_lock; /* to protect the whole mailbox handling */
87
88 DIB_LOCK mem_lock; /* to protect the memory accesses */
89 DIB_LOCK mem_mbx_lock; /* to protect the memory-based mailbox */
90
91#define MBX_MAX_WORDS (256 - 200 - 2)
92#define DIB9000_MSG_CACHE_SIZE 2
93 u16 message_cache[DIB9000_MSG_CACHE_SIZE][MBX_MAX_WORDS];
94 u8 fw_is_running;
95 } risc;
96 } platform;
97
98 union { /* common for all platforms */
99 struct {
100 struct dib9000_config cfg;
101 } d9;
102 } chip;
103
104 struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
105 u16 component_bus_speed;
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300106
107 /* for the I2C transfer */
108 struct i2c_msg msg[2];
109 u8 i2c_write_buffer[255];
110 u8 i2c_read_buffer[255];
Patrick Boettcher79fcce32011-08-03 12:08:21 -0300111 DIB_LOCK demod_lock;
112 u8 get_frontend_internal;
113 struct dib9000_pid_ctrl pid_ctrl[10];
114 s8 pid_ctrl_index; /* -1: empty list; -2: do not use the list */
Olivier Greniedd316c62011-01-04 04:28:59 -0300115};
116
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300117static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Olivier Greniedd316c62011-01-04 04:28:59 -0300118 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300119 0, 0, 0, 0, 0, 0, 0, 0
Olivier Greniedd316c62011-01-04 04:28:59 -0300120};
121
122enum dib9000_power_mode {
123 DIB9000_POWER_ALL = 0,
124
125 DIB9000_POWER_NO,
126 DIB9000_POWER_INTERF_ANALOG_AGC,
127 DIB9000_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD,
128 DIB9000_POWER_COR4_CRY_ESRAM_MOUT_NUD,
129 DIB9000_POWER_INTERFACE_ONLY,
130};
131
132enum dib9000_out_messages {
133 OUT_MSG_HBM_ACK,
134 OUT_MSG_HOST_BUF_FAIL,
135 OUT_MSG_REQ_VERSION,
136 OUT_MSG_BRIDGE_I2C_W,
137 OUT_MSG_BRIDGE_I2C_R,
138 OUT_MSG_BRIDGE_APB_W,
139 OUT_MSG_BRIDGE_APB_R,
140 OUT_MSG_SCAN_CHANNEL,
141 OUT_MSG_MONIT_DEMOD,
142 OUT_MSG_CONF_GPIO,
143 OUT_MSG_DEBUG_HELP,
144 OUT_MSG_SUBBAND_SEL,
145 OUT_MSG_ENABLE_TIME_SLICE,
146 OUT_MSG_FE_FW_DL,
147 OUT_MSG_FE_CHANNEL_SEARCH,
148 OUT_MSG_FE_CHANNEL_TUNE,
149 OUT_MSG_FE_SLEEP,
150 OUT_MSG_FE_SYNC,
151 OUT_MSG_CTL_MONIT,
152
153 OUT_MSG_CONF_SVC,
154 OUT_MSG_SET_HBM,
155 OUT_MSG_INIT_DEMOD,
156 OUT_MSG_ENABLE_DIVERSITY,
157 OUT_MSG_SET_OUTPUT_MODE,
158 OUT_MSG_SET_PRIORITARY_CHANNEL,
159 OUT_MSG_ACK_FRG,
160 OUT_MSG_INIT_PMU,
161};
162
163enum dib9000_in_messages {
164 IN_MSG_DATA,
165 IN_MSG_FRAME_INFO,
166 IN_MSG_CTL_MONIT,
167 IN_MSG_ACK_FREE_ITEM,
168 IN_MSG_DEBUG_BUF,
169 IN_MSG_MPE_MONITOR,
170 IN_MSG_RAWTS_MONITOR,
171 IN_MSG_END_BRIDGE_I2C_RW,
172 IN_MSG_END_BRIDGE_APB_RW,
173 IN_MSG_VERSION,
174 IN_MSG_END_OF_SCAN,
175 IN_MSG_MONIT_DEMOD,
176 IN_MSG_ERROR,
177 IN_MSG_FE_FW_DL_DONE,
178 IN_MSG_EVENT,
179 IN_MSG_ACK_CHANGE_SVC,
180 IN_MSG_HBM_PROF,
181};
182
183/* memory_access requests */
184#define FE_MM_W_CHANNEL 0
185#define FE_MM_W_FE_INFO 1
186#define FE_MM_RW_SYNC 2
187
188#define FE_SYNC_CHANNEL 1
189#define FE_SYNC_W_GENERIC_MONIT 2
190#define FE_SYNC_COMPONENT_ACCESS 3
191
192#define FE_MM_R_CHANNEL_SEARCH_STATE 3
193#define FE_MM_R_CHANNEL_UNION_CONTEXT 4
194#define FE_MM_R_FE_INFO 5
195#define FE_MM_R_FE_MONITOR 6
196
197#define FE_MM_W_CHANNEL_HEAD 7
198#define FE_MM_W_CHANNEL_UNION 8
199#define FE_MM_W_CHANNEL_CONTEXT 9
200#define FE_MM_R_CHANNEL_UNION 10
201#define FE_MM_R_CHANNEL_CONTEXT 11
202#define FE_MM_R_CHANNEL_TUNE_STATE 12
203
204#define FE_MM_R_GENERIC_MONITORING_SIZE 13
205#define FE_MM_W_GENERIC_MONITORING 14
206#define FE_MM_R_GENERIC_MONITORING 15
207
208#define FE_MM_W_COMPONENT_ACCESS 16
209#define FE_MM_RW_COMPONENT_ACCESS_BUFFER 17
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300210static int dib9000_risc_apb_access_read(struct dib9000_state *state, u32 address, u16 attribute, const u8 * tx, u32 txlen, u8 * b, u32 len);
Olivier Greniedd316c62011-01-04 04:28:59 -0300211static int dib9000_risc_apb_access_write(struct dib9000_state *state, u32 address, u16 attribute, const u8 * b, u32 len);
212
213static u16 to_fw_output_mode(u16 mode)
214{
215 switch (mode) {
216 case OUTMODE_HIGH_Z:
217 return 0;
218 case OUTMODE_MPEG2_PAR_GATED_CLK:
219 return 4;
220 case OUTMODE_MPEG2_PAR_CONT_CLK:
221 return 8;
222 case OUTMODE_MPEG2_SERIAL:
223 return 16;
224 case OUTMODE_DIVERSITY:
225 return 128;
226 case OUTMODE_MPEG2_FIFO:
227 return 2;
228 case OUTMODE_ANALOG_ADC:
229 return 1;
230 default:
231 return 0;
232 }
233}
234
235static u16 dib9000_read16_attr(struct dib9000_state *state, u16 reg, u8 * b, u32 len, u16 attribute)
236{
237 u32 chunk_size = 126;
238 u32 l;
239 int ret;
Olivier Greniedd316c62011-01-04 04:28:59 -0300240
241 if (state->platform.risc.fw_is_running && (reg < 1024))
242 return dib9000_risc_apb_access_read(state, reg, attribute, NULL, 0, b, len);
243
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300244 memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
245 state->msg[0].addr = state->i2c.i2c_addr >> 1;
246 state->msg[0].flags = 0;
247 state->msg[0].buf = state->i2c_write_buffer;
248 state->msg[0].len = 2;
249 state->msg[1].addr = state->i2c.i2c_addr >> 1;
250 state->msg[1].flags = I2C_M_RD;
251 state->msg[1].buf = b;
252 state->msg[1].len = len;
253
254 state->i2c_write_buffer[0] = reg >> 8;
255 state->i2c_write_buffer[1] = reg & 0xff;
256
Olivier Greniedd316c62011-01-04 04:28:59 -0300257 if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300258 state->i2c_write_buffer[0] |= (1 << 5);
Olivier Greniedd316c62011-01-04 04:28:59 -0300259 if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300260 state->i2c_write_buffer[0] |= (1 << 4);
Olivier Greniedd316c62011-01-04 04:28:59 -0300261
262 do {
263 l = len < chunk_size ? len : chunk_size;
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300264 state->msg[1].len = l;
265 state->msg[1].buf = b;
266 ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 2) != 2 ? -EREMOTEIO : 0;
Olivier Greniedd316c62011-01-04 04:28:59 -0300267 if (ret != 0) {
268 dprintk("i2c read error on %d", reg);
269 return -EREMOTEIO;
270 }
271
272 b += l;
273 len -= l;
274
275 if (!(attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT))
276 reg += l / 2;
277 } while ((ret == 0) && len);
278
279 return 0;
280}
281
282static u16 dib9000_i2c_read16(struct i2c_device *i2c, u16 reg)
283{
Olivier Greniedd316c62011-01-04 04:28:59 -0300284 struct i2c_msg msg[2] = {
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300285 {.addr = i2c->i2c_addr >> 1, .flags = 0,
286 .buf = i2c->i2c_write_buffer, .len = 2},
287 {.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD,
288 .buf = i2c->i2c_read_buffer, .len = 2},
Olivier Greniedd316c62011-01-04 04:28:59 -0300289 };
290
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300291 i2c->i2c_write_buffer[0] = reg >> 8;
292 i2c->i2c_write_buffer[1] = reg & 0xff;
293
Olivier Greniedd316c62011-01-04 04:28:59 -0300294 if (i2c_transfer(i2c->i2c_adap, msg, 2) != 2) {
295 dprintk("read register %x error", reg);
296 return 0;
297 }
298
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300299 return (i2c->i2c_read_buffer[0] << 8) | i2c->i2c_read_buffer[1];
Olivier Greniedd316c62011-01-04 04:28:59 -0300300}
301
302static inline u16 dib9000_read_word(struct dib9000_state *state, u16 reg)
303{
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300304 if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2, 0) != 0)
Olivier Greniedd316c62011-01-04 04:28:59 -0300305 return 0;
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300306 return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
Olivier Greniedd316c62011-01-04 04:28:59 -0300307}
308
309static inline u16 dib9000_read_word_attr(struct dib9000_state *state, u16 reg, u16 attribute)
310{
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300311 if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2,
312 attribute) != 0)
Olivier Greniedd316c62011-01-04 04:28:59 -0300313 return 0;
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300314 return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
Olivier Greniedd316c62011-01-04 04:28:59 -0300315}
316
317#define dib9000_read16_noinc_attr(state, reg, b, len, attribute) dib9000_read16_attr(state, reg, b, len, (attribute) | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
318
319static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 * buf, u32 len, u16 attribute)
320{
Olivier Greniedd316c62011-01-04 04:28:59 -0300321 u32 chunk_size = 126;
322 u32 l;
323 int ret;
324
Olivier Greniedd316c62011-01-04 04:28:59 -0300325 if (state->platform.risc.fw_is_running && (reg < 1024)) {
326 if (dib9000_risc_apb_access_write
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300327 (state, reg, DATA_BUS_ACCESS_MODE_16BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | attribute, buf, len) != 0)
Olivier Greniedd316c62011-01-04 04:28:59 -0300328 return -EINVAL;
329 return 0;
330 }
331
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300332 memset(&state->msg[0], 0, sizeof(struct i2c_msg));
333 state->msg[0].addr = state->i2c.i2c_addr >> 1;
334 state->msg[0].flags = 0;
335 state->msg[0].buf = state->i2c_write_buffer;
336 state->msg[0].len = len + 2;
337
338 state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
339 state->i2c_write_buffer[1] = (reg) & 0xff;
Olivier Greniedd316c62011-01-04 04:28:59 -0300340
341 if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300342 state->i2c_write_buffer[0] |= (1 << 5);
Olivier Greniedd316c62011-01-04 04:28:59 -0300343 if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300344 state->i2c_write_buffer[0] |= (1 << 4);
Olivier Greniedd316c62011-01-04 04:28:59 -0300345
346 do {
347 l = len < chunk_size ? len : chunk_size;
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300348 state->msg[0].len = l + 2;
349 memcpy(&state->i2c_write_buffer[2], buf, l);
Olivier Greniedd316c62011-01-04 04:28:59 -0300350
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300351 ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
Olivier Greniedd316c62011-01-04 04:28:59 -0300352
353 buf += l;
354 len -= l;
355
356 if (!(attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT))
357 reg += l / 2;
358 } while ((ret == 0) && len);
359
360 return ret;
361}
362
363static int dib9000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
364{
Olivier Greniedd316c62011-01-04 04:28:59 -0300365 struct i2c_msg msg = {
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300366 .addr = i2c->i2c_addr >> 1, .flags = 0,
367 .buf = i2c->i2c_write_buffer, .len = 4
Olivier Greniedd316c62011-01-04 04:28:59 -0300368 };
369
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300370 i2c->i2c_write_buffer[0] = (reg >> 8) & 0xff;
371 i2c->i2c_write_buffer[1] = reg & 0xff;
372 i2c->i2c_write_buffer[2] = (val >> 8) & 0xff;
373 i2c->i2c_write_buffer[3] = val & 0xff;
374
Olivier Greniedd316c62011-01-04 04:28:59 -0300375 return i2c_transfer(i2c->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
376}
377
378static inline int dib9000_write_word(struct dib9000_state *state, u16 reg, u16 val)
379{
380 u8 b[2] = { val >> 8, val & 0xff };
381 return dib9000_write16_attr(state, reg, b, 2, 0);
382}
383
384static inline int dib9000_write_word_attr(struct dib9000_state *state, u16 reg, u16 val, u16 attribute)
385{
386 u8 b[2] = { val >> 8, val & 0xff };
387 return dib9000_write16_attr(state, reg, b, 2, attribute);
388}
389
390#define dib9000_write(state, reg, buf, len) dib9000_write16_attr(state, reg, buf, len, 0)
391#define dib9000_write16_noinc(state, reg, buf, len) dib9000_write16_attr(state, reg, buf, len, DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
392#define dib9000_write16_noinc_attr(state, reg, buf, len, attribute) dib9000_write16_attr(state, reg, buf, len, DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | (attribute))
393
394#define dib9000_mbx_send(state, id, data, len) dib9000_mbx_send_attr(state, id, data, len, 0)
395#define dib9000_mbx_get_message(state, id, msg, len) dib9000_mbx_get_message_attr(state, id, msg, len, 0)
396
397#define MAC_IRQ (1 << 1)
398#define IRQ_POL_MSK (1 << 4)
399
400#define dib9000_risc_mem_read_chunks(state, b, len) dib9000_read16_attr(state, 1063, b, len, DATA_BUS_ACCESS_MODE_8BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
401#define dib9000_risc_mem_write_chunks(state, buf, len) dib9000_write16_attr(state, 1063, buf, len, DATA_BUS_ACCESS_MODE_8BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
402
403static void dib9000_risc_mem_setup_cmd(struct dib9000_state *state, u32 addr, u32 len, u8 reading)
404{
405 u8 b[14] = { 0 };
406
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300407/* dprintk("%d memcmd: %d %d %d\n", state->fe_id, addr, addr+len, len); */
408/* b[0] = 0 << 7; */
Olivier Greniedd316c62011-01-04 04:28:59 -0300409 b[1] = 1;
410
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300411/* b[2] = 0; */
412/* b[3] = 0; */
413 b[4] = (u8) (addr >> 8);
Olivier Greniedd316c62011-01-04 04:28:59 -0300414 b[5] = (u8) (addr & 0xff);
415
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300416/* b[10] = 0; */
417/* b[11] = 0; */
418 b[12] = (u8) (addr >> 8);
Olivier Greniedd316c62011-01-04 04:28:59 -0300419 b[13] = (u8) (addr & 0xff);
420
421 addr += len;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300422/* b[6] = 0; */
423/* b[7] = 0; */
424 b[8] = (u8) (addr >> 8);
Olivier Greniedd316c62011-01-04 04:28:59 -0300425 b[9] = (u8) (addr & 0xff);
426
427 dib9000_write(state, 1056, b, 14);
428 if (reading)
429 dib9000_write_word(state, 1056, (1 << 15) | 1);
430 state->platform.risc.memcmd = -1; /* if it was called directly reset it - to force a future setup-call to set it */
431}
432
433static void dib9000_risc_mem_setup(struct dib9000_state *state, u8 cmd)
434{
435 struct dib9000_fe_memory_map *m = &state->platform.risc.fe_mm[cmd & 0x7f];
436 /* decide whether we need to "refresh" the memory controller */
437 if (state->platform.risc.memcmd == cmd && /* same command */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300438 !(cmd & 0x80 && m->size < 67)) /* and we do not want to read something with less than 67 bytes looping - working around a bug in the memory controller */
Olivier Greniedd316c62011-01-04 04:28:59 -0300439 return;
440 dib9000_risc_mem_setup_cmd(state, m->addr, m->size, cmd & 0x80);
441 state->platform.risc.memcmd = cmd;
442}
443
444static int dib9000_risc_mem_read(struct dib9000_state *state, u8 cmd, u8 * b, u16 len)
445{
446 if (!state->platform.risc.fw_is_running)
447 return -EIO;
448
449 DibAcquireLock(&state->platform.risc.mem_lock);
450 dib9000_risc_mem_setup(state, cmd | 0x80);
451 dib9000_risc_mem_read_chunks(state, b, len);
452 DibReleaseLock(&state->platform.risc.mem_lock);
453 return 0;
454}
455
456static int dib9000_risc_mem_write(struct dib9000_state *state, u8 cmd, const u8 * b)
457{
458 struct dib9000_fe_memory_map *m = &state->platform.risc.fe_mm[cmd];
459 if (!state->platform.risc.fw_is_running)
460 return -EIO;
461
462 DibAcquireLock(&state->platform.risc.mem_lock);
463 dib9000_risc_mem_setup(state, cmd);
464 dib9000_risc_mem_write_chunks(state, b, m->size);
465 DibReleaseLock(&state->platform.risc.mem_lock);
466 return 0;
467}
468
469static int dib9000_firmware_download(struct dib9000_state *state, u8 risc_id, u16 key, const u8 * code, u32 len)
470{
471 u16 offs;
472
473 if (risc_id == 1)
474 offs = 16;
475 else
476 offs = 0;
477
478 /* config crtl reg */
479 dib9000_write_word(state, 1024 + offs, 0x000f);
480 dib9000_write_word(state, 1025 + offs, 0);
481 dib9000_write_word(state, 1031 + offs, key);
482
483 dprintk("going to download %dB of microcode", len);
484 if (dib9000_write16_noinc(state, 1026 + offs, (u8 *) code, (u16) len) != 0) {
485 dprintk("error while downloading microcode for RISC %c", 'A' + risc_id);
486 return -EIO;
487 }
488
489 dprintk("Microcode for RISC %c loaded", 'A' + risc_id);
490
491 return 0;
492}
493
494static int dib9000_mbx_host_init(struct dib9000_state *state, u8 risc_id)
495{
496 u16 mbox_offs;
497 u16 reset_reg;
498 u16 tries = 1000;
499
500 if (risc_id == 1)
501 mbox_offs = 16;
502 else
503 mbox_offs = 0;
504
505 /* Reset mailbox */
506 dib9000_write_word(state, 1027 + mbox_offs, 0x8000);
507
508 /* Read reset status */
509 do {
510 reset_reg = dib9000_read_word(state, 1027 + mbox_offs);
511 msleep(100);
512 } while ((reset_reg & 0x8000) && --tries);
513
514 if (reset_reg & 0x8000) {
515 dprintk("MBX: init ERROR, no response from RISC %c", 'A' + risc_id);
516 return -EIO;
517 }
518 dprintk("MBX: initialized");
519 return 0;
520}
521
522#define MAX_MAILBOX_TRY 100
523static int dib9000_mbx_send_attr(struct dib9000_state *state, u8 id, u16 * data, u8 len, u16 attr)
524{
Dan Carpenterb00aff62011-01-19 11:28:27 -0300525 u8 *d, b[2];
Olivier Greniedd316c62011-01-04 04:28:59 -0300526 u16 tmp;
527 u16 size;
528 u32 i;
Dan Carpenterb00aff62011-01-19 11:28:27 -0300529 int ret = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -0300530
531 if (!state->platform.risc.fw_is_running)
532 return -EINVAL;
533
534 DibAcquireLock(&state->platform.risc.mbx_if_lock);
535 tmp = MAX_MAILBOX_TRY;
536 do {
537 size = dib9000_read_word_attr(state, 1043, attr) & 0xff;
538 if ((size + len + 1) > MBX_MAX_WORDS && --tmp) {
539 dprintk("MBX: RISC mbx full, retrying");
540 msleep(100);
541 } else
542 break;
543 } while (1);
544
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300545 /*dprintk( "MBX: size: %d", size); */
Olivier Greniedd316c62011-01-04 04:28:59 -0300546
547 if (tmp == 0) {
548 ret = -EINVAL;
549 goto out;
550 }
551#ifdef DUMP_MSG
552 dprintk("--> %02x %d ", id, len + 1);
553 for (i = 0; i < len; i++)
554 dprintk("%04x ", data[i]);
555 dprintk("\n");
556#endif
557
558 /* byte-order conversion - works on big (where it is not necessary) or little endian */
559 d = (u8 *) data;
560 for (i = 0; i < len; i++) {
561 tmp = data[i];
562 *d++ = tmp >> 8;
563 *d++ = tmp & 0xff;
564 }
565
566 /* write msg */
567 b[0] = id;
568 b[1] = len + 1;
569 if (dib9000_write16_noinc_attr(state, 1045, b, 2, attr) != 0 || dib9000_write16_noinc_attr(state, 1045, (u8 *) data, len * 2, attr) != 0) {
570 ret = -EIO;
571 goto out;
572 }
573
574 /* update register nb_mes_in_RX */
575 ret = (u8) dib9000_write_word_attr(state, 1043, 1 << 14, attr);
576
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300577out:
Olivier Greniedd316c62011-01-04 04:28:59 -0300578 DibReleaseLock(&state->platform.risc.mbx_if_lock);
579
580 return ret;
581}
582
583static u8 dib9000_mbx_read(struct dib9000_state *state, u16 * data, u8 risc_id, u16 attr)
584{
585#ifdef DUMP_MSG
586 u16 *d = data;
587#endif
588
589 u16 tmp, i;
590 u8 size;
591 u8 mc_base;
592
593 if (!state->platform.risc.fw_is_running)
594 return 0;
595
596 DibAcquireLock(&state->platform.risc.mbx_if_lock);
597 if (risc_id == 1)
598 mc_base = 16;
599 else
600 mc_base = 0;
601
602 /* Length and type in the first word */
603 *data = dib9000_read_word_attr(state, 1029 + mc_base, attr);
604
605 size = *data & 0xff;
606 if (size <= MBX_MAX_WORDS) {
607 data++;
608 size--; /* Initial word already read */
609
610 dib9000_read16_noinc_attr(state, 1029 + mc_base, (u8 *) data, size * 2, attr);
611
612 /* to word conversion */
613 for (i = 0; i < size; i++) {
614 tmp = *data;
615 *data = (tmp >> 8) | (tmp << 8);
616 data++;
617 }
618
619#ifdef DUMP_MSG
620 dprintk("<-- ");
621 for (i = 0; i < size + 1; i++)
622 dprintk("%04x ", d[i]);
623 dprintk("\n");
624#endif
625 } else {
626 dprintk("MBX: message is too big for message cache (%d), flushing message", size);
627 size--; /* Initial word already read */
628 while (size--)
629 dib9000_read16_noinc_attr(state, 1029 + mc_base, (u8 *) data, 2, attr);
630 }
631 /* Update register nb_mes_in_TX */
632 dib9000_write_word_attr(state, 1028 + mc_base, 1 << 14, attr);
633
634 DibReleaseLock(&state->platform.risc.mbx_if_lock);
635
636 return size + 1;
637}
638
639static int dib9000_risc_debug_buf(struct dib9000_state *state, u16 * data, u8 size)
640{
641 u32 ts = data[1] << 16 | data[0];
642 char *b = (char *)&data[2];
643
644 b[2 * (size - 2) - 1] = '\0'; /* Bullet proof the buffer */
645 if (*b == '~') {
646 b++;
647 dprintk(b);
648 } else
649 dprintk("RISC%d: %d.%04d %s", state->fe_id, ts / 10000, ts % 10000, *b ? b : "<emtpy>");
650 return 1;
651}
652
653static int dib9000_mbx_fetch_to_cache(struct dib9000_state *state, u16 attr)
654{
655 int i;
656 u8 size;
657 u16 *block;
658 /* find a free slot */
659 for (i = 0; i < DIB9000_MSG_CACHE_SIZE; i++) {
660 block = state->platform.risc.message_cache[i];
661 if (*block == 0) {
662 size = dib9000_mbx_read(state, block, 1, attr);
663
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300664/* dprintk( "MBX: fetched %04x message to cache", *block); */
Olivier Greniedd316c62011-01-04 04:28:59 -0300665
666 switch (*block >> 8) {
667 case IN_MSG_DEBUG_BUF:
668 dib9000_risc_debug_buf(state, block + 1, size); /* debug-messages are going to be printed right away */
669 *block = 0; /* free the block */
670 break;
671#if 0
672 case IN_MSG_DATA: /* FE-TRACE */
673 dib9000_risc_data_process(state, block + 1, size);
674 *block = 0;
675 break;
676#endif
677 default:
678 break;
679 }
680
681 return 1;
682 }
683 }
684 dprintk("MBX: no free cache-slot found for new message...");
685 return -1;
686}
687
688static u8 dib9000_mbx_count(struct dib9000_state *state, u8 risc_id, u16 attr)
689{
690 if (risc_id == 0)
691 return (u8) (dib9000_read_word_attr(state, 1028, attr) >> 10) & 0x1f; /* 5 bit field */
692 else
693 return (u8) (dib9000_read_word_attr(state, 1044, attr) >> 8) & 0x7f; /* 7 bit field */
694}
695
696static int dib9000_mbx_process(struct dib9000_state *state, u16 attr)
697{
698 int ret = 0;
699 u16 tmp;
700
701 if (!state->platform.risc.fw_is_running)
702 return -1;
703
704 DibAcquireLock(&state->platform.risc.mbx_lock);
705
706 if (dib9000_mbx_count(state, 1, attr)) /* 1=RiscB */
707 ret = dib9000_mbx_fetch_to_cache(state, attr);
708
709 tmp = dib9000_read_word_attr(state, 1229, attr); /* Clear the IRQ */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300710/* if (tmp) */
711/* dprintk( "cleared IRQ: %x", tmp); */
Olivier Greniedd316c62011-01-04 04:28:59 -0300712 DibReleaseLock(&state->platform.risc.mbx_lock);
713
714 return ret;
715}
716
717static int dib9000_mbx_get_message_attr(struct dib9000_state *state, u16 id, u16 * msg, u8 * size, u16 attr)
718{
719 u8 i;
720 u16 *block;
721 u16 timeout = 30;
722
723 *msg = 0;
724 do {
725 /* dib9000_mbx_get_from_cache(); */
726 for (i = 0; i < DIB9000_MSG_CACHE_SIZE; i++) {
727 block = state->platform.risc.message_cache[i];
728 if ((*block >> 8) == id) {
729 *size = (*block & 0xff) - 1;
730 memcpy(msg, block + 1, (*size) * 2);
731 *block = 0; /* free the block */
732 i = 0; /* signal that we found a message */
733 break;
734 }
735 }
736
737 if (i == 0)
738 break;
739
740 if (dib9000_mbx_process(state, attr) == -1) /* try to fetch one message - if any */
741 return -1;
742
743 } while (--timeout);
744
745 if (timeout == 0) {
746 dprintk("waiting for message %d timed out", id);
747 return -1;
748 }
749
750 return i == 0;
751}
752
753static int dib9000_risc_check_version(struct dib9000_state *state)
754{
755 u8 r[4];
756 u8 size;
757 u16 fw_version = 0;
758
759 if (dib9000_mbx_send(state, OUT_MSG_REQ_VERSION, &fw_version, 1) != 0)
760 return -EIO;
761
762 if (dib9000_mbx_get_message(state, IN_MSG_VERSION, (u16 *) r, &size) < 0)
763 return -EIO;
764
765 fw_version = (r[0] << 8) | r[1];
766 dprintk("RISC: ver: %d.%02d (IC: %d)", fw_version >> 10, fw_version & 0x3ff, (r[2] << 8) | r[3]);
767
768 if ((fw_version >> 10) != 7)
769 return -EINVAL;
770
771 switch (fw_version & 0x3ff) {
772 case 11:
773 case 12:
774 case 14:
775 case 15:
776 case 16:
777 case 17:
778 break;
779 default:
780 dprintk("RISC: invalid firmware version");
781 return -EINVAL;
782 }
783
784 dprintk("RISC: valid firmware version");
785 return 0;
786}
787
788static int dib9000_fw_boot(struct dib9000_state *state, const u8 * codeA, u32 lenA, const u8 * codeB, u32 lenB)
789{
790 /* Reconfig pool mac ram */
791 dib9000_write_word(state, 1225, 0x02); /* A: 8k C, 4 k D - B: 32k C 6 k D - IRAM 96k */
792 dib9000_write_word(state, 1226, 0x05);
793
794 /* Toggles IP crypto to Host APB interface. */
795 dib9000_write_word(state, 1542, 1);
796
797 /* Set jump and no jump in the dma box */
798 dib9000_write_word(state, 1074, 0);
799 dib9000_write_word(state, 1075, 0);
800
801 /* Set MAC as APB Master. */
802 dib9000_write_word(state, 1237, 0);
803
804 /* Reset the RISCs */
805 if (codeA != NULL)
806 dib9000_write_word(state, 1024, 2);
807 else
808 dib9000_write_word(state, 1024, 15);
809 if (codeB != NULL)
810 dib9000_write_word(state, 1040, 2);
811
812 if (codeA != NULL)
813 dib9000_firmware_download(state, 0, 0x1234, codeA, lenA);
814 if (codeB != NULL)
815 dib9000_firmware_download(state, 1, 0x1234, codeB, lenB);
816
817 /* Run the RISCs */
818 if (codeA != NULL)
819 dib9000_write_word(state, 1024, 0);
820 if (codeB != NULL)
821 dib9000_write_word(state, 1040, 0);
822
823 if (codeA != NULL)
824 if (dib9000_mbx_host_init(state, 0) != 0)
825 return -EIO;
826 if (codeB != NULL)
827 if (dib9000_mbx_host_init(state, 1) != 0)
828 return -EIO;
829
830 msleep(100);
831 state->platform.risc.fw_is_running = 1;
832
833 if (dib9000_risc_check_version(state) != 0)
834 return -EINVAL;
835
836 state->platform.risc.memcmd = 0xff;
837 return 0;
838}
839
840static u16 dib9000_identify(struct i2c_device *client)
841{
842 u16 value;
843
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300844 value = dib9000_i2c_read16(client, 896);
845 if (value != 0x01b3) {
Olivier Greniedd316c62011-01-04 04:28:59 -0300846 dprintk("wrong Vendor ID (0x%x)", value);
847 return 0;
848 }
849
850 value = dib9000_i2c_read16(client, 897);
851 if (value != 0x4000 && value != 0x4001 && value != 0x4002 && value != 0x4003 && value != 0x4004 && value != 0x4005) {
852 dprintk("wrong Device ID (0x%x)", value);
853 return 0;
854 }
855
856 /* protect this driver to be used with 7000PC */
857 if (value == 0x4000 && dib9000_i2c_read16(client, 769) == 0x4000) {
858 dprintk("this driver does not work with DiB7000PC");
859 return 0;
860 }
861
862 switch (value) {
863 case 0x4000:
864 dprintk("found DiB7000MA/PA/MB/PB");
865 break;
866 case 0x4001:
867 dprintk("found DiB7000HC");
868 break;
869 case 0x4002:
870 dprintk("found DiB7000MC");
871 break;
872 case 0x4003:
873 dprintk("found DiB9000A");
874 break;
875 case 0x4004:
876 dprintk("found DiB9000H");
877 break;
878 case 0x4005:
879 dprintk("found DiB9000M");
880 break;
881 }
882
883 return value;
884}
885
886static void dib9000_set_power_mode(struct dib9000_state *state, enum dib9000_power_mode mode)
887{
888 /* by default everything is going to be powered off */
889 u16 reg_903 = 0x3fff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906;
890 u8 offset;
891
892 if (state->revision == 0x4003 || state->revision == 0x4004 || state->revision == 0x4005)
893 offset = 1;
894 else
895 offset = 0;
896
897 reg_906 = dib9000_read_word(state, 906 + offset) | 0x3; /* keep settings for RISC */
898
899 /* now, depending on the requested mode, we power on */
900 switch (mode) {
901 /* power up everything in the demod */
902 case DIB9000_POWER_ALL:
903 reg_903 = 0x0000;
904 reg_904 = 0x0000;
905 reg_905 = 0x0000;
906 reg_906 = 0x0000;
907 break;
908
909 /* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */
910 case DIB9000_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */
911 reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2));
912 break;
913
914 case DIB9000_POWER_INTERF_ANALOG_AGC:
915 reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10));
916 reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2));
917 reg_906 &= ~((1 << 0));
918 break;
919
920 case DIB9000_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD:
921 reg_903 = 0x0000;
922 reg_904 = 0x801f;
923 reg_905 = 0x0000;
924 reg_906 &= ~((1 << 0));
925 break;
926
927 case DIB9000_POWER_COR4_CRY_ESRAM_MOUT_NUD:
928 reg_903 = 0x0000;
929 reg_904 = 0x8000;
930 reg_905 = 0x010b;
931 reg_906 &= ~((1 << 0));
932 break;
933 default:
934 case DIB9000_POWER_NO:
935 break;
936 }
937
938 /* always power down unused parts */
939 if (!state->platform.host.mobile_mode)
940 reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1);
941
942 /* P_sdio_select_clk = 0 on MC and after */
943 if (state->revision != 0x4000)
944 reg_906 <<= 1;
945
946 dib9000_write_word(state, 903 + offset, reg_903);
947 dib9000_write_word(state, 904 + offset, reg_904);
948 dib9000_write_word(state, 905 + offset, reg_905);
949 dib9000_write_word(state, 906 + offset, reg_906);
950}
951
952static int dib9000_fw_reset(struct dvb_frontend *fe)
953{
954 struct dib9000_state *state = fe->demodulator_priv;
955
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300956 dib9000_write_word(state, 1817, 0x0003);
Olivier Greniedd316c62011-01-04 04:28:59 -0300957
958 dib9000_write_word(state, 1227, 1);
959 dib9000_write_word(state, 1227, 0);
960
961 switch ((state->revision = dib9000_identify(&state->i2c))) {
962 case 0x4003:
963 case 0x4004:
964 case 0x4005:
965 state->reg_offs = 1;
966 break;
967 default:
968 return -EINVAL;
969 }
970
971 /* reset the i2c-master to use the host interface */
972 dibx000_reset_i2c_master(&state->i2c_master);
973
974 dib9000_set_power_mode(state, DIB9000_POWER_ALL);
975
976 /* unforce divstr regardless whether i2c enumeration was done or not */
977 dib9000_write_word(state, 1794, dib9000_read_word(state, 1794) & ~(1 << 1));
978 dib9000_write_word(state, 1796, 0);
979 dib9000_write_word(state, 1805, 0x805);
980
981 /* restart all parts */
982 dib9000_write_word(state, 898, 0xffff);
983 dib9000_write_word(state, 899, 0xffff);
984 dib9000_write_word(state, 900, 0x0001);
985 dib9000_write_word(state, 901, 0xff19);
986 dib9000_write_word(state, 902, 0x003c);
987
988 dib9000_write_word(state, 898, 0);
989 dib9000_write_word(state, 899, 0);
990 dib9000_write_word(state, 900, 0);
991 dib9000_write_word(state, 901, 0);
992 dib9000_write_word(state, 902, 0);
993
994 dib9000_write_word(state, 911, state->chip.d9.cfg.if_drives);
995
996 dib9000_set_power_mode(state, DIB9000_POWER_INTERFACE_ONLY);
997
998 return 0;
999}
1000
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001001static int dib9000_risc_apb_access_read(struct dib9000_state *state, u32 address, u16 attribute, const u8 * tx, u32 txlen, u8 * b, u32 len)
Olivier Greniedd316c62011-01-04 04:28:59 -03001002{
1003 u16 mb[10];
1004 u8 i, s;
1005
1006 if (address >= 1024 || !state->platform.risc.fw_is_running)
1007 return -EINVAL;
1008
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001009 /* dprintk( "APB access thru rd fw %d %x", address, attribute); */
Olivier Greniedd316c62011-01-04 04:28:59 -03001010
1011 mb[0] = (u16) address;
1012 mb[1] = len / 2;
1013 dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_R, mb, 2, attribute);
1014 switch (dib9000_mbx_get_message_attr(state, IN_MSG_END_BRIDGE_APB_RW, mb, &s, attribute)) {
1015 case 1:
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001016 s--;
Olivier Greniedd316c62011-01-04 04:28:59 -03001017 for (i = 0; i < s; i++) {
1018 b[i * 2] = (mb[i + 1] >> 8) & 0xff;
1019 b[i * 2 + 1] = (mb[i + 1]) & 0xff;
1020 }
1021 return 0;
1022 default:
1023 return -EIO;
1024 }
1025 return -EIO;
1026}
1027
1028static int dib9000_risc_apb_access_write(struct dib9000_state *state, u32 address, u16 attribute, const u8 * b, u32 len)
1029{
1030 u16 mb[10];
1031 u8 s, i;
1032
1033 if (address >= 1024 || !state->platform.risc.fw_is_running)
1034 return -EINVAL;
1035
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001036 /* dprintk( "APB access thru wr fw %d %x", address, attribute); */
Olivier Greniedd316c62011-01-04 04:28:59 -03001037
1038 mb[0] = (unsigned short)address;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001039 for (i = 0; i < len && i < 20; i += 2)
Olivier Greniedd316c62011-01-04 04:28:59 -03001040 mb[1 + (i / 2)] = (b[i] << 8 | b[i + 1]);
1041
1042 dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_W, mb, 1 + len / 2, attribute);
1043 return dib9000_mbx_get_message_attr(state, IN_MSG_END_BRIDGE_APB_RW, mb, &s, attribute) == 1 ? 0 : -EINVAL;
1044}
1045
1046static int dib9000_fw_memmbx_sync(struct dib9000_state *state, u8 i)
1047{
1048 u8 index_loop = 10;
1049
1050 if (!state->platform.risc.fw_is_running)
1051 return 0;
1052 dib9000_risc_mem_write(state, FE_MM_RW_SYNC, &i);
1053 do {
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001054 dib9000_risc_mem_read(state, FE_MM_RW_SYNC, state->i2c_read_buffer, 1);
1055 } while (state->i2c_read_buffer[0] && index_loop--);
Olivier Greniedd316c62011-01-04 04:28:59 -03001056
1057 if (index_loop > 0)
1058 return 0;
1059 return -EIO;
1060}
1061
1062static int dib9000_fw_init(struct dib9000_state *state)
1063{
1064 struct dibGPIOFunction *f;
1065 u16 b[40] = { 0 };
1066 u8 i;
1067 u8 size;
1068
1069 if (dib9000_fw_boot(state, NULL, 0, state->chip.d9.cfg.microcode_B_fe_buffer, state->chip.d9.cfg.microcode_B_fe_size) != 0)
Olivier Greniedd316c62011-01-04 04:28:59 -03001070 return -EIO;
1071
1072 /* initialize the firmware */
1073 for (i = 0; i < ARRAY_SIZE(state->chip.d9.cfg.gpio_function); i++) {
1074 f = &state->chip.d9.cfg.gpio_function[i];
1075 if (f->mask) {
1076 switch (f->function) {
1077 case BOARD_GPIO_FUNCTION_COMPONENT_ON:
1078 b[0] = (u16) f->mask;
1079 b[1] = (u16) f->direction;
1080 b[2] = (u16) f->value;
1081 break;
1082 case BOARD_GPIO_FUNCTION_COMPONENT_OFF:
1083 b[3] = (u16) f->mask;
1084 b[4] = (u16) f->direction;
1085 b[5] = (u16) f->value;
1086 break;
1087 }
1088 }
1089 }
1090 if (dib9000_mbx_send(state, OUT_MSG_CONF_GPIO, b, 15) != 0)
1091 return -EIO;
1092
1093 /* subband */
1094 b[0] = state->chip.d9.cfg.subband.size; /* type == 0 -> GPIO - PWM not yet supported */
1095 for (i = 0; i < state->chip.d9.cfg.subband.size; i++) {
1096 b[1 + i * 4] = state->chip.d9.cfg.subband.subband[i].f_mhz;
1097 b[2 + i * 4] = (u16) state->chip.d9.cfg.subband.subband[i].gpio.mask;
1098 b[3 + i * 4] = (u16) state->chip.d9.cfg.subband.subband[i].gpio.direction;
1099 b[4 + i * 4] = (u16) state->chip.d9.cfg.subband.subband[i].gpio.value;
Olivier Greniedd316c62011-01-04 04:28:59 -03001100 }
1101 b[1 + i * 4] = 0; /* fe_id */
1102 if (dib9000_mbx_send(state, OUT_MSG_SUBBAND_SEL, b, 2 + 4 * i) != 0)
1103 return -EIO;
1104
1105 /* 0 - id, 1 - no_of_frontends */
1106 b[0] = (0 << 8) | 1;
1107 /* 0 = i2c-address demod, 0 = tuner */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001108 b[1] = (0 << 8) | (0);
Olivier Greniedd316c62011-01-04 04:28:59 -03001109 b[2] = (u16) (((state->chip.d9.cfg.xtal_clock_khz * 1000) >> 16) & 0xffff);
1110 b[3] = (u16) (((state->chip.d9.cfg.xtal_clock_khz * 1000)) & 0xffff);
1111 b[4] = (u16) ((state->chip.d9.cfg.vcxo_timer >> 16) & 0xffff);
1112 b[5] = (u16) ((state->chip.d9.cfg.vcxo_timer) & 0xffff);
1113 b[6] = (u16) ((state->chip.d9.cfg.timing_frequency >> 16) & 0xffff);
1114 b[7] = (u16) ((state->chip.d9.cfg.timing_frequency) & 0xffff);
1115 b[29] = state->chip.d9.cfg.if_drives;
1116 if (dib9000_mbx_send(state, OUT_MSG_INIT_DEMOD, b, ARRAY_SIZE(b)) != 0)
1117 return -EIO;
1118
1119 if (dib9000_mbx_send(state, OUT_MSG_FE_FW_DL, NULL, 0) != 0)
1120 return -EIO;
1121
1122 if (dib9000_mbx_get_message(state, IN_MSG_FE_FW_DL_DONE, b, &size) < 0)
1123 return -EIO;
1124
1125 if (size > ARRAY_SIZE(b)) {
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001126 dprintk("error : firmware returned %dbytes needed but the used buffer has only %dbytes\n Firmware init ABORTED", size,
1127 (int)ARRAY_SIZE(b));
Olivier Greniedd316c62011-01-04 04:28:59 -03001128 return -EINVAL;
1129 }
1130
1131 for (i = 0; i < size; i += 2) {
1132 state->platform.risc.fe_mm[i / 2].addr = b[i + 0];
1133 state->platform.risc.fe_mm[i / 2].size = b[i + 1];
Olivier Greniedd316c62011-01-04 04:28:59 -03001134 }
1135
1136 return 0;
1137}
1138
Mauro Carvalho Chehab759e2362011-12-22 19:54:08 -03001139static void dib9000_fw_set_channel_head(struct dib9000_state *state)
Olivier Greniedd316c62011-01-04 04:28:59 -03001140{
1141 u8 b[9];
1142 u32 freq = state->fe[0]->dtv_property_cache.frequency / 1000;
1143 if (state->fe_id % 2)
1144 freq += 101;
1145
1146 b[0] = (u8) ((freq >> 0) & 0xff);
1147 b[1] = (u8) ((freq >> 8) & 0xff);
1148 b[2] = (u8) ((freq >> 16) & 0xff);
1149 b[3] = (u8) ((freq >> 24) & 0xff);
1150 b[4] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 0) & 0xff);
1151 b[5] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 8) & 0xff);
1152 b[6] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 16) & 0xff);
1153 b[7] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 24) & 0xff);
1154 b[8] = 0x80; /* do not wait for CELL ID when doing autosearch */
1155 if (state->fe[0]->dtv_property_cache.delivery_system == SYS_DVBT)
1156 b[8] |= 1;
1157 dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_HEAD, b);
1158}
1159
Mauro Carvalho Chehab759e2362011-12-22 19:54:08 -03001160static int dib9000_fw_get_channel(struct dvb_frontend *fe)
Olivier Greniedd316c62011-01-04 04:28:59 -03001161{
1162 struct dib9000_state *state = fe->demodulator_priv;
1163 struct dibDVBTChannel {
1164 s8 spectrum_inversion;
1165
1166 s8 nfft;
1167 s8 guard;
1168 s8 constellation;
1169
1170 s8 hrch;
1171 s8 alpha;
1172 s8 code_rate_hp;
1173 s8 code_rate_lp;
1174 s8 select_hp;
1175
1176 s8 intlv_native;
1177 };
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001178 struct dibDVBTChannel *ch;
Olivier Greniedd316c62011-01-04 04:28:59 -03001179 int ret = 0;
1180
1181 DibAcquireLock(&state->platform.risc.mem_mbx_lock);
1182 if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001183 ret = -EIO;
Dan Carpenter2f098cb2011-08-06 05:01:51 -03001184 goto error;
Olivier Greniedd316c62011-01-04 04:28:59 -03001185 }
1186
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001187 dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION,
1188 state->i2c_read_buffer, sizeof(struct dibDVBTChannel));
1189 ch = (struct dibDVBTChannel *)state->i2c_read_buffer;
Olivier Greniedd316c62011-01-04 04:28:59 -03001190
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001191
1192 switch (ch->spectrum_inversion & 0x7) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001193 case 1:
1194 state->fe[0]->dtv_property_cache.inversion = INVERSION_ON;
1195 break;
1196 case 0:
1197 state->fe[0]->dtv_property_cache.inversion = INVERSION_OFF;
1198 break;
1199 default:
1200 case -1:
1201 state->fe[0]->dtv_property_cache.inversion = INVERSION_AUTO;
1202 break;
1203 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001204 switch (ch->nfft) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001205 case 0:
1206 state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
1207 break;
1208 case 2:
1209 state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_4K;
1210 break;
1211 case 1:
1212 state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
1213 break;
1214 default:
1215 case -1:
1216 state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO;
1217 break;
1218 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001219 switch (ch->guard) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001220 case 0:
1221 state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
1222 break;
1223 case 1:
1224 state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16;
1225 break;
1226 case 2:
1227 state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
1228 break;
1229 case 3:
1230 state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4;
1231 break;
1232 default:
1233 case -1:
1234 state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO;
1235 break;
1236 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001237 switch (ch->constellation) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001238 case 2:
1239 state->fe[0]->dtv_property_cache.modulation = QAM_64;
1240 break;
1241 case 1:
1242 state->fe[0]->dtv_property_cache.modulation = QAM_16;
1243 break;
1244 case 0:
1245 state->fe[0]->dtv_property_cache.modulation = QPSK;
1246 break;
1247 default:
1248 case -1:
1249 state->fe[0]->dtv_property_cache.modulation = QAM_AUTO;
1250 break;
1251 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001252 switch (ch->hrch) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001253 case 0:
1254 state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_NONE;
1255 break;
1256 case 1:
1257 state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_1;
1258 break;
1259 default:
1260 case -1:
1261 state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_AUTO;
1262 break;
1263 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001264 switch (ch->code_rate_hp) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001265 case 1:
1266 state->fe[0]->dtv_property_cache.code_rate_HP = FEC_1_2;
1267 break;
1268 case 2:
1269 state->fe[0]->dtv_property_cache.code_rate_HP = FEC_2_3;
1270 break;
1271 case 3:
1272 state->fe[0]->dtv_property_cache.code_rate_HP = FEC_3_4;
1273 break;
1274 case 5:
1275 state->fe[0]->dtv_property_cache.code_rate_HP = FEC_5_6;
1276 break;
1277 case 7:
1278 state->fe[0]->dtv_property_cache.code_rate_HP = FEC_7_8;
1279 break;
1280 default:
1281 case -1:
1282 state->fe[0]->dtv_property_cache.code_rate_HP = FEC_AUTO;
1283 break;
1284 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001285 switch (ch->code_rate_lp) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001286 case 1:
1287 state->fe[0]->dtv_property_cache.code_rate_LP = FEC_1_2;
1288 break;
1289 case 2:
1290 state->fe[0]->dtv_property_cache.code_rate_LP = FEC_2_3;
1291 break;
1292 case 3:
1293 state->fe[0]->dtv_property_cache.code_rate_LP = FEC_3_4;
1294 break;
1295 case 5:
1296 state->fe[0]->dtv_property_cache.code_rate_LP = FEC_5_6;
1297 break;
1298 case 7:
1299 state->fe[0]->dtv_property_cache.code_rate_LP = FEC_7_8;
1300 break;
1301 default:
1302 case -1:
1303 state->fe[0]->dtv_property_cache.code_rate_LP = FEC_AUTO;
1304 break;
1305 }
1306
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001307error:
Olivier Greniedd316c62011-01-04 04:28:59 -03001308 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
1309 return ret;
1310}
1311
Mauro Carvalho Chehabf20b12e2011-12-22 20:42:12 -03001312static int dib9000_fw_set_channel_union(struct dvb_frontend *fe)
Olivier Greniedd316c62011-01-04 04:28:59 -03001313{
1314 struct dib9000_state *state = fe->demodulator_priv;
1315 struct dibDVBTChannel {
1316 s8 spectrum_inversion;
1317
1318 s8 nfft;
1319 s8 guard;
1320 s8 constellation;
1321
1322 s8 hrch;
1323 s8 alpha;
1324 s8 code_rate_hp;
1325 s8 code_rate_lp;
1326 s8 select_hp;
1327
1328 s8 intlv_native;
1329 };
1330 struct dibDVBTChannel ch;
1331
1332 switch (state->fe[0]->dtv_property_cache.inversion) {
1333 case INVERSION_ON:
1334 ch.spectrum_inversion = 1;
1335 break;
1336 case INVERSION_OFF:
1337 ch.spectrum_inversion = 0;
1338 break;
1339 default:
1340 case INVERSION_AUTO:
1341 ch.spectrum_inversion = -1;
1342 break;
1343 }
1344 switch (state->fe[0]->dtv_property_cache.transmission_mode) {
1345 case TRANSMISSION_MODE_2K:
1346 ch.nfft = 0;
1347 break;
1348 case TRANSMISSION_MODE_4K:
1349 ch.nfft = 2;
1350 break;
1351 case TRANSMISSION_MODE_8K:
1352 ch.nfft = 1;
1353 break;
1354 default:
1355 case TRANSMISSION_MODE_AUTO:
1356 ch.nfft = 1;
1357 break;
1358 }
1359 switch (state->fe[0]->dtv_property_cache.guard_interval) {
1360 case GUARD_INTERVAL_1_32:
1361 ch.guard = 0;
1362 break;
1363 case GUARD_INTERVAL_1_16:
1364 ch.guard = 1;
1365 break;
1366 case GUARD_INTERVAL_1_8:
1367 ch.guard = 2;
1368 break;
1369 case GUARD_INTERVAL_1_4:
1370 ch.guard = 3;
1371 break;
1372 default:
1373 case GUARD_INTERVAL_AUTO:
1374 ch.guard = -1;
1375 break;
1376 }
1377 switch (state->fe[0]->dtv_property_cache.modulation) {
1378 case QAM_64:
1379 ch.constellation = 2;
1380 break;
1381 case QAM_16:
1382 ch.constellation = 1;
1383 break;
1384 case QPSK:
1385 ch.constellation = 0;
1386 break;
1387 default:
1388 case QAM_AUTO:
1389 ch.constellation = -1;
1390 break;
1391 }
1392 switch (state->fe[0]->dtv_property_cache.hierarchy) {
1393 case HIERARCHY_NONE:
1394 ch.hrch = 0;
1395 break;
1396 case HIERARCHY_1:
1397 case HIERARCHY_2:
1398 case HIERARCHY_4:
1399 ch.hrch = 1;
1400 break;
1401 default:
1402 case HIERARCHY_AUTO:
1403 ch.hrch = -1;
1404 break;
1405 }
1406 ch.alpha = 1;
1407 switch (state->fe[0]->dtv_property_cache.code_rate_HP) {
1408 case FEC_1_2:
1409 ch.code_rate_hp = 1;
1410 break;
1411 case FEC_2_3:
1412 ch.code_rate_hp = 2;
1413 break;
1414 case FEC_3_4:
1415 ch.code_rate_hp = 3;
1416 break;
1417 case FEC_5_6:
1418 ch.code_rate_hp = 5;
1419 break;
1420 case FEC_7_8:
1421 ch.code_rate_hp = 7;
1422 break;
1423 default:
1424 case FEC_AUTO:
1425 ch.code_rate_hp = -1;
1426 break;
1427 }
1428 switch (state->fe[0]->dtv_property_cache.code_rate_LP) {
1429 case FEC_1_2:
1430 ch.code_rate_lp = 1;
1431 break;
1432 case FEC_2_3:
1433 ch.code_rate_lp = 2;
1434 break;
1435 case FEC_3_4:
1436 ch.code_rate_lp = 3;
1437 break;
1438 case FEC_5_6:
1439 ch.code_rate_lp = 5;
1440 break;
1441 case FEC_7_8:
1442 ch.code_rate_lp = 7;
1443 break;
1444 default:
1445 case FEC_AUTO:
1446 ch.code_rate_lp = -1;
1447 break;
1448 }
1449 ch.select_hp = 1;
1450 ch.intlv_native = 1;
1451
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001452 dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_UNION, (u8 *) &ch);
Olivier Greniedd316c62011-01-04 04:28:59 -03001453
1454 return 0;
1455}
1456
Mauro Carvalho Chehabf20b12e2011-12-22 20:42:12 -03001457static int dib9000_fw_tune(struct dvb_frontend *fe)
Olivier Greniedd316c62011-01-04 04:28:59 -03001458{
1459 struct dib9000_state *state = fe->demodulator_priv;
1460 int ret = 10, search = state->channel_status.status == CHANNEL_STATUS_PARAMETERS_UNKNOWN;
1461 s8 i;
1462
1463 switch (state->tune_state) {
1464 case CT_DEMOD_START:
Mauro Carvalho Chehab759e2362011-12-22 19:54:08 -03001465 dib9000_fw_set_channel_head(state);
Olivier Greniedd316c62011-01-04 04:28:59 -03001466
1467 /* write the channel context - a channel is initialized to 0, so it is OK */
1468 dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_CONTEXT, (u8 *) fe_info);
1469 dib9000_risc_mem_write(state, FE_MM_W_FE_INFO, (u8 *) fe_info);
1470
1471 if (search)
1472 dib9000_mbx_send(state, OUT_MSG_FE_CHANNEL_SEARCH, NULL, 0);
1473 else {
Mauro Carvalho Chehabf20b12e2011-12-22 20:42:12 -03001474 dib9000_fw_set_channel_union(fe);
Olivier Greniedd316c62011-01-04 04:28:59 -03001475 dib9000_mbx_send(state, OUT_MSG_FE_CHANNEL_TUNE, NULL, 0);
1476 }
1477 state->tune_state = CT_DEMOD_STEP_1;
1478 break;
1479 case CT_DEMOD_STEP_1:
1480 if (search)
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001481 dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, state->i2c_read_buffer, 1);
Olivier Greniedd316c62011-01-04 04:28:59 -03001482 else
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001483 dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, state->i2c_read_buffer, 1);
1484 i = (s8)state->i2c_read_buffer[0];
Olivier Greniedd316c62011-01-04 04:28:59 -03001485 switch (i) { /* something happened */
1486 case 0:
1487 break;
1488 case -2: /* tps locks are "slower" than MPEG locks -> even in autosearch data is OK here */
1489 if (search)
1490 state->status = FE_STATUS_DEMOD_SUCCESS;
1491 else {
1492 state->tune_state = CT_DEMOD_STOP;
1493 state->status = FE_STATUS_LOCKED;
1494 }
1495 break;
1496 default:
1497 state->status = FE_STATUS_TUNE_FAILED;
1498 state->tune_state = CT_DEMOD_STOP;
1499 break;
1500 }
1501 break;
1502 default:
1503 ret = FE_CALLBACK_TIME_NEVER;
1504 break;
1505 }
1506
1507 return ret;
1508}
1509
1510static int dib9000_fw_set_diversity_in(struct dvb_frontend *fe, int onoff)
1511{
1512 struct dib9000_state *state = fe->demodulator_priv;
1513 u16 mode = (u16) onoff;
1514 return dib9000_mbx_send(state, OUT_MSG_ENABLE_DIVERSITY, &mode, 1);
1515}
1516
1517static int dib9000_fw_set_output_mode(struct dvb_frontend *fe, int mode)
1518{
1519 struct dib9000_state *state = fe->demodulator_priv;
1520 u16 outreg, smo_mode;
1521
1522 dprintk("setting output mode for demod %p to %d", fe, mode);
1523
1524 switch (mode) {
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001525 case OUTMODE_MPEG2_PAR_GATED_CLK:
Olivier Greniedd316c62011-01-04 04:28:59 -03001526 outreg = (1 << 10); /* 0x0400 */
1527 break;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001528 case OUTMODE_MPEG2_PAR_CONT_CLK:
Olivier Greniedd316c62011-01-04 04:28:59 -03001529 outreg = (1 << 10) | (1 << 6); /* 0x0440 */
1530 break;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001531 case OUTMODE_MPEG2_SERIAL:
Olivier Greniedd316c62011-01-04 04:28:59 -03001532 outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */
1533 break;
1534 case OUTMODE_DIVERSITY:
1535 outreg = (1 << 10) | (4 << 6); /* 0x0500 */
1536 break;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001537 case OUTMODE_MPEG2_FIFO:
Olivier Greniedd316c62011-01-04 04:28:59 -03001538 outreg = (1 << 10) | (5 << 6);
1539 break;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001540 case OUTMODE_HIGH_Z:
Olivier Greniedd316c62011-01-04 04:28:59 -03001541 outreg = 0;
1542 break;
1543 default:
1544 dprintk("Unhandled output_mode passed to be set for demod %p", &state->fe[0]);
1545 return -EINVAL;
1546 }
1547
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001548 dib9000_write_word(state, 1795, outreg);
Olivier Greniedd316c62011-01-04 04:28:59 -03001549
1550 switch (mode) {
1551 case OUTMODE_MPEG2_PAR_GATED_CLK:
1552 case OUTMODE_MPEG2_PAR_CONT_CLK:
1553 case OUTMODE_MPEG2_SERIAL:
1554 case OUTMODE_MPEG2_FIFO:
1555 smo_mode = (dib9000_read_word(state, 295) & 0x0010) | (1 << 1);
1556 if (state->chip.d9.cfg.output_mpeg2_in_188_bytes)
1557 smo_mode |= (1 << 5);
1558 dib9000_write_word(state, 295, smo_mode);
1559 break;
1560 }
1561
1562 outreg = to_fw_output_mode(mode);
1563 return dib9000_mbx_send(state, OUT_MSG_SET_OUTPUT_MODE, &outreg, 1);
1564}
1565
1566static int dib9000_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
1567{
1568 struct dib9000_state *state = i2c_get_adapdata(i2c_adap);
1569 u16 i, len, t, index_msg;
1570
1571 for (index_msg = 0; index_msg < num; index_msg++) {
1572 if (msg[index_msg].flags & I2C_M_RD) { /* read */
1573 len = msg[index_msg].len;
1574 if (len > 16)
1575 len = 16;
1576
1577 if (dib9000_read_word(state, 790) != 0)
1578 dprintk("TunerITF: read busy");
1579
1580 dib9000_write_word(state, 784, (u16) (msg[index_msg].addr));
1581 dib9000_write_word(state, 787, (len / 2) - 1);
1582 dib9000_write_word(state, 786, 1); /* start read */
1583
1584 i = 1000;
1585 while (dib9000_read_word(state, 790) != (len / 2) && i)
1586 i--;
1587
1588 if (i == 0)
1589 dprintk("TunerITF: read failed");
1590
1591 for (i = 0; i < len; i += 2) {
1592 t = dib9000_read_word(state, 785);
1593 msg[index_msg].buf[i] = (t >> 8) & 0xff;
1594 msg[index_msg].buf[i + 1] = (t) & 0xff;
1595 }
1596 if (dib9000_read_word(state, 790) != 0)
1597 dprintk("TunerITF: read more data than expected");
1598 } else {
1599 i = 1000;
1600 while (dib9000_read_word(state, 789) && i)
1601 i--;
1602 if (i == 0)
1603 dprintk("TunerITF: write busy");
1604
1605 len = msg[index_msg].len;
1606 if (len > 16)
1607 len = 16;
1608
1609 for (i = 0; i < len; i += 2)
1610 dib9000_write_word(state, 785, (msg[index_msg].buf[i] << 8) | msg[index_msg].buf[i + 1]);
1611 dib9000_write_word(state, 784, (u16) msg[index_msg].addr);
1612 dib9000_write_word(state, 787, (len / 2) - 1);
1613 dib9000_write_word(state, 786, 0); /* start write */
1614
1615 i = 1000;
1616 while (dib9000_read_word(state, 791) > 0 && i)
1617 i--;
1618 if (i == 0)
1619 dprintk("TunerITF: write failed");
1620 }
1621 }
1622 return num;
1623}
1624
1625int dib9000_fw_set_component_bus_speed(struct dvb_frontend *fe, u16 speed)
1626{
1627 struct dib9000_state *state = fe->demodulator_priv;
1628
1629 state->component_bus_speed = speed;
1630 return 0;
1631}
1632EXPORT_SYMBOL(dib9000_fw_set_component_bus_speed);
1633
1634static int dib9000_fw_component_bus_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
1635{
1636 struct dib9000_state *state = i2c_get_adapdata(i2c_adap);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001637 u8 type = 0; /* I2C */
Olivier Greniedd316c62011-01-04 04:28:59 -03001638 u8 port = DIBX000_I2C_INTERFACE_GPIO_3_4;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001639 u16 scl = state->component_bus_speed; /* SCL frequency */
Olivier Greniedd316c62011-01-04 04:28:59 -03001640 struct dib9000_fe_memory_map *m = &state->platform.risc.fe_mm[FE_MM_RW_COMPONENT_ACCESS_BUFFER];
1641 u8 p[13] = { 0 };
1642
1643 p[0] = type;
1644 p[1] = port;
1645 p[2] = msg[0].addr << 1;
1646
1647 p[3] = (u8) scl & 0xff; /* scl */
1648 p[4] = (u8) (scl >> 8);
1649
Olivier Greniedd316c62011-01-04 04:28:59 -03001650 p[7] = 0;
1651 p[8] = 0;
1652
1653 p[9] = (u8) (msg[0].len);
1654 p[10] = (u8) (msg[0].len >> 8);
1655 if ((num > 1) && (msg[1].flags & I2C_M_RD)) {
1656 p[11] = (u8) (msg[1].len);
1657 p[12] = (u8) (msg[1].len >> 8);
1658 } else {
1659 p[11] = 0;
1660 p[12] = 0;
1661 }
1662
1663 DibAcquireLock(&state->platform.risc.mem_mbx_lock);
1664
1665 dib9000_risc_mem_write(state, FE_MM_W_COMPONENT_ACCESS, p);
1666
1667 { /* write-part */
1668 dib9000_risc_mem_setup_cmd(state, m->addr, msg[0].len, 0);
1669 dib9000_risc_mem_write_chunks(state, msg[0].buf, msg[0].len);
1670 }
1671
1672 /* do the transaction */
1673 if (dib9000_fw_memmbx_sync(state, FE_SYNC_COMPONENT_ACCESS) < 0) {
1674 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
1675 return 0;
1676 }
1677
1678 /* read back any possible result */
1679 if ((num > 1) && (msg[1].flags & I2C_M_RD))
1680 dib9000_risc_mem_read(state, FE_MM_RW_COMPONENT_ACCESS_BUFFER, msg[1].buf, msg[1].len);
1681
1682 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
1683
1684 return num;
1685}
1686
1687static u32 dib9000_i2c_func(struct i2c_adapter *adapter)
1688{
1689 return I2C_FUNC_I2C;
1690}
1691
1692static struct i2c_algorithm dib9000_tuner_algo = {
1693 .master_xfer = dib9000_tuner_xfer,
1694 .functionality = dib9000_i2c_func,
1695};
1696
1697static struct i2c_algorithm dib9000_component_bus_algo = {
1698 .master_xfer = dib9000_fw_component_bus_xfer,
1699 .functionality = dib9000_i2c_func,
1700};
1701
1702struct i2c_adapter *dib9000_get_tuner_interface(struct dvb_frontend *fe)
1703{
1704 struct dib9000_state *st = fe->demodulator_priv;
1705 return &st->tuner_adap;
1706}
Olivier Greniedd316c62011-01-04 04:28:59 -03001707EXPORT_SYMBOL(dib9000_get_tuner_interface);
1708
1709struct i2c_adapter *dib9000_get_component_bus_interface(struct dvb_frontend *fe)
1710{
1711 struct dib9000_state *st = fe->demodulator_priv;
1712 return &st->component_bus;
1713}
Olivier Greniedd316c62011-01-04 04:28:59 -03001714EXPORT_SYMBOL(dib9000_get_component_bus_interface);
1715
1716struct i2c_adapter *dib9000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
1717{
1718 struct dib9000_state *st = fe->demodulator_priv;
1719 return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
1720}
Olivier Greniedd316c62011-01-04 04:28:59 -03001721EXPORT_SYMBOL(dib9000_get_i2c_master);
1722
1723int dib9000_set_i2c_adapter(struct dvb_frontend *fe, struct i2c_adapter *i2c)
1724{
1725 struct dib9000_state *st = fe->demodulator_priv;
1726
1727 st->i2c.i2c_adap = i2c;
1728 return 0;
1729}
Olivier Greniedd316c62011-01-04 04:28:59 -03001730EXPORT_SYMBOL(dib9000_set_i2c_adapter);
1731
1732static int dib9000_cfg_gpio(struct dib9000_state *st, u8 num, u8 dir, u8 val)
1733{
1734 st->gpio_dir = dib9000_read_word(st, 773);
1735 st->gpio_dir &= ~(1 << num); /* reset the direction bit */
1736 st->gpio_dir |= (dir & 0x1) << num; /* set the new direction */
1737 dib9000_write_word(st, 773, st->gpio_dir);
1738
1739 st->gpio_val = dib9000_read_word(st, 774);
1740 st->gpio_val &= ~(1 << num); /* reset the direction bit */
1741 st->gpio_val |= (val & 0x01) << num; /* set the new value */
1742 dib9000_write_word(st, 774, st->gpio_val);
1743
1744 dprintk("gpio dir: %04x: gpio val: %04x", st->gpio_dir, st->gpio_val);
1745
1746 return 0;
1747}
1748
1749int dib9000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
1750{
1751 struct dib9000_state *state = fe->demodulator_priv;
1752 return dib9000_cfg_gpio(state, num, dir, val);
1753}
Olivier Greniedd316c62011-01-04 04:28:59 -03001754EXPORT_SYMBOL(dib9000_set_gpio);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001755
Olivier Greniedd316c62011-01-04 04:28:59 -03001756int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
1757{
1758 struct dib9000_state *state = fe->demodulator_priv;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001759 u16 val;
1760 int ret;
1761
1762 if ((state->pid_ctrl_index != -2) && (state->pid_ctrl_index < 9)) {
1763 /* postpone the pid filtering cmd */
1764 dprintk("pid filter cmd postpone");
1765 state->pid_ctrl_index++;
1766 state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER_CTRL;
1767 state->pid_ctrl[state->pid_ctrl_index].onoff = onoff;
1768 return 0;
1769 }
1770
1771 DibAcquireLock(&state->demod_lock);
1772
1773 val = dib9000_read_word(state, 294 + 1) & 0xffef;
Olivier Greniedd316c62011-01-04 04:28:59 -03001774 val |= (onoff & 0x1) << 4;
1775
1776 dprintk("PID filter enabled %d", onoff);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001777 ret = dib9000_write_word(state, 294 + 1, val);
1778 DibReleaseLock(&state->demod_lock);
1779 return ret;
1780
Olivier Greniedd316c62011-01-04 04:28:59 -03001781}
Olivier Greniedd316c62011-01-04 04:28:59 -03001782EXPORT_SYMBOL(dib9000_fw_pid_filter_ctrl);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001783
Olivier Greniedd316c62011-01-04 04:28:59 -03001784int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
1785{
1786 struct dib9000_state *state = fe->demodulator_priv;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001787 int ret;
1788
1789 if (state->pid_ctrl_index != -2) {
1790 /* postpone the pid filtering cmd */
1791 dprintk("pid filter postpone");
1792 if (state->pid_ctrl_index < 9) {
1793 state->pid_ctrl_index++;
1794 state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER;
1795 state->pid_ctrl[state->pid_ctrl_index].id = id;
1796 state->pid_ctrl[state->pid_ctrl_index].pid = pid;
1797 state->pid_ctrl[state->pid_ctrl_index].onoff = onoff;
1798 } else
1799 dprintk("can not add any more pid ctrl cmd");
1800 return 0;
1801 }
1802
1803 DibAcquireLock(&state->demod_lock);
Olivier Greniedd316c62011-01-04 04:28:59 -03001804 dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001805 ret = dib9000_write_word(state, 300 + 1 + id,
1806 onoff ? (1 << 13) | pid : 0);
1807 DibReleaseLock(&state->demod_lock);
1808 return ret;
Olivier Greniedd316c62011-01-04 04:28:59 -03001809}
Olivier Greniedd316c62011-01-04 04:28:59 -03001810EXPORT_SYMBOL(dib9000_fw_pid_filter);
1811
1812int dib9000_firmware_post_pll_init(struct dvb_frontend *fe)
1813{
1814 struct dib9000_state *state = fe->demodulator_priv;
1815 return dib9000_fw_init(state);
1816}
Olivier Greniedd316c62011-01-04 04:28:59 -03001817EXPORT_SYMBOL(dib9000_firmware_post_pll_init);
1818
1819static void dib9000_release(struct dvb_frontend *demod)
1820{
1821 struct dib9000_state *st = demod->demodulator_priv;
1822 u8 index_frontend;
1823
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001824 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (st->fe[index_frontend] != NULL); index_frontend++)
Olivier Greniedd316c62011-01-04 04:28:59 -03001825 dvb_frontend_detach(st->fe[index_frontend]);
1826
1827 DibFreeLock(&state->platform.risc.mbx_if_lock);
1828 DibFreeLock(&state->platform.risc.mbx_lock);
1829 DibFreeLock(&state->platform.risc.mem_lock);
1830 DibFreeLock(&state->platform.risc.mem_mbx_lock);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001831 DibFreeLock(&state->demod_lock);
Olivier Greniedd316c62011-01-04 04:28:59 -03001832 dibx000_exit_i2c_master(&st->i2c_master);
1833
1834 i2c_del_adapter(&st->tuner_adap);
1835 i2c_del_adapter(&st->component_bus);
1836 kfree(st->fe[0]);
1837 kfree(st);
1838}
1839
1840static int dib9000_wakeup(struct dvb_frontend *fe)
1841{
1842 return 0;
1843}
1844
1845static int dib9000_sleep(struct dvb_frontend *fe)
1846{
1847 struct dib9000_state *state = fe->demodulator_priv;
1848 u8 index_frontend;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001849 int ret = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03001850
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001851 DibAcquireLock(&state->demod_lock);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001852 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001853 ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]);
1854 if (ret < 0)
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001855 goto error;
Olivier Greniedd316c62011-01-04 04:28:59 -03001856 }
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001857 ret = dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0);
1858
1859error:
1860 DibReleaseLock(&state->demod_lock);
1861 return ret;
Olivier Greniedd316c62011-01-04 04:28:59 -03001862}
1863
1864static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
1865{
1866 tune->min_delay_ms = 1000;
1867 return 0;
1868}
1869
Mauro Carvalho Chehab9e9c5bf2011-12-22 20:12:18 -03001870static int dib9000_get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *c)
Olivier Greniedd316c62011-01-04 04:28:59 -03001871{
1872 struct dib9000_state *state = fe->demodulator_priv;
1873 u8 index_frontend, sub_index_frontend;
1874 fe_status_t stat;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001875 int ret = 0;
1876
1877 if (state->get_frontend_internal == 0)
1878 DibAcquireLock(&state->demod_lock);
Olivier Greniedd316c62011-01-04 04:28:59 -03001879
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001880 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001881 state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
1882 if (stat & FE_HAS_SYNC) {
1883 dprintk("TPS lock on the slave%i", index_frontend);
1884
1885 /* synchronize the cache with the other frontends */
Mauro Carvalho Chehab9e9c5bf2011-12-22 20:12:18 -03001886 state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], c);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001887 for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL);
1888 sub_index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001889 if (sub_index_frontend != index_frontend) {
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001890 state->fe[sub_index_frontend]->dtv_property_cache.modulation =
1891 state->fe[index_frontend]->dtv_property_cache.modulation;
1892 state->fe[sub_index_frontend]->dtv_property_cache.inversion =
1893 state->fe[index_frontend]->dtv_property_cache.inversion;
1894 state->fe[sub_index_frontend]->dtv_property_cache.transmission_mode =
1895 state->fe[index_frontend]->dtv_property_cache.transmission_mode;
1896 state->fe[sub_index_frontend]->dtv_property_cache.guard_interval =
1897 state->fe[index_frontend]->dtv_property_cache.guard_interval;
1898 state->fe[sub_index_frontend]->dtv_property_cache.hierarchy =
1899 state->fe[index_frontend]->dtv_property_cache.hierarchy;
1900 state->fe[sub_index_frontend]->dtv_property_cache.code_rate_HP =
1901 state->fe[index_frontend]->dtv_property_cache.code_rate_HP;
1902 state->fe[sub_index_frontend]->dtv_property_cache.code_rate_LP =
1903 state->fe[index_frontend]->dtv_property_cache.code_rate_LP;
1904 state->fe[sub_index_frontend]->dtv_property_cache.rolloff =
1905 state->fe[index_frontend]->dtv_property_cache.rolloff;
Olivier Greniedd316c62011-01-04 04:28:59 -03001906 }
1907 }
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001908 ret = 0;
1909 goto return_value;
Olivier Greniedd316c62011-01-04 04:28:59 -03001910 }
1911 }
1912
1913 /* get the channel from master chip */
Mauro Carvalho Chehab759e2362011-12-22 19:54:08 -03001914 ret = dib9000_fw_get_channel(fe);
Olivier Greniedd316c62011-01-04 04:28:59 -03001915 if (ret != 0)
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001916 goto return_value;
Olivier Greniedd316c62011-01-04 04:28:59 -03001917
1918 /* synchronize the cache with the other frontends */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001919 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001920 state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion;
1921 state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode;
1922 state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval;
1923 state->fe[index_frontend]->dtv_property_cache.modulation = fe->dtv_property_cache.modulation;
1924 state->fe[index_frontend]->dtv_property_cache.hierarchy = fe->dtv_property_cache.hierarchy;
1925 state->fe[index_frontend]->dtv_property_cache.code_rate_HP = fe->dtv_property_cache.code_rate_HP;
1926 state->fe[index_frontend]->dtv_property_cache.code_rate_LP = fe->dtv_property_cache.code_rate_LP;
1927 state->fe[index_frontend]->dtv_property_cache.rolloff = fe->dtv_property_cache.rolloff;
1928 }
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001929 ret = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03001930
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001931return_value:
1932 if (state->get_frontend_internal == 0)
1933 DibReleaseLock(&state->demod_lock);
1934 return ret;
Olivier Greniedd316c62011-01-04 04:28:59 -03001935}
1936
1937static int dib9000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
1938{
1939 struct dib9000_state *state = fe->demodulator_priv;
1940 state->tune_state = tune_state;
1941 if (tune_state == CT_DEMOD_START)
1942 state->status = FE_STATUS_TUNE_PENDING;
1943
1944 return 0;
1945}
1946
1947static u32 dib9000_get_status(struct dvb_frontend *fe)
1948{
1949 struct dib9000_state *state = fe->demodulator_priv;
1950 return state->status;
1951}
1952
1953static int dib9000_set_channel_status(struct dvb_frontend *fe, struct dvb_frontend_parametersContext *channel_status)
1954{
1955 struct dib9000_state *state = fe->demodulator_priv;
1956
1957 memcpy(&state->channel_status, channel_status, sizeof(struct dvb_frontend_parametersContext));
1958 return 0;
1959}
1960
Mauro Carvalho Chehab9e9c5bf2011-12-22 20:12:18 -03001961static int dib9000_set_frontend(struct dvb_frontend *fe)
Olivier Greniedd316c62011-01-04 04:28:59 -03001962{
1963 struct dib9000_state *state = fe->demodulator_priv;
1964 int sleep_time, sleep_time_slave;
1965 u32 frontend_status;
1966 u8 nbr_pending, exit_condition, index_frontend, index_frontend_success;
1967 struct dvb_frontend_parametersContext channel_status;
1968
1969 /* check that the correct parameters are set */
1970 if (state->fe[0]->dtv_property_cache.frequency == 0) {
1971 dprintk("dib9000: must specify frequency ");
1972 return 0;
1973 }
1974
1975 if (state->fe[0]->dtv_property_cache.bandwidth_hz == 0) {
1976 dprintk("dib9000: must specify bandwidth ");
1977 return 0;
1978 }
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001979
1980 state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */
1981 DibAcquireLock(&state->demod_lock);
1982
Olivier Greniedd316c62011-01-04 04:28:59 -03001983 fe->dtv_property_cache.delivery_system = SYS_DVBT;
1984
1985 /* set the master status */
Mauro Carvalho Chehab9e9c5bf2011-12-22 20:12:18 -03001986 if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO ||
1987 state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO ||
1988 state->fe[0]->dtv_property_cache.modulation == QAM_AUTO ||
1989 state->fe[0]->dtv_property_cache.code_rate_HP == FEC_AUTO) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001990 /* no channel specified, autosearch the channel */
1991 state->channel_status.status = CHANNEL_STATUS_PARAMETERS_UNKNOWN;
1992 } else
1993 state->channel_status.status = CHANNEL_STATUS_PARAMETERS_SET;
1994
1995 /* set mode and status for the different frontends */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001996 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001997 dib9000_fw_set_diversity_in(state->fe[index_frontend], 1);
1998
1999 /* synchronization of the cache */
2000 memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties));
2001
2002 state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_DVBT;
2003 dib9000_fw_set_output_mode(state->fe[index_frontend], OUTMODE_HIGH_Z);
2004
2005 dib9000_set_channel_status(state->fe[index_frontend], &state->channel_status);
2006 dib9000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
2007 }
2008
2009 /* actual tune */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002010 exit_condition = 0; /* 0: tune pending; 1: tune failed; 2:tune success */
Olivier Greniedd316c62011-01-04 04:28:59 -03002011 index_frontend_success = 0;
2012 do {
Mauro Carvalho Chehabf20b12e2011-12-22 20:42:12 -03002013 sleep_time = dib9000_fw_tune(state->fe[0]);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002014 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Mauro Carvalho Chehabf20b12e2011-12-22 20:42:12 -03002015 sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend]);
Olivier Greniedd316c62011-01-04 04:28:59 -03002016 if (sleep_time == FE_CALLBACK_TIME_NEVER)
2017 sleep_time = sleep_time_slave;
2018 else if ((sleep_time_slave != FE_CALLBACK_TIME_NEVER) && (sleep_time_slave > sleep_time))
2019 sleep_time = sleep_time_slave;
2020 }
2021 if (sleep_time != FE_CALLBACK_TIME_NEVER)
2022 msleep(sleep_time / 10);
2023 else
2024 break;
2025
2026 nbr_pending = 0;
2027 exit_condition = 0;
2028 index_frontend_success = 0;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002029 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03002030 frontend_status = -dib9000_get_status(state->fe[index_frontend]);
2031 if (frontend_status > -FE_STATUS_TUNE_PENDING) {
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002032 exit_condition = 2; /* tune success */
Olivier Greniedd316c62011-01-04 04:28:59 -03002033 index_frontend_success = index_frontend;
2034 break;
2035 }
2036 if (frontend_status == -FE_STATUS_TUNE_PENDING)
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002037 nbr_pending++; /* some frontends are still tuning */
Olivier Greniedd316c62011-01-04 04:28:59 -03002038 }
2039 if ((exit_condition != 2) && (nbr_pending == 0))
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002040 exit_condition = 1; /* if all tune are done and no success, exit: tune failed */
Olivier Greniedd316c62011-01-04 04:28:59 -03002041
2042 } while (exit_condition == 0);
2043
2044 /* check the tune result */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002045 if (exit_condition == 1) { /* tune failed */
Olivier Greniedd316c62011-01-04 04:28:59 -03002046 dprintk("tune failed");
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002047 DibReleaseLock(&state->demod_lock);
2048 /* tune failed; put all the pid filtering cmd to junk */
2049 state->pid_ctrl_index = -1;
Olivier Greniedd316c62011-01-04 04:28:59 -03002050 return 0;
2051 }
2052
2053 dprintk("tune success on frontend%i", index_frontend_success);
2054
2055 /* synchronize all the channel cache */
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002056 state->get_frontend_internal = 1;
Mauro Carvalho Chehab9e9c5bf2011-12-22 20:12:18 -03002057 dib9000_get_frontend(state->fe[0], &state->fe[0]->dtv_property_cache);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002058 state->get_frontend_internal = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03002059
2060 /* retune the other frontends with the found channel */
2061 channel_status.status = CHANNEL_STATUS_PARAMETERS_SET;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002062 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03002063 /* only retune the frontends which was not tuned success */
2064 if (index_frontend != index_frontend_success) {
2065 dib9000_set_channel_status(state->fe[index_frontend], &channel_status);
2066 dib9000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
2067 }
2068 }
2069 do {
2070 sleep_time = FE_CALLBACK_TIME_NEVER;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002071 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03002072 if (index_frontend != index_frontend_success) {
Mauro Carvalho Chehabf20b12e2011-12-22 20:42:12 -03002073 sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend]);
Olivier Greniedd316c62011-01-04 04:28:59 -03002074 if (sleep_time == FE_CALLBACK_TIME_NEVER)
2075 sleep_time = sleep_time_slave;
2076 else if ((sleep_time_slave != FE_CALLBACK_TIME_NEVER) && (sleep_time_slave > sleep_time))
2077 sleep_time = sleep_time_slave;
2078 }
2079 }
2080 if (sleep_time != FE_CALLBACK_TIME_NEVER)
2081 msleep(sleep_time / 10);
2082 else
2083 break;
2084
2085 nbr_pending = 0;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002086 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03002087 if (index_frontend != index_frontend_success) {
2088 frontend_status = -dib9000_get_status(state->fe[index_frontend]);
2089 if ((index_frontend != index_frontend_success) && (frontend_status == -FE_STATUS_TUNE_PENDING))
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002090 nbr_pending++; /* some frontends are still tuning */
Olivier Greniedd316c62011-01-04 04:28:59 -03002091 }
2092 }
2093 } while (nbr_pending != 0);
2094
2095 /* set the output mode */
2096 dib9000_fw_set_output_mode(state->fe[0], state->chip.d9.cfg.output_mode);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002097 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
Olivier Greniedd316c62011-01-04 04:28:59 -03002098 dib9000_fw_set_output_mode(state->fe[index_frontend], OUTMODE_DIVERSITY);
2099
2100 /* turn off the diversity for the last frontend */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002101 dib9000_fw_set_diversity_in(state->fe[index_frontend - 1], 0);
Olivier Greniedd316c62011-01-04 04:28:59 -03002102
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002103 DibReleaseLock(&state->demod_lock);
2104 if (state->pid_ctrl_index >= 0) {
2105 u8 index_pid_filter_cmd;
2106 u8 pid_ctrl_index = state->pid_ctrl_index;
2107
2108 state->pid_ctrl_index = -2;
2109 for (index_pid_filter_cmd = 0;
2110 index_pid_filter_cmd <= pid_ctrl_index;
2111 index_pid_filter_cmd++) {
2112 if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER_CTRL)
2113 dib9000_fw_pid_filter_ctrl(state->fe[0],
2114 state->pid_ctrl[index_pid_filter_cmd].onoff);
2115 else if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER)
2116 dib9000_fw_pid_filter(state->fe[0],
2117 state->pid_ctrl[index_pid_filter_cmd].id,
2118 state->pid_ctrl[index_pid_filter_cmd].pid,
2119 state->pid_ctrl[index_pid_filter_cmd].onoff);
2120 }
2121 }
2122 /* do not postpone any more the pid filtering */
2123 state->pid_ctrl_index = -2;
2124
Olivier Greniedd316c62011-01-04 04:28:59 -03002125 return 0;
2126}
2127
2128static u16 dib9000_read_lock(struct dvb_frontend *fe)
2129{
2130 struct dib9000_state *state = fe->demodulator_priv;
2131
2132 return dib9000_read_word(state, 535);
2133}
2134
2135static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
2136{
2137 struct dib9000_state *state = fe->demodulator_priv;
2138 u8 index_frontend;
2139 u16 lock = 0, lock_slave = 0;
2140
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002141 DibAcquireLock(&state->demod_lock);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002142 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
Olivier Greniedd316c62011-01-04 04:28:59 -03002143 lock_slave |= dib9000_read_lock(state->fe[index_frontend]);
2144
2145 lock = dib9000_read_word(state, 535);
2146
2147 *stat = 0;
2148
2149 if ((lock & 0x8000) || (lock_slave & 0x8000))
2150 *stat |= FE_HAS_SIGNAL;
2151 if ((lock & 0x3000) || (lock_slave & 0x3000))
2152 *stat |= FE_HAS_CARRIER;
2153 if ((lock & 0x0100) || (lock_slave & 0x0100))
2154 *stat |= FE_HAS_VITERBI;
2155 if (((lock & 0x0038) == 0x38) || ((lock_slave & 0x0038) == 0x38))
2156 *stat |= FE_HAS_SYNC;
2157 if ((lock & 0x0008) || (lock_slave & 0x0008))
2158 *stat |= FE_HAS_LOCK;
2159
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002160 DibReleaseLock(&state->demod_lock);
2161
Olivier Greniedd316c62011-01-04 04:28:59 -03002162 return 0;
2163}
2164
2165static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
2166{
2167 struct dib9000_state *state = fe->demodulator_priv;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002168 u16 *c;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002169 int ret = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03002170
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002171 DibAcquireLock(&state->demod_lock);
Olivier Greniedd316c62011-01-04 04:28:59 -03002172 DibAcquireLock(&state->platform.risc.mem_mbx_lock);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002173 if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
Dan Carpenter2f4cf2c2011-09-29 02:10:06 -03002174 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002175 ret = -EIO;
2176 goto error;
2177 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002178 dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR,
2179 state->i2c_read_buffer, 16 * 2);
Olivier Greniedd316c62011-01-04 04:28:59 -03002180 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
2181
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002182 c = (u16 *)state->i2c_read_buffer;
2183
Olivier Greniedd316c62011-01-04 04:28:59 -03002184 *ber = c[10] << 16 | c[11];
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002185
2186error:
2187 DibReleaseLock(&state->demod_lock);
2188 return ret;
Olivier Greniedd316c62011-01-04 04:28:59 -03002189}
2190
2191static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
2192{
2193 struct dib9000_state *state = fe->demodulator_priv;
2194 u8 index_frontend;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002195 u16 *c = (u16 *)state->i2c_read_buffer;
Olivier Greniedd316c62011-01-04 04:28:59 -03002196 u16 val;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002197 int ret = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03002198
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002199 DibAcquireLock(&state->demod_lock);
Olivier Greniedd316c62011-01-04 04:28:59 -03002200 *strength = 0;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002201 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03002202 state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val);
2203 if (val > 65535 - *strength)
2204 *strength = 65535;
2205 else
2206 *strength += val;
2207 }
2208
2209 DibAcquireLock(&state->platform.risc.mem_mbx_lock);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002210 if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
2211 ret = -EIO;
2212 goto error;
2213 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002214 dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
Olivier Greniedd316c62011-01-04 04:28:59 -03002215 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
2216
2217 val = 65535 - c[4];
2218 if (val > 65535 - *strength)
2219 *strength = 65535;
2220 else
2221 *strength += val;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002222
2223error:
2224 DibReleaseLock(&state->demod_lock);
2225 return ret;
Olivier Greniedd316c62011-01-04 04:28:59 -03002226}
2227
2228static u32 dib9000_get_snr(struct dvb_frontend *fe)
2229{
2230 struct dib9000_state *state = fe->demodulator_priv;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002231 u16 *c = (u16 *)state->i2c_read_buffer;
Olivier Greniedd316c62011-01-04 04:28:59 -03002232 u32 n, s, exp;
2233 u16 val;
2234
2235 DibAcquireLock(&state->platform.risc.mem_mbx_lock);
2236 if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
2237 return -EIO;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002238 dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
Olivier Greniedd316c62011-01-04 04:28:59 -03002239 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
2240
2241 val = c[7];
2242 n = (val >> 4) & 0xff;
2243 exp = ((val & 0xf) << 2);
2244 val = c[8];
2245 exp += ((val >> 14) & 0x3);
2246 if ((exp & 0x20) != 0)
2247 exp -= 0x40;
2248 n <<= exp + 16;
2249
2250 s = (val >> 6) & 0xFF;
2251 exp = (val & 0x3F);
2252 if ((exp & 0x20) != 0)
2253 exp -= 0x40;
2254 s <<= exp + 16;
2255
2256 if (n > 0) {
2257 u32 t = (s / n) << 16;
2258 return t + ((s << 16) - n * t) / n;
2259 }
2260 return 0xffffffff;
2261}
2262
2263static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr)
2264{
2265 struct dib9000_state *state = fe->demodulator_priv;
2266 u8 index_frontend;
2267 u32 snr_master;
2268
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002269 DibAcquireLock(&state->demod_lock);
Olivier Greniedd316c62011-01-04 04:28:59 -03002270 snr_master = dib9000_get_snr(fe);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002271 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
Olivier Greniedd316c62011-01-04 04:28:59 -03002272 snr_master += dib9000_get_snr(state->fe[index_frontend]);
2273
2274 if ((snr_master >> 16) != 0) {
2275 snr_master = 10 * intlog10(snr_master >> 16);
2276 *snr = snr_master / ((1 << 24) / 10);
2277 } else
2278 *snr = 0;
2279
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002280 DibReleaseLock(&state->demod_lock);
2281
Olivier Greniedd316c62011-01-04 04:28:59 -03002282 return 0;
2283}
2284
2285static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
2286{
2287 struct dib9000_state *state = fe->demodulator_priv;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002288 u16 *c = (u16 *)state->i2c_read_buffer;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002289 int ret = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03002290
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002291 DibAcquireLock(&state->demod_lock);
Olivier Greniedd316c62011-01-04 04:28:59 -03002292 DibAcquireLock(&state->platform.risc.mem_mbx_lock);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002293 if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
2294 ret = -EIO;
2295 goto error;
2296 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002297 dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
Olivier Greniedd316c62011-01-04 04:28:59 -03002298 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
2299
2300 *unc = c[12];
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002301
2302error:
2303 DibReleaseLock(&state->demod_lock);
2304 return ret;
Olivier Greniedd316c62011-01-04 04:28:59 -03002305}
2306
2307int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr)
2308{
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002309 int k = 0, ret = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03002310 u8 new_addr = 0;
2311 struct i2c_device client = {.i2c_adap = i2c };
2312
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002313 client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
2314 if (!client.i2c_write_buffer) {
2315 dprintk("%s: not enough memory", __func__);
2316 return -ENOMEM;
2317 }
2318 client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
2319 if (!client.i2c_read_buffer) {
2320 dprintk("%s: not enough memory", __func__);
2321 ret = -ENOMEM;
2322 goto error_memory;
2323 }
2324
Olivier Greniedd316c62011-01-04 04:28:59 -03002325 client.i2c_addr = default_addr + 16;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002326 dib9000_i2c_write16(&client, 1796, 0x0);
Olivier Greniedd316c62011-01-04 04:28:59 -03002327
2328 for (k = no_of_demods - 1; k >= 0; k--) {
2329 /* designated i2c address */
2330 new_addr = first_addr + (k << 1);
2331 client.i2c_addr = default_addr;
2332
2333 dib9000_i2c_write16(&client, 1817, 3);
2334 dib9000_i2c_write16(&client, 1796, 0);
2335 dib9000_i2c_write16(&client, 1227, 1);
2336 dib9000_i2c_write16(&client, 1227, 0);
2337
2338 client.i2c_addr = new_addr;
2339 dib9000_i2c_write16(&client, 1817, 3);
2340 dib9000_i2c_write16(&client, 1796, 0);
2341 dib9000_i2c_write16(&client, 1227, 1);
2342 dib9000_i2c_write16(&client, 1227, 0);
2343
2344 if (dib9000_identify(&client) == 0) {
2345 client.i2c_addr = default_addr;
2346 if (dib9000_identify(&client) == 0) {
2347 dprintk("DiB9000 #%d: not identified", k);
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002348 ret = -EIO;
2349 goto error;
Olivier Greniedd316c62011-01-04 04:28:59 -03002350 }
2351 }
2352
2353 dib9000_i2c_write16(&client, 1795, (1 << 10) | (4 << 6));
2354 dib9000_i2c_write16(&client, 1794, (new_addr << 2) | 2);
2355
2356 dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
2357 }
2358
2359 for (k = 0; k < no_of_demods; k++) {
2360 new_addr = first_addr | (k << 1);
2361 client.i2c_addr = new_addr;
2362
2363 dib9000_i2c_write16(&client, 1794, (new_addr << 2));
2364 dib9000_i2c_write16(&client, 1795, 0);
2365 }
2366
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002367error:
2368 kfree(client.i2c_read_buffer);
2369error_memory:
2370 kfree(client.i2c_write_buffer);
2371
2372 return ret;
Olivier Greniedd316c62011-01-04 04:28:59 -03002373}
Olivier Greniedd316c62011-01-04 04:28:59 -03002374EXPORT_SYMBOL(dib9000_i2c_enumeration);
2375
2376int dib9000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
2377{
2378 struct dib9000_state *state = fe->demodulator_priv;
2379 u8 index_frontend = 1;
2380
2381 while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
2382 index_frontend++;
2383 if (index_frontend < MAX_NUMBER_OF_FRONTENDS) {
2384 dprintk("set slave fe %p to index %i", fe_slave, index_frontend);
2385 state->fe[index_frontend] = fe_slave;
2386 return 0;
2387 }
2388
2389 dprintk("too many slave frontend");
2390 return -ENOMEM;
2391}
2392EXPORT_SYMBOL(dib9000_set_slave_frontend);
2393
2394int dib9000_remove_slave_frontend(struct dvb_frontend *fe)
2395{
2396 struct dib9000_state *state = fe->demodulator_priv;
2397 u8 index_frontend = 1;
2398
2399 while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
2400 index_frontend++;
2401 if (index_frontend != 1) {
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002402 dprintk("remove slave fe %p (index %i)", state->fe[index_frontend - 1], index_frontend - 1);
Olivier Greniedd316c62011-01-04 04:28:59 -03002403 state->fe[index_frontend] = NULL;
2404 return 0;
2405 }
2406
2407 dprintk("no frontend to be removed");
2408 return -ENODEV;
2409}
2410EXPORT_SYMBOL(dib9000_remove_slave_frontend);
2411
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002412struct dvb_frontend *dib9000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
Olivier Greniedd316c62011-01-04 04:28:59 -03002413{
2414 struct dib9000_state *state = fe->demodulator_priv;
2415
2416 if (slave_index >= MAX_NUMBER_OF_FRONTENDS)
2417 return NULL;
2418 return state->fe[slave_index];
2419}
2420EXPORT_SYMBOL(dib9000_get_slave_frontend);
2421
2422static struct dvb_frontend_ops dib9000_ops;
2423struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, const struct dib9000_config *cfg)
2424{
2425 struct dvb_frontend *fe;
2426 struct dib9000_state *st;
2427 st = kzalloc(sizeof(struct dib9000_state), GFP_KERNEL);
2428 if (st == NULL)
2429 return NULL;
2430 fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL);
Jesper Juhl451a51b2011-04-07 16:34:30 -03002431 if (fe == NULL) {
2432 kfree(st);
Olivier Greniedd316c62011-01-04 04:28:59 -03002433 return NULL;
Jesper Juhl451a51b2011-04-07 16:34:30 -03002434 }
Olivier Greniedd316c62011-01-04 04:28:59 -03002435
2436 memcpy(&st->chip.d9.cfg, cfg, sizeof(struct dib9000_config));
2437 st->i2c.i2c_adap = i2c_adap;
2438 st->i2c.i2c_addr = i2c_addr;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002439 st->i2c.i2c_write_buffer = st->i2c_write_buffer;
2440 st->i2c.i2c_read_buffer = st->i2c_read_buffer;
Olivier Greniedd316c62011-01-04 04:28:59 -03002441
2442 st->gpio_dir = DIB9000_GPIO_DEFAULT_DIRECTIONS;
2443 st->gpio_val = DIB9000_GPIO_DEFAULT_VALUES;
2444 st->gpio_pwm_pos = DIB9000_GPIO_DEFAULT_PWM_POS;
2445
2446 DibInitLock(&st->platform.risc.mbx_if_lock);
2447 DibInitLock(&st->platform.risc.mbx_lock);
2448 DibInitLock(&st->platform.risc.mem_lock);
2449 DibInitLock(&st->platform.risc.mem_mbx_lock);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002450 DibInitLock(&st->demod_lock);
2451 st->get_frontend_internal = 0;
2452
2453 st->pid_ctrl_index = -2;
Olivier Greniedd316c62011-01-04 04:28:59 -03002454
2455 st->fe[0] = fe;
2456 fe->demodulator_priv = st;
2457 memcpy(&st->fe[0]->ops, &dib9000_ops, sizeof(struct dvb_frontend_ops));
2458
2459 /* Ensure the output mode remains at the previous default if it's
2460 * not specifically set by the caller.
2461 */
2462 if ((st->chip.d9.cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (st->chip.d9.cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
2463 st->chip.d9.cfg.output_mode = OUTMODE_MPEG2_FIFO;
2464
2465 if (dib9000_identify(&st->i2c) == 0)
2466 goto error;
2467
2468 dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c.i2c_adap, st->i2c.i2c_addr);
2469
2470 st->tuner_adap.dev.parent = i2c_adap->dev.parent;
2471 strncpy(st->tuner_adap.name, "DIB9000_FW TUNER ACCESS", sizeof(st->tuner_adap.name));
2472 st->tuner_adap.algo = &dib9000_tuner_algo;
2473 st->tuner_adap.algo_data = NULL;
2474 i2c_set_adapdata(&st->tuner_adap, st);
2475 if (i2c_add_adapter(&st->tuner_adap) < 0)
2476 goto error;
2477
2478 st->component_bus.dev.parent = i2c_adap->dev.parent;
2479 strncpy(st->component_bus.name, "DIB9000_FW COMPONENT BUS ACCESS", sizeof(st->component_bus.name));
2480 st->component_bus.algo = &dib9000_component_bus_algo;
2481 st->component_bus.algo_data = NULL;
2482 st->component_bus_speed = 340;
2483 i2c_set_adapdata(&st->component_bus, st);
2484 if (i2c_add_adapter(&st->component_bus) < 0)
2485 goto component_bus_add_error;
2486
2487 dib9000_fw_reset(fe);
2488
2489 return fe;
2490
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002491component_bus_add_error:
Olivier Greniedd316c62011-01-04 04:28:59 -03002492 i2c_del_adapter(&st->tuner_adap);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002493error:
Olivier Greniedd316c62011-01-04 04:28:59 -03002494 kfree(st);
2495 return NULL;
2496}
Olivier Greniedd316c62011-01-04 04:28:59 -03002497EXPORT_SYMBOL(dib9000_attach);
2498
2499static struct dvb_frontend_ops dib9000_ops = {
Mauro Carvalho Chehab9e9c5bf2011-12-22 20:12:18 -03002500 .delsys = { SYS_DVBT },
Olivier Greniedd316c62011-01-04 04:28:59 -03002501 .info = {
2502 .name = "DiBcom 9000",
2503 .type = FE_OFDM,
2504 .frequency_min = 44250000,
2505 .frequency_max = 867250000,
2506 .frequency_stepsize = 62500,
2507 .caps = FE_CAN_INVERSION_AUTO |
2508 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
2509 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
2510 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
2511 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
2512 },
2513
2514 .release = dib9000_release,
2515
2516 .init = dib9000_wakeup,
2517 .sleep = dib9000_sleep,
2518
Mauro Carvalho Chehab9e9c5bf2011-12-22 20:12:18 -03002519 .set_frontend = dib9000_set_frontend,
Olivier Greniedd316c62011-01-04 04:28:59 -03002520 .get_tune_settings = dib9000_fe_get_tune_settings,
Mauro Carvalho Chehab9e9c5bf2011-12-22 20:12:18 -03002521 .get_frontend = dib9000_get_frontend,
Olivier Greniedd316c62011-01-04 04:28:59 -03002522
2523 .read_status = dib9000_read_status,
2524 .read_ber = dib9000_read_ber,
2525 .read_signal_strength = dib9000_read_signal_strength,
2526 .read_snr = dib9000_read_snr,
2527 .read_ucblocks = dib9000_read_unc_blocks,
2528};
2529
2530MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
2531MODULE_AUTHOR("Olivier Grenie <ogrenie@dibcom.fr>");
2532MODULE_DESCRIPTION("Driver for the DiBcom 9000 COFDM demodulator");
2533MODULE_LICENSE("GPL");