Add sound card 1 for HDMI i2s, RK616 codec:add path for tiny alsa
author陈金泉 <chenjq@rock-chips.com>
Fri, 21 Jun 2013 02:21:21 +0000 (10:21 +0800)
committer陈金泉 <chenjq@rock-chips.com>
Fri, 21 Jun 2013 02:21:21 +0000 (10:21 +0800)
18 files changed:
arch/arm/configs/rk3168m_tb_defconfig
arch/arm/configs/rk3188_jettaplus_defconfig
arch/arm/configs/rk3188m_tb_defconfig
drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.h
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/hdmi_i2s.c [new file with mode: 0644]
sound/soc/codecs/hdmi_spdif.c [new file with mode: 0644]
sound/soc/codecs/rk616_codec.c
sound/soc/codecs/rk616_codec.h
sound/soc/codecs/spdif_transciever.c [deleted file]
sound/soc/rk29/Kconfig
sound/soc/rk29/Makefile
sound/soc/rk29/rk_hdmi_i2s.c [new file with mode: 0644]
sound/soc/rk29/rk_hdmi_spdif.c [new file with mode: 0644]
sound/soc/rk29/rk_spdif.c
sound/soc/rk29/spdif.c [deleted file]
sound/soc/rk29/spdif.h [deleted file]

index 9e64d950b02b600cf80c5f5b6f306a76e3e94768..7e1c2603b2f652c609a8bb93271768a508178130 100644 (file)
@@ -327,7 +327,8 @@ CONFIG_SND_SOC=y
 CONFIG_SND_RK29_SOC=y
 CONFIG_SND_I2S_USE_33V=y
 CONFIG_SND_I2S_DMA_EVENT_STATIC=y
-CONFIG_SND_RK29_SOC_RK616=y
+CONFIG_SND_RK_SOC_HDMI_I2S=y
+CONFIG_SND_RK_SOC_RK616=y
 CONFIG_SND_RK29_CODEC_SOC_SLAVE=y
 CONFIG_UHID=y
 CONFIG_HID_A4TECH=y
index 2d37e9eb75ce90f98a11023922099719ad90714a..469c9ca9fdedfd0c37d48e65ace457f98a5c5a9d 100644 (file)
@@ -327,8 +327,8 @@ CONFIG_SND=y
 CONFIG_SND_SOC=y
 CONFIG_SND_RK29_SOC=y
 CONFIG_SND_I2S_DMA_EVENT_DYNAMIC=y
-CONFIG_SND_RK_SOC_SPDIF=y
-CONFIG_SND_RK29_SOC_RK616=y
+CONFIG_SND_RK_SOC_HDMI_I2S=y
+CONFIG_SND_RK_SOC_RK616=y
 CONFIG_SND_RK29_CODEC_SOC_SLAVE=y
 CONFIG_UHID=y
 CONFIG_HID_A4TECH=y
index b1f657bd2c78783917dc8f8470d11cf2ede086e9..c32e63319d10d2e388034ed6aadaa905fa33d2b9 100644 (file)
@@ -326,7 +326,8 @@ CONFIG_SND=y
 CONFIG_SND_SOC=y
 CONFIG_SND_RK29_SOC=y
 CONFIG_SND_I2S_DMA_EVENT_STATIC=y
-CONFIG_SND_RK29_SOC_RK616=y
+CONFIG_SND_RK_SOC_HDMI_I2S=y
+CONFIG_SND_RK_SOC_RK616=y
 CONFIG_SND_RK29_CODEC_SOC_SLAVE=y
 CONFIG_UHID=y
 CONFIG_HID_A4TECH=y
index 97362b4bbf758364ff28208fe9eb4533a6957814..7fcd7f6da6f9fd088d46956f4d092fd4822d0301 100755 (executable)
@@ -13,7 +13,12 @@ enum{
        INPUT_IIS,
        INPUT_SPDIF
 };
+
+#if defined(CONFIG_SND_RK_SOC_HDMI_SPDIF)
+#define HDMI_CODEC_SOURCE_SELECT INPUT_SPDIF
+#else
 #define HDMI_CODEC_SOURCE_SELECT INPUT_IIS
+#endif
 
 extern void rk616_hdmi_control_output(int enable);
 extern int rk616_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
index 3889aff2bd7f682f84f76ec4371bd3b46d6015ee..04e27b2582a0375f1814536e81c631b42477c816 100755 (executable)
@@ -42,7 +42,8 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_PCM3008
        select SND_SOC_SGTL5000 if I2C
        select SND_SOC_SN95031 if INTEL_SCU_IPC
-       select SND_SOC_SPDIF
+       select SND_SOC_HDMI_I2S
+       select SND_SOC_HDMI_SPDIF
        select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI
        select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
        select SND_SOC_TLV320AIC23 if I2C
@@ -230,7 +231,10 @@ config SND_SOC_SGTL5000
 config SND_SOC_SN95031
        tristate
 
-config SND_SOC_SPDIF
+config SND_SOC_HDMI_I2S
+       tristate
+
+config SND_SOC_HDMI_SPDIF
        tristate
 
 config SND_SOC_SSM2602
index 62292a90224e59420c6c8128f5fec49c8da8a20d..813ae0a4752280bbf5bf41738524b20709c2b79c 100755 (executable)
@@ -27,7 +27,8 @@ snd-soc-pcm3008-objs := pcm3008.o
 snd-soc-sgtl5000-objs := sgtl5000.o
 snd-soc-alc5623-objs := alc5623.o
 snd-soc-sn95031-objs := sn95031.o
-snd-soc-spdif-objs := spdif_transciever.o
+snd-soc-hdmi-i2s-objs := hdmi_i2s.o
+snd-soc-hdmi-spdif-objs := hdmi_spdif.o
 snd-soc-ssm2602-objs := ssm2602.o
 snd-soc-stac9766-objs := stac9766.o
 snd-soc-tlv320aic23-objs := tlv320aic23.o
@@ -140,7 +141,8 @@ obj-$(CONFIG_SND_SOC_MAX9850)       += snd-soc-max9850.o
 obj-$(CONFIG_SND_SOC_PCM3008)  += snd-soc-pcm3008.o
 obj-$(CONFIG_SND_SOC_SGTL5000)  += snd-soc-sgtl5000.o
 obj-$(CONFIG_SND_SOC_SN95031)  +=snd-soc-sn95031.o
-obj-$(CONFIG_SND_SOC_SPDIF)    += snd-soc-spdif.o
+obj-$(CONFIG_SND_SOC_HDMI_I2S) += snd-soc-hdmi-i2s.o
+obj-$(CONFIG_SND_SOC_HDMI_SPDIF)       += snd-soc-hdmi-spdif.o
 obj-$(CONFIG_SND_SOC_SSM2602)  += snd-soc-ssm2602.o
 obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)      += snd-soc-tlv320aic23.o
diff --git a/sound/soc/codecs/hdmi_i2s.c b/sound/soc/codecs/hdmi_i2s.c
new file mode 100644 (file)
index 0000000..c923d65
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * hdmi_i2s.c  --  HDMI i2s audio for rockchip
+ *
+ * Copyright 2013 Rockship
+ * Author: chenjq <chenjq@rock-chips.com>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/version.h>
+
+#include <asm/dma.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <asm/io.h>
+
+#include <mach/board.h>
+#include <mach/hardware.h>
+#include <mach/io.h>
+#include <mach/gpio.h>
+#include <mach/iomux.h>
+
+#if 0
+#define DBG(x...) printk(KERN_INFO "hdmi i2s:"x)
+#else
+#define DBG(x...) do { } while (0)
+#endif
+
+struct snd_soc_dai_driver hdmi_i2s_dai = {
+       .name = "rk-hdmi-i2s-hifi",
+       .playback = {
+               .stream_name = "HiFi Playback",
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = (SNDRV_PCM_RATE_32000 |
+                       SNDRV_PCM_RATE_44100 |
+                       SNDRV_PCM_RATE_48000 |
+                       SNDRV_PCM_RATE_96000),
+               .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S20_3LE |
+                       SNDRV_PCM_FMTBIT_S24_LE),
+       },
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_hdmi_i2s;
+
+static int hdmi_i2s_platform_probe(struct platform_device *pdev)
+{
+       DBG("Entered %s\n", __func__);
+
+       return snd_soc_register_codec(&pdev->dev,
+               &soc_codec_dev_hdmi_i2s,
+               &hdmi_i2s_dai, 1);
+}
+
+static int hdmi_i2s_platform_remove(struct platform_device *pdev)
+{
+       DBG("Entered %s\n", __func__);
+
+       snd_soc_unregister_codec(&pdev->dev);
+
+       return 0;
+}
+
+
+static struct platform_driver hdmi_i2s_driver = {
+       .probe = hdmi_i2s_platform_probe,
+       .remove = hdmi_i2s_platform_remove,
+       .driver = {
+               .name   = "hdmi-i2s",
+               .owner  = THIS_MODULE,
+       },
+};
+
+
+static int __init hdmi_i2s_init(void)
+{
+       DBG("Entered %s\n", __func__);
+
+       return platform_driver_register(&hdmi_i2s_driver);
+}
+
+static void __exit hdmi_i2s_exit(void)
+{
+       DBG("Entered %s\n", __func__);
+
+       platform_driver_unregister(&hdmi_i2s_driver);
+}
+module_init(hdmi_i2s_init);
+module_exit(hdmi_i2s_exit);
+
+MODULE_DESCRIPTION("HDMI I2S Controller Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:hdmi-i2s");
diff --git a/sound/soc/codecs/hdmi_spdif.c b/sound/soc/codecs/hdmi_spdif.c
new file mode 100644 (file)
index 0000000..6a1a7e7
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * ALSA SoC SPDIF DIT driver
+ *
+ *  This driver is used by controllers which can operate in DIT (SPDI/F) where
+ *  no codec is needed.  This file provides stub codec that can be used
+ *  in these configurations. TI DaVinci Audio controller uses this driver.
+ *
+ * Author:      Steve Chen,  <schen@mvista.com>
+ * Copyright:   (C) 2009 MontaVista Software, Inc., <source@mvista.com>
+ * Copyright:   (C) 2009  Texas Instruments, India
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <sound/soc.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+
+#define DRV_NAME "spdif-dit"
+
+#define STUB_RATES     SNDRV_PCM_RATE_8000_96000
+#define STUB_FORMATS   SNDRV_PCM_FMTBIT_S16_LE
+
+
+static struct snd_soc_codec_driver soc_codec_spdif_dit;
+
+static struct snd_soc_dai_driver dit_stub_dai = {
+       .name           = "dit-hifi",
+       .playback       = {
+               .stream_name    = "Playback",
+               .channels_min   = 1,
+               .channels_max   = 384,
+               .rates          = STUB_RATES,
+               .formats        = STUB_FORMATS,
+       },
+};
+
+static int spdif_dit_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_codec(&pdev->dev, &soc_codec_spdif_dit,
+                       &dit_stub_dai, 1);
+}
+
+static int spdif_dit_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_codec(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver spdif_dit_driver = {
+       .probe          = spdif_dit_probe,
+       .remove         = spdif_dit_remove,
+       .driver         = {
+               .name   = DRV_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init dit_modinit(void)
+{
+       return platform_driver_register(&spdif_dit_driver);
+}
+
+static void __exit dit_exit(void)
+{
+       platform_driver_unregister(&spdif_dit_driver);
+}
+
+module_init(dit_modinit);
+module_exit(dit_exit);
+
+MODULE_AUTHOR("Steve Chen <schen@mvista.com>");
+MODULE_DESCRIPTION("SPDIF dummy codec driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
index 14ba97633fbf301b7ef0150ab6b6f6f494d114a4..67d90555717525168d04247390441000968051b6 100755 (executable)
@@ -63,6 +63,10 @@ struct rk616_codec_priv {
 
        int spk_ctl_gpio;
        int hp_ctl_gpio;
+
+       long int playback_path;
+       long int capture_path;
+       long int voice_call_path;
 };
 
 static struct rk616_codec_priv *rk616_priv = NULL;
@@ -899,6 +903,231 @@ static const struct snd_kcontrol_new rk616_snd_controls[] = {
        SOC_ENUM("I2S Loop Enable",  rk616_loop_enum),
 };
 
+//For tiny alsa playback/capture/voice call path
+static const char *rk616_playback_path_mode[] = {"OFF", "RCV", "SPK", "HP", "HP_NO_MIC", "BT", "SPK_HP", //0-6
+               "RING_SPK", "RING_HP", "RING_HP_NO_MIC", "RING_SPK_HP"};//7-10
+
+static const char *rk616_capture_path_mode[] = {"MIC OFF", "Main Mic", "Hands Free Mic", "BT Sco Mic"};
+
+static const char *rk616_voice_call_path_mode[] = {"OFF", "RCV", "SPK", "HP", "HP_NO_MIC", "BT"};//0-5
+
+static const SOC_ENUM_SINGLE_DECL(rk616_playback_path_type, 0, 0, rk616_playback_path_mode);
+
+static const SOC_ENUM_SINGLE_DECL(rk616_capture_path_type, 0, 0, rk616_capture_path_mode);
+
+static const SOC_ENUM_SINGLE_DECL(rk616_voice_call_path_type, 0, 0, rk616_voice_call_path_mode);
+
+static int rk616_playback_path_get(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       if (!rk616_priv) {
+               printk("%s : rk616_priv is NULL\n", __func__);
+               return -EINVAL;
+       }
+
+       DBG("%s : playback_path = %ld\n",__func__,ucontrol->value.integer.value[0]);
+
+       ucontrol->value.integer.value[0] = rk616_priv->playback_path;
+
+       return 0;
+}
+
+static int rk616_playback_path_put(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+       if (!rk616_priv) {
+               printk("%s : rk616_priv is NULL\n", __func__);
+               return -EINVAL;
+       }
+
+       if (rk616_priv->playback_path == ucontrol->value.integer.value[0]){
+               printk("%s : playback_path is not changed!\n",__func__);
+               //return 0;
+       }
+
+       rk616_priv->playback_path = ucontrol->value.integer.value[0];
+
+       DBG("%s : set playback_path = %ld, hdmi %s\n", __func__,
+               rk616_priv->playback_path, get_hdmi_state() ? "in" : "out");
+
+       if(get_hdmi_state())
+               return 0;
+
+       switch (rk616_priv->playback_path) {
+       case OFF:
+               snd_soc_dapm_disable_pin(&codec->dapm, "Headphone Jack");
+               snd_soc_dapm_disable_pin(&codec->dapm, "Ext Spk");
+               snd_soc_dapm_sync(&codec->dapm);
+               break;
+       case RCV:
+               break;
+       case SPK_PATH:
+       case RING_SPK:
+               snd_soc_dapm_disable_pin(&codec->dapm, "Headphone Jack");
+               snd_soc_dapm_enable_pin(&codec->dapm, "Ext Spk");
+               snd_soc_dapm_sync(&codec->dapm);
+               break;
+       case HP_PATH:
+       case HP_NO_MIC:
+       case RING_HP:
+       case RING_HP_NO_MIC:
+               snd_soc_dapm_disable_pin(&codec->dapm, "Ext Spk");
+               snd_soc_dapm_enable_pin(&codec->dapm, "Headphone Jack");
+               snd_soc_dapm_sync(&codec->dapm);
+               break;
+       case BT:
+               break;
+       case SPK_HP:
+       case RING_SPK_HP:
+               snd_soc_dapm_enable_pin(&codec->dapm, "Headphone Jack");
+               snd_soc_dapm_enable_pin(&codec->dapm, "Ext Spk");
+               snd_soc_dapm_sync(&codec->dapm);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int rk616_capture_path_get(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       if (!rk616_priv) {
+               printk("%s : rk616_priv is NULL\n", __func__);
+               return -EINVAL;
+       }
+
+       DBG("%s : capture_path = %ld\n", __func__,
+               ucontrol->value.integer.value[0]);
+
+       ucontrol->value.integer.value[0] = rk616_priv->capture_path;
+
+       return 0;
+}
+
+static int rk616_capture_path_put(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+       if (!rk616_priv) {
+               printk("%s : rk616_priv is NULL\n", __func__);
+               return -EINVAL;
+       }
+
+       if (rk616_priv->capture_path == ucontrol->value.integer.value[0]){
+               printk("%s : capture_path is not changed!\n", __func__);
+               //return 0;
+       }
+
+       rk616_priv->capture_path = ucontrol->value.integer.value[0];
+
+       DBG("%s : set capture_path = %ld\n", __func__, rk616_priv->capture_path);
+
+       switch (rk616_priv->capture_path) {
+       case MIC_OFF:
+               snd_soc_dapm_disable_pin(&codec->dapm, "Mic Jack");
+               snd_soc_dapm_disable_pin(&codec->dapm, "Headset Jack");
+               snd_soc_dapm_sync(&codec->dapm);
+               break;
+       case Main_Mic:
+               snd_soc_dapm_enable_pin(&codec->dapm, "Mic Jack");
+               snd_soc_dapm_disable_pin(&codec->dapm,"Headset Jack");
+               snd_soc_dapm_sync(&codec->dapm);
+               break;
+       case Hands_Free_Mic:
+               snd_soc_dapm_enable_pin(&codec->dapm, "Headset Jack");
+               snd_soc_dapm_disable_pin(&codec->dapm, "Mic Jack");
+               snd_soc_dapm_sync(&codec->dapm);
+               break;
+       case BT_Sco_Mic:
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int rk616_voice_call_path_get(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       if (!rk616_priv) {
+               printk("%s : rk616_priv is NULL\n", __func__);
+               return -EINVAL;
+       }
+
+       DBG("%s : playback_path = %ld\n", __func__,
+               ucontrol->value.integer.value[0]);
+
+       ucontrol->value.integer.value[0] = rk616_priv->voice_call_path;
+
+       return 0;
+}
+
+static int rk616_voice_call_path_put(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+       if (!rk616_priv) {
+               printk("%s : rk616_priv is NULL\n", __func__);
+               return -EINVAL;
+       }
+
+       if (rk616_priv->voice_call_path == ucontrol->value.integer.value[0]){
+               printk("%s : playback_path is not changed!\n",__func__);
+               //return 0;
+       }
+
+       rk616_priv->voice_call_path = ucontrol->value.integer.value[0];
+
+       DBG("%s : set playback_path = %ld\n", __func__,
+               rk616_priv->voice_call_path);
+
+       switch (rk616_priv->voice_call_path) {
+       case OFF:
+               snd_soc_dapm_disable_pin(&codec->dapm, "Headphone Jack");
+               snd_soc_dapm_disable_pin(&codec->dapm, "Ext Spk");
+               snd_soc_dapm_sync(&codec->dapm);
+               break;
+       case RCV:
+               break;
+       case SPK_PATH:
+               snd_soc_dapm_disable_pin(&codec->dapm, "Headphone Jack");
+               snd_soc_dapm_enable_pin(&codec->dapm, "Ext Spk");
+               snd_soc_dapm_sync(&codec->dapm);
+               break;
+       case HP_PATH:
+       case HP_NO_MIC:
+               snd_soc_dapm_disable_pin(&codec->dapm, "Ext Spk");
+               snd_soc_dapm_enable_pin(&codec->dapm, "Headphone Jack");
+               snd_soc_dapm_sync(&codec->dapm);
+               break;
+       case BT:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct snd_kcontrol_new rk616_snd_path_controls[] = {
+       SOC_ENUM_EXT("Playback Path", rk616_playback_path_type,
+               rk616_playback_path_get, rk616_playback_path_put),
+
+       SOC_ENUM_EXT("Capture MIC Path", rk616_capture_path_type,
+               rk616_capture_path_get, rk616_capture_path_put),
+
+       SOC_ENUM_EXT("Voice Call Path", rk616_voice_call_path_type,
+               rk616_voice_call_path_get, rk616_voice_call_path_put),
+};
+
 static int rk616_dacl_event(struct snd_soc_dapm_widget *w,
        struct snd_kcontrol *kcontrol, int event)
 {
@@ -1683,18 +1912,18 @@ static struct rk616_reg_val_typ capture_power_up_list[] = {
        {0x89c, 0x7f}, //MICBIAS1 power up (bit 7, Vout = 1.7 * Vref(1.65V) = 2.8V (bit 3-5)
        {0x8a8, 0x09}, //ADCL/R power, and clear ADCL/R buf
        {0x8a8, 0x00}, //ADCL/R power, and clear ADCL/R buf
-    {0x8c4, 0x57}, //L mod time 
-  //{0x904, 0x57}, //R mod time 
-    {0x828, 0x39}, //Set for Capture pop noise && enable agc control pga
-    {0x8a4, 0x03}, //enable cross zero detect
-    {0x8c0, 0x00}, //L agc choice mod 2
-  //{0x900, 0x00}, //R agc choice mod 2
-    {0x8d4, 0x13}, //max low
-    {0x8d8, 0x08}, //max high 
-    {0x8dc, 0xc2}, //min low
-    {0x8e0, 0x16}, //min high 
-    {0x8e4, 0x70}, //L enable agc
-  //{0x924, 0x70}, //R enbale agc
+       {0x8c4, 0x57}, //L mod time
+       //{0x904, 0x57}, //R mod time
+       {0x828, 0x39}, //Set for Capture pop noise && enable agc control pga
+       {0x8a4, 0x03}, //enable cross zero detect
+       {0x8c0, 0x00}, //L agc choice mod 2
+       //{0x900, 0x00}, //R agc choice mod 2
+       {0x8d4, 0x13}, //max low
+       {0x8d8, 0x08}, //max high
+       {0x8dc, 0xc2}, //min low
+       {0x8e0, 0x16}, //min high
+       {0x8e4, 0x70}, //L enable agc
+       //{0x924, 0x70}, //R enbale agc
 };
 #define RK616_CODEC_CAPTURE_POWER_UP_LIST_LEN ARRAY_SIZE(capture_power_up_list)
 
@@ -1706,18 +1935,18 @@ static struct rk616_reg_val_typ capture_power_down_list[] = {
        {0x848, 0x1f}, //MIXINL power down and mute, MININL No selecting, MICMUX from BST_L
        {0x840, 0x99}, //BST_L power down, mute, and Single-Ended(bit 6), volume 0(bit 5)
        {0x83c, 0x7c}, //power down
-    {0x8e4, 0x38}, //L disable agc
-  //{0x924, 0x38}, //R disbale agc
-    {0x8c4, 0x25}, 
-  //{0x904, 0x25}, 
-    {0x828, 0x09}, 
-    {0x8a4, 0x0F},
-    {0x8c0, 0x10}, 
-  //{0x900, 0x10}, 
-    {0x8d4, 0x26}, 
-    {0x8d8, 0x40}, 
-    {0x8dc, 0x36}, 
-    {0x8e0, 0x20},
+       {0x8e4, 0x38}, //L disable agc
+       //{0x924, 0x38}, //R disbale agc
+       {0x8c4, 0x25},
+       //{0x904, 0x25},
+       {0x828, 0x09},
+       {0x8a4, 0x0F},
+       {0x8c0, 0x10},
+       //{0x900, 0x10},
+       {0x8d4, 0x26},
+       {0x8d8, 0x40},
+       {0x8dc, 0x36},
+       {0x8e0, 0x20},
 };
 #define RK616_CODEC_CAPTURE_POWER_DOWN_LIST_LEN ARRAY_SIZE(capture_power_down_list)
 
@@ -1736,11 +1965,11 @@ static int rk616_codec_power_up(int type)
                type == RK616_CODEC_CAPTURE ? "capture" : "");
 
        if (type == RK616_CODEC_PALYBACK) {
-               if(! get_hdmi_state())
                for (i = 0; i < RK616_CODEC_PALYBACK_POWER_UP_LIST_LEN; i++) {
                        snd_soc_write(codec, palyback_power_up_list[i].reg,
                                palyback_power_up_list[i].value);
                }
+               codec_set_spk(!get_hdmi_state());
        } else if (type == RK616_CODEC_CAPTURE) {
                for (i = 0; i < RK616_CODEC_CAPTURE_POWER_UP_LIST_LEN; i++) {
                        snd_soc_write(codec, capture_power_up_list[i].reg,
index c1342e63f394b1e8274bca54f161fd14740acd06..a541fd63c77d28de645f821241f75d55044722ee 100755 (executable)
@@ -747,6 +747,27 @@ enum {
        RK616_STEREO,
 };
 
+enum {
+       OFF,
+       RCV,
+       SPK_PATH,
+       HP_PATH,
+       HP_NO_MIC,
+       BT,
+       SPK_HP,
+       RING_SPK,
+       RING_HP,
+       RING_HP_NO_MIC,
+       RING_SPK_HP,
+};
+
+enum {
+       MIC_OFF,
+       Main_Mic,
+       Hands_Free_Mic,
+       BT_Sco_Mic,
+};
+
 struct rk616_reg_val_typ {
        unsigned int reg;
        unsigned int value;
diff --git a/sound/soc/codecs/spdif_transciever.c b/sound/soc/codecs/spdif_transciever.c
deleted file mode 100644 (file)
index 6a1a7e7..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * ALSA SoC SPDIF DIT driver
- *
- *  This driver is used by controllers which can operate in DIT (SPDI/F) where
- *  no codec is needed.  This file provides stub codec that can be used
- *  in these configurations. TI DaVinci Audio controller uses this driver.
- *
- * Author:      Steve Chen,  <schen@mvista.com>
- * Copyright:   (C) 2009 MontaVista Software, Inc., <source@mvista.com>
- * Copyright:   (C) 2009  Texas Instruments, India
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/slab.h>
-#include <sound/soc.h>
-#include <sound/pcm.h>
-#include <sound/initval.h>
-
-#define DRV_NAME "spdif-dit"
-
-#define STUB_RATES     SNDRV_PCM_RATE_8000_96000
-#define STUB_FORMATS   SNDRV_PCM_FMTBIT_S16_LE
-
-
-static struct snd_soc_codec_driver soc_codec_spdif_dit;
-
-static struct snd_soc_dai_driver dit_stub_dai = {
-       .name           = "dit-hifi",
-       .playback       = {
-               .stream_name    = "Playback",
-               .channels_min   = 1,
-               .channels_max   = 384,
-               .rates          = STUB_RATES,
-               .formats        = STUB_FORMATS,
-       },
-};
-
-static int spdif_dit_probe(struct platform_device *pdev)
-{
-       return snd_soc_register_codec(&pdev->dev, &soc_codec_spdif_dit,
-                       &dit_stub_dai, 1);
-}
-
-static int spdif_dit_remove(struct platform_device *pdev)
-{
-       snd_soc_unregister_codec(&pdev->dev);
-       return 0;
-}
-
-static struct platform_driver spdif_dit_driver = {
-       .probe          = spdif_dit_probe,
-       .remove         = spdif_dit_remove,
-       .driver         = {
-               .name   = DRV_NAME,
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init dit_modinit(void)
-{
-       return platform_driver_register(&spdif_dit_driver);
-}
-
-static void __exit dit_exit(void)
-{
-       platform_driver_unregister(&spdif_dit_driver);
-}
-
-module_init(dit_modinit);
-module_exit(dit_exit);
-
-MODULE_AUTHOR("Steve Chen <schen@mvista.com>");
-MODULE_DESCRIPTION("SPDIF dummy codec driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
index f311a74e62d6a43c14e85bdab70c750ba6628653..9a809966f77ad3c5616a7445449056953a3c6356 100755 (executable)
@@ -9,6 +9,9 @@ config SND_RK29_SOC
 config SND_RK29_SOC_I2S
        tristate
 
+config SND_RK_SOC_SPDIF
+       tristate
+
 config SND_RK29_SOC_I2S_8CH
        bool "Soc RK29 I2S 8 Channel support(I2S0)"
        default y
@@ -54,9 +57,6 @@ config SND_RK_SOC_I2S2_2CH
        help
                This supports the use of the 2 Channel I2S2 interface on rk30 processors.
 
-config SND_ROCKCHIP_SPDIF
-       tristate
-       select SND_SOC_SPDIF
 if     SND_RK29_SOC_I2S_2CH || SND_RK29_SOC_I2S_8CH || SND_RK_SOC_I2S2_2CH
 choice
   bool "Set i2s on DMA event mode"
@@ -68,21 +68,24 @@ choice
                tristate  "static mode"
 endchoice
 endif
-config SND_RK_SOC_SPDIF
-       bool "spdif support for rockchip rk29 or rk30"
-       depends on SND_RK29_SOC 
-       select SND_ROCKCHIP_SPDIF
-       help
-         Say Y if you want to add support for SoC audio on rockchip
-         with the spdif.
-         
-config SND_RK29_SOC_SPDIF
-       bool "Soc RK29 SPDIF support"
-       depends on SND_RK29_SOC
-       depends on SND_RK29_SOC_I2S
-       help
-               This supports the use of SPDIF interface on rk29 processors
-               
+
+if SND_RK29_SOC && RK_HDMI
+choice
+  bool "Set audio support for HDMI"
+  default SND_RK_SOC_HDMI_I2S
+       config SND_RK_SOC_HDMI_I2S
+               select SND_RK29_SOC_I2S
+               select SND_SOC_HDMI_I2S
+               tristate  "HDMI use I2S"
+
+       config SND_RK_SOC_HDMI_SPDIF
+               depends on SND_RK_SOC_RK616
+               select SND_RK_SOC_SPDIF
+               select SND_SOC_HDMI_SPDIF
+               tristate  "HDMI use SPDIF"
+endchoice
+endif
+
 config SND_RK29_SOC_ES8323
        tristate "SoC I2S Audio support for rockchip - ES8323"
        depends on SND_RK29_SOC
@@ -256,14 +259,6 @@ config SND_RK29_SOC_RK1000
          Say Y if you want to add support for SoC audio on rockchip
          with the RK1000.
 
-config SND_RK29_SOC_HDMI
-       tristate "SoC I2S Audio support for rockchip - HDMI"
-       depends on SND_RK29_SOC && HDMI_ITV
-       select SND_RK29_SOC_I2S
-       help
-         Say Y if you want to add support for SoC audio on rockchip
-         with the HDMI.
-
 config SND_RK29_SOC_RK610
        tristate "SoC I2S Audio support for rockchip - RK610"
        depends on SND_RK29_SOC && MFD_RK610
@@ -273,7 +268,7 @@ config SND_RK29_SOC_RK610
          Say Y if you want to add support for SoC audio on rockchip
          with the RK610(JETTA).
 
-config SND_RK29_SOC_RK616
+config SND_RK_SOC_RK616
        tristate "SoC I2S Audio support for rockchip - RK616"
        depends on SND_RK29_SOC && MFD_RK616
        select SND_RK29_SOC_I2S
index 728bdae8dcdede685c889bb1b6bf04133e58c4c2..ddd5806241d6e97e02c6a0aebe82aebd02508528 100755 (executable)
@@ -5,11 +5,11 @@ snd-soc-rockchip-i2s-objs := rk29_i2s.o
 else
 snd-soc-rockchip-i2s-objs := rk30_i2s.o
 endif
-snd-soc-rockchip-spdif-objs := spdif.o
+snd-soc-rockchip-spdif-objs := rk_spdif.o
 
 obj-$(CONFIG_SND_RK29_SOC) += snd-soc-rockchip.o
 obj-$(CONFIG_SND_RK29_SOC_I2S) += snd-soc-rockchip-i2s.o
-obj-$(CONFIG_SND_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o
+obj-$(CONFIG_SND_RK_SOC_SPDIF) += snd-soc-rockchip-spdif.o
 
 # ROCKCHIP Machine Support
 snd-soc-wm8900-objs := rk29_wm8900.o
@@ -27,13 +27,13 @@ snd-soc-aic3111-objs := rk29_aic3111.o
 snd-soc-wm8988-objs := rk29_wm8988.o
 snd-soc-rk1000-objs := rk29_rk1000codec.o
 snd-soc-wm8994-objs := rk29_wm8994.o
-snd-soc-hdmi-objs := rk29_hdmi.o
 snd-soc-rk610-objs := rk29_jetta_codec.o
 snd-soc-rk616-objs := rk_rk616.o
 snd-soc-aic3262-objs := rk29_aic3262.o
 snd-soc-rk2928-objs := rk2928-card.o
 snd-soc-es8323-objs := rk29_es8323.o
-snd-soc-rk_spdif-objs := rk_spdif.o
+snd-soc-hdmi-i2s-objs := rk_hdmi_i2s.o
+snd-soc-hdmi-spdif-objs := rk_hdmi_spdif.o
 
 obj-$(CONFIG_SND_RK29_SOC_WM8994) += snd-soc-wm8994.o
 obj-$(CONFIG_SND_RK29_SOC_WM8988) += snd-soc-wm8988.o
@@ -51,9 +51,9 @@ obj-$(CONFIG_SND_RK29_SOC_RK1000) += snd-soc-rk1000.o
 obj-$(CONFIG_SND_RK29_SOC_CS42L52) += snd-soc-cs42l52.o
 obj-$(CONFIG_SND_RK29_SOC_AIC3111) += snd-soc-aic3111.o
 obj-$(CONFIG_SND_RK29_SOC_AIC3262) += snd-soc-aic3262.o
-obj-$(CONFIG_SND_RK29_SOC_HDMI) += snd-soc-hdmi.o
 obj-$(CONFIG_SND_RK29_SOC_RK610) += snd-soc-rk610.o
-obj-$(CONFIG_SND_RK29_SOC_RK616) += snd-soc-rk616.o
-obj-$(CONFIG_SND_RK_SOC_SPDIF) += snd-soc-rk_spdif.o
+obj-$(CONFIG_SND_RK_SOC_RK616) += snd-soc-rk616.o
+obj-$(CONFIG_SND_RK_SOC_HDMI_I2S) += snd-soc-hdmi-i2s.o
+obj-$(CONFIG_SND_RK_SOC_HDMI_SPDIF) += snd-soc-hdmi-spdif.o
 obj-$(CONFIG_SND_RK_SOC_RK2928) += snd-soc-rk2928.o
 obj-$(CONFIG_SND_RK29_SOC_ES8323) += snd-soc-es8323.o
diff --git a/sound/soc/rk29/rk_hdmi_i2s.c b/sound/soc/rk29/rk_hdmi_i2s.c
new file mode 100644 (file)
index 0000000..a41c0bd
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * rk_hdmi_i2s.c  --  HDMI i2s audio for rockchip
+ *
+ * Copyright 2013 Rockship
+ * Author: chenjq <chenjq@rock-chips.com>
+ */
+
+#include <linux/clk.h>
+#include <sound/soc.h>
+#include <mach/iomux.h>
+
+#include "rk29_pcm.h"
+#include "rk29_i2s.h"
+
+#if 0
+#define DBG(x...) printk(KERN_INFO "rk_hdmi_i2s:"x)
+#else
+#define DBG(x...) do { } while (0)
+#endif
+
+
+static int hdmi_i2s_hifi_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       unsigned int pll_out = 0;
+       int ret;
+
+       DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
+
+       /* set cpu DAI configuration */
+       #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
+       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+                       SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+       #endif
+       #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER)
+       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+                       SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+       #endif
+       if (ret < 0)
+               return ret;
+
+       switch(params_rate(params)) {
+               case 8000:
+               case 16000:
+               case 24000:
+               case 32000:
+               case 48000:
+                       pll_out = 12288000;
+                       break;
+               case 11025:
+               case 22050:
+               case 44100:
+                       pll_out = 11289600;
+                       break;
+               default:
+                       printk("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));
+                       return -EINVAL;
+                       break;
+       }
+
+       DBG("Enter:%s, %d, rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));
+
+       snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
+       snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (pll_out/4)/params_rate(params)-1);
+       snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3);
+
+       DBG("Enter:%s, %d, pll_out/4/params_rate(params) = %d \n", __FUNCTION__, __LINE__, (pll_out/4)/params_rate(params));
+
+       return 0;
+}
+
+
+
+static struct snd_soc_ops hdmi_i2s_hifi_ops = {
+       .hw_params = hdmi_i2s_hifi_hw_params,
+};
+
+static struct snd_soc_dai_link hdmi_i2s_dai = {
+       .name = "HDMI I2S",
+       .stream_name = "HDMI PCM",
+       .codec_name = "hdmi-i2s",
+       .platform_name = "rockchip-audio",
+       .cpu_dai_name = "rk29_i2s.1",
+       .codec_dai_name = "rk-hdmi-i2s-hifi",
+       .ops = &hdmi_i2s_hifi_ops,
+};
+
+static struct snd_soc_card snd_soc_card_hdmi_i2s = {
+       .name = "RK-HDMI-I2S",
+       .dai_link = &hdmi_i2s_dai,
+       .num_links = 1,
+};
+
+static struct platform_device *hdmi_i2s_snd_device;
+static struct platform_device *hdmi_i2s_device;
+
+static int __init audio_card_init(void)
+{
+       int ret =0;
+
+       DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
+
+       hdmi_i2s_device = platform_device_alloc("hdmi-i2s", -1);
+
+       if (!hdmi_i2s_device){
+               printk("spdif:platform_device_alloc hdmi-i2s\n");
+               return -ENOMEM;
+       }
+
+       ret = platform_device_add(hdmi_i2s_device);
+       if (ret) {
+               printk("platform device add hdmi-i2s failed\n");
+
+               platform_device_put(hdmi_i2s_device);
+               return ret;
+       }
+       DBG("Enter::%s----%d 1\n",__FUNCTION__,__LINE__);
+       hdmi_i2s_snd_device = platform_device_alloc("soc-audio", -3);
+       if (!hdmi_i2s_snd_device) {
+               printk("platform device allocation failed\n");
+
+               platform_device_put(hdmi_i2s_device);
+               return -ENOMEM;
+       }
+
+       platform_set_drvdata(hdmi_i2s_snd_device, &snd_soc_card_hdmi_i2s);
+       ret = platform_device_add(hdmi_i2s_snd_device);
+       if (ret) {
+               printk("platform device add soc-audio failed\n");
+
+               platform_device_put(hdmi_i2s_device);
+               platform_device_put(hdmi_i2s_snd_device);
+               return ret;
+       }
+
+        return ret;
+}
+
+static void __exit audio_card_exit(void)
+{
+       platform_device_unregister(hdmi_i2s_snd_device);
+}
+
+late_initcall(audio_card_init);
+module_exit(audio_card_exit);
+/* Module information */
+MODULE_AUTHOR("rockchip");
+MODULE_DESCRIPTION("ROCKCHIP hdmi i2s ASoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/rk29/rk_hdmi_spdif.c b/sound/soc/rk29/rk_hdmi_spdif.c
new file mode 100644 (file)
index 0000000..0e69efc
--- /dev/null
@@ -0,0 +1,186 @@
+/*$_FOR_ROCKCHIP_RBOX_$*/
+/*$_rbox_$_modify_$_huangzhibao for spdif output*/
+
+/*
+ * smdk_spdif.c  --  S/PDIF audio for SMDK
+ *
+ * Copyright 2010 Samsung Electronics Co. Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/clk.h>
+
+#include <sound/soc.h>
+
+#include <mach/iomux.h>
+
+#if 0
+#define RK_SPDIF_DBG(x...) printk(KERN_INFO "rk_hdmi_spdif:"x)
+#else
+#define RK_SPDIF_DBG(x...) do { } while (0)
+#endif
+
+
+static int set_audio_clock_rate(unsigned long pll_rate,
+                               unsigned long audio_rate)
+{
+       struct clk *hclk_spdif, *sclk_spdif;
+
+#if defined (CONFIG_ARCH_RK30) || (CONFIG_ARCH_RK3188) 
+       hclk_spdif = clk_get(NULL, "hclk_spdif");
+       if (IS_ERR(hclk_spdif)) {
+               printk(KERN_ERR "spdif:failed to get hclk_spdif\n");
+               return -ENOENT;
+       }
+
+       clk_set_rate(hclk_spdif, pll_rate);
+       clk_put(hclk_spdif);
+#endif
+
+       sclk_spdif = clk_get(NULL, "spdif");
+       if (IS_ERR(sclk_spdif)) {
+               printk(KERN_ERR "spdif:failed to get sclk_spdif\n");
+               return -ENOENT;
+       }
+
+       clk_set_rate(sclk_spdif, audio_rate);
+       clk_put(sclk_spdif);
+
+       return 0;
+}
+
+static int rk_hw_params(struct snd_pcm_substream *substream,
+               struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       unsigned long pll_out, rclk_rate;
+       int ret, ratio;
+
+  RK_SPDIF_DBG("spdif:Entered %s\n", __func__);
+  
+       switch (params_rate(params)) {
+       case 44100:
+               pll_out = 11289600;
+               break;
+       case 32000:
+               pll_out = 8192000;
+               break;
+       case 48000:
+               pll_out = 12288000;
+               break;
+       case 96000:
+               pll_out = 24576000;
+               break;
+       default:
+               printk("rk_spdif: params not support\n");
+               return -EINVAL;
+       }
+
+       ratio = 256;
+       rclk_rate = params_rate(params) * ratio;
+
+       /* Set audio source clock rates */
+       ret = set_audio_clock_rate(pll_out, rclk_rate);
+       if (ret < 0)
+               return ret;
+
+       /* Set S/PDIF uses internal source clock */
+       //ret = snd_soc_dai_set_sysclk(cpu_dai, SND_SOC_SPDIF_INT_MCLK,
+                                       //rclk_rate, SND_SOC_CLOCK_IN);
+       //if (ret < 0)
+               //return ret;
+
+       return ret;
+}
+
+static struct snd_soc_ops rk_spdif_ops = {
+       .hw_params = rk_hw_params,
+};
+
+static struct snd_soc_dai_link rk_dai = {
+       .name = "SPDIF",
+       .stream_name = "SPDIF PCM Playback",
+       .platform_name = "rockchip-audio",
+       .cpu_dai_name = "rk-spdif.0",
+       .codec_dai_name = "dit-hifi",
+       .codec_name = "spdif-dit",
+       .ops = &rk_spdif_ops,
+};
+
+static struct snd_soc_card rk_spdif = {
+       .name = "ROCKCHIP-SPDIF",
+       .dai_link = &rk_dai,
+       .num_links = 1,
+};
+
+static struct platform_device *rk_snd_spdif_dit_device;
+static struct platform_device *rk_snd_spdif_device;
+
+static int __init rk_spdif_init(void)
+{
+       int ret;
+       
+       RK_SPDIF_DBG("Entered %s\n", __func__);
+       
+       rk_snd_spdif_dit_device = platform_device_alloc("spdif-dit", -1);
+       if (!rk_snd_spdif_dit_device){
+               printk("spdif:platform_device_alloc spdif-dit\n");
+               return -ENOMEM;
+       }
+
+       ret = platform_device_add(rk_snd_spdif_dit_device);
+       if (ret)
+               goto err1;
+
+       rk_snd_spdif_device = platform_device_alloc("soc-audio", -3);
+       if (!rk_snd_spdif_device) {
+               printk("spdif:platform_device_alloc rk_soc-audio\n");
+               ret = -ENOMEM;
+               goto err2;
+       }
+       
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+       platform_set_drvdata(rk_snd_spdif_device, &rk_spdif);
+#else
+       platform_set_drvdata(rk_snd_spdif_device, &rk_spdif);
+       rk_spdif.dev = &rk_snd_spdif_device->dev;
+#endif
+
+       //platform_set_drvdata(rk_snd_spdif_device, &rk_spdif);
+
+       ret = platform_device_add(rk_snd_spdif_device);
+       if (ret)
+               goto err3;
+       
+       RK_SPDIF_DBG("rk_spdif_init ok\n");
+       return ret;
+err3:
+       platform_device_put(rk_snd_spdif_device);
+err2:
+       platform_device_del(rk_snd_spdif_dit_device);
+err1:
+       platform_device_put(rk_snd_spdif_dit_device);
+       
+       return ret;
+}
+
+static void __exit rk_spdif_exit(void)
+{
+       platform_device_unregister(rk_snd_spdif_device);
+       platform_device_unregister(rk_snd_spdif_dit_device);
+}
+
+//using late_initcall to make sure spdif is after board codec. added by zxg.
+//module_init(rk_spdif_init);
+late_initcall(rk_spdif_init);
+module_exit(rk_spdif_exit);
+
+MODULE_AUTHOR("hzb, <hzb@rock-chips.com>");
+MODULE_DESCRIPTION("ALSA SoC RK+S/PDIF");
+MODULE_LICENSE("GPL");
index 6ec311ed63bd5bf69acc92a641ff5163917ed20e..d3eedba78680b96b6db5dd9df26aaa0c4e597e06 100644 (file)
@@ -1,25 +1,54 @@
 /*$_FOR_ROCKCHIP_RBOX_$*/
 /*$_rbox_$_modify_$_huangzhibao for spdif output*/
 
-/*
- * smdk_spdif.c  --  S/PDIF audio for SMDK
+/* sound/soc/rockchip/spdif.c
  *
- * Copyright 2010 Samsung Electronics Co. Ltd.
+ * ALSA SoC Audio Layer - rockchip S/PDIF Controller driver
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
+ * Copyright (c) 2010 rockchip Electronics Co. Ltd
+ *             http://www.rockchip.com/
  *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
  */
 
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/delay.h>
 #include <linux/clk.h>
+#include <linux/version.h>
 
+#include <asm/dma.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
 #include <sound/soc.h>
+#include <asm/io.h>
 
-#include "spdif.h"
+#include <mach/board.h>
+#include <mach/hardware.h>
+#include <mach/io.h>
+#include <mach/gpio.h>
 #include <mach/iomux.h>
 
+#if defined (CONFIG_ARCH_RK29)
+#include <mach/rk29-dma-pl330.h>
+#endif
+
+#if defined (CONFIG_ARCH_RK30)
+#include <mach/dma-pl330.h>
+#endif
+
+#if defined (CONFIG_ARCH_RK3188)
+#include <mach/dma-pl330.h>
+#endif
+
+#include "rk29_pcm.h"
+
 #if 0
 #define RK_SPDIF_DBG(x...) printk(KERN_INFO "rk_spdif:"x)
 #else
 #endif
 
 
-static int set_audio_clock_rate(unsigned long pll_rate,
-                               unsigned long audio_rate)
+/* Registers */
+#define CFGR                           0x00
+#define SDBLR                          0x04
+#define DMACR                          0x08
+#define INTCR                          0x0C
+#define INTSR                    0x10
+#define XFER                           0x18
+#define SMPDR                          0x20
+
+#define DATA_OUTBUF                    0x20   
+#define CFGR_MASK                      0x0ffffff
+#define CFGR_VALID_DATA_16bit       (00)
+#define CFGR_VALID_DATA_20bit       (01)
+#define CFGR_VALID_DATA_24bit       (10)
+#define CFGR_VALID_DATA_MASK        (11)
+
+#define CFGR_HALFWORD_TX_ENABLE     (0x1 << 2)
+#define CFGR_HALFWORD_TX_DISABLE    (0x0 << 2)
+#define CFGR_HALFWORD_TX_MASK       (0x1 << 2)  
+
+#define CFGR_CLK_RATE_MASK          (0xFF<<16)                 
+
+#define CFGR_JUSTIFIED_RIGHT        (0<<3)
+#define CFGR_JUSTIFIED_LEFT         (1<<3)
+#define CFGR_JUSTIFIED_MASK         (1<<3)
+
+#define XFER_TRAN_STOP        (0)
+#define XFER_TRAN_START       (1)
+#define XFER_MASK             (1)
+
+#define DMACR_TRAN_DMA_DISABLE   (0<<5)
+#define DMACR_TRAN_DMA_ENABLE   (1<<5)
+#define DMACR_TRAN_DMA_CTL_MASK   (1<<5)
+
+#define DMACR_TRAN_DATA_LEVEL       0x10
+#define DMACR_TRAN_DATA_LEVEL_MASK  0x1F
+
+#define DMACR_TRAN_DMA_MASK   (0x3F)
+
+
+struct rockchip_spdif_info {
+       spinlock_t      lock;
+       struct device   *dev;
+       void __iomem    *regs;
+       unsigned long   clk_rate;
+       struct clk      *hclk;
+       struct clk      *clk;
+       u32             saved_clkcon;
+       u32             saved_con;
+       u32             saved_cstas;
+       struct rockchip_pcm_dma_params  *dma_playback;
+};
+
+static struct rk29_dma_client spdif_dma_client_out = {
+       .name           = "SPDIF Stereo out"
+};
+
+static struct rockchip_pcm_dma_params spdif_stereo_out;
+
+static struct rockchip_spdif_info spdif_info;
+
+static inline struct rockchip_spdif_info *to_info(struct snd_soc_dai *cpu_dai)
 {
-       struct clk *hclk_spdif, *sclk_spdif;
+       return snd_soc_dai_get_drvdata(cpu_dai);
+}
 
-#if defined (CONFIG_ARCH_RK30) || (CONFIG_ARCH_RK3188) 
-       hclk_spdif = clk_get(NULL, "hclk_spdif");
-       if (IS_ERR(hclk_spdif)) {
-               printk(KERN_ERR "spdif:failed to get hclk_spdif\n");
-               return -ENOENT;
-       }
+static void spdif_snd_txctrl(struct rockchip_spdif_info *spdif, int on)
+{
+       void __iomem *regs = spdif->regs;
+       u32 opr,xfer;
 
-       clk_set_rate(hclk_spdif, pll_rate);
-       clk_put(hclk_spdif);
-#endif
+       RK_SPDIF_DBG( "Entered %s\n", __func__);
 
-       sclk_spdif = clk_get(NULL, "spdif");
-       if (IS_ERR(sclk_spdif)) {
-               printk(KERN_ERR "spdif:failed to get sclk_spdif\n");
-               return -ENOENT;
-       }
+       xfer = readl(regs + XFER) & XFER_MASK;
+       opr  = readl(regs + DMACR) & DMACR_TRAN_DMA_MASK & (~DMACR_TRAN_DMA_CTL_MASK);
+       
+       if (on){
+               xfer |= XFER_TRAN_START;
+               opr |= DMACR_TRAN_DMA_ENABLE;
+               writel(xfer, regs + XFER);
+               writel(opr|0x10, regs + DMACR);
+               RK_SPDIF_DBG("on xfer=0x%x,opr=0x%x\n",readl(regs + XFER),readl(regs + DMACR));
+  }    else{
+       xfer &= ~XFER_TRAN_START;
+       opr  &= ~DMACR_TRAN_DMA_ENABLE; 
+               writel(xfer, regs + XFER);
+               writel(opr|0x10, regs + DMACR);
+  }
+}
+
+static int spdif_set_syclk(struct snd_soc_dai *cpu_dai,
+                               int clk_id, unsigned int freq, int dir)
+{
+       struct rockchip_spdif_info *spdif = to_info(cpu_dai);
+       u32 clkcon;
 
-       clk_set_rate(sclk_spdif, audio_rate);
-       clk_put(sclk_spdif);
+       RK_SPDIF_DBG("Entered %s\n", __func__);
+
+       spdif->clk_rate = freq;
 
        return 0;
 }
 
-static int rk_hw_params(struct snd_pcm_substream *substream,
-               struct snd_pcm_hw_params *params)
+static int spdif_trigger(struct snd_pcm_substream *substream, int cmd,
+                               struct snd_soc_dai *dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       unsigned long pll_out, rclk_rate;
-       int ret, ratio;
+       struct rockchip_spdif_info *spdif = to_info(rtd->cpu_dai);
+       unsigned long flags;
 
-  RK_SPDIF_DBG("spdif:Entered %s\n", __func__);
-  
-       switch (params_rate(params)) {
-       case 44100:
-               pll_out = 11289600;
+       RK_SPDIF_DBG( "Entered %s\n", __func__);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               spin_lock_irqsave(&spdif->lock, flags);
+               spdif_snd_txctrl(spdif, 1);
+               spin_unlock_irqrestore(&spdif->lock, flags);
                break;
-       case 32000:
-               pll_out = 8192000;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               spin_lock_irqsave(&spdif->lock, flags);
+               spdif_snd_txctrl(spdif, 0);
+               spin_unlock_irqrestore(&spdif->lock, flags);
                break;
-       case 48000:
-               pll_out = 12288000;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+
+static int spdif_hw_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params,
+                               struct snd_soc_dai *socdai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct rockchip_spdif_info *spdif = to_info(rtd->cpu_dai);
+       void __iomem *regs = spdif->regs;
+       struct rockchip_pcm_dma_params *dma_data;
+       unsigned long flags;
+       int i, cfgr, dmac;
+
+       RK_SPDIF_DBG("Entered %s\n", __func__);
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               dma_data = spdif->dma_playback;
+       else {
+               printk("spdif:Capture is not supported\n");
+               return -EINVAL;
+       }
+
+       snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data);
+       spin_lock_irqsave(&spdif->lock, flags);
+       
+       cfgr = readl(regs + CFGR) & CFGR_VALID_DATA_MASK;
+       
+  cfgr &= ~CFGR_VALID_DATA_MASK;
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               cfgr |= CFGR_VALID_DATA_16bit;
                break;
-       case 96000:
-               pll_out = 24576000;
+       case SNDRV_PCM_FMTBIT_S20_3LE :
+               cfgr |= CFGR_VALID_DATA_20bit;
                break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               cfgr |= CFGR_VALID_DATA_24bit;
+               break;                  
        default:
-               printk("rk_spdif: params not support\n");
-               return -EINVAL;
+               goto err;
        }
+       
+       cfgr &= ~CFGR_HALFWORD_TX_MASK;
+       cfgr |= CFGR_HALFWORD_TX_ENABLE;
+       
+       cfgr &= ~CFGR_CLK_RATE_MASK;
+       cfgr |= (1<<16);
+       
+       cfgr &= ~CFGR_JUSTIFIED_MASK;
+       cfgr |= CFGR_JUSTIFIED_RIGHT;
+       
+       writel(cfgr, regs + CFGR);
+  
+  dmac = readl(regs + DMACR) & DMACR_TRAN_DMA_MASK & (~DMACR_TRAN_DATA_LEVEL_MASK);
+  dmac |= 0x10;
+  writel(dmac, regs + DMACR);
+  
+       spin_unlock_irqrestore(&spdif->lock, flags);
 
-       ratio = 256;
-       rclk_rate = params_rate(params) * ratio;
+       return 0;
+err:
+       spin_unlock_irqrestore(&spdif->lock, flags);
+       return -EINVAL;
+}
 
-       /* Set audio source clock rates */
-       ret = set_audio_clock_rate(pll_out, rclk_rate);
-       if (ret < 0)
-               return ret;
+static void spdif_shutdown(struct snd_pcm_substream *substream,
+                               struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct rockchip_spdif_info *spdif = to_info(rtd->cpu_dai);
+       void __iomem *regs = spdif->regs;
+       u32 con, clkcon;
 
-       /* Set S/PDIF uses internal source clock */
-       //ret = snd_soc_dai_set_sysclk(cpu_dai, SND_SOC_SPDIF_INT_MCLK,
-                                       //rclk_rate, SND_SOC_CLOCK_IN);
-       //if (ret < 0)
-               //return ret;
+       RK_SPDIF_DBG( "spdif:Entered %s\n", __func__);
 
-       return ret;
 }
 
-static struct snd_soc_ops rk_spdif_ops = {
-       .hw_params = rk_hw_params,
-};
+#ifdef CONFIG_PM
+static int spdif_suspend(struct snd_soc_dai *cpu_dai)
+{
+       struct rockchip_spdif_info *spdif = to_info(cpu_dai);
+       u32 con = spdif->saved_con;
+
+       RK_SPDIF_DBG( "spdif:Entered %s\n", __func__);
+
+       return 0;
+}
+
+static int spdif_resume(struct snd_soc_dai *cpu_dai)
+{
+       struct rockchip_spdif_info *spdif = to_info(cpu_dai);
+
+       RK_SPDIF_DBG( "spdif:Entered %s\n", __func__);
 
-static struct snd_soc_dai_link rk_dai = {
-       .name = "SPDIF",
-       .stream_name = "SPDIF PCM Playback",
-       .platform_name = "rockchip-audio",
-       .cpu_dai_name = "rk-spdif.0",
-       .codec_dai_name = "dit-hifi",
-       .codec_name = "spdif-dit",
-       .ops = &rk_spdif_ops,
+       return 0;
+}
+#else
+#define spdif_suspend NULL
+#define spdif_resume NULL
+#endif
+
+static struct snd_soc_dai_ops spdif_dai_ops = {
+       .set_sysclk     = spdif_set_syclk,
+       .trigger        = spdif_trigger,
+       .hw_params      = spdif_hw_params,
+       .shutdown       = spdif_shutdown,
 };
 
-static struct snd_soc_card rk_spdif = {
-       .name = "ROCKCHIP-SPDIF",
-       .dai_link = &rk_dai,
-       .num_links = 1,
+struct snd_soc_dai_driver rockchip_spdif_dai = {
+       .name = "rk-spdif",
+       .playback = {
+               .stream_name = "SPDIF Playback",
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = (SNDRV_PCM_RATE_32000 |
+                               SNDRV_PCM_RATE_44100 |
+                               SNDRV_PCM_RATE_48000 |
+                               SNDRV_PCM_RATE_96000),
+               .formats = SNDRV_PCM_FMTBIT_S16_LE|
+               SNDRV_PCM_FMTBIT_S20_3LE|
+               SNDRV_PCM_FMTBIT_S24_LE, },
+       .ops = &spdif_dai_ops,
+       .suspend = spdif_suspend,
+       .resume = spdif_resume,
 };
 
-static struct platform_device *rk_snd_spdif_dit_device;
-static struct platform_device *rk_snd_spdif_device;
 
-static int __init rk_spdif_init(void)
+static __devinit int spdif_probe(struct platform_device *pdev)
 {
+       struct s3c_audio_pdata *spdif_pdata;
+       struct resource *mem_res, *dma_res;
+       struct rockchip_spdif_info *spdif;
        int ret;
-       
+  
+       spdif_pdata = pdev->dev.platform_data;
+
        RK_SPDIF_DBG("Entered %s\n", __func__);
        
-       rk_snd_spdif_dit_device = platform_device_alloc("spdif-dit", -1);
-       if (!rk_snd_spdif_dit_device){
-               printk("spdif:platform_device_alloc spdif-dit\n");
-               return -ENOMEM;
-  }
-       ret = platform_device_add(rk_snd_spdif_dit_device);
-       if (ret)
-               goto err1;
+#if defined  (CONFIG_ARCH_RK29)
+    rk29_mux_api_set(GPIO4A7_SPDIFTX_NAME, GPIO4L_SPDIF_TX);
+#endif
 
-       rk_snd_spdif_device = platform_device_alloc("soc-audio", -3);
-       if (!rk_snd_spdif_device) {
-               printk("spdif:platform_device_alloc rk_soc-audio\n");
-               ret = -ENOMEM;
-               goto err2;
+#if defined (CONFIG_ARCH_RK30)    
+    #if defined (CONFIG_ARCH_RK3066B)
+    iomux_set(SPDIF_TX);
+    #else
+    rk30_mux_api_set(GPIO1B2_SPDIFTX_NAME, GPIO1B_SPDIF_TX);
+    #endif
+#elif defined (CONFIG_ARCH_RK3188)
+    iomux_set(SPDIF_TX);
+#endif
+
+
+       dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "spdif_dma");
+       if (!dma_res) {
+               printk("spdif:Unable to get dma resource.\n");
+               return -ENXIO;
+       }
+
+       mem_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "spdif_base");
+       if (!mem_res) {
+               printk("spdif:Unable to get register resource.\n");
+               return -ENXIO;
        }
+
+       spdif = &spdif_info;
+       spdif->dev = &pdev->dev;
+
+       spin_lock_init(&spdif->lock);
        
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
-       platform_set_drvdata(rk_snd_spdif_device, &rk_spdif);
-#else
-       platform_set_drvdata(rk_snd_spdif_device, &rk_spdif);
-       rk_spdif.dev = &rk_snd_spdif_device->dev;
+       spdif->clk = clk_get(&pdev->dev, "spdif");
+       if (IS_ERR(spdif->clk)) {
+               printk("spdif:failed to get internal source clock\n");
+               ret = -ENOENT;
+               goto err1;
+       }
+       clk_enable(spdif->clk);
+       clk_set_rate(spdif->clk, 11289600);
+       
+#if 1// defined (CONFIG_ARCH_RK30)     
+       spdif->hclk = clk_get(&pdev->dev, "hclk_spdif");
+       if (IS_ERR(spdif->hclk)) {
+               printk("spdif:failed to get spdif hclk\n");
+               ret = -ENOENT;
+               goto err0;
+       }
+       clk_enable(spdif->hclk);
+       clk_set_rate(spdif->hclk, 11289600);
 #endif
 
-       //platform_set_drvdata(rk_snd_spdif_device, &rk_spdif);
+       /* Request S/PDIF Register's memory region */
+       if (!request_mem_region(mem_res->start,
+                               resource_size(mem_res), "rockchip-spdif")) {
+               printk("spdif:Unable to request register region\n");
+               ret = -EBUSY;
+               goto err2;
+       }
 
-       ret = platform_device_add(rk_snd_spdif_device);
-       if (ret)
+       spdif->regs = ioremap(mem_res->start, mem_res->end - mem_res->start + 1);
+       if (spdif->regs == NULL) {
+               printk("spdif:Cannot ioremap registers\n");
+               ret = -ENXIO;
                goto err3;
+       }
+
+       dev_set_drvdata(&pdev->dev, spdif);
        
-       RK_SPDIF_DBG("rk_spdif_init ok\n");
-       return ret;
+       ret = snd_soc_register_dai(&pdev->dev, &rockchip_spdif_dai);
+       if (ret != 0) {
+               printk("spdif:fail to register dai\n");
+               goto err4;
+       }
+
+       spdif_stereo_out.dma_size = 4;
+       spdif_stereo_out.client = &spdif_dma_client_out;
+       spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF;
+       spdif_stereo_out.channel = dma_res->start;
+
+       spdif->dma_playback = &spdif_stereo_out;
+#ifdef CONFIG_SND_DMA_EVENT_STATIC
+       WARN_ON(rk29_dma_request(spdif_stereo_out.channel, spdif_stereo_out.client, NULL));
+#endif
+
+       RK_SPDIF_DBG("spdif:spdif probe ok!\n");
+       
+       return 0;
+
+err4:
+       iounmap(spdif->regs);
 err3:
-       platform_device_put(rk_snd_spdif_device);
+       release_mem_region(mem_res->start, resource_size(mem_res));
 err2:
-       platform_device_del(rk_snd_spdif_dit_device);
+       clk_disable(spdif->clk);
+       clk_put(spdif->clk);
 err1:
-       platform_device_put(rk_snd_spdif_dit_device);
-       
+       clk_disable(spdif->hclk);
+       clk_put(spdif->hclk);
+#if  1//defined (CONFIG_ARCH_RK30)     
+err0:
+#endif
        return ret;
 }
 
-static void __exit rk_spdif_exit(void)
+static __devexit int spdif_remove(struct platform_device *pdev)
 {
-       platform_device_unregister(rk_snd_spdif_device);
-       platform_device_unregister(rk_snd_spdif_dit_device);
+       struct rockchip_spdif_info *spdif = &spdif_info;
+       struct resource *mem_res;
+       
+       RK_SPDIF_DBG("Entered %s\n", __func__);
+       
+       snd_soc_unregister_dai(&pdev->dev);
+
+       iounmap(spdif->regs);
+
+       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (mem_res)
+               release_mem_region(mem_res->start, resource_size(mem_res));
+
+       clk_disable(spdif->clk);
+       clk_put(spdif->clk);
+       clk_disable(spdif->hclk);
+       clk_put(spdif->hclk);
+
+       return 0;
+}
+
+
+static struct platform_driver rockchip_spdif_driver = {
+       .probe  = spdif_probe,
+       .remove = spdif_remove,
+       .driver = {
+               .name   = "rk-spdif",
+               .owner  = THIS_MODULE,
+       },
+};
+
+
+static int __init spdif_init(void)
+{
+       RK_SPDIF_DBG("Entered %s\n", __func__);
+       return platform_driver_register(&rockchip_spdif_driver);
 }
+module_init(spdif_init);
 
-//using late_initcall to make sure spdif is after board codec. added by zxg.
-//module_init(rk_spdif_init);
-late_initcall(rk_spdif_init);
-module_exit(rk_spdif_exit);
+static void __exit spdif_exit(void)
+{
+       RK_SPDIF_DBG("Entered %s\n", __func__);
+       platform_driver_unregister(&rockchip_spdif_driver);
+}
+module_exit(spdif_exit);
 
-MODULE_AUTHOR("hzb, <hzb@rock-chips.com>");
-MODULE_DESCRIPTION("ALSA SoC RK+S/PDIF");
+MODULE_AUTHOR("Seungwhan Youn, <sw.youn@rockchip.com>");
+MODULE_DESCRIPTION("rockchip S/PDIF Controller Driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:rockchip-spdif");
diff --git a/sound/soc/rk29/spdif.c b/sound/soc/rk29/spdif.c
deleted file mode 100644 (file)
index 9537160..0000000
+++ /dev/null
@@ -1,489 +0,0 @@
-/*$_FOR_ROCKCHIP_RBOX_$*/
-/*$_rbox_$_modify_$_huangzhibao for spdif output*/
-
-/* sound/soc/rockchip/spdif.c
- *
- * ALSA SoC Audio Layer - rockchip S/PDIF Controller driver
- *
- * Copyright (c) 2010 rockchip Electronics Co. Ltd
- *             http://www.rockchip.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/version.h>
-
-#include <asm/dma.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
-#include <sound/soc.h>
-#include <asm/io.h>
-
-#include <mach/board.h>
-#include <mach/hardware.h>
-#include <mach/io.h>
-#include <mach/gpio.h>
-#include <mach/iomux.h>
-
-#if defined (CONFIG_ARCH_RK29)
-#include <mach/rk29-dma-pl330.h>
-#endif
-
-#if defined (CONFIG_ARCH_RK30)
-#include <mach/dma-pl330.h>
-#endif
-
-#if defined (CONFIG_ARCH_RK3188)
-#include <mach/dma-pl330.h>
-#endif
-
-#include "rk29_pcm.h"
-#include "spdif.h"
-
-#if 1
-#define RK_SPDIF_DBG(x...) printk(KERN_INFO "spdif:"x)
-#else
-#define RK_SPDIF_DBG(x...) do { } while (0)
-#endif
-
-
-/* Registers */
-#define CFGR                           0x00
-#define SDBLR                          0x04
-#define DMACR                          0x08
-#define INTCR                          0x0C
-#define INTSR                    0x10
-#define XFER                           0x18
-#define SMPDR                          0x20
-
-#define DATA_OUTBUF                    0x20   
-#define CFGR_MASK                      0x0ffffff
-#define CFGR_VALID_DATA_16bit       (00)
-#define CFGR_VALID_DATA_20bit       (01)
-#define CFGR_VALID_DATA_24bit       (10)
-#define CFGR_VALID_DATA_MASK        (11)
-
-#define CFGR_HALFWORD_TX_ENABLE     (0x1 << 2)
-#define CFGR_HALFWORD_TX_DISABLE    (0x0 << 2)
-#define CFGR_HALFWORD_TX_MASK       (0x1 << 2)  
-
-#define CFGR_CLK_RATE_MASK          (0xFF<<16)                 
-
-#define CFGR_JUSTIFIED_RIGHT        (0<<3)
-#define CFGR_JUSTIFIED_LEFT         (1<<3)
-#define CFGR_JUSTIFIED_MASK         (1<<3)
-
-#define XFER_TRAN_STOP        (0)
-#define XFER_TRAN_START       (1)
-#define XFER_MASK             (1)
-
-#define DMACR_TRAN_DMA_DISABLE   (0<<5)
-#define DMACR_TRAN_DMA_ENABLE   (1<<5)
-#define DMACR_TRAN_DMA_CTL_MASK   (1<<5)
-
-#define DMACR_TRAN_DATA_LEVEL       0x10
-#define DMACR_TRAN_DATA_LEVEL_MASK  0x1F
-
-#define DMACR_TRAN_DMA_MASK   (0x3F)
-
-
-struct rockchip_spdif_info {
-       spinlock_t      lock;
-       struct device   *dev;
-       void __iomem    *regs;
-       unsigned long   clk_rate;
-       struct clk      *hclk;
-       struct clk      *clk;
-       u32             saved_clkcon;
-       u32             saved_con;
-       u32             saved_cstas;
-       struct rockchip_pcm_dma_params  *dma_playback;
-};
-
-static struct rk29_dma_client spdif_dma_client_out = {
-       .name           = "SPDIF Stereo out"
-};
-
-static struct rockchip_pcm_dma_params spdif_stereo_out;
-
-static struct rockchip_spdif_info spdif_info;
-
-static inline struct rockchip_spdif_info *to_info(struct snd_soc_dai *cpu_dai)
-{
-       return snd_soc_dai_get_drvdata(cpu_dai);
-}
-
-static void spdif_snd_txctrl(struct rockchip_spdif_info *spdif, int on)
-{
-       void __iomem *regs = spdif->regs;
-       u32 opr,xfer;
-
-       RK_SPDIF_DBG( "Entered %s\n", __func__);
-
-       xfer = readl(regs + XFER) & XFER_MASK;
-       opr  = readl(regs + DMACR) & DMACR_TRAN_DMA_MASK & (~DMACR_TRAN_DMA_CTL_MASK);
-       
-       if (on){
-               xfer |= XFER_TRAN_START;
-               opr |= DMACR_TRAN_DMA_ENABLE;
-               writel(xfer, regs + XFER);
-               writel(opr|0x10, regs + DMACR);
-               RK_SPDIF_DBG("on xfer=0x%x,opr=0x%x\n",readl(regs + XFER),readl(regs + DMACR));
-  }    else{
-       xfer &= ~XFER_TRAN_START;
-       opr  &= ~DMACR_TRAN_DMA_ENABLE; 
-               writel(xfer, regs + XFER);
-               writel(opr|0x10, regs + DMACR);
-  }
-}
-
-static int spdif_set_syclk(struct snd_soc_dai *cpu_dai,
-                               int clk_id, unsigned int freq, int dir)
-{
-       struct rockchip_spdif_info *spdif = to_info(cpu_dai);
-       u32 clkcon;
-
-       RK_SPDIF_DBG("Entered %s\n", __func__);
-
-       spdif->clk_rate = freq;
-
-       return 0;
-}
-
-static int spdif_trigger(struct snd_pcm_substream *substream, int cmd,
-                               struct snd_soc_dai *dai)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct rockchip_spdif_info *spdif = to_info(rtd->cpu_dai);
-       unsigned long flags;
-
-       RK_SPDIF_DBG( "Entered %s\n", __func__);
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-       case SNDRV_PCM_TRIGGER_RESUME:
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               spin_lock_irqsave(&spdif->lock, flags);
-               spdif_snd_txctrl(spdif, 1);
-               spin_unlock_irqrestore(&spdif->lock, flags);
-               break;
-       case SNDRV_PCM_TRIGGER_STOP:
-       case SNDRV_PCM_TRIGGER_SUSPEND:
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               spin_lock_irqsave(&spdif->lock, flags);
-               spdif_snd_txctrl(spdif, 0);
-               spin_unlock_irqrestore(&spdif->lock, flags);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-
-static int spdif_hw_params(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *params,
-                               struct snd_soc_dai *socdai)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct rockchip_spdif_info *spdif = to_info(rtd->cpu_dai);
-       void __iomem *regs = spdif->regs;
-       struct rockchip_pcm_dma_params *dma_data;
-       unsigned long flags;
-       int i, cfgr, dmac;
-
-       RK_SPDIF_DBG("Entered %s\n", __func__);
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               dma_data = spdif->dma_playback;
-       else {
-               printk("spdif:Capture is not supported\n");
-               return -EINVAL;
-       }
-
-       snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data);
-       spin_lock_irqsave(&spdif->lock, flags);
-       
-       cfgr = readl(regs + CFGR) & CFGR_VALID_DATA_MASK;
-       
-  cfgr &= ~CFGR_VALID_DATA_MASK;
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
-               cfgr |= CFGR_VALID_DATA_16bit;
-               break;
-       case SNDRV_PCM_FMTBIT_S20_3LE :
-               cfgr |= CFGR_VALID_DATA_20bit;
-               break;
-       case SNDRV_PCM_FORMAT_S24_LE:
-               cfgr |= CFGR_VALID_DATA_24bit;
-               break;                  
-       default:
-               goto err;
-       }
-       
-       cfgr &= ~CFGR_HALFWORD_TX_MASK;
-       cfgr |= CFGR_HALFWORD_TX_ENABLE;
-       
-       cfgr &= ~CFGR_CLK_RATE_MASK;
-       cfgr |= (1<<16);
-       
-       cfgr &= ~CFGR_JUSTIFIED_MASK;
-       cfgr |= CFGR_JUSTIFIED_RIGHT;
-       
-       writel(cfgr, regs + CFGR);
-  
-  dmac = readl(regs + DMACR) & DMACR_TRAN_DMA_MASK & (~DMACR_TRAN_DATA_LEVEL_MASK);
-  dmac |= 0x10;
-  writel(dmac, regs + DMACR);
-  
-       spin_unlock_irqrestore(&spdif->lock, flags);
-
-       return 0;
-err:
-       spin_unlock_irqrestore(&spdif->lock, flags);
-       return -EINVAL;
-}
-
-static void spdif_shutdown(struct snd_pcm_substream *substream,
-                               struct snd_soc_dai *dai)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct rockchip_spdif_info *spdif = to_info(rtd->cpu_dai);
-       void __iomem *regs = spdif->regs;
-       u32 con, clkcon;
-
-       RK_SPDIF_DBG( "spdif:Entered %s\n", __func__);
-
-}
-
-#ifdef CONFIG_PM
-static int spdif_suspend(struct snd_soc_dai *cpu_dai)
-{
-       struct rockchip_spdif_info *spdif = to_info(cpu_dai);
-       u32 con = spdif->saved_con;
-
-       RK_SPDIF_DBG( "spdif:Entered %s\n", __func__);
-
-       return 0;
-}
-
-static int spdif_resume(struct snd_soc_dai *cpu_dai)
-{
-       struct rockchip_spdif_info *spdif = to_info(cpu_dai);
-
-       RK_SPDIF_DBG( "spdif:Entered %s\n", __func__);
-
-       return 0;
-}
-#else
-#define spdif_suspend NULL
-#define spdif_resume NULL
-#endif
-
-static struct snd_soc_dai_ops spdif_dai_ops = {
-       .set_sysclk     = spdif_set_syclk,
-       .trigger        = spdif_trigger,
-       .hw_params      = spdif_hw_params,
-       .shutdown       = spdif_shutdown,
-};
-
-struct snd_soc_dai_driver rockchip_spdif_dai = {
-       .name = "rk-spdif",
-       .playback = {
-               .stream_name = "SPDIF Playback",
-               .channels_min = 2,
-               .channels_max = 2,
-               .rates = (SNDRV_PCM_RATE_32000 |
-                               SNDRV_PCM_RATE_44100 |
-                               SNDRV_PCM_RATE_48000 |
-                               SNDRV_PCM_RATE_96000),
-               .formats = SNDRV_PCM_FMTBIT_S16_LE|
-               SNDRV_PCM_FMTBIT_S20_3LE|
-               SNDRV_PCM_FMTBIT_S24_LE, },
-       .ops = &spdif_dai_ops,
-       .suspend = spdif_suspend,
-       .resume = spdif_resume,
-};
-
-
-static __devinit int spdif_probe(struct platform_device *pdev)
-{
-       struct s3c_audio_pdata *spdif_pdata;
-       struct resource *mem_res, *dma_res;
-       struct rockchip_spdif_info *spdif;
-       int ret;
-  
-       spdif_pdata = pdev->dev.platform_data;
-
-       RK_SPDIF_DBG("Entered %s\n", __func__);
-       
-#if defined  (CONFIG_ARCH_RK29)
-    rk29_mux_api_set(GPIO4A7_SPDIFTX_NAME, GPIO4L_SPDIF_TX);
-#endif
-
-#if defined (CONFIG_ARCH_RK30)    
-    #if defined (CONFIG_ARCH_RK3066B)
-    iomux_set(SPDIF_TX);
-    #else
-    rk30_mux_api_set(GPIO1B2_SPDIFTX_NAME, GPIO1B_SPDIF_TX);
-    #endif
-#elif defined (CONFIG_ARCH_RK3188)
-    iomux_set(SPDIF_TX);
-#endif
-
-
-       dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "spdif_dma");
-       if (!dma_res) {
-               printk("spdif:Unable to get dma resource.\n");
-               return -ENXIO;
-       }
-
-       mem_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "spdif_base");
-       if (!mem_res) {
-               printk("spdif:Unable to get register resource.\n");
-               return -ENXIO;
-       }
-
-       spdif = &spdif_info;
-       spdif->dev = &pdev->dev;
-
-       spin_lock_init(&spdif->lock);
-       
-       spdif->clk = clk_get(&pdev->dev, "spdif");
-       if (IS_ERR(spdif->clk)) {
-               printk("spdif:failed to get internal source clock\n");
-               ret = -ENOENT;
-               goto err1;
-       }
-       clk_enable(spdif->clk);
-       clk_set_rate(spdif->clk, 11289600);
-       
-#if 1// defined (CONFIG_ARCH_RK30)     
-       spdif->hclk = clk_get(&pdev->dev, "hclk_spdif");
-       if (IS_ERR(spdif->hclk)) {
-               printk("spdif:failed to get spdif hclk\n");
-               ret = -ENOENT;
-               goto err0;
-       }
-       clk_enable(spdif->hclk);
-       clk_set_rate(spdif->hclk, 11289600);
-#endif
-
-       /* Request S/PDIF Register's memory region */
-       if (!request_mem_region(mem_res->start,
-                               resource_size(mem_res), "rockchip-spdif")) {
-               printk("spdif:Unable to request register region\n");
-               ret = -EBUSY;
-               goto err2;
-       }
-
-       spdif->regs = ioremap(mem_res->start, mem_res->end - mem_res->start + 1);
-       if (spdif->regs == NULL) {
-               printk("spdif:Cannot ioremap registers\n");
-               ret = -ENXIO;
-               goto err3;
-       }
-
-       dev_set_drvdata(&pdev->dev, spdif);
-       
-       ret = snd_soc_register_dai(&pdev->dev, &rockchip_spdif_dai);
-       if (ret != 0) {
-               printk("spdif:fail to register dai\n");
-               goto err4;
-       }
-
-       spdif_stereo_out.dma_size = 4;
-       spdif_stereo_out.client = &spdif_dma_client_out;
-       spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF;
-       spdif_stereo_out.channel = dma_res->start;
-
-       spdif->dma_playback = &spdif_stereo_out;
-#ifdef CONFIG_SND_DMA_EVENT_STATIC
-       WARN_ON(rk29_dma_request(spdif_stereo_out.channel, spdif_stereo_out.client, NULL));
-#endif
-
-       RK_SPDIF_DBG("spdif:spdif probe ok!\n");
-       
-       return 0;
-
-err4:
-       iounmap(spdif->regs);
-err3:
-       release_mem_region(mem_res->start, resource_size(mem_res));
-err2:
-       clk_disable(spdif->clk);
-       clk_put(spdif->clk);
-err1:
-       clk_disable(spdif->hclk);
-       clk_put(spdif->hclk);
-#if  1//defined (CONFIG_ARCH_RK30)     
-err0:
-#endif
-       return ret;
-}
-
-static __devexit int spdif_remove(struct platform_device *pdev)
-{
-       struct rockchip_spdif_info *spdif = &spdif_info;
-       struct resource *mem_res;
-       
-       RK_SPDIF_DBG("Entered %s\n", __func__);
-       
-       snd_soc_unregister_dai(&pdev->dev);
-
-       iounmap(spdif->regs);
-
-       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (mem_res)
-               release_mem_region(mem_res->start, resource_size(mem_res));
-
-       clk_disable(spdif->clk);
-       clk_put(spdif->clk);
-       clk_disable(spdif->hclk);
-       clk_put(spdif->hclk);
-
-       return 0;
-}
-
-
-static struct platform_driver rockchip_spdif_driver = {
-       .probe  = spdif_probe,
-       .remove = spdif_remove,
-       .driver = {
-               .name   = "rk-spdif",
-               .owner  = THIS_MODULE,
-       },
-};
-
-
-static int __init spdif_init(void)
-{
-       RK_SPDIF_DBG("Entered %s\n", __func__);
-       return platform_driver_register(&rockchip_spdif_driver);
-}
-module_init(spdif_init);
-
-static void __exit spdif_exit(void)
-{
-       RK_SPDIF_DBG("Entered %s\n", __func__);
-       platform_driver_unregister(&rockchip_spdif_driver);
-}
-module_exit(spdif_exit);
-
-MODULE_AUTHOR("Seungwhan Youn, <sw.youn@rockchip.com>");
-MODULE_DESCRIPTION("rockchip S/PDIF Controller Driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:rockchip-spdif");
diff --git a/sound/soc/rk29/spdif.h b/sound/soc/rk29/spdif.h
deleted file mode 100644 (file)
index d669f7d..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*$_FOR_ROCKCHIP_RBOX_$*/
-/*$_rbox_$_modify_$_huangzhibao for spdif output*/
-
-/*
- *
- * ALSA SoC Audio Layer - 
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __SND_SOC_SAMSUNG_SPDIF_H
-#define __SND_SOC_SAMSUNG_SPDIF_H      __FILE__
-
-
-#endif /* __SND_SOC_RK_SPDIF_H */