/* si4713_g_modulator - get modulator attributes */ static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) { struct si4713_device *sdev = to_si4713_device(sd); int rval = 0; if (!sdev) { rval = -ENODEV; goto exit; } if (vm->index > 0) { rval = -EINVAL; goto exit; } strncpy(vm->name, "FM Modulator", 32); vm->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_RDS; /* Report current frequency range limits */ vm->rangelow = si4713_to_v4l2(FREQ_RANGE_LOW); vm->rangehigh = si4713_to_v4l2(FREQ_RANGE_HIGH); mutex_lock(&sdev->mutex); if (sdev->power_state) { u32 comp_en = 0; rval = si4713_read_property(sdev, SI4713_TX_COMPONENT_ENABLE, &comp_en); if (rval < 0) goto unlock; sdev->stereo = get_status_bit(comp_en, 1, 1 << 1); sdev->rds_info.enabled = get_status_bit(comp_en, 2, 1 << 2); } /* Report current audio mode: mono or stereo */ if (sdev->stereo) vm->txsubchans = V4L2_TUNER_SUB_STEREO; else vm->txsubchans = V4L2_TUNER_SUB_MONO; /* Report rds feature status */ if (sdev->rds_info.enabled) vm->txsubchans |= V4L2_TUNER_SUB_RDS; else vm->txsubchans &= ~V4L2_TUNER_SUB_RDS; unlock: mutex_unlock(&sdev->mutex); exit: return rval; }
/* si4713_s_frequency - set tuner or modulator radio frequency */ static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) { struct si4713_device *sdev = to_si4713_device(sd); int rval = 0; u16 frequency = v4l2_to_si4713(f->frequency); /* Check frequency range */ if (frequency < FREQ_RANGE_LOW || frequency > FREQ_RANGE_HIGH) return -EDOM; mutex_lock(&sdev->mutex); if (sdev->power_state) { rval = si4713_tx_tune_freq(sdev, frequency); if (rval < 0) goto unlock; frequency = rval; rval = 0; } sdev->frequency = frequency; f->frequency = si4713_to_v4l2(frequency); unlock: mutex_unlock(&sdev->mutex); return rval; }
/* si4713_g_frequency - get tuner or modulator radio frequency */ static int si4713_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) { struct si4713_device *sdev = to_si4713_device(sd); int rval = 0; f->type = V4L2_TUNER_RADIO; mutex_lock(&sdev->mutex); if (sdev->power_state) { u16 freq; u8 p, a, n; rval = si4713_tx_tune_status(sdev, 0x00, &freq, &p, &a, &n); if (rval < 0) goto unlock; sdev->frequency = freq; } f->frequency = si4713_to_v4l2(sdev->frequency); unlock: mutex_unlock(&sdev->mutex); return rval; }
/* * si4713_setup - Sets the device up with current configuration. * @sdev: si4713_device structure for the device we are communicating */ static int si4713_setup(struct si4713_device *sdev) { struct v4l2_frequency f; struct v4l2_modulator vm; int rval; /* Device procedure needs to set frequency first */ f.tuner = 0; f.frequency = sdev->frequency ? sdev->frequency : DEFAULT_FREQUENCY; f.frequency = si4713_to_v4l2(f.frequency); rval = si4713_s_frequency(&sdev->sd, &f); vm.index = 0; if (sdev->stereo) vm.txsubchans = V4L2_TUNER_SUB_STEREO; else vm.txsubchans = V4L2_TUNER_SUB_MONO; if (sdev->rds_enabled) vm.txsubchans |= V4L2_TUNER_SUB_RDS; si4713_s_modulator(&sdev->sd, &vm); return rval; }
/* si4713_g_frequency - get tuner or modulator radio frequency */ static int si4713_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) { struct si4713_device *sdev = to_si4713_device(sd); int rval = 0; if (f->tuner) return -EINVAL; if (sdev->power_state) { u16 freq; u8 p, a, n; rval = si4713_tx_tune_status(sdev, 0x00, &freq, &p, &a, &n); if (rval < 0) return rval; sdev->frequency = freq; } f->frequency = si4713_to_v4l2(sdev->frequency); return rval; }
static int si4713_setup(struct si4713_device *sdev) { struct v4l2_ext_control ctrl; struct v4l2_frequency f; struct v4l2_modulator vm; struct si4713_device *tmp; int rval = 0; tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); if (!tmp) return -ENOMEM; /* Get a local copy to avoid race */ mutex_lock(&sdev->mutex); memcpy(tmp, sdev, sizeof(*sdev)); mutex_unlock(&sdev->mutex); ctrl.id = V4L2_CID_RDS_TX_PI; ctrl.value = tmp->rds_info.pi; rval |= si4713_write_econtrol_integers(sdev, &ctrl); ctrl.id = V4L2_CID_AUDIO_COMPRESSION_THRESHOLD; ctrl.value = tmp->acomp_info.threshold; rval |= si4713_write_econtrol_integers(sdev, &ctrl); ctrl.id = V4L2_CID_AUDIO_COMPRESSION_GAIN; ctrl.value = tmp->acomp_info.gain; rval |= si4713_write_econtrol_integers(sdev, &ctrl); ctrl.id = V4L2_CID_PILOT_TONE_FREQUENCY; ctrl.value = tmp->pilot_info.frequency; rval |= si4713_write_econtrol_integers(sdev, &ctrl); ctrl.id = V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME; ctrl.value = tmp->acomp_info.attack_time; rval |= si4713_write_econtrol_integers(sdev, &ctrl); ctrl.id = V4L2_CID_PILOT_TONE_DEVIATION; ctrl.value = tmp->pilot_info.deviation; rval |= si4713_write_econtrol_integers(sdev, &ctrl); ctrl.id = V4L2_CID_AUDIO_LIMITER_DEVIATION; ctrl.value = tmp->limiter_info.deviation; rval |= si4713_write_econtrol_integers(sdev, &ctrl); ctrl.id = V4L2_CID_RDS_TX_DEVIATION; ctrl.value = tmp->rds_info.deviation; rval |= si4713_write_econtrol_integers(sdev, &ctrl); ctrl.id = V4L2_CID_RDS_TX_PTY; ctrl.value = tmp->rds_info.pty; rval |= si4713_write_econtrol_integers(sdev, &ctrl); ctrl.id = V4L2_CID_AUDIO_LIMITER_ENABLED; ctrl.value = tmp->limiter_info.enabled; rval |= si4713_write_econtrol_integers(sdev, &ctrl); ctrl.id = V4L2_CID_AUDIO_COMPRESSION_ENABLED; ctrl.value = tmp->acomp_info.enabled; rval |= si4713_write_econtrol_integers(sdev, &ctrl); ctrl.id = V4L2_CID_PILOT_TONE_ENABLED; ctrl.value = tmp->pilot_info.enabled; rval |= si4713_write_econtrol_integers(sdev, &ctrl); ctrl.id = V4L2_CID_AUDIO_LIMITER_RELEASE_TIME; ctrl.value = tmp->limiter_info.release_time; rval |= si4713_write_econtrol_integers(sdev, &ctrl); ctrl.id = V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME; ctrl.value = tmp->acomp_info.release_time; rval |= si4713_write_econtrol_integers(sdev, &ctrl); ctrl.id = V4L2_CID_TUNE_PREEMPHASIS; ctrl.value = tmp->preemphasis; rval |= si4713_write_econtrol_integers(sdev, &ctrl); ctrl.id = V4L2_CID_RDS_TX_PS_NAME; rval |= si4713_set_rds_ps_name(sdev, tmp->rds_info.ps_name); ctrl.id = V4L2_CID_RDS_TX_RADIO_TEXT; rval |= si4713_set_rds_radio_text(sdev, tmp->rds_info.radio_text); /* Device procedure needs to set frequency first */ f.frequency = tmp->frequency ? tmp->frequency : DEFAULT_FREQUENCY; f.frequency = si4713_to_v4l2(f.frequency); rval |= si4713_s_frequency(&sdev->sd, &f); ctrl.id = V4L2_CID_TUNE_POWER_LEVEL; ctrl.value = tmp->power_level; rval |= si4713_write_econtrol_tune(sdev, &ctrl); ctrl.id = V4L2_CID_TUNE_ANTENNA_CAPACITOR; ctrl.value = tmp->antenna_capacitor; rval |= si4713_write_econtrol_tune(sdev, &ctrl); vm.index = 0; if (tmp->stereo) vm.txsubchans = V4L2_TUNER_SUB_STEREO; else vm.txsubchans = V4L2_TUNER_SUB_MONO; if (tmp->rds_info.enabled) vm.txsubchans |= V4L2_TUNER_SUB_RDS; si4713_s_modulator(&sdev->sd, &vm); kfree(tmp); return rval; }