[ARM] mfd: cpcap-audio: Add support for dynamic CODEC and STDAC rates
authorChris Fries <C.Fries@motorola.com>
Fri, 1 Oct 2010 03:08:06 +0000 (22:08 -0500)
committerIliyan Malchev <malchev@google.com>
Thu, 7 Oct 2010 02:22:34 +0000 (19:22 -0700)
Add new IOCTLs for get/set rates.  This is in anticipation of VOIP
requirements.

Signed-off-by: Iliyan Malchev <malchev@google.com>
drivers/mfd/cpcap-audio-core.c
drivers/mfd/tegra-cpcap-audio.c
include/linux/cpcap_audio.h

index 59fbbb3cc9bff4c92735708f1c33e2802ddc234e..ec19105f4dfb951e2f9f0e5c8346e19f6ae26039 100644 (file)
@@ -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 |
index 543fe7ef8ef8987550649a8530b3811ab45489bf..6aecc6dfcf19156db1863f953d5432105b145d66 100644 (file)
@@ -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:
index 573c3ce376a8755fd7ba1dda6c692a7fe4cab646..f91f712ec1d91ba9ccd2a486ccbb70641f607ddf 100644 (file)
@@ -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*/