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

dib3000mc.c (26792B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Driver for DiBcom DiB3000MC/P-demodulator.
      4 *
      5 * Copyright (C) 2004-7 DiBcom (http://www.dibcom.fr/)
      6 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de)
      7 *
      8 * This code is partially based on the previous dib3000mc.c .
      9 */
     10
     11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     12
     13#include <linux/kernel.h>
     14#include <linux/slab.h>
     15#include <linux/i2c.h>
     16
     17#include <media/dvb_frontend.h>
     18
     19#include "dib3000mc.h"
     20
     21static int debug;
     22module_param(debug, int, 0644);
     23MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
     24
     25static int buggy_sfn_workaround;
     26module_param(buggy_sfn_workaround, int, 0644);
     27MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)");
     28
     29#define dprintk(fmt, arg...) do {					\
     30	if (debug)							\
     31		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
     32		       __func__, ##arg);				\
     33} while (0)
     34
     35struct dib3000mc_state {
     36	struct dvb_frontend demod;
     37	struct dib3000mc_config *cfg;
     38
     39	u8 i2c_addr;
     40	struct i2c_adapter *i2c_adap;
     41
     42	struct dibx000_i2c_master i2c_master;
     43
     44	u32 timf;
     45
     46	u32 current_bandwidth;
     47
     48	u16 dev_id;
     49
     50	u8 sfn_workaround_active :1;
     51};
     52
     53static u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg)
     54{
     55	struct i2c_msg msg[2] = {
     56		{ .addr = state->i2c_addr >> 1, .flags = 0,        .len = 2 },
     57		{ .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .len = 2 },
     58	};
     59	u16 word;
     60	u8 *b;
     61
     62	b = kmalloc(4, GFP_KERNEL);
     63	if (!b)
     64		return 0;
     65
     66	b[0] = (reg >> 8) | 0x80;
     67	b[1] = reg;
     68	b[2] = 0;
     69	b[3] = 0;
     70
     71	msg[0].buf = b;
     72	msg[1].buf = b + 2;
     73
     74	if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
     75		dprintk("i2c read error on %d\n",reg);
     76
     77	word = (b[2] << 8) | b[3];
     78	kfree(b);
     79
     80	return word;
     81}
     82
     83static int dib3000mc_write_word(struct dib3000mc_state *state, u16 reg, u16 val)
     84{
     85	struct i2c_msg msg = {
     86		.addr = state->i2c_addr >> 1, .flags = 0, .len = 4
     87	};
     88	int rc;
     89	u8 *b;
     90
     91	b = kmalloc(4, GFP_KERNEL);
     92	if (!b)
     93		return -ENOMEM;
     94
     95	b[0] = reg >> 8;
     96	b[1] = reg;
     97	b[2] = val >> 8;
     98	b[3] = val;
     99
    100	msg.buf = b;
    101
    102	rc = i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
    103	kfree(b);
    104
    105	return rc;
    106}
    107
    108static int dib3000mc_identify(struct dib3000mc_state *state)
    109{
    110	u16 value;
    111	if ((value = dib3000mc_read_word(state, 1025)) != 0x01b3) {
    112		dprintk("-E-  DiB3000MC/P: wrong Vendor ID (read=0x%x)\n",value);
    113		return -EREMOTEIO;
    114	}
    115
    116	value = dib3000mc_read_word(state, 1026);
    117	if (value != 0x3001 && value != 0x3002) {
    118		dprintk("-E-  DiB3000MC/P: wrong Device ID (%x)\n",value);
    119		return -EREMOTEIO;
    120	}
    121	state->dev_id = value;
    122
    123	dprintk("-I-  found DiB3000MC/P: %x\n",state->dev_id);
    124
    125	return 0;
    126}
    127
    128static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u32 bw, u8 update_offset)
    129{
    130	u32 timf;
    131
    132	if (state->timf == 0) {
    133		timf = 1384402; // default value for 8MHz
    134		if (update_offset)
    135			msleep(200); // first time we do an update
    136	} else
    137		timf = state->timf;
    138
    139	timf *= (bw / 1000);
    140
    141	if (update_offset) {
    142		s16 tim_offs = dib3000mc_read_word(state, 416);
    143
    144		if (tim_offs &  0x2000)
    145			tim_offs -= 0x4000;
    146
    147		if (nfft == TRANSMISSION_MODE_2K)
    148			tim_offs *= 4;
    149
    150		timf += tim_offs;
    151		state->timf = timf / (bw / 1000);
    152	}
    153
    154	dprintk("timf: %d\n", timf);
    155
    156	dib3000mc_write_word(state, 23, (u16) (timf >> 16));
    157	dib3000mc_write_word(state, 24, (u16) (timf      ) & 0xffff);
    158
    159	return 0;
    160}
    161
    162static int dib3000mc_setup_pwm_state(struct dib3000mc_state *state)
    163{
    164	u16 reg_51, reg_52 = state->cfg->agc->setup & 0xfefb;
    165	if (state->cfg->pwm3_inversion) {
    166		reg_51 =  (2 << 14) | (0 << 10) | (7 << 6) | (2 << 2) | (2 << 0);
    167		reg_52 |= (1 << 2);
    168	} else {
    169		reg_51 = (2 << 14) | (4 << 10) | (7 << 6) | (2 << 2) | (2 << 0);
    170		reg_52 |= (1 << 8);
    171	}
    172	dib3000mc_write_word(state, 51, reg_51);
    173	dib3000mc_write_word(state, 52, reg_52);
    174
    175	if (state->cfg->use_pwm3)
    176		dib3000mc_write_word(state, 245, (1 << 3) | (1 << 0));
    177	else
    178		dib3000mc_write_word(state, 245, 0);
    179
    180	dib3000mc_write_word(state, 1040, 0x3);
    181	return 0;
    182}
    183
    184static int dib3000mc_set_output_mode(struct dib3000mc_state *state, int mode)
    185{
    186	int    ret = 0;
    187	u16 fifo_threshold = 1792;
    188	u16 outreg = 0;
    189	u16 outmode = 0;
    190	u16 elecout = 1;
    191	u16 smo_reg = dib3000mc_read_word(state, 206) & 0x0010; /* keep the pid_parse bit */
    192
    193	dprintk("-I-  Setting output mode for demod %p to %d\n",
    194			&state->demod, mode);
    195
    196	switch (mode) {
    197		case OUTMODE_HIGH_Z:  // disable
    198			elecout = 0;
    199			break;
    200		case OUTMODE_MPEG2_PAR_GATED_CLK:   // STBs with parallel gated clock
    201			outmode = 0;
    202			break;
    203		case OUTMODE_MPEG2_PAR_CONT_CLK:    // STBs with parallel continues clock
    204			outmode = 1;
    205			break;
    206		case OUTMODE_MPEG2_SERIAL:          // STBs with serial input
    207			outmode = 2;
    208			break;
    209		case OUTMODE_MPEG2_FIFO:            // e.g. USB feeding
    210			elecout = 3;
    211			/*ADDR @ 206 :
    212			P_smo_error_discard  [1;6:6] = 0
    213			P_smo_rs_discard     [1;5:5] = 0
    214			P_smo_pid_parse      [1;4:4] = 0
    215			P_smo_fifo_flush     [1;3:3] = 0
    216			P_smo_mode           [2;2:1] = 11
    217			P_smo_ovf_prot       [1;0:0] = 0
    218			*/
    219			smo_reg |= 3 << 1;
    220			fifo_threshold = 512;
    221			outmode = 5;
    222			break;
    223		case OUTMODE_DIVERSITY:
    224			outmode = 4;
    225			elecout = 1;
    226			break;
    227		default:
    228			dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod);
    229			outmode = 0;
    230			break;
    231	}
    232
    233	if ((state->cfg->output_mpeg2_in_188_bytes))
    234		smo_reg |= (1 << 5); // P_smo_rs_discard     [1;5:5] = 1
    235
    236	outreg = dib3000mc_read_word(state, 244) & 0x07FF;
    237	outreg |= (outmode << 11);
    238	ret |= dib3000mc_write_word(state,  244, outreg);
    239	ret |= dib3000mc_write_word(state,  206, smo_reg);   /*smo_ mode*/
    240	ret |= dib3000mc_write_word(state,  207, fifo_threshold); /* synchronous fread */
    241	ret |= dib3000mc_write_word(state, 1040, elecout);         /* P_out_cfg */
    242	return ret;
    243}
    244
    245static int dib3000mc_set_bandwidth(struct dib3000mc_state *state, u32 bw)
    246{
    247	u16 bw_cfg[6] = { 0 };
    248	u16 imp_bw_cfg[3] = { 0 };
    249	u16 reg;
    250
    251/* settings here are for 27.7MHz */
    252	switch (bw) {
    253		case 8000:
    254			bw_cfg[0] = 0x0019; bw_cfg[1] = 0x5c30; bw_cfg[2] = 0x0054; bw_cfg[3] = 0x88a0; bw_cfg[4] = 0x01a6; bw_cfg[5] = 0xab20;
    255			imp_bw_cfg[0] = 0x04db; imp_bw_cfg[1] = 0x00db; imp_bw_cfg[2] = 0x00b7;
    256			break;
    257
    258		case 7000:
    259			bw_cfg[0] = 0x001c; bw_cfg[1] = 0xfba5; bw_cfg[2] = 0x0060; bw_cfg[3] = 0x9c25; bw_cfg[4] = 0x01e3; bw_cfg[5] = 0x0cb7;
    260			imp_bw_cfg[0] = 0x04c0; imp_bw_cfg[1] = 0x00c0; imp_bw_cfg[2] = 0x00a0;
    261			break;
    262
    263		case 6000:
    264			bw_cfg[0] = 0x0021; bw_cfg[1] = 0xd040; bw_cfg[2] = 0x0070; bw_cfg[3] = 0xb62b; bw_cfg[4] = 0x0233; bw_cfg[5] = 0x8ed5;
    265			imp_bw_cfg[0] = 0x04a5; imp_bw_cfg[1] = 0x00a5; imp_bw_cfg[2] = 0x0089;
    266			break;
    267
    268		case 5000:
    269			bw_cfg[0] = 0x0028; bw_cfg[1] = 0x9380; bw_cfg[2] = 0x0087; bw_cfg[3] = 0x4100; bw_cfg[4] = 0x02a4; bw_cfg[5] = 0x4500;
    270			imp_bw_cfg[0] = 0x0489; imp_bw_cfg[1] = 0x0089; imp_bw_cfg[2] = 0x0072;
    271			break;
    272
    273		default: return -EINVAL;
    274	}
    275
    276	for (reg = 6; reg < 12; reg++)
    277		dib3000mc_write_word(state, reg, bw_cfg[reg - 6]);
    278	dib3000mc_write_word(state, 12, 0x0000);
    279	dib3000mc_write_word(state, 13, 0x03e8);
    280	dib3000mc_write_word(state, 14, 0x0000);
    281	dib3000mc_write_word(state, 15, 0x03f2);
    282	dib3000mc_write_word(state, 16, 0x0001);
    283	dib3000mc_write_word(state, 17, 0xb0d0);
    284	// P_sec_len
    285	dib3000mc_write_word(state, 18, 0x0393);
    286	dib3000mc_write_word(state, 19, 0x8700);
    287
    288	for (reg = 55; reg < 58; reg++)
    289		dib3000mc_write_word(state, reg, imp_bw_cfg[reg - 55]);
    290
    291	// Timing configuration
    292	dib3000mc_set_timing(state, TRANSMISSION_MODE_2K, bw, 0);
    293
    294	return 0;
    295}
    296
    297static u16 impulse_noise_val[29] =
    298
    299{
    300	0x38, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c, 0x3ffe, 0x7f3,
    301	0x2d94, 0x76, 0x53d, 0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3, 0x3feb, 0x7d2,
    302	0x365e, 0x76, 0x48c, 0x3ffe, 0x5b3, 0x3feb, 0x76, 0x0000, 0xd
    303};
    304
    305static void dib3000mc_set_impulse_noise(struct dib3000mc_state *state, u8 mode, s16 nfft)
    306{
    307	u16 i;
    308	for (i = 58; i < 87; i++)
    309		dib3000mc_write_word(state, i, impulse_noise_val[i-58]);
    310
    311	if (nfft == TRANSMISSION_MODE_8K) {
    312		dib3000mc_write_word(state, 58, 0x3b);
    313		dib3000mc_write_word(state, 84, 0x00);
    314		dib3000mc_write_word(state, 85, 0x8200);
    315	}
    316
    317	dib3000mc_write_word(state, 34, 0x1294);
    318	dib3000mc_write_word(state, 35, 0x1ff8);
    319	if (mode == 1)
    320		dib3000mc_write_word(state, 55, dib3000mc_read_word(state, 55) | (1 << 10));
    321}
    322
    323static int dib3000mc_init(struct dvb_frontend *demod)
    324{
    325	struct dib3000mc_state *state = demod->demodulator_priv;
    326	struct dibx000_agc_config *agc = state->cfg->agc;
    327
    328	// Restart Configuration
    329	dib3000mc_write_word(state, 1027, 0x8000);
    330	dib3000mc_write_word(state, 1027, 0x0000);
    331
    332	// power up the demod + mobility configuration
    333	dib3000mc_write_word(state, 140, 0x0000);
    334	dib3000mc_write_word(state, 1031, 0);
    335
    336	if (state->cfg->mobile_mode) {
    337		dib3000mc_write_word(state, 139,  0x0000);
    338		dib3000mc_write_word(state, 141,  0x0000);
    339		dib3000mc_write_word(state, 175,  0x0002);
    340		dib3000mc_write_word(state, 1032, 0x0000);
    341	} else {
    342		dib3000mc_write_word(state, 139,  0x0001);
    343		dib3000mc_write_word(state, 141,  0x0000);
    344		dib3000mc_write_word(state, 175,  0x0000);
    345		dib3000mc_write_word(state, 1032, 0x012C);
    346	}
    347	dib3000mc_write_word(state, 1033, 0x0000);
    348
    349	// P_clk_cfg
    350	dib3000mc_write_word(state, 1037, 0x3130);
    351
    352	// other configurations
    353
    354	// P_ctrl_sfreq
    355	dib3000mc_write_word(state, 33, (5 << 0));
    356	dib3000mc_write_word(state, 88, (1 << 10) | (0x10 << 0));
    357
    358	// Phase noise control
    359	// P_fft_phacor_inh, P_fft_phacor_cpe, P_fft_powrange
    360	dib3000mc_write_word(state, 99, (1 << 9) | (0x20 << 0));
    361
    362	if (state->cfg->phase_noise_mode == 0)
    363		dib3000mc_write_word(state, 111, 0x00);
    364	else
    365		dib3000mc_write_word(state, 111, 0x02);
    366
    367	// P_agc_global
    368	dib3000mc_write_word(state, 50, 0x8000);
    369
    370	// agc setup misc
    371	dib3000mc_setup_pwm_state(state);
    372
    373	// P_agc_counter_lock
    374	dib3000mc_write_word(state, 53, 0x87);
    375	// P_agc_counter_unlock
    376	dib3000mc_write_word(state, 54, 0x87);
    377
    378	/* agc */
    379	dib3000mc_write_word(state, 36, state->cfg->max_time);
    380	dib3000mc_write_word(state, 37, (state->cfg->agc_command1 << 13) | (state->cfg->agc_command2 << 12) | (0x1d << 0));
    381	dib3000mc_write_word(state, 38, state->cfg->pwm3_value);
    382	dib3000mc_write_word(state, 39, state->cfg->ln_adc_level);
    383
    384	// set_agc_loop_Bw
    385	dib3000mc_write_word(state, 40, 0x0179);
    386	dib3000mc_write_word(state, 41, 0x03f0);
    387
    388	dib3000mc_write_word(state, 42, agc->agc1_max);
    389	dib3000mc_write_word(state, 43, agc->agc1_min);
    390	dib3000mc_write_word(state, 44, agc->agc2_max);
    391	dib3000mc_write_word(state, 45, agc->agc2_min);
    392	dib3000mc_write_word(state, 46, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
    393	dib3000mc_write_word(state, 47, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
    394	dib3000mc_write_word(state, 48, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
    395	dib3000mc_write_word(state, 49, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
    396
    397// Begin: TimeOut registers
    398	// P_pha3_thres
    399	dib3000mc_write_word(state, 110, 3277);
    400	// P_timf_alpha = 6, P_corm_alpha = 6, P_corm_thres = 0x80
    401	dib3000mc_write_word(state,  26, 0x6680);
    402	// lock_mask0
    403	dib3000mc_write_word(state, 1, 4);
    404	// lock_mask1
    405	dib3000mc_write_word(state, 2, 4);
    406	// lock_mask2
    407	dib3000mc_write_word(state, 3, 0x1000);
    408	// P_search_maxtrial=1
    409	dib3000mc_write_word(state, 5, 1);
    410
    411	dib3000mc_set_bandwidth(state, 8000);
    412
    413	// div_lock_mask
    414	dib3000mc_write_word(state,  4, 0x814);
    415
    416	dib3000mc_write_word(state, 21, (1 << 9) | 0x164);
    417	dib3000mc_write_word(state, 22, 0x463d);
    418
    419	// Spurious rm cfg
    420	// P_cspu_regul, P_cspu_win_cut
    421	dib3000mc_write_word(state, 120, 0x200f);
    422	// P_adp_selec_monit
    423	dib3000mc_write_word(state, 134, 0);
    424
    425	// Fec cfg
    426	dib3000mc_write_word(state, 195, 0x10);
    427
    428	// diversity register: P_dvsy_sync_wait..
    429	dib3000mc_write_word(state, 180, 0x2FF0);
    430
    431	// Impulse noise configuration
    432	dib3000mc_set_impulse_noise(state, 0, TRANSMISSION_MODE_8K);
    433
    434	// output mode set-up
    435	dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
    436
    437	/* close the i2c-gate */
    438	dib3000mc_write_word(state, 769, (1 << 7) );
    439
    440	return 0;
    441}
    442
    443static int dib3000mc_sleep(struct dvb_frontend *demod)
    444{
    445	struct dib3000mc_state *state = demod->demodulator_priv;
    446
    447	dib3000mc_write_word(state, 1031, 0xFFFF);
    448	dib3000mc_write_word(state, 1032, 0xFFFF);
    449	dib3000mc_write_word(state, 1033, 0xFFF0);
    450
    451	return 0;
    452}
    453
    454static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam)
    455{
    456	u16 cfg[4] = { 0 },reg;
    457	switch (qam) {
    458		case QPSK:
    459			cfg[0] = 0x099a; cfg[1] = 0x7fae; cfg[2] = 0x0333; cfg[3] = 0x7ff0;
    460			break;
    461		case QAM_16:
    462			cfg[0] = 0x023d; cfg[1] = 0x7fdf; cfg[2] = 0x00a4; cfg[3] = 0x7ff0;
    463			break;
    464		case QAM_64:
    465			cfg[0] = 0x0148; cfg[1] = 0x7ff0; cfg[2] = 0x00a4; cfg[3] = 0x7ff8;
    466			break;
    467	}
    468	for (reg = 129; reg < 133; reg++)
    469		dib3000mc_write_word(state, reg, cfg[reg - 129]);
    470}
    471
    472static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state,
    473				      struct dtv_frontend_properties *ch, u16 seq)
    474{
    475	u16 value;
    476	u32 bw = BANDWIDTH_TO_KHZ(ch->bandwidth_hz);
    477
    478	dib3000mc_set_bandwidth(state, bw);
    479	dib3000mc_set_timing(state, ch->transmission_mode, bw, 0);
    480
    481#if 1
    482	dib3000mc_write_word(state, 100, (16 << 6) + 9);
    483#else
    484	if (boost)
    485		dib3000mc_write_word(state, 100, (11 << 6) + 6);
    486	else
    487		dib3000mc_write_word(state, 100, (16 << 6) + 9);
    488#endif
    489
    490	dib3000mc_write_word(state, 1027, 0x0800);
    491	dib3000mc_write_word(state, 1027, 0x0000);
    492
    493	//Default cfg isi offset adp
    494	dib3000mc_write_word(state, 26,  0x6680);
    495	dib3000mc_write_word(state, 29,  0x1273);
    496	dib3000mc_write_word(state, 33,       5);
    497	dib3000mc_set_adp_cfg(state, QAM_16);
    498	dib3000mc_write_word(state, 133,  15564);
    499
    500	dib3000mc_write_word(state, 12 , 0x0);
    501	dib3000mc_write_word(state, 13 , 0x3e8);
    502	dib3000mc_write_word(state, 14 , 0x0);
    503	dib3000mc_write_word(state, 15 , 0x3f2);
    504
    505	dib3000mc_write_word(state, 93,0);
    506	dib3000mc_write_word(state, 94,0);
    507	dib3000mc_write_word(state, 95,0);
    508	dib3000mc_write_word(state, 96,0);
    509	dib3000mc_write_word(state, 97,0);
    510	dib3000mc_write_word(state, 98,0);
    511
    512	dib3000mc_set_impulse_noise(state, 0, ch->transmission_mode);
    513
    514	value = 0;
    515	switch (ch->transmission_mode) {
    516		case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
    517		default:
    518		case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
    519	}
    520	switch (ch->guard_interval) {
    521		case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
    522		case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
    523		case GUARD_INTERVAL_1_4:  value |= (3 << 5); break;
    524		default:
    525		case GUARD_INTERVAL_1_8:  value |= (2 << 5); break;
    526	}
    527	switch (ch->modulation) {
    528		case QPSK:  value |= (0 << 3); break;
    529		case QAM_16: value |= (1 << 3); break;
    530		default:
    531		case QAM_64: value |= (2 << 3); break;
    532	}
    533	switch (HIERARCHY_1) {
    534		case HIERARCHY_2: value |= 2; break;
    535		case HIERARCHY_4: value |= 4; break;
    536		default:
    537		case HIERARCHY_1: value |= 1; break;
    538	}
    539	dib3000mc_write_word(state, 0, value);
    540	dib3000mc_write_word(state, 5, (1 << 8) | ((seq & 0xf) << 4));
    541
    542	value = 0;
    543	if (ch->hierarchy == 1)
    544		value |= (1 << 4);
    545	if (1 == 1)
    546		value |= 1;
    547	switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
    548		case FEC_2_3: value |= (2 << 1); break;
    549		case FEC_3_4: value |= (3 << 1); break;
    550		case FEC_5_6: value |= (5 << 1); break;
    551		case FEC_7_8: value |= (7 << 1); break;
    552		default:
    553		case FEC_1_2: value |= (1 << 1); break;
    554	}
    555	dib3000mc_write_word(state, 181, value);
    556
    557	// diversity synchro delay add 50% SFN margin
    558	switch (ch->transmission_mode) {
    559		case TRANSMISSION_MODE_8K: value = 256; break;
    560		case TRANSMISSION_MODE_2K:
    561		default: value = 64; break;
    562	}
    563	switch (ch->guard_interval) {
    564		case GUARD_INTERVAL_1_16: value *= 2; break;
    565		case GUARD_INTERVAL_1_8:  value *= 4; break;
    566		case GUARD_INTERVAL_1_4:  value *= 8; break;
    567		default:
    568		case GUARD_INTERVAL_1_32: value *= 1; break;
    569	}
    570	value <<= 4;
    571	value |= dib3000mc_read_word(state, 180) & 0x000f;
    572	dib3000mc_write_word(state, 180, value);
    573
    574	// restart demod
    575	value = dib3000mc_read_word(state, 0);
    576	dib3000mc_write_word(state, 0, value | (1 << 9));
    577	dib3000mc_write_word(state, 0, value);
    578
    579	msleep(30);
    580
    581	dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, ch->transmission_mode);
    582}
    583
    584static int dib3000mc_autosearch_start(struct dvb_frontend *demod)
    585{
    586	struct dtv_frontend_properties *chan = &demod->dtv_property_cache;
    587	struct dib3000mc_state *state = demod->demodulator_priv;
    588	u16 reg;
    589//	u32 val;
    590	struct dtv_frontend_properties schan;
    591
    592	schan = *chan;
    593
    594	/* TODO what is that ? */
    595
    596	/* a channel for autosearch */
    597	schan.transmission_mode = TRANSMISSION_MODE_8K;
    598	schan.guard_interval = GUARD_INTERVAL_1_32;
    599	schan.modulation = QAM_64;
    600	schan.code_rate_HP = FEC_2_3;
    601	schan.code_rate_LP = FEC_2_3;
    602	schan.hierarchy = 0;
    603
    604	dib3000mc_set_channel_cfg(state, &schan, 11);
    605
    606	reg = dib3000mc_read_word(state, 0);
    607	dib3000mc_write_word(state, 0, reg | (1 << 8));
    608	dib3000mc_read_word(state, 511);
    609	dib3000mc_write_word(state, 0, reg);
    610
    611	return 0;
    612}
    613
    614static int dib3000mc_autosearch_is_irq(struct dvb_frontend *demod)
    615{
    616	struct dib3000mc_state *state = demod->demodulator_priv;
    617	u16 irq_pending = dib3000mc_read_word(state, 511);
    618
    619	if (irq_pending & 0x1) // failed
    620		return 1;
    621
    622	if (irq_pending & 0x2) // succeeded
    623		return 2;
    624
    625	return 0; // still pending
    626}
    627
    628static int dib3000mc_tune(struct dvb_frontend *demod)
    629{
    630	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
    631	struct dib3000mc_state *state = demod->demodulator_priv;
    632
    633	// ** configure demod **
    634	dib3000mc_set_channel_cfg(state, ch, 0);
    635
    636	// activates isi
    637	if (state->sfn_workaround_active) {
    638		dprintk("SFN workaround is active\n");
    639		dib3000mc_write_word(state, 29, 0x1273);
    640		dib3000mc_write_word(state, 108, 0x4000); // P_pha3_force_pha_shift
    641	} else {
    642		dib3000mc_write_word(state, 29, 0x1073);
    643		dib3000mc_write_word(state, 108, 0x0000); // P_pha3_force_pha_shift
    644	}
    645
    646	dib3000mc_set_adp_cfg(state, (u8)ch->modulation);
    647	if (ch->transmission_mode == TRANSMISSION_MODE_8K) {
    648		dib3000mc_write_word(state, 26, 38528);
    649		dib3000mc_write_word(state, 33, 8);
    650	} else {
    651		dib3000mc_write_word(state, 26, 30336);
    652		dib3000mc_write_word(state, 33, 6);
    653	}
    654
    655	if (dib3000mc_read_word(state, 509) & 0x80)
    656		dib3000mc_set_timing(state, ch->transmission_mode,
    657				     BANDWIDTH_TO_KHZ(ch->bandwidth_hz), 1);
    658
    659	return 0;
    660}
    661
    662struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating)
    663{
    664	struct dib3000mc_state *st = demod->demodulator_priv;
    665	return dibx000_get_i2c_adapter(&st->i2c_master, DIBX000_I2C_INTERFACE_TUNER, gating);
    666}
    667
    668EXPORT_SYMBOL(dib3000mc_get_tuner_i2c_master);
    669
    670static int dib3000mc_get_frontend(struct dvb_frontend* fe,
    671				  struct dtv_frontend_properties *fep)
    672{
    673	struct dib3000mc_state *state = fe->demodulator_priv;
    674	u16 tps = dib3000mc_read_word(state,458);
    675
    676	fep->inversion = INVERSION_AUTO;
    677
    678	fep->bandwidth_hz = state->current_bandwidth;
    679
    680	switch ((tps >> 8) & 0x1) {
    681		case 0: fep->transmission_mode = TRANSMISSION_MODE_2K; break;
    682		case 1: fep->transmission_mode = TRANSMISSION_MODE_8K; break;
    683	}
    684
    685	switch (tps & 0x3) {
    686		case 0: fep->guard_interval = GUARD_INTERVAL_1_32; break;
    687		case 1: fep->guard_interval = GUARD_INTERVAL_1_16; break;
    688		case 2: fep->guard_interval = GUARD_INTERVAL_1_8; break;
    689		case 3: fep->guard_interval = GUARD_INTERVAL_1_4; break;
    690	}
    691
    692	switch ((tps >> 13) & 0x3) {
    693		case 0: fep->modulation = QPSK; break;
    694		case 1: fep->modulation = QAM_16; break;
    695		case 2:
    696		default: fep->modulation = QAM_64; break;
    697	}
    698
    699	/* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
    700	/* (tps >> 12) & 0x1 == hrch is used, (tps >> 9) & 0x7 == alpha */
    701
    702	fep->hierarchy = HIERARCHY_NONE;
    703	switch ((tps >> 5) & 0x7) {
    704		case 1: fep->code_rate_HP = FEC_1_2; break;
    705		case 2: fep->code_rate_HP = FEC_2_3; break;
    706		case 3: fep->code_rate_HP = FEC_3_4; break;
    707		case 5: fep->code_rate_HP = FEC_5_6; break;
    708		case 7:
    709		default: fep->code_rate_HP = FEC_7_8; break;
    710
    711	}
    712
    713	switch ((tps >> 2) & 0x7) {
    714		case 1: fep->code_rate_LP = FEC_1_2; break;
    715		case 2: fep->code_rate_LP = FEC_2_3; break;
    716		case 3: fep->code_rate_LP = FEC_3_4; break;
    717		case 5: fep->code_rate_LP = FEC_5_6; break;
    718		case 7:
    719		default: fep->code_rate_LP = FEC_7_8; break;
    720	}
    721
    722	return 0;
    723}
    724
    725static int dib3000mc_set_frontend(struct dvb_frontend *fe)
    726{
    727	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
    728	struct dib3000mc_state *state = fe->demodulator_priv;
    729	int ret;
    730
    731	dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
    732
    733	state->current_bandwidth = fep->bandwidth_hz;
    734	dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->bandwidth_hz));
    735
    736	/* maybe the parameter has been changed */
    737	state->sfn_workaround_active = buggy_sfn_workaround;
    738
    739	if (fe->ops.tuner_ops.set_params) {
    740		fe->ops.tuner_ops.set_params(fe);
    741		msleep(100);
    742	}
    743
    744	if (fep->transmission_mode  == TRANSMISSION_MODE_AUTO ||
    745	    fep->guard_interval == GUARD_INTERVAL_AUTO ||
    746	    fep->modulation     == QAM_AUTO ||
    747	    fep->code_rate_HP   == FEC_AUTO) {
    748		int i = 1000, found;
    749
    750		dib3000mc_autosearch_start(fe);
    751		do {
    752			msleep(1);
    753			found = dib3000mc_autosearch_is_irq(fe);
    754		} while (found == 0 && i--);
    755
    756		dprintk("autosearch returns: %d\n",found);
    757		if (found == 0 || found == 1)
    758			return 0; // no channel found
    759
    760		dib3000mc_get_frontend(fe, fep);
    761	}
    762
    763	ret = dib3000mc_tune(fe);
    764
    765	/* make this a config parameter */
    766	dib3000mc_set_output_mode(state, OUTMODE_MPEG2_FIFO);
    767	return ret;
    768}
    769
    770static int dib3000mc_read_status(struct dvb_frontend *fe, enum fe_status *stat)
    771{
    772	struct dib3000mc_state *state = fe->demodulator_priv;
    773	u16 lock = dib3000mc_read_word(state, 509);
    774
    775	*stat = 0;
    776
    777	if (lock & 0x8000)
    778		*stat |= FE_HAS_SIGNAL;
    779	if (lock & 0x3000)
    780		*stat |= FE_HAS_CARRIER;
    781	if (lock & 0x0100)
    782		*stat |= FE_HAS_VITERBI;
    783	if (lock & 0x0010)
    784		*stat |= FE_HAS_SYNC;
    785	if (lock & 0x0008)
    786		*stat |= FE_HAS_LOCK;
    787
    788	return 0;
    789}
    790
    791static int dib3000mc_read_ber(struct dvb_frontend *fe, u32 *ber)
    792{
    793	struct dib3000mc_state *state = fe->demodulator_priv;
    794	*ber = (dib3000mc_read_word(state, 500) << 16) | dib3000mc_read_word(state, 501);
    795	return 0;
    796}
    797
    798static int dib3000mc_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
    799{
    800	struct dib3000mc_state *state = fe->demodulator_priv;
    801	*unc = dib3000mc_read_word(state, 508);
    802	return 0;
    803}
    804
    805static int dib3000mc_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
    806{
    807	struct dib3000mc_state *state = fe->demodulator_priv;
    808	u16 val = dib3000mc_read_word(state, 392);
    809	*strength = 65535 - val;
    810	return 0;
    811}
    812
    813static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr)
    814{
    815	*snr = 0x0000;
    816	return 0;
    817}
    818
    819static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
    820{
    821	tune->min_delay_ms = 1000;
    822	return 0;
    823}
    824
    825static void dib3000mc_release(struct dvb_frontend *fe)
    826{
    827	struct dib3000mc_state *state = fe->demodulator_priv;
    828	dibx000_exit_i2c_master(&state->i2c_master);
    829	kfree(state);
    830}
    831
    832int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff)
    833{
    834	struct dib3000mc_state *state = fe->demodulator_priv;
    835	dib3000mc_write_word(state, 212 + index,  onoff ? (1 << 13) | pid : 0);
    836	return 0;
    837}
    838EXPORT_SYMBOL(dib3000mc_pid_control);
    839
    840int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff)
    841{
    842	struct dib3000mc_state *state = fe->demodulator_priv;
    843	u16 tmp = dib3000mc_read_word(state, 206) & ~(1 << 4);
    844	tmp |= (onoff << 4);
    845	return dib3000mc_write_word(state, 206, tmp);
    846}
    847EXPORT_SYMBOL(dib3000mc_pid_parse);
    848
    849void dib3000mc_set_config(struct dvb_frontend *fe, struct dib3000mc_config *cfg)
    850{
    851	struct dib3000mc_state *state = fe->demodulator_priv;
    852	state->cfg = cfg;
    853}
    854EXPORT_SYMBOL(dib3000mc_set_config);
    855
    856int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib3000mc_config cfg[])
    857{
    858	struct dib3000mc_state *dmcst;
    859	int k;
    860	u8 new_addr;
    861
    862	static const u8 DIB3000MC_I2C_ADDRESS[] = { 20, 22, 24, 26 };
    863
    864	dmcst = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
    865	if (dmcst == NULL)
    866		return -ENOMEM;
    867
    868	dmcst->i2c_adap = i2c;
    869
    870	for (k = no_of_demods-1; k >= 0; k--) {
    871		dmcst->cfg = &cfg[k];
    872
    873		/* designated i2c address */
    874		new_addr          = DIB3000MC_I2C_ADDRESS[k];
    875		dmcst->i2c_addr = new_addr;
    876		if (dib3000mc_identify(dmcst) != 0) {
    877			dmcst->i2c_addr = default_addr;
    878			if (dib3000mc_identify(dmcst) != 0) {
    879				dprintk("-E-  DiB3000P/MC #%d: not identified\n", k);
    880				kfree(dmcst);
    881				return -ENODEV;
    882			}
    883		}
    884
    885		dib3000mc_set_output_mode(dmcst, OUTMODE_MPEG2_PAR_CONT_CLK);
    886
    887		// set new i2c address and force divstr (Bit 1) to value 0 (Bit 0)
    888		dib3000mc_write_word(dmcst, 1024, (new_addr << 3) | 0x1);
    889		dmcst->i2c_addr = new_addr;
    890	}
    891
    892	for (k = 0; k < no_of_demods; k++) {
    893		dmcst->cfg = &cfg[k];
    894		dmcst->i2c_addr = DIB3000MC_I2C_ADDRESS[k];
    895
    896		dib3000mc_write_word(dmcst, 1024, dmcst->i2c_addr << 3);
    897
    898		/* turn off data output */
    899		dib3000mc_set_output_mode(dmcst, OUTMODE_HIGH_Z);
    900	}
    901
    902	kfree(dmcst);
    903	return 0;
    904}
    905EXPORT_SYMBOL(dib3000mc_i2c_enumeration);
    906
    907static const struct dvb_frontend_ops dib3000mc_ops;
    908
    909struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg)
    910{
    911	struct dvb_frontend *demod;
    912	struct dib3000mc_state *st;
    913	st = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
    914	if (st == NULL)
    915		return NULL;
    916
    917	st->cfg = cfg;
    918	st->i2c_adap = i2c_adap;
    919	st->i2c_addr = i2c_addr;
    920
    921	demod                   = &st->demod;
    922	demod->demodulator_priv = st;
    923	memcpy(&st->demod.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
    924
    925	if (dib3000mc_identify(st) != 0)
    926		goto error;
    927
    928	dibx000_init_i2c_master(&st->i2c_master, DIB3000MC, st->i2c_adap, st->i2c_addr);
    929
    930	dib3000mc_write_word(st, 1037, 0x3130);
    931
    932	return demod;
    933
    934error:
    935	kfree(st);
    936	return NULL;
    937}
    938EXPORT_SYMBOL(dib3000mc_attach);
    939
    940static const struct dvb_frontend_ops dib3000mc_ops = {
    941	.delsys = { SYS_DVBT },
    942	.info = {
    943		.name = "DiBcom 3000MC/P",
    944		.frequency_min_hz      =  44250 * kHz,
    945		.frequency_max_hz      = 867250 * kHz,
    946		.frequency_stepsize_hz = 62500,
    947		.caps = FE_CAN_INVERSION_AUTO |
    948			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
    949			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
    950			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
    951			FE_CAN_TRANSMISSION_MODE_AUTO |
    952			FE_CAN_GUARD_INTERVAL_AUTO |
    953			FE_CAN_RECOVER |
    954			FE_CAN_HIERARCHY_AUTO,
    955	},
    956
    957	.release              = dib3000mc_release,
    958
    959	.init                 = dib3000mc_init,
    960	.sleep                = dib3000mc_sleep,
    961
    962	.set_frontend         = dib3000mc_set_frontend,
    963	.get_tune_settings    = dib3000mc_fe_get_tune_settings,
    964	.get_frontend         = dib3000mc_get_frontend,
    965
    966	.read_status          = dib3000mc_read_status,
    967	.read_ber             = dib3000mc_read_ber,
    968	.read_signal_strength = dib3000mc_read_signal_strength,
    969	.read_snr             = dib3000mc_read_snr,
    970	.read_ucblocks        = dib3000mc_read_unc_blocks,
    971};
    972
    973MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
    974MODULE_DESCRIPTION("Driver for the DiBcom 3000MC/P COFDM demodulator");
    975MODULE_LICENSE("GPL");