/* Read RX RDS data */
static ssize_t fm_v4l2_fops_read(struct file *file, char __user * buf,
					size_t count, loff_t *ppos)
{
	u8 rds_mode;
	int ret, no_of_chans;
	struct fmdev *fmdev;

	fmdev = video_drvdata(file);

	no_of_chans = fmdev->rx.no_of_chans;

	if (!radio_disconnected) {
		fmerr("FM device is already disconnected\n");
		return -EIO;
	}

	if (fmdev->rx.comp_scan_status == 1) {
		fmdev->rx.comp_scan_status = 0;
		memcpy(buf, &fmdev->rx.stat_found[0], 4*fmdev->rx.no_of_chans);

		if (fmdev->rx.rds.pause == 1) {
			fmdev->rx.rds.pause = 0;

			ret = fmc_set_rds_mode(fmdev, FM_RDS_ENABLE);
			if (ret < 0)
				fmerr("Failed to set RX RDS mode\n");
		}

		/* Set back the Original Frequency */
		fmc_set_freq(fmdev, fmdev->rx.freq);

		return 4*fmdev->rx.no_of_chans;
	}

	/* Turn on RDS mode , if it is disabled */
	ret = fm_rx_get_rds_mode(fmdev, &rds_mode);
	if (ret < 0) {
		fmerr("Unable to read current rds mode\n");
		return ret;
	}

	if (rds_mode == FM_RDS_DISABLE) {
		ret = fmc_set_rds_mode(fmdev, FM_RDS_ENABLE);
		if (ret < 0) {
			fmerr("Failed to enable rds mode\n");
			return ret;
		}
	}

	/* Copy RDS data from internal buffer to user buffer */
	return fmc_transfer_rds_from_internal_buff(fmdev, file, buf, count);
}
示例#2
0
/* Read RX RDS data */
static ssize_t fm_v4l2_fops_read(struct file *file, char __user * buf,
					size_t count, loff_t *ppos)
{
	u8 rds_mode;
	int ret;
	struct fmdev *fmdev;

	fmdev = video_drvdata(file);

	if (!radio_disconnected) {
		fmerr("FM device is already disconnected\n");
		return -EIO;
	}

	/* Turn on RDS mode , if it is disabled */
	ret = fm_rx_get_rds_mode(fmdev, &rds_mode);
	if (ret < 0) {
		fmerr("Unable to read current rds mode\n");
		return ret;
	}

	if (rds_mode == FM_RDS_DISABLE) {
		ret = fmc_set_rds_mode(fmdev, FM_RDS_ENABLE);
		if (ret < 0) {
			fmerr("Failed to enable rds mode\n");
			return ret;
		}
	}

	/* Copy RDS data from internal buffer to user buffer */
	return fmc_transfer_rds_from_internal_buff(fmdev, file, buf, count);
}
/*
 * Set tuner attributes. If current mode is NOT RX, set to RX.
 * Currently, we set only audio mode (mono/stereo) and RDS state (on/off).
 * Should we set other tuner attributes, too?
 */
static int fm_v4l2_vidioc_s_tuner(struct file *file, void *priv,
		struct v4l2_tuner *tuner)
{
	struct fmdev *fmdev = video_drvdata(file);
	u16 aud_mode;
	u8 rds_mode;
	int ret;

	if (tuner->index != 0)
		return -EINVAL;

	aud_mode = (tuner->audmode == V4L2_TUNER_MODE_STEREO) ?
			FM_STEREO_MODE : FM_MONO_MODE;
	rds_mode = (tuner->rxsubchans & V4L2_TUNER_SUB_RDS) ?
			FM_RDS_ENABLE : FM_RDS_DISABLE;

	if (fmdev->curr_fmmode != FM_MODE_RX) {
		ret = fmc_set_mode(fmdev, FM_MODE_RX);
		if (ret < 0) {
			fmerr("Failed to set RX mode\n");
			return ret;
		}
	}

	ret = fmc_set_stereo_mono(fmdev, aud_mode);
	if (ret < 0) {
		fmerr("Failed to set RX stereo/mono mode\n");
		return ret;
	}

	ret = fmc_set_rds_mode(fmdev, rds_mode);
	if (ret < 0)
		fmerr("Failed to set RX RDS mode\n");

	return ret;
}