blob: b931074a952172a0718aada770eb195aaf0d083b [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
1139static void dib9000_fw_set_channel_head(struct dib9000_state *state, struct dvb_frontend_parameters *ch)
1140{
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
1160static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_parameters *channel)
1161{
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) {
1183 goto error;
1184 ret = -EIO;
1185 }
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
1312static int dib9000_fw_set_channel_union(struct dvb_frontend *fe, struct dvb_frontend_parameters *channel)
1313{
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
1457static int dib9000_fw_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
1458{
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:
1465 dib9000_fw_set_channel_head(state, ch);
1466
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 {
1474 dib9000_fw_set_channel_union(fe, ch);
1475 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
1870static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
1871{
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 */
1886 state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], fep);
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 */
1914 ret = dib9000_fw_get_channel(fe, fep);
1915 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
1961static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
1962{
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 */
1986 if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001987 fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || fep->u.ofdm.constellation == QAM_AUTO || fep->u.ofdm.code_rate_HP == FEC_AUTO) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001988 /* no channel specified, autosearch the channel */
1989 state->channel_status.status = CHANNEL_STATUS_PARAMETERS_UNKNOWN;
1990 } else
1991 state->channel_status.status = CHANNEL_STATUS_PARAMETERS_SET;
1992
1993 /* set mode and status for the different frontends */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001994 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001995 dib9000_fw_set_diversity_in(state->fe[index_frontend], 1);
1996
1997 /* synchronization of the cache */
1998 memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties));
1999
2000 state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_DVBT;
2001 dib9000_fw_set_output_mode(state->fe[index_frontend], OUTMODE_HIGH_Z);
2002
2003 dib9000_set_channel_status(state->fe[index_frontend], &state->channel_status);
2004 dib9000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
2005 }
2006
2007 /* actual tune */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002008 exit_condition = 0; /* 0: tune pending; 1: tune failed; 2:tune success */
Olivier Greniedd316c62011-01-04 04:28:59 -03002009 index_frontend_success = 0;
2010 do {
2011 sleep_time = dib9000_fw_tune(state->fe[0], NULL);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002012 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03002013 sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend], NULL);
2014 if (sleep_time == FE_CALLBACK_TIME_NEVER)
2015 sleep_time = sleep_time_slave;
2016 else if ((sleep_time_slave != FE_CALLBACK_TIME_NEVER) && (sleep_time_slave > sleep_time))
2017 sleep_time = sleep_time_slave;
2018 }
2019 if (sleep_time != FE_CALLBACK_TIME_NEVER)
2020 msleep(sleep_time / 10);
2021 else
2022 break;
2023
2024 nbr_pending = 0;
2025 exit_condition = 0;
2026 index_frontend_success = 0;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002027 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03002028 frontend_status = -dib9000_get_status(state->fe[index_frontend]);
2029 if (frontend_status > -FE_STATUS_TUNE_PENDING) {
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002030 exit_condition = 2; /* tune success */
Olivier Greniedd316c62011-01-04 04:28:59 -03002031 index_frontend_success = index_frontend;
2032 break;
2033 }
2034 if (frontend_status == -FE_STATUS_TUNE_PENDING)
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002035 nbr_pending++; /* some frontends are still tuning */
Olivier Greniedd316c62011-01-04 04:28:59 -03002036 }
2037 if ((exit_condition != 2) && (nbr_pending == 0))
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002038 exit_condition = 1; /* if all tune are done and no success, exit: tune failed */
Olivier Greniedd316c62011-01-04 04:28:59 -03002039
2040 } while (exit_condition == 0);
2041
2042 /* check the tune result */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002043 if (exit_condition == 1) { /* tune failed */
Olivier Greniedd316c62011-01-04 04:28:59 -03002044 dprintk("tune failed");
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002045 DibReleaseLock(&state->demod_lock);
2046 /* tune failed; put all the pid filtering cmd to junk */
2047 state->pid_ctrl_index = -1;
Olivier Greniedd316c62011-01-04 04:28:59 -03002048 return 0;
2049 }
2050
2051 dprintk("tune success on frontend%i", index_frontend_success);
2052
2053 /* synchronize all the channel cache */
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002054 state->get_frontend_internal = 1;
Olivier Greniedd316c62011-01-04 04:28:59 -03002055 dib9000_get_frontend(state->fe[0], fep);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002056 state->get_frontend_internal = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03002057
2058 /* retune the other frontends with the found channel */
2059 channel_status.status = CHANNEL_STATUS_PARAMETERS_SET;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002060 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03002061 /* only retune the frontends which was not tuned success */
2062 if (index_frontend != index_frontend_success) {
2063 dib9000_set_channel_status(state->fe[index_frontend], &channel_status);
2064 dib9000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
2065 }
2066 }
2067 do {
2068 sleep_time = FE_CALLBACK_TIME_NEVER;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002069 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03002070 if (index_frontend != index_frontend_success) {
2071 sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend], NULL);
2072 if (sleep_time == FE_CALLBACK_TIME_NEVER)
2073 sleep_time = sleep_time_slave;
2074 else if ((sleep_time_slave != FE_CALLBACK_TIME_NEVER) && (sleep_time_slave > sleep_time))
2075 sleep_time = sleep_time_slave;
2076 }
2077 }
2078 if (sleep_time != FE_CALLBACK_TIME_NEVER)
2079 msleep(sleep_time / 10);
2080 else
2081 break;
2082
2083 nbr_pending = 0;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002084 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03002085 if (index_frontend != index_frontend_success) {
2086 frontend_status = -dib9000_get_status(state->fe[index_frontend]);
2087 if ((index_frontend != index_frontend_success) && (frontend_status == -FE_STATUS_TUNE_PENDING))
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002088 nbr_pending++; /* some frontends are still tuning */
Olivier Greniedd316c62011-01-04 04:28:59 -03002089 }
2090 }
2091 } while (nbr_pending != 0);
2092
2093 /* set the output mode */
2094 dib9000_fw_set_output_mode(state->fe[0], state->chip.d9.cfg.output_mode);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002095 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
Olivier Greniedd316c62011-01-04 04:28:59 -03002096 dib9000_fw_set_output_mode(state->fe[index_frontend], OUTMODE_DIVERSITY);
2097
2098 /* turn off the diversity for the last frontend */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002099 dib9000_fw_set_diversity_in(state->fe[index_frontend - 1], 0);
Olivier Greniedd316c62011-01-04 04:28:59 -03002100
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002101 DibReleaseLock(&state->demod_lock);
2102 if (state->pid_ctrl_index >= 0) {
2103 u8 index_pid_filter_cmd;
2104 u8 pid_ctrl_index = state->pid_ctrl_index;
2105
2106 state->pid_ctrl_index = -2;
2107 for (index_pid_filter_cmd = 0;
2108 index_pid_filter_cmd <= pid_ctrl_index;
2109 index_pid_filter_cmd++) {
2110 if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER_CTRL)
2111 dib9000_fw_pid_filter_ctrl(state->fe[0],
2112 state->pid_ctrl[index_pid_filter_cmd].onoff);
2113 else if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER)
2114 dib9000_fw_pid_filter(state->fe[0],
2115 state->pid_ctrl[index_pid_filter_cmd].id,
2116 state->pid_ctrl[index_pid_filter_cmd].pid,
2117 state->pid_ctrl[index_pid_filter_cmd].onoff);
2118 }
2119 }
2120 /* do not postpone any more the pid filtering */
2121 state->pid_ctrl_index = -2;
2122
Olivier Greniedd316c62011-01-04 04:28:59 -03002123 return 0;
2124}
2125
2126static u16 dib9000_read_lock(struct dvb_frontend *fe)
2127{
2128 struct dib9000_state *state = fe->demodulator_priv;
2129
2130 return dib9000_read_word(state, 535);
2131}
2132
2133static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
2134{
2135 struct dib9000_state *state = fe->demodulator_priv;
2136 u8 index_frontend;
2137 u16 lock = 0, lock_slave = 0;
2138
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002139 DibAcquireLock(&state->demod_lock);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002140 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
Olivier Greniedd316c62011-01-04 04:28:59 -03002141 lock_slave |= dib9000_read_lock(state->fe[index_frontend]);
2142
2143 lock = dib9000_read_word(state, 535);
2144
2145 *stat = 0;
2146
2147 if ((lock & 0x8000) || (lock_slave & 0x8000))
2148 *stat |= FE_HAS_SIGNAL;
2149 if ((lock & 0x3000) || (lock_slave & 0x3000))
2150 *stat |= FE_HAS_CARRIER;
2151 if ((lock & 0x0100) || (lock_slave & 0x0100))
2152 *stat |= FE_HAS_VITERBI;
2153 if (((lock & 0x0038) == 0x38) || ((lock_slave & 0x0038) == 0x38))
2154 *stat |= FE_HAS_SYNC;
2155 if ((lock & 0x0008) || (lock_slave & 0x0008))
2156 *stat |= FE_HAS_LOCK;
2157
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002158 DibReleaseLock(&state->demod_lock);
2159
Olivier Greniedd316c62011-01-04 04:28:59 -03002160 return 0;
2161}
2162
2163static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
2164{
2165 struct dib9000_state *state = fe->demodulator_priv;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002166 u16 *c;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002167 int ret = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03002168
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002169 DibAcquireLock(&state->demod_lock);
Olivier Greniedd316c62011-01-04 04:28:59 -03002170 DibAcquireLock(&state->platform.risc.mem_mbx_lock);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002171 if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
2172 ret = -EIO;
2173 goto error;
2174 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002175 dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR,
2176 state->i2c_read_buffer, 16 * 2);
Olivier Greniedd316c62011-01-04 04:28:59 -03002177 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
2178
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002179 c = (u16 *)state->i2c_read_buffer;
2180
Olivier Greniedd316c62011-01-04 04:28:59 -03002181 *ber = c[10] << 16 | c[11];
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002182
2183error:
2184 DibReleaseLock(&state->demod_lock);
2185 return ret;
Olivier Greniedd316c62011-01-04 04:28:59 -03002186}
2187
2188static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
2189{
2190 struct dib9000_state *state = fe->demodulator_priv;
2191 u8 index_frontend;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002192 u16 *c = (u16 *)state->i2c_read_buffer;
Olivier Greniedd316c62011-01-04 04:28:59 -03002193 u16 val;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002194 int ret = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03002195
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002196 DibAcquireLock(&state->demod_lock);
Olivier Greniedd316c62011-01-04 04:28:59 -03002197 *strength = 0;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002198 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03002199 state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val);
2200 if (val > 65535 - *strength)
2201 *strength = 65535;
2202 else
2203 *strength += val;
2204 }
2205
2206 DibAcquireLock(&state->platform.risc.mem_mbx_lock);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002207 if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
2208 ret = -EIO;
2209 goto error;
2210 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002211 dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
Olivier Greniedd316c62011-01-04 04:28:59 -03002212 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
2213
2214 val = 65535 - c[4];
2215 if (val > 65535 - *strength)
2216 *strength = 65535;
2217 else
2218 *strength += val;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002219
2220error:
2221 DibReleaseLock(&state->demod_lock);
2222 return ret;
Olivier Greniedd316c62011-01-04 04:28:59 -03002223}
2224
2225static u32 dib9000_get_snr(struct dvb_frontend *fe)
2226{
2227 struct dib9000_state *state = fe->demodulator_priv;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002228 u16 *c = (u16 *)state->i2c_read_buffer;
Olivier Greniedd316c62011-01-04 04:28:59 -03002229 u32 n, s, exp;
2230 u16 val;
2231
2232 DibAcquireLock(&state->platform.risc.mem_mbx_lock);
2233 if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
2234 return -EIO;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002235 dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
Olivier Greniedd316c62011-01-04 04:28:59 -03002236 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
2237
2238 val = c[7];
2239 n = (val >> 4) & 0xff;
2240 exp = ((val & 0xf) << 2);
2241 val = c[8];
2242 exp += ((val >> 14) & 0x3);
2243 if ((exp & 0x20) != 0)
2244 exp -= 0x40;
2245 n <<= exp + 16;
2246
2247 s = (val >> 6) & 0xFF;
2248 exp = (val & 0x3F);
2249 if ((exp & 0x20) != 0)
2250 exp -= 0x40;
2251 s <<= exp + 16;
2252
2253 if (n > 0) {
2254 u32 t = (s / n) << 16;
2255 return t + ((s << 16) - n * t) / n;
2256 }
2257 return 0xffffffff;
2258}
2259
2260static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr)
2261{
2262 struct dib9000_state *state = fe->demodulator_priv;
2263 u8 index_frontend;
2264 u32 snr_master;
2265
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002266 DibAcquireLock(&state->demod_lock);
Olivier Greniedd316c62011-01-04 04:28:59 -03002267 snr_master = dib9000_get_snr(fe);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002268 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
Olivier Greniedd316c62011-01-04 04:28:59 -03002269 snr_master += dib9000_get_snr(state->fe[index_frontend]);
2270
2271 if ((snr_master >> 16) != 0) {
2272 snr_master = 10 * intlog10(snr_master >> 16);
2273 *snr = snr_master / ((1 << 24) / 10);
2274 } else
2275 *snr = 0;
2276
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002277 DibReleaseLock(&state->demod_lock);
2278
Olivier Greniedd316c62011-01-04 04:28:59 -03002279 return 0;
2280}
2281
2282static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
2283{
2284 struct dib9000_state *state = fe->demodulator_priv;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002285 u16 *c = (u16 *)state->i2c_read_buffer;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002286 int ret = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03002287
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002288 DibAcquireLock(&state->demod_lock);
Olivier Greniedd316c62011-01-04 04:28:59 -03002289 DibAcquireLock(&state->platform.risc.mem_mbx_lock);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002290 if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
2291 ret = -EIO;
2292 goto error;
2293 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002294 dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
Olivier Greniedd316c62011-01-04 04:28:59 -03002295 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
2296
2297 *unc = c[12];
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002298
2299error:
2300 DibReleaseLock(&state->demod_lock);
2301 return ret;
Olivier Greniedd316c62011-01-04 04:28:59 -03002302}
2303
2304int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr)
2305{
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002306 int k = 0, ret = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03002307 u8 new_addr = 0;
2308 struct i2c_device client = {.i2c_adap = i2c };
2309
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002310 client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
2311 if (!client.i2c_write_buffer) {
2312 dprintk("%s: not enough memory", __func__);
2313 return -ENOMEM;
2314 }
2315 client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
2316 if (!client.i2c_read_buffer) {
2317 dprintk("%s: not enough memory", __func__);
2318 ret = -ENOMEM;
2319 goto error_memory;
2320 }
2321
Olivier Greniedd316c62011-01-04 04:28:59 -03002322 client.i2c_addr = default_addr + 16;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002323 dib9000_i2c_write16(&client, 1796, 0x0);
Olivier Greniedd316c62011-01-04 04:28:59 -03002324
2325 for (k = no_of_demods - 1; k >= 0; k--) {
2326 /* designated i2c address */
2327 new_addr = first_addr + (k << 1);
2328 client.i2c_addr = default_addr;
2329
2330 dib9000_i2c_write16(&client, 1817, 3);
2331 dib9000_i2c_write16(&client, 1796, 0);
2332 dib9000_i2c_write16(&client, 1227, 1);
2333 dib9000_i2c_write16(&client, 1227, 0);
2334
2335 client.i2c_addr = new_addr;
2336 dib9000_i2c_write16(&client, 1817, 3);
2337 dib9000_i2c_write16(&client, 1796, 0);
2338 dib9000_i2c_write16(&client, 1227, 1);
2339 dib9000_i2c_write16(&client, 1227, 0);
2340
2341 if (dib9000_identify(&client) == 0) {
2342 client.i2c_addr = default_addr;
2343 if (dib9000_identify(&client) == 0) {
2344 dprintk("DiB9000 #%d: not identified", k);
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002345 ret = -EIO;
2346 goto error;
Olivier Greniedd316c62011-01-04 04:28:59 -03002347 }
2348 }
2349
2350 dib9000_i2c_write16(&client, 1795, (1 << 10) | (4 << 6));
2351 dib9000_i2c_write16(&client, 1794, (new_addr << 2) | 2);
2352
2353 dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
2354 }
2355
2356 for (k = 0; k < no_of_demods; k++) {
2357 new_addr = first_addr | (k << 1);
2358 client.i2c_addr = new_addr;
2359
2360 dib9000_i2c_write16(&client, 1794, (new_addr << 2));
2361 dib9000_i2c_write16(&client, 1795, 0);
2362 }
2363
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002364error:
2365 kfree(client.i2c_read_buffer);
2366error_memory:
2367 kfree(client.i2c_write_buffer);
2368
2369 return ret;
Olivier Greniedd316c62011-01-04 04:28:59 -03002370}
Olivier Greniedd316c62011-01-04 04:28:59 -03002371EXPORT_SYMBOL(dib9000_i2c_enumeration);
2372
2373int dib9000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
2374{
2375 struct dib9000_state *state = fe->demodulator_priv;
2376 u8 index_frontend = 1;
2377
2378 while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
2379 index_frontend++;
2380 if (index_frontend < MAX_NUMBER_OF_FRONTENDS) {
2381 dprintk("set slave fe %p to index %i", fe_slave, index_frontend);
2382 state->fe[index_frontend] = fe_slave;
2383 return 0;
2384 }
2385
2386 dprintk("too many slave frontend");
2387 return -ENOMEM;
2388}
2389EXPORT_SYMBOL(dib9000_set_slave_frontend);
2390
2391int dib9000_remove_slave_frontend(struct dvb_frontend *fe)
2392{
2393 struct dib9000_state *state = fe->demodulator_priv;
2394 u8 index_frontend = 1;
2395
2396 while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
2397 index_frontend++;
2398 if (index_frontend != 1) {
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002399 dprintk("remove slave fe %p (index %i)", state->fe[index_frontend - 1], index_frontend - 1);
Olivier Greniedd316c62011-01-04 04:28:59 -03002400 state->fe[index_frontend] = NULL;
2401 return 0;
2402 }
2403
2404 dprintk("no frontend to be removed");
2405 return -ENODEV;
2406}
2407EXPORT_SYMBOL(dib9000_remove_slave_frontend);
2408
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002409struct dvb_frontend *dib9000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
Olivier Greniedd316c62011-01-04 04:28:59 -03002410{
2411 struct dib9000_state *state = fe->demodulator_priv;
2412
2413 if (slave_index >= MAX_NUMBER_OF_FRONTENDS)
2414 return NULL;
2415 return state->fe[slave_index];
2416}
2417EXPORT_SYMBOL(dib9000_get_slave_frontend);
2418
2419static struct dvb_frontend_ops dib9000_ops;
2420struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, const struct dib9000_config *cfg)
2421{
2422 struct dvb_frontend *fe;
2423 struct dib9000_state *st;
2424 st = kzalloc(sizeof(struct dib9000_state), GFP_KERNEL);
2425 if (st == NULL)
2426 return NULL;
2427 fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL);
Jesper Juhl451a51b2011-04-07 16:34:30 -03002428 if (fe == NULL) {
2429 kfree(st);
Olivier Greniedd316c62011-01-04 04:28:59 -03002430 return NULL;
Jesper Juhl451a51b2011-04-07 16:34:30 -03002431 }
Olivier Greniedd316c62011-01-04 04:28:59 -03002432
2433 memcpy(&st->chip.d9.cfg, cfg, sizeof(struct dib9000_config));
2434 st->i2c.i2c_adap = i2c_adap;
2435 st->i2c.i2c_addr = i2c_addr;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002436 st->i2c.i2c_write_buffer = st->i2c_write_buffer;
2437 st->i2c.i2c_read_buffer = st->i2c_read_buffer;
Olivier Greniedd316c62011-01-04 04:28:59 -03002438
2439 st->gpio_dir = DIB9000_GPIO_DEFAULT_DIRECTIONS;
2440 st->gpio_val = DIB9000_GPIO_DEFAULT_VALUES;
2441 st->gpio_pwm_pos = DIB9000_GPIO_DEFAULT_PWM_POS;
2442
2443 DibInitLock(&st->platform.risc.mbx_if_lock);
2444 DibInitLock(&st->platform.risc.mbx_lock);
2445 DibInitLock(&st->platform.risc.mem_lock);
2446 DibInitLock(&st->platform.risc.mem_mbx_lock);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002447 DibInitLock(&st->demod_lock);
2448 st->get_frontend_internal = 0;
2449
2450 st->pid_ctrl_index = -2;
Olivier Greniedd316c62011-01-04 04:28:59 -03002451
2452 st->fe[0] = fe;
2453 fe->demodulator_priv = st;
2454 memcpy(&st->fe[0]->ops, &dib9000_ops, sizeof(struct dvb_frontend_ops));
2455
2456 /* Ensure the output mode remains at the previous default if it's
2457 * not specifically set by the caller.
2458 */
2459 if ((st->chip.d9.cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (st->chip.d9.cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
2460 st->chip.d9.cfg.output_mode = OUTMODE_MPEG2_FIFO;
2461
2462 if (dib9000_identify(&st->i2c) == 0)
2463 goto error;
2464
2465 dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c.i2c_adap, st->i2c.i2c_addr);
2466
2467 st->tuner_adap.dev.parent = i2c_adap->dev.parent;
2468 strncpy(st->tuner_adap.name, "DIB9000_FW TUNER ACCESS", sizeof(st->tuner_adap.name));
2469 st->tuner_adap.algo = &dib9000_tuner_algo;
2470 st->tuner_adap.algo_data = NULL;
2471 i2c_set_adapdata(&st->tuner_adap, st);
2472 if (i2c_add_adapter(&st->tuner_adap) < 0)
2473 goto error;
2474
2475 st->component_bus.dev.parent = i2c_adap->dev.parent;
2476 strncpy(st->component_bus.name, "DIB9000_FW COMPONENT BUS ACCESS", sizeof(st->component_bus.name));
2477 st->component_bus.algo = &dib9000_component_bus_algo;
2478 st->component_bus.algo_data = NULL;
2479 st->component_bus_speed = 340;
2480 i2c_set_adapdata(&st->component_bus, st);
2481 if (i2c_add_adapter(&st->component_bus) < 0)
2482 goto component_bus_add_error;
2483
2484 dib9000_fw_reset(fe);
2485
2486 return fe;
2487
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002488component_bus_add_error:
Olivier Greniedd316c62011-01-04 04:28:59 -03002489 i2c_del_adapter(&st->tuner_adap);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002490error:
Olivier Greniedd316c62011-01-04 04:28:59 -03002491 kfree(st);
2492 return NULL;
2493}
Olivier Greniedd316c62011-01-04 04:28:59 -03002494EXPORT_SYMBOL(dib9000_attach);
2495
2496static struct dvb_frontend_ops dib9000_ops = {
2497 .info = {
2498 .name = "DiBcom 9000",
2499 .type = FE_OFDM,
2500 .frequency_min = 44250000,
2501 .frequency_max = 867250000,
2502 .frequency_stepsize = 62500,
2503 .caps = FE_CAN_INVERSION_AUTO |
2504 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
2505 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
2506 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
2507 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
2508 },
2509
2510 .release = dib9000_release,
2511
2512 .init = dib9000_wakeup,
2513 .sleep = dib9000_sleep,
2514
2515 .set_frontend = dib9000_set_frontend,
2516 .get_tune_settings = dib9000_fe_get_tune_settings,
2517 .get_frontend = dib9000_get_frontend,
2518
2519 .read_status = dib9000_read_status,
2520 .read_ber = dib9000_read_ber,
2521 .read_signal_strength = dib9000_read_signal_strength,
2522 .read_snr = dib9000_read_snr,
2523 .read_ucblocks = dib9000_read_unc_blocks,
2524};
2525
2526MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
2527MODULE_AUTHOR("Olivier Grenie <ogrenie@dibcom.fr>");
2528MODULE_DESCRIPTION("Driver for the DiBcom 9000 COFDM demodulator");
2529MODULE_LICENSE("GPL");