diff options
-rw-r--r-- | sound/soc/codecs/ab8500_audio.c | 22 | ||||
-rw-r--r-- | sound/soc/ux500/ux500_ab8500.c | 38 |
2 files changed, 41 insertions, 19 deletions
diff --git a/sound/soc/codecs/ab8500_audio.c b/sound/soc/codecs/ab8500_audio.c index ae516469046..d56aed95a72 100644 --- a/sound/soc/codecs/ab8500_audio.c +++ b/sound/soc/codecs/ab8500_audio.c @@ -31,6 +31,7 @@ #include <sound/tlv.h> #include <linux/mfd/ab8500.h> #include <linux/mfd/abx500.h> +#include <linux/mfd/ab8500/sysctrl.h> #include "ab8500_audio.h" /* To convert register definition shifts to masks */ @@ -48,7 +49,6 @@ /* Macrocell register definitions */ #define AB8500_CTRL3_REG 0x0200 -#define AB8500_SYSULPCLK_CTRL1_REG 0x020B #define AB8500_GPIO_DIR4_REG 0x1013 #define AB8500_GPIO_DIR5_REG 0x1014 #define AB8500_GPIO_OUT5_REG 0x1024 @@ -1680,19 +1680,13 @@ static int ab8500_codec_set_bit_delay_if1(struct snd_soc_codec *codec, unsigned /* Configures audio macrocell into the AB8500 Chip */ static void ab8500_codec_configure_audio_macrocell(struct snd_soc_codec *codec) { - int data; - - data = ab8500_codec_read_reg(codec, AB8500_SYS_CTRL2_BLOCK, AB8500_CTRL3_REG); - data &= ~CLK_32K_OUT2_DISABLE; - ab8500_codec_write_reg(codec, AB8500_SYS_CTRL2_BLOCK, AB8500_CTRL3_REG, data); - data |= INACTIVE_RESET_AUDIO; - ab8500_codec_write_reg(codec, AB8500_SYS_CTRL2_BLOCK, AB8500_CTRL3_REG, data); - - data = ab8500_codec_read_reg(codec, AB8500_SYS_CTRL2_BLOCK, - AB8500_SYSULPCLK_CTRL1_REG); - data |= ENABLE_AUDIO_CLK_TO_AUDIO_BLK; - ab8500_codec_write_reg(codec, AB8500_SYS_CTRL2_BLOCK, - AB8500_SYSULPCLK_CTRL1_REG, data); + int data, ret; + + ret = ab8500_sysctrl_write(AB8500_STW4500CTRL3, + AB8500_STW4500CTRL3_CLK32KOUT2DIS | AB8500_STW4500CTRL3_RESETAUDN, + AB8500_STW4500CTRL3_RESETAUDN); + if (ret < 0) + pr_err("%s: WARN: Unable to set reg STW4500CTRL3!\n", __func__); data = ab8500_codec_read_reg(codec, AB8500_MISC, AB8500_GPIO_DIR4_REG); data |= GPIO27_DIR_OUTPUT | GPIO29_DIR_OUTPUT | GPIO31_DIR_OUTPUT; diff --git a/sound/soc/ux500/ux500_ab8500.c b/sound/soc/ux500/ux500_ab8500.c index 43ba196d86c..f32a6a45029 100644 --- a/sound/soc/ux500/ux500_ab8500.c +++ b/sound/soc/ux500/ux500_ab8500.c @@ -46,7 +46,9 @@ static struct snd_soc_jack jack; static int master_clock_sel; +/* audioclk -> intclk -> sysclk/ulpclk */ static struct clk *clk_ptr_audioclk; +static struct clk *clk_ptr_intclk; static struct clk *clk_ptr_sysclk; static struct clk *clk_ptr_ulpclk; static DEFINE_MUTEX(power_lock); @@ -199,14 +201,13 @@ static int ux500_ab8500_power_control_inc(void) ab8500_power_count); if (ab8500_power_count == 1) { - ret = clk_set_parent(clk_ptr_audioclk, + ret = clk_set_parent(clk_ptr_intclk, (master_clock_sel == 0) ? clk_ptr_sysclk : clk_ptr_ulpclk); if (ret) { pr_err("%s: ERROR: Setting master-clock to %s failed (ret = %d)!", __func__, (master_clock_sel == 0) ? "SYSCLK" : "ULPCLK", ret); - clk_put(clk_ptr_sysclk); return ret; } @@ -433,8 +434,11 @@ int ux500_ab8500_machine_codec_init(struct snd_soc_pcm_runtime *rtd) /* Add controls */ snd_ctl_add(codec->card->snd_card, snd_ctl_new1(&mclk_input_control, codec)); - /* Setup master clocks */ - ab8500_power_count = 0; + /* Get references to clock-nodes */ + clk_ptr_sysclk = NULL; + clk_ptr_ulpclk = NULL; + clk_ptr_intclk = NULL; + clk_ptr_audioclk = NULL; clk_ptr_sysclk = clk_get(codec->dev, "sysclk"); if (IS_ERR(clk_ptr_sysclk)) { pr_err("ERROR: clk_get failed (ret = %d)!", -EFAULT); @@ -445,15 +449,30 @@ int ux500_ab8500_machine_codec_init(struct snd_soc_pcm_runtime *rtd) pr_err("ERROR: clk_get failed (ret = %d)!", -EFAULT); return -EFAULT; } + clk_ptr_intclk = clk_get(codec->dev, "intclk"); + if (IS_ERR(clk_ptr_audioclk)) { + pr_err("ERROR: clk_get failed (ret = %d)!", -EFAULT); + return -EFAULT; + } clk_ptr_audioclk = clk_get(codec->dev, "audioclk"); if (IS_ERR(clk_ptr_audioclk)) { pr_err("ERROR: clk_get failed (ret = %d)!", -EFAULT); - clk_put(clk_ptr_sysclk); + return -EFAULT; + } + + /* Set intclk default parent to ulpclk */ + ret = clk_set_parent(clk_ptr_intclk, clk_ptr_ulpclk); + if (ret) { + pr_err("%s: ERROR: Setting intclk parent to ulpclk failed (ret = %d)!", + __func__, + ret); return -EFAULT; } master_clock_sel = 1; + ab8500_power_count = 0; + return 0; } @@ -478,6 +497,15 @@ void ux500_ab8500_soc_machine_drv_cleanup(void) pr_info("%s: Enter.\n", __func__); regulator_bulk_free(ARRAY_SIZE(ab8500_regus), ab8500_regus); + + if (clk_ptr_sysclk != NULL) + clk_put(clk_ptr_sysclk); + if (clk_ptr_ulpclk != NULL) + clk_put(clk_ptr_ulpclk); + if (clk_ptr_intclk != NULL) + clk_put(clk_ptr_intclk); + if (clk_ptr_audioclk != NULL) + clk_put(clk_ptr_audioclk); } /* Extended interface */ |