11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher * Driver for DiBcom DiB3000MC/P-demodulator.
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher * Copyright (C) 2004-7 DiBcom (http://www.dibcom.fr/)
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
7b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher * This code is partially based on the previous dib3000mc.c .
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher * This program is free software; you can redistribute it and/or
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	modify it under the terms of the GNU General Public License as
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	published by the Free Software Foundation, version 2.
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
13b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
155a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
16b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher#include <linux/i2c.h>
17b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
18b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher#include "dvb_frontend.h"
19b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
20b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher#include "dib3000mc.h"
21b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int debug;
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debug, int, 0644);
24b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick BoettcherMODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
268f6956c7f9fa72c502bde47df4122bd32d0b86d5Matt Doranstatic int buggy_sfn_workaround;
278f6956c7f9fa72c502bde47df4122bd32d0b86d5Matt Doranmodule_param(buggy_sfn_workaround, int, 0644);
288d99996b0942ff566c62602d83ac2c13521bbe40Patrick BoettcherMODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)");
298f6956c7f9fa72c502bde47df4122bd32d0b86d5Matt Doran
30b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); printk("\n"); } } while (0)
31b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
32b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstruct dib3000mc_state {
33b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dvb_frontend demod;
34b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dib3000mc_config *cfg;
35b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
36b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u8 i2c_addr;
37b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct i2c_adapter *i2c_adap;
38b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
39b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dibx000_i2c_master i2c_master;
40b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
4101b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher	u32 timf;
4201b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher
4388ab898f6639ca5a14943a882fbd141afc81fe90Mauro Carvalho Chehab	u32 current_bandwidth;
44b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
45b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u16 dev_id;
468f6956c7f9fa72c502bde47df4122bd32d0b86d5Matt Doran
478f6956c7f9fa72c502bde47df4122bd32d0b86d5Matt Doran	u8 sfn_workaround_active :1;
48b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher};
49b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
50b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstatic u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg)
51b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher{
52b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff };
53b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u8 rb[2];
54b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct i2c_msg msg[2] = {
55b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		{ .addr = state->i2c_addr >> 1, .flags = 0,        .buf = wb, .len = 2 },
56b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		{ .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
57b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	};
58b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
59b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
60b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dprintk("i2c read error on %d\n",reg);
61b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
62b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	return (rb[0] << 8) | rb[1];
63b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher}
64b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
65b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstatic int dib3000mc_write_word(struct dib3000mc_state *state, u16 reg, u16 val)
66b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher{
67b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u8 b[4] = {
68b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		(reg >> 8) & 0xff, reg & 0xff,
69b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		(val >> 8) & 0xff, val & 0xff,
70b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	};
71b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct i2c_msg msg = {
72b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		.addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
73b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	};
74b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
75b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher}
76b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
77b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstatic int dib3000mc_identify(struct dib3000mc_state *state)
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
79b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u16 value;
80b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	if ((value = dib3000mc_read_word(state, 1025)) != 0x01b3) {
81b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dprintk("-E-  DiB3000MC/P: wrong Vendor ID (read=0x%x)\n",value);
82b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		return -EREMOTEIO;
83b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	}
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
85b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	value = dib3000mc_read_word(state, 1026);
86b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	if (value != 0x3001 && value != 0x3002) {
87b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dprintk("-E-  DiB3000MC/P: wrong Device ID (%x)\n",value);
88b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		return -EREMOTEIO;
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
90b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	state->dev_id = value;
91b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
92b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dprintk("-I-  found DiB3000MC/P: %x\n",state->dev_id);
93b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
94b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	return 0;
95b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher}
96b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
97b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcherstatic int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u32 bw, u8 update_offset)
98b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher{
9901b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher	u32 timf;
100b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
10101b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher	if (state->timf == 0) {
10201b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher		timf = 1384402; // default value for 8MHz
10301b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher		if (update_offset)
10401b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher			msleep(200); // first time we do an update
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
10601b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher		timf = state->timf;
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
108b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	timf *= (bw / 1000);
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11001b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher	if (update_offset) {
11101b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher		s16 tim_offs = dib3000mc_read_word(state, 416);
11201b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher
11301b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher		if (tim_offs &  0x2000)
11401b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher			tim_offs -= 0x4000;
11501b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher
116b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		if (nfft == TRANSMISSION_MODE_2K)
11701b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher			tim_offs *= 4;
11801b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher
11901b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher		timf += tim_offs;
120b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		state->timf = timf / (bw / 1000);
12101b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher	}
122b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
12301b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher	dprintk("timf: %d\n", timf);
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
125b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	dib3000mc_write_word(state, 23, (u16) (timf >> 16));
126b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	dib3000mc_write_word(state, 24, (u16) (timf      ) & 0xffff);
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13101b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcherstatic int dib3000mc_setup_pwm_state(struct dib3000mc_state *state)
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13301b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher	u16 reg_51, reg_52 = state->cfg->agc->setup & 0xfefb;
134b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher    if (state->cfg->pwm3_inversion) {
13501b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher		reg_51 =  (2 << 14) | (0 << 10) | (7 << 6) | (2 << 2) | (2 << 0);
13601b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher		reg_52 |= (1 << 2);
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
13801b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher		reg_51 = (2 << 14) | (4 << 10) | (7 << 6) | (2 << 2) | (2 << 0);
13901b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher		reg_52 |= (1 << 8);
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14101b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher	dib3000mc_write_word(state, 51, reg_51);
14201b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher	dib3000mc_write_word(state, 52, reg_52);
143b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
144b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher    if (state->cfg->use_pwm3)
145b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 245, (1 << 3) | (1 << 0));
146b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	else
147b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 245, 0);
148b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
149b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher    dib3000mc_write_word(state, 1040, 0x3);
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
153b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstatic int dib3000mc_set_output_mode(struct dib3000mc_state *state, int mode)
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
155b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	int    ret = 0;
156b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u16 fifo_threshold = 1792;
157b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u16 outreg = 0;
158b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u16 outmode = 0;
159b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u16 elecout = 1;
160fb6065bbd915f9cf6022d52e114f5078654834b5Patrick Boettcher	u16 smo_reg = dib3000mc_read_word(state, 206) & 0x0010; /* keep the pid_parse bit */
161b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
162b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dprintk("-I-  Setting output mode for demod %p to %d\n",
163b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			&state->demod, mode);
164b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
165b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	switch (mode) {
166b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		case OUTMODE_HIGH_Z:  // disable
167b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			elecout = 0;
168b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			break;
169b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		case OUTMODE_MPEG2_PAR_GATED_CLK:   // STBs with parallel gated clock
170b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			outmode = 0;
171b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			break;
172b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		case OUTMODE_MPEG2_PAR_CONT_CLK:    // STBs with parallel continues clock
173b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			outmode = 1;
174b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			break;
175b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		case OUTMODE_MPEG2_SERIAL:          // STBs with serial input
176b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			outmode = 2;
177b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			break;
178b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		case OUTMODE_MPEG2_FIFO:            // e.g. USB feeding
179b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			elecout = 3;
180b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			/*ADDR @ 206 :
181b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			P_smo_error_discard  [1;6:6] = 0
182b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			P_smo_rs_discard     [1;5:5] = 0
183b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			P_smo_pid_parse      [1;4:4] = 0
184b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			P_smo_fifo_flush     [1;3:3] = 0
185b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			P_smo_mode           [2;2:1] = 11
186b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			P_smo_ovf_prot       [1;0:0] = 0
187b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			*/
188fb6065bbd915f9cf6022d52e114f5078654834b5Patrick Boettcher			smo_reg |= 3 << 1;
189b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			fifo_threshold = 512;
190b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			outmode = 5;
191b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			break;
192b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		case OUTMODE_DIVERSITY:
193b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			outmode = 4;
194b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			elecout = 1;
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
197b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod);
198b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			outmode = 0;
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
201b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
202b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	if ((state->cfg->output_mpeg2_in_188_bytes))
203559463bba8b91d36b12f6722dc27440567e4f6bePatrick Boettcher		smo_reg |= (1 << 5); // P_smo_rs_discard     [1;5:5] = 1
204b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
205b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	outreg = dib3000mc_read_word(state, 244) & 0x07FF;
206b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	outreg |= (outmode << 11);
207b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	ret |= dib3000mc_write_word(state,  244, outreg);
208b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	ret |= dib3000mc_write_word(state,  206, smo_reg);   /*smo_ mode*/
209b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	ret |= dib3000mc_write_word(state,  207, fifo_threshold); /* synchronous fread */
210b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	ret |= dib3000mc_write_word(state, 1040, elecout);         /* P_out_cfg */
211b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	return ret;
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
214b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcherstatic int dib3000mc_set_bandwidth(struct dib3000mc_state *state, u32 bw)
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
216b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u16 bw_cfg[6] = { 0 };
217b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u16 imp_bw_cfg[3] = { 0 };
218b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u16 reg;
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
220b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher/* settings here are for 27.7MHz */
221b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	switch (bw) {
222b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case 8000:
223b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			bw_cfg[0] = 0x0019; bw_cfg[1] = 0x5c30; bw_cfg[2] = 0x0054; bw_cfg[3] = 0x88a0; bw_cfg[4] = 0x01a6; bw_cfg[5] = 0xab20;
224b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			imp_bw_cfg[0] = 0x04db; imp_bw_cfg[1] = 0x00db; imp_bw_cfg[2] = 0x00b7;
225b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			break;
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
227b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case 7000:
228b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			bw_cfg[0] = 0x001c; bw_cfg[1] = 0xfba5; bw_cfg[2] = 0x0060; bw_cfg[3] = 0x9c25; bw_cfg[4] = 0x01e3; bw_cfg[5] = 0x0cb7;
229b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			imp_bw_cfg[0] = 0x04c0; imp_bw_cfg[1] = 0x00c0; imp_bw_cfg[2] = 0x00a0;
230b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			break;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
232b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case 6000:
233b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			bw_cfg[0] = 0x0021; bw_cfg[1] = 0xd040; bw_cfg[2] = 0x0070; bw_cfg[3] = 0xb62b; bw_cfg[4] = 0x0233; bw_cfg[5] = 0x8ed5;
234b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			imp_bw_cfg[0] = 0x04a5; imp_bw_cfg[1] = 0x00a5; imp_bw_cfg[2] = 0x0089;
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
236b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
237b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case 5000:
238b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			bw_cfg[0] = 0x0028; bw_cfg[1] = 0x9380; bw_cfg[2] = 0x0087; bw_cfg[3] = 0x4100; bw_cfg[4] = 0x02a4; bw_cfg[5] = 0x4500;
239b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			imp_bw_cfg[0] = 0x0489; imp_bw_cfg[1] = 0x0089; imp_bw_cfg[2] = 0x0072;
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
241b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
242b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		default: return -EINVAL;
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
245b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	for (reg = 6; reg < 12; reg++)
246b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, reg, bw_cfg[reg - 6]);
247b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 12, 0x0000);
248b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 13, 0x03e8);
249b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 14, 0x0000);
250b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 15, 0x03f2);
251b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 16, 0x0001);
252b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 17, 0xb0d0);
253b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// P_sec_len
254b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 18, 0x0393);
255b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 19, 0x8700);
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
257b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	for (reg = 55; reg < 58; reg++)
258b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, reg, imp_bw_cfg[reg - 55]);
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
260b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// Timing configuration
261b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	dib3000mc_set_timing(state, TRANSMISSION_MODE_2K, bw, 0);
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
263b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	return 0;
264b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher}
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
266b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstatic u16 impulse_noise_val[29] =
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
268b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher{
269b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	0x38, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c, 0x3ffe, 0x7f3,
270b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	0x2d94, 0x76, 0x53d, 0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3, 0x3feb, 0x7d2,
271b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	0x365e, 0x76, 0x48c, 0x3ffe, 0x5b3, 0x3feb, 0x76, 0x0000, 0xd
272b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher};
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
274b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstatic void dib3000mc_set_impulse_noise(struct dib3000mc_state *state, u8 mode, s16 nfft)
275b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher{
276b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u16 i;
277b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	for (i = 58; i < 87; i++)
278b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, i, impulse_noise_val[i-58]);
279b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
280b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	if (nfft == TRANSMISSION_MODE_8K) {
281b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 58, 0x3b);
282b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 84, 0x00);
283b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 85, 0x8200);
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
286b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 34, 0x1294);
287b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 35, 0x1ff8);
288b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	if (mode == 1)
289b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 55, dib3000mc_read_word(state, 55) | (1 << 10));
290b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher}
291b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
292b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstatic int dib3000mc_init(struct dvb_frontend *demod)
293b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher{
294b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dib3000mc_state *state = demod->demodulator_priv;
295b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dibx000_agc_config *agc = state->cfg->agc;
296b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
297b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// Restart Configuration
298b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 1027, 0x8000);
299b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 1027, 0x0000);
300b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
301b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// power up the demod + mobility configuration
302b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 140, 0x0000);
303b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 1031, 0);
304b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
305b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	if (state->cfg->mobile_mode) {
306b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 139,  0x0000);
307b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 141,  0x0000);
308b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 175,  0x0002);
309b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 1032, 0x0000);
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
311b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 139,  0x0001);
312b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 141,  0x0000);
313b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 175,  0x0000);
314b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 1032, 0x012C);
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
316303cbeaaacd449545d259f82b966d070418c58afPatrick Boettcher	dib3000mc_write_word(state, 1033, 0x0000);
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
318b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// P_clk_cfg
319303cbeaaacd449545d259f82b966d070418c58afPatrick Boettcher	dib3000mc_write_word(state, 1037, 0x3130);
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
321b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// other configurations
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
323b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// P_ctrl_sfreq
324b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 33, (5 << 0));
325b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 88, (1 << 10) | (0x10 << 0));
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
327b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// Phase noise control
328b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// P_fft_phacor_inh, P_fft_phacor_cpe, P_fft_powrange
329b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 99, (1 << 9) | (0x20 << 0));
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
331b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	if (state->cfg->phase_noise_mode == 0)
332b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 111, 0x00);
333b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	else
334b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 111, 0x02);
335b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
336b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// P_agc_global
337b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 50, 0x8000);
338b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
339b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// agc setup misc
34001b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher	dib3000mc_setup_pwm_state(state);
341b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
342b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// P_agc_counter_lock
343b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 53, 0x87);
344b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// P_agc_counter_unlock
345b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 54, 0x87);
346b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
347b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	/* agc */
348b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 36, state->cfg->max_time);
3495570dd02ca7fb2e28d32516fae05031d48711aa5Patrick Boettcher	dib3000mc_write_word(state, 37, (state->cfg->agc_command1 << 13) | (state->cfg->agc_command2 << 12) | (0x1d << 0));
350b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 38, state->cfg->pwm3_value);
351b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 39, state->cfg->ln_adc_level);
352b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
353b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// set_agc_loop_Bw
354b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 40, 0x0179);
355b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 41, 0x03f0);
356b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
357b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 42, agc->agc1_max);
358b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 43, agc->agc1_min);
359b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 44, agc->agc2_max);
360b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 45, agc->agc2_min);
361b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 46, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
362b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 47, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
363b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 48, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
364b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 49, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
365b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
366b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher// Begin: TimeOut registers
367b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// P_pha3_thres
368b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 110, 3277);
369b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// P_timf_alpha = 6, P_corm_alpha = 6, P_corm_thres = 0x80
370b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state,  26, 0x6680);
371b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// lock_mask0
372b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 1, 4);
373b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// lock_mask1
374b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 2, 4);
375b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// lock_mask2
376b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 3, 0x1000);
377b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// P_search_maxtrial=1
378b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 5, 1);
379b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
380b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	dib3000mc_set_bandwidth(state, 8000);
381b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
382b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// div_lock_mask
383b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state,  4, 0x814);
384b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
385b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 21, (1 << 9) | 0x164);
386b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 22, 0x463d);
387b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
388b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// Spurious rm cfg
389b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// P_cspu_regul, P_cspu_win_cut
390b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 120, 0x200f);
391b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// P_adp_selec_monit
392b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 134, 0);
393b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
394b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// Fec cfg
395b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 195, 0x10);
396b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
397b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// diversity register: P_dvsy_sync_wait..
398b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 180, 0x2FF0);
399b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
400b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// Impulse noise configuration
401b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	dib3000mc_set_impulse_noise(state, 0, TRANSMISSION_MODE_8K);
402b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
403b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// output mode set-up
404b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
405b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
406b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	/* close the i2c-gate */
407b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 769, (1 << 7) );
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
409b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	return 0;
410b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher}
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
412b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstatic int dib3000mc_sleep(struct dvb_frontend *demod)
413b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher{
414b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dib3000mc_state *state = demod->demodulator_priv;
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
416b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 1031, 0xFFFF);
417b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 1032, 0xFFFF);
418303cbeaaacd449545d259f82b966d070418c58afPatrick Boettcher	dib3000mc_write_word(state, 1033, 0xFFF0);
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
420b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher    return 0;
421b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher}
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
423b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstatic void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam)
424b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher{
425b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u16 cfg[4] = { 0 },reg;
426b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	switch (qam) {
427b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case QPSK:
428b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			cfg[0] = 0x099a; cfg[1] = 0x7fae; cfg[2] = 0x0333; cfg[3] = 0x7ff0;
429b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			break;
430b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case QAM_16:
431b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			cfg[0] = 0x023d; cfg[1] = 0x7fdf; cfg[2] = 0x00a4; cfg[3] = 0x7ff0;
432b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			break;
433b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case QAM_64:
434b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			cfg[0] = 0x0148; cfg[1] = 0x7ff0; cfg[2] = 0x00a4; cfg[3] = 0x7ff8;
435b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			break;
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
437b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	for (reg = 129; reg < 133; reg++)
438b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, reg, cfg[reg - 129]);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
441c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehabstatic void dib3000mc_set_channel_cfg(struct dib3000mc_state *state,
442c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab				      struct dtv_frontend_properties *ch, u16 seq)
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
444b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	u16 value;
445c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	u32 bw = BANDWIDTH_TO_KHZ(ch->bandwidth_hz);
446c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab
447c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	dib3000mc_set_bandwidth(state, bw);
448c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	dib3000mc_set_timing(state, ch->transmission_mode, bw, 0);
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
450b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher//	if (boost)
451b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher//		dib3000mc_write_word(state, 100, (11 << 6) + 6);
452b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher//	else
453b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 100, (16 << 6) + 9);
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
455b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 1027, 0x0800);
456b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 1027, 0x0000);
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
458b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	//Default cfg isi offset adp
459b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 26,  0x6680);
460b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 29,  0x1273);
461b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 33,       5);
462b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	dib3000mc_set_adp_cfg(state, QAM_16);
463b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 133,  15564);
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
465b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 12 , 0x0);
466b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 13 , 0x3e8);
467b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 14 , 0x0);
468b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 15 , 0x3f2);
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
470b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 93,0);
471b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 94,0);
472b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 95,0);
473b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 96,0);
474b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 97,0);
475b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 98,0);
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
477c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	dib3000mc_set_impulse_noise(state, 0, ch->transmission_mode);
478e4d6c1f74aaac1bbe5be50e7368e5ac99d54e5a2Patrick Boettcher
479b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	value = 0;
480c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	switch (ch->transmission_mode) {
481b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
482b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		default:
483b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
484b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	}
485c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	switch (ch->guard_interval) {
486b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
487b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
488b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case GUARD_INTERVAL_1_4:  value |= (3 << 5); break;
489b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		default:
490b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case GUARD_INTERVAL_1_8:  value |= (2 << 5); break;
491b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	}
492c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	switch (ch->modulation) {
493b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case QPSK:  value |= (0 << 3); break;
494b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case QAM_16: value |= (1 << 3); break;
495b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		default:
496b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case QAM_64: value |= (2 << 3); break;
497b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	}
498b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	switch (HIERARCHY_1) {
499b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case HIERARCHY_2: value |= 2; break;
500b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case HIERARCHY_4: value |= 4; break;
501b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		default:
502b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case HIERARCHY_1: value |= 1; break;
503b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	}
504b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	dib3000mc_write_word(state, 0, value);
505e3ab2fdd3f5efe62d266877c53c578fe5b547b31Mario Rossi	dib3000mc_write_word(state, 5, (1 << 8) | ((seq & 0xf) << 4));
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
507b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	value = 0;
508c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	if (ch->hierarchy == 1)
509b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		value |= (1 << 4);
510b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	if (1 == 1)
511b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		value |= 1;
512c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
513b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case FEC_2_3: value |= (2 << 1); break;
514b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case FEC_3_4: value |= (3 << 1); break;
515b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case FEC_5_6: value |= (5 << 1); break;
516b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case FEC_7_8: value |= (7 << 1); break;
517b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		default:
518b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case FEC_1_2: value |= (1 << 1); break;
519b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	}
520b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	dib3000mc_write_word(state, 181, value);
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
522b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	// diversity synchro delay add 50% SFN margin
523c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	switch (ch->transmission_mode) {
524b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case TRANSMISSION_MODE_8K: value = 256; break;
525b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case TRANSMISSION_MODE_2K:
526b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		default: value = 64; break;
527b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	}
528c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	switch (ch->guard_interval) {
529b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case GUARD_INTERVAL_1_16: value *= 2; break;
530b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case GUARD_INTERVAL_1_8:  value *= 4; break;
531b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case GUARD_INTERVAL_1_4:  value *= 8; break;
532b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		default:
533b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher		case GUARD_INTERVAL_1_32: value *= 1; break;
534b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	}
535b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	value <<= 4;
536b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	value |= dib3000mc_read_word(state, 180) & 0x000f;
537b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	dib3000mc_write_word(state, 180, value);
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
539b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// restart demod
540b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	value = dib3000mc_read_word(state, 0);
541b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	dib3000mc_write_word(state, 0, value | (1 << 9));
542b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	dib3000mc_write_word(state, 0, value);
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
544b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	msleep(30);
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
546c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, ch->transmission_mode);
547b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher}
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
549c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehabstatic int dib3000mc_autosearch_start(struct dvb_frontend *demod)
550b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher{
551c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	struct dtv_frontend_properties *chan = &demod->dtv_property_cache;
552b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dib3000mc_state *state = demod->demodulator_priv;
553b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u16 reg;
554b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher//	u32 val;
555c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	struct dtv_frontend_properties schan;
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
557b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	schan = *chan;
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
559b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	/* TODO what is that ? */
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
561b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	/* a channel for autosearch */
562c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	schan.transmission_mode = TRANSMISSION_MODE_8K;
563c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	schan.guard_interval = GUARD_INTERVAL_1_32;
564c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	schan.modulation = QAM_64;
565c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	schan.code_rate_HP = FEC_2_3;
566c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	schan.code_rate_LP = FEC_2_3;
567c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	schan.hierarchy = 0;
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
569b6884a17fc70e979ef34e4b5560988b522bb50a0Patrick Boettcher	dib3000mc_set_channel_cfg(state, &schan, 11);
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
571b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	reg = dib3000mc_read_word(state, 0);
572b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 0, reg | (1 << 8));
57301b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher	dib3000mc_read_word(state, 511);
574b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 0, reg);
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
576b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	return 0;
577b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher}
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
579b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstatic int dib3000mc_autosearch_is_irq(struct dvb_frontend *demod)
580b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher{
581b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dib3000mc_state *state = demod->demodulator_priv;
582b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u16 irq_pending = dib3000mc_read_word(state, 511);
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
584b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	if (irq_pending & 0x1) // failed
585b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		return 1;
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
587b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	if (irq_pending & 0x2) // succeeded
588b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		return 2;
589a16bf5d5603184dc1db88f37051881b2eeacfd17Olivier DANET
590b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	return 0; // still pending
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
592b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
593c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehabstatic int dib3000mc_tune(struct dvb_frontend *demod)
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
595c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
596b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dib3000mc_state *state = demod->demodulator_priv;
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
598b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// ** configure demod **
599b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_set_channel_cfg(state, ch, 0);
600b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
601b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	// activates isi
6028f6956c7f9fa72c502bde47df4122bd32d0b86d5Matt Doran	if (state->sfn_workaround_active) {
6038f6956c7f9fa72c502bde47df4122bd32d0b86d5Matt Doran		dprintk("SFN workaround is active\n");
6048f6956c7f9fa72c502bde47df4122bd32d0b86d5Matt Doran		dib3000mc_write_word(state, 29, 0x1273);
6058f6956c7f9fa72c502bde47df4122bd32d0b86d5Matt Doran		dib3000mc_write_word(state, 108, 0x4000); // P_pha3_force_pha_shift
6068f6956c7f9fa72c502bde47df4122bd32d0b86d5Matt Doran	} else {
6078f6956c7f9fa72c502bde47df4122bd32d0b86d5Matt Doran		dib3000mc_write_word(state, 29, 0x1073);
6088f6956c7f9fa72c502bde47df4122bd32d0b86d5Matt Doran		dib3000mc_write_word(state, 108, 0x0000); // P_pha3_force_pha_shift
6098f6956c7f9fa72c502bde47df4122bd32d0b86d5Matt Doran	}
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
611c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	dib3000mc_set_adp_cfg(state, (u8)ch->modulation);
612c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	if (ch->transmission_mode == TRANSMISSION_MODE_8K) {
613b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 26, 38528);
614b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 33, 8);
615b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	} else {
616b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 26, 30336);
617b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dib3000mc_write_word(state, 33, 6);
618b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	}
619b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
62001b4bf31ce6ca6c1de31c773fa281a34fd98ff87Patrick Boettcher	if (dib3000mc_read_word(state, 509) & 0x80)
621c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		dib3000mc_set_timing(state, ch->transmission_mode,
622c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab				     BANDWIDTH_TO_KHZ(ch->bandwidth_hz), 1);
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
627b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstruct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating)
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
629b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dib3000mc_state *st = demod->demodulator_priv;
630b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	return dibx000_get_i2c_adapter(&st->i2c_master, DIBX000_I2C_INTERFACE_TUNER, gating);
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
633b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick BoettcherEXPORT_SYMBOL(dib3000mc_get_tuner_i2c_master);
634b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
6357c61d80a9bcfc3fdec8ffd75756cad6a64678229Mauro Carvalho Chehabstatic int dib3000mc_get_frontend(struct dvb_frontend* fe)
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6377c61d80a9bcfc3fdec8ffd75756cad6a64678229Mauro Carvalho Chehab	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
638b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dib3000mc_state *state = fe->demodulator_priv;
639b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u16 tps = dib3000mc_read_word(state,458);
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
641b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	fep->inversion = INVERSION_AUTO;
642b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
643c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	fep->bandwidth_hz = state->current_bandwidth;
644b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
645b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	switch ((tps >> 8) & 0x1) {
646c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		case 0: fep->transmission_mode = TRANSMISSION_MODE_2K; break;
647c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		case 1: fep->transmission_mode = TRANSMISSION_MODE_8K; break;
648b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	}
649b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
650b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	switch (tps & 0x3) {
651c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		case 0: fep->guard_interval = GUARD_INTERVAL_1_32; break;
652c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		case 1: fep->guard_interval = GUARD_INTERVAL_1_16; break;
653c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		case 2: fep->guard_interval = GUARD_INTERVAL_1_8; break;
654c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		case 3: fep->guard_interval = GUARD_INTERVAL_1_4; break;
655b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	}
656b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
657b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	switch ((tps >> 13) & 0x3) {
658c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		case 0: fep->modulation = QPSK; break;
659c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		case 1: fep->modulation = QAM_16; break;
660b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		case 2:
661c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		default: fep->modulation = QAM_64; break;
662b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	}
663b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
664b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	/* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
665b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	/* (tps >> 12) & 0x1 == hrch is used, (tps >> 9) & 0x7 == alpha */
666b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
667c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	fep->hierarchy = HIERARCHY_NONE;
668b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	switch ((tps >> 5) & 0x7) {
669c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		case 1: fep->code_rate_HP = FEC_1_2; break;
670c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		case 2: fep->code_rate_HP = FEC_2_3; break;
671c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		case 3: fep->code_rate_HP = FEC_3_4; break;
672c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		case 5: fep->code_rate_HP = FEC_5_6; break;
673b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		case 7:
674c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		default: fep->code_rate_HP = FEC_7_8; break;
675b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
676b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	}
677b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
678b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	switch ((tps >> 2) & 0x7) {
679c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		case 1: fep->code_rate_LP = FEC_1_2; break;
680c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		case 2: fep->code_rate_LP = FEC_2_3; break;
681c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		case 3: fep->code_rate_LP = FEC_3_4; break;
682c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		case 5: fep->code_rate_LP = FEC_5_6; break;
683b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		case 7:
684c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		default: fep->code_rate_LP = FEC_7_8; break;
685b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	}
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
690c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehabstatic int dib3000mc_set_frontend(struct dvb_frontend *fe)
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6927c61d80a9bcfc3fdec8ffd75756cad6a64678229Mauro Carvalho Chehab	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
693b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dib3000mc_state *state = fe->demodulator_priv;
694c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	int ret;
695853ea132c75ff2c4e3c3aaf61bf3ef5779774dbcSoeren Moch
696853ea132c75ff2c4e3c3aaf61bf3ef5779774dbcSoeren Moch	dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
697b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
698c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	state->current_bandwidth = fep->bandwidth_hz;
699c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->bandwidth_hz));
700b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
7018f6956c7f9fa72c502bde47df4122bd32d0b86d5Matt Doran	/* maybe the parameter has been changed */
7028f6956c7f9fa72c502bde47df4122bd32d0b86d5Matt Doran	state->sfn_workaround_active = buggy_sfn_workaround;
7038f6956c7f9fa72c502bde47df4122bd32d0b86d5Matt Doran
704b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	if (fe->ops.tuner_ops.set_params) {
70514d24d148c7521b2b88b396652e36f55d061e195Mauro Carvalho Chehab		fe->ops.tuner_ops.set_params(fe);
706b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		msleep(100);
707b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	}
708b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
709c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	if (fep->transmission_mode  == TRANSMISSION_MODE_AUTO ||
710c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	    fep->guard_interval == GUARD_INTERVAL_AUTO ||
711c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	    fep->modulation     == QAM_AUTO ||
712c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	    fep->code_rate_HP   == FEC_AUTO) {
7133a0311c6c539bd022a65d298355471aacbd7a618Jose Alberto Reguero		int i = 1000, found;
714b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
715c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab		dib3000mc_autosearch_start(fe);
716b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		do {
717b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			msleep(1);
718b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			found = dib3000mc_autosearch_is_irq(fe);
719b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		} while (found == 0 && i--);
720b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
721b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		dprintk("autosearch returns: %d\n",found);
722b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		if (found == 0 || found == 1)
723b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			return 0; // no channel found
724b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
7257c61d80a9bcfc3fdec8ffd75756cad6a64678229Mauro Carvalho Chehab		dib3000mc_get_frontend(fe);
726b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	}
727b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
728c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	ret = dib3000mc_tune(fe);
729853ea132c75ff2c4e3c3aaf61bf3ef5779774dbcSoeren Moch
730b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	/* make this a config parameter */
731b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_set_output_mode(state, OUTMODE_MPEG2_FIFO);
732c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	return ret;
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
735b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstatic int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat)
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
737b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dib3000mc_state *state = fe->demodulator_priv;
738b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u16 lock = dib3000mc_read_word(state, 509);
739b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
740b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	*stat = 0;
741b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
742b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	if (lock & 0x8000)
743b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		*stat |= FE_HAS_SIGNAL;
744b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	if (lock & 0x3000)
745b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		*stat |= FE_HAS_CARRIER;
746b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	if (lock & 0x0100)
747b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		*stat |= FE_HAS_VITERBI;
748b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	if (lock & 0x0010)
749b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		*stat |= FE_HAS_SYNC;
750b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	if (lock & 0x0008)
751b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		*stat |= FE_HAS_LOCK;
752b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
756b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstatic int dib3000mc_read_ber(struct dvb_frontend *fe, u32 *ber)
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
758b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dib3000mc_state *state = fe->demodulator_priv;
759b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	*ber = (dib3000mc_read_word(state, 500) << 16) | dib3000mc_read_word(state, 501);
760b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	return 0;
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
763b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstatic int dib3000mc_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
765b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dib3000mc_state *state = fe->demodulator_priv;
766b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	*unc = dib3000mc_read_word(state, 508);
767b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	return 0;
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
770b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstatic int dib3000mc_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
772b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dib3000mc_state *state = fe->demodulator_priv;
773b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u16 val = dib3000mc_read_word(state, 392);
774b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	*strength = 65535 - val;
775b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	return 0;
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
778b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstatic int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr)
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
780b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	*snr = 0x0000;
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
784b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstatic int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
786b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	tune->min_delay_ms = 1000;
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
790b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherstatic void dib3000mc_release(struct dvb_frontend *fe)
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
792b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dib3000mc_state *state = fe->demodulator_priv;
793b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dibx000_exit_i2c_master(&state->i2c_master);
794b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	kfree(state);
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
797b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherint dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff)
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
799b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dib3000mc_state *state = fe->demodulator_priv;
800b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	dib3000mc_write_word(state, 212 + index,  onoff ? (1 << 13) | pid : 0);
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
803b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick BoettcherEXPORT_SYMBOL(dib3000mc_pid_control);
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
805b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcherint dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff)
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
807b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dib3000mc_state *state = fe->demodulator_priv;
808b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	u16 tmp = dib3000mc_read_word(state, 206) & ~(1 << 4);
809b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	tmp |= (onoff << 4);
810b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	return dib3000mc_write_word(state, 206, tmp);
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
812b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick BoettcherEXPORT_SYMBOL(dib3000mc_pid_parse);
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
814b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettchervoid dib3000mc_set_config(struct dvb_frontend *fe, struct dib3000mc_config *cfg)
815e4d6c1f74aaac1bbe5be50e7368e5ac99d54e5a2Patrick Boettcher{
816b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	struct dib3000mc_state *state = fe->demodulator_priv;
817b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	state->cfg = cfg;
818e4d6c1f74aaac1bbe5be50e7368e5ac99d54e5a2Patrick Boettcher}
819b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick BoettcherEXPORT_SYMBOL(dib3000mc_set_config);
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
821136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcherint dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib3000mc_config cfg[])
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8230de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap	struct dib3000mc_state *dmcst;
824136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	int k;
825136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	u8 new_addr;
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
827136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	static u8 DIB3000MC_I2C_ADDRESS[] = {20,22,24,26};
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8290de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap	dmcst = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
8300de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap	if (dmcst == NULL)
831febe2ea10e041c014b295a0321f7ec62c05b7e3fAndrew Morton		return -ENOMEM;
8320de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap
8330de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap	dmcst->i2c_adap = i2c;
8340de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap
835136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	for (k = no_of_demods-1; k >= 0; k--) {
8360de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap		dmcst->cfg = &cfg[k];
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
838136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher		/* designated i2c address */
839136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher		new_addr          = DIB3000MC_I2C_ADDRESS[k];
8400de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap		dmcst->i2c_addr = new_addr;
8410de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap		if (dib3000mc_identify(dmcst) != 0) {
8420de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap			dmcst->i2c_addr = default_addr;
8430de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap			if (dib3000mc_identify(dmcst) != 0) {
844136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher				dprintk("-E-  DiB3000P/MC #%d: not identified\n", k);
8450de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap				kfree(dmcst);
846136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher				return -ENODEV;
847136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher			}
848136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher		}
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8500de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap		dib3000mc_set_output_mode(dmcst, OUTMODE_MPEG2_PAR_CONT_CLK);
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
852136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher		// set new i2c address and force divstr (Bit 1) to value 0 (Bit 0)
8530de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap		dib3000mc_write_word(dmcst, 1024, (new_addr << 3) | 0x1);
8540de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap		dmcst->i2c_addr = new_addr;
855b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	}
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
857136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	for (k = 0; k < no_of_demods; k++) {
8580de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap		dmcst->cfg = &cfg[k];
8590de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap		dmcst->i2c_addr = DIB3000MC_I2C_ADDRESS[k];
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8610de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap		dib3000mc_write_word(dmcst, 1024, dmcst->i2c_addr << 3);
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
863136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher		/* turn off data output */
8640de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap		dib3000mc_set_output_mode(dmcst, OUTMODE_HIGH_Z);
865136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	}
8660de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap
8670de8e3533e08745616a30bdb3fa5106c85083e51Randy Dunlap	kfree(dmcst);
868b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	return 0;
869136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher}
870136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick BoettcherEXPORT_SYMBOL(dib3000mc_i2c_enumeration);
871136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher
872136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcherstatic struct dvb_frontend_ops dib3000mc_ops;
873136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher
874136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcherstruct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg)
875136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher{
876136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	struct dvb_frontend *demod;
877136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	struct dib3000mc_state *st;
878136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	st = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
879136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	if (st == NULL)
880136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher		return NULL;
881136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher
882136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	st->cfg = cfg;
883136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	st->i2c_adap = i2c_adap;
8846958effedb0dc709966c22e7fd0e8210b5401b84Patrick Boettcher	st->i2c_addr = i2c_addr;
885136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher
886136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	demod                   = &st->demod;
887136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	demod->demodulator_priv = st;
888136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	memcpy(&st->demod.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
889136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher
890136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	if (dib3000mc_identify(st) != 0)
891136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher		goto error;
892136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher
893136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	dibx000_init_i2c_master(&st->i2c_master, DIB3000MC, st->i2c_adap, st->i2c_addr);
894136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher
895303cbeaaacd449545d259f82b966d070418c58afPatrick Boettcher	dib3000mc_write_word(st, 1037, 0x3130);
896303cbeaaacd449545d259f82b966d070418c58afPatrick Boettcher
897136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	return demod;
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserror:
900136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	kfree(st);
901136cafbf4a024b52ba0a10627217f03cea9ff9f8Patrick Boettcher	return NULL;
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
903e4d6c1f74aaac1bbe5be50e7368e5ac99d54e5a2Patrick BoettcherEXPORT_SYMBOL(dib3000mc_attach);
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct dvb_frontend_ops dib3000mc_ops = {
906c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	.delsys = { SYS_DVBT },
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.info = {
908b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		.name = "DiBcom 3000MC/P",
909b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		.frequency_min      = 44250000,
910b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		.frequency_max      = 867250000,
911b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher		.frequency_stepsize = 62500,
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.caps = FE_CAN_INVERSION_AUTO |
913b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
914b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
915b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
916b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			FE_CAN_TRANSMISSION_MODE_AUTO |
917b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			FE_CAN_GUARD_INTERVAL_AUTO |
918b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			FE_CAN_RECOVER |
919b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher			FE_CAN_HIERARCHY_AUTO,
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
922b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	.release              = dib3000mc_release,
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
924b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	.init                 = dib3000mc_init,
925b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	.sleep                = dib3000mc_sleep,
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
927c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	.set_frontend         = dib3000mc_set_frontend,
928b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	.get_tune_settings    = dib3000mc_fe_get_tune_settings,
929c1f814f49904ae5b275407f71aefd3a31c774098Mauro Carvalho Chehab	.get_frontend         = dib3000mc_get_frontend,
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
931b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	.read_status          = dib3000mc_read_status,
932b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	.read_ber             = dib3000mc_read_ber,
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read_signal_strength = dib3000mc_read_signal_strength,
934b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	.read_snr             = dib3000mc_read_snr,
935b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick Boettcher	.read_ucblocks        = dib3000mc_read_unc_blocks,
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
938b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick BoettcherMODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
939b7571f8d7e12cd70048331e6a0199a42dc995d99Patrick BoettcherMODULE_DESCRIPTION("Driver for the DiBcom 3000MC/P COFDM demodulator");
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
941