/* Read RDS data */
static ssize_t fm_v4l2_fops_read(struct file *file, char __user * buf,
				 size_t count, loff_t *ppos)
{
	unsigned char rds_mode;
	int ret, noof_bytes_copied;
	FMDRV_API_START();

	if (!radio_disconnected) {
		FM_DRV_ERR("FM device is already disconnected\n");
		FMDRV_API_EXIT(-EIO);
		return -EIO;
	}
	/* Turn on RDS mode , if it is disabled */
	ret = fm_core_rx_get_rds_mode(&rds_mode);
	if (ret) {
		FM_DRV_ERR("Unable to read current rds mode");
		FMDRV_API_EXIT(ret);
		return ret;
	}
	if (rds_mode == FM_RX_RDS_DISABLE) {
		ret = fm_core_set_rds_mode(FM_RX_RDS_ENABLE);
		if (ret < 0) {
			FM_DRV_ERR("Unable to enable rds mode");
			FMDRV_API_EXIT(ret);
			return ret;
		}
	}
	/* Copy RDS data from internal buffer to user buffer */
	noof_bytes_copied =
	    fm_core_transfer_rds_from_internal_buff(file, buf, count);

	FMDRV_API_EXIT(noof_bytes_copied);
	return noof_bytes_copied;
}
Example #2
0
/* Forwards FM Packets to Shared Transport */
int fm_st_send(struct sk_buff *skb)
{
	long len;

	FMDRV_API_START();

	if (skb == NULL) {
		FM_DRV_ERR("Invalid skb, can't send");
		FMDRV_API_EXIT(-ENOMEM);
		return -ENOMEM;
	}

	/* Is anyone called without claiming FM ST? */
	if (is_fm_st_claimed == FM_ST_CLAIMED ) {
		/* Forward FM packet(SKB) to ST for the transmission */
		len = st_write(skb);
		if (len < 0) {
			/* Something went wrong in st write , free skb memory */
			kfree_skb(skb);
			FM_DRV_ERR(" ST write failed (%ld)", len);
			FMDRV_API_EXIT(-EAGAIN);
			return -EAGAIN;
		}
	} else {		/* Nobody calimed FM ST */

		kfree_skb(skb);
		FM_DRV_ERR("FM ST is not claimed, Can't send skb");
		FMDRV_API_EXIT(-EAGAIN);
		return -EAGAIN;
	}

	FMDRV_API_EXIT(0);
	return 0;
}
int fm_v4l2_init_video_device(struct fmdrv_ops *fmdev)
{
	FMDRV_API_START();

	/* Allocate new video device */
	fmdev->v4l2dev = video_device_alloc();
	if (!fmdev->v4l2dev) {
		FM_DRV_ERR("Can't allocate video device");
		FMDRV_API_EXIT(-ENOMEM);
		return -ENOMEM;
	}

	/* Setup FM driver's V4L2 properties */
	memcpy(fmdev->v4l2dev, &fm_viddev_template, sizeof(fm_viddev_template));

	video_set_drvdata(fmdev->v4l2dev, fmdev);

	/* Register with V4L2 subsystem as RADIO device */
	if (video_register_device(fmdev->v4l2dev, VFL_TYPE_RADIO, 0)) {
		video_device_release(fmdev->v4l2dev);
		fmdev->v4l2dev = NULL;

		FM_DRV_ERR("Could not register video device");
		FMDRV_API_EXIT(-ENOMEM);
		return -ENOMEM;
	}
	FMDRV_API_EXIT(0);
	return 0;
}
/* Set the value of a control */
static int fm_v4l2_vidioc_s_ctrl(struct file *file, void *priv,
				 struct v4l2_control *ctrl)
{
	int ret;
	FMDRV_API_START();

	switch (ctrl->id) {

	case V4L2_CID_AUDIO_MUTE:	/* set mute */
		ret = fm_core_set_mute_mode((unsigned char)ctrl->value);
		if (ret < 0) {
			FMDRV_API_EXIT(ret);
			return ret;
		}
		break;

	case V4L2_CID_AUDIO_VOLUME:	/* set volume */
		ret = fm_core_rx_set_volume((unsigned short)ctrl->value);
		if (ret < 0) {
			FMDRV_API_EXIT(ret);
			return ret;
		}
		break;
	}
	FMDRV_API_EXIT(0);
	return 0;
}
/* Set tuner attributes */
static int fm_v4l2_vidioc_s_tuner(struct file *file, void *priv,
				  struct v4l2_tuner *tuner)
{
	unsigned short mode;
	int ret;

	FMDRV_API_START();

	if ((tuner->index != 0) ||
	    (tuner->audmode != V4L2_TUNER_MODE_MONO &&
	     tuner->audmode != V4L2_TUNER_MODE_STEREO)) {
		FMDRV_API_EXIT(-EINVAL);
		return -EINVAL;
	}
	/* Map V4L2 stereo/mono macro to our local stereo/mono macro */
	mode = (tuner->audmode == V4L2_TUNER_MODE_STEREO) ?
	    FM_STEREO_MODE : FM_MONO_MODE;
	ret = fm_core_set_stereo_mono(mode);
	if (ret) {
		FMDRV_API_EXIT(ret);
		return ret;
	}

	FMDRV_API_EXIT(0);
	return 0;
}
/* Get the value of a control */
static int fm_v4l2_vidioc_g_ctrl(struct file *file, void *priv,
				 struct v4l2_control *ctrl)
{
	int ret;
	unsigned short curr_vol;
	unsigned char curr_mute_mode;

	FMDRV_API_START();

	switch (ctrl->id) {

	case V4L2_CID_AUDIO_MUTE:	/* get mute mode */
		ret = fm_core_rx_get_mute_mode(&curr_mute_mode);
		if (ret < 0) {
			FMDRV_API_EXIT(ret);
			return ret;
		}
		ctrl->value = curr_mute_mode;
		break;

	case V4L2_CID_AUDIO_VOLUME:	/* get volume */
		ret = fm_core_rx_get_volume(&curr_vol);
		if (ret < 0) {
			FMDRV_API_EXIT(ret);
			return ret;
		}
		ctrl->value = curr_vol;
		break;
	}
	FMDRV_API_EXIT(0);
	return 0;
}
/* Get tuner attributes */
static int fm_v4l2_vidioc_g_tuner(struct file *file, void *priv,
				  struct v4l2_tuner *tuner)
{
	unsigned int bottom_frequency;
	unsigned int top_frequency;
	unsigned short stereo_mono_mode;
	unsigned short rssilvl;
	int ret;

	FMDRV_API_START();

	if (tuner->index != 0) {
		FMDRV_API_EXIT(-EINVAL);
		return -EINVAL;
	}
	ret =
	    fm_core_rx_get_currband_lowhigh_freq(&bottom_frequency,
						 &top_frequency);
	if (ret) {
		FMDRV_API_EXIT(ret);
		return ret;
	}
	ret = fm_core_rx_get_stereo_mono(&stereo_mono_mode);
	if (ret) {
		FMDRV_API_EXIT(ret);
		return ret;
	}
	ret = fm_core_rx_get_rssi_level(&rssilvl);
	if (ret) {
		FMDRV_API_EXIT(ret);
		return ret;
	}
	strcpy(tuner->name, "FM");
	tuner->type = V4L2_TUNER_RADIO;
	/* Store rangelow and rangehigh freq in unit of 62.5 KHz */
	tuner->rangelow = (bottom_frequency * 10000) / 625;
	tuner->rangehigh = (top_frequency * 10000) / 625;
	tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
	tuner->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW;
	tuner->audmode = (stereo_mono_mode ?
			  V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO);

	/* Actual rssi value lies in between -128 to +127.
	 * Convert this range from 0 to 255 by adding +128
	 */
	rssilvl += 128;

	/* Return signal strength value should be within 0 to 65535.
	 * Find out correct signal radio by multiplying (65535/255) = 257
	 */
	tuner->signal = rssilvl * 257;
	tuner->afc = 0;

	FMDRV_API_EXIT(0);
	return 0;
}
/* Set audio attributes */
static int fm_v4l2_vidioc_s_audio(struct file *file, void *priv,
				  struct v4l2_audio *audio)
{
	FMDRV_API_START();

	if (audio->index != 0) {
		FMDRV_API_EXIT(-EINVAL);
		return -EINVAL;
	}
	FMDRV_API_EXIT(0);
	return 0;
}
/* Set tuner or modulator radio frequency */
static int fm_v4l2_vidioc_s_frequency(struct file *file, void *priv,
				      struct v4l2_frequency *freq)
{
	int ret;
	FMDRV_API_START();

	ret = fm_core_set_frequency(freq->frequency);
	if (ret) {
		FMDRV_API_EXIT(ret);
		return ret;
	}
	FMDRV_API_EXIT(0);
	return 0;
}
/* Poll RDS data */
static unsigned int fm_v4l2_fops_poll(struct file *file,
				      struct poll_table_struct *pts)
{
	int ret;
	FMDRV_API_START();

	ret = fm_core_is_rds_data_available(file, pts);
	if (!ret) {
		FMDRV_API_EXIT(POLLIN | POLLRDNORM);
		return POLLIN | POLLRDNORM;
	}

	FMDRV_API_EXIT(0);
	return 0;
}
/* Set hardware frequency seek */
static int fm_v4l2_vidioc_s_hw_freq_seek(struct file *file, void *priv,
					 struct v4l2_hw_freq_seek *seek)
{
	int ret;

	FMDRV_API_START();

	ret = fm_core_rx_seek(seek->seek_upward, seek->wrap_around);
	if (ret) {
		FMDRV_API_EXIT(ret);
		return ret;
	}

	FMDRV_API_EXIT(0);
	return 0;
}
static int fm_mixer_rx_rds_opmode_get(struct snd_kcontrol *kcontrol,
				      struct snd_ctl_elem_value *ucontrol)
{
	unsigned char rds_mode;
	int ret;

	FMDRV_API_START();
	ret = fm_core_rx_get_rds_system(&rds_mode);
	if (ret) {
		FMDRV_API_EXIT(ret);
		return ret;
	}
	ucontrol->value.enumerated.item[0] = rds_mode & 0x1;
	FMDRV_API_EXIT(0);
	return 0;
}
static int fm_mixer_rx_deemphasis_get(struct snd_kcontrol *kcontrol,
				      struct snd_ctl_elem_value *ucontrol)
{
	unsigned short mode;
	int ret;

	FMDRV_API_START();
	ret = fm_core_rx_get_deemphasis_mode(&mode);
	if (ret) {
		FMDRV_API_EXIT(ret);
		return ret;
	}
	ucontrol->value.enumerated.item[0] = mode & 0x1;
	FMDRV_API_EXIT(0);
	return 0;
}
static int fm_mixer_region_get(struct snd_kcontrol *kcontrol,
			       struct snd_ctl_elem_value *ucontrol)
{
	unsigned char region;
	int ret;

	FMDRV_API_START();
	ret = fm_core_region_get(&region);
	if (ret) {
		FMDRV_API_EXIT(ret);
		return ret;
	}
	ucontrol->value.enumerated.item[0] = region & 0x1;

	FMDRV_API_EXIT(0);
	return 0;
}
Example #15
0
/* Called from FM Core and FM Char device interface to claim
 * FM ST. Who ever comes first, ownership of FM ST will be
 * given to them.
 */
int fm_st_claim(void)
{
	FMDRV_API_START();

	/* Give ownership of FM ST to first caller */
	if (is_fm_st_claimed == FM_ST_NOT_CLAIMED) {
		is_fm_st_claimed = FM_ST_CLAIMED;

		FMDRV_API_EXIT(FM_ST_SUCCESS);
		return FM_ST_SUCCESS;
	}

	FM_DRV_DBG("FM ST claimed already");

	FMDRV_API_EXIT(FM_ST_FAILED);
	return FM_ST_FAILED;
}
int fm_mixer_init(struct fmdrv_ops *fmdev)
{
	int idx;
	int ret;

	FMDRV_API_START();

	/* Allocate new card for FM driver */
	fmdev->card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
				   THIS_MODULE, 0);
	if (!fmdev->card) {
		FM_DRV_ERR("No memory to allocate new card");
		FMDRV_API_EXIT(-ENOMEM);
		return -ENOMEM;
	}
	fmdev->card->private_data = fmdev;

	/* Add FM mixer controls to the card */
	strcpy(fmdev->card->mixername, FM_DRV_MIXER_NAME);
	for (idx = 0; idx < ARRAY_SIZE(snd_fm_controls); idx++) {
		ret = snd_ctl_add(fmdev->card,
				  snd_ctl_new1(&snd_fm_controls[idx], fmdev));
		if (ret < 0) {
			snd_card_free(fmdev->card);
			FM_DRV_ERR("Failed to add mixer controls");
			FMDRV_API_EXIT(ret);
			return ret;
		}
	}

	/* Register FM card with ALSA */
	ret = snd_card_register(fmdev->card);
	if (ret) {
		snd_card_free(fmdev->card);
		FM_DRV_ERR("Failed to register new card");
		FMDRV_API_EXIT(ret);
		return ret;
	}

	strcpy(fmdev->card->driver, FM_DRV_NAME);
	strcpy(fmdev->card->shortname, FM_DRV_CARD_SHORT_NAME);
	sprintf(fmdev->card->longname, FM_DRV_CARD_LONG_NAME);

	FMDRV_API_EXIT(0);
	return 0;
}
static int fm_mixer_rx_af_switch_get(struct snd_kcontrol *kcontrol,
				     struct snd_ctl_elem_value *ucontrol)
{
	unsigned char af_mode;
	int ret;

	FMDRV_API_START();

	ret = fm_core_rx_get_af_switch(&af_mode);
	if (ret) {
		FMDRV_API_EXIT(ret);
		return ret;
	}
	ucontrol->value.enumerated.item[0] = af_mode & 0x1;
	FMDRV_API_EXIT(0);
	return 0;
}
static int fm_mixer_rfdepend_mute_get(struct snd_kcontrol *kcontrol,
				      struct snd_ctl_elem_value *ucontrol)
{
	unsigned char en_dis;
	int ret;

	FMDRV_API_START();

	ret = fm_core_rx_get_rfdepend_softmute(&en_dis);
	if (ret) {
		FMDRV_API_EXIT(ret);
		return ret;
	}
	ucontrol->value.enumerated.item[0] = en_dis & 0x1;
	FMDRV_API_EXIT(0);
	return 0;
}
static int fm_mixer_mode_get(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_value *ucontrol)
{
	int ret;
	unsigned char current_fmmode;

	FMDRV_API_START();
	ret = fm_core_mode_get(&current_fmmode);
	if (ret) {
		FMDRV_API_EXIT(ret);
		return ret;
	}
	ucontrol->value.enumerated.item[0] = current_fmmode & 3;

	FMDRV_API_EXIT(0);
	return 0;
}
static int fm_mixer_rx_rssi_threshold_get(struct snd_kcontrol *kcontrol,
					  struct snd_ctl_elem_value *ucontrol)
{
	short curr_rssi_threshold;
	int ret;
	FMDRV_API_START();

	ret = fm_core_rx_get_rssi_threshold(&curr_rssi_threshold);
	if (ret) {
		FMDRV_API_EXIT(ret);
		return ret;
	}

	ucontrol->value.integer.value[0] = curr_rssi_threshold;

	FMDRV_API_EXIT(0);
	return 0;
}
Example #21
0
/* Called from FM Core and FM Char device interface
 * to release FM ST.
 */
int fm_st_release(void)
{
	FMDRV_API_START();

	/* Release FM ST if it is already claimed */
	if (is_fm_st_claimed == FM_ST_CLAIMED) {
		is_fm_st_claimed = FM_ST_NOT_CLAIMED;

		FMDRV_API_EXIT(FM_ST_SUCCESS);
		return FM_ST_SUCCESS;

	}

	FM_DRV_ERR("FM ST is not claimed,called again?");

	FMDRV_API_EXIT(FM_ST_FAILED);
	return FM_ST_FAILED;
}
int fm_mixer_deinit(struct fmdrv_ops *fmdev)
{
	FMDRV_API_START();

	/* Unregister FM card from ALSA */
	snd_card_free(fmdev->card);

	FMDRV_API_EXIT(0);
	return 0;
}
static int fm_mixer_rx_af_switch_put(struct snd_kcontrol *kcontrol,
				     struct snd_ctl_elem_value *ucontrol)
{
	unsigned char af_mode;
	int changed, ret;

	FMDRV_API_START();

	af_mode = ucontrol->value.integer.value[0] & 0x1;
	ret = fm_core_rx_set_af_switch(af_mode);
	if (ret) {
		FMDRV_API_EXIT(ret);
		return ret;
	}
	changed = 1;

	FMDRV_API_EXIT(changed);
	return changed;
}
int fm_v4l2_deinit_video_device(struct fmdrv_ops *fmdev)
{
	FMDRV_API_START();

	/* Unregister RADIO device from V4L2 subsystem */
	video_unregister_device(fmdev->v4l2dev);

	FMDRV_API_EXIT(0);
	return 0;
}
static int fm_mixer_rfdepend_mute_put(struct snd_kcontrol *kcontrol,
				      struct snd_ctl_elem_value *ucontrol)
{
	unsigned char en_dis;
	int changed, ret;

	FMDRV_API_START();

	en_dis = ucontrol->value.integer.value[0] & 0x1;
	ret = fm_core_rx_set_rfdepend_softmute(en_dis);
	if (ret) {
		FMDRV_API_EXIT(ret);
		return ret;
	}
	changed = 1;

	FMDRV_API_EXIT(changed);
	return changed;
}
/* File Open */
static int fm_v4l2_fops_open(struct file *file)
{
	int ret;

	FMDRV_API_START();

	/* Don't allow multiple open */
	if (radio_disconnected) {
		FM_DRV_ERR("FM device is already opened\n");
		FMDRV_API_EXIT(-EBUSY);
		return -EBUSY;
	}

	/* Request FM Core to link with FM ST */
	ret = fm_core_setup_transport();
	if (ret) {
		FM_DRV_ERR("Unable to setup FM Core transport");
		FMDRV_API_EXIT(ret);
		return ret;
	}
	/* Initialize FM Core */
	ret = fm_core_prepare();
	if (ret) {
		FM_DRV_ERR("Unable to prepare FM CORE");
		FMDRV_API_EXIT(ret);
		return ret;
	}

	FM_DRV_DBG("Load FM RX firmware..");
	/* By default load FM RX firmware */
	ret = fm_core_mode_set(FM_MODE_RX);
	if (ret) {
		FM_DRV_ERR("Unable to load FM RX firmware");
		FMDRV_API_EXIT(ret);
		return ret;
	}
	radio_disconnected = 1;
	FM_DRV_DBG("FM CORE is ready");

	FMDRV_API_EXIT(0);
	return 0;
}
static int fm_mixer_rx_rds_opmode_put(struct snd_kcontrol *kcontrol,
				      struct snd_ctl_elem_value *ucontrol)
{
	int ret;
	unsigned char rds_mode;
	int changed;

	FMDRV_API_START();

	rds_mode = ucontrol->value.integer.value[0] & 0x1;
	ret = fm_core_rx_set_rds_system(rds_mode);
	if (ret) {
		FMDRV_API_EXIT(ret);
		return ret;
	}
	changed = 1;

	FMDRV_API_EXIT(changed);
	return changed;
}
static int fm_mixer_rx_deemphasis_put(struct snd_kcontrol *kcontrol,
				      struct snd_ctl_elem_value *ucontrol)
{
	int ret;
	unsigned short mode;
	int changed;

	FMDRV_API_START();

	mode = ucontrol->value.integer.value[0] & 0x1;
	ret = fm_core_rx_set_deemphasis_mode(mode);
	if (ret) {
		FMDRV_API_EXIT(ret);
		return ret;
	}
	changed = 1;

	FMDRV_API_EXIT(changed);
	return changed;
}
static int fm_mixer_region_put(struct snd_kcontrol *kcontrol,
			       struct snd_ctl_elem_value *ucontrol)
{
	int ret;
	unsigned char region;
	int changed;

	FMDRV_API_START();

	region = ucontrol->value.integer.value[0] & 0x1;
	ret = fm_core_region_set(region);
	if (ret) {
		FMDRV_API_EXIT(ret);
		return ret;
	}
	changed = 1;

	FMDRV_API_EXIT(changed);
	return changed;
}
Example #30
0
/* Unregister FM Driver from Shared Transport */
int fm_st_unregister(void)
{
	int ret;

	FMDRV_API_START();

	/* Unregister FM Driver from ST */
	ret = st_unregister(8);
	if (ret != ST_SUCCESS) {
		FM_DRV_ERR("st_unregister failed %d", ret);
		FMDRV_API_EXIT(-EBUSY);
		return -EBUSY;
	}

	g_rx_task = NULL;
	g_rx_q = NULL;

	FMDRV_API_EXIT(0);
	return 0;
}