forked from rubenslte/android_kernel_samsung_msm8226
Merge "ASoC: msm: flush if prior and current backends rate not matching"
This commit is contained in:
committed by
Gerrit - the friendly Code Review server
commit
cc131431cd
@@ -67,6 +67,8 @@
|
||||
/* Enable Sample_Rate/Channel_Mode notification event from Decoder */
|
||||
#define SR_CM_NOTIFY_ENABLE 0x0004
|
||||
|
||||
#define TUN_WRITE_IO_MODE 0x0008 /* tunnel read write mode */
|
||||
#define TUN_READ_IO_MODE 0x0004 /* tunnel read write mode */
|
||||
#define SYNC_IO_MODE 0x0001
|
||||
#define ASYNC_IO_MODE 0x0002
|
||||
#define COMPRESSED_IO 0x0040
|
||||
|
||||
@@ -109,6 +109,25 @@ static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
|
||||
.mask = 0,
|
||||
};
|
||||
|
||||
static void msm_pcm_route_event_handler(enum msm_pcm_routing_event event,
|
||||
void *priv_data)
|
||||
{
|
||||
struct msm_audio *prtd = priv_data;
|
||||
|
||||
BUG_ON(!prtd);
|
||||
|
||||
pr_debug("%s: event %x\n", __func__, event);
|
||||
|
||||
switch (event) {
|
||||
case MSM_PCM_RT_EVT_BUF_RECFG:
|
||||
q6asm_cmd(prtd->audio_client, CMD_PAUSE);
|
||||
q6asm_cmd(prtd->audio_client, CMD_FLUSH);
|
||||
q6asm_run(prtd->audio_client, 0, 0, 0);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void event_handler(uint32_t opcode,
|
||||
uint32_t token, uint32_t *payload, void *priv)
|
||||
{
|
||||
@@ -151,18 +170,31 @@ static void event_handler(uint32_t opcode,
|
||||
pr_debug("token = 0x%08x\n", token);
|
||||
in_frame_info[token][0] = payload[4];
|
||||
in_frame_info[token][1] = payload[5];
|
||||
prtd->pcm_irq_pos += in_frame_info[token][0];
|
||||
pr_debug("pcm_irq_pos=%d\n", prtd->pcm_irq_pos);
|
||||
if (atomic_read(&prtd->start))
|
||||
snd_pcm_period_elapsed(substream);
|
||||
if (atomic_read(&prtd->in_count) <= prtd->periods)
|
||||
atomic_inc(&prtd->in_count);
|
||||
wake_up(&the_locks.read_wait);
|
||||
if (prtd->mmap_flag
|
||||
&& q6asm_is_cpu_buf_avail_nolock(OUT,
|
||||
/* assume data size = 0 during flushing */
|
||||
if (in_frame_info[token][0]) {
|
||||
prtd->pcm_irq_pos += in_frame_info[token][0];
|
||||
pr_debug("pcm_irq_pos=%d\n", prtd->pcm_irq_pos);
|
||||
if (atomic_read(&prtd->start))
|
||||
snd_pcm_period_elapsed(substream);
|
||||
if (atomic_read(&prtd->in_count) <= prtd->periods)
|
||||
atomic_inc(&prtd->in_count);
|
||||
wake_up(&the_locks.read_wait);
|
||||
if (prtd->mmap_flag &&
|
||||
q6asm_is_cpu_buf_avail_nolock(OUT,
|
||||
prtd->audio_client,
|
||||
&size, &idx))
|
||||
q6asm_read_nolock(prtd->audio_client);
|
||||
q6asm_read_nolock(prtd->audio_client);
|
||||
} else {
|
||||
pr_debug("%s: reclaim flushed buf in_count %x\n",
|
||||
__func__, atomic_read(&prtd->in_count));
|
||||
atomic_inc(&prtd->in_count);
|
||||
if (atomic_read(&prtd->in_count) == prtd->periods) {
|
||||
pr_info("%s: reclaimed all bufs\n", __func__);
|
||||
if (atomic_read(&prtd->start))
|
||||
snd_pcm_period_elapsed(substream);
|
||||
wake_up(&the_locks.read_wait);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case APR_BASIC_RSP_RESULT: {
|
||||
@@ -681,6 +713,7 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
int dir, ret;
|
||||
struct msm_plat_data *pdata;
|
||||
uint16_t bits_per_sample = 16;
|
||||
struct msm_pcm_routing_evt event;
|
||||
|
||||
pdata = (struct msm_plat_data *)
|
||||
dev_get_drvdata(soc_prtd->platform->dev);
|
||||
@@ -737,9 +770,12 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
pr_debug("%s: session ID %d\n",
|
||||
__func__, prtd->audio_client->session);
|
||||
prtd->session_id = prtd->audio_client->session;
|
||||
msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
|
||||
event.event_func = msm_pcm_route_event_handler;
|
||||
event.priv_data = (void *) prtd;
|
||||
msm_pcm_routing_reg_phy_stream_v2(soc_prtd->dai_link->be_id,
|
||||
prtd->audio_client->perf_mode,
|
||||
prtd->session_id, substream->stream);
|
||||
prtd->session_id, substream->stream,
|
||||
event);
|
||||
}
|
||||
|
||||
ret = q6asm_audio_client_buf_alloc_contiguous(dir,
|
||||
|
||||
@@ -50,6 +50,12 @@ struct msm_pcm_routing_bdai_data {
|
||||
unsigned int format;
|
||||
};
|
||||
|
||||
struct msm_pcm_routing_fdai_data {
|
||||
u16 be_srate; /* track prior backend sample rate for flushing purpose */
|
||||
int strm_id; /* ASM stream ID */
|
||||
struct msm_pcm_routing_evt event_info;
|
||||
};
|
||||
|
||||
#define INVALID_SESSION -1
|
||||
#define SESSION_TYPE_RX 0
|
||||
#define SESSION_TYPE_TX 1
|
||||
@@ -250,25 +256,35 @@ static struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
|
||||
|
||||
|
||||
/* Track ASM playback & capture sessions of DAI */
|
||||
static int fe_dai_map[MSM_FRONTEND_DAI_MM_SIZE][2] = {
|
||||
static struct msm_pcm_routing_fdai_data
|
||||
fe_dai_map[MSM_FRONTEND_DAI_MM_SIZE][2] = {
|
||||
/* MULTIMEDIA1 */
|
||||
{INVALID_SESSION, INVALID_SESSION},
|
||||
{{0, INVALID_SESSION, {NULL, NULL} },
|
||||
{0, INVALID_SESSION, {NULL, NULL} } },
|
||||
/* MULTIMEDIA2 */
|
||||
{INVALID_SESSION, INVALID_SESSION},
|
||||
{{0, INVALID_SESSION, {NULL, NULL} },
|
||||
{0, INVALID_SESSION, {NULL, NULL} } },
|
||||
/* MULTIMEDIA3 */
|
||||
{INVALID_SESSION, INVALID_SESSION},
|
||||
{{0, INVALID_SESSION, {NULL, NULL} },
|
||||
{0, INVALID_SESSION, {NULL, NULL} } },
|
||||
/* MULTIMEDIA4 */
|
||||
{INVALID_SESSION, INVALID_SESSION},
|
||||
{{0, INVALID_SESSION, {NULL, NULL} },
|
||||
{0, INVALID_SESSION, {NULL, NULL} } },
|
||||
/* MULTIMEDIA5 */
|
||||
{INVALID_SESSION, INVALID_SESSION},
|
||||
{{0, INVALID_SESSION, {NULL, NULL} },
|
||||
{0, INVALID_SESSION, {NULL, NULL} } },
|
||||
/* MULTIMEDIA6 */
|
||||
{INVALID_SESSION, INVALID_SESSION},
|
||||
/* MULTIMEDIA7 */
|
||||
{INVALID_SESSION, INVALID_SESSION},
|
||||
{{0, INVALID_SESSION, {NULL, NULL} },
|
||||
{0, INVALID_SESSION, {NULL, NULL} } },
|
||||
/* MULTIMEDIA7*/
|
||||
{{0, INVALID_SESSION, {NULL, NULL} },
|
||||
{0, INVALID_SESSION, {NULL, NULL} } },
|
||||
/* MULTIMEDIA8 */
|
||||
{INVALID_SESSION, INVALID_SESSION},
|
||||
{{0, INVALID_SESSION, {NULL, NULL} },
|
||||
{0, INVALID_SESSION, {NULL, NULL} } },
|
||||
/* MULTIMEDIA9 */
|
||||
{INVALID_SESSION, INVALID_SESSION},
|
||||
{{0, INVALID_SESSION, {NULL, NULL} },
|
||||
{0, INVALID_SESSION, {NULL, NULL} } },
|
||||
};
|
||||
|
||||
/* Track performance mode of all front-end multimedia sessions.
|
||||
@@ -334,7 +350,7 @@ void msm_pcm_routing_reg_psthr_stream(int fedai_id, int dspst_id,
|
||||
|
||||
mutex_lock(&routing_lock);
|
||||
|
||||
fe_dai_map[fedai_id][session_type] = dspst_id;
|
||||
fe_dai_map[fedai_id][session_type].strm_id = dspst_id;
|
||||
for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
|
||||
if (!is_be_dai_extproc(i) &&
|
||||
(afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
|
||||
@@ -376,7 +392,7 @@ void msm_pcm_routing_reg_phy_stream(int fedai_id, bool perf_mode,
|
||||
mutex_lock(&routing_lock);
|
||||
|
||||
payload.num_copps = 0; /* only RX needs to use payload */
|
||||
fe_dai_map[fedai_id][session_type] = dspst_id;
|
||||
fe_dai_map[fedai_id][session_type].strm_id = dspst_id;
|
||||
fe_dai_perf_mode[fedai_id][session_type] = perf_mode;
|
||||
|
||||
/* re-enable EQ if active */
|
||||
@@ -435,6 +451,19 @@ void msm_pcm_routing_reg_phy_stream(int fedai_id, bool perf_mode,
|
||||
mutex_unlock(&routing_lock);
|
||||
}
|
||||
|
||||
void msm_pcm_routing_reg_phy_stream_v2(int fedai_id, bool perf_mode,
|
||||
int dspst_id, int stream_type,
|
||||
struct msm_pcm_routing_evt event_info)
|
||||
{
|
||||
msm_pcm_routing_reg_phy_stream(fedai_id, perf_mode, dspst_id,
|
||||
stream_type);
|
||||
|
||||
if (stream_type == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
fe_dai_map[fedai_id][SESSION_TYPE_RX].event_info = event_info;
|
||||
else
|
||||
fe_dai_map[fedai_id][SESSION_TYPE_TX].event_info = event_info;
|
||||
}
|
||||
|
||||
void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type)
|
||||
{
|
||||
int i, port_type, session_type, path_type, topology;
|
||||
@@ -470,8 +499,8 @@ void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type)
|
||||
}
|
||||
}
|
||||
|
||||
fe_dai_map[fedai_id][session_type] = INVALID_SESSION;
|
||||
|
||||
fe_dai_map[fedai_id][session_type].strm_id = INVALID_SESSION;
|
||||
fe_dai_map[fedai_id][session_type].be_srate = 0;
|
||||
mutex_unlock(&routing_lock);
|
||||
}
|
||||
|
||||
@@ -497,6 +526,7 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
|
||||
int session_type, path_type, port_id, topology;
|
||||
u32 channels;
|
||||
uint16_t bits_per_sample = 16;
|
||||
struct msm_pcm_routing_fdai_data *fdai;
|
||||
|
||||
pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
|
||||
|
||||
@@ -523,10 +553,23 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
|
||||
(msm_bedais[reg].port_id == VOICE2_PLAYBACK_TX)))
|
||||
voc_start_playback(set, msm_bedais[reg].port_id);
|
||||
set_bit(val, &msm_bedais[reg].fe_sessions);
|
||||
if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
|
||||
fdai = &fe_dai_map[val][session_type];
|
||||
if (msm_bedais[reg].active && fdai->strm_id !=
|
||||
INVALID_SESSION) {
|
||||
|
||||
channels = msm_bedais[reg].channel;
|
||||
if (session_type == SESSION_TYPE_TX &&
|
||||
fdai->be_srate &&
|
||||
(fdai->be_srate != msm_bedais[reg].sample_rate)) {
|
||||
pr_debug("%s: flush strm %d diff BE rates\n",
|
||||
__func__, fdai->strm_id);
|
||||
|
||||
if (fdai->event_info.event_func)
|
||||
fdai->event_info.event_func(
|
||||
MSM_PCM_RT_EVT_BUF_RECFG,
|
||||
fdai->event_info.priv_data);
|
||||
fdai->be_srate = 0; /* might not need it */
|
||||
}
|
||||
if (msm_bedais[reg].format == SNDRV_PCM_FORMAT_S24_LE)
|
||||
bits_per_sample = 24;
|
||||
|
||||
@@ -550,7 +593,7 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
|
||||
topology, false, bits_per_sample);
|
||||
|
||||
msm_pcm_routing_build_matrix(val,
|
||||
fe_dai_map[val][session_type], path_type,
|
||||
fdai->strm_id, path_type,
|
||||
fe_dai_perf_mode[val][session_type]);
|
||||
port_id = srs_port_id = msm_bedais[reg].port_id;
|
||||
srs_send_params(srs_port_id, 1, 0);
|
||||
@@ -566,7 +609,8 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
|
||||
(msm_bedais[reg].port_id == VOICE2_PLAYBACK_TX)))
|
||||
voc_start_playback(set, msm_bedais[reg].port_id);
|
||||
clear_bit(val, &msm_bedais[reg].fe_sessions);
|
||||
if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
|
||||
fdai = &fe_dai_map[val][session_type];
|
||||
if (msm_bedais[reg].active && fdai->strm_id !=
|
||||
INVALID_SESSION) {
|
||||
adm_close(msm_bedais[reg].port_id,
|
||||
fe_dai_perf_mode[val][session_type]);
|
||||
@@ -574,7 +618,7 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
|
||||
(fe_dai_perf_mode[val][session_type] == false))
|
||||
dolby_dap_deinit(msm_bedais[reg].port_id);
|
||||
msm_pcm_routing_build_matrix(val,
|
||||
fe_dai_map[val][session_type], path_type,
|
||||
fdai->strm_id, path_type,
|
||||
fe_dai_perf_mode[val][session_type]);
|
||||
}
|
||||
}
|
||||
@@ -1203,12 +1247,12 @@ static int msm_routing_set_srs_trumedia_control_HDMI(
|
||||
static void msm_send_eq_values(int eq_idx)
|
||||
{
|
||||
int result;
|
||||
struct audio_client *ac =
|
||||
q6asm_get_audio_client(fe_dai_map[eq_idx][SESSION_TYPE_RX]);
|
||||
struct audio_client *ac = q6asm_get_audio_client(
|
||||
fe_dai_map[eq_idx][SESSION_TYPE_RX].strm_id);
|
||||
|
||||
if (ac == NULL) {
|
||||
pr_err("%s: Could not get audio client for session: %d\n",
|
||||
__func__, fe_dai_map[eq_idx][SESSION_TYPE_RX]);
|
||||
__func__, fe_dai_map[eq_idx][SESSION_TYPE_RX].strm_id);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -3881,7 +3925,9 @@ static int msm_pcm_routing_close(struct snd_pcm_substream *substream)
|
||||
mutex_lock(&routing_lock);
|
||||
topology = get_topology(path_type);
|
||||
for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
|
||||
if (fe_dai_map[i][session_type] != INVALID_SESSION) {
|
||||
if (fe_dai_map[i][session_type].strm_id != INVALID_SESSION) {
|
||||
fe_dai_map[i][session_type].be_srate =
|
||||
bedai->sample_rate;
|
||||
adm_close(bedai->port_id,
|
||||
fe_dai_perf_mode[i][session_type]);
|
||||
srs_port_id = -1;
|
||||
@@ -3908,6 +3954,7 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream)
|
||||
u32 channels;
|
||||
bool playback, capture;
|
||||
uint16_t bits_per_sample = 16;
|
||||
struct msm_pcm_routing_fdai_data *fdai;
|
||||
|
||||
if (be_id >= MSM_BACKEND_DAI_MAX) {
|
||||
pr_err("%s: unexpected be_id %d\n", __func__, be_id);
|
||||
@@ -3939,8 +3986,21 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream)
|
||||
capture = substream->stream == SNDRV_PCM_STREAM_CAPTURE;
|
||||
|
||||
for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
|
||||
if (fe_dai_map[i][session_type] != INVALID_SESSION) {
|
||||
fdai = &fe_dai_map[i][session_type];
|
||||
if (fdai->strm_id != INVALID_SESSION) {
|
||||
if (session_type == SESSION_TYPE_TX &&
|
||||
fdai->be_srate &&
|
||||
(fdai->be_srate != bedai->sample_rate)) {
|
||||
pr_debug("%s: flush strm %d diff BE rates\n",
|
||||
__func__,
|
||||
fdai->strm_id);
|
||||
|
||||
if (fdai->event_info.event_func)
|
||||
fdai->event_info.event_func(
|
||||
MSM_PCM_RT_EVT_BUF_RECFG,
|
||||
fdai->event_info.priv_data);
|
||||
fdai->be_srate = 0; /* might not need it */
|
||||
}
|
||||
channels = bedai->channel;
|
||||
if (bedai->format == SNDRV_PCM_FORMAT_S24_LE)
|
||||
bits_per_sample = 24;
|
||||
@@ -3967,7 +4027,7 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream)
|
||||
}
|
||||
|
||||
msm_pcm_routing_build_matrix(i,
|
||||
fe_dai_map[i][session_type], path_type,
|
||||
fdai->strm_id, path_type,
|
||||
fe_dai_perf_mode[i][session_type]);
|
||||
port_id = srs_port_id = bedai->port_id;
|
||||
srs_send_params(srs_port_id, 1, 0);
|
||||
|
||||
@@ -133,6 +133,11 @@ enum {
|
||||
MSM_BACKEND_DAI_MAX,
|
||||
};
|
||||
|
||||
enum msm_pcm_routing_event {
|
||||
MSM_PCM_RT_EVT_BUF_RECFG,
|
||||
MSM_PCM_RT_EVT_MAX,
|
||||
};
|
||||
|
||||
/* dai_id: front-end ID,
|
||||
* dspst_id: DSP audio stream ID
|
||||
* stream_type: playback or capture
|
||||
@@ -142,6 +147,15 @@ void msm_pcm_routing_reg_phy_stream(int fedai_id, bool perf_mode, int dspst_id,
|
||||
void msm_pcm_routing_reg_psthr_stream(int fedai_id, int dspst_id,
|
||||
int stream_type);
|
||||
|
||||
struct msm_pcm_routing_evt {
|
||||
void (*event_func)(enum msm_pcm_routing_event, void *);
|
||||
void *priv_data;
|
||||
};
|
||||
|
||||
void msm_pcm_routing_reg_phy_stream_v2(int fedai_id, bool perf_mode,
|
||||
int dspst_id, int stream_type,
|
||||
struct msm_pcm_routing_evt event_info);
|
||||
|
||||
void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type);
|
||||
|
||||
int msm_routing_check_backend_enabled(int fedai_id);
|
||||
|
||||
@@ -1745,6 +1745,7 @@ static int __q6asm_open_read(struct audio_client *ac,
|
||||
rc);
|
||||
goto fail_cmd;
|
||||
}
|
||||
ac->io_mode |= TUN_READ_IO_MODE;
|
||||
return 0;
|
||||
fail_cmd:
|
||||
return -EINVAL;
|
||||
@@ -1838,6 +1839,7 @@ static int __q6asm_open_write(struct audio_client *ac, uint32_t format,
|
||||
rc);
|
||||
goto fail_cmd;
|
||||
}
|
||||
ac->io_mode |= TUN_WRITE_IO_MODE;
|
||||
return 0;
|
||||
fail_cmd:
|
||||
return -EINVAL;
|
||||
@@ -4261,9 +4263,11 @@ static void q6asm_reset_buf_state(struct audio_client *ac)
|
||||
{
|
||||
int cnt = 0;
|
||||
int loopcnt = 0;
|
||||
int used;
|
||||
struct audio_port_data *port = NULL;
|
||||
|
||||
if (ac->io_mode & SYNC_IO_MODE) {
|
||||
used = (ac->io_mode & TUN_WRITE_IO_MODE ? 1 : 0);
|
||||
mutex_lock(&ac->cmd_lock);
|
||||
for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
|
||||
port = &ac->port[loopcnt];
|
||||
@@ -4273,7 +4277,7 @@ static void q6asm_reset_buf_state(struct audio_client *ac)
|
||||
while (cnt >= 0) {
|
||||
if (!port->buf)
|
||||
continue;
|
||||
port->buf[cnt].used = 1;
|
||||
port->buf[cnt].used = used;
|
||||
cnt--;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user