brintos

brintos / linux-shallow public Read only

0
0
Text · 25.2 KiB · def06c2 Raw
1016 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver4 *5 * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>6 */7 8#include "si2157_priv.h"9 10static const struct dvb_tuner_ops si2157_ops;11 12static int tuner_lock_debug;13module_param(tuner_lock_debug, int, 0644);14MODULE_PARM_DESC(tuner_lock_debug, "if set, signal lock is briefly waited on after setting params");15 16/* execute firmware command */17static int si2157_cmd_execute(struct i2c_client *client, struct si2157_cmd *cmd)18{19	struct si2157_dev *dev = i2c_get_clientdata(client);20	int ret;21	unsigned long timeout;22 23	mutex_lock(&dev->i2c_mutex);24 25	if (cmd->wlen) {26		/* write cmd and args for firmware */27		ret = i2c_master_send(client, cmd->args, cmd->wlen);28		if (ret < 0) {29			goto err_mutex_unlock;30		} else if (ret != cmd->wlen) {31			ret = -EREMOTEIO;32			goto err_mutex_unlock;33		}34	}35 36	if (cmd->rlen) {37		/* wait cmd execution terminate */38		#define TIMEOUT 8039		timeout = jiffies + msecs_to_jiffies(TIMEOUT);40		while (!time_after(jiffies, timeout)) {41			ret = i2c_master_recv(client, cmd->args, cmd->rlen);42			if (ret < 0) {43				goto err_mutex_unlock;44			} else if (ret != cmd->rlen) {45				ret = -EREMOTEIO;46				goto err_mutex_unlock;47			}48 49			/* firmware ready? */50			if ((cmd->args[0] >> 7) & 0x01)51				break;52		}53 54		dev_dbg(&client->dev, "cmd execution took %d ms, status=%x\n",55			jiffies_to_msecs(jiffies) -56			(jiffies_to_msecs(timeout) - TIMEOUT),57			cmd->args[0]);58 59		if (!((cmd->args[0] >> 7) & 0x01)) {60			ret = -ETIMEDOUT;61			goto err_mutex_unlock;62		}63		/* check error status bit */64		if (cmd->args[0] & 0x40) {65			ret = -EAGAIN;66			goto err_mutex_unlock;67		}68	}69 70	mutex_unlock(&dev->i2c_mutex);71	return 0;72 73err_mutex_unlock:74	mutex_unlock(&dev->i2c_mutex);75	dev_dbg(&client->dev, "failed=%d\n", ret);76	return ret;77}78 79static const struct si2157_tuner_info si2157_tuners[] = {80	{ SI2141, 0x60, false, SI2141_60_FIRMWARE, SI2141_A10_FIRMWARE },81	{ SI2141, 0x61, false, SI2141_61_FIRMWARE, SI2141_A10_FIRMWARE },82	{ SI2146, 0x11, false, SI2146_11_FIRMWARE, NULL },83	{ SI2147, 0x50, false, SI2147_50_FIRMWARE, NULL },84	{ SI2148, 0x32, true,  SI2148_32_FIRMWARE, SI2158_A20_FIRMWARE },85	{ SI2148, 0x33, true,  SI2148_33_FIRMWARE, SI2158_A20_FIRMWARE },86	{ SI2157, 0x50, false, SI2157_50_FIRMWARE, SI2157_A30_FIRMWARE },87	{ SI2158, 0x50, false, SI2158_50_FIRMWARE, SI2158_A20_FIRMWARE },88	{ SI2158, 0x51, false, SI2158_51_FIRMWARE, SI2158_A20_FIRMWARE },89	{ SI2177, 0x50, false, SI2177_50_FIRMWARE, SI2157_A30_FIRMWARE },90};91 92static int si2157_load_firmware(struct dvb_frontend *fe,93				const char *fw_name)94{95	struct i2c_client *client = fe->tuner_priv;96	const struct firmware *fw;97	int ret, len, remaining;98	struct si2157_cmd cmd;99 100	/* request the firmware, this will block and timeout */101	ret = firmware_request_nowarn(&fw, fw_name, &client->dev);102	if (ret)103		return ret;104 105	/* firmware should be n chunks of 17 bytes */106	if (fw->size % 17 != 0) {107		dev_err(&client->dev, "firmware file '%s' is invalid\n",108			fw_name);109		ret = -EINVAL;110		goto err_release_firmware;111	}112 113	dev_info(&client->dev, "downloading firmware from file '%s'\n",114		 fw_name);115 116	for (remaining = fw->size; remaining > 0; remaining -= 17) {117		len = fw->data[fw->size - remaining];118		if (len > SI2157_ARGLEN) {119			dev_err(&client->dev, "Bad firmware length\n");120			ret = -EINVAL;121			goto err_release_firmware;122		}123		memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);124		cmd.wlen = len;125		cmd.rlen = 1;126		ret = si2157_cmd_execute(client, &cmd);127		if (ret) {128			dev_err(&client->dev, "firmware download failed %d\n",129					ret);130			goto err_release_firmware;131		}132	}133 134err_release_firmware:135	release_firmware(fw);136 137	return ret;138}139 140static int si2157_find_and_load_firmware(struct dvb_frontend *fe)141{142	struct i2c_client *client = fe->tuner_priv;143	struct si2157_dev *dev = i2c_get_clientdata(client);144	const char *fw_alt_name = NULL;145	unsigned char part_id, rom_id;146	const char *fw_name = NULL;147	struct si2157_cmd cmd;148	bool required = true;149	int ret, i;150 151	if (dev->dont_load_firmware) {152		dev_info(&client->dev,153			 "device is buggy, skipping firmware download\n");154		return 0;155	}156 157	/* query chip revision */158	memcpy(cmd.args, "\x02", 1);159	cmd.wlen = 1;160	cmd.rlen = 13;161	ret = si2157_cmd_execute(client, &cmd);162	if (ret)163		return ret;164 165	part_id = cmd.args[2];166	rom_id = cmd.args[12];167 168	for (i = 0; i < ARRAY_SIZE(si2157_tuners); i++) {169		if (si2157_tuners[i].part_id != part_id)170			continue;171		required = si2157_tuners[i].required;172		fw_alt_name = si2157_tuners[i].fw_alt_name;173 174		/* Both part and rom ID match */175		if (si2157_tuners[i].rom_id == rom_id) {176			fw_name = si2157_tuners[i].fw_name;177			break;178		}179	}180 181	if (required && !fw_name && !fw_alt_name) {182		dev_err(&client->dev,183			"unknown chip version Si21%d-%c%c%c ROM 0x%02x\n",184			part_id, cmd.args[1], cmd.args[3], cmd.args[4], rom_id);185		return -EINVAL;186	}187 188	/* Update the part id based on device's report */189	dev->part_id = part_id;190 191	dev_info(&client->dev,192		 "found a 'Silicon Labs Si21%d-%c%c%c ROM 0x%02x'\n",193		 part_id, cmd.args[1], cmd.args[3], cmd.args[4], rom_id);194 195	if (fw_name)196		ret = si2157_load_firmware(fe, fw_name);197	else198		ret = -ENOENT;199 200	/* Try alternate name, if any */201	if (ret == -ENOENT && fw_alt_name)202		ret = si2157_load_firmware(fe, fw_alt_name);203 204	if (ret == -ENOENT) {205		if (!required) {206			dev_info(&client->dev, "Using ROM firmware.\n");207			return 0;208		}209		dev_err(&client->dev, "Can't continue without a firmware.\n");210	} else if (ret < 0) {211		dev_err(&client->dev, "error %d when loading firmware\n", ret);212	}213	return ret;214}215 216static int si2157_init(struct dvb_frontend *fe)217{218	struct dtv_frontend_properties *c = &fe->dtv_property_cache;219	struct i2c_client *client = fe->tuner_priv;220	struct si2157_dev *dev = i2c_get_clientdata(client);221	unsigned int xtal_trim;222	struct si2157_cmd cmd;223	int ret;224 225	dev_dbg(&client->dev, "\n");226 227	/* Try to get Xtal trim property, to verify tuner still running */228	memcpy(cmd.args, "\x15\x00\x02\x04", 4);229	cmd.wlen = 4;230	cmd.rlen = 4;231	ret = si2157_cmd_execute(client, &cmd);232 233	xtal_trim = cmd.args[2] | (cmd.args[3] << 8);234 235	if (ret == 0 && xtal_trim < 16)236		goto warm;237 238	dev->if_frequency = 0; /* we no longer know current tuner state */239 240	/* power up */241	if (dev->part_id == SI2146) {242		/* clock_mode = XTAL, clock_freq = 24MHz */243		memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9);244		cmd.wlen = 9;245	} else if (dev->part_id == SI2141) {246		/* clock_mode: XTAL, xout enabled */247		memcpy(cmd.args, "\xc0\x00\x0d\x0e\x00\x01\x01\x01\x01\x03", 10);248		cmd.wlen = 10;249	} else {250		memcpy(cmd.args, "\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15);251		cmd.wlen = 15;252	}253	cmd.rlen = 1;254	ret = si2157_cmd_execute(client, &cmd);255	if (ret && (dev->part_id != SI2141 || ret != -EAGAIN))256		goto err;257 258	/* Si2141 needs a wake up command */259	if (dev->part_id == SI2141) {260		memcpy(cmd.args, "\xc0\x08\x01\x02\x00\x00\x01", 7);261		cmd.wlen = 7;262		ret = si2157_cmd_execute(client, &cmd);263		if (ret)264			goto err;265	}266 267	/* Try to load the firmware */268	ret = si2157_find_and_load_firmware(fe);269	if (ret < 0)270		goto err;271 272	/* reboot the tuner with new firmware? */273	memcpy(cmd.args, "\x01\x01", 2);274	cmd.wlen = 2;275	cmd.rlen = 1;276	ret = si2157_cmd_execute(client, &cmd);277	if (ret)278		goto err;279 280	/* query firmware version */281	memcpy(cmd.args, "\x11", 1);282	cmd.wlen = 1;283	cmd.rlen = 10;284	ret = si2157_cmd_execute(client, &cmd);285	if (ret)286		goto err;287 288	dev_info(&client->dev, "firmware version: %c.%c.%d\n",289			cmd.args[6], cmd.args[7], cmd.args[8]);290 291	/* enable tuner status flags */292	memcpy(cmd.args, "\x14\x00\x01\x05\x01\x00", 6);293	cmd.wlen = 6;294	cmd.rlen = 1;295	ret = si2157_cmd_execute(client, &cmd);296	if (ret)297		goto err;298 299	memcpy(cmd.args, "\x14\x00\x01\x06\x01\x00", 6);300	cmd.wlen = 6;301	cmd.rlen = 1;302	ret = si2157_cmd_execute(client, &cmd);303	if (ret)304		goto err;305 306	memcpy(cmd.args, "\x14\x00\x01\x07\x01\x00", 6);307	cmd.wlen = 6;308	cmd.rlen = 1;309	ret = si2157_cmd_execute(client, &cmd);310	if (ret)311		goto err;312warm:313	/* init statistics in order signal app which are supported */314	c->strength.len = 1;315	c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;316	/* start statistics polling */317	schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(1000));318 319	dev->active = true;320	return 0;321 322err:323	dev_dbg(&client->dev, "failed=%d\n", ret);324	return ret;325}326 327static int si2157_sleep(struct dvb_frontend *fe)328{329	struct i2c_client *client = fe->tuner_priv;330	struct si2157_dev *dev = i2c_get_clientdata(client);331	int ret;332	struct si2157_cmd cmd;333 334	dev_dbg(&client->dev, "\n");335 336	dev->active = false;337 338	/* stop statistics polling */339	cancel_delayed_work_sync(&dev->stat_work);340 341	/* standby */342	memcpy(cmd.args, "\x16\x00", 2);343	cmd.wlen = 2;344	cmd.rlen = 1;345	ret = si2157_cmd_execute(client, &cmd);346	if (ret)347		goto err;348 349	return 0;350err:351	dev_dbg(&client->dev, "failed=%d\n", ret);352	return ret;353}354 355static int si2157_tune_wait(struct i2c_client *client, u8 is_digital)356{357#define TUN_TIMEOUT 40358#define DIG_TIMEOUT 30359#define ANALOG_TIMEOUT 150360	struct si2157_dev *dev = i2c_get_clientdata(client);361	int ret;362	unsigned long timeout;363	unsigned long start_time;364	u8 wait_status;365	u8  tune_lock_mask;366 367	if (is_digital)368		tune_lock_mask = 0x04;369	else370		tune_lock_mask = 0x02;371 372	mutex_lock(&dev->i2c_mutex);373 374	/* wait tuner command complete */375	start_time = jiffies;376	timeout = start_time + msecs_to_jiffies(TUN_TIMEOUT);377	while (1) {378		ret = i2c_master_recv(client, &wait_status,379				      sizeof(wait_status));380		if (ret < 0) {381			goto err_mutex_unlock;382		} else if (ret != sizeof(wait_status)) {383			ret = -EREMOTEIO;384			goto err_mutex_unlock;385		}386 387		if (time_after(jiffies, timeout))388			break;389 390		/* tuner done? */391		if ((wait_status & 0x81) == 0x81)392			break;393		usleep_range(5000, 10000);394	}395 396	dev_dbg(&client->dev, "tuning took %d ms, status=0x%x\n",397		jiffies_to_msecs(jiffies) - jiffies_to_msecs(start_time),398		wait_status);399 400	/* if we tuned ok, wait a bit for tuner lock */401	if (tuner_lock_debug && (wait_status & 0x81) == 0x81) {402		if (is_digital)403			timeout = jiffies + msecs_to_jiffies(DIG_TIMEOUT);404		else405			timeout = jiffies + msecs_to_jiffies(ANALOG_TIMEOUT);406 407		while (!time_after(jiffies, timeout)) {408			ret = i2c_master_recv(client, &wait_status,409					      sizeof(wait_status));410			if (ret < 0) {411				goto err_mutex_unlock;412			} else if (ret != sizeof(wait_status)) {413				ret = -EREMOTEIO;414				goto err_mutex_unlock;415			}416 417			/* tuner locked? */418			if (wait_status & tune_lock_mask)419				break;420			usleep_range(5000, 10000);421		}422 423		dev_dbg(&client->dev, "tuning+lock took %d ms, status=0x%x\n",424			jiffies_to_msecs(jiffies) - jiffies_to_msecs(start_time),425			wait_status);426	}427 428	if ((wait_status & 0xc0) != 0x80) {429		ret = -ETIMEDOUT;430		goto err_mutex_unlock;431	}432 433	mutex_unlock(&dev->i2c_mutex);434	return 0;435 436err_mutex_unlock:437	mutex_unlock(&dev->i2c_mutex);438	dev_err(&client->dev, "failed=%d\n", ret);439	return ret;440}441 442static int si2157_set_params(struct dvb_frontend *fe)443{444	struct i2c_client *client = fe->tuner_priv;445	struct si2157_dev *dev = i2c_get_clientdata(client);446	struct dtv_frontend_properties *c = &fe->dtv_property_cache;447	int ret;448	struct si2157_cmd cmd;449	u8 bw, delivery_system;450	u32 bandwidth;451	u32 if_frequency = 5000000;452 453	dev_dbg(&client->dev,454			"delivery_system=%d frequency=%u bandwidth_hz=%u\n",455			c->delivery_system, c->frequency, c->bandwidth_hz);456 457	if (!dev->active) {458		ret = -EAGAIN;459		goto err;460	}461 462	if (SUPPORTS_1700KHz(dev) && c->bandwidth_hz <= 1700000) {463		bandwidth = 1700000;464		bw = 9;465	} else if (c->bandwidth_hz <= 6000000) {466		bandwidth = 6000000;467		bw = 6;468	} else if (SUPPORTS_1700KHz(dev) && c->bandwidth_hz <= 6100000) {469		bandwidth = 6100000;470		bw = 10;471	} else if (c->bandwidth_hz <= 7000000) {472		bandwidth = 7000000;473		bw = 7;474	} else {475		bandwidth = 8000000;476		bw = 8;477	}478 479	switch (c->delivery_system) {480	case SYS_ATSC:481			delivery_system = 0x00;482			if_frequency = 3250000;483			break;484	case SYS_DVBC_ANNEX_B:485			delivery_system = 0x10;486			if_frequency = 4000000;487			break;488	case SYS_DVBT:489	case SYS_DVBT2: /* it seems DVB-T and DVB-T2 both are 0x20 here */490			delivery_system = 0x20;491			break;492	case SYS_DVBC_ANNEX_A:493	case SYS_DVBC_ANNEX_C:494			delivery_system = 0x30;495			break;496	case SYS_ISDBT:497			delivery_system = 0x40;498			break;499	case SYS_DTMB:500			delivery_system = 0x60;501			break;502	default:503			ret = -EINVAL;504			goto err;505	}506 507	memcpy(cmd.args, "\x14\x00\x03\x07\x00\x00", 6);508	cmd.args[4] = delivery_system | bw;509	if (dev->inversion)510		cmd.args[5] = 0x01;511	cmd.wlen = 6;512	cmd.rlen = 4;513	ret = si2157_cmd_execute(client, &cmd);514	if (ret)515		goto err;516 517	/* On SI2146, set DTV AGC source to DLIF_AGC_3DB */518	if (dev->part_id == SI2146)519		memcpy(cmd.args, "\x14\x00\x02\x07\x00\x01", 6);520	else521		memcpy(cmd.args, "\x14\x00\x02\x07\x00\x00", 6);522	cmd.args[4] = dev->if_port;523	cmd.wlen = 6;524	cmd.rlen = 4;525	ret = si2157_cmd_execute(client, &cmd);526	if (ret)527		goto err;528 529	/* set digital if frequency if needed */530	if (if_frequency != dev->if_frequency) {531		memcpy(cmd.args, "\x14\x00\x06\x07", 4);532		cmd.args[4] = (if_frequency / 1000) & 0xff;533		cmd.args[5] = ((if_frequency / 1000) >> 8) & 0xff;534		cmd.wlen = 6;535		cmd.rlen = 4;536		ret = si2157_cmd_execute(client, &cmd);537		if (ret)538			goto err;539 540		dev->if_frequency = if_frequency;541	}542 543	/* set digital frequency */544	memcpy(cmd.args, "\x41\x00\x00\x00\x00\x00\x00\x00", 8);545	cmd.args[4] = (c->frequency >>  0) & 0xff;546	cmd.args[5] = (c->frequency >>  8) & 0xff;547	cmd.args[6] = (c->frequency >> 16) & 0xff;548	cmd.args[7] = (c->frequency >> 24) & 0xff;549	cmd.wlen = 8;550	cmd.rlen = 1;551	ret = si2157_cmd_execute(client, &cmd);552	if (ret)553		goto err;554 555	dev->bandwidth = bandwidth;556	dev->frequency = c->frequency;557 558	si2157_tune_wait(client, 1); /* wait to complete, ignore any errors */559 560	return 0;561err:562	dev->bandwidth = 0;563	dev->frequency = 0;564	dev->if_frequency = 0;565	dev_dbg(&client->dev, "failed=%d\n", ret);566	return ret;567}568 569static int si2157_set_analog_params(struct dvb_frontend *fe,570				    struct analog_parameters *params)571{572	struct i2c_client *client = fe->tuner_priv;573	struct si2157_dev *dev = i2c_get_clientdata(client);574	char *std; /* for debugging */575	int ret;576	struct si2157_cmd cmd;577	u32 bandwidth = 0;578	u32 if_frequency = 0;579	u32 freq = 0;580	u64 tmp_lval = 0;581	u8 system = 0;582	u8 color = 0;    /* 0=NTSC/PAL, 0x10=SECAM */583	u8 invert_analog = 1; /* analog tuner spectrum; 0=normal, 1=inverted */584 585	if (!SUPPORTS_ATV_IF(dev)) {586		dev_info(&client->dev, "Analog tuning not supported yet for Si21%d\n",587			 dev->part_id);588		ret = -EINVAL;589		goto err;590	}591 592	if (!dev->active)593		si2157_init(fe);594 595	if (!dev->active) {596		ret = -EAGAIN;597		goto err;598	}599	if (params->mode == V4L2_TUNER_RADIO) {600	/*601	 * std = "fm";602	 * bandwidth = 1700000; //best can do for FM, AGC will be a mess though603	 * if_frequency = 1250000;  //HVR-225x(saa7164), HVR-12xx(cx23885)604	 * if_frequency = 6600000;  //HVR-9xx(cx231xx)605	 * if_frequency = 5500000;  //HVR-19xx(pvrusb2)606	 */607		dev_err(&client->dev, "si2157 does not currently support FM radio\n");608		ret = -EINVAL;609		goto err;610	}611	tmp_lval = params->frequency * 625LL;612	do_div(tmp_lval, 10); /* convert to HZ */613	freq = (u32)tmp_lval;614 615	if (freq < 1000000) /* is freq in KHz */616		freq = freq * 1000;617	dev->frequency = freq;618 619	/* if_frequency values based on tda187271C2 */620	if (params->std & (V4L2_STD_B | V4L2_STD_GH)) {621		if (freq >= 470000000) {622			std = "palGH";623			bandwidth = 8000000;624			if_frequency = 6000000;625			system = 1;626			if (params->std &627			    (V4L2_STD_SECAM_G | V4L2_STD_SECAM_H)) {628				std = "secamGH";629				color = 0x10;630			}631		} else {632			std = "palB";633			bandwidth = 7000000;634			if_frequency = 6000000;635			system = 0;636			if (params->std & V4L2_STD_SECAM_B) {637				std = "secamB";638				color = 0x10;639			}640		}641	} else if (params->std & V4L2_STD_MN) {642		std = "MN";643		bandwidth = 6000000;644		if_frequency = 5400000;645		system = 2;646	} else if (params->std & V4L2_STD_PAL_I) {647		std = "palI";648		bandwidth = 8000000;649		if_frequency = 7250000; /* TODO: does not work yet */650		system = 4;651	} else if (params->std & V4L2_STD_DK) {652		std = "palDK";653		bandwidth = 8000000;654		if_frequency = 6900000; /* TODO: does not work yet */655		system = 5;656		if (params->std & V4L2_STD_SECAM_DK) {657			std = "secamDK";658			color = 0x10;659		}660	} else if (params->std & V4L2_STD_SECAM_L) {661		std = "secamL";662		bandwidth = 8000000;663		if_frequency = 6750000; /* TODO: untested */664		system = 6;665		color = 0x10;666	} else if (params->std & V4L2_STD_SECAM_LC) {667		std = "secamL'";668		bandwidth = 7000000;669		if_frequency = 1250000; /* TODO: untested */670		system = 7;671		color = 0x10;672	} else {673		std = "unknown";674	}675	/* calc channel center freq */676	freq = freq - 1250000 + (bandwidth / 2);677 678	dev_dbg(&client->dev,679		"mode=%d system=%u std='%s' params->frequency=%u center freq=%u if=%u bandwidth=%u\n",680		params->mode, system, std, params->frequency,681		freq, if_frequency, bandwidth);682 683	/* set analog IF port */684	memcpy(cmd.args, "\x14\x00\x03\x06\x08\x02", 6);685	/* in using dev->if_port, we assume analog and digital IF's */686	/*   are always on different ports */687	/* assumes if_port definition is 0 or 1 for digital out */688	cmd.args[4] = (dev->if_port == 1) ? 8 : 10;689	/* Analog AGC assumed external */690	cmd.args[5] = (dev->if_port == 1) ? 2 : 1;691	cmd.wlen = 6;692	cmd.rlen = 4;693	ret = si2157_cmd_execute(client, &cmd);694	if (ret)695		goto err;696 697	/* set analog IF output config */698	memcpy(cmd.args, "\x14\x00\x0d\x06\x94\x64", 6);699	cmd.wlen = 6;700	cmd.rlen = 4;701	ret = si2157_cmd_execute(client, &cmd);702	if (ret)703		goto err;704 705	/* make this distinct from a digital IF */706	dev->if_frequency = if_frequency | 1;707 708	/* calc and set tuner analog if center frequency */709	if_frequency = if_frequency + 1250000 - (bandwidth / 2);710	dev_dbg(&client->dev, "IF Ctr freq=%d\n", if_frequency);711 712	memcpy(cmd.args, "\x14\x00\x0C\x06", 4);713	cmd.args[4] = (if_frequency / 1000) & 0xff;714	cmd.args[5] = ((if_frequency / 1000) >> 8) & 0xff;715	cmd.wlen = 6;716	cmd.rlen = 4;717	ret = si2157_cmd_execute(client, &cmd);718	if (ret)719		goto err;720 721	/* set analog AGC config */722	memcpy(cmd.args, "\x14\x00\x07\x06\x32\xc8", 6);723	cmd.wlen = 6;724	cmd.rlen = 4;725	ret = si2157_cmd_execute(client, &cmd);726	if (ret)727		goto err;728 729	/* set analog video mode */730	memcpy(cmd.args, "\x14\x00\x04\x06\x00\x00", 6);731	cmd.args[4] = system | color;732	/* can use dev->inversion if assumed applies to both digital/analog */733	if (invert_analog)734		cmd.args[5] |= 0x02;735	cmd.wlen = 6;736	cmd.rlen = 1;737	ret = si2157_cmd_execute(client, &cmd);738	if (ret)739		goto err;740 741	/* set analog frequency */742	memcpy(cmd.args, "\x41\x01\x00\x00\x00\x00\x00\x00", 8);743	cmd.args[4] = (freq >>  0) & 0xff;744	cmd.args[5] = (freq >>  8) & 0xff;745	cmd.args[6] = (freq >> 16) & 0xff;746	cmd.args[7] = (freq >> 24) & 0xff;747	cmd.wlen = 8;748	cmd.rlen = 1;749	ret = si2157_cmd_execute(client, &cmd);750	if (ret)751		goto err;752 753	dev->bandwidth = bandwidth;754 755	si2157_tune_wait(client, 0); /* wait to complete, ignore any errors */756 757	return 0;758err:759	dev->bandwidth = 0;760	dev->frequency = 0;761	dev->if_frequency = 0;762	dev_dbg(&client->dev, "failed=%d\n", ret);763	return ret;764}765 766static int si2157_get_frequency(struct dvb_frontend *fe, u32 *frequency)767{768	struct i2c_client *client = fe->tuner_priv;769	struct si2157_dev *dev = i2c_get_clientdata(client);770 771	*frequency = dev->frequency;772	dev_dbg(&client->dev, "freq=%u\n", dev->frequency);773	return 0;774}775 776static int si2157_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)777{778	struct i2c_client *client = fe->tuner_priv;779	struct si2157_dev *dev = i2c_get_clientdata(client);780 781	*bandwidth = dev->bandwidth;782	dev_dbg(&client->dev, "bandwidth=%u\n", dev->bandwidth);783	return 0;784}785 786static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)787{788	struct i2c_client *client = fe->tuner_priv;789	struct si2157_dev *dev = i2c_get_clientdata(client);790 791	*frequency = dev->if_frequency & ~1; /* strip analog IF indicator bit */792	dev_dbg(&client->dev, "if_frequency=%u\n", *frequency);793	return 0;794}795 796static int si2157_get_rf_strength(struct dvb_frontend *fe, u16 *rssi)797{798	struct i2c_client *client = fe->tuner_priv;799	struct dtv_frontend_properties *c = &fe->dtv_property_cache;800	struct si2157_cmd cmd;801	int ret;802	int strength;803 804	dev_dbg(&client->dev, "\n");805 806	memcpy(cmd.args, "\x42\x00", 2);807	cmd.wlen = 2;808	cmd.rlen = 12;809	ret = si2157_cmd_execute(client, &cmd);810	if (ret)811		goto err;812 813	c->strength.stat[0].scale = FE_SCALE_DECIBEL;814	c->strength.stat[0].svalue = (s8)cmd.args[3] * 1000;815 816	/* normalize values based on Silicon Labs reference817	 * add 100, then anything > 80 is 100% signal818	 */819	strength = (s8)cmd.args[3] + 100;820	strength = clamp_val(strength, 0, 80);821	*rssi = (u16)(strength * 0xffff / 80);822 823	dev_dbg(&client->dev, "strength=%d rssi=%u\n",824		(s8)cmd.args[3], *rssi);825 826	return 0;827err:828	dev_dbg(&client->dev, "failed=%d\n", ret);829	return ret;830}831 832static const struct dvb_tuner_ops si2157_ops = {833	.info = {834		.name             = "Silicon Labs Si2141/Si2146/2147/2148/2157/2158",835		.frequency_min_hz =  42 * MHz,836		.frequency_max_hz = 870 * MHz,837	},838 839	.init = si2157_init,840	.sleep = si2157_sleep,841	.set_params = si2157_set_params,842	.set_analog_params = si2157_set_analog_params,843	.get_frequency     = si2157_get_frequency,844	.get_bandwidth     = si2157_get_bandwidth,845	.get_if_frequency  = si2157_get_if_frequency,846 847	.get_rf_strength   = si2157_get_rf_strength,848};849 850static void si2157_stat_work(struct work_struct *work)851{852	struct si2157_dev *dev = container_of(work, struct si2157_dev, stat_work.work);853	struct dvb_frontend *fe = dev->fe;854	struct i2c_client *client = fe->tuner_priv;855	struct dtv_frontend_properties *c = &fe->dtv_property_cache;856	struct si2157_cmd cmd;857	int ret;858 859	dev_dbg(&client->dev, "\n");860 861	memcpy(cmd.args, "\x42\x00", 2);862	cmd.wlen = 2;863	cmd.rlen = 12;864	ret = si2157_cmd_execute(client, &cmd);865	if (ret)866		goto err;867 868	c->strength.stat[0].scale = FE_SCALE_DECIBEL;869	c->strength.stat[0].svalue = (s8) cmd.args[3] * 1000;870 871	schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));872	return;873err:874	c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;875	dev_dbg(&client->dev, "failed=%d\n", ret);876}877 878static int si2157_probe(struct i2c_client *client)879{880	const struct i2c_device_id *id = i2c_client_get_device_id(client);881	struct si2157_config *cfg = client->dev.platform_data;882	struct dvb_frontend *fe = cfg->fe;883	struct si2157_dev *dev;884	struct si2157_cmd cmd;885	int ret;886 887	dev = kzalloc(sizeof(*dev), GFP_KERNEL);888	if (!dev) {889		ret = -ENOMEM;890		dev_err(&client->dev, "kzalloc() failed\n");891		goto err;892	}893 894	i2c_set_clientdata(client, dev);895	dev->fe = cfg->fe;896	dev->inversion = cfg->inversion;897	dev->dont_load_firmware = cfg->dont_load_firmware;898	dev->if_port = cfg->if_port;899	dev->part_id = (u8)id->driver_data;900	dev->if_frequency = 5000000; /* default value of property 0x0706 */901	mutex_init(&dev->i2c_mutex);902	INIT_DELAYED_WORK(&dev->stat_work, si2157_stat_work);903 904	/* check if the tuner is there */905	cmd.wlen = 0;906	cmd.rlen = 1;907	ret = si2157_cmd_execute(client, &cmd);908	if (ret && ret != -EAGAIN)909		goto err_kfree;910 911	memcpy(&fe->ops.tuner_ops, &si2157_ops, sizeof(struct dvb_tuner_ops));912	fe->tuner_priv = client;913 914#ifdef CONFIG_MEDIA_CONTROLLER915	if (cfg->mdev) {916		dev->mdev = cfg->mdev;917 918		dev->ent.name = KBUILD_MODNAME;919		dev->ent.function = MEDIA_ENT_F_TUNER;920 921		dev->pad[SI2157_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK;922		dev->pad[SI2157_PAD_RF_INPUT].sig_type = PAD_SIGNAL_ANALOG;923		dev->pad[SI2157_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;924		dev->pad[SI2157_PAD_VID_OUT].sig_type = PAD_SIGNAL_ANALOG;925		dev->pad[SI2157_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE;926		dev->pad[SI2157_PAD_AUD_OUT].sig_type = PAD_SIGNAL_AUDIO;927 928		ret = media_entity_pads_init(&dev->ent, SI2157_NUM_PADS,929					     &dev->pad[0]);930 931		if (ret)932			goto err_kfree;933 934		ret = media_device_register_entity(cfg->mdev, &dev->ent);935		if (ret) {936			media_entity_cleanup(&dev->ent);937			goto err_kfree;938		}939	}940#endif941 942	dev_info(&client->dev, "Silicon Labs Si21%d successfully attached\n",943		 dev->part_id);944 945	return 0;946 947err_kfree:948	kfree(dev);949err:950	dev_dbg(&client->dev, "failed=%d\n", ret);951	return ret;952}953 954static void si2157_remove(struct i2c_client *client)955{956	struct si2157_dev *dev = i2c_get_clientdata(client);957	struct dvb_frontend *fe = dev->fe;958 959	dev_dbg(&client->dev, "\n");960 961	/* stop statistics polling */962	cancel_delayed_work_sync(&dev->stat_work);963 964#ifdef CONFIG_MEDIA_CONTROLLER_DVB965	if (dev->mdev)966		media_device_unregister_entity(&dev->ent);967#endif968 969	memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));970	fe->tuner_priv = NULL;971	kfree(dev);972}973 974/*975 * The part_id used here will only be used on buggy devices that don't976 * accept firmware uploads. Non-buggy devices should just use "si2157" for977 * all SiLabs TER tuners, as the driver should auto-detect it.978 */979static const struct i2c_device_id si2157_id_table[] = {980	{"si2157", SI2157},981	{"si2146", SI2146},982	{"si2141", SI2141},983	{"si2177", SI2177},984	{}985};986MODULE_DEVICE_TABLE(i2c, si2157_id_table);987 988static struct i2c_driver si2157_driver = {989	.driver = {990		.name		     = "si2157",991		.suppress_bind_attrs = true,992	},993	.probe		= si2157_probe,994	.remove		= si2157_remove,995	.id_table	= si2157_id_table,996};997 998module_i2c_driver(si2157_driver);999 1000MODULE_DESCRIPTION("Silicon Labs Si2141/Si2146/2147/2148/2157/2158 silicon tuner driver");1001MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");1002MODULE_LICENSE("GPL");1003MODULE_FIRMWARE(SI2158_A20_FIRMWARE);1004MODULE_FIRMWARE(SI2141_A10_FIRMWARE);1005MODULE_FIRMWARE(SI2157_A30_FIRMWARE);1006MODULE_FIRMWARE(SI2141_60_FIRMWARE);1007MODULE_FIRMWARE(SI2141_61_FIRMWARE);1008MODULE_FIRMWARE(SI2146_11_FIRMWARE);1009MODULE_FIRMWARE(SI2147_50_FIRMWARE);1010MODULE_FIRMWARE(SI2148_32_FIRMWARE);1011MODULE_FIRMWARE(SI2148_33_FIRMWARE);1012MODULE_FIRMWARE(SI2157_50_FIRMWARE);1013MODULE_FIRMWARE(SI2158_50_FIRMWARE);1014MODULE_FIRMWARE(SI2158_51_FIRMWARE);1015MODULE_FIRMWARE(SI2177_50_FIRMWARE);1016