Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7d67e798 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ASoC: msm: flush if prior and current backends rate not matching"

parents 1b6e7200 444ef0c3
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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
+51 −14
Original line number Diff line number Diff line
@@ -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,6 +170,8 @@ 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];
		/* 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))
@@ -159,11 +180,23 @@ static void event_handler(uint32_t opcode,
				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,
			    q6asm_is_cpu_buf_avail_nolock(OUT,
				prtd->audio_client,
				&size, &idx) &&
			    (substream->runtime->status->state ==
			     SNDRV_PCM_STATE_RUNNING))
				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: {
@@ -682,6 +715,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);
@@ -738,9 +772,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,
+88 −27
Original line number Diff line number Diff line
@@ -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
@@ -252,25 +258,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},
	{{0, INVALID_SESSION, {NULL, NULL} },
	{0, INVALID_SESSION, {NULL, NULL} } },
	/* MULTIMEDIA7*/
	{INVALID_SESSION, INVALID_SESSION},
	{{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} } },
};

static int send_stereo_to_custom_stereo_cmd(int port_id,
@@ -411,7 +427,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) &&
@@ -454,7 +470,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 */
@@ -525,6 +541,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;
@@ -560,8 +589,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);
}

@@ -587,6 +616,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);

@@ -613,10 +643,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;

@@ -640,7 +683,7 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
				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);
@@ -656,7 +699,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]);
@@ -664,7 +708,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]);
		}
	}
@@ -1287,12 +1331,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;
	}

@@ -2892,7 +2936,8 @@ static int msm_routing_put_stereo_to_custom_stereo_control(
				MSM_FRONTEND_DAI_MM_SIZE) {
				if (fe_dai_perf_mode[i][SESSION_TYPE_RX])
					goto skip_send_custom_stereo;
				session_id = fe_dai_map[i][SESSION_TYPE_RX];
				session_id =
					fe_dai_map[i][SESSION_TYPE_RX].strm_id;
				if (is_custom_stereo_on) {
					rc = send_stereo_to_custom_stereo_cmd(
						msm_bedais[be_index].port_id,
@@ -4116,7 +4161,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;
@@ -4143,6 +4190,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);
@@ -4174,8 +4222,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;
@@ -4201,7 +4262,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);
+14 −0
Original line number Diff line number Diff line
@@ -137,6 +137,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
@@ -146,6 +151,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);
+5 −1
Original line number Diff line number Diff line
@@ -1744,6 +1744,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;
@@ -1837,6 +1838,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;
@@ -4287,9 +4289,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];
@@ -4299,7 +4303,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--;
			}
		}