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

radio-si470x-i2c.c (13947B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * drivers/media/radio/si470x/radio-si470x-i2c.c
      4 *
      5 * I2C driver for radios with Silicon Labs Si470x FM Radio Receivers
      6 *
      7 * Copyright (c) 2009 Samsung Electronics Co.Ltd
      8 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
      9 */
     10
     11
     12/* driver definitions */
     13#define DRIVER_AUTHOR "Joonyoung Shim <jy0922.shim@samsung.com>";
     14#define DRIVER_CARD "Silicon Labs Si470x FM Radio"
     15#define DRIVER_DESC "I2C radio driver for Si470x FM Radio Receivers"
     16#define DRIVER_VERSION "1.0.2"
     17
     18/* kernel includes */
     19#include <linux/i2c.h>
     20#include <linux/slab.h>
     21#include <linux/delay.h>
     22#include <linux/gpio/consumer.h>
     23#include <linux/interrupt.h>
     24
     25#include "radio-si470x.h"
     26
     27
     28/* I2C Device ID List */
     29static const struct i2c_device_id si470x_i2c_id[] = {
     30	/* Generic Entry */
     31	{ "si470x", 0 },
     32	/* Terminating entry */
     33	{ }
     34};
     35MODULE_DEVICE_TABLE(i2c, si470x_i2c_id);
     36
     37
     38/**************************************************************************
     39 * Module Parameters
     40 **************************************************************************/
     41
     42/* Radio Nr */
     43static int radio_nr = -1;
     44module_param(radio_nr, int, 0444);
     45MODULE_PARM_DESC(radio_nr, "Radio Nr");
     46
     47/* RDS buffer blocks */
     48static unsigned int rds_buf = 100;
     49module_param(rds_buf, uint, 0444);
     50MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
     51
     52/* RDS maximum block errors */
     53static unsigned short max_rds_errors = 1;
     54/* 0 means   0  errors requiring correction */
     55/* 1 means 1-2  errors requiring correction (used by original USBRadio.exe) */
     56/* 2 means 3-5  errors requiring correction */
     57/* 3 means   6+ errors or errors in checkword, correction not possible */
     58module_param(max_rds_errors, ushort, 0644);
     59MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*");
     60
     61
     62
     63/**************************************************************************
     64 * I2C Definitions
     65 **************************************************************************/
     66
     67/* Write starts with the upper byte of register 0x02 */
     68#define WRITE_REG_NUM		8
     69#define WRITE_INDEX(i)		(i + 0x02)
     70
     71/* Read starts with the upper byte of register 0x0a */
     72#define READ_REG_NUM		RADIO_REGISTER_NUM
     73#define READ_INDEX(i)		((i + RADIO_REGISTER_NUM - 0x0a) % READ_REG_NUM)
     74
     75
     76
     77/**************************************************************************
     78 * General Driver Functions - REGISTERs
     79 **************************************************************************/
     80
     81/*
     82 * si470x_get_register - read register
     83 */
     84static int si470x_get_register(struct si470x_device *radio, int regnr)
     85{
     86	__be16 buf[READ_REG_NUM];
     87	struct i2c_msg msgs[1] = {
     88		{
     89			.addr = radio->client->addr,
     90			.flags = I2C_M_RD,
     91			.len = sizeof(u16) * READ_REG_NUM,
     92			.buf = (void *)buf
     93		},
     94	};
     95
     96	if (i2c_transfer(radio->client->adapter, msgs, 1) != 1)
     97		return -EIO;
     98
     99	radio->registers[regnr] = __be16_to_cpu(buf[READ_INDEX(regnr)]);
    100
    101	return 0;
    102}
    103
    104
    105/*
    106 * si470x_set_register - write register
    107 */
    108static int si470x_set_register(struct si470x_device *radio, int regnr)
    109{
    110	int i;
    111	__be16 buf[WRITE_REG_NUM];
    112	struct i2c_msg msgs[1] = {
    113		{
    114			.addr = radio->client->addr,
    115			.len = sizeof(u16) * WRITE_REG_NUM,
    116			.buf = (void *)buf
    117		},
    118	};
    119
    120	for (i = 0; i < WRITE_REG_NUM; i++)
    121		buf[i] = __cpu_to_be16(radio->registers[WRITE_INDEX(i)]);
    122
    123	if (i2c_transfer(radio->client->adapter, msgs, 1) != 1)
    124		return -EIO;
    125
    126	return 0;
    127}
    128
    129
    130
    131/**************************************************************************
    132 * General Driver Functions - ENTIRE REGISTERS
    133 **************************************************************************/
    134
    135/*
    136 * si470x_get_all_registers - read entire registers
    137 */
    138static int si470x_get_all_registers(struct si470x_device *radio)
    139{
    140	int i;
    141	__be16 buf[READ_REG_NUM];
    142	struct i2c_msg msgs[1] = {
    143		{
    144			.addr = radio->client->addr,
    145			.flags = I2C_M_RD,
    146			.len = sizeof(u16) * READ_REG_NUM,
    147			.buf = (void *)buf
    148		},
    149	};
    150
    151	if (i2c_transfer(radio->client->adapter, msgs, 1) != 1)
    152		return -EIO;
    153
    154	for (i = 0; i < READ_REG_NUM; i++)
    155		radio->registers[i] = __be16_to_cpu(buf[READ_INDEX(i)]);
    156
    157	return 0;
    158}
    159
    160
    161
    162/**************************************************************************
    163 * File Operations Interface
    164 **************************************************************************/
    165
    166/*
    167 * si470x_fops_open - file open
    168 */
    169static int si470x_fops_open(struct file *file)
    170{
    171	struct si470x_device *radio = video_drvdata(file);
    172	int retval = v4l2_fh_open(file);
    173
    174	if (retval)
    175		return retval;
    176
    177	if (v4l2_fh_is_singular_file(file)) {
    178		/* start radio */
    179		retval = si470x_start(radio);
    180		if (retval < 0)
    181			goto done;
    182
    183		/* enable RDS / STC interrupt */
    184		radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDSIEN;
    185		radio->registers[SYSCONFIG1] |= SYSCONFIG1_STCIEN;
    186		radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_GPIO2;
    187		radio->registers[SYSCONFIG1] |= 0x1 << 2;
    188		retval = si470x_set_register(radio, SYSCONFIG1);
    189	}
    190
    191done:
    192	if (retval)
    193		v4l2_fh_release(file);
    194	return retval;
    195}
    196
    197
    198/*
    199 * si470x_fops_release - file release
    200 */
    201static int si470x_fops_release(struct file *file)
    202{
    203	struct si470x_device *radio = video_drvdata(file);
    204
    205	if (v4l2_fh_is_singular_file(file))
    206		/* stop radio */
    207		si470x_stop(radio);
    208
    209	return v4l2_fh_release(file);
    210}
    211
    212
    213
    214/**************************************************************************
    215 * Video4Linux Interface
    216 **************************************************************************/
    217
    218/*
    219 * si470x_vidioc_querycap - query device capabilities
    220 */
    221static int si470x_vidioc_querycap(struct file *file, void *priv,
    222				  struct v4l2_capability *capability)
    223{
    224	strscpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
    225	strscpy(capability->card, DRIVER_CARD, sizeof(capability->card));
    226	return 0;
    227}
    228
    229
    230
    231/**************************************************************************
    232 * I2C Interface
    233 **************************************************************************/
    234
    235/*
    236 * si470x_i2c_interrupt - interrupt handler
    237 */
    238static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id)
    239{
    240	struct si470x_device *radio = dev_id;
    241	unsigned char regnr;
    242	unsigned char blocknum;
    243	unsigned short bler; /* rds block errors */
    244	unsigned short rds;
    245	unsigned char tmpbuf[3];
    246	int retval = 0;
    247
    248	/* check Seek/Tune Complete */
    249	retval = si470x_get_register(radio, STATUSRSSI);
    250	if (retval < 0)
    251		goto end;
    252
    253	if (radio->registers[STATUSRSSI] & STATUSRSSI_STC)
    254		complete(&radio->completion);
    255
    256	/* safety checks */
    257	if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
    258		goto end;
    259
    260	/* Update RDS registers */
    261	for (regnr = 1; regnr < RDS_REGISTER_NUM; regnr++) {
    262		retval = si470x_get_register(radio, STATUSRSSI + regnr);
    263		if (retval < 0)
    264			goto end;
    265	}
    266
    267	/* get rds blocks */
    268	if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0)
    269		/* No RDS group ready, better luck next time */
    270		goto end;
    271
    272	for (blocknum = 0; blocknum < 4; blocknum++) {
    273		switch (blocknum) {
    274		default:
    275			bler = (radio->registers[STATUSRSSI] &
    276					STATUSRSSI_BLERA) >> 9;
    277			rds = radio->registers[RDSA];
    278			break;
    279		case 1:
    280			bler = (radio->registers[READCHAN] &
    281					READCHAN_BLERB) >> 14;
    282			rds = radio->registers[RDSB];
    283			break;
    284		case 2:
    285			bler = (radio->registers[READCHAN] &
    286					READCHAN_BLERC) >> 12;
    287			rds = radio->registers[RDSC];
    288			break;
    289		case 3:
    290			bler = (radio->registers[READCHAN] &
    291					READCHAN_BLERD) >> 10;
    292			rds = radio->registers[RDSD];
    293			break;
    294		}
    295
    296		/* Fill the V4L2 RDS buffer */
    297		put_unaligned_le16(rds, &tmpbuf);
    298		tmpbuf[2] = blocknum;		/* offset name */
    299		tmpbuf[2] |= blocknum << 3;	/* received offset */
    300		if (bler > max_rds_errors)
    301			tmpbuf[2] |= 0x80;	/* uncorrectable errors */
    302		else if (bler > 0)
    303			tmpbuf[2] |= 0x40;	/* corrected error(s) */
    304
    305		/* copy RDS block to internal buffer */
    306		memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3);
    307		radio->wr_index += 3;
    308
    309		/* wrap write pointer */
    310		if (radio->wr_index >= radio->buf_size)
    311			radio->wr_index = 0;
    312
    313		/* check for overflow */
    314		if (radio->wr_index == radio->rd_index) {
    315			/* increment and wrap read pointer */
    316			radio->rd_index += 3;
    317			if (radio->rd_index >= radio->buf_size)
    318				radio->rd_index = 0;
    319		}
    320	}
    321
    322	if (radio->wr_index != radio->rd_index)
    323		wake_up_interruptible(&radio->read_queue);
    324
    325end:
    326	return IRQ_HANDLED;
    327}
    328
    329
    330/*
    331 * si470x_i2c_probe - probe for the device
    332 */
    333static int si470x_i2c_probe(struct i2c_client *client)
    334{
    335	struct si470x_device *radio;
    336	int retval = 0;
    337
    338	/* private data allocation and initialization */
    339	radio = devm_kzalloc(&client->dev, sizeof(*radio), GFP_KERNEL);
    340	if (!radio) {
    341		retval = -ENOMEM;
    342		goto err_initial;
    343	}
    344
    345	radio->client = client;
    346	radio->band = 1; /* Default to 76 - 108 MHz */
    347	mutex_init(&radio->lock);
    348	init_completion(&radio->completion);
    349
    350	radio->get_register = si470x_get_register;
    351	radio->set_register = si470x_set_register;
    352	radio->fops_open = si470x_fops_open;
    353	radio->fops_release = si470x_fops_release;
    354	radio->vidioc_querycap = si470x_vidioc_querycap;
    355
    356	retval = v4l2_device_register(&client->dev, &radio->v4l2_dev);
    357	if (retval < 0) {
    358		dev_err(&client->dev, "couldn't register v4l2_device\n");
    359		goto err_initial;
    360	}
    361
    362	v4l2_ctrl_handler_init(&radio->hdl, 2);
    363	v4l2_ctrl_new_std(&radio->hdl, &si470x_ctrl_ops,
    364			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
    365	v4l2_ctrl_new_std(&radio->hdl, &si470x_ctrl_ops,
    366			V4L2_CID_AUDIO_VOLUME, 0, 15, 1, 15);
    367	if (radio->hdl.error) {
    368		retval = radio->hdl.error;
    369		dev_err(&client->dev, "couldn't register control\n");
    370		goto err_all;
    371	}
    372
    373	/* video device initialization */
    374	radio->videodev = si470x_viddev_template;
    375	radio->videodev.ctrl_handler = &radio->hdl;
    376	radio->videodev.lock = &radio->lock;
    377	radio->videodev.v4l2_dev = &radio->v4l2_dev;
    378	radio->videodev.release = video_device_release_empty;
    379	radio->videodev.device_caps =
    380		V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_READWRITE | V4L2_CAP_TUNER |
    381		V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE;
    382	video_set_drvdata(&radio->videodev, radio);
    383
    384	radio->gpio_reset = devm_gpiod_get_optional(&client->dev, "reset",
    385						    GPIOD_OUT_LOW);
    386	if (IS_ERR(radio->gpio_reset)) {
    387		retval = PTR_ERR(radio->gpio_reset);
    388		dev_err(&client->dev, "Failed to request gpio: %d\n", retval);
    389		goto err_all;
    390	}
    391
    392	if (radio->gpio_reset)
    393		gpiod_set_value(radio->gpio_reset, 1);
    394
    395	/* power up : need 110ms */
    396	radio->registers[POWERCFG] = POWERCFG_ENABLE;
    397	if (si470x_set_register(radio, POWERCFG) < 0) {
    398		retval = -EIO;
    399		goto err_all;
    400	}
    401	msleep(110);
    402
    403	/* get device and chip versions */
    404	if (si470x_get_all_registers(radio) < 0) {
    405		retval = -EIO;
    406		goto err_all;
    407	}
    408	dev_info(&client->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
    409			radio->registers[DEVICEID], radio->registers[SI_CHIPID]);
    410	if ((radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE) < RADIO_FW_VERSION) {
    411		dev_warn(&client->dev,
    412			"This driver is known to work with firmware version %u, but the device has firmware version %u.\n"
    413			"If you have some trouble using this driver, please report to V4L ML at linux-media@vger.kernel.org\n",
    414			RADIO_FW_VERSION,
    415			radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE);
    416	}
    417
    418	/* set initial frequency */
    419	si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
    420
    421	/* rds buffer allocation */
    422	radio->buf_size = rds_buf * 3;
    423	radio->buffer = devm_kmalloc(&client->dev, radio->buf_size, GFP_KERNEL);
    424	if (!radio->buffer) {
    425		retval = -EIO;
    426		goto err_all;
    427	}
    428
    429	/* rds buffer configuration */
    430	radio->wr_index = 0;
    431	radio->rd_index = 0;
    432	init_waitqueue_head(&radio->read_queue);
    433
    434	retval = devm_request_threaded_irq(&client->dev, client->irq, NULL,
    435					   si470x_i2c_interrupt,
    436					   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
    437					   DRIVER_NAME, radio);
    438	if (retval) {
    439		dev_err(&client->dev, "Failed to register interrupt\n");
    440		goto err_all;
    441	}
    442
    443	/* register video device */
    444	retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO,
    445			radio_nr);
    446	if (retval) {
    447		dev_warn(&client->dev, "Could not register video device\n");
    448		goto err_all;
    449	}
    450	i2c_set_clientdata(client, radio);
    451
    452	return 0;
    453err_all:
    454	v4l2_ctrl_handler_free(&radio->hdl);
    455	v4l2_device_unregister(&radio->v4l2_dev);
    456err_initial:
    457	return retval;
    458}
    459
    460
    461/*
    462 * si470x_i2c_remove - remove the device
    463 */
    464static int si470x_i2c_remove(struct i2c_client *client)
    465{
    466	struct si470x_device *radio = i2c_get_clientdata(client);
    467
    468	video_unregister_device(&radio->videodev);
    469
    470	if (radio->gpio_reset)
    471		gpiod_set_value(radio->gpio_reset, 0);
    472
    473	v4l2_ctrl_handler_free(&radio->hdl);
    474	v4l2_device_unregister(&radio->v4l2_dev);
    475	return 0;
    476}
    477
    478
    479#ifdef CONFIG_PM_SLEEP
    480/*
    481 * si470x_i2c_suspend - suspend the device
    482 */
    483static int si470x_i2c_suspend(struct device *dev)
    484{
    485	struct i2c_client *client = to_i2c_client(dev);
    486	struct si470x_device *radio = i2c_get_clientdata(client);
    487
    488	/* power down */
    489	radio->registers[POWERCFG] |= POWERCFG_DISABLE;
    490	if (si470x_set_register(radio, POWERCFG) < 0)
    491		return -EIO;
    492
    493	return 0;
    494}
    495
    496
    497/*
    498 * si470x_i2c_resume - resume the device
    499 */
    500static int si470x_i2c_resume(struct device *dev)
    501{
    502	struct i2c_client *client = to_i2c_client(dev);
    503	struct si470x_device *radio = i2c_get_clientdata(client);
    504
    505	/* power up : need 110ms */
    506	radio->registers[POWERCFG] |= POWERCFG_ENABLE;
    507	if (si470x_set_register(radio, POWERCFG) < 0)
    508		return -EIO;
    509	msleep(110);
    510
    511	return 0;
    512}
    513
    514static SIMPLE_DEV_PM_OPS(si470x_i2c_pm, si470x_i2c_suspend, si470x_i2c_resume);
    515#endif
    516
    517#if IS_ENABLED(CONFIG_OF)
    518static const struct of_device_id si470x_of_match[] = {
    519	{ .compatible = "silabs,si470x" },
    520	{ },
    521};
    522MODULE_DEVICE_TABLE(of, si470x_of_match);
    523#endif
    524
    525/*
    526 * si470x_i2c_driver - i2c driver interface
    527 */
    528static struct i2c_driver si470x_i2c_driver = {
    529	.driver = {
    530		.name		= "si470x",
    531		.of_match_table = of_match_ptr(si470x_of_match),
    532#ifdef CONFIG_PM_SLEEP
    533		.pm		= &si470x_i2c_pm,
    534#endif
    535	},
    536	.probe_new		= si470x_i2c_probe,
    537	.remove			= si470x_i2c_remove,
    538	.id_table		= si470x_i2c_id,
    539};
    540
    541module_i2c_driver(si470x_i2c_driver);
    542
    543MODULE_LICENSE("GPL");
    544MODULE_AUTHOR(DRIVER_AUTHOR);
    545MODULE_DESCRIPTION(DRIVER_DESC);
    546MODULE_VERSION(DRIVER_VERSION);