Merge "asoc: msm: update asm channel map for push pull mode"

This commit is contained in:
Linux Build Service Account 2018-08-07 06:18:42 -07:00 committed by Gerrit - the friendly Code Review server
commit ed06521452
4 changed files with 149 additions and 80 deletions

View file

@ -275,6 +275,8 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
int dir = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? IN : OUT;
unsigned long topology;
int perf_mode;
bool use_default_chmap = true;
char *chmap = NULL;
pdata = (struct msm_plat_data *)
dev_get_drvdata(soc_prtd->platform->dev);
@ -311,6 +313,13 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
if (prtd->enabled)
return 0;
if (pdata->ch_map[soc_prtd->dai_link->id]) {
use_default_chmap =
!(pdata->ch_map[soc_prtd->dai_link->id]->set_ch_map);
chmap =
pdata->ch_map[soc_prtd->dai_link->id]->channel_map;
}
switch (runtime->format) {
case SNDRV_PCM_FORMAT_S24_LE:
bits_per_sample = 24;
@ -335,7 +344,8 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
config.bufsz = params_buffer_bytes(params) / params_periods(params);
config.bufcnt = params_periods(params);
ret = q6asm_open_shared_io(prtd->audio_client, &config, dir);
ret = q6asm_open_shared_io(prtd->audio_client, &config, dir,
use_default_chmap, chmap);
if (ret) {
pr_err("%s: q6asm_open_write_shared_io failed ret: %d\n",
__func__, ret);
@ -718,89 +728,126 @@ static int msm_pcm_add_volume_control(struct snd_soc_pcm_runtime *rtd)
return 0;
}
static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
static int msm_pcm_channel_map_put(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_component *pcm = snd_kcontrol_chip(kcontrol);
u64 fe_id = kcontrol->private_value;
struct msm_plat_data *pdata = (struct msm_plat_data *)
snd_soc_component_get_drvdata(pcm);
int rc = 0, i = 0;
pr_debug("%s", __func__);
substream = snd_pcm_chmap_substream(info, idx);
if (!substream)
return -ENODEV;
if (!substream->runtime)
return 0;
pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
prtd = substream->runtime->private_data;
if (prtd) {
prtd->set_channel_map = true;
for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
prtd->channel_map[i] =
(char)(ucontrol->value.integer.value[i]);
if (fe_id >= MSM_FRONTEND_DAI_MAX) {
pr_err("%s Received out of bounds fe_id %llu\n",
__func__, fe_id);
rc = -EINVAL;
goto end;
}
if (pdata->ch_map[fe_id]) {
pdata->ch_map[fe_id]->set_ch_map = true;
for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
pdata->ch_map[fe_id]->channel_map[i] =
(char)(ucontrol->value.integer.value[i]);
} else {
pr_debug("%s: no memory for ch_map, default will be set\n",
__func__);
}
end:
pr_debug("%s: ret %d\n", __func__, rc);
return rc;
}
static int msm_pcm_channel_map_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 8;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = 0xFFFFFFFF;
return 0;
}
static int msm_pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
static int msm_pcm_channel_map_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_component *pcm = snd_kcontrol_chip(kcontrol);
u64 fe_id = kcontrol->private_value;
struct msm_plat_data *pdata = (struct msm_plat_data *)
snd_soc_component_get_drvdata(pcm);
int rc = 0, i = 0;
pr_debug("%s", __func__);
substream = snd_pcm_chmap_substream(info, idx);
if (!substream)
return -ENODEV;
memset(ucontrol->value.integer.value, 0,
sizeof(ucontrol->value.integer.value));
if (!substream->runtime)
return 0; /* no channels set */
prtd = substream->runtime->private_data;
if (prtd && prtd->set_channel_map == true) {
pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
if (fe_id >= MSM_FRONTEND_DAI_MAX) {
pr_err("%s: Received out of bounds fe_id %llu\n",
__func__, fe_id);
rc = -EINVAL;
goto end;
}
if (pdata->ch_map[fe_id]) {
for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
ucontrol->value.integer.value[i] =
(int)prtd->channel_map[i];
} else {
for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
ucontrol->value.integer.value[i] = 0;
pdata->ch_map[fe_id]->channel_map[i];
}
return 0;
end:
pr_debug("%s: ret %d\n", __func__, rc);
return rc;
}
static int msm_pcm_add_chmap_control(struct snd_soc_pcm_runtime *rtd)
static int msm_pcm_add_channel_map_control(struct snd_soc_pcm_runtime *rtd)
{
struct snd_pcm *pcm = rtd->pcm;
struct snd_pcm_chmap *chmap_info;
struct snd_kcontrol *kctl;
char device_num[12];
int i, ret;
const char *mixer_ctl_name = "Playback Channel Map";
const char *deviceNo = "NN";
char *mixer_str = NULL;
struct msm_plat_data *pdata = NULL;
int ctl_len = 0;
struct snd_kcontrol_new fe_channel_map_control[1] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "?",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.info = msm_pcm_channel_map_info,
.get = msm_pcm_channel_map_get,
.put = msm_pcm_channel_map_put,
.private_value = 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, 0,
&chmap_info);
if (ret)
return ret;
if (!rtd) {
pr_err("%s: NULL rtd\n", __func__);
return -EINVAL;
}
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",
__func__, kctl->id.name);
kctl->put = msm_pcm_chmap_ctl_put;
kctl->get = msm_pcm_chmap_ctl_get;
pr_debug("%s: added new pcm FE with name %s, id %d, cpu dai %s, device no %d\n",
__func__, rtd->dai_link->name, rtd->dai_link->id,
rtd->dai_link->cpu_dai_name, rtd->pcm->device);
ctl_len = strlen(mixer_ctl_name) + strlen(deviceNo) + 1;
mixer_str = kzalloc(ctl_len, GFP_KERNEL);
if (!mixer_str)
return -ENOMEM;
snprintf(mixer_str, ctl_len, "%s%d", mixer_ctl_name, rtd->pcm->device);
fe_channel_map_control[0].name = mixer_str;
fe_channel_map_control[0].private_value = rtd->dai_link->id;
pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
snd_soc_add_platform_controls(rtd->platform,
fe_channel_map_control,
ARRAY_SIZE(fe_channel_map_control));
pdata = snd_soc_platform_get_drvdata(rtd->platform);
pdata->ch_map[rtd->dai_link->id] =
kzalloc(sizeof(struct msm_pcm_ch_map), GFP_KERNEL);
if (!pdata->ch_map[rtd->dai_link->id]) {
pr_err("%s: Could not allocate memory for channel map\n",
__func__);
kfree(mixer_str);
return -ENOMEM;
}
kfree(mixer_str);
return 0;
}
@ -1155,11 +1202,11 @@ static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
ret = msm_pcm_add_chmap_control(rtd);
if (ret) {
pr_err("%s failed to add chmap cntls\n", __func__);
goto exit;
}
ret = msm_pcm_add_channel_map_control(rtd);
if (ret)
pr_err("%s: Could not add pcm Channel Map Control\n",
__func__);
ret = msm_pcm_add_volume_control(rtd);
if (ret) {
pr_err("%s: Could not add pcm Volume Control %d\n",
@ -1181,7 +1228,7 @@ static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
if (ret)
pr_err("%s: Could not add hw dep node\n", __func__);
pcm->nonatomic = true;
exit:
return ret;
}

View file

@ -20,7 +20,7 @@
#define _MSM_PCM_H
#include <dsp/apr_audio-v2.h>
#include <dsp/q6asm-v2.h>
#include "msm-pcm-routing-v2.h"
/* Support unconventional sample rates 12000, 24000 as well */
@ -125,6 +125,12 @@ struct output_meta_data_st {
struct msm_plat_data {
int perf_mode;
struct snd_pcm *pcm;
struct msm_pcm_ch_map *ch_map[MSM_FRONTEND_DAI_MAX];
};
struct msm_pcm_ch_map {
bool set_ch_map;
char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL];
};
#endif /*_MSM_PCM_H*/

View file

@ -4027,11 +4027,13 @@ int q6asm_set_shared_pos_buff(struct audio_client *ac,
* parameters
* config - session parameters (channels, bits_per_sample, sr)
* dir - stream direction (IN for playback, OUT for capture)
* use_default_chmap: true if default channel map to be used
* channel_map: input channel map
* returns 0 if successful, error code otherwise
*/
int q6asm_open_shared_io(struct audio_client *ac,
struct shared_io_config *config,
int dir)
int dir, bool use_default_chmap, u8 *channel_map)
{
struct asm_stream_cmd_open_shared_io *open;
u8 *channel_mapping;
@ -4041,6 +4043,12 @@ int q6asm_open_shared_io(struct audio_client *ac,
if (!ac || !config)
return -EINVAL;
if (!use_default_chmap && (channel_map == NULL)) {
pr_err("%s: No valid chan map and can't use default\n",
__func__);
return -EINVAL;
}
bufsz = config->bufsz;
bufcnt = config->bufcnt;
num_watermarks = 0;
@ -4137,10 +4145,17 @@ int q6asm_open_shared_io(struct audio_client *ac,
memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
rc = q6asm_map_channels(channel_mapping, config->channels, false);
if (rc) {
pr_err("%s: Map channels failed, ret: %d\n", __func__, rc);
goto done;
if (use_default_chmap) {
rc = q6asm_map_channels(channel_mapping, config->channels,
false);
if (rc) {
pr_err("%s: Map channels failed, ret: %d\n",
__func__, rc);
goto done;
}
} else {
memcpy(channel_mapping, channel_map,
PCM_FORMAT_MAX_NUM_CHANNEL);
}
open->num_watermark_levels = num_watermarks;

View file

@ -303,7 +303,8 @@ int q6asm_open_write_v2(struct audio_client *ac, uint32_t format,
uint16_t bits_per_sample);
int q6asm_open_shared_io(struct audio_client *ac,
struct shared_io_config *c, int dir);
struct shared_io_config *c, int dir,
bool use_default_chmap, u8 *channel_map);
int q6asm_open_write_v3(struct audio_client *ac, uint32_t format,
uint16_t bits_per_sample);