Merge "dsp: add support to send uevents"
diff --git a/Makefile.am b/Makefile.am
index bce2711..09e2504 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -25,7 +25,7 @@
ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), sdm670 qcs605))
obj-m += asoc/codecs/wcd934x/
endif
-ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), apq8053 sdm670 qcs605))
+ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), apq8053 sdm670 qcs605 apq8009))
obj-m += asoc/codecs/sdm660_cdc/
endif
ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), sdm670 qcs605))
diff --git a/asoc/Kbuild b/asoc/Kbuild
index fce6328..229299d 100644
--- a/asoc/Kbuild
+++ b/asoc/Kbuild
@@ -115,6 +115,10 @@
MACHINE_OBJS += msm8952.o
endif
+ifdef CONFIG_SND_SOC_MSM8909
+ MACHINE_INT_OBJS += msm8952.o
+endif
+
# for SDM450 external codec sound card driver
ifdef CONFIG_SND_SOC_EXT_CODEC_SDM450
MACHINE_EXT_OBJS += msm8952-slimbus.o
@@ -214,6 +218,9 @@
obj-$(CONFIG_SND_SOC_SDM450) += machine_dlkm.o
machine_dlkm-y := $(MACHINE_OBJS)
+obj-$(CONFIG_SND_SOC_MSM8909) += machine_int_dlkm.o
+machine_int_dlkm-y := $(MACHINE_INT_OBJS)
+
obj-$(CONFIG_SND_SOC_EXT_CODEC_8909) += machine_ext_dlkm.o
machine_ext_dlkm-y := $(MACHINE_EXT_OBJS)
diff --git a/asoc/codecs/sdm660_cdc/Kbuild b/asoc/codecs/sdm660_cdc/Kbuild
index e5b3ae9..0744af0 100644
--- a/asoc/codecs/sdm660_cdc/Kbuild
+++ b/asoc/codecs/sdm660_cdc/Kbuild
@@ -40,6 +40,11 @@
export
INCS += -include $(AUDIO_ROOT)/config/sdm450autoconf.h
endif
+ ifeq ($(CONFIG_ARCH_MSM8909), y)
+ include $(AUDIO_ROOT)/config/msm8909auto.conf
+ export
+ INCS += -include $(AUDIO_ROOT)/config/msm8909autoconf.h
+ endif
endif
# As per target team, build is done as follows:
diff --git a/asoc/codecs/sdm660_cdc/msm-analog-cdc.c b/asoc/codecs/sdm660_cdc/msm-analog-cdc.c
index 77981dd..de112bc 100644
--- a/asoc/codecs/sdm660_cdc/msm-analog-cdc.c
+++ b/asoc/codecs/sdm660_cdc/msm-analog-cdc.c
@@ -4577,7 +4577,7 @@
int adsp_state;
adsp_state = apr_get_subsys_state();
- if (adsp_state != APR_SUBSYS_LOADED ||
+ if (adsp_state == APR_SUBSYS_DOWN ||
!q6core_is_adsp_ready()) {
dev_err(&pdev->dev, "Adsp is not loaded yet %d\n",
adsp_state);
diff --git a/asoc/codecs/sdm660_cdc/msm-digital-cdc-legacy.c b/asoc/codecs/sdm660_cdc/msm-digital-cdc-legacy.c
index 9805b2d..bc56412 100644
--- a/asoc/codecs/sdm660_cdc/msm-digital-cdc-legacy.c
+++ b/asoc/codecs/sdm660_cdc/msm-digital-cdc-legacy.c
@@ -1977,6 +1977,14 @@
u32 dig_cdc_addr;
struct msm_dig_priv *msm_dig_cdc;
struct dig_ctrl_platform_data *pdata;
+ int adsp_state = 0;
+
+ adsp_state = apr_get_subsys_state();
+ if (adsp_state == APR_SUBSYS_DOWN) {
+ dev_err(&pdev->dev, "Adsp is not loaded yet %d\n",
+ adsp_state);
+ return -EPROBE_DEFER;
+ }
msm_dig_cdc = devm_kzalloc(&pdev->dev, sizeof(struct msm_dig_priv),
GFP_KERNEL);
diff --git a/asoc/codecs/wcd-dsp-mgr.c b/asoc/codecs/wcd-dsp-mgr.c
index cde9851..b0e5315 100644
--- a/asoc/codecs/wcd-dsp-mgr.c
+++ b/asoc/codecs/wcd-dsp-mgr.c
@@ -802,6 +802,7 @@
__wdsp_clr_ready_locked(wdsp, WDSP_SSR_STATUS_WDSP_READY);
wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_PRE_SHUTDOWN,
NULL);
+ reinit_completion(&wdsp->ready_compl);
schedule_work(&wdsp->ssr_work);
break;
@@ -818,7 +819,7 @@
WDSP_EVENT_PRE_SHUTDOWN,
NULL);
}
-
+ reinit_completion(&wdsp->ready_compl);
schedule_work(&wdsp->ssr_work);
break;
diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c
index 8989fea..80f5e3d 100644
--- a/asoc/msm-dai-q6-v2.c
+++ b/asoc/msm-dai-q6-v2.c
@@ -46,6 +46,7 @@
enum {
ENC_FMT_NONE,
+ DEC_FMT_NONE = ENC_FMT_NONE,
ENC_FMT_SBC = ASM_MEDIA_FMT_SBC,
ENC_FMT_AAC_V2 = ASM_MEDIA_FMT_AAC_V2,
ENC_FMT_APTX = ASM_MEDIA_FMT_APTX,
@@ -200,6 +201,7 @@
u32 afe_in_channels;
u16 afe_in_bitformat;
struct afe_enc_config enc_config;
+ struct afe_dec_config dec_config;
union afe_port_config port_config;
u16 vi_feed_mono;
};
@@ -1546,22 +1548,46 @@
if (dai_data->enc_config.format != ENC_FMT_NONE) {
int bitwidth = 0;
- if (dai_data->afe_in_bitformat ==
- SNDRV_PCM_FORMAT_S24_LE)
+ switch (dai_data->afe_in_bitformat) {
+ case SNDRV_PCM_FORMAT_S32_LE:
+ bitwidth = 32;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
bitwidth = 24;
- else if (dai_data->afe_in_bitformat ==
- SNDRV_PCM_FORMAT_S16_LE)
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ default:
bitwidth = 16;
+ break;
+ }
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);
+ &dai_data->enc_config, NULL);
if (rc < 0)
pr_err("%s: afe_port_start_v2 failed error: %d\n",
__func__, rc);
+ } else if (dai_data->dec_config.format != DEC_FMT_NONE) {
+ /*
+ * A dummy Tx session is established in LPASS to
+ * get the link statistics from BTSoC.
+ * Depacketizer extracts the bit rate levels and
+ * transmits them to the encoder on the Rx path.
+ * Since this is a dummy decoder - channels, bit
+ * width are sent as 0 and encoder config is NULL.
+ * This could be updated in the future if there is
+ * a complete Tx path set up that uses this decoder.
+ */
+ rc = afe_port_start_v2(dai->id, &dai_data->port_config,
+ dai_data->rate, 0, 0, NULL,
+ &dai_data->dec_config);
+ if (rc < 0) {
+ pr_err("%s: fail to open AFE port 0x%x\n",
+ __func__, dai->id);
+ }
} else {
rc = afe_port_start(dai->id, &dai_data->port_config,
dai_data->rate);
@@ -2273,7 +2299,7 @@
if (dai_data) {
int format_size = sizeof(dai_data->enc_config.format);
- pr_debug("%s:encoder config for %d format\n",
+ pr_debug("%s: encoder config for %d format\n",
__func__, dai_data->enc_config.format);
memcpy(ucontrol->value.bytes.data,
&dai_data->enc_config.format,
@@ -2385,10 +2411,11 @@
SOC_ENUM_SINGLE_EXT(3, afe_input_chs_text),
};
-static const char *const afe_input_bit_format_text[] = {"S16_LE", "S24_LE"};
+static const char *const afe_input_bit_format_text[] = {"S16_LE", "S24_LE",
+ "S32_LE"};
static const struct soc_enum afe_input_bit_format_enum[] = {
- SOC_ENUM_SINGLE_EXT(2, afe_input_bit_format_text),
+ SOC_ENUM_SINGLE_EXT(3, afe_input_bit_format_text),
};
static int msm_dai_q6_afe_input_channel_get(struct snd_kcontrol *kcontrol,
@@ -2431,6 +2458,9 @@
}
switch (dai_data->afe_in_bitformat) {
+ case SNDRV_PCM_FORMAT_S32_LE:
+ ucontrol->value.integer.value[0] = 2;
+ break;
case SNDRV_PCM_FORMAT_S24_LE:
ucontrol->value.integer.value[0] = 1;
break;
@@ -2456,6 +2486,9 @@
return -EINVAL;
}
switch (ucontrol->value.integer.value[0]) {
+ case 2:
+ dai_data->afe_in_bitformat = SNDRV_PCM_FORMAT_S32_LE;
+ break;
case 1:
dai_data->afe_in_bitformat = SNDRV_PCM_FORMAT_S24_LE;
break;
@@ -2523,6 +2556,73 @@
msm_dai_q6_afe_scrambler_mode_put),
};
+static int msm_dai_q6_afe_dec_cfg_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+ uinfo->count = sizeof(struct afe_dec_config);
+
+ return 0;
+}
+
+static int msm_dai_q6_afe_dec_cfg_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+ int format_size = 0;
+
+ if (!dai_data) {
+ pr_err("%s: Invalid dai data\n", __func__);
+ return -EINVAL;
+ }
+
+ format_size = sizeof(dai_data->dec_config.format);
+ memcpy(ucontrol->value.bytes.data,
+ &dai_data->dec_config.format,
+ format_size);
+ memcpy(ucontrol->value.bytes.data + format_size,
+ &dai_data->dec_config.abr_dec_cfg,
+ sizeof(struct afe_abr_dec_cfg_t));
+
+ return 0;
+}
+
+static int msm_dai_q6_afe_dec_cfg_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data;
+ int format_size = 0;
+
+ if (!dai_data) {
+ pr_err("%s: Invalid dai data\n", __func__);
+ return -EINVAL;
+ }
+
+ memset(&dai_data->dec_config, 0x0,
+ sizeof(struct afe_dec_config));
+ format_size = sizeof(dai_data->dec_config.format);
+ memcpy(&dai_data->dec_config.format,
+ ucontrol->value.bytes.data,
+ format_size);
+ memcpy(&dai_data->dec_config.abr_dec_cfg,
+ ucontrol->value.bytes.data + format_size,
+ sizeof(struct afe_abr_dec_cfg_t));
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new afe_dec_config_controls[] = {
+ {
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_INACTIVE),
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "SLIM_7_TX Decoder Config",
+ .info = msm_dai_q6_afe_dec_cfg_info,
+ .get = msm_dai_q6_afe_dec_cfg_get,
+ .put = msm_dai_q6_afe_dec_cfg_put,
+ },
+};
+
static int msm_dai_q6_slim_rx_drift_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
@@ -2694,6 +2794,11 @@
snd_ctl_new1(&avd_drift_config_controls[2],
dai));
break;
+ case SLIMBUS_7_TX:
+ rc = snd_ctl_add(dai->component->card->snd_card,
+ snd_ctl_new1(&afe_dec_config_controls[0],
+ dai_data));
+ break;
case RT_PROXY_DAI_001_RX:
rc = snd_ctl_add(dai->component->card->snd_card,
snd_ctl_new1(&rt_proxy_config_controls[0],
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index 7e61358..6d9ba11 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -61,6 +61,7 @@
static int fm_switch_enable;
static int hfp_switch_enable;
+static int a2dp_switch_enable;
static int int0_mi2s_switch_enable;
static int int4_mi2s_switch_enable;
static int pri_mi2s_switch_enable;
@@ -2162,6 +2163,34 @@
return 1;
}
+static int msm_routing_a2dp_switch_mixer_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = a2dp_switch_enable;
+ pr_debug("%s: A2DP Switch enable %ld\n", __func__,
+ ucontrol->value.integer.value[0]);
+ return 0;
+}
+
+static int msm_routing_a2dp_switch_mixer_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget *widget =
+ snd_soc_dapm_kcontrol_widget(kcontrol);
+ struct snd_soc_dapm_update *update = NULL;
+
+ pr_debug("%s: A2DP Switch enable %ld\n", __func__,
+ ucontrol->value.integer.value[0]);
+ a2dp_switch_enable = ucontrol->value.integer.value[0];
+ if (a2dp_switch_enable)
+ snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol,
+ 1, update);
+ else
+ snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol,
+ 0, update);
+ return 1;
+}
+
static int msm_routing_get_int0_mi2s_switch_mixer(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -11680,6 +11709,11 @@
0, 1, 0, msm_routing_get_usb_switch_mixer,
msm_routing_put_usb_switch_mixer);
+static const struct snd_kcontrol_new a2dp_slim7_switch_mixer_controls =
+ SOC_SINGLE_EXT("Switch", SND_SOC_NOPM,
+ 0, 1, 0, msm_routing_a2dp_switch_mixer_get,
+ msm_routing_a2dp_switch_mixer_put);
+
static const struct soc_enum lsm_port_enum =
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lsm_port_text), lsm_port_text);
@@ -13498,6 +13532,8 @@
&hfp_slim7_switch_mixer_controls),
SND_SOC_DAPM_SWITCH("USB_DL_HL", SND_SOC_NOPM, 0, 0,
&usb_switch_mixer_controls),
+ SND_SOC_DAPM_SWITCH("A2DP_SLIM7_UL_HL", SND_SOC_NOPM, 0, 0,
+ &a2dp_slim7_switch_mixer_controls),
/* Mixer definitions */
SND_SOC_DAPM_MIXER("PRI_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
@@ -15943,6 +15979,8 @@
{"HFP_SLIM7_UL_HL", "Switch", "SLIMBUS_7_TX"},
{"AUX_PCM_RX", NULL, "AUXPCM_DL_HL"},
{"AUX_PCM_RX", NULL, "INTHFP_DL_HL"},
+ {"SLIM7_UL_HL", NULL, "A2DP_SLIM7_UL_HL"},
+ {"A2DP_SLIM7_UL_HL", "Switch", "SLIMBUS_7_TX"},
{"SEC_AUX_PCM_RX", NULL, "SEC_AUXPCM_DL_HL"},
{"AUXPCM_UL_HL", NULL, "AUX_PCM_TX"},
{"SEC_AUXPCM_UL_HL", NULL, "SEC_AUX_PCM_TX"},
diff --git a/asoc/sdm660-common.c b/asoc/sdm660-common.c
index 3695ae5..093eef4 100644
--- a/asoc/sdm660-common.c
+++ b/asoc/sdm660-common.c
@@ -3364,6 +3364,8 @@
.data = "tavil_codec"},
{ .compatible = "qcom,qcs605-dig-asoc-snd",
.data = "digital_codec"},
+ { .compatible = "qcom,qcs605-asoc-snd-tavil",
+ .data = "tavil_codec"},
{},
};
diff --git a/config/msm8909auto.conf b/config/msm8909auto.conf
index ac6f399..2adfae5 100644
--- a/config/msm8909auto.conf
+++ b/config/msm8909auto.conf
@@ -35,3 +35,4 @@
CONFIG_SND_SOC_WSA881X=m
CONFIG_COMMON_CLK_MSM=m
CONFIG_SND_SOC_EXT_CODEC_8909=m
+CONFIG_SND_SOC_WSA881X_ANALOG=m
diff --git a/config/msm8909autoconf.h b/config/msm8909autoconf.h
index bb80f88..9faddb1 100644
--- a/config/msm8909autoconf.h
+++ b/config/msm8909autoconf.h
@@ -48,3 +48,4 @@
#define CONFIG_SND_SOC_WSA881X 1
#define CONFIG_COMMON_CLK_MSM 1
#define CONFIG_SND_SOC_EXT_CODEC_8909 1
+#define CONFIG_SND_SOC_WSA881X_ANALOG 1
diff --git a/dsp/q6afe.c b/dsp/q6afe.c
index 5a92fa5..ce67a19 100644
--- a/dsp/q6afe.c
+++ b/dsp/q6afe.c
@@ -2997,6 +2997,93 @@
return ret;
}
+static int q6afe_send_dec_config(u16 port_id,
+ union afe_port_config afe_config,
+ struct afe_dec_config *cfg)
+{
+ struct afe_audioif_config_command config;
+ int index = 0;
+ int ret = 0;
+ size_t payload_size = sizeof(config) - sizeof(struct apr_hdr) -
+ sizeof(config.param) - sizeof(config.port);
+
+ index = q6audio_get_port_index(port_id);
+ if (index < 0) {
+ pr_err("%s: Invalid index number: %d\n", __func__, index);
+ return -EINVAL;
+ }
+ memset(&config, 0, sizeof(config));
+
+ config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ config.hdr.pkt_size = sizeof(config);
+ config.hdr.src_port = 0;
+ config.hdr.dest_port = 0;
+ config.hdr.token = index;
+
+ config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
+ config.param.port_id = q6audio_get_port_id(port_id);
+ config.param.payload_address_lsw = 0x00;
+ config.param.payload_address_msw = 0x00;
+ config.param.mem_map_handle = 0x00;
+ config.pdata.module_id = AFE_MODULE_ID_DECODER;
+ config.param.payload_size =
+ payload_size + sizeof(config.port.dec_depkt_id_param);
+ pr_debug("%s:sending AFE_DECODER_PARAM_ID_DEPACKETIZER to DSP payload = %d\n",
+ __func__, config.param.payload_size);
+ config.pdata.param_id = AFE_DECODER_PARAM_ID_DEPACKETIZER_ID;
+ config.pdata.param_size = sizeof(config.port.dec_depkt_id_param);
+ config.port.dec_depkt_id_param.dec_depacketizer_id =
+ AFE_MODULE_ID_DEPACKETIZER_COP;
+ ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
+ if (ret) {
+ pr_err("%s: AFE_DECODER_PARAM_ID_DEPACKETIZER for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+ goto exit;
+ }
+
+ config.param.payload_size =
+ payload_size + sizeof(config.port.imc_info_param);
+ pr_debug("%s:sending AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION to DSP payload = %d\n",
+ __func__, config.param.payload_size);
+ config.pdata.param_id = AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION;
+ config.pdata.param_size = sizeof(config.port.imc_info_param);
+ config.port.imc_info_param.imc_info = cfg->abr_dec_cfg.imc_info;
+ ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
+ if (ret) {
+ pr_err("%s: AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+ goto exit;
+ }
+
+ config.param.payload_size =
+ payload_size + sizeof(config.port.media_type);
+ config.pdata.param_size = sizeof(config.port.media_type);
+
+ pr_debug("%s:Sending AFE_API_VERSION_PORT_MEDIA_TYPE to DSP\n",
+ __func__);
+ config.pdata.module_id = AFE_MODULE_PORT;
+ 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;
+ config.port.media_type.num_channels =
+ afe_config.slim_sch.num_channels;
+ config.port.media_type.data_format = AFE_PORT_DATA_FORMAT_PCM;
+ config.port.media_type.reserved = 0;
+
+ ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
+ if (ret) {
+ pr_err("%s: AFE_API_VERSION_PORT_MEDIA_TYPE for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+ goto exit;
+ }
+
+exit:
+ return ret;
+}
+
static int q6afe_send_enc_config(u16 port_id,
union afe_enc_config_data *cfg, u32 format,
union afe_port_config afe_config,
@@ -3048,15 +3135,25 @@
__func__);
goto exit;
}
-
- config.param.payload_size = payload_size
+ if (format == ASM_MEDIA_FMT_LDAC) {
+ config.param.payload_size = payload_size
+ + sizeof(config.port.enc_blk_param)
+ - sizeof(struct afe_abr_enc_cfg_t);
+ config.pdata.param_size = sizeof(config.port.enc_blk_param)
+ - sizeof(struct afe_abr_enc_cfg_t);
+ config.port.enc_blk_param.enc_cfg_blk_size =
+ sizeof(config.port.enc_blk_param.enc_blk_config)
+ - sizeof(struct afe_abr_enc_cfg_t);
+ } else {
+ config.param.payload_size = payload_size
+ sizeof(config.port.enc_blk_param);
+ config.pdata.param_size = sizeof(config.port.enc_blk_param);
+ config.port.enc_blk_param.enc_cfg_blk_size =
+ sizeof(config.port.enc_blk_param.enc_blk_config);
+ }
pr_debug("%s:send AFE_ENCODER_PARAM_ID_ENC_CFG_BLK to DSP payload:%d\n",
__func__, config.param.payload_size);
config.pdata.param_id = AFE_ENCODER_PARAM_ID_ENC_CFG_BLK;
- config.pdata.param_size = sizeof(config.port.enc_blk_param);
- config.port.enc_blk_param.enc_cfg_blk_size =
- sizeof(config.port.enc_blk_param.enc_blk_config);
config.port.enc_blk_param.enc_blk_config = *cfg;
ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
if (ret) {
@@ -3112,22 +3209,54 @@
goto exit;
}
+ if (format == ASM_MEDIA_FMT_LDAC) {
+ config.param.payload_size =
+ payload_size + sizeof(config.port.map_param);
+ pr_debug("%s:sending AFE_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP to DSP payload = %d\n",
+ __func__, config.param.payload_size);
+ config.pdata.param_id = AFE_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP;
+ config.pdata.param_size = sizeof(config.port.map_param);
+ config.port.map_param.mapping_table =
+ cfg->ldac_config.abr_config.mapping_info;
+ ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
+ if (ret) {
+ pr_err("%s: AFE_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+ goto exit;
+ }
+
+ config.param.payload_size =
+ payload_size + sizeof(config.port.imc_info_param);
+ pr_debug("%s:sending AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION to DSP payload = %d\n",
+ __func__, config.param.payload_size);
+ config.pdata.param_id =
+ AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION;
+ config.pdata.param_size = sizeof(config.port.imc_info_param);
+ config.port.imc_info_param.imc_info =
+ cfg->ldac_config.abr_config.imc_info;
+ ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
+ if (ret) {
+ pr_err("%s: AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+ goto exit;
+ }
+ }
+
config.param.payload_size =
payload_size + sizeof(config.port.media_type);
config.pdata.param_size = sizeof(config.port.media_type);
- pr_debug("%s:Sending AFE_API_VERSION_PORT_MEDIA_TYPE to DSP", __func__);
+ pr_debug("%s:Sending AFE_API_VERSION_PORT_MEDIA_TYPE to DSP\n",
+ __func__);
config.pdata.module_id = AFE_MODULE_PORT;
config.pdata.param_id = AFE_PARAM_ID_PORT_MEDIA_TYPE;
config.port.media_type.minor_version = AFE_API_VERSION_PORT_MEDIA_TYPE;
- if (format == ASM_MEDIA_FMT_LDAC) {
+ if (format == ASM_MEDIA_FMT_LDAC)
config.port.media_type.sample_rate =
- config.port.enc_blk_param.enc_blk_config.ldac_config.
- custom_config.sample_rate;
- } else {
+ cfg->ldac_config.custom_config.sample_rate;
+ else
config.port.media_type.sample_rate =
afe_config.slim_sch.sample_rate;
- }
if (afe_in_bit_width)
config.port.media_type.bit_width = afe_in_bit_width;
@@ -3156,8 +3285,9 @@
static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
- union afe_enc_config_data *cfg, u32 enc_format,
- u32 scrambler_mode)
+ union afe_enc_config_data *enc_cfg,
+ u32 codec_format, u32 scrambler_mode,
+ struct afe_dec_config *dec_cfg)
{
struct afe_audioif_config_command config;
int ret = 0;
@@ -3402,7 +3532,8 @@
config.pdata.param_size = sizeof(config.port);
config.port = *afe_config;
- if ((enc_format != ASM_MEDIA_FMT_NONE) &&
+ if (((enc_cfg != NULL) || (dec_cfg != NULL)) &&
+ (codec_format != ASM_MEDIA_FMT_NONE) &&
(cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) {
config.port.slim_sch.data_format =
AFE_SB_DATA_FORMAT_GENERIC_COMPRESSED;
@@ -3414,18 +3545,32 @@
goto fail_cmd;
}
- if ((enc_format != ASM_MEDIA_FMT_NONE) &&
+ if ((codec_format != ASM_MEDIA_FMT_NONE) &&
(cfg_type == AFE_PARAM_ID_SLIMBUS_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_in_bit_width,
- scrambler_mode);
- if (ret) {
- pr_err("%s: AFE encoder config for port 0x%x failed %d\n",
- __func__, port_id, ret);
- goto fail_cmd;
+ if (enc_cfg != NULL) {
+ pr_debug("%s: Found AFE encoder support for SLIMBUS enc_format = %d\n",
+ __func__, codec_format);
+ ret = q6afe_send_enc_config(port_id, enc_cfg,
+ codec_format, *afe_config,
+ afe_in_channels,
+ afe_in_bit_width,
+ scrambler_mode);
+ if (ret) {
+ pr_err("%s: AFE encoder config for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+ goto fail_cmd;
+ }
+ }
+ if (dec_cfg != NULL) {
+ pr_debug("%s: Found AFE decoder support for SLIMBUS dec_format = %d\n",
+ __func__, codec_format);
+ ret = q6afe_send_dec_config(port_id, *afe_config,
+ dec_cfg);
+ if (ret) {
+ pr_err("%s: AFE decoder config for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+ goto fail_cmd;
+ }
}
}
@@ -3474,31 +3619,42 @@
u32 rate)
{
return __afe_port_start(port_id, afe_config, rate,
- 0, 0, NULL, ASM_MEDIA_FMT_NONE, 0);
+ 0, 0, NULL, ASM_MEDIA_FMT_NONE, 0, NULL);
}
EXPORT_SYMBOL(afe_port_start);
/**
* afe_port_start_v2 - to configure AFE session with
- * specified port configuration and encoder params
+ * specified port configuration and encoder/decoder params
*
* @port_id: AFE port id number
* @afe_config: port configutation
* @rate: sampling rate of port
- * @cfg: AFE encoder configuration information to setup encoder
+ * @enc_cfg: AFE enc configuration information to setup encoder
* @afe_in_channels: AFE input channel configuration, this needs
* update only if input channel is differ from AFE output
+ * @dec_cfg: AFE dec configuration information to set up decoder
*
* 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, u16 afe_in_bit_width,
- struct afe_enc_config *enc_cfg)
+ struct afe_enc_config *enc_cfg,
+ struct afe_dec_config *dec_cfg)
{
- return __afe_port_start(port_id, afe_config, rate,
- afe_in_channels, afe_in_bit_width,
- &enc_cfg->data, enc_cfg->format,
- enc_cfg->scrambler_mode);
+ int ret = 0;
+
+ if (enc_cfg != NULL)
+ ret = __afe_port_start(port_id, afe_config, rate,
+ afe_in_channels, afe_in_bit_width,
+ &enc_cfg->data, enc_cfg->format,
+ enc_cfg->scrambler_mode, NULL);
+ else if (dec_cfg != NULL)
+ ret = __afe_port_start(port_id, afe_config, rate,
+ afe_in_channels, afe_in_bit_width,
+ NULL, dec_cfg->format, 0, dec_cfg);
+
+ return ret;
}
EXPORT_SYMBOL(afe_port_start_v2);
diff --git a/dsp/q6asm.c b/dsp/q6asm.c
index 2553ec9..ce12374 100644
--- a/dsp/q6asm.c
+++ b/dsp/q6asm.c
@@ -576,7 +576,7 @@
static void q6asm_session_free(struct audio_client *ac)
{
int session_id;
- unsigned long flags;
+ unsigned long flags = 0;
pr_debug("%s: sessionid[%d]\n", __func__, ac->session);
session_id = ac->session;
@@ -1639,7 +1639,7 @@
uint32_t dir = 0;
uint32_t i = IN;
uint32_t *payload;
- unsigned long dsp_flags;
+ unsigned long dsp_flags = 0;
unsigned long flags = 0;
struct asm_buffer_node *buf_node = NULL;
struct list_head *ptr, *next;
@@ -1856,7 +1856,7 @@
{
int i = 0;
struct audio_client *ac = (struct audio_client *)priv;
- unsigned long dsp_flags;
+ unsigned long dsp_flags = 0;
uint32_t *payload;
uint32_t wakeup_flag = 1;
int32_t ret = 0;
@@ -1864,7 +1864,7 @@
uint8_t buf_index;
struct msm_adsp_event_data *pp_event_package = NULL;
uint32_t payload_size = 0;
- unsigned long flags;
+ unsigned long flags = 0;
int session_id;
if (ac == NULL) {
@@ -2549,7 +2549,7 @@
static void __q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr,
uint32_t pkt_size, uint32_t cmd_flg, uint32_t stream_id)
{
- unsigned long flags;
+ unsigned long flags = 0;
dev_vdbg(ac->dev, "%s: pkt_size=%d cmd_flg=%d session=%d stream_id=%d\n",
__func__, pkt_size, cmd_flg, ac->session, stream_id);
diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h
index 2510852..a608a66 100644
--- a/include/dsp/apr_audio-v2.h
+++ b/include/dsp/apr_audio-v2.h
@@ -3101,6 +3101,72 @@
u32 topology_id;
} __packed;
+#define MAX_ABR_LEVELS 5
+
+struct afe_bit_rate_level_map_t {
+ /*
+ * Key value pair for link quality level to bitrate
+ * mapping in AFE
+ */
+ uint32_t link_quality_level;
+ uint32_t bitrate;
+} __packed;
+
+struct afe_quality_level_to_bitrate_info {
+ /*
+ * Number of quality levels being mapped.
+ * This will be equal to the size of mapping table.
+ */
+ uint32_t num_levels;
+ /*
+ * Quality level to bitrate mapping table
+ */
+ struct afe_bit_rate_level_map_t bit_rate_level_map[MAX_ABR_LEVELS];
+} __packed;
+
+struct afe_imc_dec_enc_info {
+ /*
+ * Decoder to encoder communication direction.
+ * Transmit = 0 / Receive = 1
+ */
+ uint32_t direction;
+ /*
+ * Enable / disable IMC between decoder and encoder
+ */
+ uint32_t enable;
+ /*
+ * Purpose of IMC being set up between decoder and encoder.
+ * Param ID defined for link quality feedback in LPASS will
+ * be the default value sent as purpose.
+ * Supported values:
+ * AFE_ENCDEC_PURPOSE_ID_BT_INFO
+ */
+ uint32_t purpose;
+ /*
+ * Unique communication instance ID.
+ * Data type a2dp_abr_instance used to set instance ID.
+ * purpose and comm_instance together form the actual key
+ * used in IMC registration, which must be the same for
+ * encoder and decoder for which IMC is being set up.
+ */
+ uint32_t comm_instance;
+} __packed;
+
+struct afe_abr_dec_cfg_t {
+ struct afe_imc_dec_enc_info imc_info;
+} __packed;
+
+struct afe_abr_enc_cfg_t {
+ /*
+ * Link quality level to bitrate mapping info sent to DSP.
+ */
+ struct afe_quality_level_to_bitrate_info mapping_info;
+ /*
+ * Information to set up IMC between decoder and encoder.
+ */
+ struct afe_imc_dec_enc_info imc_info;
+} __packed;
+
#define AFE_PARAM_ID_APTX_SYNC_MODE 0x00013205
struct afe_param_id_aptx_sync_mode {
@@ -3152,6 +3218,39 @@
#define AFE_ENCODER_PARAM_ID_ENABLE_SCRAMBLING 0x0001323C
/*
+ * Link quality level to bitrate mapping info sent to AFE Encoder.
+ * This parameter may be set runtime.
+ */
+#define AFE_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP 0x000132E1
+
+/*
+ * Parameter to set up Inter Module Communication (IMC) between
+ * AFE Decoder and Encoder.
+ * This parameter may be set runtime.
+ */
+#define AFE_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION 0x0001323D
+
+/*
+ * Purpose of IMC set up between encoder and decoder.
+ * Communication instance and purpose together form the
+ * actual key used for IMC registration.
+ */
+#define AFE_ENCDEC_PURPOSE_ID_BT_INFO 0x000132E2
+
+#define AFE_MODULE_ID_DECODER 0x00013231
+
+/*
+ * Macro for defining the depacketizer ID: COP.
+ */
+#define AFE_MODULE_ID_DEPACKETIZER_COP 0x00013233
+
+/*
+ * Depacketizer type parameter for the #AVS_MODULE_ID_DECODER module.
+ * This parameter cannot be set runtime.
+ */
+#define AFE_DECODER_PARAM_ID_DEPACKETIZER_ID 0x00013235
+
+/*
* Data format to send compressed data
* is transmitted/received over Slimbus lines.
*/
@@ -3452,6 +3551,7 @@
struct asm_ldac_enc_cfg_t {
struct asm_custom_enc_cfg_t custom_config;
struct asm_ldac_specific_enc_cfg_t ldac_specific_config;
+ struct afe_abr_enc_cfg_t abr_config;
} __packed;
struct afe_enc_fmt_id_param_t {
@@ -3533,6 +3633,11 @@
union afe_enc_config_data data;
};
+struct afe_dec_config {
+ u32 format;
+ struct afe_abr_dec_cfg_t abr_dec_cfg;
+};
+
struct afe_enc_cfg_blk_param_t {
uint32_t enc_cfg_blk_size;
/*
@@ -3565,6 +3670,39 @@
uint32_t enable_scrambler;
};
+/*
+ * Payload of the AVS_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP parameter.
+ */
+struct afe_enc_level_to_bitrate_map_param_t {
+ /*
+ * Parameter for mapping link quality level to bitrate.
+ */
+ struct afe_quality_level_to_bitrate_info mapping_table;
+};
+
+/*
+ * Payload of the AVS_ENCDEC_PARAM_ID_DEC_TO_ENC_COMMUNICATION parameter.
+ */
+struct afe_enc_dec_imc_info_param_t {
+ /*
+ * Parameter to set up Inter Module Communication (IMC) between
+ * AFE Decoder and Encoder.
+ */
+ struct afe_imc_dec_enc_info imc_info;
+};
+
+/*
+ * Payload of the AVS_DECODER_PARAM_ID_DEPACKETIZER_ID parameter.
+ */
+struct avs_dec_depacketizer_id_param_t {
+ /*
+ * Supported values:
+ * #AVS_MODULE_ID_DEPACKETIZER_COP
+ * Any OpenDSP supported values
+ */
+ uint32_t dec_depacketizer_id;
+};
+
union afe_port_config {
struct afe_param_id_pcm_cfg pcm;
struct afe_param_id_i2s_cfg i2s;
@@ -3584,6 +3722,9 @@
struct afe_enc_cfg_blk_param_t enc_blk_param;
struct avs_enc_packetizer_id_param_t enc_pkt_id_param;
struct avs_enc_set_scrambler_param_t enc_set_scrambler_param;
+ struct avs_dec_depacketizer_id_param_t dec_depkt_id_param;
+ struct afe_enc_level_to_bitrate_map_param_t map_param;
+ struct afe_enc_dec_imc_info_param_t imc_info_param;
} __packed;
struct afe_audioif_config_command_no_payload {
diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h
index 8b79c9b..7edbedd 100644
--- a/include/dsp/q6afe-v2.h
+++ b/include/dsp/q6afe-v2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -326,7 +326,8 @@
u32 rate);
int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config,
u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
- struct afe_enc_config *enc_config);
+ struct afe_enc_config *enc_config,
+ struct afe_dec_config *dec_config);
int afe_spk_prot_feed_back_cfg(int src_port, int dst_port,
int l_ch, int r_ch, u32 enable);
int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib);