summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/cpu/armv7/exynos/clock.c61
-rw-r--r--arch/arm/cpu/armv7/exynos/pinmux.c23
-rw-r--r--arch/arm/include/asm/arch-exynos/clk.h5
-rw-r--r--arch/arm/include/asm/arch-exynos/clock.h4
-rw-r--r--arch/arm/include/asm/arch-exynos/cpu.h4
-rw-r--r--arch/arm/include/asm/arch-exynos/periph.h1
-rw-r--r--drivers/sound/samsung-i2s.c26
7 files changed, 93 insertions, 31 deletions
diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
index 0cb1a61..36fedd6 100644
--- a/arch/arm/cpu/armv7/exynos/clock.c
+++ b/arch/arm/cpu/armv7/exynos/clock.c
@@ -282,6 +282,9 @@ static unsigned long exynos5_get_periph_rate(int peripheral)
src = readl(&clk->src_peric0);
div = readl(&clk->div_peric3);
break;
+ case PERIPH_ID_I2S0:
+ src = readl(&clk->src_mau);
+ div = readl(&clk->div_mau);
case PERIPH_ID_SPI0:
case PERIPH_ID_SPI1:
src = readl(&clk->src_peric1);
@@ -1146,17 +1149,29 @@ int exynos5_set_epll_clk(unsigned long rate)
return 0;
}
-void exynos5_set_i2s_clk_source(void)
+int exynos5_set_i2s_clk_source(unsigned int i2s_id)
{
struct exynos5_clock *clk =
(struct exynos5_clock *)samsung_get_base_clock();
-
- clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
- (CLK_SRC_SCLK_EPLL));
+ unsigned int *audio_ass = (unsigned int *)samsung_get_base_audio_ass();
+
+ if (i2s_id == 0) {
+ setbits_le32(&clk->src_top2, CLK_SRC_MOUT_EPLL);
+ clrsetbits_le32(&clk->src_mau, AUDIO0_SEL_MASK,
+ (CLK_SRC_SCLK_EPLL));
+ setbits_le32(audio_ass, AUDIO_CLKMUX_ASS);
+ } else if (i2s_id == 1) {
+ clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
+ (CLK_SRC_SCLK_EPLL));
+ } else {
+ return -1;
+ }
+ return 0;
}
int exynos5_set_i2s_clk_prescaler(unsigned int src_frq,
- unsigned int dst_frq)
+ unsigned int dst_frq,
+ unsigned int i2s_id)
{
struct exynos5_clock *clk =
(struct exynos5_clock *)samsung_get_base_clock();
@@ -1169,13 +1184,27 @@ int exynos5_set_i2s_clk_prescaler(unsigned int src_frq,
}
div = (src_frq / dst_frq);
- if (div > AUDIO_1_RATIO_MASK) {
- debug("%s: Frequency ratio is out of range\n", __func__);
- debug("src frq = %d des frq = %d ", src_frq, dst_frq);
+ if (i2s_id == 0) {
+ if (div > AUDIO_0_RATIO_MASK) {
+ debug("%s: Frequency ratio is out of range\n",
+ __func__);
+ debug("src frq = %d des frq = %d ", src_frq, dst_frq);
+ return -1;
+ }
+ clrsetbits_le32(&clk->div_mau, AUDIO_0_RATIO_MASK,
+ (div & AUDIO_0_RATIO_MASK));
+ } else if(i2s_id == 1) {
+ if (div > AUDIO_1_RATIO_MASK) {
+ debug("%s: Frequency ratio is out of range\n",
+ __func__);
+ debug("src frq = %d des frq = %d ", src_frq, dst_frq);
+ return -1;
+ }
+ clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK,
+ (div & AUDIO_1_RATIO_MASK));
+ } else {
return -1;
}
- clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK,
- (div & AUDIO_1_RATIO_MASK));
return 0;
}
@@ -1415,19 +1444,21 @@ int set_spi_clk(int periph_id, unsigned int rate)
return 0;
}
-int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq)
+int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq,
+ unsigned int i2s_id)
{
-
if (cpu_is_exynos5())
- return exynos5_set_i2s_clk_prescaler(src_frq, dst_frq);
+ return exynos5_set_i2s_clk_prescaler(src_frq, dst_frq, i2s_id);
else
return 0;
}
-void set_i2s_clk_source(void)
+int set_i2s_clk_source(unsigned int i2s_id)
{
if (cpu_is_exynos5())
- exynos5_set_i2s_clk_source();
+ return exynos5_set_i2s_clk_source(i2s_id);
+ else
+ return 0;
}
int set_epll_clk(unsigned long rate)
diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c
index 1b05ebf..8002bce 100644
--- a/arch/arm/cpu/armv7/exynos/pinmux.c
+++ b/arch/arm/cpu/armv7/exynos/pinmux.c
@@ -220,10 +220,20 @@ static void exynos5_i2s_config(int peripheral)
{
int i;
struct exynos5_gpio_part1 *gpio1 =
- (struct exynos5_gpio_part1 *) samsung_get_base_gpio_part1();
+ (struct exynos5_gpio_part1 *)samsung_get_base_gpio_part1();
+ struct exynos5_gpio_part4 *gpio4 =
+ (struct exynos5_gpio_part4 *)samsung_get_base_gpio_part4();
- for (i = 0; i < 5; i++)
- s5p_gpio_cfg_pin(&gpio1->b0, i, GPIO_FUNC(0x02));
+ switch (peripheral) {
+ case PERIPH_ID_I2S0:
+ for (i = 0; i < 5; i++)
+ s5p_gpio_cfg_pin(&gpio4->z, i, GPIO_FUNC(0x02));
+ break;
+ case PERIPH_ID_I2S1:
+ for (i = 0; i < 5; i++)
+ s5p_gpio_cfg_pin(&gpio1->b0, i, GPIO_FUNC(0x02));
+ break;
+ }
}
void exynos5_spi_config(int peripheral)
@@ -296,6 +306,7 @@ static int exynos5_pinmux_config(int peripheral, int flags)
case PERIPH_ID_I2C7:
exynos5_i2c_config(peripheral, flags);
break;
+ case PERIPH_ID_I2S0:
case PERIPH_ID_I2S1:
exynos5_i2s_config(peripheral);
break;
@@ -463,11 +474,11 @@ static int exynos4_pinmux_config(int peripheral, int flags)
int exynos_pinmux_config(int peripheral, int flags)
{
- if (cpu_is_exynos5())
+ if (cpu_is_exynos5()) {
return exynos5_pinmux_config(peripheral, flags);
- else if (cpu_is_exynos4())
+ } else if (cpu_is_exynos4()) {
return exynos4_pinmux_config(peripheral, flags);
- else {
+ } else {
debug("pinmux functionality not supported\n");
return -1;
}
diff --git a/arch/arm/include/asm/arch-exynos/clk.h b/arch/arm/include/asm/arch-exynos/clk.h
index 71075bd..1d6fa93 100644
--- a/arch/arm/include/asm/arch-exynos/clk.h
+++ b/arch/arm/include/asm/arch-exynos/clk.h
@@ -31,8 +31,9 @@ void set_mmc_clk(int dev_index, unsigned int div);
unsigned long get_lcd_clk(void);
void set_lcd_clk(void);
void set_mipi_clk(void);
-void set_i2s_clk_source(void);
-int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq);
+int set_i2s_clk_source(unsigned int i2s_id);
+int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq,
+ unsigned int i2s_id);
int set_epll_clk(unsigned long rate);
int set_spi_clk(int periph_id, unsigned int rate);
diff --git a/arch/arm/include/asm/arch-exynos/clock.h b/arch/arm/include/asm/arch-exynos/clock.h
index 2b97b9a..cf26eef 100644
--- a/arch/arm/include/asm/arch-exynos/clock.h
+++ b/arch/arm/include/asm/arch-exynos/clock.h
@@ -876,8 +876,12 @@ struct set_epll_con_val {
#define AUDIO_0_RATIO_MASK 0x0f
#define AUDIO_1_RATIO_MASK 0x0f
+#define AUDIO0_SEL_MASK 0xf
#define AUDIO1_SEL_MASK 0xf
+
#define CLK_SRC_SCLK_EPLL 0x7
+#define CLK_SRC_MOUT_EPLL (1<<12)
+#define AUDIO_CLKMUX_ASS (1<<0)
/* CON0 bit-fields */
#define EPLL_CON0_MDIV_MASK 0x1ff
diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h
index cb924fb..4b67191 100644
--- a/arch/arm/include/asm/arch-exynos/cpu.h
+++ b/arch/arm/include/asm/arch-exynos/cpu.h
@@ -50,6 +50,7 @@
#define EXYNOS4_SPI_ISP_BASE DEVICE_NOT_AVAILABLE
#define EXYNOS4_ACE_SFR_BASE DEVICE_NOT_AVAILABLE
#define EXYNOS4_DMC_PHY_BASE DEVICE_NOT_AVAILABLE
+#define EXYNOS4_AUDIOSS_BASE DEVICE_NOT_AVAILABLE
/* EXYNOS4X12 */
#define EXYNOS4X12_GPIO_PART3_BASE 0x03860000
@@ -85,10 +86,12 @@
#define EXYNOS4X12_SPI_ISP_BASE DEVICE_NOT_AVAILABLE
#define EXYNOS4X12_ACE_SFR_BASE DEVICE_NOT_AVAILABLE
#define EXYNOS4X12_DMC_PHY_BASE DEVICE_NOT_AVAILABLE
+#define EXYNOS4X12_AUDIOSS_BASE DEVICE_NOT_AVAILABLE
/* EXYNOS5 Common*/
#define EXYNOS5_I2C_SPACING 0x10000
+#define EXYNOS5_AUDIOSS_BASE 0x03810000
#define EXYNOS5_GPIO_PART4_BASE 0x03860000
#define EXYNOS5_PRO_ID 0x10000000
#define EXYNOS5_CLOCK_BASE 0x10010000
@@ -226,6 +229,7 @@ SAMSUNG_BASE(spi_isp, SPI_ISP_BASE)
SAMSUNG_BASE(tzpc, TZPC_BASE)
SAMSUNG_BASE(dmc_ctrl, DMC_CTRL_BASE)
SAMSUNG_BASE(dmc_phy, DMC_PHY_BASE)
+SAMSUNG_BASE(audio_ass, AUDIOSS_BASE)
#endif
#endif /* _EXYNOS4_CPU_H */
diff --git a/arch/arm/include/asm/arch-exynos/periph.h b/arch/arm/include/asm/arch-exynos/periph.h
index 9952155..64bd8b7 100644
--- a/arch/arm/include/asm/arch-exynos/periph.h
+++ b/arch/arm/include/asm/arch-exynos/periph.h
@@ -34,6 +34,7 @@ enum periph_id {
PERIPH_ID_SDMMC1,
PERIPH_ID_SDMMC2,
PERIPH_ID_SDMMC3,
+ PERIPH_ID_I2S0 = 98,
PERIPH_ID_I2S1 = 99,
/* Since following peripherals do
diff --git a/drivers/sound/samsung-i2s.c b/drivers/sound/samsung-i2s.c
index 49921e5..30d1470 100644
--- a/drivers/sound/samsung-i2s.c
+++ b/drivers/sound/samsung-i2s.c
@@ -67,7 +67,6 @@ static void i2s_txctrl(struct i2s_reg *i2s_reg, int on)
con &= ~CON_TXCH_PAUSE;
} else {
-
con |= CON_TXCH_PAUSE;
con &= ~CON_ACTIVE;
}
@@ -172,7 +171,7 @@ int i2s_set_fmt(struct i2s_reg *i2s_reg, unsigned int fmt)
break;
default:
debug("%s: Invalid format priority [0x%x]\n", __func__,
- (fmt & SND_SOC_DAIFMT_FORMAT_MASK));
+ (fmt & SND_SOC_DAIFMT_FORMAT_MASK));
return -1;
}
@@ -191,7 +190,7 @@ int i2s_set_fmt(struct i2s_reg *i2s_reg, unsigned int fmt)
break;
default:
debug("%s: Invalid clock ploarity input [0x%x]\n", __func__,
- (fmt & SND_SOC_DAIFMT_INV_MASK));
+ (fmt & SND_SOC_DAIFMT_INV_MASK));
return -1;
}
@@ -209,7 +208,7 @@ int i2s_set_fmt(struct i2s_reg *i2s_reg, unsigned int fmt)
break;
default:
debug("%s: Invalid master selection [0x%x]\n", __func__,
- (fmt & SND_SOC_DAIFMT_MASTER_MASK));
+ (fmt & SND_SOC_DAIFMT_MASTER_MASK));
return -1;
}
@@ -250,7 +249,7 @@ int i2s_set_samplesize(struct i2s_reg *i2s_reg, unsigned int blc)
break;
default:
debug("%s: Invalid sample size input [0x%x]\n",
- __func__, blc);
+ __func__, blc);
return -1;
}
writel(mod, &i2s_reg->mod);
@@ -313,11 +312,22 @@ int i2s_tx_init(struct i2stx_info *pi2s_tx)
}
/* Select Clk Source for Audio1 */
- set_i2s_clk_source();
+ ret = set_i2s_clk_source(pi2s_tx->id);
+ if (ret == -1) {
+ debug("%s: unsupported clock for i2s-%d\n", __func__,
+ pi2s_tx->id);
+ return -1;
+ }
/* Set Prescaler to get MCLK */
- set_i2s_clk_prescaler(pi2s_tx->audio_pll_clk,
- (pi2s_tx->samplingrate * (pi2s_tx->rfs)));
+ ret = set_i2s_clk_prescaler(pi2s_tx->audio_pll_clk,
+ (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
+ pi2s_tx->id);
+ if (ret == -1) {
+ debug("%s: unsupported prescalar for i2s-%d\n", __func__,
+ pi2s_tx->id);
+ return -1;
+ }
/* Configure I2s format */
ret = i2s_set_fmt(i2s_reg, (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |