diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h index 8d9016e3557c..3464726c408a 100644 --- a/include/sound/apr_audio-v2.h +++ b/include/sound/apr_audio-v2.h @@ -2738,6 +2738,333 @@ struct afe_param_id_set_topology_cfg { u32 topology_id; } __packed; + +/* + * Generic encoder module ID. + * This module supports the following parameter IDs: + * #AVS_ENCODER_PARAM_ID_ENC_FMT_ID (cannot be set run time) + * #AVS_ENCODER_PARAM_ID_ENC_CFG_BLK (may be set run time) + * #AVS_ENCODER_PARAM_ID_ENC_BITRATE (may be set run time) + * #AVS_ENCODER_PARAM_ID_PACKETIZER_ID (cannot be set run time) + * Opcode - AVS_MODULE_ID_ENCODER + * AFE Command AFE_PORT_CMD_SET_PARAM_V2 supports this module ID. + */ +#define AFE_MODULE_ID_ENCODER 0x00013229 + +/* Macro for defining the packetizer ID: COP. */ +#define AFE_MODULE_ID_PACKETIZER_COP 0x0001322A + +/* + * Packetizer type parameter for the #AVS_MODULE_ID_ENCODER module. + * This parameter cannot be set runtime. + */ +#define AFE_ENCODER_PARAM_ID_PACKETIZER_ID 0x0001322E + +/* + * Encoder config block parameter for the #AVS_MODULE_ID_ENCODER module. + * This parameter may be set runtime. + */ +#define AFE_ENCODER_PARAM_ID_ENC_CFG_BLK 0x0001322C + +/* + * Encoder format ID parameter for the #AVS_MODULE_ID_ENCODER module. + * This parameter cannot be set runtime. + */ +#define AFE_ENCODER_PARAM_ID_ENC_FMT_ID 0x0001322B + +/* + * Data format to send compressed data + * is transmitted/received over Slimbus lines. + */ +#define AFE_SB_DATA_FORMAT_GENERIC_COMPRESSED 0x3 + +/* + * ID for AFE port module. This will be used to define port properties. + * This module supports following parameter IDs: + * #AFE_PARAM_ID_PORT_MEDIA_TYPE + * To configure the port property, the client must use the + * #AFE_PORT_CMD_SET_PARAM_V2 command, + * and fill the module ID with the respective parameter IDs as listed above. + * @apr_hdr_fields + * Opcode -- AFE_MODULE_PORT + */ +#define AFE_MODULE_PORT 0x000102a6 + +/* + * ID of the parameter used by #AFE_MODULE_PORT to set the port media type. + * parameter ID is currently supported using#AFE_PORT_CMD_SET_PARAM_V2 command. + */ +#define AFE_PARAM_ID_PORT_MEDIA_TYPE 0x000102a7 + +/* + * Macros for defining the "data_format" field in the + * #AFE_PARAM_ID_PORT_MEDIA_TYPE + */ +#define AFE_PORT_DATA_FORMAT_PCM 0x0 +#define AFE_PORT_DATA_FORMAT_GENERIC_COMPRESSED 0x1 + +/* + * Macro for defining the "minor_version" field in the + * #AFE_PARAM_ID_PORT_MEDIA_TYPE + */ +#define AFE_API_VERSION_PORT_MEDIA_TYPE 0x1 + +#define ASM_MEDIA_FMT_NONE 0x0 + +/* + * Media format ID for SBC encode configuration. + * @par SBC encode configuration (asm_sbc_enc_cfg_t) + * @table{weak__asm__sbc__enc__cfg__t} + */ +#define ASM_MEDIA_FMT_SBC 0x00010BF2 + +/* SBC channel Mono mode.*/ +#define ASM_MEDIA_FMT_SBC_CHANNEL_MODE_MONO 1 + +/* SBC channel Stereo mode. */ +#define ASM_MEDIA_FMT_SBC_CHANNEL_MODE_STEREO 2 + +/* SBC channel Dual Mono mode. */ +#define ASM_MEDIA_FMT_SBC_CHANNEL_MODE_DUAL_MONO 8 + +/* SBC channel Joint Stereo mode. */ +#define ASM_MEDIA_FMT_SBC_CHANNEL_MODE_JOINT_STEREO 9 + +/* SBC bit allocation method = loudness. */ +#define ASM_MEDIA_FMT_SBC_ALLOCATION_METHOD_LOUDNESS 0 + +/* SBC bit allocation method = SNR. */ +#define ASM_MEDIA_FMT_SBC_ALLOCATION_METHOD_SNR 1 + + +/* + * Payload of the SBC encoder configuration parameters in the + * #ASM_MEDIA_FMT_SBC media format. + */ +struct asm_sbc_enc_cfg_t { + /* + * Number of subbands. + * @values 4, 8 + */ + uint32_t num_subbands; + + /* + * Size of the encoded block in samples. + * @values 4, 8, 12, 16 + */ + uint32_t blk_len; + + /* + * Mode used to allocate bits between channels. + * @values + * 0 (Native mode) + * #ASM_MEDIA_FMT_SBC_CHANNEL_MODE_MONO + * #ASM_MEDIA_FMT_SBC_CHANNEL_MODE_STEREO + * #ASM_MEDIA_FMT_SBC_CHANNEL_MODE_DUAL_MONO + * #ASM_MEDIA_FMT_SBC_CHANNEL_MODE_JOINT_STEREO + * Native mode indicates that encoding must be performed with the number + * of channels at the input. + * If postprocessing outputs one-channel data, Mono mode is used. If + * postprocessing outputs two-channel data, Stereo mode is used. + * The number of channels must not change during encoding. + */ + uint32_t channel_mode; + + /* + * Encoder bit allocation method. + * @values + * #ASM_MEDIA_FMT_SBC_ALLOCATION_METHOD_LOUDNESS + * #ASM_MEDIA_FMT_SBC_ALLOCATION_METHOD_SNR @tablebulletend + */ + uint32_t alloc_method; + + /* + * Number of encoded bits per second. + * @values + * Mono channel -- Maximum of 320 kbps + * Stereo channel -- Maximum of 512 kbps @tablebulletend + */ + uint32_t bit_rate; + + /* + * Number of samples per second. + * @values 0 (Native mode), 16000, 32000, 44100, 48000 Hz + * Native mode indicates that encoding must be performed with the + * sampling rate at the input. + * The sampling rate must not change during encoding. + */ + uint32_t sample_rate; +}; + +#define ASM_MEDIA_FMT_AAC_AOT_LC 2 +#define ASM_MEDIA_FMT_AAC_AOT_SBR 5 +#define ASM_MEDIA_FMT_AAC_AOT_PS 29 +#define ASM_MEDIA_FMT_AAC_FORMAT_FLAG_ADTS 0 +#define ASM_MEDIA_FMT_AAC_FORMAT_FLAG_RAW 3 + +struct asm_aac_enc_cfg_v2_t { + + /* Encoding rate in bits per second.*/ + uint32_t bit_rate; + + /* + * Encoding mode. + * Supported values: + * #ASM_MEDIA_FMT_AAC_AOT_LC + * #ASM_MEDIA_FMT_AAC_AOT_SBR + * #ASM_MEDIA_FMT_AAC_AOT_PS + */ + uint32_t enc_mode; + + /* + * AAC format flag. + * Supported values: + * #ASM_MEDIA_FMT_AAC_FORMAT_FLAG_ADTS + * #ASM_MEDIA_FMT_AAC_FORMAT_FLAG_RAW + */ + uint16_t aac_fmt_flag; + + /* + * Number of channels to encode. + * Supported values: + * 0 - Native mode + * 1 - Mono + * 2 - Stereo + * Other values are not supported. + * @note1hang The eAAC+ encoder mode supports only stereo. + * Native mode indicates that encoding must be performed with the + * number of channels at the input. + * The number of channels must not change during encoding. + */ + uint32_t channel_cfg; + + /* + * Number of samples per second. + * Supported values: - 0 -- Native mode - For other values, + * Native mode indicates that encoding must be performed with the + * sampling rate at the input. + * The sampling rate must not change during encoding. + */ + uint32_t sample_rate; +} __packed; + +/* FMT ID for apt-X Classic */ +#define ASM_MEDIA_FMT_APTX 0x000131ff + +/* FMT ID for apt-X HD */ +#define ASM_MEDIA_FMT_APTX_HD 0x00013200 + +#define PCM_CHANNEL_L 1 +#define PCM_CHANNEL_R 2 +#define PCM_CHANNEL_C 3 + +struct asm_custom_enc_cfg_aptx_t { + uint32_t sample_rate; + /* Mono or stereo */ + uint16_t num_channels; + uint16_t reserved; + /* num_ch == 1, then PCM_CHANNEL_C, + * num_ch == 2, then {PCM_CHANNEL_L, PCM_CHANNEL_R} + */ + uint8_t channel_mapping[8]; + uint32_t custom_size; +} __packed; + +struct afe_enc_fmt_id_param_t { + /* + * Supported values: + * #ASM_MEDIA_FMT_SBC + * #ASM_MEDIA_FMT_AAC_V2 + * Any OpenDSP supported values + */ + uint32_t fmt_id; +} __packed; + +struct afe_port_media_type_t { + /* + * Minor version + * @values #AFE_API_VERSION_PORT_MEDIA_TYPE. + */ + uint32_t minor_version; + + /* + * Sampling rate of the port. + * @values + * #AFE_PORT_SAMPLE_RATE_8K + * #AFE_PORT_SAMPLE_RATE_11_025K + * #AFE_PORT_SAMPLE_RATE_12K + * #AFE_PORT_SAMPLE_RATE_16K + * #AFE_PORT_SAMPLE_RATE_22_05K + * #AFE_PORT_SAMPLE_RATE_24K + * #AFE_PORT_SAMPLE_RATE_32K + * #AFE_PORT_SAMPLE_RATE_44_1K + * #AFE_PORT_SAMPLE_RATE_48K + * #AFE_PORT_SAMPLE_RATE_88_2K + * #AFE_PORT_SAMPLE_RATE_96K + * #AFE_PORT_SAMPLE_RATE_176_4K + * #AFE_PORT_SAMPLE_RATE_192K + * #AFE_PORT_SAMPLE_RATE_352_8K + * #AFE_PORT_SAMPLE_RATE_384K + */ + uint32_t sample_rate; + + /* + * Bit width of the sample. + * @values 16, 24 + */ + uint16_t bit_width; + + /* + * Number of channels. + * @values 1 to #AFE_PORT_MAX_AUDIO_CHAN_CNT + */ + uint16_t num_channels; + + /* + * Data format supported by this port. + * If the port media type and device media type are different, + * it signifies a encoding/decoding use case + * @values + * #AFE_PORT_DATA_FORMAT_PCM + * #AFE_PORT_DATA_FORMAT_GENERIC_COMPRESSED + */ + uint16_t data_format; + + /*This field must be set to zero.*/ + uint16_t reserved; +} __packed; + +union afe_enc_config_data { + struct asm_sbc_enc_cfg_t sbc_config; + struct asm_aac_enc_cfg_v2_t aac_config; + struct asm_custom_enc_cfg_aptx_t aptx_config; +}; + +struct afe_enc_config { + u32 format; + union afe_enc_config_data data; +}; + +struct afe_enc_cfg_blk_param_t { + uint32_t enc_cfg_blk_size; + /* + *Size of the encoder configuration block that follows this member + */ + union afe_enc_config_data enc_blk_config; +}; + +/* + * Payload of the AVS_ENCODER_PARAM_ID_PACKETIZER_ID parameter. + */ +struct avs_enc_packetizer_id_param_t { + /* + * Supported values: + * #AVS_MODULE_ID_PACKETIZER_COP + * Any OpenDSP supported values + */ + uint32_t enc_packetizer_id; +}; + union afe_port_config { struct afe_param_id_pcm_cfg pcm; struct afe_param_id_i2s_cfg i2s; @@ -2751,6 +3078,10 @@ union afe_port_config { struct afe_param_id_set_topology_cfg topology; struct afe_param_id_tdm_cfg tdm; struct afe_param_id_usb_audio_cfg usb_audio; + struct afe_enc_fmt_id_param_t enc_fmt; + struct afe_port_media_type_t media_type; + struct afe_enc_cfg_blk_param_t enc_blk_param; + struct avs_enc_packetizer_id_param_t enc_pkt_id_param; } __packed; struct afe_audioif_config_command_no_payload { diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h index 5cd65357dd95..6be903a4c8d0 100644 --- a/include/sound/q6afe-v2.h +++ b/include/sound/q6afe-v2.h @@ -274,6 +274,9 @@ int afe_rt_proxy_port_read(phys_addr_t buf_addr_p, 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, + 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); int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib); diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c index 7684d27d60a0..c439c5cf2de5 100644 --- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c @@ -37,6 +37,14 @@ #define CHANNEL_STATUS_MASK 0x4 #define AFE_API_VERSION_CLOCK_SET 1 +enum { + 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, + ENC_FMT_APTX_HD = ASM_MEDIA_FMT_APTX_HD, +}; + static const struct afe_clk_set lpass_clk_set_default = { AFE_API_VERSION_CLOCK_SET, Q6AFE_LPASS_CLK_ID_PRI_PCM_IBIT, @@ -157,6 +165,8 @@ struct msm_dai_q6_dai_data { u32 channels; u32 bitwidth; u32 cal_mode; + u32 afe_in_channels; + struct afe_enc_config enc_config; union afe_port_config port_config; }; @@ -1330,9 +1340,20 @@ static int msm_dai_q6_prepare(struct snd_pcm_substream *substream, int rc = 0; if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { - rc = afe_port_start(dai->id, &dai_data->port_config, - dai_data->rate); - + if (dai_data->enc_config.format != ENC_FMT_NONE) { + 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, + &dai_data->enc_config); + if (rc < 0) + pr_err("%s: afe_port_start_v2 failed error: %d\n", + __func__, rc); + } else { + rc = afe_port_start(dai->id, &dai_data->port_config, + dai_data->rate); + } if (IS_ERR_VALUE(rc)) dev_err(dai->dev, "fail to open AFE port 0x%x\n", dai->id); @@ -1941,6 +1962,151 @@ static int msm_dai_q6_usb_audio_cfg_get(struct snd_kcontrol *kcontrol, return 0; } +static int msm_dai_q6_afe_enc_cfg_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; + uinfo->count = sizeof(struct afe_enc_config); + + return 0; +} + +static int msm_dai_q6_afe_enc_cfg_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret = 0; + struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data; + + if (dai_data) { + int format_size = sizeof(dai_data->enc_config.format); + + 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, + format_size); + switch (dai_data->enc_config.format) { + case ENC_FMT_SBC: + memcpy(ucontrol->value.bytes.data + format_size, + &dai_data->enc_config.data, + sizeof(struct asm_sbc_enc_cfg_t)); + break; + case ENC_FMT_AAC_V2: + memcpy(ucontrol->value.bytes.data + format_size, + &dai_data->enc_config.data, + sizeof(struct asm_aac_enc_cfg_v2_t)); + break; + case ENC_FMT_APTX: + case ENC_FMT_APTX_HD: + memcpy(ucontrol->value.bytes.data + format_size, + &dai_data->enc_config.data, + sizeof(struct asm_aac_enc_cfg_v2_t)); + break; + default: + pr_debug("%s: unknown format = %d\n", + __func__, dai_data->enc_config.format); + ret = -EINVAL; + break; + } + } + + return ret; +} + +static int msm_dai_q6_afe_enc_cfg_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret = 0; + struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data; + + if (dai_data) { + int format_size = sizeof(dai_data->enc_config.format); + + memset(&dai_data->enc_config, 0x0, + sizeof(struct afe_enc_config)); + memcpy(&dai_data->enc_config.format, + ucontrol->value.bytes.data, + format_size); + pr_debug("%s: Received encoder config for %d format\n", + __func__, dai_data->enc_config.format); + switch (dai_data->enc_config.format) { + case ENC_FMT_SBC: + memcpy(&dai_data->enc_config.data, + ucontrol->value.bytes.data + format_size, + sizeof(struct asm_sbc_enc_cfg_t)); + break; + case ENC_FMT_AAC_V2: + memcpy(&dai_data->enc_config.data, + ucontrol->value.bytes.data + format_size, + sizeof(struct asm_aac_enc_cfg_v2_t)); + break; + case ENC_FMT_APTX: + case ENC_FMT_APTX_HD: + memcpy(&dai_data->enc_config.data, + ucontrol->value.bytes.data + format_size, + sizeof(struct asm_custom_enc_cfg_aptx_t)); + break; + default: + pr_debug("%s: Ignore enc config for unknown format = %d\n", + __func__, dai_data->enc_config.format); + ret = -EINVAL; + break; + } + } else + ret = -EINVAL; + + return ret; +} + +static const char *const afe_input_chs_text[] = {"Zero", "One", "Two"}; + +static const struct soc_enum afe_input_chs_enum[] = { + SOC_ENUM_SINGLE_EXT(3, afe_input_chs_text), +}; + +static int msm_dai_q6_afe_input_channel_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) { + ucontrol->value.integer.value[0] = dai_data->afe_in_channels; + pr_debug("%s:afe input channel = %d\n", + __func__, dai_data->afe_in_channels); + } + + return 0; +} + +static int msm_dai_q6_afe_input_channel_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) { + dai_data->afe_in_channels = ucontrol->value.integer.value[0]; + pr_debug("%s: updating afe input channel : %d\n", + __func__, dai_data->afe_in_channels); + } + + return 0; +} + +static const struct snd_kcontrol_new afe_enc_config_controls[] = { + { + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_INACTIVE), + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "SLIM_7_RX Encoder Config", + .info = msm_dai_q6_afe_enc_cfg_info, + .get = msm_dai_q6_afe_enc_cfg_get, + .put = msm_dai_q6_afe_enc_cfg_put, + }, + 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), +}; + static const char * const afe_cal_mode_text[] = { "CAL_MODE_DEFAULT", "CAL_MODE_NONE" }; @@ -2020,6 +2186,17 @@ static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai) snd_ctl_new1(&sb_config_controls[1], dai_data)); break; + case SLIMBUS_7_RX: + rc = snd_ctl_add(dai->component->card->snd_card, + snd_ctl_new1(&afe_enc_config_controls[0], + dai_data)); + rc = snd_ctl_add(dai->component->card->snd_card, + snd_ctl_new1(&afe_enc_config_controls[1], + dai_data)); + rc = snd_ctl_add(dai->component->card->snd_card, + snd_ctl_new1(&afe_enc_config_controls[2], + 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/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c index b76cb7f4b210..d8efd587c3da 100644 --- a/sound/soc/msm/qdsp6v2/q6afe.c +++ b/sound/soc/msm/qdsp6v2/q6afe.c @@ -2632,8 +2632,113 @@ exit: return ret; } -int afe_port_start(u16 port_id, union afe_port_config *afe_config, - u32 rate) /* This function is no blocking */ +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) +{ + struct afe_audioif_config_command config; + int index; + int ret; + int payload_size = sizeof(config) - sizeof(struct apr_hdr) - + sizeof(config.param) - sizeof(config.port); + + pr_debug("%s:update DSP for enc format = %d\n", __func__, format); + if (format != ASM_MEDIA_FMT_SBC && format != ASM_MEDIA_FMT_AAC_V2 && + format != ASM_MEDIA_FMT_APTX && format != ASM_MEDIA_FMT_APTX_HD) { + pr_err("%s:Unsuppported format Ignore AFE config\n", __func__); + return 0; + } + memset(&config, 0, sizeof(config)); + index = q6audio_get_port_index(port_id); + 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_size = payload_size + sizeof(config.port.enc_fmt); + 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_ENCODER; + config.pdata.param_id = AFE_ENCODER_PARAM_ID_ENC_FMT_ID; + config.pdata.param_size = sizeof(config.port.enc_fmt); + config.port.enc_fmt.fmt_id = format; + pr_debug("%s:sending AFE_ENCODER_PARAM_ID_ENC_FMT_ID payload: %d\n", + __func__, config.param.payload_size); + ret = afe_apr_send_pkt(&config, &this_afe.wait[index]); + if (ret) { + pr_err("%s:unable to send AFE_ENCODER_PARAM_ID_ENC_FMT_ID", + __func__); + goto exit; + } + + config.param.payload_size = payload_size + + sizeof(config.port.enc_blk_param); + 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) { + pr_err("%s: AFE_ENCODER_PARAM_ID_ENC_CFG_BLK for port 0x%x failed %d\n", + __func__, port_id, ret); + goto exit; + } + + config.param.payload_size = + payload_size + sizeof(config.port.enc_pkt_id_param); + pr_debug("%s:sending AFE_ENCODER_PARAM_ID_PACKETIZER to DSP payload = %d", + __func__, config.param.payload_size); + config.pdata.param_id = AFE_ENCODER_PARAM_ID_PACKETIZER_ID; + config.pdata.param_size = sizeof(config.port.enc_pkt_id_param); + config.port.enc_pkt_id_param.enc_packetizer_id = + AFE_MODULE_ID_PACKETIZER_COP; + ret = afe_apr_send_pkt(&config, &this_afe.wait[index]); + if (ret) { + pr_err("%s: AFE_ENCODER_PARAM_ID_PACKETIZER 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__); + 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; + if (afe_in_channels != 0) + config.port.media_type.num_channels = afe_in_channels; + else + 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 __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) { struct afe_audioif_config_command config; int ret = 0; @@ -2850,7 +2955,11 @@ int afe_port_start(u16 port_id, union afe_port_config *afe_config, config.pdata.param_size = sizeof(config.port); config.port = *afe_config; - + if ((enc_format != ASM_MEDIA_FMT_NONE) && + (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) { + config.port.slim_sch.data_format = + AFE_SB_DATA_FORMAT_GENERIC_COMPRESSED; + } ret = afe_apr_send_pkt(&config, &this_afe.wait[index]); if (ret) { pr_err("%s: AFE enable for port 0x%x failed %d\n", @@ -2858,6 +2967,19 @@ int afe_port_start(u16 port_id, union afe_port_config *afe_config, goto fail_cmd; } + if ((enc_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); + if (ret) { + pr_err("%s: AFE encoder config for port 0x%x failed %d\n", + __func__, port_id, ret); + goto fail_cmd; + } + } + port_index = afe_get_port_index(port_id); if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) { this_afe.afe_sample_rates[port_index] = rate; @@ -2890,6 +3012,47 @@ fail_cmd: return ret; } +/** + * afe_port_start - to configure AFE session with + * specified port configuration + * + * @port_id: AFE port id number + * @afe_config: port configutation + * @rate: sampling rate of port + * + * Returns 0 on success or error value on port start failure. + */ +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); +} +EXPORT_SYMBOL(afe_port_start); + +/** + * afe_port_start_v2 - to configure AFE session with + * specified port configuration and encoder params + * + * @port_id: AFE port id number + * @afe_config: port configutation + * @rate: sampling rate of port + * @cfg: AFE encoder configuration information to setup encoder + * @afe_in_channels: AFE input channel configuration, this needs + * update only if input channel is differ from AFE output + * + * 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, + struct afe_enc_config *enc_cfg) +{ + return __afe_port_start(port_id, afe_config, rate, + afe_in_channels, &enc_cfg->data, + enc_cfg->format); +} +EXPORT_SYMBOL(afe_port_start_v2); + int afe_get_port_index(u16 port_id) { switch (port_id) {