brintos

brintos / linux-shallow public Read only

0
0
Text · 39.4 KiB · f5dd3a8 Raw
1498 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3    Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver4 5    Copyright (C) 2006-2008 Steven Toth <stoth@hauppauge.com>6    Copyright (C) 2006-2007 Georg Acher7    Copyright (C) 2007-2008 Darron Broad8	March 20079	    Fixed some bugs.10	    Added diseqc support.11	    Added corrected signal strength support.12	August 200713	    Sync with legacy version.14	    Some clean ups.15    Copyright (C) 2008 Igor Liplianin16	September, 9th 200817	    Fixed locking on high symbol rates (>30000).18	    Implement MPEG initialization parameter.19	January, 17th 200920	    Fill set_voltage with actually control voltage code.21	    Correct set tone to not affect voltage.22 23*/24 25#include <linux/slab.h>26#include <linux/kernel.h>27#include <linux/module.h>28#include <linux/moduleparam.h>29#include <linux/init.h>30#include <linux/firmware.h>31 32#include <media/dvb_frontend.h>33#include "cx24116.h"34 35static int debug;36module_param(debug, int, 0644);37MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");38 39#define dprintk(args...) \40	do { \41		if (debug) \42			printk(KERN_INFO "cx24116: " args); \43	} while (0)44 45#define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw"46#define CX24116_SEARCH_RANGE_KHZ 500047 48/* known registers */49#define CX24116_REG_COMMAND (0x00)      /* command args 0x00..0x1e */50#define CX24116_REG_EXECUTE (0x1f)      /* execute command */51#define CX24116_REG_MAILBOX (0x96)      /* FW or multipurpose mailbox? */52#define CX24116_REG_RESET   (0x20)      /* reset status > 0     */53#define CX24116_REG_SIGNAL  (0x9e)      /* signal low           */54#define CX24116_REG_SSTATUS (0x9d)      /* signal high / status */55#define CX24116_REG_QUALITY8 (0xa3)56#define CX24116_REG_QSTATUS (0xbc)57#define CX24116_REG_QUALITY0 (0xd5)58#define CX24116_REG_BER0    (0xc9)59#define CX24116_REG_BER8    (0xc8)60#define CX24116_REG_BER16   (0xc7)61#define CX24116_REG_BER24   (0xc6)62#define CX24116_REG_UCB0    (0xcb)63#define CX24116_REG_UCB8    (0xca)64#define CX24116_REG_CLKDIV  (0xf3)65#define CX24116_REG_RATEDIV (0xf9)66 67/* configured fec (not tuned) or actual FEC (tuned) 1=1/2 2=2/3 etc */68#define CX24116_REG_FECSTATUS (0x9c)69 70/* FECSTATUS bits */71/* mask to determine configured fec (not tuned) or actual fec (tuned) */72#define CX24116_FEC_FECMASK   (0x1f)73 74/* Select DVB-S demodulator, else DVB-S2 */75#define CX24116_FEC_DVBS      (0x20)76#define CX24116_FEC_UNKNOWN   (0x40)    /* Unknown/unused */77 78/* Pilot mode requested when tuning else always reset when tuned */79#define CX24116_FEC_PILOT     (0x80)80 81/* arg buffer size */82#define CX24116_ARGLEN (0x1e)83 84/* rolloff */85#define CX24116_ROLLOFF_020 (0x00)86#define CX24116_ROLLOFF_025 (0x01)87#define CX24116_ROLLOFF_035 (0x02)88 89/* pilot bit */90#define CX24116_PILOT_OFF (0x00)91#define CX24116_PILOT_ON (0x40)92 93/* signal status */94#define CX24116_HAS_SIGNAL   (0x01)95#define CX24116_HAS_CARRIER  (0x02)96#define CX24116_HAS_VITERBI  (0x04)97#define CX24116_HAS_SYNCLOCK (0x08)98#define CX24116_HAS_UNKNOWN1 (0x10)99#define CX24116_HAS_UNKNOWN2 (0x20)100#define CX24116_STATUS_MASK  (0x0f)101#define CX24116_SIGNAL_MASK  (0xc0)102 103#define CX24116_DISEQC_TONEOFF   (0)    /* toneburst never sent */104#define CX24116_DISEQC_TONECACHE (1)    /* toneburst cached     */105#define CX24116_DISEQC_MESGCACHE (2)    /* message cached       */106 107/* arg offset for DiSEqC */108#define CX24116_DISEQC_BURST  (1)109#define CX24116_DISEQC_ARG2_2 (2)   /* unknown value=2 */110#define CX24116_DISEQC_ARG3_0 (3)   /* unknown value=0 */111#define CX24116_DISEQC_ARG4_0 (4)   /* unknown value=0 */112#define CX24116_DISEQC_MSGLEN (5)113#define CX24116_DISEQC_MSGOFS (6)114 115/* DiSEqC burst */116#define CX24116_DISEQC_MINI_A (0)117#define CX24116_DISEQC_MINI_B (1)118 119/* DiSEqC tone burst */120static int toneburst = 1;121module_param(toneburst, int, 0644);122MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, "\123	"2=MESSAGE CACHE (default:1)");124 125/* SNR measurements */126static int esno_snr;127module_param(esno_snr, int, 0644);128MODULE_PARM_DESC(esno_snr, "SNR return units, 0=PERCENTAGE 0-100, "\129	"1=ESNO(db * 10) (default:0)");130 131enum cmds {132	CMD_SET_VCO     = 0x10,133	CMD_TUNEREQUEST = 0x11,134	CMD_MPEGCONFIG  = 0x13,135	CMD_TUNERINIT   = 0x14,136	CMD_BANDWIDTH   = 0x15,137	CMD_GETAGC      = 0x19,138	CMD_LNBCONFIG   = 0x20,139	CMD_LNBSEND     = 0x21, /* Formerly CMD_SEND_DISEQC */140	CMD_LNBDCLEVEL  = 0x22,141	CMD_SET_TONE    = 0x23,142	CMD_UPDFWVERS   = 0x35,143	CMD_TUNERSLEEP  = 0x36,144	CMD_AGCCONTROL  = 0x3b, /* Unknown */145};146 147/* The Demod/Tuner can't easily provide these, we cache them */148struct cx24116_tuning {149	u32 frequency;150	u32 symbol_rate;151	enum fe_spectral_inversion inversion;152	enum fe_code_rate fec;153 154	enum fe_delivery_system delsys;155	enum fe_modulation modulation;156	enum fe_pilot pilot;157	enum fe_rolloff rolloff;158 159	/* Demod values */160	u8 fec_val;161	u8 fec_mask;162	u8 inversion_val;163	u8 pilot_val;164	u8 rolloff_val;165};166 167/* Basic commands that are sent to the firmware */168struct cx24116_cmd {169	u8 len;170	u8 args[CX24116_ARGLEN];171};172 173struct cx24116_state {174	struct i2c_adapter *i2c;175	const struct cx24116_config *config;176 177	struct dvb_frontend frontend;178 179	struct cx24116_tuning dcur;180	struct cx24116_tuning dnxt;181 182	u8 skip_fw_load;183	u8 burst;184	struct cx24116_cmd dsec_cmd;185};186 187static int cx24116_writereg(struct cx24116_state *state, int reg, int data)188{189	u8 buf[] = { reg, data };190	struct i2c_msg msg = { .addr = state->config->demod_address,191		.flags = 0, .buf = buf, .len = 2 };192	int err;193 194	if (debug > 1)195		printk("cx24116: %s: write reg 0x%02x, value 0x%02x\n",196			__func__, reg, data);197 198	err = i2c_transfer(state->i2c, &msg, 1);199	if (err != 1) {200		printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x, value == 0x%02x)\n",201		       __func__, err, reg, data);202		return -EREMOTEIO;203	}204 205	return 0;206}207 208/* Bulk byte writes to a single I2C address, for 32k firmware load */209static int cx24116_writeregN(struct cx24116_state *state, int reg,210			     const u8 *data, u16 len)211{212	int ret;213	struct i2c_msg msg;214	u8 *buf;215 216	buf = kmalloc(len + 1, GFP_KERNEL);217	if (!buf)218		return -ENOMEM;219 220	*(buf) = reg;221	memcpy(buf + 1, data, len);222 223	msg.addr = state->config->demod_address;224	msg.flags = 0;225	msg.buf = buf;226	msg.len = len + 1;227 228	if (debug > 1)229		printk(KERN_INFO "cx24116: %s:  write regN 0x%02x, len = %d\n",230			__func__, reg, len);231 232	ret = i2c_transfer(state->i2c, &msg, 1);233	if (ret != 1) {234		printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x\n",235			 __func__, ret, reg);236		ret = -EREMOTEIO;237	}238 239	kfree(buf);240 241	return ret;242}243 244static int cx24116_readreg(struct cx24116_state *state, u8 reg)245{246	int ret;247	u8 b0[] = { reg };248	u8 b1[] = { 0 };249	struct i2c_msg msg[] = {250		{ .addr = state->config->demod_address, .flags = 0,251			.buf = b0, .len = 1 },252		{ .addr = state->config->demod_address, .flags = I2C_M_RD,253			.buf = b1, .len = 1 }254	};255 256	ret = i2c_transfer(state->i2c, msg, 2);257 258	if (ret != 2) {259		printk(KERN_ERR "%s: reg=0x%x (error=%d)\n",260			__func__, reg, ret);261		return ret;262	}263 264	if (debug > 1)265		printk(KERN_INFO "cx24116: read reg 0x%02x, value 0x%02x\n",266			reg, b1[0]);267 268	return b1[0];269}270 271static int cx24116_set_inversion(struct cx24116_state *state,272	enum fe_spectral_inversion inversion)273{274	dprintk("%s(%d)\n", __func__, inversion);275 276	switch (inversion) {277	case INVERSION_OFF:278		state->dnxt.inversion_val = 0x00;279		break;280	case INVERSION_ON:281		state->dnxt.inversion_val = 0x04;282		break;283	case INVERSION_AUTO:284		state->dnxt.inversion_val = 0x0C;285		break;286	default:287		return -EINVAL;288	}289 290	state->dnxt.inversion = inversion;291 292	return 0;293}294 295/*296 * modfec (modulation and FEC)297 * ===========================298 *299 * MOD          FEC             mask/val    standard300 * ----         --------        ----------- --------301 * QPSK         FEC_1_2         0x02 0x02+X DVB-S302 * QPSK         FEC_2_3         0x04 0x02+X DVB-S303 * QPSK         FEC_3_4         0x08 0x02+X DVB-S304 * QPSK         FEC_4_5         0x10 0x02+X DVB-S (?)305 * QPSK         FEC_5_6         0x20 0x02+X DVB-S306 * QPSK         FEC_6_7         0x40 0x02+X DVB-S307 * QPSK         FEC_7_8         0x80 0x02+X DVB-S308 * QPSK         FEC_8_9         0x01 0x02+X DVB-S (?) (NOT SUPPORTED?)309 * QPSK         AUTO            0xff 0x02+X DVB-S310 *311 * For DVB-S high byte probably represents FEC312 * and low byte selects the modulator. The high313 * byte is search range mask. Bit 5 may turn314 * on DVB-S and remaining bits represent some315 * kind of calibration (how/what i do not know).316 *317 * Eg.(2/3) szap "Zone Horror"318 *319 * mask/val = 0x04, 0x20320 * status 1f | signal c3c0 | snr a333 | ber 00000098 | unc 0 | FE_HAS_LOCK321 *322 * mask/val = 0x04, 0x30323 * status 1f | signal c3c0 | snr a333 | ber 00000000 | unc 0 | FE_HAS_LOCK324 *325 * After tuning FECSTATUS contains actual FEC326 * in use numbered 1 through to 8 for 1/2 .. 2/3 etc327 *328 * NBC=NOT/NON BACKWARD COMPATIBLE WITH DVB-S (DVB-S2 only)329 *330 * NBC-QPSK     FEC_1_2         0x00, 0x04      DVB-S2331 * NBC-QPSK     FEC_3_5         0x00, 0x05      DVB-S2332 * NBC-QPSK     FEC_2_3         0x00, 0x06      DVB-S2333 * NBC-QPSK     FEC_3_4         0x00, 0x07      DVB-S2334 * NBC-QPSK     FEC_4_5         0x00, 0x08      DVB-S2335 * NBC-QPSK     FEC_5_6         0x00, 0x09      DVB-S2336 * NBC-QPSK     FEC_8_9         0x00, 0x0a      DVB-S2337 * NBC-QPSK     FEC_9_10        0x00, 0x0b      DVB-S2338 *339 * NBC-8PSK     FEC_3_5         0x00, 0x0c      DVB-S2340 * NBC-8PSK     FEC_2_3         0x00, 0x0d      DVB-S2341 * NBC-8PSK     FEC_3_4         0x00, 0x0e      DVB-S2342 * NBC-8PSK     FEC_5_6         0x00, 0x0f      DVB-S2343 * NBC-8PSK     FEC_8_9         0x00, 0x10      DVB-S2344 * NBC-8PSK     FEC_9_10        0x00, 0x11      DVB-S2345 *346 * For DVB-S2 low bytes selects both modulator347 * and FEC. High byte is meaningless here. To348 * set pilot, bit 6 (0x40) is set. When inspecting349 * FECSTATUS bit 7 (0x80) represents the pilot350 * selection whilst not tuned. When tuned, actual FEC351 * in use is found in FECSTATUS as per above. Pilot352 * value is reset.353 */354 355/* A table of modulation, fec and configuration bytes for the demod.356 * Not all S2 mmodulation schemes are support and not all rates with357 * a scheme are support. Especially, no auto detect when in S2 mode.358 */359static struct cx24116_modfec {360	enum fe_delivery_system delivery_system;361	enum fe_modulation modulation;362	enum fe_code_rate fec;363	u8 mask;	/* In DVBS mode this is used to autodetect */364	u8 val;		/* Passed to the firmware to indicate mode selection */365} CX24116_MODFEC_MODES[] = {366 /* QPSK. For unknown rates we set hardware to auto detect 0xfe 0x30 */367 368 /*mod   fec       mask  val */369 { SYS_DVBS, QPSK, FEC_NONE, 0xfe, 0x30 },370 { SYS_DVBS, QPSK, FEC_1_2,  0x02, 0x2e }, /* 00000010 00101110 */371 { SYS_DVBS, QPSK, FEC_2_3,  0x04, 0x2f }, /* 00000100 00101111 */372 { SYS_DVBS, QPSK, FEC_3_4,  0x08, 0x30 }, /* 00001000 00110000 */373 { SYS_DVBS, QPSK, FEC_4_5,  0xfe, 0x30 }, /* 000?0000 ?        */374 { SYS_DVBS, QPSK, FEC_5_6,  0x20, 0x31 }, /* 00100000 00110001 */375 { SYS_DVBS, QPSK, FEC_6_7,  0xfe, 0x30 }, /* 0?000000 ?        */376 { SYS_DVBS, QPSK, FEC_7_8,  0x80, 0x32 }, /* 10000000 00110010 */377 { SYS_DVBS, QPSK, FEC_8_9,  0xfe, 0x30 }, /* 0000000? ?        */378 { SYS_DVBS, QPSK, FEC_AUTO, 0xfe, 0x30 },379 /* NBC-QPSK */380 { SYS_DVBS2, QPSK, FEC_1_2,  0x00, 0x04 },381 { SYS_DVBS2, QPSK, FEC_3_5,  0x00, 0x05 },382 { SYS_DVBS2, QPSK, FEC_2_3,  0x00, 0x06 },383 { SYS_DVBS2, QPSK, FEC_3_4,  0x00, 0x07 },384 { SYS_DVBS2, QPSK, FEC_4_5,  0x00, 0x08 },385 { SYS_DVBS2, QPSK, FEC_5_6,  0x00, 0x09 },386 { SYS_DVBS2, QPSK, FEC_8_9,  0x00, 0x0a },387 { SYS_DVBS2, QPSK, FEC_9_10, 0x00, 0x0b },388 /* 8PSK */389 { SYS_DVBS2, PSK_8, FEC_3_5,  0x00, 0x0c },390 { SYS_DVBS2, PSK_8, FEC_2_3,  0x00, 0x0d },391 { SYS_DVBS2, PSK_8, FEC_3_4,  0x00, 0x0e },392 { SYS_DVBS2, PSK_8, FEC_5_6,  0x00, 0x0f },393 { SYS_DVBS2, PSK_8, FEC_8_9,  0x00, 0x10 },394 { SYS_DVBS2, PSK_8, FEC_9_10, 0x00, 0x11 },395 /*396  * `val' can be found in the FECSTATUS register when tuning.397  * FECSTATUS will give the actual FEC in use if tuning was successful.398  */399};400 401static int cx24116_lookup_fecmod(struct cx24116_state *state,402	enum fe_delivery_system d, enum fe_modulation m, enum fe_code_rate f)403{404	int i, ret = -EOPNOTSUPP;405 406	dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f);407 408	for (i = 0; i < ARRAY_SIZE(CX24116_MODFEC_MODES); i++) {409		if ((d == CX24116_MODFEC_MODES[i].delivery_system) &&410			(m == CX24116_MODFEC_MODES[i].modulation) &&411			(f == CX24116_MODFEC_MODES[i].fec)) {412				ret = i;413				break;414			}415	}416 417	return ret;418}419 420static int cx24116_set_fec(struct cx24116_state *state,421			   enum fe_delivery_system delsys,422			   enum fe_modulation mod,423			   enum fe_code_rate fec)424{425	int ret = 0;426 427	dprintk("%s(0x%02x,0x%02x)\n", __func__, mod, fec);428 429	ret = cx24116_lookup_fecmod(state, delsys, mod, fec);430 431	if (ret < 0)432		return ret;433 434	state->dnxt.fec = fec;435	state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val;436	state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask;437	dprintk("%s() mask/val = 0x%02x/0x%02x\n", __func__,438		state->dnxt.fec_mask, state->dnxt.fec_val);439 440	return 0;441}442 443static int cx24116_set_symbolrate(struct cx24116_state *state, u32 rate)444{445	dprintk("%s(%d)\n", __func__, rate);446 447	/*  check if symbol rate is within limits */448	if ((rate > state->frontend.ops.info.symbol_rate_max) ||449	    (rate < state->frontend.ops.info.symbol_rate_min)) {450		dprintk("%s() unsupported symbol_rate = %d\n", __func__, rate);451		return -EOPNOTSUPP;452	}453 454	state->dnxt.symbol_rate = rate;455	dprintk("%s() symbol_rate = %d\n", __func__, rate);456 457	return 0;458}459 460static int cx24116_load_firmware(struct dvb_frontend *fe,461	const struct firmware *fw);462 463static int cx24116_firmware_ondemand(struct dvb_frontend *fe)464{465	struct cx24116_state *state = fe->demodulator_priv;466	const struct firmware *fw;467	int ret = 0;468 469	dprintk("%s()\n", __func__);470 471	if (cx24116_readreg(state, 0x20) > 0) {472 473		if (state->skip_fw_load)474			return 0;475 476		/* Load firmware */477		/* request the firmware, this will block until loaded */478		printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n",479			__func__, CX24116_DEFAULT_FIRMWARE);480		ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE,481			state->i2c->dev.parent);482		printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n",483			__func__);484		if (ret) {485			printk(KERN_ERR "%s: No firmware uploaded (timeout or file not found?)\n",486			       __func__);487			return ret;488		}489 490		/* Make sure we don't recurse back through here491		 * during loading */492		state->skip_fw_load = 1;493 494		ret = cx24116_load_firmware(fe, fw);495		if (ret)496			printk(KERN_ERR "%s: Writing firmware to device failed\n",497				__func__);498 499		release_firmware(fw);500 501		printk(KERN_INFO "%s: Firmware upload %s\n", __func__,502			ret == 0 ? "complete" : "failed");503 504		/* Ensure firmware is always loaded if required */505		state->skip_fw_load = 0;506	}507 508	return ret;509}510 511/* Take a basic firmware command structure, format it512 * and forward it for processing513 */514static int cx24116_cmd_execute(struct dvb_frontend *fe, struct cx24116_cmd *cmd)515{516	struct cx24116_state *state = fe->demodulator_priv;517	int i, ret;518 519	dprintk("%s()\n", __func__);520 521	/* Load the firmware if required */522	ret = cx24116_firmware_ondemand(fe);523	if (ret != 0) {524		printk(KERN_ERR "%s(): Unable initialise the firmware\n",525			__func__);526		return ret;527	}528 529	/* Write the command */530	for (i = 0; i < cmd->len ; i++) {531		dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]);532		cx24116_writereg(state, i, cmd->args[i]);533	}534 535	/* Start execution and wait for cmd to terminate */536	cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01);537	while (cx24116_readreg(state, CX24116_REG_EXECUTE)) {538		msleep(10);539		if (i++ > 64) {540			/* Avoid looping forever if the firmware does541				not respond */542			printk(KERN_WARNING "%s() Firmware not responding\n",543				__func__);544			return -EREMOTEIO;545		}546	}547	return 0;548}549 550static int cx24116_load_firmware(struct dvb_frontend *fe,551	const struct firmware *fw)552{553	struct cx24116_state *state = fe->demodulator_priv;554	struct cx24116_cmd cmd;555	int i, ret, len, max, remaining;556	unsigned char vers[4];557 558	dprintk("%s\n", __func__);559	dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n",560			fw->size,561			fw->data[0],562			fw->data[1],563			fw->data[fw->size-2],564			fw->data[fw->size-1]);565 566	/* Toggle 88x SRST pin to reset demod */567	if (state->config->reset_device)568		state->config->reset_device(fe);569 570	/* Begin the firmware load process */571	/* Prepare the demod, load the firmware, cleanup after load */572 573	/* Init PLL */574	cx24116_writereg(state, 0xE5, 0x00);575	cx24116_writereg(state, 0xF1, 0x08);576	cx24116_writereg(state, 0xF2, 0x13);577 578	/* Start PLL */579	cx24116_writereg(state, 0xe0, 0x03);580	cx24116_writereg(state, 0xe0, 0x00);581 582	/* Unknown */583	cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);584	cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);585 586	/* Unknown */587	cx24116_writereg(state, 0xF0, 0x03);588	cx24116_writereg(state, 0xF4, 0x81);589	cx24116_writereg(state, 0xF5, 0x00);590	cx24116_writereg(state, 0xF6, 0x00);591 592	/* Split firmware to the max I2C write len and write.593	 * Writes whole firmware as one write when i2c_wr_max is set to 0. */594	if (state->config->i2c_wr_max)595		max = state->config->i2c_wr_max;596	else597		max = INT_MAX; /* enough for 32k firmware */598 599	for (remaining = fw->size; remaining > 0; remaining -= max - 1) {600		len = remaining;601		if (len > max - 1)602			len = max - 1;603 604		cx24116_writeregN(state, 0xF7, &fw->data[fw->size - remaining],605			len);606	}607 608	cx24116_writereg(state, 0xF4, 0x10);609	cx24116_writereg(state, 0xF0, 0x00);610	cx24116_writereg(state, 0xF8, 0x06);611 612	/* Firmware CMD 10: VCO config */613	cmd.args[0x00] = CMD_SET_VCO;614	cmd.args[0x01] = 0x05;615	cmd.args[0x02] = 0xdc;616	cmd.args[0x03] = 0xda;617	cmd.args[0x04] = 0xae;618	cmd.args[0x05] = 0xaa;619	cmd.args[0x06] = 0x04;620	cmd.args[0x07] = 0x9d;621	cmd.args[0x08] = 0xfc;622	cmd.args[0x09] = 0x06;623	cmd.len = 0x0a;624	ret = cx24116_cmd_execute(fe, &cmd);625	if (ret != 0)626		return ret;627 628	cx24116_writereg(state, CX24116_REG_SSTATUS, 0x00);629 630	/* Firmware CMD 14: Tuner config */631	cmd.args[0x00] = CMD_TUNERINIT;632	cmd.args[0x01] = 0x00;633	cmd.args[0x02] = 0x00;634	cmd.len = 0x03;635	ret = cx24116_cmd_execute(fe, &cmd);636	if (ret != 0)637		return ret;638 639	cx24116_writereg(state, 0xe5, 0x00);640 641	/* Firmware CMD 13: MPEG config */642	cmd.args[0x00] = CMD_MPEGCONFIG;643	cmd.args[0x01] = 0x01;644	cmd.args[0x02] = 0x75;645	cmd.args[0x03] = 0x00;646	if (state->config->mpg_clk_pos_pol)647		cmd.args[0x04] = state->config->mpg_clk_pos_pol;648	else649		cmd.args[0x04] = 0x02;650	cmd.args[0x05] = 0x00;651	cmd.len = 0x06;652	ret = cx24116_cmd_execute(fe, &cmd);653	if (ret != 0)654		return ret;655 656	/* Firmware CMD 35: Get firmware version */657	cmd.args[0x00] = CMD_UPDFWVERS;658	cmd.len = 0x02;659	for (i = 0; i < 4; i++) {660		cmd.args[0x01] = i;661		ret = cx24116_cmd_execute(fe, &cmd);662		if (ret != 0)663			return ret;664		vers[i] = cx24116_readreg(state, CX24116_REG_MAILBOX);665	}666	printk(KERN_INFO "%s: FW version %i.%i.%i.%i\n", __func__,667		vers[0], vers[1], vers[2], vers[3]);668 669	return 0;670}671 672static int cx24116_read_status(struct dvb_frontend *fe, enum fe_status *status)673{674	struct cx24116_state *state = fe->demodulator_priv;675 676	int lock = cx24116_readreg(state, CX24116_REG_SSTATUS) &677		CX24116_STATUS_MASK;678 679	dprintk("%s: status = 0x%02x\n", __func__, lock);680 681	*status = 0;682 683	if (lock & CX24116_HAS_SIGNAL)684		*status |= FE_HAS_SIGNAL;685	if (lock & CX24116_HAS_CARRIER)686		*status |= FE_HAS_CARRIER;687	if (lock & CX24116_HAS_VITERBI)688		*status |= FE_HAS_VITERBI;689	if (lock & CX24116_HAS_SYNCLOCK)690		*status |= FE_HAS_SYNC | FE_HAS_LOCK;691 692	return 0;693}694 695static int cx24116_read_ber(struct dvb_frontend *fe, u32 *ber)696{697	struct cx24116_state *state = fe->demodulator_priv;698 699	dprintk("%s()\n", __func__);700 701	*ber =  (cx24116_readreg(state, CX24116_REG_BER24) << 24) |702		(cx24116_readreg(state, CX24116_REG_BER16) << 16) |703		(cx24116_readreg(state, CX24116_REG_BER8)  << 8)  |704		 cx24116_readreg(state, CX24116_REG_BER0);705 706	return 0;707}708 709/* TODO Determine function and scale appropriately */710static int cx24116_read_signal_strength(struct dvb_frontend *fe,711	u16 *signal_strength)712{713	struct cx24116_state *state = fe->demodulator_priv;714	struct cx24116_cmd cmd;715	int ret;716	u16 sig_reading;717 718	dprintk("%s()\n", __func__);719 720	/* Firmware CMD 19: Get AGC */721	cmd.args[0x00] = CMD_GETAGC;722	cmd.len = 0x01;723	ret = cx24116_cmd_execute(fe, &cmd);724	if (ret != 0)725		return ret;726 727	sig_reading =728		(cx24116_readreg(state,729			CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK) |730		(cx24116_readreg(state, CX24116_REG_SIGNAL) << 6);731	*signal_strength = 0 - sig_reading;732 733	dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n",734		__func__, sig_reading, *signal_strength);735 736	return 0;737}738 739/* SNR (0..100)% = (sig & 0xf0) * 10 + (sig & 0x0f) * 10 / 16 */740static int cx24116_read_snr_pct(struct dvb_frontend *fe, u16 *snr)741{742	struct cx24116_state *state = fe->demodulator_priv;743	u8 snr_reading;744	int ret;745	static const u32 snr_tab[] = { /* 10 x Table (rounded up) */746		0x00000, 0x0199A, 0x03333, 0x04ccD, 0x06667,747		0x08000, 0x0999A, 0x0b333, 0x0cccD, 0x0e667,748		0x10000, 0x1199A, 0x13333, 0x14ccD, 0x16667,749		0x18000 };750 751	dprintk("%s()\n", __func__);752 753	ret = cx24116_readreg(state, CX24116_REG_QUALITY0);754	if (ret  < 0)755		return ret;756 757	snr_reading = ret;758 759	if (snr_reading >= 0xa0 /* 100% */)760		*snr = 0xffff;761	else762		*snr = snr_tab[(snr_reading & 0xf0) >> 4] +763			(snr_tab[(snr_reading & 0x0f)] >> 4);764 765	dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,766		snr_reading, *snr);767 768	return 0;769}770 771/* The reelbox patches show the value in the registers represents772 * ESNO, from 0->30db (values 0->300). We provide this value by773 * default.774 */775static int cx24116_read_snr_esno(struct dvb_frontend *fe, u16 *snr)776{777	struct cx24116_state *state = fe->demodulator_priv;778 779	dprintk("%s()\n", __func__);780 781	*snr = cx24116_readreg(state, CX24116_REG_QUALITY8) << 8 |782		cx24116_readreg(state, CX24116_REG_QUALITY0);783 784	dprintk("%s: raw 0x%04x\n", __func__, *snr);785 786	return 0;787}788 789static int cx24116_read_snr(struct dvb_frontend *fe, u16 *snr)790{791	if (esno_snr == 1)792		return cx24116_read_snr_esno(fe, snr);793	else794		return cx24116_read_snr_pct(fe, snr);795}796 797static int cx24116_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)798{799	struct cx24116_state *state = fe->demodulator_priv;800 801	dprintk("%s()\n", __func__);802 803	*ucblocks = (cx24116_readreg(state, CX24116_REG_UCB8) << 8) |804		cx24116_readreg(state, CX24116_REG_UCB0);805 806	return 0;807}808 809/* Overwrite the current tuning params, we are about to tune */810static void cx24116_clone_params(struct dvb_frontend *fe)811{812	struct cx24116_state *state = fe->demodulator_priv;813	state->dcur = state->dnxt;814}815 816/* Wait for LNB */817static int cx24116_wait_for_lnb(struct dvb_frontend *fe)818{819	struct cx24116_state *state = fe->demodulator_priv;820	int i;821 822	dprintk("%s() qstatus = 0x%02x\n", __func__,823		cx24116_readreg(state, CX24116_REG_QSTATUS));824 825	/* Wait for up to 300 ms */826	for (i = 0; i < 30 ; i++) {827		if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20)828			return 0;829		msleep(10);830	}831 832	dprintk("%s(): LNB not ready\n", __func__);833 834	return -ETIMEDOUT; /* -EBUSY ? */835}836 837static int cx24116_set_voltage(struct dvb_frontend *fe,838	enum fe_sec_voltage voltage)839{840	struct cx24116_cmd cmd;841	int ret;842 843	dprintk("%s: %s\n", __func__,844		voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :845		voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");846 847	/* Wait for LNB ready */848	ret = cx24116_wait_for_lnb(fe);849	if (ret != 0)850		return ret;851 852	/* Wait for voltage/min repeat delay */853	msleep(100);854 855	cmd.args[0x00] = CMD_LNBDCLEVEL;856	cmd.args[0x01] = (voltage == SEC_VOLTAGE_18 ? 0x01 : 0x00);857	cmd.len = 0x02;858 859	/* Min delay time before DiSEqC send */860	msleep(15);861 862	return cx24116_cmd_execute(fe, &cmd);863}864 865static int cx24116_set_tone(struct dvb_frontend *fe,866	enum fe_sec_tone_mode tone)867{868	struct cx24116_cmd cmd;869	int ret;870 871	dprintk("%s(%d)\n", __func__, tone);872	if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) {873		printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone);874		return -EINVAL;875	}876 877	/* Wait for LNB ready */878	ret = cx24116_wait_for_lnb(fe);879	if (ret != 0)880		return ret;881 882	/* Min delay time after DiSEqC send */883	msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */884 885	/* Now we set the tone */886	cmd.args[0x00] = CMD_SET_TONE;887	cmd.args[0x01] = 0x00;888	cmd.args[0x02] = 0x00;889 890	switch (tone) {891	case SEC_TONE_ON:892		dprintk("%s: setting tone on\n", __func__);893		cmd.args[0x03] = 0x01;894		break;895	case SEC_TONE_OFF:896		dprintk("%s: setting tone off\n", __func__);897		cmd.args[0x03] = 0x00;898		break;899	}900	cmd.len = 0x04;901 902	/* Min delay time before DiSEqC send */903	msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */904 905	return cx24116_cmd_execute(fe, &cmd);906}907 908/* Initialise DiSEqC */909static int cx24116_diseqc_init(struct dvb_frontend *fe)910{911	struct cx24116_state *state = fe->demodulator_priv;912	struct cx24116_cmd cmd;913	int ret;914 915	/* Firmware CMD 20: LNB/DiSEqC config */916	cmd.args[0x00] = CMD_LNBCONFIG;917	cmd.args[0x01] = 0x00;918	cmd.args[0x02] = 0x10;919	cmd.args[0x03] = 0x00;920	cmd.args[0x04] = 0x8f;921	cmd.args[0x05] = 0x28;922	cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01;923	cmd.args[0x07] = 0x01;924	cmd.len = 0x08;925	ret = cx24116_cmd_execute(fe, &cmd);926	if (ret != 0)927		return ret;928 929	/* Prepare a DiSEqC command */930	state->dsec_cmd.args[0x00] = CMD_LNBSEND;931 932	/* DiSEqC burst */933	state->dsec_cmd.args[CX24116_DISEQC_BURST]  = CX24116_DISEQC_MINI_A;934 935	/* Unknown */936	state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;937	state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;938	/* Continuation flag? */939	state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00;940 941	/* DiSEqC message length */942	state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00;943 944	/* Command length */945	state->dsec_cmd.len = CX24116_DISEQC_MSGOFS;946 947	return 0;948}949 950/* Send DiSEqC message with derived burst (hack) || previous burst */951static int cx24116_send_diseqc_msg(struct dvb_frontend *fe,952	struct dvb_diseqc_master_cmd *d)953{954	struct cx24116_state *state = fe->demodulator_priv;955	int i, ret;956 957	/* Validate length */958	if (d->msg_len > sizeof(d->msg))959		return -EINVAL;960 961	/* Dump DiSEqC message */962	if (debug) {963		printk(KERN_INFO "cx24116: %s(", __func__);964		for (i = 0 ; i < d->msg_len ;) {965			printk(KERN_INFO "0x%02x", d->msg[i]);966			if (++i < d->msg_len)967				printk(KERN_INFO ", ");968		}969		printk(") toneburst=%d\n", toneburst);970	}971 972	/* DiSEqC message */973	for (i = 0; i < d->msg_len; i++)974		state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i];975 976	/* DiSEqC message length */977	state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len;978 979	/* Command length */980	state->dsec_cmd.len = CX24116_DISEQC_MSGOFS +981		state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];982 983	/* DiSEqC toneburst */984	if (toneburst == CX24116_DISEQC_MESGCACHE)985		/* Message is cached */986		return 0;987 988	else if (toneburst == CX24116_DISEQC_TONEOFF)989		/* Message is sent without burst */990		state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0;991 992	else if (toneburst == CX24116_DISEQC_TONECACHE) {993		/*994		 * Message is sent with derived else cached burst995		 *996		 * WRITE PORT GROUP COMMAND 38997		 *998		 * 0/A/A: E0 10 38 F0..F3999		 * 1/B/B: E0 10 38 F4..F71000		 * 2/C/A: E0 10 38 F8..FB1001		 * 3/D/B: E0 10 38 FC..FF1002		 *1003		 * databyte[3]= 8421:84211004		 *              ABCD:WXYZ1005		 *              CLR :SET1006		 *1007		 *              WX= PORT SELECT 0..3    (X=TONEBURST)1008		 *              Y = VOLTAGE             (0=13V, 1=18V)1009		 *              Z = BAND                (0=LOW, 1=HIGH(22K))1010		 */1011		if (d->msg_len >= 4 && d->msg[2] == 0x38)1012			state->dsec_cmd.args[CX24116_DISEQC_BURST] =1013				((d->msg[3] & 4) >> 2);1014		if (debug)1015			dprintk("%s burst=%d\n", __func__,1016				state->dsec_cmd.args[CX24116_DISEQC_BURST]);1017	}1018 1019	/* Wait for LNB ready */1020	ret = cx24116_wait_for_lnb(fe);1021	if (ret != 0)1022		return ret;1023 1024	/* Wait for voltage/min repeat delay */1025	msleep(100);1026 1027	/* Command */1028	ret = cx24116_cmd_execute(fe, &state->dsec_cmd);1029	if (ret != 0)1030		return ret;1031	/*1032	 * Wait for send1033	 *1034	 * Eutelsat spec:1035	 * >15ms delay          + (XXX determine if FW does this, see set_tone)1036	 *  13.5ms per byte     +1037	 * >15ms delay          +1038	 *  12.5ms burst        +1039	 * >15ms delay            (XXX determine if FW does this, see set_tone)1040	 */1041	msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) +1042		((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60));1043 1044	return 0;1045}1046 1047/* Send DiSEqC burst */1048static int cx24116_diseqc_send_burst(struct dvb_frontend *fe,1049	enum fe_sec_mini_cmd burst)1050{1051	struct cx24116_state *state = fe->demodulator_priv;1052	int ret;1053 1054	dprintk("%s(%d) toneburst=%d\n", __func__, burst, toneburst);1055 1056	/* DiSEqC burst */1057	if (burst == SEC_MINI_A)1058		state->dsec_cmd.args[CX24116_DISEQC_BURST] =1059			CX24116_DISEQC_MINI_A;1060	else if (burst == SEC_MINI_B)1061		state->dsec_cmd.args[CX24116_DISEQC_BURST] =1062			CX24116_DISEQC_MINI_B;1063	else1064		return -EINVAL;1065 1066	/* DiSEqC toneburst */1067	if (toneburst != CX24116_DISEQC_MESGCACHE)1068		/* Burst is cached */1069		return 0;1070 1071	/* Burst is to be sent with cached message */1072 1073	/* Wait for LNB ready */1074	ret = cx24116_wait_for_lnb(fe);1075	if (ret != 0)1076		return ret;1077 1078	/* Wait for voltage/min repeat delay */1079	msleep(100);1080 1081	/* Command */1082	ret = cx24116_cmd_execute(fe, &state->dsec_cmd);1083	if (ret != 0)1084		return ret;1085 1086	/*1087	 * Wait for send1088	 *1089	 * Eutelsat spec:1090	 * >15ms delay          + (XXX determine if FW does this, see set_tone)1091	 *  13.5ms per byte     +1092	 * >15ms delay          +1093	 *  12.5ms burst        +1094	 * >15ms delay            (XXX determine if FW does this, see set_tone)1095	 */1096	msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60);1097 1098	return 0;1099}1100 1101static void cx24116_release(struct dvb_frontend *fe)1102{1103	struct cx24116_state *state = fe->demodulator_priv;1104	dprintk("%s\n", __func__);1105	kfree(state);1106}1107 1108static const struct dvb_frontend_ops cx24116_ops;1109 1110struct dvb_frontend *cx24116_attach(const struct cx24116_config *config,1111	struct i2c_adapter *i2c)1112{1113	struct cx24116_state *state;1114	int ret;1115 1116	dprintk("%s\n", __func__);1117 1118	/* allocate memory for the internal state */1119	state = kzalloc(sizeof(*state), GFP_KERNEL);1120	if (state == NULL)1121		return NULL;1122 1123	state->config = config;1124	state->i2c = i2c;1125 1126	/* check if the demod is present */1127	ret = (cx24116_readreg(state, 0xFF) << 8) |1128		cx24116_readreg(state, 0xFE);1129	if (ret != 0x0501) {1130		kfree(state);1131		printk(KERN_INFO "Invalid probe, probably not a CX24116 device\n");1132		return NULL;1133	}1134 1135	/* create dvb_frontend */1136	memcpy(&state->frontend.ops, &cx24116_ops,1137		sizeof(struct dvb_frontend_ops));1138	state->frontend.demodulator_priv = state;1139	return &state->frontend;1140}1141EXPORT_SYMBOL_GPL(cx24116_attach);1142 1143/*1144 * Initialise or wake up device1145 *1146 * Power config will reset and load initial firmware if required1147 */1148static int cx24116_initfe(struct dvb_frontend *fe)1149{1150	struct cx24116_state *state = fe->demodulator_priv;1151	struct cx24116_cmd cmd;1152	int ret;1153 1154	dprintk("%s()\n", __func__);1155 1156	/* Power on */1157	cx24116_writereg(state, 0xe0, 0);1158	cx24116_writereg(state, 0xe1, 0);1159	cx24116_writereg(state, 0xea, 0);1160 1161	/* Firmware CMD 36: Power config */1162	cmd.args[0x00] = CMD_TUNERSLEEP;1163	cmd.args[0x01] = 0;1164	cmd.len = 0x02;1165	ret = cx24116_cmd_execute(fe, &cmd);1166	if (ret != 0)1167		return ret;1168 1169	ret = cx24116_diseqc_init(fe);1170	if (ret != 0)1171		return ret;1172 1173	/* HVR-4000 needs this */1174	return cx24116_set_voltage(fe, SEC_VOLTAGE_13);1175}1176 1177/*1178 * Put device to sleep1179 */1180static int cx24116_sleep(struct dvb_frontend *fe)1181{1182	struct cx24116_state *state = fe->demodulator_priv;1183	struct cx24116_cmd cmd;1184	int ret;1185 1186	dprintk("%s()\n", __func__);1187 1188	/* Firmware CMD 36: Power config */1189	cmd.args[0x00] = CMD_TUNERSLEEP;1190	cmd.args[0x01] = 1;1191	cmd.len = 0x02;1192	ret = cx24116_cmd_execute(fe, &cmd);1193	if (ret != 0)1194		return ret;1195 1196	/* Power off (Shutdown clocks) */1197	cx24116_writereg(state, 0xea, 0xff);1198	cx24116_writereg(state, 0xe1, 1);1199	cx24116_writereg(state, 0xe0, 1);1200 1201	return 0;1202}1203 1204/* dvb-core told us to tune, the tv property cache will be complete,1205 * it's safe for is to pull values and use them for tuning purposes.1206 */1207static int cx24116_set_frontend(struct dvb_frontend *fe)1208{1209	struct cx24116_state *state = fe->demodulator_priv;1210	struct dtv_frontend_properties *c = &fe->dtv_property_cache;1211	struct cx24116_cmd cmd;1212	enum fe_status tunerstat;1213	int i, status, ret, retune = 1;1214 1215	dprintk("%s()\n", __func__);1216 1217	switch (c->delivery_system) {1218	case SYS_DVBS:1219		dprintk("%s: DVB-S delivery system selected\n", __func__);1220 1221		/* Only QPSK is supported for DVB-S */1222		if (c->modulation != QPSK) {1223			dprintk("%s: unsupported modulation selected (%d)\n",1224				__func__, c->modulation);1225			return -EOPNOTSUPP;1226		}1227 1228		/* Pilot doesn't exist in DVB-S, turn bit off */1229		state->dnxt.pilot_val = CX24116_PILOT_OFF;1230 1231		/* DVB-S only supports 0.35 */1232		if (c->rolloff != ROLLOFF_35) {1233			dprintk("%s: unsupported rolloff selected (%d)\n",1234				__func__, c->rolloff);1235			return -EOPNOTSUPP;1236		}1237		state->dnxt.rolloff_val = CX24116_ROLLOFF_035;1238		break;1239 1240	case SYS_DVBS2:1241		dprintk("%s: DVB-S2 delivery system selected\n", __func__);1242 1243		/*1244		 * NBC 8PSK/QPSK with DVB-S is supported for DVB-S2,1245		 * but not hardware auto detection1246		 */1247		if (c->modulation != PSK_8 && c->modulation != QPSK) {1248			dprintk("%s: unsupported modulation selected (%d)\n",1249				__func__, c->modulation);1250			return -EOPNOTSUPP;1251		}1252 1253		switch (c->pilot) {1254		case PILOT_AUTO:	/* Not supported but emulated */1255			state->dnxt.pilot_val = (c->modulation == QPSK)1256				? CX24116_PILOT_OFF : CX24116_PILOT_ON;1257			retune++;1258			break;1259		case PILOT_OFF:1260			state->dnxt.pilot_val = CX24116_PILOT_OFF;1261			break;1262		case PILOT_ON:1263			state->dnxt.pilot_val = CX24116_PILOT_ON;1264			break;1265		default:1266			dprintk("%s: unsupported pilot mode selected (%d)\n",1267				__func__, c->pilot);1268			return -EOPNOTSUPP;1269		}1270 1271		switch (c->rolloff) {1272		case ROLLOFF_20:1273			state->dnxt.rolloff_val = CX24116_ROLLOFF_020;1274			break;1275		case ROLLOFF_25:1276			state->dnxt.rolloff_val = CX24116_ROLLOFF_025;1277			break;1278		case ROLLOFF_35:1279			state->dnxt.rolloff_val = CX24116_ROLLOFF_035;1280			break;1281		case ROLLOFF_AUTO:	/* Rolloff must be explicit */1282		default:1283			dprintk("%s: unsupported rolloff selected (%d)\n",1284				__func__, c->rolloff);1285			return -EOPNOTSUPP;1286		}1287		break;1288 1289	default:1290		dprintk("%s: unsupported delivery system selected (%d)\n",1291			__func__, c->delivery_system);1292		return -EOPNOTSUPP;1293	}1294	state->dnxt.delsys = c->delivery_system;1295	state->dnxt.modulation = c->modulation;1296	state->dnxt.frequency = c->frequency;1297	state->dnxt.pilot = c->pilot;1298	state->dnxt.rolloff = c->rolloff;1299 1300	ret = cx24116_set_inversion(state, c->inversion);1301	if (ret !=  0)1302		return ret;1303 1304	/* FEC_NONE/AUTO for DVB-S2 is not supported and detected here */1305	ret = cx24116_set_fec(state, c->delivery_system, c->modulation, c->fec_inner);1306	if (ret !=  0)1307		return ret;1308 1309	ret = cx24116_set_symbolrate(state, c->symbol_rate);1310	if (ret !=  0)1311		return ret;1312 1313	/* discard the 'current' tuning parameters and prepare to tune */1314	cx24116_clone_params(fe);1315 1316	dprintk("%s:   delsys      = %d\n", __func__, state->dcur.delsys);1317	dprintk("%s:   modulation  = %d\n", __func__, state->dcur.modulation);1318	dprintk("%s:   frequency   = %d\n", __func__, state->dcur.frequency);1319	dprintk("%s:   pilot       = %d (val = 0x%02x)\n", __func__,1320		state->dcur.pilot, state->dcur.pilot_val);1321	dprintk("%s:   retune      = %d\n", __func__, retune);1322	dprintk("%s:   rolloff     = %d (val = 0x%02x)\n", __func__,1323		state->dcur.rolloff, state->dcur.rolloff_val);1324	dprintk("%s:   symbol_rate = %d\n", __func__, state->dcur.symbol_rate);1325	dprintk("%s:   FEC         = %d (mask/val = 0x%02x/0x%02x)\n", __func__,1326		state->dcur.fec, state->dcur.fec_mask, state->dcur.fec_val);1327	dprintk("%s:   Inversion   = %d (val = 0x%02x)\n", __func__,1328		state->dcur.inversion, state->dcur.inversion_val);1329 1330	/* This is also done in advise/acquire on HVR4000 but not on LITE */1331	if (state->config->set_ts_params)1332		state->config->set_ts_params(fe, 0);1333 1334	/* Set/Reset B/W */1335	cmd.args[0x00] = CMD_BANDWIDTH;1336	cmd.args[0x01] = 0x01;1337	cmd.len = 0x02;1338	ret = cx24116_cmd_execute(fe, &cmd);1339	if (ret != 0)1340		return ret;1341 1342	/* Prepare a tune request */1343	cmd.args[0x00] = CMD_TUNEREQUEST;1344 1345	/* Frequency */1346	cmd.args[0x01] = (state->dcur.frequency & 0xff0000) >> 16;1347	cmd.args[0x02] = (state->dcur.frequency & 0x00ff00) >> 8;1348	cmd.args[0x03] = (state->dcur.frequency & 0x0000ff);1349 1350	/* Symbol Rate */1351	cmd.args[0x04] = ((state->dcur.symbol_rate / 1000) & 0xff00) >> 8;1352	cmd.args[0x05] = ((state->dcur.symbol_rate / 1000) & 0x00ff);1353 1354	/* Automatic Inversion */1355	cmd.args[0x06] = state->dcur.inversion_val;1356 1357	/* Modulation / FEC / Pilot */1358	cmd.args[0x07] = state->dcur.fec_val | state->dcur.pilot_val;1359 1360	cmd.args[0x08] = CX24116_SEARCH_RANGE_KHZ >> 8;1361	cmd.args[0x09] = CX24116_SEARCH_RANGE_KHZ & 0xff;1362	cmd.args[0x0a] = 0x00;1363	cmd.args[0x0b] = 0x00;1364	cmd.args[0x0c] = state->dcur.rolloff_val;1365	cmd.args[0x0d] = state->dcur.fec_mask;1366 1367	if (state->dcur.symbol_rate > 30000000) {1368		cmd.args[0x0e] = 0x04;1369		cmd.args[0x0f] = 0x00;1370		cmd.args[0x10] = 0x01;1371		cmd.args[0x11] = 0x77;1372		cmd.args[0x12] = 0x36;1373		cx24116_writereg(state, CX24116_REG_CLKDIV, 0x44);1374		cx24116_writereg(state, CX24116_REG_RATEDIV, 0x01);1375	} else {1376		cmd.args[0x0e] = 0x06;1377		cmd.args[0x0f] = 0x00;1378		cmd.args[0x10] = 0x00;1379		cmd.args[0x11] = 0xFA;1380		cmd.args[0x12] = 0x24;1381		cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);1382		cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);1383	}1384 1385	cmd.len = 0x13;1386 1387	/* We need to support pilot and non-pilot tuning in the1388	 * driver automatically. This is a workaround for because1389	 * the demod does not support autodetect.1390	 */1391	do {1392		/* Reset status register */1393		status = cx24116_readreg(state, CX24116_REG_SSTATUS)1394			& CX24116_SIGNAL_MASK;1395		cx24116_writereg(state, CX24116_REG_SSTATUS, status);1396 1397		/* Tune */1398		ret = cx24116_cmd_execute(fe, &cmd);1399		if (ret != 0)1400			break;1401 1402		/*1403		 * Wait for up to 500 ms before retrying1404		 *1405		 * If we are able to tune then generally it occurs within 100ms.1406		 * If it takes longer, try a different toneburst setting.1407		 */1408		for (i = 0; i < 50 ; i++) {1409			cx24116_read_status(fe, &tunerstat);1410			status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC);1411			if (status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {1412				dprintk("%s: Tuned\n", __func__);1413				goto tuned;1414			}1415			msleep(10);1416		}1417 1418		dprintk("%s: Not tuned\n", __func__);1419 1420		/* Toggle pilot bit when in auto-pilot */1421		if (state->dcur.pilot == PILOT_AUTO)1422			cmd.args[0x07] ^= CX24116_PILOT_ON;1423	} while (--retune);1424 1425tuned:  /* Set/Reset B/W */1426	cmd.args[0x00] = CMD_BANDWIDTH;1427	cmd.args[0x01] = 0x00;1428	cmd.len = 0x02;1429	return cx24116_cmd_execute(fe, &cmd);1430}1431 1432static int cx24116_tune(struct dvb_frontend *fe, bool re_tune,1433	unsigned int mode_flags, unsigned int *delay, enum fe_status *status)1434{1435	/*1436	 * It is safe to discard "params" here, as the DVB core will sync1437	 * fe->dtv_property_cache with fepriv->parameters_in, where the1438	 * DVBv3 params are stored. The only practical usage for it indicate1439	 * that re-tuning is needed, e. g. (fepriv->state & FESTATE_RETUNE) is1440	 * true.1441	 */1442 1443	*delay = HZ / 5;1444	if (re_tune) {1445		int ret = cx24116_set_frontend(fe);1446		if (ret)1447			return ret;1448	}1449	return cx24116_read_status(fe, status);1450}1451 1452static enum dvbfe_algo cx24116_get_algo(struct dvb_frontend *fe)1453{1454	return DVBFE_ALGO_HW;1455}1456 1457static const struct dvb_frontend_ops cx24116_ops = {1458	.delsys = { SYS_DVBS, SYS_DVBS2 },1459	.info = {1460		.name = "Conexant CX24116/CX24118",1461		.frequency_min_hz = 950 * MHz,1462		.frequency_max_hz = 2150 * MHz,1463		.frequency_stepsize_hz = 1011 * kHz,1464		.frequency_tolerance_hz = 5 * MHz,1465		.symbol_rate_min = 1000000,1466		.symbol_rate_max = 45000000,1467		.caps = FE_CAN_INVERSION_AUTO |1468			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |1469			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |1470			FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |1471			FE_CAN_2G_MODULATION |1472			FE_CAN_QPSK | FE_CAN_RECOVER1473	},1474 1475	.release = cx24116_release,1476 1477	.init = cx24116_initfe,1478	.sleep = cx24116_sleep,1479	.read_status = cx24116_read_status,1480	.read_ber = cx24116_read_ber,1481	.read_signal_strength = cx24116_read_signal_strength,1482	.read_snr = cx24116_read_snr,1483	.read_ucblocks = cx24116_read_ucblocks,1484	.set_tone = cx24116_set_tone,1485	.set_voltage = cx24116_set_voltage,1486	.diseqc_send_master_cmd = cx24116_send_diseqc_msg,1487	.diseqc_send_burst = cx24116_diseqc_send_burst,1488	.get_frontend_algo = cx24116_get_algo,1489	.tune = cx24116_tune,1490 1491	.set_frontend = cx24116_set_frontend,1492};1493 1494MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware");1495MODULE_AUTHOR("Steven Toth");1496MODULE_LICENSE("GPL");1497 1498