OSDN Git Service

ASoC: msm: qdsp6v2: support for configurable bit format for AFE encoder
authorNaresh Tanniru <ntanniru@codeaurora.org>
Tue, 27 Sep 2016 13:26:31 +0000 (18:56 +0530)
committerGerrit - the friendly Code Review server <code-review@localhost>
Wed, 5 Oct 2016 13:27:08 +0000 (06:27 -0700)
Add support for configurable bit width for AFE encoder.
Add new mixer ctl to set for usecases which enables
configuring different input/output bit format
on AFE for usecases such as APTXHD encoder for 24bit input
and 16bit output.

Change-Id: I62326a097cbd71a3ec2b93a0120284d8f71f5d57
Signed-off-by: Naresh Tanniru <ntanniru@codeaurora.org>
include/sound/q6afe-v2.h
sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
sound/soc/msm/qdsp6v2/q6afe.c

index 9ed6510..31f7c02 100644 (file)
@@ -281,7 +281,7 @@ void afe_set_cal_mode(u16 port_id, enum afe_cal_mode afe_cal_mode);
 int afe_port_start(u16 port_id, union afe_port_config *afe_config,
        u32 rate);
 int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config,
-                     u32 rate, u16 afe_in_channels,
+                     u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
                      struct afe_enc_config *enc_config);
 int afe_spk_prot_feed_back_cfg(int src_port, int dst_port,
        int l_ch, int r_ch, u32 enable);
index a89d88e..776f002 100644 (file)
@@ -173,6 +173,7 @@ struct msm_dai_q6_dai_data {
        u32 bitwidth;
        u32 cal_mode;
        u32 afe_in_channels;
+       u16 afe_in_bitformat;
        struct afe_enc_config enc_config;
        union afe_port_config port_config;
 };
@@ -1417,11 +1418,20 @@ static int msm_dai_q6_prepare(struct snd_pcm_substream *substream,
 
        if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
                if (dai_data->enc_config.format != ENC_FMT_NONE) {
+                       int bitwidth = 0;
+
+                       if (dai_data->afe_in_bitformat ==
+                           SNDRV_PCM_FORMAT_S24_LE)
+                               bitwidth = 24;
+                       else if (dai_data->afe_in_bitformat ==
+                                SNDRV_PCM_FORMAT_S16_LE)
+                               bitwidth = 16;
                        pr_debug("%s: calling AFE_PORT_START_V2 with enc_format: %d\n",
                                 __func__, dai_data->enc_config.format);
                        rc = afe_port_start_v2(dai->id, &dai_data->port_config,
                                               dai_data->rate,
                                               dai_data->afe_in_channels,
+                                              bitwidth,
                                               &dai_data->enc_config);
                        if (rc < 0)
                                pr_err("%s: afe_port_start_v2 failed error: %d\n",
@@ -2140,6 +2150,12 @@ static const struct soc_enum afe_input_chs_enum[] = {
        SOC_ENUM_SINGLE_EXT(3, afe_input_chs_text),
 };
 
+static const char *const afe_input_bit_format_text[] = {"S16_LE", "S24_LE"};
+
+static const struct soc_enum afe_input_bit_format_enum[] = {
+       SOC_ENUM_SINGLE_EXT(2, afe_input_bit_format_text),
+};
+
 static int msm_dai_q6_afe_input_channel_get(struct snd_kcontrol *kcontrol,
                        struct snd_ctl_elem_value *ucontrol)
 {
@@ -2168,6 +2184,58 @@ static int msm_dai_q6_afe_input_channel_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+static int msm_dai_q6_afe_input_bit_format_get(
+                       struct snd_kcontrol *kcontrol,
+                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+
+       if (!dai_data) {
+               pr_err("%s: Invalid dai data\n", __func__);
+               return -EINVAL;
+       }
+
+       switch (dai_data->afe_in_bitformat) {
+       case SNDRV_PCM_FORMAT_S24_LE:
+               ucontrol->value.integer.value[0] = 1;
+               break;
+       case SNDRV_PCM_FORMAT_S16_LE:
+       default:
+               ucontrol->value.integer.value[0] = 0;
+               break;
+       }
+       pr_debug("%s: afe input bit format : %ld\n",
+                 __func__, ucontrol->value.integer.value[0]);
+
+       return 0;
+}
+
+static int msm_dai_q6_afe_input_bit_format_put(
+                       struct snd_kcontrol *kcontrol,
+                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+
+       if (!dai_data) {
+               pr_err("%s: Invalid dai data\n", __func__);
+               return -EINVAL;
+       }
+       switch (ucontrol->value.integer.value[0]) {
+       case 1:
+               dai_data->afe_in_bitformat = SNDRV_PCM_FORMAT_S24_LE;
+               break;
+       case 0:
+       default:
+               dai_data->afe_in_bitformat = SNDRV_PCM_FORMAT_S16_LE;
+               break;
+       }
+       pr_debug("%s: updating afe input bit format : %d\n",
+               __func__, dai_data->afe_in_bitformat);
+
+       return 0;
+}
+
+
 static const struct snd_kcontrol_new afe_enc_config_controls[] = {
        {
                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -2181,6 +2249,9 @@ static const struct snd_kcontrol_new afe_enc_config_controls[] = {
        SOC_ENUM_EXT("AFE Input Channels", afe_input_chs_enum[0],
                     msm_dai_q6_afe_input_channel_get,
                     msm_dai_q6_afe_input_channel_put),
+       SOC_ENUM_EXT("AFE Input Bit Format", afe_input_bit_format_enum[0],
+                    msm_dai_q6_afe_input_bit_format_get,
+                    msm_dai_q6_afe_input_bit_format_put),
 };
 
 static const char * const afe_cal_mode_text[] = {
index af5a99e..be0a8b2 100644 (file)
@@ -2645,8 +2645,9 @@ exit:
 }
 
 static int q6afe_send_enc_config(u16 port_id,
-                       union afe_enc_config_data *cfg, u32 format,
-                       union afe_port_config afe_config, u16 afe_in_channels)
+                                union afe_enc_config_data *cfg, u32 format,
+                                union afe_port_config afe_config,
+                                u16 afe_in_channels, u16 afe_in_bit_width)
 {
        struct afe_audioif_config_command config;
        int index;
@@ -2728,8 +2729,13 @@ static int q6afe_send_enc_config(u16 port_id,
        config.pdata.param_id = AFE_PARAM_ID_PORT_MEDIA_TYPE;
        config.port.media_type.minor_version = AFE_API_VERSION_PORT_MEDIA_TYPE;
        config.port.media_type.sample_rate = afe_config.slim_sch.sample_rate;
-       config.port.media_type.bit_width = afe_config.slim_sch.bit_width;
-       if (afe_in_channels != 0)
+       if (afe_in_bit_width)
+               config.port.media_type.bit_width = afe_in_bit_width;
+       else
+               config.port.media_type.bit_width =
+                                       afe_config.slim_sch.bit_width;
+
+       if (afe_in_channels)
                config.port.media_type.num_channels = afe_in_channels;
        else
                config.port.media_type.num_channels =
@@ -2749,8 +2755,8 @@ exit:
 }
 
 static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
-                          u32 rate,  u16 afe_in_channels,
-                          union afe_enc_config_data *cfg, u32 enc_format)
+                           u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
+                           union afe_enc_config_data *cfg, u32 enc_format)
 {
        struct afe_audioif_config_command config;
        int ret = 0;
@@ -2989,7 +2995,8 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
                pr_debug("%s: Found AFE encoder support for SLIMBUS enc_format = %d\n",
                                        __func__, enc_format);
                ret = q6afe_send_enc_config(port_id, cfg, enc_format,
-                                       *afe_config, afe_in_channels);
+                                           *afe_config, afe_in_channels,
+                                           afe_in_bit_width);
                if (ret) {
                        pr_err("%s: AFE encoder config for port 0x%x failed %d\n",
                                __func__, port_id, ret);
@@ -3043,7 +3050,7 @@ int afe_port_start(u16 port_id, union afe_port_config *afe_config,
                   u32 rate)
 {
        return __afe_port_start(port_id, afe_config, rate,
-                               0, NULL, ASM_MEDIA_FMT_NONE);
+                               0, 0, NULL, ASM_MEDIA_FMT_NONE);
 }
 EXPORT_SYMBOL(afe_port_start);
 
@@ -3061,12 +3068,12 @@ EXPORT_SYMBOL(afe_port_start);
  * Returns 0 on success or error value on port start failure.
  */
 int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config,
-                     u32 rate, u16 afe_in_channels,
+                     u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
                      struct afe_enc_config *enc_cfg)
 {
        return __afe_port_start(port_id, afe_config, rate,
-                               afe_in_channels, &enc_cfg->data,
-                               enc_cfg->format);
+                               afe_in_channels, afe_in_bit_width,
+                               &enc_cfg->data, enc_cfg->format);
 }
 EXPORT_SYMBOL(afe_port_start_v2);