cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

si2157.c (25823B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver
      4 *
      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 80
     39		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	else
    198		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 40
    358#define DIG_TIMEOUT 30
    359#define ANALOG_TIMEOUT 150
    360	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	else
    370		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		else
    405			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	else
    521		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 though
    603	 * 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 reference
    817	 * add 100, then anything > 80 is 100% signal
    818	 */
    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			const struct i2c_device_id *id)
    880{
    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_CONTROLLER
    915	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#endif
    941
    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 int 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_DVB
    965	if (dev->mdev)
    966		media_device_unregister_entity(&dev->ent);
    967#endif
    968
    969	memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
    970	fe->tuner_priv = NULL;
    971	kfree(dev);
    972
    973	return 0;
    974}
    975
    976/*
    977 * The part_id used here will only be used on buggy devices that don't
    978 * accept firmware uploads. Non-buggy devices should just use "si2157" for
    979 * all SiLabs TER tuners, as the driver should auto-detect it.
    980 */
    981static const struct i2c_device_id si2157_id_table[] = {
    982	{"si2157", SI2157},
    983	{"si2146", SI2146},
    984	{"si2141", SI2141},
    985	{"si2177", SI2177},
    986	{}
    987};
    988MODULE_DEVICE_TABLE(i2c, si2157_id_table);
    989
    990static struct i2c_driver si2157_driver = {
    991	.driver = {
    992		.name		     = "si2157",
    993		.suppress_bind_attrs = true,
    994	},
    995	.probe		= si2157_probe,
    996	.remove		= si2157_remove,
    997	.id_table	= si2157_id_table,
    998};
    999
   1000module_i2c_driver(si2157_driver);
   1001
   1002MODULE_DESCRIPTION("Silicon Labs Si2141/Si2146/2147/2148/2157/2158 silicon tuner driver");
   1003MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
   1004MODULE_LICENSE("GPL");
   1005MODULE_FIRMWARE(SI2158_A20_FIRMWARE);
   1006MODULE_FIRMWARE(SI2141_A10_FIRMWARE);
   1007MODULE_FIRMWARE(SI2157_A30_FIRMWARE);
   1008MODULE_FIRMWARE(SI2141_60_FIRMWARE);
   1009MODULE_FIRMWARE(SI2141_61_FIRMWARE);
   1010MODULE_FIRMWARE(SI2146_11_FIRMWARE);
   1011MODULE_FIRMWARE(SI2147_50_FIRMWARE);
   1012MODULE_FIRMWARE(SI2148_32_FIRMWARE);
   1013MODULE_FIRMWARE(SI2148_33_FIRMWARE);
   1014MODULE_FIRMWARE(SI2157_50_FIRMWARE);
   1015MODULE_FIRMWARE(SI2158_50_FIRMWARE);
   1016MODULE_FIRMWARE(SI2158_51_FIRMWARE);
   1017MODULE_FIRMWARE(SI2177_50_FIRMWARE);