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>
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);
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;
};
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",
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)
{
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 |
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[] = {
}
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;
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 =
}
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;
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);
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);
* 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);