mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-12 07:37:31 -04:00
Merge "asoc: support non-runtime per-stream, per-device asm channel map"
This commit is contained in:
commit
fabbedbba2
4 changed files with 168 additions and 78 deletions
1
asoc/msm-compress-q6-v2.c
Executable file → Normal file
1
asoc/msm-compress-q6-v2.c
Executable file → Normal file
|
|
@ -1886,6 +1886,7 @@ static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream)
|
|||
ret = q6asm_enc_cfg_blk_pcm_format_support_v5(
|
||||
prtd->audio_client,
|
||||
prtd->sample_rate, prtd->num_channels,
|
||||
true, NULL,
|
||||
bits_per_sample, sample_word_size,
|
||||
ASM_LITTLE_ENDIAN, DEFAULT_QF);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -59,6 +59,11 @@ struct snd_msm {
|
|||
struct snd_pcm *pcm;
|
||||
};
|
||||
|
||||
struct msm_pcm_channel_map {
|
||||
bool set_channel_map;
|
||||
char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL_V8];
|
||||
};
|
||||
|
||||
#define CMD_EOS_MIN_TIMEOUT_LENGTH 50
|
||||
#define CMD_EOS_TIMEOUT_MULTIPLIER (HZ * 50)
|
||||
#define MAX_PB_COPY_RETRIES 3
|
||||
|
|
@ -123,6 +128,8 @@ static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
|
|||
.mask = 0,
|
||||
};
|
||||
|
||||
struct msm_pcm_channel_map *chmap_pspd[MSM_FRONTEND_DAI_MM_SIZE][2];
|
||||
|
||||
static void msm_pcm_route_event_handler(enum msm_pcm_routing_event event,
|
||||
void *priv_data)
|
||||
{
|
||||
|
|
@ -324,6 +331,23 @@ static void event_handler(uint32_t opcode,
|
|||
}
|
||||
}
|
||||
|
||||
static struct msm_pcm_channel_map *msm_pcm_get_chmap(u64 fe_id,
|
||||
int session_type)
|
||||
{
|
||||
if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
|
||||
pr_err("%s: invalid FE %llu\n", __func__, fe_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((session_type != SESSION_TYPE_TX) &&
|
||||
(session_type != SESSION_TYPE_RX)) {
|
||||
pr_err("%s: invalid session type %d\n", __func__, session_type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return chmap_pspd[fe_id][session_type];
|
||||
}
|
||||
|
||||
static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
|
|
@ -333,6 +357,7 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
|
|||
struct msm_audio *prtd = runtime->private_data;
|
||||
struct msm_plat_data *pdata;
|
||||
struct snd_pcm_hw_params *params;
|
||||
struct msm_pcm_channel_map *chmap;
|
||||
int ret;
|
||||
uint32_t fmt_type = FORMAT_LINEAR_PCM;
|
||||
uint16_t bits_per_sample;
|
||||
|
|
@ -356,6 +381,12 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
|
|||
}
|
||||
params = &soc_prtd->dpcm[substream->stream].hw_params;
|
||||
|
||||
chmap = msm_pcm_get_chmap(soc_prtd->dai_link->id, SESSION_TYPE_RX);
|
||||
if (!chmap) {
|
||||
pr_err("%s: invalid chmap handle\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
|
||||
prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
|
||||
|
|
@ -458,8 +489,8 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
|
|||
|
||||
ret = q6asm_media_format_block_multi_ch_pcm_v5(
|
||||
prtd->audio_client, runtime->rate,
|
||||
runtime->channels, !prtd->set_channel_map,
|
||||
prtd->channel_map, bits_per_sample,
|
||||
runtime->channels, !chmap->set_channel_map,
|
||||
chmap->channel_map, bits_per_sample,
|
||||
sample_word_size, ASM_LITTLE_ENDIAN,
|
||||
DEFAULT_QF);
|
||||
} else {
|
||||
|
|
@ -472,7 +503,7 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
|
|||
}
|
||||
}
|
||||
if (ret < 0)
|
||||
pr_info("%s: CMD Format block failed\n", __func__);
|
||||
pr_err("%s: CMD Format block failed\n", __func__);
|
||||
|
||||
atomic_set(&prtd->out_count, runtime->periods);
|
||||
|
||||
|
|
@ -493,6 +524,7 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
|
|||
struct msm_plat_data *pdata;
|
||||
struct snd_pcm_hw_params *params;
|
||||
struct msm_pcm_routing_evt event;
|
||||
struct msm_pcm_channel_map *chmap;
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
uint16_t bits_per_sample = 16;
|
||||
|
|
@ -515,6 +547,12 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
chmap = msm_pcm_get_chmap(soc_prtd->dai_link->id, SESSION_TYPE_TX);
|
||||
if (!chmap) {
|
||||
pr_err("%s: invalid chmap handle\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (prtd->enabled == IDLE) {
|
||||
pr_debug("%s:perf_mode=%d periods=%d\n", __func__,
|
||||
pdata->perf_mode, runtime->periods);
|
||||
|
|
@ -622,6 +660,8 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
|
|||
prtd->audio_client,
|
||||
prtd->samp_rate,
|
||||
prtd->channel_mode,
|
||||
!chmap->set_channel_map,
|
||||
chmap->channel_map,
|
||||
bits_per_sample,
|
||||
sample_word_size,
|
||||
ASM_LITTLE_ENDIAN,
|
||||
|
|
@ -1841,9 +1881,12 @@ static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
|
|||
struct msm_plat_data *pdata = NULL;
|
||||
struct msm_pcm_channel_mixer *chmixer_pspd = NULL;
|
||||
struct snd_soc_component *component = NULL;
|
||||
u64 fe_id = 0;
|
||||
struct msm_pcm_channel_map *chmap;
|
||||
u64 fe_id = kcontrol->private_value & 0xFF;
|
||||
int session_type = (kcontrol->private_value >> 8) & 0xFF;
|
||||
|
||||
pr_debug("%s", __func__);
|
||||
pr_debug("%s: chmap ctl for fe_id: %d, session_type: %d\n",
|
||||
__func__, fe_id, session_type);
|
||||
substream = snd_pcm_chmap_substream(info, idx);
|
||||
if (!substream)
|
||||
return -ENODEV;
|
||||
|
|
@ -1864,6 +1907,17 @@ static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
|
|||
}
|
||||
}
|
||||
|
||||
chmap = msm_pcm_get_chmap(fe_id, session_type);
|
||||
if (!chmap) {
|
||||
pr_err("%s: invalid chmap handle\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
|
||||
chmap->channel_map[i] =
|
||||
ucontrol->value.integer.value[i];
|
||||
|
||||
chmap->set_channel_map = true;
|
||||
|
||||
if (!rtd)
|
||||
return 0;
|
||||
|
||||
|
|
@ -1905,60 +1959,23 @@ static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
|
|||
static int msm_pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
int i;
|
||||
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
|
||||
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
|
||||
struct snd_pcm_substream *substream;
|
||||
struct msm_audio *prtd;
|
||||
struct snd_soc_pcm_runtime *rtd = NULL;
|
||||
struct msm_plat_data *pdata = NULL;
|
||||
struct snd_soc_component *component = NULL;
|
||||
int i = 0;
|
||||
struct msm_pcm_channel_map *chmap;
|
||||
u64 fe_id = kcontrol->private_value & 0xFF;
|
||||
int session_type = (kcontrol->private_value >> 8) & 0xFF;
|
||||
|
||||
pr_debug("%s", __func__);
|
||||
substream = snd_pcm_chmap_substream(info, idx);
|
||||
if (!substream)
|
||||
return -ENODEV;
|
||||
pr_debug("%s: chmap ctl for fe_id: %d, session_type: %d\n",
|
||||
__func__, fe_id, session_type);
|
||||
|
||||
rtd = substream->private_data;
|
||||
if (rtd) {
|
||||
component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
|
||||
if (component) {
|
||||
pdata = (struct msm_plat_data *)
|
||||
dev_get_drvdata(component->dev);
|
||||
if (!pdata) {
|
||||
pr_err("%s: pdata not found\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
} else {
|
||||
pr_err("%s: component is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
memset(ucontrol->value.integer.value, 0,
|
||||
sizeof(ucontrol->value.integer.value));
|
||||
if (!rtd)
|
||||
return 0; /* no channels set */
|
||||
|
||||
mutex_lock(&pdata->lock);
|
||||
if (substream->runtime && substream->ref_count <= 0) {
|
||||
pr_err_ratelimited("%s: substream ref_count:%d invalid\n",
|
||||
__func__, substream->ref_count);
|
||||
mutex_unlock(&pdata->lock);
|
||||
chmap = msm_pcm_get_chmap(fe_id, session_type);
|
||||
if (!chmap) {
|
||||
pr_err("%s: invalid chmap handle\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
prtd = substream->runtime ? substream->runtime->private_data : NULL;
|
||||
for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
|
||||
ucontrol->value.integer.value[i] =
|
||||
chmap->channel_map[i];
|
||||
|
||||
if (prtd && prtd->set_channel_map == true) {
|
||||
for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
|
||||
ucontrol->value.integer.value[i] =
|
||||
(int)prtd->channel_map[i];
|
||||
} else {
|
||||
for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL_V8; i++)
|
||||
ucontrol->value.integer.value[i] = 0;
|
||||
}
|
||||
|
||||
mutex_unlock(&pdata->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1971,24 +1988,82 @@ static int msm_pcm_add_chmap_controls(struct snd_soc_pcm_runtime *rtd)
|
|||
int i, ret = 0;
|
||||
|
||||
pr_debug("%s, Channel map cntrl add\n", __func__);
|
||||
ret = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
|
||||
snd_pcm_std_chmaps,
|
||||
PCM_FORMAT_MAX_NUM_CHANNEL_V8, 0,
|
||||
&chmap_info);
|
||||
if (ret < 0) {
|
||||
pr_err("%s, channel map cntrl add failed\n", __func__);
|
||||
return ret;
|
||||
|
||||
if (rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream &&
|
||||
!chmap_pspd[rtd->dai_link->id][SESSION_TYPE_RX]) {
|
||||
|
||||
chmap_pspd[rtd->dai_link->id][SESSION_TYPE_RX] =
|
||||
kzalloc(sizeof(struct msm_pcm_channel_map), GFP_KERNEL);
|
||||
if (!chmap_pspd[rtd->dai_link->id][SESSION_TYPE_RX]) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
|
||||
snd_pcm_std_chmaps,
|
||||
PCM_FORMAT_MAX_NUM_CHANNEL_V8,
|
||||
(rtd->dai_link->id) | (SESSION_TYPE_RX << 8),
|
||||
&chmap_info);
|
||||
if (ret < 0) {
|
||||
pr_err("%s, channel map cntrl add failed\n", __func__);
|
||||
goto fail;
|
||||
}
|
||||
kctl = chmap_info->kctl;
|
||||
for (i = 0; i < kctl->count; i++)
|
||||
kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
|
||||
|
||||
snprintf(device_num, sizeof(device_num), "%d", pcm->device);
|
||||
strlcat(kctl->id.name, device_num, sizeof(kctl->id.name));
|
||||
pr_debug("%s, Overwriting channel map control name to: %s\n",
|
||||
__func__, kctl->id.name);
|
||||
|
||||
kctl->put = msm_pcm_chmap_ctl_put;
|
||||
kctl->get = msm_pcm_chmap_ctl_get;
|
||||
}
|
||||
kctl = chmap_info->kctl;
|
||||
for (i = 0; i < kctl->count; i++)
|
||||
kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
|
||||
snprintf(device_num, sizeof(device_num), "%d", pcm->device);
|
||||
strlcat(kctl->id.name, device_num, sizeof(kctl->id.name));
|
||||
pr_debug("%s, Overwriting channel map control name to: %s\n",
|
||||
__func__, kctl->id.name);
|
||||
kctl->put = msm_pcm_chmap_ctl_put;
|
||||
kctl->get = msm_pcm_chmap_ctl_get;
|
||||
|
||||
if (rtd->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream &&
|
||||
!chmap_pspd[rtd->dai_link->id][SESSION_TYPE_TX]) {
|
||||
|
||||
chmap_pspd[rtd->dai_link->id][SESSION_TYPE_TX] =
|
||||
kzalloc(sizeof(struct msm_pcm_channel_map), GFP_KERNEL);
|
||||
if (!chmap_pspd[rtd->dai_link->id][SESSION_TYPE_TX]) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_CAPTURE,
|
||||
snd_pcm_std_chmaps,
|
||||
PCM_FORMAT_MAX_NUM_CHANNEL_V8,
|
||||
(rtd->dai_link->id) | (SESSION_TYPE_TX << 8),
|
||||
&chmap_info);
|
||||
if (ret < 0) {
|
||||
pr_err("%s, channel map cntrl add failed\n", __func__);
|
||||
goto fail;
|
||||
}
|
||||
kctl = chmap_info->kctl;
|
||||
for (i = 0; i < kctl->count; i++)
|
||||
kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
|
||||
|
||||
snprintf(device_num, sizeof(device_num), "%d", pcm->device);
|
||||
strlcat(kctl->id.name, device_num, sizeof(kctl->id.name));
|
||||
pr_debug("%s, Overwriting channel map control name to: %s\n",
|
||||
__func__, kctl->id.name);
|
||||
|
||||
kctl->put = msm_pcm_chmap_ctl_put;
|
||||
kctl->get = msm_pcm_chmap_ctl_get;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
pr_err("%s: failed add chmap ctls, err = %d\n", __func__, ret);
|
||||
|
||||
kfree(chmap_pspd[rtd->dai_link->id][SESSION_TYPE_RX]);
|
||||
kfree(chmap_pspd[rtd->dai_link->id][SESSION_TYPE_TX]);
|
||||
chmap_pspd[rtd->dai_link->id][SESSION_TYPE_RX] = NULL;
|
||||
chmap_pspd[rtd->dai_link->id][SESSION_TYPE_TX] = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_AUDIO_QGKI)
|
||||
|
|
|
|||
18
dsp/q6asm.c
18
dsp/q6asm.c
|
|
@ -5529,13 +5529,17 @@ EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_v2);
|
|||
|
||||
static int __q6asm_enc_cfg_blk_pcm_v5(struct audio_client *ac,
|
||||
uint32_t rate, uint32_t channels,
|
||||
bool use_default_chmap,
|
||||
char *channel_map,
|
||||
uint16_t bits_per_sample,
|
||||
uint16_t sample_word_size,
|
||||
uint16_t endianness,
|
||||
uint16_t mode)
|
||||
{
|
||||
return q6asm_enc_cfg_blk_pcm_v5(ac, rate, channels,
|
||||
bits_per_sample, true, false, NULL,
|
||||
bits_per_sample,
|
||||
use_default_chmap, false,
|
||||
channel_map,
|
||||
sample_word_size, endianness, mode);
|
||||
}
|
||||
|
||||
|
|
@ -5644,20 +5648,28 @@ EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_format_support_v4);
|
|||
* @rate: sample rate
|
||||
* @channels: number of channels
|
||||
* @bits_per_sample: bit width of encoder session
|
||||
* @use_default_chmap: true if default channel map to be used
|
||||
* @channel_map: input channel map
|
||||
* @sample_word_size: Size in bits of the word that holds a sample of a channel
|
||||
* @endianness: endianness of the pcm data
|
||||
* @mode: Mode to provide additional info about the pcm input data
|
||||
*/
|
||||
int q6asm_enc_cfg_blk_pcm_format_support_v5(struct audio_client *ac,
|
||||
uint32_t rate, uint32_t channels,
|
||||
bool use_default_chmap,
|
||||
char *channel_map,
|
||||
uint16_t bits_per_sample,
|
||||
uint16_t sample_word_size,
|
||||
uint16_t endianness,
|
||||
uint16_t mode)
|
||||
{
|
||||
return __q6asm_enc_cfg_blk_pcm_v5(ac, rate, channels,
|
||||
bits_per_sample, sample_word_size,
|
||||
endianness, mode);
|
||||
use_default_chmap,
|
||||
channel_map,
|
||||
bits_per_sample,
|
||||
sample_word_size,
|
||||
endianness,
|
||||
mode);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_format_support_v5);
|
||||
|
|
|
|||
|
|
@ -478,11 +478,13 @@ int q6asm_enc_cfg_blk_pcm_format_support_v4(struct audio_client *ac,
|
|||
uint16_t mode);
|
||||
|
||||
int q6asm_enc_cfg_blk_pcm_format_support_v5(struct audio_client *ac,
|
||||
uint32_t rate, uint32_t channels,
|
||||
uint16_t bits_per_sample,
|
||||
uint16_t sample_word_size,
|
||||
uint16_t endianness,
|
||||
uint16_t mode);
|
||||
uint32_t rate, uint32_t channels,
|
||||
bool use_default_chmap,
|
||||
char *channel_map,
|
||||
uint16_t bits_per_sample,
|
||||
uint16_t sample_word_size,
|
||||
uint16_t endianness,
|
||||
uint16_t mode);
|
||||
|
||||
int q6asm_enc_cfg_blk_custom(struct audio_client *ac,
|
||||
uint32_t sample_rate, uint32_t channels,
|
||||
|
|
|
|||
Loading…
Reference in a new issue