brintos

brintos / linux-shallow public Read only

0
0
Text · 28.7 KiB · 1c549ad Raw
1221 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *    Support for NXT2002 and NXT2004 - VSB/QAM4 *5 *    Copyright (C) 2005 Kirk Lapray <kirk.lapray@gmail.com>6 *    Copyright (C) 2006-2014 Michael Krufky <mkrufky@linuxtv.org>7 *    based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net>8 *    and nxt2004 by Jean-Francois Thibert <jeanfrancois@sagetv.com>9*/10 11/*12 *                      NOTES ABOUT THIS DRIVER13 *14 * This Linux driver supports:15 *   B2C2/BBTI Technisat Air2PC - ATSC (NXT2002)16 *   AverTVHD MCE A180 (NXT2004)17 *   ATI HDTV Wonder (NXT2004)18 *19 * This driver needs external firmware. Please use the command20 * "<kerneldir>/scripts/get_dvb_firmware nxt2002" or21 * "<kerneldir>/scripts/get_dvb_firmware nxt2004" to22 * download/extract the appropriate firmware, and then copy it to23 * /usr/lib/hotplug/firmware/ or /lib/firmware/24 * (depending on configuration of firmware hotplug).25 */26#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt27 28/* Max transfer size done by I2C transfer functions */29#define MAX_XFER_SIZE  25630 31#define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw"32#define NXT2004_DEFAULT_FIRMWARE "dvb-fe-nxt2004.fw"33#define CRC_CCIT_MASK 0x102134 35#include <linux/kernel.h>36#include <linux/init.h>37#include <linux/module.h>38#include <linux/slab.h>39#include <linux/string.h>40 41#include <media/dvb_frontend.h>42#include "nxt200x.h"43 44struct nxt200x_state {45 46	struct i2c_adapter* i2c;47	const struct nxt200x_config* config;48	struct dvb_frontend frontend;49 50	/* demodulator private data */51	nxt_chip_type demod_chip;52	u8 initialised:1;53};54 55static int debug;56#define dprintk(args...)	do { if (debug) pr_debug(args); } while (0)57 58static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len)59{60	int err;61	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = len };62 63	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {64		pr_warn("%s: i2c write error (addr 0x%02x, err == %i)\n",65			__func__, addr, err);66		return -EREMOTEIO;67	}68	return 0;69}70 71static int i2c_readbytes(struct nxt200x_state *state, u8 addr, u8 *buf, u8 len)72{73	int err;74	struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len };75 76	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {77		pr_warn("%s: i2c read error (addr 0x%02x, err == %i)\n",78			__func__, addr, err);79		return -EREMOTEIO;80	}81	return 0;82}83 84static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg,85			       const u8 *buf, u8 len)86{87	u8 buf2[MAX_XFER_SIZE];88	int err;89	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf2, .len = len + 1 };90 91	if (1 + len > sizeof(buf2)) {92		pr_warn("%s: i2c wr reg=%04x: len=%d is too big!\n",93			 __func__, reg, len);94		return -EINVAL;95	}96 97	buf2[0] = reg;98	memcpy(&buf2[1], buf, len);99 100	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {101		pr_warn("%s: i2c write error (addr 0x%02x, err == %i)\n",102			__func__, state->config->demod_address, err);103		return -EREMOTEIO;104	}105	return 0;106}107 108static int nxt200x_readbytes(struct nxt200x_state *state, u8 reg, u8 *buf, u8 len)109{110	u8 reg2 [] = { reg };111 112	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = reg2, .len = 1 },113			{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } };114 115	int err;116 117	if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {118		pr_warn("%s: i2c read error (addr 0x%02x, err == %i)\n",119			__func__, state->config->demod_address, err);120		return -EREMOTEIO;121	}122	return 0;123}124 125static u16 nxt200x_crc(u16 crc, u8 c)126{127	u8 i;128	u16 input = (u16) c & 0xFF;129 130	input<<=8;131	for(i=0; i<8; i++) {132		if((crc^input) & 0x8000)133			crc=(crc<<1)^CRC_CCIT_MASK;134		else135			crc<<=1;136		input<<=1;137	}138	return crc;139}140 141static int nxt200x_writereg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len)142{143	u8 attr, len2, buf;144	dprintk("%s\n", __func__);145 146	/* set multi register register */147	nxt200x_writebytes(state, 0x35, &reg, 1);148 149	/* send the actual data */150	nxt200x_writebytes(state, 0x36, data, len);151 152	switch (state->demod_chip) {153		case NXT2002:154			len2 = len;155			buf = 0x02;156			break;157		case NXT2004:158			/* probably not right, but gives correct values */159			attr = 0x02;160			if (reg & 0x80) {161				attr = attr << 1;162				if (reg & 0x04)163					attr = attr >> 1;164			}165			/* set write bit */166			len2 = ((attr << 4) | 0x10) | len;167			buf = 0x80;168			break;169		default:170			return -EINVAL;171	}172 173	/* set multi register length */174	nxt200x_writebytes(state, 0x34, &len2, 1);175 176	/* toggle the multireg write bit */177	nxt200x_writebytes(state, 0x21, &buf, 1);178 179	nxt200x_readbytes(state, 0x21, &buf, 1);180 181	switch (state->demod_chip) {182		case NXT2002:183			if ((buf & 0x02) == 0)184				return 0;185			break;186		case NXT2004:187			if (buf == 0)188				return 0;189			break;190		default:191			return -EINVAL;192	}193 194	pr_warn("Error writing multireg register 0x%02X\n", reg);195 196	return 0;197}198 199static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len)200{201	int i;202	u8 buf, len2, attr;203	dprintk("%s\n", __func__);204 205	/* set multi register register */206	nxt200x_writebytes(state, 0x35, &reg, 1);207 208	switch (state->demod_chip) {209		case NXT2002:210			/* set multi register length */211			len2 = len & 0x80;212			nxt200x_writebytes(state, 0x34, &len2, 1);213 214			/* read the actual data */215			nxt200x_readbytes(state, reg, data, len);216			return 0;217		case NXT2004:218			/* probably not right, but gives correct values */219			attr = 0x02;220			if (reg & 0x80) {221				attr = attr << 1;222				if (reg & 0x04)223					attr = attr >> 1;224			}225 226			/* set multi register length */227			len2 = (attr << 4) | len;228			nxt200x_writebytes(state, 0x34, &len2, 1);229 230			/* toggle the multireg bit*/231			buf = 0x80;232			nxt200x_writebytes(state, 0x21, &buf, 1);233 234			/* read the actual data */235			for(i = 0; i < len; i++) {236				nxt200x_readbytes(state, 0x36 + i, &data[i], 1);237			}238			return 0;239		default:240			return -EINVAL;241	}242}243 244static void nxt200x_microcontroller_stop (struct nxt200x_state* state)245{246	u8 buf, stopval, counter = 0;247	dprintk("%s\n", __func__);248 249	/* set correct stop value */250	switch (state->demod_chip) {251		case NXT2002:252			stopval = 0x40;253			break;254		case NXT2004:255			stopval = 0x10;256			break;257		default:258			stopval = 0;259			break;260	}261 262	buf = 0x80;263	nxt200x_writebytes(state, 0x22, &buf, 1);264 265	while (counter < 20) {266		nxt200x_readbytes(state, 0x31, &buf, 1);267		if (buf & stopval)268			return;269		msleep(10);270		counter++;271	}272 273	pr_warn("Timeout waiting for nxt200x to stop. This is ok after firmware upload.\n");274	return;275}276 277static void nxt200x_microcontroller_start (struct nxt200x_state* state)278{279	u8 buf;280	dprintk("%s\n", __func__);281 282	buf = 0x00;283	nxt200x_writebytes(state, 0x22, &buf, 1);284}285 286static void nxt2004_microcontroller_init (struct nxt200x_state* state)287{288	u8 buf[9];289	u8 counter = 0;290	dprintk("%s\n", __func__);291 292	buf[0] = 0x00;293	nxt200x_writebytes(state, 0x2b, buf, 1);294	buf[0] = 0x70;295	nxt200x_writebytes(state, 0x34, buf, 1);296	buf[0] = 0x04;297	nxt200x_writebytes(state, 0x35, buf, 1);298	buf[0] = 0x01; buf[1] = 0x23; buf[2] = 0x45; buf[3] = 0x67; buf[4] = 0x89;299	buf[5] = 0xAB; buf[6] = 0xCD; buf[7] = 0xEF; buf[8] = 0xC0;300	nxt200x_writebytes(state, 0x36, buf, 9);301	buf[0] = 0x80;302	nxt200x_writebytes(state, 0x21, buf, 1);303 304	while (counter < 20) {305		nxt200x_readbytes(state, 0x21, buf, 1);306		if (buf[0] == 0)307			return;308		msleep(10);309		counter++;310	}311 312	pr_warn("Timeout waiting for nxt2004 to init.\n");313 314	return;315}316 317static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)318{319	u8 buf, count = 0;320 321	dprintk("%s\n", __func__);322 323	dprintk("Tuner Bytes: %*ph\n", 4, data + 1);324 325	/* if NXT2004, write directly to tuner. if NXT2002, write through NXT chip.326	 * direct write is required for Philips TUV1236D and ALPS TDHU2 */327	switch (state->demod_chip) {328		case NXT2004:329			if (i2c_writebytes(state, data[0], data+1, 4))330				pr_warn("error writing to tuner\n");331			/* wait until we have a lock */332			while (count < 20) {333				i2c_readbytes(state, data[0], &buf, 1);334				if (buf & 0x40)335					return 0;336				msleep(100);337				count++;338			}339			pr_warn("timeout waiting for tuner lock\n");340			break;341		case NXT2002:342			/* set the i2c transfer speed to the tuner */343			buf = 0x03;344			nxt200x_writebytes(state, 0x20, &buf, 1);345 346			/* setup to transfer 4 bytes via i2c */347			buf = 0x04;348			nxt200x_writebytes(state, 0x34, &buf, 1);349 350			/* write actual tuner bytes */351			nxt200x_writebytes(state, 0x36, data+1, 4);352 353			/* set tuner i2c address */354			buf = data[0] << 1;355			nxt200x_writebytes(state, 0x35, &buf, 1);356 357			/* write UC Opmode to begin transfer */358			buf = 0x80;359			nxt200x_writebytes(state, 0x21, &buf, 1);360 361			while (count < 20) {362				nxt200x_readbytes(state, 0x21, &buf, 1);363				if ((buf & 0x80)== 0x00)364					return 0;365				msleep(100);366				count++;367			}368			pr_warn("timeout error writing to tuner\n");369			break;370		default:371			return -EINVAL;372	}373	return 0;374}375 376static void nxt200x_agc_reset(struct nxt200x_state* state)377{378	u8 buf;379	dprintk("%s\n", __func__);380 381	switch (state->demod_chip) {382		case NXT2002:383			buf = 0x08;384			nxt200x_writebytes(state, 0x08, &buf, 1);385			buf = 0x00;386			nxt200x_writebytes(state, 0x08, &buf, 1);387			break;388		case NXT2004:389			nxt200x_readreg_multibyte(state, 0x08, &buf, 1);390			buf = 0x08;391			nxt200x_writereg_multibyte(state, 0x08, &buf, 1);392			buf = 0x00;393			nxt200x_writereg_multibyte(state, 0x08, &buf, 1);394			break;395		default:396			break;397	}398	return;399}400 401static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)402{403 404	struct nxt200x_state* state = fe->demodulator_priv;405	u8 buf[3], written = 0, chunkpos = 0;406	u16 rambase, position, crc = 0;407 408	dprintk("%s\n", __func__);409	dprintk("Firmware is %zu bytes\n", fw->size);410 411	/* Get the RAM base for this nxt2002 */412	nxt200x_readbytes(state, 0x10, buf, 1);413 414	if (buf[0] & 0x10)415		rambase = 0x1000;416	else417		rambase = 0x0000;418 419	dprintk("rambase on this nxt2002 is %04X\n", rambase);420 421	/* Hold the micro in reset while loading firmware */422	buf[0] = 0x80;423	nxt200x_writebytes(state, 0x2B, buf, 1);424 425	for (position = 0; position < fw->size; position++) {426		if (written == 0) {427			crc = 0;428			chunkpos = 0x28;429			buf[0] = ((rambase + position) >> 8);430			buf[1] = (rambase + position) & 0xFF;431			buf[2] = 0x81;432			/* write starting address */433			nxt200x_writebytes(state, 0x29, buf, 3);434		}435		written++;436		chunkpos++;437 438		if ((written % 4) == 0)439			nxt200x_writebytes(state, chunkpos, &fw->data[position-3], 4);440 441		crc = nxt200x_crc(crc, fw->data[position]);442 443		if ((written == 255) || (position+1 == fw->size)) {444			/* write remaining bytes of firmware */445			nxt200x_writebytes(state, chunkpos+4-(written %4),446				&fw->data[position-(written %4) + 1],447				written %4);448			buf[0] = crc << 8;449			buf[1] = crc & 0xFF;450 451			/* write crc */452			nxt200x_writebytes(state, 0x2C, buf, 2);453 454			/* do a read to stop things */455			nxt200x_readbytes(state, 0x2A, buf, 1);456 457			/* set transfer mode to complete */458			buf[0] = 0x80;459			nxt200x_writebytes(state, 0x2B, buf, 1);460 461			written = 0;462		}463	}464 465	return 0;466};467 468static int nxt2004_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)469{470 471	struct nxt200x_state* state = fe->demodulator_priv;472	u8 buf[3];473	u16 rambase, position, crc=0;474 475	dprintk("%s\n", __func__);476	dprintk("Firmware is %zu bytes\n", fw->size);477 478	/* set rambase */479	rambase = 0x1000;480 481	/* hold the micro in reset while loading firmware */482	buf[0] = 0x80;483	nxt200x_writebytes(state, 0x2B, buf,1);484 485	/* calculate firmware CRC */486	for (position = 0; position < fw->size; position++) {487		crc = nxt200x_crc(crc, fw->data[position]);488	}489 490	buf[0] = rambase >> 8;491	buf[1] = rambase & 0xFF;492	buf[2] = 0x81;493	/* write starting address */494	nxt200x_writebytes(state,0x29,buf,3);495 496	for (position = 0; position < fw->size;) {497		nxt200x_writebytes(state, 0x2C, &fw->data[position],498			fw->size-position > 255 ? 255 : fw->size-position);499		position += (fw->size-position > 255 ? 255 : fw->size-position);500	}501	buf[0] = crc >> 8;502	buf[1] = crc & 0xFF;503 504	dprintk("firmware crc is 0x%02X 0x%02X\n", buf[0], buf[1]);505 506	/* write crc */507	nxt200x_writebytes(state, 0x2C, buf,2);508 509	/* do a read to stop things */510	nxt200x_readbytes(state, 0x2C, buf, 1);511 512	/* set transfer mode to complete */513	buf[0] = 0x80;514	nxt200x_writebytes(state, 0x2B, buf,1);515 516	return 0;517};518 519static int nxt200x_setup_frontend_parameters(struct dvb_frontend *fe)520{521	struct dtv_frontend_properties *p = &fe->dtv_property_cache;522	struct nxt200x_state* state = fe->demodulator_priv;523	u8 buf[5];524 525	/* stop the micro first */526	nxt200x_microcontroller_stop(state);527 528	if (state->demod_chip == NXT2004) {529		/* make sure demod is set to digital */530		buf[0] = 0x04;531		nxt200x_writebytes(state, 0x14, buf, 1);532		buf[0] = 0x00;533		nxt200x_writebytes(state, 0x17, buf, 1);534	}535 536	/* set additional params */537	switch (p->modulation) {538		case QAM_64:539		case QAM_256:540			/* Set punctured clock for QAM */541			/* This is just a guess since I am unable to test it */542			if (state->config->set_ts_params)543				state->config->set_ts_params(fe, 1);544			break;545		case VSB_8:546			/* Set non-punctured clock for VSB */547			if (state->config->set_ts_params)548				state->config->set_ts_params(fe, 0);549			break;550		default:551			return -EINVAL;552	}553 554	if (fe->ops.tuner_ops.calc_regs) {555		/* get tuning information */556		fe->ops.tuner_ops.calc_regs(fe, buf, 5);557 558		/* write frequency information */559		nxt200x_writetuner(state, buf);560	}561 562	/* reset the agc now that tuning has been completed */563	nxt200x_agc_reset(state);564 565	/* set target power level */566	switch (p->modulation) {567		case QAM_64:568		case QAM_256:569			buf[0] = 0x74;570			break;571		case VSB_8:572			buf[0] = 0x70;573			break;574		default:575			return -EINVAL;576	}577	nxt200x_writebytes(state, 0x42, buf, 1);578 579	/* configure sdm */580	switch (state->demod_chip) {581		case NXT2002:582			buf[0] = 0x87;583			break;584		case NXT2004:585			buf[0] = 0x07;586			break;587		default:588			return -EINVAL;589	}590	nxt200x_writebytes(state, 0x57, buf, 1);591 592	/* write sdm1 input */593	buf[0] = 0x10;594	buf[1] = 0x00;595	switch (state->demod_chip) {596		case NXT2002:597			nxt200x_writereg_multibyte(state, 0x58, buf, 2);598			break;599		case NXT2004:600			nxt200x_writebytes(state, 0x58, buf, 2);601			break;602		default:603			return -EINVAL;604	}605 606	/* write sdmx input */607	switch (p->modulation) {608		case QAM_64:609				buf[0] = 0x68;610				break;611		case QAM_256:612				buf[0] = 0x64;613				break;614		case VSB_8:615				buf[0] = 0x60;616				break;617		default:618				return -EINVAL;619	}620	buf[1] = 0x00;621	switch (state->demod_chip) {622		case NXT2002:623			nxt200x_writereg_multibyte(state, 0x5C, buf, 2);624			break;625		case NXT2004:626			nxt200x_writebytes(state, 0x5C, buf, 2);627			break;628		default:629			return -EINVAL;630	}631 632	/* write adc power lpf fc */633	buf[0] = 0x05;634	nxt200x_writebytes(state, 0x43, buf, 1);635 636	if (state->demod_chip == NXT2004) {637		/* write ??? */638		buf[0] = 0x00;639		buf[1] = 0x00;640		nxt200x_writebytes(state, 0x46, buf, 2);641	}642 643	/* write accumulator2 input */644	buf[0] = 0x80;645	buf[1] = 0x00;646	switch (state->demod_chip) {647		case NXT2002:648			nxt200x_writereg_multibyte(state, 0x4B, buf, 2);649			break;650		case NXT2004:651			nxt200x_writebytes(state, 0x4B, buf, 2);652			break;653		default:654			return -EINVAL;655	}656 657	/* write kg1 */658	buf[0] = 0x00;659	nxt200x_writebytes(state, 0x4D, buf, 1);660 661	/* write sdm12 lpf fc */662	buf[0] = 0x44;663	nxt200x_writebytes(state, 0x55, buf, 1);664 665	/* write agc control reg */666	buf[0] = 0x04;667	nxt200x_writebytes(state, 0x41, buf, 1);668 669	if (state->demod_chip == NXT2004) {670		nxt200x_readreg_multibyte(state, 0x80, buf, 1);671		buf[0] = 0x24;672		nxt200x_writereg_multibyte(state, 0x80, buf, 1);673 674		/* soft reset? */675		nxt200x_readreg_multibyte(state, 0x08, buf, 1);676		buf[0] = 0x10;677		nxt200x_writereg_multibyte(state, 0x08, buf, 1);678		nxt200x_readreg_multibyte(state, 0x08, buf, 1);679		buf[0] = 0x00;680		nxt200x_writereg_multibyte(state, 0x08, buf, 1);681 682		nxt200x_readreg_multibyte(state, 0x80, buf, 1);683		buf[0] = 0x04;684		nxt200x_writereg_multibyte(state, 0x80, buf, 1);685		buf[0] = 0x00;686		nxt200x_writereg_multibyte(state, 0x81, buf, 1);687		buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00;688		nxt200x_writereg_multibyte(state, 0x82, buf, 3);689		nxt200x_readreg_multibyte(state, 0x88, buf, 1);690		buf[0] = 0x11;691		nxt200x_writereg_multibyte(state, 0x88, buf, 1);692		nxt200x_readreg_multibyte(state, 0x80, buf, 1);693		buf[0] = 0x44;694		nxt200x_writereg_multibyte(state, 0x80, buf, 1);695	}696 697	/* write agc ucgp0 */698	switch (p->modulation) {699		case QAM_64:700				buf[0] = 0x02;701				break;702		case QAM_256:703				buf[0] = 0x03;704				break;705		case VSB_8:706				buf[0] = 0x00;707				break;708		default:709				return -EINVAL;710	}711	nxt200x_writebytes(state, 0x30, buf, 1);712 713	/* write agc control reg */714	buf[0] = 0x00;715	nxt200x_writebytes(state, 0x41, buf, 1);716 717	/* write accumulator2 input */718	buf[0] = 0x80;719	buf[1] = 0x00;720	switch (state->demod_chip) {721		case NXT2002:722			nxt200x_writereg_multibyte(state, 0x49, buf, 2);723			nxt200x_writereg_multibyte(state, 0x4B, buf, 2);724			break;725		case NXT2004:726			nxt200x_writebytes(state, 0x49, buf, 2);727			nxt200x_writebytes(state, 0x4B, buf, 2);728			break;729		default:730			return -EINVAL;731	}732 733	/* write agc control reg */734	buf[0] = 0x04;735	nxt200x_writebytes(state, 0x41, buf, 1);736 737	nxt200x_microcontroller_start(state);738 739	if (state->demod_chip == NXT2004) {740		nxt2004_microcontroller_init(state);741 742		/* ???? */743		buf[0] = 0xF0;744		buf[1] = 0x00;745		nxt200x_writebytes(state, 0x5C, buf, 2);746	}747 748	/* adjacent channel detection should be done here, but I don't749	have any stations with this need so I cannot test it */750 751	return 0;752}753 754static int nxt200x_read_status(struct dvb_frontend *fe, enum fe_status *status)755{756	struct nxt200x_state* state = fe->demodulator_priv;757	u8 lock;758	nxt200x_readbytes(state, 0x31, &lock, 1);759 760	*status = 0;761	if (lock & 0x20) {762		*status |= FE_HAS_SIGNAL;763		*status |= FE_HAS_CARRIER;764		*status |= FE_HAS_VITERBI;765		*status |= FE_HAS_SYNC;766		*status |= FE_HAS_LOCK;767	}768	return 0;769}770 771static int nxt200x_read_ber(struct dvb_frontend* fe, u32* ber)772{773	struct nxt200x_state* state = fe->demodulator_priv;774	u8 b[3];775 776	nxt200x_readreg_multibyte(state, 0xE6, b, 3);777 778	*ber = ((b[0] << 8) + b[1]) * 8;779 780	return 0;781}782 783static int nxt200x_read_signal_strength(struct dvb_frontend* fe, u16* strength)784{785	struct nxt200x_state* state = fe->demodulator_priv;786	u8 b[2];787	u16 temp = 0;788 789	/* setup to read cluster variance */790	b[0] = 0x00;791	nxt200x_writebytes(state, 0xA1, b, 1);792 793	/* get multreg val */794	nxt200x_readreg_multibyte(state, 0xA6, b, 2);795 796	temp = (b[0] << 8) | b[1];797	*strength = ((0x7FFF - temp) & 0x0FFF) * 16;798 799	return 0;800}801 802static int nxt200x_read_snr(struct dvb_frontend* fe, u16* snr)803{804 805	struct nxt200x_state* state = fe->demodulator_priv;806	u8 b[2];807	u16 temp = 0, temp2;808	u32 snrdb = 0;809 810	/* setup to read cluster variance */811	b[0] = 0x00;812	nxt200x_writebytes(state, 0xA1, b, 1);813 814	/* get multreg val from 0xA6 */815	nxt200x_readreg_multibyte(state, 0xA6, b, 2);816 817	temp = (b[0] << 8) | b[1];818	temp2 = 0x7FFF - temp;819 820	/* snr will be in db */821	if (temp2 > 0x7F00)822		snrdb = 1000*24 + ( 1000*(30-24) * ( temp2 - 0x7F00 ) / ( 0x7FFF - 0x7F00 ) );823	else if (temp2 > 0x7EC0)824		snrdb = 1000*18 + ( 1000*(24-18) * ( temp2 - 0x7EC0 ) / ( 0x7F00 - 0x7EC0 ) );825	else if (temp2 > 0x7C00)826		snrdb = 1000*12 + ( 1000*(18-12) * ( temp2 - 0x7C00 ) / ( 0x7EC0 - 0x7C00 ) );827	else828		snrdb = 1000*0 + ( 1000*(12-0) * ( temp2 - 0 ) / ( 0x7C00 - 0 ) );829 830	/* the value reported back from the frontend will be FFFF=32db 0000=0db */831	*snr = snrdb * (0xFFFF/32000);832 833	return 0;834}835 836static int nxt200x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)837{838	struct nxt200x_state* state = fe->demodulator_priv;839	u8 b[3];840 841	nxt200x_readreg_multibyte(state, 0xE6, b, 3);842	*ucblocks = b[2];843 844	return 0;845}846 847static int nxt200x_sleep(struct dvb_frontend* fe)848{849	return 0;850}851 852static int nxt2002_init(struct dvb_frontend* fe)853{854	struct nxt200x_state* state = fe->demodulator_priv;855	const struct firmware *fw;856	int ret;857	u8 buf[2];858 859	/* request the firmware, this will block until someone uploads it */860	pr_debug("%s: Waiting for firmware upload (%s)...\n",861		 __func__, NXT2002_DEFAULT_FIRMWARE);862	ret = request_firmware(&fw, NXT2002_DEFAULT_FIRMWARE,863			       state->i2c->dev.parent);864	pr_debug("%s: Waiting for firmware upload(2)...\n", __func__);865	if (ret) {866		pr_err("%s: No firmware uploaded (timeout or file not found?)\n",867		       __func__);868		return ret;869	}870 871	ret = nxt2002_load_firmware(fe, fw);872	release_firmware(fw);873	if (ret) {874		pr_err("%s: Writing firmware to device failed\n", __func__);875		return ret;876	}877	pr_info("%s: Firmware upload complete\n", __func__);878 879	/* Put the micro into reset */880	nxt200x_microcontroller_stop(state);881 882	/* ensure transfer is complete */883	buf[0]=0x00;884	nxt200x_writebytes(state, 0x2B, buf, 1);885 886	/* Put the micro into reset for real this time */887	nxt200x_microcontroller_stop(state);888 889	/* soft reset everything (agc,frontend,eq,fec)*/890	buf[0] = 0x0F;891	nxt200x_writebytes(state, 0x08, buf, 1);892	buf[0] = 0x00;893	nxt200x_writebytes(state, 0x08, buf, 1);894 895	/* write agc sdm configure */896	buf[0] = 0xF1;897	nxt200x_writebytes(state, 0x57, buf, 1);898 899	/* write mod output format */900	buf[0] = 0x20;901	nxt200x_writebytes(state, 0x09, buf, 1);902 903	/* write fec mpeg mode */904	buf[0] = 0x7E;905	buf[1] = 0x00;906	nxt200x_writebytes(state, 0xE9, buf, 2);907 908	/* write mux selection */909	buf[0] = 0x00;910	nxt200x_writebytes(state, 0xCC, buf, 1);911 912	return 0;913}914 915static int nxt2004_init(struct dvb_frontend* fe)916{917	struct nxt200x_state* state = fe->demodulator_priv;918	const struct firmware *fw;919	int ret;920	u8 buf[3];921 922	/* ??? */923	buf[0]=0x00;924	nxt200x_writebytes(state, 0x1E, buf, 1);925 926	/* request the firmware, this will block until someone uploads it */927	pr_debug("%s: Waiting for firmware upload (%s)...\n",928		 __func__, NXT2004_DEFAULT_FIRMWARE);929	ret = request_firmware(&fw, NXT2004_DEFAULT_FIRMWARE,930			       state->i2c->dev.parent);931	pr_debug("%s: Waiting for firmware upload(2)...\n", __func__);932	if (ret) {933		pr_err("%s: No firmware uploaded (timeout or file not found?)\n",934		       __func__);935		return ret;936	}937 938	ret = nxt2004_load_firmware(fe, fw);939	release_firmware(fw);940	if (ret) {941		pr_err("%s: Writing firmware to device failed\n", __func__);942		return ret;943	}944	pr_info("%s: Firmware upload complete\n", __func__);945 946	/* ensure transfer is complete */947	buf[0] = 0x01;948	nxt200x_writebytes(state, 0x19, buf, 1);949 950	nxt2004_microcontroller_init(state);951	nxt200x_microcontroller_stop(state);952	nxt200x_microcontroller_stop(state);953	nxt2004_microcontroller_init(state);954	nxt200x_microcontroller_stop(state);955 956	/* soft reset everything (agc,frontend,eq,fec)*/957	buf[0] = 0xFF;958	nxt200x_writereg_multibyte(state, 0x08, buf, 1);959	buf[0] = 0x00;960	nxt200x_writereg_multibyte(state, 0x08, buf, 1);961 962	/* write agc sdm configure */963	buf[0] = 0xD7;964	nxt200x_writebytes(state, 0x57, buf, 1);965 966	/* ???*/967	buf[0] = 0x07;968	buf[1] = 0xfe;969	nxt200x_writebytes(state, 0x35, buf, 2);970	buf[0] = 0x12;971	nxt200x_writebytes(state, 0x34, buf, 1);972	buf[0] = 0x80;973	nxt200x_writebytes(state, 0x21, buf, 1);974 975	/* ???*/976	buf[0] = 0x21;977	nxt200x_writebytes(state, 0x0A, buf, 1);978 979	/* ???*/980	buf[0] = 0x01;981	nxt200x_writereg_multibyte(state, 0x80, buf, 1);982 983	/* write fec mpeg mode */984	buf[0] = 0x7E;985	buf[1] = 0x00;986	nxt200x_writebytes(state, 0xE9, buf, 2);987 988	/* write mux selection */989	buf[0] = 0x00;990	nxt200x_writebytes(state, 0xCC, buf, 1);991 992	/* ???*/993	nxt200x_readreg_multibyte(state, 0x80, buf, 1);994	buf[0] = 0x00;995	nxt200x_writereg_multibyte(state, 0x80, buf, 1);996 997	/* soft reset? */998	nxt200x_readreg_multibyte(state, 0x08, buf, 1);999	buf[0] = 0x10;1000	nxt200x_writereg_multibyte(state, 0x08, buf, 1);1001	nxt200x_readreg_multibyte(state, 0x08, buf, 1);1002	buf[0] = 0x00;1003	nxt200x_writereg_multibyte(state, 0x08, buf, 1);1004 1005	/* ???*/1006	nxt200x_readreg_multibyte(state, 0x80, buf, 1);1007	buf[0] = 0x01;1008	nxt200x_writereg_multibyte(state, 0x80, buf, 1);1009	buf[0] = 0x70;1010	nxt200x_writereg_multibyte(state, 0x81, buf, 1);1011	buf[0] = 0x31; buf[1] = 0x5E; buf[2] = 0x66;1012	nxt200x_writereg_multibyte(state, 0x82, buf, 3);1013 1014	nxt200x_readreg_multibyte(state, 0x88, buf, 1);1015	buf[0] = 0x11;1016	nxt200x_writereg_multibyte(state, 0x88, buf, 1);1017	nxt200x_readreg_multibyte(state, 0x80, buf, 1);1018	buf[0] = 0x40;1019	nxt200x_writereg_multibyte(state, 0x80, buf, 1);1020 1021	nxt200x_readbytes(state, 0x10, buf, 1);1022	buf[0] = 0x10;1023	nxt200x_writebytes(state, 0x10, buf, 1);1024	nxt200x_readbytes(state, 0x0A, buf, 1);1025	buf[0] = 0x21;1026	nxt200x_writebytes(state, 0x0A, buf, 1);1027 1028	nxt2004_microcontroller_init(state);1029 1030	buf[0] = 0x21;1031	nxt200x_writebytes(state, 0x0A, buf, 1);1032	buf[0] = 0x7E;1033	nxt200x_writebytes(state, 0xE9, buf, 1);1034	buf[0] = 0x00;1035	nxt200x_writebytes(state, 0xEA, buf, 1);1036 1037	nxt200x_readreg_multibyte(state, 0x80, buf, 1);1038	buf[0] = 0x00;1039	nxt200x_writereg_multibyte(state, 0x80, buf, 1);1040	nxt200x_readreg_multibyte(state, 0x80, buf, 1);1041	buf[0] = 0x00;1042	nxt200x_writereg_multibyte(state, 0x80, buf, 1);1043 1044	/* soft reset? */1045	nxt200x_readreg_multibyte(state, 0x08, buf, 1);1046	buf[0] = 0x10;1047	nxt200x_writereg_multibyte(state, 0x08, buf, 1);1048	nxt200x_readreg_multibyte(state, 0x08, buf, 1);1049	buf[0] = 0x00;1050	nxt200x_writereg_multibyte(state, 0x08, buf, 1);1051 1052	nxt200x_readreg_multibyte(state, 0x80, buf, 1);1053	buf[0] = 0x04;1054	nxt200x_writereg_multibyte(state, 0x80, buf, 1);1055	buf[0] = 0x00;1056	nxt200x_writereg_multibyte(state, 0x81, buf, 1);1057	buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00;1058	nxt200x_writereg_multibyte(state, 0x82, buf, 3);1059 1060	nxt200x_readreg_multibyte(state, 0x88, buf, 1);1061	buf[0] = 0x11;1062	nxt200x_writereg_multibyte(state, 0x88, buf, 1);1063 1064	nxt200x_readreg_multibyte(state, 0x80, buf, 1);1065	buf[0] = 0x44;1066	nxt200x_writereg_multibyte(state, 0x80, buf, 1);1067 1068	/* initialize tuner */1069	nxt200x_readbytes(state, 0x10, buf, 1);1070	buf[0] = 0x12;1071	nxt200x_writebytes(state, 0x10, buf, 1);1072	buf[0] = 0x04;1073	nxt200x_writebytes(state, 0x13, buf, 1);1074	buf[0] = 0x00;1075	nxt200x_writebytes(state, 0x16, buf, 1);1076	buf[0] = 0x04;1077	nxt200x_writebytes(state, 0x14, buf, 1);1078	buf[0] = 0x00;1079	nxt200x_writebytes(state, 0x14, buf, 1);1080	nxt200x_writebytes(state, 0x17, buf, 1);1081	nxt200x_writebytes(state, 0x14, buf, 1);1082	nxt200x_writebytes(state, 0x17, buf, 1);1083 1084	return 0;1085}1086 1087static int nxt200x_init(struct dvb_frontend* fe)1088{1089	struct nxt200x_state* state = fe->demodulator_priv;1090	int ret = 0;1091 1092	if (!state->initialised) {1093		switch (state->demod_chip) {1094			case NXT2002:1095				ret = nxt2002_init(fe);1096				break;1097			case NXT2004:1098				ret = nxt2004_init(fe);1099				break;1100			default:1101				return -EINVAL;1102		}1103		state->initialised = 1;1104	}1105	return ret;1106}1107 1108static int nxt200x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)1109{1110	fesettings->min_delay_ms = 500;1111	fesettings->step_size = 0;1112	fesettings->max_drift = 0;1113	return 0;1114}1115 1116static void nxt200x_release(struct dvb_frontend* fe)1117{1118	struct nxt200x_state* state = fe->demodulator_priv;1119	kfree(state);1120}1121 1122static const struct dvb_frontend_ops nxt200x_ops;1123 1124struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,1125				   struct i2c_adapter* i2c)1126{1127	struct nxt200x_state* state = NULL;1128	u8 buf [] = {0,0,0,0,0};1129 1130	/* allocate memory for the internal state */1131	state = kzalloc(sizeof(struct nxt200x_state), GFP_KERNEL);1132	if (state == NULL)1133		goto error;1134 1135	/* setup the state */1136	state->config = config;1137	state->i2c = i2c;1138	state->initialised = 0;1139 1140	/* read card id */1141	nxt200x_readbytes(state, 0x00, buf, 5);1142	dprintk("NXT info: %*ph\n", 5, buf);1143 1144	/* set demod chip */1145	switch (buf[0]) {1146		case 0x04:1147			state->demod_chip = NXT2002;1148			pr_info("NXT2002 Detected\n");1149			break;1150		case 0x05:1151			state->demod_chip = NXT2004;1152			pr_info("NXT2004 Detected\n");1153			break;1154		default:1155			goto error;1156	}1157 1158	/* make sure demod chip is supported */1159	switch (state->demod_chip) {1160		case NXT2002:1161			if (buf[0] != 0x04) goto error;		/* device id */1162			if (buf[1] != 0x02) goto error;		/* fab id */1163			if (buf[2] != 0x11) goto error;		/* month */1164			if (buf[3] != 0x20) goto error;		/* year msb */1165			if (buf[4] != 0x00) goto error;		/* year lsb */1166			break;1167		case NXT2004:1168			if (buf[0] != 0x05) goto error;		/* device id */1169			break;1170		default:1171			goto error;1172	}1173 1174	/* create dvb_frontend */1175	memcpy(&state->frontend.ops, &nxt200x_ops, sizeof(struct dvb_frontend_ops));1176	state->frontend.demodulator_priv = state;1177	return &state->frontend;1178 1179error:1180	kfree(state);1181	pr_err("Unknown/Unsupported NXT chip: %*ph\n", 5, buf);1182	return NULL;1183}1184 1185static const struct dvb_frontend_ops nxt200x_ops = {1186	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },1187	.info = {1188		.name = "Nextwave NXT200X VSB/QAM frontend",1189		.frequency_min_hz =  54 * MHz,1190		.frequency_max_hz = 860 * MHz,1191		.frequency_stepsize_hz = 166666,	/* stepsize is just a guess */1192		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |1193			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |1194			FE_CAN_8VSB | FE_CAN_QAM_64 | FE_CAN_QAM_2561195	},1196 1197	.release = nxt200x_release,1198 1199	.init = nxt200x_init,1200	.sleep = nxt200x_sleep,1201 1202	.set_frontend = nxt200x_setup_frontend_parameters,1203	.get_tune_settings = nxt200x_get_tune_settings,1204 1205	.read_status = nxt200x_read_status,1206	.read_ber = nxt200x_read_ber,1207	.read_signal_strength = nxt200x_read_signal_strength,1208	.read_snr = nxt200x_read_snr,1209	.read_ucblocks = nxt200x_read_ucblocks,1210};1211 1212module_param(debug, int, 0644);1213MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");1214 1215MODULE_DESCRIPTION("NXT200X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");1216MODULE_AUTHOR("Kirk Lapray, Michael Krufky, Jean-Francois Thibert, and Taylor Jacob");1217MODULE_LICENSE("GPL");1218 1219EXPORT_SYMBOL_GPL(nxt200x_attach);1220 1221