[U-Boot] [PATCH V3 5/5] Sound: MAX98095: Support I2S0 channel

Dani Krishna Mohan krishna.md at samsung.com
Wed Sep 11 13:08:50 CEST 2013


This patch modifies the MAX98095 audio codec to support
 I2S0 channel in codec slave mode.

Signed-off-by: Dani Krishna Mohan <krishna.md at samsung.com>
---
 drivers/sound/max98095.c |  155 +++++++++++++++++++++++++++++-----------------
 drivers/sound/max98095.h |   10 ++-
 drivers/sound/sound.c    |   17 ++---
 3 files changed, 115 insertions(+), 67 deletions(-)

diff --git a/drivers/sound/max98095.c b/drivers/sound/max98095.c
index d69db58..febf419 100644
--- a/drivers/sound/max98095.c
+++ b/drivers/sound/max98095.c
@@ -52,7 +52,7 @@ int rate_table[] = {0, 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000,
 static int max98095_i2c_write(unsigned int reg, unsigned char data)
 {
 	debug("%s: Write Addr : 0x%02X, Data :  0x%02X\n",
-		__func__, reg, data);
+	      __func__, reg, data);
 	return i2c_write(g_max98095_i2c_dev_addr, reg, 1, &data, 1);
 }
 
@@ -71,7 +71,7 @@ static unsigned int max98095_i2c_read(unsigned int reg, unsigned char *data)
 	ret = i2c_read(g_max98095_i2c_dev_addr, reg, 1, data, 1);
 	if (ret != 0) {
 		debug("%s: Error while reading register %#04x\n",
-			__func__, reg);
+		      __func__, reg);
 		return -1;
 	}
 
@@ -138,43 +138,57 @@ static int rate_value(int rate, u8 *value)
  * @return -1 for error  and 0  Success.
  */
 static int max98095_hw_params(struct max98095_priv *max98095,
-		unsigned int rate, unsigned int bits_per_sample)
+			      enum en_max_audio_interface aif_id,
+			      unsigned int rate, unsigned int bits_per_sample)
 {
 	u8 regval;
 	int error;
+	unsigned short M98095_DAI_CLKMODE;
+	unsigned short M98095_DAI_FORMAT;
+	unsigned short M98095_DAI_FILTERS;
+
+	if (aif_id == AIF1) {
+		M98095_DAI_CLKMODE = M98095_027_DAI1_CLKMODE;
+		M98095_DAI_FORMAT = M98095_02A_DAI1_FORMAT;
+		M98095_DAI_FILTERS = M98095_02E_DAI1_FILTERS;
+	} else {
+		M98095_DAI_CLKMODE = M98095_031_DAI2_CLKMODE;
+		M98095_DAI_FORMAT = M98095_034_DAI2_FORMAT;
+		M98095_DAI_FILTERS = M98095_038_DAI2_FILTERS;
+	}
 
 	switch (bits_per_sample) {
 	case 16:
-		error = max98095_update_bits(M98095_034_DAI2_FORMAT,
-			M98095_DAI_WS, 0);
+		error = max98095_update_bits(M98095_DAI_FORMAT,
+					     M98095_DAI_WS, 0);
 		break;
 	case 24:
-		error = max98095_update_bits(M98095_034_DAI2_FORMAT,
-			M98095_DAI_WS, M98095_DAI_WS);
+		error = max98095_update_bits(M98095_DAI_FORMAT,
+					     M98095_DAI_WS, M98095_DAI_WS);
 		break;
 	default:
 		debug("%s: Illegal bits per sample %d.\n",
-			__func__, bits_per_sample);
+		      __func__, bits_per_sample);
 		return -1;
 	}
 
 	if (rate_value(rate, &regval)) {
 		debug("%s: Failed to set sample rate to %d.\n",
-			__func__, rate);
+		      __func__, rate);
 		return -1;
 	}
 	max98095->rate = rate;
 
-	error |= max98095_update_bits(M98095_031_DAI2_CLKMODE,
-		M98095_CLKMODE_MASK, regval);
+	error |= max98095_update_bits(M98095_DAI_CLKMODE,
+				      M98095_CLKMODE_MASK, regval);
 
 	/* Update sample rate mode */
 	if (rate < 50000)
-		error |= max98095_update_bits(M98095_038_DAI2_FILTERS,
-			M98095_DAI_DHF, 0);
+		error |= max98095_update_bits(M98095_DAI_FILTERS,
+					      M98095_DAI_DHF, 0);
 	else
-		error |= max98095_update_bits(M98095_038_DAI2_FILTERS,
-			M98095_DAI_DHF, M98095_DAI_DHF);
+		error |= max98095_update_bits(M98095_DAI_FILTERS,
+					      M98095_DAI_DHF, M98095_DAI_DHF);
 
 	if (error < 0) {
 		debug("%s: Error setting hardware params.\n", __func__);
@@ -193,7 +207,7 @@ static int max98095_hw_params(struct max98095_priv *max98095,
  * @return -1 for error and 0 success.
  */
 static int max98095_set_sysclk(struct max98095_priv *max98095,
-				unsigned int freq)
+			       unsigned int freq)
 {
 	int error = 0;
 
@@ -235,22 +249,39 @@ static int max98095_set_sysclk(struct max98095_priv *max98095,
  *
  * @return -1 for error and 0  Success.
  */
-static int max98095_set_fmt(struct max98095_priv *max98095, int fmt)
+static int max98095_set_fmt(struct max98095_priv *max98095, int fmt,
+			    enum en_max_audio_interface aif_id)
 {
 	u8 regval = 0;
 	int error = 0;
+	unsigned short M98095_DAI_CLKCFG_HI;
+	unsigned short M98095_DAI_CLKCFG_LO;
+	unsigned short M98095_DAI_FORMAT;
+	unsigned short M98095_DAI_CLOCK;
 
 	if (fmt == max98095->fmt)
 		return 0;
 
 	max98095->fmt = fmt;
 
+	if (aif_id == AIF1) {
+		M98095_DAI_CLKCFG_HI = M98095_028_DAI1_CLKCFG_HI;
+		M98095_DAI_CLKCFG_LO = M98095_029_DAI1_CLKCFG_LO;
+		M98095_DAI_FORMAT = M98095_02A_DAI1_FORMAT;
+		M98095_DAI_CLOCK = M98095_02B_DAI1_CLOCK;
+	} else {
+		M98095_DAI_CLKCFG_HI = M98095_032_DAI2_CLKCFG_HI;
+		M98095_DAI_CLKCFG_LO = M98095_033_DAI2_CLKCFG_LO;
+		M98095_DAI_FORMAT = M98095_034_DAI2_FORMAT;
+		M98095_DAI_CLOCK = M98095_035_DAI2_CLOCK;
+	}
+
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 	case SND_SOC_DAIFMT_CBS_CFS:
 		/* Slave mode PLL */
-		error |= max98095_i2c_write(M98095_032_DAI2_CLKCFG_HI,
+		error |= max98095_i2c_write(M98095_DAI_CLKCFG_HI,
 					0x80);
-		error |= max98095_i2c_write(M98095_033_DAI2_CLKCFG_LO,
+		error |= max98095_i2c_write(M98095_DAI_CLKCFG_LO,
 					0x00);
 		break;
 	case SND_SOC_DAIFMT_CBM_CFM:
@@ -292,12 +323,13 @@ static int max98095_set_fmt(struct max98095_priv *max98095, int fmt)
 		return -1;
 	}
 
-	error |= max98095_update_bits(M98095_034_DAI2_FORMAT,
-		M98095_DAI_MAS | M98095_DAI_DLY | M98095_DAI_BCI |
-		M98095_DAI_WCI, regval);
+	error |= max98095_update_bits(M98095_DAI_FORMAT,
+				      M98095_DAI_MAS | M98095_DAI_DLY |
+				      M98095_DAI_BCI | M98095_DAI_WCI,
+				      regval);
 
-	error |= max98095_i2c_write(M98095_035_DAI2_CLOCK,
-		M98095_DAI_BSEL64);
+	error |= max98095_i2c_write(M98095_DAI_CLOCK,
+				    M98095_DAI_BSEL64);
 
 	if (error < 0) {
 		debug("%s: Error setting i2s format.\n", __func__);
@@ -354,7 +386,8 @@ static int max98095_reset(void)
  *
  * @returns -1 for error  and 0 Success.
  */
-static int max98095_device_init(struct max98095_priv *max98095)
+static int max98095_device_init(struct max98095_priv *max98095,
+				enum en_max_audio_interface aif_id)
 {
 	unsigned char id;
 	int error = 0;
@@ -374,7 +407,7 @@ static int max98095_device_init(struct max98095_priv *max98095)
 	error = max98095_i2c_read(M98095_0FF_REV_ID, &id);
 	if (error < 0) {
 		debug("%s: Failure reading hardware revision: %d\n",
-			__func__, id);
+		      __func__, id);
 		goto err_access;
 	}
 	debug("%s: Hardware revision: %c\n", __func__, (id - 0x40) + 'A');
@@ -385,26 +418,28 @@ static int max98095_device_init(struct max98095_priv *max98095)
 	 * initialize registers to hardware default configuring audio
 	 * interface2 to DAC
 	 */
-	error |= max98095_i2c_write(M98095_048_MIX_DAC_LR,
-		M98095_DAI2M_TO_DACL|M98095_DAI2M_TO_DACR);
+	if (aif_id == AIF1)
+		error |= max98095_i2c_write(M98095_048_MIX_DAC_LR,
+					    M98095_DAI1L_TO_DACL |
+					    M98095_DAI1R_TO_DACR);
+	else
+		error |= max98095_i2c_write(M98095_048_MIX_DAC_LR,
+					    M98095_DAI2M_TO_DACL |
+					    M98095_DAI2M_TO_DACR);
 
 	error |= max98095_i2c_write(M98095_092_PWR_EN_OUT,
-			M98095_SPK_SPREADSPECTRUM);
-	error |= max98095_i2c_write(M98095_045_CFG_DSP, M98095_DSPNORMAL);
+				    M98095_SPK_SPREADSPECTRUM);
 	error |= max98095_i2c_write(M98095_04E_CFG_HP, M98095_HPNORMAL);
-
-	error |= max98095_i2c_write(M98095_02C_DAI1_IOCFG,
-			M98095_S1NORMAL|M98095_SDATA);
-
-	error |= max98095_i2c_write(M98095_036_DAI2_IOCFG,
-			M98095_S2NORMAL|M98095_SDATA);
-
-	error |= max98095_i2c_write(M98095_040_DAI3_IOCFG,
-			M98095_S3NORMAL|M98095_SDATA);
+	if (aif_id == AIF1)
+		error |= max98095_i2c_write(M98095_02C_DAI1_IOCFG,
+					    M98095_S1NORMAL | M98095_SDATA);
+	else
+		error |= max98095_i2c_write(M98095_036_DAI2_IOCFG,
+					    M98095_S2NORMAL | M98095_SDATA);
 
 	/* take the codec out of the shut down */
 	error |= max98095_update_bits(M98095_097_PWR_SYS, M98095_SHDNRUN,
-			M98095_SHDNRUN);
+				      M98095_SHDNRUN);
 	/* route DACL and DACR output to HO and Spekers */
 	error |= max98095_i2c_write(M98095_050_MIX_SPK_LEFT, 0x01); /* DACL */
 	error |= max98095_i2c_write(M98095_051_MIX_SPK_RIGHT, 0x01);/* DACR */
@@ -422,7 +457,10 @@ static int max98095_device_init(struct max98095_priv *max98095)
 
 	/* Enable DAIs */
 	error |= max98095_i2c_write(M98095_093_BIAS_CTRL, 0x30);
-	error |= max98095_i2c_write(M98095_096_PWR_DAC_CK, 0x07);
+	if (aif_id == AIF1)
+		error |= max98095_i2c_write(M98095_096_PWR_DAC_CK, 0x01);
+	else
+		error |= max98095_i2c_write(M98095_096_PWR_DAC_CK, 0x07);
 
 err_access:
 	if (error < 0)
@@ -432,8 +470,9 @@ err_access:
 }
 
 static int max98095_do_init(struct sound_codec_info *pcodec_info,
-			int sampling_rate, int mclk_freq,
-			int bits_per_sample)
+			    enum en_max_audio_interface aif_id,
+			    int sampling_rate, int mclk_freq,
+			    int bits_per_sample)
 {
 	int ret = 0;
 
@@ -443,15 +482,15 @@ static int max98095_do_init(struct sound_codec_info *pcodec_info,
 	/* shift the device address by 1 for 7 bit addressing */
 	g_max98095_i2c_dev_addr = pcodec_info->i2c_dev_addr >> 1;
 
-	if (pcodec_info->codec_type == CODEC_MAX_98095)
+	if (pcodec_info->codec_type == CODEC_MAX_98095) {
 		g_max98095_info.devtype = MAX98095;
-	else {
+	} else {
 		debug("%s: Codec id [%d] not defined\n", __func__,
-				pcodec_info->codec_type);
+		      pcodec_info->codec_type);
 		return -1;
 	}
 
-	ret = max98095_device_init(&g_max98095_info);
+	ret = max98095_device_init(&g_max98095_info, aif_id);
 	if (ret < 0) {
 		debug("%s: max98095 codec chip init failed\n", __func__);
 		return ret;
@@ -463,14 +502,15 @@ static int max98095_do_init(struct sound_codec_info *pcodec_info,
 		return ret;
 	}
 
-	ret = max98095_hw_params(&g_max98095_info, sampling_rate,
-				bits_per_sample);
+	ret = max98095_hw_params(&g_max98095_info, aif_id, sampling_rate,
+				 bits_per_sample);
 
 	if (ret == 0) {
 		ret = max98095_set_fmt(&g_max98095_info,
-					SND_SOC_DAIFMT_I2S |
-					SND_SOC_DAIFMT_NB_NF |
-					SND_SOC_DAIFMT_CBS_CFS);
+				       SND_SOC_DAIFMT_I2S |
+				       SND_SOC_DAIFMT_NB_NF |
+				       SND_SOC_DAIFMT_CBS_CFS,
+				       aif_id);
 	}
 
 	return ret;
@@ -529,8 +569,9 @@ static int get_max98095_codec_values(struct sound_codec_info *pcodec_info,
 }
 
 /* max98095 Device Initialisation */
-int max98095_init(const void *blob, int sampling_rate, int mclk_freq,
-			int bits_per_sample)
+int max98095_init(const void *blob, enum en_max_audio_interface aif_id,
+		  int sampling_rate, int mclk_freq,
+		  int bits_per_sample)
 {
 	int ret;
 	int old_bus = i2c_get_bus_num();
@@ -538,12 +579,12 @@ int max98095_init(const void *blob, int sampling_rate, int mclk_freq,
 
 	if (get_max98095_codec_values(pcodec_info, blob) < 0) {
 		debug("FDT Codec values failed\n");
-		 return -1;
+		return -1;
 	}
 
 	i2c_set_bus_num(pcodec_info->i2c_bus);
-	ret = max98095_do_init(pcodec_info, sampling_rate, mclk_freq,
-				bits_per_sample);
+	ret = max98095_do_init(pcodec_info, aif_id, sampling_rate, mclk_freq,
+			       bits_per_sample);
 	i2c_set_bus_num(old_bus);
 
 	return ret;
diff --git a/drivers/sound/max98095.h b/drivers/sound/max98095.h
index ae5eb14..44b1e3a 100644
--- a/drivers/sound/max98095.h
+++ b/drivers/sound/max98095.h
@@ -11,6 +11,12 @@
 #ifndef _MAX98095_H
 #define _MAX98095_H
 
+/*  Available audio interface ports in wm8994 codec */
+enum en_max_audio_interface {
+	AIF1 = 1,
+	AIF2,
+};
+
 /*
  * MAX98095 Registers Definition
  */
@@ -305,7 +311,7 @@
  *
  * @returns -1 for error and 0 Success.
  */
-int max98095_init(const void *blob, int sampling_rate, int mclk_freq,
-			int bits_per_sample);
+int max98095_init(const void *blob, enum en_max_audio_interface aif_id,
+		  int sampling_rate, int mclk_freq, int bits_per_sample);
 
 #endif
diff --git a/drivers/sound/sound.c b/drivers/sound/sound.c
index f3342f2..9b8ce5a 100644
--- a/drivers/sound/sound.c
+++ b/drivers/sound/sound.c
@@ -116,7 +116,7 @@ static int codec_init(const void *blob, struct i2stx_info *pi2s_tx)
 	int node;
 
 	/* Get the node from FDT for sound */
-	node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_SOUND);
+	node = fdt_path_offset(blob, "i2s");
 	if (node <= 0) {
 		debug("EXYNOS_SOUND: No node for sound in device tree\n");
 		debug("node = %d\n", node);
@@ -136,13 +136,14 @@ static int codec_init(const void *blob, struct i2stx_info *pi2s_tx)
 	if (!strcmp(codectype, "wm8994")) {
 		/* Check the codec type and initialise the same */
 		ret = wm8994_init(blob, pi2s_tx->id + 1,
-				pi2s_tx->samplingrate,
-				(pi2s_tx->samplingrate * (pi2s_tx->rfs)),
-				pi2s_tx->bitspersample, pi2s_tx->channels);
+				  pi2s_tx->samplingrate,
+				  (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
+				  pi2s_tx->bitspersample, pi2s_tx->channels);
 	} else if (!strcmp(codectype, "max98095")) {
-		ret = max98095_init(blob, pi2s_tx->samplingrate,
-				(pi2s_tx->samplingrate * (pi2s_tx->rfs)),
-				pi2s_tx->bitspersample);
+		ret = max98095_init(blob, pi2s_tx->id + 1,
+				    pi2s_tx->samplingrate,
+				    (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
+				    pi2s_tx->bitspersample);
 	} else {
 		debug("%s: Unknown codec type %s\n", __func__, codectype);
 		return -1;
@@ -235,7 +236,7 @@ int sound_play(uint32_t msec, uint32_t frequency)
 	}
 
 	sound_prepare_buffer((unsigned short *)data,
-				data_size / sizeof(unsigned short), frequency);
+			     data_size / sizeof(unsigned short), frequency);
 
 	while (msec >= 1000) {
 		ret = i2s_transfer_tx_data(&g_i2stx_pri, data,
-- 
1.7.9.5



More information about the U-Boot mailing list