Sound: WM8994: Support I2S0 channel
This patch modifies the WM8994 codec to support I2S0 channel in codec slave mode Signed-off-by: Dani Krishna Mohan <krishna.md@samsung.com>
This commit is contained in:
parent
d7884e047d
commit
d981d80d74
|
@ -36,8 +36,7 @@ static int get_sound_i2s_values(struct i2stx_info *i2s, const void *blob)
|
|||
int error = 0;
|
||||
int base;
|
||||
|
||||
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");
|
||||
return -1;
|
||||
|
@ -80,6 +79,11 @@ static int get_sound_i2s_values(struct i2stx_info *i2s, const void *blob)
|
|||
node, "samsung,i2s-bit-clk-framesize", -1);
|
||||
error |= i2s->bfs;
|
||||
debug("bfs = %d\n", i2s->bfs);
|
||||
|
||||
i2s->id = fdtdec_get_int(blob, node, "samsung,i2s-id", -1);
|
||||
error |= i2s->id;
|
||||
debug("id = %d\n", i2s->id);
|
||||
|
||||
if (error == -1) {
|
||||
debug("fail to get sound i2s node properties\n");
|
||||
return -1;
|
||||
|
@ -92,6 +96,7 @@ static int get_sound_i2s_values(struct i2stx_info *i2s, const void *blob)
|
|||
i2s->channels = I2S_CHANNELS;
|
||||
i2s->rfs = I2S_RFS;
|
||||
i2s->bfs = I2S_BFS;
|
||||
i2s->id = 0;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -130,10 +135,10 @@ static int codec_init(const void *blob, struct i2stx_info *pi2s_tx)
|
|||
#endif
|
||||
if (!strcmp(codectype, "wm8994")) {
|
||||
/* Check the codec type and initialise the same */
|
||||
ret = wm8994_init(blob, WM8994_AIF2,
|
||||
pi2s_tx->samplingrate,
|
||||
(pi2s_tx->samplingrate * (pi2s_tx->rfs)),
|
||||
pi2s_tx->bitspersample, pi2s_tx->channels);
|
||||
ret = wm8994_init(blob, pi2s_tx->id + 1,
|
||||
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)),
|
||||
|
|
|
@ -432,12 +432,12 @@ static int configure_aif_clock(struct wm8994_priv *wm8994, int aif)
|
|||
int ret;
|
||||
|
||||
/* AIF(1/0) register adress offset calculated */
|
||||
if (aif)
|
||||
if (aif-1)
|
||||
offset = 4;
|
||||
else
|
||||
offset = 0;
|
||||
|
||||
switch (wm8994->sysclk[aif]) {
|
||||
switch (wm8994->sysclk[aif-1]) {
|
||||
case WM8994_SYSCLK_MCLK1:
|
||||
reg1 |= SEL_MCLK1;
|
||||
rate = wm8994->mclk[0];
|
||||
|
@ -460,7 +460,7 @@ static int configure_aif_clock(struct wm8994_priv *wm8994, int aif)
|
|||
|
||||
default:
|
||||
debug("%s: Invalid input clock selection [%d]\n",
|
||||
__func__, wm8994->sysclk[aif]);
|
||||
__func__, wm8994->sysclk[aif-1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -470,13 +470,18 @@ static int configure_aif_clock(struct wm8994_priv *wm8994, int aif)
|
|||
reg1 |= WM8994_AIF1CLK_DIV;
|
||||
}
|
||||
|
||||
wm8994->aifclk[aif] = rate;
|
||||
wm8994->aifclk[aif-1] = rate;
|
||||
|
||||
ret = wm8994_update_bits(WM8994_AIF1_CLOCKING_1 + offset,
|
||||
WM8994_AIF1CLK_SRC_MASK | WM8994_AIF1CLK_DIV,
|
||||
reg1);
|
||||
|
||||
ret |= wm8994_update_bits(WM8994_CLOCKING_1,
|
||||
if (aif == WM8994_AIF1)
|
||||
ret |= wm8994_update_bits(WM8994_CLOCKING_1,
|
||||
WM8994_AIF1DSPCLK_ENA_MASK | WM8994_SYSDSPCLK_ENA_MASK,
|
||||
WM8994_AIF1DSPCLK_ENA | WM8994_SYSDSPCLK_ENA);
|
||||
else if (aif == WM8994_AIF2)
|
||||
ret |= wm8994_update_bits(WM8994_CLOCKING_1,
|
||||
WM8994_SYSCLK_SRC | WM8994_AIF2DSPCLK_ENA_MASK |
|
||||
WM8994_SYSDSPCLK_ENA_MASK, WM8994_SYSCLK_SRC |
|
||||
WM8994_AIF2DSPCLK_ENA | WM8994_SYSDSPCLK_ENA);
|
||||
|
@ -536,7 +541,7 @@ static int wm8994_set_sysclk(struct wm8994_priv *wm8994, int aif_id,
|
|||
break;
|
||||
if (i == ARRAY_SIZE(opclk_divs)) {
|
||||
debug("%s frequency divisor not found\n",
|
||||
__func__);
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
ret = wm8994_update_bits(WM8994_CLOCKING_2,
|
||||
|
@ -554,7 +559,7 @@ static int wm8994_set_sysclk(struct wm8994_priv *wm8994, int aif_id,
|
|||
return -1;
|
||||
}
|
||||
|
||||
ret |= configure_aif_clock(wm8994, aif_id - 1);
|
||||
ret |= configure_aif_clock(wm8994, aif_id);
|
||||
|
||||
if (ret < 0) {
|
||||
debug("%s: codec register access error\n", __func__);
|
||||
|
@ -607,6 +612,38 @@ static int wm8994_init_volume_aif2_dac1(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes Volume for AIF1 to HP path
|
||||
*
|
||||
* @returns -1 for error and 0 Success.
|
||||
*
|
||||
*/
|
||||
static int wm8994_init_volume_aif1_dac1(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* Unmute AIF1DAC */
|
||||
ret |= wm8994_i2c_write(WM8994_AIF1_DAC_FILTERS_1, 0x0000);
|
||||
|
||||
ret |= wm8994_update_bits(WM8994_DAC1_LEFT_VOLUME,
|
||||
WM8994_DAC1_VU_MASK | WM8994_DAC1L_VOL_MASK |
|
||||
WM8994_DAC1L_MUTE_MASK, WM8994_DAC1_VU | 0xc0);
|
||||
|
||||
ret |= wm8994_update_bits(WM8994_DAC1_RIGHT_VOLUME,
|
||||
WM8994_DAC1_VU_MASK | WM8994_DAC1R_VOL_MASK |
|
||||
WM8994_DAC1R_MUTE_MASK, WM8994_DAC1_VU | 0xc0);
|
||||
/* Head Phone Volume */
|
||||
ret |= wm8994_i2c_write(WM8994_LEFT_OUTPUT_VOLUME, 0x12D);
|
||||
ret |= wm8994_i2c_write(WM8994_RIGHT_OUTPUT_VOLUME, 0x12D);
|
||||
|
||||
if (ret < 0) {
|
||||
debug("%s: codec register access error\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Intialise wm8994 codec device
|
||||
*
|
||||
|
@ -614,7 +651,8 @@ static int wm8994_init_volume_aif2_dac1(void)
|
|||
*
|
||||
* @returns -1 for error and 0 Success.
|
||||
*/
|
||||
static int wm8994_device_init(struct wm8994_priv *wm8994)
|
||||
static int wm8994_device_init(struct wm8994_priv *wm8994,
|
||||
enum en_audio_interface aif_id)
|
||||
{
|
||||
const char *devname;
|
||||
unsigned short reg_data;
|
||||
|
@ -661,13 +699,30 @@ static int wm8994_device_init(struct wm8994_priv *wm8994)
|
|||
ret |= wm8994_update_bits(WM8994_POWER_MANAGEMENT_1,
|
||||
WM8994_HPOUT1R_ENA_MASK, WM8994_HPOUT1R_ENA);
|
||||
|
||||
/* Power enable for AIF2 and DAC1 */
|
||||
ret |= wm8994_update_bits(WM8994_POWER_MANAGEMENT_5,
|
||||
WM8994_AIF2DACL_ENA_MASK | WM8994_AIF2DACR_ENA_MASK |
|
||||
WM8994_DAC1L_ENA_MASK | WM8994_DAC1R_ENA_MASK,
|
||||
WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA | WM8994_DAC1L_ENA |
|
||||
WM8994_DAC1R_ENA);
|
||||
if (aif_id == WM8994_AIF1) {
|
||||
ret |= wm8994_i2c_write(WM8994_POWER_MANAGEMENT_2,
|
||||
WM8994_TSHUT_ENA | WM8994_MIXINL_ENA |
|
||||
WM8994_MIXINR_ENA | WM8994_IN2L_ENA |
|
||||
WM8994_IN2R_ENA);
|
||||
|
||||
ret |= wm8994_i2c_write(WM8994_POWER_MANAGEMENT_4,
|
||||
WM8994_ADCL_ENA | WM8994_ADCR_ENA |
|
||||
WM8994_AIF1ADC1R_ENA |
|
||||
WM8994_AIF1ADC1L_ENA);
|
||||
|
||||
/* Power enable for AIF1 and DAC1 */
|
||||
ret |= wm8994_i2c_write(WM8994_POWER_MANAGEMENT_5,
|
||||
WM8994_AIF1DACL_ENA |
|
||||
WM8994_AIF1DACR_ENA |
|
||||
WM8994_DAC1L_ENA | WM8994_DAC1R_ENA);
|
||||
} else if (aif_id == WM8994_AIF2) {
|
||||
/* Power enable for AIF2 and DAC1 */
|
||||
ret |= wm8994_update_bits(WM8994_POWER_MANAGEMENT_5,
|
||||
WM8994_AIF2DACL_ENA_MASK | WM8994_AIF2DACR_ENA_MASK |
|
||||
WM8994_DAC1L_ENA_MASK | WM8994_DAC1R_ENA_MASK,
|
||||
WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA |
|
||||
WM8994_DAC1L_ENA | WM8994_DAC1R_ENA);
|
||||
}
|
||||
/* Head Phone Initialisation */
|
||||
ret |= wm8994_update_bits(WM8994_ANALOGUE_HP_1,
|
||||
WM8994_HPOUT1L_DLY_MASK | WM8994_HPOUT1R_DLY_MASK,
|
||||
|
@ -695,35 +750,49 @@ static int wm8994_device_init(struct wm8994_priv *wm8994)
|
|||
ret |= wm8994_update_bits(WM8994_OUTPUT_MIXER_2,
|
||||
WM8994_DAC1R_TO_HPOUT1R_MASK, WM8994_DAC1R_TO_HPOUT1R);
|
||||
|
||||
/* Routing AIF2 to DAC1 */
|
||||
ret |= wm8994_update_bits(WM8994_DAC1_LEFT_MIXER_ROUTING,
|
||||
WM8994_AIF2DACL_TO_DAC1L_MASK,
|
||||
WM8994_AIF2DACL_TO_DAC1L);
|
||||
if (aif_id == WM8994_AIF1) {
|
||||
/* Routing AIF1 to DAC1 */
|
||||
ret |= wm8994_i2c_write(WM8994_DAC1_LEFT_MIXER_ROUTING,
|
||||
WM8994_AIF1DAC1L_TO_DAC1L);
|
||||
|
||||
ret |= wm8994_update_bits(WM8994_DAC1_RIGHT_MIXER_ROUTING,
|
||||
WM8994_AIF2DACR_TO_DAC1R_MASK,
|
||||
WM8994_AIF2DACR_TO_DAC1R);
|
||||
ret |= wm8994_i2c_write(WM8994_DAC1_RIGHT_MIXER_ROUTING,
|
||||
WM8994_AIF1DAC1R_TO_DAC1R);
|
||||
|
||||
/* GPIO Settings for AIF2 */
|
||||
/* B CLK */
|
||||
ret |= wm8994_update_bits(WM8994_GPIO_3, WM8994_GPIO_DIR_MASK |
|
||||
WM8994_GPIO_FUNCTION_MASK ,
|
||||
WM8994_GPIO_DIR_OUTPUT |
|
||||
WM8994_GPIO_FUNCTION_I2S_CLK);
|
||||
/* GPIO Settings for AIF1 */
|
||||
ret |= wm8994_i2c_write(WM8994_GPIO_1, WM8994_GPIO_DIR_OUTPUT
|
||||
| WM8994_GPIO_FUNCTION_I2S_CLK
|
||||
| WM8994_GPIO_INPUT_DEBOUNCE);
|
||||
|
||||
/* LR CLK */
|
||||
ret |= wm8994_update_bits(WM8994_GPIO_4, WM8994_GPIO_DIR_MASK |
|
||||
WM8994_GPIO_FUNCTION_MASK,
|
||||
WM8994_GPIO_DIR_OUTPUT |
|
||||
WM8994_GPIO_FUNCTION_I2S_CLK);
|
||||
ret |= wm8994_init_volume_aif1_dac1();
|
||||
} else if (aif_id == WM8994_AIF2) {
|
||||
/* Routing AIF2 to DAC1 */
|
||||
ret |= wm8994_update_bits(WM8994_DAC1_LEFT_MIXER_ROUTING,
|
||||
WM8994_AIF2DACL_TO_DAC1L_MASK,
|
||||
WM8994_AIF2DACL_TO_DAC1L);
|
||||
|
||||
/* DATA */
|
||||
ret |= wm8994_update_bits(WM8994_GPIO_5, WM8994_GPIO_DIR_MASK |
|
||||
WM8994_GPIO_FUNCTION_MASK,
|
||||
WM8994_GPIO_DIR_OUTPUT |
|
||||
WM8994_GPIO_FUNCTION_I2S_CLK);
|
||||
ret |= wm8994_update_bits(WM8994_DAC1_RIGHT_MIXER_ROUTING,
|
||||
WM8994_AIF2DACR_TO_DAC1R_MASK,
|
||||
WM8994_AIF2DACR_TO_DAC1R);
|
||||
|
||||
/* GPIO Settings for AIF2 */
|
||||
/* B CLK */
|
||||
ret |= wm8994_update_bits(WM8994_GPIO_3, WM8994_GPIO_DIR_MASK |
|
||||
WM8994_GPIO_FUNCTION_MASK ,
|
||||
WM8994_GPIO_DIR_OUTPUT);
|
||||
|
||||
/* LR CLK */
|
||||
ret |= wm8994_update_bits(WM8994_GPIO_4, WM8994_GPIO_DIR_MASK |
|
||||
WM8994_GPIO_FUNCTION_MASK,
|
||||
WM8994_GPIO_DIR_OUTPUT);
|
||||
|
||||
/* DATA */
|
||||
ret |= wm8994_update_bits(WM8994_GPIO_5, WM8994_GPIO_DIR_MASK |
|
||||
WM8994_GPIO_FUNCTION_MASK,
|
||||
WM8994_GPIO_DIR_OUTPUT);
|
||||
|
||||
ret |= wm8994_init_volume_aif2_dac1();
|
||||
}
|
||||
|
||||
ret |= wm8994_init_volume_aif2_dac1();
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
|
@ -795,7 +864,7 @@ static int get_codec_values(struct sound_codec_info *pcodec_info,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*wm8994 Device Initialisation */
|
||||
/* WM8994 Device Initialisation */
|
||||
int wm8994_init(const void *blob, enum en_audio_interface aif_id,
|
||||
int sampling_rate, int mclk_freq,
|
||||
int bits_per_sample, unsigned int channels)
|
||||
|
@ -813,15 +882,15 @@ int wm8994_init(const void *blob, enum en_audio_interface aif_id,
|
|||
g_wm8994_i2c_dev_addr = pcodec_info->i2c_dev_addr;
|
||||
wm8994_i2c_init(pcodec_info->i2c_bus);
|
||||
|
||||
if (pcodec_info->codec_type == CODEC_WM_8994)
|
||||
if (pcodec_info->codec_type == CODEC_WM_8994) {
|
||||
g_wm8994_info.type = WM8994;
|
||||
else {
|
||||
} else {
|
||||
debug("%s: Codec id [%d] not defined\n", __func__,
|
||||
pcodec_info->codec_type);
|
||||
pcodec_info->codec_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = wm8994_device_init(&g_wm8994_info);
|
||||
ret = wm8994_device_init(&g_wm8994_info, aif_id);
|
||||
if (ret < 0) {
|
||||
debug("%s: wm8994 codec chip init failed\n", __func__);
|
||||
return ret;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define WM8994_SOFTWARE_RESET 0x00
|
||||
#define WM8994_POWER_MANAGEMENT_1 0x01
|
||||
#define WM8994_POWER_MANAGEMENT_2 0x02
|
||||
#define WM8994_POWER_MANAGEMENT_4 0x04
|
||||
#define WM8994_POWER_MANAGEMENT_5 0x05
|
||||
#define WM8994_LEFT_OUTPUT_VOLUME 0x1C
|
||||
#define WM8994_RIGHT_OUTPUT_VOLUME 0x1D
|
||||
|
@ -38,6 +39,7 @@
|
|||
#define WM8994_AIF2_CONTROL_2 0x311
|
||||
#define WM8994_AIF2_MASTER_SLAVE 0x312
|
||||
#define WM8994_AIF2_BCLK 0x313
|
||||
#define WM8994_AIF1_DAC_FILTERS_1 0x420
|
||||
#define WM8994_AIF2_DAC_LEFT_VOLUME 0x502
|
||||
#define WM8994_AIF2_DAC_RIGHT_VOLUME 0x503
|
||||
#define WM8994_AIF2_DAC_FILTERS_1 0x520
|
||||
|
@ -45,6 +47,7 @@
|
|||
#define WM8994_DAC1_RIGHT_MIXER_ROUTING 0x602
|
||||
#define WM8994_DAC1_LEFT_VOLUME 0x610
|
||||
#define WM8994_DAC1_RIGHT_VOLUME 0x611
|
||||
#define WM8994_GPIO_1 0x700
|
||||
#define WM8994_GPIO_3 0x702
|
||||
#define WM8994_GPIO_4 0x703
|
||||
#define WM8994_GPIO_5 0x704
|
||||
|
@ -82,6 +85,20 @@
|
|||
/* OPCLK_ENA */
|
||||
#define WM8994_OPCLK_ENA 0x0800
|
||||
|
||||
#define WM8994_TSHUT_ENA 0x4000
|
||||
#define WM8994_MIXINL_ENA 0x0200
|
||||
#define WM8994_MIXINR_ENA 0x0100
|
||||
#define WM8994_IN2L_ENA 0x0080
|
||||
#define WM8994_IN2R_ENA 0x0020
|
||||
|
||||
/*
|
||||
* R5 (0x04) - Power Management (4)
|
||||
*/
|
||||
#define WM8994_ADCL_ENA 0x0001
|
||||
#define WM8994_ADCR_ENA 0x0002
|
||||
#define WM8994_AIF1ADC1R_ENA 0x0100
|
||||
#define WM8994_AIF1ADC1L_ENA 0x0200
|
||||
|
||||
/*
|
||||
* R5 (0x05) - Power Management (5)
|
||||
*/
|
||||
|
@ -91,6 +108,12 @@
|
|||
/* AIF2DACR_ENA */
|
||||
#define WM8994_AIF2DACR_ENA 0x1000
|
||||
#define WM8994_AIF2DACR_ENA_MASK 0x1000
|
||||
/* AIF1DACL_ENA */
|
||||
#define WM8994_AIF1DACL_ENA 0x0200
|
||||
#define WM8994_AIF1DACL_ENA_MASK 0x0200
|
||||
/* AIF1DACR_ENA */
|
||||
#define WM8994_AIF1DACR_ENA 0x0100
|
||||
#define WM8994_AIF1DACR_ENA_MASK 0x0100
|
||||
/* DAC1L_ENA */
|
||||
#define WM8994_DAC1L_ENA 0x0002
|
||||
#define WM8994_DAC1L_ENA_MASK 0x0002
|
||||
|
@ -170,6 +193,9 @@
|
|||
/*
|
||||
* R520 (0x208) - Clocking (1)
|
||||
*/
|
||||
/* AIF1DSPCLK_ENA */
|
||||
#define WM8994_AIF1DSPCLK_ENA 0x0008
|
||||
#define WM8994_AIF1DSPCLK_ENA_MASK 0x0008
|
||||
/* AIF2DSPCLK_ENA */
|
||||
#define WM8994_AIF2DSPCLK_ENA 0x0004
|
||||
#define WM8994_AIF2DSPCLK_ENA_MASK 0x0004
|
||||
|
@ -254,6 +280,8 @@
|
|||
/* AIF2DACL_TO_DAC1L */
|
||||
#define WM8994_AIF2DACL_TO_DAC1L 0x0004
|
||||
#define WM8994_AIF2DACL_TO_DAC1L_MASK 0x0004
|
||||
/* AIF1DAC1L_TO_DAC1L */
|
||||
#define WM8994_AIF1DAC1L_TO_DAC1L 0x0001
|
||||
|
||||
/*
|
||||
* R1538 (0x602) - DAC1 Right Mixer Routing
|
||||
|
@ -261,6 +289,8 @@
|
|||
/* AIF2DACR_TO_DAC1R */
|
||||
#define WM8994_AIF2DACR_TO_DAC1R 0x0004
|
||||
#define WM8994_AIF2DACR_TO_DAC1R_MASK 0x0004
|
||||
/* AIF1DAC1R_TO_DAC1R */
|
||||
#define WM8994_AIF1DAC1R_TO_DAC1R 0x0001
|
||||
|
||||
/*
|
||||
* R1552 (0x610) - DAC1 Left Volume
|
||||
|
@ -285,11 +315,12 @@
|
|||
* GPIO
|
||||
*/
|
||||
/* OUTPUT PIN */
|
||||
#define WM8994_GPIO_DIR_OUTPUT 0x8000
|
||||
#define WM8994_GPIO_DIR_OUTPUT 0x8000
|
||||
/* GPIO PIN MASK */
|
||||
#define WM8994_GPIO_DIR_MASK 0xFFE0
|
||||
#define WM8994_GPIO_DIR_MASK 0xFFE0
|
||||
/* I2S CLK */
|
||||
#define WM8994_GPIO_FUNCTION_I2S_CLK 0x0000
|
||||
#define WM8994_GPIO_FUNCTION_I2S_CLK 0x0001
|
||||
#define WM8994_GPIO_INPUT_DEBOUNCE 0x0100
|
||||
/* GPn FN */
|
||||
#define WM8994_GPIO_FUNCTION_MASK 0x001F
|
||||
#define WM8994_GPIO_FUNCTION_MASK 0x001F
|
||||
#endif
|
||||
|
|
|
@ -85,6 +85,7 @@ struct i2stx_info {
|
|||
unsigned int bitspersample; /* bits per sample */
|
||||
unsigned int channels; /* audio channels */
|
||||
unsigned int base_address; /* I2S Register Base */
|
||||
unsigned int id; /* I2S controller id */
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue