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

Commit 64743885 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: add support for faster CPE data transfer rate"

parents 93442ba7 5d8d8223
Loading
Loading
Loading
Loading
+177 −20
Original line number Diff line number Diff line
@@ -456,12 +456,13 @@ static const struct wcd9xxx_ch tasha_tx_chs[TASHA_TX_MAX] = {

static const u32 vport_check_table[NUM_CODEC_DAIS] = {
	0,							/* AIF1_PB */
	(1 << AIF2_CAP) | (1 << AIF3_CAP),	/* AIF1_CAP */
	BIT(AIF2_CAP) | BIT(AIF3_CAP) | BIT(AIF4_MAD_TX),	/* AIF1_CAP */
	0,							/* AIF2_PB */
	(1 << AIF1_CAP) | (1 << AIF3_CAP),	/* AIF2_CAP */
	BIT(AIF1_CAP) | BIT(AIF3_CAP) | BIT(AIF4_MAD_TX),	/* AIF2_CAP */
	0,							/* AIF3_PB */
	(1 << AIF1_CAP) | (1 << AIF2_CAP),	/* AIF3_CAP */
	BIT(AIF1_CAP) | BIT(AIF2_CAP) | BIT(AIF4_MAD_TX),	/* AIF3_CAP */
	0,						     /* AIF_MIX1_PB */
	BIT(AIF1_CAP) | BIT(AIF2_CAP) | BIT(AIF3_CAP),	     /* AIF4_MAD_TX */
};


@@ -2192,6 +2193,8 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kcontrol,
			return 0;
		}
		break;
	case AIF4_MAD_TX:
		break;
	default:
		pr_err("Unknown AIF %d\n", dai_id);
		mutex_unlock(&codec->mutex);
@@ -2432,6 +2435,13 @@ static const struct snd_kcontrol_new aif3_cap_mixer[] = {
			slim_tx_mixer_get, slim_tx_mixer_put),
};

static const struct snd_kcontrol_new aif4_mad_mixer[] = {
	SOC_SINGLE_EXT("SLIM TX12", SND_SOC_NOPM, TASHA_TX12, 1, 0,
			slim_tx_mixer_get, slim_tx_mixer_put),
	SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, TASHA_TX13, 1, 0,
			slim_tx_mixer_get, slim_tx_mixer_put),
};

static const struct snd_kcontrol_new rx_int1_spline_mix_switch[] = {
	SOC_DAPM_SINGLE("HPHL Switch", SND_SOC_NOPM, 0, 1, 0),
	SOC_DAPM_SINGLE("HPHL Native Switch", SND_SOC_NOPM, 0, 1, 0)
@@ -2957,6 +2967,105 @@ static int tasha_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
	return __tasha_codec_enable_slimtx(codec, event, dai);
}

static void tasha_codec_cpe_pp_set_cfg(struct snd_soc_codec *codec, int event)
{
	struct tasha_priv *tasha_p = snd_soc_codec_get_drvdata(codec);
	struct wcd9xxx_codec_dai_data *dai;
	u8 bit_width, rate, buf_period;

	dai = &tasha_p->dai[AIF4_MAD_TX];
	switch (event) {
	case SND_SOC_DAPM_POST_PMU:
		switch (dai->bit_width) {
		case 32:
			bit_width = 0xF;
			break;
		case 24:
			bit_width = 0xE;
			break;
		case 20:
			bit_width = 0xD;
			break;
		case 16:
		default:
			bit_width = 0x0;
			break;
		}
		snd_soc_update_bits(codec, WCD9335_CPE_SS_TX_PP_CFG, 0x0F,
				    bit_width);

		switch (dai->rate) {
		case 384000:
			rate = 0x30;
			break;
		case 192000:
			rate = 0x20;
			break;
		case 48000:
			rate = 0x10;
			break;
		case 16000:
		default:
			rate = 0x00;
			break;
		}
		snd_soc_update_bits(codec, WCD9335_CPE_SS_TX_PP_CFG, 0x70,
				    rate);

		buf_period = (dai->rate * (dai->bit_width/8)) / (16*1000);
		snd_soc_update_bits(codec, WCD9335_CPE_SS_TX_PP_BUF_INT_PERIOD,
				    0xFF, buf_period);
		dev_dbg(codec->dev, "%s: PP buffer period= 0x%x\n",
			__func__, buf_period);
		break;

	case SND_SOC_DAPM_POST_PMD:
		snd_soc_write(codec, WCD9335_CPE_SS_TX_PP_CFG, 0x3C);
		snd_soc_write(codec, WCD9335_CPE_SS_TX_PP_BUF_INT_PERIOD, 0x60);
		break;

	default:
		break;
	}
}

/*
 * tasha_codec_get_mad_port_id: Callback function that will be invoked
 *	to get the port ID for MAD.
 * @codec: Handle to the codec
 * @port_id: cpe port_id needs to enable
 */
static int tasha_codec_get_mad_port_id(struct snd_soc_codec *codec,
				       u16 *port_id)
{
	struct tasha_priv *tasha_p;
	struct wcd9xxx_codec_dai_data *dai;
	struct wcd9xxx_ch *ch;

	if (!port_id || !codec)
		return -EINVAL;

	tasha_p = snd_soc_codec_get_drvdata(codec);
	if (!tasha_p)
		return -EINVAL;

	dai = &tasha_p->dai[AIF4_MAD_TX];
	list_for_each_entry(ch, &dai->wcd9xxx_ch_list, list) {
		if (ch->port == TASHA_TX12)
			*port_id = WCD_CPE_AFE_OUT_PORT_2;
		else if (ch->port == TASHA_TX13)
			*port_id = WCD_CPE_AFE_OUT_PORT_4;
		else {
			dev_err(codec->dev, "%s: invalid mad_port = %d\n",
					__func__, ch->port);
			return -EINVAL;
		}
	}
	dev_dbg(codec->dev, "%s: port_id = %d\n", __func__, *port_id);

	return 0;
}

/*
 * tasha_codec_enable_slimtx_mad: Callback function that will be invoked
 *	to setup the slave port for MAD.
@@ -2968,7 +3077,10 @@ static int tasha_codec_enable_slimtx_mad(struct snd_soc_codec *codec,
{
	struct tasha_priv *tasha_p = snd_soc_codec_get_drvdata(codec);
	struct wcd9xxx_codec_dai_data *dai;
	struct wcd9xxx_ch *ch;
	int dapm_event = SND_SOC_DAPM_POST_PMU;
	u16 port = 0;
	int ret = 0;

	dai = &tasha_p->dai[AIF4_MAD_TX];

@@ -2978,9 +3090,40 @@ static int tasha_codec_enable_slimtx_mad(struct snd_soc_codec *codec,
	dev_dbg(codec->dev,
		"%s: mad_channel, event = 0x%x\n",
		 __func__, event);
	return __tasha_codec_enable_slimtx(codec, dapm_event, dai);

	list_for_each_entry(ch, &dai->wcd9xxx_ch_list, list) {
		dev_dbg(codec->dev, "%s: mad_port = %d, event = 0x%x\n",
			__func__, ch->port, event);
		if (ch->port == TASHA_TX13) {
			tasha_codec_cpe_pp_set_cfg(codec, dapm_event);
			port = TASHA_TX13;
			break;
		}
	}

	ret = __tasha_codec_enable_slimtx(codec, dapm_event, dai);

	if (port == TASHA_TX13) {
		switch (dapm_event) {
		case SND_SOC_DAPM_POST_PMU:
			snd_soc_update_bits(codec,
				WCD9335_DATA_HUB_DATA_HUB_SB_TX13_INP_CFG,
				0x03, 0x02);
			snd_soc_update_bits(codec, WCD9335_CPE_SS_CFG,
					    0x80, 0x80);
			break;
		case SND_SOC_DAPM_POST_PMD:
			snd_soc_update_bits(codec,
				WCD9335_DATA_HUB_DATA_HUB_SB_TX13_INP_CFG,
				0x03, 0x00);
			snd_soc_update_bits(codec, WCD9335_CPE_SS_CFG,
					    0x80, 0x00);
			break;
		}
	}

	return ret;
}

static int tasha_put_iir_band_audio_mixer(
					struct snd_kcontrol *kcontrol,
@@ -5108,10 +5251,12 @@ static const struct snd_soc_dapm_route audio_map[] = {
	{"MAD_SEL MUX", "MSM", "MADINPUT"},
	{"MADONOFF", "Switch", "MAD_SEL MUX"},
	{"MAD_BROADCAST", "Switch", "MAD_SEL MUX"},
	{"TX13 INP MUX", "CPE_TX_PP", "MADONOFF"},

	{"AIF4", "Switch", "TX13 INP MUX"},
	{"AIF4_MAD Mixer", "SLIM TX12", "MADONOFF"},
	{"AIF4_MAD Mixer", "SLIM TX13", "TX13 INP MUX"},
	{"AIF4 MAD", NULL, "AIF4_MAD Mixer"},
	{"AIF4 MAD", NULL, "AIF4"},
	{"AIF4 MAD", NULL, "MADONOFF"},

	/* SLIMBUS Connections */
	{"AIF1 CAP", NULL, "AIF1_CAP Mixer"},
@@ -7735,7 +7880,7 @@ static const char * const sb_tx13_mux_text[] = {
};

static const char * const tx13_inp_mux_text[] = {
	"CDC_DEC_5", "MAD_BRDCST"
	"CDC_DEC_5", "MAD_BRDCST", "CPE_TX_PP"
};

static const char * const iir_inp_mux_text[] = {
@@ -8216,7 +8361,7 @@ static const struct soc_enum sb_tx13_mux_enum =
			sb_tx13_mux_text);

static const struct soc_enum tx13_inp_mux_enum =
	SOC_ENUM_SINGLE(WCD9335_DATA_HUB_DATA_HUB_SB_TX13_INP_CFG, 0, 2,
	SOC_ENUM_SINGLE(WCD9335_DATA_HUB_DATA_HUB_SB_TX13_INP_CFG, 0, 3,
			tx13_inp_mux_text);

static const struct soc_enum rx_mix_tx0_mux_enum =
@@ -9277,6 +9422,9 @@ static const struct snd_soc_dapm_widget tasha_dapm_widgets[] = {
	SND_SOC_DAPM_MIXER("AIF3_CAP Mixer", SND_SOC_NOPM, AIF3_CAP, 0,
		aif3_cap_mixer, ARRAY_SIZE(aif3_cap_mixer)),

	SND_SOC_DAPM_MIXER("AIF4_MAD Mixer", SND_SOC_NOPM, AIF4_MAD_TX, 0,
		aif4_mad_mixer, ARRAY_SIZE(aif4_mad_mixer)),

	SND_SOC_DAPM_INPUT("VIINPUT"),
	/* Digital Mic Inputs */
	SND_SOC_DAPM_ADC_E("DMIC0", NULL, SND_SOC_NOPM, 0, 0,
@@ -9599,9 +9747,13 @@ static int tasha_set_channel_map(struct snd_soc_dai *dai,
	if (tasha->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
		wcd9xxx_init_slimslave(core, core->slim->laddr,
					   tx_num, tx_slot, rx_num, rx_slot);
		/* Reserve TX12 for MAD data channel */
		/* Reserve TX12/TX13 for MAD data channel */
		dai_data = &tasha->dai[AIF4_MAD_TX];
		if (dai_data) {
			if (TASHA_IS_2_0(tasha->wcd9xxx->version))
				list_add_tail(&core->tx_chs[TASHA_TX13].list,
					      &dai_data->wcd9xxx_ch_list);
			else
				list_add_tail(&core->tx_chs[TASHA_TX12].list,
					      &dai_data->wcd9xxx_ch_list);
		}
@@ -9904,6 +10056,9 @@ static int tasha_hw_params(struct snd_pcm_substream *substream,
		case 192000:
			tx_fs_rate = 6;
			break;
		case 384000:
			tx_fs_rate = 7;
			break;
		};
		if (tx_fs_rate < 0) {
			dev_err(tasha->dev, "%s: Invalid TX sample rate: %d\n",
@@ -10074,10 +10229,11 @@ static struct snd_soc_dai_driver tasha_dai[] = {
		.id = AIF4_MAD_TX,
		.capture = {
			.stream_name = "AIF4 MAD TX",
			.rates = SNDRV_PCM_RATE_16000,
			.formats = TASHA_FORMATS_S16_S24_LE,
			.rates = SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_48000 |
				 SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_384000,
			.formats = TASHA_FORMATS_S16_S24_S32_LE,
			.rate_min = 16000,
			.rate_max = 16000,
			.rate_max = 384000,
			.channels_min = 1,
			.channels_max = 1,
		},
@@ -11285,6 +11441,7 @@ static int tasha_cpe_err_irq_control(struct snd_soc_codec *codec,
static const struct wcd_cpe_cdc_cb cpe_cb = {
	.cdc_clk_en = tasha_codec_internal_rco_ctrl,
	.cpe_clk_en = tasha_codec_cpe_fll_enable,
	.get_afe_out_port_id = tasha_codec_get_mad_port_id,
	.lab_cdc_ch_ctl = tasha_codec_enable_slimtx_mad,
	.cdc_ext_clk = tasha_cdc_mclk_enable,
	.bus_vote_bw = tasha_codec_vote_max_bw,
+32 −19
Original line number Diff line number Diff line
@@ -31,8 +31,8 @@
#define LSM_VOICE_WAKEUP_APP_V2 2
#define AFE_OUT_PORT_2 2
#define LISTEN_MIN_NUM_PERIODS     2
#define LISTEN_MAX_NUM_PERIODS     8
#define LISTEN_MAX_PERIOD_SIZE     4096
#define LISTEN_MAX_NUM_PERIODS     12
#define LISTEN_MAX_PERIOD_SIZE     61440
#define LISTEN_MIN_PERIOD_SIZE     320
#define LISTEN_MAX_STATUS_PAYLOAD_SIZE 256
#define MSM_CPE_MAX_CUSTOM_PARAM_SIZE 2048
@@ -55,7 +55,7 @@

/* Conventional and unconventional sample rate supported */
static unsigned int supported_sample_rates[] = {
	8000, 16000
	8000, 16000, 48000, 192000, 384000
};

static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
@@ -72,10 +72,12 @@ static struct snd_pcm_hardware msm_pcm_hardware_listen = {
		 SNDRV_PCM_INFO_PAUSE |
		 SNDRV_PCM_INFO_RESUME),
	.formats = (SNDRV_PCM_FMTBIT_S16_LE |
		    SNDRV_PCM_FMTBIT_S24_LE),
	.rates = SNDRV_PCM_RATE_16000,
		    SNDRV_PCM_FMTBIT_S24_LE |
		    SNDRV_PCM_FMTBIT_S32_LE),
	.rates = (SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_48000 |
		  SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_384000),
	.rate_min = 16000,
	.rate_max = 16000,
	.rate_max = 384000,
	.channels_min =	1,
	.channels_max =	1,
	.buffer_bytes_max = LISTEN_MAX_NUM_PERIODS *
@@ -102,7 +104,7 @@ enum cpe_lab_thread_status {
};

struct cpe_hw_params {
	u16 sample_rate;
	u32 sample_rate;
	u16 sample_size;
	u32 buf_sz;
	u32 period_count;
@@ -681,9 +683,9 @@ static int msm_cpe_lab_thread(void *data)
				buf_count++;
			}
			dev_dbg(rtd->dev,
				"%s: Cur buf = %p Next Buf = %p\n"
				" buf count = 0x%x\n",
				 __func__, cur_buf, next_buf, buf_count);
				"%s: Cur buf.mem = %p Next Buf.mem = %p\n"
				" buf count = 0x%x\n", __func__,
				cur_buf->mem, next_buf->mem, buf_count);
		} else {
			dev_err(rtd->dev,
				"%s: SB get status, invalid len = 0x%x\n",
@@ -1351,6 +1353,14 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
		dev_dbg(rtd->dev,
			"%s: %s\n",
			__func__, "SNDRV_LSM_START");
		rc = lsm_ops->lsm_get_afe_out_port_id(cpe->core_handle,
						      session);
		if (rc != 0) {
			dev_err(rtd->dev,
				"%s: failed to get port id, err = %d\n",
				__func__, rc);
			return rc;
		}
		rc = lsm_ops->lsm_start(cpe->core_handle, session);
		if (rc != 0) {
			dev_err(rtd->dev,
@@ -1540,13 +1550,14 @@ static int msm_cpe_lsm_lab_start(struct snd_pcm_substream *substream,
	if (session->lab_enable &&
	    event_status->status ==
	    LSM_VOICE_WAKEUP_STATUS_DETECTED) {


		out_port = &session->afe_out_port_cfg;
		out_port->port_id = AFE_OUT_PORT_2;
		out_port->port_id = session->afe_out_port_id;
		out_port->bit_width = hw_params->sample_size;
		out_port->num_channels = hw_params->channels;
		out_port->sample_rate = hw_params->sample_rate;
		dev_dbg(rtd->dev, "%s: port_id= %u, bit_width= %u, rate= %u\n",
			 __func__, out_port->port_id, out_port->bit_width,
			out_port->sample_rate);

		rc = afe_ops->afe_port_cmd_cfg(cpe->core_handle,
					       out_port);
@@ -2797,6 +2808,9 @@ static int msm_cpe_lsm_hwparams(struct snd_pcm_substream *substream,
	else if (params_format(params) ==
		 SNDRV_PCM_FORMAT_S24_LE)
		hw_params->sample_size = 24;
	else if (params_format(params) ==
		 SNDRV_PCM_FORMAT_S32_LE)
		hw_params->sample_size = 32;
	else {
		dev_err(rtd->dev,
			"%s: Invalid Format 0x%x\n",
@@ -2806,10 +2820,11 @@ static int msm_cpe_lsm_hwparams(struct snd_pcm_substream *substream,

	dev_dbg(rtd->dev,
		"%s: Format %d buffer size(bytes) %d period count %d\n"
		" Channel %d period in bytes 0x%x Period Size 0x%x\n",
		" Channel %d period in bytes 0x%x Period Size 0x%x rate = %d\n",
		__func__, params_format(params), params_buffer_bytes(params),
		params_periods(params), params_channels(params),
		params_period_bytes(params), params_period_size(params));
		params_period_bytes(params), params_period_size(params),
		params_rate(params));

	return 0;
}
@@ -2894,10 +2909,8 @@ static int msm_cpe_lsm_copy(struct snd_pcm_substream *substream, int a,
	if (lab_d->buf_idx >= (lsm_d->hw_params.period_count))
		lab_d->buf_idx = 0;
	pcm_buf = (lab_d->pcm_buf[lab_d->buf_idx].mem);
	pr_debug("%s: Buf IDX = 0x%x pcm_buf %pa\n",
			__func__,
			lab_d->buf_idx,
			&(lab_d->pcm_buf[lab_d->buf_idx]));
	pr_debug("%s: Buf IDX = 0x%x pcm_buf %p\n",
		 __func__,  lab_d->buf_idx, pcm_buf);
	if (pcm_buf) {
		if (copy_to_user(buf, pcm_buf, fbytes)) {
			pr_err("Failed to copy buf to user\n");
+10 −5
Original line number Diff line number Diff line
/*
 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -27,10 +27,12 @@
			SNDRV_PCM_RATE_8000 | \
			SNDRV_PCM_RATE_16000 | \
			SNDRV_PCM_RATE_96000 | \
			SNDRV_PCM_RATE_192000)
			SNDRV_PCM_RATE_192000 | \
			SNDRV_PCM_RATE_384000)

#define SLIM_DAI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
			  SNDRV_PCM_FMTBIT_S24_LE)
			  SNDRV_PCM_FMTBIT_S24_LE | \
			  SNDRV_PCM_FMTBIT_S32_LE)

#define DAI_STATE_INITIALIZED (0x01 << 0)
#define DAI_STATE_PREPARED (0x01 << 1)
@@ -52,7 +54,7 @@ struct msm_slim_dai_data {
	u16 *chan_h;
	u16 *sh_ch;
	u16 grph;
	u16 rate;
	u32 rate;
	u16 bits;
	u16 ch_cnt;
	u8 status;
@@ -235,6 +237,9 @@ static int msm_dai_slim_hw_params(
	case SNDRV_PCM_FORMAT_S24_LE:
		dai_data->bits = 24;
		break;
	case SNDRV_PCM_FORMAT_S32_LE:
		dai_data->bits = 32;
		break;
	default:
		dev_err(dai->dev, "%s: invalid format %d\n", __func__,
			params_format(params));
@@ -423,7 +428,7 @@ static struct snd_soc_dai_driver msm_slim_dais[] = {
			 */
			.channels_max = 1,
			.rate_min = 8000,
			.rate_max = 192000,
			.rate_max = 384000,
			.stream_name = "SLIM_DAI0 Capture",
		},
		.ops = &msm_dai_slim_ops,