From: 陈金泉 Date: Tue, 21 Jan 2014 09:24:35 +0000 (+0800) Subject: update codec driver X-Git-Tag: firefly_0821_release~6375 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=53d00cb8c38af426565fa5618a57fba1f43064a4;p=firefly-linux-kernel-4.4.55.git update codec driver --- diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 2f45f00e31b0..998c628c479d 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -42,6 +42,8 @@ config SND_SOC_ALL_CODECS select SND_SOC_DA9055 if I2C select SND_SOC_DFBMCS320 select SND_SOC_ISABELLE if I2C + select SND_SOC_ES8323 if SND_SOC_I2C_AND_SPI + select SND_SOC_ES8323_PCM if SND_SOC_I2C_AND_SPI select SND_SOC_JZ4740_CODEC select SND_SOC_LM4857 if I2C select SND_SOC_LM49453 if I2C @@ -55,11 +57,12 @@ config SND_SOC_ALL_CODECS select SND_SOC_ML26124 if I2C select SND_SOC_OMAP_HDMI_CODEC if OMAP4_DSS_HDMI select SND_SOC_PCM3008 - select SND_SOC_RT5631 if I2C select SND_SOC_SGTL5000 if I2C select SND_SOC_SI476X if MFD_SI476X_CORE 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_STA32X if I2C select SND_SOC_STA529 if I2C @@ -71,6 +74,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_TLV320AIC3X if I2C select SND_SOC_TPA6130A2 if I2C select SND_SOC_TLV320DAC33 if I2C + select SND_SOC_TLV320AIC3111 if I2C select SND_SOC_TWL4030 if TWL4030_CORE select SND_SOC_TWL6040 if TWL6040_CORE select SND_SOC_UDA134X @@ -101,6 +105,20 @@ config SND_SOC_ALL_CODECS select SND_SOC_WM8782 select SND_SOC_WM8804 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8900 if I2C + select SND_SOC_RT5621 if I2C + select SND_SOC_RT5631 if I2C + select SND_SOC_AK4396 if SPI_MASTER + select SND_SOC_RT5631_PHONE if I2C + select SND_SOC_RT5625 if I2C + select SND_SOC_RT5640 if I2C + select SND_SOC_RT3261 if I2C + select SND_SOC_RT3224 if I2C + select SND_SOC_RT5623 if I2C + select SND_SOC_RT5639 if I2C + select SND_SOC_RT5616 if I2C + select SND_SOC_RT5512 if I2C + select SND_SOC_RK610 if I2C + select SND_SOC_RK616 if I2C select SND_SOC_WM8903 if I2C && GENERIC_HARDIRQS select SND_SOC_WM8904 if I2C select SND_SOC_WM8940 if I2C @@ -269,6 +287,9 @@ config SND_SOC_DFBMCS320 config SND_SOC_DMIC tristate +config SND_SOC_ES8323 + tristate + config SND_SOC_ISABELLE tristate @@ -293,9 +314,6 @@ config SND_SOC_OMAP_HDMI_CODEC config SND_SOC_PCM3008 tristate -config SND_SOC_RT5631 - tristate - #Freescale sgtl5000 codec config SND_SOC_SGTL5000 tristate @@ -310,9 +328,13 @@ config SND_SOC_SIGMADSP 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 tristate @@ -344,6 +366,9 @@ config SND_SOC_TLV320AIC3X config SND_SOC_TLV320DAC33 tristate +config SND_SOC_TLV320AIC3111 + tristate + config SND_SOC_TWL4030 select MFD_TWL4030_AUDIO tristate @@ -435,6 +460,42 @@ config SND_SOC_WM8804 config SND_SOC_WM8900 tristate +config SND_SOC_RT5621 + tristate + +config SND_SOC_RT5623 + tristate + +config SND_SOC_RT5639 + tristate + +config SND_SOC_RT5616 + tristate + +config SND_SOC_AK4396 + tristate + +config SND_SOC_RT5631 + tristate + +config SND_SOC_RT5631_PHONE + tristate + +config SND_SOC_RT5625 + tristate + +config SND_SOC_RT5640 + select SND_HWDEP + tristate + +config SND_SOC_RT3224 + select SND_HWDEP + tristate + +config SND_SOC_RT3261 + select SND_HWDEP + tristate + config SND_SOC_WM8903 tristate @@ -507,6 +568,31 @@ config SND_SOC_WM9712 config SND_SOC_WM9713 tristate +config SND_SOC_RK1000 + tristate +# depends on RK1000_CONTROL + +config SND_SOC_RK610 + tristate + depends on MFD_RK610 + +config SND_SOC_RK616 + tristate + depends on MFD_RK616 + +config SND_SOC_RK2928 + tristate + depends on ARCH_RK2928 + +config SND_SOC_RK3026 + tristate + depends on ARCH_RK3026 + +config SND_SOC_RK3190 + tristate + #depends on ARCH_RK3190 + + # Amp config SND_SOC_LM4857 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index b9e41c9a1f4c..4cbe4959ae2b 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -29,6 +29,8 @@ snd-soc-da732x-objs := da732x.o snd-soc-da9055-objs := da9055.o snd-soc-dfbmcs320-objs := dfbmcs320.o snd-soc-dmic-objs := dmic.o +snd-soc-es8323-objs := es8323.o +snd-soc-es8323-pcm-objs := es8323_pcm.o snd-soc-isabelle-objs := isabelle.o snd-soc-jz4740-codec-objs := jz4740.o snd-soc-l3-objs := l3.o @@ -50,8 +52,8 @@ snd-soc-alc5632-objs := alc5632.o snd-soc-sigmadsp-objs := sigmadsp.o snd-soc-si476x-objs := si476x.o snd-soc-sn95031-objs := sn95031.o -snd-soc-spdif-tx-objs := spdif_transciever.o -snd-soc-spdif-rx-objs := spdif_receiver.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-sta32x-objs := sta32x.o snd-soc-sta529-objs := sta529.o @@ -61,6 +63,7 @@ snd-soc-tlv320aic23-objs := tlv320aic23.o snd-soc-tlv320aic26-objs := tlv320aic26.o snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o +snd-soc-tlv320aic3111-objs := tlv320aic3111.o snd-soc-tlv320dac33-objs := tlv320dac33.o snd-soc-twl4030-objs := twl4030.o snd-soc-twl6040-objs := twl6040.o @@ -93,6 +96,14 @@ snd-soc-wm8776-objs := wm8776.o snd-soc-wm8782-objs := wm8782.o snd-soc-wm8804-objs := wm8804.o snd-soc-wm8900-objs := wm8900.o +snd-soc-rt5621-objs := rt5621.o +snd-soc-rt5623-objs := rt5623.o +snd-soc-rt5631-objs := rt5631.o +snd-soc-ak4396-objs := ak4396.o +snd-soc-rt5616-objs := rt5616.o +snd-soc-rt5631-phone-objs := rt5631_phone.o +snd-soc-rt5625-objs := rt5625.o +snd-soc-cs42l52-objs := cs42l52.o snd-soc-wm8903-objs := wm8903.o snd-soc-wm8904-objs := wm8904.o snd-soc-wm8996-objs := wm8996.o @@ -118,11 +129,26 @@ snd-soc-wm9705-objs := wm9705.o snd-soc-wm9712-objs := wm9712.o snd-soc-wm9713-objs := wm9713.o snd-soc-wm-hubs-objs := wm_hubs.o +snd-soc-rk1000-objs := rk1000_codec.o +snd-soc-jz4740-codec-objs := jz4740.o +snd-soc-rk610-objs := rk610_codec.o +snd-soc-rk616-objs := rk616_codec.o +snd-soc-rt5640-objs := rt5640.o rt5640-dsp.o rt5640_ioctl.o rt56xx_ioctl.o +snd-soc-rt3261-objs := rt3261.o rt3261-dsp.o rt3261_ioctl.o rt_codec_ioctl.o +snd-soc-rt3224-objs := rt3261.o rt3261_ioctl.o rt_codec_ioctl.o +snd-soc-rk2928-objs := rk2928_codec.o +snd-soc-rk3026-objs := rk3026_codec.o +snd-soc-rk3190-objs := rk3190_codec.o +snd-soc-rt5639-objs := rt5639.o rt5639_ioctl.o rt56xx_ioctl.o # Amp snd-soc-max9877-objs := max9877.o snd-soc-tpa6130a2-objs := tpa6130a2.o +obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o +obj-$(CONFIG_SND_SOC_RT3261) += snd-soc-rt3261.o +obj-$(CONFIG_SND_SOC_RT3224) += snd-soc-rt3224.o +obj-$(CONFIG_SND_SOC_RT5639) += snd-soc-rt5639.o obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o @@ -156,6 +182,8 @@ obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o +obj-$(CONFIG_SND_SOC_ES8323) += snd-soc-es8323.o +obj-$(CONFIG_SND_SOC_ES8323_PCM) += snd-soc-es8323-pcm.o obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o @@ -175,7 +203,8 @@ obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o -obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.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_STA32X) += snd-soc-sta32x.o obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o @@ -185,6 +214,7 @@ obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o +obj-$(CONFIG_SND_SOC_TLV320AIC3111) += snd-soc-tlv320aic3111.o obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o @@ -216,6 +246,14 @@ obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o obj-$(CONFIG_SND_SOC_WM8782) += snd-soc-wm8782.o obj-$(CONFIG_SND_SOC_WM8804) += snd-soc-wm8804.o obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o +obj-$(CONFIG_SND_SOC_RT5621) += snd-soc-rt5621.o +obj-$(CONFIG_SND_SOC_RT5623) += snd-soc-rt5623.o +obj-$(CONFIG_SND_SOC_AK4396) += snd-soc-ak4396.o +obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o +obj-$(CONFIG_SND_SOC_RT5616) += snd-soc-rt5616.o +obj-$(CONFIG_SND_SOC_RT5631_PHONE) += snd-soc-rt5631-phone.o +obj-$(CONFIG_SND_SOC_RT5625) += snd-soc-rt5625.o +obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o obj-$(CONFIG_SND_SOC_WM8904) += snd-soc-wm8904.o obj-$(CONFIG_SND_SOC_WM8996) += snd-soc-wm8996.o @@ -242,6 +280,13 @@ obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o obj-$(CONFIG_SND_SOC_WM_ADSP) += snd-soc-wm-adsp.o obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o +obj-$(CONFIG_SND_SOC_RK1000) += snd-soc-rk1000.o +obj-$(CONFIG_SND_SOC_RK610) += snd-soc-rk610.o +obj-$(CONFIG_SND_SOC_RK616) += snd-soc-rk616.o +obj-$(CONFIG_SND_SOC_RK2928) += snd-soc-rk2928.o +obj-$(CONFIG_SND_SOC_RK3026) += snd-soc-rk3026.o +obj-$(CONFIG_SND_SOC_RK3190) += snd-soc-rk3190.o +obj-$(CONFIG_SND_SOC_RT5512) += snd-soc-rt5512.o # Amp obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o diff --git a/sound/soc/codecs/cx2070x.c b/sound/soc/codecs/cx2070x.c index 3fe2141fb713..47e6dfd9aab1 100755 --- a/sound/soc/codecs/cx2070x.c +++ b/sound/soc/codecs/cx2070x.c @@ -902,7 +902,7 @@ static int cx2070x_add_controls(struct snd_soc_codec *codec) { INFO("%lu: %s() called\n",jiffies,__func__); - return (snd_soc_add_controls(codec, cx2070x_snd_controls, ARRAY_SIZE(cx2070x_snd_controls))); + return (snd_soc_add_codec_controls(codec, cx2070x_snd_controls, ARRAY_SIZE(cx2070x_snd_controls))); } static int hpportpga_event(struct snd_soc_dapm_widget *w, @@ -1785,7 +1785,7 @@ static int NOINLINE cx2070x_init(struct snd_soc_codec* codec) //cx2070x_add_controls(codec); //cx2070x_add_widgets(codec); - snd_soc_add_controls(codec, cx2070x_snd_path_controls, + snd_soc_add_codec_controls(codec, cx2070x_snd_path_controls, ARRAY_SIZE(cx2070x_snd_path_controls)); //snd_soc_dapm_nc_pin(&codec->dapm, "LINE IN"); diff --git a/sound/soc/codecs/es8323.c b/sound/soc/codecs/es8323.c index cbbe3a911160..344796e6a70a 100755 --- a/sound/soc/codecs/es8323.c +++ b/sound/soc/codecs/es8323.c @@ -1126,7 +1126,7 @@ snd_soc_write(codec, 0x04,0x2c); //pdn_ana=0,ibiasgen_pdn=0 //s8323_set_bias_level(codec, SND_SOC_BIAS_STANDBY); //codec->dapm.bias_level = SND_SOC_BIAS_STANDBY; - snd_soc_add_controls(codec, es8323_snd_controls, + snd_soc_add_codec_controls(codec, es8323_snd_controls, ARRAY_SIZE(es8323_snd_controls)); snd_soc_dapm_new_controls(dapm, es8323_dapm_widgets, ARRAY_SIZE(es8323_dapm_widgets)); @@ -1191,7 +1191,7 @@ static struct snd_soc_codec_driver soc_codec_dev_es8323 = { }; #if defined(CONFIG_SPI_MASTER) -static int __devinit es8323_spi_probe(struct spi_device *spi) +static int es8323_spi_probe(struct spi_device *spi) { struct es8323_priv *es8323; int ret; @@ -1210,7 +1210,7 @@ static int __devinit es8323_spi_probe(struct spi_device *spi) return ret; } -static int __devexit es8323_spi_remove(struct spi_device *spi) +static int es8323_spi_remove(struct spi_device *spi) { snd_soc_unregister_codec(&spi->dev); kfree(spi_get_drvdata(spi)); @@ -1223,7 +1223,7 @@ static struct spi_driver es8323_spi_driver = { .owner = THIS_MODULE, }, .probe = es8323_spi_probe, - .remove = __devexit_p(es8323_spi_remove), + .remove = es8323_spi_remove, }; #endif /* CONFIG_SPI_MASTER */ @@ -1306,7 +1306,7 @@ static ssize_t es8323_store(struct device *dev, static struct device *es8323_dev = NULL; static struct class *es8323_class = NULL; static DEVICE_ATTR(es8323, 0664, es8323_show, es8323_store); -static __devinit int es8323_i2c_probe(struct i2c_client *i2c, +static int es8323_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -1363,7 +1363,7 @@ static __devinit int es8323_i2c_probe(struct i2c_client *i2c, return ret; } -static __devexit int es8323_i2c_remove(struct i2c_client *client) +static int es8323_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); kfree(i2c_get_clientdata(client)); @@ -1475,7 +1475,7 @@ static struct i2c_driver es8323_i2c_driver = { .owner = THIS_MODULE, }, .probe = es8323_i2c_probe, - .remove = __devexit_p(es8323_i2c_remove), + .remove = es8323_i2c_remove, .shutdown = es8323_i2c_shutdown, .suspend = es8323_i2c_suspend, .resume = es8323_i2c_resume, diff --git a/sound/soc/codecs/es8323_pcm.c b/sound/soc/codecs/es8323_pcm.c index a318f0a41128..8000d51c4206 100755 --- a/sound/soc/codecs/es8323_pcm.c +++ b/sound/soc/codecs/es8323_pcm.c @@ -211,7 +211,7 @@ MODULE_DEVICE_TABLE(i2c, es8323_i2c_id); static int es8323_proc_init(void); #endif -static int __devinit es8323_i2c_probe(struct i2c_client *i2c, +static int es8323_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { DBG("%s\n", __func__); @@ -226,7 +226,7 @@ static int __devinit es8323_i2c_probe(struct i2c_client *i2c, return 0; } -static int __devexit es8323_i2c_remove(struct i2c_client *i2c) +static int es8323_i2c_remove(struct i2c_client *i2c) { return 0; } @@ -237,7 +237,7 @@ struct i2c_driver es8323_i2c_driver = { .owner = THIS_MODULE, }, .probe = es8323_i2c_probe, - .remove = __devexit_p(es8323_i2c_remove), + .remove = es8323_i2c_remove, .id_table = es8323_i2c_id, }; diff --git a/sound/soc/codecs/rk1000_codec.c b/sound/soc/codecs/rk1000_codec.c index d6b796a9acaf..5ac8f15ed0c3 100755 --- a/sound/soc/codecs/rk1000_codec.c +++ b/sound/soc/codecs/rk1000_codec.c @@ -834,7 +834,7 @@ static int rk1000_codec_probe(struct snd_soc_codec *codec) return -ENOMEM; rk1000_reg_init(codec); -// snd_soc_add_controls(codec, rk1000_codec_snd_controls, +// snd_soc_add_codec_controls(codec, rk1000_codec_snd_controls, // ARRAY_SIZE(rk1000_codec_snd_controls)); // snd_soc_dapm_new_controls(codec, rk1000_codec_dapm_widgets, // ARRAY_SIZE(rk1000_codec_dapm_widgets)); @@ -873,7 +873,7 @@ static struct snd_soc_codec_driver soc_codec_dev_rk1000_codec = { static int rk1000_codec_proc_init(void); #endif -static __devinit int rk1000_codec_i2c_probe(struct i2c_client *i2c, +static int rk1000_codec_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct rk1000_codec_priv *rk1000_codec; @@ -899,7 +899,7 @@ static __devinit int rk1000_codec_i2c_probe(struct i2c_client *i2c, return ret; } -static __devexit int rk1000_codec_i2c_remove(struct i2c_client *client) +static int rk1000_codec_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); kfree(i2c_get_clientdata(client)); @@ -919,7 +919,7 @@ static struct i2c_driver rk1000_codec_i2c_driver = { .owner = THIS_MODULE, }, .probe = rk1000_codec_i2c_probe, - .remove = __devexit_p(rk1000_codec_i2c_remove), + .remove = rk1000_codec_i2c_remove, .id_table = rk1000_codec_i2c_id, }; @@ -1162,4 +1162,4 @@ module_exit(rk1000_control_exit); MODULE_DESCRIPTION("ASoC RK1000 CODEC driver"); MODULE_AUTHOR("lhh lhh@rock-chips.com"); MODULE_LICENSE("GPL"); -#endif \ No newline at end of file +#endif diff --git a/sound/soc/codecs/rk2928_codec.c b/sound/soc/codecs/rk2928_codec.c index db03786f1340..17ea4849e4c6 100755 --- a/sound/soc/codecs/rk2928_codec.c +++ b/sound/soc/codecs/rk2928_codec.c @@ -632,7 +632,7 @@ static struct snd_soc_dai_driver rk2928_codec_dai = { .ops = &rk2928_audio_codec_ops, }; -static __devinit int rk2928_codec_probe(struct platform_device *pdev) +static int rk2928_codec_probe(struct platform_device *pdev) { int r; diff --git a/sound/soc/codecs/rk3026_codec.c b/sound/soc/codecs/rk3026_codec.c index 2d3ee646eb07..42cfec90f2b3 100755 --- a/sound/soc/codecs/rk3026_codec.c +++ b/sound/soc/codecs/rk3026_codec.c @@ -2087,7 +2087,7 @@ static int rk3026_probe(struct snd_soc_codec *codec) codec->dapm.bias_level = SND_SOC_BIAS_OFF; rk3026_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - snd_soc_add_controls(codec, rk3026_snd_controls, + snd_soc_add_codec_controls(codec, rk3026_snd_controls, ARRAY_SIZE(rk3026_snd_controls)); snd_soc_dapm_new_controls(&codec->dapm, rk3026_dapm_widgets, ARRAY_SIZE(rk3026_dapm_widgets)); @@ -2163,7 +2163,7 @@ static struct snd_soc_codec_driver soc_codec_dev_rk3026 = { .reg_cache_step = sizeof(unsigned int), }; -static __devinit int rk3026_platform_probe(struct platform_device *pdev) +static int rk3026_platform_probe(struct platform_device *pdev) { DBG("%s\n", __func__); @@ -2171,7 +2171,7 @@ static __devinit int rk3026_platform_probe(struct platform_device *pdev) &soc_codec_dev_rk3026, rk3026_dai, ARRAY_SIZE(rk3026_dai)); } -static __devexit int rk3026_platform_remove(struct platform_device *pdev) +static int rk3026_platform_remove(struct platform_device *pdev) { snd_soc_unregister_codec(&pdev->dev); return 0; @@ -2217,7 +2217,7 @@ static struct platform_driver rk3026_codec_driver = { .owner = THIS_MODULE, }, .probe = rk3026_platform_probe, - .remove = __devexit_p(rk3026_platform_remove), + .remove = rk3026_platform_remove, .shutdown = rk3026_platform_shutdown, }; diff --git a/sound/soc/codecs/rk610_codec.c b/sound/soc/codecs/rk610_codec.c index 92b94e403de9..0ea4b8214d6b 100755 --- a/sound/soc/codecs/rk610_codec.c +++ b/sound/soc/codecs/rk610_codec.c @@ -631,7 +631,7 @@ static int rk610_codec_pcm_hw_params(struct snd_pcm_substream *substream, rk610_codec_write(codec,ACCELCODEC_R0B, ASC_DEC_DISABLE|ASC_INT_DISABLE); //0x00 /* set iface & srate */ - #ifdef CONFIG_SND_RK29_CODEC_SOC_MASTER + #ifdef CONFIG_SND_RK_CODEC_SOC_MASTER iface |= ASC_INVERT_BCLK;//·­×ªBCLK master״̬ËͳöµÄÉÙÁË°ë¸öʱÖÓ£¬µ¼ÖÂδµ½×î´óÒôÁ¿µÄʱºòÆÆÒô¡¢ #endif rk610_codec_write(codec, ACCELCODEC_R09, iface); diff --git a/sound/soc/codecs/rk616_codec.c b/sound/soc/codecs/rk616_codec.c index a531fe9b2856..166527baa052 100755 --- a/sound/soc/codecs/rk616_codec.c +++ b/sound/soc/codecs/rk616_codec.c @@ -33,6 +33,8 @@ //#define RK616_HPMIC_FROM_LINEIN +//#define RK616_HPMIC_FROM_MIC2IN + //#define VIRTUAL_HPGND /* volume setting @@ -628,8 +630,11 @@ void codec_set_spk(bool on) } else { + mutex_lock(&codec->mutex); snd_soc_dapm_enable_pin(&codec->dapm, "Headphone Jack"); snd_soc_dapm_enable_pin(&codec->dapm, "Ext Spk"); + snd_soc_dapm_sync(&codec->dapm); + mutex_unlock(&codec->mutex); } } else { rk616_set_gpio(RK616_CODEC_SET_SPK | RK616_CODEC_SET_HP, GPIO_LOW); @@ -647,11 +652,13 @@ void codec_set_spk(bool on) } else { + mutex_lock(&codec->mutex); snd_soc_dapm_disable_pin(&codec->dapm, "Headphone Jack"); snd_soc_dapm_disable_pin(&codec->dapm, "Ext Spk"); + snd_soc_dapm_sync(&codec->dapm); + mutex_unlock(&codec->mutex); } } - snd_soc_dapm_sync(&codec->dapm); is_hdmi_in = on ? 0 : 1; } @@ -1130,6 +1137,17 @@ int snd_soc_put_gpio_enum_double(struct snd_kcontrol *kcontrol, return 0; } +#define SOC_DOUBLE_R_STEP_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ + SNDRV_CTL_ELEM_ACCESS_READWRITE,\ + .tlv.p = (tlv_array), \ + .info = snd_soc_info_volsw_2r, \ + .get = snd_soc_get_volsw_2r, .put = snd_soc_put_step_volsw_2r, \ + .private_value = (unsigned long)&(struct soc_mixer_control) \ + {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ + .max = xmax, .platform_max = xmax, .invert = xinvert} } + #define SOC_GPIO_ENUM(xname, xenum) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\ .info = snd_soc_info_enum_double, \ @@ -1139,41 +1157,12 @@ int snd_soc_put_gpio_enum_double(struct snd_kcontrol *kcontrol, static const struct snd_kcontrol_new rk616_snd_controls[] = { //add for incall volume setting - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = ("Speaker Playback Volume"),\ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (out_vol_tlv), \ - .info = snd_soc_info_volsw_2r, \ - .get = snd_soc_get_volsw_2r, .put = snd_soc_put_step_volsw_2r, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = RK616_SPKL_CTL, .rreg = RK616_SPKR_CTL, .shift = RK616_VOL_SFT, \ - .max = SPKOUT_VOLUME, .platform_max = SPKOUT_VOLUME, .invert = 0} - }, - - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = ("Headphone Playback Volume"),\ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (out_vol_tlv), \ - .info = snd_soc_info_volsw_2r, \ - .get = snd_soc_get_volsw_2r, .put = snd_soc_put_step_volsw_2r, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = RK616_HPL_CTL, .rreg = RK616_HPR_CTL, .shift = RK616_VOL_SFT, \ - .max = HPOUT_VOLUME, .platform_max = HPOUT_VOLUME, .invert = 0} - }, - - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = ("Earpiece Playback Volume"),\ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (out_vol_tlv), \ - .info = snd_soc_info_volsw_2r, \ - .get = snd_soc_get_volsw_2r, .put = snd_soc_put_step_volsw_2r, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = RK616_SPKL_CTL, .rreg = RK616_SPKR_CTL, .shift = RK616_VOL_SFT, \ - .max = SPKOUT_VOLUME, .platform_max = SPKOUT_VOLUME, .invert = 0} - }, + SOC_DOUBLE_R_STEP_TLV("Speaker Playback Volume", RK616_SPKL_CTL, + RK616_SPKR_CTL, RK616_VOL_SFT, SPKOUT_VOLUME, 0, out_vol_tlv), + SOC_DOUBLE_R_STEP_TLV("Headphone Playback Volume", RK616_HPL_CTL, + RK616_HPR_CTL, RK616_VOL_SFT, HPOUT_VOLUME, 0, out_vol_tlv), + SOC_DOUBLE_R_STEP_TLV("Earpiece Playback Volume", RK616_SPKL_CTL, + RK616_SPKR_CTL, RK616_VOL_SFT, SPKOUT_VOLUME, 0, out_vol_tlv), SOC_DOUBLE_R("Speaker Playback Switch", RK616_SPKL_CTL, RK616_SPKR_CTL, RK616_MUTE_SFT, 1, 1), @@ -1476,6 +1465,9 @@ static int rk616_capture_path_put(struct snd_kcontrol *kcontrol, { struct rk616_codec_priv *rk616 = rk616_priv; long int pre_path; +#if (defined RK616_HPMIC_FROM_LINEIN) || (defined RK616_HPMIC_FROM_MIC2IN) + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); +#endif if (!rk616) { printk("%s : rk616_priv is NULL\n", __func__); @@ -1505,6 +1497,11 @@ static int rk616_capture_path_put(struct snd_kcontrol *kcontrol, #ifdef RK616_HPMIC_FROM_LINEIN snd_soc_write(codec, 0x848, 0x06); //MIXINL power up and unmute, MININL from MICMUX, MICMUX from BST_L #endif + +#ifdef RK616_HPMIC_FROM_MIC2IN + snd_soc_write(codec, 0x848, 0x06); //MIXINL power up and unmute, MININL from MICMUX, MICMUX from BST_L + snd_soc_write(codec, 0x840, 0x69); //BST_L power up, unmute, and Single-Ended(bit 6), volume 0-20dB(bit 5) +#endif rk616_set_gpio(RK616_CODEC_SET_MIC, GPIO_HIGH); break; case Hands_Free_Mic: @@ -1514,6 +1511,11 @@ static int rk616_capture_path_put(struct snd_kcontrol *kcontrol, #ifdef RK616_HPMIC_FROM_LINEIN snd_soc_write(codec, 0x848, 0x03); //MIXINL power up and unmute, MININL from MICMUX, MICMUX from IN3L #endif + +#ifdef RK616_HPMIC_FROM_MIC2IN + snd_soc_write(codec, 0x848, 0x26); //MIXINL power up and unmute, MININL from MICMUX, MICMUX from BST_R + snd_soc_write(codec, 0x840, 0x96); //BST_R power up, unmute, and Single-Ended(bit 2), volume 0-20dB(bit 1) +#endif rk616_set_gpio(RK616_CODEC_SET_MIC, GPIO_LOW); break; case BT_Sco_Mic: @@ -1875,29 +1877,13 @@ static const struct snd_kcontrol_new rk616_snd_path_controls[] = { rk616_voip_path_get, rk616_voip_path_put), //add for incall volume setting - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = ("Speaker Playback Volume"),\ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (out_vol_tlv), \ - .info = snd_soc_info_volsw_2r, \ - .get = snd_soc_get_volsw_2r, .put = snd_soc_put_step_volsw_2r, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = RK616_SPKL_CTL, .rreg = RK616_SPKR_CTL, .shift = RK616_VOL_SFT, \ - .max = SPKOUT_VOLUME, .platform_max = SPKOUT_VOLUME, .invert = 0} - }, - - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = ("Headphone Playback Volume"),\ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (out_vol_tlv), \ - .info = snd_soc_info_volsw_2r, \ - .get = snd_soc_get_volsw_2r, .put = snd_soc_put_step_volsw_2r, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = RK616_SPKL_CTL, .rreg = RK616_SPKR_CTL, .shift = RK616_VOL_SFT, \ - .max = SPKOUT_VOLUME, .platform_max = SPKOUT_VOLUME, .invert = 0} - }, + SOC_DOUBLE_R_STEP_TLV("Speaker Playback Volume", RK616_SPKL_CTL, + RK616_SPKR_CTL, RK616_VOL_SFT, SPKOUT_VOLUME, 0, out_vol_tlv), + SOC_DOUBLE_R_STEP_TLV("Headphone Playback Volume", RK616_SPKL_CTL, + RK616_SPKR_CTL, RK616_VOL_SFT, HPOUT_VOLUME, 0, out_vol_tlv), + //Earpiece incall volume is setting by modem + //SOC_DOUBLE_R_STEP_TLV("Earpiece Playback Volume", RK616_SPKL_CTL, + //RK616_SPKR_CTL, RK616_VOL_SFT, SPKOUT_VOLUME, 0, out_vol_tlv), /* * When modem connecting, it will make some pop noise. @@ -2830,7 +2816,7 @@ static int rk616_probe(struct snd_soc_codec *codec) rk616_reset(codec); if (rk616_for_mid) { - snd_soc_add_controls(codec, rk616_snd_path_controls, + snd_soc_add_codec_controls(codec, rk616_snd_path_controls, ARRAY_SIZE(rk616_snd_path_controls)); snd_soc_write(codec, RK616_MICBIAS_CTL, RK616_MICBIAS2_PWRD | RK616_MICBIAS1_V_1_7); @@ -2838,7 +2824,7 @@ static int rk616_probe(struct snd_soc_codec *codec) codec->dapm.bias_level = SND_SOC_BIAS_OFF; rk616_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - snd_soc_add_controls(codec, rk616_snd_controls, + snd_soc_add_codec_controls(codec, rk616_snd_controls, ARRAY_SIZE(rk616_snd_controls)); snd_soc_dapm_new_controls(&codec->dapm, rk616_dapm_widgets, ARRAY_SIZE(rk616_dapm_widgets)); @@ -2896,7 +2882,7 @@ static struct snd_soc_codec_driver soc_codec_dev_rk616 = { .readable_register = rk616_codec_register, }; -static __devinit int rk616_platform_probe(struct platform_device *pdev) +static int rk616_platform_probe(struct platform_device *pdev) { struct mfd_rk616 *rk616 = dev_get_drvdata(pdev->dev.parent); @@ -2913,7 +2899,7 @@ static __devinit int rk616_platform_probe(struct platform_device *pdev) &soc_codec_dev_rk616, rk616_dai, ARRAY_SIZE(rk616_dai)); } -static __devexit int rk616_platform_remove(struct platform_device *pdev) +static int rk616_platform_remove(struct platform_device *pdev) { snd_soc_unregister_codec(&pdev->dev); return 0; @@ -2951,7 +2937,7 @@ static struct platform_driver rk616_codec_driver = { .owner = THIS_MODULE, }, .probe = rk616_platform_probe, - .remove = __devexit_p(rk616_platform_remove), + .remove = rk616_platform_remove, .shutdown = rk616_platform_shutdown, }; diff --git a/sound/soc/codecs/rt3261-dsp.c b/sound/soc/codecs/rt3261-dsp.c index 3618fcc788b2..c425c94e9455 100644 --- a/sound/soc/codecs/rt3261-dsp.c +++ b/sound/soc/codecs/rt3261-dsp.c @@ -1156,7 +1156,7 @@ int rt3261_dsp_probe(struct snd_soc_codec *codec) if (codec == NULL) return -EINVAL; - snd_soc_add_controls(codec, rt3261_dsp_snd_controls, + snd_soc_add_codec_controls(codec, rt3261_dsp_snd_controls, ARRAY_SIZE(rt3261_dsp_snd_controls)); snd_soc_dapm_new_controls(&codec->dapm, rt3261_dsp_dapm_widgets, ARRAY_SIZE(rt3261_dsp_dapm_widgets)); diff --git a/sound/soc/codecs/rt3261.c b/sound/soc/codecs/rt3261.c index 71aae73386a8..ee38eec20ba0 100755 --- a/sound/soc/codecs/rt3261.c +++ b/sound/soc/codecs/rt3261.c @@ -28,7 +28,7 @@ #include #include -#define RT3261_PROC +//#define RT3261_PROC #ifdef RT3261_PROC #include #include @@ -3378,7 +3378,7 @@ static int rt3261_probe(struct snd_soc_codec *codec) #if defined (CONFIG_SND_SOC_RT5623) struct clk *iis_clk; //for rt5623 MCLK use - iis_clk = clk_get_sys("rk29_i2s.2", "i2s"); + iis_clk = clk_get_sys("rk_i2s.2", "i2s"); if (IS_ERR(iis_clk)) { DBG("failed to get i2s clk\n"); ret = PTR_ERR(iis_clk); @@ -3436,7 +3436,7 @@ static int rt3261_probe(struct snd_soc_codec *codec) codec->dapm.bias_level = SND_SOC_BIAS_STANDBY; rt3261->codec = codec; - snd_soc_add_controls(codec, rt3261_snd_controls, + snd_soc_add_codec_controls(codec, rt3261_snd_controls, ARRAY_SIZE(rt3261_snd_controls)); snd_soc_dapm_new_controls(&codec->dapm, rt3261_dapm_widgets, ARRAY_SIZE(rt3261_dapm_widgets)); @@ -3581,7 +3581,7 @@ static const struct i2c_device_id rt3261_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, rt3261_i2c_id); -static int __devinit rt3261_i2c_probe(struct i2c_client *i2c, +static int rt3261_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct rt3261_priv *rt3261; @@ -3618,7 +3618,7 @@ static int __devinit rt3261_i2c_probe(struct i2c_client *i2c, return ret; } -static int __devexit rt3261_i2c_remove(struct i2c_client *i2c) +static int rt3261_i2c_remove(struct i2c_client *i2c) { snd_soc_unregister_codec(&i2c->dev); kfree(i2c_get_clientdata(i2c)); @@ -3640,7 +3640,7 @@ struct i2c_driver rt3261_i2c_driver = { .owner = THIS_MODULE, }, .probe = rt3261_i2c_probe, - .remove = __devexit_p(rt3261_i2c_remove), + .remove = rt3261_i2c_remove, .shutdown = rt3261_i2c_shutdown, .id_table = rt3261_i2c_id, }; diff --git a/sound/soc/codecs/rt5512.c b/sound/soc/codecs/rt5512.c index 90b036082d9f..fc62e50ed22f 100755 --- a/sound/soc/codecs/rt5512.c +++ b/sound/soc/codecs/rt5512.c @@ -1480,7 +1480,7 @@ static int rt5512_codec_probe(struct snd_soc_codec *codec) - snd_soc_add_controls(codec, rt5512_snd_controls, + snd_soc_add_codec_controls(codec, rt5512_snd_controls, ARRAY_SIZE(rt5512_snd_controls)); return 0; } @@ -1753,7 +1753,7 @@ static const struct file_operations codec_debug_ops = { }; #endif -static int __devinit rt5512_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) +static int rt5512_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret; struct rt5512_codec_chip *chip; @@ -1807,7 +1807,7 @@ codec_reg_fail: return ret; } -static int __devexit rt5512_i2c_remove(struct i2c_client *client) +static int rt5512_i2c_remove(struct i2c_client *client) { struct rt5512_codec_chip *chip = i2c_get_clientdata(client); @@ -1831,7 +1831,7 @@ struct i2c_driver rt5512_i2c_driver = .owner = THIS_MODULE, }, .probe = rt5512_i2c_probe, - .remove = __devexit_p(rt5512_i2c_remove), + .remove = rt5512_i2c_remove, .id_table = rt5512_i2c_id, }; diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c index 6472a9e93c7b..7e68ce5dcf95 100755 --- a/sound/soc/codecs/rt5616.c +++ b/sound/soc/codecs/rt5616.c @@ -1533,7 +1533,7 @@ static int rt5616_probe(struct snd_soc_codec *codec) rt5616_codec = codec; - snd_soc_add_controls(codec, rt5616_snd_controls, + snd_soc_add_codec_controls(codec, rt5616_snd_controls, ARRAY_SIZE(rt5616_snd_controls)); snd_soc_dapm_new_controls(&codec->dapm, rt5616_dapm_widgets, ARRAY_SIZE(rt5616_dapm_widgets)); @@ -1628,7 +1628,7 @@ static const struct i2c_device_id rt5616_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, rt5616_i2c_id); -static int __devinit rt5616_i2c_probe(struct i2c_client *i2c, +static int rt5616_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct rt5616_priv *rt5616; @@ -1649,7 +1649,7 @@ static int __devinit rt5616_i2c_probe(struct i2c_client *i2c, return ret; } -static int __devexit rt5616_i2c_remove(struct i2c_client *i2c) +static int rt5616_i2c_remove(struct i2c_client *i2c) { snd_soc_unregister_codec(&i2c->dev); kfree(i2c_get_clientdata(i2c)); @@ -1676,7 +1676,7 @@ struct i2c_driver rt5616_i2c_driver = { .owner = THIS_MODULE, }, .probe = rt5616_i2c_probe, - .remove = __devexit_p(rt5616_i2c_remove), + .remove = rt5616_i2c_remove, .shutdown = rt5616_i2c_shutdown, .id_table = rt5616_i2c_id, }; diff --git a/sound/soc/codecs/rt5623.c b/sound/soc/codecs/rt5623.c index f4ac82c7e532..9ea32e120a70 100644 --- a/sound/soc/codecs/rt5623.c +++ b/sound/soc/codecs/rt5623.c @@ -164,7 +164,7 @@ MODULE_DEVICE_TABLE(i2c, rt5623_i2c_id); static int rt5623_proc_init(void); -static int __devinit rt5623_i2c_probe(struct i2c_client *i2c, +static int rt5623_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { pr_info("%s(%d)\n", __func__, __LINE__); diff --git a/sound/soc/codecs/rt5631_phone.c b/sound/soc/codecs/rt5631_phone.c index 6409a170ea6b..df48a5fcee6f 100755 --- a/sound/soc/codecs/rt5631_phone.c +++ b/sound/soc/codecs/rt5631_phone.c @@ -2222,7 +2222,7 @@ static int rt5631_probe(struct snd_soc_codec *codec) codec->dapm.bias_level = SND_SOC_BIAS_STANDBY; rt5631->codec = codec; rt5631_codec = codec; - snd_soc_add_controls(codec, rt5631_snd_controls, + snd_soc_add_codec_controls(codec, rt5631_snd_controls, ARRAY_SIZE(rt5631_snd_controls)); snd_soc_dapm_new_controls(&codec->dapm, rt5631_dapm_widgets, ARRAY_SIZE(rt5631_dapm_widgets)); @@ -2363,7 +2363,7 @@ static int rt5631_i2c_probe(struct i2c_client *i2c, return ret; } -static __devexit int rt5631_i2c_remove(struct i2c_client *client) +static int rt5631_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); kfree(i2c_get_clientdata(client)); @@ -2387,7 +2387,7 @@ struct i2c_driver rt5631_i2c_driver = { .owner = THIS_MODULE, }, .probe = rt5631_i2c_probe, - .remove = __devexit_p(rt5631_i2c_remove), + .remove = rt5631_i2c_remove, .shutdown = rt5631_i2c_shutdown, .id_table = rt5631_i2c_id, }; diff --git a/sound/soc/codecs/rt5639.c b/sound/soc/codecs/rt5639.c index a35aeb05cb93..da86fb7a299b 100755 --- a/sound/soc/codecs/rt5639.c +++ b/sound/soc/codecs/rt5639.c @@ -3057,7 +3057,7 @@ static int rt5639_probe(struct snd_soc_codec *codec) codec->dapm.bias_level = SND_SOC_BIAS_STANDBY; rt5639->codec = codec; - snd_soc_add_controls(codec, rt5639_snd_controls, + snd_soc_add_codec_controls(codec, rt5639_snd_controls, ARRAY_SIZE(rt5639_snd_controls)); snd_soc_dapm_new_controls(&codec->dapm, rt5639_dapm_widgets, ARRAY_SIZE(rt5639_dapm_widgets)); @@ -3190,7 +3190,7 @@ static const struct i2c_device_id rt5639_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, rt5639_i2c_id); -static int __devinit rt5639_i2c_probe(struct i2c_client *i2c, +static int rt5639_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct rt5639_priv *rt5639; @@ -3210,7 +3210,7 @@ printk("rt5639 i2c probe initial\n"); return ret; } -static int __devexit rt5639_i2c_remove(struct i2c_client *i2c) +static int rt5639_i2c_remove(struct i2c_client *i2c) { snd_soc_unregister_codec(&i2c->dev); kfree(i2c_get_clientdata(i2c)); @@ -3233,7 +3233,7 @@ struct i2c_driver rt5639_i2c_driver = { .owner = THIS_MODULE, }, .probe = rt5639_i2c_probe, - .remove = __devexit_p(rt5639_i2c_remove), + .remove = rt5639_i2c_remove, .shutdown = rt5639_i2c_shutdown, .id_table = rt5639_i2c_id, }; diff --git a/sound/soc/codecs/rt5640-dsp.c b/sound/soc/codecs/rt5640-dsp.c index d5cb99966bcf..e5f2515014f0 100755 --- a/sound/soc/codecs/rt5640-dsp.c +++ b/sound/soc/codecs/rt5640-dsp.c @@ -1251,7 +1251,7 @@ int rt5640_dsp_probe(struct snd_soc_codec *codec) if (codec == NULL) return -EINVAL; - snd_soc_add_controls(codec, rt5640_dsp_snd_controls, + snd_soc_add_codec_controls(codec, rt5640_dsp_snd_controls, ARRAY_SIZE(rt5640_dsp_snd_controls)); snd_soc_dapm_new_controls(&codec->dapm, rt5640_dsp_dapm_widgets, ARRAY_SIZE(rt5640_dsp_dapm_widgets)); diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 33a49cec392a..545c043d5604 100755 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -3210,7 +3210,7 @@ static int rt5640_probe(struct snd_soc_codec *codec) /* by magf for codec_set_spk */ rt5640_codec = codec; - snd_soc_add_controls(codec, rt5640_snd_controls, + snd_soc_add_codec_controls(codec, rt5640_snd_controls, ARRAY_SIZE(rt5640_snd_controls)); snd_soc_dapm_new_controls(&codec->dapm, rt5640_dapm_widgets, ARRAY_SIZE(rt5640_dapm_widgets)); @@ -3381,7 +3381,7 @@ static const struct i2c_device_id rt5640_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id); -static int __devinit rt5640_i2c_probe(struct i2c_client *i2c, +static int rt5640_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct rt5640_priv *rt5640; @@ -3401,7 +3401,7 @@ static int __devinit rt5640_i2c_probe(struct i2c_client *i2c, return ret; } -static int __devexit rt5640_i2c_remove(struct i2c_client *i2c) +static int rt5640_i2c_remove(struct i2c_client *i2c) { snd_soc_unregister_codec(&i2c->dev); kfree(i2c_get_clientdata(i2c)); @@ -3424,7 +3424,7 @@ struct i2c_driver rt5640_i2c_driver = { .owner = THIS_MODULE, }, .probe = rt5640_i2c_probe, - .remove = __devexit_p(rt5640_i2c_remove), + .remove = rt5640_i2c_remove, .shutdown = rt5640_i2c_shutdown, .id_table = rt5640_i2c_id, }; diff --git a/sound/soc/codecs/tlv320aic326x.c b/sound/soc/codecs/tlv320aic326x.c index ce91b343a992..a6c324d4477f 100755 --- a/sound/soc/codecs/tlv320aic326x.c +++ b/sound/soc/codecs/tlv320aic326x.c @@ -2404,7 +2404,7 @@ static int aic3262_codec_probe(struct snd_soc_codec *codec) aic3262->mute_asi = 0; - snd_soc_add_controls(codec, aic3262_snd_controls, + snd_soc_add_codec_controls(codec, aic3262_snd_controls, ARRAY_SIZE(aic3262_snd_controls)); mutex_init(&codec->mutex); @@ -2499,7 +2499,7 @@ static struct platform_driver aic326x_codec_driver = { .owner = THIS_MODULE, }, .probe = aic326x_probe, - .remove = __devexit_p(aic326x_remove), + .remove = aic326x_remove, }; /* *---------------------------------------------------------------------------- diff --git a/sound/soc/rk/Kconfig b/sound/soc/rk/Kconfig new file mode 100755 index 000000000000..4cc3afb43f3b --- /dev/null +++ b/sound/soc/rk/Kconfig @@ -0,0 +1,359 @@ +config SND_RK_SOC + tristate "SoC Audio for the Rockchip System-on-Chip" + depends on SND_SOC#PLAT_RK && SND_SOC + help + Say Y or M if you want to add support for codecs attached to + the ROCKCHIP IIS interface. You will also need + to select the audio interfaces to support below. + +config SND_RK_SOC_I2S + tristate + +config SND_RK_SOC_SPDIF + tristate + +config SND_RK_SOC_I2S_8CH + bool "Soc RK I2S 8 Channel support(I2S0)" + default y + depends on SND_RK_SOC_I2S && !ARCH_RK3066B && !ARCH_RK3188 && !ARCH_RK319X + help + This supports the use of the 8 Channel I2S interface on rk processors. + +if SND_RK_SOC_I2S_8CH +choice + bool "Set I2S0 using the number of channels" + default SND_I2SO_USE_DOUBLE_CHANNELS + config SND_I2SO_USE_EIGHT_CHANNELS + tristate "I2S0 use 8 channels" + + config SND_I2SO_USE_DOUBLE_CHANNELS + tristate "I2S0 use 2 channels" +endchoice +endif + +config SND_RK_SOC_I2S_2CH + bool "Soc RK I2S 2 Channel support(I2S1)" + depends on SND_RK_SOC_I2S && !ARCH_RK2928 && !ARCH_RK3026 + default y if (ARCH_RK3066B || ARCH_RK3188) + help + This supports the use of the 2 Channel I2S interface on rk processors. + +choice + bool "Set I2S GRF Output Voltage" + depends on (ARCH_RK3066B || ARCH_RK3188) && SND_RK_SOC_I2S_2CH + default SND_I2S_USE_33V + + config SND_I2S_USE_33V + bool "I2S use 3.3V" + + config SND_I2S_USE_18V + bool "I2S use 1.8V" +endchoice + +config SND_RK_SOC_I2S2_2CH + bool "Soc RK I2S 2 Channel support(I2S2)" + default n + depends on SND_RK_SOC_I2S && ARCH_RK30 && !ARCH_RK2928 && !ARCH_RK3066B && !ARCH_RK3026 + help + This supports the use of the 2 Channel I2S2 interface on rk30 processors. + +if SND_RK_SOC_I2S_2CH || SND_RK_SOC_I2S_8CH || SND_RK_SOC_I2S2_2CH +choice + bool "Set i2s on DMA event mode" + default SND_I2S_DMA_EVENT_STATIC + config SND_I2S_DMA_EVENT_DYNAMIC + tristate "dynamic mode" + + config SND_I2S_DMA_EVENT_STATIC + tristate "static mode" +endchoice +endif + +if SND_RK_SOC && RK_HDMI +choice + bool "Set audio support for HDMI" + default SND_RK_SOC_HDMI_I2S + config SND_RK_SOC_HDMI_I2S + depends on !RK616_USE_MCLK_12M || !SND_RK_SOC_RK616 + select SND_RK_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_RK_SOC_AK4396 + tristate "SoC I2S Audio support for rockchip - AK4396" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + select SND_SOC_AK4396 + help + Say Y if you want to add support for SoC audio on rockchip + with the AK4396. + +config SND_RK_SOC_ES8323 + tristate "SoC I2S Audio support for rockchip - ES8323" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + select SND_SOC_ES8323 + help + Say Y if you want to add support for SoC audio on rockchip + with the ES8323. + +config SND_SOC_ES8323_PCM + tristate "SoC I2S Audio support for rockchip - ES8323 for PCM modem" + depends on SND_RK_SOC + help + Say Y if you want to add support for SoC audio on rockchip + with the ES8323 for PCM modem. + +config SND_RK_SOC_WM8988 + tristate "SoC I2S Audio support for rockchip - WM8988" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + select SND_SOC_WM8988 + help + Say Y if you want to add support for SoC audio on rockchip + with the WM8988. + +config SND_RK_SOC_WM8900 + tristate "SoC I2S Audio support for rockchip - WM8900" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + select SND_SOC_WM8900 + help + Say Y if you want to add support for SoC audio on rockchip + with the WM8900. + +config SND_RK_SOC_RT5512 + tristate "SoC I2S Audio support for rockchip - RICHTEK5512" + depends on SND_RK_SOC + select SND_SOC_RT5512 + select SND_RK_SOC_I2S + help + Say Y if you want to add support for SoC audio on the rockchip. + +config SND_RK_SOC_CX2070X + tristate "SoC I2S Audio support for rockchip - CX2070X" + depends on SND_RK_SOC + select SND_SOC_CX2070X + select SND_RK_SOC_I2S + help + Say Y if you want to add support for SoC audio on the rockchip. + +config SND_RK_SOC_RT5621 + tristate "SoC I2S Audio support for rockchip - rt5621" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + select SND_SOC_RT5621 + help + Say Y if you want to add support for SoC audio on rockchip + with the rt5621. +config SND_RK_SOC_RT5623 + tristate "SoC I2S Audio support for rockchip - rt5623" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + select SND_SOC_RT5623 + help + Say Y if you want to add support for SoC audio on rockchip + with the rt5623. + +config SND_RK_SOC_RT5631 + tristate "SoC I2S Audio support for rockchip - RT5631" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + select SND_SOC_RT5631 + help + Say Y if you want to add support for SoC audio on rockchip + with the RT5631. + +config SND_RK_SOC_RT5631_PHONE + tristate "SoC I2S Audio support for rockchip(phone) - RT5631" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + select SND_SOC_RT5631_PHONE + help + Say Y if you want to add support for SoC audio on rockchip + with the RT5631. + Driver code to use on the phone or voice Tablet. + +config SND_RK_SOC_RT5625 + tristate "SoC I2S Audio support for rockchip - RT5625" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + help + Say Y if you want to add support for SoC audio on rockchip + with the RT5625. + +choice + depends on SND_RK_SOC_RT5625 + prompt "RT5625 hardware select" + + config SND_SOC_RT5625_SPK_FORM_SPKOUT + bool "spk from spkout" + select SND_SOC_RT5625 + help + if your codec output hardware connect is spk from spkout, choose it + + config SND_SOC_RT5625_SPK_FORM_HPOUT + bool "spk from hpout" + select SND_SOC_RT5625 + help + if your codec output hardware connect is spk from spkout, choose it +endchoice + +config SND_RK_SOC_RT5640 + tristate "SoC I2S Audio support for rockchip - RT5640(RT5642)" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + select SND_SOC_RT5640 + help + RT5640 is pin to pin as RT5642, but not have dsp function. + +config SND_RK_SOC_RT3224 + tristate "SoC I2S Audio support for rockchip - RT3224" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + select SND_SOC_RT3224 + help + RT3224 is pin to pin as RT3261, but not have dsp function. + +config SND_RK_SOC_RT5639 + tristate "SoC I2S Audio support for rockchip - RT5639" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + select SND_SOC_RT5639 + help + rt5639 + +config SND_RK_SOC_RT5616 + tristate "SoC I2S Audio support for rockchip - RT5616" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + select SND_SOC_RT5616 + help + Say Y if you want to add support for SoC audio on rockchip + with the RT5616. + +config SND_RK_SOC_RT3261 + tristate "SoC I2S Audio support for rockchip - RT3261" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + select SND_SOC_RT3261 + help + Say Y if you want to add support for SoC audio on rockchip + with the RT3261. + +config SND_RK_SOC_WM8994 + tristate "SoC I2S Audio support for rockchip - WM8994" + depends on SND_RK_SOC && MFD_WM8994 + select SND_RK_SOC_I2S + select SND_SOC_WM8994 + help + Say Y if you want to add support for SoC audio on rockchip + with the WM8994. + +config SND_RK_SOC_CS42L52 + tristate "SoC I2S Audio support for rockchip - CS42L52" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + select SND_SOC_CS42L52 + help + Say Y if you want to add support for SoC audio on rockchip + with the CS42L52. + +config SND_RK_SOC_AIC3111 + tristate "SoC I2S Audio support for rockchip - AIC3111" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + select SND_SOC_TLV320AIC3111 + help + Say Y if you want to add support for SoC audio on rockchip + with the AIC3111. + +config SND_RK_SOC_AIC3262 + tristate "SoC I2S Audio support for rockchip - AIC3262" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + select SND_SOC_TLV320AIC326X + help + Say Y if you want to add support for SoC audio on rockchip + with the AIC3262. + +config SND_RK_SOC_RK1000 + tristate "SoC I2S Audio support for rockchip - RK1000" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + select SND_SOC_RK1000 + help + Say Y if you want to add support for SoC audio on rockchip + with the RK1000. + +config SND_RK_SOC_RK610 + tristate "SoC I2S Audio support for rockchip - RK610" + depends on SND_RK_SOC && MFD_RK610 + select SND_RK_SOC_I2S + select SND_SOC_RK610 + help + Say Y if you want to add support for SoC audio on rockchip + with the RK610(JETTA). + +config SND_RK_SOC_RK616 + tristate "SoC I2S Audio support for rockchip - RK616" + depends on SND_RK_SOC && MFD_RK616 + select SND_RK_SOC_I2S + select SND_SOC_RK616 + help + Say Y if you want to add support for SoC audio on rockchip + with the RK616(JETTA). + +config SND_RK_SOC_RK2928 + tristate "SoC I2S Audio support for rockchip - RK2928" + depends on SND_RK_SOC && ARCH_RK2928 + select SND_RK_SOC_I2S + select SND_SOC_RK2928 + select SND_RK_CODEC_SOC_SLAVE + help + Say Y if you want to add support for SoC audio on rockchip + with the RK2928 internal codec. + +config SND_RK_SOC_RK3026 + tristate "SoC I2S Audio support for rockchip - RK3026&R3028A" + depends on SND_RK_SOC && ARCH_RK3026 + select SND_RK_SOC_I2S + select SND_SOC_RK3026 + select SND_RK_CODEC_SOC_SLAVE + help + Say Y if you want to add support for SoC audio on rockchip + with the RK3026 internal codec. + +if SND_RK_SOC_I2S_2CH || SND_RK_SOC_I2S_8CH || SND_RK_SOC_I2S2_2CH +choice + bool "Set i2s type" + default SND_RK_CODEC_SOC_SLAVE + config SND_RK_CODEC_SOC_MASTER + tristate "Codec run in Master" + + config SND_RK_CODEC_SOC_SLAVE + tristate "Codec run in Slave" +endchoice + +config ADJUST_VOL_BY_CODEC + bool "Adjust volume by codec" + default n + help + adjust volume by codec + +config PHONE_INCALL_IS_SUSPEND + bool "Incalling Whether suspend codec" + default n + help + set "y" phone incall status cannot into suspend codec + +endif + diff --git a/sound/soc/rk/Makefile b/sound/soc/rk/Makefile new file mode 100755 index 000000000000..1542f472dd83 --- /dev/null +++ b/sound/soc/rk/Makefile @@ -0,0 +1,67 @@ +# ROCKCHIP Platform Support +snd-soc-rockchip-objs := rk_pcm.o +ifdef CONFIG_ARCH_RK29 +snd-soc-rockchip-i2s-objs := rk29_i2s.o +else +snd-soc-rockchip-i2s-objs := rk30_i2s.o +endif +snd-soc-rockchip-spdif-objs := rk_spdif.o + +obj-$(CONFIG_SND_RK_SOC) += snd-soc-rockchip.o +obj-$(CONFIG_SND_RK_SOC_I2S) += snd-soc-rockchip-i2s.o +obj-$(CONFIG_SND_RK_SOC_SPDIF) += snd-soc-rockchip-spdif.o + +# ROCKCHIP Machine Support +snd-soc-wm8900-objs := rk_wm8900.o +snd-soc-rt5621-objs := rk_rt5621.o +snd-soc-rt5631-objs := rk_rt5631.o +snd-soc-ak4396-objs := rk_ak4396.o +snd-soc-rt5616-objs := rk_rt5616.o +snd-soc-rt5631-phone-objs := rk_rt5631_phone.o +snd-soc-rt5625-objs := rk_rt5625.o +snd-soc-rt5640-objs := rk_rt5640.o +snd-soc-rt3261-objs := rk_rt3261.o +snd-soc-rt3224-objs := rk_rt3261.o +snd-soc-rt5639-objs := rk_rt5639.o +snd-soc-cs42l52-objs := rk_cs42l52.o +snd-soc-aic3111-objs := rk_aic3111.o +snd-soc-wm8988-objs := rk_wm8988.o +snd-soc-rk1000-objs := rk_rk1000codec.o +snd-soc-wm8994-objs := rk_wm8994.o +snd-soc-rk610-objs := rk_jetta_codec.o +snd-soc-rk616-objs := rk_rk616.o +snd-soc-aic3262-objs := rk_aic3262.o +snd-soc-rk2928-objs := rk2928-card.o +snd-soc-es8323-objs := rk_es8323.o +snd-soc-rk3026-objs := rk_rk3026.o +snd-soc-hdmi-i2s-objs := rk_hdmi_i2s.o +snd-soc-hdmi-spdif-objs := rk_hdmi_spdif.o +snd-soc-rt5512-objs := rk_rt5512.o +snd-soc-cx2070x-objs := rk_cx2070x.o + +obj-$(CONFIG_SND_RK_SOC_WM8994) += snd-soc-wm8994.o +obj-$(CONFIG_SND_RK_SOC_WM8988) += snd-soc-wm8988.o +obj-$(CONFIG_SND_RK_SOC_WM8900) += snd-soc-wm8900.o +obj-$(CONFIG_SND_RK_SOC_RT5621) += snd-soc-rt5621.o +obj-$(CONFIG_SND_RK_SOC_RT5631) += snd-soc-rt5631.o +obj-$(CONFIG_SND_RK_SOC_AK4396) += snd-soc-ak4396.o +obj-$(CONFIG_SND_RK_SOC_RT5631_PHONE) += snd-soc-rt5631-phone.o +obj-$(CONFIG_SND_RK_SOC_RT5625) += snd-soc-rt5625.o +obj-$(CONFIG_SND_RK_SOC_RT5640) += snd-soc-rt5640.o +obj-$(CONFIG_SND_RK_SOC_RT3261) += snd-soc-rt3261.o +obj-$(CONFIG_SND_RK_SOC_RT3224) += snd-soc-rt3224.o +obj-$(CONFIG_SND_RK_SOC_RT5639) += snd-soc-rt5639.o +obj-$(CONFIG_SND_RK_SOC_RT5616) += snd-soc-rt5616.o +obj-$(CONFIG_SND_RK_SOC_RK1000) += snd-soc-rk1000.o +obj-$(CONFIG_SND_RK_SOC_CS42L52) += snd-soc-cs42l52.o +obj-$(CONFIG_SND_RK_SOC_AIC3111) += snd-soc-aic3111.o +obj-$(CONFIG_SND_RK_SOC_AIC3262) += snd-soc-aic3262.o +obj-$(CONFIG_SND_RK_SOC_RK610) += snd-soc-rk610.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_RK_SOC_ES8323) += snd-soc-es8323.o +obj-$(CONFIG_SND_RK_SOC_RK3026) += snd-soc-rk3026.o +obj-$(CONFIG_SND_RK_SOC_RT5512) += snd-soc-rt5512.o +obj-$(CONFIG_SND_RK_SOC_CX2070X) += snd-soc-cx2070x.o diff --git a/sound/soc/rk/rk2928-card.c b/sound/soc/rk/rk2928-card.c new file mode 100755 index 000000000000..4ccd2fadef12 --- /dev/null +++ b/sound/soc/rk/rk2928-card.c @@ -0,0 +1,138 @@ +/* + * rk2928-card.c -- SoC audio for RockChip RK2928 + * + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ +#include +#include +#include + +#include "rk_pcm.h" +#include "rk29_i2s.h" + +#ifdef DEBUG +#define DBG(format, ...) \ + printk(KERN_INFO "RK2928 Card: " format "\n", ## __VA_ARGS__) +#else +#define DBG(format, ...) +#endif + +static int rk2928_dai_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 div_bclk,div_mclk; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + DBG("Set cpu_dai master\n"); + 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_RK_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); + DBG("Set cpu_dai slave\n"); + #endif + if (ret < 0) + return ret; + + DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + pll_out = 256 * params_rate(params); + + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + #endif + + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + div_bclk = 63; + div_mclk = pll_out/(params_rate(params)*64) - 1; + + snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); + #endif + + return 0; +} + +static struct snd_soc_ops rk2928_dai_ops = { + .hw_params = rk2928_dai_hw_params, +}; + +static struct snd_soc_dai_link rk2928_dai[] = { + { + .name = "RK2928", + .stream_name = "RK2928", + .cpu_dai_name = "rk_i2s.0", + .platform_name = "rockchip-audio", + .codec_name = "rk2928-codec", + .codec_dai_name = "rk2928-codec", + .ops = &rk2928_dai_ops, + }, +}; + +/* Audio machine driver */ +static struct snd_soc_card snd_soc_rk2928 = { + .name = "RK2928", + .dai_link = rk2928_dai, + .num_links = ARRAY_SIZE(rk2928_dai), +}; + +static struct platform_device *rk2928_snd_device; + +static int __init rk2928_soc_init(void) +{ + int ret; + + printk(KERN_INFO "RK2928 SoC init\n"); + + rk2928_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk2928_snd_device) { + printk(KERN_ERR "Platform device allocation failed\n"); + return -ENOMEM; + } + + platform_set_drvdata(rk2928_snd_device, &snd_soc_rk2928); + + ret = platform_device_add(rk2928_snd_device); + if (ret) + goto err1; + + return 0; + +err1: + printk(KERN_ERR "Unable to add platform device\n"); + platform_device_put(rk2928_snd_device); + + return ret; +} +module_init(rk2928_soc_init); + +static void __exit rk2928_soc_exit(void) +{ + platform_device_unregister(rk2928_snd_device); +} +module_exit(rk2928_soc_exit); + +MODULE_DESCRIPTION("ALSA SoC RK2928"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk/rk29_i2s.c b/sound/soc/rk/rk29_i2s.c new file mode 100755 index 000000000000..097fc22442cb --- /dev/null +++ b/sound/soc/rk/rk29_i2s.c @@ -0,0 +1,862 @@ +/* + * rk29_i2s.c -- ALSA SoC ROCKCHIP IIS Audio Layer Platform driver + * + * Driver for rockchip iis audio + * + * + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "rk_pcm.h" +#include "rk29_i2s.h" + + +#if 0 +#define I2S_DBG(x...) printk(KERN_INFO x) +#else +#define I2S_DBG(x...) do { } while (0) +#endif + +#define pheadi2s ((pI2S_REG)(i2s->regs)) + +#define MAX_I2S 2 + +struct rk29_i2s_info { + struct device *dev; + void __iomem *regs; + + u32 feature; + + struct clk *iis_clk; + struct clk *iis_pclk; + + unsigned char master; + + struct rockchip_pcm_dma_params *dma_playback; + struct rockchip_pcm_dma_params *dma_capture; + + u32 suspend_iismod; + u32 suspend_iiscon; + u32 suspend_iispsr; +}; + +static struct rk29_dma_client rk29_dma_client_out = { + .name = "I2S PCM Stereo Out" +}; + +static struct rk29_dma_client rk29_dma_client_in = { + .name = "I2S PCM Stereo In" +}; + +static inline struct rk29_i2s_info *to_info(struct snd_soc_dai *cpu_dai) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + return snd_soc_dai_get_drvdata(cpu_dai); +#else + return cpu_dai->private_data; +#endif +} + +static struct rockchip_pcm_dma_params rk29_i2s_pcm_stereo_out[MAX_I2S]; +static struct rockchip_pcm_dma_params rk29_i2s_pcm_stereo_in[MAX_I2S]; +static struct rk29_i2s_info rk29_i2s[MAX_I2S]; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) +struct snd_soc_dai_driver rk29_i2s_dai[MAX_I2S]; +#else +struct snd_soc_dai rk29_i2s_dai[MAX_I2S]; +#endif +EXPORT_SYMBOL_GPL(rk29_i2s_dai); + +/* +static struct rockchip_pcm_dma_params rockchip_i2s_pcm_stereo_out[MAX_I2S] = { + [0] = { + .client = &rk29_dma_client_out, + .channel = DMACH_I2S_2CH_TX, ///0, //DMACH_I2S_OUT, + .dma_addr = RK29_I2S_2CH_PHYS + I2S_TXR_BUFF, + .dma_size = 4, + }, + [1] = { + .client = &rk29_dma_client_out, + .channel = DMACH_I2S_8CH_TX, ///0, //DMACH_I2S_OUT, + .dma_addr = RK29_I2S_8CH_PHYS + I2S_TXR_BUFF, + .dma_size = 4, + }, +}; + +static struct rockchip_pcm_dma_params rockchip_i2s_pcm_stereo_in[MAX_I2S] = { + [0] = { + .client = &rk29_dma_client_in, + .channel = DMACH_I2S_2CH_RX, ///1, //DMACH_I2S_IN, + .dma_addr = RK29_I2S_2CH_PHYS + I2S_RXR_BUFF, + .dma_size = 4, + }, + [1] = { + .client = &rk29_dma_client_in, + .channel = DMACH_I2S_8CH_RX, ///1, //DMACH_I2S_IN, + .dma_addr = RK29_I2S_8CH_PHYS + I2S_RXR_BUFF, + .dma_size = 4, + }, +}; +*/ + +#if 1 +static u32 i2s0_clk_enter(void) +{ + u32 clk = cru_readl(CRU_CLKSEL3_CON); + cru_writel(0x1ffff, CRU_CLKSEL3_CON); + mdelay(1); + return clk; +} + +static void i2s0_clk_exit(u32 clk) +{ + mdelay(1); + cru_writel(clk, CRU_CLKSEL3_CON); + mdelay(1); +} +#else +static u32 i2s0_clk_enter() +{ + return 0; +} + +static void i2s0_clk_exit(u32 clk) +{ +} +#endif + +/* + *Turn on or off the transmission path. + */ + +static int flag_i2s_tx = 0; +static int flag_i2s_rx = 0; +static void rockchip_snd_txctrl(struct rk29_i2s_info *i2s, int on, bool stopI2S) +{ + u32 opr,xfer; + u32 clk; + + opr = readl(&(pheadi2s->I2S_DMACR)); + xfer = readl(&(pheadi2s->I2S_XFER)); + + if (on) + { + I2S_DBG("rockchip_snd_txctrl: on\n"); + + //start tx + //if ((flag_i2s_tx == 0) && (flag_i2s_rx == 0)) + if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0) + { + clk = i2s0_clk_enter(); + + //if start tx & rx clk, need reset i2s + xfer |= I2S_TX_TRAN_START; + xfer |= I2S_RX_TRAN_START; + writel(xfer, &(pheadi2s->I2S_XFER)); + + i2s0_clk_exit(clk); + } + + if ((opr & I2S_TRAN_DMA_ENABLE) == 0) + { + opr |= I2S_TRAN_DMA_ENABLE; + writel(opr, &(pheadi2s->I2S_DMACR)); + } + + flag_i2s_tx = 1; + } + else + { + //stop tx + + flag_i2s_tx = 0; + if ((flag_i2s_rx == 0) && (flag_i2s_tx == 0)) + { + opr &= ~I2S_TRAN_DMA_ENABLE; + writel(opr, &(pheadi2s->I2S_DMACR)); + if(stopI2S) + { + clk = i2s0_clk_enter(); + + xfer &= ~I2S_RX_TRAN_START; + xfer &= ~I2S_TX_TRAN_START; + writel(xfer, &(pheadi2s->I2S_XFER)); + + i2s0_clk_exit(clk); + } + + //after stop rx & tx clk, reset i2s + //writel(0x001,&(pheadi2s->I2S_TXRST)); + //writel(0x001,&(pheadi2s->I2S_RXRST)); + } + + I2S_DBG("rockchip_snd_txctrl: off\n"); + } +} + +static void rockchip_snd_rxctrl(struct rk29_i2s_info *i2s, int on, bool stopI2S) +{ + u32 opr,xfer; + u32 clk; + + opr = readl(&(pheadi2s->I2S_DMACR)); + xfer = readl(&(pheadi2s->I2S_XFER)); + + if (on) + { + I2S_DBG("rockchip_snd_rxctrl: on\n"); + + //start rx + //if ((flag_i2s_tx == 0) && (flag_i2s_rx == 0)) + if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0) + { + clk = i2s0_clk_enter(); + + xfer |= I2S_TX_TRAN_START; + xfer |= I2S_RX_TRAN_START; + writel(xfer, &(pheadi2s->I2S_XFER)); + + i2s0_clk_exit(clk); + } + + if ((opr & I2S_RECE_DMA_ENABLE) == 0) + { + opr |= I2S_RECE_DMA_ENABLE; + writel(opr, &(pheadi2s->I2S_DMACR)); + } + + flag_i2s_rx = 1; +#if (CONFIG_SND_SOC_RT5631) +//bard 7-16 s + schedule_delayed_work(&rt5631_delay_cap,HZ/4); +//bard 7-16 e +#endif + } + else + { + //stop rx + flag_i2s_rx = 0; + if ((flag_i2s_rx == 0) && (flag_i2s_tx == 0)) + { + opr &= ~I2S_RECE_DMA_ENABLE; + writel(opr, &(pheadi2s->I2S_DMACR)); + + if(stopI2S) + { + clk = i2s0_clk_enter(); + + xfer &= ~I2S_RX_TRAN_START; + xfer &= ~I2S_TX_TRAN_START; + writel(xfer, &(pheadi2s->I2S_XFER)); + + i2s0_clk_exit(clk); + } + + //after stop rx & tx clk, reset i2s + //writel(0x001,&(pheadi2s->I2S_TXRST)); + //writel(0x001,&(pheadi2s->I2S_RXRST)); + } + + I2S_DBG("rockchip_snd_rxctrl: off\n"); + } +} + +/* + * Set Rockchip I2S DAI format + */ +static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, + unsigned int fmt) +{ + struct rk29_i2s_info *i2s = to_info(cpu_dai); + u32 tx_ctl,rx_ctl; + + I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + tx_ctl = readl(&(pheadi2s->I2S_TXCR)); + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + tx_ctl &= ~I2S_MODE_MASK; + tx_ctl |= I2S_MASTER_MODE; + break; + case SND_SOC_DAIFMT_CBS_CFS: + tx_ctl &= ~I2S_MODE_MASK; + tx_ctl |= I2S_SLAVE_MODE; + break; + default: + I2S_DBG("unknwon master/slave format\n"); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_RIGHT_J: + tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode + tx_ctl |= I2S_BUS_MODE_RSJM; + break; + case SND_SOC_DAIFMT_LEFT_J: + tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode + tx_ctl |= I2S_BUS_MODE_LSJM; + break; + case SND_SOC_DAIFMT_I2S: + tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode + tx_ctl |= I2S_BUS_MODE_NOR; + break; + default: + I2S_DBG("Unknown data format\n"); + return -EINVAL; + } + I2S_DBG("Enter::%s----%d, I2S_TXCR=0x%X\n",__FUNCTION__,__LINE__,tx_ctl); +#if 0//defined(CONFIG_SND_RK_SOC_alc5631) || defined(CONFIG_SND_RK_SOC_alc5621) + rx_ctl = tx_ctl; + rx_ctl &= ~I2S_MODE_MASK; + rx_ctl |= I2S_SLAVE_MODE; // set tx slave, rx master + writel(rx_ctl, &(pheadi2s->I2S_TXCR)); +#else + writel(tx_ctl, &(pheadi2s->I2S_TXCR)); +#endif + rx_ctl = tx_ctl & 0x00007FFF; + writel(rx_ctl, &(pheadi2s->I2S_RXCR)); + return 0; +} + +static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *socdai) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + struct rk29_i2s_info *i2s = to_info(socdai); +#else + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai_link *dai = rtd->dai; + struct rk29_i2s_info *i2s = to_info(dai->cpu_dai); +#endif + u32 iismod; + u32 dmarc; + + I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); + /*by Vincent Hsiung for EQ Vol Change*/ + #define HW_PARAMS_FLAG_EQVOL_ON 0x21 + #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 + if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) + { + return 0; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + snd_soc_dai_set_dma_data(socdai, substream, i2s->dma_playback); + else + snd_soc_dai_set_dma_data(socdai, substream, i2s->dma_capture); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dai->cpu_dai->playback.dma_data = i2s->dma_playback; + else + dai->cpu_dai->capture.dma_data = i2s->dma_capture; +#else + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dai->cpu_dai->dma_data = i2s->dma_playback; + else + dai->cpu_dai->dma_data = i2s->dma_capture; +#endif + + /* Working copies of register */ + iismod = readl(&(pheadi2s->I2S_TXCR)); + //iismod &= (~((1<<5)-1)); + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + iismod |= SAMPLE_DATA_8bit; + break; + case SNDRV_PCM_FORMAT_S16_LE: + iismod |= I2S_DATA_WIDTH(15); + break; + case SNDRV_PCM_FORMAT_S20_3LE: + iismod |= I2S_DATA_WIDTH(19); + break; + case SNDRV_PCM_FORMAT_S24_LE: + iismod |= I2S_DATA_WIDTH(23); + break; + case SNDRV_PCM_FORMAT_S32_LE: + iismod |= I2S_DATA_WIDTH(31); + break; + } + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + iismod &= ~I2S_SLAVE_MODE; + #endif + + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + iismod |= I2S_SLAVE_MODE; + #endif + + //writel((16<<24) |(16<<18)|(16<<12)|(16<<6)|16, &(pheadi2s->I2S_FIFOLR)); + dmarc = readl(&(pheadi2s->I2S_DMACR)); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dmarc = ((dmarc & 0xFFFFFE00) | 16); + else + dmarc = ((dmarc & 0xFE00FFFF) | 16<<16); + + writel(dmarc, &(pheadi2s->I2S_DMACR)); + I2S_DBG("Enter %s, %d I2S_TXCR=0x%08X\n", __func__, __LINE__, iismod); +#if 0//defined(CONFIG_SND_RK_SOC_alc5631) || defined(CONFIG_SND_RK_SOC_alc5621) + dmarc = iismod; + dmarc &= ~I2S_MODE_MASK; + dmarc |= I2S_SLAVE_MODE; // set tx slave, rx master + writel(dmarc, &(pheadi2s->I2S_TXCR)); +#else + writel(iismod, &(pheadi2s->I2S_TXCR)); +#endif + iismod = iismod & 0x00007FFF; + writel(iismod, &(pheadi2s->I2S_RXCR)); + return 0; +} + + +static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + struct rk29_i2s_info *i2s = to_info(rtd->cpu_dai); +#else + struct rk29_i2s_info *i2s = to_info(rtd->dai->cpu_dai); +#endif + bool stopI2S = false; + + I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + rockchip_snd_rxctrl(i2s, 1, stopI2S); + else + rockchip_snd_txctrl(i2s, 1, stopI2S); + break; + + case SNDRV_PCM_TRIGGER_SUSPEND: + stopI2S = true; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + rockchip_snd_rxctrl(i2s, 0, stopI2S); + else + rockchip_snd_txctrl(i2s, 0, stopI2S); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} +/* + * Set Rockchip Clock source + */ +static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, + int clk_id, unsigned int freq, int dir) +{ + struct rk29_i2s_info *i2s; + + i2s = to_info(cpu_dai); + + I2S_DBG("Enter:%s, %d, i2s=0x%p, freq=%d\n", __FUNCTION__, __LINE__, i2s, freq); + /*add scu clk source and enable clk*/ + clk_set_rate(i2s->iis_clk, freq); + return 0; +} + +/* + * Set Rockchip Clock dividers + */ +static int rockchip_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, + int div_id, int div) +{ + struct rk29_i2s_info *i2s; + u32 reg; + + i2s = to_info(cpu_dai); + + /*stereo mode MCLK/SCK=4*/ + + reg = readl(&(pheadi2s->I2S_TXCKR)); + + I2S_DBG("Enter:%s, %d, div_id=0x%08X, div=0x%08X\n", __FUNCTION__, __LINE__, div_id, div); + + /*when i2s in master mode ,must set codec pll div*/ + switch (div_id) { + case ROCKCHIP_DIV_BCLK: + reg &= ~I2S_TX_SCLK_DIV_MASK; + reg |= I2S_TX_SCLK_DIV(div); + break; + case ROCKCHIP_DIV_MCLK: + reg &= ~I2S_MCLK_DIV_MASK; + reg |= I2S_MCLK_DIV(div); + break; + case ROCKCHIP_DIV_PRESCALER: + + break; + default: + return -EINVAL; + } + writel(reg, &(pheadi2s->I2S_TXCKR)); + writel(reg, &(pheadi2s->I2S_RXCKR)); + return 0; +} + +/* + * To avoid duplicating clock code, allow machine driver to + * get the clockrate from here. + */ +u32 rockchip_i2s_get_clockrate(void) +{ + I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + return 0; ///clk_get_rate(s3c24xx_i2s.iis_clk); +} +EXPORT_SYMBOL_GPL(rockchip_i2s_get_clockrate); + +#ifdef CONFIG_PM +int rockchip_i2s_suspend(struct snd_soc_dai *cpu_dai) +{ + I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + //clk_disable(clk); + return 0; +} + +int rockchip_i2s_resume(struct snd_soc_dai *cpu_dai) +{ + I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + //clk_enable(clk); + return 0; +} +#else +#define rockchip_i2s_suspend NULL +#define rockchip_i2s_resume NULL +#endif + +#if defined(CONFIG_SND_RK_SOC_alc5631) || defined(CONFIG_SND_RK_SOC_alc5621) +#define ROCKCHIP_I2S_RATES (SNDRV_PCM_RATE_44100) //zyy 20110704, playback and record use same sample rate +#else +#define ROCKCHIP_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ + SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) +#endif + +static struct snd_soc_dai_ops rockchip_i2s_dai_ops = { + .trigger = rockchip_i2s_trigger, + .hw_params = rockchip_i2s_hw_params, + .set_fmt = rockchip_i2s_set_fmt, + .set_clkdiv = rockchip_i2s_set_clkdiv, + .set_sysclk = rockchip_i2s_set_sysclk, +}; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) +static int rockchip_i2s_dai_probe(struct snd_soc_dai *dai) +#else +static int rockchip_i2s_dai_probe(struct platform_device *pdev, struct snd_soc_dai *dai) +#endif +{ + I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); + + switch(dai->id) { + case 0: + rk29_mux_api_set(GPIO2D0_I2S0CLK_MIIRXCLKIN_NAME, GPIO2H_I2S0_CLK); + rk29_mux_api_set(GPIO2D1_I2S0SCLK_MIICRS_NAME, GPIO2H_I2S0_SCLK); + rk29_mux_api_set(GPIO2D2_I2S0LRCKRX_MIITXERR_NAME, GPIO2H_I2S0_LRCK_RX); + rk29_mux_api_set(GPIO2D3_I2S0SDI_MIICOL_NAME, GPIO2H_I2S0_SDI); + rk29_mux_api_set(GPIO2D4_I2S0SDO0_MIIRXD2_NAME, GPIO2H_I2S0_SDO0); + rk29_mux_api_set(GPIO2D5_I2S0SDO1_MIIRXD3_NAME, GPIO2H_I2S0_SDO1); + rk29_mux_api_set(GPIO2D6_I2S0SDO2_MIITXD2_NAME, GPIO2H_I2S0_SDO2); + rk29_mux_api_set(GPIO2D7_I2S0SDO3_MIITXD3_NAME, GPIO2H_I2S0_SDO3); + + rk29_mux_api_set(GPIO4D6_I2S0LRCKTX0_NAME, GPIO4H_I2S0_LRCK_TX0); + rk29_mux_api_set(GPIO4D7_I2S0LRCKTX1_NAME, GPIO4H_I2S0_LRCK_TX1); + break; + case 1: + rk29_mux_api_set(GPIO3A0_I2S1CLK_NAME, GPIO3L_I2S1_CLK); + rk29_mux_api_set(GPIO3A1_I2S1SCLK_NAME, GPIO3L_I2S1_SCLK); + rk29_mux_api_set(GPIO3A2_I2S1LRCKRX_NAME, GPIO3L_I2S1_LRCK_RX); + rk29_mux_api_set(GPIO3A3_I2S1SDI_NAME, GPIO3L_I2S1_SDI); + rk29_mux_api_set(GPIO3A4_I2S1SDO_NAME, GPIO3L_I2S1_SDO); + rk29_mux_api_set(GPIO3A5_I2S1LRCKTX_NAME, GPIO3L_I2S1_LRCK_TX); + break; + default: + I2S_DBG("Enter:%s, %d, Error For DevId!!!", __FUNCTION__, __LINE__); + return -EINVAL; + } + return 0; +} + +static int rk29_i2s_probe(struct platform_device *pdev, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + struct snd_soc_dai_driver *dai, +#else + struct snd_soc_dai *dai, +#endif + struct rk29_i2s_info *i2s, + unsigned long base) +{ + struct device *dev = &pdev->dev; + struct resource *res; + + I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); + + i2s->dev = dev; + + /* record our i2s structure for later use in the callbacks */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + dev_set_drvdata(&pdev->dev, i2s); +#else + dai->private_data = i2s; +#endif + + if (!base) { + res = platform_get_resource(pdev, + IORESOURCE_MEM, + 0); + if (!res) { + dev_err(dev, "Unable to get register resource\n"); + return -ENXIO; + } + + if (!request_mem_region(res->start, resource_size(res), + "rk29_i2s")) { + dev_err(dev, "Unable to request register region\n"); + return -EBUSY; + } + + base = res->start; + } + + i2s->regs = ioremap(base, (res->end - res->start) + 1); ////res)); + if (i2s->regs == NULL) { + dev_err(dev, "cannot ioremap registers\n"); + return -ENXIO; + } + + i2s->iis_pclk = clk_get(dev, "i2s"); + if (IS_ERR(i2s->iis_pclk)) { + dev_err(dev, "failed to get iis_clock\n"); + iounmap(i2s->regs); + return -ENOENT; + } + + clk_enable(i2s->iis_pclk); + + /* Mark ourselves as in TXRX mode so we can run through our cleanup + * process without warnings. */ + rockchip_snd_txctrl(i2s, 0, true); + rockchip_snd_rxctrl(i2s, 0, true); + + return 0; +} + +static int __devinit rockchip_i2s_probe(struct platform_device *pdev) +{ + struct rk29_i2s_info *i2s; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + struct snd_soc_dai_driver *dai; +#else + struct snd_soc_dai *dai; +#endif + int ret; + + I2S_DBG("Enter %s, %d pdev->id = %d >>>>>>>>>>>\n", __func__, __LINE__, pdev->id); + + if(pdev->id >= MAX_I2S) { + dev_err(&pdev->dev, "id %d out of range\n", pdev->id); + return -EINVAL; + } + + i2s = &rk29_i2s[pdev->id]; + dai = &rk29_i2s_dai[pdev->id]; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)) + dai->dev = &pdev->dev; +#endif + dai->id = pdev->id; + dai->symmetric_rates = 1; + if(pdev->id == 0) { + dai->name = "rk_i2s.0"; + dai->playback.channels_min = 2; + dai->playback.channels_max = 8; + }else{ + dai->name = "rk_i2s.1"; + dai->playback.channels_min = 2; + dai->playback.channels_max = 2; + } + dai->playback.rates = ROCKCHIP_I2S_RATES; + dai->playback.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE; + dai->capture.channels_min = 2; + dai->capture.channels_max = 2; + dai->capture.rates = ROCKCHIP_I2S_RATES;//;SNDRV_PCM_RATE_44100 + dai->capture.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE; + dai->probe = rockchip_i2s_dai_probe; + dai->ops = &rockchip_i2s_dai_ops; + dai->suspend = rockchip_i2s_suspend; + dai->resume = rockchip_i2s_resume; + + //i2s->feature |= S3C_FEATURE_CDCLKCON; + + i2s->dma_capture = &rk29_i2s_pcm_stereo_in[pdev->id]; + i2s->dma_playback = &rk29_i2s_pcm_stereo_out[pdev->id]; + + if (pdev->id == 1) { + i2s->dma_capture->channel = DMACH_I2S_2CH_RX; + i2s->dma_capture->dma_addr = RK29_I2S_2CH_PHYS + I2S_RXR_BUFF; + i2s->dma_playback->channel = DMACH_I2S_2CH_TX; + i2s->dma_playback->dma_addr = RK29_I2S_2CH_PHYS + I2S_TXR_BUFF; + } else { + i2s->dma_capture->channel = DMACH_I2S_8CH_RX; + i2s->dma_capture->dma_addr = RK29_I2S_8CH_PHYS + I2S_RXR_BUFF; + i2s->dma_playback->channel = DMACH_I2S_8CH_TX; + i2s->dma_playback->dma_addr = RK29_I2S_8CH_PHYS + I2S_TXR_BUFF; + } + + i2s->dma_capture->client = &rk29_dma_client_in; + i2s->dma_capture->dma_size = 4; + i2s->dma_capture->flag = 0; //add by sxj, used for burst change + i2s->dma_playback->client = &rk29_dma_client_out; + i2s->dma_playback->dma_size = 4; + i2s->dma_playback->flag = 0; //add by sxj, used for burst change +#ifdef CONFIG_SND_I2S_DMA_EVENT_STATIC + WARN_ON(rk29_dma_request(i2s->dma_playback->channel, i2s->dma_playback->client, NULL)); + WARN_ON(rk29_dma_request(i2s->dma_capture->channel, i2s->dma_capture->client, NULL)); +#endif + i2s->iis_clk = clk_get(&pdev->dev, "i2s"); + I2S_DBG("Enter:%s, %d, iis_clk=%p\n", __FUNCTION__, __LINE__, i2s->iis_clk); + if (IS_ERR(i2s->iis_clk)) { + dev_err(&pdev->dev, "failed to get i2s clk\n"); + ret = PTR_ERR(i2s->iis_clk); + goto err; + } + + clk_enable(i2s->iis_clk); + clk_set_rate(i2s->iis_clk, 11289600); + ret = rk29_i2s_probe(pdev, dai, i2s, 0); + if (ret) + goto err_clk; + + ret = snd_soc_register_dai(&pdev->dev, dai); + if (ret != 0) + goto err_i2sv2; + + return 0; + +err_i2sv2: + /* Not implemented for I2Sv2 core yet */ +err_clk: + clk_put(i2s->iis_clk); +err: + return ret; +} + + +static int __devexit rockchip_i2s_remove(struct platform_device *pdev) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + snd_soc_unregister_dai(&pdev->dev); +#else + snd_soc_unregister_dai(&rk29_i2s_dai); +#endif + + return 0; +} + +static struct platform_driver rockchip_i2s_driver = { + .probe = rockchip_i2s_probe, + .remove = __devexit_p(rockchip_i2s_remove), + .driver = { + .name = "rk29_i2s", + .owner = THIS_MODULE, + }, +}; + +static int __init rockchip_i2s_init(void) +{ + I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); + + return platform_driver_register(&rockchip_i2s_driver); +} +module_init(rockchip_i2s_init); + +static void __exit rockchip_i2s_exit(void) +{ + platform_driver_unregister(&rockchip_i2s_driver); +} +module_exit(rockchip_i2s_exit); + +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface"); +MODULE_LICENSE("GPL"); + + +#ifdef CONFIG_PROC_FS +#include +#include +static int proc_i2s_show(struct seq_file *s, void *v) +{ + struct rk29_i2s_info *i2s=&rk29_i2s[0]; + + printk("========Show I2S reg========\n"); + + printk("I2S_TXCR = 0x%08X\n", readl(&(pheadi2s->I2S_TXCR))); + printk("I2S_RXCR = 0x%08X\n", readl(&(pheadi2s->I2S_RXCR))); + printk("I2S_TXCKR = 0x%08X\n", readl(&(pheadi2s->I2S_TXCKR))); + printk("I2S_RXCKR = 0x%08X\n", readl(&(pheadi2s->I2S_RXCKR))); + printk("I2S_DMACR = 0x%08X\n", readl(&(pheadi2s->I2S_DMACR))); + printk("I2S_INTCR = 0x%08X\n", readl(&(pheadi2s->I2S_INTCR))); + printk("I2S_INTSR = 0x%08X\n", readl(&(pheadi2s->I2S_INTSR))); + printk("I2S_XFER = 0x%08X\n", readl(&(pheadi2s->I2S_XFER))); + + printk("========Show I2S reg========\n"); + return 0; +} + +static int proc_i2s_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_i2s_show, NULL); +} + +static const struct file_operations proc_i2s_fops = { + .open = proc_i2s_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init i2s_proc_init(void) +{ + proc_create("i2s_reg", 0, NULL, &proc_i2s_fops); + return 0; + +} +late_initcall(i2s_proc_init); +#endif /* CONFIG_PROC_FS */ + diff --git a/sound/soc/rk/rk29_i2s.h b/sound/soc/rk/rk29_i2s.h new file mode 100755 index 000000000000..91d09ab2c75a --- /dev/null +++ b/sound/soc/rk/rk29_i2s.h @@ -0,0 +1,257 @@ +/* + * rockchip-iis.h - ALSA IIS interface for the Rockchip rk28 SoC + * + * Driver for rockchip iis audio + * + * 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 + +#ifndef _ROCKCHIP_IIS_H +#define _ROCKCHIP_IIS_H + +//I2S_TXCR + +#define PCM_2DATA (0<<18) +#define PCM_4DATA (1<<18) +#define PCM_6DATA (2<<18) +#define PCM_8DATA (3<<18) + +#define CHANNEL_1_EN (0<<15) +#define CHANNEL_2_EN (1<<15) +#define CHANNEL_3_EN (2<<15) +#define CHANNLE_4_EN (3<<15) +#define TX_MODE_MASTER (0<<13) +#define TX_MODE_SLAVE (1<<13) +#define RESET_TX (1<<17) +#define RESET_RX (1<<16) +#define I2S_DMA_REQ1_DISABLE (1<<6) +#define I2S_DMA_REQ1_ENABLE (0) +#define I2S_DMA_REQ2_DISABLE (1<<5) +#define I2S_DMA_REQ2_ENABLE (0) +#define I2S_DMA_REQ1_TX_ENABLE (0) +#define I2S_DMA_REQ1_RX_ENABLE (1<<4) +#define I2S_DMA_REQ2_TX_ENABLE (0) +#define I2S_DMA_REQ2_RX_ENABLE (1<<3) +#define TX_START (1<<1) +#define RX_START (1) + + + +//I2S_TXCTL I2S_RXCTL +#define CLEAR_RXFIFO (1<<24) +#define TRAN_DEVICES0 (0) +#define TRAN_DEVICES1 (1<<18) +#define TRAN_DEVICES2 (2<<18) +#define TRAN_DEVICES3 (3<<18) +#define OVERSAMPLING_RATE_32FS (0) +#define OVERSAMPLING_RATE_64FS (1<<16) +#define OVERSAMPLING_RATE_128FS (2<<16) +#define SCK_RATE2 (0x02<<8) +#define SCK_RATE4 (0x04<<8) +#define SCK_RATE8 (0x08<<8) +#define SAMPLE_DATA_8bit (0) +#define SAMPLE_DATA_16bit (1<<4) +#define SAMPLE_DATA_MASK (3<<4) +#define MONO_MODE (1<<3) +#define STEREO_MODE (0) +#define I2S_MODE (0) +#define LEFT_JUSTIFIED (1<<1) +#define RIGHT_JUSTIFIED (2<<1) +#define IISMOD_SDF_MASK (3<<1) +#define MASTER_MODE (1) +#define SLAVE_MODE (0) + +//I2S_FIFOSTS +#define TX_HALF_FULL (1<<18) +#define RX_HALF_FULL (1<<16) + +/* Clock dividers */ +#define ROCKCHIP_DIV_MCLK 0 +#define ROCKCHIP_DIV_BCLK 1 +#define ROCKCHIP_DIV_PRESCALER 2 + + +/* I2S_TXCR */ +#define I2S_RSTL_SCLK(c) ((c&0x3F)<<26) +#define I2S_RSTR_SCLK(c) ((c&0x3F)<<20) + +#define I2S_PCM_2DATA (0<<18) +#define I2S_PCM_4DATA (1<<18) +#define I2S_PCM_6DATA (2<<18) +#define I2S_PCM_8DATA (3<<18) +#define I2S_PCM_DATA_MASK (3<<18) + +#define I2S_CSR_CH2 (0<<15) +#define I2S_CSR_CH4 (1<<15) +#define I2S_CRS_CH6 (2<<15) +#define I2S_CRS_CH8 (3<<15) +#define I2S_CRS_CH_MASK (3<<15) + +#define I2S_HWT_16BIT (0<<14) +#define I2S_HWT_32BIT (1<<14) + +#ifdef CONFIG_ARCH_RK29 + #define I2S_MASTER_MODE (0<<13) + #define I2S_SLAVE_MODE (1<<13) + #define I2S_MODE_MASK (1<<13) +#endif + +#define I2S_JUSTIFIED_RIGHT (0<<12) +#define I2S_JUSTIFIED_LEFT (1<<12) + +#define I2S_FIRST_BIT_MSB (0<<11) +#define I2S_FIRST_BIT_LSB (1<<11) + +#define I2S_BUS_MODE_NOR (0<<9) +#define I2S_BUS_MODE_LSJM (1<<9) +#define I2S_BUS_MODE_RSJM (2<<9) +#define I2S_BUS_MODE_MASK (3<<9) + +#define I2S_PCM_NO_DELAY (0<<7) +#define I2S_PCM_DELAY_1MODE (1<<7) +#define I2S_PCM_DELAY_2MODE (2<<7) +#define I2S_PCM_DELAY_3MODE (3<<7) +#define I2S_PCM_DELAY_MASK (3<<7) + +#define I2S_TX_LRCK_OUT_BT_DISABLE (0<<6) +#define I2S_TX_LRCK_OUT_BT_ENABLE (1<<6) + +#define I2S_TX_LRCK_OUT_I2S (0<<5) +#define I2S_TX_LRCK_OUT_PCM (1<<5) + +#define I2S_DATA_WIDTH(w) ((w&0x1F)<<0) + +/* */ + + +/* I2S_TXCKR */ +#ifdef CONFIG_ARCH_RK29 + #define I2S_TSP_POSEDGE (0<<25) + #define I2S_TSP_NEGEDGE (1<<25) + #define I2S_TLP_NORMAL (0<<24) + #define I2S_TLP_OPPSITE (1<<24) + + #define I2S_MCLK_DIV(x) ((0xFF&x)<<16) + #define I2S_MCLK_DIV_MASK ((0xFF)<<16) + + #define I2S_TSD_FIXED (0<<12) + #define I2S_TSD_CHANGED (1<<12) + + #define I2S_TX_LRCK_NO_DELAY (0<<10) + #define I2S_TX_LRCK_DELAY_ONE (1<<10) + #define I2S_TX_LRCK_DELAY_TWO (2<<10) + #define I2S_TX_LRCK_DELAY_THREE (3<<10) + #define I2S_TX_LRCK_DELAY_MASK (3<<10) + + #define I2S_TX_SCLK_DIV(x) (x&0x3FF) + #define I2S_TX_SCLK_DIV_MASK (0x3FF); +#else +//I2S_CKR + #define I2S_MASTER_MODE (0<<27) + #define I2S_SLAVE_MODE (1<<27) + #define I2S_MODE_MASK (1<<27) + + #define I2S_BCLK_POSEDGE (0<<26)//sclk polarity invert?? + #define I2S_BCLK_NEGEDGE (1<<26) + + #define I2S_RX_LRCK_POSEDGE (0<<25)//LRCK polarity invert?? + #define I2S_RX_LRCK_NEGEDGE (1<<25) + + #define I2S_TX_LRCK_POSEDGE (0<<24) + #define I2S_TX_LRCK_NEGEDGE (1<<24) + + #define I2S_MCLK_DIV(x) ((0xFF&x)<<16) + #define I2S_MCLK_DIV_MASK ((0xFF)<<16) + + #define I2S_RX_SCLK_DIV(x) ((x&0xFF)<<8) + #define I2S_RX_SCLK_DIV_MASK ((0xFF)<<8) + + #define I2S_TX_SCLK_DIV(x) (x&0xFF) + #define I2S_TX_SCLK_DIV_MASK (0xFF) +#endif + +/* I2S_DMACR */ +#define I2S_RECE_DMA_DISABLE (0<<24) +#define I2S_RECE_DMA_ENABLE (1<<24) +#define I2S_DMARDL(x) ((x&0x1f)<<16) + +#define I2S_TRAN_DMA_DISABLE (0<<8) +#define I2S_TRAN_DMA_ENABLE (1<<8) +#define I2S_DMATDL(x) ((x&0x1f)<<0) + +/* I2S_INTCR */ +#define I2S_RXOV_INT_DISABLE (0<<17) +#define I2S_RXOV_INT_ENABLE (1<<17) +#define I2S_RXFU_INT_DISABLE (0<<16) +#define I2S_RXFU_INT_ENABLE (1<<16) + +#define I2S_TXUND_INT_DISABLE (0<<1) +#define I2S_TXUND_INT_ENABLE (1<<1) +#define I2S_TXEMP_INT_DISABLE (0<<0) +#define I2S_TXEMP_INT_ENABLE (1<<0) + +/* I2S_XFER */ +#define I2S_RX_TRAN_STOP (0<<1) +#define I2S_RX_TRAN_START (1<<1) +#define I2S_TX_TRAN_STOP (0<<0) +#define I2S_TX_TRAN_START (1<<0) + +//I2S_CLR +#define I2S_RX_CLEAR (1<<1) +#define I2S_TX_CLEAR 1 + + +#ifdef CONFIG_ARCH_RK29 +#define I2S_TXR_BUFF 0x20 +#define I2S_RXR_BUFF 0x24 +//I2S Registers +typedef volatile struct tagIIS_STRUCT +{ + unsigned int I2S_TXCR; + unsigned int I2S_RXCR; + unsigned int I2S_TXCKR; + unsigned int I2S_RXCKR; + unsigned int I2S_FIFOLR; + unsigned int I2S_DMACR; + unsigned int I2S_INTCR; + unsigned int I2S_INTSR; + unsigned int I2S_TXDR; + unsigned int I2S_RXDR; + unsigned int I2S_XFER; + unsigned int I2S_TXRST; + unsigned int I2S_RXRST; +}I2S_REG,*pI2S_REG; +#else +#define I2S_TXR_BUFF 0x24 +#define I2S_RXR_BUFF 0x28 +typedef volatile struct tagIIS_STRUCT +{ + unsigned int I2S_TXCR;//0xF 0 + unsigned int I2S_RXCR;//0xF 4 + unsigned int I2S_CKR;//0x3F 8 + unsigned int I2S_FIFOLR;//c + unsigned int I2S_DMACR;//0x001F0110 10 + unsigned int I2S_INTCR;//0x01F00000 14 + unsigned int I2S_INTSR;//0x00 18 + unsigned int I2S_XFER;//0x00000003 1c + unsigned int I2S_CLR;//20 + unsigned int I2S_TXDR;//24 + unsigned int I2S_RXDR; +}I2S_REG,*pI2S_REG; +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) +extern struct snd_soc_dai_driver rk29_i2s_dai[]; +#else +extern struct snd_soc_dai rk29_i2s_dai[]; +#endif + +#ifdef CONFIG_SND_SOC_RT5631 +extern struct delayed_work rt5631_delay_cap; //bard 7-16 +#endif + +#endif /* _ROCKCHIP_IIS_H */ + diff --git a/sound/soc/rk/rk30_i2s.c b/sound/soc/rk/rk30_i2s.c new file mode 100755 index 000000000000..798bd770b52a --- /dev/null +++ b/sound/soc/rk/rk30_i2s.c @@ -0,0 +1,929 @@ +/* + * rk29_i2s.c -- ALSA SoC ROCKCHIP IIS Audio Layer Platform driver + * + * Driver for rockchip iis audio + * + * + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "rk_pcm.h" +#include "rk29_i2s.h" + +#define ANDROID_REC +#if 0 +#define I2S_DBG(x...) printk(KERN_INFO x) +#else +#define I2S_DBG(x...) do { } while (0) +#endif + +#define pheadi2s ((pI2S_REG)(i2s->regs)) + +#define MAX_I2S 3 + +struct rk29_i2s_info { + struct device *dev; + void __iomem *regs; + + u32 feature; + + struct clk *iis_clk; + struct clk *iis_pclk; + + unsigned char master; + + struct rockchip_pcm_dma_params *dma_playback; + struct rockchip_pcm_dma_params *dma_capture; + + u32 suspend_iismod; + u32 suspend_iiscon; + u32 suspend_iispsr; + + bool i2s_tx_status;//active = true; + bool i2s_rx_status; + spinlock_t spinlock_wr;//write read reg spin_lock +}; + +static struct snd_soc_dai *rk_cpu_dai=NULL; +static struct rk29_dma_client rk29_dma_client_out = { + .name = "I2S PCM Stereo Out" +}; + +static struct rk29_dma_client rk29_dma_client_in = { + .name = "I2S PCM Stereo In" +}; + +static inline struct rk29_i2s_info *to_info(struct snd_soc_dai *cpu_dai) +{ + return snd_soc_dai_get_drvdata(cpu_dai); +} + +static struct rockchip_pcm_dma_params rk29_i2s_pcm_stereo_out[MAX_I2S]; +static struct rockchip_pcm_dma_params rk29_i2s_pcm_stereo_in[MAX_I2S]; +static struct rk29_i2s_info rk29_i2s[MAX_I2S]; + +struct snd_soc_dai_driver rk29_i2s_dai[MAX_I2S]; +EXPORT_SYMBOL_GPL(rk29_i2s_dai); +#if defined (CONFIG_RK_HDMI) && defined (CONFIG_SND_RK_SOC_HDMI_I2S) +extern int hdmi_get_hotplug(void); +#endif +/* + *Turn on or off the transmission path. + */ +static void rockchip_snd_txctrl(struct rk29_i2s_info *i2s, int on) +{ + u32 opr,xfer,clr; + spin_lock(&i2s->spinlock_wr); + opr = readl(&(pheadi2s->I2S_DMACR)); + xfer = readl(&(pheadi2s->I2S_XFER)); + clr = readl(&(pheadi2s->I2S_CLR)); + if (on) + { + I2S_DBG("rockchip_snd_txctrl: on\n"); + if ((opr & I2S_TRAN_DMA_ENABLE) == 0) + { + opr |= I2S_TRAN_DMA_ENABLE; + writel(opr, &(pheadi2s->I2S_DMACR)); + } + if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0) + { + xfer |= I2S_TX_TRAN_START; + xfer |= I2S_RX_TRAN_START; + writel(xfer, &(pheadi2s->I2S_XFER)); + } + i2s->i2s_tx_status = true; + spin_unlock(&i2s->spinlock_wr); + } + else + { + //stop tx + i2s->i2s_tx_status = false; + I2S_DBG("rockchip_snd_txctrl: off\n"); + opr &= ~I2S_TRAN_DMA_ENABLE; + writel(opr, &(pheadi2s->I2S_DMACR)); + if(!i2s->i2s_tx_status && !i2s->i2s_rx_status//sync stop i2s rx tx lcrk +#if defined (CONFIG_RK_HDMI) && defined (CONFIG_SND_RK_SOC_HDMI_I2S) + && hdmi_get_hotplug() == 0 //HDMI_HPD_REMOVED +#endif + ) + { + xfer &= ~I2S_TX_TRAN_START; + xfer &= ~I2S_RX_TRAN_START; + writel(xfer, &(pheadi2s->I2S_XFER)); + clr |= I2S_TX_CLEAR; + clr |= I2S_RX_CLEAR; + writel(clr, &(pheadi2s->I2S_CLR)); + spin_unlock(&i2s->spinlock_wr); + udelay(1); + I2S_DBG("rockchip_snd_txctrl: stop xfer\n"); + } + else + spin_unlock(&i2s->spinlock_wr); + } +} + +static void rockchip_snd_rxctrl(struct rk29_i2s_info *i2s, int on) +{ + u32 opr,xfer,clr; + spin_lock(&i2s->spinlock_wr); + opr = readl(&(pheadi2s->I2S_DMACR)); + xfer = readl(&(pheadi2s->I2S_XFER)); + clr = readl(&(pheadi2s->I2S_CLR)); + if (on) + { + I2S_DBG("rockchip_snd_rxctrl: on\n"); + if ((opr & I2S_RECE_DMA_ENABLE) == 0) + { + opr |= I2S_RECE_DMA_ENABLE; + writel(opr, &(pheadi2s->I2S_DMACR)); + } + if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0) + { + xfer |= I2S_RX_TRAN_START; + xfer |= I2S_TX_TRAN_START; + writel(xfer, &(pheadi2s->I2S_XFER)); + } + i2s->i2s_rx_status = true; + spin_unlock(&i2s->spinlock_wr); +#ifdef CONFIG_SND_SOC_RT5631 +//bard 7-16 s + schedule_delayed_work(&rt5631_delay_cap,HZ/4); +//bard 7-16 e +#endif + } + else + { + i2s->i2s_rx_status = false; + I2S_DBG("rockchip_snd_rxctrl: off\n"); + opr &= ~I2S_RECE_DMA_ENABLE; + writel(opr, &(pheadi2s->I2S_DMACR)); + if(!i2s->i2s_tx_status && !i2s->i2s_rx_status //sync stop i2s rx tx lcrk +#if defined (CONFIG_RK_HDMI) && defined (CONFIG_SND_RK_SOC_HDMI_I2S) + && hdmi_get_hotplug() == 0 //HDMI_HPD_REMOVED +#endif + ) + { + xfer &= ~I2S_RX_TRAN_START; + xfer &= ~I2S_TX_TRAN_START; + writel(xfer, &(pheadi2s->I2S_XFER)); + clr |= I2S_RX_CLEAR; + clr |= I2S_TX_CLEAR; + writel(clr, &(pheadi2s->I2S_CLR)); + spin_unlock(&i2s->spinlock_wr); + udelay(1); + I2S_DBG("rockchip_snd_rxctrl: stop xfer\n"); + } + else + spin_unlock(&i2s->spinlock_wr); + } +} + +/* + * Set Rockchip I2S DAI format + */ +static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, + unsigned int fmt) +{ + struct rk29_i2s_info *i2s = to_info(cpu_dai); + u32 tx_ctl,rx_ctl; + u32 iis_ckr_value;//clock generation register + + I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + spin_lock(&i2s->spinlock_wr); + tx_ctl = readl(&(pheadi2s->I2S_TXCR)); + iis_ckr_value = readl(&(pheadi2s->I2S_CKR)); + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + iis_ckr_value &= ~I2S_MODE_MASK; + iis_ckr_value |= I2S_MASTER_MODE; + break; + case SND_SOC_DAIFMT_CBS_CFS: + iis_ckr_value &= ~I2S_MODE_MASK; + iis_ckr_value |= I2S_SLAVE_MODE; + break; + default: + I2S_DBG("unknwon master/slave format\n"); + return -EINVAL; + } + writel(iis_ckr_value, &(pheadi2s->I2S_CKR)); + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_RIGHT_J: + tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode + tx_ctl |= I2S_BUS_MODE_RSJM; + break; + case SND_SOC_DAIFMT_LEFT_J: + tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode + tx_ctl |= I2S_BUS_MODE_LSJM; + break; + case SND_SOC_DAIFMT_I2S: + tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode + tx_ctl |= I2S_BUS_MODE_NOR; + break; + default: + I2S_DBG("Unknown data format\n"); + return -EINVAL; + } + I2S_DBG("Enter::%s----%d, I2S_TXCR=0x%X\n",__FUNCTION__,__LINE__,tx_ctl); + + writel(tx_ctl, &(pheadi2s->I2S_TXCR)); + + rx_ctl = tx_ctl & 0x00007FFF; + writel(rx_ctl, &(pheadi2s->I2S_RXCR)); + spin_unlock(&i2s->spinlock_wr); + return 0; +} + +static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *socdai) +{ + struct rk29_i2s_info *i2s = to_info(socdai); + u32 iismod; + u32 dmarc; + u32 iis_ckr_value;//clock generation register + + I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + snd_soc_dai_set_dma_data(socdai, substream, i2s->dma_playback); + else + snd_soc_dai_set_dma_data(socdai, substream, i2s->dma_capture); + + /* Working copies of register */ + spin_lock(&i2s->spinlock_wr); + iismod = readl(&(pheadi2s->I2S_TXCR)); + + iismod &= (~((1<<5)-1)); + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + iismod |= SAMPLE_DATA_8bit; + break; + case SNDRV_PCM_FORMAT_S16_LE: + iismod |= I2S_DATA_WIDTH(15); + break; + case SNDRV_PCM_FORMAT_S20_3LE: + iismod |= I2S_DATA_WIDTH(19); + break; + case SNDRV_PCM_FORMAT_S24_LE: + iismod |= I2S_DATA_WIDTH(23); + break; + case SNDRV_PCM_FORMAT_S32_LE: + iismod |= I2S_DATA_WIDTH(31); + break; + } + + iis_ckr_value = readl(&(pheadi2s->I2S_CKR)); + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + iis_ckr_value &= ~I2S_SLAVE_MODE; + #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + iis_ckr_value |= I2S_SLAVE_MODE; + #endif + writel(iis_ckr_value, &(pheadi2s->I2S_CKR)); + +// writel((16<<24) |(16<<18)|(16<<12)|(16<<6)|16, &(pheadi2s->I2S_FIFOLR)); + dmarc = readl(&(pheadi2s->I2S_DMACR)); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dmarc = ((dmarc & 0xFFFFFE00) | 16); + else + dmarc = ((dmarc & 0xFE00FFFF) | 16<<16); + + writel(dmarc, &(pheadi2s->I2S_DMACR)); + I2S_DBG("Enter %s, %d I2S_TXCR=0x%08X\n", __func__, __LINE__, iismod); + + writel(iismod, &(pheadi2s->I2S_TXCR)); + + iismod = iismod & 0x00007FFF; + writel(iismod, &(pheadi2s->I2S_RXCR)); + spin_unlock(&i2s->spinlock_wr); + return 0; +} + +static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct rk29_i2s_info *i2s = to_info(rtd->cpu_dai); + + I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + rockchip_snd_rxctrl(i2s, 1); + else + rockchip_snd_txctrl(i2s, 1); + break; + + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + rockchip_snd_rxctrl(i2s, 0); + else + rockchip_snd_txctrl(i2s, 0); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/* + * Set Rockchip I2S MCLK source + */ +static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, + int clk_id, unsigned int freq, int dir) +{ + struct rk29_i2s_info *i2s; + + i2s = to_info(cpu_dai); + + I2S_DBG("Enter:%s, %d, i2s=0x%p, freq=%d\n", __FUNCTION__, __LINE__, i2s, freq); + /*add scu clk source and enable clk*/ + clk_set_rate(i2s->iis_clk, freq); + return 0; +} + +/* + * Set Rockchip Clock dividers + */ +static int rockchip_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, + int div_id, int div) +{ + struct rk29_i2s_info *i2s; + u32 reg; + + i2s = to_info(cpu_dai); + + //stereo mode MCLK/SCK=4 + spin_lock(&i2s->spinlock_wr); + reg = readl(&(pheadi2s->I2S_CKR)); + + I2S_DBG("Enter:%s, %d, div_id=0x%08X, div=0x%08X\n", __FUNCTION__, __LINE__, div_id, div); + + //when i2s in master mode ,must set codec pll div + switch (div_id) { + case ROCKCHIP_DIV_BCLK: + reg &= ~I2S_TX_SCLK_DIV_MASK; + reg |= I2S_TX_SCLK_DIV(div); + reg &= ~I2S_RX_SCLK_DIV_MASK; + reg |= I2S_RX_SCLK_DIV(div); + break; + case ROCKCHIP_DIV_MCLK: + reg &= ~I2S_MCLK_DIV_MASK; + reg |= I2S_MCLK_DIV(div); + break; + case ROCKCHIP_DIV_PRESCALER: + break; + default: + return -EINVAL; + } + writel(reg, &(pheadi2s->I2S_CKR)); + spin_unlock(&i2s->spinlock_wr); + return 0; +} + +static int i2s_set_gpio_mode(struct snd_soc_dai *dai) +{ + I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); + switch(dai->id) { +#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) + case 1: + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_MCLK)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SCLK)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_LRCKRX)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_LRCKTX)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SDI)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SDO)); + break; +#elif defined(CONFIG_ARCH_RK30) + case 0: + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_MCLK)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SCLK)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_LRCKRX)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_LRCKTX)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SDI)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SDO0)); + #ifdef CONFIG_SND_I2SO_USE_EIGHT_CHANNELS + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SDO1)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SDO2)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SDO3)); + #endif + break; + case 1: + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S1_MCLK)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S1_SCLK)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S1_LRCKRX)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S1_LRCKTX)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S1_SDI)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S1_SDO)); + break; + case 2: + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S2_MCLK)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S2_SCLK)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S2_LRCKRX)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S2_LRCKTX)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S2_SDI)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S2_SDO)); + break; +#endif +#if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026) + case 0: + #if 0 //iomux --> gps(.ko) + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_MCLK)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SCLK)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_LRCKRX)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_LRCKTX)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SDI)); + iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SDO)); + #endif + break; +#endif + default: + I2S_DBG("Enter:%s, %d, Error For DevId!!!", __FUNCTION__, __LINE__); + return -EINVAL; + } + return 0; +} + +static int rockchip_i2s_dai_probe(struct snd_soc_dai *dai) +{ + I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); + if(rk_cpu_dai == NULL) + rk_cpu_dai = dai; + switch(dai->id) { +#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) + case 1: + iomux_set(I2S0_MCLK); + iomux_set(I2S0_SCLK); + iomux_set(I2S0_LRCKRX); + iomux_set(I2S0_LRCKTX); + iomux_set(I2S0_SDI); + iomux_set(I2S0_SDO); + break; +#elif defined(CONFIG_ARCH_RK30) + case 0: + rk30_mux_api_set(GPIO0A7_I2S8CHSDI_NAME, GPIO0A_I2S_8CH_SDI); + rk30_mux_api_set(GPIO0B0_I2S8CHCLK_NAME, GPIO0B_I2S_8CH_CLK); + rk30_mux_api_set(GPIO0B1_I2S8CHSCLK_NAME, GPIO0B_I2S_8CH_SCLK); + rk30_mux_api_set(GPIO0B2_I2S8CHLRCKRX_NAME, GPIO0B_I2S_8CH_LRCK_RX); + rk30_mux_api_set(GPIO0B3_I2S8CHLRCKTX_NAME, GPIO0B_I2S_8CH_LRCK_TX); + rk30_mux_api_set(GPIO0B4_I2S8CHSDO0_NAME, GPIO0B_I2S_8CH_SDO0); + #ifdef CONFIG_SND_I2SO_USE_EIGHT_CHANNELS + rk30_mux_api_set(GPIO0B5_I2S8CHSDO1_NAME, GPIO0B_I2S_8CH_SDO1); + rk30_mux_api_set(GPIO0B6_I2S8CHSDO2_NAME, GPIO0B_I2S_8CH_SDO2); + rk30_mux_api_set(GPIO0B7_I2S8CHSDO3_NAME, GPIO0B_I2S_8CH_SDO3); + #endif + break; + case 1: + rk30_mux_api_set(GPIO0C0_I2S12CHCLK_NAME, GPIO0C_I2S1_2CH_CLK); + rk30_mux_api_set(GPIO0C1_I2S12CHSCLK_NAME, GPIO0C_I2S1_2CH_SCLK); + rk30_mux_api_set(GPIO0C2_I2S12CHLRCKRX_NAME, GPIO0C_I2S1_2CH_LRCK_RX); + rk30_mux_api_set(GPIO0C3_I2S12CHLRCKTX_NAME, GPIO0C_I2S1_2CH_LRCK_TX); + rk30_mux_api_set(GPIO0C4_I2S12CHSDI_NAME, GPIO0C_I2S1_2CH_SDI); + rk30_mux_api_set(GPIO0C5_I2S12CHSDO_NAME, GPIO0C_I2S1_2CH_SDO); + break; + case 2: + rk30_mux_api_set(GPIO0D0_I2S22CHCLK_SMCCSN0_NAME, GPIO0D_I2S2_2CH_CLK); + rk30_mux_api_set(GPIO0D1_I2S22CHSCLK_SMCWEN_NAME, GPIO0D_I2S2_2CH_SCLK); + rk30_mux_api_set(GPIO0D2_I2S22CHLRCKRX_SMCOEN_NAME, GPIO0D_I2S2_2CH_LRCK_RX); + rk30_mux_api_set(GPIO0D3_I2S22CHLRCKTX_SMCADVN_NAME, GPIO0D_I2S2_2CH_LRCK_TX); + rk30_mux_api_set(GPIO0D4_I2S22CHSDI_SMCADDR0_NAME, GPIO0D_I2S2_2CH_SDI); + rk30_mux_api_set(GPIO0D5_I2S22CHSDO_SMCADDR1_NAME, GPIO0D_I2S2_2CH_SDO); + break; +#endif +#if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026) + case 0: + #if 0 //iomux --> gps(.ko) + rk30_mux_api_set(GPIO1A0_I2S_MCLK_NAME, GPIO1A_I2S_MCLK); + rk30_mux_api_set(GPIO1A1_I2S_SCLK_NAME, GPIO1A_I2S_SCLK); + rk30_mux_api_set(GPIO1A2_I2S_LRCKRX_GPS_CLK_NAME, GPIO1A_I2S_LRCKRX); + rk30_mux_api_set(GPIO1A3_I2S_LRCKTX_NAME, GPIO1A_I2S_LRCKTX); + rk30_mux_api_set(GPIO1A4_I2S_SDO_GPS_MAG_NAME, GPIO1A_I2S_SDO); + rk30_mux_api_set(GPIO1A5_I2S_SDI_GPS_SIGN_NAME, GPIO1A_I2S_SDI); + #endif + break; +#endif + default: + I2S_DBG("Enter:%s, %d, Error For DevId!!!", __FUNCTION__, __LINE__); + return -EINVAL; + } + return 0; +} + +#ifdef CONFIG_PM +int rockchip_i2s_suspend(struct snd_soc_dai *cpu_dai) +{ + I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); +// clk_disable(clk); + return 0; +} + +int rockchip_i2s_resume(struct snd_soc_dai *cpu_dai) +{ + I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); +// clk_enable(clk); + return 0; +} +#else +#define rockchip_i2s_suspend NULL +#define rockchip_i2s_resume NULL +#endif + +#ifdef ANDROID_REC +#define ROCKCHIP_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) +#else +#define ROCKCHIP_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ + SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) +#endif + +static struct snd_soc_dai_ops rockchip_i2s_dai_ops = { + .trigger = rockchip_i2s_trigger, + .hw_params = rockchip_i2s_hw_params, + .set_fmt = rockchip_i2s_set_fmt, + .set_clkdiv = rockchip_i2s_set_clkdiv, + .set_sysclk = rockchip_i2s_set_sysclk, +}; + +static int rk29_i2s_probe(struct platform_device *pdev, + struct snd_soc_dai_driver *dai, + struct rk29_i2s_info *i2s, + unsigned long base) +{ + struct device *dev = &pdev->dev; + struct resource *res; + + I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); + + i2s->dev = dev; + + /* record our i2s structure for later use in the callbacks */ + dev_set_drvdata(&pdev->dev, i2s); + + if (!base) { + res = platform_get_resource(pdev, + IORESOURCE_MEM, + 0); + if (!res) { + dev_err(dev, "Unable to get register resource\n"); + return -ENXIO; + } + + if (!request_mem_region(res->start, resource_size(res), + "rk29_i2s")) { + dev_err(dev, "Unable to request register region\n"); + return -EBUSY; + } + + base = res->start; + } + + i2s->regs = ioremap(base, (res->end - res->start) + 1); ////res)); + if (i2s->regs == NULL) { + dev_err(dev, "cannot ioremap registers\n"); + return -ENXIO; + } + + i2s->iis_pclk = clk_get(dev, "hclk_i2s"); + if (IS_ERR(i2s->iis_pclk)) { + dev_err(dev, "failed to get iis_clock\n"); + iounmap(i2s->regs); + return -ENOENT; + } + clk_enable(i2s->iis_pclk); + + + /* Mark ourselves as in TXRX mode so we can run through our cleanup + * process without warnings. */ + rockchip_snd_txctrl(i2s, 0); + rockchip_snd_rxctrl(i2s, 0); + + return 0; +} + +static int __devinit rockchip_i2s_probe(struct platform_device *pdev) +{ + struct rk29_i2s_info *i2s; + struct snd_soc_dai_driver *dai; + int ret; + +#if defined(CONFIG_SND_I2S_USE_18V) + writel_relaxed(0x2000200,RK30_GRF_BASE + GRF_IO_CON4);//bit9: 1,1.8v;0,3.3v +#elif defined(CONFIG_SND_I2S_USE_33V) + writel_relaxed(0x2000000,RK30_GRF_BASE + GRF_IO_CON4); +#endif + +#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) + //default 8ma 0xF000F = 12ma 0xF0005=4ma 0xF0000=2ma + writel_relaxed(0xF000A,RK30_GRF_BASE + GRF_IO_CON1); +#endif + I2S_DBG("Enter %s, %d pdev->id = %d >>>>>>>>>>>\n", __func__, __LINE__, pdev->id); + + if(pdev->id >= MAX_I2S) { + dev_err(&pdev->dev, "id %d out of range\n", pdev->id); + return -EINVAL; + } + + i2s = &rk29_i2s[pdev->id]; + dai = &rk29_i2s_dai[pdev->id]; + dai->id = pdev->id; + dai->symmetric_rates = 1; + + switch(pdev->id) + { + case 0: + dai->name = "rk_i2s.0"; + dai->playback.channels_min = 2; + dai->playback.channels_max = 8; + break; + case 1: + dai->name = "rk_i2s.1"; + dai->playback.channels_min = 2; + dai->playback.channels_max = 2; + break; + case 2: + dai->name = "rk_i2s.2"; + dai->playback.channels_min = 2; + dai->playback.channels_max = 2; + break; + } + + spin_lock_init(&i2s->spinlock_wr); + dai->playback.rates = SNDRV_PCM_RATE_8000_192000; + dai->playback.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | + SNDRV_PCM_FMTBIT_S24_LE| SNDRV_PCM_FMTBIT_S32_LE; + dai->capture.channels_min = 2; + dai->capture.channels_max = 2; + dai->capture.rates = ROCKCHIP_I2S_RATES; + dai->capture.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE; + dai->probe = rockchip_i2s_dai_probe; + dai->ops = &rockchip_i2s_dai_ops; + dai->suspend = rockchip_i2s_suspend; + dai->resume = rockchip_i2s_resume; + + i2s->dma_capture = &rk29_i2s_pcm_stereo_in[pdev->id]; + i2s->dma_playback = &rk29_i2s_pcm_stereo_out[pdev->id]; + + switch(pdev->id) + { +#ifdef CONFIG_ARCH_RK30 + case 0: + i2s->dma_capture->channel = DMACH_I2S0_8CH_RX; + i2s->dma_capture->dma_addr = RK30_I2S0_8CH_PHYS + I2S_RXR_BUFF; + i2s->dma_playback->channel = DMACH_I2S0_8CH_TX; + i2s->dma_playback->dma_addr = RK30_I2S0_8CH_PHYS + I2S_TXR_BUFF; + break; + case 1: + i2s->dma_capture->channel = DMACH_I2S1_2CH_RX; + i2s->dma_capture->dma_addr = RK30_I2S1_2CH_PHYS + I2S_RXR_BUFF; + i2s->dma_playback->channel = DMACH_I2S1_2CH_TX; + i2s->dma_playback->dma_addr = RK30_I2S1_2CH_PHYS + I2S_TXR_BUFF; + break; + case 2: + i2s->dma_capture->channel = DMACH_I2S2_2CH_RX; + i2s->dma_capture->dma_addr = RK30_I2S2_2CH_PHYS + I2S_RXR_BUFF; + i2s->dma_playback->channel = DMACH_I2S2_2CH_TX; + i2s->dma_playback->dma_addr = RK30_I2S2_2CH_PHYS + I2S_TXR_BUFF; + break; +#endif +#if defined(CONFIG_ARCH_RK3188) + case 1: + i2s->dma_capture->channel = DMACH_I2S1_2CH_RX; + i2s->dma_capture->dma_addr = RK30_I2S1_2CH_PHYS + I2S_RXR_BUFF; + i2s->dma_playback->channel = DMACH_I2S1_2CH_TX; + i2s->dma_playback->dma_addr = RK30_I2S1_2CH_PHYS + I2S_TXR_BUFF; + break; +#endif +#if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026) + case 0: + i2s->dma_capture->channel = DMACH_I2S0_8CH_RX; + i2s->dma_capture->dma_addr = RK2928_I2S_PHYS + I2S_RXR_BUFF; + i2s->dma_playback->channel = DMACH_I2S0_8CH_TX; + i2s->dma_playback->dma_addr = RK2928_I2S_PHYS + I2S_TXR_BUFF; + break; +#endif + } + + i2s->dma_capture->client = &rk29_dma_client_in; + i2s->dma_capture->dma_size = 4; + i2s->dma_capture->flag = 0; //add by sxj, used for burst change + i2s->dma_playback->client = &rk29_dma_client_out; + i2s->dma_playback->dma_size = 4; + i2s->dma_playback->flag = 0; //add by sxj, used for burst change + i2s->i2s_tx_status = false; + i2s->i2s_rx_status = false; +#ifdef CONFIG_SND_I2S_DMA_EVENT_STATIC + WARN_ON(rk29_dma_request(i2s->dma_playback->channel, i2s->dma_playback->client, NULL)); + WARN_ON(rk29_dma_request(i2s->dma_capture->channel, i2s->dma_capture->client, NULL)); +#endif + + i2s->iis_clk = clk_get(&pdev->dev, "i2s"); + I2S_DBG("Enter:%s, %d, iis_clk=%p\n", __FUNCTION__, __LINE__, i2s->iis_clk); + if (IS_ERR(i2s->iis_clk)) { + dev_err(&pdev->dev, "failed to get i2s clk\n"); + ret = PTR_ERR(i2s->iis_clk); + goto err; + } + + clk_enable(i2s->iis_clk); + clk_set_rate(i2s->iis_clk, 11289600); + + ret = rk29_i2s_probe(pdev, dai, i2s, 0); + if (ret) + goto err_clk; + + ret = snd_soc_register_dai(&pdev->dev, dai); + if (ret != 0) + goto err_i2sv2; + + return 0; + +err_i2sv2: + /* Not implemented for I2Sv2 core yet */ +err_clk: + clk_put(i2s->iis_clk); +err: + return ret; +} + +static int rockchip_i2s_suspend_noirq(struct device *dev) +{ + struct snd_soc_dai *dai = rk_cpu_dai; + I2S_DBG("Enter %s, %d\n", __func__, __LINE__); + + return i2s_set_gpio_mode(dai); +} + +static int rockchip_i2s_resume_noirq(struct device *dev) +{ + struct snd_soc_dai *dai = rk_cpu_dai; + I2S_DBG("Enter %s, %d\n", __func__, __LINE__); + + return rockchip_i2s_dai_probe(dai); +} + +static const struct dev_pm_ops rockchip_i2s_pm_ops = { + .suspend_noirq = rockchip_i2s_suspend_noirq, + .resume_noirq = rockchip_i2s_resume_noirq, +}; + +static int __devexit rockchip_i2s_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dai(&pdev->dev); + return 0; +} + +static struct platform_driver rockchip_i2s_driver = { + .probe = rockchip_i2s_probe, + .remove = __devexit_p(rockchip_i2s_remove), + .driver = { + .name = "rk29_i2s", + .owner = THIS_MODULE, + .pm = &rockchip_i2s_pm_ops, + }, +}; + +static int __init rockchip_i2s_init(void) +{ + I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); + + return platform_driver_register(&rockchip_i2s_driver); +} +module_init(rockchip_i2s_init); + +static void __exit rockchip_i2s_exit(void) +{ + platform_driver_unregister(&rockchip_i2s_driver); +} +module_exit(rockchip_i2s_exit); + +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface"); +MODULE_LICENSE("GPL"); + + +#ifdef CONFIG_PROC_FS +#include +#include +static int proc_i2s_show(struct seq_file *s, void *v) +{ +#ifdef CONFIG_SND_RK_SOC_I2S_8CH + struct rk29_i2s_info *i2s=&rk29_i2s[0]; +#else +#ifdef CONFIG_SND_RK_SOC_I2S_2CH + struct rk29_i2s_info *i2s=&rk29_i2s[1]; +#else + struct rk29_i2s_info *i2s=&rk29_i2s[2]; +#endif +#endif + printk("========Show I2S reg========\n"); + + printk("I2S_TXCR = 0x%08X\n", readl(&(pheadi2s->I2S_TXCR))); + printk("I2S_RXCR = 0x%08X\n", readl(&(pheadi2s->I2S_RXCR))); + printk("I2S_CKR = 0x%08X\n", readl(&(pheadi2s->I2S_CKR))); + printk("I2S_DMACR = 0x%08X\n", readl(&(pheadi2s->I2S_DMACR))); + printk("I2S_INTCR = 0x%08X\n", readl(&(pheadi2s->I2S_INTCR))); + printk("I2S_INTSR = 0x%08X\n", readl(&(pheadi2s->I2S_INTSR))); + printk("I2S_XFER = 0x%08X\n", readl(&(pheadi2s->I2S_XFER))); + + printk("========Show I2S reg========\n"); +#if 0 + writel(0x0000000F, &(pheadi2s->I2S_TXCR)); + writel(0x0000000F, &(pheadi2s->I2S_RXCR)); + writel(0x00071f1F, &(pheadi2s->I2S_CKR)); + writel(0x001F0110, &(pheadi2s->I2S_DMACR)); + writel(0x00000003, &(pheadi2s->I2S_XFER)); + while(1) + { + writel(0x5555aaaa, &(pheadi2s->I2S_TXDR)); + } +#endif + return 0; +} + +static ssize_t i2s_reg_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ +#ifdef CONFIG_SND_RK_SOC_I2S_8CH + struct rk29_i2s_info *i2s=&rk29_i2s[0]; +#else +#ifdef CONFIG_SND_RK_SOC_I2S_2CH + struct rk29_i2s_info *i2s=&rk29_i2s[1]; +#else + struct rk29_i2s_info *i2s=&rk29_i2s[2]; +#endif +#endif + char buf[32]; + size_t buf_size; + char *start = buf; + unsigned long value; + + buf_size = min(count, (sizeof(buf)-1)); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + buf[buf_size] = 0; + + while (*start == ' ') + start++; + value = simple_strtoul(start, &start, 10); + + printk("test --- freq = %ld ret=%d\n",value,clk_set_rate(i2s->iis_clk, value)); + return buf_size; +} + +static int proc_i2s_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_i2s_show, NULL); +} + +static const struct file_operations proc_i2s_fops = { + .open = proc_i2s_open, + .read = seq_read, + .write = i2s_reg_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init i2s_proc_init(void) +{ + proc_create("i2s_reg", 0, NULL, &proc_i2s_fops); + return 0; +} +late_initcall(i2s_proc_init); +#endif /* CONFIG_PROC_FS */ + diff --git a/sound/soc/rk/rk_aic3111.c b/sound/soc/rk/rk_aic3111.c new file mode 100644 index 000000000000..e6f11eb3951f --- /dev/null +++ b/sound/soc/rk/rk_aic3111.c @@ -0,0 +1,219 @@ +/* + * rk29_tlv320dac3100.c -- SoC audio for rockchip + * + * Driver for rockchip tlv320aic3100 audio + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include "../codecs/tlv320aic3111.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" + +#if 0 +#define AIC_DBG(x...) printk(KERN_INFO x) +#else +#define AIC_DBG(x...) do { } while (0) +#endif + +#ifdef CODECHPDET + #define HP_DET_PIN RK29_PIN6_PA0 +#endif + + + +static int rk29_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int ret; + + AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /*by Vincent Hsiung for EQ Vol Change*/ + #define HW_PARAMS_FLAG_EQVOL_ON 0x21 + #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 + if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) + { + ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); + AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + } + else + { + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + ret = snd_soc_dai_set_fmt(codec_dai, + SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS); + #endif + + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + ret = snd_soc_dai_set_fmt(codec_dai, + SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM ); + #endif + + if (ret < 0) + return ret; + + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_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_RK_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; + } + AIC_DBG("Enter:%s, %d, rate=%d, pll_out = %d\n",__FUNCTION__,__LINE__,params_rate(params), pll_out); + //pll_out = 12000000; + snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); + + return 0; +} + +static const struct snd_soc_dapm_widget dac3100_dapm_widgets[] = { +/* SND_SOC_DAPM_LINE("Audio Out", NULL), + SND_SOC_DAPM_LINE("Line in", NULL), + SND_SOC_DAPM_MIC("Micn", NULL), + SND_SOC_DAPM_MIC("Micp", NULL),*/ +}; + +static const struct snd_soc_dapm_route audio_map[]= { +/* {"Audio Out", NULL, "HPL"}, + {"Audio Out", NULL, "HPR"}, + {"Line in", NULL, "RINPUT1"}, + {"Line in", NULL, "LINPUT1"}, + {"Micn", NULL, "RINPUT2"}, + {"Micp", NULL, "LINPUT2"},*/ +}; + +/* + * Logic for a tlv320dac3100 as connected on a rockchip board. + */ +static int rk29_aic3111_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + + AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* Add specific widgets */ + snd_soc_dapm_new_controls(dapm, dac3100_dapm_widgets, + ARRAY_SIZE(dac3100_dapm_widgets)); + + /* Set up specific audio path audio_mapnects */ + snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + snd_soc_dapm_nc_pin(dapm, "HPL"); + AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + snd_soc_dapm_nc_pin(dapm, "HPR"); + AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + snd_soc_dapm_sync(dapm); + AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + return 0; +} + +static struct snd_soc_ops rk29_ops = { + .hw_params = rk29_hw_params, +}; + +static struct snd_soc_dai_link rk29_dai = { + .name = "AIC3111", + .stream_name = "AIC3111 PCM", + .codec_name = "AIC3111.0-0018", + .platform_name = "rockchip-audio", + .cpu_dai_name = "rk_i2s.0", + .codec_dai_name = "AIC3111 HiFi", + .init = rk29_aic3111_init, + .ops = &rk29_ops, +}; + +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_AIC3111", + .dai_link = &rk29_dai, + .num_links = 1, +}; + +static struct platform_device *rk29_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; + + AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) { + AIC_DBG("platform device allocation failed\n"); + ret = -ENOMEM; + return ret; + } + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + ret = platform_device_add(rk29_snd_device); + if (ret) { + AIC_DBG("platform device add failed\n"); + platform_device_put(rk29_snd_device); + } + return ret; +} + +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk/rk_aic3262.c b/sound/soc/rk/rk_aic3262.c new file mode 100644 index 000000000000..eb77229f0d2a --- /dev/null +++ b/sound/soc/rk/rk_aic3262.c @@ -0,0 +1,539 @@ +/* + * rk29_aic3262.c -- SoC audio for rockchip + * + * Driver for rockchip aic3262 audio + * Copyright (C) 2009 lhh + * + * 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. + * + * + */ + +#define DEBUG 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include "../codecs/wm8994.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" +#include +#include +#include "../codecs/tlv320aic326x.h" + +#if 0 +#define DBG_AIC3262(x...) printk(KERN_INFO x) +#else +#define DBG_AIC3262(x...) +#endif + +//struct regulator *vddhf_reg=NULL; + +/* Headset jack */ +//static struct snd_soc_jack hs_jack; + +/*Headset jack detection DAPM pins */ +/*static struct snd_soc_jack_pin hs_jack_pins[] = { + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, + { + .pin = "Headset Stereophone", + .mask = SND_JACK_HEADPHONE, + }, +}; + +static int spk_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + //struct snd_soc_codec *codec = w->codec; + int ret; + if (SND_SOC_DAPM_EVENT_ON(event)) { + + printk(" I am NULL is %d event is %d\n",vddhf_reg,event); + + if (vddhf_reg) { + ret = regulator_enable(vddhf_reg); + if(ret) { + printk("failed to enable vddhf \n"); + return ret; + } + } + } + else { + + if (vddhf_reg) { + ret = regulator_disable(vddhf_reg); + if (ret) { + printk("failed to disable " + "VDDHF regulator %d\n", ret); + return ret; + } + } + } + return 0; +}*/ + + + +/* rk29 machine DAPM */ +static const struct snd_soc_dapm_widget rk29_aic3262_dapm_widgets[] = { + SND_SOC_DAPM_MIC("Ext Mic", NULL), + SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_HP("Headset Stereophone", NULL), + SND_SOC_DAPM_SPK("Earphone Spk", NULL), + SND_SOC_DAPM_INPUT("FM Stereo In"), + SND_SOC_DAPM_LINE("FM Stereo Out",NULL), +}; + +static const struct snd_soc_dapm_route audio_map[] = { + /* External Mics: MAINMIC, SUBMIC with bias*/ + {"IN1L", NULL, "Mic Bias Int"}, + {"IN1R", NULL, "Mic Bias Int"}, + {"IN4L", NULL, "Mic Bias Int"}, + {"IN4R", NULL, "Mic Bias Int"}, + {"Mic Bias Int", NULL, "Ext Mic"}, + + /* External Speakers: HFL, HFR */ + {"Ext Spk", NULL, "SPKL"}, + {"Ext Spk", NULL, "SPKR"}, + + /* Headset Mic: HSMIC with bias */ + {"IN2L", NULL, "Mic Bias Ext"}, + {"IN2R", NULL, "Mic Bias Ext"}, + {"Mic Bias Ext", NULL, "Headset Mic"}, + + /* Headset Stereophone (Headphone): HPL, HPR */ + {"Headset Stereophone", NULL, "HPL"}, + {"Headset Stereophone", NULL, "HPR"}, + + /* Earphone speaker */ + {"Earphone Spk", NULL, "RECP"}, + {"Earphone Spk", NULL, "RECM"}, + + /* Aux/FM Stereo In: IN4L, IN4R */ + {"IN3L", NULL, "FM Stereo In"}, + {"IN3R", NULL, "FM Stereo In"}, + + /* Aux/FM Stereo Out: LOL, LOR */ + {"FM Stereo Out", NULL, "LOL"}, + {"FM Stereo Out", NULL, "LOR"}, +}; + +static const struct snd_kcontrol_new rk29_aic326x_controls[] = { + SOC_DAPM_PIN_SWITCH("Ext Mic"), + SOC_DAPM_PIN_SWITCH("Ext Spk"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Headset Stereophone"), + SOC_DAPM_PIN_SWITCH("Earphone Spk"), + SOC_DAPM_PIN_SWITCH("FM Stereo In"), + SOC_DAPM_PIN_SWITCH("FM Stereo Out"), +}; + +static int rk29_aic3262_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + int ret; + + DBG_AIC3262("rk29_aic3262_init\n"); + + ret = snd_soc_add_codec_controls(codec, rk29_aic326x_controls, + ARRAY_SIZE(rk29_aic326x_controls)); + + if (ret < 0) { + printk("rk29_aic3262: Err snd_soc_add_codec_controls ret: %d\n", ret ); + return ret; + } + + /* Add rk29 specific widgets */ + ret = snd_soc_dapm_new_controls(dapm, rk29_aic3262_dapm_widgets, + ARRAY_SIZE(rk29_aic3262_dapm_widgets)); + if (ret) + return ret; + + /* Set up rk29 specific audio path audio_map */ + snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + + + ret = snd_soc_dapm_sync(dapm); + if (ret) + return ret; + + /* Headset jack detection */ + /*ret = snd_soc_jack_new(codec, "Headset Jack", + SND_JACK_HEADSET, &hs_jack); + if (ret) + return ret; + + ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), + hs_jack_pins); + aic3262_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);*/ + + /* don't wait before switching of HS power */ + rtd->pmdown_time = 0; + return ret; +} + +static int rk29_aif1_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int div_bclk,div_mclk; + int ret; + + printk("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* set codec DAI configuration */ +#if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + DBG_AIC3262("Set codec_dai slave\n"); + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); +#endif +#if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + DBG_AIC3262("Set codec_dai master\n"); +#endif + if (ret < 0) + return ret; + + /* set cpu DAI configuration */ +#if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + DBG_AIC3262("Set cpu_dai master\n"); + 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_RK_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); + DBG_AIC3262("Set cpu_dai slave\n"); +#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: + DBG_AIC3262("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + return -EINVAL; + } + + + div_bclk=(pll_out/4)/params_rate(params)-1; + div_mclk=3; + + DBG_AIC3262(" %s, pll_out=%d, div_bclk=%d, div_mclk=%d\n",__FUNCTION__,pll_out,div_bclk,div_mclk); + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + if(ret < 0) + { + DBG_AIC3262("rk29_hw_params_aic3262:failed to set the cpu sysclk for codec side\n"); + return ret; + } + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, div_bclk); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); + DBG_AIC3262("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); + + //MCLK == 11289600 or 12288000 + ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, 0); + if (ret < 0) { + DBG_AIC3262("rk29_hw_params_aic3262:failed to set the sysclk for codec side\n"); + return ret; + } + + return ret; +} + +static int rk29_aif2_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int div_bclk,div_mclk; + int ret; + + DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + + /* set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) + { + printk("%s: snd_soc_dai_set_fmt err =%d\n",__FUNCTION__,ret); + 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: + DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + return -EINVAL; + } + + div_bclk=(pll_out/4)/params_rate(params)-1; + div_mclk=3; + + DBG_AIC3262(" %s, pll_out=%d, div_bclk=%d, div_mclk=%d\n",__FUNCTION__,pll_out,div_bclk,div_mclk); + + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + if(ret < 0) + { + DBG("rk29_hw_params_aic3262:failed to set the cpu sysclk for codec side\n"); + return ret; + } + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, div_bclk); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); + DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); + + /* set the codec system clock */ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, 0); + if (ret < 0) + { + printk("%s: snd_soc_dai_set_sysclk err =%d\n",__FUNCTION__,ret); + return ret; + } + + /* set the codec FLL */ + ret = snd_soc_dai_set_pll(codec_dai, 0, AIC3262_PLL_CLKIN_MCLK1 , pll_out, 8000*256); + if (ret < 0) + { + printk("%s: snd_soc_dai_set_pll err =%d\n",__FUNCTION__,ret); + return ret; + } + + return ret; +} + +static int rk29_aif3_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int div_bclk,div_mclk; + int ret; + + DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + + /* set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) + { + printk("%s: snd_soc_dai_set_fmt err =%d\n",__FUNCTION__,ret); + 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: + DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + return -EINVAL; + } + + div_bclk=(pll_out/4)/params_rate(params)-1; + div_mclk=3; + + DBG_AIC3262(" %s, pll_out=%d, div_bclk=%d, div_mclk=%d\n",__FUNCTION__,pll_out,div_bclk,div_mclk); + + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + if(ret < 0) + { + DBG("rk29_hw_params_aic3262:failed to set the cpu sysclk for codec side\n"); + return ret; + } + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, div_bclk); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); + DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); + + /* set the codec system clock */ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, 0); + if (ret < 0) + { + printk("%s: snd_soc_dai_set_sysclk err =%d\n",__FUNCTION__,ret); + return ret; + } + + /* set the codec FLL */ + ret = snd_soc_dai_set_pll(codec_dai, 0, AIC3262_PLL_CLKIN_MCLK1 , pll_out, 8000*256); + if (ret < 0) + { + printk("%s: snd_soc_dai_set_pll err =%d\n",__FUNCTION__,ret); + return ret; + } + + return ret; +} + +static struct snd_soc_ops rk29_aif1_ops = { + .hw_params = rk29_aif1_hw_params, +}; + +static struct snd_soc_ops rk29_aif2_ops = { + .hw_params = rk29_aif2_hw_params, +}; + +static struct snd_soc_ops rk29_aif3_ops = { + .hw_params = rk29_aif3_hw_params, +}; + +static struct snd_soc_dai_link rk29_dai[] = { + + { + .name = "AIC3262 I2S1", + .stream_name = "AIC3262 PCM", + .codec_name = "tlv320aic3262-codec", + .platform_name = "rockchip-audio", +#if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", +#elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", +#else + .cpu_dai_name = "rk_i2s.2", +#endif + .codec_dai_name = "aic326x-asi1", + .ops = &rk29_aif1_ops, + .init = rk29_aic3262_init, + }, + + { + .name = "AIC3262 I2S2", + .stream_name = "AIC3262 PCM", + .codec_name = "tlv320aic3262-codec", + .platform_name = "rockchip-audio", +#if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", +#elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", +#else + .cpu_dai_name = "rk_i2s.2", +#endif + .codec_dai_name = "aic326x-asi2", + .ops = &rk29_aif2_ops, + }, + + + { + .name = "AIC3262 I2S3", + .stream_name = "AIC3262 PCM", + .codec_name = "tlv320aic3262-codec", + .platform_name = "rockchip-audio", +#if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", +#elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", +#else + .cpu_dai_name = "rk_i2s.2", +#endif + .codec_dai_name = "aic326x-asi3", + .ops = &rk29_aif3_ops, + }, + +}; + + +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_AIC3262", + .dai_link = rk29_dai, + .num_links = ARRAY_SIZE(rk29_dai), +}; + +static struct platform_device *rk29_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; + + DBG_AIC3262("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) { + printk("platform device allocation failed\n"); + return -ENOMEM; + } + + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + ret = platform_device_add(rk29_snd_device); + if (ret) { + printk("platform device add failed\n"); + // snd_soc_unregister_dai(&rk29_snd_device->dev); + platform_device_put(rk29_snd_device); + return ret; + } + + return ret; +} + +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); + +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); + diff --git a/sound/soc/rk/rk_ak4396.c b/sound/soc/rk/rk_ak4396.c new file mode 100755 index 000000000000..a266f5ec4cd6 --- /dev/null +++ b/sound/soc/rk/rk_ak4396.c @@ -0,0 +1,177 @@ +/* + * rk29_ak4396.c -- SoC audio for rockchip + * + * Driver for rockchip ak4396 audio + * + * 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 +#include +#include +#include +#include +#include +#include "rk_pcm.h" +#include "rk29_i2s.h" + +#include + +#if 1 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +static int rk29_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int ret=-1; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_RIGHT_J | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) return ret; + /* set cpu DAI configuration */ + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_RIGHT_J | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) return ret; + #endif + + 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; + case 88200: + case 176400: + pll_out = 11289600*2; + break; + case 96000: + case 192000: + pll_out = 12288000*2; + break; + default: + DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + return -EINVAL; + } + + DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (2 * 32 )-1); //bclk = 2 * 32 * lrck + + switch(params_rate(params)){ + case 192000: + case 176400: + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK,1); + DBG("Enter:%s, %d, MCLK=%d BCLK=%d LRCK=%d\n", + __FUNCTION__,__LINE__,pll_out,pll_out/2,params_rate(params)); + break; + default : + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3); + DBG("default:%s, %d, MCLK=%d BCLK=%d LRCK=%d\n", + __FUNCTION__,__LINE__,pll_out,pll_out/4,params_rate(params)); + break; + } + snd_soc_dai_set_sysclk(codec_dai,0,pll_out,SND_SOC_CLOCK_IN); + #endif + return ret; +} + +/* + * Logic for a ak4396 as connected on a rockchip board. + */ +static int rk29_ak4396_init(struct snd_soc_pcm_runtime *rtd) +{ + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + return 0; +} + +static struct snd_soc_ops rk29_ops = { + .hw_params = rk29_hw_params, +}; + +static struct snd_soc_dai_link rk29_dai = { + .name = "AK4396", + .stream_name = "AK4396 PCM", + .codec_name = "spi1.0", + .platform_name = "rockchip-audio", +#if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", +#elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", +#else + .cpu_dai_name = "rk_i2s.2", +#endif + .codec_dai_name = "AK4396 HiFi", + .init = rk29_ak4396_init, + .ops = &rk29_ops, +}; + +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_AK4396", + .dai_link = &rk29_dai, + .num_links = 1, +}; + +static struct platform_device *rk29_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; + + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) { + printk("platform device allocation failed\n"); + ret = -ENOMEM; + return ret; + } + + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + + ret = platform_device_add(rk29_snd_device); + if (ret) { + printk("platform device add failed\n"); + platform_device_put(rk29_snd_device); + return ret; + } + + return ret; +} + +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device);; +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk/rk_cs42l52.c b/sound/soc/rk/rk_cs42l52.c new file mode 100755 index 000000000000..a69b1ae3b363 --- /dev/null +++ b/sound/soc/rk/rk_cs42l52.c @@ -0,0 +1,231 @@ +/* + * rk29_cs42l52.c -- SoC audio for rockchip + * + * Driver for rockchip cs42l52 audio + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include "../codecs/cs42l52.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" + + +#define HW_PARAMS_FLAG_EQVOL_ON 0x21 +#define HW_PARAMS_FLAG_EQVOL_OFF 0x22 +static const struct snd_soc_dapm_widget cs42l52_dapm_widgets[] = { + SND_SOC_DAPM_LINE("Audio Out", NULL), + SND_SOC_DAPM_LINE("Line in", NULL), + SND_SOC_DAPM_MIC("Micn", NULL), + SND_SOC_DAPM_MIC("Micp", NULL), +}; + +static const struct snd_soc_dapm_route audio_map[]= { + + {"Audio Out", NULL, "HPA"}, + {"Audio Out", NULL, "HPB"}, + {"Line in", NULL, "INPUT1A"}, + {"Line in", NULL, "INPUT1B"}, + {"Micn", NULL, "INPUT2A"}, + {"Micp", NULL, "INPUT2B"}, +}; + +static int rk29_cs42l52_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 *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + unsigned int pll_out = 0; + unsigned int lrclk = 0; + int div_bclk,div_mclk; + struct clk *general_pll; + int ret; + + if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) + { + ret = codec_dai->ops->hw_params(substream, params, codec_dai); //by Vincent + } + else + { + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + #endif + if (ret < 0) + return ret; + + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_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_RK_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: + return -EINVAL; + break; + } + + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + general_pll=clk_get(NULL, "general_pll"); + if(clk_get_rate(general_pll)>260000000) + { + div_bclk=(pll_out/4)/params_rate(params)-1; + //div_bclk= 63; + div_mclk= 3; + } + else if(clk_get_rate(general_pll)>130000000) + { + div_bclk=(pll_out/2)/params_rate(params)-1; + div_mclk=1; + } + else + { + pll_out=pll_out/4; + div_bclk=(pll_out)/params_rate(params)-1; + div_mclk=0; + } + + //snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, 0); + snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); + #endif + + + return 0; +} + +static int rk29_cs42l52_dai_init(struct snd_soc_codec *codec) +{ + struct snd_soc_dai *codec_dai = &codec->dai[0]; + int ret; + + snd_soc_dapm_nc_pin(codec, "INPUT1A"); + snd_soc_dapm_nc_pin(codec, "INPUT2A"); + snd_soc_dapm_nc_pin(codec, "INPUT3A"); + snd_soc_dapm_nc_pin(codec, "INPUT4A"); + snd_soc_dapm_nc_pin(codec, "INPUT1B"); + snd_soc_dapm_nc_pin(codec, "INPUT2B"); + snd_soc_dapm_nc_pin(codec, "INPUT3B"); + snd_soc_dapm_nc_pin(codec, "INPUT4B"); + snd_soc_dapm_nc_pin(codec, "MICB"); + snd_soc_dapm_sync(codec); + return 0; +} + +static struct snd_soc_ops rk29_cs42l52_ops = { + .hw_params = rk29_cs42l52_hw_params, +}; + +static struct snd_soc_dai_link rk29_cs42l52_dai_link = { + .name = "CS42L52", + .stream_name = "CS42L52 PCM", + .cpu_dai = &rk29_i2s_dai[0], + .codec_dai = &soc_cs42l52_dai, + .init = rk29_cs42l52_dai_init, + .ops = &rk29_cs42l52_ops, +}; + +static struct snd_soc_card snd_soc_card_rk29_cs42l52 = { + .name = "RK_CS42L52", + .platform = &rk29_soc_platform, + .dai_link = &rk29_cs42l52_dai_link, + .num_links = 1, +}; + + +static struct snd_soc_device rk29_cs42l52_snd_devdata = { + .card = &snd_soc_card_rk29_cs42l52, + .codec_dev = &soc_codec_dev_cs42l52, +}; + +static struct platform_device *rk29_cs42l52_snd_device; + +static int rk29_cs42l52_probe(struct platform_device *pdev) +{ + int ret =0; + printk("RK CS42L52 SoC Audio driver\n"); + rk29_cs42l52_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_cs42l52_snd_device) { + ret = -ENOMEM; + printk("%s:platform device alloc fail\n",__FUNCTION__); + return ret; + } + platform_set_drvdata(rk29_cs42l52_snd_device, &rk29_cs42l52_snd_devdata); + rk29_cs42l52_snd_devdata.dev = &rk29_cs42l52_snd_device->dev; + ret = platform_device_add(rk29_cs42l52_snd_device); + if (ret) { + platform_device_put(rk29_cs42l52_snd_device); + printk("%s:platform device add fail,ret = %d\n",__FUNCTION__,ret); + } + return ret; +} + +static int rk29_cs42l52_remove(struct platform_device *pdev) +{ + platform_device_unregister(rk29_cs42l52_snd_device); + return 0; +} + +static struct platform_driver rk29_cs42l52_driver = { + .probe = rk29_cs42l52_probe, + .remove = rk29_cs42l52_remove, + .driver = { + .name = "rk29_cs42l52", + .owner = THIS_MODULE, + }, +}; + +static int __init rk29_cs42l52_init(void) +{ + return platform_driver_register(&rk29_cs42l52_driver); +} + +static void __exit rk29_cs42l52_exit(void) +{ + platform_driver_unregister(&rk29_cs42l52_driver); +} + +module_init(rk29_cs42l52_init); +module_exit(rk29_cs42l52_exit); +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); + diff --git a/sound/soc/rk/rk_cx2070x.c b/sound/soc/rk/rk_cx2070x.c new file mode 100644 index 000000000000..254f88c175f8 --- /dev/null +++ b/sound/soc/rk/rk_cx2070x.c @@ -0,0 +1,272 @@ +/* + * rk29_cx2070x.c + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include "rk_pcm.h" +#include "rk29_i2s.h" +#if 1 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +#include "../codecs/cx2070x.h" + +static struct platform_device *rk29_snd_device; + + +static int rk29_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + //unsigned int pll_div; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_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_RK_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; + + + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #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; + case 96000: + case 192000: + pll_out = 12288000*2; + break; + case 88200: + case 176400: + pll_out = 11289600*2; + break; + default: + DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + return -EINVAL; + break; + } +#if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, 64-1);//bclk = 2*32*lrck; 2*32fs + switch(params_rate(params)) { + case 176400: + case 192000: + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 1); + DBG("Enter:%s, %d, MCLK=%d BCLK=%d LRCK=%d\n", + __FUNCTION__,__LINE__,pll_out,pll_out/2,params_rate(params)); + break; + default: + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3); + DBG("default:%s, %d, MCLK=%d BCLK=%d LRCK=%d\n", + __FUNCTION__,__LINE__,pll_out,pll_out/4,params_rate(params)); + break; + } + + /*Set the system clk for codec*/ + ret=snd_soc_dai_set_sysclk(codec_dai, 0,pll_out,SND_SOC_CLOCK_IN); + if (ret < 0) + { + DBG("rk29_hw_params_rt5631:failed to set the sysclk for codec side\n"); + return ret; + } +#endif + +#if 0 + switch (params_rate(params)) + { + case 8000: + pll_div = 12; + break; + case 16000: + pll_div = 6; + break; + case 32000: + pll_div = 3; + break; + case 48000: + pll_div = 2; + break; + case 96000: + pll_div = 1; + break; + case 11025: + pll_div = 8; + break; + case 22050: + pll_div = 4; + break; + case 44100: + pll_div = 2; + break; + case 88200: + pll_div = 1; + break; + default: + printk("Not yet supported!\n"); + return -EINVAL; + } + ret = snd_soc_dai_set_clkdiv(codec_dai, cx2070x_CLK_DIV_ID, pll_div*4); + if (ret < 0) + return ret; +#endif + +#if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + //snd_soc_dai_set_pll(codec_dai,0,pll_out, 22579200); + snd_soc_dai_set_sysclk(codec_dai,0,pll_out, SND_SOC_CLOCK_IN); +#endif + return 0; +} + +//--------------------------------------------------------------------------------- +/* + * cx2070x DAI operations. + */ +static struct snd_soc_ops rk29_ops = { + .hw_params = rk29_hw_params, +}; + +static const struct snd_soc_dapm_widget cx2070x_dapm_widgets[] = { + // Input + SND_SOC_DAPM_MIC("Mic Jack", NULL), + //SND_SOC_DAPM_LINE("Headset Jack", NULL), + SND_SOC_DAPM_INPUT("BT IN"), + // Output + SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_LINE("ALineOut", NULL), + SND_SOC_DAPM_OUTPUT("BT OUT"), + +}; + +static const struct snd_soc_dapm_route cx2070x_audio_map[] = { + // Input + {"MIC IN", NULL,"Mic Jack"}, + {"PCM IN", NULL, "BT IN"}, + // Output + {"Ext Spk", NULL, "SPK OUT"}, + {"Headphone Jack", NULL, "HP OUT"}, + {"ALineOut", NULL, "LINE OUT"}, + {"BT OUT", NULL, "PCM OUT"}, +}; + +static int cx2070x_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + //struct cx2070x_codec_chip *chip = snd_soc_codec_get_drvdata(codec); + //int err = 0; + printk(">>>>>>>>>>%s",__FUNCTION__); + snd_soc_dapm_new_controls(dapm, cx2070x_dapm_widgets, + ARRAY_SIZE(cx2070x_dapm_widgets)); + + snd_soc_dapm_add_routes(dapm, cx2070x_audio_map, + ARRAY_SIZE(cx2070x_audio_map)); +#if FOR_MID + snd_soc_dapm_disable_pin(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin(dapm, "BT IN"); + snd_soc_dapm_disable_pin(dapm, "Ext Spk"); + snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin(dapm, "ALineOut"); + snd_soc_dapm_disable_pin(dapm, "BT OUT"); +#endif + + snd_soc_dapm_sync(dapm); + return 0; +} + +static struct snd_soc_dai_link rk29_dai[] = { + { /* Primary DAI i/f */ + .name = "CX2070X AIF1", + .stream_name = "CX2070X PCM", + .cpu_dai_name = "rk_i2s.1", + .codec_dai_name = "cx2070x-hifi", + .platform_name = "rockchip-audio", + .codec_name = "cx2070x.0-0014", + .init = cx2070x_init, + .ops = &rk29_ops, + }, +}; + +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_CX2070X", + .dai_link = rk29_dai, + + /* If you want to use sec_fifo device, + * changes the num_link = 2 or ARRAY_SIZE(snd_soc_card_rk29). */ + .num_links = ARRAY_SIZE(rk29_dai), +}; + +static int __init audio_card_init(void) +{ + int ret; + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) + return -ENOMEM; + + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + + ret = platform_device_add(rk29_snd_device); + printk(">>>>>>>>>>%s ret = %d",__FUNCTION__, ret); + if (ret) + platform_device_put(rk29_snd_device); + + return ret; +} +module_init(audio_card_init); + +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device); +} +module_exit(audio_card_exit); + +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_AUTHOR("showy.zhang "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk/rk_es8323.c b/sound/soc/rk/rk_es8323.c new file mode 100755 index 000000000000..446977bf289e --- /dev/null +++ b/sound/soc/rk/rk_es8323.c @@ -0,0 +1,246 @@ +/* + * rk29_es8323.c -- SoC audio for rockchip + * + * Driver for rockchip es8323 audio + * + * 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 +#include +#include +#include +#include +#include +//#include +//#include +#include "../codecs/es8323.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" + +#include +#ifdef CONFIG_MACH_RK_FAC +#include +extern int codec_type; +#endif + +#if 1 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +//static void *rk29_speaker = NULL; + +static int rk29_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /*by Vincent Hsiung for EQ Vol Change*/ + #define HW_PARAMS_FLAG_EQVOL_ON 0x21 + #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 + if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) + { + ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + } + else + { + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #endif + if (ret < 0) + return ret; + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_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_RK_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: + DBG("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)); + + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + 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); + #endif + + DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); + return 0; +} + +static const struct snd_soc_dapm_widget rk29_dapm_widgets[] = { + SND_SOC_DAPM_LINE("Audio Out", NULL), + SND_SOC_DAPM_LINE("Line in", NULL), + SND_SOC_DAPM_MIC("Micn", NULL), + SND_SOC_DAPM_MIC("Micp", NULL), +}; + +static const struct snd_soc_dapm_route audio_map[]= { + + {"Audio Out", NULL, "LOUT1"}, + {"Audio Out", NULL, "ROUT1"}, + {"Line in", NULL, "RINPUT1"}, + {"Line in", NULL, "LINPUT1"}, + {"Micn", NULL, "RINPUT2"}, + {"Micp", NULL, "LINPUT2"}, +}; + +/* + * Logic for a es8323 as connected on a rockchip board. + */ +static int rk29_es8323_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + ret = snd_soc_dai_set_sysclk(codec_dai, 0, + /*12000000*/11289600, SND_SOC_CLOCK_IN); + if (ret < 0) { + printk(KERN_ERR "Failed to set es8323 SYSCLK: %d\n", ret); + return ret; + } + + /* Add specific widgets */ + snd_soc_dapm_new_controls(dapm, rk29_dapm_widgets, + ARRAY_SIZE(rk29_dapm_widgets)); + //snd_soc_dapm_nc_pin(codec, "LOUT2"); + //snd_soc_dapm_nc_pin(codec, "ROUT2"); + + /* Set up specific audio path audio_mapnects */ + snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + + snd_soc_dapm_sync(dapm); + + return 0; +} + +static struct snd_soc_ops rk29_ops = { + .hw_params = rk29_hw_params, +}; + +static struct snd_soc_dai_link rk29_dai = { + .name = "ES8323", + .stream_name = "ES8323 PCM", + .codec_name = "ES8323.4-0010", // ES8323.0-0010 + .platform_name = "rockchip-audio", +#if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", +#elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", //Ó²¼þÉÏÊǽӵ½IIS0ÉÏ£¬µ«ÊÇÓÉÓÚxxÔ­Òò£¬Õâ±ß¶¨ÒåΪIIS1ÉÏ +#else + .cpu_dai_name = "rk_i2s.2", +#endif + .codec_dai_name = "ES8323 HiFi", + .init = rk29_es8323_init, + .ops = &rk29_ops, +}; + +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_ES8323", + .dai_link = &rk29_dai, + .num_links = 1, +}; + +static struct platform_device *rk29_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; +#ifdef CONFIG_MACH_RK_FAC + if(codec_type!=CODEC_TYPE_ES8323) + return -1; +#endif + DBG("ES8323 audio_card_init\n"); +#if 0 + extern int get_sound_card_exist() ; + extern void set_sound_card_exist(int i) ; + extern int i2c0_prober_verify(u32 dev_addr, u16 reg, u32 reg_addr_len, u32 reg_val_len, u32 id); + if(i2c0_prober_verify(0x10, 0x35, 1, 1, 0x0000) != 0) { + printk("%s(): Ping error with 0x1a\n", __FUNCTION__); + return -ENODEV; + } + else + printk("%s(): Ping OK with 0x1a\n", __FUNCTION__); +#endif +//leaf if(0 == tcsi_get_value(TCSI_CODEC_ES8323)) +//leaf2012-7-26 return; + DBG("XXXXEnter::%s----%d\n",__FUNCTION__,__LINE__); + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) { + DBG("platform device allocation failed\n"); + ret = -ENOMEM; + return ret; + } + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + ret = platform_device_add(rk29_snd_device); + if (ret) { + DBG("platform device add failed\n"); + platform_device_put(rk29_snd_device); + return ret; + } + + return ret; +} +static void __exit audio_card_exit(void) +{ +//leaf 2012-7-26 if(0 == tcsi_get_value(TCSI_CODEC_ES8323)) +//leaf 2012-7-26 return; + platform_device_unregister(rk29_snd_device); + //rk29_speaker_deinit(rk29_speaker); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); + diff --git a/sound/soc/rk/rk_hdmi_i2s.c b/sound/soc/rk/rk_hdmi_i2s.c new file mode 100644 index 000000000000..d1692f6e49e6 --- /dev/null +++ b/sound/soc/rk/rk_hdmi_i2s.c @@ -0,0 +1,155 @@ +/* + * rk_hdmi_i2s.c -- HDMI i2s audio for rockchip + * + * Copyright 2013 Rockship + * Author: chenjq + */ + +#include +#include +#include + +#include "rk_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_RK_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_RK_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", +#if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", +#elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", +#endif + .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; + } + + 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/rk/rk_hdmi_spdif.c b/sound/soc/rk/rk_hdmi_spdif.c new file mode 100755 index 000000000000..c93a23957b4e --- /dev/null +++ b/sound/soc/rk/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", + .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/rk/rk_jetta_codec.c b/sound/soc/rk/rk_jetta_codec.c new file mode 100755 index 000000000000..b120959a1b1d --- /dev/null +++ b/sound/soc/rk/rk_jetta_codec.c @@ -0,0 +1,192 @@ +/* + * rk29_wm8988.c -- SoC audio for rockchip + * + * Driver for rockchip wm8988 audio + * + * 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 +#include +#include +#include +#include +#include +#include "../codecs/rk610_codec.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" +#ifdef CONFIG_MACH_RK_FAC +#include +extern int codec_type; +#endif + +#if 0 +#define DBG(x...) printk(KERN_ERR x) +#else +#define DBG(x...) +#endif + +static int rk29_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int ret; + unsigned int pll_out = 0; + int div_bclk,div_mclk; +// struct clk *general_pll; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /*by Vincent Hsiung for EQ Vol Change*/ + #define HW_PARAMS_FLAG_EQVOL_ON 0x21 + #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 + if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) + { + ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent + } + else + { + /* set codec DAI configuration */ + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #elif defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #endif + if (ret < 0) + return ret; + /* set cpu DAI configuration */ + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + #if defined (CONFIG_SND_RK_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); + #elif defined (CONFIG_SND_RK_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: + case 96000: + pll_out = 12288000; + break; + case 11025: + case 22050: + case 44100: + case 88200: + pll_out = 11289600; + break; + case 176400: + pll_out = 11289600*2; + break; + case 192000: + pll_out = 12288000*2; + break; + default: + DBG("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(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); + +// #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) +// snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); +// #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + div_bclk = 63; + div_mclk = pll_out/(params_rate(params)*64) - 1; + + DBG("func is%s,pll_out=%d,div_mclk=%d div_bclk\n", + __FUNCTION__,pll_out,div_mclk, div_bclk); + snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); +// DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); + #endif + return 0; +} + +static struct snd_soc_ops rk29_ops = { + .hw_params = rk29_hw_params, +}; + +static struct snd_soc_dai_link rk29_dai = { + .name = "RK610_CODEC", + .stream_name = "RK610 CODEC PCM", +#if defined(CONFIG_MACH_RK3168_DS1006H)|| defined(CONFIG_MACH_RK3168_LR097) + .codec_name = "RK610_CODEC.4-0060", +#else + .codec_name = "RK610_CODEC.0-0060", +#endif + .platform_name = "rockchip-audio", +#if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", +#elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", +#else + .cpu_dai_name = "rk_i2s.2", +#endif + .codec_dai_name = "rk610_codec", + .ops = &rk29_ops, +}; +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_RK610", + .dai_link = &rk29_dai, + .num_links = 1, +}; + + +static struct platform_device *rk29_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; +#ifdef CONFIG_MACH_RK_FAC + if(codec_type!=CODEC_TYPE_RK616) + return -1; +#endif + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) { + printk("[%s] platform device allocation failed\n", __FUNCTION__); + ret = -ENOMEM; + return ret; + } + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + + ret = platform_device_add(rk29_snd_device); + if (ret) { + DBG("platform device add failed\n"); + platform_device_put(rk29_snd_device); + } + return ret; +} +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk/rk_pcm.c b/sound/soc/rk/rk_pcm.c new file mode 100755 index 000000000000..70b0e6b54c81 --- /dev/null +++ b/sound/soc/rk/rk_pcm.c @@ -0,0 +1,690 @@ +/* + * rk_pcm.c -- ALSA SoC ROCKCHIP PCM Audio Layer Platform driver + * + * Driver for rockchip pcm audio + * + * + * 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 +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "rk_pcm.h" + +#define PCM_DMA_DEBUG 0 + +#if 0 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) do { } while (0) +#endif + +//#define INFIN_LOOP +#ifdef INFIN_LOOP +#define DMA_INFIN_LOOP() rk29_dma_has_infiniteloop() +#else +#define DMA_INFIN_LOOP() 0 +#endif + +static const struct snd_pcm_hardware rockchip_pcm_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S20_3LE | + SNDRV_PCM_FMTBIT_S16_LE, + .channels_min = 2, + .channels_max = 8, +#ifdef CONFIG_RK_SRAM_DMA + .buffer_bytes_max = 24*1024,//period_bytes_max * periods_max +#else + .buffer_bytes_max = 128*1024, +#endif + .period_bytes_min = 64, ///PAGE_SIZE, +#ifdef CONFIG_RK_SRAM_DMA + .period_bytes_max = 8*1024, +#else + .period_bytes_max = 2048*4,///PAGE_SIZE*2, +#endif + .periods_min = 3,///2, + .periods_max = 128, + .fifo_size = 16, +}; + + +struct rockchip_dma_buf_set { + struct rockchip_dma_buf_set *next; + struct scatterlist sg; +}; + +struct rockchip_runtime_data { + spinlock_t lock; + int state; + int transfer_first; + unsigned int dma_loaded; + unsigned int dma_limit; + unsigned int dma_period; + dma_addr_t dma_start; + dma_addr_t dma_pos; + dma_addr_t dma_end; + struct rockchip_pcm_dma_params *params; + struct rockchip_dma_buf_set *curr; /* current dma buffer set */ + struct rockchip_dma_buf_set *next; /* next buffer set to load */ + struct rockchip_dma_buf_set *end; /* end of queue set*/ +}; + + +/* rockchip_pcm_enqueue + * + * place a dma buffer onto the queue for the dma system + * to handle. +*/ +static void rockchip_pcm_enqueue(struct snd_pcm_substream *substream) +{ + struct rockchip_runtime_data *prtd = substream->runtime->private_data; + dma_addr_t pos = prtd->dma_pos; + unsigned int limit; + int ret; + + DBG("Enter::%s----%d prtd->dma_period = %d prtd->dma_limit = %d\n",__FUNCTION__,__LINE__,prtd->dma_period,prtd->dma_limit); + + if (rk29_dma_has_circular()) + limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period; + else + limit = prtd->dma_limit; + + if (DMA_INFIN_LOOP()) { + if(prtd->dma_period % (prtd->params->dma_size*16)){ + printk("dma_period(%d) is not an integer multiple of dma_size(%d)",prtd->dma_period,prtd->params->dma_size*16); + rk29_dma_config(prtd->params->channel, + prtd->params->dma_size, 1); + } + else + rk29_dma_config(prtd->params->channel, + prtd->params->dma_size, 16); + ret = rk29_dma_enqueue_ring(prtd->params->channel, + substream, pos, prtd->dma_period, limit ,true); + if (ret == 0) + pos = prtd->dma_start; + } else { + while (prtd->dma_loaded < prtd->dma_limit) { + unsigned long len = prtd->dma_period; + // DBG("dma_loaded: %d\n", prtd->dma_loaded); + if ((pos + len) > prtd->dma_end) { + len = prtd->dma_end - pos; + } + + if((len%(prtd->params->dma_size*16) == 0) && (prtd->params->flag == 1)) + { + ret = rk29_dma_config(prtd->params->channel, + prtd->params->dma_size, 16); + prtd->params->flag = 0; + DBG("size = 16, channel = %d, flag = %d\n",prtd->params->channel,prtd->params->flag); + } + else if((len%(prtd->params->dma_size*16) != 0) && (prtd->params->flag == 0)) + { + ret = rk29_dma_config(prtd->params->channel, + prtd->params->dma_size, 1); + prtd->params->flag = 1; + DBG("size = 1, channel = %d, flag = %d\n",prtd->params->channel,prtd->params->flag); + } + + ret = rk29_dma_enqueue(prtd->params->channel,substream, pos, len); + // if(prtd->params->channel == 2) + DBG("Enter::%s, %d, ret=%d, Channel=%d, Addr=0x%X, Len=%lu\n", + __FUNCTION__,__LINE__, ret, prtd->params->channel, pos, len); + if (ret == 0) { + prtd->dma_loaded++; + pos += prtd->dma_period; + if (pos >= prtd->dma_end) + pos = prtd->dma_start; + } else + break; + } + } + prtd->dma_pos = pos; +} + +void rk29_audio_buffdone(void *dev_id, int size, + enum rk29_dma_buffresult result) +{ + struct snd_pcm_substream *substream = dev_id; + struct rockchip_runtime_data *prtd; +#if PCM_DMA_DEBUG + static ktime_t before = {0},after = {0}; + s64 t; + before = after; + after = ktime_get(); + t = ktime_to_us(ktime_sub(after, before)); + if(result == RK29_RES_OK) + { + if(t > prtd->dma_period/4/44100 +73 && t != ktime_to_us(after)) // (23220)4096/4/44100 + 32/44100 + { + printk(KERN_DEBUG "Time out:: Audio DMA buffdone time out!!! the time = %lld!\n", t); + } + printk(KERN_DEBUG "audio DMA callback time = %lld\n", t); + } +// printk(KERN_DEBUG "a %d %d\n", size, result); +#endif + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + if (!substream){ + DBG("substream is free\n"); + return; + } + if (!substream->runtime){ + DBG("substream->runtime is free\n"); + return; + } + switch(result) + { + case RK29_RES_OK: + break; + case RK29_RES_ERR: + case RK29_RES_ABORT: + DBG("Enter::%s dma about or error result = %d \n",__FUNCTION__,result); + return; + } + + prtd = substream->runtime->private_data; + +// if(prtd->params->channel == 2) + DBG("Enter::%s----%d channel =%d \n",__FUNCTION__,__LINE__,prtd->params->channel); + if(!(prtd->state & ST_RUNNING)) + return; + if (substream){ + snd_pcm_period_elapsed(substream); + } + spin_lock(&prtd->lock); + if (!DMA_INFIN_LOOP() && prtd->state & ST_RUNNING) { + prtd->dma_loaded--; + rockchip_pcm_enqueue(substream); + } + spin_unlock(&prtd->lock); +} + +static int rockchip_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct rockchip_runtime_data *prtd = runtime->private_data; + struct snd_soc_pcm_runtime *rtd = substream->private_data; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + struct rockchip_pcm_dma_params *dma = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) + struct rockchip_pcm_dma_params *dma = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); +#else + struct rockchip_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; +#endif + unsigned long totbytes = params_buffer_bytes(params); + int ret = 0; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /* return if this is a bufferless transfer e.g. + * codec <--> BT codec or GSM modem -- lg FIXME */ + if (!dma) + return 0; + + /* this may get called several times by oss emulation + * with different params -HW */ + if (prtd->params == NULL) { + /* prepare DMA */ + prtd->params = dma; +#ifdef CONFIG_SND_I2S_DMA_EVENT_DYNAMIC + DBG("params %p, client %p, channel %d\n", prtd->params,prtd->params->client, prtd->params->channel); + ret = rk29_dma_request(prtd->params->channel, prtd->params->client, NULL); + DBG("Enter::%s, %d, ret=%d, Channel=%d\n", __FUNCTION__, __LINE__, ret, prtd->params->channel); + if (ret) { + DBG(KERN_ERR "failed to get dma channel\n"); + return ret; + } +#endif + } + + ret = rk29_dma_set_buffdone_fn(prtd->params->channel, rk29_audio_buffdone); + if(ret < 0){ + DBG(KERN_ERR "failed to rk29_dma_set_buffdone_fn\n"); + return ret; + } + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + + runtime->dma_bytes = totbytes; + + spin_lock_irq(&prtd->lock); + prtd->dma_loaded = 0; + prtd->dma_limit = params_periods(params);//runtime->hw.periods_min; + prtd->dma_period = params_period_bytes(params); + prtd->dma_start = runtime->dma_addr; + prtd->dma_pos = prtd->dma_start; + prtd->dma_end = prtd->dma_start + prtd->dma_limit*prtd->dma_period; + prtd->transfer_first = 1; + prtd->curr = NULL; + prtd->next = NULL; + prtd->end = NULL; + spin_unlock_irq(&prtd->lock); + printk(KERN_DEBUG "i2s dma info:periodsize(%ld),limit(%d),buffersize(%d),over(%d)\n", + prtd->dma_period,prtd->dma_limit,totbytes,totbytes-(prtd->dma_period*prtd->dma_limit)); + return ret; +} + +static int rockchip_pcm_hw_free(struct snd_pcm_substream *substream) +{ + struct rockchip_runtime_data *prtd = substream->runtime->private_data; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /* TODO - do we need to ensure DMA flushed */ + snd_pcm_set_runtime_buffer(substream, NULL); + + if (prtd->params) { +#ifdef CONFIG_SND_I2S_DMA_EVENT_DYNAMIC + rk29_dma_free(prtd->params->channel, prtd->params->client); + prtd->params = NULL; +#endif + } + + return 0; +} + +static int rockchip_pcm_prepare(struct snd_pcm_substream *substream) +{ + struct rockchip_runtime_data *prtd = substream->runtime->private_data; + int ret = 0; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* return if this is a bufferless transfer e.g. + * codec <--> BT codec or GSM modem -- lg FIXME */ + if (!prtd->params) + return 0; + + if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ret = rk29_dma_devconfig(prtd->params->channel, + RK29_DMASRC_MEM, + prtd->params->dma_addr); + }else{ + ret = rk29_dma_devconfig(prtd->params->channel, + RK29_DMASRC_HW, + prtd->params->dma_addr); + } + DBG("Enter::%s, %d, ret=%d, Channel=%d, Addr=0x%X\n", __FUNCTION__, __LINE__, ret, prtd->params->channel, prtd->params->dma_addr); + ret = rk29_dma_config(prtd->params->channel, + prtd->params->dma_size, 1); + prtd->params->flag = 1; + + DBG("Enter:%s, %d, ret = %d, Channel=%d, Size=%d\n", + __FUNCTION__, __LINE__, ret, prtd->params->channel, + prtd->params->dma_size); + + ret= rk29_dma_ctrl(prtd->params->channel, RK29_DMAOP_FLUSH); + DBG("Enter:%s, %d, ret = %d, Channel=%d\n", + __FUNCTION__, __LINE__, ret, prtd->params->channel); + + prtd->dma_loaded = 0; + prtd->dma_pos = prtd->dma_start; + + /* enqueue dma buffers */ + rockchip_pcm_enqueue(substream); + return ret; +} + +static int rockchip_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct rockchip_runtime_data *prtd = substream->runtime->private_data; + int ret = 0; + /**************add by qiuen for volume*****/ + struct snd_soc_pcm_runtime *rtd = substream->private_data; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + struct snd_soc_dai *pCodec_dai = rtd->codec_dai; +#else + struct snd_soc_dai *pCodec_dai = rtd->dai->codec_dai; +#endif + int vol = 0; + int streamType = 0; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + if(cmd==SNDRV_PCM_TRIGGER_VOLUME){ + vol = substream->number % 100; + streamType = (substream->number / 100) % 100; + DBG("enter:vol=%d,streamType=%d\n",vol,streamType); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + if(pCodec_dai->driver->ops->set_volume) + pCodec_dai->driver->ops->set_volume(streamType, vol); +#else + if(pCodec_dai->ops->set_volume) + pCodec_dai->ops->set_volume(streamType, vol); +#endif + } + /****************************************************/ + spin_lock(&prtd->lock); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + DBG(" START \n"); + prtd->state |= ST_RUNNING; + rk29_dma_ctrl(prtd->params->channel, RK29_DMAOP_START); + break; + case SNDRV_PCM_TRIGGER_RESUME: + DBG(" RESUME \n"); + break; + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + DBG(" RESTART \n"); + break; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + DBG(" STOPS \n"); + prtd->state &= ~ST_RUNNING; + rk29_dma_ctrl(prtd->params->channel, RK29_DMAOP_STOP); + break; + default: + ret = -EINVAL; + break; + } + + spin_unlock(&prtd->lock); + return ret; +} + + +static snd_pcm_uframes_t +rockchip_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct rockchip_runtime_data *prtd = runtime->private_data; + unsigned long res; + dma_addr_t src, dst; + snd_pcm_uframes_t ret; + + + spin_lock(&prtd->lock); + + rk29_dma_getposition(prtd->params->channel, &src, &dst); + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + res = dst - prtd->dma_start; + else + res = src - prtd->dma_start; + + spin_unlock(&prtd->lock); + + ret = bytes_to_frames(runtime, res); + if (ret == runtime->buffer_size) + ret = 0; + + if(prtd->params->channel == 2) + DBG("Enter:%s src = %x res = %x ret = %d\n",__FUNCTION__,src,res,ret); + + return ret; +} + + +static int rockchip_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct rockchip_runtime_data *prtd; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + snd_soc_set_runtime_hwparams(substream, &rockchip_pcm_hardware); + + prtd = kzalloc(sizeof(struct rockchip_runtime_data), GFP_KERNEL); + if (prtd == NULL) + return -ENOMEM; + + spin_lock_init(&prtd->lock); + + runtime->private_data = prtd; + return 0; +} + +static int rockchip_pcm_close(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct rockchip_runtime_data *prtd = runtime->private_data; + struct rockchip_dma_buf_set *sg_buf = NULL; + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + if (!prtd) { + DBG("rockchip_pcm_close called with prtd == NULL\n"); + return 0; + } + + if (prtd->params) + rk29_dma_set_buffdone_fn(prtd->params->channel, NULL); + sg_buf = prtd->curr; + + while (sg_buf != NULL) { + prtd->curr = sg_buf->next; + prtd->next = sg_buf->next; + sg_buf->next = NULL; + kfree(sg_buf); + sg_buf = NULL; + sg_buf = prtd->curr; + } + kfree(prtd); + + return 0; +} + +static int rockchip_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + +#ifdef CONFIG_RK_SRAM_DMA + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + return remap_pfn_range(vma, vma->vm_start, + substream->dma_buffer.addr >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot); +#else + return dma_mmap_writecombine(substream->pcm->card->dev, vma, + runtime->dma_area, + runtime->dma_addr, + runtime->dma_bytes); +#endif +} + +static struct snd_pcm_ops rockchip_pcm_ops = { + .open = rockchip_pcm_open, + .close = rockchip_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = rockchip_pcm_hw_params, + .hw_free = rockchip_pcm_hw_free, + .prepare = rockchip_pcm_prepare, + .trigger = rockchip_pcm_trigger, + .pointer = rockchip_pcm_pointer, + .mmap = rockchip_pcm_mmap, +}; + +#if defined(CONFIG_ARCH_RK3066B) +#elif defined(CONFIG_ARCH_RK30) +#define SRAM_DMA_PHYS_PLAYBACK (dma_addr_t)(RK30_IMEM_PHYS + 16*1024) +#define SRAM_DMA_START_PLAYBACK (RK30_IMEM_NONCACHED + 16*1024) +#define SRAM_DMA_PHYS_CAPTURE (dma_addr_t)(SRAM_DMA_PHYS_PLAYBACK + 24*1024) +#define SRAM_DMA_START_CAPTURE (SRAM_DMA_START_PLAYBACK + 24*1024) +#endif + +static int rockchip_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) +{ + struct snd_pcm_substream *substream = pcm->streams[stream].substream; + struct snd_dma_buffer *buf = &substream->dma_buffer; + size_t size = rockchip_pcm_hardware.buffer_bytes_max; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + buf->dev.type = SNDRV_DMA_TYPE_DEV; + buf->dev.dev = pcm->card->dev; + buf->private_data = NULL; +#ifdef CONFIG_RK_SRAM_DMA + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + buf->area = SRAM_DMA_START_PLAYBACK; + buf->addr = SRAM_DMA_PHYS_PLAYBACK; + } else{ + buf->area = SRAM_DMA_START_CAPTURE; + buf->addr = SRAM_DMA_PHYS_CAPTURE; + } +#else + buf->area = dma_alloc_writecombine(pcm->card->dev, size, + &buf->addr, GFP_KERNEL); +#endif + if (!buf->area) + return -ENOMEM; + buf->bytes = size; + DBG("%s: size %d\n",__FUNCTION__, size); + return 0; +} + +static void rockchip_pcm_free_dma_buffers(struct snd_pcm *pcm) +{ + struct snd_pcm_substream *substream; + struct snd_dma_buffer *buf; + int stream; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + for (stream = 0; stream < 2; stream++) { + substream = pcm->streams[stream].substream; + if (!substream) + continue; + + buf = &substream->dma_buffer; + if (!buf->area) + continue; + + dma_free_writecombine(pcm->card->dev, buf->bytes, + buf->area, buf->addr); + buf->area = NULL; + } +} + +static u64 rockchip_pcm_dmamask = DMA_BIT_MASK(32); + +static int rockchip_pcm_new(struct snd_card *card, + struct snd_soc_dai *dai, struct snd_pcm *pcm) +{ + int ret = 0; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + if (!card->dev->dma_mask) + card->dev->dma_mask = &rockchip_pcm_dmamask; + if (!card->dev->coherent_dma_mask) + card->dev->coherent_dma_mask = 0xffffffff; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + if (dai->driver->playback.channels_min) { +#else + if (dai->playback.channels_min) { +#endif + ret = rockchip_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_PLAYBACK); + if (ret) + goto out; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + if (dai->driver->capture.channels_min) { +#else + if (dai->capture.channels_min) { +#endif + ret = rockchip_pcm_preallocate_dma_buffer(pcm, + SNDRV_PCM_STREAM_CAPTURE); + if (ret) + goto out; + } + out: + return ret; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) +static struct snd_soc_platform_driver rockchip_pcm_platform = { + .ops = &rockchip_pcm_ops, + .pcm_new = rockchip_pcm_new, + .pcm_free = rockchip_pcm_free_dma_buffers, +}; + +static int __devinit rockchip_pcm_platform_probe(struct platform_device *pdev) +{ + DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__); + return snd_soc_register_platform(&pdev->dev, &rockchip_pcm_platform); +} + +static int __devexit rockchip_pcm_platform_remove(struct platform_device *pdev) +{ + snd_soc_unregister_platform(&pdev->dev); + return 0; +} + +static struct platform_driver rockchip_pcm_driver = { + .driver = { + .name = "rockchip-audio", + .owner = THIS_MODULE, + }, + .probe = rockchip_pcm_platform_probe, + .remove = __devexit_p(rockchip_pcm_platform_remove), +}; + +static int __init snd_rockchip_pcm_init(void) +{ + DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__); + return platform_driver_register(&rockchip_pcm_driver); +} +module_init(snd_rockchip_pcm_init); + +static void __exit snd_rockchip_pcm_exit(void) +{ + platform_driver_unregister(&rockchip_pcm_driver); +} +module_exit(snd_rockchip_pcm_exit); +#else +struct snd_soc_platform rk29_soc_platform = { + .name = "rockchip-audio", + .pcm_ops = &rockchip_pcm_ops, + .pcm_new = rockchip_pcm_new, + .pcm_free = rockchip_pcm_free_dma_buffers, +}; +EXPORT_SYMBOL_GPL(rk29_soc_platform); + +static int __init rockchip_soc_platform_init(void) +{ + DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__); + return snd_soc_register_platform(&rk29_soc_platform); +} +module_init(rockchip_soc_platform_init); + +static void __exit rockchip_soc_platform_exit(void) +{ + snd_soc_unregister_platform(&rk29_soc_platform); +} +module_exit(rockchip_soc_platform_exit); +#endif + +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP PCM ASoC Interface"); +MODULE_LICENSE("GPL"); + diff --git a/sound/soc/rk/rk_pcm.h b/sound/soc/rk/rk_pcm.h new file mode 100755 index 000000000000..62c92e2acba1 --- /dev/null +++ b/sound/soc/rk/rk_pcm.h @@ -0,0 +1,30 @@ +/* + * rockchip-pcm.h - ALSA PCM interface for the Rockchip rk28 SoC + * + * Driver for rockchip iis audio + * + * + * 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 _ROCKCHIP_PCM_H +#define _ROCKCHIP_PCM_H + +#include + +#define ST_RUNNING (1<<0) +#define ST_OPENED (1<<1) + +struct rockchip_pcm_dma_params { + struct rk29_dma_client *client; /* stream identifier */ + int channel; /* Channel ID */ + dma_addr_t dma_addr; + int dma_size; /* Size of the DMA transfer */ + int flag; /*burst change flag*/ +}; + +extern struct snd_soc_platform rk29_soc_platform; + +#endif /* _ROCKCHIP_PCM_H */ diff --git a/sound/soc/rk/rk_rk1000codec.c b/sound/soc/rk/rk_rk1000codec.c new file mode 100755 index 000000000000..7825020431cd --- /dev/null +++ b/sound/soc/rk/rk_rk1000codec.c @@ -0,0 +1,140 @@ +/* + * rk29_wm8988.c -- SoC audio for rockchip + * + * Driver for rockchip wm8988 audio + * + * 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 +#include +#include +#include +#include +#include +#include "../codecs/rk1000_codec.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" + +#if 1 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +static int rk29_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #endif + if (ret < 0) + return ret; + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_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_RK_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; + +//ÉèÖ÷ÖƵ²¿·Ö£¬ÔÝʱδÉèÖà + return 0; +} + +/* + * Logic for a rk1000 codec as connected on a rockchip board. + */ +static int rk29_rk1000_codec_init(struct snd_soc_pcm_runtime *rtd) +{ + return 0; +} + +static struct snd_soc_ops rk29_ops = { + .hw_params = rk29_hw_params, +}; + +static struct snd_soc_dai_link rk29_dai[] = { + { + .name = "RK1000", + .stream_name = "RK1000 CODEC PCM", + .platform_name = "rockchip-audio", + .codec_name = "RK1000_CODEC.0-0060", + .codec_dai_name = "rk1000_codec", +#if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", +#elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", +#endif + .init = rk29_rk1000_codec_init, + .ops = &rk29_ops, + } +}; + +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_RK1000", + .dai_link = rk29_dai, + .num_links = 1, +}; + + +static struct platform_device *rk29_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) { + printk("platform device allocation failed\n"); + ret = -ENOMEM; + return ret; + } + + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + ret = platform_device_add(rk29_snd_device); + if (ret) { + printk("platform device add failed\n"); + platform_device_put(rk29_snd_device); + } + printk("audio_card_init end....\n"); + return ret; +} + +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk/rk_rk3026.c b/sound/soc/rk/rk_rk3026.c new file mode 100644 index 000000000000..191aef64269c --- /dev/null +++ b/sound/soc/rk/rk_rk3026.c @@ -0,0 +1,290 @@ +/* + * rk_rk3026.c -- SoC audio for rockchip + * + * Driver for rockchip rk3026 audio + * + * 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 +#include +#include +#include +#include +#include +#include "../codecs/rk3026_codec.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" + +#if 0 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +static const struct snd_soc_dapm_widget rk_dapm_widgets[] = { + SND_SOC_DAPM_MIC("Mic Jack", NULL), + SND_SOC_DAPM_MIC("Headset Jack", NULL), + SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_HP("Headphone Jack", NULL), +}; + +static const struct snd_soc_dapm_route rk_audio_map[]={ + + /* Mic Jack --> MIC_IN*/ + {"Mic Bias", NULL, "Mic Jack"}, + {"MICP", NULL, "Mic Bias"}, + {"MICN", NULL, "Mic Bias"}, + + // HP MIC + {"Mic Bias", NULL, "Headset Jack"}, + + {"Ext Spk", NULL, "HPOUTR"}, + {"Ext Spk", NULL, "HPOUTL"}, + + {"Headphone Jack", NULL, "HPOUTR"}, + {"Headphone Jack", NULL, "HPOUTL"}, +} ; + +static const struct snd_kcontrol_new rk_controls[] = { + SOC_DAPM_PIN_SWITCH("Mic Jack"), + SOC_DAPM_PIN_SWITCH("Headset Jack"), + SOC_DAPM_PIN_SWITCH("Ext Spk"), + SOC_DAPM_PIN_SWITCH("Headphone Jack"), +}; + +static int rk3026_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + snd_soc_add_codec_controls(codec, rk_controls, + ARRAY_SIZE(rk_controls)); + + /* Add specific widgets */ + snd_soc_dapm_new_controls(dapm, rk_dapm_widgets, + ARRAY_SIZE(rk_dapm_widgets)); + /* Set up specific audio path audio_mapnects */ + snd_soc_dapm_add_routes(dapm, rk_audio_map, ARRAY_SIZE(rk_audio_map)); + + snd_soc_dapm_enable_pin(dapm, "Mic Jack"); + snd_soc_dapm_enable_pin(dapm, "Headset Jack"); + snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); + + snd_soc_dapm_sync(dapm); + + return 0; +} + +static int rk_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #endif + if (ret < 0) + return ret; + + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_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_RK_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: + DBG("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)); + + /*Set the system clk for codec*/ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); + if (ret < 0) { + DBG("rk_hifi_hw_params:failed to set the sysclk for codec side\n"); + return ret; + } + + 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 int rk_voice_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | + SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS); + + 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: + DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params)); + return -EINVAL; + break; + } + + /*Set the system clk for codec*/ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); + + if (ret < 0) { + printk("rk_voice_hw_params:failed to set the sysclk for codec side\n"); + return ret; + } + + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + + return 0; +} + +static struct snd_soc_ops rk3026_hifi_ops = { + .hw_params = rk_hifi_hw_params, +}; + +static struct snd_soc_ops rk3026_voice_ops = { + .hw_params = rk_voice_hw_params, +}; + +static struct snd_soc_dai_link rk_dai[] = { + { + .name = "RK3026 I2S1", + .stream_name = "RK3026 PCM", + .codec_name = "rk3026-codec", + .platform_name = "rockchip-audio", +#if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", +#elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", +#endif + .codec_dai_name = "rk3026-hifi", + .init = rk3026_init, + .ops = &rk3026_hifi_ops, + }, + { + .name = "RK3026 I2S2", + .stream_name = "RK3026 PCM", + .codec_name = "rk3026-codec", + .platform_name = "rockchip-audio", +#if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", +#elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", +#endif + .codec_dai_name = "rk3026-voice", + .ops = &rk3026_voice_ops, + }, +}; + +static struct snd_soc_card snd_soc_card_rk = { + .name = "RK_RK3026", + .dai_link = rk_dai, + .num_links = 2, +}; + +static struct platform_device *rk_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + rk_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk_snd_device) { + printk("platform device allocation failed\n"); + return -ENOMEM; + } + + platform_set_drvdata(rk_snd_device, &snd_soc_card_rk); + ret = platform_device_add(rk_snd_device); + if (ret) { + printk("platform device add failed\n"); + + platform_device_put(rk_snd_device); + return ret; + } + + return ret; +} + +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk_snd_device); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk/rk_rk616.c b/sound/soc/rk/rk_rk616.c new file mode 100755 index 000000000000..a88e7284d1f0 --- /dev/null +++ b/sound/soc/rk/rk_rk616.c @@ -0,0 +1,320 @@ +/* + * rk_rk616.c -- SoC audio for rockchip + * + * Driver for rockchip rk616 audio + * + * 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 +#include +#include +#include +#include +#include +#include "../codecs/rk616_codec.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" + +#if 1 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +static const struct snd_soc_dapm_widget rk_dapm_widgets[] = { + SND_SOC_DAPM_MIC("Mic Jack", NULL), + SND_SOC_DAPM_MIC("Headset Jack", NULL), + SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_HP("Headphone Jack", NULL), +}; + +static const struct snd_soc_dapm_route rk_audio_map[]={ + + /* Mic Jack --> MIC_IN*/ + {"Mic1 Bias", NULL, "Mic Jack"}, + {"MIC1P", NULL, "Mic1 Bias"}, + {"MIC1N", NULL, "Mic1 Bias"}, + + // HP MIC + {"Mic2 Bias", NULL, "Headset Jack"}, + {"MIC2P", NULL, "Mic2 Bias"}, + {"MIC2N", NULL, "Mic2 Bias"}, + + {"Ext Spk", NULL, "SPKOUTR"}, + {"Ext Spk", NULL, "SPKOUTL"}, + + {"Headphone Jack", NULL, "HPOUTR"}, + {"Headphone Jack", NULL, "HPOUTL"}, +} ; + +static const struct snd_kcontrol_new rk_controls[] = { + SOC_DAPM_PIN_SWITCH("Mic Jack"), + SOC_DAPM_PIN_SWITCH("Headset Jack"), + SOC_DAPM_PIN_SWITCH("Ext Spk"), + SOC_DAPM_PIN_SWITCH("Headphone Jack"), +}; + +static int rk616_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + + // if is for mid that using tiny alsa, + // it don't need this controls and route, so return. + if (rk616_get_for_mid()) + return 0; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + snd_soc_add_codec_controls(codec, rk_controls, + ARRAY_SIZE(rk_controls)); + + /* Add specific widgets */ + snd_soc_dapm_new_controls(dapm, rk_dapm_widgets, + ARRAY_SIZE(rk_dapm_widgets)); + /* Set up specific audio path audio_mapnects */ + snd_soc_dapm_add_routes(dapm, rk_audio_map, ARRAY_SIZE(rk_audio_map)); + + snd_soc_dapm_enable_pin(dapm, "Mic Jack"); + snd_soc_dapm_enable_pin(dapm, "Headset Jack"); + snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); + + snd_soc_dapm_sync(dapm); + + return 0; +} + +static int rk_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0, div = 4; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #endif + if (ret < 0) + return ret; + + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_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_RK_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 16000: + case 24000: + case 32000: + case 48000: + pll_out = 12288000; + break; + case 11025: + case 22050: + case 44100: + pll_out = 11289600; + break; + case 8000: + pll_out = 12000000; + div = 6; + break; + default: + DBG("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)); + + #if defined(CONFIG_RK616_USE_MCLK_12M) + /* MCLK must be 12M when RK616 HDMI is in */ + if (get_hdmi_state() && pll_out != 12000000) { + DBG("%s : HDMI is in, don't set sys clk %u\n",__FUNCTION__, pll_out); + goto __setdiv; + } + #endif + + /* Set the system clk for codec + mclk will be setted in set_sysclk of codec_dai*/ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); + if (ret < 0) { + DBG("rk_hifi_hw_params:failed to set the sysclk for codec side\n"); + return ret; + } +#if defined(CONFIG_RK616_USE_MCLK_12M) +__setdiv: +#endif + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (pll_out / div)/params_rate(params)-1); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div - 1); + + DBG("Enter:%s, %d, pll_out/div/params_rate(params) = %d \n", __FUNCTION__, __LINE__, (pll_out/div)/params_rate(params)); + + return 0; +} + +static int rk_voice_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | + SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS); + + 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: + DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params)); + return -EINVAL; + break; + } + + /* MCLK must be 12M when RK616 HDMI is in */ + #if defined(CONFIG_RK616_USE_MCLK_12M) + if (get_hdmi_state() && pll_out != 12000000) { + DBG("%s : HDMI is in, set mclk to 12Mn",__FUNCTION__); + pll_out = 12000000; + } + #endif + + //snd_soc_dai_set_pll(codec_dai, RT5625_PLL_MCLK_TO_VSYSCLK, 0, pll_out, 24576000); + + /*Set the system clk for codec*/ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); + + if (ret < 0) { + printk("rk_voice_hw_params:failed to set the sysclk for codec side\n"); + return ret; + } + + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + + return 0; +} + +static struct snd_soc_ops rk616_hifi_ops = { + .hw_params = rk_hifi_hw_params, +}; + +static struct snd_soc_ops rk616_voice_ops = { + .hw_params = rk_voice_hw_params, +}; + +static struct snd_soc_dai_link rk_dai[] = { + { + .name = "RK616 I2S1", + .stream_name = "RK616 PCM", + .codec_name = "rk616-codec.4-0050", + .platform_name = "rockchip-audio", +#if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", +#elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", +#endif + .codec_dai_name = "rk616-hifi", + .init = rk616_init, + .ops = &rk616_hifi_ops, + }, + { + .name = "RK616 I2S2", + .stream_name = "RK616 PCM", + .codec_name = "rk616-codec.4-0050", + .platform_name = "rockchip-audio", +#if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", +#elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", +#endif + .codec_dai_name = "rk616-voice", + .ops = &rk616_voice_ops, + }, +}; + +static struct snd_soc_card snd_soc_card_rk = { + .name = "RK_RK616", + .dai_link = rk_dai, + .num_links = 2, +}; + +static struct platform_device *rk_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + rk_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk_snd_device) { + printk("platform device allocation failed\n"); + return -ENOMEM; + } + + platform_set_drvdata(rk_snd_device, &snd_soc_card_rk); + ret = platform_device_add(rk_snd_device); + if (ret) { + printk("platform device add failed\n"); + + platform_device_put(rk_snd_device); + return ret; + } + + return ret; +} + +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk_snd_device); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk/rk_rt3261.c b/sound/soc/rk/rk_rt3261.c new file mode 100644 index 000000000000..fd0f97f375ad --- /dev/null +++ b/sound/soc/rk/rk_rt3261.c @@ -0,0 +1,327 @@ +/* + * rk29_rt3261.c -- SoC audio for rockchip + * + * Driver for rockchip rt3261 audio + * + * 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 +#include +#include +#include +#include +#include + +#include "../codecs/rt3261.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" + + +#if 0 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +static int rk29_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /*by Vincent Hsiung for EQ Vol Change*/ + #define HW_PARAMS_FLAG_EQVOL_ON 0x21 + #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 + if (codec_dai->driver->ops->hw_params && ((params->flags == HW_PARAMS_FLAG_EQVOL_ON) || (params->flags == HW_PARAMS_FLAG_EQVOL_OFF))) + { + ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + } else { + + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #endif + if (ret < 0) + return ret; + + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_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_RK_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: + DBG("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)); + + /*Set the system clk for codec*/ + snd_soc_dai_set_pll(codec_dai, 0, RT3261_PLL1_S_MCLK, pll_out, pll_out*2); //bard 8-29 + ret = snd_soc_dai_set_sysclk(codec_dai, RT3261_SCLK_S_PLL1, pll_out*2, SND_SOC_CLOCK_IN); //bard 8-29 + if (ret < 0) + { + DBG("rk29_hw_params_rt3261:failed to set the sysclk for codec side\n"); + return ret; + } + + 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);// 256k = 48-1 3M=3 + + DBG("Enter:%s, %d, pll_out/4/params_rate(params) = %d \n", __FUNCTION__, __LINE__, (pll_out/4)/params_rate(params)); + + return 0; +} + +static int rt3261_voice_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | + SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS ); + + 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: + DBG("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)); + + /*Set the system clk for codec*/ + snd_soc_dai_set_pll(codec_dai, 0, RT3261_PLL1_S_MCLK, pll_out, pll_out*2); //bard 8-29 + ret = snd_soc_dai_set_sysclk(codec_dai, RT3261_SCLK_S_PLL1, pll_out*2, SND_SOC_CLOCK_IN); //bard 8-29 + + + if (ret < 0) { + printk("rk29_hw_params_rt3261:failed to set the sysclk for codec side\n"); + return ret; + } + + 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 const struct snd_soc_dapm_widget rt3261_dapm_widgets[] = { + SND_SOC_DAPM_MIC("Mic Jack", NULL), + SND_SOC_DAPM_MIC("Headset Jack", NULL), + SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_HP("Headphone Jack", NULL), +}; + +static const struct snd_soc_dapm_route audio_map[]={ + + /* Mic Jack --> MIC_IN*/ + {"micbias1", NULL, "Mic Jack"}, + {"MIC1", NULL, "micbias1"}, + + // HP MIC + {"micbias1", NULL, "Headset Jack"}, + {"MIC3", NULL, "micbias1"}, + + {"Ext Spk", NULL, "SPOLP"}, + {"Ext Spk", NULL, "SPOLN"}, + {"Ext Spk", NULL, "SPORP"}, + {"Ext Spk", NULL, "SPORN"}, + + {"Headphone Jack", NULL, "HPOL"}, + {"Headphone Jack", NULL, "HPOR"}, +} ; + +static const struct snd_kcontrol_new rk_controls[] = { + SOC_DAPM_PIN_SWITCH("Mic Jack"), + SOC_DAPM_PIN_SWITCH("Headset Jack"), + SOC_DAPM_PIN_SWITCH("Ext Spk"), + SOC_DAPM_PIN_SWITCH("Headphone Jack"), +}; + +/* + * Logic for a rt3261 as connected on a rockchip board. + */ +static int rk29_rt3261_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + snd_soc_add_codec_controls(codec, rk_controls, + ARRAY_SIZE(rk_controls)); + + /* Add specific widgets */ + snd_soc_dapm_new_controls(dapm, rt3261_dapm_widgets, + ARRAY_SIZE(rt3261_dapm_widgets)); + /* Set up specific audio path audio_mapnects */ + snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + + snd_soc_dapm_enable_pin(dapm, "Mic Jack"); + snd_soc_dapm_enable_pin(dapm, "Headset Jack"); + snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); +#ifdef CONFIG_HDMI + extern int hdmi_is_insert(void); + extern void codec_set_spk(bool on); + if(hdmi_is_insert()) + codec_set_spk(false); +#endif + +#ifdef CONFIG_HDMI_RK30 + extern int hdmi_get_hotplug(void); + if(hdmi_get_hotplug() == 2/*HDMI_HPD_ACTIVED*/) + codec_set_spk(false); +#endif + + snd_soc_dapm_sync(dapm); + + return 0; +} + +static struct snd_soc_ops rk29_ops = { + .hw_params = rk29_hw_params, +}; + +static struct snd_soc_ops rt3261_voice_ops = { + .hw_params = rt3261_voice_hw_params, +}; + +static struct snd_soc_dai_link rk29_dai[] = { + { + .name = "RT3261 I2S1", + .stream_name = "RT3261 PCM", + .codec_name = "rt3261.0-001c", + .platform_name = "rockchip-audio", + #if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", + #elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", + #endif + .codec_dai_name = "rt3261-aif1", + .init = rk29_rt3261_init, + .ops = &rk29_ops, + }, + { + .name = "RT3261 I2S2", + .stream_name = "RT3261 PCM", + .codec_name = "rt3261.0-001c", + .platform_name = "rockchip-audio", + #if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", + #elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", + #endif + .codec_dai_name = "rt3261-aif2", + .ops = &rt3261_voice_ops, + }, +}; + +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_RT3261", + .dai_link = rk29_dai, + .num_links = 2, +}; + +static struct platform_device *rk29_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) { + printk("platform device allocation failed\n"); + return -ENOMEM; + } + + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + ret = platform_device_add(rk29_snd_device); + if (ret) { + printk("platform device add failed\n"); + + platform_device_put(rk29_snd_device); + return ret; + } + + return ret; +} + +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk/rk_rt5512.c b/sound/soc/rk/rk_rt5512.c new file mode 100755 index 000000000000..33a6f830c45e --- /dev/null +++ b/sound/soc/rk/rk_rt5512.c @@ -0,0 +1,334 @@ +/* + * odroid_rt5512.c + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include "rk_pcm.h" +#include "rk29_i2s.h" +#if 1 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +#include "../codecs/rt5512.h" + +static struct platform_device *rk29_snd_device; + + +static int rk29_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + unsigned int pll_div; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_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_RK_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; + + + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #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; + case 96000: + case 192000: + pll_out = 12288000*2; + break; + case 88200: + case 176400: + pll_out = 11289600*2; + break; + default: + DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + return -EINVAL; + break; + } +#if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, 64-1);//bclk = 2*32*lrck; 2*32fs + switch(params_rate(params)) { + case 176400: + case 192000: + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 1); + DBG("Enter:%s, %d, MCLK=%d BCLK=%d LRCK=%d\n", + __FUNCTION__,__LINE__,pll_out,pll_out/2,params_rate(params)); + break; + default: + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3); + DBG("default:%s, %d, MCLK=%d BCLK=%d LRCK=%d\n", + __FUNCTION__,__LINE__,pll_out,pll_out/4,params_rate(params)); + break; + } + + /*Set the system clk for codec*/ + ret=snd_soc_dai_set_sysclk(codec_dai, 0,pll_out,SND_SOC_CLOCK_IN); + if (ret < 0) + { + DBG("rk29_hw_params_rt5631:failed to set the sysclk for codec side\n"); + return ret; + } + + switch (params_rate(params)) + { + case 8000: + pll_div = 12; + break; + case 16000: + pll_div = 6; + break; + case 32000: + pll_div = 3; + break; + case 48000: + pll_div = 2; + break; + case 96000: + pll_div = 1; + break; + case 11025: + pll_div = 8; + break; + case 22050: + pll_div = 4; + break; + case 44100: + pll_div = 2; + break; + case 88200: + pll_div = 1; + break; + default: + printk("Not yet supported!\n"); + return -EINVAL; + } + ret = snd_soc_dai_set_clkdiv(codec_dai, RT5512_CLK_DIV_ID, pll_div*4); + if (ret < 0) + return ret; +#endif + +#if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + //snd_soc_dai_set_pll(codec_dai,0,pll_out, 22579200); + snd_soc_dai_set_sysclk(codec_dai,0,pll_out, SND_SOC_CLOCK_IN); +#endif + return 0; +} + +//--------------------------------------------------------------------------------- +/* + * rt5512 DAI operations. + */ +static struct snd_soc_ops rk29_ops = { + .hw_params = rk29_hw_params, +}; + +static const struct snd_soc_dapm_widget rt5512_dapm_widgets[] = { + // Input + SND_SOC_DAPM_MIC("Main Mic", NULL), + SND_SOC_DAPM_LINE("LineIn", NULL), + // Output + SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_HP("Headphone Jack", NULL), +}; + +static const struct snd_soc_dapm_route rt5512_audio_map[] = { + // Input + {"MicBias1", NULL,"Main Mic"}, + {"Mic2", NULL, "MicBias1"}, + {"MicBias2", NULL, "LineIn"}, + {"Aux", NULL, "MicBias2"}, + // Output + {"Ext Spk", NULL, "LSpeaker"}, + {"Ext Spk", NULL, "RSpeaker"}, + {"Headphone Jack", NULL, "LHeadphone"}, + {"Headphone Jack", NULL, "RHeadphone"}, +}; + +#if 0 + +static struct snd_soc_jack rk29_soc_jack; + + + +static struct snd_soc_jack_gpio odroid_soc_jack_gpio[] = { + { + .gpio = 28, + .name "headset event", + .report = SND_JACK_HEADSET, + .debounce_time = 200, + }, +}; +#endif + +#if 0 +static int rt5512_headset_keys(struct snd_soc_jack *jack) +{ + int err = 0; + + err = snd_jack_set_key(jack->jack, SND_JACK_BTN_0, 0x80); + if (err) + return err; + + err = snd_jack_set_key(jack->jack, SND_JACK_BTN_1, 0x81); + if (err) + return err; + + err = snd_jack_set_key(jack->jack, SND_JACK_BTN_2, 0x82); + if (err) + return err; + + return 0; +} +#endif + +static int rt5512_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + //struct rt5512_codec_chip *chip = snd_soc_codec_get_drvdata(codec); + //int err = 0; + + snd_soc_dapm_new_controls(dapm, rt5512_dapm_widgets, + ARRAY_SIZE(rt5512_dapm_widgets)); + + snd_soc_dapm_add_routes(dapm, rt5512_audio_map, + ARRAY_SIZE(rt5512_audio_map)); +#if FOR_MID + snd_soc_dapm_disable_pin(dapm, "Main Mic"); + snd_soc_dapm_disable_pin(dapm, "LineIn"); + snd_soc_dapm_disable_pin(dapm, "Ext Spk"); + snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); +#endif + +#if 0 + if (!chip->rt_jack) + { + err = snd_soc_jack_new(codec, "Headset Jack" , SND_JACK_HEADSET, &rk29_soc_jack); + if (err) + return err; + + #if 0 + // How-to use gpio, just declare snd_soc_jack_gpios, then it will + // help you to register a interrupt and set wakeup, and delayed schedule + // work + err = snd_soc_jack_add_gpios(&odroid_soc_jack, gpio_count, odroid_soc_jack_gpios); + if (err) + return err; + + // If use this, when trigger, just use snd_soc_jack_get_type + // then snd_soc_jack_report to send the event to upper layer + err = snd_soc_jack_add_zones(&odroid_soc_jack, zone_count, tcc_soc_zones); + if (err) + return err; + #endif + + err = rt5512_headset_keys(&rk29_soc_jack); + if (err) + return err; + + chip->rt_jack = &rk29_soc_jack; + } +#endif + snd_soc_dapm_sync(dapm); + return 0; +} + +static struct snd_soc_dai_link rk29_dai[] = { + { /* Primary DAI i/f */ + .name = "RT5512 AIF1", + .stream_name = "RT5512 PCM", + .cpu_dai_name = "rk_i2s.1", + .codec_dai_name = "RT5512-aif1", + .platform_name = "rockchip-audio", + .codec_name = "rt5512.1-0018", + .init = rt5512_init, + .ops = &rk29_ops, + }, +}; + +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_RT5512", + .dai_link = rk29_dai, + + /* If you want to use sec_fifo device, + * changes the num_link = 2 or ARRAY_SIZE(odroid_dai). */ + .num_links = ARRAY_SIZE(rk29_dai), +}; + +static int __init audio_card_init(void) +{ + int ret; + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) + return -ENOMEM; + + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + + ret = platform_device_add(rk29_snd_device); + if (ret) + platform_device_put(rk29_snd_device); + + return ret; +} +module_init(audio_card_init); + +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device); +} +module_exit(audio_card_exit); + +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_AUTHOR("cy_huang "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk/rk_rt5616.c b/sound/soc/rk/rk_rt5616.c new file mode 100755 index 000000000000..0a49430be7b0 --- /dev/null +++ b/sound/soc/rk/rk_rt5616.c @@ -0,0 +1,249 @@ +/* + * rk29_rt5631.c -- SoC audio for rockchip + * + * Driver for rockchip rt5631 audio + * + * 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 +#include +#include +#include +#include +#include +#include "../codecs/rt5631.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" + +#if 0 +:#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +static int rk29_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /*by Vincent Hsiung for EQ Vol Change*/ + #define HW_PARAMS_FLAG_EQVOL_ON 0x21 + #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 + if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) + { + ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + } + else + { + + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #endif + if (ret < 0) + return ret; + + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_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_RK_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: + DBG("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)); + + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) +#if 0 //use pll from blck + /*Set the pll of rt5631,the Pll source from BITCLK on CPU is master mode*/ + //bitclk is 64fs + ret=snd_soc_dai_set_pll(codec_dai,0,params_rate(params)*64,pll_out); + if (ret < 0) + { + DBG("rk29_hw_params_rt5631:failed to set the pll for codec side\n"); + return ret; + } +#endif + /*Set the system clk for codec*/ + ret=snd_soc_dai_set_sysclk(codec_dai, 0,pll_out,SND_SOC_CLOCK_IN); + if (ret < 0) + { + DBG("rk29_hw_params_rt5631:failed to set the sysclk for codec side\n"); + return ret; + } + #endif + + + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + + // snd_soc_dai_set_pll(codec_dai,0,pll_out, 22579200); + snd_soc_dai_set_sysclk(codec_dai,0,pll_out, SND_SOC_CLOCK_IN); + + #endif + + + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + 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); + #endif + + DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); + + return 0; +} + +static const struct snd_soc_dapm_widget rt5631_dapm_widgets[] = { + + SND_SOC_DAPM_MIC("Mic Jack", NULL), + SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_HP("Headphone Jack", NULL), + +}; + +static const struct snd_soc_dapm_route audio_map[]={ + + /* Mic Jack --> MIC_IN*/ + {"Mic Bias1", NULL, "Mic Jack"}, + {"MIC1", NULL, "Mic Bias1"}, + /* HP_OUT --> Headphone Jack */ + {"Headphone Jack", NULL, "HPOL"}, + {"Headphone Jack", NULL, "HPOR"}, + /* LINE_OUT --> Ext Speaker */ + {"Ext Spk", NULL, "SPOL"}, + {"Ext Spk", NULL, "SPOR"}, + +} ; + +/* + * Logic for a rt5631 as connected on a rockchip board. + */ +static int rk29_rt5631_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* Add specific widgets */ + snd_soc_dapm_new_controls(dapm, rt5631_dapm_widgets, + ARRAY_SIZE(rt5631_dapm_widgets)); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /* Set up specific audio path audio_mapnects */ + snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + snd_soc_dapm_nc_pin(dapm, "HP_L"); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + snd_soc_dapm_nc_pin(dapm, "HP_R"); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + snd_soc_dapm_sync(dapm); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + return 0; +} + +static struct snd_soc_ops rk29_ops = { + .hw_params = rk29_hw_params, +}; + +static struct snd_soc_dai_link rk29_dai = { + .name = "rt5616", + .stream_name = "rt5616 PCM", + .codec_name = "rt5616.4-001b", + .platform_name = "rockchip-audio", +#if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", +#elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", +#else + .cpu_dai_name = "rk_i2s.2", +#endif + .codec_dai_name = "rt5616-aif1", + .init = rk29_rt5631_init, + .ops = &rk29_ops, +}; + +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_RT5616", + .dai_link = &rk29_dai, + .num_links = 1, +}; + +static struct platform_device *rk29_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) { + printk("platform device allocation failed\n"); + ret = -ENOMEM; + return ret; + } + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + ret = platform_device_add(rk29_snd_device); + if (ret) { + printk("platform device add failed\n"); + platform_device_put(rk29_snd_device); + } + return ret; +} + +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); + diff --git a/sound/soc/rk/rk_rt5621.c b/sound/soc/rk/rk_rt5621.c new file mode 100644 index 000000000000..3469e085036c --- /dev/null +++ b/sound/soc/rk/rk_rt5621.c @@ -0,0 +1,229 @@ +/* + * rk29_rt5621.c -- SoC audio for rockchip + * + * Driver for rockchip rt5621 audio + * + * 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 +#include +#include +#include +#include +#include +#include +#include "../codecs/rt5621.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" + +#if 0 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +static int rk29_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + unsigned int lrclk = 0; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /*by Vincent Hsiung for EQ Vol Change*/ + #define HW_PARAMS_FLAG_EQVOL_ON 0x21 + #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 + if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) + { + ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + } else { + /* set codec DAI configuration */ +#if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); +#endif +#if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); +#endif + if (ret < 0) + return ret; + /* set cpu DAI configuration */ +#if defined (CONFIG_SND_RK_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_RK_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: + DBG("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)); + +#if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) +#if 0 //use pll from blck + /*Set the pll of rt5621,the Pll source from BITCLK on CPU is master mode*/ + //bitclk is 64fs + ret=snd_soc_dai_set_pll(codec_dai,RT5621_PLL_FR_BCLK,params_rate(params)*64,pll_out); + if (ret < 0) { + DBG("rk29_hw_params_rt5621:failed to set the pll for codec side\n"); + return ret; + } +#endif + /*Set the system clk for codec*/ + ret=snd_soc_dai_set_sysclk(codec_dai, 0,pll_out,SND_SOC_CLOCK_IN); + if (ret < 0) { + DBG("rk29_hw_params_rt5621:failed to set the sysclk for codec side\n"); + return ret; + } +#endif + + + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + + if((24576000%params_rate(params))==0) //for 8k,16k,32k,48k + { + snd_soc_dai_set_pll(codec_dai,RT5621_PLL_FR_MCLK,pll_out, 24576000); + snd_soc_dai_set_sysclk(codec_dai,0, 24576000, SND_SOC_CLOCK_IN); + } + else if((22579200%params_rate(params))==0) //for 11k,22k,44k + { + snd_soc_dai_set_pll(codec_dai,RT5621_PLL_FR_MCLK,pll_out, 22579200); + snd_soc_dai_set_sysclk(codec_dai,0, 22579200, SND_SOC_CLOCK_IN); + } + +#endif + + +#if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + 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); +#endif + + DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); + + return 0; +} + +static const struct snd_soc_dapm_widget rt5621_dapm_widgets[] = { + + SND_SOC_DAPM_MIC("Mic Jack", NULL), + SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_HP("Headphone Jack", NULL), + +}; + +static const struct snd_soc_dapm_route audio_map[]={ + + /* Mic Jack --> MIC_IN*/ + {"Mic Bias1", NULL, "Mic Jack"}, + {"MIC1", NULL, "Mic Bias1"}, + /* HP_OUT --> Headphone Jack */ + {"Headphone Jack", NULL, "HPOL"}, + {"Headphone Jack", NULL, "HPOR"}, + /* LINE_OUT --> Ext Speaker */ + {"Ext Spk", NULL, "SPOL"}, + {"Ext Spk", NULL, "SPOR"}, + +} ; + +/* + * Logic for a rt5621 as connected on a rockchip board. + */ +static int rk29_rt5621_init(struct snd_soc_pcm_runtime *rtd) +{ + return 0; +} + +static struct snd_soc_ops rk29_ops = { + .hw_params = rk29_hw_params, +}; + +static struct snd_soc_dai_link rk29_dai = { + .name = "RT5621", + .stream_name = "RT5621 PCM", + .codec_name = "RT5621.0-001a", + .platform_name = "rockchip-audio", + .cpu_dai_name = "rk_i2s.0", + .codec_dai_name = "RT5621 HiFi", + .init = rk29_rt5621_init, + .ops = &rk29_ops, +}; + +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_RT5621", + .dai_link = &rk29_dai, + .num_links = 1, +}; + +static struct platform_device *rk29_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; + + //rk29_speaker = rk29_speaker_init(RK29_PIN6_PB6, GPIO_HIGH, 2, (200*1000*1000)); + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) { + DBG("platform device allocation failed\n"); + ret = -ENOMEM; + return ret; + } + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + ret = platform_device_add(rk29_snd_device); + if (ret) { + DBG("platform device add failed\n"); + platform_device_put(rk29_snd_device); + return ret; + } + return ret; +} + +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk/rk_rt5625.c b/sound/soc/rk/rk_rt5625.c new file mode 100644 index 000000000000..3d46289f54ba --- /dev/null +++ b/sound/soc/rk/rk_rt5625.c @@ -0,0 +1,247 @@ +/* + * rk29_rt5625.c -- SoC audio for rockchip + * + * Driver for rockchip rt5625 audio + * + * 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 +#include +#include +#include +#include +#include +#include +#include "../codecs/rt5625.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" + +#if 1 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +static int rk29_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /*by Vincent Hsiung for EQ Vol Change*/ + #define HW_PARAMS_FLAG_EQVOL_ON 0x21 + #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 + if (codec_dai->driver->ops->hw_params && ((params->flags == HW_PARAMS_FLAG_EQVOL_ON) || (params->flags == HW_PARAMS_FLAG_EQVOL_OFF))) + { + ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + } else { + + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #endif + if (ret < 0) + return ret; + + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_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_RK_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: + DBG("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)); + + /*Set the system clk for codec*/ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); + if (ret < 0) + { + DBG("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); + return ret; + } + + 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 int rt5625_voice_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* set codec DAI configuration */ + //#if defined (CONFIG_SND_CODEC_SOC_SLAVE) + DBG("Enter::%s----codec slave\n",__FUNCTION__); + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | + SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS); + /*#endif + //#if defined (CONFIG_SND_CODEC_SOC_MASTER) + DBG("Enter::%s----codec master\n",__FUNCTION__); + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | + SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #endif*/ + + 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: + DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params)); + return -EINVAL; + break; + } + + snd_soc_dai_set_pll(codec_dai, RT5625_PLL_MCLK_TO_VSYSCLK, 0, pll_out, 24576000); + + /*Set the system clk for codec*/ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, 24576000, SND_SOC_CLOCK_IN); + + if (ret < 0) { + printk("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); + return ret; + } + + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + + return 0; +} + +static struct snd_soc_ops rk29_ops = { + .hw_params = rk29_hw_params, +}; + +static struct snd_soc_ops rt5625_voice_ops = { + .hw_params = rt5625_voice_hw_params, +}; + +static struct snd_soc_dai_link rk29_dai[] = { + { + .name = "RT5625 I2S1", + .stream_name = "RT5625 PCM", + .codec_name = "rt5625.0-001f", + .platform_name = "rockchip-audio", + .cpu_dai_name = "rk_i2s.0", + .codec_dai_name = "rt5625-aif1", + .ops = &rk29_ops, + }, + { + .name = "RT5625 I2S2", + .stream_name = "RT5625 PCM", + .codec_name = "rt5625.0-001f", + .platform_name = "rockchip-audio", + .cpu_dai_name = "rk_i2s.0", + .codec_dai_name = "rt5625-aif2", + .ops = &rt5625_voice_ops, + }, +}; + +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_RT5625", + .dai_link = rk29_dai, + .num_links = 2, +}; + +static struct platform_device *rk29_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) { + printk("platform device allocation failed\n"); + return -ENOMEM; + } + + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + ret = platform_device_add(rk29_snd_device); + if (ret) { + printk("platform device add failed\n"); + + platform_device_put(rk29_snd_device); + return ret; + } + + return ret; +} + +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk/rk_rt5631.c b/sound/soc/rk/rk_rt5631.c new file mode 100755 index 000000000000..8ddc988e1b89 --- /dev/null +++ b/sound/soc/rk/rk_rt5631.c @@ -0,0 +1,266 @@ +/* + * rk29_rt5631.c -- SoC audio for rockchip + * + * Driver for rockchip rt5631 audio + * + * 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 +#include +#include +#include +#include +#include +#include "../codecs/rt5631.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" + +#ifdef CONFIG_MACH_RK_FAC +#include +extern int codec_type; +#endif +#if 0 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +static int rk29_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /*by Vincent Hsiung for EQ Vol Change*/ + #define HW_PARAMS_FLAG_EQVOL_ON 0x21 + #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 + if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) + { + ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + } + else + { + + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #endif + if (ret < 0) + return ret; + + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_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_RK_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; + case 96000: + case 192000: + pll_out = 12288000*2; + break; + case 88200: + case 176400: + pll_out = 11289600*2; + break; + default: + DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + return -EINVAL; + break; + } +#if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, 64-1);//bclk = 2*32*lrck; 2*32fs + switch(params_rate(params)) { + case 176400: + case 192000: + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 1); + DBG("Enter:%s, %d, MCLK=%d BCLK=%d LRCK=%d\n", + __FUNCTION__,__LINE__,pll_out,pll_out/2,params_rate(params)); + break; + default: + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3); + DBG("default:%s, %d, MCLK=%d BCLK=%d LRCK=%d\n", + __FUNCTION__,__LINE__,pll_out,pll_out/4,params_rate(params)); + break; + } + +#if 0 //use pll from blck + /*Set the pll of rt5631,the Pll source from BITCLK on CPU is master mode*/ + //bitclk is 64fs + ret=snd_soc_dai_set_pll(codec_dai,0,params_rate(params)*64,pll_out); + if (ret < 0) + { + DBG("rk29_hw_params_rt5631:failed to set the pll for codec side\n"); + return ret; + } +#endif + /*Set the system clk for codec*/ + ret=snd_soc_dai_set_sysclk(codec_dai, 0,pll_out,SND_SOC_CLOCK_IN); + if (ret < 0) + { + DBG("rk29_hw_params_rt5631:failed to set the sysclk for codec side\n"); + return ret; + } +#endif + +#if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + //snd_soc_dai_set_pll(codec_dai,0,pll_out, 22579200); + snd_soc_dai_set_sysclk(codec_dai,0,pll_out, SND_SOC_CLOCK_IN); +#endif + return 0; +} + +static const struct snd_soc_dapm_widget rt5631_dapm_widgets[] = { + + SND_SOC_DAPM_MIC("Mic Jack", NULL), + SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_HP("Headphone Jack", NULL), + +}; + +static const struct snd_soc_dapm_route audio_map[]={ + + /* Mic Jack --> MIC_IN*/ + {"Mic Bias1", NULL, "Mic Jack"}, + {"MIC1", NULL, "Mic Bias1"}, + /* HP_OUT --> Headphone Jack */ + {"Headphone Jack", NULL, "HPOL"}, + {"Headphone Jack", NULL, "HPOR"}, + /* LINE_OUT --> Ext Speaker */ + {"Ext Spk", NULL, "SPOL"}, + {"Ext Spk", NULL, "SPOR"}, + +} ; + +/* + * Logic for a rt5631 as connected on a rockchip board. + */ +static int rk29_rt5631_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* Add specific widgets */ + snd_soc_dapm_new_controls(dapm, rt5631_dapm_widgets, + ARRAY_SIZE(rt5631_dapm_widgets)); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /* Set up specific audio path audio_mapnects */ + snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + snd_soc_dapm_nc_pin(dapm, "HP_L"); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + snd_soc_dapm_nc_pin(dapm, "HP_R"); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + snd_soc_dapm_sync(dapm); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + return 0; +} + +static struct snd_soc_ops rk29_ops = { + .hw_params = rk29_hw_params, +}; + +static struct snd_soc_dai_link rk29_dai = { + .name = "RT5631", + .stream_name = "RT5631 PCM", + .codec_name = "RT5631.0-001a", + .platform_name = "rockchip-audio", +#if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", +#elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", +#else + .cpu_dai_name = "rk_i2s.2", +#endif + .codec_dai_name = "RT5631 HiFi", + .init = rk29_rt5631_init, + .ops = &rk29_ops, +}; + +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_RT5631", + .dai_link = &rk29_dai, + .num_links = 1, +}; + +static struct platform_device *rk29_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; + +#ifdef CONFIG_MACH_RK_FAC + if(codec_type!=CODEC_TYPE_RT5631) + return -1; +#endif + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) { + printk("platform device allocation failed\n"); + ret = -ENOMEM; + return ret; + } + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + ret = platform_device_add(rk29_snd_device); + if (ret) { + printk("platform device add failed\n"); + platform_device_put(rk29_snd_device); + } + return ret; +} + +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); + diff --git a/sound/soc/rk/rk_rt5631_phone.c b/sound/soc/rk/rk_rt5631_phone.c new file mode 100755 index 000000000000..cd585f8aee8f --- /dev/null +++ b/sound/soc/rk/rk_rt5631_phone.c @@ -0,0 +1,320 @@ +/* + * rk_rt5631.c -- SoC audio for rockchip + * + * Driver for rockchip rt5631 audio + * + * 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 +#include +#include +#include +#include +#include +#include "../codecs/rt5631_phone.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" + +#if 1 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +static int rk29_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #endif + if (ret < 0) + return ret; + + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_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_RK_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: + DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + return -EINVAL; + } + DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + + snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + /*Set the system clk for codec*/ + ret=snd_soc_dai_set_sysclk(codec_dai, 0,pll_out,SND_SOC_CLOCK_IN); + if (ret < 0) + { + DBG("rk29_hw_params_rt5631:failed to set the sysclk for codec side\n"); + return ret; + } + 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); + #endif + + + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + snd_soc_dai_set_sysclk(codec_dai,0,pll_out, SND_SOC_CLOCK_IN); + #endif + + DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); + + return 0; +} + +static int rk29_hw_params_voice(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + //change to 8Khz + params->intervals[SNDRV_PCM_HW_PARAM_RATE - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].min = 8000; + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #endif + if (ret < 0) + return ret; + + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_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_RK_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; + pll_out = 2048000; + break; + default: + DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + return -EINVAL; + } + DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + + snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + /*Set the system clk for codec*/ + ret=snd_soc_dai_set_sysclk(codec_dai, 0,pll_out,SND_SOC_CLOCK_IN); + if (ret < 0) + { + DBG("rk29_hw_params_rt5631:failed to set the sysclk for codec side\n"); + return ret; + } + 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); + #endif + + + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + snd_soc_dai_set_sysclk(codec_dai,0,pll_out, SND_SOC_CLOCK_IN); + #endif + + DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); + + return 0; +} + +static const struct snd_soc_dapm_widget rt5631_dapm_widgets[] = { + + SND_SOC_DAPM_MIC("Mic Jack", NULL), + SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_HP("Headphone Jack", NULL), + +}; + +static const struct snd_soc_dapm_route audio_map[]={ + {"Headphone Jack", NULL, "HPOL"}, + {"Headphone Jack", NULL, "HPOR"}, + {"Ext Spk", NULL, "SPOL"}, + {"Ext Spk", NULL, "SPOR"}, + {"MIC1", NULL, "MIC Bias1"}, + {"MIC Bias1", NULL, "Mic Jack"}, +} ; +//bard 7-5 s +static const struct snd_kcontrol_new rk29_controls[] = { + SOC_DAPM_PIN_SWITCH("Mic Jack"), + SOC_DAPM_PIN_SWITCH("Ext Spk"), + SOC_DAPM_PIN_SWITCH("Headphone Jack"), +}; +//bard 7-5 e +/* + * Logic for a rt5631 as connected on a rockchip board. + */ +static int rk29_rt5631_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); +//bard 7-5 s + snd_soc_add_codec_controls(codec, rk29_controls, + ARRAY_SIZE(rk29_controls)); +//bard 7-5 e + /* Add specific widgets */ + snd_soc_dapm_new_controls(dapm, rt5631_dapm_widgets, + ARRAY_SIZE(rt5631_dapm_widgets)); + /* Set up specific audio path audio_mapnects */ + snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); +// snd_soc_dapm_nc_pin(dapm, "MONO"); +// snd_soc_dapm_nc_pin(dapm, "MONOIN_RXN"); +// snd_soc_dapm_nc_pin(dapm, "MONOIN_RXP"); + snd_soc_dapm_nc_pin(dapm, "DMIC"); + snd_soc_dapm_sync(dapm); + + return 0; +} + +static struct snd_soc_ops rk29_ops = { + .hw_params = rk29_hw_params, +}; +static struct snd_soc_ops rk29_ops_voice = { + .hw_params = rk29_hw_params_voice, +}; + +static struct snd_soc_dai_link rk29_dai[] = { + { + .name = "RT5631 hifi", + .stream_name = "RT5631 hifi stream", + .codec_name = "RT5631.0-001a", + .platform_name = "rockchip-audio", + #if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", + #elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", + #else + .cpu_dai_name = "rk_i2s.2", + #endif + .codec_dai_name = "RT5631 HiFi", + .init = rk29_rt5631_init, + .ops = &rk29_ops, + }, + { + .name = "RT5631 voice", + .stream_name = "RT5631 voice stream", + .codec_name = "RT5631.0-001a", + .platform_name = "rockchip-audio", + #if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", + #elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", + #else + .cpu_dai_name = "rk_i2s.2", + #endif + .codec_dai_name = "rt5631-voice", + .ops = &rk29_ops_voice, + }, +}; + +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_RT5631", + .dai_link = rk29_dai, + .num_links = 2, +}; + +static struct platform_device *rk29_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) { + printk("platform device allocation failed\n"); + ret = -ENOMEM; + return ret; + } + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + ret = platform_device_add(rk29_snd_device); + if (ret) { + printk("platform device add failed\n"); + platform_device_put(rk29_snd_device); + } + return ret; +} + +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); + diff --git a/sound/soc/rk/rk_rt5639.c b/sound/soc/rk/rk_rt5639.c new file mode 100755 index 000000000000..91d0f49a2659 --- /dev/null +++ b/sound/soc/rk/rk_rt5639.c @@ -0,0 +1,247 @@ +/* + * rk29_rt5625.c -- SoC audio for rockchip + * + * Driver for rockchip rt5625 audio + * + * 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 +#include +#include +#include +#include +#include + +#include "../codecs/rt3261.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" + +#if 1 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +static int rk29_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /*by Vincent Hsiung for EQ Vol Change*/ + #define HW_PARAMS_FLAG_EQVOL_ON 0x21 + #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 + if (codec_dai->driver->ops->hw_params && ((params->flags == HW_PARAMS_FLAG_EQVOL_ON) || (params->flags == HW_PARAMS_FLAG_EQVOL_OFF))) + { + ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + } else { + + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #endif + if (ret < 0) + return ret; + + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_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_RK_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: + DBG("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)); + + /*Set the system clk for codec*/ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); + if (ret < 0) + { + DBG("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); + return ret; + } + + 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 int rt3261_voice_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* set codec DAI configuration */ + //#if defined (CONFIG_SND_CODEC_SOC_SLAVE) + DBG("Enter::%s----codec slave\n",__FUNCTION__); + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | + SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS); + /*#endif + //#if defined (CONFIG_SND_CODEC_SOC_MASTER) + DBG("Enter::%s----codec master\n",__FUNCTION__); + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | + SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #endif*/ + + 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: + DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params)); + return -EINVAL; + break; + } + + //snd_soc_dai_set_pll(codec_dai, RT5625_PLL_MCLK_TO_VSYSCLK, 0, pll_out, 24576000);??????? + + /*Set the system clk for codec*/ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, 24576000, SND_SOC_CLOCK_IN); + + if (ret < 0) { + printk("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); + return ret; + } + + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + + return 0; +} + +static struct snd_soc_ops rk29_ops = { + .hw_params = rk29_hw_params, +}; + +static struct snd_soc_ops rt5639_voice_ops = { + .hw_params = rt3261_voice_hw_params, +}; + +static struct snd_soc_dai_link rk29_dai[] = { + { + .name = "RT5639 I2S1", + .stream_name = "RT5639 PCM", + .codec_name = "rt5639.0-001c", + .platform_name = "rockchip-audio", + .cpu_dai_name = "rk_i2s.0", + .codec_dai_name = "rt5639-aif1", + .ops = &rk29_ops, + }, + { + .name = "RT5639 I2S2", + .stream_name = "RT5639 PCM", + .codec_name = "rt5639.0-001c", + .platform_name = "rockchip-audio", + .cpu_dai_name = "rk_i2s.0", + .codec_dai_name = "rt5639-aif2", + .ops = &rt5639_voice_ops, + }, +}; + +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_RT5639", + .dai_link = rk29_dai, + .num_links = 2, +}; + +static struct platform_device *rk29_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) { + printk("platform device allocation failed\n"); + return -ENOMEM; + } + + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + ret = platform_device_add(rk29_snd_device); + if (ret) { + printk("platform device add failed\n"); + + platform_device_put(rk29_snd_device); + return ret; + } + + return ret; +} + +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk/rk_rt5640.c b/sound/soc/rk/rk_rt5640.c new file mode 100755 index 000000000000..6756f33fb84f --- /dev/null +++ b/sound/soc/rk/rk_rt5640.c @@ -0,0 +1,327 @@ +/* + * rk29_rt3261.c -- SoC audio for rockchip + * + * Driver for rockchip rt3261 audio + * + * 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 +#include +#include +#include +#include +#include + +#include "../codecs/rt3261.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" + + +#if 0 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +static int rk29_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /*by Vincent Hsiung for EQ Vol Change*/ + #define HW_PARAMS_FLAG_EQVOL_ON 0x21 + #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 + if (codec_dai->driver->ops->hw_params && ((params->flags == HW_PARAMS_FLAG_EQVOL_ON) || (params->flags == HW_PARAMS_FLAG_EQVOL_OFF))) + { + ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + } else { + + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #endif + if (ret < 0) + return ret; + + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_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_RK_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: + DBG("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)); + + /*Set the system clk for codec*/ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); + if (ret < 0) + { + DBG("rk29_hw_params_rt3261:failed to set the sysclk for codec side\n"); + return ret; + } + + 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 int rt3261_voice_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | + SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS ); + + 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: + DBG("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)); + + /*Set the system clk for codec*/ + snd_soc_dai_set_pll(codec_dai, 0, RT3261_PLL1_S_MCLK, pll_out, 24576000); + + ret = snd_soc_dai_set_sysclk(codec_dai, RT3261_SCLK_S_PLL1, 24576000, SND_SOC_CLOCK_IN); + + + if (ret < 0) { + printk("rk29_hw_params_rt3261:failed to set the sysclk for codec side\n"); + return ret; + } + + 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 const struct snd_soc_dapm_widget rt3261_dapm_widgets[] = { + SND_SOC_DAPM_MIC("Mic Jack", NULL), + SND_SOC_DAPM_MIC("Headset Jack", NULL), + SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_HP("Headphone Jack", NULL), +}; + +static const struct snd_soc_dapm_route audio_map[]={ + + /* Mic Jack --> MIC_IN*/ + {"micbias1", NULL, "Mic Jack"}, + {"MIC1", NULL, "micbias1"}, + + // HP MIC + {"micbias1", NULL, "Headset Jack"}, + {"MIC3", NULL, "micbias1"}, + + {"Ext Spk", NULL, "SPOLP"}, + {"Ext Spk", NULL, "SPOLN"}, + {"Ext Spk", NULL, "SPORP"}, + {"Ext Spk", NULL, "SPORN"}, + + {"Headphone Jack", NULL, "HPOL"}, + {"Headphone Jack", NULL, "HPOR"}, +} ; + +static const struct snd_kcontrol_new rk_controls[] = { + SOC_DAPM_PIN_SWITCH("Mic Jack"), + SOC_DAPM_PIN_SWITCH("Headset Jack"), + SOC_DAPM_PIN_SWITCH("Ext Spk"), + SOC_DAPM_PIN_SWITCH("Headphone Jack"), +}; + +/* + * Logic for a rt3261 as connected on a rockchip board. + */ +static int rk29_rt3261_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + snd_soc_add_codec_controls(codec, rk_controls, + ARRAY_SIZE(rk_controls)); + + /* Add specific widgets */ + snd_soc_dapm_new_controls(dapm, rt3261_dapm_widgets, + ARRAY_SIZE(rt3261_dapm_widgets)); + /* Set up specific audio path audio_mapnects */ + snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + + snd_soc_dapm_enable_pin(dapm, "Mic Jack"); + snd_soc_dapm_enable_pin(dapm, "Headset Jack"); + snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); +#ifdef CONFIG_HDMI + extern int hdmi_is_insert(void); + extern void codec_set_spk(bool on); + if(hdmi_is_insert()) + codec_set_spk(false); +#endif + +#ifdef CONFIG_HDMI_RK30 + extern int hdmi_get_hotplug(void); + if(hdmi_get_hotplug() == 2/*HDMI_HPD_ACTIVED*/) + codec_set_spk(false); +#endif + + snd_soc_dapm_sync(dapm); + + return 0; +} + +static struct snd_soc_ops rk29_ops = { + .hw_params = rk29_hw_params, +}; + +static struct snd_soc_ops rt3261_voice_ops = { + .hw_params = rt3261_voice_hw_params, +}; + +static struct snd_soc_dai_link rk29_dai[] = { + { + .name = "RT5640 I2S1", + .stream_name = "RT5640 PCM", + .codec_name = "rt5640.0-001c", + .platform_name = "rockchip-audio", + #if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.1", + #elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", + #endif + .codec_dai_name = "rt5640-aif1", + .init = rk29_rt3261_init, + .ops = &rk29_ops, + }, + { + .name = "RT5640 I2S2", + .stream_name = "RT5640 PCM", + .codec_name = "rt5640.0-001c", + .platform_name = "rockchip-audio", + #if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.1", + #elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", + #endif + .codec_dai_name = "rt5640-aif2", + .ops = &rt3261_voice_ops, + }, +}; + +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_RT5640", + .dai_link = rk29_dai, + .num_links = 2, +}; + +static struct platform_device *rk29_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) { + printk("platform device allocation failed\n"); + return -ENOMEM; + } + + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + ret = platform_device_add(rk29_snd_device); + if (ret) { + printk("platform device add failed\n"); + + platform_device_put(rk29_snd_device); + return ret; + } + + return ret; +} + +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk/rk_spdif.c b/sound/soc/rk/rk_spdif.c new file mode 100755 index 000000000000..22387735399c --- /dev/null +++ b/sound/soc/rk/rk_spdif.c @@ -0,0 +1,483 @@ +/*$_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 "rk_pcm.h" + +#if 0 +#define RK_SPDIF_DBG(x...) printk(KERN_INFO "rk_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); + + 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); + + /* 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_I2S_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); +err0: + 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/rk/rk_wm8900.c b/sound/soc/rk/rk_wm8900.c new file mode 100755 index 000000000000..68f60a360b2d --- /dev/null +++ b/sound/soc/rk/rk_wm8900.c @@ -0,0 +1,301 @@ +/* + * rk29_wm8900.c -- SoC audio for rockchip + * + * Driver for rockchip wm8900 audio + * + * 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 +#include +#include +#include +#include +#include +#include +#include "../codecs/wm8900.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" +#include + +#if 0 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +static int rk29_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; +#else + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; +#endif + unsigned int pll_out = 0; + int div_bclk,div_mclk; + int ret; + struct clk *general_pll; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /*by Vincent Hsiung for EQ Vol Change*/ + #define HW_PARAMS_FLAG_EQVOL_ON 0x21 + #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 + if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) + { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent +#else + ret = codec_dai->ops->hw_params(substream, params, codec_dai); //by Vincent +#endif + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + } + else + { + + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #endif + if (ret < 0) + return ret; + + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_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_RK_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: + DBG("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)); + + //pll_out = 12000000; + //snd_soc_dai_set_pll(codec_dai, NULL, 12000000, pll_out); + snd_soc_dai_set_clkdiv(codec_dai, WM8900_LRCLK_MODE, 0x000); + + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + snd_soc_dai_set_clkdiv(codec_dai, WM8900_BCLK_DIV, WM8900_BCLK_DIV_4); + snd_soc_dai_set_clkdiv(codec_dai, WM8900_DAC_LRCLK,(pll_out/4)/params_rate(params)); + snd_soc_dai_set_clkdiv(codec_dai, WM8900_ADC_LRCLK,(pll_out/4)/params_rate(params)); + #endif + + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + general_pll=clk_get(NULL, "general_pll"); + if(clk_get_rate(general_pll)>260000000) + { + div_bclk=(pll_out/4)/params_rate(params)-1; + div_mclk=3; + } + else if(clk_get_rate(general_pll)>130000000) + { + div_bclk=(pll_out/2)/params_rate(params)-1; + div_mclk=1; + } + else + { + pll_out=pll_out/4; + div_bclk=(pll_out)/params_rate(params)-1; + div_mclk=0; + } + DBG("func is%s,gpll=%ld,pll_out=%u,div_mclk=%d\n", + __FUNCTION__,clk_get_rate(general_pll),pll_out,div_mclk); + snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); + #endif + DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); + + return 0; +} + +static const struct snd_soc_dapm_widget wm8900_dapm_widgets[] = { + SND_SOC_DAPM_LINE("Audio Out", NULL), + SND_SOC_DAPM_LINE("Line in", NULL), + SND_SOC_DAPM_MIC("Micn", NULL), + SND_SOC_DAPM_MIC("Micp", NULL), +}; + +static const struct snd_soc_dapm_route audio_map[]= { + + {"Audio Out", NULL, "HP_L"}, + {"Audio Out", NULL, "HP_R"}, + {"Line in", NULL, "RINPUT1"}, + {"Line in", NULL, "LINPUT1"}, + {"Micn", NULL, "RINPUT2"}, + {"Micp", NULL, "LINPUT2"}, +}; + +/* + * Logic for a wm8900 as connected on a rockchip board. + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) +static int rk29_wm8900_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* Add specific widgets */ + snd_soc_dapm_new_controls(dapm, wm8900_dapm_widgets, + ARRAY_SIZE(wm8900_dapm_widgets)); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /* Set up specific audio path audio_mapnects */ + snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + snd_soc_dapm_nc_pin(dapm, "HP_L"); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + snd_soc_dapm_nc_pin(dapm, "HP_R"); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + snd_soc_dapm_sync(dapm); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + return 0; +} +#else +static int rk29_wm8900_init(struct snd_soc_codec *codec) +{ + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* Add specific widgets */ + snd_soc_dapm_new_controls(codec, wm8900_dapm_widgets, + ARRAY_SIZE(wm8900_dapm_widgets)); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /* Set up specific audio path audio_mapnects */ + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + snd_soc_dapm_nc_pin(codec, "HP_L"); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + snd_soc_dapm_nc_pin(codec, "HP_R"); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + snd_soc_dapm_sync(codec); + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + return 0; +} +#endif + +static struct snd_soc_ops rk29_ops = { + .hw_params = rk29_hw_params, +}; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) +static struct snd_soc_dai_link rk29_dai = { + .name = "WM8900", + .stream_name = "WM8900 PCM", + .codec_name = "WM8900.0-001a", + .platform_name = "rockchip-audio", + .cpu_dai_name = "rk_i2s.0", + .codec_dai_name = "WM8900 HiFi", + .init = rk29_wm8900_init, + .ops = &rk29_ops, +}; +#else +static struct snd_soc_dai_link rk29_dai = { + .name = "WM8900", + .stream_name = "WM8900 PCM", + .cpu_dai = &rk29_i2s_dai[0], + .codec_dai = &wm8900_dai, + .init = rk29_wm8900_init, + .ops = &rk29_ops, +}; +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_WM8900", + .dai_link = &rk29_dai, + .num_links = 1, +}; +#else +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_WM8900", + .platform = &rk29_soc_platform, + .dai_link = &rk29_dai, + .num_links = 1, +}; + + +static struct snd_soc_card rk29_snd_devdata = { + .card = &snd_soc_card_rk29, + .codec_dev = &soc_codec_dev_wm8900, +}; +#endif + +static struct platform_device *rk29_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) { + DBG("platform device allocation failed\n"); + ret = -ENOMEM; + return ret; + } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); +#else + platform_set_drvdata(rk29_snd_device, &rk29_snd_devdata); + rk29_snd_devdata.dev = &rk29_snd_device->dev; +#endif + ret = platform_device_add(rk29_snd_device); + if (ret) { + DBG("platform device add failed\n"); + platform_device_put(rk29_snd_device); + } + return ret; +} + +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk/rk_wm8988.c b/sound/soc/rk/rk_wm8988.c new file mode 100755 index 000000000000..dadc25340a67 --- /dev/null +++ b/sound/soc/rk/rk_wm8988.c @@ -0,0 +1,190 @@ +/* + * rk29_wm8988.c -- SoC audio for rockchip + * + * Driver for rockchip wm8988 audio + * + * 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 +#include +#include +#include +#include +#include +#include +#include "../codecs/wm8988.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" + +#include + +#if 0 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +//static void *rk29_speaker = NULL; + +static int rk29_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + /*by Vincent Hsiung for EQ Vol Change*/ + #define HW_PARAMS_FLAG_EQVOL_ON 0x21 + #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 + if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) + { + ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + } + else + { + /* set codec DAI configuration */ + #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + #endif + #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); + #endif + if (ret < 0) + return ret; + /* set cpu DAI configuration */ + #if defined (CONFIG_SND_RK_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_RK_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; + } + + return 0; +} + +static const struct snd_soc_dapm_widget rk29_dapm_widgets[] = { + SND_SOC_DAPM_LINE("Audio Out", NULL), + SND_SOC_DAPM_LINE("Line in", NULL), + SND_SOC_DAPM_MIC("Micn", NULL), + SND_SOC_DAPM_MIC("Micp", NULL), +}; + +static const struct snd_soc_dapm_route audio_map[]= { + + {"Audio Out", NULL, "LOUT1"}, + {"Audio Out", NULL, "ROUT1"}, + {"Line in", NULL, "RINPUT1"}, + {"Line in", NULL, "LINPUT1"}, + {"Micn", NULL, "RINPUT2"}, + {"Micp", NULL, "LINPUT2"}, +}; + +/* + * Logic for a wm8988 as connected on a rockchip board. + */ +static int rk29_wm8988_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + int ret; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + ret = snd_soc_dai_set_sysclk(codec_dai, 0, + /*12000000*/11289600, SND_SOC_CLOCK_IN); + if (ret < 0) { + printk(KERN_ERR "Failed to set WM8988 SYSCLK: %d\n", ret); + return ret; + } + + /* Add specific widgets */ + snd_soc_dapm_new_controls(dapm, rk29_dapm_widgets, + ARRAY_SIZE(rk29_dapm_widgets)); + //snd_soc_dapm_nc_pin(codec, "LOUT2"); + //snd_soc_dapm_nc_pin(codec, "ROUT2"); + + /* Set up specific audio path audio_mapnects */ + snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + + snd_soc_dapm_sync(dapm); + + return 0; +} + +static struct snd_soc_ops rk29_ops = { + .hw_params = rk29_hw_params, +}; + +static struct snd_soc_dai_link rk29_dai = { + .name = "WM8988", + .stream_name = "WM8988 PCM", + .codec_name = "WM8988.0-001a", + .platform_name = "rockchip-audio", + .cpu_dai_name = "rk_i2s.0", + .codec_dai_name = "WM8988 HiFi", + .init = rk29_wm8988_init, + .ops = &rk29_ops, +}; + +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_WM8988", + .dai_link = &rk29_dai, + .num_links = 1, +}; + +static struct platform_device *rk29_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; + + //rk29_speaker = rk29_speaker_init(RK29_PIN6_PB6, GPIO_HIGH, 2, (200*1000*1000)); + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) { + DBG("platform device allocation failed\n"); + ret = -ENOMEM; + return ret; + } + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + ret = platform_device_add(rk29_snd_device); + if (ret) { + DBG("platform device add failed\n"); + platform_device_put(rk29_snd_device); + return ret; + } + + return ret; +} +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device); + //rk29_speaker_deinit(rk29_speaker); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk/rk_wm8994.c b/sound/soc/rk/rk_wm8994.c new file mode 100755 index 000000000000..df0a8e65c17a --- /dev/null +++ b/sound/soc/rk/rk_wm8994.c @@ -0,0 +1,450 @@ +/* + * rk29_wm8994.c -- SoC audio for rockchip + * + * Driver for rockchip wm8994 audio + * Copyright (C) 2009 lhh + * + * 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 +#include +#include +#include +#include +#include +#include "../codecs/wm8994.h" +#include "rk_pcm.h" +#include "rk29_i2s.h" +#include + +#if 0 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +static int rk29_aif1_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int div_bclk,div_mclk; + int ret; + struct clk *general_pll; + + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* set codec DAI configuration */ +#if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + DBG("Set codec_dai slave\n"); + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); +#endif +#if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + DBG("Set codec_dai master\n"); +#endif + if (ret < 0) + return ret; + + /* set cpu DAI configuration */ +#if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) + DBG("Set cpu_dai master\n"); + 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_RK_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); + DBG("Set cpu_dai slave\n"); +#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: + DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + return -EINVAL; + } + +// DBG("Enter:%s, %d, rate=%d,pll_out = %d\n",__FUNCTION__,__LINE__,params_rate(params),pll_out); +#ifdef CONFIG_ARCH_RK29 + general_pll=clk_get(NULL, "general_pll"); + if(clk_get_rate(general_pll)>260000000) + { + div_bclk=(pll_out/4)/params_rate(params)-1; + div_mclk=3; + } + else if(clk_get_rate(general_pll)>130000000) + { + div_bclk=(pll_out/2)/params_rate(params)-1; + div_mclk=1; + } + else + {//96M + pll_out=pll_out/4; + div_bclk=(pll_out)/params_rate(params)-1; + div_mclk=0; + } +#else + div_bclk=(pll_out/4)/params_rate(params)-1; + div_mclk=3; +#endif + + DBG("func is%s,gpll=%ld,pll_out=%d,div_mclk=%d\n",__FUNCTION__,clk_get_rate(general_pll),pll_out,div_mclk); + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + if(ret < 0) + { + DBG("rk29_hw_params_wm8994:failed to set the cpu sysclk for codec side\n"); + return ret; + } + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); + DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); + + if(div_mclk== 3) + {//MCLK == 11289600 or 12288000 + ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK1, pll_out, 0); + if (ret < 0) { + DBG("rk29_hw_params_wm8994:failed to set the sysclk for codec side\n"); + return ret; + } + } + else + { + /* set the codec FLL */ + ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1, pll_out, + params_rate(params) * 256); + if (ret < 0) + { + printk("%s: snd_soc_dai_set_pll err =%d\n",__FUNCTION__,ret); + return ret; + } + /* set the codec system clock */ + ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, + params_rate(params) * 256, SND_SOC_CLOCK_IN); + if (ret < 0) + { + printk("%s: snd_soc_dai_set_sysclk err =%d\n",__FUNCTION__,ret); + return ret; + } + } + + return 0; +} + +static int rk29_aif2_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 *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + unsigned int pll_out = 0; + int div_bclk,div_mclk; + int ret; + struct clk *general_pll; + + //change to 8Khz +// params->intervals[SNDRV_PCM_HW_PARAM_RATE - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].min = 8000; + + DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + +// if (params_rate(params) != 8000) +// return -EINVAL; + + /* set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | + SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM); + if (ret < 0) + { + printk("%s: snd_soc_dai_set_fmt err =%d\n",__FUNCTION__,ret); + 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: + DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); + return -EINVAL; + } + + general_pll=clk_get(NULL, "general_pll"); + if(clk_get_rate(general_pll)>260000000) + { + div_bclk=(pll_out/4)/params_rate(params)-1; + div_mclk=3; + } + else if(clk_get_rate(general_pll)>130000000) + { + div_bclk=(pll_out/2)/params_rate(params)-1; + div_mclk=1; + } + else + {//96M + pll_out=pll_out/4; + div_bclk=(pll_out)/params_rate(params)-1; + div_mclk=0; + } + + DBG("func is%s,gpll=%ld,pll_out=%d,div_mclk=%d\n", + __FUNCTION__,clk_get_rate(general_pll),pll_out,div_mclk); + + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); + if(ret < 0) + { + DBG("rk29_hw_params_wm8994:failed to set the cpu sysclk for codec side\n"); + return ret; + } + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk); + snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); + DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); + + /* set the codec FLL */ + ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, WM8994_FLL_SRC_MCLK1, pll_out, + 8000 * 256); + if (ret < 0) + { + printk("%s: snd_soc_dai_set_pll err =%d\n",__FUNCTION__,ret); + return ret; + } + /* set the codec system clock */ + ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2, + 8000 * 256, SND_SOC_CLOCK_IN); + if (ret < 0) + { + printk("%s: snd_soc_dai_set_sysclk err =%d\n",__FUNCTION__,ret); + return ret; + } + + return ret; +} + + +static const struct snd_soc_dapm_widget rk29_dapm_widgets[] = { + SND_SOC_DAPM_SPK("Ext Left Spk", NULL), + SND_SOC_DAPM_SPK("Ext Right Spk", NULL), + SND_SOC_DAPM_SPK("Ext Rcv", NULL), + SND_SOC_DAPM_HP("Headset Stereophone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Main Mic", NULL), + SND_SOC_DAPM_MIC("2nd Mic", NULL), +// SND_SOC_DAPM_LINE("Radio In", NULL), + SND_SOC_DAPM_LINE("Line In", NULL), + SND_SOC_DAPM_LINE("Line Out", NULL), + +}; + +static const struct snd_soc_dapm_route rk29_dapm_routes[] = { + {"Ext Left Spk", NULL, "SPKOUTLP"}, + {"Ext Left Spk", NULL, "SPKOUTLN"}, + + {"Ext Right Spk", NULL, "SPKOUTRP"}, + {"Ext Right Spk", NULL, "SPKOUTRN"}, + + {"Ext Rcv", NULL, "HPOUT2N"}, + {"Ext Rcv", NULL, "HPOUT2P"}, + + {"Headset Stereophone", NULL, "HPOUT1L"}, + {"Headset Stereophone", NULL, "HPOUT1R"}, + + {"IN1LN", NULL, "Headset Mic"}, + {"IN1LP", NULL, "Headset Mic"}, + + {"IN1LN", NULL, "2nd Mic"}, + {"IN1LP", NULL, "2nd Mic"}, + + {"IN1RN", NULL, "Main Mic"}, + {"IN1RP", NULL, "Main Mic"}, + +// {"IN2LN", NULL, "Radio In"}, +// {"IN2RN", NULL, "Radio In"}, + + {"IN2LP:VXRN", NULL, "Line In"}, + {"IN2RP:VXRP", NULL, "Line In"}, + + {"Line Out", NULL, "LINEOUT1N"}, + {"Line Out", NULL, "LINEOUT1P"}, + +}; + +static int rk29_wm8994_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; +// int ret; + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + /* add goni specific widgets */ + snd_soc_dapm_new_controls(dapm, rk29_dapm_widgets, + ARRAY_SIZE(rk29_dapm_widgets)); + + /* set up goni specific audio routes */ + snd_soc_dapm_add_routes(dapm, rk29_dapm_routes, + ARRAY_SIZE(rk29_dapm_routes)); + + /* set endpoints to not connected */ +// snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN"); +// snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP"); + snd_soc_dapm_nc_pin(dapm, "IN2LN"); + snd_soc_dapm_nc_pin(dapm, "IN2RN"); +// snd_soc_dapm_nc_pin(dapm, "LINEOUT1N"); +// snd_soc_dapm_nc_pin(dapm, "LINEOUT1P"); + snd_soc_dapm_nc_pin(dapm, "LINEOUT2N"); + snd_soc_dapm_nc_pin(dapm, "LINEOUT2P"); +#ifdef CONFIG_HDMI +extern int hdmi_is_insert(void); +extern void codec_set_spk(bool on); + if(hdmi_is_insert()) + codec_set_spk(false); +#endif + snd_soc_dapm_sync(dapm); + + /* Headset jack detection */ +/* ret = snd_soc_jack_new(codec, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT, + &jack); + if (ret) + return ret; + + ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins); + if (ret) + return ret; + + ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios); + if (ret) + return ret; +*/ + return 0; +} + + +static struct snd_soc_ops rk29_aif1_ops = { + .hw_params = rk29_aif1_hw_params, +}; + +static struct snd_soc_ops rk29_aif2_ops = { + .hw_params = rk29_aif2_hw_params, +}; + +static struct snd_soc_dai_driver voice_dai = { + .name = "rk29-voice-dai", + .id = 0, + .playback = { + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, +}; + +static struct snd_soc_dai_link rk29_dai[] = { + { + .name = "WM8994 I2S1", + .stream_name = "WM8994 PCM", + .codec_name = "wm8994-codec", + .platform_name = "rockchip-audio", +#if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", +#elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", +#endif + .codec_dai_name = "wm8994-aif1", + .ops = &rk29_aif1_ops, + .init = rk29_wm8994_init, + }, + { + .name = "WM8994 I2S2", + .stream_name = "WM8994 PCM", + .codec_name = "wm8994-codec", + .platform_name = "rockchip-audio", +#if defined(CONFIG_SND_RK_SOC_I2S_8CH) + .cpu_dai_name = "rk_i2s.0", +#elif defined(CONFIG_SND_RK_SOC_I2S_2CH) + .cpu_dai_name = "rk_i2s.1", +#endif + .codec_dai_name = "wm8994-aif2", + .ops = &rk29_aif2_ops, + }, +}; + +static struct snd_soc_card snd_soc_card_rk29 = { + .name = "RK_WM8994", + .dai_link = rk29_dai, + .num_links = ARRAY_SIZE(rk29_dai), +}; + +static struct platform_device *rk29_snd_device; + +static int __init audio_card_init(void) +{ + int ret =0; + + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + rk29_snd_device = platform_device_alloc("soc-audio", -1); + if (!rk29_snd_device) { + printk("platform device allocation failed\n"); + return -ENOMEM; + } + + platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); + ret = platform_device_add(rk29_snd_device); + if (ret) { + printk("platform device add failed\n"); + // snd_soc_unregister_dai(&rk29_snd_device->dev); + platform_device_put(rk29_snd_device); + return ret; + } + + return ret; +} + +static void __exit audio_card_exit(void) +{ + platform_device_unregister(rk29_snd_device); +} + +module_init(audio_card_init); +module_exit(audio_card_exit); +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk29/Kconfig b/sound/soc/rk29/Kconfig deleted file mode 100755 index 8a5ce5fd32e4..000000000000 --- a/sound/soc/rk29/Kconfig +++ /dev/null @@ -1,359 +0,0 @@ -config SND_RK29_SOC - tristate "SoC Audio for the Rockchip System-on-Chip" - depends on PLAT_RK && SND_SOC - help - Say Y or M if you want to add support for codecs attached to - the ROCKCHIP IIS interface. You will also need - to select the audio interfaces to support below. - -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 - depends on SND_RK29_SOC_I2S && !ARCH_RK3066B && !ARCH_RK3188 && !ARCH_RK319X - help - This supports the use of the 8 Channel I2S interface on rk29 processors. - -if SND_RK29_SOC_I2S_8CH -choice - bool "Set I2S0 using the number of channels" - default SND_I2SO_USE_DOUBLE_CHANNELS - config SND_I2SO_USE_EIGHT_CHANNELS - tristate "I2S0 use 8 channels" - - config SND_I2SO_USE_DOUBLE_CHANNELS - tristate "I2S0 use 2 channels" -endchoice -endif - -config SND_RK29_SOC_I2S_2CH - bool "Soc RK29 I2S 2 Channel support(I2S1)" - depends on SND_RK29_SOC_I2S && !ARCH_RK2928 && !ARCH_RK3026 - default y if (ARCH_RK3066B || ARCH_RK3188) - help - This supports the use of the 2 Channel I2S interface on rk29 processors. - -choice - bool "Set I2S GRF Output Voltage" - depends on (ARCH_RK3066B || ARCH_RK3188) && SND_RK29_SOC_I2S_2CH - default SND_I2S_USE_33V - - config SND_I2S_USE_33V - bool "I2S use 3.3V" - - config SND_I2S_USE_18V - bool "I2S use 1.8V" -endchoice - -config SND_RK_SOC_I2S2_2CH - bool "Soc RK29 I2S 2 Channel support(I2S2)" - default n - depends on SND_RK29_SOC_I2S && ARCH_RK30 && !ARCH_RK2928 && !ARCH_RK3066B && !ARCH_RK3026 - help - This supports the use of the 2 Channel I2S2 interface on rk30 processors. - -if SND_RK29_SOC_I2S_2CH || SND_RK29_SOC_I2S_8CH || SND_RK_SOC_I2S2_2CH -choice - bool "Set i2s on DMA event mode" - default SND_I2S_DMA_EVENT_STATIC - config SND_I2S_DMA_EVENT_DYNAMIC - tristate "dynamic mode" - - config SND_I2S_DMA_EVENT_STATIC - tristate "static mode" -endchoice -endif - -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 - depends on !RK616_USE_MCLK_12M || !SND_RK_SOC_RK616 - 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_AK4396 - tristate "SoC I2S Audio support for rockchip - AK4396" - depends on SND_RK29_SOC - select SND_RK29_SOC_I2S - select SND_SOC_AK4396 - help - Say Y if you want to add support for SoC audio on rockchip - with the AK4396. - -config SND_RK29_SOC_ES8323 - tristate "SoC I2S Audio support for rockchip - ES8323" - depends on SND_RK29_SOC - select SND_RK29_SOC_I2S - select SND_SOC_ES8323 - help - Say Y if you want to add support for SoC audio on rockchip - with the ES8323. - -config SND_SOC_ES8323_PCM - tristate "SoC I2S Audio support for rockchip - ES8323 for PCM modem" - depends on SND_RK29_SOC - help - Say Y if you want to add support for SoC audio on rockchip - with the ES8323 for PCM modem. - -config SND_RK29_SOC_WM8988 - tristate "SoC I2S Audio support for rockchip - WM8988" - depends on SND_RK29_SOC - select SND_RK29_SOC_I2S - select SND_SOC_WM8988 - help - Say Y if you want to add support for SoC audio on rockchip - with the WM8988. - -config SND_RK29_SOC_WM8900 - tristate "SoC I2S Audio support for rockchip - WM8900" - depends on SND_RK29_SOC - select SND_RK29_SOC_I2S - select SND_SOC_WM8900 - help - Say Y if you want to add support for SoC audio on rockchip - with the WM8900. - -config SND_RK29_SOC_RT5512 - tristate "SoC I2S Audio support for rockchip - RICHTEK5512" - depends on SND_RK29_SOC - select SND_SOC_RT5512 - select SND_RK29_SOC_I2S - help - Say Y if you want to add support for SoC audio on the rockchip. - -config SND_RK29_SOC_CX2070X - tristate "SoC I2S Audio support for rockchip - CX2070X" - depends on SND_RK29_SOC - select SND_SOC_CX2070X - select SND_RK29_SOC_I2S - help - Say Y if you want to add support for SoC audio on the rockchip. - -config SND_RK29_SOC_RT5621 - tristate "SoC I2S Audio support for rockchip - rt5621" - depends on SND_RK29_SOC - select SND_RK29_SOC_I2S - select SND_SOC_RT5621 - help - Say Y if you want to add support for SoC audio on rockchip - with the rt5621. -config SND_RK29_SOC_RT5623 - tristate "SoC I2S Audio support for rockchip - rt5623" - depends on SND_RK29_SOC - select SND_RK29_SOC_I2S - select SND_SOC_RT5623 - help - Say Y if you want to add support for SoC audio on rockchip - with the rt5623. - -config SND_RK29_SOC_RT5631 - tristate "SoC I2S Audio support for rockchip - RT5631" - depends on SND_RK29_SOC - select SND_RK29_SOC_I2S - select SND_SOC_RT5631 - help - Say Y if you want to add support for SoC audio on rockchip - with the RT5631. - -config SND_RK29_SOC_RT5631_PHONE - tristate "SoC I2S Audio support for rockchip(phone) - RT5631" - depends on SND_RK29_SOC - select SND_RK29_SOC_I2S - select SND_SOC_RT5631_PHONE - help - Say Y if you want to add support for SoC audio on rockchip - with the RT5631. - Driver code to use on the phone or voice Tablet. - -config SND_RK29_SOC_RT5625 - tristate "SoC I2S Audio support for rockchip - RT5625" - depends on SND_RK29_SOC - select SND_RK29_SOC_I2S - help - Say Y if you want to add support for SoC audio on rockchip - with the RT5625. - -choice - depends on SND_RK29_SOC_RT5625 - prompt "RT5625 hardware select" - - config SND_SOC_RT5625_SPK_FORM_SPKOUT - bool "spk from spkout" - select SND_SOC_RT5625 - help - if your codec output hardware connect is spk from spkout, choose it - - config SND_SOC_RT5625_SPK_FORM_HPOUT - bool "spk from hpout" - select SND_SOC_RT5625 - help - if your codec output hardware connect is spk from spkout, choose it -endchoice - -config SND_RK29_SOC_RT5640 - tristate "SoC I2S Audio support for rockchip - RT5640(RT5642)" - depends on SND_RK29_SOC - select SND_RK29_SOC_I2S - select SND_SOC_RT5640 - help - RT5640 is pin to pin as RT5642, but not have dsp function. - -config SND_RK29_SOC_RT3224 - tristate "SoC I2S Audio support for rockchip - RT3224" - depends on SND_RK29_SOC - select SND_RK29_SOC_I2S - select SND_SOC_RT3224 - help - RT3224 is pin to pin as RT3261, but not have dsp function. - -config SND_RK29_SOC_RT5639 - tristate "SoC I2S Audio support for rockchip - RT5639" - depends on SND_RK29_SOC - select SND_RK29_SOC_I2S - select SND_SOC_RT5639 - help - rt5639 - -config SND_RK29_SOC_RT5616 - tristate "SoC I2S Audio support for rockchip - RT5616" - depends on SND_RK29_SOC - select SND_RK29_SOC_I2S - select SND_SOC_RT5616 - help - Say Y if you want to add support for SoC audio on rockchip - with the RT5616. - -config SND_RK29_SOC_RT3261 - tristate "SoC I2S Audio support for rockchip - RT3261" - depends on SND_RK29_SOC - select SND_RK29_SOC_I2S - select SND_SOC_RT3261 - help - Say Y if you want to add support for SoC audio on rockchip - with the RT3261. - -config SND_RK29_SOC_WM8994 - tristate "SoC I2S Audio support for rockchip - WM8994" - depends on SND_RK29_SOC && MFD_WM8994 - select SND_RK29_SOC_I2S - select SND_SOC_WM8994 - help - Say Y if you want to add support for SoC audio on rockchip - with the WM8994. - -config SND_RK29_SOC_CS42L52 - tristate "SoC I2S Audio support for rockchip - CS42L52" - depends on SND_RK29_SOC - select SND_RK29_SOC_I2S - select SND_SOC_CS42L52 - help - Say Y if you want to add support for SoC audio on rockchip - with the CS42L52. - -config SND_RK29_SOC_AIC3111 - tristate "SoC I2S Audio support for rockchip - AIC3111" - depends on SND_RK29_SOC - select SND_RK29_SOC_I2S - select SND_SOC_TLV320AIC3111 - help - Say Y if you want to add support for SoC audio on rockchip - with the AIC3111. - -config SND_RK29_SOC_AIC3262 - tristate "SoC I2S Audio support for rockchip - AIC3262" - depends on SND_RK29_SOC - select SND_RK29_SOC_I2S - select SND_SOC_TLV320AIC326X - help - Say Y if you want to add support for SoC audio on rockchip - with the AIC3262. - -config SND_RK29_SOC_RK1000 - tristate "SoC I2S Audio support for rockchip - RK1000" - depends on SND_RK29_SOC - select SND_RK29_SOC_I2S - select SND_SOC_RK1000 - help - Say Y if you want to add support for SoC audio on rockchip - with the RK1000. - -config SND_RK29_SOC_RK610 - tristate "SoC I2S Audio support for rockchip - RK610" - depends on SND_RK29_SOC && MFD_RK610 - select SND_RK29_SOC_I2S - select SND_SOC_RK610 - help - Say Y if you want to add support for SoC audio on rockchip - with the RK610(JETTA). - -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 - select SND_SOC_RK616 - help - Say Y if you want to add support for SoC audio on rockchip - with the RK616(JETTA). - -config SND_RK_SOC_RK2928 - tristate "SoC I2S Audio support for rockchip - RK2928" - depends on SND_RK29_SOC && ARCH_RK2928 - select SND_RK29_SOC_I2S - select SND_SOC_RK2928 - select SND_RK29_CODEC_SOC_SLAVE - help - Say Y if you want to add support for SoC audio on rockchip - with the RK2928 internal codec. - -config SND_RK_SOC_RK3026 - tristate "SoC I2S Audio support for rockchip - RK3026&R3028A" - depends on SND_RK29_SOC && ARCH_RK3026 - select SND_RK29_SOC_I2S - select SND_SOC_RK3026 - select SND_RK29_CODEC_SOC_SLAVE - help - Say Y if you want to add support for SoC audio on rockchip - with the RK3026 internal codec. - -if SND_RK29_SOC_I2S_2CH || SND_RK29_SOC_I2S_8CH || SND_RK_SOC_I2S2_2CH -choice - bool "Set i2s type" - default SND_RK29_CODEC_SOC_SLAVE - config SND_RK29_CODEC_SOC_MASTER - tristate "Codec run in Master" - - config SND_RK29_CODEC_SOC_SLAVE - tristate "Codec run in Slave" -endchoice - -config ADJUST_VOL_BY_CODEC - bool "Adjust volume by codec" - default n - help - adjust volume by codec - -config PHONE_INCALL_IS_SUSPEND - bool "Incalling Whether suspend codec" - default n - help - set "y" phone incall status cannot into suspend codec - -endif - diff --git a/sound/soc/rk29/Makefile b/sound/soc/rk29/Makefile deleted file mode 100755 index 88fec2ee7f83..000000000000 --- a/sound/soc/rk29/Makefile +++ /dev/null @@ -1,67 +0,0 @@ -# ROCKCHIP Platform Support -snd-soc-rockchip-objs := rk29_pcm.o -ifdef CONFIG_ARCH_RK29 -snd-soc-rockchip-i2s-objs := rk29_i2s.o -else -snd-soc-rockchip-i2s-objs := rk30_i2s.o -endif -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_RK_SOC_SPDIF) += snd-soc-rockchip-spdif.o - -# ROCKCHIP Machine Support -snd-soc-wm8900-objs := rk29_wm8900.o -snd-soc-rt5621-objs := rk29_rt5621.o -snd-soc-rt5631-objs := rk29_rt5631.o -snd-soc-ak4396-objs := rk29_ak4396.o -snd-soc-rt5616-objs := rk29_rt5616.o -snd-soc-rt5631-phone-objs := rk29_rt5631_phone.o -snd-soc-rt5625-objs := rk29_rt5625.o -snd-soc-rt5640-objs := rk29_rt5640.o -snd-soc-rt3261-objs := rk29_rt3261.o -snd-soc-rt3224-objs := rk29_rt3261.o -snd-soc-rt5639-objs := rk29_rt5639.o -snd-soc-cs42l52-objs := rk29_cs42l52.o -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-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-rk3026-objs := rk_rk3026.o -snd-soc-hdmi-i2s-objs := rk_hdmi_i2s.o -snd-soc-hdmi-spdif-objs := rk_hdmi_spdif.o -snd-soc-rt5512-objs := rk29_rt5512.o -snd-soc-cx2070x-objs := rk29_cx2070x.o - -obj-$(CONFIG_SND_RK29_SOC_WM8994) += snd-soc-wm8994.o -obj-$(CONFIG_SND_RK29_SOC_WM8988) += snd-soc-wm8988.o -obj-$(CONFIG_SND_RK29_SOC_WM8900) += snd-soc-wm8900.o -obj-$(CONFIG_SND_RK29_SOC_RT5621) += snd-soc-rt5621.o -obj-$(CONFIG_SND_RK29_SOC_RT5631) += snd-soc-rt5631.o -obj-$(CONFIG_SND_RK29_SOC_AK4396) += snd-soc-ak4396.o -obj-$(CONFIG_SND_RK29_SOC_RT5631_PHONE) += snd-soc-rt5631-phone.o -obj-$(CONFIG_SND_RK29_SOC_RT5625) += snd-soc-rt5625.o -obj-$(CONFIG_SND_RK29_SOC_RT5640) += snd-soc-rt5640.o -obj-$(CONFIG_SND_RK29_SOC_RT3261) += snd-soc-rt3261.o -obj-$(CONFIG_SND_RK29_SOC_RT3224) += snd-soc-rt3224.o -obj-$(CONFIG_SND_RK29_SOC_RT5639) += snd-soc-rt5639.o -obj-$(CONFIG_SND_RK29_SOC_RT5616) += snd-soc-rt5616.o -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_RK610) += snd-soc-rk610.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 -obj-$(CONFIG_SND_RK_SOC_RK3026) += snd-soc-rk3026.o -obj-$(CONFIG_SND_RK29_SOC_RT5512) += snd-soc-rt5512.o -obj-$(CONFIG_SND_RK29_SOC_CX2070X) += snd-soc-cx2070x.o diff --git a/sound/soc/rk29/rk2928-card.c b/sound/soc/rk29/rk2928-card.c deleted file mode 100755 index 412460cb4cdf..000000000000 --- a/sound/soc/rk29/rk2928-card.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * rk2928-card.c -- SoC audio for RockChip RK2928 - * - * - * 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. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ -#include -#include -#include - -#include "rk29_pcm.h" -#include "rk29_i2s.h" - -#ifdef DEBUG -#define DBG(format, ...) \ - printk(KERN_INFO "RK2928 Card: " format "\n", ## __VA_ARGS__) -#else -#define DBG(format, ...) -#endif - -static int rk2928_dai_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 div_bclk,div_mclk; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* set cpu DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - DBG("Set cpu_dai master\n"); - 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); - DBG("Set cpu_dai slave\n"); - #endif - if (ret < 0) - return ret; - - DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); - pll_out = 256 * params_rate(params); - - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - #endif - - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - div_bclk = 63; - div_mclk = pll_out/(params_rate(params)*64) - 1; - - snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk); - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); - #endif - - return 0; -} - -static struct snd_soc_ops rk2928_dai_ops = { - .hw_params = rk2928_dai_hw_params, -}; - -static struct snd_soc_dai_link rk2928_dai[] = { - { - .name = "RK2928", - .stream_name = "RK2928", - .cpu_dai_name = "rk29_i2s.0", - .platform_name = "rockchip-audio", - .codec_name = "rk2928-codec", - .codec_dai_name = "rk2928-codec", - .ops = &rk2928_dai_ops, - }, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_rk2928 = { - .name = "RK2928", - .dai_link = rk2928_dai, - .num_links = ARRAY_SIZE(rk2928_dai), -}; - -static struct platform_device *rk2928_snd_device; - -static int __init rk2928_soc_init(void) -{ - int ret; - - printk(KERN_INFO "RK2928 SoC init\n"); - - rk2928_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk2928_snd_device) { - printk(KERN_ERR "Platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(rk2928_snd_device, &snd_soc_rk2928); - - ret = platform_device_add(rk2928_snd_device); - if (ret) - goto err1; - - return 0; - -err1: - printk(KERN_ERR "Unable to add platform device\n"); - platform_device_put(rk2928_snd_device); - - return ret; -} -module_init(rk2928_soc_init); - -static void __exit rk2928_soc_exit(void) -{ - platform_device_unregister(rk2928_snd_device); -} -module_exit(rk2928_soc_exit); - -MODULE_DESCRIPTION("ALSA SoC RK2928"); -MODULE_LICENSE("GPL"); \ No newline at end of file diff --git a/sound/soc/rk29/rk29_aic3111.c b/sound/soc/rk29/rk29_aic3111.c deleted file mode 100644 index 68311b117077..000000000000 --- a/sound/soc/rk29/rk29_aic3111.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * rk29_tlv320dac3100.c -- SoC audio for rockchip - * - * Driver for rockchip tlv320aic3100 audio - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include "../codecs/tlv320aic3111.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" - -#if 0 -#define AIC_DBG(x...) printk(KERN_INFO x) -#else -#define AIC_DBG(x...) do { } while (0) -#endif - -#ifdef CODECHPDET - #define HP_DET_PIN RK29_PIN6_PA0 -#endif - - - -static int rk29_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int ret; - - AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /*by Vincent Hsiung for EQ Vol Change*/ - #define HW_PARAMS_FLAG_EQVOL_ON 0x21 - #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 - if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) - { - ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); - AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - } - else - { - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - ret = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS); - #endif - - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - ret = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM ); - #endif - - if (ret < 0) - return ret; - - /* 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; - } - AIC_DBG("Enter:%s, %d, rate=%d, pll_out = %d\n",__FUNCTION__,__LINE__,params_rate(params), pll_out); - //pll_out = 12000000; - snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); - - return 0; -} - -static const struct snd_soc_dapm_widget dac3100_dapm_widgets[] = { -/* SND_SOC_DAPM_LINE("Audio Out", NULL), - SND_SOC_DAPM_LINE("Line in", NULL), - SND_SOC_DAPM_MIC("Micn", NULL), - SND_SOC_DAPM_MIC("Micp", NULL),*/ -}; - -static const struct snd_soc_dapm_route audio_map[]= { -/* {"Audio Out", NULL, "HPL"}, - {"Audio Out", NULL, "HPR"}, - {"Line in", NULL, "RINPUT1"}, - {"Line in", NULL, "LINPUT1"}, - {"Micn", NULL, "RINPUT2"}, - {"Micp", NULL, "LINPUT2"},*/ -}; - -/* - * Logic for a tlv320dac3100 as connected on a rockchip board. - */ -static int rk29_aic3111_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* Add specific widgets */ - snd_soc_dapm_new_controls(dapm, dac3100_dapm_widgets, - ARRAY_SIZE(dac3100_dapm_widgets)); - - /* Set up specific audio path audio_mapnects */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - snd_soc_dapm_nc_pin(dapm, "HPL"); - AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - snd_soc_dapm_nc_pin(dapm, "HPR"); - AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - snd_soc_dapm_sync(dapm); - AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - return 0; -} - -static struct snd_soc_ops rk29_ops = { - .hw_params = rk29_hw_params, -}; - -static struct snd_soc_dai_link rk29_dai = { - .name = "AIC3111", - .stream_name = "AIC3111 PCM", - .codec_name = "AIC3111.0-0018", - .platform_name = "rockchip-audio", - .cpu_dai_name = "rk29_i2s.0", - .codec_dai_name = "AIC3111 HiFi", - .init = rk29_aic3111_init, - .ops = &rk29_ops, -}; - -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_AIC3111", - .dai_link = &rk29_dai, - .num_links = 1, -}; - -static struct platform_device *rk29_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; - - AIC_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) { - AIC_DBG("platform device allocation failed\n"); - ret = -ENOMEM; - return ret; - } - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); - ret = platform_device_add(rk29_snd_device); - if (ret) { - AIC_DBG("platform device add failed\n"); - platform_device_put(rk29_snd_device); - } - return ret; -} - -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk29_snd_device); -} - -module_init(audio_card_init); -module_exit(audio_card_exit); -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk29/rk29_aic3262.c b/sound/soc/rk29/rk29_aic3262.c deleted file mode 100644 index 89f30b5f5e21..000000000000 --- a/sound/soc/rk29/rk29_aic3262.c +++ /dev/null @@ -1,539 +0,0 @@ -/* - * rk29_aic3262.c -- SoC audio for rockchip - * - * Driver for rockchip aic3262 audio - * Copyright (C) 2009 lhh - * - * 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. - * - * - */ - -#define DEBUG 1 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include "../codecs/wm8994.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" -#include -#include -#include "../codecs/tlv320aic326x.h" - -#if 0 -#define DBG_AIC3262(x...) printk(KERN_INFO x) -#else -#define DBG_AIC3262(x...) -#endif - -//struct regulator *vddhf_reg=NULL; - -/* Headset jack */ -//static struct snd_soc_jack hs_jack; - -/*Headset jack detection DAPM pins */ -/*static struct snd_soc_jack_pin hs_jack_pins[] = { - { - .pin = "Headset Mic", - .mask = SND_JACK_MICROPHONE, - }, - { - .pin = "Headset Stereophone", - .mask = SND_JACK_HEADPHONE, - }, -}; - -static int spk_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - //struct snd_soc_codec *codec = w->codec; - int ret; - if (SND_SOC_DAPM_EVENT_ON(event)) { - - printk(" I am NULL is %d event is %d\n",vddhf_reg,event); - - if (vddhf_reg) { - ret = regulator_enable(vddhf_reg); - if(ret) { - printk("failed to enable vddhf \n"); - return ret; - } - } - } - else { - - if (vddhf_reg) { - ret = regulator_disable(vddhf_reg); - if (ret) { - printk("failed to disable " - "VDDHF regulator %d\n", ret); - return ret; - } - } - } - return 0; -}*/ - - - -/* rk29 machine DAPM */ -static const struct snd_soc_dapm_widget rk29_aic3262_dapm_widgets[] = { - SND_SOC_DAPM_MIC("Ext Mic", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_HP("Headset Stereophone", NULL), - SND_SOC_DAPM_SPK("Earphone Spk", NULL), - SND_SOC_DAPM_INPUT("FM Stereo In"), - SND_SOC_DAPM_LINE("FM Stereo Out",NULL), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /* External Mics: MAINMIC, SUBMIC with bias*/ - {"IN1L", NULL, "Mic Bias Int"}, - {"IN1R", NULL, "Mic Bias Int"}, - {"IN4L", NULL, "Mic Bias Int"}, - {"IN4R", NULL, "Mic Bias Int"}, - {"Mic Bias Int", NULL, "Ext Mic"}, - - /* External Speakers: HFL, HFR */ - {"Ext Spk", NULL, "SPKL"}, - {"Ext Spk", NULL, "SPKR"}, - - /* Headset Mic: HSMIC with bias */ - {"IN2L", NULL, "Mic Bias Ext"}, - {"IN2R", NULL, "Mic Bias Ext"}, - {"Mic Bias Ext", NULL, "Headset Mic"}, - - /* Headset Stereophone (Headphone): HPL, HPR */ - {"Headset Stereophone", NULL, "HPL"}, - {"Headset Stereophone", NULL, "HPR"}, - - /* Earphone speaker */ - {"Earphone Spk", NULL, "RECP"}, - {"Earphone Spk", NULL, "RECM"}, - - /* Aux/FM Stereo In: IN4L, IN4R */ - {"IN3L", NULL, "FM Stereo In"}, - {"IN3R", NULL, "FM Stereo In"}, - - /* Aux/FM Stereo Out: LOL, LOR */ - {"FM Stereo Out", NULL, "LOL"}, - {"FM Stereo Out", NULL, "LOR"}, -}; - -static const struct snd_kcontrol_new rk29_aic326x_controls[] = { - SOC_DAPM_PIN_SWITCH("Ext Mic"), - SOC_DAPM_PIN_SWITCH("Ext Spk"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Headset Stereophone"), - SOC_DAPM_PIN_SWITCH("Earphone Spk"), - SOC_DAPM_PIN_SWITCH("FM Stereo In"), - SOC_DAPM_PIN_SWITCH("FM Stereo Out"), -}; - -static int rk29_aic3262_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - DBG_AIC3262("rk29_aic3262_init\n"); - - ret = snd_soc_add_controls(codec, rk29_aic326x_controls, - ARRAY_SIZE(rk29_aic326x_controls)); - - if (ret < 0) { - printk("rk29_aic3262: Err snd_soc_add_controls ret: %d\n", ret ); - return ret; - } - - /* Add rk29 specific widgets */ - ret = snd_soc_dapm_new_controls(dapm, rk29_aic3262_dapm_widgets, - ARRAY_SIZE(rk29_aic3262_dapm_widgets)); - if (ret) - return ret; - - /* Set up rk29 specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - - ret = snd_soc_dapm_sync(dapm); - if (ret) - return ret; - - /* Headset jack detection */ - /*ret = snd_soc_jack_new(codec, "Headset Jack", - SND_JACK_HEADSET, &hs_jack); - if (ret) - return ret; - - ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), - hs_jack_pins); - aic3262_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);*/ - - /* don't wait before switching of HS power */ - rtd->pmdown_time = 0; - return ret; -} - -static int rk29_aif1_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int div_bclk,div_mclk; - int ret; - - printk("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* set codec DAI configuration */ -#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - DBG_AIC3262("Set codec_dai slave\n"); - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); -#endif -#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); - DBG_AIC3262("Set codec_dai master\n"); -#endif - if (ret < 0) - return ret; - - /* set cpu DAI configuration */ -#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - DBG_AIC3262("Set cpu_dai master\n"); - 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); - DBG_AIC3262("Set cpu_dai slave\n"); -#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: - DBG_AIC3262("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); - return -EINVAL; - } - - - div_bclk=(pll_out/4)/params_rate(params)-1; - div_mclk=3; - - DBG_AIC3262(" %s, pll_out=%d, div_bclk=%d, div_mclk=%d\n",__FUNCTION__,pll_out,div_bclk,div_mclk); - ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - if(ret < 0) - { - DBG_AIC3262("rk29_hw_params_aic3262:failed to set the cpu sysclk for codec side\n"); - return ret; - } - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, div_bclk); - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); - DBG_AIC3262("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); - - //MCLK == 11289600 or 12288000 - ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, 0); - if (ret < 0) { - DBG_AIC3262("rk29_hw_params_aic3262:failed to set the sysclk for codec side\n"); - return ret; - } - - return ret; -} - -static int rk29_aif2_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int div_bclk,div_mclk; - int ret; - - DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); - - /* set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) - { - printk("%s: snd_soc_dai_set_fmt err =%d\n",__FUNCTION__,ret); - 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: - DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); - return -EINVAL; - } - - div_bclk=(pll_out/4)/params_rate(params)-1; - div_mclk=3; - - DBG_AIC3262(" %s, pll_out=%d, div_bclk=%d, div_mclk=%d\n",__FUNCTION__,pll_out,div_bclk,div_mclk); - - ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - if(ret < 0) - { - DBG("rk29_hw_params_aic3262:failed to set the cpu sysclk for codec side\n"); - return ret; - } - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, div_bclk); - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); - DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); - - /* set the codec system clock */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, 0); - if (ret < 0) - { - printk("%s: snd_soc_dai_set_sysclk err =%d\n",__FUNCTION__,ret); - return ret; - } - - /* set the codec FLL */ - ret = snd_soc_dai_set_pll(codec_dai, 0, AIC3262_PLL_CLKIN_MCLK1 , pll_out, 8000*256); - if (ret < 0) - { - printk("%s: snd_soc_dai_set_pll err =%d\n",__FUNCTION__,ret); - return ret; - } - - return ret; -} - -static int rk29_aif3_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int div_bclk,div_mclk; - int ret; - - DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); - - /* set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) - { - printk("%s: snd_soc_dai_set_fmt err =%d\n",__FUNCTION__,ret); - 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: - DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); - return -EINVAL; - } - - div_bclk=(pll_out/4)/params_rate(params)-1; - div_mclk=3; - - DBG_AIC3262(" %s, pll_out=%d, div_bclk=%d, div_mclk=%d\n",__FUNCTION__,pll_out,div_bclk,div_mclk); - - ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - if(ret < 0) - { - DBG("rk29_hw_params_aic3262:failed to set the cpu sysclk for codec side\n"); - return ret; - } - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, div_bclk); - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); - DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); - - /* set the codec system clock */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, 0); - if (ret < 0) - { - printk("%s: snd_soc_dai_set_sysclk err =%d\n",__FUNCTION__,ret); - return ret; - } - - /* set the codec FLL */ - ret = snd_soc_dai_set_pll(codec_dai, 0, AIC3262_PLL_CLKIN_MCLK1 , pll_out, 8000*256); - if (ret < 0) - { - printk("%s: snd_soc_dai_set_pll err =%d\n",__FUNCTION__,ret); - return ret; - } - - return ret; -} - -static struct snd_soc_ops rk29_aif1_ops = { - .hw_params = rk29_aif1_hw_params, -}; - -static struct snd_soc_ops rk29_aif2_ops = { - .hw_params = rk29_aif2_hw_params, -}; - -static struct snd_soc_ops rk29_aif3_ops = { - .hw_params = rk29_aif3_hw_params, -}; - -static struct snd_soc_dai_link rk29_dai[] = { - - { - .name = "AIC3262 I2S1", - .stream_name = "AIC3262 PCM", - .codec_name = "tlv320aic3262-codec", - .platform_name = "rockchip-audio", -#if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", -#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", -#else - .cpu_dai_name = "rk29_i2s.2", -#endif - .codec_dai_name = "aic326x-asi1", - .ops = &rk29_aif1_ops, - .init = rk29_aic3262_init, - }, - - { - .name = "AIC3262 I2S2", - .stream_name = "AIC3262 PCM", - .codec_name = "tlv320aic3262-codec", - .platform_name = "rockchip-audio", -#if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", -#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", -#else - .cpu_dai_name = "rk29_i2s.2", -#endif - .codec_dai_name = "aic326x-asi2", - .ops = &rk29_aif2_ops, - }, - - - { - .name = "AIC3262 I2S3", - .stream_name = "AIC3262 PCM", - .codec_name = "tlv320aic3262-codec", - .platform_name = "rockchip-audio", -#if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", -#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", -#else - .cpu_dai_name = "rk29_i2s.2", -#endif - .codec_dai_name = "aic326x-asi3", - .ops = &rk29_aif3_ops, - }, - -}; - - -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_AIC3262", - .dai_link = rk29_dai, - .num_links = ARRAY_SIZE(rk29_dai), -}; - -static struct platform_device *rk29_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; - - DBG_AIC3262("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) { - printk("platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); - ret = platform_device_add(rk29_snd_device); - if (ret) { - printk("platform device add failed\n"); - // snd_soc_unregister_dai(&rk29_snd_device->dev); - platform_device_put(rk29_snd_device); - return ret; - } - - return ret; -} - -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk29_snd_device); -} - -module_init(audio_card_init); -module_exit(audio_card_exit); - -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); - diff --git a/sound/soc/rk29/rk29_ak4396.c b/sound/soc/rk29/rk29_ak4396.c deleted file mode 100755 index c5a324014069..000000000000 --- a/sound/soc/rk29/rk29_ak4396.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * rk29_ak4396.c -- SoC audio for rockchip - * - * Driver for rockchip ak4396 audio - * - * 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 -#include -#include -#include -#include -#include -#include "rk29_pcm.h" -#include "rk29_i2s.h" - -#include - -#if 1 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif - -static int rk29_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int ret=-1; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_RIGHT_J | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - if (ret < 0) return ret; - /* set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_RIGHT_J | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) return ret; - #endif - - 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; - case 88200: - case 176400: - pll_out = 11289600*2; - break; - case 96000: - case 192000: - pll_out = 12288000*2; - break; - default: - DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); - return -EINVAL; - } - - DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); - - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (2 * 32 )-1); //bclk = 2 * 32 * lrck - - switch(params_rate(params)){ - case 192000: - case 176400: - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK,1); - DBG("Enter:%s, %d, MCLK=%d BCLK=%d LRCK=%d\n", - __FUNCTION__,__LINE__,pll_out,pll_out/2,params_rate(params)); - break; - default : - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3); - DBG("default:%s, %d, MCLK=%d BCLK=%d LRCK=%d\n", - __FUNCTION__,__LINE__,pll_out,pll_out/4,params_rate(params)); - break; - } - snd_soc_dai_set_sysclk(codec_dai,0,pll_out,SND_SOC_CLOCK_IN); - #endif - return ret; -} - -/* - * Logic for a ak4396 as connected on a rockchip board. - */ -static int rk29_ak4396_init(struct snd_soc_pcm_runtime *rtd) -{ - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - return 0; -} - -static struct snd_soc_ops rk29_ops = { - .hw_params = rk29_hw_params, -}; - -static struct snd_soc_dai_link rk29_dai = { - .name = "AK4396", - .stream_name = "AK4396 PCM", - .codec_name = "spi1.0", - .platform_name = "rockchip-audio", -#if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", -#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", -#else - .cpu_dai_name = "rk29_i2s.2", -#endif - .codec_dai_name = "AK4396 HiFi", - .init = rk29_ak4396_init, - .ops = &rk29_ops, -}; - -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_AK4396", - .dai_link = &rk29_dai, - .num_links = 1, -}; - -static struct platform_device *rk29_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; - - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) { - printk("platform device allocation failed\n"); - ret = -ENOMEM; - return ret; - } - - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); - - ret = platform_device_add(rk29_snd_device); - if (ret) { - printk("platform device add failed\n"); - platform_device_put(rk29_snd_device); - return ret; - } - - return ret; -} - -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk29_snd_device);; -} - -module_init(audio_card_init); -module_exit(audio_card_exit); -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk29/rk29_cs42l52.c b/sound/soc/rk29/rk29_cs42l52.c deleted file mode 100755 index ee3d8c2409bf..000000000000 --- a/sound/soc/rk29/rk29_cs42l52.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * rk29_cs42l52.c -- SoC audio for rockchip - * - * Driver for rockchip cs42l52 audio - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include "../codecs/cs42l52.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" - - -#define HW_PARAMS_FLAG_EQVOL_ON 0x21 -#define HW_PARAMS_FLAG_EQVOL_OFF 0x22 -static const struct snd_soc_dapm_widget cs42l52_dapm_widgets[] = { - SND_SOC_DAPM_LINE("Audio Out", NULL), - SND_SOC_DAPM_LINE("Line in", NULL), - SND_SOC_DAPM_MIC("Micn", NULL), - SND_SOC_DAPM_MIC("Micp", NULL), -}; - -static const struct snd_soc_dapm_route audio_map[]= { - - {"Audio Out", NULL, "HPA"}, - {"Audio Out", NULL, "HPB"}, - {"Line in", NULL, "INPUT1A"}, - {"Line in", NULL, "INPUT1B"}, - {"Micn", NULL, "INPUT2A"}, - {"Micp", NULL, "INPUT2B"}, -}; - -static int rk29_cs42l52_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 *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - unsigned int pll_out = 0; - unsigned int lrclk = 0; - int div_bclk,div_mclk; - struct clk *general_pll; - int ret; - - if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) - { - ret = codec_dai->ops->hw_params(substream, params, codec_dai); //by Vincent - } - else - { - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); - #endif - if (ret < 0) - return ret; - - /* 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: - return -EINVAL; - break; - } - - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - general_pll=clk_get(NULL, "general_pll"); - if(clk_get_rate(general_pll)>260000000) - { - div_bclk=(pll_out/4)/params_rate(params)-1; - //div_bclk= 63; - div_mclk= 3; - } - else if(clk_get_rate(general_pll)>130000000) - { - div_bclk=(pll_out/2)/params_rate(params)-1; - div_mclk=1; - } - else - { - pll_out=pll_out/4; - div_bclk=(pll_out)/params_rate(params)-1; - div_mclk=0; - } - - //snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, 0); - snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk); - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); - #endif - - - return 0; -} - -static int rk29_cs42l52_dai_init(struct snd_soc_codec *codec) -{ - struct snd_soc_dai *codec_dai = &codec->dai[0]; - int ret; - - snd_soc_dapm_nc_pin(codec, "INPUT1A"); - snd_soc_dapm_nc_pin(codec, "INPUT2A"); - snd_soc_dapm_nc_pin(codec, "INPUT3A"); - snd_soc_dapm_nc_pin(codec, "INPUT4A"); - snd_soc_dapm_nc_pin(codec, "INPUT1B"); - snd_soc_dapm_nc_pin(codec, "INPUT2B"); - snd_soc_dapm_nc_pin(codec, "INPUT3B"); - snd_soc_dapm_nc_pin(codec, "INPUT4B"); - snd_soc_dapm_nc_pin(codec, "MICB"); - snd_soc_dapm_sync(codec); - return 0; -} - -static struct snd_soc_ops rk29_cs42l52_ops = { - .hw_params = rk29_cs42l52_hw_params, -}; - -static struct snd_soc_dai_link rk29_cs42l52_dai_link = { - .name = "CS42L52", - .stream_name = "CS42L52 PCM", - .cpu_dai = &rk29_i2s_dai[0], - .codec_dai = &soc_cs42l52_dai, - .init = rk29_cs42l52_dai_init, - .ops = &rk29_cs42l52_ops, -}; - -static struct snd_soc_card snd_soc_card_rk29_cs42l52 = { - .name = "RK29_CS42L52", - .platform = &rk29_soc_platform, - .dai_link = &rk29_cs42l52_dai_link, - .num_links = 1, -}; - - -static struct snd_soc_device rk29_cs42l52_snd_devdata = { - .card = &snd_soc_card_rk29_cs42l52, - .codec_dev = &soc_codec_dev_cs42l52, -}; - -static struct platform_device *rk29_cs42l52_snd_device; - -static int rk29_cs42l52_probe(struct platform_device *pdev) -{ - int ret =0; - printk("RK29 CS42L52 SoC Audio driver\n"); - rk29_cs42l52_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_cs42l52_snd_device) { - ret = -ENOMEM; - printk("%s:platform device alloc fail\n",__FUNCTION__); - return ret; - } - platform_set_drvdata(rk29_cs42l52_snd_device, &rk29_cs42l52_snd_devdata); - rk29_cs42l52_snd_devdata.dev = &rk29_cs42l52_snd_device->dev; - ret = platform_device_add(rk29_cs42l52_snd_device); - if (ret) { - platform_device_put(rk29_cs42l52_snd_device); - printk("%s:platform device add fail,ret = %d\n",__FUNCTION__,ret); - } - return ret; -} - -static int rk29_cs42l52_remove(struct platform_device *pdev) -{ - platform_device_unregister(rk29_cs42l52_snd_device); - return 0; -} - -static struct platform_driver rk29_cs42l52_driver = { - .probe = rk29_cs42l52_probe, - .remove = rk29_cs42l52_remove, - .driver = { - .name = "rk29_cs42l52", - .owner = THIS_MODULE, - }, -}; - -static int __init rk29_cs42l52_init(void) -{ - return platform_driver_register(&rk29_cs42l52_driver); -} - -static void __exit rk29_cs42l52_exit(void) -{ - platform_driver_unregister(&rk29_cs42l52_driver); -} - -module_init(rk29_cs42l52_init); -module_exit(rk29_cs42l52_exit); -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); - diff --git a/sound/soc/rk29/rk29_cx2070x.c b/sound/soc/rk29/rk29_cx2070x.c deleted file mode 100644 index 44013aceba89..000000000000 --- a/sound/soc/rk29/rk29_cx2070x.c +++ /dev/null @@ -1,272 +0,0 @@ -/* - * rk29_cx2070x.c - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include "rk29_pcm.h" -#include "rk29_i2s.h" -#if 1 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif - -#include "../codecs/cx2070x.h" - -static struct platform_device *rk29_snd_device; - - -static int rk29_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - //unsigned int pll_div; - 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; - - - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #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; - case 96000: - case 192000: - pll_out = 12288000*2; - break; - case 88200: - case 176400: - pll_out = 11289600*2; - break; - default: - DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); - return -EINVAL; - break; - } -#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, 64-1);//bclk = 2*32*lrck; 2*32fs - switch(params_rate(params)) { - case 176400: - case 192000: - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 1); - DBG("Enter:%s, %d, MCLK=%d BCLK=%d LRCK=%d\n", - __FUNCTION__,__LINE__,pll_out,pll_out/2,params_rate(params)); - break; - default: - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3); - DBG("default:%s, %d, MCLK=%d BCLK=%d LRCK=%d\n", - __FUNCTION__,__LINE__,pll_out,pll_out/4,params_rate(params)); - break; - } - - /*Set the system clk for codec*/ - ret=snd_soc_dai_set_sysclk(codec_dai, 0,pll_out,SND_SOC_CLOCK_IN); - if (ret < 0) - { - DBG("rk29_hw_params_rt5631:failed to set the sysclk for codec side\n"); - return ret; - } -#endif - -#if 0 - switch (params_rate(params)) - { - case 8000: - pll_div = 12; - break; - case 16000: - pll_div = 6; - break; - case 32000: - pll_div = 3; - break; - case 48000: - pll_div = 2; - break; - case 96000: - pll_div = 1; - break; - case 11025: - pll_div = 8; - break; - case 22050: - pll_div = 4; - break; - case 44100: - pll_div = 2; - break; - case 88200: - pll_div = 1; - break; - default: - printk("Not yet supported!\n"); - return -EINVAL; - } - ret = snd_soc_dai_set_clkdiv(codec_dai, cx2070x_CLK_DIV_ID, pll_div*4); - if (ret < 0) - return ret; -#endif - -#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - //snd_soc_dai_set_pll(codec_dai,0,pll_out, 22579200); - snd_soc_dai_set_sysclk(codec_dai,0,pll_out, SND_SOC_CLOCK_IN); -#endif - return 0; -} - -//--------------------------------------------------------------------------------- -/* - * cx2070x DAI operations. - */ -static struct snd_soc_ops rk29_ops = { - .hw_params = rk29_hw_params, -}; - -static const struct snd_soc_dapm_widget cx2070x_dapm_widgets[] = { - // Input - SND_SOC_DAPM_MIC("Mic Jack", NULL), - //SND_SOC_DAPM_LINE("Headset Jack", NULL), - SND_SOC_DAPM_INPUT("BT IN"), - // Output - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_LINE("ALineOut", NULL), - SND_SOC_DAPM_OUTPUT("BT OUT"), - -}; - -static const struct snd_soc_dapm_route cx2070x_audio_map[] = { - // Input - {"MIC IN", NULL,"Mic Jack"}, - {"PCM IN", NULL, "BT IN"}, - // Output - {"Ext Spk", NULL, "SPK OUT"}, - {"Headphone Jack", NULL, "HP OUT"}, - {"ALineOut", NULL, "LINE OUT"}, - {"BT OUT", NULL, "PCM OUT"}, -}; - -static int cx2070x_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - //struct cx2070x_codec_chip *chip = snd_soc_codec_get_drvdata(codec); - //int err = 0; - printk(">>>>>>>>>>%s",__FUNCTION__); - snd_soc_dapm_new_controls(dapm, cx2070x_dapm_widgets, - ARRAY_SIZE(cx2070x_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, cx2070x_audio_map, - ARRAY_SIZE(cx2070x_audio_map)); -#if FOR_MID - snd_soc_dapm_disable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "BT IN"); - snd_soc_dapm_disable_pin(dapm, "Ext Spk"); - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "ALineOut"); - snd_soc_dapm_disable_pin(dapm, "BT OUT"); -#endif - - snd_soc_dapm_sync(dapm); - return 0; -} - -static struct snd_soc_dai_link rk29_dai[] = { - { /* Primary DAI i/f */ - .name = "CX2070X AIF1", - .stream_name = "CX2070X PCM", - .cpu_dai_name = "rk29_i2s.1", - .codec_dai_name = "cx2070x-hifi", - .platform_name = "rockchip-audio", - .codec_name = "cx2070x.0-0014", - .init = cx2070x_init, - .ops = &rk29_ops, - }, -}; - -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_CX2070X", - .dai_link = rk29_dai, - - /* If you want to use sec_fifo device, - * changes the num_link = 2 or ARRAY_SIZE(snd_soc_card_rk29). */ - .num_links = ARRAY_SIZE(rk29_dai), -}; - -static int __init audio_card_init(void) -{ - int ret; - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) - return -ENOMEM; - - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); - - ret = platform_device_add(rk29_snd_device); - printk(">>>>>>>>>>%s ret = %d",__FUNCTION__, ret); - if (ret) - platform_device_put(rk29_snd_device); - - return ret; -} -module_init(audio_card_init); - -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk29_snd_device); -} -module_exit(audio_card_exit); - -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_AUTHOR("showy.zhang "); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk29/rk29_es8323.c b/sound/soc/rk29/rk29_es8323.c deleted file mode 100755 index afc6241214ad..000000000000 --- a/sound/soc/rk29/rk29_es8323.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * rk29_es8323.c -- SoC audio for rockchip - * - * Driver for rockchip es8323 audio - * - * 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 -#include -#include -#include -#include -#include -//#include -//#include -#include "../codecs/es8323.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" - -#include -#ifdef CONFIG_MACH_RK_FAC -#include -extern int codec_type; -#endif - -#if 1 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif - -//static void *rk29_speaker = NULL; - -static int rk29_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - /*by Vincent Hsiung for EQ Vol Change*/ - #define HW_PARAMS_FLAG_EQVOL_ON 0x21 - #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 - if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) - { - ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - } - else - { - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #endif - if (ret < 0) - return ret; - /* 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: - DBG("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)); - - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - 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); - #endif - - DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); - return 0; -} - -static const struct snd_soc_dapm_widget rk29_dapm_widgets[] = { - SND_SOC_DAPM_LINE("Audio Out", NULL), - SND_SOC_DAPM_LINE("Line in", NULL), - SND_SOC_DAPM_MIC("Micn", NULL), - SND_SOC_DAPM_MIC("Micp", NULL), -}; - -static const struct snd_soc_dapm_route audio_map[]= { - - {"Audio Out", NULL, "LOUT1"}, - {"Audio Out", NULL, "ROUT1"}, - {"Line in", NULL, "RINPUT1"}, - {"Line in", NULL, "LINPUT1"}, - {"Micn", NULL, "RINPUT2"}, - {"Micp", NULL, "LINPUT2"}, -}; - -/* - * Logic for a es8323 as connected on a rockchip board. - */ -static int rk29_es8323_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - ret = snd_soc_dai_set_sysclk(codec_dai, 0, - /*12000000*/11289600, SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "Failed to set es8323 SYSCLK: %d\n", ret); - return ret; - } - - /* Add specific widgets */ - snd_soc_dapm_new_controls(dapm, rk29_dapm_widgets, - ARRAY_SIZE(rk29_dapm_widgets)); - //snd_soc_dapm_nc_pin(codec, "LOUT2"); - //snd_soc_dapm_nc_pin(codec, "ROUT2"); - - /* Set up specific audio path audio_mapnects */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - snd_soc_dapm_sync(dapm); - - return 0; -} - -static struct snd_soc_ops rk29_ops = { - .hw_params = rk29_hw_params, -}; - -static struct snd_soc_dai_link rk29_dai = { - .name = "ES8323", - .stream_name = "ES8323 PCM", - .codec_name = "ES8323.4-0010", // ES8323.0-0010 - .platform_name = "rockchip-audio", -#if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", -#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", //Ó²¼þÉÏÊǽӵ½IIS0ÉÏ£¬µ«ÊÇÓÉÓÚxxÔ­Òò£¬Õâ±ß¶¨ÒåΪIIS1ÉÏ -#else - .cpu_dai_name = "rk29_i2s.2", -#endif - .codec_dai_name = "ES8323 HiFi", - .init = rk29_es8323_init, - .ops = &rk29_ops, -}; - -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_ES8323", - .dai_link = &rk29_dai, - .num_links = 1, -}; - -static struct platform_device *rk29_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; -#ifdef CONFIG_MACH_RK_FAC - if(codec_type!=CODEC_TYPE_ES8323) - return -1; -#endif - DBG("ES8323 audio_card_init\n"); -#if 0 - extern int get_sound_card_exist() ; - extern void set_sound_card_exist(int i) ; - extern int i2c0_prober_verify(u32 dev_addr, u16 reg, u32 reg_addr_len, u32 reg_val_len, u32 id); - if(i2c0_prober_verify(0x10, 0x35, 1, 1, 0x0000) != 0) { - printk("%s(): Ping error with 0x1a\n", __FUNCTION__); - return -ENODEV; - } - else - printk("%s(): Ping OK with 0x1a\n", __FUNCTION__); -#endif -//leaf if(0 == tcsi_get_value(TCSI_CODEC_ES8323)) -//leaf2012-7-26 return; - DBG("XXXXEnter::%s----%d\n",__FUNCTION__,__LINE__); - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) { - DBG("platform device allocation failed\n"); - ret = -ENOMEM; - return ret; - } - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); - ret = platform_device_add(rk29_snd_device); - if (ret) { - DBG("platform device add failed\n"); - platform_device_put(rk29_snd_device); - return ret; - } - - return ret; -} -static void __exit audio_card_exit(void) -{ -//leaf 2012-7-26 if(0 == tcsi_get_value(TCSI_CODEC_ES8323)) -//leaf 2012-7-26 return; - platform_device_unregister(rk29_snd_device); - //rk29_speaker_deinit(rk29_speaker); -} - -module_init(audio_card_init); -module_exit(audio_card_exit); -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); - diff --git a/sound/soc/rk29/rk29_i2s.c b/sound/soc/rk29/rk29_i2s.c deleted file mode 100755 index 923aa15acd3b..000000000000 --- a/sound/soc/rk29/rk29_i2s.c +++ /dev/null @@ -1,862 +0,0 @@ -/* - * rk29_i2s.c -- ALSA SoC ROCKCHIP IIS Audio Layer Platform driver - * - * Driver for rockchip iis audio - * - * - * 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 -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "rk29_pcm.h" -#include "rk29_i2s.h" - - -#if 0 -#define I2S_DBG(x...) printk(KERN_INFO x) -#else -#define I2S_DBG(x...) do { } while (0) -#endif - -#define pheadi2s ((pI2S_REG)(i2s->regs)) - -#define MAX_I2S 2 - -struct rk29_i2s_info { - struct device *dev; - void __iomem *regs; - - u32 feature; - - struct clk *iis_clk; - struct clk *iis_pclk; - - unsigned char master; - - struct rockchip_pcm_dma_params *dma_playback; - struct rockchip_pcm_dma_params *dma_capture; - - u32 suspend_iismod; - u32 suspend_iiscon; - u32 suspend_iispsr; -}; - -static struct rk29_dma_client rk29_dma_client_out = { - .name = "I2S PCM Stereo Out" -}; - -static struct rk29_dma_client rk29_dma_client_in = { - .name = "I2S PCM Stereo In" -}; - -static inline struct rk29_i2s_info *to_info(struct snd_soc_dai *cpu_dai) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) - return snd_soc_dai_get_drvdata(cpu_dai); -#else - return cpu_dai->private_data; -#endif -} - -static struct rockchip_pcm_dma_params rk29_i2s_pcm_stereo_out[MAX_I2S]; -static struct rockchip_pcm_dma_params rk29_i2s_pcm_stereo_in[MAX_I2S]; -static struct rk29_i2s_info rk29_i2s[MAX_I2S]; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) -struct snd_soc_dai_driver rk29_i2s_dai[MAX_I2S]; -#else -struct snd_soc_dai rk29_i2s_dai[MAX_I2S]; -#endif -EXPORT_SYMBOL_GPL(rk29_i2s_dai); - -/* -static struct rockchip_pcm_dma_params rockchip_i2s_pcm_stereo_out[MAX_I2S] = { - [0] = { - .client = &rk29_dma_client_out, - .channel = DMACH_I2S_2CH_TX, ///0, //DMACH_I2S_OUT, - .dma_addr = RK29_I2S_2CH_PHYS + I2S_TXR_BUFF, - .dma_size = 4, - }, - [1] = { - .client = &rk29_dma_client_out, - .channel = DMACH_I2S_8CH_TX, ///0, //DMACH_I2S_OUT, - .dma_addr = RK29_I2S_8CH_PHYS + I2S_TXR_BUFF, - .dma_size = 4, - }, -}; - -static struct rockchip_pcm_dma_params rockchip_i2s_pcm_stereo_in[MAX_I2S] = { - [0] = { - .client = &rk29_dma_client_in, - .channel = DMACH_I2S_2CH_RX, ///1, //DMACH_I2S_IN, - .dma_addr = RK29_I2S_2CH_PHYS + I2S_RXR_BUFF, - .dma_size = 4, - }, - [1] = { - .client = &rk29_dma_client_in, - .channel = DMACH_I2S_8CH_RX, ///1, //DMACH_I2S_IN, - .dma_addr = RK29_I2S_8CH_PHYS + I2S_RXR_BUFF, - .dma_size = 4, - }, -}; -*/ - -#if 1 -static u32 i2s0_clk_enter(void) -{ - u32 clk = cru_readl(CRU_CLKSEL3_CON); - cru_writel(0x1ffff, CRU_CLKSEL3_CON); - mdelay(1); - return clk; -} - -static void i2s0_clk_exit(u32 clk) -{ - mdelay(1); - cru_writel(clk, CRU_CLKSEL3_CON); - mdelay(1); -} -#else -static u32 i2s0_clk_enter() -{ - return 0; -} - -static void i2s0_clk_exit(u32 clk) -{ -} -#endif - -/* - *Turn on or off the transmission path. - */ - -static int flag_i2s_tx = 0; -static int flag_i2s_rx = 0; -static void rockchip_snd_txctrl(struct rk29_i2s_info *i2s, int on, bool stopI2S) -{ - u32 opr,xfer; - u32 clk; - - opr = readl(&(pheadi2s->I2S_DMACR)); - xfer = readl(&(pheadi2s->I2S_XFER)); - - if (on) - { - I2S_DBG("rockchip_snd_txctrl: on\n"); - - //start tx - //if ((flag_i2s_tx == 0) && (flag_i2s_rx == 0)) - if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0) - { - clk = i2s0_clk_enter(); - - //if start tx & rx clk, need reset i2s - xfer |= I2S_TX_TRAN_START; - xfer |= I2S_RX_TRAN_START; - writel(xfer, &(pheadi2s->I2S_XFER)); - - i2s0_clk_exit(clk); - } - - if ((opr & I2S_TRAN_DMA_ENABLE) == 0) - { - opr |= I2S_TRAN_DMA_ENABLE; - writel(opr, &(pheadi2s->I2S_DMACR)); - } - - flag_i2s_tx = 1; - } - else - { - //stop tx - - flag_i2s_tx = 0; - if ((flag_i2s_rx == 0) && (flag_i2s_tx == 0)) - { - opr &= ~I2S_TRAN_DMA_ENABLE; - writel(opr, &(pheadi2s->I2S_DMACR)); - if(stopI2S) - { - clk = i2s0_clk_enter(); - - xfer &= ~I2S_RX_TRAN_START; - xfer &= ~I2S_TX_TRAN_START; - writel(xfer, &(pheadi2s->I2S_XFER)); - - i2s0_clk_exit(clk); - } - - //after stop rx & tx clk, reset i2s - //writel(0x001,&(pheadi2s->I2S_TXRST)); - //writel(0x001,&(pheadi2s->I2S_RXRST)); - } - - I2S_DBG("rockchip_snd_txctrl: off\n"); - } -} - -static void rockchip_snd_rxctrl(struct rk29_i2s_info *i2s, int on, bool stopI2S) -{ - u32 opr,xfer; - u32 clk; - - opr = readl(&(pheadi2s->I2S_DMACR)); - xfer = readl(&(pheadi2s->I2S_XFER)); - - if (on) - { - I2S_DBG("rockchip_snd_rxctrl: on\n"); - - //start rx - //if ((flag_i2s_tx == 0) && (flag_i2s_rx == 0)) - if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0) - { - clk = i2s0_clk_enter(); - - xfer |= I2S_TX_TRAN_START; - xfer |= I2S_RX_TRAN_START; - writel(xfer, &(pheadi2s->I2S_XFER)); - - i2s0_clk_exit(clk); - } - - if ((opr & I2S_RECE_DMA_ENABLE) == 0) - { - opr |= I2S_RECE_DMA_ENABLE; - writel(opr, &(pheadi2s->I2S_DMACR)); - } - - flag_i2s_rx = 1; -#if (CONFIG_SND_SOC_RT5631) -//bard 7-16 s - schedule_delayed_work(&rt5631_delay_cap,HZ/4); -//bard 7-16 e -#endif - } - else - { - //stop rx - flag_i2s_rx = 0; - if ((flag_i2s_rx == 0) && (flag_i2s_tx == 0)) - { - opr &= ~I2S_RECE_DMA_ENABLE; - writel(opr, &(pheadi2s->I2S_DMACR)); - - if(stopI2S) - { - clk = i2s0_clk_enter(); - - xfer &= ~I2S_RX_TRAN_START; - xfer &= ~I2S_TX_TRAN_START; - writel(xfer, &(pheadi2s->I2S_XFER)); - - i2s0_clk_exit(clk); - } - - //after stop rx & tx clk, reset i2s - //writel(0x001,&(pheadi2s->I2S_TXRST)); - //writel(0x001,&(pheadi2s->I2S_RXRST)); - } - - I2S_DBG("rockchip_snd_rxctrl: off\n"); - } -} - -/* - * Set Rockchip I2S DAI format - */ -static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - struct rk29_i2s_info *i2s = to_info(cpu_dai); - u32 tx_ctl,rx_ctl; - - I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - tx_ctl = readl(&(pheadi2s->I2S_TXCR)); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - tx_ctl &= ~I2S_MODE_MASK; - tx_ctl |= I2S_MASTER_MODE; - break; - case SND_SOC_DAIFMT_CBS_CFS: - tx_ctl &= ~I2S_MODE_MASK; - tx_ctl |= I2S_SLAVE_MODE; - break; - default: - I2S_DBG("unknwon master/slave format\n"); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_RIGHT_J: - tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode - tx_ctl |= I2S_BUS_MODE_RSJM; - break; - case SND_SOC_DAIFMT_LEFT_J: - tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode - tx_ctl |= I2S_BUS_MODE_LSJM; - break; - case SND_SOC_DAIFMT_I2S: - tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode - tx_ctl |= I2S_BUS_MODE_NOR; - break; - default: - I2S_DBG("Unknown data format\n"); - return -EINVAL; - } - I2S_DBG("Enter::%s----%d, I2S_TXCR=0x%X\n",__FUNCTION__,__LINE__,tx_ctl); -#if 0//defined(CONFIG_SND_RK29_SOC_alc5631) || defined(CONFIG_SND_RK29_SOC_alc5621) - rx_ctl = tx_ctl; - rx_ctl &= ~I2S_MODE_MASK; - rx_ctl |= I2S_SLAVE_MODE; // set tx slave, rx master - writel(rx_ctl, &(pheadi2s->I2S_TXCR)); -#else - writel(tx_ctl, &(pheadi2s->I2S_TXCR)); -#endif - rx_ctl = tx_ctl & 0x00007FFF; - writel(rx_ctl, &(pheadi2s->I2S_RXCR)); - return 0; -} - -static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *socdai) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) - struct rk29_i2s_info *i2s = to_info(socdai); -#else - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai_link *dai = rtd->dai; - struct rk29_i2s_info *i2s = to_info(dai->cpu_dai); -#endif - u32 iismod; - u32 dmarc; - - I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); - /*by Vincent Hsiung for EQ Vol Change*/ - #define HW_PARAMS_FLAG_EQVOL_ON 0x21 - #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 - if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) - { - return 0; - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - snd_soc_dai_set_dma_data(socdai, substream, i2s->dma_playback); - else - snd_soc_dai_set_dma_data(socdai, substream, i2s->dma_capture); -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dai->cpu_dai->playback.dma_data = i2s->dma_playback; - else - dai->cpu_dai->capture.dma_data = i2s->dma_capture; -#else - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dai->cpu_dai->dma_data = i2s->dma_playback; - else - dai->cpu_dai->dma_data = i2s->dma_capture; -#endif - - /* Working copies of register */ - iismod = readl(&(pheadi2s->I2S_TXCR)); - //iismod &= (~((1<<5)-1)); - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S8: - iismod |= SAMPLE_DATA_8bit; - break; - case SNDRV_PCM_FORMAT_S16_LE: - iismod |= I2S_DATA_WIDTH(15); - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iismod |= I2S_DATA_WIDTH(19); - break; - case SNDRV_PCM_FORMAT_S24_LE: - iismod |= I2S_DATA_WIDTH(23); - break; - case SNDRV_PCM_FORMAT_S32_LE: - iismod |= I2S_DATA_WIDTH(31); - break; - } - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - iismod &= ~I2S_SLAVE_MODE; - #endif - - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - iismod |= I2S_SLAVE_MODE; - #endif - - //writel((16<<24) |(16<<18)|(16<<12)|(16<<6)|16, &(pheadi2s->I2S_FIFOLR)); - dmarc = readl(&(pheadi2s->I2S_DMACR)); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dmarc = ((dmarc & 0xFFFFFE00) | 16); - else - dmarc = ((dmarc & 0xFE00FFFF) | 16<<16); - - writel(dmarc, &(pheadi2s->I2S_DMACR)); - I2S_DBG("Enter %s, %d I2S_TXCR=0x%08X\n", __func__, __LINE__, iismod); -#if 0//defined(CONFIG_SND_RK29_SOC_alc5631) || defined(CONFIG_SND_RK29_SOC_alc5621) - dmarc = iismod; - dmarc &= ~I2S_MODE_MASK; - dmarc |= I2S_SLAVE_MODE; // set tx slave, rx master - writel(dmarc, &(pheadi2s->I2S_TXCR)); -#else - writel(iismod, &(pheadi2s->I2S_TXCR)); -#endif - iismod = iismod & 0x00007FFF; - writel(iismod, &(pheadi2s->I2S_RXCR)); - return 0; -} - - -static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) -{ - int ret = 0; - struct snd_soc_pcm_runtime *rtd = substream->private_data; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) - struct rk29_i2s_info *i2s = to_info(rtd->cpu_dai); -#else - struct rk29_i2s_info *i2s = to_info(rtd->dai->cpu_dai); -#endif - bool stopI2S = false; - - I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - rockchip_snd_rxctrl(i2s, 1, stopI2S); - else - rockchip_snd_txctrl(i2s, 1, stopI2S); - break; - - case SNDRV_PCM_TRIGGER_SUSPEND: - stopI2S = true; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - rockchip_snd_rxctrl(i2s, 0, stopI2S); - else - rockchip_snd_txctrl(i2s, 0, stopI2S); - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} -/* - * Set Rockchip Clock source - */ -static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, - int clk_id, unsigned int freq, int dir) -{ - struct rk29_i2s_info *i2s; - - i2s = to_info(cpu_dai); - - I2S_DBG("Enter:%s, %d, i2s=0x%p, freq=%d\n", __FUNCTION__, __LINE__, i2s, freq); - /*add scu clk source and enable clk*/ - clk_set_rate(i2s->iis_clk, freq); - return 0; -} - -/* - * Set Rockchip Clock dividers - */ -static int rockchip_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, - int div_id, int div) -{ - struct rk29_i2s_info *i2s; - u32 reg; - - i2s = to_info(cpu_dai); - - /*stereo mode MCLK/SCK=4*/ - - reg = readl(&(pheadi2s->I2S_TXCKR)); - - I2S_DBG("Enter:%s, %d, div_id=0x%08X, div=0x%08X\n", __FUNCTION__, __LINE__, div_id, div); - - /*when i2s in master mode ,must set codec pll div*/ - switch (div_id) { - case ROCKCHIP_DIV_BCLK: - reg &= ~I2S_TX_SCLK_DIV_MASK; - reg |= I2S_TX_SCLK_DIV(div); - break; - case ROCKCHIP_DIV_MCLK: - reg &= ~I2S_MCLK_DIV_MASK; - reg |= I2S_MCLK_DIV(div); - break; - case ROCKCHIP_DIV_PRESCALER: - - break; - default: - return -EINVAL; - } - writel(reg, &(pheadi2s->I2S_TXCKR)); - writel(reg, &(pheadi2s->I2S_RXCKR)); - return 0; -} - -/* - * To avoid duplicating clock code, allow machine driver to - * get the clockrate from here. - */ -u32 rockchip_i2s_get_clockrate(void) -{ - I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - return 0; ///clk_get_rate(s3c24xx_i2s.iis_clk); -} -EXPORT_SYMBOL_GPL(rockchip_i2s_get_clockrate); - -#ifdef CONFIG_PM -int rockchip_i2s_suspend(struct snd_soc_dai *cpu_dai) -{ - I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - //clk_disable(clk); - return 0; -} - -int rockchip_i2s_resume(struct snd_soc_dai *cpu_dai) -{ - I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - //clk_enable(clk); - return 0; -} -#else -#define rockchip_i2s_suspend NULL -#define rockchip_i2s_resume NULL -#endif - -#if defined(CONFIG_SND_RK29_SOC_alc5631) || defined(CONFIG_SND_RK29_SOC_alc5621) -#define ROCKCHIP_I2S_RATES (SNDRV_PCM_RATE_44100) //zyy 20110704, playback and record use same sample rate -#else -#define ROCKCHIP_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) -#endif - -static struct snd_soc_dai_ops rockchip_i2s_dai_ops = { - .trigger = rockchip_i2s_trigger, - .hw_params = rockchip_i2s_hw_params, - .set_fmt = rockchip_i2s_set_fmt, - .set_clkdiv = rockchip_i2s_set_clkdiv, - .set_sysclk = rockchip_i2s_set_sysclk, -}; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) -static int rockchip_i2s_dai_probe(struct snd_soc_dai *dai) -#else -static int rockchip_i2s_dai_probe(struct platform_device *pdev, struct snd_soc_dai *dai) -#endif -{ - I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); - - switch(dai->id) { - case 0: - rk29_mux_api_set(GPIO2D0_I2S0CLK_MIIRXCLKIN_NAME, GPIO2H_I2S0_CLK); - rk29_mux_api_set(GPIO2D1_I2S0SCLK_MIICRS_NAME, GPIO2H_I2S0_SCLK); - rk29_mux_api_set(GPIO2D2_I2S0LRCKRX_MIITXERR_NAME, GPIO2H_I2S0_LRCK_RX); - rk29_mux_api_set(GPIO2D3_I2S0SDI_MIICOL_NAME, GPIO2H_I2S0_SDI); - rk29_mux_api_set(GPIO2D4_I2S0SDO0_MIIRXD2_NAME, GPIO2H_I2S0_SDO0); - rk29_mux_api_set(GPIO2D5_I2S0SDO1_MIIRXD3_NAME, GPIO2H_I2S0_SDO1); - rk29_mux_api_set(GPIO2D6_I2S0SDO2_MIITXD2_NAME, GPIO2H_I2S0_SDO2); - rk29_mux_api_set(GPIO2D7_I2S0SDO3_MIITXD3_NAME, GPIO2H_I2S0_SDO3); - - rk29_mux_api_set(GPIO4D6_I2S0LRCKTX0_NAME, GPIO4H_I2S0_LRCK_TX0); - rk29_mux_api_set(GPIO4D7_I2S0LRCKTX1_NAME, GPIO4H_I2S0_LRCK_TX1); - break; - case 1: - rk29_mux_api_set(GPIO3A0_I2S1CLK_NAME, GPIO3L_I2S1_CLK); - rk29_mux_api_set(GPIO3A1_I2S1SCLK_NAME, GPIO3L_I2S1_SCLK); - rk29_mux_api_set(GPIO3A2_I2S1LRCKRX_NAME, GPIO3L_I2S1_LRCK_RX); - rk29_mux_api_set(GPIO3A3_I2S1SDI_NAME, GPIO3L_I2S1_SDI); - rk29_mux_api_set(GPIO3A4_I2S1SDO_NAME, GPIO3L_I2S1_SDO); - rk29_mux_api_set(GPIO3A5_I2S1LRCKTX_NAME, GPIO3L_I2S1_LRCK_TX); - break; - default: - I2S_DBG("Enter:%s, %d, Error For DevId!!!", __FUNCTION__, __LINE__); - return -EINVAL; - } - return 0; -} - -static int rk29_i2s_probe(struct platform_device *pdev, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) - struct snd_soc_dai_driver *dai, -#else - struct snd_soc_dai *dai, -#endif - struct rk29_i2s_info *i2s, - unsigned long base) -{ - struct device *dev = &pdev->dev; - struct resource *res; - - I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); - - i2s->dev = dev; - - /* record our i2s structure for later use in the callbacks */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) - dev_set_drvdata(&pdev->dev, i2s); -#else - dai->private_data = i2s; -#endif - - if (!base) { - res = platform_get_resource(pdev, - IORESOURCE_MEM, - 0); - if (!res) { - dev_err(dev, "Unable to get register resource\n"); - return -ENXIO; - } - - if (!request_mem_region(res->start, resource_size(res), - "rk29_i2s")) { - dev_err(dev, "Unable to request register region\n"); - return -EBUSY; - } - - base = res->start; - } - - i2s->regs = ioremap(base, (res->end - res->start) + 1); ////res)); - if (i2s->regs == NULL) { - dev_err(dev, "cannot ioremap registers\n"); - return -ENXIO; - } - - i2s->iis_pclk = clk_get(dev, "i2s"); - if (IS_ERR(i2s->iis_pclk)) { - dev_err(dev, "failed to get iis_clock\n"); - iounmap(i2s->regs); - return -ENOENT; - } - - clk_enable(i2s->iis_pclk); - - /* Mark ourselves as in TXRX mode so we can run through our cleanup - * process without warnings. */ - rockchip_snd_txctrl(i2s, 0, true); - rockchip_snd_rxctrl(i2s, 0, true); - - return 0; -} - -static int __devinit rockchip_i2s_probe(struct platform_device *pdev) -{ - struct rk29_i2s_info *i2s; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) - struct snd_soc_dai_driver *dai; -#else - struct snd_soc_dai *dai; -#endif - int ret; - - I2S_DBG("Enter %s, %d pdev->id = %d >>>>>>>>>>>\n", __func__, __LINE__, pdev->id); - - if(pdev->id >= MAX_I2S) { - dev_err(&pdev->dev, "id %d out of range\n", pdev->id); - return -EINVAL; - } - - i2s = &rk29_i2s[pdev->id]; - dai = &rk29_i2s_dai[pdev->id]; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)) - dai->dev = &pdev->dev; -#endif - dai->id = pdev->id; - dai->symmetric_rates = 1; - if(pdev->id == 0) { - dai->name = "rk29_i2s.0"; - dai->playback.channels_min = 2; - dai->playback.channels_max = 8; - }else{ - dai->name = "rk29_i2s.1"; - dai->playback.channels_min = 2; - dai->playback.channels_max = 2; - } - dai->playback.rates = ROCKCHIP_I2S_RATES; - dai->playback.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE; - dai->capture.channels_min = 2; - dai->capture.channels_max = 2; - dai->capture.rates = ROCKCHIP_I2S_RATES;//;SNDRV_PCM_RATE_44100 - dai->capture.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE; - dai->probe = rockchip_i2s_dai_probe; - dai->ops = &rockchip_i2s_dai_ops; - dai->suspend = rockchip_i2s_suspend; - dai->resume = rockchip_i2s_resume; - - //i2s->feature |= S3C_FEATURE_CDCLKCON; - - i2s->dma_capture = &rk29_i2s_pcm_stereo_in[pdev->id]; - i2s->dma_playback = &rk29_i2s_pcm_stereo_out[pdev->id]; - - if (pdev->id == 1) { - i2s->dma_capture->channel = DMACH_I2S_2CH_RX; - i2s->dma_capture->dma_addr = RK29_I2S_2CH_PHYS + I2S_RXR_BUFF; - i2s->dma_playback->channel = DMACH_I2S_2CH_TX; - i2s->dma_playback->dma_addr = RK29_I2S_2CH_PHYS + I2S_TXR_BUFF; - } else { - i2s->dma_capture->channel = DMACH_I2S_8CH_RX; - i2s->dma_capture->dma_addr = RK29_I2S_8CH_PHYS + I2S_RXR_BUFF; - i2s->dma_playback->channel = DMACH_I2S_8CH_TX; - i2s->dma_playback->dma_addr = RK29_I2S_8CH_PHYS + I2S_TXR_BUFF; - } - - i2s->dma_capture->client = &rk29_dma_client_in; - i2s->dma_capture->dma_size = 4; - i2s->dma_capture->flag = 0; //add by sxj, used for burst change - i2s->dma_playback->client = &rk29_dma_client_out; - i2s->dma_playback->dma_size = 4; - i2s->dma_playback->flag = 0; //add by sxj, used for burst change -#ifdef CONFIG_SND_I2S_DMA_EVENT_STATIC - WARN_ON(rk29_dma_request(i2s->dma_playback->channel, i2s->dma_playback->client, NULL)); - WARN_ON(rk29_dma_request(i2s->dma_capture->channel, i2s->dma_capture->client, NULL)); -#endif - i2s->iis_clk = clk_get(&pdev->dev, "i2s"); - I2S_DBG("Enter:%s, %d, iis_clk=%p\n", __FUNCTION__, __LINE__, i2s->iis_clk); - if (IS_ERR(i2s->iis_clk)) { - dev_err(&pdev->dev, "failed to get i2s clk\n"); - ret = PTR_ERR(i2s->iis_clk); - goto err; - } - - clk_enable(i2s->iis_clk); - clk_set_rate(i2s->iis_clk, 11289600); - ret = rk29_i2s_probe(pdev, dai, i2s, 0); - if (ret) - goto err_clk; - - ret = snd_soc_register_dai(&pdev->dev, dai); - if (ret != 0) - goto err_i2sv2; - - return 0; - -err_i2sv2: - /* Not implemented for I2Sv2 core yet */ -err_clk: - clk_put(i2s->iis_clk); -err: - return ret; -} - - -static int __devexit rockchip_i2s_remove(struct platform_device *pdev) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) - snd_soc_unregister_dai(&pdev->dev); -#else - snd_soc_unregister_dai(&rk29_i2s_dai); -#endif - - return 0; -} - -static struct platform_driver rockchip_i2s_driver = { - .probe = rockchip_i2s_probe, - .remove = __devexit_p(rockchip_i2s_remove), - .driver = { - .name = "rk29_i2s", - .owner = THIS_MODULE, - }, -}; - -static int __init rockchip_i2s_init(void) -{ - I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); - - return platform_driver_register(&rockchip_i2s_driver); -} -module_init(rockchip_i2s_init); - -static void __exit rockchip_i2s_exit(void) -{ - platform_driver_unregister(&rockchip_i2s_driver); -} -module_exit(rockchip_i2s_exit); - -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface"); -MODULE_LICENSE("GPL"); - - -#ifdef CONFIG_PROC_FS -#include -#include -static int proc_i2s_show(struct seq_file *s, void *v) -{ - struct rk29_i2s_info *i2s=&rk29_i2s[0]; - - printk("========Show I2S reg========\n"); - - printk("I2S_TXCR = 0x%08X\n", readl(&(pheadi2s->I2S_TXCR))); - printk("I2S_RXCR = 0x%08X\n", readl(&(pheadi2s->I2S_RXCR))); - printk("I2S_TXCKR = 0x%08X\n", readl(&(pheadi2s->I2S_TXCKR))); - printk("I2S_RXCKR = 0x%08X\n", readl(&(pheadi2s->I2S_RXCKR))); - printk("I2S_DMACR = 0x%08X\n", readl(&(pheadi2s->I2S_DMACR))); - printk("I2S_INTCR = 0x%08X\n", readl(&(pheadi2s->I2S_INTCR))); - printk("I2S_INTSR = 0x%08X\n", readl(&(pheadi2s->I2S_INTSR))); - printk("I2S_XFER = 0x%08X\n", readl(&(pheadi2s->I2S_XFER))); - - printk("========Show I2S reg========\n"); - return 0; -} - -static int proc_i2s_open(struct inode *inode, struct file *file) -{ - return single_open(file, proc_i2s_show, NULL); -} - -static const struct file_operations proc_i2s_fops = { - .open = proc_i2s_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init i2s_proc_init(void) -{ - proc_create("i2s_reg", 0, NULL, &proc_i2s_fops); - return 0; - -} -late_initcall(i2s_proc_init); -#endif /* CONFIG_PROC_FS */ - diff --git a/sound/soc/rk29/rk29_i2s.h b/sound/soc/rk29/rk29_i2s.h deleted file mode 100755 index 91d09ab2c75a..000000000000 --- a/sound/soc/rk29/rk29_i2s.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * rockchip-iis.h - ALSA IIS interface for the Rockchip rk28 SoC - * - * Driver for rockchip iis audio - * - * 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 - -#ifndef _ROCKCHIP_IIS_H -#define _ROCKCHIP_IIS_H - -//I2S_TXCR - -#define PCM_2DATA (0<<18) -#define PCM_4DATA (1<<18) -#define PCM_6DATA (2<<18) -#define PCM_8DATA (3<<18) - -#define CHANNEL_1_EN (0<<15) -#define CHANNEL_2_EN (1<<15) -#define CHANNEL_3_EN (2<<15) -#define CHANNLE_4_EN (3<<15) -#define TX_MODE_MASTER (0<<13) -#define TX_MODE_SLAVE (1<<13) -#define RESET_TX (1<<17) -#define RESET_RX (1<<16) -#define I2S_DMA_REQ1_DISABLE (1<<6) -#define I2S_DMA_REQ1_ENABLE (0) -#define I2S_DMA_REQ2_DISABLE (1<<5) -#define I2S_DMA_REQ2_ENABLE (0) -#define I2S_DMA_REQ1_TX_ENABLE (0) -#define I2S_DMA_REQ1_RX_ENABLE (1<<4) -#define I2S_DMA_REQ2_TX_ENABLE (0) -#define I2S_DMA_REQ2_RX_ENABLE (1<<3) -#define TX_START (1<<1) -#define RX_START (1) - - - -//I2S_TXCTL I2S_RXCTL -#define CLEAR_RXFIFO (1<<24) -#define TRAN_DEVICES0 (0) -#define TRAN_DEVICES1 (1<<18) -#define TRAN_DEVICES2 (2<<18) -#define TRAN_DEVICES3 (3<<18) -#define OVERSAMPLING_RATE_32FS (0) -#define OVERSAMPLING_RATE_64FS (1<<16) -#define OVERSAMPLING_RATE_128FS (2<<16) -#define SCK_RATE2 (0x02<<8) -#define SCK_RATE4 (0x04<<8) -#define SCK_RATE8 (0x08<<8) -#define SAMPLE_DATA_8bit (0) -#define SAMPLE_DATA_16bit (1<<4) -#define SAMPLE_DATA_MASK (3<<4) -#define MONO_MODE (1<<3) -#define STEREO_MODE (0) -#define I2S_MODE (0) -#define LEFT_JUSTIFIED (1<<1) -#define RIGHT_JUSTIFIED (2<<1) -#define IISMOD_SDF_MASK (3<<1) -#define MASTER_MODE (1) -#define SLAVE_MODE (0) - -//I2S_FIFOSTS -#define TX_HALF_FULL (1<<18) -#define RX_HALF_FULL (1<<16) - -/* Clock dividers */ -#define ROCKCHIP_DIV_MCLK 0 -#define ROCKCHIP_DIV_BCLK 1 -#define ROCKCHIP_DIV_PRESCALER 2 - - -/* I2S_TXCR */ -#define I2S_RSTL_SCLK(c) ((c&0x3F)<<26) -#define I2S_RSTR_SCLK(c) ((c&0x3F)<<20) - -#define I2S_PCM_2DATA (0<<18) -#define I2S_PCM_4DATA (1<<18) -#define I2S_PCM_6DATA (2<<18) -#define I2S_PCM_8DATA (3<<18) -#define I2S_PCM_DATA_MASK (3<<18) - -#define I2S_CSR_CH2 (0<<15) -#define I2S_CSR_CH4 (1<<15) -#define I2S_CRS_CH6 (2<<15) -#define I2S_CRS_CH8 (3<<15) -#define I2S_CRS_CH_MASK (3<<15) - -#define I2S_HWT_16BIT (0<<14) -#define I2S_HWT_32BIT (1<<14) - -#ifdef CONFIG_ARCH_RK29 - #define I2S_MASTER_MODE (0<<13) - #define I2S_SLAVE_MODE (1<<13) - #define I2S_MODE_MASK (1<<13) -#endif - -#define I2S_JUSTIFIED_RIGHT (0<<12) -#define I2S_JUSTIFIED_LEFT (1<<12) - -#define I2S_FIRST_BIT_MSB (0<<11) -#define I2S_FIRST_BIT_LSB (1<<11) - -#define I2S_BUS_MODE_NOR (0<<9) -#define I2S_BUS_MODE_LSJM (1<<9) -#define I2S_BUS_MODE_RSJM (2<<9) -#define I2S_BUS_MODE_MASK (3<<9) - -#define I2S_PCM_NO_DELAY (0<<7) -#define I2S_PCM_DELAY_1MODE (1<<7) -#define I2S_PCM_DELAY_2MODE (2<<7) -#define I2S_PCM_DELAY_3MODE (3<<7) -#define I2S_PCM_DELAY_MASK (3<<7) - -#define I2S_TX_LRCK_OUT_BT_DISABLE (0<<6) -#define I2S_TX_LRCK_OUT_BT_ENABLE (1<<6) - -#define I2S_TX_LRCK_OUT_I2S (0<<5) -#define I2S_TX_LRCK_OUT_PCM (1<<5) - -#define I2S_DATA_WIDTH(w) ((w&0x1F)<<0) - -/* */ - - -/* I2S_TXCKR */ -#ifdef CONFIG_ARCH_RK29 - #define I2S_TSP_POSEDGE (0<<25) - #define I2S_TSP_NEGEDGE (1<<25) - #define I2S_TLP_NORMAL (0<<24) - #define I2S_TLP_OPPSITE (1<<24) - - #define I2S_MCLK_DIV(x) ((0xFF&x)<<16) - #define I2S_MCLK_DIV_MASK ((0xFF)<<16) - - #define I2S_TSD_FIXED (0<<12) - #define I2S_TSD_CHANGED (1<<12) - - #define I2S_TX_LRCK_NO_DELAY (0<<10) - #define I2S_TX_LRCK_DELAY_ONE (1<<10) - #define I2S_TX_LRCK_DELAY_TWO (2<<10) - #define I2S_TX_LRCK_DELAY_THREE (3<<10) - #define I2S_TX_LRCK_DELAY_MASK (3<<10) - - #define I2S_TX_SCLK_DIV(x) (x&0x3FF) - #define I2S_TX_SCLK_DIV_MASK (0x3FF); -#else -//I2S_CKR - #define I2S_MASTER_MODE (0<<27) - #define I2S_SLAVE_MODE (1<<27) - #define I2S_MODE_MASK (1<<27) - - #define I2S_BCLK_POSEDGE (0<<26)//sclk polarity invert?? - #define I2S_BCLK_NEGEDGE (1<<26) - - #define I2S_RX_LRCK_POSEDGE (0<<25)//LRCK polarity invert?? - #define I2S_RX_LRCK_NEGEDGE (1<<25) - - #define I2S_TX_LRCK_POSEDGE (0<<24) - #define I2S_TX_LRCK_NEGEDGE (1<<24) - - #define I2S_MCLK_DIV(x) ((0xFF&x)<<16) - #define I2S_MCLK_DIV_MASK ((0xFF)<<16) - - #define I2S_RX_SCLK_DIV(x) ((x&0xFF)<<8) - #define I2S_RX_SCLK_DIV_MASK ((0xFF)<<8) - - #define I2S_TX_SCLK_DIV(x) (x&0xFF) - #define I2S_TX_SCLK_DIV_MASK (0xFF) -#endif - -/* I2S_DMACR */ -#define I2S_RECE_DMA_DISABLE (0<<24) -#define I2S_RECE_DMA_ENABLE (1<<24) -#define I2S_DMARDL(x) ((x&0x1f)<<16) - -#define I2S_TRAN_DMA_DISABLE (0<<8) -#define I2S_TRAN_DMA_ENABLE (1<<8) -#define I2S_DMATDL(x) ((x&0x1f)<<0) - -/* I2S_INTCR */ -#define I2S_RXOV_INT_DISABLE (0<<17) -#define I2S_RXOV_INT_ENABLE (1<<17) -#define I2S_RXFU_INT_DISABLE (0<<16) -#define I2S_RXFU_INT_ENABLE (1<<16) - -#define I2S_TXUND_INT_DISABLE (0<<1) -#define I2S_TXUND_INT_ENABLE (1<<1) -#define I2S_TXEMP_INT_DISABLE (0<<0) -#define I2S_TXEMP_INT_ENABLE (1<<0) - -/* I2S_XFER */ -#define I2S_RX_TRAN_STOP (0<<1) -#define I2S_RX_TRAN_START (1<<1) -#define I2S_TX_TRAN_STOP (0<<0) -#define I2S_TX_TRAN_START (1<<0) - -//I2S_CLR -#define I2S_RX_CLEAR (1<<1) -#define I2S_TX_CLEAR 1 - - -#ifdef CONFIG_ARCH_RK29 -#define I2S_TXR_BUFF 0x20 -#define I2S_RXR_BUFF 0x24 -//I2S Registers -typedef volatile struct tagIIS_STRUCT -{ - unsigned int I2S_TXCR; - unsigned int I2S_RXCR; - unsigned int I2S_TXCKR; - unsigned int I2S_RXCKR; - unsigned int I2S_FIFOLR; - unsigned int I2S_DMACR; - unsigned int I2S_INTCR; - unsigned int I2S_INTSR; - unsigned int I2S_TXDR; - unsigned int I2S_RXDR; - unsigned int I2S_XFER; - unsigned int I2S_TXRST; - unsigned int I2S_RXRST; -}I2S_REG,*pI2S_REG; -#else -#define I2S_TXR_BUFF 0x24 -#define I2S_RXR_BUFF 0x28 -typedef volatile struct tagIIS_STRUCT -{ - unsigned int I2S_TXCR;//0xF 0 - unsigned int I2S_RXCR;//0xF 4 - unsigned int I2S_CKR;//0x3F 8 - unsigned int I2S_FIFOLR;//c - unsigned int I2S_DMACR;//0x001F0110 10 - unsigned int I2S_INTCR;//0x01F00000 14 - unsigned int I2S_INTSR;//0x00 18 - unsigned int I2S_XFER;//0x00000003 1c - unsigned int I2S_CLR;//20 - unsigned int I2S_TXDR;//24 - unsigned int I2S_RXDR; -}I2S_REG,*pI2S_REG; -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) -extern struct snd_soc_dai_driver rk29_i2s_dai[]; -#else -extern struct snd_soc_dai rk29_i2s_dai[]; -#endif - -#ifdef CONFIG_SND_SOC_RT5631 -extern struct delayed_work rt5631_delay_cap; //bard 7-16 -#endif - -#endif /* _ROCKCHIP_IIS_H */ - diff --git a/sound/soc/rk29/rk29_jetta_codec.c b/sound/soc/rk29/rk29_jetta_codec.c deleted file mode 100755 index 8f39dbaecf5f..000000000000 --- a/sound/soc/rk29/rk29_jetta_codec.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * rk29_wm8988.c -- SoC audio for rockchip - * - * Driver for rockchip wm8988 audio - * - * 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 -#include -#include -#include -#include -#include -#include "../codecs/rk610_codec.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" -#ifdef CONFIG_MACH_RK_FAC -#include -extern int codec_type; -#endif - -#if 0 -#define DBG(x...) printk(KERN_ERR x) -#else -#define DBG(x...) -#endif - -static int rk29_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int ret; - unsigned int pll_out = 0; - int div_bclk,div_mclk; -// struct clk *general_pll; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - /*by Vincent Hsiung for EQ Vol Change*/ - #define HW_PARAMS_FLAG_EQVOL_ON 0x21 - #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 - if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) - { - ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent - } - else - { - /* set codec DAI configuration */ - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - #elif defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #endif - if (ret < 0) - return ret; - /* set cpu DAI configuration */ - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - #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); - #elif 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: - case 96000: - pll_out = 12288000; - break; - case 11025: - case 22050: - case 44100: - case 88200: - pll_out = 11289600; - break; - case 176400: - pll_out = 11289600*2; - break; - case 192000: - pll_out = 12288000*2; - break; - default: - DBG("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(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); - -// #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) -// snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); -// #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - div_bclk = 63; - div_mclk = pll_out/(params_rate(params)*64) - 1; - - DBG("func is%s,pll_out=%d,div_mclk=%d div_bclk\n", - __FUNCTION__,pll_out,div_mclk, div_bclk); - snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk); - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); -// DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); - #endif - return 0; -} - -static struct snd_soc_ops rk29_ops = { - .hw_params = rk29_hw_params, -}; - -static struct snd_soc_dai_link rk29_dai = { - .name = "RK610_CODEC", - .stream_name = "RK610 CODEC PCM", -#if defined(CONFIG_MACH_RK3168_DS1006H)|| defined(CONFIG_MACH_RK3168_LR097) - .codec_name = "RK610_CODEC.4-0060", -#else - .codec_name = "RK610_CODEC.0-0060", -#endif - .platform_name = "rockchip-audio", -#if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", -#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", -#else - .cpu_dai_name = "rk29_i2s.2", -#endif - .codec_dai_name = "rk610_codec", - .ops = &rk29_ops, -}; -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_RK610", - .dai_link = &rk29_dai, - .num_links = 1, -}; - - -static struct platform_device *rk29_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; -#ifdef CONFIG_MACH_RK_FAC - if(codec_type!=CODEC_TYPE_RK616) - return -1; -#endif - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) { - printk("[%s] platform device allocation failed\n", __FUNCTION__); - ret = -ENOMEM; - return ret; - } - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); - - ret = platform_device_add(rk29_snd_device); - if (ret) { - DBG("platform device add failed\n"); - platform_device_put(rk29_snd_device); - } - return ret; -} -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk29_snd_device); -} - -module_init(audio_card_init); -module_exit(audio_card_exit); -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk29/rk29_pcm.c b/sound/soc/rk29/rk29_pcm.c deleted file mode 100755 index 2b1f57bd5358..000000000000 --- a/sound/soc/rk29/rk29_pcm.c +++ /dev/null @@ -1,690 +0,0 @@ -/* - * rk29_pcm.c -- ALSA SoC ROCKCHIP PCM Audio Layer Platform driver - * - * Driver for rockchip pcm audio - * - * - * 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 -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include "rk29_pcm.h" - -#define PCM_DMA_DEBUG 0 - -#if 0 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) do { } while (0) -#endif - -//#define INFIN_LOOP -#ifdef INFIN_LOOP -#define DMA_INFIN_LOOP() rk29_dma_has_infiniteloop() -#else -#define DMA_INFIN_LOOP() 0 -#endif - -static const struct snd_pcm_hardware rockchip_pcm_hardware = { - .info = SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME, - .formats = SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S20_3LE | - SNDRV_PCM_FMTBIT_S16_LE, - .channels_min = 2, - .channels_max = 8, -#ifdef CONFIG_RK_SRAM_DMA - .buffer_bytes_max = 24*1024,//period_bytes_max * periods_max -#else - .buffer_bytes_max = 128*1024, -#endif - .period_bytes_min = 64, ///PAGE_SIZE, -#ifdef CONFIG_RK_SRAM_DMA - .period_bytes_max = 8*1024, -#else - .period_bytes_max = 2048*4,///PAGE_SIZE*2, -#endif - .periods_min = 3,///2, - .periods_max = 128, - .fifo_size = 16, -}; - - -struct rockchip_dma_buf_set { - struct rockchip_dma_buf_set *next; - struct scatterlist sg; -}; - -struct rockchip_runtime_data { - spinlock_t lock; - int state; - int transfer_first; - unsigned int dma_loaded; - unsigned int dma_limit; - unsigned int dma_period; - dma_addr_t dma_start; - dma_addr_t dma_pos; - dma_addr_t dma_end; - struct rockchip_pcm_dma_params *params; - struct rockchip_dma_buf_set *curr; /* current dma buffer set */ - struct rockchip_dma_buf_set *next; /* next buffer set to load */ - struct rockchip_dma_buf_set *end; /* end of queue set*/ -}; - - -/* rockchip_pcm_enqueue - * - * place a dma buffer onto the queue for the dma system - * to handle. -*/ -static void rockchip_pcm_enqueue(struct snd_pcm_substream *substream) -{ - struct rockchip_runtime_data *prtd = substream->runtime->private_data; - dma_addr_t pos = prtd->dma_pos; - unsigned int limit; - int ret; - - DBG("Enter::%s----%d prtd->dma_period = %d prtd->dma_limit = %d\n",__FUNCTION__,__LINE__,prtd->dma_period,prtd->dma_limit); - - if (rk29_dma_has_circular()) - limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period; - else - limit = prtd->dma_limit; - - if (DMA_INFIN_LOOP()) { - if(prtd->dma_period % (prtd->params->dma_size*16)){ - printk("dma_period(%d) is not an integer multiple of dma_size(%d)",prtd->dma_period,prtd->params->dma_size*16); - rk29_dma_config(prtd->params->channel, - prtd->params->dma_size, 1); - } - else - rk29_dma_config(prtd->params->channel, - prtd->params->dma_size, 16); - ret = rk29_dma_enqueue_ring(prtd->params->channel, - substream, pos, prtd->dma_period, limit ,true); - if (ret == 0) - pos = prtd->dma_start; - } else { - while (prtd->dma_loaded < prtd->dma_limit) { - unsigned long len = prtd->dma_period; - // DBG("dma_loaded: %d\n", prtd->dma_loaded); - if ((pos + len) > prtd->dma_end) { - len = prtd->dma_end - pos; - } - - if((len%(prtd->params->dma_size*16) == 0) && (prtd->params->flag == 1)) - { - ret = rk29_dma_config(prtd->params->channel, - prtd->params->dma_size, 16); - prtd->params->flag = 0; - DBG("size = 16, channel = %d, flag = %d\n",prtd->params->channel,prtd->params->flag); - } - else if((len%(prtd->params->dma_size*16) != 0) && (prtd->params->flag == 0)) - { - ret = rk29_dma_config(prtd->params->channel, - prtd->params->dma_size, 1); - prtd->params->flag = 1; - DBG("size = 1, channel = %d, flag = %d\n",prtd->params->channel,prtd->params->flag); - } - - ret = rk29_dma_enqueue(prtd->params->channel,substream, pos, len); - // if(prtd->params->channel == 2) - DBG("Enter::%s, %d, ret=%d, Channel=%d, Addr=0x%X, Len=%lu\n", - __FUNCTION__,__LINE__, ret, prtd->params->channel, pos, len); - if (ret == 0) { - prtd->dma_loaded++; - pos += prtd->dma_period; - if (pos >= prtd->dma_end) - pos = prtd->dma_start; - } else - break; - } - } - prtd->dma_pos = pos; -} - -void rk29_audio_buffdone(void *dev_id, int size, - enum rk29_dma_buffresult result) -{ - struct snd_pcm_substream *substream = dev_id; - struct rockchip_runtime_data *prtd; -#if PCM_DMA_DEBUG - static ktime_t before = {0},after = {0}; - s64 t; - before = after; - after = ktime_get(); - t = ktime_to_us(ktime_sub(after, before)); - if(result == RK29_RES_OK) - { - if(t > prtd->dma_period/4/44100 +73 && t != ktime_to_us(after)) // (23220)4096/4/44100 + 32/44100 - { - printk(KERN_DEBUG "Time out:: Audio DMA buffdone time out!!! the time = %lld!\n", t); - } - printk(KERN_DEBUG "audio DMA callback time = %lld\n", t); - } -// printk(KERN_DEBUG "a %d %d\n", size, result); -#endif - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - if (!substream){ - DBG("substream is free\n"); - return; - } - if (!substream->runtime){ - DBG("substream->runtime is free\n"); - return; - } - switch(result) - { - case RK29_RES_OK: - break; - case RK29_RES_ERR: - case RK29_RES_ABORT: - DBG("Enter::%s dma about or error result = %d \n",__FUNCTION__,result); - return; - } - - prtd = substream->runtime->private_data; - -// if(prtd->params->channel == 2) - DBG("Enter::%s----%d channel =%d \n",__FUNCTION__,__LINE__,prtd->params->channel); - if(!(prtd->state & ST_RUNNING)) - return; - if (substream){ - snd_pcm_period_elapsed(substream); - } - spin_lock(&prtd->lock); - if (!DMA_INFIN_LOOP() && prtd->state & ST_RUNNING) { - prtd->dma_loaded--; - rockchip_pcm_enqueue(substream); - } - spin_unlock(&prtd->lock); -} - -static int rockchip_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct rockchip_runtime_data *prtd = runtime->private_data; - struct snd_soc_pcm_runtime *rtd = substream->private_data; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) - struct rockchip_pcm_dma_params *dma = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) - struct rockchip_pcm_dma_params *dma = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); -#else - struct rockchip_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; -#endif - unsigned long totbytes = params_buffer_bytes(params); - int ret = 0; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - /* return if this is a bufferless transfer e.g. - * codec <--> BT codec or GSM modem -- lg FIXME */ - if (!dma) - return 0; - - /* this may get called several times by oss emulation - * with different params -HW */ - if (prtd->params == NULL) { - /* prepare DMA */ - prtd->params = dma; -#ifdef CONFIG_SND_I2S_DMA_EVENT_DYNAMIC - DBG("params %p, client %p, channel %d\n", prtd->params,prtd->params->client, prtd->params->channel); - ret = rk29_dma_request(prtd->params->channel, prtd->params->client, NULL); - DBG("Enter::%s, %d, ret=%d, Channel=%d\n", __FUNCTION__, __LINE__, ret, prtd->params->channel); - if (ret) { - DBG(KERN_ERR "failed to get dma channel\n"); - return ret; - } -#endif - } - - ret = rk29_dma_set_buffdone_fn(prtd->params->channel, rk29_audio_buffdone); - if(ret < 0){ - DBG(KERN_ERR "failed to rk29_dma_set_buffdone_fn\n"); - return ret; - } - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - - runtime->dma_bytes = totbytes; - - spin_lock_irq(&prtd->lock); - prtd->dma_loaded = 0; - prtd->dma_limit = params_periods(params);//runtime->hw.periods_min; - prtd->dma_period = params_period_bytes(params); - prtd->dma_start = runtime->dma_addr; - prtd->dma_pos = prtd->dma_start; - prtd->dma_end = prtd->dma_start + prtd->dma_limit*prtd->dma_period; - prtd->transfer_first = 1; - prtd->curr = NULL; - prtd->next = NULL; - prtd->end = NULL; - spin_unlock_irq(&prtd->lock); - printk(KERN_DEBUG "i2s dma info:periodsize(%ld),limit(%d),buffersize(%d),over(%d)\n", - prtd->dma_period,prtd->dma_limit,totbytes,totbytes-(prtd->dma_period*prtd->dma_limit)); - return ret; -} - -static int rockchip_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct rockchip_runtime_data *prtd = substream->runtime->private_data; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - /* TODO - do we need to ensure DMA flushed */ - snd_pcm_set_runtime_buffer(substream, NULL); - - if (prtd->params) { -#ifdef CONFIG_SND_I2S_DMA_EVENT_DYNAMIC - rk29_dma_free(prtd->params->channel, prtd->params->client); - prtd->params = NULL; -#endif - } - - return 0; -} - -static int rockchip_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct rockchip_runtime_data *prtd = substream->runtime->private_data; - int ret = 0; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* return if this is a bufferless transfer e.g. - * codec <--> BT codec or GSM modem -- lg FIXME */ - if (!prtd->params) - return 0; - - if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - ret = rk29_dma_devconfig(prtd->params->channel, - RK29_DMASRC_MEM, - prtd->params->dma_addr); - }else{ - ret = rk29_dma_devconfig(prtd->params->channel, - RK29_DMASRC_HW, - prtd->params->dma_addr); - } - DBG("Enter::%s, %d, ret=%d, Channel=%d, Addr=0x%X\n", __FUNCTION__, __LINE__, ret, prtd->params->channel, prtd->params->dma_addr); - ret = rk29_dma_config(prtd->params->channel, - prtd->params->dma_size, 1); - prtd->params->flag = 1; - - DBG("Enter:%s, %d, ret = %d, Channel=%d, Size=%d\n", - __FUNCTION__, __LINE__, ret, prtd->params->channel, - prtd->params->dma_size); - - ret= rk29_dma_ctrl(prtd->params->channel, RK29_DMAOP_FLUSH); - DBG("Enter:%s, %d, ret = %d, Channel=%d\n", - __FUNCTION__, __LINE__, ret, prtd->params->channel); - - prtd->dma_loaded = 0; - prtd->dma_pos = prtd->dma_start; - - /* enqueue dma buffers */ - rockchip_pcm_enqueue(substream); - return ret; -} - -static int rockchip_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct rockchip_runtime_data *prtd = substream->runtime->private_data; - int ret = 0; - /**************add by qiuen for volume*****/ - struct snd_soc_pcm_runtime *rtd = substream->private_data; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) - struct snd_soc_dai *pCodec_dai = rtd->codec_dai; -#else - struct snd_soc_dai *pCodec_dai = rtd->dai->codec_dai; -#endif - int vol = 0; - int streamType = 0; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - if(cmd==SNDRV_PCM_TRIGGER_VOLUME){ - vol = substream->number % 100; - streamType = (substream->number / 100) % 100; - DBG("enter:vol=%d,streamType=%d\n",vol,streamType); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) - if(pCodec_dai->driver->ops->set_volume) - pCodec_dai->driver->ops->set_volume(streamType, vol); -#else - if(pCodec_dai->ops->set_volume) - pCodec_dai->ops->set_volume(streamType, vol); -#endif - } - /****************************************************/ - spin_lock(&prtd->lock); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - DBG(" START \n"); - prtd->state |= ST_RUNNING; - rk29_dma_ctrl(prtd->params->channel, RK29_DMAOP_START); - break; - case SNDRV_PCM_TRIGGER_RESUME: - DBG(" RESUME \n"); - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - DBG(" RESTART \n"); - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - DBG(" STOPS \n"); - prtd->state &= ~ST_RUNNING; - rk29_dma_ctrl(prtd->params->channel, RK29_DMAOP_STOP); - break; - default: - ret = -EINVAL; - break; - } - - spin_unlock(&prtd->lock); - return ret; -} - - -static snd_pcm_uframes_t -rockchip_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct rockchip_runtime_data *prtd = runtime->private_data; - unsigned long res; - dma_addr_t src, dst; - snd_pcm_uframes_t ret; - - - spin_lock(&prtd->lock); - - rk29_dma_getposition(prtd->params->channel, &src, &dst); - - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - res = dst - prtd->dma_start; - else - res = src - prtd->dma_start; - - spin_unlock(&prtd->lock); - - ret = bytes_to_frames(runtime, res); - if (ret == runtime->buffer_size) - ret = 0; - - if(prtd->params->channel == 2) - DBG("Enter:%s src = %x res = %x ret = %d\n",__FUNCTION__,src,res,ret); - - return ret; -} - - -static int rockchip_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct rockchip_runtime_data *prtd; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - snd_soc_set_runtime_hwparams(substream, &rockchip_pcm_hardware); - - prtd = kzalloc(sizeof(struct rockchip_runtime_data), GFP_KERNEL); - if (prtd == NULL) - return -ENOMEM; - - spin_lock_init(&prtd->lock); - - runtime->private_data = prtd; - return 0; -} - -static int rockchip_pcm_close(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct rockchip_runtime_data *prtd = runtime->private_data; - struct rockchip_dma_buf_set *sg_buf = NULL; - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - if (!prtd) { - DBG("rockchip_pcm_close called with prtd == NULL\n"); - return 0; - } - - if (prtd->params) - rk29_dma_set_buffdone_fn(prtd->params->channel, NULL); - sg_buf = prtd->curr; - - while (sg_buf != NULL) { - prtd->curr = sg_buf->next; - prtd->next = sg_buf->next; - sg_buf->next = NULL; - kfree(sg_buf); - sg_buf = NULL; - sg_buf = prtd->curr; - } - kfree(prtd); - - return 0; -} - -static int rockchip_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - -#ifdef CONFIG_RK_SRAM_DMA - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); - return remap_pfn_range(vma, vma->vm_start, - substream->dma_buffer.addr >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, vma->vm_page_prot); -#else - return dma_mmap_writecombine(substream->pcm->card->dev, vma, - runtime->dma_area, - runtime->dma_addr, - runtime->dma_bytes); -#endif -} - -static struct snd_pcm_ops rockchip_pcm_ops = { - .open = rockchip_pcm_open, - .close = rockchip_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = rockchip_pcm_hw_params, - .hw_free = rockchip_pcm_hw_free, - .prepare = rockchip_pcm_prepare, - .trigger = rockchip_pcm_trigger, - .pointer = rockchip_pcm_pointer, - .mmap = rockchip_pcm_mmap, -}; - -#if defined(CONFIG_ARCH_RK3066B) -#elif defined(CONFIG_ARCH_RK30) -#define SRAM_DMA_PHYS_PLAYBACK (dma_addr_t)(RK30_IMEM_PHYS + 16*1024) -#define SRAM_DMA_START_PLAYBACK (RK30_IMEM_NONCACHED + 16*1024) -#define SRAM_DMA_PHYS_CAPTURE (dma_addr_t)(SRAM_DMA_PHYS_PLAYBACK + 24*1024) -#define SRAM_DMA_START_CAPTURE (SRAM_DMA_START_PLAYBACK + 24*1024) -#endif - -static int rockchip_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = rockchip_pcm_hardware.buffer_bytes_max; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; -#ifdef CONFIG_RK_SRAM_DMA - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - buf->area = SRAM_DMA_START_PLAYBACK; - buf->addr = SRAM_DMA_PHYS_PLAYBACK; - } else{ - buf->area = SRAM_DMA_START_CAPTURE; - buf->addr = SRAM_DMA_PHYS_CAPTURE; - } -#else - buf->area = dma_alloc_writecombine(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); -#endif - if (!buf->area) - return -ENOMEM; - buf->bytes = size; - DBG("%s: size %d\n",__FUNCTION__, size); - return 0; -} - -static void rockchip_pcm_free_dma_buffers(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - - dma_free_writecombine(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } -} - -static u64 rockchip_pcm_dmamask = DMA_BIT_MASK(32); - -static int rockchip_pcm_new(struct snd_card *card, - struct snd_soc_dai *dai, struct snd_pcm *pcm) -{ - int ret = 0; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - if (!card->dev->dma_mask) - card->dev->dma_mask = &rockchip_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = 0xffffffff; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) - if (dai->driver->playback.channels_min) { -#else - if (dai->playback.channels_min) { -#endif - ret = rockchip_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - goto out; - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) - if (dai->driver->capture.channels_min) { -#else - if (dai->capture.channels_min) { -#endif - ret = rockchip_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - goto out; - } - out: - return ret; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) -static struct snd_soc_platform_driver rockchip_pcm_platform = { - .ops = &rockchip_pcm_ops, - .pcm_new = rockchip_pcm_new, - .pcm_free = rockchip_pcm_free_dma_buffers, -}; - -static int __devinit rockchip_pcm_platform_probe(struct platform_device *pdev) -{ - DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__); - return snd_soc_register_platform(&pdev->dev, &rockchip_pcm_platform); -} - -static int __devexit rockchip_pcm_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; -} - -static struct platform_driver rockchip_pcm_driver = { - .driver = { - .name = "rockchip-audio", - .owner = THIS_MODULE, - }, - .probe = rockchip_pcm_platform_probe, - .remove = __devexit_p(rockchip_pcm_platform_remove), -}; - -static int __init snd_rockchip_pcm_init(void) -{ - DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__); - return platform_driver_register(&rockchip_pcm_driver); -} -module_init(snd_rockchip_pcm_init); - -static void __exit snd_rockchip_pcm_exit(void) -{ - platform_driver_unregister(&rockchip_pcm_driver); -} -module_exit(snd_rockchip_pcm_exit); -#else -struct snd_soc_platform rk29_soc_platform = { - .name = "rockchip-audio", - .pcm_ops = &rockchip_pcm_ops, - .pcm_new = rockchip_pcm_new, - .pcm_free = rockchip_pcm_free_dma_buffers, -}; -EXPORT_SYMBOL_GPL(rk29_soc_platform); - -static int __init rockchip_soc_platform_init(void) -{ - DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__); - return snd_soc_register_platform(&rk29_soc_platform); -} -module_init(rockchip_soc_platform_init); - -static void __exit rockchip_soc_platform_exit(void) -{ - snd_soc_unregister_platform(&rk29_soc_platform); -} -module_exit(rockchip_soc_platform_exit); -#endif - -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP PCM ASoC Interface"); -MODULE_LICENSE("GPL"); - diff --git a/sound/soc/rk29/rk29_pcm.h b/sound/soc/rk29/rk29_pcm.h deleted file mode 100755 index 62c92e2acba1..000000000000 --- a/sound/soc/rk29/rk29_pcm.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * rockchip-pcm.h - ALSA PCM interface for the Rockchip rk28 SoC - * - * Driver for rockchip iis audio - * - * - * 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 _ROCKCHIP_PCM_H -#define _ROCKCHIP_PCM_H - -#include - -#define ST_RUNNING (1<<0) -#define ST_OPENED (1<<1) - -struct rockchip_pcm_dma_params { - struct rk29_dma_client *client; /* stream identifier */ - int channel; /* Channel ID */ - dma_addr_t dma_addr; - int dma_size; /* Size of the DMA transfer */ - int flag; /*burst change flag*/ -}; - -extern struct snd_soc_platform rk29_soc_platform; - -#endif /* _ROCKCHIP_PCM_H */ diff --git a/sound/soc/rk29/rk29_rk1000codec.c b/sound/soc/rk29/rk29_rk1000codec.c deleted file mode 100755 index a65bfba54617..000000000000 --- a/sound/soc/rk29/rk29_rk1000codec.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * rk29_wm8988.c -- SoC audio for rockchip - * - * Driver for rockchip wm8988 audio - * - * 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 -#include -#include -#include -#include -#include -#include "../codecs/rk1000_codec.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" - -#if 1 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif - -static int rk29_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #endif - if (ret < 0) - return ret; - /* 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; - -//ÉèÖ÷ÖƵ²¿·Ö£¬ÔÝʱδÉèÖà - return 0; -} - -/* - * Logic for a rk1000 codec as connected on a rockchip board. - */ -static int rk29_rk1000_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - return 0; -} - -static struct snd_soc_ops rk29_ops = { - .hw_params = rk29_hw_params, -}; - -static struct snd_soc_dai_link rk29_dai[] = { - { - .name = "RK1000", - .stream_name = "RK1000 CODEC PCM", - .platform_name = "rockchip-audio", - .codec_name = "RK1000_CODEC.0-0060", - .codec_dai_name = "rk1000_codec", -#if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", -#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", -#endif - .init = rk29_rk1000_codec_init, - .ops = &rk29_ops, - } -}; - -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_RK1000", - .dai_link = rk29_dai, - .num_links = 1, -}; - - -static struct platform_device *rk29_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) { - printk("platform device allocation failed\n"); - ret = -ENOMEM; - return ret; - } - - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); - ret = platform_device_add(rk29_snd_device); - if (ret) { - printk("platform device add failed\n"); - platform_device_put(rk29_snd_device); - } - printk("audio_card_init end....\n"); - return ret; -} - -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk29_snd_device); -} - -module_init(audio_card_init); -module_exit(audio_card_exit); -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk29/rk29_rt3261.c b/sound/soc/rk29/rk29_rt3261.c deleted file mode 100644 index 639ffcf139c0..000000000000 --- a/sound/soc/rk29/rk29_rt3261.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * rk29_rt3261.c -- SoC audio for rockchip - * - * Driver for rockchip rt3261 audio - * - * 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 -#include -#include -#include -#include -#include - -#include "../codecs/rt3261.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" - - -#if 0 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif - -static int rk29_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - /*by Vincent Hsiung for EQ Vol Change*/ - #define HW_PARAMS_FLAG_EQVOL_ON 0x21 - #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 - if (codec_dai->driver->ops->hw_params && ((params->flags == HW_PARAMS_FLAG_EQVOL_ON) || (params->flags == HW_PARAMS_FLAG_EQVOL_OFF))) - { - ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - } else { - - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #endif - if (ret < 0) - return ret; - - /* 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: - DBG("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)); - - /*Set the system clk for codec*/ - snd_soc_dai_set_pll(codec_dai, 0, RT3261_PLL1_S_MCLK, pll_out, pll_out*2); //bard 8-29 - ret = snd_soc_dai_set_sysclk(codec_dai, RT3261_SCLK_S_PLL1, pll_out*2, SND_SOC_CLOCK_IN); //bard 8-29 - if (ret < 0) - { - DBG("rk29_hw_params_rt3261:failed to set the sysclk for codec side\n"); - return ret; - } - - 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);// 256k = 48-1 3M=3 - - DBG("Enter:%s, %d, pll_out/4/params_rate(params) = %d \n", __FUNCTION__, __LINE__, (pll_out/4)/params_rate(params)); - - return 0; -} - -static int rt3261_voice_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS ); - - 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: - DBG("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)); - - /*Set the system clk for codec*/ - snd_soc_dai_set_pll(codec_dai, 0, RT3261_PLL1_S_MCLK, pll_out, pll_out*2); //bard 8-29 - ret = snd_soc_dai_set_sysclk(codec_dai, RT3261_SCLK_S_PLL1, pll_out*2, SND_SOC_CLOCK_IN); //bard 8-29 - - - if (ret < 0) { - printk("rk29_hw_params_rt3261:failed to set the sysclk for codec side\n"); - return ret; - } - - 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 const struct snd_soc_dapm_widget rt3261_dapm_widgets[] = { - SND_SOC_DAPM_MIC("Mic Jack", NULL), - SND_SOC_DAPM_MIC("Headset Jack", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_HP("Headphone Jack", NULL), -}; - -static const struct snd_soc_dapm_route audio_map[]={ - - /* Mic Jack --> MIC_IN*/ - {"micbias1", NULL, "Mic Jack"}, - {"MIC1", NULL, "micbias1"}, - - // HP MIC - {"micbias1", NULL, "Headset Jack"}, - {"MIC3", NULL, "micbias1"}, - - {"Ext Spk", NULL, "SPOLP"}, - {"Ext Spk", NULL, "SPOLN"}, - {"Ext Spk", NULL, "SPORP"}, - {"Ext Spk", NULL, "SPORN"}, - - {"Headphone Jack", NULL, "HPOL"}, - {"Headphone Jack", NULL, "HPOR"}, -} ; - -static const struct snd_kcontrol_new rk_controls[] = { - SOC_DAPM_PIN_SWITCH("Mic Jack"), - SOC_DAPM_PIN_SWITCH("Headset Jack"), - SOC_DAPM_PIN_SWITCH("Ext Spk"), - SOC_DAPM_PIN_SWITCH("Headphone Jack"), -}; - -/* - * Logic for a rt3261 as connected on a rockchip board. - */ -static int rk29_rt3261_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - snd_soc_add_controls(codec, rk_controls, - ARRAY_SIZE(rk_controls)); - - /* Add specific widgets */ - snd_soc_dapm_new_controls(dapm, rt3261_dapm_widgets, - ARRAY_SIZE(rt3261_dapm_widgets)); - /* Set up specific audio path audio_mapnects */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - snd_soc_dapm_enable_pin(dapm, "Headset Jack"); - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); -#ifdef CONFIG_HDMI - extern int hdmi_is_insert(void); - extern void codec_set_spk(bool on); - if(hdmi_is_insert()) - codec_set_spk(false); -#endif - -#ifdef CONFIG_HDMI_RK30 - extern int hdmi_get_hotplug(void); - if(hdmi_get_hotplug() == 2/*HDMI_HPD_ACTIVED*/) - codec_set_spk(false); -#endif - - snd_soc_dapm_sync(dapm); - - return 0; -} - -static struct snd_soc_ops rk29_ops = { - .hw_params = rk29_hw_params, -}; - -static struct snd_soc_ops rt3261_voice_ops = { - .hw_params = rt3261_voice_hw_params, -}; - -static struct snd_soc_dai_link rk29_dai[] = { - { - .name = "RT3261 I2S1", - .stream_name = "RT3261 PCM", - .codec_name = "rt3261.0-001c", - .platform_name = "rockchip-audio", - #if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", - #elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", - #endif - .codec_dai_name = "rt3261-aif1", - .init = rk29_rt3261_init, - .ops = &rk29_ops, - }, - { - .name = "RT3261 I2S2", - .stream_name = "RT3261 PCM", - .codec_name = "rt3261.0-001c", - .platform_name = "rockchip-audio", - #if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", - #elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", - #endif - .codec_dai_name = "rt3261-aif2", - .ops = &rt3261_voice_ops, - }, -}; - -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_RT3261", - .dai_link = rk29_dai, - .num_links = 2, -}; - -static struct platform_device *rk29_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) { - printk("platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); - ret = platform_device_add(rk29_snd_device); - if (ret) { - printk("platform device add failed\n"); - - platform_device_put(rk29_snd_device); - return ret; - } - - return ret; -} - -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk29_snd_device); -} - -module_init(audio_card_init); -module_exit(audio_card_exit); -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk29/rk29_rt5512.c b/sound/soc/rk29/rk29_rt5512.c deleted file mode 100755 index 0d30236738e8..000000000000 --- a/sound/soc/rk29/rk29_rt5512.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - * odroid_rt5512.c - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include "rk29_pcm.h" -#include "rk29_i2s.h" -#if 1 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif - -#include "../codecs/rt5512.h" - -static struct platform_device *rk29_snd_device; - - -static int rk29_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - unsigned int pll_div; - 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; - - - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #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; - case 96000: - case 192000: - pll_out = 12288000*2; - break; - case 88200: - case 176400: - pll_out = 11289600*2; - break; - default: - DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); - return -EINVAL; - break; - } -#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, 64-1);//bclk = 2*32*lrck; 2*32fs - switch(params_rate(params)) { - case 176400: - case 192000: - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 1); - DBG("Enter:%s, %d, MCLK=%d BCLK=%d LRCK=%d\n", - __FUNCTION__,__LINE__,pll_out,pll_out/2,params_rate(params)); - break; - default: - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3); - DBG("default:%s, %d, MCLK=%d BCLK=%d LRCK=%d\n", - __FUNCTION__,__LINE__,pll_out,pll_out/4,params_rate(params)); - break; - } - - /*Set the system clk for codec*/ - ret=snd_soc_dai_set_sysclk(codec_dai, 0,pll_out,SND_SOC_CLOCK_IN); - if (ret < 0) - { - DBG("rk29_hw_params_rt5631:failed to set the sysclk for codec side\n"); - return ret; - } - - switch (params_rate(params)) - { - case 8000: - pll_div = 12; - break; - case 16000: - pll_div = 6; - break; - case 32000: - pll_div = 3; - break; - case 48000: - pll_div = 2; - break; - case 96000: - pll_div = 1; - break; - case 11025: - pll_div = 8; - break; - case 22050: - pll_div = 4; - break; - case 44100: - pll_div = 2; - break; - case 88200: - pll_div = 1; - break; - default: - printk("Not yet supported!\n"); - return -EINVAL; - } - ret = snd_soc_dai_set_clkdiv(codec_dai, RT5512_CLK_DIV_ID, pll_div*4); - if (ret < 0) - return ret; -#endif - -#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - //snd_soc_dai_set_pll(codec_dai,0,pll_out, 22579200); - snd_soc_dai_set_sysclk(codec_dai,0,pll_out, SND_SOC_CLOCK_IN); -#endif - return 0; -} - -//--------------------------------------------------------------------------------- -/* - * rt5512 DAI operations. - */ -static struct snd_soc_ops rk29_ops = { - .hw_params = rk29_hw_params, -}; - -static const struct snd_soc_dapm_widget rt5512_dapm_widgets[] = { - // Input - SND_SOC_DAPM_MIC("Main Mic", NULL), - SND_SOC_DAPM_LINE("LineIn", NULL), - // Output - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_HP("Headphone Jack", NULL), -}; - -static const struct snd_soc_dapm_route rt5512_audio_map[] = { - // Input - {"MicBias1", NULL,"Main Mic"}, - {"Mic2", NULL, "MicBias1"}, - {"MicBias2", NULL, "LineIn"}, - {"Aux", NULL, "MicBias2"}, - // Output - {"Ext Spk", NULL, "LSpeaker"}, - {"Ext Spk", NULL, "RSpeaker"}, - {"Headphone Jack", NULL, "LHeadphone"}, - {"Headphone Jack", NULL, "RHeadphone"}, -}; - -#if 0 - -static struct snd_soc_jack rk29_soc_jack; - - - -static struct snd_soc_jack_gpio odroid_soc_jack_gpio[] = { - { - .gpio = 28, - .name "headset event", - .report = SND_JACK_HEADSET, - .debounce_time = 200, - }, -}; -#endif - -#if 0 -static int rt5512_headset_keys(struct snd_soc_jack *jack) -{ - int err = 0; - - err = snd_jack_set_key(jack->jack, SND_JACK_BTN_0, 0x80); - if (err) - return err; - - err = snd_jack_set_key(jack->jack, SND_JACK_BTN_1, 0x81); - if (err) - return err; - - err = snd_jack_set_key(jack->jack, SND_JACK_BTN_2, 0x82); - if (err) - return err; - - return 0; -} -#endif - -static int rt5512_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - //struct rt5512_codec_chip *chip = snd_soc_codec_get_drvdata(codec); - //int err = 0; - - snd_soc_dapm_new_controls(dapm, rt5512_dapm_widgets, - ARRAY_SIZE(rt5512_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, rt5512_audio_map, - ARRAY_SIZE(rt5512_audio_map)); -#if FOR_MID - snd_soc_dapm_disable_pin(dapm, "Main Mic"); - snd_soc_dapm_disable_pin(dapm, "LineIn"); - snd_soc_dapm_disable_pin(dapm, "Ext Spk"); - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); -#endif - -#if 0 - if (!chip->rt_jack) - { - err = snd_soc_jack_new(codec, "Headset Jack" , SND_JACK_HEADSET, &rk29_soc_jack); - if (err) - return err; - - #if 0 - // How-to use gpio, just declare snd_soc_jack_gpios, then it will - // help you to register a interrupt and set wakeup, and delayed schedule - // work - err = snd_soc_jack_add_gpios(&odroid_soc_jack, gpio_count, odroid_soc_jack_gpios); - if (err) - return err; - - // If use this, when trigger, just use snd_soc_jack_get_type - // then snd_soc_jack_report to send the event to upper layer - err = snd_soc_jack_add_zones(&odroid_soc_jack, zone_count, tcc_soc_zones); - if (err) - return err; - #endif - - err = rt5512_headset_keys(&rk29_soc_jack); - if (err) - return err; - - chip->rt_jack = &rk29_soc_jack; - } -#endif - snd_soc_dapm_sync(dapm); - return 0; -} - -static struct snd_soc_dai_link rk29_dai[] = { - { /* Primary DAI i/f */ - .name = "RT5512 AIF1", - .stream_name = "RT5512 PCM", - .cpu_dai_name = "rk29_i2s.1", - .codec_dai_name = "RT5512-aif1", - .platform_name = "rockchip-audio", - .codec_name = "rt5512.1-0018", - .init = rt5512_init, - .ops = &rk29_ops, - }, -}; - -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_RT5512", - .dai_link = rk29_dai, - - /* If you want to use sec_fifo device, - * changes the num_link = 2 or ARRAY_SIZE(odroid_dai). */ - .num_links = ARRAY_SIZE(rk29_dai), -}; - -static int __init audio_card_init(void) -{ - int ret; - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) - return -ENOMEM; - - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); - - ret = platform_device_add(rk29_snd_device); - if (ret) - platform_device_put(rk29_snd_device); - - return ret; -} -module_init(audio_card_init); - -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk29_snd_device); -} -module_exit(audio_card_exit); - -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_AUTHOR("cy_huang "); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk29/rk29_rt5616.c b/sound/soc/rk29/rk29_rt5616.c deleted file mode 100755 index 8dcd265345ff..000000000000 --- a/sound/soc/rk29/rk29_rt5616.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * rk29_rt5631.c -- SoC audio for rockchip - * - * Driver for rockchip rt5631 audio - * - * 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 -#include -#include -#include -#include -#include -#include "../codecs/rt5631.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" - -#if 0 -:#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif - -static int rk29_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - /*by Vincent Hsiung for EQ Vol Change*/ - #define HW_PARAMS_FLAG_EQVOL_ON 0x21 - #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 - if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) - { - ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - } - else - { - - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #endif - if (ret < 0) - return ret; - - /* 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: - DBG("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)); - - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) -#if 0 //use pll from blck - /*Set the pll of rt5631,the Pll source from BITCLK on CPU is master mode*/ - //bitclk is 64fs - ret=snd_soc_dai_set_pll(codec_dai,0,params_rate(params)*64,pll_out); - if (ret < 0) - { - DBG("rk29_hw_params_rt5631:failed to set the pll for codec side\n"); - return ret; - } -#endif - /*Set the system clk for codec*/ - ret=snd_soc_dai_set_sysclk(codec_dai, 0,pll_out,SND_SOC_CLOCK_IN); - if (ret < 0) - { - DBG("rk29_hw_params_rt5631:failed to set the sysclk for codec side\n"); - return ret; - } - #endif - - - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - - // snd_soc_dai_set_pll(codec_dai,0,pll_out, 22579200); - snd_soc_dai_set_sysclk(codec_dai,0,pll_out, SND_SOC_CLOCK_IN); - - #endif - - - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - 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); - #endif - - DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); - - return 0; -} - -static const struct snd_soc_dapm_widget rt5631_dapm_widgets[] = { - - SND_SOC_DAPM_MIC("Mic Jack", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_HP("Headphone Jack", NULL), - -}; - -static const struct snd_soc_dapm_route audio_map[]={ - - /* Mic Jack --> MIC_IN*/ - {"Mic Bias1", NULL, "Mic Jack"}, - {"MIC1", NULL, "Mic Bias1"}, - /* HP_OUT --> Headphone Jack */ - {"Headphone Jack", NULL, "HPOL"}, - {"Headphone Jack", NULL, "HPOR"}, - /* LINE_OUT --> Ext Speaker */ - {"Ext Spk", NULL, "SPOL"}, - {"Ext Spk", NULL, "SPOR"}, - -} ; - -/* - * Logic for a rt5631 as connected on a rockchip board. - */ -static int rk29_rt5631_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* Add specific widgets */ - snd_soc_dapm_new_controls(dapm, rt5631_dapm_widgets, - ARRAY_SIZE(rt5631_dapm_widgets)); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - /* Set up specific audio path audio_mapnects */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - snd_soc_dapm_nc_pin(dapm, "HP_L"); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - snd_soc_dapm_nc_pin(dapm, "HP_R"); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - snd_soc_dapm_sync(dapm); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - return 0; -} - -static struct snd_soc_ops rk29_ops = { - .hw_params = rk29_hw_params, -}; - -static struct snd_soc_dai_link rk29_dai = { - .name = "rt5616", - .stream_name = "rt5616 PCM", - .codec_name = "rt5616.4-001b", - .platform_name = "rockchip-audio", -#if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", -#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", -#else - .cpu_dai_name = "rk29_i2s.2", -#endif - .codec_dai_name = "rt5616-aif1", - .init = rk29_rt5631_init, - .ops = &rk29_ops, -}; - -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_RT5616", - .dai_link = &rk29_dai, - .num_links = 1, -}; - -static struct platform_device *rk29_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) { - printk("platform device allocation failed\n"); - ret = -ENOMEM; - return ret; - } - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); - ret = platform_device_add(rk29_snd_device); - if (ret) { - printk("platform device add failed\n"); - platform_device_put(rk29_snd_device); - } - return ret; -} - -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk29_snd_device); -} - -module_init(audio_card_init); -module_exit(audio_card_exit); -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); - diff --git a/sound/soc/rk29/rk29_rt5621.c b/sound/soc/rk29/rk29_rt5621.c deleted file mode 100644 index dca3e849a3bc..000000000000 --- a/sound/soc/rk29/rk29_rt5621.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * rk29_rt5621.c -- SoC audio for rockchip - * - * Driver for rockchip rt5621 audio - * - * 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 -#include -#include -#include -#include -#include -#include -#include "../codecs/rt5621.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" - -#if 0 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif - -static int rk29_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - unsigned int lrclk = 0; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /*by Vincent Hsiung for EQ Vol Change*/ - #define HW_PARAMS_FLAG_EQVOL_ON 0x21 - #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 - if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) - { - ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - } else { - /* set codec DAI configuration */ -#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); -#endif -#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); -#endif - if (ret < 0) - return ret; - /* 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: - DBG("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)); - -#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) -#if 0 //use pll from blck - /*Set the pll of rt5621,the Pll source from BITCLK on CPU is master mode*/ - //bitclk is 64fs - ret=snd_soc_dai_set_pll(codec_dai,RT5621_PLL_FR_BCLK,params_rate(params)*64,pll_out); - if (ret < 0) { - DBG("rk29_hw_params_rt5621:failed to set the pll for codec side\n"); - return ret; - } -#endif - /*Set the system clk for codec*/ - ret=snd_soc_dai_set_sysclk(codec_dai, 0,pll_out,SND_SOC_CLOCK_IN); - if (ret < 0) { - DBG("rk29_hw_params_rt5621:failed to set the sysclk for codec side\n"); - return ret; - } -#endif - - - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - - if((24576000%params_rate(params))==0) //for 8k,16k,32k,48k - { - snd_soc_dai_set_pll(codec_dai,RT5621_PLL_FR_MCLK,pll_out, 24576000); - snd_soc_dai_set_sysclk(codec_dai,0, 24576000, SND_SOC_CLOCK_IN); - } - else if((22579200%params_rate(params))==0) //for 11k,22k,44k - { - snd_soc_dai_set_pll(codec_dai,RT5621_PLL_FR_MCLK,pll_out, 22579200); - snd_soc_dai_set_sysclk(codec_dai,0, 22579200, SND_SOC_CLOCK_IN); - } - -#endif - - -#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - 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); -#endif - - DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); - - return 0; -} - -static const struct snd_soc_dapm_widget rt5621_dapm_widgets[] = { - - SND_SOC_DAPM_MIC("Mic Jack", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_HP("Headphone Jack", NULL), - -}; - -static const struct snd_soc_dapm_route audio_map[]={ - - /* Mic Jack --> MIC_IN*/ - {"Mic Bias1", NULL, "Mic Jack"}, - {"MIC1", NULL, "Mic Bias1"}, - /* HP_OUT --> Headphone Jack */ - {"Headphone Jack", NULL, "HPOL"}, - {"Headphone Jack", NULL, "HPOR"}, - /* LINE_OUT --> Ext Speaker */ - {"Ext Spk", NULL, "SPOL"}, - {"Ext Spk", NULL, "SPOR"}, - -} ; - -/* - * Logic for a rt5621 as connected on a rockchip board. - */ -static int rk29_rt5621_init(struct snd_soc_pcm_runtime *rtd) -{ - return 0; -} - -static struct snd_soc_ops rk29_ops = { - .hw_params = rk29_hw_params, -}; - -static struct snd_soc_dai_link rk29_dai = { - .name = "RT5621", - .stream_name = "RT5621 PCM", - .codec_name = "RT5621.0-001a", - .platform_name = "rockchip-audio", - .cpu_dai_name = "rk29_i2s.0", - .codec_dai_name = "RT5621 HiFi", - .init = rk29_rt5621_init, - .ops = &rk29_ops, -}; - -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_RT5621", - .dai_link = &rk29_dai, - .num_links = 1, -}; - -static struct platform_device *rk29_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; - - //rk29_speaker = rk29_speaker_init(RK29_PIN6_PB6, GPIO_HIGH, 2, (200*1000*1000)); - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) { - DBG("platform device allocation failed\n"); - ret = -ENOMEM; - return ret; - } - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); - ret = platform_device_add(rk29_snd_device); - if (ret) { - DBG("platform device add failed\n"); - platform_device_put(rk29_snd_device); - return ret; - } - return ret; -} - -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk29_snd_device); -} - -module_init(audio_card_init); -module_exit(audio_card_exit); -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk29/rk29_rt5625.c b/sound/soc/rk29/rk29_rt5625.c deleted file mode 100644 index 9a72e440ceb4..000000000000 --- a/sound/soc/rk29/rk29_rt5625.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * rk29_rt5625.c -- SoC audio for rockchip - * - * Driver for rockchip rt5625 audio - * - * 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 -#include -#include -#include -#include -#include -#include -#include "../codecs/rt5625.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" - -#if 1 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif - -static int rk29_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - /*by Vincent Hsiung for EQ Vol Change*/ - #define HW_PARAMS_FLAG_EQVOL_ON 0x21 - #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 - if (codec_dai->driver->ops->hw_params && ((params->flags == HW_PARAMS_FLAG_EQVOL_ON) || (params->flags == HW_PARAMS_FLAG_EQVOL_OFF))) - { - ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - } else { - - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #endif - if (ret < 0) - return ret; - - /* 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: - DBG("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)); - - /*Set the system clk for codec*/ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); - if (ret < 0) - { - DBG("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); - return ret; - } - - 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 int rt5625_voice_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* set codec DAI configuration */ - //#if defined (CONFIG_SND_CODEC_SOC_SLAVE) - DBG("Enter::%s----codec slave\n",__FUNCTION__); - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS); - /*#endif - //#if defined (CONFIG_SND_CODEC_SOC_MASTER) - DBG("Enter::%s----codec master\n",__FUNCTION__); - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #endif*/ - - 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: - DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params)); - return -EINVAL; - break; - } - - snd_soc_dai_set_pll(codec_dai, RT5625_PLL_MCLK_TO_VSYSCLK, 0, pll_out, 24576000); - - /*Set the system clk for codec*/ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 24576000, SND_SOC_CLOCK_IN); - - if (ret < 0) { - printk("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); - return ret; - } - - ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - - return 0; -} - -static struct snd_soc_ops rk29_ops = { - .hw_params = rk29_hw_params, -}; - -static struct snd_soc_ops rt5625_voice_ops = { - .hw_params = rt5625_voice_hw_params, -}; - -static struct snd_soc_dai_link rk29_dai[] = { - { - .name = "RT5625 I2S1", - .stream_name = "RT5625 PCM", - .codec_name = "rt5625.0-001f", - .platform_name = "rockchip-audio", - .cpu_dai_name = "rk29_i2s.0", - .codec_dai_name = "rt5625-aif1", - .ops = &rk29_ops, - }, - { - .name = "RT5625 I2S2", - .stream_name = "RT5625 PCM", - .codec_name = "rt5625.0-001f", - .platform_name = "rockchip-audio", - .cpu_dai_name = "rk29_i2s.0", - .codec_dai_name = "rt5625-aif2", - .ops = &rt5625_voice_ops, - }, -}; - -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_RT5625", - .dai_link = rk29_dai, - .num_links = 2, -}; - -static struct platform_device *rk29_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) { - printk("platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); - ret = platform_device_add(rk29_snd_device); - if (ret) { - printk("platform device add failed\n"); - - platform_device_put(rk29_snd_device); - return ret; - } - - return ret; -} - -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk29_snd_device); -} - -module_init(audio_card_init); -module_exit(audio_card_exit); -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk29/rk29_rt5631.c b/sound/soc/rk29/rk29_rt5631.c deleted file mode 100755 index c230f63fc58a..000000000000 --- a/sound/soc/rk29/rk29_rt5631.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * rk29_rt5631.c -- SoC audio for rockchip - * - * Driver for rockchip rt5631 audio - * - * 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 -#include -#include -#include -#include -#include -#include "../codecs/rt5631.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" - -#ifdef CONFIG_MACH_RK_FAC -#include -extern int codec_type; -#endif -#if 0 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif - -static int rk29_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - /*by Vincent Hsiung for EQ Vol Change*/ - #define HW_PARAMS_FLAG_EQVOL_ON 0x21 - #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 - if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) - { - ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - } - else - { - - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #endif - if (ret < 0) - return ret; - - /* 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; - case 96000: - case 192000: - pll_out = 12288000*2; - break; - case 88200: - case 176400: - pll_out = 11289600*2; - break; - default: - DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); - return -EINVAL; - break; - } -#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, 64-1);//bclk = 2*32*lrck; 2*32fs - switch(params_rate(params)) { - case 176400: - case 192000: - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 1); - DBG("Enter:%s, %d, MCLK=%d BCLK=%d LRCK=%d\n", - __FUNCTION__,__LINE__,pll_out,pll_out/2,params_rate(params)); - break; - default: - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3); - DBG("default:%s, %d, MCLK=%d BCLK=%d LRCK=%d\n", - __FUNCTION__,__LINE__,pll_out,pll_out/4,params_rate(params)); - break; - } - -#if 0 //use pll from blck - /*Set the pll of rt5631,the Pll source from BITCLK on CPU is master mode*/ - //bitclk is 64fs - ret=snd_soc_dai_set_pll(codec_dai,0,params_rate(params)*64,pll_out); - if (ret < 0) - { - DBG("rk29_hw_params_rt5631:failed to set the pll for codec side\n"); - return ret; - } -#endif - /*Set the system clk for codec*/ - ret=snd_soc_dai_set_sysclk(codec_dai, 0,pll_out,SND_SOC_CLOCK_IN); - if (ret < 0) - { - DBG("rk29_hw_params_rt5631:failed to set the sysclk for codec side\n"); - return ret; - } -#endif - -#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - //snd_soc_dai_set_pll(codec_dai,0,pll_out, 22579200); - snd_soc_dai_set_sysclk(codec_dai,0,pll_out, SND_SOC_CLOCK_IN); -#endif - return 0; -} - -static const struct snd_soc_dapm_widget rt5631_dapm_widgets[] = { - - SND_SOC_DAPM_MIC("Mic Jack", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_HP("Headphone Jack", NULL), - -}; - -static const struct snd_soc_dapm_route audio_map[]={ - - /* Mic Jack --> MIC_IN*/ - {"Mic Bias1", NULL, "Mic Jack"}, - {"MIC1", NULL, "Mic Bias1"}, - /* HP_OUT --> Headphone Jack */ - {"Headphone Jack", NULL, "HPOL"}, - {"Headphone Jack", NULL, "HPOR"}, - /* LINE_OUT --> Ext Speaker */ - {"Ext Spk", NULL, "SPOL"}, - {"Ext Spk", NULL, "SPOR"}, - -} ; - -/* - * Logic for a rt5631 as connected on a rockchip board. - */ -static int rk29_rt5631_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* Add specific widgets */ - snd_soc_dapm_new_controls(dapm, rt5631_dapm_widgets, - ARRAY_SIZE(rt5631_dapm_widgets)); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - /* Set up specific audio path audio_mapnects */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - snd_soc_dapm_nc_pin(dapm, "HP_L"); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - snd_soc_dapm_nc_pin(dapm, "HP_R"); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - snd_soc_dapm_sync(dapm); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - return 0; -} - -static struct snd_soc_ops rk29_ops = { - .hw_params = rk29_hw_params, -}; - -static struct snd_soc_dai_link rk29_dai = { - .name = "RT5631", - .stream_name = "RT5631 PCM", - .codec_name = "RT5631.0-001a", - .platform_name = "rockchip-audio", -#if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", -#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", -#else - .cpu_dai_name = "rk29_i2s.2", -#endif - .codec_dai_name = "RT5631 HiFi", - .init = rk29_rt5631_init, - .ops = &rk29_ops, -}; - -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_RT5631", - .dai_link = &rk29_dai, - .num_links = 1, -}; - -static struct platform_device *rk29_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; - -#ifdef CONFIG_MACH_RK_FAC - if(codec_type!=CODEC_TYPE_RT5631) - return -1; -#endif - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) { - printk("platform device allocation failed\n"); - ret = -ENOMEM; - return ret; - } - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); - ret = platform_device_add(rk29_snd_device); - if (ret) { - printk("platform device add failed\n"); - platform_device_put(rk29_snd_device); - } - return ret; -} - -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk29_snd_device); -} - -module_init(audio_card_init); -module_exit(audio_card_exit); -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); - diff --git a/sound/soc/rk29/rk29_rt5631_phone.c b/sound/soc/rk29/rk29_rt5631_phone.c deleted file mode 100755 index 84cb83bdc068..000000000000 --- a/sound/soc/rk29/rk29_rt5631_phone.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * rk29_rt5631.c -- SoC audio for rockchip - * - * Driver for rockchip rt5631 audio - * - * 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 -#include -#include -#include -#include -#include -#include "../codecs/rt5631_phone.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" - -#if 1 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif - -static int rk29_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #endif - if (ret < 0) - return ret; - - /* 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: - DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); - return -EINVAL; - } - DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); - - snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - /*Set the system clk for codec*/ - ret=snd_soc_dai_set_sysclk(codec_dai, 0,pll_out,SND_SOC_CLOCK_IN); - if (ret < 0) - { - DBG("rk29_hw_params_rt5631:failed to set the sysclk for codec side\n"); - return ret; - } - 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); - #endif - - - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - snd_soc_dai_set_sysclk(codec_dai,0,pll_out, SND_SOC_CLOCK_IN); - #endif - - DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); - - return 0; -} - -static int rk29_hw_params_voice(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - //change to 8Khz - params->intervals[SNDRV_PCM_HW_PARAM_RATE - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].min = 8000; - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #endif - if (ret < 0) - return ret; - - /* 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; - pll_out = 2048000; - break; - default: - DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); - return -EINVAL; - } - DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); - - snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - /*Set the system clk for codec*/ - ret=snd_soc_dai_set_sysclk(codec_dai, 0,pll_out,SND_SOC_CLOCK_IN); - if (ret < 0) - { - DBG("rk29_hw_params_rt5631:failed to set the sysclk for codec side\n"); - return ret; - } - 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); - #endif - - - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - snd_soc_dai_set_sysclk(codec_dai,0,pll_out, SND_SOC_CLOCK_IN); - #endif - - DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); - - return 0; -} - -static const struct snd_soc_dapm_widget rt5631_dapm_widgets[] = { - - SND_SOC_DAPM_MIC("Mic Jack", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_HP("Headphone Jack", NULL), - -}; - -static const struct snd_soc_dapm_route audio_map[]={ - {"Headphone Jack", NULL, "HPOL"}, - {"Headphone Jack", NULL, "HPOR"}, - {"Ext Spk", NULL, "SPOL"}, - {"Ext Spk", NULL, "SPOR"}, - {"MIC1", NULL, "MIC Bias1"}, - {"MIC Bias1", NULL, "Mic Jack"}, -} ; -//bard 7-5 s -static const struct snd_kcontrol_new rk29_controls[] = { - SOC_DAPM_PIN_SWITCH("Mic Jack"), - SOC_DAPM_PIN_SWITCH("Ext Spk"), - SOC_DAPM_PIN_SWITCH("Headphone Jack"), -}; -//bard 7-5 e -/* - * Logic for a rt5631 as connected on a rockchip board. - */ -static int rk29_rt5631_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); -//bard 7-5 s - snd_soc_add_controls(codec, rk29_controls, - ARRAY_SIZE(rk29_controls)); -//bard 7-5 e - /* Add specific widgets */ - snd_soc_dapm_new_controls(dapm, rt5631_dapm_widgets, - ARRAY_SIZE(rt5631_dapm_widgets)); - /* Set up specific audio path audio_mapnects */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); -// snd_soc_dapm_nc_pin(dapm, "MONO"); -// snd_soc_dapm_nc_pin(dapm, "MONOIN_RXN"); -// snd_soc_dapm_nc_pin(dapm, "MONOIN_RXP"); - snd_soc_dapm_nc_pin(dapm, "DMIC"); - snd_soc_dapm_sync(dapm); - - return 0; -} - -static struct snd_soc_ops rk29_ops = { - .hw_params = rk29_hw_params, -}; -static struct snd_soc_ops rk29_ops_voice = { - .hw_params = rk29_hw_params_voice, -}; - -static struct snd_soc_dai_link rk29_dai[] = { - { - .name = "RT5631 hifi", - .stream_name = "RT5631 hifi stream", - .codec_name = "RT5631.0-001a", - .platform_name = "rockchip-audio", - #if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", - #elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", - #else - .cpu_dai_name = "rk29_i2s.2", - #endif - .codec_dai_name = "RT5631 HiFi", - .init = rk29_rt5631_init, - .ops = &rk29_ops, - }, - { - .name = "RT5631 voice", - .stream_name = "RT5631 voice stream", - .codec_name = "RT5631.0-001a", - .platform_name = "rockchip-audio", - #if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", - #elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", - #else - .cpu_dai_name = "rk29_i2s.2", - #endif - .codec_dai_name = "rt5631-voice", - .ops = &rk29_ops_voice, - }, -}; - -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_RT5631", - .dai_link = rk29_dai, - .num_links = 2, -}; - -static struct platform_device *rk29_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) { - printk("platform device allocation failed\n"); - ret = -ENOMEM; - return ret; - } - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); - ret = platform_device_add(rk29_snd_device); - if (ret) { - printk("platform device add failed\n"); - platform_device_put(rk29_snd_device); - } - return ret; -} - -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk29_snd_device); -} - -module_init(audio_card_init); -module_exit(audio_card_exit); -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); - diff --git a/sound/soc/rk29/rk29_rt5639.c b/sound/soc/rk29/rk29_rt5639.c deleted file mode 100755 index 79ae984acc29..000000000000 --- a/sound/soc/rk29/rk29_rt5639.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * rk29_rt5625.c -- SoC audio for rockchip - * - * Driver for rockchip rt5625 audio - * - * 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 -#include -#include -#include -#include -#include - -#include "../codecs/rt3261.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" - -#if 1 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif - -static int rk29_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - /*by Vincent Hsiung for EQ Vol Change*/ - #define HW_PARAMS_FLAG_EQVOL_ON 0x21 - #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 - if (codec_dai->driver->ops->hw_params && ((params->flags == HW_PARAMS_FLAG_EQVOL_ON) || (params->flags == HW_PARAMS_FLAG_EQVOL_OFF))) - { - ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - } else { - - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #endif - if (ret < 0) - return ret; - - /* 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: - DBG("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)); - - /*Set the system clk for codec*/ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); - if (ret < 0) - { - DBG("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); - return ret; - } - - 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 int rt3261_voice_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* set codec DAI configuration */ - //#if defined (CONFIG_SND_CODEC_SOC_SLAVE) - DBG("Enter::%s----codec slave\n",__FUNCTION__); - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS); - /*#endif - //#if defined (CONFIG_SND_CODEC_SOC_MASTER) - DBG("Enter::%s----codec master\n",__FUNCTION__); - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #endif*/ - - 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: - DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params)); - return -EINVAL; - break; - } - - //snd_soc_dai_set_pll(codec_dai, RT5625_PLL_MCLK_TO_VSYSCLK, 0, pll_out, 24576000);??????? - - /*Set the system clk for codec*/ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 24576000, SND_SOC_CLOCK_IN); - - if (ret < 0) { - printk("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); - return ret; - } - - ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - - return 0; -} - -static struct snd_soc_ops rk29_ops = { - .hw_params = rk29_hw_params, -}; - -static struct snd_soc_ops rt5639_voice_ops = { - .hw_params = rt3261_voice_hw_params, -}; - -static struct snd_soc_dai_link rk29_dai[] = { - { - .name = "RT5639 I2S1", - .stream_name = "RT5639 PCM", - .codec_name = "rt5639.0-001c", - .platform_name = "rockchip-audio", - .cpu_dai_name = "rk29_i2s.0", - .codec_dai_name = "rt5639-aif1", - .ops = &rk29_ops, - }, - { - .name = "RT5639 I2S2", - .stream_name = "RT5639 PCM", - .codec_name = "rt5639.0-001c", - .platform_name = "rockchip-audio", - .cpu_dai_name = "rk29_i2s.0", - .codec_dai_name = "rt5639-aif2", - .ops = &rt5639_voice_ops, - }, -}; - -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_RT5639", - .dai_link = rk29_dai, - .num_links = 2, -}; - -static struct platform_device *rk29_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) { - printk("platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); - ret = platform_device_add(rk29_snd_device); - if (ret) { - printk("platform device add failed\n"); - - platform_device_put(rk29_snd_device); - return ret; - } - - return ret; -} - -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk29_snd_device); -} - -module_init(audio_card_init); -module_exit(audio_card_exit); -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk29/rk29_rt5640.c b/sound/soc/rk29/rk29_rt5640.c deleted file mode 100755 index bd29c1ed144a..000000000000 --- a/sound/soc/rk29/rk29_rt5640.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * rk29_rt3261.c -- SoC audio for rockchip - * - * Driver for rockchip rt3261 audio - * - * 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 -#include -#include -#include -#include -#include - -#include "../codecs/rt3261.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" - - -#if 0 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif - -static int rk29_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - /*by Vincent Hsiung for EQ Vol Change*/ - #define HW_PARAMS_FLAG_EQVOL_ON 0x21 - #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 - if (codec_dai->driver->ops->hw_params && ((params->flags == HW_PARAMS_FLAG_EQVOL_ON) || (params->flags == HW_PARAMS_FLAG_EQVOL_OFF))) - { - ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - } else { - - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #endif - if (ret < 0) - return ret; - - /* 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: - DBG("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)); - - /*Set the system clk for codec*/ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); - if (ret < 0) - { - DBG("rk29_hw_params_rt3261:failed to set the sysclk for codec side\n"); - return ret; - } - - 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 int rt3261_voice_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS ); - - 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: - DBG("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)); - - /*Set the system clk for codec*/ - snd_soc_dai_set_pll(codec_dai, 0, RT3261_PLL1_S_MCLK, pll_out, 24576000); - - ret = snd_soc_dai_set_sysclk(codec_dai, RT3261_SCLK_S_PLL1, 24576000, SND_SOC_CLOCK_IN); - - - if (ret < 0) { - printk("rk29_hw_params_rt3261:failed to set the sysclk for codec side\n"); - return ret; - } - - 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 const struct snd_soc_dapm_widget rt3261_dapm_widgets[] = { - SND_SOC_DAPM_MIC("Mic Jack", NULL), - SND_SOC_DAPM_MIC("Headset Jack", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_HP("Headphone Jack", NULL), -}; - -static const struct snd_soc_dapm_route audio_map[]={ - - /* Mic Jack --> MIC_IN*/ - {"micbias1", NULL, "Mic Jack"}, - {"MIC1", NULL, "micbias1"}, - - // HP MIC - {"micbias1", NULL, "Headset Jack"}, - {"MIC3", NULL, "micbias1"}, - - {"Ext Spk", NULL, "SPOLP"}, - {"Ext Spk", NULL, "SPOLN"}, - {"Ext Spk", NULL, "SPORP"}, - {"Ext Spk", NULL, "SPORN"}, - - {"Headphone Jack", NULL, "HPOL"}, - {"Headphone Jack", NULL, "HPOR"}, -} ; - -static const struct snd_kcontrol_new rk_controls[] = { - SOC_DAPM_PIN_SWITCH("Mic Jack"), - SOC_DAPM_PIN_SWITCH("Headset Jack"), - SOC_DAPM_PIN_SWITCH("Ext Spk"), - SOC_DAPM_PIN_SWITCH("Headphone Jack"), -}; - -/* - * Logic for a rt3261 as connected on a rockchip board. - */ -static int rk29_rt3261_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - snd_soc_add_controls(codec, rk_controls, - ARRAY_SIZE(rk_controls)); - - /* Add specific widgets */ - snd_soc_dapm_new_controls(dapm, rt3261_dapm_widgets, - ARRAY_SIZE(rt3261_dapm_widgets)); - /* Set up specific audio path audio_mapnects */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - snd_soc_dapm_enable_pin(dapm, "Headset Jack"); - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); -#ifdef CONFIG_HDMI - extern int hdmi_is_insert(void); - extern void codec_set_spk(bool on); - if(hdmi_is_insert()) - codec_set_spk(false); -#endif - -#ifdef CONFIG_HDMI_RK30 - extern int hdmi_get_hotplug(void); - if(hdmi_get_hotplug() == 2/*HDMI_HPD_ACTIVED*/) - codec_set_spk(false); -#endif - - snd_soc_dapm_sync(dapm); - - return 0; -} - -static struct snd_soc_ops rk29_ops = { - .hw_params = rk29_hw_params, -}; - -static struct snd_soc_ops rt3261_voice_ops = { - .hw_params = rt3261_voice_hw_params, -}; - -static struct snd_soc_dai_link rk29_dai[] = { - { - .name = "RT5640 I2S1", - .stream_name = "RT5640 PCM", - .codec_name = "rt5640.0-001c", - .platform_name = "rockchip-audio", - #if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.1", - #elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", - #endif - .codec_dai_name = "rt5640-aif1", - .init = rk29_rt3261_init, - .ops = &rk29_ops, - }, - { - .name = "RT5640 I2S2", - .stream_name = "RT5640 PCM", - .codec_name = "rt5640.0-001c", - .platform_name = "rockchip-audio", - #if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.1", - #elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", - #endif - .codec_dai_name = "rt5640-aif2", - .ops = &rt3261_voice_ops, - }, -}; - -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_RT5640", - .dai_link = rk29_dai, - .num_links = 2, -}; - -static struct platform_device *rk29_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) { - printk("platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); - ret = platform_device_add(rk29_snd_device); - if (ret) { - printk("platform device add failed\n"); - - platform_device_put(rk29_snd_device); - return ret; - } - - return ret; -} - -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk29_snd_device); -} - -module_init(audio_card_init); -module_exit(audio_card_exit); -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk29/rk29_wm8900.c b/sound/soc/rk29/rk29_wm8900.c deleted file mode 100755 index aca84583eac8..000000000000 --- a/sound/soc/rk29/rk29_wm8900.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - * rk29_wm8900.c -- SoC audio for rockchip - * - * Driver for rockchip wm8900 audio - * - * 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 -#include -#include -#include -#include -#include -#include -#include "../codecs/wm8900.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" -#include - -#if 0 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif - -static int rk29_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -#else - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; -#endif - unsigned int pll_out = 0; - int div_bclk,div_mclk; - int ret; - struct clk *general_pll; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - /*by Vincent Hsiung for EQ Vol Change*/ - #define HW_PARAMS_FLAG_EQVOL_ON 0x21 - #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 - if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) - { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) - ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent -#else - ret = codec_dai->ops->hw_params(substream, params, codec_dai); //by Vincent -#endif - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - } - else - { - - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #endif - if (ret < 0) - return ret; - - /* 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: - DBG("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)); - - //pll_out = 12000000; - //snd_soc_dai_set_pll(codec_dai, NULL, 12000000, pll_out); - snd_soc_dai_set_clkdiv(codec_dai, WM8900_LRCLK_MODE, 0x000); - - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - snd_soc_dai_set_clkdiv(codec_dai, WM8900_BCLK_DIV, WM8900_BCLK_DIV_4); - snd_soc_dai_set_clkdiv(codec_dai, WM8900_DAC_LRCLK,(pll_out/4)/params_rate(params)); - snd_soc_dai_set_clkdiv(codec_dai, WM8900_ADC_LRCLK,(pll_out/4)/params_rate(params)); - #endif - - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - general_pll=clk_get(NULL, "general_pll"); - if(clk_get_rate(general_pll)>260000000) - { - div_bclk=(pll_out/4)/params_rate(params)-1; - div_mclk=3; - } - else if(clk_get_rate(general_pll)>130000000) - { - div_bclk=(pll_out/2)/params_rate(params)-1; - div_mclk=1; - } - else - { - pll_out=pll_out/4; - div_bclk=(pll_out)/params_rate(params)-1; - div_mclk=0; - } - DBG("func is%s,gpll=%ld,pll_out=%u,div_mclk=%d\n", - __FUNCTION__,clk_get_rate(general_pll),pll_out,div_mclk); - snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk); - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); - #endif - DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); - - return 0; -} - -static const struct snd_soc_dapm_widget wm8900_dapm_widgets[] = { - SND_SOC_DAPM_LINE("Audio Out", NULL), - SND_SOC_DAPM_LINE("Line in", NULL), - SND_SOC_DAPM_MIC("Micn", NULL), - SND_SOC_DAPM_MIC("Micp", NULL), -}; - -static const struct snd_soc_dapm_route audio_map[]= { - - {"Audio Out", NULL, "HP_L"}, - {"Audio Out", NULL, "HP_R"}, - {"Line in", NULL, "RINPUT1"}, - {"Line in", NULL, "LINPUT1"}, - {"Micn", NULL, "RINPUT2"}, - {"Micp", NULL, "LINPUT2"}, -}; - -/* - * Logic for a wm8900 as connected on a rockchip board. - */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) -static int rk29_wm8900_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* Add specific widgets */ - snd_soc_dapm_new_controls(dapm, wm8900_dapm_widgets, - ARRAY_SIZE(wm8900_dapm_widgets)); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - /* Set up specific audio path audio_mapnects */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - snd_soc_dapm_nc_pin(dapm, "HP_L"); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - snd_soc_dapm_nc_pin(dapm, "HP_R"); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - snd_soc_dapm_sync(dapm); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - return 0; -} -#else -static int rk29_wm8900_init(struct snd_soc_codec *codec) -{ - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* Add specific widgets */ - snd_soc_dapm_new_controls(codec, wm8900_dapm_widgets, - ARRAY_SIZE(wm8900_dapm_widgets)); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - /* Set up specific audio path audio_mapnects */ - snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - snd_soc_dapm_nc_pin(codec, "HP_L"); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - snd_soc_dapm_nc_pin(codec, "HP_R"); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - snd_soc_dapm_sync(codec); - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - return 0; -} -#endif - -static struct snd_soc_ops rk29_ops = { - .hw_params = rk29_hw_params, -}; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) -static struct snd_soc_dai_link rk29_dai = { - .name = "WM8900", - .stream_name = "WM8900 PCM", - .codec_name = "WM8900.0-001a", - .platform_name = "rockchip-audio", - .cpu_dai_name = "rk29_i2s.0", - .codec_dai_name = "WM8900 HiFi", - .init = rk29_wm8900_init, - .ops = &rk29_ops, -}; -#else -static struct snd_soc_dai_link rk29_dai = { - .name = "WM8900", - .stream_name = "WM8900 PCM", - .cpu_dai = &rk29_i2s_dai[0], - .codec_dai = &wm8900_dai, - .init = rk29_wm8900_init, - .ops = &rk29_ops, -}; -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_WM8900", - .dai_link = &rk29_dai, - .num_links = 1, -}; -#else -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_WM8900", - .platform = &rk29_soc_platform, - .dai_link = &rk29_dai, - .num_links = 1, -}; - - -static struct snd_soc_card rk29_snd_devdata = { - .card = &snd_soc_card_rk29, - .codec_dev = &soc_codec_dev_wm8900, -}; -#endif - -static struct platform_device *rk29_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) { - DBG("platform device allocation failed\n"); - ret = -ENOMEM; - return ret; - } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); -#else - platform_set_drvdata(rk29_snd_device, &rk29_snd_devdata); - rk29_snd_devdata.dev = &rk29_snd_device->dev; -#endif - ret = platform_device_add(rk29_snd_device); - if (ret) { - DBG("platform device add failed\n"); - platform_device_put(rk29_snd_device); - } - return ret; -} - -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk29_snd_device); -} - -module_init(audio_card_init); -module_exit(audio_card_exit); -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk29/rk29_wm8988.c b/sound/soc/rk29/rk29_wm8988.c deleted file mode 100755 index e9abd89e43b5..000000000000 --- a/sound/soc/rk29/rk29_wm8988.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * rk29_wm8988.c -- SoC audio for rockchip - * - * Driver for rockchip wm8988 audio - * - * 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 -#include -#include -#include -#include -#include -#include -#include "../codecs/wm8988.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" - -#include - -#if 0 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif - -//static void *rk29_speaker = NULL; - -static int rk29_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - /*by Vincent Hsiung for EQ Vol Change*/ - #define HW_PARAMS_FLAG_EQVOL_ON 0x21 - #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 - if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) - { - ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - } - else - { - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #endif - if (ret < 0) - return ret; - /* 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; - } - - return 0; -} - -static const struct snd_soc_dapm_widget rk29_dapm_widgets[] = { - SND_SOC_DAPM_LINE("Audio Out", NULL), - SND_SOC_DAPM_LINE("Line in", NULL), - SND_SOC_DAPM_MIC("Micn", NULL), - SND_SOC_DAPM_MIC("Micp", NULL), -}; - -static const struct snd_soc_dapm_route audio_map[]= { - - {"Audio Out", NULL, "LOUT1"}, - {"Audio Out", NULL, "ROUT1"}, - {"Line in", NULL, "RINPUT1"}, - {"Line in", NULL, "LINPUT1"}, - {"Micn", NULL, "RINPUT2"}, - {"Micp", NULL, "LINPUT2"}, -}; - -/* - * Logic for a wm8988 as connected on a rockchip board. - */ -static int rk29_wm8988_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - ret = snd_soc_dai_set_sysclk(codec_dai, 0, - /*12000000*/11289600, SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "Failed to set WM8988 SYSCLK: %d\n", ret); - return ret; - } - - /* Add specific widgets */ - snd_soc_dapm_new_controls(dapm, rk29_dapm_widgets, - ARRAY_SIZE(rk29_dapm_widgets)); - //snd_soc_dapm_nc_pin(codec, "LOUT2"); - //snd_soc_dapm_nc_pin(codec, "ROUT2"); - - /* Set up specific audio path audio_mapnects */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - snd_soc_dapm_sync(dapm); - - return 0; -} - -static struct snd_soc_ops rk29_ops = { - .hw_params = rk29_hw_params, -}; - -static struct snd_soc_dai_link rk29_dai = { - .name = "WM8988", - .stream_name = "WM8988 PCM", - .codec_name = "WM8988.0-001a", - .platform_name = "rockchip-audio", - .cpu_dai_name = "rk29_i2s.0", - .codec_dai_name = "WM8988 HiFi", - .init = rk29_wm8988_init, - .ops = &rk29_ops, -}; - -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_WM8988", - .dai_link = &rk29_dai, - .num_links = 1, -}; - -static struct platform_device *rk29_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; - - //rk29_speaker = rk29_speaker_init(RK29_PIN6_PB6, GPIO_HIGH, 2, (200*1000*1000)); - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) { - DBG("platform device allocation failed\n"); - ret = -ENOMEM; - return ret; - } - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); - ret = platform_device_add(rk29_snd_device); - if (ret) { - DBG("platform device add failed\n"); - platform_device_put(rk29_snd_device); - return ret; - } - - return ret; -} -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk29_snd_device); - //rk29_speaker_deinit(rk29_speaker); -} - -module_init(audio_card_init); -module_exit(audio_card_exit); -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk29/rk29_wm8994.c b/sound/soc/rk29/rk29_wm8994.c deleted file mode 100755 index 1b43a84ba760..000000000000 --- a/sound/soc/rk29/rk29_wm8994.c +++ /dev/null @@ -1,450 +0,0 @@ -/* - * rk29_wm8994.c -- SoC audio for rockchip - * - * Driver for rockchip wm8994 audio - * Copyright (C) 2009 lhh - * - * 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 -#include -#include -#include -#include -#include -#include "../codecs/wm8994.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" -#include - -#if 0 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif - -static int rk29_aif1_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int div_bclk,div_mclk; - int ret; - struct clk *general_pll; - - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* set codec DAI configuration */ -#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - DBG("Set codec_dai slave\n"); - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); -#endif -#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); - DBG("Set codec_dai master\n"); -#endif - if (ret < 0) - return ret; - - /* set cpu DAI configuration */ -#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - DBG("Set cpu_dai master\n"); - 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); - DBG("Set cpu_dai slave\n"); -#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: - DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); - return -EINVAL; - } - -// DBG("Enter:%s, %d, rate=%d,pll_out = %d\n",__FUNCTION__,__LINE__,params_rate(params),pll_out); -#ifdef CONFIG_ARCH_RK29 - general_pll=clk_get(NULL, "general_pll"); - if(clk_get_rate(general_pll)>260000000) - { - div_bclk=(pll_out/4)/params_rate(params)-1; - div_mclk=3; - } - else if(clk_get_rate(general_pll)>130000000) - { - div_bclk=(pll_out/2)/params_rate(params)-1; - div_mclk=1; - } - else - {//96M - pll_out=pll_out/4; - div_bclk=(pll_out)/params_rate(params)-1; - div_mclk=0; - } -#else - div_bclk=(pll_out/4)/params_rate(params)-1; - div_mclk=3; -#endif - - DBG("func is%s,gpll=%ld,pll_out=%d,div_mclk=%d\n",__FUNCTION__,clk_get_rate(general_pll),pll_out,div_mclk); - ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - if(ret < 0) - { - DBG("rk29_hw_params_wm8994:failed to set the cpu sysclk for codec side\n"); - return ret; - } - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk); - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); - DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); - - if(div_mclk== 3) - {//MCLK == 11289600 or 12288000 - ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK1, pll_out, 0); - if (ret < 0) { - DBG("rk29_hw_params_wm8994:failed to set the sysclk for codec side\n"); - return ret; - } - } - else - { - /* set the codec FLL */ - ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1, pll_out, - params_rate(params) * 256); - if (ret < 0) - { - printk("%s: snd_soc_dai_set_pll err =%d\n",__FUNCTION__,ret); - return ret; - } - /* set the codec system clock */ - ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, - params_rate(params) * 256, SND_SOC_CLOCK_IN); - if (ret < 0) - { - printk("%s: snd_soc_dai_set_sysclk err =%d\n",__FUNCTION__,ret); - return ret; - } - } - - return 0; -} - -static int rk29_aif2_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int div_bclk,div_mclk; - int ret; - struct clk *general_pll; - - //change to 8Khz -// params->intervals[SNDRV_PCM_HW_PARAM_RATE - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].min = 8000; - - DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); - -// if (params_rate(params) != 8000) -// return -EINVAL; - - /* set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) - { - printk("%s: snd_soc_dai_set_fmt err =%d\n",__FUNCTION__,ret); - 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: - DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); - return -EINVAL; - } - - general_pll=clk_get(NULL, "general_pll"); - if(clk_get_rate(general_pll)>260000000) - { - div_bclk=(pll_out/4)/params_rate(params)-1; - div_mclk=3; - } - else if(clk_get_rate(general_pll)>130000000) - { - div_bclk=(pll_out/2)/params_rate(params)-1; - div_mclk=1; - } - else - {//96M - pll_out=pll_out/4; - div_bclk=(pll_out)/params_rate(params)-1; - div_mclk=0; - } - - DBG("func is%s,gpll=%ld,pll_out=%d,div_mclk=%d\n", - __FUNCTION__,clk_get_rate(general_pll),pll_out,div_mclk); - - ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - if(ret < 0) - { - DBG("rk29_hw_params_wm8994:failed to set the cpu sysclk for codec side\n"); - return ret; - } - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk); - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); - DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); - - /* set the codec FLL */ - ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, WM8994_FLL_SRC_MCLK1, pll_out, - 8000 * 256); - if (ret < 0) - { - printk("%s: snd_soc_dai_set_pll err =%d\n",__FUNCTION__,ret); - return ret; - } - /* set the codec system clock */ - ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2, - 8000 * 256, SND_SOC_CLOCK_IN); - if (ret < 0) - { - printk("%s: snd_soc_dai_set_sysclk err =%d\n",__FUNCTION__,ret); - return ret; - } - - return ret; -} - - -static const struct snd_soc_dapm_widget rk29_dapm_widgets[] = { - SND_SOC_DAPM_SPK("Ext Left Spk", NULL), - SND_SOC_DAPM_SPK("Ext Right Spk", NULL), - SND_SOC_DAPM_SPK("Ext Rcv", NULL), - SND_SOC_DAPM_HP("Headset Stereophone", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_MIC("Main Mic", NULL), - SND_SOC_DAPM_MIC("2nd Mic", NULL), -// SND_SOC_DAPM_LINE("Radio In", NULL), - SND_SOC_DAPM_LINE("Line In", NULL), - SND_SOC_DAPM_LINE("Line Out", NULL), - -}; - -static const struct snd_soc_dapm_route rk29_dapm_routes[] = { - {"Ext Left Spk", NULL, "SPKOUTLP"}, - {"Ext Left Spk", NULL, "SPKOUTLN"}, - - {"Ext Right Spk", NULL, "SPKOUTRP"}, - {"Ext Right Spk", NULL, "SPKOUTRN"}, - - {"Ext Rcv", NULL, "HPOUT2N"}, - {"Ext Rcv", NULL, "HPOUT2P"}, - - {"Headset Stereophone", NULL, "HPOUT1L"}, - {"Headset Stereophone", NULL, "HPOUT1R"}, - - {"IN1LN", NULL, "Headset Mic"}, - {"IN1LP", NULL, "Headset Mic"}, - - {"IN1LN", NULL, "2nd Mic"}, - {"IN1LP", NULL, "2nd Mic"}, - - {"IN1RN", NULL, "Main Mic"}, - {"IN1RP", NULL, "Main Mic"}, - -// {"IN2LN", NULL, "Radio In"}, -// {"IN2RN", NULL, "Radio In"}, - - {"IN2LP:VXRN", NULL, "Line In"}, - {"IN2RP:VXRP", NULL, "Line In"}, - - {"Line Out", NULL, "LINEOUT1N"}, - {"Line Out", NULL, "LINEOUT1P"}, - -}; - -static int rk29_wm8994_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; -// int ret; - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* add goni specific widgets */ - snd_soc_dapm_new_controls(dapm, rk29_dapm_widgets, - ARRAY_SIZE(rk29_dapm_widgets)); - - /* set up goni specific audio routes */ - snd_soc_dapm_add_routes(dapm, rk29_dapm_routes, - ARRAY_SIZE(rk29_dapm_routes)); - - /* set endpoints to not connected */ -// snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN"); -// snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP"); - snd_soc_dapm_nc_pin(dapm, "IN2LN"); - snd_soc_dapm_nc_pin(dapm, "IN2RN"); -// snd_soc_dapm_nc_pin(dapm, "LINEOUT1N"); -// snd_soc_dapm_nc_pin(dapm, "LINEOUT1P"); - snd_soc_dapm_nc_pin(dapm, "LINEOUT2N"); - snd_soc_dapm_nc_pin(dapm, "LINEOUT2P"); -#ifdef CONFIG_HDMI -extern int hdmi_is_insert(void); -extern void codec_set_spk(bool on); - if(hdmi_is_insert()) - codec_set_spk(false); -#endif - snd_soc_dapm_sync(dapm); - - /* Headset jack detection */ -/* ret = snd_soc_jack_new(codec, "Headset Jack", - SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT, - &jack); - if (ret) - return ret; - - ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins); - if (ret) - return ret; - - ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios); - if (ret) - return ret; -*/ - return 0; -} - - -static struct snd_soc_ops rk29_aif1_ops = { - .hw_params = rk29_aif1_hw_params, -}; - -static struct snd_soc_ops rk29_aif2_ops = { - .hw_params = rk29_aif2_hw_params, -}; - -static struct snd_soc_dai_driver voice_dai = { - .name = "rk29-voice-dai", - .id = 0, - .playback = { - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .capture = { - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, -}; - -static struct snd_soc_dai_link rk29_dai[] = { - { - .name = "WM8994 I2S1", - .stream_name = "WM8994 PCM", - .codec_name = "wm8994-codec", - .platform_name = "rockchip-audio", -#if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", -#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", -#endif - .codec_dai_name = "wm8994-aif1", - .ops = &rk29_aif1_ops, - .init = rk29_wm8994_init, - }, - { - .name = "WM8994 I2S2", - .stream_name = "WM8994 PCM", - .codec_name = "wm8994-codec", - .platform_name = "rockchip-audio", -#if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", -#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", -#endif - .codec_dai_name = "wm8994-aif2", - .ops = &rk29_aif2_ops, - }, -}; - -static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_WM8994", - .dai_link = rk29_dai, - .num_links = ARRAY_SIZE(rk29_dai), -}; - -static struct platform_device *rk29_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - rk29_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk29_snd_device) { - printk("platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29); - ret = platform_device_add(rk29_snd_device); - if (ret) { - printk("platform device add failed\n"); - // snd_soc_unregister_dai(&rk29_snd_device->dev); - platform_device_put(rk29_snd_device); - return ret; - } - - return ret; -} - -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk29_snd_device); -} - -module_init(audio_card_init); -module_exit(audio_card_exit); -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk29/rk30_i2s.c b/sound/soc/rk29/rk30_i2s.c deleted file mode 100755 index 117aa5456f48..000000000000 --- a/sound/soc/rk29/rk30_i2s.c +++ /dev/null @@ -1,929 +0,0 @@ -/* - * rk29_i2s.c -- ALSA SoC ROCKCHIP IIS Audio Layer Platform driver - * - * Driver for rockchip iis audio - * - * - * 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 -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "rk29_pcm.h" -#include "rk29_i2s.h" - -#define ANDROID_REC -#if 0 -#define I2S_DBG(x...) printk(KERN_INFO x) -#else -#define I2S_DBG(x...) do { } while (0) -#endif - -#define pheadi2s ((pI2S_REG)(i2s->regs)) - -#define MAX_I2S 3 - -struct rk29_i2s_info { - struct device *dev; - void __iomem *regs; - - u32 feature; - - struct clk *iis_clk; - struct clk *iis_pclk; - - unsigned char master; - - struct rockchip_pcm_dma_params *dma_playback; - struct rockchip_pcm_dma_params *dma_capture; - - u32 suspend_iismod; - u32 suspend_iiscon; - u32 suspend_iispsr; - - bool i2s_tx_status;//active = true; - bool i2s_rx_status; - spinlock_t spinlock_wr;//write read reg spin_lock -}; - -static struct snd_soc_dai *rk_cpu_dai=NULL; -static struct rk29_dma_client rk29_dma_client_out = { - .name = "I2S PCM Stereo Out" -}; - -static struct rk29_dma_client rk29_dma_client_in = { - .name = "I2S PCM Stereo In" -}; - -static inline struct rk29_i2s_info *to_info(struct snd_soc_dai *cpu_dai) -{ - return snd_soc_dai_get_drvdata(cpu_dai); -} - -static struct rockchip_pcm_dma_params rk29_i2s_pcm_stereo_out[MAX_I2S]; -static struct rockchip_pcm_dma_params rk29_i2s_pcm_stereo_in[MAX_I2S]; -static struct rk29_i2s_info rk29_i2s[MAX_I2S]; - -struct snd_soc_dai_driver rk29_i2s_dai[MAX_I2S]; -EXPORT_SYMBOL_GPL(rk29_i2s_dai); -#if defined (CONFIG_RK_HDMI) && defined (CONFIG_SND_RK_SOC_HDMI_I2S) -extern int hdmi_get_hotplug(void); -#endif -/* - *Turn on or off the transmission path. - */ -static void rockchip_snd_txctrl(struct rk29_i2s_info *i2s, int on) -{ - u32 opr,xfer,clr; - spin_lock(&i2s->spinlock_wr); - opr = readl(&(pheadi2s->I2S_DMACR)); - xfer = readl(&(pheadi2s->I2S_XFER)); - clr = readl(&(pheadi2s->I2S_CLR)); - if (on) - { - I2S_DBG("rockchip_snd_txctrl: on\n"); - if ((opr & I2S_TRAN_DMA_ENABLE) == 0) - { - opr |= I2S_TRAN_DMA_ENABLE; - writel(opr, &(pheadi2s->I2S_DMACR)); - } - if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0) - { - xfer |= I2S_TX_TRAN_START; - xfer |= I2S_RX_TRAN_START; - writel(xfer, &(pheadi2s->I2S_XFER)); - } - i2s->i2s_tx_status = true; - spin_unlock(&i2s->spinlock_wr); - } - else - { - //stop tx - i2s->i2s_tx_status = false; - I2S_DBG("rockchip_snd_txctrl: off\n"); - opr &= ~I2S_TRAN_DMA_ENABLE; - writel(opr, &(pheadi2s->I2S_DMACR)); - if(!i2s->i2s_tx_status && !i2s->i2s_rx_status//sync stop i2s rx tx lcrk -#if defined (CONFIG_RK_HDMI) && defined (CONFIG_SND_RK_SOC_HDMI_I2S) - && hdmi_get_hotplug() == 0 //HDMI_HPD_REMOVED -#endif - ) - { - xfer &= ~I2S_TX_TRAN_START; - xfer &= ~I2S_RX_TRAN_START; - writel(xfer, &(pheadi2s->I2S_XFER)); - clr |= I2S_TX_CLEAR; - clr |= I2S_RX_CLEAR; - writel(clr, &(pheadi2s->I2S_CLR)); - spin_unlock(&i2s->spinlock_wr); - udelay(1); - I2S_DBG("rockchip_snd_txctrl: stop xfer\n"); - } - else - spin_unlock(&i2s->spinlock_wr); - } -} - -static void rockchip_snd_rxctrl(struct rk29_i2s_info *i2s, int on) -{ - u32 opr,xfer,clr; - spin_lock(&i2s->spinlock_wr); - opr = readl(&(pheadi2s->I2S_DMACR)); - xfer = readl(&(pheadi2s->I2S_XFER)); - clr = readl(&(pheadi2s->I2S_CLR)); - if (on) - { - I2S_DBG("rockchip_snd_rxctrl: on\n"); - if ((opr & I2S_RECE_DMA_ENABLE) == 0) - { - opr |= I2S_RECE_DMA_ENABLE; - writel(opr, &(pheadi2s->I2S_DMACR)); - } - if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0) - { - xfer |= I2S_RX_TRAN_START; - xfer |= I2S_TX_TRAN_START; - writel(xfer, &(pheadi2s->I2S_XFER)); - } - i2s->i2s_rx_status = true; - spin_unlock(&i2s->spinlock_wr); -#ifdef CONFIG_SND_SOC_RT5631 -//bard 7-16 s - schedule_delayed_work(&rt5631_delay_cap,HZ/4); -//bard 7-16 e -#endif - } - else - { - i2s->i2s_rx_status = false; - I2S_DBG("rockchip_snd_rxctrl: off\n"); - opr &= ~I2S_RECE_DMA_ENABLE; - writel(opr, &(pheadi2s->I2S_DMACR)); - if(!i2s->i2s_tx_status && !i2s->i2s_rx_status //sync stop i2s rx tx lcrk -#if defined (CONFIG_RK_HDMI) && defined (CONFIG_SND_RK_SOC_HDMI_I2S) - && hdmi_get_hotplug() == 0 //HDMI_HPD_REMOVED -#endif - ) - { - xfer &= ~I2S_RX_TRAN_START; - xfer &= ~I2S_TX_TRAN_START; - writel(xfer, &(pheadi2s->I2S_XFER)); - clr |= I2S_RX_CLEAR; - clr |= I2S_TX_CLEAR; - writel(clr, &(pheadi2s->I2S_CLR)); - spin_unlock(&i2s->spinlock_wr); - udelay(1); - I2S_DBG("rockchip_snd_rxctrl: stop xfer\n"); - } - else - spin_unlock(&i2s->spinlock_wr); - } -} - -/* - * Set Rockchip I2S DAI format - */ -static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - struct rk29_i2s_info *i2s = to_info(cpu_dai); - u32 tx_ctl,rx_ctl; - u32 iis_ckr_value;//clock generation register - - I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - spin_lock(&i2s->spinlock_wr); - tx_ctl = readl(&(pheadi2s->I2S_TXCR)); - iis_ckr_value = readl(&(pheadi2s->I2S_CKR)); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - iis_ckr_value &= ~I2S_MODE_MASK; - iis_ckr_value |= I2S_MASTER_MODE; - break; - case SND_SOC_DAIFMT_CBS_CFS: - iis_ckr_value &= ~I2S_MODE_MASK; - iis_ckr_value |= I2S_SLAVE_MODE; - break; - default: - I2S_DBG("unknwon master/slave format\n"); - return -EINVAL; - } - writel(iis_ckr_value, &(pheadi2s->I2S_CKR)); - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_RIGHT_J: - tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode - tx_ctl |= I2S_BUS_MODE_RSJM; - break; - case SND_SOC_DAIFMT_LEFT_J: - tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode - tx_ctl |= I2S_BUS_MODE_LSJM; - break; - case SND_SOC_DAIFMT_I2S: - tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode - tx_ctl |= I2S_BUS_MODE_NOR; - break; - default: - I2S_DBG("Unknown data format\n"); - return -EINVAL; - } - I2S_DBG("Enter::%s----%d, I2S_TXCR=0x%X\n",__FUNCTION__,__LINE__,tx_ctl); - - writel(tx_ctl, &(pheadi2s->I2S_TXCR)); - - rx_ctl = tx_ctl & 0x00007FFF; - writel(rx_ctl, &(pheadi2s->I2S_RXCR)); - spin_unlock(&i2s->spinlock_wr); - return 0; -} - -static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *socdai) -{ - struct rk29_i2s_info *i2s = to_info(socdai); - u32 iismod; - u32 dmarc; - u32 iis_ckr_value;//clock generation register - - I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - snd_soc_dai_set_dma_data(socdai, substream, i2s->dma_playback); - else - snd_soc_dai_set_dma_data(socdai, substream, i2s->dma_capture); - - /* Working copies of register */ - spin_lock(&i2s->spinlock_wr); - iismod = readl(&(pheadi2s->I2S_TXCR)); - - iismod &= (~((1<<5)-1)); - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S8: - iismod |= SAMPLE_DATA_8bit; - break; - case SNDRV_PCM_FORMAT_S16_LE: - iismod |= I2S_DATA_WIDTH(15); - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iismod |= I2S_DATA_WIDTH(19); - break; - case SNDRV_PCM_FORMAT_S24_LE: - iismod |= I2S_DATA_WIDTH(23); - break; - case SNDRV_PCM_FORMAT_S32_LE: - iismod |= I2S_DATA_WIDTH(31); - break; - } - - iis_ckr_value = readl(&(pheadi2s->I2S_CKR)); - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - iis_ckr_value &= ~I2S_SLAVE_MODE; - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - iis_ckr_value |= I2S_SLAVE_MODE; - #endif - writel(iis_ckr_value, &(pheadi2s->I2S_CKR)); - -// writel((16<<24) |(16<<18)|(16<<12)|(16<<6)|16, &(pheadi2s->I2S_FIFOLR)); - dmarc = readl(&(pheadi2s->I2S_DMACR)); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dmarc = ((dmarc & 0xFFFFFE00) | 16); - else - dmarc = ((dmarc & 0xFE00FFFF) | 16<<16); - - writel(dmarc, &(pheadi2s->I2S_DMACR)); - I2S_DBG("Enter %s, %d I2S_TXCR=0x%08X\n", __func__, __LINE__, iismod); - - writel(iismod, &(pheadi2s->I2S_TXCR)); - - iismod = iismod & 0x00007FFF; - writel(iismod, &(pheadi2s->I2S_RXCR)); - spin_unlock(&i2s->spinlock_wr); - return 0; -} - -static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) -{ - int ret = 0; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct rk29_i2s_info *i2s = to_info(rtd->cpu_dai); - - I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - rockchip_snd_rxctrl(i2s, 1); - else - rockchip_snd_txctrl(i2s, 1); - break; - - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - rockchip_snd_rxctrl(i2s, 0); - else - rockchip_snd_txctrl(i2s, 0); - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -/* - * Set Rockchip I2S MCLK source - */ -static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, - int clk_id, unsigned int freq, int dir) -{ - struct rk29_i2s_info *i2s; - - i2s = to_info(cpu_dai); - - I2S_DBG("Enter:%s, %d, i2s=0x%p, freq=%d\n", __FUNCTION__, __LINE__, i2s, freq); - /*add scu clk source and enable clk*/ - clk_set_rate(i2s->iis_clk, freq); - return 0; -} - -/* - * Set Rockchip Clock dividers - */ -static int rockchip_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, - int div_id, int div) -{ - struct rk29_i2s_info *i2s; - u32 reg; - - i2s = to_info(cpu_dai); - - //stereo mode MCLK/SCK=4 - spin_lock(&i2s->spinlock_wr); - reg = readl(&(pheadi2s->I2S_CKR)); - - I2S_DBG("Enter:%s, %d, div_id=0x%08X, div=0x%08X\n", __FUNCTION__, __LINE__, div_id, div); - - //when i2s in master mode ,must set codec pll div - switch (div_id) { - case ROCKCHIP_DIV_BCLK: - reg &= ~I2S_TX_SCLK_DIV_MASK; - reg |= I2S_TX_SCLK_DIV(div); - reg &= ~I2S_RX_SCLK_DIV_MASK; - reg |= I2S_RX_SCLK_DIV(div); - break; - case ROCKCHIP_DIV_MCLK: - reg &= ~I2S_MCLK_DIV_MASK; - reg |= I2S_MCLK_DIV(div); - break; - case ROCKCHIP_DIV_PRESCALER: - break; - default: - return -EINVAL; - } - writel(reg, &(pheadi2s->I2S_CKR)); - spin_unlock(&i2s->spinlock_wr); - return 0; -} - -static int i2s_set_gpio_mode(struct snd_soc_dai *dai) -{ - I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); - switch(dai->id) { -#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) - case 1: - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_MCLK)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SCLK)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_LRCKRX)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_LRCKTX)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SDI)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SDO)); - break; -#elif defined(CONFIG_ARCH_RK30) - case 0: - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_MCLK)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SCLK)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_LRCKRX)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_LRCKTX)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SDI)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SDO0)); - #ifdef CONFIG_SND_I2SO_USE_EIGHT_CHANNELS - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SDO1)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SDO2)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SDO3)); - #endif - break; - case 1: - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S1_MCLK)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S1_SCLK)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S1_LRCKRX)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S1_LRCKTX)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S1_SDI)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S1_SDO)); - break; - case 2: - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S2_MCLK)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S2_SCLK)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S2_LRCKRX)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S2_LRCKTX)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S2_SDI)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S2_SDO)); - break; -#endif -#if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026) - case 0: - #if 0 //iomux --> gps(.ko) - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_MCLK)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SCLK)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_LRCKRX)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_LRCKTX)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SDI)); - iomux_set_gpio_mode(iomux_mode_to_gpio(I2S0_SDO)); - #endif - break; -#endif - default: - I2S_DBG("Enter:%s, %d, Error For DevId!!!", __FUNCTION__, __LINE__); - return -EINVAL; - } - return 0; -} - -static int rockchip_i2s_dai_probe(struct snd_soc_dai *dai) -{ - I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); - if(rk_cpu_dai == NULL) - rk_cpu_dai = dai; - switch(dai->id) { -#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) - case 1: - iomux_set(I2S0_MCLK); - iomux_set(I2S0_SCLK); - iomux_set(I2S0_LRCKRX); - iomux_set(I2S0_LRCKTX); - iomux_set(I2S0_SDI); - iomux_set(I2S0_SDO); - break; -#elif defined(CONFIG_ARCH_RK30) - case 0: - rk30_mux_api_set(GPIO0A7_I2S8CHSDI_NAME, GPIO0A_I2S_8CH_SDI); - rk30_mux_api_set(GPIO0B0_I2S8CHCLK_NAME, GPIO0B_I2S_8CH_CLK); - rk30_mux_api_set(GPIO0B1_I2S8CHSCLK_NAME, GPIO0B_I2S_8CH_SCLK); - rk30_mux_api_set(GPIO0B2_I2S8CHLRCKRX_NAME, GPIO0B_I2S_8CH_LRCK_RX); - rk30_mux_api_set(GPIO0B3_I2S8CHLRCKTX_NAME, GPIO0B_I2S_8CH_LRCK_TX); - rk30_mux_api_set(GPIO0B4_I2S8CHSDO0_NAME, GPIO0B_I2S_8CH_SDO0); - #ifdef CONFIG_SND_I2SO_USE_EIGHT_CHANNELS - rk30_mux_api_set(GPIO0B5_I2S8CHSDO1_NAME, GPIO0B_I2S_8CH_SDO1); - rk30_mux_api_set(GPIO0B6_I2S8CHSDO2_NAME, GPIO0B_I2S_8CH_SDO2); - rk30_mux_api_set(GPIO0B7_I2S8CHSDO3_NAME, GPIO0B_I2S_8CH_SDO3); - #endif - break; - case 1: - rk30_mux_api_set(GPIO0C0_I2S12CHCLK_NAME, GPIO0C_I2S1_2CH_CLK); - rk30_mux_api_set(GPIO0C1_I2S12CHSCLK_NAME, GPIO0C_I2S1_2CH_SCLK); - rk30_mux_api_set(GPIO0C2_I2S12CHLRCKRX_NAME, GPIO0C_I2S1_2CH_LRCK_RX); - rk30_mux_api_set(GPIO0C3_I2S12CHLRCKTX_NAME, GPIO0C_I2S1_2CH_LRCK_TX); - rk30_mux_api_set(GPIO0C4_I2S12CHSDI_NAME, GPIO0C_I2S1_2CH_SDI); - rk30_mux_api_set(GPIO0C5_I2S12CHSDO_NAME, GPIO0C_I2S1_2CH_SDO); - break; - case 2: - rk30_mux_api_set(GPIO0D0_I2S22CHCLK_SMCCSN0_NAME, GPIO0D_I2S2_2CH_CLK); - rk30_mux_api_set(GPIO0D1_I2S22CHSCLK_SMCWEN_NAME, GPIO0D_I2S2_2CH_SCLK); - rk30_mux_api_set(GPIO0D2_I2S22CHLRCKRX_SMCOEN_NAME, GPIO0D_I2S2_2CH_LRCK_RX); - rk30_mux_api_set(GPIO0D3_I2S22CHLRCKTX_SMCADVN_NAME, GPIO0D_I2S2_2CH_LRCK_TX); - rk30_mux_api_set(GPIO0D4_I2S22CHSDI_SMCADDR0_NAME, GPIO0D_I2S2_2CH_SDI); - rk30_mux_api_set(GPIO0D5_I2S22CHSDO_SMCADDR1_NAME, GPIO0D_I2S2_2CH_SDO); - break; -#endif -#if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026) - case 0: - #if 0 //iomux --> gps(.ko) - rk30_mux_api_set(GPIO1A0_I2S_MCLK_NAME, GPIO1A_I2S_MCLK); - rk30_mux_api_set(GPIO1A1_I2S_SCLK_NAME, GPIO1A_I2S_SCLK); - rk30_mux_api_set(GPIO1A2_I2S_LRCKRX_GPS_CLK_NAME, GPIO1A_I2S_LRCKRX); - rk30_mux_api_set(GPIO1A3_I2S_LRCKTX_NAME, GPIO1A_I2S_LRCKTX); - rk30_mux_api_set(GPIO1A4_I2S_SDO_GPS_MAG_NAME, GPIO1A_I2S_SDO); - rk30_mux_api_set(GPIO1A5_I2S_SDI_GPS_SIGN_NAME, GPIO1A_I2S_SDI); - #endif - break; -#endif - default: - I2S_DBG("Enter:%s, %d, Error For DevId!!!", __FUNCTION__, __LINE__); - return -EINVAL; - } - return 0; -} - -#ifdef CONFIG_PM -int rockchip_i2s_suspend(struct snd_soc_dai *cpu_dai) -{ - I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); -// clk_disable(clk); - return 0; -} - -int rockchip_i2s_resume(struct snd_soc_dai *cpu_dai) -{ - I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); -// clk_enable(clk); - return 0; -} -#else -#define rockchip_i2s_suspend NULL -#define rockchip_i2s_resume NULL -#endif - -#ifdef ANDROID_REC -#define ROCKCHIP_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) -#else -#define ROCKCHIP_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) -#endif - -static struct snd_soc_dai_ops rockchip_i2s_dai_ops = { - .trigger = rockchip_i2s_trigger, - .hw_params = rockchip_i2s_hw_params, - .set_fmt = rockchip_i2s_set_fmt, - .set_clkdiv = rockchip_i2s_set_clkdiv, - .set_sysclk = rockchip_i2s_set_sysclk, -}; - -static int rk29_i2s_probe(struct platform_device *pdev, - struct snd_soc_dai_driver *dai, - struct rk29_i2s_info *i2s, - unsigned long base) -{ - struct device *dev = &pdev->dev; - struct resource *res; - - I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); - - i2s->dev = dev; - - /* record our i2s structure for later use in the callbacks */ - dev_set_drvdata(&pdev->dev, i2s); - - if (!base) { - res = platform_get_resource(pdev, - IORESOURCE_MEM, - 0); - if (!res) { - dev_err(dev, "Unable to get register resource\n"); - return -ENXIO; - } - - if (!request_mem_region(res->start, resource_size(res), - "rk29_i2s")) { - dev_err(dev, "Unable to request register region\n"); - return -EBUSY; - } - - base = res->start; - } - - i2s->regs = ioremap(base, (res->end - res->start) + 1); ////res)); - if (i2s->regs == NULL) { - dev_err(dev, "cannot ioremap registers\n"); - return -ENXIO; - } - - i2s->iis_pclk = clk_get(dev, "hclk_i2s"); - if (IS_ERR(i2s->iis_pclk)) { - dev_err(dev, "failed to get iis_clock\n"); - iounmap(i2s->regs); - return -ENOENT; - } - clk_enable(i2s->iis_pclk); - - - /* Mark ourselves as in TXRX mode so we can run through our cleanup - * process without warnings. */ - rockchip_snd_txctrl(i2s, 0); - rockchip_snd_rxctrl(i2s, 0); - - return 0; -} - -static int __devinit rockchip_i2s_probe(struct platform_device *pdev) -{ - struct rk29_i2s_info *i2s; - struct snd_soc_dai_driver *dai; - int ret; - -#if defined(CONFIG_SND_I2S_USE_18V) - writel_relaxed(0x2000200,RK30_GRF_BASE + GRF_IO_CON4);//bit9: 1,1.8v;0,3.3v -#elif defined(CONFIG_SND_I2S_USE_33V) - writel_relaxed(0x2000000,RK30_GRF_BASE + GRF_IO_CON4); -#endif - -#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) - //default 8ma 0xF000F = 12ma 0xF0005=4ma 0xF0000=2ma - writel_relaxed(0xF000A,RK30_GRF_BASE + GRF_IO_CON1); -#endif - I2S_DBG("Enter %s, %d pdev->id = %d >>>>>>>>>>>\n", __func__, __LINE__, pdev->id); - - if(pdev->id >= MAX_I2S) { - dev_err(&pdev->dev, "id %d out of range\n", pdev->id); - return -EINVAL; - } - - i2s = &rk29_i2s[pdev->id]; - dai = &rk29_i2s_dai[pdev->id]; - dai->id = pdev->id; - dai->symmetric_rates = 1; - - switch(pdev->id) - { - case 0: - dai->name = "rk29_i2s.0"; - dai->playback.channels_min = 2; - dai->playback.channels_max = 8; - break; - case 1: - dai->name = "rk29_i2s.1"; - dai->playback.channels_min = 2; - dai->playback.channels_max = 2; - break; - case 2: - dai->name = "rk29_i2s.2"; - dai->playback.channels_min = 2; - dai->playback.channels_max = 2; - break; - } - - spin_lock_init(&i2s->spinlock_wr); - dai->playback.rates = SNDRV_PCM_RATE_8000_192000; - dai->playback.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | - SNDRV_PCM_FMTBIT_S24_LE| SNDRV_PCM_FMTBIT_S32_LE; - dai->capture.channels_min = 2; - dai->capture.channels_max = 2; - dai->capture.rates = ROCKCHIP_I2S_RATES; - dai->capture.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE; - dai->probe = rockchip_i2s_dai_probe; - dai->ops = &rockchip_i2s_dai_ops; - dai->suspend = rockchip_i2s_suspend; - dai->resume = rockchip_i2s_resume; - - i2s->dma_capture = &rk29_i2s_pcm_stereo_in[pdev->id]; - i2s->dma_playback = &rk29_i2s_pcm_stereo_out[pdev->id]; - - switch(pdev->id) - { -#ifdef CONFIG_ARCH_RK30 - case 0: - i2s->dma_capture->channel = DMACH_I2S0_8CH_RX; - i2s->dma_capture->dma_addr = RK30_I2S0_8CH_PHYS + I2S_RXR_BUFF; - i2s->dma_playback->channel = DMACH_I2S0_8CH_TX; - i2s->dma_playback->dma_addr = RK30_I2S0_8CH_PHYS + I2S_TXR_BUFF; - break; - case 1: - i2s->dma_capture->channel = DMACH_I2S1_2CH_RX; - i2s->dma_capture->dma_addr = RK30_I2S1_2CH_PHYS + I2S_RXR_BUFF; - i2s->dma_playback->channel = DMACH_I2S1_2CH_TX; - i2s->dma_playback->dma_addr = RK30_I2S1_2CH_PHYS + I2S_TXR_BUFF; - break; - case 2: - i2s->dma_capture->channel = DMACH_I2S2_2CH_RX; - i2s->dma_capture->dma_addr = RK30_I2S2_2CH_PHYS + I2S_RXR_BUFF; - i2s->dma_playback->channel = DMACH_I2S2_2CH_TX; - i2s->dma_playback->dma_addr = RK30_I2S2_2CH_PHYS + I2S_TXR_BUFF; - break; -#endif -#if defined(CONFIG_ARCH_RK3188) - case 1: - i2s->dma_capture->channel = DMACH_I2S1_2CH_RX; - i2s->dma_capture->dma_addr = RK30_I2S1_2CH_PHYS + I2S_RXR_BUFF; - i2s->dma_playback->channel = DMACH_I2S1_2CH_TX; - i2s->dma_playback->dma_addr = RK30_I2S1_2CH_PHYS + I2S_TXR_BUFF; - break; -#endif -#if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026) - case 0: - i2s->dma_capture->channel = DMACH_I2S0_8CH_RX; - i2s->dma_capture->dma_addr = RK2928_I2S_PHYS + I2S_RXR_BUFF; - i2s->dma_playback->channel = DMACH_I2S0_8CH_TX; - i2s->dma_playback->dma_addr = RK2928_I2S_PHYS + I2S_TXR_BUFF; - break; -#endif - } - - i2s->dma_capture->client = &rk29_dma_client_in; - i2s->dma_capture->dma_size = 4; - i2s->dma_capture->flag = 0; //add by sxj, used for burst change - i2s->dma_playback->client = &rk29_dma_client_out; - i2s->dma_playback->dma_size = 4; - i2s->dma_playback->flag = 0; //add by sxj, used for burst change - i2s->i2s_tx_status = false; - i2s->i2s_rx_status = false; -#ifdef CONFIG_SND_I2S_DMA_EVENT_STATIC - WARN_ON(rk29_dma_request(i2s->dma_playback->channel, i2s->dma_playback->client, NULL)); - WARN_ON(rk29_dma_request(i2s->dma_capture->channel, i2s->dma_capture->client, NULL)); -#endif - - i2s->iis_clk = clk_get(&pdev->dev, "i2s"); - I2S_DBG("Enter:%s, %d, iis_clk=%p\n", __FUNCTION__, __LINE__, i2s->iis_clk); - if (IS_ERR(i2s->iis_clk)) { - dev_err(&pdev->dev, "failed to get i2s clk\n"); - ret = PTR_ERR(i2s->iis_clk); - goto err; - } - - clk_enable(i2s->iis_clk); - clk_set_rate(i2s->iis_clk, 11289600); - - ret = rk29_i2s_probe(pdev, dai, i2s, 0); - if (ret) - goto err_clk; - - ret = snd_soc_register_dai(&pdev->dev, dai); - if (ret != 0) - goto err_i2sv2; - - return 0; - -err_i2sv2: - /* Not implemented for I2Sv2 core yet */ -err_clk: - clk_put(i2s->iis_clk); -err: - return ret; -} - -static int rockchip_i2s_suspend_noirq(struct device *dev) -{ - struct snd_soc_dai *dai = rk_cpu_dai; - I2S_DBG("Enter %s, %d\n", __func__, __LINE__); - - return i2s_set_gpio_mode(dai); -} - -static int rockchip_i2s_resume_noirq(struct device *dev) -{ - struct snd_soc_dai *dai = rk_cpu_dai; - I2S_DBG("Enter %s, %d\n", __func__, __LINE__); - - return rockchip_i2s_dai_probe(dai); -} - -static const struct dev_pm_ops rockchip_i2s_pm_ops = { - .suspend_noirq = rockchip_i2s_suspend_noirq, - .resume_noirq = rockchip_i2s_resume_noirq, -}; - -static int __devexit rockchip_i2s_remove(struct platform_device *pdev) -{ - snd_soc_unregister_dai(&pdev->dev); - return 0; -} - -static struct platform_driver rockchip_i2s_driver = { - .probe = rockchip_i2s_probe, - .remove = __devexit_p(rockchip_i2s_remove), - .driver = { - .name = "rk29_i2s", - .owner = THIS_MODULE, - .pm = &rockchip_i2s_pm_ops, - }, -}; - -static int __init rockchip_i2s_init(void) -{ - I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); - - return platform_driver_register(&rockchip_i2s_driver); -} -module_init(rockchip_i2s_init); - -static void __exit rockchip_i2s_exit(void) -{ - platform_driver_unregister(&rockchip_i2s_driver); -} -module_exit(rockchip_i2s_exit); - -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface"); -MODULE_LICENSE("GPL"); - - -#ifdef CONFIG_PROC_FS -#include -#include -static int proc_i2s_show(struct seq_file *s, void *v) -{ -#ifdef CONFIG_SND_RK29_SOC_I2S_8CH - struct rk29_i2s_info *i2s=&rk29_i2s[0]; -#else -#ifdef CONFIG_SND_RK29_SOC_I2S_2CH - struct rk29_i2s_info *i2s=&rk29_i2s[1]; -#else - struct rk29_i2s_info *i2s=&rk29_i2s[2]; -#endif -#endif - printk("========Show I2S reg========\n"); - - printk("I2S_TXCR = 0x%08X\n", readl(&(pheadi2s->I2S_TXCR))); - printk("I2S_RXCR = 0x%08X\n", readl(&(pheadi2s->I2S_RXCR))); - printk("I2S_CKR = 0x%08X\n", readl(&(pheadi2s->I2S_CKR))); - printk("I2S_DMACR = 0x%08X\n", readl(&(pheadi2s->I2S_DMACR))); - printk("I2S_INTCR = 0x%08X\n", readl(&(pheadi2s->I2S_INTCR))); - printk("I2S_INTSR = 0x%08X\n", readl(&(pheadi2s->I2S_INTSR))); - printk("I2S_XFER = 0x%08X\n", readl(&(pheadi2s->I2S_XFER))); - - printk("========Show I2S reg========\n"); -#if 0 - writel(0x0000000F, &(pheadi2s->I2S_TXCR)); - writel(0x0000000F, &(pheadi2s->I2S_RXCR)); - writel(0x00071f1F, &(pheadi2s->I2S_CKR)); - writel(0x001F0110, &(pheadi2s->I2S_DMACR)); - writel(0x00000003, &(pheadi2s->I2S_XFER)); - while(1) - { - writel(0x5555aaaa, &(pheadi2s->I2S_TXDR)); - } -#endif - return 0; -} - -static ssize_t i2s_reg_write(struct file *file, - const char __user *user_buf, size_t count, loff_t *ppos) -{ -#ifdef CONFIG_SND_RK29_SOC_I2S_8CH - struct rk29_i2s_info *i2s=&rk29_i2s[0]; -#else -#ifdef CONFIG_SND_RK29_SOC_I2S_2CH - struct rk29_i2s_info *i2s=&rk29_i2s[1]; -#else - struct rk29_i2s_info *i2s=&rk29_i2s[2]; -#endif -#endif - char buf[32]; - size_t buf_size; - char *start = buf; - unsigned long value; - - buf_size = min(count, (sizeof(buf)-1)); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - buf[buf_size] = 0; - - while (*start == ' ') - start++; - value = simple_strtoul(start, &start, 10); - - printk("test --- freq = %ld ret=%d\n",value,clk_set_rate(i2s->iis_clk, value)); - return buf_size; -} - -static int proc_i2s_open(struct inode *inode, struct file *file) -{ - return single_open(file, proc_i2s_show, NULL); -} - -static const struct file_operations proc_i2s_fops = { - .open = proc_i2s_open, - .read = seq_read, - .write = i2s_reg_write, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init i2s_proc_init(void) -{ - proc_create("i2s_reg", 0, NULL, &proc_i2s_fops); - return 0; -} -late_initcall(i2s_proc_init); -#endif /* CONFIG_PROC_FS */ - diff --git a/sound/soc/rk29/rk_hdmi_i2s.c b/sound/soc/rk29/rk_hdmi_i2s.c deleted file mode 100644 index 6665b2bacf8f..000000000000 --- a/sound/soc/rk29/rk_hdmi_i2s.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * 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", -#if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", -#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", -#endif - .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; - } - - 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 deleted file mode 100755 index c93a23957b4e..000000000000 --- a/sound/soc/rk29/rk_hdmi_spdif.c +++ /dev/null @@ -1,186 +0,0 @@ -/*$_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", - .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_rk3026.c b/sound/soc/rk29/rk_rk3026.c deleted file mode 100644 index 45fe8d7b9b5d..000000000000 --- a/sound/soc/rk29/rk_rk3026.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * rk_rk3026.c -- SoC audio for rockchip - * - * Driver for rockchip rk3026 audio - * - * 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 -#include -#include -#include -#include -#include -#include "../codecs/rk3026_codec.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" - -#if 0 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif - -static const struct snd_soc_dapm_widget rk_dapm_widgets[] = { - SND_SOC_DAPM_MIC("Mic Jack", NULL), - SND_SOC_DAPM_MIC("Headset Jack", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_HP("Headphone Jack", NULL), -}; - -static const struct snd_soc_dapm_route rk_audio_map[]={ - - /* Mic Jack --> MIC_IN*/ - {"Mic Bias", NULL, "Mic Jack"}, - {"MICP", NULL, "Mic Bias"}, - {"MICN", NULL, "Mic Bias"}, - - // HP MIC - {"Mic Bias", NULL, "Headset Jack"}, - - {"Ext Spk", NULL, "HPOUTR"}, - {"Ext Spk", NULL, "HPOUTL"}, - - {"Headphone Jack", NULL, "HPOUTR"}, - {"Headphone Jack", NULL, "HPOUTL"}, -} ; - -static const struct snd_kcontrol_new rk_controls[] = { - SOC_DAPM_PIN_SWITCH("Mic Jack"), - SOC_DAPM_PIN_SWITCH("Headset Jack"), - SOC_DAPM_PIN_SWITCH("Ext Spk"), - SOC_DAPM_PIN_SWITCH("Headphone Jack"), -}; - -static int rk3026_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - snd_soc_add_controls(codec, rk_controls, - ARRAY_SIZE(rk_controls)); - - /* Add specific widgets */ - snd_soc_dapm_new_controls(dapm, rk_dapm_widgets, - ARRAY_SIZE(rk_dapm_widgets)); - /* Set up specific audio path audio_mapnects */ - snd_soc_dapm_add_routes(dapm, rk_audio_map, ARRAY_SIZE(rk_audio_map)); - - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - snd_soc_dapm_enable_pin(dapm, "Headset Jack"); - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); - - snd_soc_dapm_sync(dapm); - - return 0; -} - -static int rk_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #endif - if (ret < 0) - return ret; - - /* 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: - DBG("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)); - - /*Set the system clk for codec*/ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); - if (ret < 0) { - DBG("rk_hifi_hw_params:failed to set the sysclk for codec side\n"); - return ret; - } - - 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 int rk_voice_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS); - - 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: - DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params)); - return -EINVAL; - break; - } - - /*Set the system clk for codec*/ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); - - if (ret < 0) { - printk("rk_voice_hw_params:failed to set the sysclk for codec side\n"); - return ret; - } - - ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - - return 0; -} - -static struct snd_soc_ops rk3026_hifi_ops = { - .hw_params = rk_hifi_hw_params, -}; - -static struct snd_soc_ops rk3026_voice_ops = { - .hw_params = rk_voice_hw_params, -}; - -static struct snd_soc_dai_link rk_dai[] = { - { - .name = "RK3026 I2S1", - .stream_name = "RK3026 PCM", - .codec_name = "rk3026-codec", - .platform_name = "rockchip-audio", -#if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", -#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", -#endif - .codec_dai_name = "rk3026-hifi", - .init = rk3026_init, - .ops = &rk3026_hifi_ops, - }, - { - .name = "RK3026 I2S2", - .stream_name = "RK3026 PCM", - .codec_name = "rk3026-codec", - .platform_name = "rockchip-audio", -#if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", -#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", -#endif - .codec_dai_name = "rk3026-voice", - .ops = &rk3026_voice_ops, - }, -}; - -static struct snd_soc_card snd_soc_card_rk = { - .name = "RK_RK3026", - .dai_link = rk_dai, - .num_links = 2, -}; - -static struct platform_device *rk_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - rk_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk_snd_device) { - printk("platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(rk_snd_device, &snd_soc_card_rk); - ret = platform_device_add(rk_snd_device); - if (ret) { - printk("platform device add failed\n"); - - platform_device_put(rk_snd_device); - return ret; - } - - return ret; -} - -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk_snd_device); -} - -module_init(audio_card_init); -module_exit(audio_card_exit); -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk29/rk_rk616.c b/sound/soc/rk29/rk_rk616.c deleted file mode 100755 index 28e843f44401..000000000000 --- a/sound/soc/rk29/rk_rk616.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * rk_rk616.c -- SoC audio for rockchip - * - * Driver for rockchip rk616 audio - * - * 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 -#include -#include -#include -#include -#include -#include "../codecs/rk616_codec.h" -#include "rk29_pcm.h" -#include "rk29_i2s.h" - -#if 1 -#define DBG(x...) printk(KERN_INFO x) -#else -#define DBG(x...) -#endif - -static const struct snd_soc_dapm_widget rk_dapm_widgets[] = { - SND_SOC_DAPM_MIC("Mic Jack", NULL), - SND_SOC_DAPM_MIC("Headset Jack", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_HP("Headphone Jack", NULL), -}; - -static const struct snd_soc_dapm_route rk_audio_map[]={ - - /* Mic Jack --> MIC_IN*/ - {"Mic1 Bias", NULL, "Mic Jack"}, - {"MIC1P", NULL, "Mic1 Bias"}, - {"MIC1N", NULL, "Mic1 Bias"}, - - // HP MIC - {"Mic2 Bias", NULL, "Headset Jack"}, - {"MIC2P", NULL, "Mic2 Bias"}, - {"MIC2N", NULL, "Mic2 Bias"}, - - {"Ext Spk", NULL, "SPKOUTR"}, - {"Ext Spk", NULL, "SPKOUTL"}, - - {"Headphone Jack", NULL, "HPOUTR"}, - {"Headphone Jack", NULL, "HPOUTL"}, -} ; - -static const struct snd_kcontrol_new rk_controls[] = { - SOC_DAPM_PIN_SWITCH("Mic Jack"), - SOC_DAPM_PIN_SWITCH("Headset Jack"), - SOC_DAPM_PIN_SWITCH("Ext Spk"), - SOC_DAPM_PIN_SWITCH("Headphone Jack"), -}; - -static int rk616_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - // if is for mid that using tiny alsa, - // it don't need this controls and route, so return. - if (rk616_get_for_mid()) - return 0; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - snd_soc_add_controls(codec, rk_controls, - ARRAY_SIZE(rk_controls)); - - /* Add specific widgets */ - snd_soc_dapm_new_controls(dapm, rk_dapm_widgets, - ARRAY_SIZE(rk_dapm_widgets)); - /* Set up specific audio path audio_mapnects */ - snd_soc_dapm_add_routes(dapm, rk_audio_map, ARRAY_SIZE(rk_audio_map)); - - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - snd_soc_dapm_enable_pin(dapm, "Headset Jack"); - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); - - snd_soc_dapm_sync(dapm); - - return 0; -} - -static int rk_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0, div = 4; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* set codec DAI configuration */ - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); - #endif - if (ret < 0) - return ret; - - /* 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 16000: - case 24000: - case 32000: - case 48000: - pll_out = 12288000; - break; - case 11025: - case 22050: - case 44100: - pll_out = 11289600; - break; - case 8000: - pll_out = 12000000; - div = 6; - break; - default: - DBG("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)); - - #if defined(CONFIG_RK616_USE_MCLK_12M) - /* MCLK must be 12M when RK616 HDMI is in */ - if (get_hdmi_state() && pll_out != 12000000) { - DBG("%s : HDMI is in, don't set sys clk %u\n",__FUNCTION__, pll_out); - goto __setdiv; - } - #endif - - /* Set the system clk for codec - mclk will be setted in set_sysclk of codec_dai*/ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); - if (ret < 0) { - DBG("rk_hifi_hw_params:failed to set the sysclk for codec side\n"); - return ret; - } -#if defined(CONFIG_RK616_USE_MCLK_12M) -__setdiv: -#endif - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (pll_out / div)/params_rate(params)-1); - snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div - 1); - - DBG("Enter:%s, %d, pll_out/div/params_rate(params) = %d \n", __FUNCTION__, __LINE__, (pll_out/div)/params_rate(params)); - - return 0; -} - -static int rk_voice_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 *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int pll_out = 0; - int ret; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - /* set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS); - - 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: - DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params)); - return -EINVAL; - break; - } - - /* MCLK must be 12M when RK616 HDMI is in */ - #if defined(CONFIG_RK616_USE_MCLK_12M) - if (get_hdmi_state() && pll_out != 12000000) { - DBG("%s : HDMI is in, set mclk to 12Mn",__FUNCTION__); - pll_out = 12000000; - } - #endif - - //snd_soc_dai_set_pll(codec_dai, RT5625_PLL_MCLK_TO_VSYSCLK, 0, pll_out, 24576000); - - /*Set the system clk for codec*/ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); - - if (ret < 0) { - printk("rk_voice_hw_params:failed to set the sysclk for codec side\n"); - return ret; - } - - ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); - - return 0; -} - -static struct snd_soc_ops rk616_hifi_ops = { - .hw_params = rk_hifi_hw_params, -}; - -static struct snd_soc_ops rk616_voice_ops = { - .hw_params = rk_voice_hw_params, -}; - -static struct snd_soc_dai_link rk_dai[] = { - { - .name = "RK616 I2S1", - .stream_name = "RK616 PCM", - .codec_name = "rk616-codec.4-0050", - .platform_name = "rockchip-audio", -#if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", -#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", -#endif - .codec_dai_name = "rk616-hifi", - .init = rk616_init, - .ops = &rk616_hifi_ops, - }, - { - .name = "RK616 I2S2", - .stream_name = "RK616 PCM", - .codec_name = "rk616-codec.4-0050", - .platform_name = "rockchip-audio", -#if defined(CONFIG_SND_RK29_SOC_I2S_8CH) - .cpu_dai_name = "rk29_i2s.0", -#elif defined(CONFIG_SND_RK29_SOC_I2S_2CH) - .cpu_dai_name = "rk29_i2s.1", -#endif - .codec_dai_name = "rk616-voice", - .ops = &rk616_voice_ops, - }, -}; - -static struct snd_soc_card snd_soc_card_rk = { - .name = "RK_RK616", - .dai_link = rk_dai, - .num_links = 2, -}; - -static struct platform_device *rk_snd_device; - -static int __init audio_card_init(void) -{ - int ret =0; - - DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - - rk_snd_device = platform_device_alloc("soc-audio", -1); - if (!rk_snd_device) { - printk("platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(rk_snd_device, &snd_soc_card_rk); - ret = platform_device_add(rk_snd_device); - if (ret) { - printk("platform device add failed\n"); - - platform_device_put(rk_snd_device); - return ret; - } - - return ret; -} - -static void __exit audio_card_exit(void) -{ - platform_device_unregister(rk_snd_device); -} - -module_init(audio_card_init); -module_exit(audio_card_exit); -/* Module information */ -MODULE_AUTHOR("rockchip"); -MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/rk29/rk_spdif.c b/sound/soc/rk29/rk_spdif.c deleted file mode 100755 index 39ad0df0686c..000000000000 --- a/sound/soc/rk29/rk_spdif.c +++ /dev/null @@ -1,483 +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" - -#if 0 -#define RK_SPDIF_DBG(x...) printk(KERN_INFO "rk_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); - - 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); - - /* 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_I2S_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); -err0: - 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");