ARM: Added I2S0 clocks for audio
authorDani Krishna Mohan <krishna.md@samsung.com>
Wed, 11 Sep 2013 11:08:48 +0000 (16:38 +0530)
committerTom Rini <trini@ti.com>
Tue, 24 Sep 2013 13:10:33 +0000 (09:10 -0400)
This patch makes the necessary changes for making use of
I2S0 channel instead of I2S1 channel on smdk board. This
changes are done to maintain the uniformity to use I2S0 channel.

Signed-off-by: Dani Krishna Mohan <krishna.md@samsung.com>
arch/arm/cpu/armv7/exynos/clock.c
arch/arm/cpu/armv7/exynos/pinmux.c
arch/arm/include/asm/arch-exynos/clk.h
arch/arm/include/asm/arch-exynos/clock.h
arch/arm/include/asm/arch-exynos/cpu.h
arch/arm/include/asm/arch-exynos/periph.h
drivers/sound/samsung-i2s.c

index 0cb1a61aa1a0bf49e65cbe98cb8168ec946e4032..36fedd630cde8e924df129bedfb72397f9fd9b11 100644 (file)
@@ -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)
index 1b05ebfd7ae9b3cb9a4aca0da1846223cc6d10d9..8002bce79c4e1c7546db53a08d3441b13ed36808 100644 (file)
@@ -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;
        }
index 71075bd5331ca6d07f72ee46010abdb4ab63f754..1d6fa9370fdd2bef94eb6e7306b7d427679506b0 100644 (file)
@@ -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);
 
index 2b97b9a042801f99d79e4dcec4420a5de1e94871..cf26eeffcfe4bf08deb8bbfadabd490c5a87f607 100644 (file)
@@ -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
index cb924fba8b09e4ede5facab1755bf71a249bd949..4b67191c07e214d25de6bcbe42ab31ff1ae0ed4e 100644 (file)
@@ -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
 #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 */
index 9952155986767dbdb15a03d09b14141c2aa26044..64bd8b7c91d1588d37a7bdb3d3a582fab5345fe5 100644 (file)
@@ -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
index 49921e55266faeaf70277f8d568fe7807c3938c0..30d1470102c29c4821d20bbd18c075ccc1d75e66 100644 (file)
@@ -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 |