From b6786cda0adeeacc6404aa4b71163f369e369977 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=99=88=E9=87=91=E6=B3=89?= Date: Fri, 21 Jun 2013 10:21:21 +0800 Subject: [PATCH] Add sound card 1 for HDMI i2s, RK616 codec:add path for tiny alsa --- arch/arm/configs/rk3168m_tb_defconfig | 3 +- arch/arm/configs/rk3188_jettaplus_defconfig | 4 +- arch/arm/configs/rk3188m_tb_defconfig | 3 +- .../rockchip/hdmi/chips/rk616/rk616_hdmi.h | 5 + sound/soc/codecs/Kconfig | 8 +- sound/soc/codecs/Makefile | 6 +- sound/soc/codecs/hdmi_i2s.c | 101 ++++ .../{spdif_transciever.c => hdmi_spdif.c} | 0 sound/soc/codecs/rk616_codec.c | 279 +++++++++- sound/soc/codecs/rk616_codec.h | 21 + sound/soc/rk29/Kconfig | 49 +- sound/soc/rk29/Makefile | 14 +- sound/soc/rk29/rk_hdmi_i2s.c | 151 +++++ sound/soc/rk29/rk_hdmi_spdif.c | 186 +++++++ sound/soc/rk29/rk_spdif.c | 526 ++++++++++++++---- sound/soc/rk29/spdif.c | 489 ---------------- sound/soc/rk29/spdif.h | 18 - 17 files changed, 1177 insertions(+), 686 deletions(-) create mode 100644 sound/soc/codecs/hdmi_i2s.c rename sound/soc/codecs/{spdif_transciever.c => hdmi_spdif.c} (100%) create mode 100644 sound/soc/rk29/rk_hdmi_i2s.c create mode 100644 sound/soc/rk29/rk_hdmi_spdif.c delete mode 100644 sound/soc/rk29/spdif.c delete mode 100644 sound/soc/rk29/spdif.h diff --git a/arch/arm/configs/rk3168m_tb_defconfig b/arch/arm/configs/rk3168m_tb_defconfig index 9e64d950b02b..7e1c2603b2f6 100644 --- a/arch/arm/configs/rk3168m_tb_defconfig +++ b/arch/arm/configs/rk3168m_tb_defconfig @@ -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 diff --git a/arch/arm/configs/rk3188_jettaplus_defconfig b/arch/arm/configs/rk3188_jettaplus_defconfig index 2d37e9eb75ce..469c9ca9fded 100644 --- a/arch/arm/configs/rk3188_jettaplus_defconfig +++ b/arch/arm/configs/rk3188_jettaplus_defconfig @@ -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 diff --git a/arch/arm/configs/rk3188m_tb_defconfig b/arch/arm/configs/rk3188m_tb_defconfig index b1f657bd2c78..c32e63319d10 100644 --- a/arch/arm/configs/rk3188m_tb_defconfig +++ b/arch/arm/configs/rk3188m_tb_defconfig @@ -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 diff --git a/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.h b/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.h index 97362b4bbf75..7fcd7f6da6f9 100755 --- a/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.h +++ b/drivers/video/rockchip/hdmi/chips/rk616/rk616_hdmi.h @@ -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), diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 3889aff2bd7f..04e27b2582a0 100755 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -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 diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 62292a90224e..813ae0a47522 100755 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -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 index 000000000000..c923d656a4cc --- /dev/null +++ b/sound/soc/codecs/hdmi_i2s.c @@ -0,0 +1,101 @@ +/* + * hdmi_i2s.c -- HDMI i2s audio for rockchip + * + * Copyright 2013 Rockship + * Author: chenjq + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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/spdif_transciever.c b/sound/soc/codecs/hdmi_spdif.c similarity index 100% rename from sound/soc/codecs/spdif_transciever.c rename to sound/soc/codecs/hdmi_spdif.c diff --git a/sound/soc/codecs/rk616_codec.c b/sound/soc/codecs/rk616_codec.c index 14ba97633fbf..67d905557175 100755 --- a/sound/soc/codecs/rk616_codec.c +++ b/sound/soc/codecs/rk616_codec.c @@ -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, diff --git a/sound/soc/codecs/rk616_codec.h b/sound/soc/codecs/rk616_codec.h index c1342e63f394..a541fd63c77d 100755 --- a/sound/soc/codecs/rk616_codec.h +++ b/sound/soc/codecs/rk616_codec.h @@ -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/rk29/Kconfig b/sound/soc/rk29/Kconfig index f311a74e62d6..9a809966f77a 100755 --- a/sound/soc/rk29/Kconfig +++ b/sound/soc/rk29/Kconfig @@ -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 diff --git a/sound/soc/rk29/Makefile b/sound/soc/rk29/Makefile index 728bdae8dcde..ddd5806241d6 100755 --- a/sound/soc/rk29/Makefile +++ b/sound/soc/rk29/Makefile @@ -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 index 000000000000..a41c0bd13ea3 --- /dev/null +++ b/sound/soc/rk29/rk_hdmi_i2s.c @@ -0,0 +1,151 @@ +/* + * rk_hdmi_i2s.c -- HDMI i2s audio for rockchip + * + * Copyright 2013 Rockship + * Author: chenjq + */ + +#include +#include +#include + +#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 index 000000000000..0e69efc164d4 --- /dev/null +++ b/sound/soc/rk29/rk_hdmi_spdif.c @@ -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 + +#include + +#include + +#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, "); +MODULE_DESCRIPTION("ALSA SoC RK+S/PDIF"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk29/rk_spdif.c b/sound/soc/rk29/rk_spdif.c index 6ec311ed63bd..d3eedba78680 100644 --- a/sound/soc/rk29/rk_spdif.c +++ b/sound/soc/rk29/rk_spdif.c @@ -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 +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include #include +#include -#include "spdif.h" +#include +#include +#include +#include #include +#if defined (CONFIG_ARCH_RK29) +#include +#endif + +#if defined (CONFIG_ARCH_RK30) +#include +#endif + +#if defined (CONFIG_ARCH_RK3188) +#include +#endif + +#include "rk29_pcm.h" + #if 0 #define RK_SPDIF_DBG(x...) printk(KERN_INFO "rk_spdif:"x) #else @@ -27,160 +56,433 @@ #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, "); -MODULE_DESCRIPTION("ALSA SoC RK+S/PDIF"); +MODULE_AUTHOR("Seungwhan Youn, "); +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 index 953716087d6f..000000000000 --- a/sound/soc/rk29/spdif.c +++ /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 -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#if defined (CONFIG_ARCH_RK29) -#include -#endif - -#if defined (CONFIG_ARCH_RK30) -#include -#endif - -#if defined (CONFIG_ARCH_RK3188) -#include -#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, "); -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 index d669f7defa8e..000000000000 --- a/sound/soc/rk29/spdif.h +++ /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 */ -- 2.34.1