From: Chris Fries Date: Fri, 1 Oct 2010 03:08:06 +0000 (-0500) Subject: [ARM] mfd: cpcap-audio: Add support for dynamic CODEC and STDAC rates X-Git-Tag: firefly_0821_release~9834^2~481 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=138a7209b8d9fdda582ba8a430402387b988976f;p=firefly-linux-kernel-4.4.55.git [ARM] mfd: cpcap-audio: Add support for dynamic CODEC and STDAC rates Add new IOCTLs for get/set rates. This is in anticipation of VOIP requirements. Signed-off-by: Iliyan Malchev --- diff --git a/drivers/mfd/cpcap-audio-core.c b/drivers/mfd/cpcap-audio-core.c index 59fbbb3cc9bf..ec19105f4dfb 100644 --- a/drivers/mfd/cpcap-audio-core.c +++ b/drivers/mfd/cpcap-audio-core.c @@ -548,9 +548,6 @@ static void cpcap_audio_configure_codec(struct cpcap_audio_state *state, if (state->microphone != CPCAP_AUDIO_IN_NONE) { codec_changes.value |= CPCAP_BIT_MIC1_CDC_EN; codec_changes.value |= CPCAP_BIT_MIC2_CDC_EN; - codec_changes.value |= CPCAP_BIT_CDC_SR2; - codec_changes.value |= CPCAP_BIT_CDC_SR1; - codec_changes.value |= CPCAP_BIT_CDC_SR0; } #else if (state->microphone != CPCAP_AUDIO_IN_AUX_INTERNAL && @@ -584,7 +581,9 @@ static void cpcap_audio_configure_codec(struct cpcap_audio_state *state, cdai_changes.value |= CPCAP_BIT_CLK_IN_SEL; cdai_changes.value |= CPCAP_BIT_CDC_PLL_SEL | CPCAP_BIT_CLK_INV; +#if 0 cdai_changes.value |= CPCAP_BIT_DIG_AUD_IN; +#endif /* Setting I2S mode */ cdai_changes.value |= CPCAP_BIT_CDC_DIG_AUD_FS0 | diff --git a/drivers/mfd/tegra-cpcap-audio.c b/drivers/mfd/tegra-cpcap-audio.c index 543fe7ef8ef8..6aecc6dfcf19 100644 --- a/drivers/mfd/tegra-cpcap-audio.c +++ b/drivers/mfd/tegra-cpcap-audio.c @@ -41,6 +41,8 @@ static struct cpcap_audio_stream current_output = { static struct cpcap_audio_stream current_input = { .id = CPCAP_AUDIO_IN_MIC1, }; +static int codec_rate; +static int stdac_rate; static int cpcap_audio_ctl_open(struct inode *inode, struct file *file) { @@ -159,12 +161,56 @@ static void tegra_setup_audio_in_headset_on(void) cpcap_audio_set_audio_state(pdata->state); } +static int rate_to_cpcap_codec_rate(int rate) +{ + return + rate == 8000 ? CPCAP_AUDIO_CODEC_RATE_8000_HZ : + rate == 11025 ? CPCAP_AUDIO_CODEC_RATE_11025_HZ : + rate == 12000 ? CPCAP_AUDIO_CODEC_RATE_12000_HZ : + rate == 16000 ? CPCAP_AUDIO_CODEC_RATE_16000_HZ : + rate == 22050 ? CPCAP_AUDIO_CODEC_RATE_22050_HZ : + rate == 24000 ? CPCAP_AUDIO_CODEC_RATE_24000_HZ : + rate == 32000 ? CPCAP_AUDIO_CODEC_RATE_32000_HZ : + rate == 44100 ? CPCAP_AUDIO_CODEC_RATE_44100_HZ : + rate == 48000 ? CPCAP_AUDIO_CODEC_RATE_48000_HZ : + /*default*/ CPCAP_AUDIO_CODEC_RATE_8000_HZ; +} + +static int rate_to_cpcap_stdac_rate(int rate) +{ + return + rate == 8000 ? CPCAP_AUDIO_STDAC_RATE_8000_HZ : + rate == 11025 ? CPCAP_AUDIO_STDAC_RATE_11025_HZ : + rate == 12000 ? CPCAP_AUDIO_STDAC_RATE_12000_HZ : + rate == 16000 ? CPCAP_AUDIO_STDAC_RATE_16000_HZ : + rate == 22050 ? CPCAP_AUDIO_STDAC_RATE_22050_HZ : + rate == 24000 ? CPCAP_AUDIO_STDAC_RATE_24000_HZ : + rate == 32000 ? CPCAP_AUDIO_STDAC_RATE_32000_HZ : + rate == 44100 ? CPCAP_AUDIO_STDAC_RATE_44100_HZ : + rate == 48000 ? CPCAP_AUDIO_STDAC_RATE_48000_HZ : + /*default*/ CPCAP_AUDIO_STDAC_RATE_44100_HZ; +} + +static void tegra_setup_audio_out_rate(int rate) +{ + pdata->state->stdac_rate = rate_to_cpcap_stdac_rate(rate); + stdac_rate = rate; + cpcap_audio_set_audio_state(pdata->state); +} + +static void tegra_setup_audio_in_rate(int rate) +{ + pdata->state->codec_rate = rate_to_cpcap_codec_rate(rate); + codec_rate = rate; + cpcap_audio_set_audio_state(pdata->state); +} + static long cpcap_audio_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int rc = 0; struct cpcap_audio_stream in, out; - + int rate; mutex_lock(&cpcap_lock); switch (cmd) { @@ -192,7 +238,7 @@ static long cpcap_audio_ctl_ioctl(struct file *file, unsigned int cmd, break; case CPCAP_AUDIO_OUT_HEADSET: pr_info("%s: setting output path to headset\n", - __func__);; + __func__); if (out.on) tegra_setup_audio_out_headset_on(); else @@ -246,14 +292,12 @@ static long cpcap_audio_ctl_ioctl(struct file *file, unsigned int cmd, rc = -EFAULT; goto done; } - if (in.id > CPCAP_AUDIO_IN_MAX) { pr_err("%s: invalid audio input selector %d\n", __func__, in.id); rc = -EINVAL; goto done; } - switch (in.id) { case CPCAP_AUDIO_IN_MIC1: if (in.on) { @@ -337,6 +381,40 @@ static long cpcap_audio_ctl_ioctl(struct file *file, unsigned int cmd, goto done; } break; + case CPCAP_AUDIO_OUT_GET_RATE: + if (copy_to_user((void __user *)arg, &stdac_rate, + sizeof(int))) { + rc = -EFAULT; + goto done; + } + break; + case CPCAP_AUDIO_OUT_SET_RATE: + rate = (int)arg; + if (rate < 8000 || rate > 48000) { + pr_err("%s: invalid rate %d\n", __func__, rate); + rc = -EFAULT; + goto done; + } + pr_info("%s: setting output rate to %dHz\n", __func__, rate); + tegra_setup_audio_out_rate(rate); + break; + case CPCAP_AUDIO_IN_GET_RATE: + if (copy_to_user((void __user *)arg, &codec_rate, + sizeof(int))) { + rc = -EFAULT; + goto done; + } + break; + case CPCAP_AUDIO_IN_SET_RATE: + rate = (int)arg; + if (rate < 8000 || rate > 48000) { + pr_err("%s: invalid in rate %d\n", __func__, rate); + rc = -EFAULT; + goto done; + } + pr_info("%s: setting input rate to %dHz\n", __func__, rate); + tegra_setup_audio_in_rate(rate); + break; } done: diff --git a/include/linux/cpcap_audio.h b/include/linux/cpcap_audio.h index 573c3ce376a8..f91f712ec1d9 100644 --- a/include/linux/cpcap_audio.h +++ b/include/linux/cpcap_audio.h @@ -65,4 +65,9 @@ struct cpcap_audio_stream { #define CPCAP_AUDIO_IN_GET_VOLUME _IOR(CPCAP_AUDIO_MAGIC, 7, unsigned int *) +#define CPCAP_AUDIO_OUT_GET_RATE _IOR(CPCAP_AUDIO_MAGIC, 8, unsigned int *) +#define CPCAP_AUDIO_OUT_SET_RATE _IOW(CPCAP_AUDIO_MAGIC, 9, unsigned int *) +#define CPCAP_AUDIO_IN_GET_RATE _IOR(CPCAP_AUDIO_MAGIC, 10, unsigned int *) +#define CPCAP_AUDIO_IN_SET_RATE _IOW(CPCAP_AUDIO_MAGIC, 11, unsigned int *) + #endif/*_CPCAP_AUDIO_H*/