Merge branch 'topic/oxygen' into for-linus
[sfrench/cifs-2.6.git] / sound / soc / s3c24xx / s3c-i2s-v2.c
index aeea49cbe74a4f8d5a361910da6b13de806b8b2c..1a283170ca92d80e00394f3cbc7cb6d01ebafc98 100644 (file)
 
 #include "s3c-i2s-v2.h"
 
+#undef S3C_IIS_V2_SUPPORTED
+
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+#define S3C_IIS_V2_SUPPORTED
+#endif
+
+#ifdef CONFIG_PLAT_S3C64XX
+#define S3C_IIS_V2_SUPPORTED
+#endif
+
+#ifndef S3C_IIS_V2_SUPPORTED
+#error Unsupported CPU model
+#endif
+
 #define S3C2412_I2S_DEBUG_CON 0
 
 static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
@@ -75,7 +89,7 @@ static inline void dbg_showcon(const char *fn, u32 con)
 
 
 /* Turn on or off the transmission path. */
-void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
+static void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
 {
        void __iomem *regs = i2s->regs;
        u32 fic, con, mod;
@@ -134,7 +148,7 @@ void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
                        break;
 
                default:
-                       dev_err(i2s->dev, "TXDIS: Invalid MODE %xin IISMOD\n",
+                       dev_err(i2s->dev, "TXDIS: Invalid MODE %x in IISMOD\n",
                                mod & S3C2412_IISMOD_MODE_MASK);
                        break;
                }
@@ -147,9 +161,8 @@ void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
        dbg_showcon(__func__, con);
        pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
 }
-EXPORT_SYMBOL_GPL(s3c2412_snd_txctrl);
 
-void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
+static void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
 {
        void __iomem *regs = i2s->regs;
        u32 fic, con, mod;
@@ -204,7 +217,7 @@ void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
                        break;
 
                default:
-                       dev_err(i2s->dev, "RXEN: Invalid MODE %x in IISMOD\n",
+                       dev_err(i2s->dev, "RXDIS: Invalid MODE %x in IISMOD\n",
                                mod & S3C2412_IISMOD_MODE_MASK);
                }
 
@@ -215,7 +228,6 @@ void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
        fic = readl(regs + S3C2412_IISFIC);
        pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
 }
-EXPORT_SYMBOL_GPL(s3c2412_snd_rxctrl);
 
 /*
  * Wait for the LR signal to allow synchronisation to the L/R clock
@@ -272,7 +284,7 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
  */
 #define IISMOD_MASTER_MASK (1 << 11)
 #define IISMOD_SLAVE (1 << 11)
-#define IISMOD_MASTER (0x0)
+#define IISMOD_MASTER (0 << 11)
 #endif
 
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -333,6 +345,7 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
        iismod = readl(i2s->regs + S3C2412_IISMOD);
        pr_debug("%s: r: IISMOD: %x\n", __func__, iismod);
 
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S8:
                iismod |= S3C2412_IISMOD_8BIT;
@@ -341,6 +354,25 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
                iismod &= ~S3C2412_IISMOD_8BIT;
                break;
        }
+#endif
+
+#ifdef CONFIG_PLAT_S3C64XX
+       iismod &= ~0x606;
+       /* Sample size */
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S8:
+               /* 8 bit sample, 16fs BCLK */
+               iismod |= 0x2004;
+               break;
+       case SNDRV_PCM_FORMAT_S16_LE:
+               /* 16 bit sample, 32fs BCLK */
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               /* 24 bit sample, 48fs BCLK */
+               iismod |= 0x4002;
+               break;
+       }
+#endif
 
        writel(iismod, i2s->regs + S3C2412_IISMOD);
        pr_debug("%s: w: IISMOD: %x\n", __func__, iismod);
@@ -495,6 +527,8 @@ int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
        unsigned int best_rate = 0;
        unsigned int best_deviation = INT_MAX;
 
+       pr_debug("Input clock rate %ldHz\n", clkrate);
+
        if (fstab == NULL)
                fstab = iis_fs_tab;
 
@@ -513,7 +547,7 @@ int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
                actual = clkrate / (fsdiv * div);
                deviation = actual - rate;
 
-               printk(KERN_DEBUG "%dfs: div %d => result %d, deviation %d\n",
+               printk(KERN_DEBUG "%ufs: div %u => result %u, deviation %d\n",
                       fsdiv, div, actual, deviation);
 
                deviation = abs(deviation);
@@ -529,7 +563,7 @@ int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
                        break;
        }
 
-       printk(KERN_DEBUG "best: fs=%d, div=%d, rate=%d\n",
+       printk(KERN_DEBUG "best: fs=%u, div=%u, rate=%u\n",
               best_fs, best_div, best_rate);
 
        info->fs_div = best_fs;
@@ -545,12 +579,31 @@ int s3c_i2sv2_probe(struct platform_device *pdev,
                    unsigned long base)
 {
        struct device *dev = &pdev->dev;
+       unsigned int iismod;
 
        i2s->dev = dev;
 
        /* record our i2s structure for later use in the callbacks */
        dai->private_data = i2s;
 
+       if (!base) {
+               struct resource *res = platform_get_resource(pdev,
+                                                            IORESOURCE_MEM,
+                                                            0);
+               if (!res) {
+                       dev_err(dev, "Unable to get register resource\n");
+                       return -ENXIO;
+               }
+
+               if (!request_mem_region(res->start, resource_size(res),
+                                       "s3c64xx-i2s-v4")) {
+                       dev_err(dev, "Unable to request register region\n");
+                       return -EBUSY;
+               }
+
+               base = res->start;
+       }
+
        i2s->regs = ioremap(base, 0x100);
        if (i2s->regs == NULL) {
                dev_err(dev, "cannot ioremap registers\n");
@@ -566,12 +619,16 @@ int s3c_i2sv2_probe(struct platform_device *pdev,
 
        clk_enable(i2s->iis_pclk);
 
+       /* Mark ourselves as in TXRX mode so we can run through our cleanup
+        * process without warnings. */
+       iismod = readl(i2s->regs + S3C2412_IISMOD);
+       iismod |= S3C2412_IISMOD_MODE_TXRX;
+       writel(iismod, i2s->regs + S3C2412_IISMOD);
        s3c2412_snd_txctrl(i2s, 0);
        s3c2412_snd_rxctrl(i2s, 0);
 
        return 0;
 }
-
 EXPORT_SYMBOL_GPL(s3c_i2sv2_probe);
 
 #ifdef CONFIG_PM