ASoC: Include header file in cs4270 and wm9705
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / sound / soc / codecs / cs4270.c
index 0bbd94501d7ea45f1aa8b491bf43d275ffb779c9..e2130d7b1e41b270cc1809d1fda77333e7c4ec01 100644 (file)
  *
  * Current features/limitations:
  *
- * 1) Software mode is supported.  Stand-alone mode is automatically
- *    selected if I2C is disabled or if a CS4270 is not found on the I2C
- *    bus.  However, stand-alone mode is only partially implemented because
- *    there is no mechanism yet for this driver and the machine driver to
- *    communicate the values of the M0, M1, MCLK1, and MCLK2 pins.
+ * 1) Software mode is supported.  Stand-alone mode is not supported.
  * 2) Only I2C is supported, not SPI
  * 3) Only Master mode is supported, not Slave.
  * 4) The machine driver's 'startup' function must call
 
 #include "cs4270.h"
 
-/* If I2C is defined, then we support software mode.  However, if we're
-   not compiled as module but I2C is, then we can't use I2C calls. */
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-#define USE_I2C
-#endif
-
 /* Private data for the CS4270 */
 struct cs4270_private {
        unsigned int mclk; /* Input frequency of the MCLK pin */
@@ -60,8 +50,6 @@ struct cs4270_private {
                        SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \
                        SNDRV_PCM_FMTBIT_S24_LE  | SNDRV_PCM_FMTBIT_S24_BE)
 
-#ifdef USE_I2C
-
 /* CS4270 registers addresses */
 #define CS4270_CHIPID  0x01    /* Chip ID */
 #define CS4270_PWRCTL  0x02    /* Power Control */
@@ -271,17 +259,6 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai,
        return ret;
 }
 
-/*
- * A list of addresses on which this CS4270 could use.  I2C addresses are
- * 7 bits.  For the CS4270, the upper four bits are always 1001, and the
- * lower three bits are determined via the AD2, AD1, and AD0 pins
- * (respectively).
- */
-static const unsigned short normal_i2c[] = {
-       0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, I2C_CLIENT_END
-};
-I2C_CLIENT_INSMOD;
-
 /*
  * Pre-fill the CS4270 register cache.
  *
@@ -360,13 +337,14 @@ static int cs4270_i2c_write(struct snd_soc_codec *codec, unsigned int reg,
 /*
  * Program the CS4270 with the given hardware parameters.
  *
- * The .dai_ops functions are used to provide board-specific data, like
+ * The .ops functions are used to provide board-specific data, like
  * input frequencies, to this driver.  This function takes that information,
  * combines it with the hardware parameters provided, and programs the
  * hardware accordingly.
  */
 static int cs4270_hw_params(struct snd_pcm_substream *substream,
-                           struct snd_pcm_hw_params *params)
+                           struct snd_pcm_hw_params *params,
+                           struct snd_soc_dai *dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_device *socdev = rtd->socdev;
@@ -450,6 +428,19 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
                return ret;
        }
 
+       /* Disable automatic volume control.  It's enabled by default, and
+        * it causes volume change commands to be delayed, sometimes until
+        * after playback has started.
+        */
+
+       reg = cs4270_read_reg_cache(codec, CS4270_TRANS);
+       reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO);
+       ret = cs4270_i2c_write(codec, CS4270_TRANS, reg);
+       if (ret < 0) {
+               printk(KERN_ERR "I2C write failed\n");
+               return ret;
+       }
+
        /* Thaw and power-up the codec */
 
        ret = snd_soc_write(codec, CS4270_PWRCTL, 0);
@@ -462,7 +453,6 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
 }
 
 #ifdef CONFIG_SND_SOC_CS4270_HWMUTE
-
 /*
  * Set the CS4270 external mute
  *
@@ -487,32 +477,16 @@ static int cs4270_mute(struct snd_soc_dai *dai, int mute)
 
        return snd_soc_write(codec, CS4270_MUTE, reg6);
 }
-
+#else
+#define cs4270_mute NULL
 #endif
 
-static int cs4270_i2c_probe(struct i2c_client *, const struct i2c_device_id *);
-
 /* A list of non-DAPM controls that the CS4270 supports */
 static const struct snd_kcontrol_new cs4270_snd_controls[] = {
        SOC_DOUBLE_R("Master Playback Volume",
                CS4270_VOLA, CS4270_VOLB, 0, 0xFF, 1)
 };
 
-static const struct i2c_device_id cs4270_id[] = {
-       {"cs4270", 0},
-       {}
-};
-MODULE_DEVICE_TABLE(i2c, cs4270_id);
-
-static struct i2c_driver cs4270_i2c_driver = {
-       .driver = {
-               .name = "CS4270 I2C",
-               .owner = THIS_MODULE,
-       },
-       .id_table = cs4270_id,
-       .probe = cs4270_i2c_probe,
-};
-
 /*
  * Global variable to store socdev for i2c probe function.
  *
@@ -619,7 +593,20 @@ error:
        return ret;
 }
 
-#endif /* USE_I2C*/
+static const struct i2c_device_id cs4270_id[] = {
+       {"cs4270", 0},
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, cs4270_id);
+
+static struct i2c_driver cs4270_i2c_driver = {
+       .driver = {
+               .name = "cs4270",
+               .owner = THIS_MODULE,
+       },
+       .id_table = cs4270_id,
+       .probe = cs4270_i2c_probe,
+};
 
 struct snd_soc_dai cs4270_dai = {
        .name = "CS4270",
@@ -684,7 +671,6 @@ static int cs4270_probe(struct platform_device *pdev)
                goto error_free_codec;
        }
 
-#ifdef USE_I2C
        cs4270_socdev = socdev;
 
        ret = i2c_add_driver(&cs4270_i2c_driver);
@@ -694,22 +680,18 @@ static int cs4270_probe(struct platform_device *pdev)
        }
 
        /* Did we find a CS4270 on the I2C bus? */
-       if (codec->control_data) {
-               /* Initialize codec ops */
-               cs4270_dai.ops.hw_params = cs4270_hw_params;
-               cs4270_dai.dai_ops.set_sysclk = cs4270_set_dai_sysclk;
-               cs4270_dai.dai_ops.set_fmt = cs4270_set_dai_fmt;
-#ifdef CONFIG_SND_SOC_CS4270_HWMUTE
-               cs4270_dai.dai_ops.digital_mute = cs4270_mute;
-#endif
-       } else
-               printk(KERN_INFO "cs4270: no I2C device found, "
-                       "using stand-alone mode\n");
-#else
-       printk(KERN_INFO "cs4270: I2C disabled, using stand-alone mode\n");
-#endif
+       if (!codec->control_data) {
+               printk(KERN_ERR "cs4270: failed to attach driver");
+               goto error_del_driver;
+       }
+
+       /* Initialize codec ops */
+       cs4270_dai.ops.hw_params = cs4270_hw_params;
+       cs4270_dai.ops.set_sysclk = cs4270_set_dai_sysclk;
+       cs4270_dai.ops.set_fmt = cs4270_set_dai_fmt;
+       cs4270_dai.ops.digital_mute = cs4270_mute;
 
-       ret = snd_soc_register_card(socdev);
+       ret = snd_soc_init_card(socdev);
        if (ret < 0) {
                printk(KERN_ERR "cs4270: failed to register card\n");
                goto error_del_driver;
@@ -718,11 +700,9 @@ static int cs4270_probe(struct platform_device *pdev)
        return 0;
 
 error_del_driver:
-#ifdef USE_I2C
        i2c_del_driver(&cs4270_i2c_driver);
 
 error_free_pcms:
-#endif
        snd_soc_free_pcms(socdev);
 
 error_free_codec:
@@ -738,9 +718,7 @@ static int cs4270_remove(struct platform_device *pdev)
 
        snd_soc_free_pcms(socdev);
 
-#ifdef USE_I2C
        i2c_del_driver(&cs4270_i2c_driver);
-#endif
 
        kfree(socdev->codec);
        socdev->codec = NULL;
@@ -760,6 +738,18 @@ struct snd_soc_codec_device soc_codec_device_cs4270 = {
 };
 EXPORT_SYMBOL_GPL(soc_codec_device_cs4270);
 
+static int __init cs4270_init(void)
+{
+       return snd_soc_register_dai(&cs4270_dai);
+}
+module_init(cs4270_init);
+
+static void __exit cs4270_exit(void)
+{
+       snd_soc_unregister_dai(&cs4270_dai);
+}
+module_exit(cs4270_exit);
+
 MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
 MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver");
 MODULE_LICENSE("GPL");