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

Commit 9d35aa1e authored by Venkat Sudhir's avatar Venkat Sudhir Committed by Gerrit - the friendly Code Review server
Browse files

ASoC: wcd9xxx: Add support for 24-bit playback for WCD9306



Add support for playback of 24 bit sample and sample rates
upto 192 kHz in WCD9306 codec driver. This change sets codec
format control registers based on the PCM sample size played.

Change-Id: I0df18d538a4e2fcd8a3c5f426af241844337032f
Signed-off-by: default avatarVenkat Sudhir <vsudhir@codeaurora.org>
parent 73116956
Loading
Loading
Loading
Loading
+70 −26
Original line number Diff line number Diff line
@@ -43,6 +43,8 @@
#define TAPAN_HPH_PA_SETTLE_COMP_OFF 13000

#define DAPM_MICBIAS2_EXTERNAL_STANDALONE "MIC BIAS2 External Standalone"
#define TAPAN_VALIDATE_RX_SBPORT_RANGE(port) ((port >= 16) && (port <= 20))
#define TAPAN_CONVERT_RX_SBPORT_ID(port) (port - 16) /* RX1 port ID = 0 */

#define TAPAN_VDD_CX_OPTIMAL_UA 10000
#define TAPAN_VDD_CX_SLEEP_UA 2000
@@ -3279,6 +3281,8 @@ static int tapan_volatile(struct snd_soc_codec *ssc, unsigned int reg)
}

#define TAPAN_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
#define TAPAN_FORMATS_S16_S24_LE (SNDRV_PCM_FMTBIT_S16_LE | \
				  SNDRV_PCM_FORMAT_S24_LE)
static int tapan_write(struct snd_soc_codec *codec, unsigned int reg,
	unsigned int value)
{
@@ -3686,6 +3690,68 @@ static int tapan_set_decimator_rate(struct snd_soc_dai *dai,
	return 0;
}

static void tapan_set_rxsb_port_format(struct snd_pcm_hw_params *params,
				       struct snd_soc_dai *dai)
{
	struct snd_soc_codec *codec = dai->codec;
	struct tapan_priv *tapan_p = snd_soc_codec_get_drvdata(codec);
	struct wcd9xxx_codec_dai_data *cdc_dai;
	struct wcd9xxx_ch *ch;
	int port;
	u8 bit_sel;
	u16 sb_ctl_reg, field_shift;

	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S16_LE:
		bit_sel = 0x2;
		tapan_p->dai[dai->id].bit_width = 16;
		break;
	case SNDRV_PCM_FORMAT_S24_LE:
		bit_sel = 0x0;
		tapan_p->dai[dai->id].bit_width = 24;
		break;
	default:
		dev_err(codec->dev, "Invalid format %x\n",
			params_format(params));
		return;
	}

	cdc_dai = &tapan_p->dai[dai->id];

	list_for_each_entry(ch, &cdc_dai->wcd9xxx_ch_list, list) {
		port = wcd9xxx_get_slave_port(ch->ch_num);

		if (IS_ERR_VALUE(port) ||
		    !TAPAN_VALIDATE_RX_SBPORT_RANGE(port)) {
			dev_warn(codec->dev,
				 "%s: invalid port ID %d returned for RX DAI\n",
				 __func__, port);
			return;
		}

		port = TAPAN_CONVERT_RX_SBPORT_ID(port);

		if (port <= 3) {
			sb_ctl_reg = TAPAN_A_CDC_CONN_RX_SB_B1_CTL;
			field_shift = port << 1;
		} else if (port <= 4) {
			sb_ctl_reg = TAPAN_A_CDC_CONN_RX_SB_B2_CTL;
			field_shift = (port - 4) << 1;
		} else { /* should not happen */
			dev_warn(codec->dev,
				 "%s: bad port ID %d\n", __func__, port);
			return;
		}

		dev_dbg(codec->dev, "%s: sb_ctl_reg %x field_shift %x\n"
			"bit_sel %x\n", __func__, sb_ctl_reg, field_shift,
			bit_sel);
		snd_soc_update_bits(codec, sb_ctl_reg, 0x3 << field_shift,
				    bit_sel << field_shift);
	}
}


static int tapan_hw_params(struct snd_pcm_substream *substream,
			    struct snd_pcm_hw_params *params,
			    struct snd_soc_dai *dai)
@@ -3798,29 +3864,7 @@ static int tapan_hw_params(struct snd_pcm_substream *substream,
			snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_I2S_CTL,
					    0x03, (rx_fs_rate >> 0x05));
		} else {
			switch (params_format(params)) {
			case SNDRV_PCM_FORMAT_S16_LE:
				snd_soc_update_bits(codec,
					TAPAN_A_CDC_CONN_RX_SB_B1_CTL,
					0xFF, 0xAA);
				snd_soc_update_bits(codec,
					TAPAN_A_CDC_CONN_RX_SB_B2_CTL,
					0xFF, 0x2A);
				tapan->dai[dai->id].bit_width = 16;
				break;
			case SNDRV_PCM_FORMAT_S24_LE:
				snd_soc_update_bits(codec,
					TAPAN_A_CDC_CONN_RX_SB_B1_CTL,
					0xFF, 0x00);
				snd_soc_update_bits(codec,
					TAPAN_A_CDC_CONN_RX_SB_B2_CTL,
					0xFF, 0x00);
				tapan->dai[dai->id].bit_width = 24;
				break;
			default:
				dev_err(codec->dev, "Invalid format\n");
				break;
			}
			tapan_set_rxsb_port_format(params, dai);
			tapan->dai[dai->id].rate   = params_rate(params);
		}
		break;
@@ -3937,7 +3981,7 @@ static struct snd_soc_dai_driver tapan_dai[] = {
		.playback = {
			.stream_name = "AIF1 Playback",
			.rates = WCD9306_RATES,
			.formats = TAPAN_FORMATS,
			.formats = TAPAN_FORMATS_S16_S24_LE,
			.rate_max = 192000,
			.rate_min = 8000,
			.channels_min = 1,
@@ -3965,7 +4009,7 @@ static struct snd_soc_dai_driver tapan_dai[] = {
		.playback = {
			.stream_name = "AIF2 Playback",
			.rates = WCD9306_RATES,
			.formats = TAPAN_FORMATS,
			.formats = TAPAN_FORMATS_S16_S24_LE,
			.rate_min = 8000,
			.rate_max = 192000,
			.channels_min = 1,
@@ -3993,7 +4037,7 @@ static struct snd_soc_dai_driver tapan_dai[] = {
		.playback = {
			.stream_name = "AIF3 Playback",
			.rates = WCD9306_RATES,
			.formats = TAPAN_FORMATS,
			.formats = TAPAN_FORMATS_S16_S24_LE,
			.rate_min = 8000,
			.rate_max = 192000,
			.channels_min = 1,