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

Commit 0b44e345 authored by Vinod Koul's avatar Vinod Koul Committed by Mark Brown
Browse files

ASoC: intel: add support for specifying PCM format



With this machines can configure the PCM format applied on SSP port using
the set_fmt API

Signed-off-by: default avatarPraveen Diwakar <praveen.diwakar@intel.com>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 711bc947
Loading
Loading
Loading
Loading
+99 −0
Original line number Original line Diff line number Diff line
@@ -774,8 +774,107 @@ int sst_handle_vb_timer(struct snd_soc_dai *dai, bool enable)
	return ret;
	return ret;
}
}


static int sst_get_frame_sync_polarity(struct snd_soc_dai *dai,
		unsigned int fmt)
{
	int format;

	format = fmt & SND_SOC_DAIFMT_INV_MASK;
	dev_dbg(dai->dev, "Enter:%s, format=%x\n", __func__, format);

	switch (format) {
	case SND_SOC_DAIFMT_NB_NF:
		return SSP_FS_ACTIVE_LOW;
	case SND_SOC_DAIFMT_NB_IF:
		return SSP_FS_ACTIVE_HIGH;
	case SND_SOC_DAIFMT_IB_IF:
		return SSP_FS_ACTIVE_LOW;
	case SND_SOC_DAIFMT_IB_NF:
		return SSP_FS_ACTIVE_HIGH;
	default:
		dev_err(dai->dev, "Invalid frame sync polarity %d\n", format);
	}

	return -EINVAL;
}

static int sst_get_ssp_mode(struct snd_soc_dai *dai, unsigned int fmt)
{
	int format;

	format = (fmt & SND_SOC_DAIFMT_MASTER_MASK);
	dev_dbg(dai->dev, "Enter:%s, format=%x\n", __func__, format);

	switch (format) {
	case SND_SOC_DAIFMT_CBS_CFS:
		return SSP_MODE_MASTER;
	case SND_SOC_DAIFMT_CBM_CFM:
		return SSP_MODE_SLAVE;
	default:
		dev_err(dai->dev, "Invalid ssp protocol: %d\n", format);
	}

	return -EINVAL;
}


int sst_fill_ssp_config(struct snd_soc_dai *dai, unsigned int fmt)
{
	unsigned int mode;
	int fs_polarity;
	struct sst_data *ctx = snd_soc_dai_get_drvdata(dai);

	mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK;

	switch (mode) {
	case SND_SOC_DAIFMT_DSP_B:
		ctx->ssp_cmd.ssp_protocol = SSP_MODE_PCM;
		ctx->ssp_cmd.mode = sst_get_ssp_mode(dai, fmt) | (SSP_PCM_MODE_NETWORK << 1);
		ctx->ssp_cmd.start_delay = 0;
		ctx->ssp_cmd.data_polarity = 1;
		ctx->ssp_cmd.frame_sync_width = 1;
		break;

	case SND_SOC_DAIFMT_DSP_A:
		ctx->ssp_cmd.ssp_protocol = SSP_MODE_PCM;
		ctx->ssp_cmd.mode = sst_get_ssp_mode(dai, fmt) | (SSP_PCM_MODE_NETWORK << 1);
		ctx->ssp_cmd.start_delay = 1;
		ctx->ssp_cmd.data_polarity = 1;
		ctx->ssp_cmd.frame_sync_width = 1;
		break;

	case SND_SOC_DAIFMT_I2S:
		ctx->ssp_cmd.ssp_protocol = SSP_MODE_I2S;
		ctx->ssp_cmd.mode = sst_get_ssp_mode(dai, fmt) | (SSP_PCM_MODE_NORMAL << 1);
		ctx->ssp_cmd.start_delay = 1;
		ctx->ssp_cmd.data_polarity = 0;
		ctx->ssp_cmd.frame_sync_width = ctx->ssp_cmd.nb_bits_per_slots;
		break;

	case SND_SOC_DAIFMT_LEFT_J:
		ctx->ssp_cmd.ssp_protocol = SSP_MODE_I2S;
		ctx->ssp_cmd.mode = sst_get_ssp_mode(dai, fmt) | (SSP_PCM_MODE_NORMAL << 1);
		ctx->ssp_cmd.start_delay = 0;
		ctx->ssp_cmd.data_polarity = 0;
		ctx->ssp_cmd.frame_sync_width = ctx->ssp_cmd.nb_bits_per_slots;
		break;

	default:
		dev_dbg(dai->dev, "using default ssp configs\n");
	}

	fs_polarity = sst_get_frame_sync_polarity(dai, fmt);
	if (fs_polarity < 0)
		return fs_polarity;

	ctx->ssp_cmd.frame_sync_polarity = fs_polarity;

	return 0;
}

/**
/**
 * sst_ssp_config - contains SSP configuration for media UC
 * sst_ssp_config - contains SSP configuration for media UC
 * this can be overwritten by set_dai_xxx APIs
 */
 */
static const struct sst_ssp_config sst_ssp_configs = {
static const struct sst_ssp_config sst_ssp_configs = {
	.ssp_id = SSP_CODEC,
	.ssp_id = SSP_CODEC,
+1 −0
Original line number Original line Diff line number Diff line
@@ -869,6 +869,7 @@ struct sst_enum {
	SOC_DAPM_ENUM(SST_MUX_CTL_NAME(xpname, xinstance), \
	SOC_DAPM_ENUM(SST_MUX_CTL_NAME(xpname, xinstance), \
			  SST_SSP_MUX_ENUM(xreg, xshift, xtexts))
			  SST_SSP_MUX_ENUM(xreg, xshift, xtexts))


int sst_fill_ssp_config(struct snd_soc_dai *dai, unsigned int fmt);
void sst_fill_ssp_defaults(struct snd_soc_dai *dai);
void sst_fill_ssp_defaults(struct snd_soc_dai *dai);


#endif
#endif
+15 −0
Original line number Original line Diff line number Diff line
@@ -450,6 +450,20 @@ static int sst_be_hw_params(struct snd_pcm_substream *substream,
	return ret;
	return ret;
}
}


static int sst_set_format(struct snd_soc_dai *dai, unsigned int fmt)
{
	int ret = 0;

	if (!dai->active)
		return 0;

	ret = sst_fill_ssp_config(dai, fmt);
	if (ret < 0)
		dev_err(dai->dev, "sst_set_format failed..\n");

	return ret;
}

static void sst_disable_ssp(struct snd_pcm_substream *substream,
static void sst_disable_ssp(struct snd_pcm_substream *substream,
			struct snd_soc_dai *dai)
			struct snd_soc_dai *dai)
{
{
@@ -475,6 +489,7 @@ static struct snd_soc_dai_ops sst_compr_dai_ops = {
static struct snd_soc_dai_ops sst_be_dai_ops = {
static struct snd_soc_dai_ops sst_be_dai_ops = {
	.startup = sst_enable_ssp,
	.startup = sst_enable_ssp,
	.hw_params = sst_be_hw_params,
	.hw_params = sst_be_hw_params,
	.set_fmt = sst_set_format,
	.shutdown = sst_disable_ssp,
	.shutdown = sst_disable_ssp,
};
};