brintos

brintos / linux-shallow public Read only

0
0
Text · 22.7 KiB · c598b2a Raw
819 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Frontend driver for mobile DVB-T demodulator DiBcom 3000M-B4 * DiBcom (http://www.dibcom.fr/)5 *6 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de)7 *8 * based on GPL code from DibCom, which has9 *10 * Copyright (C) 2004 Amaury Demol for DiBcom11 *12 * Acknowledgements13 *14 *  Amaury Demol from DiBcom for providing specs and driver15 *  sources, on which this driver (and the dvb-dibusb) are based.16 *17 * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information18 */19 20#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt21 22#include <linux/kernel.h>23#include <linux/module.h>24#include <linux/init.h>25#include <linux/delay.h>26#include <linux/string.h>27#include <linux/slab.h>28 29#include <media/dvb_frontend.h>30 31#include "dib3000.h"32#include "dib3000mb_priv.h"33 34/* Version information */35#define DRIVER_VERSION "0.1"36#define DRIVER_DESC "DiBcom 3000M-B DVB-T demodulator"37#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@posteo.de"38 39static int debug;40module_param(debug, int, 0644);41MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-able)).");42 43#define deb_info(args...) dprintk(0x01, args)44#define deb_i2c(args...)  dprintk(0x02, args)45#define deb_srch(args...) dprintk(0x04, args)46#define deb_info(args...) dprintk(0x01, args)47#define deb_xfer(args...) dprintk(0x02, args)48#define deb_setf(args...) dprintk(0x04, args)49#define deb_getf(args...) dprintk(0x08, args)50 51static int dib3000_read_reg(struct dib3000_state *state, u16 reg)52{53	u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };54	u8 rb[2];55	struct i2c_msg msg[] = {56		{ .addr = state->config.demod_address, .flags = 0,        .buf = wb, .len = 2 },57		{ .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 },58	};59 60	if (i2c_transfer(state->i2c, msg, 2) != 2)61		deb_i2c("i2c read error\n");62 63	deb_i2c("reading i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,64			(rb[0] << 8) | rb[1],(rb[0] << 8) | rb[1]);65 66	return (rb[0] << 8) | rb[1];67}68 69static int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val)70{71	u8 b[] = {72		(reg >> 8) & 0xff, reg & 0xff,73		(val >> 8) & 0xff, val & 0xff,74	};75	struct i2c_msg msg[] = {76		{ .addr = state->config.demod_address, .flags = 0, .buf = b, .len = 4 }77	};78	deb_i2c("writing i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,val,val);79 80	return i2c_transfer(state->i2c,msg, 1) != 1 ? -EREMOTEIO : 0;81}82 83static int dib3000_search_status(u16 irq,u16 lock)84{85	if (irq & 0x02) {86		if (lock & 0x01) {87			deb_srch("auto search succeeded\n");88			return 1; // auto search succeeded89		} else {90			deb_srch("auto search not successful\n");91			return 0; // auto search failed92		}93	} else if (irq & 0x01)  {94		deb_srch("auto search failed\n");95		return 0; // auto search failed96	}97	return -1; // try again98}99 100/* for auto search */101static u16 dib3000_seq[2][2][2] =     /* fft,gua,   inv   */102	{ /* fft */103		{ /* gua */104			{ 0, 1 },                   /*  0   0   { 0,1 } */105			{ 3, 9 },                   /*  0   1   { 0,1 } */106		},107		{108			{ 2, 5 },                   /*  1   0   { 0,1 } */109			{ 6, 11 },                  /*  1   1   { 0,1 } */110		}111	};112 113static int dib3000mb_get_frontend(struct dvb_frontend* fe,114				  struct dtv_frontend_properties *c);115 116static int dib3000mb_set_frontend(struct dvb_frontend *fe, int tuner)117{118	struct dib3000_state* state = fe->demodulator_priv;119	struct dtv_frontend_properties *c = &fe->dtv_property_cache;120	enum fe_code_rate fe_cr = FEC_NONE;121	int search_state, seq;122 123	if (tuner && fe->ops.tuner_ops.set_params) {124		fe->ops.tuner_ops.set_params(fe);125		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);126 127		switch (c->bandwidth_hz) {128			case 8000000:129				wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]);130				wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz);131				break;132			case 7000000:133				wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[1]);134				wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_7mhz);135				break;136			case 6000000:137				wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[0]);138				wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_6mhz);139				break;140			case 0:141				return -EOPNOTSUPP;142			default:143				pr_err("unknown bandwidth value.\n");144				return -EINVAL;145		}146		deb_setf("bandwidth: %d MHZ\n", c->bandwidth_hz / 1000000);147	}148	wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4);149 150	switch (c->transmission_mode) {151		case TRANSMISSION_MODE_2K:152			deb_setf("transmission mode: 2k\n");153			wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_2K);154			break;155		case TRANSMISSION_MODE_8K:156			deb_setf("transmission mode: 8k\n");157			wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_8K);158			break;159		case TRANSMISSION_MODE_AUTO:160			deb_setf("transmission mode: auto\n");161			break;162		default:163			return -EINVAL;164	}165 166	switch (c->guard_interval) {167		case GUARD_INTERVAL_1_32:168			deb_setf("guard 1_32\n");169			wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_32);170			break;171		case GUARD_INTERVAL_1_16:172			deb_setf("guard 1_16\n");173			wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_16);174			break;175		case GUARD_INTERVAL_1_8:176			deb_setf("guard 1_8\n");177			wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_8);178			break;179		case GUARD_INTERVAL_1_4:180			deb_setf("guard 1_4\n");181			wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_4);182			break;183		case GUARD_INTERVAL_AUTO:184			deb_setf("guard auto\n");185			break;186		default:187			return -EINVAL;188	}189 190	switch (c->inversion) {191		case INVERSION_OFF:192			deb_setf("inversion off\n");193			wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_OFF);194			break;195		case INVERSION_AUTO:196			deb_setf("inversion auto\n");197			break;198		case INVERSION_ON:199			deb_setf("inversion on\n");200			wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_ON);201			break;202		default:203			return -EINVAL;204	}205 206	switch (c->modulation) {207		case QPSK:208			deb_setf("modulation: qpsk\n");209			wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_QPSK);210			break;211		case QAM_16:212			deb_setf("modulation: qam16\n");213			wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_16QAM);214			break;215		case QAM_64:216			deb_setf("modulation: qam64\n");217			wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_64QAM);218			break;219		case QAM_AUTO:220			break;221		default:222			return -EINVAL;223	}224	switch (c->hierarchy) {225		case HIERARCHY_NONE:226			deb_setf("hierarchy: none\n");227			fallthrough;228		case HIERARCHY_1:229			deb_setf("hierarchy: alpha=1\n");230			wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_1);231			break;232		case HIERARCHY_2:233			deb_setf("hierarchy: alpha=2\n");234			wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_2);235			break;236		case HIERARCHY_4:237			deb_setf("hierarchy: alpha=4\n");238			wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_4);239			break;240		case HIERARCHY_AUTO:241			deb_setf("hierarchy: alpha=auto\n");242			break;243		default:244			return -EINVAL;245	}246 247	if (c->hierarchy == HIERARCHY_NONE) {248		wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_OFF);249		wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_HP);250		fe_cr = c->code_rate_HP;251	} else if (c->hierarchy != HIERARCHY_AUTO) {252		wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_ON);253		wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_LP);254		fe_cr = c->code_rate_LP;255	}256	switch (fe_cr) {257		case FEC_1_2:258			deb_setf("fec: 1_2\n");259			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_1_2);260			break;261		case FEC_2_3:262			deb_setf("fec: 2_3\n");263			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_2_3);264			break;265		case FEC_3_4:266			deb_setf("fec: 3_4\n");267			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_3_4);268			break;269		case FEC_5_6:270			deb_setf("fec: 5_6\n");271			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_5_6);272			break;273		case FEC_7_8:274			deb_setf("fec: 7_8\n");275			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_7_8);276			break;277		case FEC_NONE:278			deb_setf("fec: none\n");279			break;280		case FEC_AUTO:281			deb_setf("fec: auto\n");282			break;283		default:284			return -EINVAL;285	}286 287	seq = dib3000_seq288		[c->transmission_mode == TRANSMISSION_MODE_AUTO]289		[c->guard_interval == GUARD_INTERVAL_AUTO]290		[c->inversion == INVERSION_AUTO];291 292	deb_setf("seq? %d\n", seq);293 294	wr(DIB3000MB_REG_SEQ, seq);295 296	wr(DIB3000MB_REG_ISI, seq ? DIB3000MB_ISI_INHIBIT : DIB3000MB_ISI_ACTIVATE);297 298	if (c->transmission_mode == TRANSMISSION_MODE_2K) {299		if (c->guard_interval == GUARD_INTERVAL_1_8) {300			wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_2K_1_8);301		} else {302			wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_DEFAULT);303		}304 305		wr(DIB3000MB_REG_UNK_121, DIB3000MB_UNK_121_2K);306	} else {307		wr(DIB3000MB_REG_UNK_121, DIB3000MB_UNK_121_DEFAULT);308	}309 310	wr(DIB3000MB_REG_MOBILE_ALGO, DIB3000MB_MOBILE_ALGO_OFF);311	wr(DIB3000MB_REG_MOBILE_MODE_QAM, DIB3000MB_MOBILE_MODE_QAM_OFF);312	wr(DIB3000MB_REG_MOBILE_MODE, DIB3000MB_MOBILE_MODE_OFF);313 314	wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_high);315 316	wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_ACTIVATE);317 318	wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AGC + DIB3000MB_RESTART_CTRL);319	wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);320 321	/* wait for AGC lock */322	msleep(70);323 324	wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_low);325 326	/* something has to be auto searched */327	if (c->modulation == QAM_AUTO ||328		c->hierarchy == HIERARCHY_AUTO ||329		fe_cr == FEC_AUTO ||330		c->inversion == INVERSION_AUTO) {331		int as_count=0;332 333		deb_setf("autosearch enabled.\n");334 335		wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_INHIBIT);336 337		wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AUTO_SEARCH);338		wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);339 340		while ((search_state =341				dib3000_search_status(342					rd(DIB3000MB_REG_AS_IRQ_PENDING),343					rd(DIB3000MB_REG_LOCK2_VALUE))) < 0 && as_count++ < 100)344			msleep(1);345 346		deb_setf("search_state after autosearch %d after %d checks\n",347			 search_state, as_count);348 349		if (search_state == 1) {350			if (dib3000mb_get_frontend(fe, c) == 0) {351				deb_setf("reading tuning data from frontend succeeded.\n");352				return dib3000mb_set_frontend(fe, 0);353			}354		}355 356	} else {357		wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_CTRL);358		wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);359	}360 361	return 0;362}363 364static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)365{366	struct dib3000_state* state = fe->demodulator_priv;367 368	deb_info("dib3000mb is getting up.\n");369	wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_UP);370 371	wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AGC);372 373	wr(DIB3000MB_REG_RESET_DEVICE, DIB3000MB_RESET_DEVICE);374	wr(DIB3000MB_REG_RESET_DEVICE, DIB3000MB_RESET_DEVICE_RST);375 376	wr(DIB3000MB_REG_CLOCK, DIB3000MB_CLOCK_DEFAULT);377 378	wr(DIB3000MB_REG_ELECT_OUT_MODE, DIB3000MB_ELECT_OUT_MODE_ON);379 380	wr(DIB3000MB_REG_DDS_FREQ_MSB, DIB3000MB_DDS_FREQ_MSB);381	wr(DIB3000MB_REG_DDS_FREQ_LSB, DIB3000MB_DDS_FREQ_LSB);382 383	wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]);384 385	wr_foreach(dib3000mb_reg_impulse_noise,386			dib3000mb_impulse_noise_values[DIB3000MB_IMPNOISE_OFF]);387 388	wr_foreach(dib3000mb_reg_agc_gain, dib3000mb_default_agc_gain);389 390	wr(DIB3000MB_REG_PHASE_NOISE, DIB3000MB_PHASE_NOISE_DEFAULT);391 392	wr_foreach(dib3000mb_reg_phase_noise, dib3000mb_default_noise_phase);393 394	wr_foreach(dib3000mb_reg_lock_duration, dib3000mb_default_lock_duration);395 396	wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_low);397 398	wr(DIB3000MB_REG_LOCK0_MASK, DIB3000MB_LOCK0_DEFAULT);399	wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4);400	wr(DIB3000MB_REG_LOCK2_MASK, DIB3000MB_LOCK2_DEFAULT);401	wr(DIB3000MB_REG_SEQ, dib3000_seq[1][1][1]);402 403	wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz);404 405	wr(DIB3000MB_REG_UNK_68, DIB3000MB_UNK_68);406	wr(DIB3000MB_REG_UNK_69, DIB3000MB_UNK_69);407	wr(DIB3000MB_REG_UNK_71, DIB3000MB_UNK_71);408	wr(DIB3000MB_REG_UNK_77, DIB3000MB_UNK_77);409	wr(DIB3000MB_REG_UNK_78, DIB3000MB_UNK_78);410	wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_INHIBIT);411	wr(DIB3000MB_REG_UNK_92, DIB3000MB_UNK_92);412	wr(DIB3000MB_REG_UNK_96, DIB3000MB_UNK_96);413	wr(DIB3000MB_REG_UNK_97, DIB3000MB_UNK_97);414	wr(DIB3000MB_REG_UNK_106, DIB3000MB_UNK_106);415	wr(DIB3000MB_REG_UNK_107, DIB3000MB_UNK_107);416	wr(DIB3000MB_REG_UNK_108, DIB3000MB_UNK_108);417	wr(DIB3000MB_REG_UNK_122, DIB3000MB_UNK_122);418	wr(DIB3000MB_REG_MOBILE_MODE_QAM, DIB3000MB_MOBILE_MODE_QAM_OFF);419	wr(DIB3000MB_REG_BERLEN, DIB3000MB_BERLEN_DEFAULT);420 421	wr_foreach(dib3000mb_reg_filter_coeffs, dib3000mb_filter_coeffs);422 423	wr(DIB3000MB_REG_MOBILE_ALGO, DIB3000MB_MOBILE_ALGO_ON);424	wr(DIB3000MB_REG_MULTI_DEMOD_MSB, DIB3000MB_MULTI_DEMOD_MSB);425	wr(DIB3000MB_REG_MULTI_DEMOD_LSB, DIB3000MB_MULTI_DEMOD_LSB);426 427	wr(DIB3000MB_REG_OUTPUT_MODE, DIB3000MB_OUTPUT_MODE_SLAVE);428 429	wr(DIB3000MB_REG_FIFO_142, DIB3000MB_FIFO_142);430	wr(DIB3000MB_REG_MPEG2_OUT_MODE, DIB3000MB_MPEG2_OUT_MODE_188);431	wr(DIB3000MB_REG_PID_PARSE, DIB3000MB_PID_PARSE_ACTIVATE);432	wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_INHIBIT);433	wr(DIB3000MB_REG_FIFO_146, DIB3000MB_FIFO_146);434	wr(DIB3000MB_REG_FIFO_147, DIB3000MB_FIFO_147);435 436	wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF);437 438	return 0;439}440 441static int dib3000mb_get_frontend(struct dvb_frontend* fe,442				  struct dtv_frontend_properties *c)443{444	struct dib3000_state* state = fe->demodulator_priv;445	enum fe_code_rate *cr;446	u16 tps_val;447	int inv_test1,inv_test2;448	u32 dds_val, threshold = 0x800000;449 450	if (!rd(DIB3000MB_REG_TPS_LOCK))451		return 0;452 453	dds_val = ((rd(DIB3000MB_REG_DDS_VALUE_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_VALUE_LSB);454	deb_getf("DDS_VAL: %x %x %x\n", dds_val, rd(DIB3000MB_REG_DDS_VALUE_MSB), rd(DIB3000MB_REG_DDS_VALUE_LSB));455	if (dds_val < threshold)456		inv_test1 = 0;457	else if (dds_val == threshold)458		inv_test1 = 1;459	else460		inv_test1 = 2;461 462	dds_val = ((rd(DIB3000MB_REG_DDS_FREQ_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_FREQ_LSB);463	deb_getf("DDS_FREQ: %x %x %x\n", dds_val, rd(DIB3000MB_REG_DDS_FREQ_MSB), rd(DIB3000MB_REG_DDS_FREQ_LSB));464	if (dds_val < threshold)465		inv_test2 = 0;466	else if (dds_val == threshold)467		inv_test2 = 1;468	else469		inv_test2 = 2;470 471	c->inversion =472		((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) ||473		((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)) ?474		INVERSION_ON : INVERSION_OFF;475 476	deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, c->inversion);477 478	switch ((tps_val = rd(DIB3000MB_REG_TPS_QAM))) {479		case DIB3000_CONSTELLATION_QPSK:480			deb_getf("QPSK\n");481			c->modulation = QPSK;482			break;483		case DIB3000_CONSTELLATION_16QAM:484			deb_getf("QAM16\n");485			c->modulation = QAM_16;486			break;487		case DIB3000_CONSTELLATION_64QAM:488			deb_getf("QAM64\n");489			c->modulation = QAM_64;490			break;491		default:492			pr_err("Unexpected constellation returned by TPS (%d)\n", tps_val);493			break;494	}495	deb_getf("TPS: %d\n", tps_val);496 497	if (rd(DIB3000MB_REG_TPS_HRCH)) {498		deb_getf("HRCH ON\n");499		cr = &c->code_rate_LP;500		c->code_rate_HP = FEC_NONE;501		switch ((tps_val = rd(DIB3000MB_REG_TPS_VIT_ALPHA))) {502			case DIB3000_ALPHA_0:503				deb_getf("HIERARCHY_NONE\n");504				c->hierarchy = HIERARCHY_NONE;505				break;506			case DIB3000_ALPHA_1:507				deb_getf("HIERARCHY_1\n");508				c->hierarchy = HIERARCHY_1;509				break;510			case DIB3000_ALPHA_2:511				deb_getf("HIERARCHY_2\n");512				c->hierarchy = HIERARCHY_2;513				break;514			case DIB3000_ALPHA_4:515				deb_getf("HIERARCHY_4\n");516				c->hierarchy = HIERARCHY_4;517				break;518			default:519				pr_err("Unexpected ALPHA value returned by TPS (%d)\n", tps_val);520				break;521		}522		deb_getf("TPS: %d\n", tps_val);523 524		tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_LP);525	} else {526		deb_getf("HRCH OFF\n");527		cr = &c->code_rate_HP;528		c->code_rate_LP = FEC_NONE;529		c->hierarchy = HIERARCHY_NONE;530 531		tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_HP);532	}533 534	switch (tps_val) {535		case DIB3000_FEC_1_2:536			deb_getf("FEC_1_2\n");537			*cr = FEC_1_2;538			break;539		case DIB3000_FEC_2_3:540			deb_getf("FEC_2_3\n");541			*cr = FEC_2_3;542			break;543		case DIB3000_FEC_3_4:544			deb_getf("FEC_3_4\n");545			*cr = FEC_3_4;546			break;547		case DIB3000_FEC_5_6:548			deb_getf("FEC_5_6\n");549			*cr = FEC_4_5;550			break;551		case DIB3000_FEC_7_8:552			deb_getf("FEC_7_8\n");553			*cr = FEC_7_8;554			break;555		default:556			pr_err("Unexpected FEC returned by TPS (%d)\n", tps_val);557			break;558	}559	deb_getf("TPS: %d\n",tps_val);560 561	switch ((tps_val = rd(DIB3000MB_REG_TPS_GUARD_TIME))) {562		case DIB3000_GUARD_TIME_1_32:563			deb_getf("GUARD_INTERVAL_1_32\n");564			c->guard_interval = GUARD_INTERVAL_1_32;565			break;566		case DIB3000_GUARD_TIME_1_16:567			deb_getf("GUARD_INTERVAL_1_16\n");568			c->guard_interval = GUARD_INTERVAL_1_16;569			break;570		case DIB3000_GUARD_TIME_1_8:571			deb_getf("GUARD_INTERVAL_1_8\n");572			c->guard_interval = GUARD_INTERVAL_1_8;573			break;574		case DIB3000_GUARD_TIME_1_4:575			deb_getf("GUARD_INTERVAL_1_4\n");576			c->guard_interval = GUARD_INTERVAL_1_4;577			break;578		default:579			pr_err("Unexpected Guard Time returned by TPS (%d)\n", tps_val);580			break;581	}582	deb_getf("TPS: %d\n", tps_val);583 584	switch ((tps_val = rd(DIB3000MB_REG_TPS_FFT))) {585		case DIB3000_TRANSMISSION_MODE_2K:586			deb_getf("TRANSMISSION_MODE_2K\n");587			c->transmission_mode = TRANSMISSION_MODE_2K;588			break;589		case DIB3000_TRANSMISSION_MODE_8K:590			deb_getf("TRANSMISSION_MODE_8K\n");591			c->transmission_mode = TRANSMISSION_MODE_8K;592			break;593		default:594			pr_err("unexpected transmission mode return by TPS (%d)\n", tps_val);595			break;596	}597	deb_getf("TPS: %d\n", tps_val);598 599	return 0;600}601 602static int dib3000mb_read_status(struct dvb_frontend *fe,603				 enum fe_status *stat)604{605	struct dib3000_state* state = fe->demodulator_priv;606 607	*stat = 0;608 609	if (rd(DIB3000MB_REG_AGC_LOCK))610		*stat |= FE_HAS_SIGNAL;611	if (rd(DIB3000MB_REG_CARRIER_LOCK))612		*stat |= FE_HAS_CARRIER;613	if (rd(DIB3000MB_REG_VIT_LCK))614		*stat |= FE_HAS_VITERBI;615	if (rd(DIB3000MB_REG_TS_SYNC_LOCK))616		*stat |= (FE_HAS_SYNC | FE_HAS_LOCK);617 618	deb_getf("actual status is %2x\n",*stat);619 620	deb_getf("autoval: tps: %d, qam: %d, hrch: %d, alpha: %d, hp: %d, lp: %d, guard: %d, fft: %d cell: %d\n",621			rd(DIB3000MB_REG_TPS_LOCK),622			rd(DIB3000MB_REG_TPS_QAM),623			rd(DIB3000MB_REG_TPS_HRCH),624			rd(DIB3000MB_REG_TPS_VIT_ALPHA),625			rd(DIB3000MB_REG_TPS_CODE_RATE_HP),626			rd(DIB3000MB_REG_TPS_CODE_RATE_LP),627			rd(DIB3000MB_REG_TPS_GUARD_TIME),628			rd(DIB3000MB_REG_TPS_FFT),629			rd(DIB3000MB_REG_TPS_CELL_ID));630 631	//*stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;632	return 0;633}634 635static int dib3000mb_read_ber(struct dvb_frontend* fe, u32 *ber)636{637	struct dib3000_state* state = fe->demodulator_priv;638 639	*ber = ((rd(DIB3000MB_REG_BER_MSB) << 16) | rd(DIB3000MB_REG_BER_LSB));640	return 0;641}642 643/* see dib3000-watch dvb-apps for exact calcuations of signal_strength and snr */644static int dib3000mb_read_signal_strength(struct dvb_frontend* fe, u16 *strength)645{646	struct dib3000_state* state = fe->demodulator_priv;647 648	*strength = rd(DIB3000MB_REG_SIGNAL_POWER) * 0xffff / 0x170;649	return 0;650}651 652static int dib3000mb_read_snr(struct dvb_frontend* fe, u16 *snr)653{654	struct dib3000_state* state = fe->demodulator_priv;655	short sigpow = rd(DIB3000MB_REG_SIGNAL_POWER);656	int icipow = ((rd(DIB3000MB_REG_NOISE_POWER_MSB) & 0xff) << 16) |657		rd(DIB3000MB_REG_NOISE_POWER_LSB);658	*snr = (sigpow << 8) / ((icipow > 0) ? icipow : 1);659	return 0;660}661 662static int dib3000mb_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)663{664	struct dib3000_state* state = fe->demodulator_priv;665 666	*unc = rd(DIB3000MB_REG_PACKET_ERROR_RATE);667	return 0;668}669 670static int dib3000mb_sleep(struct dvb_frontend* fe)671{672	struct dib3000_state* state = fe->demodulator_priv;673	deb_info("dib3000mb is going to bed.\n");674	wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_DOWN);675	return 0;676}677 678static int dib3000mb_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)679{680	tune->min_delay_ms = 800;681	return 0;682}683 684static int dib3000mb_fe_init_nonmobile(struct dvb_frontend* fe)685{686	return dib3000mb_fe_init(fe, 0);687}688 689static int dib3000mb_set_frontend_and_tuner(struct dvb_frontend *fe)690{691	return dib3000mb_set_frontend(fe, 1);692}693 694static void dib3000mb_release(struct dvb_frontend* fe)695{696	struct dib3000_state *state = fe->demodulator_priv;697	kfree(state);698}699 700/* pid filter and transfer stuff */701static int dib3000mb_pid_control(struct dvb_frontend *fe,int index, int pid,int onoff)702{703	struct dib3000_state *state = fe->demodulator_priv;704	pid = (onoff ? pid | DIB3000_ACTIVATE_PID_FILTERING : 0);705	wr(index+DIB3000MB_REG_FIRST_PID,pid);706	return 0;707}708 709static int dib3000mb_fifo_control(struct dvb_frontend *fe, int onoff)710{711	struct dib3000_state *state = fe->demodulator_priv;712 713	deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling");714	if (onoff) {715		wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_ACTIVATE);716	} else {717		wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_INHIBIT);718	}719	return 0;720}721 722static int dib3000mb_pid_parse(struct dvb_frontend *fe, int onoff)723{724	struct dib3000_state *state = fe->demodulator_priv;725	deb_xfer("%s pid parsing\n",onoff ? "enabling" : "disabling");726	wr(DIB3000MB_REG_PID_PARSE,onoff);727	return 0;728}729 730static int dib3000mb_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr)731{732	struct dib3000_state *state = fe->demodulator_priv;733	if (onoff) {734		wr(DIB3000MB_REG_TUNER, DIB3000_TUNER_WRITE_ENABLE(pll_addr));735	} else {736		wr(DIB3000MB_REG_TUNER, DIB3000_TUNER_WRITE_DISABLE(pll_addr));737	}738	return 0;739}740 741static const struct dvb_frontend_ops dib3000mb_ops;742 743struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,744				      struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)745{746	struct dib3000_state* state = NULL;747 748	/* allocate memory for the internal state */749	state = kzalloc(sizeof(struct dib3000_state), GFP_KERNEL);750	if (state == NULL)751		goto error;752 753	/* setup the state */754	state->i2c = i2c;755	memcpy(&state->config,config,sizeof(struct dib3000_config));756 757	/* check for the correct demod */758	if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)759		goto error;760 761	if (rd(DIB3000_REG_DEVICE_ID) != DIB3000MB_DEVICE_ID)762		goto error;763 764	/* create dvb_frontend */765	memcpy(&state->frontend.ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops));766	state->frontend.demodulator_priv = state;767 768	/* set the xfer operations */769	xfer_ops->pid_parse = dib3000mb_pid_parse;770	xfer_ops->fifo_ctrl = dib3000mb_fifo_control;771	xfer_ops->pid_ctrl = dib3000mb_pid_control;772	xfer_ops->tuner_pass_ctrl = dib3000mb_tuner_pass_ctrl;773 774	return &state->frontend;775 776error:777	kfree(state);778	return NULL;779}780 781static const struct dvb_frontend_ops dib3000mb_ops = {782	.delsys = { SYS_DVBT },783	.info = {784		.name			= "DiBcom 3000M-B DVB-T",785		.frequency_min_hz	=  44250 * kHz,786		.frequency_max_hz	= 867250 * kHz,787		.frequency_stepsize_hz	= 62500,788		.caps = FE_CAN_INVERSION_AUTO |789				FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |790				FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |791				FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |792				FE_CAN_TRANSMISSION_MODE_AUTO |793				FE_CAN_GUARD_INTERVAL_AUTO |794				FE_CAN_RECOVER |795				FE_CAN_HIERARCHY_AUTO,796	},797 798	.release = dib3000mb_release,799 800	.init = dib3000mb_fe_init_nonmobile,801	.sleep = dib3000mb_sleep,802 803	.set_frontend = dib3000mb_set_frontend_and_tuner,804	.get_frontend = dib3000mb_get_frontend,805	.get_tune_settings = dib3000mb_fe_get_tune_settings,806 807	.read_status = dib3000mb_read_status,808	.read_ber = dib3000mb_read_ber,809	.read_signal_strength = dib3000mb_read_signal_strength,810	.read_snr = dib3000mb_read_snr,811	.read_ucblocks = dib3000mb_read_unc_blocks,812};813 814MODULE_AUTHOR(DRIVER_AUTHOR);815MODULE_DESCRIPTION(DRIVER_DESC);816MODULE_LICENSE("GPL");817 818EXPORT_SYMBOL_GPL(dib3000mb_attach);819