File Index
Files and directories
Sign in
FILE

si2157.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/tuners/si2157.c C
   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{
 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_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 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_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
 974/*
 975 * The part_id used here will only be used on buggy devices that don't
 976 * accept firmware uploads. Non-buggy devices should just use "si2157" for
 977 * 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);
~/ Read-only file preview.