cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dib7000m.c (42153B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Linux-DVB Driver for DiBcom's DiB7000M and
      4 *              first generation DiB7000P-demodulator-family.
      5 *
      6 * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
      7 */
      8
      9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     10
     11#include <linux/kernel.h>
     12#include <linux/slab.h>
     13#include <linux/i2c.h>
     14#include <linux/mutex.h>
     15
     16#include <media/dvb_frontend.h>
     17
     18#include "dib7000m.h"
     19
     20static int debug;
     21module_param(debug, int, 0644);
     22MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
     23
     24#define dprintk(fmt, arg...) do {					\
     25	if (debug)							\
     26		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
     27		       __func__, ##arg);				\
     28} while (0)
     29
     30struct dib7000m_state {
     31	struct dvb_frontend demod;
     32    struct dib7000m_config cfg;
     33
     34	u8 i2c_addr;
     35	struct i2c_adapter   *i2c_adap;
     36
     37	struct dibx000_i2c_master i2c_master;
     38
     39/* offset is 1 in case of the 7000MC */
     40	u8 reg_offs;
     41
     42	u16 wbd_ref;
     43
     44	u8 current_band;
     45	u32 current_bandwidth;
     46	struct dibx000_agc_config *current_agc;
     47	u32 timf;
     48	u32 timf_default;
     49	u32 internal_clk;
     50
     51	u8 div_force_off : 1;
     52	u8 div_state : 1;
     53	u16 div_sync_wait;
     54
     55	u16 revision;
     56
     57	u8 agc_state;
     58
     59	/* for the I2C transfer */
     60	struct i2c_msg msg[2];
     61	u8 i2c_write_buffer[4];
     62	u8 i2c_read_buffer[2];
     63	struct mutex i2c_buffer_lock;
     64};
     65
     66enum dib7000m_power_mode {
     67	DIB7000M_POWER_ALL = 0,
     68
     69	DIB7000M_POWER_NO,
     70	DIB7000M_POWER_INTERF_ANALOG_AGC,
     71	DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD,
     72	DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD,
     73	DIB7000M_POWER_INTERFACE_ONLY,
     74};
     75
     76static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
     77{
     78	u16 ret;
     79
     80	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
     81		dprintk("could not acquire lock\n");
     82		return 0;
     83	}
     84
     85	state->i2c_write_buffer[0] = (reg >> 8) | 0x80;
     86	state->i2c_write_buffer[1] = reg & 0xff;
     87
     88	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
     89	state->msg[0].addr = state->i2c_addr >> 1;
     90	state->msg[0].flags = 0;
     91	state->msg[0].buf = state->i2c_write_buffer;
     92	state->msg[0].len = 2;
     93	state->msg[1].addr = state->i2c_addr >> 1;
     94	state->msg[1].flags = I2C_M_RD;
     95	state->msg[1].buf = state->i2c_read_buffer;
     96	state->msg[1].len = 2;
     97
     98	if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
     99		dprintk("i2c read error on %d\n", reg);
    100
    101	ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
    102	mutex_unlock(&state->i2c_buffer_lock);
    103
    104	return ret;
    105}
    106
    107static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
    108{
    109	int ret;
    110
    111	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
    112		dprintk("could not acquire lock\n");
    113		return -EINVAL;
    114	}
    115
    116	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
    117	state->i2c_write_buffer[1] = reg & 0xff;
    118	state->i2c_write_buffer[2] = (val >> 8) & 0xff;
    119	state->i2c_write_buffer[3] = val & 0xff;
    120
    121	memset(&state->msg[0], 0, sizeof(struct i2c_msg));
    122	state->msg[0].addr = state->i2c_addr >> 1;
    123	state->msg[0].flags = 0;
    124	state->msg[0].buf = state->i2c_write_buffer;
    125	state->msg[0].len = 4;
    126
    127	ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
    128			-EREMOTEIO : 0);
    129	mutex_unlock(&state->i2c_buffer_lock);
    130	return ret;
    131}
    132static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
    133{
    134	u16 l = 0, r, *n;
    135	n = buf;
    136	l = *n++;
    137	while (l) {
    138		r = *n++;
    139
    140		if (state->reg_offs && (r >= 112 && r <= 331)) // compensate for 7000MC
    141			r++;
    142
    143		do {
    144			dib7000m_write_word(state, r, *n++);
    145			r++;
    146		} while (--l);
    147		l = *n++;
    148	}
    149}
    150
    151static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode)
    152{
    153	int    ret = 0;
    154	u16 outreg, fifo_threshold, smo_mode,
    155		sram = 0x0005; /* by default SRAM output is disabled */
    156
    157	outreg = 0;
    158	fifo_threshold = 1792;
    159	smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1);
    160
    161	dprintk("setting output mode for demod %p to %d\n", &state->demod, mode);
    162
    163	switch (mode) {
    164		case OUTMODE_MPEG2_PAR_GATED_CLK:   // STBs with parallel gated clock
    165			outreg = (1 << 10);  /* 0x0400 */
    166			break;
    167		case OUTMODE_MPEG2_PAR_CONT_CLK:    // STBs with parallel continues clock
    168			outreg = (1 << 10) | (1 << 6); /* 0x0440 */
    169			break;
    170		case OUTMODE_MPEG2_SERIAL:          // STBs with serial input
    171			outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */
    172			break;
    173		case OUTMODE_DIVERSITY:
    174			if (state->cfg.hostbus_diversity)
    175				outreg = (1 << 10) | (4 << 6); /* 0x0500 */
    176			else
    177				sram   |= 0x0c00;
    178			break;
    179		case OUTMODE_MPEG2_FIFO:            // e.g. USB feeding
    180			smo_mode |= (3 << 1);
    181			fifo_threshold = 512;
    182			outreg = (1 << 10) | (5 << 6);
    183			break;
    184		case OUTMODE_HIGH_Z:  // disable
    185			outreg = 0;
    186			break;
    187		default:
    188			dprintk("Unhandled output_mode passed to be set for demod %p\n", &state->demod);
    189			break;
    190	}
    191
    192	if (state->cfg.output_mpeg2_in_188_bytes)
    193		smo_mode |= (1 << 5) ;
    194
    195	ret |= dib7000m_write_word(state,  294 + state->reg_offs, smo_mode);
    196	ret |= dib7000m_write_word(state,  295 + state->reg_offs, fifo_threshold); /* synchronous fread */
    197	ret |= dib7000m_write_word(state, 1795, outreg);
    198	ret |= dib7000m_write_word(state, 1805, sram);
    199
    200	if (state->revision == 0x4003) {
    201		u16 clk_cfg1 = dib7000m_read_word(state, 909) & 0xfffd;
    202		if (mode == OUTMODE_DIVERSITY)
    203			clk_cfg1 |= (1 << 1); // P_O_CLK_en
    204		dib7000m_write_word(state, 909, clk_cfg1);
    205	}
    206	return ret;
    207}
    208
    209static void dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode)
    210{
    211	/* by default everything is going to be powered off */
    212	u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906  = 0x3fff;
    213	u8  offset = 0;
    214
    215	/* now, depending on the requested mode, we power on */
    216	switch (mode) {
    217		/* power up everything in the demod */
    218		case DIB7000M_POWER_ALL:
    219			reg_903 = 0x0000; reg_904 = 0x0000; reg_905 = 0x0000; reg_906 = 0x0000;
    220			break;
    221
    222		/* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */
    223		case DIB7000M_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */
    224			reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2));
    225			break;
    226
    227		case DIB7000M_POWER_INTERF_ANALOG_AGC:
    228			reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10));
    229			reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2));
    230			reg_906 &= ~((1 << 0));
    231			break;
    232
    233		case DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD:
    234			reg_903 = 0x0000; reg_904 = 0x801f; reg_905 = 0x0000; reg_906 = 0x0000;
    235			break;
    236
    237		case DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD:
    238			reg_903 = 0x0000; reg_904 = 0x8000; reg_905 = 0x010b; reg_906 = 0x0000;
    239			break;
    240		case DIB7000M_POWER_NO:
    241			break;
    242	}
    243
    244	/* always power down unused parts */
    245	if (!state->cfg.mobile_mode)
    246		reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1);
    247
    248	/* P_sdio_select_clk = 0 on MC and after*/
    249	if (state->revision != 0x4000)
    250		reg_906 <<= 1;
    251
    252	if (state->revision == 0x4003)
    253		offset = 1;
    254
    255	dib7000m_write_word(state, 903 + offset, reg_903);
    256	dib7000m_write_word(state, 904 + offset, reg_904);
    257	dib7000m_write_word(state, 905 + offset, reg_905);
    258	dib7000m_write_word(state, 906 + offset, reg_906);
    259}
    260
    261static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no)
    262{
    263	int ret = 0;
    264	u16 reg_913 = dib7000m_read_word(state, 913),
    265	       reg_914 = dib7000m_read_word(state, 914);
    266
    267	switch (no) {
    268		case DIBX000_SLOW_ADC_ON:
    269			reg_914 |= (1 << 1) | (1 << 0);
    270			ret |= dib7000m_write_word(state, 914, reg_914);
    271			reg_914 &= ~(1 << 1);
    272			break;
    273
    274		case DIBX000_SLOW_ADC_OFF:
    275			reg_914 |=  (1 << 1) | (1 << 0);
    276			break;
    277
    278		case DIBX000_ADC_ON:
    279			if (state->revision == 0x4000) { // workaround for PA/MA
    280				// power-up ADC
    281				dib7000m_write_word(state, 913, 0);
    282				dib7000m_write_word(state, 914, reg_914 & 0x3);
    283				// power-down bandgag
    284				dib7000m_write_word(state, 913, (1 << 15));
    285				dib7000m_write_word(state, 914, reg_914 & 0x3);
    286			}
    287
    288			reg_913 &= 0x0fff;
    289			reg_914 &= 0x0003;
    290			break;
    291
    292		case DIBX000_ADC_OFF: // leave the VBG voltage on
    293			reg_913 |= (1 << 14) | (1 << 13) | (1 << 12);
    294			reg_914 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
    295			break;
    296
    297		case DIBX000_VBG_ENABLE:
    298			reg_913 &= ~(1 << 15);
    299			break;
    300
    301		case DIBX000_VBG_DISABLE:
    302			reg_913 |= (1 << 15);
    303			break;
    304
    305		default:
    306			break;
    307	}
    308
    309//	dprintk("913: %x, 914: %x\n", reg_913, reg_914);
    310	ret |= dib7000m_write_word(state, 913, reg_913);
    311	ret |= dib7000m_write_word(state, 914, reg_914);
    312
    313	return ret;
    314}
    315
    316static int dib7000m_set_bandwidth(struct dib7000m_state *state, u32 bw)
    317{
    318	u32 timf;
    319
    320	if (!bw)
    321		bw = 8000;
    322
    323	// store the current bandwidth for later use
    324	state->current_bandwidth = bw;
    325
    326	if (state->timf == 0) {
    327		dprintk("using default timf\n");
    328		timf = state->timf_default;
    329	} else {
    330		dprintk("using updated timf\n");
    331		timf = state->timf;
    332	}
    333
    334	timf = timf * (bw / 50) / 160;
    335
    336	dib7000m_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
    337	dib7000m_write_word(state, 24, (u16) ((timf      ) & 0xffff));
    338
    339	return 0;
    340}
    341
    342static int dib7000m_set_diversity_in(struct dvb_frontend *demod, int onoff)
    343{
    344	struct dib7000m_state *state = demod->demodulator_priv;
    345
    346	if (state->div_force_off) {
    347		dprintk("diversity combination deactivated - forced by COFDM parameters\n");
    348		onoff = 0;
    349	}
    350	state->div_state = (u8)onoff;
    351
    352	if (onoff) {
    353		dib7000m_write_word(state, 263 + state->reg_offs, 6);
    354		dib7000m_write_word(state, 264 + state->reg_offs, 6);
    355		dib7000m_write_word(state, 266 + state->reg_offs, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
    356	} else {
    357		dib7000m_write_word(state, 263 + state->reg_offs, 1);
    358		dib7000m_write_word(state, 264 + state->reg_offs, 0);
    359		dib7000m_write_word(state, 266 + state->reg_offs, 0);
    360	}
    361
    362	return 0;
    363}
    364
    365static int dib7000m_sad_calib(struct dib7000m_state *state)
    366{
    367
    368/* internal */
    369//	dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writing in set_bandwidth
    370	dib7000m_write_word(state, 929, (0 << 1) | (0 << 0));
    371	dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096
    372
    373	/* do the calibration */
    374	dib7000m_write_word(state, 929, (1 << 0));
    375	dib7000m_write_word(state, 929, (0 << 0));
    376
    377	msleep(1);
    378
    379	return 0;
    380}
    381
    382static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw)
    383{
    384	dib7000m_write_word(state, 18, (u16) (((bw->internal*1000) >> 16) & 0xffff));
    385	dib7000m_write_word(state, 19, (u16) ( (bw->internal*1000)        & 0xffff));
    386	dib7000m_write_word(state, 21, (u16) ( (bw->ifreq          >> 16) & 0xffff));
    387	dib7000m_write_word(state, 22, (u16) (  bw->ifreq                 & 0xffff));
    388
    389	dib7000m_write_word(state, 928, bw->sad_cfg);
    390}
    391
    392static void dib7000m_reset_pll(struct dib7000m_state *state)
    393{
    394	const struct dibx000_bandwidth_config *bw = state->cfg.bw;
    395	u16 reg_907,reg_910;
    396
    397	/* default */
    398	reg_907 = (bw->pll_bypass << 15) | (bw->modulo << 7) |
    399		(bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) |
    400		(bw->enable_refdiv << 1) | (0 << 0);
    401	reg_910 = (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset;
    402
    403	// for this oscillator frequency should be 30 MHz for the Master (default values in the board_parameters give that value)
    404	// this is only working only for 30 MHz crystals
    405	if (!state->cfg.quartz_direct) {
    406		reg_910 |= (1 << 5);  // forcing the predivider to 1
    407
    408		// if the previous front-end is baseband, its output frequency is 15 MHz (prev freq divided by 2)
    409		if(state->cfg.input_clk_is_div_2)
    410			reg_907 |= (16 << 9);
    411		else // otherwise the previous front-end puts out its input (default 30MHz) - no extra division necessary
    412			reg_907 |= (8 << 9);
    413	} else {
    414		reg_907 |= (bw->pll_ratio & 0x3f) << 9;
    415		reg_910 |= (bw->pll_prediv << 5);
    416	}
    417
    418	dib7000m_write_word(state, 910, reg_910); // pll cfg
    419	dib7000m_write_word(state, 907, reg_907); // clk cfg0
    420	dib7000m_write_word(state, 908, 0x0006);  // clk_cfg1
    421
    422	dib7000m_reset_pll_common(state, bw);
    423}
    424
    425static void dib7000mc_reset_pll(struct dib7000m_state *state)
    426{
    427	const struct dibx000_bandwidth_config *bw = state->cfg.bw;
    428	u16 clk_cfg1;
    429
    430	// clk_cfg0
    431	dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0));
    432
    433	// clk_cfg1
    434	//dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) |
    435	clk_cfg1 = (0 << 14) | (3 << 12) |(0 << 11) |
    436			(bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) |
    437			(1 << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0);
    438	dib7000m_write_word(state, 908, clk_cfg1);
    439	clk_cfg1 = (clk_cfg1 & 0xfff7) | (bw->pll_bypass << 3);
    440	dib7000m_write_word(state, 908, clk_cfg1);
    441
    442	// smpl_cfg
    443	dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7));
    444
    445	dib7000m_reset_pll_common(state, bw);
    446}
    447
    448static int dib7000m_reset_gpio(struct dib7000m_state *st)
    449{
    450	/* reset the GPIOs */
    451	dib7000m_write_word(st, 773, st->cfg.gpio_dir);
    452	dib7000m_write_word(st, 774, st->cfg.gpio_val);
    453
    454	/* TODO 782 is P_gpio_od */
    455
    456	dib7000m_write_word(st, 775, st->cfg.gpio_pwm_pos);
    457
    458	dib7000m_write_word(st, 780, st->cfg.pwm_freq_div);
    459	return 0;
    460}
    461
    462static u16 dib7000m_defaults_common[] =
    463
    464{
    465	// auto search configuration
    466	3, 2,
    467		0x0004,
    468		0x1000,
    469		0x0814,
    470
    471	12, 6,
    472		0x001b,
    473		0x7740,
    474		0x005b,
    475		0x8d80,
    476		0x01c9,
    477		0xc380,
    478		0x0000,
    479		0x0080,
    480		0x0000,
    481		0x0090,
    482		0x0001,
    483		0xd4c0,
    484
    485	1, 26,
    486		0x6680, // P_corm_thres Lock algorithms configuration
    487
    488	1, 170,
    489		0x0410, // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on
    490
    491	8, 173,
    492		0,
    493		0,
    494		0,
    495		0,
    496		0,
    497		0,
    498		0,
    499		0,
    500
    501	1, 182,
    502		8192, // P_fft_nb_to_cut
    503
    504	2, 195,
    505		0x0ccd, // P_pha3_thres
    506		0,      // P_cti_use_cpe, P_cti_use_prog
    507
    508	1, 205,
    509		0x200f, // P_cspu_regul, P_cspu_win_cut
    510
    511	5, 214,
    512		0x023d, // P_adp_regul_cnt
    513		0x00a4, // P_adp_noise_cnt
    514		0x00a4, // P_adp_regul_ext
    515		0x7ff0, // P_adp_noise_ext
    516		0x3ccc, // P_adp_fil
    517
    518	1, 226,
    519		0, // P_2d_byp_ti_num
    520
    521	1, 255,
    522		0x800, // P_equal_thres_wgn
    523
    524	1, 263,
    525		0x0001,
    526
    527	1, 281,
    528		0x0010, // P_fec_*
    529
    530	1, 294,
    531		0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
    532
    533	0
    534};
    535
    536static u16 dib7000m_defaults[] =
    537
    538{
    539	/* set ADC level to -16 */
    540	11, 76,
    541		(1 << 13) - 825 - 117,
    542		(1 << 13) - 837 - 117,
    543		(1 << 13) - 811 - 117,
    544		(1 << 13) - 766 - 117,
    545		(1 << 13) - 737 - 117,
    546		(1 << 13) - 693 - 117,
    547		(1 << 13) - 648 - 117,
    548		(1 << 13) - 619 - 117,
    549		(1 << 13) - 575 - 117,
    550		(1 << 13) - 531 - 117,
    551		(1 << 13) - 501 - 117,
    552
    553	// Tuner IO bank: max drive (14mA)
    554	1, 912,
    555		0x2c8a,
    556
    557	1, 1817,
    558		1,
    559
    560	0,
    561};
    562
    563static int dib7000m_demod_reset(struct dib7000m_state *state)
    564{
    565	dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
    566
    567	/* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */
    568	dib7000m_set_adc_state(state, DIBX000_VBG_ENABLE);
    569
    570	/* restart all parts */
    571	dib7000m_write_word(state,  898, 0xffff);
    572	dib7000m_write_word(state,  899, 0xffff);
    573	dib7000m_write_word(state,  900, 0xff0f);
    574	dib7000m_write_word(state,  901, 0xfffc);
    575
    576	dib7000m_write_word(state,  898, 0);
    577	dib7000m_write_word(state,  899, 0);
    578	dib7000m_write_word(state,  900, 0);
    579	dib7000m_write_word(state,  901, 0);
    580
    581	if (state->revision == 0x4000)
    582		dib7000m_reset_pll(state);
    583	else
    584		dib7000mc_reset_pll(state);
    585
    586	if (dib7000m_reset_gpio(state) != 0)
    587		dprintk("GPIO reset was not successful.\n");
    588
    589	if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
    590		dprintk("OUTPUT_MODE could not be reset.\n");
    591
    592	/* unforce divstr regardless whether i2c enumeration was done or not */
    593	dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) );
    594
    595	dib7000m_set_bandwidth(state, 8000);
    596
    597	dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON);
    598	dib7000m_sad_calib(state);
    599	dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
    600
    601	if (state->cfg.dvbt_mode)
    602		dib7000m_write_word(state, 1796, 0x0); // select DVB-T output
    603
    604	if (state->cfg.mobile_mode)
    605		dib7000m_write_word(state, 261 + state->reg_offs, 2);
    606	else
    607		dib7000m_write_word(state, 224 + state->reg_offs, 1);
    608
    609	// P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ...
    610	if(state->cfg.tuner_is_baseband)
    611		dib7000m_write_word(state, 36, 0x0755);
    612	else
    613		dib7000m_write_word(state, 36, 0x1f55);
    614
    615	// P_divclksel=3 P_divbitsel=1
    616	if (state->revision == 0x4000)
    617		dib7000m_write_word(state, 909, (3 << 10) | (1 << 6));
    618	else
    619		dib7000m_write_word(state, 909, (3 << 4) | 1);
    620
    621	dib7000m_write_tab(state, dib7000m_defaults_common);
    622	dib7000m_write_tab(state, dib7000m_defaults);
    623
    624	dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY);
    625
    626	state->internal_clk = state->cfg.bw->internal;
    627
    628	return 0;
    629}
    630
    631static void dib7000m_restart_agc(struct dib7000m_state *state)
    632{
    633	// P_restart_iqc & P_restart_agc
    634	dib7000m_write_word(state, 898, 0x0c00);
    635	dib7000m_write_word(state, 898, 0x0000);
    636}
    637
    638static int dib7000m_agc_soft_split(struct dib7000m_state *state)
    639{
    640	u16 agc,split_offset;
    641
    642	if(!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0)
    643		return 0;
    644
    645	// n_agc_global
    646	agc = dib7000m_read_word(state, 390);
    647
    648	if (agc > state->current_agc->split.min_thres)
    649		split_offset = state->current_agc->split.min;
    650	else if (agc < state->current_agc->split.max_thres)
    651		split_offset = state->current_agc->split.max;
    652	else
    653		split_offset = state->current_agc->split.max *
    654			(agc - state->current_agc->split.min_thres) /
    655			(state->current_agc->split.max_thres - state->current_agc->split.min_thres);
    656
    657	dprintk("AGC split_offset: %d\n", split_offset);
    658
    659	// P_agc_force_split and P_agc_split_offset
    660	return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset);
    661}
    662
    663static int dib7000m_update_lna(struct dib7000m_state *state)
    664{
    665	u16 dyn_gain;
    666
    667	if (state->cfg.update_lna) {
    668		// read dyn_gain here (because it is demod-dependent and not fe)
    669		dyn_gain = dib7000m_read_word(state, 390);
    670
    671		if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
    672			dib7000m_restart_agc(state);
    673			return 1;
    674		}
    675	}
    676	return 0;
    677}
    678
    679static int dib7000m_set_agc_config(struct dib7000m_state *state, u8 band)
    680{
    681	struct dibx000_agc_config *agc = NULL;
    682	int i;
    683	if (state->current_band == band && state->current_agc != NULL)
    684		return 0;
    685	state->current_band = band;
    686
    687	for (i = 0; i < state->cfg.agc_config_count; i++)
    688		if (state->cfg.agc[i].band_caps & band) {
    689			agc = &state->cfg.agc[i];
    690			break;
    691		}
    692
    693	if (agc == NULL) {
    694		dprintk("no valid AGC configuration found for band 0x%02x\n", band);
    695		return -EINVAL;
    696	}
    697
    698	state->current_agc = agc;
    699
    700	/* AGC */
    701	dib7000m_write_word(state, 72 ,  agc->setup);
    702	dib7000m_write_word(state, 73 ,  agc->inv_gain);
    703	dib7000m_write_word(state, 74 ,  agc->time_stabiliz);
    704	dib7000m_write_word(state, 97 , (agc->alpha_level << 12) | agc->thlock);
    705
    706	// Demod AGC loop configuration
    707	dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp);
    708	dib7000m_write_word(state, 99, (agc->beta_mant  << 6) | agc->beta_exp);
    709
    710	dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d\n",
    711		state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
    712
    713	/* AGC continued */
    714	if (state->wbd_ref != 0)
    715		dib7000m_write_word(state, 102, state->wbd_ref);
    716	else // use default
    717		dib7000m_write_word(state, 102, agc->wbd_ref);
    718
    719	dib7000m_write_word(state, 103, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) );
    720	dib7000m_write_word(state, 104,  agc->agc1_max);
    721	dib7000m_write_word(state, 105,  agc->agc1_min);
    722	dib7000m_write_word(state, 106,  agc->agc2_max);
    723	dib7000m_write_word(state, 107,  agc->agc2_min);
    724	dib7000m_write_word(state, 108, (agc->agc1_pt1 << 8) | agc->agc1_pt2 );
    725	dib7000m_write_word(state, 109, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
    726	dib7000m_write_word(state, 110, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
    727	dib7000m_write_word(state, 111, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
    728
    729	if (state->revision > 0x4000) { // settings for the MC
    730		dib7000m_write_word(state, 71,   agc->agc1_pt3);
    731//		dprintk("929: %x %d %d\n",
    732//			(dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel);
    733		dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2));
    734	} else {
    735		// wrong default values
    736		u16 b[9] = { 676, 696, 717, 737, 758, 778, 799, 819, 840 };
    737		for (i = 0; i < 9; i++)
    738			dib7000m_write_word(state, 88 + i, b[i]);
    739	}
    740	return 0;
    741}
    742
    743static void dib7000m_update_timf(struct dib7000m_state *state)
    744{
    745	u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437);
    746	state->timf = timf * 160 / (state->current_bandwidth / 50);
    747	dib7000m_write_word(state, 23, (u16) (timf >> 16));
    748	dib7000m_write_word(state, 24, (u16) (timf & 0xffff));
    749	dprintk("updated timf_frequency: %d (default: %d)\n", state->timf, state->timf_default);
    750}
    751
    752static int dib7000m_agc_startup(struct dvb_frontend *demod)
    753{
    754	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
    755	struct dib7000m_state *state = demod->demodulator_priv;
    756	u16 cfg_72 = dib7000m_read_word(state, 72);
    757	int ret = -1;
    758	u8 *agc_state = &state->agc_state;
    759	u8 agc_split;
    760
    761	switch (state->agc_state) {
    762		case 0:
    763			// set power-up level: interf+analog+AGC
    764			dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC);
    765			dib7000m_set_adc_state(state, DIBX000_ADC_ON);
    766
    767			if (dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0)
    768				return -1;
    769
    770			ret = 7; /* ADC power up */
    771			(*agc_state)++;
    772			break;
    773
    774		case 1:
    775			/* AGC initialization */
    776			if (state->cfg.agc_control)
    777				state->cfg.agc_control(&state->demod, 1);
    778
    779			dib7000m_write_word(state, 75, 32768);
    780			if (!state->current_agc->perform_agc_softsplit) {
    781				/* we are using the wbd - so slow AGC startup */
    782				dib7000m_write_word(state, 103, 1 << 8); /* force 0 split on WBD and restart AGC */
    783				(*agc_state)++;
    784				ret = 5;
    785			} else {
    786				/* default AGC startup */
    787				(*agc_state) = 4;
    788				/* wait AGC rough lock time */
    789				ret = 7;
    790			}
    791
    792			dib7000m_restart_agc(state);
    793			break;
    794
    795		case 2: /* fast split search path after 5sec */
    796			dib7000m_write_word(state,  72, cfg_72 | (1 << 4)); /* freeze AGC loop */
    797			dib7000m_write_word(state, 103, 2 << 9);            /* fast split search 0.25kHz */
    798			(*agc_state)++;
    799			ret = 14;
    800			break;
    801
    802	case 3: /* split search ended */
    803			agc_split = (u8)dib7000m_read_word(state, 392); /* store the split value for the next time */
    804			dib7000m_write_word(state, 75, dib7000m_read_word(state, 390)); /* set AGC gain start value */
    805
    806			dib7000m_write_word(state, 72,  cfg_72 & ~(1 << 4));   /* std AGC loop */
    807			dib7000m_write_word(state, 103, (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */
    808
    809			dib7000m_restart_agc(state);
    810
    811			dprintk("SPLIT %p: %u\n", demod, agc_split);
    812
    813			(*agc_state)++;
    814			ret = 5;
    815			break;
    816
    817		case 4: /* LNA startup */
    818			/* wait AGC accurate lock time */
    819			ret = 7;
    820
    821			if (dib7000m_update_lna(state))
    822				// wait only AGC rough lock time
    823				ret = 5;
    824			else
    825				(*agc_state)++;
    826			break;
    827
    828		case 5:
    829			dib7000m_agc_soft_split(state);
    830
    831			if (state->cfg.agc_control)
    832				state->cfg.agc_control(&state->demod, 0);
    833
    834			(*agc_state)++;
    835			break;
    836
    837		default:
    838			break;
    839	}
    840	return ret;
    841}
    842
    843static void dib7000m_set_channel(struct dib7000m_state *state, struct dtv_frontend_properties *ch,
    844				 u8 seq)
    845{
    846	u16 value, est[4];
    847
    848	dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
    849
    850	/* nfft, guard, qam, alpha */
    851	value = 0;
    852	switch (ch->transmission_mode) {
    853		case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
    854		case TRANSMISSION_MODE_4K: value |= (2 << 7); break;
    855		default:
    856		case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
    857	}
    858	switch (ch->guard_interval) {
    859		case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
    860		case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
    861		case GUARD_INTERVAL_1_4:  value |= (3 << 5); break;
    862		default:
    863		case GUARD_INTERVAL_1_8:  value |= (2 << 5); break;
    864	}
    865	switch (ch->modulation) {
    866		case QPSK:  value |= (0 << 3); break;
    867		case QAM_16: value |= (1 << 3); break;
    868		default:
    869		case QAM_64: value |= (2 << 3); break;
    870	}
    871	switch (HIERARCHY_1) {
    872		case HIERARCHY_2: value |= 2; break;
    873		case HIERARCHY_4: value |= 4; break;
    874		default:
    875		case HIERARCHY_1: value |= 1; break;
    876	}
    877	dib7000m_write_word(state, 0, value);
    878	dib7000m_write_word(state, 5, (seq << 4));
    879
    880	/* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
    881	value = 0;
    882	if (1 != 0)
    883		value |= (1 << 6);
    884	if (ch->hierarchy == 1)
    885		value |= (1 << 4);
    886	if (1 == 1)
    887		value |= 1;
    888	switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
    889		case FEC_2_3: value |= (2 << 1); break;
    890		case FEC_3_4: value |= (3 << 1); break;
    891		case FEC_5_6: value |= (5 << 1); break;
    892		case FEC_7_8: value |= (7 << 1); break;
    893		default:
    894		case FEC_1_2: value |= (1 << 1); break;
    895	}
    896	dib7000m_write_word(state, 267 + state->reg_offs, value);
    897
    898	/* offset loop parameters */
    899
    900	/* P_timf_alpha = 6, P_corm_alpha=6, P_corm_thres=0x80 */
    901	dib7000m_write_word(state, 26, (6 << 12) | (6 << 8) | 0x80);
    902
    903	/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=1, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
    904	dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (1 << 9) | (3 << 5) | (1 << 4) | (0x3));
    905
    906	/* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max=3 */
    907	dib7000m_write_word(state, 32, (0 << 4) | 0x3);
    908
    909	/* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step=5 */
    910	dib7000m_write_word(state, 33, (0 << 4) | 0x5);
    911
    912	/* P_dvsy_sync_wait */
    913	switch (ch->transmission_mode) {
    914		case TRANSMISSION_MODE_8K: value = 256; break;
    915		case TRANSMISSION_MODE_4K: value = 128; break;
    916		case TRANSMISSION_MODE_2K:
    917		default: value = 64; break;
    918	}
    919	switch (ch->guard_interval) {
    920		case GUARD_INTERVAL_1_16: value *= 2; break;
    921		case GUARD_INTERVAL_1_8:  value *= 4; break;
    922		case GUARD_INTERVAL_1_4:  value *= 8; break;
    923		default:
    924		case GUARD_INTERVAL_1_32: value *= 1; break;
    925	}
    926	state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO
    927
    928	/* deactivate the possibility of diversity reception if extended interleave - not for 7000MC */
    929	/* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
    930	if (1 == 1 || state->revision > 0x4000)
    931		state->div_force_off = 0;
    932	else
    933		state->div_force_off = 1;
    934	dib7000m_set_diversity_in(&state->demod, state->div_state);
    935
    936	/* channel estimation fine configuration */
    937	switch (ch->modulation) {
    938		case QAM_64:
    939			est[0] = 0x0148;       /* P_adp_regul_cnt 0.04 */
    940			est[1] = 0xfff0;       /* P_adp_noise_cnt -0.002 */
    941			est[2] = 0x00a4;       /* P_adp_regul_ext 0.02 */
    942			est[3] = 0xfff8;       /* P_adp_noise_ext -0.001 */
    943			break;
    944		case QAM_16:
    945			est[0] = 0x023d;       /* P_adp_regul_cnt 0.07 */
    946			est[1] = 0xffdf;       /* P_adp_noise_cnt -0.004 */
    947			est[2] = 0x00a4;       /* P_adp_regul_ext 0.02 */
    948			est[3] = 0xfff0;       /* P_adp_noise_ext -0.002 */
    949			break;
    950		default:
    951			est[0] = 0x099a;       /* P_adp_regul_cnt 0.3 */
    952			est[1] = 0xffae;       /* P_adp_noise_cnt -0.01 */
    953			est[2] = 0x0333;       /* P_adp_regul_ext 0.1 */
    954			est[3] = 0xfff8;       /* P_adp_noise_ext -0.002 */
    955			break;
    956	}
    957	for (value = 0; value < 4; value++)
    958		dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]);
    959
    960	// set power-up level: autosearch
    961	dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD);
    962}
    963
    964static int dib7000m_autosearch_start(struct dvb_frontend *demod)
    965{
    966	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
    967	struct dib7000m_state *state = demod->demodulator_priv;
    968	struct dtv_frontend_properties schan;
    969	int ret = 0;
    970	u32 value, factor;
    971
    972	schan = *ch;
    973
    974	schan.modulation = QAM_64;
    975	schan.guard_interval        = GUARD_INTERVAL_1_32;
    976	schan.transmission_mode         = TRANSMISSION_MODE_8K;
    977	schan.code_rate_HP = FEC_2_3;
    978	schan.code_rate_LP = FEC_3_4;
    979	schan.hierarchy    = 0;
    980
    981	dib7000m_set_channel(state, &schan, 7);
    982
    983	factor = BANDWIDTH_TO_KHZ(schan.bandwidth_hz);
    984	if (factor >= 5000)
    985		factor = 1;
    986	else
    987		factor = 6;
    988
    989	// always use the setting for 8MHz here lock_time for 7,6 MHz are longer
    990	value = 30 * state->internal_clk * factor;
    991	ret |= dib7000m_write_word(state, 6,  (u16) ((value >> 16) & 0xffff)); // lock0 wait time
    992	ret |= dib7000m_write_word(state, 7,  (u16)  (value        & 0xffff)); // lock0 wait time
    993	value = 100 * state->internal_clk * factor;
    994	ret |= dib7000m_write_word(state, 8,  (u16) ((value >> 16) & 0xffff)); // lock1 wait time
    995	ret |= dib7000m_write_word(state, 9,  (u16)  (value        & 0xffff)); // lock1 wait time
    996	value = 500 * state->internal_clk * factor;
    997	ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time
    998	ret |= dib7000m_write_word(state, 11, (u16)  (value        & 0xffff)); // lock2 wait time
    999
   1000	// start search
   1001	value = dib7000m_read_word(state, 0);
   1002	ret |= dib7000m_write_word(state, 0, (u16) (value | (1 << 9)));
   1003
   1004	/* clear n_irq_pending */
   1005	if (state->revision == 0x4000)
   1006		dib7000m_write_word(state, 1793, 0);
   1007	else
   1008		dib7000m_read_word(state, 537);
   1009
   1010	ret |= dib7000m_write_word(state, 0, (u16) value);
   1011
   1012	return ret;
   1013}
   1014
   1015static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg)
   1016{
   1017	u16 irq_pending = dib7000m_read_word(state, reg);
   1018
   1019	if (irq_pending & 0x1) { // failed
   1020		dprintk("autosearch failed\n");
   1021		return 1;
   1022	}
   1023
   1024	if (irq_pending & 0x2) { // succeeded
   1025		dprintk("autosearch succeeded\n");
   1026		return 2;
   1027	}
   1028	return 0; // still pending
   1029}
   1030
   1031static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod)
   1032{
   1033	struct dib7000m_state *state = demod->demodulator_priv;
   1034	if (state->revision == 0x4000)
   1035		return dib7000m_autosearch_irq(state, 1793);
   1036	else
   1037		return dib7000m_autosearch_irq(state, 537);
   1038}
   1039
   1040static int dib7000m_tune(struct dvb_frontend *demod)
   1041{
   1042	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
   1043	struct dib7000m_state *state = demod->demodulator_priv;
   1044	int ret = 0;
   1045	u16 value;
   1046
   1047	// we are already tuned - just resuming from suspend
   1048	dib7000m_set_channel(state, ch, 0);
   1049
   1050	// restart demod
   1051	ret |= dib7000m_write_word(state, 898, 0x4000);
   1052	ret |= dib7000m_write_word(state, 898, 0x0000);
   1053	msleep(45);
   1054
   1055	dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD);
   1056	/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
   1057	ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3));
   1058
   1059	// never achieved a lock before - wait for timfreq to update
   1060	if (state->timf == 0)
   1061		msleep(200);
   1062
   1063	//dump_reg(state);
   1064	/* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
   1065	value = (6 << 8) | 0x80;
   1066	switch (ch->transmission_mode) {
   1067		case TRANSMISSION_MODE_2K: value |= (7 << 12); break;
   1068		case TRANSMISSION_MODE_4K: value |= (8 << 12); break;
   1069		default:
   1070		case TRANSMISSION_MODE_8K: value |= (9 << 12); break;
   1071	}
   1072	ret |= dib7000m_write_word(state, 26, value);
   1073
   1074	/* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
   1075	value = (0 << 4);
   1076	switch (ch->transmission_mode) {
   1077		case TRANSMISSION_MODE_2K: value |= 0x6; break;
   1078		case TRANSMISSION_MODE_4K: value |= 0x7; break;
   1079		default:
   1080		case TRANSMISSION_MODE_8K: value |= 0x8; break;
   1081	}
   1082	ret |= dib7000m_write_word(state, 32, value);
   1083
   1084	/* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
   1085	value = (0 << 4);
   1086	switch (ch->transmission_mode) {
   1087		case TRANSMISSION_MODE_2K: value |= 0x6; break;
   1088		case TRANSMISSION_MODE_4K: value |= 0x7; break;
   1089		default:
   1090		case TRANSMISSION_MODE_8K: value |= 0x8; break;
   1091	}
   1092	ret |= dib7000m_write_word(state, 33,  value);
   1093
   1094	// we achieved a lock - it's time to update the timf freq
   1095	if ((dib7000m_read_word(state, 535) >> 6)  & 0x1)
   1096		dib7000m_update_timf(state);
   1097
   1098	dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
   1099	return ret;
   1100}
   1101
   1102static int dib7000m_wakeup(struct dvb_frontend *demod)
   1103{
   1104	struct dib7000m_state *state = demod->demodulator_priv;
   1105
   1106	dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
   1107
   1108	if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
   1109		dprintk("could not start Slow ADC\n");
   1110
   1111	return 0;
   1112}
   1113
   1114static int dib7000m_sleep(struct dvb_frontend *demod)
   1115{
   1116	struct dib7000m_state *st = demod->demodulator_priv;
   1117	dib7000m_set_output_mode(st, OUTMODE_HIGH_Z);
   1118	dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY);
   1119	return dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) |
   1120		dib7000m_set_adc_state(st, DIBX000_ADC_OFF);
   1121}
   1122
   1123static int dib7000m_identify(struct dib7000m_state *state)
   1124{
   1125	u16 value;
   1126
   1127	if ((value = dib7000m_read_word(state, 896)) != 0x01b3) {
   1128		dprintk("wrong Vendor ID (0x%x)\n", value);
   1129		return -EREMOTEIO;
   1130	}
   1131
   1132	state->revision = dib7000m_read_word(state, 897);
   1133	if (state->revision != 0x4000 &&
   1134		state->revision != 0x4001 &&
   1135		state->revision != 0x4002 &&
   1136		state->revision != 0x4003) {
   1137		dprintk("wrong Device ID (0x%x)\n", value);
   1138		return -EREMOTEIO;
   1139	}
   1140
   1141	/* protect this driver to be used with 7000PC */
   1142	if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) {
   1143		dprintk("this driver does not work with DiB7000PC\n");
   1144		return -EREMOTEIO;
   1145	}
   1146
   1147	switch (state->revision) {
   1148	case 0x4000: dprintk("found DiB7000MA/PA/MB/PB\n"); break;
   1149	case 0x4001: state->reg_offs = 1; dprintk("found DiB7000HC\n"); break;
   1150	case 0x4002: state->reg_offs = 1; dprintk("found DiB7000MC\n"); break;
   1151	case 0x4003: state->reg_offs = 1; dprintk("found DiB9000\n"); break;
   1152	}
   1153
   1154	return 0;
   1155}
   1156
   1157
   1158static int dib7000m_get_frontend(struct dvb_frontend* fe,
   1159				 struct dtv_frontend_properties *fep)
   1160{
   1161	struct dib7000m_state *state = fe->demodulator_priv;
   1162	u16 tps = dib7000m_read_word(state,480);
   1163
   1164	fep->inversion = INVERSION_AUTO;
   1165
   1166	fep->bandwidth_hz = BANDWIDTH_TO_HZ(state->current_bandwidth);
   1167
   1168	switch ((tps >> 8) & 0x3) {
   1169		case 0: fep->transmission_mode = TRANSMISSION_MODE_2K; break;
   1170		case 1: fep->transmission_mode = TRANSMISSION_MODE_8K; break;
   1171		/* case 2: fep->transmission_mode = TRANSMISSION_MODE_4K; break; */
   1172	}
   1173
   1174	switch (tps & 0x3) {
   1175		case 0: fep->guard_interval = GUARD_INTERVAL_1_32; break;
   1176		case 1: fep->guard_interval = GUARD_INTERVAL_1_16; break;
   1177		case 2: fep->guard_interval = GUARD_INTERVAL_1_8; break;
   1178		case 3: fep->guard_interval = GUARD_INTERVAL_1_4; break;
   1179	}
   1180
   1181	switch ((tps >> 14) & 0x3) {
   1182		case 0: fep->modulation = QPSK; break;
   1183		case 1: fep->modulation = QAM_16; break;
   1184		case 2:
   1185		default: fep->modulation = QAM_64; break;
   1186	}
   1187
   1188	/* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
   1189	/* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
   1190
   1191	fep->hierarchy = HIERARCHY_NONE;
   1192	switch ((tps >> 5) & 0x7) {
   1193		case 1: fep->code_rate_HP = FEC_1_2; break;
   1194		case 2: fep->code_rate_HP = FEC_2_3; break;
   1195		case 3: fep->code_rate_HP = FEC_3_4; break;
   1196		case 5: fep->code_rate_HP = FEC_5_6; break;
   1197		case 7:
   1198		default: fep->code_rate_HP = FEC_7_8; break;
   1199
   1200	}
   1201
   1202	switch ((tps >> 2) & 0x7) {
   1203		case 1: fep->code_rate_LP = FEC_1_2; break;
   1204		case 2: fep->code_rate_LP = FEC_2_3; break;
   1205		case 3: fep->code_rate_LP = FEC_3_4; break;
   1206		case 5: fep->code_rate_LP = FEC_5_6; break;
   1207		case 7:
   1208		default: fep->code_rate_LP = FEC_7_8; break;
   1209	}
   1210
   1211	/* native interleaver: (dib7000m_read_word(state, 481) >>  5) & 0x1 */
   1212
   1213	return 0;
   1214}
   1215
   1216static int dib7000m_set_frontend(struct dvb_frontend *fe)
   1217{
   1218	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
   1219	struct dib7000m_state *state = fe->demodulator_priv;
   1220	int time, ret;
   1221
   1222	dib7000m_set_output_mode(state, OUTMODE_HIGH_Z);
   1223
   1224	dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->bandwidth_hz));
   1225
   1226	if (fe->ops.tuner_ops.set_params)
   1227		fe->ops.tuner_ops.set_params(fe);
   1228
   1229	/* start up the AGC */
   1230	state->agc_state = 0;
   1231	do {
   1232		time = dib7000m_agc_startup(fe);
   1233		if (time != -1)
   1234			msleep(time);
   1235	} while (time != -1);
   1236
   1237	if (fep->transmission_mode == TRANSMISSION_MODE_AUTO ||
   1238		fep->guard_interval    == GUARD_INTERVAL_AUTO ||
   1239		fep->modulation        == QAM_AUTO ||
   1240		fep->code_rate_HP      == FEC_AUTO) {
   1241		int i = 800, found;
   1242
   1243		dib7000m_autosearch_start(fe);
   1244		do {
   1245			msleep(1);
   1246			found = dib7000m_autosearch_is_irq(fe);
   1247		} while (found == 0 && i--);
   1248
   1249		dprintk("autosearch returns: %d\n", found);
   1250		if (found == 0 || found == 1)
   1251			return 0; // no channel found
   1252
   1253		dib7000m_get_frontend(fe, fep);
   1254	}
   1255
   1256	ret = dib7000m_tune(fe);
   1257
   1258	/* make this a config parameter */
   1259	dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO);
   1260	return ret;
   1261}
   1262
   1263static int dib7000m_read_status(struct dvb_frontend *fe, enum fe_status *stat)
   1264{
   1265	struct dib7000m_state *state = fe->demodulator_priv;
   1266	u16 lock = dib7000m_read_word(state, 535);
   1267
   1268	*stat = 0;
   1269
   1270	if (lock & 0x8000)
   1271		*stat |= FE_HAS_SIGNAL;
   1272	if (lock & 0x3000)
   1273		*stat |= FE_HAS_CARRIER;
   1274	if (lock & 0x0100)
   1275		*stat |= FE_HAS_VITERBI;
   1276	if (lock & 0x0010)
   1277		*stat |= FE_HAS_SYNC;
   1278	if (lock & 0x0008)
   1279		*stat |= FE_HAS_LOCK;
   1280
   1281	return 0;
   1282}
   1283
   1284static int dib7000m_read_ber(struct dvb_frontend *fe, u32 *ber)
   1285{
   1286	struct dib7000m_state *state = fe->demodulator_priv;
   1287	*ber = (dib7000m_read_word(state, 526) << 16) | dib7000m_read_word(state, 527);
   1288	return 0;
   1289}
   1290
   1291static int dib7000m_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
   1292{
   1293	struct dib7000m_state *state = fe->demodulator_priv;
   1294	*unc = dib7000m_read_word(state, 534);
   1295	return 0;
   1296}
   1297
   1298static int dib7000m_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
   1299{
   1300	struct dib7000m_state *state = fe->demodulator_priv;
   1301	u16 val = dib7000m_read_word(state, 390);
   1302	*strength = 65535 - val;
   1303	return 0;
   1304}
   1305
   1306static int dib7000m_read_snr(struct dvb_frontend* fe, u16 *snr)
   1307{
   1308	*snr = 0x0000;
   1309	return 0;
   1310}
   1311
   1312static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
   1313{
   1314	tune->min_delay_ms = 1000;
   1315	return 0;
   1316}
   1317
   1318static void dib7000m_release(struct dvb_frontend *demod)
   1319{
   1320	struct dib7000m_state *st = demod->demodulator_priv;
   1321	dibx000_exit_i2c_master(&st->i2c_master);
   1322	kfree(st);
   1323}
   1324
   1325struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
   1326{
   1327	struct dib7000m_state *st = demod->demodulator_priv;
   1328	return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
   1329}
   1330EXPORT_SYMBOL(dib7000m_get_i2c_master);
   1331
   1332int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
   1333{
   1334	struct dib7000m_state *state = fe->demodulator_priv;
   1335	u16 val = dib7000m_read_word(state, 294 + state->reg_offs) & 0xffef;
   1336	val |= (onoff & 0x1) << 4;
   1337	dprintk("PID filter enabled %d\n", onoff);
   1338	return dib7000m_write_word(state, 294 + state->reg_offs, val);
   1339}
   1340EXPORT_SYMBOL(dib7000m_pid_filter_ctrl);
   1341
   1342int dib7000m_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
   1343{
   1344	struct dib7000m_state *state = fe->demodulator_priv;
   1345	dprintk("PID filter: index %x, PID %d, OnOff %d\n", id, pid, onoff);
   1346	return dib7000m_write_word(state, 300 + state->reg_offs + id,
   1347			onoff ? (1 << 13) | pid : 0);
   1348}
   1349EXPORT_SYMBOL(dib7000m_pid_filter);
   1350
   1351#if 0
   1352/* used with some prototype boards */
   1353int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods,
   1354		u8 default_addr, struct dib7000m_config cfg[])
   1355{
   1356	struct dib7000m_state st = { .i2c_adap = i2c };
   1357	int k = 0;
   1358	u8 new_addr = 0;
   1359
   1360	for (k = no_of_demods-1; k >= 0; k--) {
   1361		st.cfg = cfg[k];
   1362
   1363		/* designated i2c address */
   1364		new_addr          = (0x40 + k) << 1;
   1365		st.i2c_addr = new_addr;
   1366		if (dib7000m_identify(&st) != 0) {
   1367			st.i2c_addr = default_addr;
   1368			if (dib7000m_identify(&st) != 0) {
   1369				dprintk("DiB7000M #%d: not identified\n", k);
   1370				return -EIO;
   1371			}
   1372		}
   1373
   1374		/* start diversity to pull_down div_str - just for i2c-enumeration */
   1375		dib7000m_set_output_mode(&st, OUTMODE_DIVERSITY);
   1376
   1377		dib7000m_write_word(&st, 1796, 0x0); // select DVB-T output
   1378
   1379		/* set new i2c address and force divstart */
   1380		dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2);
   1381
   1382		dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr);
   1383	}
   1384
   1385	for (k = 0; k < no_of_demods; k++) {
   1386		st.cfg = cfg[k];
   1387		st.i2c_addr = (0x40 + k) << 1;
   1388
   1389		// unforce divstr
   1390		dib7000m_write_word(&st,1794, st.i2c_addr << 2);
   1391
   1392		/* deactivate div - it was just for i2c-enumeration */
   1393		dib7000m_set_output_mode(&st, OUTMODE_HIGH_Z);
   1394	}
   1395
   1396	return 0;
   1397}
   1398EXPORT_SYMBOL(dib7000m_i2c_enumeration);
   1399#endif
   1400
   1401static const struct dvb_frontend_ops dib7000m_ops;
   1402struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg)
   1403{
   1404	struct dvb_frontend *demod;
   1405	struct dib7000m_state *st;
   1406	st = kzalloc(sizeof(struct dib7000m_state), GFP_KERNEL);
   1407	if (st == NULL)
   1408		return NULL;
   1409
   1410	memcpy(&st->cfg, cfg, sizeof(struct dib7000m_config));
   1411	st->i2c_adap = i2c_adap;
   1412	st->i2c_addr = i2c_addr;
   1413
   1414	demod                   = &st->demod;
   1415	demod->demodulator_priv = st;
   1416	memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops));
   1417	mutex_init(&st->i2c_buffer_lock);
   1418
   1419	st->timf_default = cfg->bw->timf;
   1420
   1421	if (dib7000m_identify(st) != 0)
   1422		goto error;
   1423
   1424	if (st->revision == 0x4000)
   1425		dibx000_init_i2c_master(&st->i2c_master, DIB7000, st->i2c_adap, st->i2c_addr);
   1426	else
   1427		dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c_adap, st->i2c_addr);
   1428
   1429	dib7000m_demod_reset(st);
   1430
   1431	return demod;
   1432
   1433error:
   1434	kfree(st);
   1435	return NULL;
   1436}
   1437EXPORT_SYMBOL(dib7000m_attach);
   1438
   1439static const struct dvb_frontend_ops dib7000m_ops = {
   1440	.delsys = { SYS_DVBT },
   1441	.info = {
   1442		.name = "DiBcom 7000MA/MB/PA/PB/MC",
   1443		.frequency_min_hz      =  44250 * kHz,
   1444		.frequency_max_hz      = 867250 * kHz,
   1445		.frequency_stepsize_hz = 62500,
   1446		.caps = FE_CAN_INVERSION_AUTO |
   1447			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
   1448			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
   1449			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
   1450			FE_CAN_TRANSMISSION_MODE_AUTO |
   1451			FE_CAN_GUARD_INTERVAL_AUTO |
   1452			FE_CAN_RECOVER |
   1453			FE_CAN_HIERARCHY_AUTO,
   1454	},
   1455
   1456	.release              = dib7000m_release,
   1457
   1458	.init                 = dib7000m_wakeup,
   1459	.sleep                = dib7000m_sleep,
   1460
   1461	.set_frontend         = dib7000m_set_frontend,
   1462	.get_tune_settings    = dib7000m_fe_get_tune_settings,
   1463	.get_frontend         = dib7000m_get_frontend,
   1464
   1465	.read_status          = dib7000m_read_status,
   1466	.read_ber             = dib7000m_read_ber,
   1467	.read_signal_strength = dib7000m_read_signal_strength,
   1468	.read_snr             = dib7000m_read_snr,
   1469	.read_ucblocks        = dib7000m_read_unc_blocks,
   1470};
   1471
   1472MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
   1473MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator");
   1474MODULE_LICENSE("GPL");