blob: 80848b4c15d4be62776c2366e8e49920ac7a664f [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
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -030036#define DibAcquireLock(lock) mutex_lock_interruptible(lock)
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
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -0300449 if (DibAcquireLock(&state->platform.risc.mem_lock) < 0) {
450 dprintk("could not get the lock");
451 return -EINTR;
452 }
Olivier Greniedd316c62011-01-04 04:28:59 -0300453 dib9000_risc_mem_setup(state, cmd | 0x80);
454 dib9000_risc_mem_read_chunks(state, b, len);
455 DibReleaseLock(&state->platform.risc.mem_lock);
456 return 0;
457}
458
459static int dib9000_risc_mem_write(struct dib9000_state *state, u8 cmd, const u8 * b)
460{
461 struct dib9000_fe_memory_map *m = &state->platform.risc.fe_mm[cmd];
462 if (!state->platform.risc.fw_is_running)
463 return -EIO;
464
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -0300465 if (DibAcquireLock(&state->platform.risc.mem_lock) < 0) {
466 dprintk("could not get the lock");
467 return -EINTR;
468 }
Olivier Greniedd316c62011-01-04 04:28:59 -0300469 dib9000_risc_mem_setup(state, cmd);
470 dib9000_risc_mem_write_chunks(state, b, m->size);
471 DibReleaseLock(&state->platform.risc.mem_lock);
472 return 0;
473}
474
475static int dib9000_firmware_download(struct dib9000_state *state, u8 risc_id, u16 key, const u8 * code, u32 len)
476{
477 u16 offs;
478
479 if (risc_id == 1)
480 offs = 16;
481 else
482 offs = 0;
483
484 /* config crtl reg */
485 dib9000_write_word(state, 1024 + offs, 0x000f);
486 dib9000_write_word(state, 1025 + offs, 0);
487 dib9000_write_word(state, 1031 + offs, key);
488
489 dprintk("going to download %dB of microcode", len);
490 if (dib9000_write16_noinc(state, 1026 + offs, (u8 *) code, (u16) len) != 0) {
491 dprintk("error while downloading microcode for RISC %c", 'A' + risc_id);
492 return -EIO;
493 }
494
495 dprintk("Microcode for RISC %c loaded", 'A' + risc_id);
496
497 return 0;
498}
499
500static int dib9000_mbx_host_init(struct dib9000_state *state, u8 risc_id)
501{
502 u16 mbox_offs;
503 u16 reset_reg;
504 u16 tries = 1000;
505
506 if (risc_id == 1)
507 mbox_offs = 16;
508 else
509 mbox_offs = 0;
510
511 /* Reset mailbox */
512 dib9000_write_word(state, 1027 + mbox_offs, 0x8000);
513
514 /* Read reset status */
515 do {
516 reset_reg = dib9000_read_word(state, 1027 + mbox_offs);
517 msleep(100);
518 } while ((reset_reg & 0x8000) && --tries);
519
520 if (reset_reg & 0x8000) {
521 dprintk("MBX: init ERROR, no response from RISC %c", 'A' + risc_id);
522 return -EIO;
523 }
524 dprintk("MBX: initialized");
525 return 0;
526}
527
528#define MAX_MAILBOX_TRY 100
529static int dib9000_mbx_send_attr(struct dib9000_state *state, u8 id, u16 * data, u8 len, u16 attr)
530{
Dan Carpenterb00aff62011-01-19 11:28:27 -0300531 u8 *d, b[2];
Olivier Greniedd316c62011-01-04 04:28:59 -0300532 u16 tmp;
533 u16 size;
534 u32 i;
Dan Carpenterb00aff62011-01-19 11:28:27 -0300535 int ret = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -0300536
537 if (!state->platform.risc.fw_is_running)
538 return -EINVAL;
539
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -0300540 if (DibAcquireLock(&state->platform.risc.mbx_if_lock) < 0) {
541 dprintk("could not get the lock");
542 return -EINTR;
543 }
Olivier Greniedd316c62011-01-04 04:28:59 -0300544 tmp = MAX_MAILBOX_TRY;
545 do {
546 size = dib9000_read_word_attr(state, 1043, attr) & 0xff;
547 if ((size + len + 1) > MBX_MAX_WORDS && --tmp) {
548 dprintk("MBX: RISC mbx full, retrying");
549 msleep(100);
550 } else
551 break;
552 } while (1);
553
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300554 /*dprintk( "MBX: size: %d", size); */
Olivier Greniedd316c62011-01-04 04:28:59 -0300555
556 if (tmp == 0) {
557 ret = -EINVAL;
558 goto out;
559 }
560#ifdef DUMP_MSG
561 dprintk("--> %02x %d ", id, len + 1);
562 for (i = 0; i < len; i++)
563 dprintk("%04x ", data[i]);
564 dprintk("\n");
565#endif
566
567 /* byte-order conversion - works on big (where it is not necessary) or little endian */
568 d = (u8 *) data;
569 for (i = 0; i < len; i++) {
570 tmp = data[i];
571 *d++ = tmp >> 8;
572 *d++ = tmp & 0xff;
573 }
574
575 /* write msg */
576 b[0] = id;
577 b[1] = len + 1;
578 if (dib9000_write16_noinc_attr(state, 1045, b, 2, attr) != 0 || dib9000_write16_noinc_attr(state, 1045, (u8 *) data, len * 2, attr) != 0) {
579 ret = -EIO;
580 goto out;
581 }
582
583 /* update register nb_mes_in_RX */
584 ret = (u8) dib9000_write_word_attr(state, 1043, 1 << 14, attr);
585
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300586out:
Olivier Greniedd316c62011-01-04 04:28:59 -0300587 DibReleaseLock(&state->platform.risc.mbx_if_lock);
588
589 return ret;
590}
591
592static u8 dib9000_mbx_read(struct dib9000_state *state, u16 * data, u8 risc_id, u16 attr)
593{
594#ifdef DUMP_MSG
595 u16 *d = data;
596#endif
597
598 u16 tmp, i;
599 u8 size;
600 u8 mc_base;
601
602 if (!state->platform.risc.fw_is_running)
603 return 0;
604
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -0300605 if (DibAcquireLock(&state->platform.risc.mbx_if_lock) < 0) {
606 dprintk("could not get the lock");
607 return 0;
608 }
Olivier Greniedd316c62011-01-04 04:28:59 -0300609 if (risc_id == 1)
610 mc_base = 16;
611 else
612 mc_base = 0;
613
614 /* Length and type in the first word */
615 *data = dib9000_read_word_attr(state, 1029 + mc_base, attr);
616
617 size = *data & 0xff;
618 if (size <= MBX_MAX_WORDS) {
619 data++;
620 size--; /* Initial word already read */
621
622 dib9000_read16_noinc_attr(state, 1029 + mc_base, (u8 *) data, size * 2, attr);
623
624 /* to word conversion */
625 for (i = 0; i < size; i++) {
626 tmp = *data;
627 *data = (tmp >> 8) | (tmp << 8);
628 data++;
629 }
630
631#ifdef DUMP_MSG
632 dprintk("<-- ");
633 for (i = 0; i < size + 1; i++)
634 dprintk("%04x ", d[i]);
635 dprintk("\n");
636#endif
637 } else {
638 dprintk("MBX: message is too big for message cache (%d), flushing message", size);
639 size--; /* Initial word already read */
640 while (size--)
641 dib9000_read16_noinc_attr(state, 1029 + mc_base, (u8 *) data, 2, attr);
642 }
643 /* Update register nb_mes_in_TX */
644 dib9000_write_word_attr(state, 1028 + mc_base, 1 << 14, attr);
645
646 DibReleaseLock(&state->platform.risc.mbx_if_lock);
647
648 return size + 1;
649}
650
651static int dib9000_risc_debug_buf(struct dib9000_state *state, u16 * data, u8 size)
652{
653 u32 ts = data[1] << 16 | data[0];
654 char *b = (char *)&data[2];
655
656 b[2 * (size - 2) - 1] = '\0'; /* Bullet proof the buffer */
657 if (*b == '~') {
658 b++;
659 dprintk(b);
660 } else
661 dprintk("RISC%d: %d.%04d %s", state->fe_id, ts / 10000, ts % 10000, *b ? b : "<emtpy>");
662 return 1;
663}
664
665static int dib9000_mbx_fetch_to_cache(struct dib9000_state *state, u16 attr)
666{
667 int i;
668 u8 size;
669 u16 *block;
670 /* find a free slot */
671 for (i = 0; i < DIB9000_MSG_CACHE_SIZE; i++) {
672 block = state->platform.risc.message_cache[i];
673 if (*block == 0) {
674 size = dib9000_mbx_read(state, block, 1, attr);
675
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300676/* dprintk( "MBX: fetched %04x message to cache", *block); */
Olivier Greniedd316c62011-01-04 04:28:59 -0300677
678 switch (*block >> 8) {
679 case IN_MSG_DEBUG_BUF:
680 dib9000_risc_debug_buf(state, block + 1, size); /* debug-messages are going to be printed right away */
681 *block = 0; /* free the block */
682 break;
683#if 0
684 case IN_MSG_DATA: /* FE-TRACE */
685 dib9000_risc_data_process(state, block + 1, size);
686 *block = 0;
687 break;
688#endif
689 default:
690 break;
691 }
692
693 return 1;
694 }
695 }
696 dprintk("MBX: no free cache-slot found for new message...");
697 return -1;
698}
699
700static u8 dib9000_mbx_count(struct dib9000_state *state, u8 risc_id, u16 attr)
701{
702 if (risc_id == 0)
703 return (u8) (dib9000_read_word_attr(state, 1028, attr) >> 10) & 0x1f; /* 5 bit field */
704 else
705 return (u8) (dib9000_read_word_attr(state, 1044, attr) >> 8) & 0x7f; /* 7 bit field */
706}
707
708static int dib9000_mbx_process(struct dib9000_state *state, u16 attr)
709{
710 int ret = 0;
711 u16 tmp;
712
713 if (!state->platform.risc.fw_is_running)
714 return -1;
715
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -0300716 if (DibAcquireLock(&state->platform.risc.mbx_lock) < 0) {
717 dprintk("could not get the lock");
718 return -1;
719 }
Olivier Greniedd316c62011-01-04 04:28:59 -0300720
721 if (dib9000_mbx_count(state, 1, attr)) /* 1=RiscB */
722 ret = dib9000_mbx_fetch_to_cache(state, attr);
723
724 tmp = dib9000_read_word_attr(state, 1229, attr); /* Clear the IRQ */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300725/* if (tmp) */
726/* dprintk( "cleared IRQ: %x", tmp); */
Olivier Greniedd316c62011-01-04 04:28:59 -0300727 DibReleaseLock(&state->platform.risc.mbx_lock);
728
729 return ret;
730}
731
732static int dib9000_mbx_get_message_attr(struct dib9000_state *state, u16 id, u16 * msg, u8 * size, u16 attr)
733{
734 u8 i;
735 u16 *block;
736 u16 timeout = 30;
737
738 *msg = 0;
739 do {
740 /* dib9000_mbx_get_from_cache(); */
741 for (i = 0; i < DIB9000_MSG_CACHE_SIZE; i++) {
742 block = state->platform.risc.message_cache[i];
743 if ((*block >> 8) == id) {
744 *size = (*block & 0xff) - 1;
745 memcpy(msg, block + 1, (*size) * 2);
746 *block = 0; /* free the block */
747 i = 0; /* signal that we found a message */
748 break;
749 }
750 }
751
752 if (i == 0)
753 break;
754
755 if (dib9000_mbx_process(state, attr) == -1) /* try to fetch one message - if any */
756 return -1;
757
758 } while (--timeout);
759
760 if (timeout == 0) {
761 dprintk("waiting for message %d timed out", id);
762 return -1;
763 }
764
765 return i == 0;
766}
767
768static int dib9000_risc_check_version(struct dib9000_state *state)
769{
770 u8 r[4];
771 u8 size;
772 u16 fw_version = 0;
773
774 if (dib9000_mbx_send(state, OUT_MSG_REQ_VERSION, &fw_version, 1) != 0)
775 return -EIO;
776
777 if (dib9000_mbx_get_message(state, IN_MSG_VERSION, (u16 *) r, &size) < 0)
778 return -EIO;
779
780 fw_version = (r[0] << 8) | r[1];
781 dprintk("RISC: ver: %d.%02d (IC: %d)", fw_version >> 10, fw_version & 0x3ff, (r[2] << 8) | r[3]);
782
783 if ((fw_version >> 10) != 7)
784 return -EINVAL;
785
786 switch (fw_version & 0x3ff) {
787 case 11:
788 case 12:
789 case 14:
790 case 15:
791 case 16:
792 case 17:
793 break;
794 default:
795 dprintk("RISC: invalid firmware version");
796 return -EINVAL;
797 }
798
799 dprintk("RISC: valid firmware version");
800 return 0;
801}
802
803static int dib9000_fw_boot(struct dib9000_state *state, const u8 * codeA, u32 lenA, const u8 * codeB, u32 lenB)
804{
805 /* Reconfig pool mac ram */
806 dib9000_write_word(state, 1225, 0x02); /* A: 8k C, 4 k D - B: 32k C 6 k D - IRAM 96k */
807 dib9000_write_word(state, 1226, 0x05);
808
809 /* Toggles IP crypto to Host APB interface. */
810 dib9000_write_word(state, 1542, 1);
811
812 /* Set jump and no jump in the dma box */
813 dib9000_write_word(state, 1074, 0);
814 dib9000_write_word(state, 1075, 0);
815
816 /* Set MAC as APB Master. */
817 dib9000_write_word(state, 1237, 0);
818
819 /* Reset the RISCs */
820 if (codeA != NULL)
821 dib9000_write_word(state, 1024, 2);
822 else
823 dib9000_write_word(state, 1024, 15);
824 if (codeB != NULL)
825 dib9000_write_word(state, 1040, 2);
826
827 if (codeA != NULL)
828 dib9000_firmware_download(state, 0, 0x1234, codeA, lenA);
829 if (codeB != NULL)
830 dib9000_firmware_download(state, 1, 0x1234, codeB, lenB);
831
832 /* Run the RISCs */
833 if (codeA != NULL)
834 dib9000_write_word(state, 1024, 0);
835 if (codeB != NULL)
836 dib9000_write_word(state, 1040, 0);
837
838 if (codeA != NULL)
839 if (dib9000_mbx_host_init(state, 0) != 0)
840 return -EIO;
841 if (codeB != NULL)
842 if (dib9000_mbx_host_init(state, 1) != 0)
843 return -EIO;
844
845 msleep(100);
846 state->platform.risc.fw_is_running = 1;
847
848 if (dib9000_risc_check_version(state) != 0)
849 return -EINVAL;
850
851 state->platform.risc.memcmd = 0xff;
852 return 0;
853}
854
855static u16 dib9000_identify(struct i2c_device *client)
856{
857 u16 value;
858
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300859 value = dib9000_i2c_read16(client, 896);
860 if (value != 0x01b3) {
Olivier Greniedd316c62011-01-04 04:28:59 -0300861 dprintk("wrong Vendor ID (0x%x)", value);
862 return 0;
863 }
864
865 value = dib9000_i2c_read16(client, 897);
866 if (value != 0x4000 && value != 0x4001 && value != 0x4002 && value != 0x4003 && value != 0x4004 && value != 0x4005) {
867 dprintk("wrong Device ID (0x%x)", value);
868 return 0;
869 }
870
871 /* protect this driver to be used with 7000PC */
872 if (value == 0x4000 && dib9000_i2c_read16(client, 769) == 0x4000) {
873 dprintk("this driver does not work with DiB7000PC");
874 return 0;
875 }
876
877 switch (value) {
878 case 0x4000:
879 dprintk("found DiB7000MA/PA/MB/PB");
880 break;
881 case 0x4001:
882 dprintk("found DiB7000HC");
883 break;
884 case 0x4002:
885 dprintk("found DiB7000MC");
886 break;
887 case 0x4003:
888 dprintk("found DiB9000A");
889 break;
890 case 0x4004:
891 dprintk("found DiB9000H");
892 break;
893 case 0x4005:
894 dprintk("found DiB9000M");
895 break;
896 }
897
898 return value;
899}
900
901static void dib9000_set_power_mode(struct dib9000_state *state, enum dib9000_power_mode mode)
902{
903 /* by default everything is going to be powered off */
904 u16 reg_903 = 0x3fff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906;
905 u8 offset;
906
907 if (state->revision == 0x4003 || state->revision == 0x4004 || state->revision == 0x4005)
908 offset = 1;
909 else
910 offset = 0;
911
912 reg_906 = dib9000_read_word(state, 906 + offset) | 0x3; /* keep settings for RISC */
913
914 /* now, depending on the requested mode, we power on */
915 switch (mode) {
916 /* power up everything in the demod */
917 case DIB9000_POWER_ALL:
918 reg_903 = 0x0000;
919 reg_904 = 0x0000;
920 reg_905 = 0x0000;
921 reg_906 = 0x0000;
922 break;
923
924 /* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */
925 case DIB9000_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */
926 reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2));
927 break;
928
929 case DIB9000_POWER_INTERF_ANALOG_AGC:
930 reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10));
931 reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2));
932 reg_906 &= ~((1 << 0));
933 break;
934
935 case DIB9000_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD:
936 reg_903 = 0x0000;
937 reg_904 = 0x801f;
938 reg_905 = 0x0000;
939 reg_906 &= ~((1 << 0));
940 break;
941
942 case DIB9000_POWER_COR4_CRY_ESRAM_MOUT_NUD:
943 reg_903 = 0x0000;
944 reg_904 = 0x8000;
945 reg_905 = 0x010b;
946 reg_906 &= ~((1 << 0));
947 break;
948 default:
949 case DIB9000_POWER_NO:
950 break;
951 }
952
953 /* always power down unused parts */
954 if (!state->platform.host.mobile_mode)
955 reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1);
956
957 /* P_sdio_select_clk = 0 on MC and after */
958 if (state->revision != 0x4000)
959 reg_906 <<= 1;
960
961 dib9000_write_word(state, 903 + offset, reg_903);
962 dib9000_write_word(state, 904 + offset, reg_904);
963 dib9000_write_word(state, 905 + offset, reg_905);
964 dib9000_write_word(state, 906 + offset, reg_906);
965}
966
967static int dib9000_fw_reset(struct dvb_frontend *fe)
968{
969 struct dib9000_state *state = fe->demodulator_priv;
970
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300971 dib9000_write_word(state, 1817, 0x0003);
Olivier Greniedd316c62011-01-04 04:28:59 -0300972
973 dib9000_write_word(state, 1227, 1);
974 dib9000_write_word(state, 1227, 0);
975
976 switch ((state->revision = dib9000_identify(&state->i2c))) {
977 case 0x4003:
978 case 0x4004:
979 case 0x4005:
980 state->reg_offs = 1;
981 break;
982 default:
983 return -EINVAL;
984 }
985
986 /* reset the i2c-master to use the host interface */
987 dibx000_reset_i2c_master(&state->i2c_master);
988
989 dib9000_set_power_mode(state, DIB9000_POWER_ALL);
990
991 /* unforce divstr regardless whether i2c enumeration was done or not */
992 dib9000_write_word(state, 1794, dib9000_read_word(state, 1794) & ~(1 << 1));
993 dib9000_write_word(state, 1796, 0);
994 dib9000_write_word(state, 1805, 0x805);
995
996 /* restart all parts */
997 dib9000_write_word(state, 898, 0xffff);
998 dib9000_write_word(state, 899, 0xffff);
999 dib9000_write_word(state, 900, 0x0001);
1000 dib9000_write_word(state, 901, 0xff19);
1001 dib9000_write_word(state, 902, 0x003c);
1002
1003 dib9000_write_word(state, 898, 0);
1004 dib9000_write_word(state, 899, 0);
1005 dib9000_write_word(state, 900, 0);
1006 dib9000_write_word(state, 901, 0);
1007 dib9000_write_word(state, 902, 0);
1008
1009 dib9000_write_word(state, 911, state->chip.d9.cfg.if_drives);
1010
1011 dib9000_set_power_mode(state, DIB9000_POWER_INTERFACE_ONLY);
1012
1013 return 0;
1014}
1015
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001016static 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 -03001017{
1018 u16 mb[10];
1019 u8 i, s;
1020
1021 if (address >= 1024 || !state->platform.risc.fw_is_running)
1022 return -EINVAL;
1023
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001024 /* dprintk( "APB access thru rd fw %d %x", address, attribute); */
Olivier Greniedd316c62011-01-04 04:28:59 -03001025
1026 mb[0] = (u16) address;
1027 mb[1] = len / 2;
1028 dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_R, mb, 2, attribute);
1029 switch (dib9000_mbx_get_message_attr(state, IN_MSG_END_BRIDGE_APB_RW, mb, &s, attribute)) {
1030 case 1:
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001031 s--;
Olivier Greniedd316c62011-01-04 04:28:59 -03001032 for (i = 0; i < s; i++) {
1033 b[i * 2] = (mb[i + 1] >> 8) & 0xff;
1034 b[i * 2 + 1] = (mb[i + 1]) & 0xff;
1035 }
1036 return 0;
1037 default:
1038 return -EIO;
1039 }
1040 return -EIO;
1041}
1042
1043static int dib9000_risc_apb_access_write(struct dib9000_state *state, u32 address, u16 attribute, const u8 * b, u32 len)
1044{
1045 u16 mb[10];
1046 u8 s, i;
1047
1048 if (address >= 1024 || !state->platform.risc.fw_is_running)
1049 return -EINVAL;
1050
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001051 /* dprintk( "APB access thru wr fw %d %x", address, attribute); */
Olivier Greniedd316c62011-01-04 04:28:59 -03001052
1053 mb[0] = (unsigned short)address;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001054 for (i = 0; i < len && i < 20; i += 2)
Olivier Greniedd316c62011-01-04 04:28:59 -03001055 mb[1 + (i / 2)] = (b[i] << 8 | b[i + 1]);
1056
1057 dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_W, mb, 1 + len / 2, attribute);
1058 return dib9000_mbx_get_message_attr(state, IN_MSG_END_BRIDGE_APB_RW, mb, &s, attribute) == 1 ? 0 : -EINVAL;
1059}
1060
1061static int dib9000_fw_memmbx_sync(struct dib9000_state *state, u8 i)
1062{
1063 u8 index_loop = 10;
1064
1065 if (!state->platform.risc.fw_is_running)
1066 return 0;
1067 dib9000_risc_mem_write(state, FE_MM_RW_SYNC, &i);
1068 do {
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001069 dib9000_risc_mem_read(state, FE_MM_RW_SYNC, state->i2c_read_buffer, 1);
1070 } while (state->i2c_read_buffer[0] && index_loop--);
Olivier Greniedd316c62011-01-04 04:28:59 -03001071
1072 if (index_loop > 0)
1073 return 0;
1074 return -EIO;
1075}
1076
1077static int dib9000_fw_init(struct dib9000_state *state)
1078{
1079 struct dibGPIOFunction *f;
1080 u16 b[40] = { 0 };
1081 u8 i;
1082 u8 size;
1083
1084 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 -03001085 return -EIO;
1086
1087 /* initialize the firmware */
1088 for (i = 0; i < ARRAY_SIZE(state->chip.d9.cfg.gpio_function); i++) {
1089 f = &state->chip.d9.cfg.gpio_function[i];
1090 if (f->mask) {
1091 switch (f->function) {
1092 case BOARD_GPIO_FUNCTION_COMPONENT_ON:
1093 b[0] = (u16) f->mask;
1094 b[1] = (u16) f->direction;
1095 b[2] = (u16) f->value;
1096 break;
1097 case BOARD_GPIO_FUNCTION_COMPONENT_OFF:
1098 b[3] = (u16) f->mask;
1099 b[4] = (u16) f->direction;
1100 b[5] = (u16) f->value;
1101 break;
1102 }
1103 }
1104 }
1105 if (dib9000_mbx_send(state, OUT_MSG_CONF_GPIO, b, 15) != 0)
1106 return -EIO;
1107
1108 /* subband */
1109 b[0] = state->chip.d9.cfg.subband.size; /* type == 0 -> GPIO - PWM not yet supported */
1110 for (i = 0; i < state->chip.d9.cfg.subband.size; i++) {
1111 b[1 + i * 4] = state->chip.d9.cfg.subband.subband[i].f_mhz;
1112 b[2 + i * 4] = (u16) state->chip.d9.cfg.subband.subband[i].gpio.mask;
1113 b[3 + i * 4] = (u16) state->chip.d9.cfg.subband.subband[i].gpio.direction;
1114 b[4 + i * 4] = (u16) state->chip.d9.cfg.subband.subband[i].gpio.value;
Olivier Greniedd316c62011-01-04 04:28:59 -03001115 }
1116 b[1 + i * 4] = 0; /* fe_id */
1117 if (dib9000_mbx_send(state, OUT_MSG_SUBBAND_SEL, b, 2 + 4 * i) != 0)
1118 return -EIO;
1119
1120 /* 0 - id, 1 - no_of_frontends */
1121 b[0] = (0 << 8) | 1;
1122 /* 0 = i2c-address demod, 0 = tuner */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001123 b[1] = (0 << 8) | (0);
Olivier Greniedd316c62011-01-04 04:28:59 -03001124 b[2] = (u16) (((state->chip.d9.cfg.xtal_clock_khz * 1000) >> 16) & 0xffff);
1125 b[3] = (u16) (((state->chip.d9.cfg.xtal_clock_khz * 1000)) & 0xffff);
1126 b[4] = (u16) ((state->chip.d9.cfg.vcxo_timer >> 16) & 0xffff);
1127 b[5] = (u16) ((state->chip.d9.cfg.vcxo_timer) & 0xffff);
1128 b[6] = (u16) ((state->chip.d9.cfg.timing_frequency >> 16) & 0xffff);
1129 b[7] = (u16) ((state->chip.d9.cfg.timing_frequency) & 0xffff);
1130 b[29] = state->chip.d9.cfg.if_drives;
1131 if (dib9000_mbx_send(state, OUT_MSG_INIT_DEMOD, b, ARRAY_SIZE(b)) != 0)
1132 return -EIO;
1133
1134 if (dib9000_mbx_send(state, OUT_MSG_FE_FW_DL, NULL, 0) != 0)
1135 return -EIO;
1136
1137 if (dib9000_mbx_get_message(state, IN_MSG_FE_FW_DL_DONE, b, &size) < 0)
1138 return -EIO;
1139
1140 if (size > ARRAY_SIZE(b)) {
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001141 dprintk("error : firmware returned %dbytes needed but the used buffer has only %dbytes\n Firmware init ABORTED", size,
1142 (int)ARRAY_SIZE(b));
Olivier Greniedd316c62011-01-04 04:28:59 -03001143 return -EINVAL;
1144 }
1145
1146 for (i = 0; i < size; i += 2) {
1147 state->platform.risc.fe_mm[i / 2].addr = b[i + 0];
1148 state->platform.risc.fe_mm[i / 2].size = b[i + 1];
Olivier Greniedd316c62011-01-04 04:28:59 -03001149 }
1150
1151 return 0;
1152}
1153
Mauro Carvalho Chehab759e2362011-12-22 19:54:08 -03001154static void dib9000_fw_set_channel_head(struct dib9000_state *state)
Olivier Greniedd316c62011-01-04 04:28:59 -03001155{
1156 u8 b[9];
1157 u32 freq = state->fe[0]->dtv_property_cache.frequency / 1000;
1158 if (state->fe_id % 2)
1159 freq += 101;
1160
1161 b[0] = (u8) ((freq >> 0) & 0xff);
1162 b[1] = (u8) ((freq >> 8) & 0xff);
1163 b[2] = (u8) ((freq >> 16) & 0xff);
1164 b[3] = (u8) ((freq >> 24) & 0xff);
1165 b[4] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 0) & 0xff);
1166 b[5] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 8) & 0xff);
1167 b[6] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 16) & 0xff);
1168 b[7] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 24) & 0xff);
1169 b[8] = 0x80; /* do not wait for CELL ID when doing autosearch */
1170 if (state->fe[0]->dtv_property_cache.delivery_system == SYS_DVBT)
1171 b[8] |= 1;
1172 dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_HEAD, b);
1173}
1174
Mauro Carvalho Chehab759e2362011-12-22 19:54:08 -03001175static int dib9000_fw_get_channel(struct dvb_frontend *fe)
Olivier Greniedd316c62011-01-04 04:28:59 -03001176{
1177 struct dib9000_state *state = fe->demodulator_priv;
1178 struct dibDVBTChannel {
1179 s8 spectrum_inversion;
1180
1181 s8 nfft;
1182 s8 guard;
1183 s8 constellation;
1184
1185 s8 hrch;
1186 s8 alpha;
1187 s8 code_rate_hp;
1188 s8 code_rate_lp;
1189 s8 select_hp;
1190
1191 s8 intlv_native;
1192 };
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001193 struct dibDVBTChannel *ch;
Olivier Greniedd316c62011-01-04 04:28:59 -03001194 int ret = 0;
1195
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -03001196 if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) {
1197 dprintk("could not get the lock");
1198 return -EINTR;
1199 }
Olivier Greniedd316c62011-01-04 04:28:59 -03001200 if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001201 ret = -EIO;
Dan Carpenter2f098cb2011-08-06 05:01:51 -03001202 goto error;
Olivier Greniedd316c62011-01-04 04:28:59 -03001203 }
1204
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001205 dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION,
1206 state->i2c_read_buffer, sizeof(struct dibDVBTChannel));
1207 ch = (struct dibDVBTChannel *)state->i2c_read_buffer;
Olivier Greniedd316c62011-01-04 04:28:59 -03001208
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001209
1210 switch (ch->spectrum_inversion & 0x7) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001211 case 1:
1212 state->fe[0]->dtv_property_cache.inversion = INVERSION_ON;
1213 break;
1214 case 0:
1215 state->fe[0]->dtv_property_cache.inversion = INVERSION_OFF;
1216 break;
1217 default:
1218 case -1:
1219 state->fe[0]->dtv_property_cache.inversion = INVERSION_AUTO;
1220 break;
1221 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001222 switch (ch->nfft) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001223 case 0:
1224 state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
1225 break;
1226 case 2:
1227 state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_4K;
1228 break;
1229 case 1:
1230 state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
1231 break;
1232 default:
1233 case -1:
1234 state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO;
1235 break;
1236 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001237 switch (ch->guard) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001238 case 0:
1239 state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
1240 break;
1241 case 1:
1242 state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16;
1243 break;
1244 case 2:
1245 state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
1246 break;
1247 case 3:
1248 state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4;
1249 break;
1250 default:
1251 case -1:
1252 state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO;
1253 break;
1254 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001255 switch (ch->constellation) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001256 case 2:
1257 state->fe[0]->dtv_property_cache.modulation = QAM_64;
1258 break;
1259 case 1:
1260 state->fe[0]->dtv_property_cache.modulation = QAM_16;
1261 break;
1262 case 0:
1263 state->fe[0]->dtv_property_cache.modulation = QPSK;
1264 break;
1265 default:
1266 case -1:
1267 state->fe[0]->dtv_property_cache.modulation = QAM_AUTO;
1268 break;
1269 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001270 switch (ch->hrch) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001271 case 0:
1272 state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_NONE;
1273 break;
1274 case 1:
1275 state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_1;
1276 break;
1277 default:
1278 case -1:
1279 state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_AUTO;
1280 break;
1281 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001282 switch (ch->code_rate_hp) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001283 case 1:
1284 state->fe[0]->dtv_property_cache.code_rate_HP = FEC_1_2;
1285 break;
1286 case 2:
1287 state->fe[0]->dtv_property_cache.code_rate_HP = FEC_2_3;
1288 break;
1289 case 3:
1290 state->fe[0]->dtv_property_cache.code_rate_HP = FEC_3_4;
1291 break;
1292 case 5:
1293 state->fe[0]->dtv_property_cache.code_rate_HP = FEC_5_6;
1294 break;
1295 case 7:
1296 state->fe[0]->dtv_property_cache.code_rate_HP = FEC_7_8;
1297 break;
1298 default:
1299 case -1:
1300 state->fe[0]->dtv_property_cache.code_rate_HP = FEC_AUTO;
1301 break;
1302 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001303 switch (ch->code_rate_lp) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001304 case 1:
1305 state->fe[0]->dtv_property_cache.code_rate_LP = FEC_1_2;
1306 break;
1307 case 2:
1308 state->fe[0]->dtv_property_cache.code_rate_LP = FEC_2_3;
1309 break;
1310 case 3:
1311 state->fe[0]->dtv_property_cache.code_rate_LP = FEC_3_4;
1312 break;
1313 case 5:
1314 state->fe[0]->dtv_property_cache.code_rate_LP = FEC_5_6;
1315 break;
1316 case 7:
1317 state->fe[0]->dtv_property_cache.code_rate_LP = FEC_7_8;
1318 break;
1319 default:
1320 case -1:
1321 state->fe[0]->dtv_property_cache.code_rate_LP = FEC_AUTO;
1322 break;
1323 }
1324
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001325error:
Olivier Greniedd316c62011-01-04 04:28:59 -03001326 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
1327 return ret;
1328}
1329
Mauro Carvalho Chehabf20b12e2011-12-22 20:42:12 -03001330static int dib9000_fw_set_channel_union(struct dvb_frontend *fe)
Olivier Greniedd316c62011-01-04 04:28:59 -03001331{
1332 struct dib9000_state *state = fe->demodulator_priv;
1333 struct dibDVBTChannel {
1334 s8 spectrum_inversion;
1335
1336 s8 nfft;
1337 s8 guard;
1338 s8 constellation;
1339
1340 s8 hrch;
1341 s8 alpha;
1342 s8 code_rate_hp;
1343 s8 code_rate_lp;
1344 s8 select_hp;
1345
1346 s8 intlv_native;
1347 };
1348 struct dibDVBTChannel ch;
1349
1350 switch (state->fe[0]->dtv_property_cache.inversion) {
1351 case INVERSION_ON:
1352 ch.spectrum_inversion = 1;
1353 break;
1354 case INVERSION_OFF:
1355 ch.spectrum_inversion = 0;
1356 break;
1357 default:
1358 case INVERSION_AUTO:
1359 ch.spectrum_inversion = -1;
1360 break;
1361 }
1362 switch (state->fe[0]->dtv_property_cache.transmission_mode) {
1363 case TRANSMISSION_MODE_2K:
1364 ch.nfft = 0;
1365 break;
1366 case TRANSMISSION_MODE_4K:
1367 ch.nfft = 2;
1368 break;
1369 case TRANSMISSION_MODE_8K:
1370 ch.nfft = 1;
1371 break;
1372 default:
1373 case TRANSMISSION_MODE_AUTO:
1374 ch.nfft = 1;
1375 break;
1376 }
1377 switch (state->fe[0]->dtv_property_cache.guard_interval) {
1378 case GUARD_INTERVAL_1_32:
1379 ch.guard = 0;
1380 break;
1381 case GUARD_INTERVAL_1_16:
1382 ch.guard = 1;
1383 break;
1384 case GUARD_INTERVAL_1_8:
1385 ch.guard = 2;
1386 break;
1387 case GUARD_INTERVAL_1_4:
1388 ch.guard = 3;
1389 break;
1390 default:
1391 case GUARD_INTERVAL_AUTO:
1392 ch.guard = -1;
1393 break;
1394 }
1395 switch (state->fe[0]->dtv_property_cache.modulation) {
1396 case QAM_64:
1397 ch.constellation = 2;
1398 break;
1399 case QAM_16:
1400 ch.constellation = 1;
1401 break;
1402 case QPSK:
1403 ch.constellation = 0;
1404 break;
1405 default:
1406 case QAM_AUTO:
1407 ch.constellation = -1;
1408 break;
1409 }
1410 switch (state->fe[0]->dtv_property_cache.hierarchy) {
1411 case HIERARCHY_NONE:
1412 ch.hrch = 0;
1413 break;
1414 case HIERARCHY_1:
1415 case HIERARCHY_2:
1416 case HIERARCHY_4:
1417 ch.hrch = 1;
1418 break;
1419 default:
1420 case HIERARCHY_AUTO:
1421 ch.hrch = -1;
1422 break;
1423 }
1424 ch.alpha = 1;
1425 switch (state->fe[0]->dtv_property_cache.code_rate_HP) {
1426 case FEC_1_2:
1427 ch.code_rate_hp = 1;
1428 break;
1429 case FEC_2_3:
1430 ch.code_rate_hp = 2;
1431 break;
1432 case FEC_3_4:
1433 ch.code_rate_hp = 3;
1434 break;
1435 case FEC_5_6:
1436 ch.code_rate_hp = 5;
1437 break;
1438 case FEC_7_8:
1439 ch.code_rate_hp = 7;
1440 break;
1441 default:
1442 case FEC_AUTO:
1443 ch.code_rate_hp = -1;
1444 break;
1445 }
1446 switch (state->fe[0]->dtv_property_cache.code_rate_LP) {
1447 case FEC_1_2:
1448 ch.code_rate_lp = 1;
1449 break;
1450 case FEC_2_3:
1451 ch.code_rate_lp = 2;
1452 break;
1453 case FEC_3_4:
1454 ch.code_rate_lp = 3;
1455 break;
1456 case FEC_5_6:
1457 ch.code_rate_lp = 5;
1458 break;
1459 case FEC_7_8:
1460 ch.code_rate_lp = 7;
1461 break;
1462 default:
1463 case FEC_AUTO:
1464 ch.code_rate_lp = -1;
1465 break;
1466 }
1467 ch.select_hp = 1;
1468 ch.intlv_native = 1;
1469
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001470 dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_UNION, (u8 *) &ch);
Olivier Greniedd316c62011-01-04 04:28:59 -03001471
1472 return 0;
1473}
1474
Mauro Carvalho Chehabf20b12e2011-12-22 20:42:12 -03001475static int dib9000_fw_tune(struct dvb_frontend *fe)
Olivier Greniedd316c62011-01-04 04:28:59 -03001476{
1477 struct dib9000_state *state = fe->demodulator_priv;
1478 int ret = 10, search = state->channel_status.status == CHANNEL_STATUS_PARAMETERS_UNKNOWN;
1479 s8 i;
1480
1481 switch (state->tune_state) {
1482 case CT_DEMOD_START:
Mauro Carvalho Chehab759e2362011-12-22 19:54:08 -03001483 dib9000_fw_set_channel_head(state);
Olivier Greniedd316c62011-01-04 04:28:59 -03001484
1485 /* write the channel context - a channel is initialized to 0, so it is OK */
1486 dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_CONTEXT, (u8 *) fe_info);
1487 dib9000_risc_mem_write(state, FE_MM_W_FE_INFO, (u8 *) fe_info);
1488
1489 if (search)
1490 dib9000_mbx_send(state, OUT_MSG_FE_CHANNEL_SEARCH, NULL, 0);
1491 else {
Mauro Carvalho Chehabf20b12e2011-12-22 20:42:12 -03001492 dib9000_fw_set_channel_union(fe);
Olivier Greniedd316c62011-01-04 04:28:59 -03001493 dib9000_mbx_send(state, OUT_MSG_FE_CHANNEL_TUNE, NULL, 0);
1494 }
1495 state->tune_state = CT_DEMOD_STEP_1;
1496 break;
1497 case CT_DEMOD_STEP_1:
1498 if (search)
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001499 dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, state->i2c_read_buffer, 1);
Olivier Greniedd316c62011-01-04 04:28:59 -03001500 else
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001501 dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, state->i2c_read_buffer, 1);
1502 i = (s8)state->i2c_read_buffer[0];
Olivier Greniedd316c62011-01-04 04:28:59 -03001503 switch (i) { /* something happened */
1504 case 0:
1505 break;
1506 case -2: /* tps locks are "slower" than MPEG locks -> even in autosearch data is OK here */
1507 if (search)
1508 state->status = FE_STATUS_DEMOD_SUCCESS;
1509 else {
1510 state->tune_state = CT_DEMOD_STOP;
1511 state->status = FE_STATUS_LOCKED;
1512 }
1513 break;
1514 default:
1515 state->status = FE_STATUS_TUNE_FAILED;
1516 state->tune_state = CT_DEMOD_STOP;
1517 break;
1518 }
1519 break;
1520 default:
1521 ret = FE_CALLBACK_TIME_NEVER;
1522 break;
1523 }
1524
1525 return ret;
1526}
1527
1528static int dib9000_fw_set_diversity_in(struct dvb_frontend *fe, int onoff)
1529{
1530 struct dib9000_state *state = fe->demodulator_priv;
1531 u16 mode = (u16) onoff;
1532 return dib9000_mbx_send(state, OUT_MSG_ENABLE_DIVERSITY, &mode, 1);
1533}
1534
1535static int dib9000_fw_set_output_mode(struct dvb_frontend *fe, int mode)
1536{
1537 struct dib9000_state *state = fe->demodulator_priv;
1538 u16 outreg, smo_mode;
1539
1540 dprintk("setting output mode for demod %p to %d", fe, mode);
1541
1542 switch (mode) {
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001543 case OUTMODE_MPEG2_PAR_GATED_CLK:
Olivier Greniedd316c62011-01-04 04:28:59 -03001544 outreg = (1 << 10); /* 0x0400 */
1545 break;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001546 case OUTMODE_MPEG2_PAR_CONT_CLK:
Olivier Greniedd316c62011-01-04 04:28:59 -03001547 outreg = (1 << 10) | (1 << 6); /* 0x0440 */
1548 break;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001549 case OUTMODE_MPEG2_SERIAL:
Olivier Greniedd316c62011-01-04 04:28:59 -03001550 outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */
1551 break;
1552 case OUTMODE_DIVERSITY:
1553 outreg = (1 << 10) | (4 << 6); /* 0x0500 */
1554 break;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001555 case OUTMODE_MPEG2_FIFO:
Olivier Greniedd316c62011-01-04 04:28:59 -03001556 outreg = (1 << 10) | (5 << 6);
1557 break;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001558 case OUTMODE_HIGH_Z:
Olivier Greniedd316c62011-01-04 04:28:59 -03001559 outreg = 0;
1560 break;
1561 default:
1562 dprintk("Unhandled output_mode passed to be set for demod %p", &state->fe[0]);
1563 return -EINVAL;
1564 }
1565
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001566 dib9000_write_word(state, 1795, outreg);
Olivier Greniedd316c62011-01-04 04:28:59 -03001567
1568 switch (mode) {
1569 case OUTMODE_MPEG2_PAR_GATED_CLK:
1570 case OUTMODE_MPEG2_PAR_CONT_CLK:
1571 case OUTMODE_MPEG2_SERIAL:
1572 case OUTMODE_MPEG2_FIFO:
1573 smo_mode = (dib9000_read_word(state, 295) & 0x0010) | (1 << 1);
1574 if (state->chip.d9.cfg.output_mpeg2_in_188_bytes)
1575 smo_mode |= (1 << 5);
1576 dib9000_write_word(state, 295, smo_mode);
1577 break;
1578 }
1579
1580 outreg = to_fw_output_mode(mode);
1581 return dib9000_mbx_send(state, OUT_MSG_SET_OUTPUT_MODE, &outreg, 1);
1582}
1583
1584static int dib9000_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
1585{
1586 struct dib9000_state *state = i2c_get_adapdata(i2c_adap);
1587 u16 i, len, t, index_msg;
1588
1589 for (index_msg = 0; index_msg < num; index_msg++) {
1590 if (msg[index_msg].flags & I2C_M_RD) { /* read */
1591 len = msg[index_msg].len;
1592 if (len > 16)
1593 len = 16;
1594
1595 if (dib9000_read_word(state, 790) != 0)
1596 dprintk("TunerITF: read busy");
1597
1598 dib9000_write_word(state, 784, (u16) (msg[index_msg].addr));
1599 dib9000_write_word(state, 787, (len / 2) - 1);
1600 dib9000_write_word(state, 786, 1); /* start read */
1601
1602 i = 1000;
1603 while (dib9000_read_word(state, 790) != (len / 2) && i)
1604 i--;
1605
1606 if (i == 0)
1607 dprintk("TunerITF: read failed");
1608
1609 for (i = 0; i < len; i += 2) {
1610 t = dib9000_read_word(state, 785);
1611 msg[index_msg].buf[i] = (t >> 8) & 0xff;
1612 msg[index_msg].buf[i + 1] = (t) & 0xff;
1613 }
1614 if (dib9000_read_word(state, 790) != 0)
1615 dprintk("TunerITF: read more data than expected");
1616 } else {
1617 i = 1000;
1618 while (dib9000_read_word(state, 789) && i)
1619 i--;
1620 if (i == 0)
1621 dprintk("TunerITF: write busy");
1622
1623 len = msg[index_msg].len;
1624 if (len > 16)
1625 len = 16;
1626
1627 for (i = 0; i < len; i += 2)
1628 dib9000_write_word(state, 785, (msg[index_msg].buf[i] << 8) | msg[index_msg].buf[i + 1]);
1629 dib9000_write_word(state, 784, (u16) msg[index_msg].addr);
1630 dib9000_write_word(state, 787, (len / 2) - 1);
1631 dib9000_write_word(state, 786, 0); /* start write */
1632
1633 i = 1000;
1634 while (dib9000_read_word(state, 791) > 0 && i)
1635 i--;
1636 if (i == 0)
1637 dprintk("TunerITF: write failed");
1638 }
1639 }
1640 return num;
1641}
1642
1643int dib9000_fw_set_component_bus_speed(struct dvb_frontend *fe, u16 speed)
1644{
1645 struct dib9000_state *state = fe->demodulator_priv;
1646
1647 state->component_bus_speed = speed;
1648 return 0;
1649}
1650EXPORT_SYMBOL(dib9000_fw_set_component_bus_speed);
1651
1652static int dib9000_fw_component_bus_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
1653{
1654 struct dib9000_state *state = i2c_get_adapdata(i2c_adap);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001655 u8 type = 0; /* I2C */
Olivier Greniedd316c62011-01-04 04:28:59 -03001656 u8 port = DIBX000_I2C_INTERFACE_GPIO_3_4;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001657 u16 scl = state->component_bus_speed; /* SCL frequency */
Olivier Greniedd316c62011-01-04 04:28:59 -03001658 struct dib9000_fe_memory_map *m = &state->platform.risc.fe_mm[FE_MM_RW_COMPONENT_ACCESS_BUFFER];
1659 u8 p[13] = { 0 };
1660
1661 p[0] = type;
1662 p[1] = port;
1663 p[2] = msg[0].addr << 1;
1664
1665 p[3] = (u8) scl & 0xff; /* scl */
1666 p[4] = (u8) (scl >> 8);
1667
Olivier Greniedd316c62011-01-04 04:28:59 -03001668 p[7] = 0;
1669 p[8] = 0;
1670
1671 p[9] = (u8) (msg[0].len);
1672 p[10] = (u8) (msg[0].len >> 8);
1673 if ((num > 1) && (msg[1].flags & I2C_M_RD)) {
1674 p[11] = (u8) (msg[1].len);
1675 p[12] = (u8) (msg[1].len >> 8);
1676 } else {
1677 p[11] = 0;
1678 p[12] = 0;
1679 }
1680
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -03001681 if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) {
1682 dprintk("could not get the lock");
1683 return 0;
1684 }
Olivier Greniedd316c62011-01-04 04:28:59 -03001685
1686 dib9000_risc_mem_write(state, FE_MM_W_COMPONENT_ACCESS, p);
1687
1688 { /* write-part */
1689 dib9000_risc_mem_setup_cmd(state, m->addr, msg[0].len, 0);
1690 dib9000_risc_mem_write_chunks(state, msg[0].buf, msg[0].len);
1691 }
1692
1693 /* do the transaction */
1694 if (dib9000_fw_memmbx_sync(state, FE_SYNC_COMPONENT_ACCESS) < 0) {
1695 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
1696 return 0;
1697 }
1698
1699 /* read back any possible result */
1700 if ((num > 1) && (msg[1].flags & I2C_M_RD))
1701 dib9000_risc_mem_read(state, FE_MM_RW_COMPONENT_ACCESS_BUFFER, msg[1].buf, msg[1].len);
1702
1703 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
1704
1705 return num;
1706}
1707
1708static u32 dib9000_i2c_func(struct i2c_adapter *adapter)
1709{
1710 return I2C_FUNC_I2C;
1711}
1712
1713static struct i2c_algorithm dib9000_tuner_algo = {
1714 .master_xfer = dib9000_tuner_xfer,
1715 .functionality = dib9000_i2c_func,
1716};
1717
1718static struct i2c_algorithm dib9000_component_bus_algo = {
1719 .master_xfer = dib9000_fw_component_bus_xfer,
1720 .functionality = dib9000_i2c_func,
1721};
1722
1723struct i2c_adapter *dib9000_get_tuner_interface(struct dvb_frontend *fe)
1724{
1725 struct dib9000_state *st = fe->demodulator_priv;
1726 return &st->tuner_adap;
1727}
Olivier Greniedd316c62011-01-04 04:28:59 -03001728EXPORT_SYMBOL(dib9000_get_tuner_interface);
1729
1730struct i2c_adapter *dib9000_get_component_bus_interface(struct dvb_frontend *fe)
1731{
1732 struct dib9000_state *st = fe->demodulator_priv;
1733 return &st->component_bus;
1734}
Olivier Greniedd316c62011-01-04 04:28:59 -03001735EXPORT_SYMBOL(dib9000_get_component_bus_interface);
1736
1737struct i2c_adapter *dib9000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
1738{
1739 struct dib9000_state *st = fe->demodulator_priv;
1740 return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
1741}
Olivier Greniedd316c62011-01-04 04:28:59 -03001742EXPORT_SYMBOL(dib9000_get_i2c_master);
1743
1744int dib9000_set_i2c_adapter(struct dvb_frontend *fe, struct i2c_adapter *i2c)
1745{
1746 struct dib9000_state *st = fe->demodulator_priv;
1747
1748 st->i2c.i2c_adap = i2c;
1749 return 0;
1750}
Olivier Greniedd316c62011-01-04 04:28:59 -03001751EXPORT_SYMBOL(dib9000_set_i2c_adapter);
1752
1753static int dib9000_cfg_gpio(struct dib9000_state *st, u8 num, u8 dir, u8 val)
1754{
1755 st->gpio_dir = dib9000_read_word(st, 773);
1756 st->gpio_dir &= ~(1 << num); /* reset the direction bit */
1757 st->gpio_dir |= (dir & 0x1) << num; /* set the new direction */
1758 dib9000_write_word(st, 773, st->gpio_dir);
1759
1760 st->gpio_val = dib9000_read_word(st, 774);
1761 st->gpio_val &= ~(1 << num); /* reset the direction bit */
1762 st->gpio_val |= (val & 0x01) << num; /* set the new value */
1763 dib9000_write_word(st, 774, st->gpio_val);
1764
1765 dprintk("gpio dir: %04x: gpio val: %04x", st->gpio_dir, st->gpio_val);
1766
1767 return 0;
1768}
1769
1770int dib9000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
1771{
1772 struct dib9000_state *state = fe->demodulator_priv;
1773 return dib9000_cfg_gpio(state, num, dir, val);
1774}
Olivier Greniedd316c62011-01-04 04:28:59 -03001775EXPORT_SYMBOL(dib9000_set_gpio);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001776
Olivier Greniedd316c62011-01-04 04:28:59 -03001777int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
1778{
1779 struct dib9000_state *state = fe->demodulator_priv;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001780 u16 val;
1781 int ret;
1782
1783 if ((state->pid_ctrl_index != -2) && (state->pid_ctrl_index < 9)) {
1784 /* postpone the pid filtering cmd */
1785 dprintk("pid filter cmd postpone");
1786 state->pid_ctrl_index++;
1787 state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER_CTRL;
1788 state->pid_ctrl[state->pid_ctrl_index].onoff = onoff;
1789 return 0;
1790 }
1791
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -03001792 if (DibAcquireLock(&state->demod_lock) < 0) {
1793 dprintk("could not get the lock");
1794 return -EINTR;
1795 }
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001796
1797 val = dib9000_read_word(state, 294 + 1) & 0xffef;
Olivier Greniedd316c62011-01-04 04:28:59 -03001798 val |= (onoff & 0x1) << 4;
1799
1800 dprintk("PID filter enabled %d", onoff);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001801 ret = dib9000_write_word(state, 294 + 1, val);
1802 DibReleaseLock(&state->demod_lock);
1803 return ret;
1804
Olivier Greniedd316c62011-01-04 04:28:59 -03001805}
Olivier Greniedd316c62011-01-04 04:28:59 -03001806EXPORT_SYMBOL(dib9000_fw_pid_filter_ctrl);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001807
Olivier Greniedd316c62011-01-04 04:28:59 -03001808int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
1809{
1810 struct dib9000_state *state = fe->demodulator_priv;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001811 int ret;
1812
1813 if (state->pid_ctrl_index != -2) {
1814 /* postpone the pid filtering cmd */
1815 dprintk("pid filter postpone");
1816 if (state->pid_ctrl_index < 9) {
1817 state->pid_ctrl_index++;
1818 state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER;
1819 state->pid_ctrl[state->pid_ctrl_index].id = id;
1820 state->pid_ctrl[state->pid_ctrl_index].pid = pid;
1821 state->pid_ctrl[state->pid_ctrl_index].onoff = onoff;
1822 } else
1823 dprintk("can not add any more pid ctrl cmd");
1824 return 0;
1825 }
1826
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -03001827 if (DibAcquireLock(&state->demod_lock) < 0) {
1828 dprintk("could not get the lock");
1829 return -EINTR;
1830 }
Olivier Greniedd316c62011-01-04 04:28:59 -03001831 dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001832 ret = dib9000_write_word(state, 300 + 1 + id,
1833 onoff ? (1 << 13) | pid : 0);
1834 DibReleaseLock(&state->demod_lock);
1835 return ret;
Olivier Greniedd316c62011-01-04 04:28:59 -03001836}
Olivier Greniedd316c62011-01-04 04:28:59 -03001837EXPORT_SYMBOL(dib9000_fw_pid_filter);
1838
1839int dib9000_firmware_post_pll_init(struct dvb_frontend *fe)
1840{
1841 struct dib9000_state *state = fe->demodulator_priv;
1842 return dib9000_fw_init(state);
1843}
Olivier Greniedd316c62011-01-04 04:28:59 -03001844EXPORT_SYMBOL(dib9000_firmware_post_pll_init);
1845
1846static void dib9000_release(struct dvb_frontend *demod)
1847{
1848 struct dib9000_state *st = demod->demodulator_priv;
1849 u8 index_frontend;
1850
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001851 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (st->fe[index_frontend] != NULL); index_frontend++)
Olivier Greniedd316c62011-01-04 04:28:59 -03001852 dvb_frontend_detach(st->fe[index_frontend]);
1853
1854 DibFreeLock(&state->platform.risc.mbx_if_lock);
1855 DibFreeLock(&state->platform.risc.mbx_lock);
1856 DibFreeLock(&state->platform.risc.mem_lock);
1857 DibFreeLock(&state->platform.risc.mem_mbx_lock);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001858 DibFreeLock(&state->demod_lock);
Olivier Greniedd316c62011-01-04 04:28:59 -03001859 dibx000_exit_i2c_master(&st->i2c_master);
1860
1861 i2c_del_adapter(&st->tuner_adap);
1862 i2c_del_adapter(&st->component_bus);
1863 kfree(st->fe[0]);
1864 kfree(st);
1865}
1866
1867static int dib9000_wakeup(struct dvb_frontend *fe)
1868{
1869 return 0;
1870}
1871
1872static int dib9000_sleep(struct dvb_frontend *fe)
1873{
1874 struct dib9000_state *state = fe->demodulator_priv;
1875 u8 index_frontend;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001876 int ret = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03001877
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -03001878 if (DibAcquireLock(&state->demod_lock) < 0) {
1879 dprintk("could not get the lock");
1880 return -EINTR;
1881 }
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001882 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001883 ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]);
1884 if (ret < 0)
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001885 goto error;
Olivier Greniedd316c62011-01-04 04:28:59 -03001886 }
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001887 ret = dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0);
1888
1889error:
1890 DibReleaseLock(&state->demod_lock);
1891 return ret;
Olivier Greniedd316c62011-01-04 04:28:59 -03001892}
1893
1894static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
1895{
1896 tune->min_delay_ms = 1000;
1897 return 0;
1898}
1899
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -03001900static int dib9000_get_frontend(struct dvb_frontend *fe)
Olivier Greniedd316c62011-01-04 04:28:59 -03001901{
1902 struct dib9000_state *state = fe->demodulator_priv;
1903 u8 index_frontend, sub_index_frontend;
1904 fe_status_t stat;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001905 int ret = 0;
1906
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -03001907 if (state->get_frontend_internal == 0) {
1908 if (DibAcquireLock(&state->demod_lock) < 0) {
1909 dprintk("could not get the lock");
1910 return -EINTR;
1911 }
1912 }
Olivier Greniedd316c62011-01-04 04:28:59 -03001913
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001914 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001915 state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
1916 if (stat & FE_HAS_SYNC) {
1917 dprintk("TPS lock on the slave%i", index_frontend);
1918
1919 /* synchronize the cache with the other frontends */
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -03001920 state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001921 for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL);
1922 sub_index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001923 if (sub_index_frontend != index_frontend) {
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001924 state->fe[sub_index_frontend]->dtv_property_cache.modulation =
1925 state->fe[index_frontend]->dtv_property_cache.modulation;
1926 state->fe[sub_index_frontend]->dtv_property_cache.inversion =
1927 state->fe[index_frontend]->dtv_property_cache.inversion;
1928 state->fe[sub_index_frontend]->dtv_property_cache.transmission_mode =
1929 state->fe[index_frontend]->dtv_property_cache.transmission_mode;
1930 state->fe[sub_index_frontend]->dtv_property_cache.guard_interval =
1931 state->fe[index_frontend]->dtv_property_cache.guard_interval;
1932 state->fe[sub_index_frontend]->dtv_property_cache.hierarchy =
1933 state->fe[index_frontend]->dtv_property_cache.hierarchy;
1934 state->fe[sub_index_frontend]->dtv_property_cache.code_rate_HP =
1935 state->fe[index_frontend]->dtv_property_cache.code_rate_HP;
1936 state->fe[sub_index_frontend]->dtv_property_cache.code_rate_LP =
1937 state->fe[index_frontend]->dtv_property_cache.code_rate_LP;
1938 state->fe[sub_index_frontend]->dtv_property_cache.rolloff =
1939 state->fe[index_frontend]->dtv_property_cache.rolloff;
Olivier Greniedd316c62011-01-04 04:28:59 -03001940 }
1941 }
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001942 ret = 0;
1943 goto return_value;
Olivier Greniedd316c62011-01-04 04:28:59 -03001944 }
1945 }
1946
1947 /* get the channel from master chip */
Mauro Carvalho Chehab759e2362011-12-22 19:54:08 -03001948 ret = dib9000_fw_get_channel(fe);
Olivier Greniedd316c62011-01-04 04:28:59 -03001949 if (ret != 0)
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001950 goto return_value;
Olivier Greniedd316c62011-01-04 04:28:59 -03001951
1952 /* synchronize the cache with the other frontends */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001953 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03001954 state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion;
1955 state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode;
1956 state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval;
1957 state->fe[index_frontend]->dtv_property_cache.modulation = fe->dtv_property_cache.modulation;
1958 state->fe[index_frontend]->dtv_property_cache.hierarchy = fe->dtv_property_cache.hierarchy;
1959 state->fe[index_frontend]->dtv_property_cache.code_rate_HP = fe->dtv_property_cache.code_rate_HP;
1960 state->fe[index_frontend]->dtv_property_cache.code_rate_LP = fe->dtv_property_cache.code_rate_LP;
1961 state->fe[index_frontend]->dtv_property_cache.rolloff = fe->dtv_property_cache.rolloff;
1962 }
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001963 ret = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03001964
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001965return_value:
1966 if (state->get_frontend_internal == 0)
1967 DibReleaseLock(&state->demod_lock);
1968 return ret;
Olivier Greniedd316c62011-01-04 04:28:59 -03001969}
1970
1971static int dib9000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
1972{
1973 struct dib9000_state *state = fe->demodulator_priv;
1974 state->tune_state = tune_state;
1975 if (tune_state == CT_DEMOD_START)
1976 state->status = FE_STATUS_TUNE_PENDING;
1977
1978 return 0;
1979}
1980
1981static u32 dib9000_get_status(struct dvb_frontend *fe)
1982{
1983 struct dib9000_state *state = fe->demodulator_priv;
1984 return state->status;
1985}
1986
1987static int dib9000_set_channel_status(struct dvb_frontend *fe, struct dvb_frontend_parametersContext *channel_status)
1988{
1989 struct dib9000_state *state = fe->demodulator_priv;
1990
1991 memcpy(&state->channel_status, channel_status, sizeof(struct dvb_frontend_parametersContext));
1992 return 0;
1993}
1994
Mauro Carvalho Chehab9e9c5bf2011-12-22 20:12:18 -03001995static int dib9000_set_frontend(struct dvb_frontend *fe)
Olivier Greniedd316c62011-01-04 04:28:59 -03001996{
1997 struct dib9000_state *state = fe->demodulator_priv;
1998 int sleep_time, sleep_time_slave;
1999 u32 frontend_status;
2000 u8 nbr_pending, exit_condition, index_frontend, index_frontend_success;
2001 struct dvb_frontend_parametersContext channel_status;
2002
2003 /* check that the correct parameters are set */
2004 if (state->fe[0]->dtv_property_cache.frequency == 0) {
2005 dprintk("dib9000: must specify frequency ");
2006 return 0;
2007 }
2008
2009 if (state->fe[0]->dtv_property_cache.bandwidth_hz == 0) {
2010 dprintk("dib9000: must specify bandwidth ");
2011 return 0;
2012 }
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002013
2014 state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -03002015 if (DibAcquireLock(&state->demod_lock) < 0) {
2016 dprintk("could not get the lock");
2017 return 0;
2018 }
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002019
Olivier Greniedd316c62011-01-04 04:28:59 -03002020 fe->dtv_property_cache.delivery_system = SYS_DVBT;
2021
2022 /* set the master status */
Mauro Carvalho Chehab9e9c5bf2011-12-22 20:12:18 -03002023 if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO ||
2024 state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO ||
2025 state->fe[0]->dtv_property_cache.modulation == QAM_AUTO ||
2026 state->fe[0]->dtv_property_cache.code_rate_HP == FEC_AUTO) {
Olivier Greniedd316c62011-01-04 04:28:59 -03002027 /* no channel specified, autosearch the channel */
2028 state->channel_status.status = CHANNEL_STATUS_PARAMETERS_UNKNOWN;
2029 } else
2030 state->channel_status.status = CHANNEL_STATUS_PARAMETERS_SET;
2031
2032 /* set mode and status for the different frontends */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002033 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03002034 dib9000_fw_set_diversity_in(state->fe[index_frontend], 1);
2035
2036 /* synchronization of the cache */
2037 memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties));
2038
2039 state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_DVBT;
2040 dib9000_fw_set_output_mode(state->fe[index_frontend], OUTMODE_HIGH_Z);
2041
2042 dib9000_set_channel_status(state->fe[index_frontend], &state->channel_status);
2043 dib9000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
2044 }
2045
2046 /* actual tune */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002047 exit_condition = 0; /* 0: tune pending; 1: tune failed; 2:tune success */
Olivier Greniedd316c62011-01-04 04:28:59 -03002048 index_frontend_success = 0;
2049 do {
Mauro Carvalho Chehabf20b12e2011-12-22 20:42:12 -03002050 sleep_time = dib9000_fw_tune(state->fe[0]);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002051 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Mauro Carvalho Chehabf20b12e2011-12-22 20:42:12 -03002052 sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend]);
Olivier Greniedd316c62011-01-04 04:28:59 -03002053 if (sleep_time == FE_CALLBACK_TIME_NEVER)
2054 sleep_time = sleep_time_slave;
2055 else if ((sleep_time_slave != FE_CALLBACK_TIME_NEVER) && (sleep_time_slave > sleep_time))
2056 sleep_time = sleep_time_slave;
2057 }
2058 if (sleep_time != FE_CALLBACK_TIME_NEVER)
2059 msleep(sleep_time / 10);
2060 else
2061 break;
2062
2063 nbr_pending = 0;
2064 exit_condition = 0;
2065 index_frontend_success = 0;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002066 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03002067 frontend_status = -dib9000_get_status(state->fe[index_frontend]);
2068 if (frontend_status > -FE_STATUS_TUNE_PENDING) {
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002069 exit_condition = 2; /* tune success */
Olivier Greniedd316c62011-01-04 04:28:59 -03002070 index_frontend_success = index_frontend;
2071 break;
2072 }
2073 if (frontend_status == -FE_STATUS_TUNE_PENDING)
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002074 nbr_pending++; /* some frontends are still tuning */
Olivier Greniedd316c62011-01-04 04:28:59 -03002075 }
2076 if ((exit_condition != 2) && (nbr_pending == 0))
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002077 exit_condition = 1; /* if all tune are done and no success, exit: tune failed */
Olivier Greniedd316c62011-01-04 04:28:59 -03002078
2079 } while (exit_condition == 0);
2080
2081 /* check the tune result */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002082 if (exit_condition == 1) { /* tune failed */
Olivier Greniedd316c62011-01-04 04:28:59 -03002083 dprintk("tune failed");
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002084 DibReleaseLock(&state->demod_lock);
2085 /* tune failed; put all the pid filtering cmd to junk */
2086 state->pid_ctrl_index = -1;
Olivier Greniedd316c62011-01-04 04:28:59 -03002087 return 0;
2088 }
2089
2090 dprintk("tune success on frontend%i", index_frontend_success);
2091
2092 /* synchronize all the channel cache */
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002093 state->get_frontend_internal = 1;
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -03002094 dib9000_get_frontend(state->fe[0]);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002095 state->get_frontend_internal = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03002096
2097 /* retune the other frontends with the found channel */
2098 channel_status.status = CHANNEL_STATUS_PARAMETERS_SET;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002099 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03002100 /* only retune the frontends which was not tuned success */
2101 if (index_frontend != index_frontend_success) {
2102 dib9000_set_channel_status(state->fe[index_frontend], &channel_status);
2103 dib9000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
2104 }
2105 }
2106 do {
2107 sleep_time = FE_CALLBACK_TIME_NEVER;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002108 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03002109 if (index_frontend != index_frontend_success) {
Mauro Carvalho Chehabf20b12e2011-12-22 20:42:12 -03002110 sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend]);
Olivier Greniedd316c62011-01-04 04:28:59 -03002111 if (sleep_time == FE_CALLBACK_TIME_NEVER)
2112 sleep_time = sleep_time_slave;
2113 else if ((sleep_time_slave != FE_CALLBACK_TIME_NEVER) && (sleep_time_slave > sleep_time))
2114 sleep_time = sleep_time_slave;
2115 }
2116 }
2117 if (sleep_time != FE_CALLBACK_TIME_NEVER)
2118 msleep(sleep_time / 10);
2119 else
2120 break;
2121
2122 nbr_pending = 0;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002123 for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03002124 if (index_frontend != index_frontend_success) {
2125 frontend_status = -dib9000_get_status(state->fe[index_frontend]);
2126 if ((index_frontend != index_frontend_success) && (frontend_status == -FE_STATUS_TUNE_PENDING))
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002127 nbr_pending++; /* some frontends are still tuning */
Olivier Greniedd316c62011-01-04 04:28:59 -03002128 }
2129 }
2130 } while (nbr_pending != 0);
2131
2132 /* set the output mode */
2133 dib9000_fw_set_output_mode(state->fe[0], state->chip.d9.cfg.output_mode);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002134 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
Olivier Greniedd316c62011-01-04 04:28:59 -03002135 dib9000_fw_set_output_mode(state->fe[index_frontend], OUTMODE_DIVERSITY);
2136
2137 /* turn off the diversity for the last frontend */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002138 dib9000_fw_set_diversity_in(state->fe[index_frontend - 1], 0);
Olivier Greniedd316c62011-01-04 04:28:59 -03002139
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002140 DibReleaseLock(&state->demod_lock);
2141 if (state->pid_ctrl_index >= 0) {
2142 u8 index_pid_filter_cmd;
2143 u8 pid_ctrl_index = state->pid_ctrl_index;
2144
2145 state->pid_ctrl_index = -2;
2146 for (index_pid_filter_cmd = 0;
2147 index_pid_filter_cmd <= pid_ctrl_index;
2148 index_pid_filter_cmd++) {
2149 if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER_CTRL)
2150 dib9000_fw_pid_filter_ctrl(state->fe[0],
2151 state->pid_ctrl[index_pid_filter_cmd].onoff);
2152 else if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER)
2153 dib9000_fw_pid_filter(state->fe[0],
2154 state->pid_ctrl[index_pid_filter_cmd].id,
2155 state->pid_ctrl[index_pid_filter_cmd].pid,
2156 state->pid_ctrl[index_pid_filter_cmd].onoff);
2157 }
2158 }
2159 /* do not postpone any more the pid filtering */
2160 state->pid_ctrl_index = -2;
2161
Olivier Greniedd316c62011-01-04 04:28:59 -03002162 return 0;
2163}
2164
2165static u16 dib9000_read_lock(struct dvb_frontend *fe)
2166{
2167 struct dib9000_state *state = fe->demodulator_priv;
2168
2169 return dib9000_read_word(state, 535);
2170}
2171
2172static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
2173{
2174 struct dib9000_state *state = fe->demodulator_priv;
2175 u8 index_frontend;
2176 u16 lock = 0, lock_slave = 0;
2177
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -03002178 if (DibAcquireLock(&state->demod_lock) < 0) {
2179 dprintk("could not get the lock");
2180 return -EINTR;
2181 }
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002182 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
Olivier Greniedd316c62011-01-04 04:28:59 -03002183 lock_slave |= dib9000_read_lock(state->fe[index_frontend]);
2184
2185 lock = dib9000_read_word(state, 535);
2186
2187 *stat = 0;
2188
2189 if ((lock & 0x8000) || (lock_slave & 0x8000))
2190 *stat |= FE_HAS_SIGNAL;
2191 if ((lock & 0x3000) || (lock_slave & 0x3000))
2192 *stat |= FE_HAS_CARRIER;
2193 if ((lock & 0x0100) || (lock_slave & 0x0100))
2194 *stat |= FE_HAS_VITERBI;
2195 if (((lock & 0x0038) == 0x38) || ((lock_slave & 0x0038) == 0x38))
2196 *stat |= FE_HAS_SYNC;
2197 if ((lock & 0x0008) || (lock_slave & 0x0008))
2198 *stat |= FE_HAS_LOCK;
2199
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002200 DibReleaseLock(&state->demod_lock);
2201
Olivier Greniedd316c62011-01-04 04:28:59 -03002202 return 0;
2203}
2204
2205static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
2206{
2207 struct dib9000_state *state = fe->demodulator_priv;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002208 u16 *c;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002209 int ret = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03002210
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -03002211 if (DibAcquireLock(&state->demod_lock) < 0) {
2212 dprintk("could not get the lock");
2213 return -EINTR;
2214 }
2215 if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) {
2216 dprintk("could not get the lock");
2217 ret = -EINTR;
2218 goto error;
2219 }
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002220 if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
Dan Carpenter2f4cf2c2011-09-29 02:10:06 -03002221 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002222 ret = -EIO;
2223 goto error;
2224 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002225 dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR,
2226 state->i2c_read_buffer, 16 * 2);
Olivier Greniedd316c62011-01-04 04:28:59 -03002227 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
2228
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002229 c = (u16 *)state->i2c_read_buffer;
2230
Olivier Greniedd316c62011-01-04 04:28:59 -03002231 *ber = c[10] << 16 | c[11];
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002232
2233error:
2234 DibReleaseLock(&state->demod_lock);
2235 return ret;
Olivier Greniedd316c62011-01-04 04:28:59 -03002236}
2237
2238static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
2239{
2240 struct dib9000_state *state = fe->demodulator_priv;
2241 u8 index_frontend;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002242 u16 *c = (u16 *)state->i2c_read_buffer;
Olivier Greniedd316c62011-01-04 04:28:59 -03002243 u16 val;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002244 int ret = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03002245
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -03002246 if (DibAcquireLock(&state->demod_lock) < 0) {
2247 dprintk("could not get the lock");
2248 return -EINTR;
2249 }
Olivier Greniedd316c62011-01-04 04:28:59 -03002250 *strength = 0;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002251 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
Olivier Greniedd316c62011-01-04 04:28:59 -03002252 state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val);
2253 if (val > 65535 - *strength)
2254 *strength = 65535;
2255 else
2256 *strength += val;
2257 }
2258
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -03002259 if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) {
2260 dprintk("could not get the lock");
2261 ret = -EINTR;
2262 goto error;
2263 }
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002264 if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
Alexey Khoroshilov9bb24a72012-03-06 17:08:16 -03002265 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002266 ret = -EIO;
2267 goto error;
2268 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002269 dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
Olivier Greniedd316c62011-01-04 04:28:59 -03002270 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
2271
2272 val = 65535 - c[4];
2273 if (val > 65535 - *strength)
2274 *strength = 65535;
2275 else
2276 *strength += val;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002277
2278error:
2279 DibReleaseLock(&state->demod_lock);
2280 return ret;
Olivier Greniedd316c62011-01-04 04:28:59 -03002281}
2282
2283static u32 dib9000_get_snr(struct dvb_frontend *fe)
2284{
2285 struct dib9000_state *state = fe->demodulator_priv;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002286 u16 *c = (u16 *)state->i2c_read_buffer;
Olivier Greniedd316c62011-01-04 04:28:59 -03002287 u32 n, s, exp;
2288 u16 val;
2289
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -03002290 if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) {
2291 dprintk("could not get the lock");
2292 return 0;
2293 }
Alexey Khoroshilov9bb24a72012-03-06 17:08:16 -03002294 if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
2295 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -03002296 return 0;
Alexey Khoroshilov9bb24a72012-03-06 17:08:16 -03002297 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002298 dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
Olivier Greniedd316c62011-01-04 04:28:59 -03002299 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
2300
2301 val = c[7];
2302 n = (val >> 4) & 0xff;
2303 exp = ((val & 0xf) << 2);
2304 val = c[8];
2305 exp += ((val >> 14) & 0x3);
2306 if ((exp & 0x20) != 0)
2307 exp -= 0x40;
2308 n <<= exp + 16;
2309
2310 s = (val >> 6) & 0xFF;
2311 exp = (val & 0x3F);
2312 if ((exp & 0x20) != 0)
2313 exp -= 0x40;
2314 s <<= exp + 16;
2315
2316 if (n > 0) {
2317 u32 t = (s / n) << 16;
2318 return t + ((s << 16) - n * t) / n;
2319 }
2320 return 0xffffffff;
2321}
2322
2323static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr)
2324{
2325 struct dib9000_state *state = fe->demodulator_priv;
2326 u8 index_frontend;
2327 u32 snr_master;
2328
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -03002329 if (DibAcquireLock(&state->demod_lock) < 0) {
2330 dprintk("could not get the lock");
2331 return -EINTR;
2332 }
Olivier Greniedd316c62011-01-04 04:28:59 -03002333 snr_master = dib9000_get_snr(fe);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002334 for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
Olivier Greniedd316c62011-01-04 04:28:59 -03002335 snr_master += dib9000_get_snr(state->fe[index_frontend]);
2336
2337 if ((snr_master >> 16) != 0) {
2338 snr_master = 10 * intlog10(snr_master >> 16);
2339 *snr = snr_master / ((1 << 24) / 10);
2340 } else
2341 *snr = 0;
2342
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002343 DibReleaseLock(&state->demod_lock);
2344
Olivier Greniedd316c62011-01-04 04:28:59 -03002345 return 0;
2346}
2347
2348static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
2349{
2350 struct dib9000_state *state = fe->demodulator_priv;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002351 u16 *c = (u16 *)state->i2c_read_buffer;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002352 int ret = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03002353
Alexey Khoroshilovf3033ae2012-03-06 17:08:29 -03002354 if (DibAcquireLock(&state->demod_lock) < 0) {
2355 dprintk("could not get the lock");
2356 return -EINTR;
2357 }
2358 if (DibAcquireLock(&state->platform.risc.mem_mbx_lock) < 0) {
2359 dprintk("could not get the lock");
2360 ret = -EINTR;
2361 goto error;
2362 }
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002363 if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
Alexey Khoroshilov9bb24a72012-03-06 17:08:16 -03002364 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002365 ret = -EIO;
2366 goto error;
2367 }
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002368 dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
Olivier Greniedd316c62011-01-04 04:28:59 -03002369 DibReleaseLock(&state->platform.risc.mem_mbx_lock);
2370
2371 *unc = c[12];
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002372
2373error:
2374 DibReleaseLock(&state->demod_lock);
2375 return ret;
Olivier Greniedd316c62011-01-04 04:28:59 -03002376}
2377
2378int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr)
2379{
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002380 int k = 0, ret = 0;
Olivier Greniedd316c62011-01-04 04:28:59 -03002381 u8 new_addr = 0;
2382 struct i2c_device client = {.i2c_adap = i2c };
2383
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002384 client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
2385 if (!client.i2c_write_buffer) {
2386 dprintk("%s: not enough memory", __func__);
2387 return -ENOMEM;
2388 }
2389 client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
2390 if (!client.i2c_read_buffer) {
2391 dprintk("%s: not enough memory", __func__);
2392 ret = -ENOMEM;
2393 goto error_memory;
2394 }
2395
Olivier Greniedd316c62011-01-04 04:28:59 -03002396 client.i2c_addr = default_addr + 16;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002397 dib9000_i2c_write16(&client, 1796, 0x0);
Olivier Greniedd316c62011-01-04 04:28:59 -03002398
2399 for (k = no_of_demods - 1; k >= 0; k--) {
2400 /* designated i2c address */
2401 new_addr = first_addr + (k << 1);
2402 client.i2c_addr = default_addr;
2403
2404 dib9000_i2c_write16(&client, 1817, 3);
2405 dib9000_i2c_write16(&client, 1796, 0);
2406 dib9000_i2c_write16(&client, 1227, 1);
2407 dib9000_i2c_write16(&client, 1227, 0);
2408
2409 client.i2c_addr = new_addr;
2410 dib9000_i2c_write16(&client, 1817, 3);
2411 dib9000_i2c_write16(&client, 1796, 0);
2412 dib9000_i2c_write16(&client, 1227, 1);
2413 dib9000_i2c_write16(&client, 1227, 0);
2414
2415 if (dib9000_identify(&client) == 0) {
2416 client.i2c_addr = default_addr;
2417 if (dib9000_identify(&client) == 0) {
2418 dprintk("DiB9000 #%d: not identified", k);
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002419 ret = -EIO;
2420 goto error;
Olivier Greniedd316c62011-01-04 04:28:59 -03002421 }
2422 }
2423
2424 dib9000_i2c_write16(&client, 1795, (1 << 10) | (4 << 6));
2425 dib9000_i2c_write16(&client, 1794, (new_addr << 2) | 2);
2426
2427 dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
2428 }
2429
2430 for (k = 0; k < no_of_demods; k++) {
2431 new_addr = first_addr | (k << 1);
2432 client.i2c_addr = new_addr;
2433
2434 dib9000_i2c_write16(&client, 1794, (new_addr << 2));
2435 dib9000_i2c_write16(&client, 1795, 0);
2436 }
2437
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002438error:
2439 kfree(client.i2c_read_buffer);
2440error_memory:
2441 kfree(client.i2c_write_buffer);
2442
2443 return ret;
Olivier Greniedd316c62011-01-04 04:28:59 -03002444}
Olivier Greniedd316c62011-01-04 04:28:59 -03002445EXPORT_SYMBOL(dib9000_i2c_enumeration);
2446
2447int dib9000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
2448{
2449 struct dib9000_state *state = fe->demodulator_priv;
2450 u8 index_frontend = 1;
2451
2452 while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
2453 index_frontend++;
2454 if (index_frontend < MAX_NUMBER_OF_FRONTENDS) {
2455 dprintk("set slave fe %p to index %i", fe_slave, index_frontend);
2456 state->fe[index_frontend] = fe_slave;
2457 return 0;
2458 }
2459
2460 dprintk("too many slave frontend");
2461 return -ENOMEM;
2462}
2463EXPORT_SYMBOL(dib9000_set_slave_frontend);
2464
2465int dib9000_remove_slave_frontend(struct dvb_frontend *fe)
2466{
2467 struct dib9000_state *state = fe->demodulator_priv;
2468 u8 index_frontend = 1;
2469
2470 while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
2471 index_frontend++;
2472 if (index_frontend != 1) {
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002473 dprintk("remove slave fe %p (index %i)", state->fe[index_frontend - 1], index_frontend - 1);
Olivier Greniedd316c62011-01-04 04:28:59 -03002474 state->fe[index_frontend] = NULL;
2475 return 0;
2476 }
2477
2478 dprintk("no frontend to be removed");
2479 return -ENODEV;
2480}
2481EXPORT_SYMBOL(dib9000_remove_slave_frontend);
2482
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002483struct dvb_frontend *dib9000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
Olivier Greniedd316c62011-01-04 04:28:59 -03002484{
2485 struct dib9000_state *state = fe->demodulator_priv;
2486
2487 if (slave_index >= MAX_NUMBER_OF_FRONTENDS)
2488 return NULL;
2489 return state->fe[slave_index];
2490}
2491EXPORT_SYMBOL(dib9000_get_slave_frontend);
2492
2493static struct dvb_frontend_ops dib9000_ops;
2494struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, const struct dib9000_config *cfg)
2495{
2496 struct dvb_frontend *fe;
2497 struct dib9000_state *st;
2498 st = kzalloc(sizeof(struct dib9000_state), GFP_KERNEL);
2499 if (st == NULL)
2500 return NULL;
2501 fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL);
Jesper Juhl451a51b2011-04-07 16:34:30 -03002502 if (fe == NULL) {
2503 kfree(st);
Olivier Greniedd316c62011-01-04 04:28:59 -03002504 return NULL;
Jesper Juhl451a51b2011-04-07 16:34:30 -03002505 }
Olivier Greniedd316c62011-01-04 04:28:59 -03002506
2507 memcpy(&st->chip.d9.cfg, cfg, sizeof(struct dib9000_config));
2508 st->i2c.i2c_adap = i2c_adap;
2509 st->i2c.i2c_addr = i2c_addr;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03002510 st->i2c.i2c_write_buffer = st->i2c_write_buffer;
2511 st->i2c.i2c_read_buffer = st->i2c_read_buffer;
Olivier Greniedd316c62011-01-04 04:28:59 -03002512
2513 st->gpio_dir = DIB9000_GPIO_DEFAULT_DIRECTIONS;
2514 st->gpio_val = DIB9000_GPIO_DEFAULT_VALUES;
2515 st->gpio_pwm_pos = DIB9000_GPIO_DEFAULT_PWM_POS;
2516
2517 DibInitLock(&st->platform.risc.mbx_if_lock);
2518 DibInitLock(&st->platform.risc.mbx_lock);
2519 DibInitLock(&st->platform.risc.mem_lock);
2520 DibInitLock(&st->platform.risc.mem_mbx_lock);
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002521 DibInitLock(&st->demod_lock);
2522 st->get_frontend_internal = 0;
2523
2524 st->pid_ctrl_index = -2;
Olivier Greniedd316c62011-01-04 04:28:59 -03002525
2526 st->fe[0] = fe;
2527 fe->demodulator_priv = st;
2528 memcpy(&st->fe[0]->ops, &dib9000_ops, sizeof(struct dvb_frontend_ops));
2529
2530 /* Ensure the output mode remains at the previous default if it's
2531 * not specifically set by the caller.
2532 */
2533 if ((st->chip.d9.cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (st->chip.d9.cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
2534 st->chip.d9.cfg.output_mode = OUTMODE_MPEG2_FIFO;
2535
2536 if (dib9000_identify(&st->i2c) == 0)
2537 goto error;
2538
2539 dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c.i2c_adap, st->i2c.i2c_addr);
2540
2541 st->tuner_adap.dev.parent = i2c_adap->dev.parent;
2542 strncpy(st->tuner_adap.name, "DIB9000_FW TUNER ACCESS", sizeof(st->tuner_adap.name));
2543 st->tuner_adap.algo = &dib9000_tuner_algo;
2544 st->tuner_adap.algo_data = NULL;
2545 i2c_set_adapdata(&st->tuner_adap, st);
2546 if (i2c_add_adapter(&st->tuner_adap) < 0)
2547 goto error;
2548
2549 st->component_bus.dev.parent = i2c_adap->dev.parent;
2550 strncpy(st->component_bus.name, "DIB9000_FW COMPONENT BUS ACCESS", sizeof(st->component_bus.name));
2551 st->component_bus.algo = &dib9000_component_bus_algo;
2552 st->component_bus.algo_data = NULL;
2553 st->component_bus_speed = 340;
2554 i2c_set_adapdata(&st->component_bus, st);
2555 if (i2c_add_adapter(&st->component_bus) < 0)
2556 goto component_bus_add_error;
2557
2558 dib9000_fw_reset(fe);
2559
2560 return fe;
2561
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002562component_bus_add_error:
Olivier Greniedd316c62011-01-04 04:28:59 -03002563 i2c_del_adapter(&st->tuner_adap);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002564error:
Olivier Greniedd316c62011-01-04 04:28:59 -03002565 kfree(st);
2566 return NULL;
2567}
Olivier Greniedd316c62011-01-04 04:28:59 -03002568EXPORT_SYMBOL(dib9000_attach);
2569
2570static struct dvb_frontend_ops dib9000_ops = {
Mauro Carvalho Chehab9e9c5bf2011-12-22 20:12:18 -03002571 .delsys = { SYS_DVBT },
Olivier Greniedd316c62011-01-04 04:28:59 -03002572 .info = {
2573 .name = "DiBcom 9000",
Olivier Greniedd316c62011-01-04 04:28:59 -03002574 .frequency_min = 44250000,
2575 .frequency_max = 867250000,
2576 .frequency_stepsize = 62500,
2577 .caps = FE_CAN_INVERSION_AUTO |
2578 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
2579 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
2580 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
2581 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
2582 },
2583
2584 .release = dib9000_release,
2585
2586 .init = dib9000_wakeup,
2587 .sleep = dib9000_sleep,
2588
Mauro Carvalho Chehab9e9c5bf2011-12-22 20:12:18 -03002589 .set_frontend = dib9000_set_frontend,
Olivier Greniedd316c62011-01-04 04:28:59 -03002590 .get_tune_settings = dib9000_fe_get_tune_settings,
Mauro Carvalho Chehab9e9c5bf2011-12-22 20:12:18 -03002591 .get_frontend = dib9000_get_frontend,
Olivier Greniedd316c62011-01-04 04:28:59 -03002592
2593 .read_status = dib9000_read_status,
2594 .read_ber = dib9000_read_ber,
2595 .read_signal_strength = dib9000_read_signal_strength,
2596 .read_snr = dib9000_read_snr,
2597 .read_ucblocks = dib9000_read_unc_blocks,
2598};
2599
2600MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
2601MODULE_AUTHOR("Olivier Grenie <ogrenie@dibcom.fr>");
2602MODULE_DESCRIPTION("Driver for the DiBcom 9000 COFDM demodulator");
2603MODULE_LICENSE("GPL");