Merge "ASoC: msm: qdsp6v2: support for AFE encoder"

This commit is contained in:
Linux Build Service Account 2016-08-13 04:51:47 -07:00 committed by Gerrit - the friendly Code Review server
commit fb24f59004
4 changed files with 680 additions and 6 deletions

View file

@ -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 {

View file

@ -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);

View file

@ -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)) {
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],

View file

@ -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) {