brintos

brintos / linux-shallow public Read only

0
0
Text · 12.0 KiB · fb09e45 Raw
514 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3    Driver for SAA6588 RDS decoder4 5    (c) 2005 Hans J. Koch6 7*/8 9 10#include <linux/module.h>11#include <linux/kernel.h>12#include <linux/i2c.h>13#include <linux/types.h>14#include <linux/videodev2.h>15#include <linux/init.h>16#include <linux/errno.h>17#include <linux/slab.h>18#include <linux/poll.h>19#include <linux/wait.h>20#include <linux/uaccess.h>21 22#include <media/i2c/saa6588.h>23#include <media/v4l2-device.h>24 25 26/* insmod options */27static unsigned int debug;28static unsigned int xtal;29static unsigned int mmbs;30static unsigned int plvl;31static unsigned int bufblocks = 100;32 33module_param(debug, int, 0644);34MODULE_PARM_DESC(debug, "enable debug messages");35module_param(xtal, int, 0);36MODULE_PARM_DESC(xtal, "select oscillator frequency (0..3), default 0");37module_param(mmbs, int, 0);38MODULE_PARM_DESC(mmbs, "enable MMBS mode: 0=off (default), 1=on");39module_param(plvl, int, 0);40MODULE_PARM_DESC(plvl, "select pause level (0..3), default 0");41module_param(bufblocks, int, 0);42MODULE_PARM_DESC(bufblocks, "number of buffered blocks, default 100");43 44MODULE_DESCRIPTION("v4l2 driver module for SAA6588 RDS decoder");45MODULE_AUTHOR("Hans J. Koch <koch@hjk-az.de>");46 47MODULE_LICENSE("GPL");48 49/* ---------------------------------------------------------------------- */50 51#define UNSET       (-1U)52#define PREFIX      "saa6588: "53#define dprintk     if (debug) printk54 55struct saa6588 {56	struct v4l2_subdev sd;57	struct delayed_work work;58	spinlock_t lock;59	unsigned char *buffer;60	unsigned int buf_size;61	unsigned int rd_index;62	unsigned int wr_index;63	unsigned int block_count;64	unsigned char last_blocknum;65	wait_queue_head_t read_queue;66	int data_available_for_read;67	u8 sync;68};69 70static inline struct saa6588 *to_saa6588(struct v4l2_subdev *sd)71{72	return container_of(sd, struct saa6588, sd);73}74 75/* ---------------------------------------------------------------------- */76 77/*78 * SAA6588 defines79 */80 81/* Initialization and mode control byte (0w) */82 83/* bit 0+1 (DAC0/DAC1) */84#define cModeStandard           0x0085#define cModeFastPI             0x0186#define cModeReducedRequest     0x0287#define cModeInvalid            0x0388 89/* bit 2 (RBDS) */90#define cProcessingModeRDS      0x0091#define cProcessingModeRBDS     0x0492 93/* bit 3+4 (SYM0/SYM1) */94#define cErrCorrectionNone      0x0095#define cErrCorrection2Bits     0x0896#define cErrCorrection5Bits     0x1097#define cErrCorrectionNoneRBDS  0x1898 99/* bit 5 (NWSY) */100#define cSyncNormal             0x00101#define cSyncRestart            0x20102 103/* bit 6 (TSQD) */104#define cSigQualityDetectOFF    0x00105#define cSigQualityDetectON     0x40106 107/* bit 7 (SQCM) */108#define cSigQualityTriggered    0x00109#define cSigQualityContinous    0x80110 111/* Pause level and flywheel control byte (1w) */112 113/* bits 0..5 (FEB0..FEB5) */114#define cFlywheelMaxBlocksMask  0x3F115#define cFlywheelDefault        0x20116 117/* bits 6+7 (PL0/PL1) */118#define cPauseLevel_11mV	0x00119#define cPauseLevel_17mV        0x40120#define cPauseLevel_27mV        0x80121#define cPauseLevel_43mV        0xC0122 123/* Pause time/oscillator frequency/quality detector control byte (1w) */124 125/* bits 0..4 (SQS0..SQS4) */126#define cQualityDetectSensMask  0x1F127#define cQualityDetectDefault   0x0F128 129/* bit 5 (SOSC) */130#define cSelectOscFreqOFF	0x00131#define cSelectOscFreqON	0x20132 133/* bit 6+7 (PTF0/PTF1) */134#define cOscFreq_4332kHz	0x00135#define cOscFreq_8664kHz	0x40136#define cOscFreq_12996kHz	0x80137#define cOscFreq_17328kHz	0xC0138 139/* ---------------------------------------------------------------------- */140 141static bool block_from_buf(struct saa6588 *s, unsigned char *buf)142{143	int i;144 145	if (s->rd_index == s->wr_index) {146		if (debug > 2)147			dprintk(PREFIX "Read: buffer empty.\n");148		return false;149	}150 151	if (debug > 2) {152		dprintk(PREFIX "Read: ");153		for (i = s->rd_index; i < s->rd_index + 3; i++)154			dprintk("0x%02x ", s->buffer[i]);155	}156 157	memcpy(buf, &s->buffer[s->rd_index], 3);158 159	s->rd_index += 3;160	if (s->rd_index >= s->buf_size)161		s->rd_index = 0;162	s->block_count--;163 164	if (debug > 2)165		dprintk("%d blocks total.\n", s->block_count);166 167	return true;168}169 170static void read_from_buf(struct saa6588 *s, struct saa6588_command *a)171{172	unsigned char __user *buf_ptr = a->buffer;173	unsigned char buf[3];174	unsigned long flags;175	unsigned int rd_blocks;176	unsigned int i;177 178	a->result = 0;179	if (!a->buffer)180		return;181 182	while (!a->nonblocking && !s->data_available_for_read) {183		int ret = wait_event_interruptible(s->read_queue,184					     s->data_available_for_read);185		if (ret == -ERESTARTSYS) {186			a->result = -EINTR;187			return;188		}189	}190 191	rd_blocks = a->block_count;192	spin_lock_irqsave(&s->lock, flags);193	if (rd_blocks > s->block_count)194		rd_blocks = s->block_count;195	spin_unlock_irqrestore(&s->lock, flags);196 197	if (!rd_blocks)198		return;199 200	for (i = 0; i < rd_blocks; i++) {201		bool got_block;202 203		spin_lock_irqsave(&s->lock, flags);204		got_block = block_from_buf(s, buf);205		spin_unlock_irqrestore(&s->lock, flags);206		if (!got_block)207			break;208		if (copy_to_user(buf_ptr, buf, 3)) {209			a->result = -EFAULT;210			return;211		}212		buf_ptr += 3;213		a->result += 3;214	}215	spin_lock_irqsave(&s->lock, flags);216	s->data_available_for_read = (s->block_count > 0);217	spin_unlock_irqrestore(&s->lock, flags);218}219 220static void block_to_buf(struct saa6588 *s, unsigned char *blockbuf)221{222	unsigned int i;223 224	if (debug > 3)225		dprintk(PREFIX "New block: ");226 227	for (i = 0; i < 3; ++i) {228		if (debug > 3)229			dprintk("0x%02x ", blockbuf[i]);230		s->buffer[s->wr_index] = blockbuf[i];231		s->wr_index++;232	}233 234	if (s->wr_index >= s->buf_size)235		s->wr_index = 0;236 237	if (s->wr_index == s->rd_index) {238		s->rd_index += 3;239		if (s->rd_index >= s->buf_size)240			s->rd_index = 0;241	} else242		s->block_count++;243 244	if (debug > 3)245		dprintk("%d blocks total.\n", s->block_count);246}247 248static void saa6588_i2c_poll(struct saa6588 *s)249{250	struct i2c_client *client = v4l2_get_subdevdata(&s->sd);251	unsigned long flags;252	unsigned char tmpbuf[6];253	unsigned char blocknum;254	unsigned char tmp;255 256	/* Although we only need 3 bytes, we have to read at least 6.257	   SAA6588 returns garbage otherwise. */258	if (6 != i2c_master_recv(client, &tmpbuf[0], 6)) {259		if (debug > 1)260			dprintk(PREFIX "read error!\n");261		return;262	}263 264	s->sync = tmpbuf[0] & 0x10;265	if (!s->sync)266		return;267	blocknum = tmpbuf[0] >> 5;268	if (blocknum == s->last_blocknum) {269		if (debug > 3)270			dprintk("Saw block %d again.\n", blocknum);271		return;272	}273 274	s->last_blocknum = blocknum;275 276	/*277	   Byte order according to v4l2 specification:278 279	   Byte 0: Least Significant Byte of RDS Block280	   Byte 1: Most Significant Byte of RDS Block281	   Byte 2 Bit 7: Error bit. Indicates that an uncorrectable error282	   occurred during reception of this block.283	   Bit 6: Corrected bit. Indicates that an error was284	   corrected for this data block.285	   Bits 5-3: Same as bits 0-2.286	   Bits 2-0: Block number.287 288	   SAA6588 byte order is Status-MSB-LSB, so we have to swap the289	   first and the last of the 3 bytes block.290	 */291 292	swap(tmpbuf[2], tmpbuf[0]);293 294	/* Map 'Invalid block E' to 'Invalid Block' */295	if (blocknum == 6)296		blocknum = V4L2_RDS_BLOCK_INVALID;297	/* And if are not in mmbs mode, then 'Block E' is also mapped298	   to 'Invalid Block'. As far as I can tell MMBS is discontinued,299	   and if there is ever a need to support E blocks, then please300	   contact the linux-media mailinglist. */301	else if (!mmbs && blocknum == 5)302		blocknum = V4L2_RDS_BLOCK_INVALID;303	tmp = blocknum;304	tmp |= blocknum << 3;	/* Received offset == Offset Name (OK ?) */305	if ((tmpbuf[2] & 0x03) == 0x03)306		tmp |= V4L2_RDS_BLOCK_ERROR;	 /* uncorrectable error */307	else if ((tmpbuf[2] & 0x03) != 0x00)308		tmp |= V4L2_RDS_BLOCK_CORRECTED; /* corrected error */309	tmpbuf[2] = tmp;	/* Is this enough ? Should we also check other bits ? */310 311	spin_lock_irqsave(&s->lock, flags);312	block_to_buf(s, tmpbuf);313	spin_unlock_irqrestore(&s->lock, flags);314	s->data_available_for_read = 1;315	wake_up_interruptible(&s->read_queue);316}317 318static void saa6588_work(struct work_struct *work)319{320	struct saa6588 *s = container_of(work, struct saa6588, work.work);321 322	saa6588_i2c_poll(s);323	schedule_delayed_work(&s->work, msecs_to_jiffies(20));324}325 326static void saa6588_configure(struct saa6588 *s)327{328	struct i2c_client *client = v4l2_get_subdevdata(&s->sd);329	unsigned char buf[3];330	int rc;331 332	buf[0] = cSyncRestart;333	if (mmbs)334		buf[0] |= cProcessingModeRBDS;335 336	buf[1] = cFlywheelDefault;337	switch (plvl) {338	case 0:339		buf[1] |= cPauseLevel_11mV;340		break;341	case 1:342		buf[1] |= cPauseLevel_17mV;343		break;344	case 2:345		buf[1] |= cPauseLevel_27mV;346		break;347	case 3:348		buf[1] |= cPauseLevel_43mV;349		break;350	default:		/* nothing */351		break;352	}353 354	buf[2] = cQualityDetectDefault | cSelectOscFreqON;355 356	switch (xtal) {357	case 0:358		buf[2] |= cOscFreq_4332kHz;359		break;360	case 1:361		buf[2] |= cOscFreq_8664kHz;362		break;363	case 2:364		buf[2] |= cOscFreq_12996kHz;365		break;366	case 3:367		buf[2] |= cOscFreq_17328kHz;368		break;369	default:		/* nothing */370		break;371	}372 373	dprintk(PREFIX "writing: 0w=0x%02x 1w=0x%02x 2w=0x%02x\n",374		buf[0], buf[1], buf[2]);375 376	rc = i2c_master_send(client, buf, 3);377	if (rc != 3)378		printk(PREFIX "i2c i/o error: rc == %d (should be 3)\n", rc);379}380 381/* ---------------------------------------------------------------------- */382 383static long saa6588_command(struct v4l2_subdev *sd, unsigned int cmd, void *arg)384{385	struct saa6588 *s = to_saa6588(sd);386	struct saa6588_command *a = arg;387 388	switch (cmd) {389		/* --- close() for /dev/radio --- */390	case SAA6588_CMD_CLOSE:391		s->data_available_for_read = 1;392		wake_up_interruptible(&s->read_queue);393		s->data_available_for_read = 0;394		a->result = 0;395		break;396		/* --- read() for /dev/radio --- */397	case SAA6588_CMD_READ:398		read_from_buf(s, a);399		break;400		/* --- poll() for /dev/radio --- */401	case SAA6588_CMD_POLL:402		a->poll_mask = 0;403		if (s->data_available_for_read)404			a->poll_mask |= EPOLLIN | EPOLLRDNORM;405		poll_wait(a->instance, &s->read_queue, a->event_list);406		break;407 408	default:409		/* nothing */410		return -ENOIOCTLCMD;411	}412	return 0;413}414 415static int saa6588_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)416{417	struct saa6588 *s = to_saa6588(sd);418 419	vt->capability |= V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO;420	if (s->sync)421		vt->rxsubchans |= V4L2_TUNER_SUB_RDS;422	return 0;423}424 425static int saa6588_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)426{427	struct saa6588 *s = to_saa6588(sd);428 429	saa6588_configure(s);430	return 0;431}432 433/* ----------------------------------------------------------------------- */434 435static const struct v4l2_subdev_core_ops saa6588_core_ops = {436	.command = saa6588_command,437};438 439static const struct v4l2_subdev_tuner_ops saa6588_tuner_ops = {440	.g_tuner = saa6588_g_tuner,441	.s_tuner = saa6588_s_tuner,442};443 444static const struct v4l2_subdev_ops saa6588_ops = {445	.core = &saa6588_core_ops,446	.tuner = &saa6588_tuner_ops,447};448 449/* ---------------------------------------------------------------------- */450 451static int saa6588_probe(struct i2c_client *client)452{453	struct saa6588 *s;454	struct v4l2_subdev *sd;455 456	v4l_info(client, "saa6588 found @ 0x%x (%s)\n",457			client->addr << 1, client->adapter->name);458 459	s = devm_kzalloc(&client->dev, sizeof(*s), GFP_KERNEL);460	if (s == NULL)461		return -ENOMEM;462 463	s->buf_size = bufblocks * 3;464 465	s->buffer = devm_kzalloc(&client->dev, s->buf_size, GFP_KERNEL);466	if (s->buffer == NULL)467		return -ENOMEM;468	sd = &s->sd;469	v4l2_i2c_subdev_init(sd, client, &saa6588_ops);470	spin_lock_init(&s->lock);471	s->block_count = 0;472	s->wr_index = 0;473	s->rd_index = 0;474	s->last_blocknum = 0xff;475	init_waitqueue_head(&s->read_queue);476	s->data_available_for_read = 0;477 478	saa6588_configure(s);479 480	/* start polling via eventd */481	INIT_DELAYED_WORK(&s->work, saa6588_work);482	schedule_delayed_work(&s->work, 0);483	return 0;484}485 486static void saa6588_remove(struct i2c_client *client)487{488	struct v4l2_subdev *sd = i2c_get_clientdata(client);489	struct saa6588 *s = to_saa6588(sd);490 491	v4l2_device_unregister_subdev(sd);492 493	cancel_delayed_work_sync(&s->work);494}495 496/* ----------------------------------------------------------------------- */497 498static const struct i2c_device_id saa6588_id[] = {499	{ "saa6588" },500	{ }501};502MODULE_DEVICE_TABLE(i2c, saa6588_id);503 504static struct i2c_driver saa6588_driver = {505	.driver = {506		.name	= "saa6588",507	},508	.probe		= saa6588_probe,509	.remove		= saa6588_remove,510	.id_table	= saa6588_id,511};512 513module_i2c_driver(saa6588_driver);514