From: 陈金泉 Date: Tue, 21 Jan 2014 10:16:11 +0000 (+0800) Subject: Change path of audio platform device from rk to rockchip X-Git-Tag: firefly_0821_release~6373 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=02006e10ce6ebd9233ae0d88b92ddfdd97a16f24;p=firefly-linux-kernel-4.4.55.git Change path of audio platform device from rk to rockchip --- diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 9e675c76436c..570bb4677502 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -54,6 +54,7 @@ source "sound/soc/sh/Kconfig" source "sound/soc/tegra/Kconfig" source "sound/soc/txx9/Kconfig" source "sound/soc/ux500/Kconfig" +source "sound/soc/rockchip/Kconfig" # Supported codecs source "sound/soc/codecs/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 197b6ae54c8d..9b2d0671006a 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -32,3 +32,4 @@ obj-$(CONFIG_SND_SOC) += sh/ obj-$(CONFIG_SND_SOC) += tegra/ obj-$(CONFIG_SND_SOC) += txx9/ obj-$(CONFIG_SND_SOC) += ux500/ +obj-$(CONFIG_SND_SOC) += rockchip/ diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 4cbe4959ae2b..dc138a1a5017 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -32,7 +32,6 @@ 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 snd-soc-lm4857-objs := lm4857.o snd-soc-lm49453-objs := lm49453.o @@ -99,7 +98,6 @@ 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 diff --git a/sound/soc/codecs/rk3190_codec.c b/sound/soc/codecs/rk3190_codec.c new file mode 100755 index 000000000000..7ce2c6698f40 --- /dev/null +++ b/sound/soc/codecs/rk3190_codec.c @@ -0,0 +1,2348 @@ +/* + * rk3190_codec.c -- RK3190 CODEC ALSA SoC audio driver + * + * Copyright 2013 Rockchip + * Author: zhangjun + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rk3190_codec.h" + +#ifdef CONFIG_RK_HEADSET_DET +#include "../../../drivers/headset_observe/rk_headset.h" +#endif + +#if 0 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +/* volume setting + * 0: -39dB + * 26: 0dB + * 31: 6dB + * Step: 1.5dB +*/ +#define OUT_VOLUME 26//0~31 + +/* capture vol set + * 0: -18db + * 12: 0db + * 31: 28.5db + * step: 1.5db +*/ +#define CAP_VOL 18//0-31 + +//with capacity or not +#define WITH_CAP +#define SPK_AMP_DELAY 200 +#define HP_MOS_DELAY 200 +#ifdef CONFIG_MACH_RK_FAC + rk3190_hdmi_ctrl=0; +#endif + +struct rk3190_codec_priv { + struct snd_soc_codec *codec; + + unsigned int stereo_sysclk; + unsigned int rate; + + int playback_active; + int capture_active; + + int spk_ctl_gpio; + int hp_ctl_gpio; + int ear_ctl_gpio; + int mic_sel_gpio; + int delay_time; + + long int playback_path; + long int capture_path; + long int voice_call_path; + + int regbase; + int regbase_phy; + int regsize_phy; + struct clk *pclk; +}; + +static struct rk3190_codec_priv *rk3190_priv = NULL; + +#define RK3190_CODEC_ALL 0 +#define RK3190_CODEC_PLAYBACK 1 +#define RK3190_CODEC_CAPTURE 2 +#define RK3190_CODEC_INCALL 3 + +static bool rk3190_for_mid = 1, is_hdmi_in = false; + +static const unsigned int rk3190_reg_defaults[RK3190_PGA_AGC_CTL5+1] = { + [RK3190_RESET] = 0x0003, + [RK3190_ADC_INT_CTL1] = 0x0050, + [RK3190_ADC_INT_CTL2] = 0x000e, + [RK3190_DAC_INT_CTL1] = 0x0050, + [RK3190_DAC_INT_CTL2] = 0x000e, + [RK3190_BIST_CTL] = 0x0000, + [RK3190_SELECT_CURRENT] = 0x0001, + [RK3190_BIAS_CTL] = 0x0000, + [RK3190_ADC_CTL] = 0x0000, + [RK3190_BST_CTL] = 0x0000, + [RK3190_ALC_MUNIN_CTL] = 0x0044, + [RK3190_ALCL_GAIN_CTL] = 0x000c, + [RK3190_ALCR_GAIN_CTL] = 0x000c, + [RK3190_ADC_ENABLE] = 0x0000, + [RK3190_DAC_CTL] = 0x0000, + [RK3190_DAC_ENABLE] = 0x0000, + [RK3190_HPMIX_CTL] = 0x0000, + [RK3190_HPMIX_S_SELECT] = 0x0000, + [RK3190_HPOUT_CTL] = 0x0000, + [RK3190_HPOUTL_GAIN] = 0x0000, + [RK3190_HPOUTR_GAIN] = 0x0000, + [RK3190_PGA_AGC_CTL1] = 0x0000, + [RK3190_PGA_AGC_CTL2] = 0x0046, + [RK3190_PGA_AGC_CTL3] = 0x0041, + [RK3190_PGA_AGC_CTL4] = 0x002c, + [RK3190_PGA_ASR_CTL] = 0x0000, + [RK3190_PGA_AGC_MAX_H] = 0x0026, + [RK3190_PGA_AGC_MAX_L] = 0x0040, + [RK3190_PGA_AGC_MIN_H] = 0x0036, + [RK3190_PGA_AGC_MIN_L] = 0x0020, + [RK3190_PGA_AGC_CTL5] = 0x0038, +}; + +static struct rk3190_init_bit_typ rk3190_init_bit_list[] = { + {RK3190_HPOUT_CTL, RK3190_HPOUTL_EN, RK3190_HPOUTL_WORK,RK3190_HPVREF_EN}, + {RK3190_HPOUT_CTL, RK3190_HPOUTR_EN, RK3190_HPOUTR_WORK,RK3190_HPVREF_WORK}, + {RK3190_HPMIX_CTL, RK3190_HPMIXR_EN, RK3190_HPMIXR_WORK2,RK3190_HPMIXR_WORK1}, + {RK3190_HPMIX_CTL, RK3190_HPMIXL_EN, RK3190_HPMIXL_WORK2,RK3190_HPMIXL_WORK1}, + +}; +#define RK3190_INIT_BIT_LIST_LEN ARRAY_SIZE(rk3190_init_bit_list) + +static int rk3190_init_bit_register(unsigned int reg, int i) +{ + for (; i < RK3190_INIT_BIT_LIST_LEN; i++) { + if (rk3190_init_bit_list[i].reg == reg) + return i; + } + + return -1; +} + +static unsigned int rk3190_codec_read(struct snd_soc_codec *codec, unsigned int reg); +static inline void rk3190_write_reg_cache(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value); + +static unsigned int rk3190_set_init_value(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) +{ + unsigned int read_value, power_bit, set_bit2,set_bit1; + int i; + int tmp = 0; + // read codec init register + i = rk3190_init_bit_register(reg, 0); + + // set codec init bit + // widget init bit should be setted 0 after widget power up or unmute, + // and should be setted 1 after widget power down or mute. + if (i >= 0) { + read_value = rk3190_codec_read(codec, reg); + while (i >= 0) { + power_bit = rk3190_init_bit_list[i].power_bit; + set_bit2 = rk3190_init_bit_list[i].init2_bit; + set_bit1 = rk3190_init_bit_list[i].init1_bit; + + if ((read_value & power_bit) != (value & power_bit)) + { + if (value & power_bit) + { + tmp = value | set_bit2 | set_bit1; + writel(value, rk3190_priv->regbase+reg); + writel(tmp, rk3190_priv->regbase+reg); + + } + else + { + tmp = value & (~set_bit2) & (~set_bit1); + writel(tmp, rk3190_priv->regbase+reg); + writel(value, rk3190_priv->regbase+reg); + } + value = tmp; + } + else + { + if (read_value != value) + writel(value, rk3190_priv->regbase+reg); + } + + i = rk3190_init_bit_register(reg, ++i); + + rk3190_write_reg_cache(codec, reg, value); + } + } + else + { + return i; + } + + return value; +} + +static int rk3190_volatile_register(struct snd_soc_codec *codec, unsigned int reg) +{ + switch (reg) { + case RK3190_RESET: + return 1; + default: + return 0; + } +} + +static int rk3190_codec_register(struct snd_soc_codec *codec, unsigned int reg) +{ + switch (reg) { + case RK3190_RESET: + case RK3190_ADC_INT_CTL1: + case RK3190_ADC_INT_CTL2: + case RK3190_DAC_INT_CTL1: + case RK3190_DAC_INT_CTL2: + case RK3190_BIST_CTL: + case RK3190_SELECT_CURRENT: + case RK3190_BIAS_CTL: + case RK3190_ADC_CTL: + case RK3190_BST_CTL: + case RK3190_ALC_MUNIN_CTL: + case RK3190_ALCL_GAIN_CTL: + case RK3190_ALCR_GAIN_CTL: + case RK3190_ADC_ENABLE: + case RK3190_DAC_CTL: + case RK3190_DAC_ENABLE: + case RK3190_HPMIX_CTL: + case RK3190_HPMIX_S_SELECT: + case RK3190_HPOUT_CTL: + case RK3190_HPOUTL_GAIN: + case RK3190_HPOUTR_GAIN: + case RK3190_PGA_AGC_CTL1: + case RK3190_PGA_AGC_CTL2: + case RK3190_PGA_AGC_CTL3: + case RK3190_PGA_AGC_CTL4: + case RK3190_PGA_ASR_CTL: + case RK3190_PGA_AGC_MAX_H: + case RK3190_PGA_AGC_MAX_L: + case RK3190_PGA_AGC_MIN_H: + case RK3190_PGA_AGC_MIN_L: + case RK3190_PGA_AGC_CTL5: + return 1; + default: + return 0; + } +} + +static inline unsigned int rk3190_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + unsigned int *cache = codec->reg_cache; + + if (rk3190_codec_register(codec, reg) ) + return cache[reg]; + + printk("%s : reg error!\n", __func__); + + return -EINVAL; +} + +static inline void rk3190_write_reg_cache(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value) +{ + unsigned int *cache = codec->reg_cache; + + if (rk3190_codec_register(codec, reg)) { + cache[reg] = value; + return; + } + + printk("%s : reg error!\n", __func__); +} + +static unsigned int rk3190_codec_read(struct snd_soc_codec *codec, unsigned int reg) +{ + unsigned int value; + + if (!rk3190_priv) { + printk("%s : rk3190 is NULL\n", __func__); + return -EINVAL; + } + + if (!rk3190_codec_register(codec, reg)) { + printk("%s : reg error!\n", __func__); + return -EINVAL; + } + + if (rk3190_volatile_register(codec, reg) == 0) { + value = rk3190_read_reg_cache(codec, reg); + } else { + value = readl_relaxed(rk3190_priv->regbase+reg); + } + + value = readl_relaxed(rk3190_priv->regbase+reg); + DBG("%s : reg = 0x%x, val= 0x%x\n", __func__, reg, value); + + return value; +} + +static int rk3190_codec_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) +{ + int new_value = -1; + + if (!rk3190_priv) { + printk("%s : rk3190 is NULL\n", __func__); + return -EINVAL; + } else if (!rk3190_codec_register(codec, reg)) { + printk("%s : reg error!\n", __func__); + return -EINVAL; + } + + //new_value = rk3190_set_init_value(codec, reg, value); + + if (new_value == -1) + { + writel(value, rk3190_priv->regbase+reg); + rk3190_write_reg_cache(codec, reg, value); + } + + DBG("%s : reg = 0x%x, val = 0x%x, new_value=%d\n", __func__, reg, value,new_value); + return 0; +} + +static int rk3190_hw_write(const struct i2c_client *client, const char *buf, int count) +{ + unsigned int reg, value; + + if (!rk3190_priv || !rk3190_priv->codec) { + printk("%s : rk3190_priv or rk3190_priv->codec is NULL\n", __func__); + return -EINVAL; + } + + if (count == 3) { + reg = (unsigned int)buf[0]; + value = (buf[1] & 0xff00) | (0x00ff & buf[2]); + writel(value, rk3190_priv->regbase+reg); + } else { + printk("%s : i2c len error\n", __func__); + } + + return count; +} + +static int rk3190_reset(struct snd_soc_codec *codec) +{ + writel(0x00, rk3190_priv->regbase+RK3190_RESET); + mdelay(10); + writel(0x03, rk3190_priv->regbase+RK3190_RESET); + mdelay(10); + + memcpy(codec->reg_cache, rk3190_reg_defaults, + sizeof(rk3190_reg_defaults)); + + return 0; +} + +int rk3190_headset_mic_detect(bool headset_status) +{ +#if 0 + struct snd_soc_codec *codec = rk3190_priv->codec; + + DBG("%s\n", __func__); + + if (!rk3190_priv || !rk3190_priv->codec) { + printk("%s : rk3190_priv or rk3190_priv->codec is NULL\n", __func__); + return -EINVAL; + } + + if (headset_status) { + snd_soc_update_bits(codec, RK3190_ADC_MIC_CTL, + RK3190_MICBIAS2_PWRD | RK3190_MICBIAS2_V_MASK, + RK3190_MICBIAS2_V_1_7); + } else {// headset is out, disable MIC2 && MIC1 Bias + DBG("%s : headset is out,disable Mic2 Bias\n", __func__); + snd_soc_update_bits(codec, RK3190_ADC_MIC_CTL, + RK3190_MICBIAS2_PWRD | RK3190_MICBIAS2_V_MASK, + RK3190_MICBIAS2_V_1_0|RK3190_MICBIAS2_PWRD); + } +#endif + return 0; +} +EXPORT_SYMBOL(rk3190_headset_mic_detect); + +bool get_hdmi_state(void) +{ + return is_hdmi_in; +} + +#ifdef CONFIG_MACH_RK_FAC +void rk3190_codec_set_spk(bool on) +#else +void codec_set_spk(bool on) +#endif +{ + struct snd_soc_codec *codec = rk3190_priv->codec; + + DBG("%s : %s\n", __func__, on ? "enable spk" : "disable spk"); + + if (!rk3190_priv || !rk3190_priv->codec) { + printk("%s : rk3190_priv or rk3190_priv->codec is NULL\n", __func__); + return; + } + + if (on) { + if (rk3190_for_mid) + { + snd_soc_update_bits(codec, RK3190_HPOUT_CTL, + RK3190_HPOUTL_MUTE_MSK, 1); + snd_soc_update_bits(codec, RK3190_HPOUT_CTL, + RK3190_HPOUTR_MUTE_MSK, RK3190_HPOUTR_MUTE_DIS); + } + else + { + snd_soc_dapm_enable_pin(&codec->dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin(&codec->dapm, "Ext Spk"); + } + } else { + if (rk3190_priv->spk_ctl_gpio != INVALID_GPIO) { + DBG("%s : set spk ctl gpio LOW\n", __func__); + gpio_set_value(rk3190_priv->spk_ctl_gpio, GPIO_LOW); + } + + if (rk3190_priv->hp_ctl_gpio != INVALID_GPIO) { + DBG("%s : set hp ctl gpio LOW\n", __func__); + gpio_set_value(rk3190_priv->hp_ctl_gpio, GPIO_LOW); + } + + if (rk3190_for_mid) + { + snd_soc_update_bits(codec, RK3190_HPOUT_CTL, + RK3190_HPOUTL_MUTE_MSK, RK3190_HPOUTL_MUTE_EN); + snd_soc_update_bits(codec, RK3190_HPOUT_CTL, + RK3190_HPOUTR_MUTE_MSK, RK3190_HPOUTR_MUTE_EN); + } + else + { + snd_soc_dapm_disable_pin(&codec->dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin(&codec->dapm, "Ext Spk"); + } + } + snd_soc_dapm_sync(&codec->dapm); + + is_hdmi_in = on ? 0 : 1; +} + +#ifdef CONFIG_MACH_RK_FAC +EXPORT_SYMBOL_GPL(rk3190_codec_set_spk); +#else +EXPORT_SYMBOL_GPL(codec_set_spk); +#endif + +#if 0 +static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -3900, 150, 0); +static const DECLARE_TLV_DB_SCALE(pga_vol_tlv, -1800, 150, 0); +static const DECLARE_TLV_DB_SCALE(bst_vol_tlv, 0, 2000, 0); +static const DECLARE_TLV_DB_SCALE(pga_agc_max_vol_tlv, -1350, 600, 0); +static const DECLARE_TLV_DB_SCALE(pga_agc_min_vol_tlv, -1800, 600, 0); + +static const char *rk3190_input_mode[] = {"Differential","Single-Ended"}; + +static const char *rk3190_micbias_ratio[] = {"1.0 Vref", "1.1 Vref", + "1.2 Vref", "1.3 Vref", "1.4 Vref", "1.5 Vref", "1.6 Vref", "1.7 Vref",}; + +static const char *rk3190_dis_en_sel[] = {"Disable", "Enable"}; + +static const char *rk3190_pga_agc_way[] = {"Normal", "Jack"}; + +static const char *rk3190_agc_backup_way[] = {"Normal", "Jack1", "Jack2", "Jack3"}; + +static const char *rk3190_pga_agc_hold_time[] = {"0ms", "2ms", + "4ms", "8ms", "16ms", "32ms", "64ms", "128ms", "256ms", "512ms", "1s"}; + +static const char *rk3190_pga_agc_ramp_up_time[] = {"Normal:500us Jack:125us", + "Normal:1ms Jack:250us", "Normal:2ms Jack:500us", "Normal:4ms Jack:1ms", + "Normal:8ms Jack:2ms", "Normal:16ms Jack:4ms", "Normal:32ms Jack:8ms", + "Normal:64ms Jack:16ms", "Normal:128ms Jack:32ms", "Normal:256ms Jack:64ms", + "Normal:512ms Jack:128ms"}; + +static const char *rk3190_pga_agc_ramp_down_time[] = {"Normal:125us Jack:32us", + "Normal:250us Jack:64us", "Normal:500us Jack:125us", "Normal:1ms Jack:250us", + "Normal:2ms Jack:500us", "Normal:4ms Jack:1ms", "Normal:8ms Jack:2ms", + "Normal:16ms Jack:4ms", "Normal:32ms Jack:8ms", "Normal:64ms Jack:16ms", + "Normal:128ms Jack:32ms"}; + +static const char *rk3190_pga_agc_mode[] = {"Normal", "Limiter"}; + +static const char *rk3190_pga_agc_recovery_mode[] = {"Right Now", "After AGC to Limiter"}; + +static const char *rk3190_pga_agc_noise_gate_threhold[] = {"-39dB", "-45dB", "-51dB", + "-57dB", "-63dB", "-69dB", "-75dB", "-81dB"}; + +static const char *rk3190_pga_agc_update_gain[] = {"Right Now", "After 1st Zero Cross"}; + +static const char *rk3190_pga_agc_approximate_sample_rate[] = {"96KHZ","48KHz","441KHZ", "32KHz", + "24KHz", "16KHz", "12KHz", "8KHz"}; + +static const struct soc_enum rk3190_bst_enum[] = { +SOC_ENUM_SINGLE(RK3190_BSTL_ALCL_CTL, RK3190_BSTL_MODE_SFT, 2, rk3190_input_mode), +}; + + +static const struct soc_enum rk3190_micbias_enum[] = { +SOC_ENUM_SINGLE(RK3190_ADC_MIC_CTL, RK3190_MICBIAS_VOL_SHT, 8, rk3190_micbias_ratio), +}; + +static const struct soc_enum rk3190_agcl_enum[] = { +SOC_ENUM_SINGLE(RK3190_PGAL_AGC_CTL1, RK3190_PGA_AGC_BK_WAY_SFT, 4, rk3190_agc_backup_way),/*0*/ +SOC_ENUM_SINGLE(RK3190_PGAL_AGC_CTL1, RK3190_PGA_AGC_WAY_SFT, 2, rk3190_pga_agc_way),/*1*/ +SOC_ENUM_SINGLE(RK3190_PGAL_AGC_CTL1, RK3190_PGA_AGC_HOLD_T_SFT, 11, rk3190_pga_agc_hold_time),/*2*/ +SOC_ENUM_SINGLE(RK3190_PGAL_AGC_CTL2, RK3190_PGA_AGC_GRU_T_SFT, 11, rk3190_pga_agc_ramp_up_time),/*3*/ +SOC_ENUM_SINGLE(RK3190_PGAL_AGC_CTL2, RK3190_PGA_AGC_GRD_T_SFT, 11, rk3190_pga_agc_ramp_down_time),/*4*/ +SOC_ENUM_SINGLE(RK3190_PGAL_AGC_CTL3, RK3190_PGA_AGC_MODE_SFT, 2, rk3190_pga_agc_mode),/*5*/ +SOC_ENUM_SINGLE(RK3190_PGAL_AGC_CTL3, RK3190_PGA_AGC_ZO_SFT, 2, rk3190_dis_en_sel),/*6*/ +SOC_ENUM_SINGLE(RK3190_PGAL_AGC_CTL3, RK3190_PGA_AGC_REC_MODE_SFT, 2, rk3190_pga_agc_recovery_mode),/*7*/ +SOC_ENUM_SINGLE(RK3190_PGAL_AGC_CTL3, RK3190_PGA_AGC_FAST_D_SFT, 2, rk3190_dis_en_sel),/*8*/ +SOC_ENUM_SINGLE(RK3190_PGAL_AGC_CTL3, RK3190_PGA_AGC_NG_SFT, 2, rk3190_dis_en_sel),/*9*/ +SOC_ENUM_SINGLE(RK3190_PGAL_AGC_CTL3, RK3190_PGA_AGC_NG_THR_SFT, 8, rk3190_pga_agc_noise_gate_threhold),/*10*/ +SOC_ENUM_SINGLE(RK3190_PGAL_AGC_CTL4, RK3190_PGA_AGC_ZO_MODE_SFT, 2, rk3190_pga_agc_update_gain),/*11*/ +SOC_ENUM_SINGLE(RK3190_PGAL_ASR_CTL, RK3190_PGA_SLOW_CLK_SFT, 2, rk3190_dis_en_sel),/*12*/ +SOC_ENUM_SINGLE(RK3190_PGAL_ASR_CTL, RK3190_PGA_ASR_SFT, 8, rk3190_pga_agc_approximate_sample_rate),/*13*/ +SOC_ENUM_SINGLE(RK3190_PGAL_AGC_CTL5, RK3190_PGA_AGC_SFT, 2, rk3190_dis_en_sel),/*14*/ +}; + +static const struct soc_enum rk3190_agcr_enum[] = { +SOC_ENUM_SINGLE(RK3190_PGAR_AGC_CTL1, RK3190_PGA_AGC_BK_WAY_SFT, 4, rk3190_agc_backup_way),/*0*/ +SOC_ENUM_SINGLE(RK3190_PGAR_AGC_CTL1, RK3190_PGA_AGC_WAY_SFT, 2, rk3190_pga_agc_way),/*1*/ +SOC_ENUM_SINGLE(RK3190_PGAR_AGC_CTL1, RK3190_PGA_AGC_HOLD_T_SFT, 11, rk3190_pga_agc_hold_time),/*2*/ +SOC_ENUM_SINGLE(RK3190_PGAR_AGC_CTL2, RK3190_PGA_AGC_GRU_T_SFT, 11, rk3190_pga_agc_ramp_up_time),/*3*/ +SOC_ENUM_SINGLE(RK3190_PGAR_AGC_CTL2, RK3190_PGA_AGC_GRD_T_SFT, 11, rk3190_pga_agc_ramp_down_time),/*4*/ +SOC_ENUM_SINGLE(RK3190_PGAR_AGC_CTL3, RK3190_PGA_AGC_MODE_SFT, 2, rk3190_pga_agc_mode),/*5*/ +SOC_ENUM_SINGLE(RK3190_PGAR_AGC_CTL3, RK3190_PGA_AGC_ZO_SFT, 2, rk3190_dis_en_sel),/*6*/ +SOC_ENUM_SINGLE(RK3190_PGAR_AGC_CTL3, RK3190_PGA_AGC_REC_MODE_SFT, 2, rk3190_pga_agc_recovery_mode),/*7*/ +SOC_ENUM_SINGLE(RK3190_PGAR_AGC_CTL3, RK3190_PGA_AGC_FAST_D_SFT, 2, rk3190_dis_en_sel),/*8*/ +SOC_ENUM_SINGLE(RK3190_PGAR_AGC_CTL3, RK3190_PGA_AGC_NG_SFT, 2, rk3190_dis_en_sel),/*9*/ +SOC_ENUM_SINGLE(RK3190_PGAR_AGC_CTL3, RK3190_PGA_AGC_NG_THR_SFT, 8, rk3190_pga_agc_noise_gate_threhold),/*10*/ +SOC_ENUM_SINGLE(RK3190_PGAR_AGC_CTL4, RK3190_PGA_AGC_ZO_MODE_SFT, 2, rk3190_pga_agc_update_gain),/*11*/ +SOC_ENUM_SINGLE(RK3190_PGAR_ASR_CTL, RK3190_PGA_SLOW_CLK_SFT, 2, rk3190_dis_en_sel),/*12*/ +SOC_ENUM_SINGLE(RK3190_PGAR_ASR_CTL, RK3190_PGA_ASR_SFT, 8, rk3190_pga_agc_approximate_sample_rate),/*13*/ +SOC_ENUM_SINGLE(RK3190_PGAR_AGC_CTL5, RK3190_PGA_AGC_SFT, 2, rk3190_dis_en_sel),/*14*/ +}; + +static const struct snd_kcontrol_new rk3190_snd_controls[] = { + //Add for set voice volume + SOC_DOUBLE_R_TLV("Speaker Playback Volume", RK3190_HPOUTL_GAIN, + RK3190_HPOUTR_GAIN, RK3190_HPOUT_GAIN_SFT, 31, 0, out_vol_tlv), + SOC_DOUBLE("Speaker Playback Switch", RK3190_HPOUT_CTL, + RK3190_HPOUTL_MUTE_SHT, RK3190_HPOUTR_MUTE_SHT, 1, 0), + SOC_DOUBLE_R_TLV("Headphone Playback Volume", RK3190_HPOUTL_GAIN, + RK3190_HPOUTR_GAIN, RK3190_HPOUT_GAIN_SFT, 31, 0, out_vol_tlv), + SOC_DOUBLE("Headphone Playback Switch", RK3190_HPOUT_CTL, + RK3190_HPOUTL_MUTE_SHT, RK3190_HPOUTR_MUTE_SHT, 1, 0), + SOC_DOUBLE_R_TLV("Earpiece Playback Volume", RK3190_HPOUTL_GAIN, + RK3190_HPOUTR_GAIN, RK3190_HPOUT_GAIN_SFT, 31, 0, out_vol_tlv), + SOC_DOUBLE("Earpiece Playback Switch", RK3190_HPOUT_CTL, + RK3190_HPOUTL_MUTE_SHT, RK3190_HPOUTR_MUTE_SHT, 1, 0), + + + //Add for set capture mute + SOC_SINGLE_TLV("Main Mic Capture Volume", RK3190_BST_CTL, + RK3190_BSTL_GAIN_SHT, 1, 0, bst_vol_tlv), + SOC_SINGLE("Main Mic Capture Switch", RK3190_BST_CTL, + RK3190_BSTL_MUTE_SHT, 1, 0), + SOC_SINGLE_TLV("Headset Mic Capture Volume", RK3190_BST_CTL, + RK3190_BSTR_GAIN_SHT, 1, 0, bst_vol_tlv), + SOC_SINGLE("Headset Mic Capture Switch", RK3190_BST_CTL, + RK3190_BSTR_MUTE_SHT, 1, 0), + + SOC_SINGLE("ALCL Switch", RK3190_ALC_MUNIN_CTL, + RK3190_ALCL_MUTE_SHT, 1, 0), + SOC_SINGLE_TLV("ALCL Capture Volume", RK3190_BSTL_ALCL_CTL, + RK3190_ALCL_GAIN_SHT, 31, 0, pga_vol_tlv), + SOC_SINGLE("ALCR Switch", RK3190_ALC_MUNIN_CTL, + RK3190_ALCR_MUTE_SHT, 1, 0), + SOC_SINGLE_TLV("ALCR Capture Volume", RK3190_ALCR_GAIN_CTL, + RK3190_ALCL_GAIN_SHT, 31, 0, pga_vol_tlv), + + SOC_ENUM("BST_L Mode", rk3190_bst_enum[0]), + + SOC_ENUM("Micbias Voltage", rk3190_micbias_enum[0]), + SOC_ENUM("PGAL AGC Back Way", rk3190_agcl_enum[0]), + SOC_ENUM("PGAL AGC Way", rk3190_agcl_enum[1]), + SOC_ENUM("PGAL AGC Hold Time", rk3190_agcl_enum[2]), + SOC_ENUM("PGAL AGC Ramp Up Time", rk3190_agcl_enum[3]), + SOC_ENUM("PGAL AGC Ramp Down Time", rk3190_agcl_enum[4]), + SOC_ENUM("PGAL AGC Mode", rk3190_agcl_enum[5]), + SOC_ENUM("PGAL AGC Gain Update Zero Enable", rk3190_agcl_enum[6]), + SOC_ENUM("PGAL AGC Gain Recovery LPGA VOL", rk3190_agcl_enum[7]), + SOC_ENUM("PGAL AGC Fast Decrement Enable", rk3190_agcl_enum[8]), + SOC_ENUM("PGAL AGC Noise Gate Enable", rk3190_agcl_enum[9]), + SOC_ENUM("PGAL AGC Noise Gate Threhold", rk3190_agcl_enum[10]), + SOC_ENUM("PGAL AGC Upate Gain", rk3190_agcl_enum[11]), + SOC_ENUM("PGAL AGC Slow Clock Enable", rk3190_agcl_enum[12]), + SOC_ENUM("PGAL AGC Approximate Sample Rate", rk3190_agcl_enum[13]), + SOC_ENUM("PGAL AGC Enable", rk3190_agcl_enum[14]), + + SOC_SINGLE_TLV("PGAL AGC Volume", RK3190_PGAL_AGC_CTL4, + RK3190_PGA_AGC_VOL_SFT, 31, 0, pga_vol_tlv),//AGC disable and 0x0a bit 5 is 1 + + SOC_SINGLE("PGAL AGC Max Level High 8 Bits", RK3190_PGAL_AGC_MAX_H, + 0, 255, 0), + SOC_SINGLE("PGAL AGC Max Level Low 8 Bits", RK3190_PGAL_AGC_MAX_L, + 0, 255, 0), + SOC_SINGLE("PGAL AGC Min Level High 8 Bits", RK3190_PGAL_AGC_MIN_H, + 0, 255, 0), + SOC_SINGLE("PGAL AGC Min Level Low 8 Bits", RK3190_PGAL_AGC_MIN_L, + 0, 255, 0), + + SOC_SINGLE_TLV("PGAL AGC Max Gain", RK3190_PGAL_AGC_CTL5, + RK3190_PGA_AGC_MAX_G_SFT, 7, 0, pga_agc_max_vol_tlv),//AGC enable and 0x0a bit 5 is 1 + SOC_SINGLE_TLV("PGAL AGC Min Gain", RK3190_PGAL_AGC_CTL5, + RK3190_PGA_AGC_MIN_G_SFT, 7, 0, pga_agc_min_vol_tlv),//AGC enable and 0x0a bit 5 is 1 + + SOC_ENUM("PGAR AGC Back Way", rk3190_agcr_enum[0]), + SOC_ENUM("PGAR AGC Way", rk3190_agcr_enum[1]), + SOC_ENUM("PGAR AGC Hold Time", rk3190_agcr_enum[2]), + SOC_ENUM("PGAR AGC Ramp Up Time", rk3190_agcr_enum[3]), + SOC_ENUM("PGAR AGC Ramp Down Time", rk3190_agcr_enum[4]), + SOC_ENUM("PGAR AGC Mode", rk3190_agcr_enum[5]), + SOC_ENUM("PGAR AGC Gain Update Zero Enable", rk3190_agcr_enum[6]), + SOC_ENUM("PGAR AGC Gain Recovery LPGA VOL", rk3190_agcr_enum[7]), + SOC_ENUM("PGAR AGC Fast Decrement Enable", rk3190_agcr_enum[8]), + SOC_ENUM("PGAR AGC Noise Gate Enable", rk3190_agcr_enum[9]), + SOC_ENUM("PGAR AGC Noise Gate Threhold", rk3190_agcr_enum[10]), + SOC_ENUM("PGAR AGC Upate Gain", rk3190_agcr_enum[11]), + SOC_ENUM("PGAR AGC Slow Clock Enable", rk3190_agcr_enum[12]), + SOC_ENUM("PGAR AGC Approximate Sample Rate", rk3190_agcr_enum[13]), + SOC_ENUM("PGAR AGC Enable", rk3190_agcr_enum[14]), + + SOC_SINGLE_TLV("PGAR AGC Volume", RK3190_PGAR_AGC_CTL4, + RK3190_PGA_AGC_VOL_SFT, 31, 0, pga_vol_tlv),//AGC disable and 0x0a bit 4 is 1 + + SOC_SINGLE("PGAR AGC Max Level High 8 Bits", RK3190_PGAR_AGC_MAX_H, + 0, 255, 0), + SOC_SINGLE("PGAR AGC Max Level Low 8 Bits", RK3190_PGAR_AGC_MAX_L, + 0, 255, 0), + SOC_SINGLE("PGAR AGC Min Level High 8 Bits", RK3190_PGAR_AGC_MIN_H, + 0, 255, 0), + SOC_SINGLE("PGAR AGC Min Level Low 8 Bits", RK3190_PGAR_AGC_MIN_L, + 0, 255, 0), + + SOC_SINGLE_TLV("PGAR AGC Max Gain", RK3190_PGAR_AGC_CTL5, + RK3190_PGA_AGC_MAX_G_SFT, 7, 0, pga_agc_max_vol_tlv),//AGC enable and 0x06 bit 4 is 1 + SOC_SINGLE_TLV("PGAR AGC Min Gain", RK3190_PGAR_AGC_CTL5, + RK3190_PGA_AGC_MIN_G_SFT, 7, 0, pga_agc_min_vol_tlv),//AGC enable and 0x06 bit 4 is 1 + +}; +#endif + +//For tiny alsa playback/capture/voice call path +static const char *rk3190_playback_path_mode[] = {"OFF", "RCV", "SPK", "HP", "HP_NO_MIC", "BT", "SPK_HP", //0-6 + "RING_SPK", "RING_HP", "RING_HP_NO_MIC", "RING_SPK_HP"};//7-10 + +static const char *rk3190_capture_path_mode[] = {"MIC OFF", "Main Mic", "Hands Free Mic", "BT Sco Mic"}; + +static const char *rk3190_voice_call_path_mode[] = {"OFF", "RCV", "SPK", "HP", "HP_NO_MIC", "BT"};//0-5 + +static const SOC_ENUM_SINGLE_DECL(rk3190_playback_path_type, 0, 0, rk3190_playback_path_mode); + +static const SOC_ENUM_SINGLE_DECL(rk3190_capture_path_type, 0, 0, rk3190_capture_path_mode); + +static const SOC_ENUM_SINGLE_DECL(rk3190_voice_call_path_type, 0, 0, rk3190_voice_call_path_mode); + +static int rk3190_codec_power_up(int type); +static int rk3190_codec_power_down(int type); + +static int rk3190_playback_path_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct rk3190_codec_priv *rk3190 = rk3190_priv; + + if (!rk3190) { + printk("%s : rk3190_priv is NULL\n", __func__); + return -EINVAL; + } + + DBG("%s : playback_path %ld\n",__func__,ucontrol->value.integer.value[0]); + + ucontrol->value.integer.value[0] = rk3190->playback_path; + + return 0; +} + +static int rk3190_playback_path_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct rk3190_codec_priv *rk3190 = rk3190_priv; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + long int pre_path; + + if (!rk3190) { + printk("%s : rk3190_priv is NULL\n", __func__); + return -EINVAL; + } + + if (rk3190->playback_path == ucontrol->value.integer.value[0]){ + DBG("%s : playback_path is not changed!\n",__func__); + return 0; + } + + pre_path = rk3190->playback_path; + rk3190->playback_path = ucontrol->value.integer.value[0]; + + printk("%s : set playback_path %ld, pre_path %ld\n", __func__, + rk3190->playback_path, pre_path); + + + // mute output for pop noise + if (rk3190 && rk3190->spk_ctl_gpio != INVALID_GPIO) { + DBG("%s : set spk ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->spk_ctl_gpio, GPIO_LOW); + } + + if (rk3190 && rk3190->hp_ctl_gpio != INVALID_GPIO) { + DBG("%s : set hp ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->hp_ctl_gpio, GPIO_LOW); + } + + if(get_hdmi_state()) + return 0; + + switch (rk3190->playback_path) { + case OFF: + if (pre_path != OFF) + rk3190_codec_power_down(RK3190_CODEC_PLAYBACK); + break; + case RCV: + if (rk3190->voice_call_path != OFF) { + //close incall route + rk3190_codec_power_down(RK3190_CODEC_INCALL); + + rk3190->voice_call_path = OFF; + } + break; + case SPK_PATH: + case RING_SPK: + DBG("%s : PUT SPK_PATH\n",__func__); + if (pre_path == OFF) + rk3190_codec_power_up(RK3190_CODEC_PLAYBACK); +#if 0 + snd_soc_update_bits(codec, RK3190_SPKL_CTL, + rk3190_VOL_MASK, SPKOUT_VOLUME); //, volume (bit 0-4) + snd_soc_update_bits(codec, rk3190_SPKR_CTL, + rk3190_VOL_MASK, SPKOUT_VOLUME); +#endif + if (rk3190 && rk3190->hp_ctl_gpio != INVALID_GPIO) { + DBG("%s : set hp ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->hp_ctl_gpio, GPIO_LOW); + //sleep for MOSFET or SPK power amplifier chip + msleep(HP_MOS_DELAY); + } + if (rk3190 && rk3190->spk_ctl_gpio != INVALID_GPIO) { + DBG("%s : set spk ctl gpio HIGH\n", __func__); + gpio_set_value(rk3190->spk_ctl_gpio, GPIO_HIGH); + //sleep for MOSFET or SPK power amplifier chip + msleep(SPK_AMP_DELAY); + } + + break; + case HP_PATH: + case HP_NO_MIC: + case RING_HP: + case RING_HP_NO_MIC: + if (pre_path == OFF) + rk3190_codec_power_up(RK3190_CODEC_PLAYBACK); +#if 0 + snd_soc_update_bits(codec, rk3190_SPKL_CTL, + rk3190_VOL_MASK, HPOUT_VOLUME); //, volume (bit 0-4) + snd_soc_update_bits(codec, rk3190_SPKR_CTL, + rk3190_VOL_MASK, HPOUT_VOLUME); +#endif + if (rk3190 && rk3190->hp_ctl_gpio != INVALID_GPIO) { + DBG("%s : set hp ctl gpio HIGH\n", __func__); + gpio_set_value(rk3190->hp_ctl_gpio, GPIO_HIGH); + //sleep for MOSFET or SPK power amplifier chip + msleep(HP_MOS_DELAY); + } + if (rk3190 && rk3190->spk_ctl_gpio != INVALID_GPIO) { + DBG("%s : set spk ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->spk_ctl_gpio, GPIO_LOW); + //sleep for MOSFET or SPK power amplifier chip + msleep(SPK_AMP_DELAY); + } + + break; + case BT: + break; + case SPK_HP: + case RING_SPK_HP: + if (pre_path == OFF) + rk3190_codec_power_up(RK3190_CODEC_PLAYBACK); +#if 0 + snd_soc_update_bits(codec, rk3190_SPKL_CTL, + rk3190_VOL_MASK, HPOUT_VOLUME); //, volume (bit 0-4) + snd_soc_update_bits(codec, rk3190_SPKR_CTL, + rk3190_VOL_MASK, HPOUT_VOLUME); +#endif + if (rk3190 && rk3190->spk_ctl_gpio != INVALID_GPIO) { + DBG("%s : set spk ctl gpio HIGH\n", __func__); + gpio_set_value(rk3190->spk_ctl_gpio, GPIO_HIGH); + //sleep for MOSFET or SPK power amplifier chip + msleep(SPK_AMP_DELAY); + } + + if (rk3190 && rk3190->hp_ctl_gpio != INVALID_GPIO) { + DBG("%s : set hp ctl gpio HIGH\n", __func__); + gpio_set_value(rk3190->hp_ctl_gpio, GPIO_HIGH); + //sleep for MOSFET or SPK power amplifier chip + msleep(HP_MOS_DELAY); + } + + break; + default: + return -EINVAL; + } + + return 0; +} + +static int rk3190_capture_path_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct rk3190_codec_priv *rk3190 = rk3190_priv; + + if (!rk3190) { + printk("%s : rk3190_priv is NULL\n", __func__); + return -EINVAL; + } + + DBG("%s : capture_path %ld\n", __func__, + ucontrol->value.integer.value[0]); + + ucontrol->value.integer.value[0] = rk3190->capture_path; + + return 0; +} + +static int rk3190_capture_path_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct rk3190_codec_priv *rk3190 = rk3190_priv; + //struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + long int pre_path; + + if (!rk3190) { + printk("%s : rk3190_priv is NULL\n", __func__); + return -EINVAL; + } + + if (rk3190->capture_path == ucontrol->value.integer.value[0]){ + DBG("%s : capture_path is not changed!\n", __func__); + return 0; + } + + pre_path = rk3190->capture_path; + rk3190->capture_path = ucontrol->value.integer.value[0]; + + printk("%s : set capture_path %ld, pre_path %ld\n", __func__, + rk3190->capture_path, pre_path); + + switch (rk3190->capture_path) { + case MIC_OFF: + if (pre_path != MIC_OFF) + rk3190_codec_power_down(RK3190_CODEC_CAPTURE); + break; + case Main_Mic: + DBG("%s : PUT MAIN_MIC_PATH\n",__func__); + if (pre_path == MIC_OFF) + rk3190_codec_power_up(RK3190_CODEC_CAPTURE); +#if 0 + if (rk3190 && rk3190->mic_sel_gpio != INVALID_GPIO) { + DBG("%s : set mic sel gpio HIGH\n", __func__); + gpio_set_value(rk3190->mic_sel_gpio, GPIO_HIGH); + } +#endif + break; + case Hands_Free_Mic: + if (pre_path == MIC_OFF) + rk3190_codec_power_up(RK3190_CODEC_CAPTURE); +#if 0 + if (rk3190 && rk3190->mic_sel_gpio != INVALID_GPIO) { + DBG("%s : set mic sel gpio HIGH\n", __func__); + gpio_set_value(rk3190->mic_sel_gpio, GPIO_LOW); + } +#endif + break; + case BT_Sco_Mic: + break; + default: + return -EINVAL; + } + + return 0; +} + +static int rk3190_voice_call_path_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct rk3190_codec_priv *rk3190 = rk3190_priv; + + if (!rk3190) { + printk("%s : rk3190_priv is NULL\n", __func__); + return -EINVAL; + } + + DBG("%s : voice_call_path %ld\n", __func__, + ucontrol->value.integer.value[0]); + + ucontrol->value.integer.value[0] = rk3190->voice_call_path; + + return 0; +} + +static int rk3190_voice_call_path_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct rk3190_codec_priv *rk3190 = rk3190_priv; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + long int pre_path; + + if (!rk3190) { + printk("%s : rk3190_priv is NULL\n", __func__); + return -EINVAL; + } + + if (rk3190->voice_call_path == ucontrol->value.integer.value[0]){ + DBG("%s : voice_call_path is not changed!\n",__func__); + return 0; + } + + pre_path = rk3190->voice_call_path; + rk3190->voice_call_path = ucontrol->value.integer.value[0]; + + printk("%s : set voice_call_path %ld, pre_path %ld\n", __func__, + rk3190->voice_call_path, pre_path); +/* + if (rk3190 && rk3190->spk_ctl_gpio != INVALID_GPIO) { + DBG("%s : set spk ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->spk_ctl_gpio, GPIO_LOW); + } + + if (rk3190 && rk3190->hp_ctl_gpio != INVALID_GPIO) { + DBG("%s : set hp ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->hp_ctl_gpio, GPIO_LOW); + } +*/ + switch (rk3190->voice_call_path) { + case OFF: + + if (rk3190 && rk3190->spk_ctl_gpio != INVALID_GPIO) { + DBG("%s : set spk ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->spk_ctl_gpio, GPIO_LOW); + } + + if (rk3190 && rk3190->hp_ctl_gpio != INVALID_GPIO) { + DBG("%s : set hp ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->hp_ctl_gpio, GPIO_LOW); + } + + if (rk3190 && rk3190->ear_ctl_gpio != INVALID_GPIO) { + DBG("%s : set ear ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->ear_ctl_gpio, GPIO_LOW); + } + + rk3190_codec_power_down(RK3190_CODEC_INCALL); + rk3190_codec_power_up(RK3190_CODEC_PLAYBACK); + break; + case RCV: +#if 0 + //set mic for modem + if (rk3190 && rk3190->mic_sel_gpio != INVALID_GPIO) { + DBG("%s : set mic sel gpio HIGH\n", __func__); + gpio_set_value(rk3190->mic_sel_gpio, GPIO_HIGH); + } +#endif + +#if 0 + //rcv is controled by modem, so close incall route + if (pre_path != OFF && pre_path != BT) + rk3190_codec_power_down(RK3190_CODEC_INCALL); +#endif + rk3190_codec_power_up(RK3190_CODEC_INCALL); + + if (rk3190 && rk3190->hp_ctl_gpio != INVALID_GPIO) { + DBG("%s : set spk ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->hp_ctl_gpio, GPIO_LOW); + } + + if (rk3190 && rk3190->spk_ctl_gpio != INVALID_GPIO) { + DBG("%s : set spk ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->spk_ctl_gpio, GPIO_LOW); + } + + if (rk3190 && rk3190->ear_ctl_gpio != INVALID_GPIO) { + DBG("%s : set ear ctl gpio HIGH\n", __func__); + gpio_set_value(rk3190->ear_ctl_gpio, GPIO_HIGH); + } + + break; + case SPK_PATH: +#if 0 + //set mic for modem + if (rk3190 && rk3190->mic_sel_gpio != INVALID_GPIO) { + DBG("%s : set mic sel gpio HIGH\n", __func__); + gpio_set_value(rk3190->mic_sel_gpio, GPIO_HIGH); + } +#endif + //open incall route + if (pre_path == OFF || + pre_path == RCV || + pre_path == BT) + rk3190_codec_power_up(RK3190_CODEC_INCALL); +#if 0 + snd_soc_update_bits(codec, rk3190_SPKL_CTL, + rk3190_VOL_MASK, SPKOUT_VOLUME); //, volume (bit 0-4) + snd_soc_update_bits(codec, rk3190_SPKR_CTL, + rk3190_VOL_MASK, SPKOUT_VOLUME); +#endif + if (rk3190 && rk3190->hp_ctl_gpio != INVALID_GPIO) { + DBG("%s : set spk ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->hp_ctl_gpio, GPIO_LOW); + } + + if (rk3190 && rk3190->ear_ctl_gpio != INVALID_GPIO) { + DBG("%s : set ear ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->ear_ctl_gpio, GPIO_LOW); + } + if (rk3190 && rk3190->spk_ctl_gpio != INVALID_GPIO) { + DBG("%s : set spk ctl gpio HIGH\n", __func__); + gpio_set_value(rk3190->spk_ctl_gpio, GPIO_HIGH); + //sleep for MOSFET or SPK power amplifier chip + msleep(SPK_AMP_DELAY); + } + break; + case HP_PATH: +#if 0 + //set mic for modem + if (rk3190 && rk3190->mic_sel_gpio != INVALID_GPIO) { + DBG("%s : set mic sel gpio HIGH\n", __func__); + gpio_set_value(rk3190->mic_sel_gpio, GPIO_LOW); + } +#endif + //open incall route + if (pre_path == OFF || + pre_path == RCV || + pre_path == BT) + rk3190_codec_power_up(RK3190_CODEC_INCALL); +#if 0 + snd_soc_update_bits(codec, rk3190_SPKL_CTL, + rk3190_VOL_MASK, HPOUT_VOLUME); //, volume (bit 0-4) + snd_soc_update_bits(codec, rk3190_SPKR_CTL, + rk3190_VOL_MASK, HPOUT_VOLUME); +#endif + + if (rk3190 && rk3190->hp_ctl_gpio != INVALID_GPIO) { + DBG("%s : set spk ctl gpio HIGH\n", __func__); + gpio_set_value(rk3190->hp_ctl_gpio, GPIO_HIGH); + //sleep for MOSFET or SPK power amplifier chip + msleep(HP_MOS_DELAY); + } + + if (rk3190 && rk3190->spk_ctl_gpio != INVALID_GPIO) { + DBG("%s : set spk ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->spk_ctl_gpio, GPIO_LOW); + } + + if (rk3190 && rk3190->ear_ctl_gpio != INVALID_GPIO) { + DBG("%s : set ear ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->ear_ctl_gpio, GPIO_LOW); + } + + break; + case HP_NO_MIC: +#if 0 + //set mic for modem + if (rk3190 && rk3190->mic_sel_gpio != INVALID_GPIO) { + DBG("%s : set mic sel gpio HIGH\n", __func__); + gpio_set_value(rk3190->mic_sel_gpio, GPIO_HIGH); + } +#endif + //open incall route + if (pre_path == OFF || + pre_path == RCV || + pre_path == BT) + rk3190_codec_power_up(RK3190_CODEC_INCALL); +#if 0 + snd_soc_update_bits(codec, rk3190_SPKL_CTL, + rk3190_VOL_MASK, HPOUT_VOLUME); //, volume (bit 0-4) + snd_soc_update_bits(codec, rk3190_SPKR_CTL, + rk3190_VOL_MASK, HPOUT_VOLUME); +#endif + + if (rk3190 && rk3190->hp_ctl_gpio != INVALID_GPIO) { + DBG("%s : set spk ctl gpio HIGH\n", __func__); + gpio_set_value(rk3190->hp_ctl_gpio, GPIO_HIGH); + //sleep for MOSFET or SPK power amplifier chip + msleep(HP_MOS_DELAY); + } + + if (rk3190 && rk3190->spk_ctl_gpio != INVALID_GPIO) { + DBG("%s : set spk ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->spk_ctl_gpio, GPIO_LOW); + } + + if (rk3190 && rk3190->ear_ctl_gpio != INVALID_GPIO) { + DBG("%s : set ear ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->ear_ctl_gpio, GPIO_LOW); + } + + break; + case BT: + //BT is controled by modem, so close incall route + if (pre_path != OFF && + pre_path != RCV) + rk3190_codec_power_down(RK3190_CODEC_INCALL); + break; + + if (rk3190 && rk3190->hp_ctl_gpio != INVALID_GPIO) { + DBG("%s : set spk ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->hp_ctl_gpio, GPIO_LOW); + //sleep for MOSFET or SPK power amplifier chip + msleep(HP_MOS_DELAY); + } + + if (rk3190 && rk3190->spk_ctl_gpio != INVALID_GPIO) { + DBG("%s : set spk ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->spk_ctl_gpio, GPIO_LOW); + } + + if (rk3190 && rk3190->ear_ctl_gpio != INVALID_GPIO) { + DBG("%s : set ear ctl gpio LOW\n", __func__); + gpio_set_value(rk3190->ear_ctl_gpio, GPIO_LOW); + } + + default: + return -EINVAL; + } + + return 0; +} + +static const struct snd_kcontrol_new rk3190_snd_path_controls[] = { + SOC_ENUM_EXT("Playback Path", rk3190_playback_path_type, + rk3190_playback_path_get, rk3190_playback_path_put), + + SOC_ENUM_EXT("Capture MIC Path", rk3190_capture_path_type, + rk3190_capture_path_get, rk3190_capture_path_put), + + SOC_ENUM_EXT("Voice Call Path", rk3190_voice_call_path_type, + rk3190_voice_call_path_get, rk3190_voice_call_path_put), +}; + +#if 0 +static int rk3190_dacl_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + snd_soc_update_bits(codec, RK3190_DAC_ENABLE, + RK3190_DACL_WORK,0); + snd_soc_update_bits(codec, RK3190_DAC_ENABLE, + RK3190_DACL_EN | RK3190_DACL_CLK_EN, + RK3190_DACL_EN | RK3190_DACL_CLK_EN); + snd_soc_update_bits(codec, RK3190_DAC_ENABLE, + RK3190_DACL_WORK, RK3190_DACL_WORK); + break; + + case SND_SOC_DAPM_POST_PMD: + snd_soc_update_bits(codec, RK3190_DAC_ENABLE, + RK3190_DACL_EN | RK3190_DACL_CLK_EN,0); + snd_soc_update_bits(codec, RK3190_DAC_ENABLE, + RK3190_DACL_WORK, 0); + break; + + default: + return 0; + } + + return 0; +} + +static int rk3190_dacr_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + snd_soc_update_bits(codec, RK3190_DAC_ENABLE, + RK3190_DACR_WORK,0); + snd_soc_update_bits(codec, RK3190_DAC_ENABLE, + RK3190_DACR_EN | RK3190_DACR_CLK_EN, + RK3190_DACR_EN | RK3190_DACR_CLK_EN); + snd_soc_update_bits(codec, RK3190_DAC_ENABLE, + RK3190_DACR_WORK, RK3190_DACR_WORK); + break; + + case SND_SOC_DAPM_POST_PMD: + snd_soc_update_bits(codec, RK3190_DAC_ENABLE, + RK3190_DACR_EN | RK3190_DACR_CLK_EN,0); + snd_soc_update_bits(codec, RK3190_DAC_ENABLE, + RK3190_DACR_WORK, 0); + break; + + default: + return 0; + } + + return 0; +} + +static int rk3190_adcl_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + snd_soc_update_bits(codec, RK3190_ADC_ENABLE, + RK3190_ADCL_CLK_EN_SFT | RK3190_ADCL_AMP_EN_SFT, + RK3190_ADCL_CLK_EN | RK3190_ADCL_AMP_EN); + break; + + case SND_SOC_DAPM_POST_PMD: + snd_soc_update_bits(codec, RK3190_ADC_ENABLE, + RK3190_ADCL_CLK_EN_SFT | RK3190_ADCL_AMP_EN_SFT,0); + break; + + default: + return 0; + } + + return 0; +} + +static int rk3190_adcr_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + snd_soc_update_bits(codec, RK3190_ADC_ENABLE, + RK3190_ADCR_CLK_EN_SFT | RK3190_ADCR_AMP_EN_SFT, + RK3190_ADCR_CLK_EN | RK3190_ADCR_AMP_EN ); + break; + + case SND_SOC_DAPM_POST_PMD: + snd_soc_update_bits(codec, RK3190_ADC_ENABLE, + RK3190_ADCR_CLK_EN_SFT | RK3190_ADCR_AMP_EN_SFT,0); + break; + + default: + return 0; + } + + return 0; +} + +/* HPmix */ +static const struct snd_kcontrol_new rk3190_hpmixl[] = { + SOC_DAPM_SINGLE("ALCR Switch", RK3190_HPMIX_S_SELECT, + RK3190_HPMIXL_SEL_ALCR_SFT, 1, 0), + SOC_DAPM_SINGLE("ALCL Switch", RK3190_HPMIX_S_SELECT, + RK3190_HPMIXL_SEL_ALCL_SFT, 1, 0), + SOC_DAPM_SINGLE("DACL Switch", RK3190_HPMIX_S_SELECT, + RK3190_HPMIXL_SEL_DACL_SFT, 1, 0), +}; + +static const struct snd_kcontrol_new rk3190_hpmixr[] = { + SOC_DAPM_SINGLE("ALCR Switch", RK3190_HPMIX_S_SELECT, + RK3190_HPMIXR_SEL_ALCR_SFT, 1, 0), + SOC_DAPM_SINGLE("ALCL Switch", RK3190_HPMIX_S_SELECT, + RK3190_HPMIXR_SEL_ALCL_SFT, 1, 0), + SOC_DAPM_SINGLE("DACR Switch", RK3190_HPMIX_S_SELECT, + RK3190_HPMIXR_SEL_DACR_SFT, 1, 0), +}; + +static int rk3190_hpmixl_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + snd_soc_update_bits(codec, RK3190_DAC_CTL, + RK3190_ZO_DET_VOUTR_SFT, RK3190_ZO_DET_VOUTR_EN); + snd_soc_update_bits(codec, RK3190_DAC_CTL, + RK3190_ZO_DET_VOUTL_SFT, RK3190_ZO_DET_VOUTL_EN); + break; + + case SND_SOC_DAPM_PRE_PMD: + snd_soc_update_bits(codec, RK3190_DAC_CTL, + RK3190_ZO_DET_VOUTR_SFT, RK3190_ZO_DET_VOUTR_DIS); + snd_soc_update_bits(codec, RK3190_DAC_CTL, + RK3190_ZO_DET_VOUTL_SFT, RK3190_ZO_DET_VOUTL_DIS); + break; + + default: + return 0; + } + + return 0; +} + +static int rk3190_hpmixr_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; +#if 0 + switch (event) { + case SND_SOC_DAPM_POST_PMU: + snd_soc_update_bits(codec, RK3190_HPMIX_CTL, + RK3190_HPMIXR_WORK2, RK3190_HPMIXR_WORK2); + break; + + case SND_SOC_DAPM_PRE_PMD: + snd_soc_update_bits(codec, RK3190_HPMIX_CTL, + RK3190_HPMIXR_WORK2, 0); + break; + + default: + return 0; + } +#endif + return 0; +} + +/* HP MUX */ + +static const char *hpl_sel[] = {"HPMIXL", "DACL"}; + +static const struct soc_enum hpl_sel_enum = + SOC_ENUM_SINGLE(RK3190_HPMIX_S_SELECT, RK3190_HPMIXL_BYPASS_SFT, + ARRAY_SIZE(hpl_sel), hpl_sel); + +static const struct snd_kcontrol_new hpl_sel_mux = + SOC_DAPM_ENUM("HPL select Mux", hpl_sel_enum); + +static const char *hpr_sel[] = {"HPMIXR", "DACR"}; + +static const struct soc_enum hpr_sel_enum = + SOC_ENUM_SINGLE(RK3190_HPMIX_S_SELECT, RK3190_HPMIXR_BYPASS_SFT, + ARRAY_SIZE(hpr_sel), hpr_sel); + +static const struct snd_kcontrol_new hpr_sel_mux = + SOC_DAPM_ENUM("HPR select Mux", hpr_sel_enum); + +/* IN_L MUX */ +static const char *lnl_sel[] = {"NO","BSTL", "LINEL","NOUSE"}; + +static const struct soc_enum lnl_sel_enum = + SOC_ENUM_SINGLE(RK3190_ALC_MUNIN_CTL, RK3190_MUXINL_F_SHT, + ARRAY_SIZE(lnl_sel), lnl_sel); + +static const struct snd_kcontrol_new lnl_sel_mux = + SOC_DAPM_ENUM("MUXIN_L select", lnl_sel_enum); + +/* IN_R MUX */ +static const char *lnr_sel[] = {"NO","BSTR", "LINER","NOUSE"}; + +static const struct soc_enum lnr_sel_enum = + SOC_ENUM_SINGLE(RK3190_ALC_MUNIN_CTL, RK3190_MUXINR_F_SHT, + ARRAY_SIZE(lnr_sel), lnr_sel); + +static const struct snd_kcontrol_new lnr_sel_mux = + SOC_DAPM_ENUM("MUXIN_R select", lnr_sel_enum); + + +static const struct snd_soc_dapm_widget rk3190_dapm_widgets[] = { + + /* microphone bias */ + SND_SOC_DAPM_MICBIAS("Mic Bias", RK3190_ADC_MIC_CTL, + RK3190_MICBIAS_VOL_ENABLE, 0), + + /* DACs */ + SND_SOC_DAPM_DAC_E("DACL", NULL, SND_SOC_NOPM, + 0, 0, rk3190_dacl_event, + SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_DAC_E("DACR", NULL, SND_SOC_NOPM, + 0, 0, rk3190_dacr_event, + SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), + + /* ADCs */ + SND_SOC_DAPM_ADC_E("ADCL", NULL, SND_SOC_NOPM, + 0, 0, rk3190_adcl_event, + SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_ADC_E("ADCR", NULL, SND_SOC_NOPM, + 0, 0, rk3190_adcr_event, + SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), + + /* PGA */ + SND_SOC_DAPM_PGA("BSTL", RK3190_BST_CTL, + RK3190_BSTL_PWRD_SFT, 0, NULL, 0), + SND_SOC_DAPM_PGA("BSTR", RK3190_BST_CTL, + RK3190_BSTR_PWRD_SFT, 0, NULL, 0), + SND_SOC_DAPM_PGA("ALCL", RK3190_ALC_MUNIN_CTL, + RK3190_ALCL_PWR_SHT , 0, NULL, 0), + SND_SOC_DAPM_PGA("ALCR", RK3190_ALC_MUNIN_CTL, + RK3190_ALCR_PWR_SHT , 0, NULL, 0), + SND_SOC_DAPM_PGA("HPL", RK3190_HPOUT_CTL, + RK3190_HPOUTL_PWR_SHT, 0, NULL, 0), + SND_SOC_DAPM_PGA("HPR", RK3190_HPOUT_CTL, + RK3190_HPOUTR_PWR_SHT, 0, NULL, 0), + + /* MIXER */ + SND_SOC_DAPM_MIXER_E("HPMIXL", RK3190_HPMIX_CTL, + RK3190_HPMIXL_SFT, 0, rk3190_hpmixl, + ARRAY_SIZE(rk3190_hpmixl),rk3190_hpmixl_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_MIXER_E("HPMIXR", RK3190_HPMIX_CTL, + RK3190_HPMIXR_SFT, 0, rk3190_hpmixr, + ARRAY_SIZE(rk3190_hpmixr),rk3190_hpmixr_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + + /* MUX */ + SND_SOC_DAPM_MUX("IN_R Mux", SND_SOC_NOPM, 0, 0, + &lnr_sel_mux), + SND_SOC_DAPM_MUX("IN_L Mux", SND_SOC_NOPM, 0, 0, + &lnl_sel_mux), + SND_SOC_DAPM_MUX("HPL Mux", SND_SOC_NOPM, 0, 0, + &hpl_sel_mux), + SND_SOC_DAPM_MUX("HPR Mux", SND_SOC_NOPM, 0, 0, + &hpr_sel_mux), + + /* Audio Interface */ + SND_SOC_DAPM_AIF_IN("I2S DAC", "HiFi Playback", 0, + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("I2S ADC", "HiFi Capture", 0, + SND_SOC_NOPM, 0, 0), + + /* Input */ + SND_SOC_DAPM_INPUT("LINEL"), + SND_SOC_DAPM_INPUT("LINER"), + SND_SOC_DAPM_INPUT("MICP"), + SND_SOC_DAPM_INPUT("MICN"), + + /* Output */ + SND_SOC_DAPM_OUTPUT("HPOUTL"), + SND_SOC_DAPM_OUTPUT("HPOUTR"), + +}; + +static const struct snd_soc_dapm_route rk3190_dapm_routes[] = { + /* Input */ + {"BSTR", NULL, "MICP"}, + {"BSTL", NULL, "MICP"}, + {"BSTL", NULL, "MICN"}, + + {"IN_R Mux", "LINER", "LINER"}, + {"IN_R Mux", "BSTR", "BSTR"}, + {"IN_L Mux", "LINEL", "LINEL"}, + {"IN_L Mux", "BSTL", "BSTL"}, + + {"ALCL", NULL, "IN_L Mux"}, + {"ALCR", NULL, "IN_R Mux"}, + + + {"ADCR", NULL, "ALCR"}, + {"ADCL", NULL, "ALCL"}, + + {"I2S ADC", NULL, "ADCR"}, + {"I2S ADC", NULL, "ADCL"}, + + /* Output */ + + {"DACR", NULL, "I2S DAC"}, + {"DACL", NULL, "I2S DAC"}, + + {"HPMIXR", "ALCR Switch", "ALCR"}, + {"HPMIXR", "ALCL Switch", "ALCL"}, + {"HPMIXR", "DACR Switch", "DACR"}, + + {"HPMIXL", "ALCR Switch", "ALCR"}, + {"HPMIXL", "ALCL Switch", "ALCL"}, + {"HPMIXL", "DACL Switch", "DACL"}, + + + {"HPR Mux", "DACR", "DACR"}, + {"HPR Mux", "HPMIXR", "HPMIXR"}, + {"HPL Mux", "DACL", "DACL"}, + {"HPL Mux", "HPMIXL", "HPMIXL"}, + + {"HPR", NULL, "HPR Mux"}, + {"HPL", NULL, "HPL Mux"}, + + {"HPOUTR", NULL, "HPR"}, + {"HPOUTL", NULL, "HPL"}, +}; +#endif + +static int rk3190_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + DBG("%s level=%d\n",__func__,level); + + switch (level) { + case SND_SOC_BIAS_ON: + break; + + case SND_SOC_BIAS_PREPARE: + break; + + case SND_SOC_BIAS_STANDBY: +#if 0 + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + writel(0x32, rk3190_priv->regbase+RK3190_DAC_INT_CTL3); + snd_soc_update_bits(codec, RK3190_ADC_MIC_CTL, + RK3190_ADC_CURRENT_ENABLE, RK3190_ADC_CURRENT_ENABLE); + snd_soc_update_bits(codec, RK3190_DAC_CTL, + RK3190_CURRENT_EN, RK3190_CURRENT_EN); + /* set power */ + snd_soc_update_bits(codec, RK3190_ADC_ENABLE, + RK3190_ADCL_REF_VOL_EN_SFT | RK3190_ADCR_REF_VOL_EN_SFT, + RK3190_ADCL_REF_VOL_EN | RK3190_ADCR_REF_VOL_EN); + + snd_soc_update_bits(codec, RK3190_ADC_MIC_CTL, + RK3190_ADCL_ZERO_DET_EN_SFT | RK3190_ADCR_ZERO_DET_EN_SFT, + RK3190_ADCL_ZERO_DET_EN | RK3190_ADCR_ZERO_DET_EN); + + snd_soc_update_bits(codec, RK3190_DAC_CTL, + RK3190_REF_VOL_DACL_EN_SFT | RK3190_REF_VOL_DACR_EN_SFT, + RK3190_REF_VOL_DACL_EN | RK3190_REF_VOL_DACR_EN ); + + snd_soc_update_bits(codec, RK3190_DAC_ENABLE, + RK3190_DACL_REF_VOL_EN_SFT | RK3190_DACR_REF_VOL_EN_SFT, + RK3190_DACL_REF_VOL_EN | RK3190_DACR_REF_VOL_EN ); + } + break; +#endif + case SND_SOC_BIAS_OFF: +#if 0 + snd_soc_update_bits(codec, RK3190_DAC_ENABLE, + RK3190_DACL_REF_VOL_EN_SFT | RK3190_DACR_REF_VOL_EN_SFT,0); + snd_soc_update_bits(codec, RK3190_DAC_CTL, + RK3190_REF_VOL_DACL_EN_SFT | RK3190_REF_VOL_DACR_EN_SFT,0); + snd_soc_update_bits(codec, RK3190_ADC_MIC_CTL, + RK3190_ADCL_ZERO_DET_EN_SFT | RK3190_ADCR_ZERO_DET_EN_SFT,0); + snd_soc_update_bits(codec, RK3190_ADC_ENABLE, + RK3190_ADCL_REF_VOL_EN_SFT | RK3190_ADCR_REF_VOL_EN_SFT,0); + snd_soc_update_bits(codec, RK3190_ADC_MIC_CTL, + RK3190_ADC_CURRENT_ENABLE, 0); + snd_soc_update_bits(codec, RK3190_DAC_CTL, + RK3190_CURRENT_EN, 0); + writel(0x22, rk3190_priv->regbase+RK3190_DAC_INT_CTL3); +#endif + break; + } + codec->dapm.bias_level = level; + + return 0; +} + +static int rk3190_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct rk3190_codec_priv *rk3190 = rk3190_priv; + + if (!rk3190) { + printk("%s : rk3190 is NULL\n", __func__); + return -EINVAL; + } + + rk3190->stereo_sysclk = freq; + + return 0; +} + +static int rk3190_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + adc_aif2 |= RK3190_I2S_MODE_SLV; + break; + case SND_SOC_DAIFMT_CBM_CFM: + adc_aif2 |= RK3190_I2S_MODE_MST; + break; + default: + printk("%s : set master mask failed!\n", __func__); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + adc_aif1 |= RK3190_ADC_DF_PCM; + dac_aif1 |= RK3190_DAC_DF_PCM; + break; + case SND_SOC_DAIFMT_DSP_B: + break; + case SND_SOC_DAIFMT_I2S: + adc_aif1 |= RK3190_ADC_DF_I2S; + dac_aif1 |= RK3190_DAC_DF_I2S; + break; + case SND_SOC_DAIFMT_RIGHT_J: + adc_aif1 |= RK3190_ADC_DF_RJ; + dac_aif1 |= RK3190_DAC_DF_RJ; + break; + case SND_SOC_DAIFMT_LEFT_J: + adc_aif1 |= RK3190_ADC_DF_LJ; + dac_aif1 |= RK3190_DAC_DF_LJ; + break; + default: + printk("%s : set format failed!\n", __func__); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + adc_aif1 |= RK3190_ALRCK_POL_DIS; + adc_aif2 |= RK3190_ABCLK_POL_DIS; + dac_aif1 |= RK3190_DLRCK_POL_DIS; + dac_aif2 |= RK3190_DBCLK_POL_DIS; + break; + case SND_SOC_DAIFMT_IB_IF: + adc_aif1 |= RK3190_ALRCK_POL_EN; + adc_aif2 |= RK3190_ABCLK_POL_EN; + dac_aif1 |= RK3190_DLRCK_POL_EN; + dac_aif2 |= RK3190_DBCLK_POL_EN; + break; + case SND_SOC_DAIFMT_IB_NF: + adc_aif1 |= RK3190_ALRCK_POL_DIS; + adc_aif2 |= RK3190_ABCLK_POL_EN; + dac_aif1 |= RK3190_DLRCK_POL_DIS; + dac_aif2 |= RK3190_DBCLK_POL_EN; + break; + case SND_SOC_DAIFMT_NB_IF: + adc_aif1 |= RK3190_ALRCK_POL_EN; + adc_aif2 |= RK3190_ABCLK_POL_DIS; + dac_aif1 |= RK3190_DLRCK_POL_EN; + dac_aif2 |= RK3190_DBCLK_POL_DIS; + break; + default: + printk("%s : set dai format failed!\n", __func__); + return -EINVAL; + } + + snd_soc_update_bits(codec, RK3190_ADC_INT_CTL1, + RK3190_ALRCK_POL_MASK | RK3190_ADC_DF_MASK, adc_aif1); + snd_soc_update_bits(codec, RK3190_ADC_INT_CTL2, + RK3190_ABCLK_POL_MASK | RK3190_I2S_MODE_MASK, adc_aif2); + snd_soc_update_bits(codec, RK3190_DAC_INT_CTL1, + RK3190_DLRCK_POL_MASK | RK3190_DAC_DF_MASK, dac_aif1); + snd_soc_update_bits(codec, RK3190_DAC_INT_CTL2, + RK3190_DBCLK_POL_MASK, dac_aif2); + + return 0; +} + +static int rk3190_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec =rtd->codec; + struct rk3190_codec_priv *rk3190 = rk3190_priv; + unsigned int rate = params_rate(params); + unsigned int div; + unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0; + + if (!rk3190) { + printk("%s : rk3190 is NULL\n", __func__); + return -EINVAL; + } + + // bclk = codec_clk / 4 + // lrck = bclk / (wl * 2) + div = (((rk3190->stereo_sysclk / 4) / rate) / 2); + + if ((rk3190->stereo_sysclk % (4 * rate * 2) > 0) || + (div != 16 && div != 20 && div != 24 && div != 32)) { + printk("%s : need PLL\n", __func__); + return -EINVAL; + } + + switch (div) { + case 16: + adc_aif2 |= RK3190_ADC_WL_16; + dac_aif2 |= RK3190_DAC_WL_16; + break; + case 20: + adc_aif2 |= RK3190_ADC_WL_20; + dac_aif2 |= RK3190_DAC_WL_20; + break; + case 24: + adc_aif2 |= RK3190_ADC_WL_24; + dac_aif2 |= RK3190_DAC_WL_24; + break; + case 32: + adc_aif2 |= RK3190_ADC_WL_32; + dac_aif2 |= RK3190_DAC_WL_32; + break; + default: + return -EINVAL; + } + + + DBG("%s : MCLK = %dHz, sample rate = %dHz, div = %d\n", __func__, + rk3190->stereo_sysclk, rate, div); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + adc_aif1 |= RK3190_ADC_VWL_16; + dac_aif1 |= RK3190_DAC_VWL_16; + break; + case SNDRV_PCM_FORMAT_S20_3LE: + adc_aif1 |= RK3190_ADC_VWL_20; + dac_aif1 |= RK3190_DAC_VWL_20; + break; + case SNDRV_PCM_FORMAT_S24_LE: + adc_aif1 |= RK3190_ADC_VWL_24; + dac_aif1 |= RK3190_DAC_VWL_24; + break; + case SNDRV_PCM_FORMAT_S32_LE: + adc_aif1 |= RK3190_ADC_VWL_32; + dac_aif1 |= RK3190_DAC_VWL_32; + break; + default: + return -EINVAL; + } + + switch (params_channels(params)) { + case RK3190_MONO: + adc_aif1 |= RK3190_ADC_TYPE_MONO; + break; + case RK3190_STEREO: + adc_aif1 |= RK3190_ADC_TYPE_STEREO; + break; + default: + return -EINVAL; + } + + adc_aif1 |= RK3190_ADC_SWAP_DIS; + adc_aif2 |= RK3190_ADC_RST_DIS; + dac_aif1 |= RK3190_DAC_SWAP_DIS; + dac_aif2 |= RK3190_DAC_RST_DIS; + + rk3190->rate = rate; + + snd_soc_update_bits(codec, RK3190_ADC_INT_CTL1, + RK3190_ADC_VWL_MASK | RK3190_ADC_SWAP_MASK | + RK3190_ADC_TYPE_MASK, adc_aif1); + snd_soc_update_bits(codec, RK3190_ADC_INT_CTL2, + RK3190_ADC_WL_MASK | RK3190_ADC_RST_MASK, adc_aif2); + snd_soc_update_bits(codec, RK3190_DAC_INT_CTL1, + RK3190_DAC_VWL_MASK | RK3190_DAC_SWAP_MASK, dac_aif1); + snd_soc_update_bits(codec, RK3190_DAC_INT_CTL2, + RK3190_DAC_WL_MASK | RK3190_DAC_RST_MASK, dac_aif2); + + return 0; +} + +static int rk3190_digital_mute(struct snd_soc_dai *dai, int mute) +{ + return 0; +} + +static struct rk3190_reg_val_typ playback_power_up_list[] = { + //{RK3190_DAC_INT_CTL3,0x32}, + {RK3190_DAC_CTL,0x40}, + {RK3190_DAC_CTL,0x62}, + {RK3190_DAC_ENABLE,0x88}, + {RK3190_DAC_ENABLE,0xcc}, + {RK3190_DAC_ENABLE,0xee}, + {RK3190_HPMIX_CTL,0x44}, + {RK3190_HPOUT_CTL,0x90}, + {RK3190_HPOUT_CTL,0xd8}, + {RK3190_HPMIX_S_SELECT,0x11},//DAC + {RK3190_HPMIX_CTL,0x55}, + {RK3190_HPMIX_CTL,0x77}, + {RK3190_DAC_ENABLE,0xff}, + {RK3190_HPOUT_CTL,0xfc}, + {RK3190_DAC_CTL,0x73}, + {RK3190_HPOUTL_GAIN,OUT_VOLUME}, + {RK3190_HPOUTR_GAIN,OUT_VOLUME}, +}; +#define RK3190_CODEC_PLAYBACK_POWER_UP_LIST_LEN ARRAY_SIZE(playback_power_up_list) + +static struct rk3190_reg_val_typ playback_power_down_list[] = { + {RK3190_HPOUT_CTL,0xdb}, + {RK3190_HPMIX_CTL,0x44}, + {RK3190_HPMIX_S_SELECT,0x00}, + {RK3190_HPOUT_CTL,0x92}, + {RK3190_DAC_CTL,0x22}, + {RK3190_HPOUT_CTL,0x00}, + {RK3190_HPMIX_CTL,0x00}, + {RK3190_DAC_ENABLE,0x00}, + {RK3190_DAC_CTL,0x00}, + //{RK3190_DAC_INT_CTL3,0x22}, +#ifdef WITH_CAP + //{RK3190_SELECT_CURRENT,0x08}, +#endif + {RK3190_HPOUTL_GAIN,0x0}, + {RK3190_HPOUTR_GAIN,0x0}, +}; +#define RK3190_CODEC_PLAYBACK_POWER_DOWN_LIST_LEN ARRAY_SIZE(playback_power_down_list) + +static struct rk3190_reg_val_typ capture_power_up_list[] = { + {RK3190_ADC_CTL, 0x40}, + //{RK3190_BIAS_CTL, 0x08}, + //{RK3190_BIAS_CTL, 0x0f}, + {RK3190_ADC_CTL, 0x62}, + {RK3190_BST_CTL, 0x88}, + {RK3190_ALC_MUNIN_CTL, 0x66}, + {RK3190_ADC_ENABLE, 0x44}, + {RK3190_ADC_ENABLE, 0x66}, + {RK3190_BST_CTL, 0xee}, + {RK3190_BST_CTL, 0xfe}, //single-ended + {RK3190_ALC_MUNIN_CTL, 0x77}, + {RK3190_ALCL_GAIN_CTL, CAP_VOL}, + {RK3190_ALCR_GAIN_CTL, CAP_VOL}, + {RK3190_ADC_CTL, 0x73}, + +}; +#define RK3190_CODEC_CAPTURE_POWER_UP_LIST_LEN ARRAY_SIZE(capture_power_up_list) + +static struct rk3190_reg_val_typ capture_power_down_list[] = { + {RK3190_ADC_ENABLE, 0x44}, + {RK3190_ALC_MUNIN_CTL, 0x66}, + {RK3190_BST_CTL, 0x88}, + {RK3190_ADC_ENABLE, 0x00}, + {RK3190_ADC_CTL, 0x62}, + //{RK3190_BIAS_CTL, 0x08}, + {RK3190_ADC_CTL, 0x40}, + {RK3190_BST_CTL, 0x00}, + {RK3190_ALCL_GAIN_CTL, 0x00}, + {RK3190_ALCR_GAIN_CTL, 0x00}, + {RK3190_ADC_CTL, 0x00}, + //{RK3190_BIAS_CTL, 0x00}, + {RK3190_ALC_MUNIN_CTL, 0x00}, +}; +#define RK3190_CODEC_CAPTURE_POWER_DOWN_LIST_LEN ARRAY_SIZE(capture_power_down_list) + +static struct rk3190_reg_val_typ lineIn_bypass_power_up_list[] = { +#if 1 + //{RK3190_DAC_INT_CTL3, 0x32}, + {RK3190_ADC_CTL, 0x40}, + {RK3190_BIAS_CTL, 0x08}, + {RK3190_BIAS_CTL, 0x0f}, + {RK3190_ALC_MUNIN_CTL, 0x22}, + {RK3190_ALC_MUNIN_CTL, 0x66}, + {RK3190_ADC_CTL, 0x62}, + {RK3190_DAC_CTL, 0x40}, + {RK3190_DAC_CTL, 0x62}, + {RK3190_DAC_ENABLE, 0x88}, + {RK3190_DAC_ENABLE, 0xcc}, + {RK3190_DAC_ENABLE, 0xee}, + {RK3190_HPMIX_CTL, 0x44}, + {RK3190_HPOUT_CTL, 0x92}, + {RK3190_HPOUT_CTL, 0xdb}, + {RK3190_HPMIX_S_SELECT, 0x22},//ALCL/R+DACL/R + {RK3190_HPMIX_CTL, 0x55}, + {RK3190_HPMIX_CTL, 0x77}, + {RK3190_DAC_ENABLE, 0xff}, + {RK3190_HPOUT_CTL, 0xff}, + {RK3190_ALC_MUNIN_CTL, 0x77}, + {RK3190_ALCL_GAIN_CTL, CAP_VOL}, + {RK3190_ALCR_GAIN_CTL, CAP_VOL}, + {RK3190_HPOUTL_GAIN, OUT_VOLUME}, + {RK3190_HPOUTR_GAIN, OUT_VOLUME}, + {RK3190_ADC_CTL, 0x73}, + {RK3190_DAC_CTL, 0x73}, +#endif +}; +#define RK3190_CODEC_LINEIN_BYPASS_POWER_UP_LIST_LEN ARRAY_SIZE(lineIn_bypass_power_up_list) + +static struct rk3190_reg_val_typ lineIn_bypass_power_down_list[] = { + {RK3190_ALC_MUNIN_CTL, 0xaa}, + {RK3190_BIAS_CTL, 0xc7}, + //{RK3190_BIAS_CTL, 0x80}, + {RK3190_ADC_CTL, 0x62}, + //{RK3190_BIAS_CTL, 0x00}, + {RK3190_ALC_MUNIN_CTL, 0x00}, + {RK3190_HPOUT_CTL, 0xdb}, + {RK3190_HPMIX_CTL, 0x44}, + {RK3190_HPMIX_S_SELECT, 0x00}, + {RK3190_HPOUT_CTL, 0x92}, + {RK3190_DAC_CTL, 0x22}, + {RK3190_ADC_CTL, 0x00}, + {RK3190_HPOUT_CTL, 0x00}, + {RK3190_HPMIX_CTL, 0x00}, + {RK3190_DAC_CTL, 0x00}, + {RK3190_DAC_ENABLE, 0x00}, + {RK3190_HPOUTL_GAIN, 0x00}, + {RK3190_HPOUTR_GAIN, 0x00}, + {RK3190_ALCL_GAIN_CTL, 0x00}, + {RK3190_ALCR_GAIN_CTL, 0x00}, + //{RK3190_DAC_INT_CTL3, 0x00}, +}; +#define RK3190_CODEC_LINEIN_BYPASS_POWER_DOWN_LIST_LEN ARRAY_SIZE(lineIn_bypass_power_down_list) + + +static int rk3190_codec_power_up(int type) +{ + struct snd_soc_codec *codec = rk3190_priv->codec; + int i; + + if (!rk3190_priv || !rk3190_priv->codec) { + printk("%s : rk3190_priv or rk3190_priv->codec is NULL\n", __func__); + return -EINVAL; + } + + printk("%s : power up %s%s%s\n", __func__, + type == RK3190_CODEC_PLAYBACK ? "playback" : "", + type == RK3190_CODEC_CAPTURE ? "capture" : "", + type == RK3190_CODEC_INCALL ? "incall" : ""); + + if (type == RK3190_CODEC_PLAYBACK) { + for (i = 0; i < RK3190_CODEC_PLAYBACK_POWER_UP_LIST_LEN; i++) { + snd_soc_write(codec, playback_power_up_list[i].reg, + playback_power_up_list[i].value); + msleep(10); + } + //codec_set_spk(!get_hdmi_state()); + } else if (type == RK3190_CODEC_CAPTURE) { + for (i = 0; i < RK3190_CODEC_CAPTURE_POWER_UP_LIST_LEN; i++) { + snd_soc_write(codec, capture_power_up_list[i].reg, + capture_power_up_list[i].value); + msleep(10); + } + } else if (type == RK3190_CODEC_INCALL) { + /*To be perfect*/ + for (i = 0; i < RK3190_CODEC_LINEIN_BYPASS_POWER_UP_LIST_LEN; i++) { + snd_soc_write(codec, lineIn_bypass_power_up_list[i].reg, + lineIn_bypass_power_up_list[i].value); + msleep(10); + } + } + + return 0; +} + +static int rk3190_codec_power_down(int type) +{ + struct snd_soc_codec *codec = rk3190_priv->codec; + int i; + + if (!rk3190_priv || !rk3190_priv->codec) { + printk("%s : rk3190_priv or rk3190_priv->codec is NULL\n", __func__); + return -EINVAL; + } + + printk("%s : power down %s%s%s%s\n", __func__, + type == RK3190_CODEC_PLAYBACK ? "playback" : "", + type == RK3190_CODEC_CAPTURE ? "capture" : "", + type == RK3190_CODEC_INCALL ? "incall" : "", + type == RK3190_CODEC_ALL ? "all" : ""); + + if ((type == RK3190_CODEC_CAPTURE) || (type == RK3190_CODEC_INCALL)) { + for (i = 0; i < RK3190_CODEC_CAPTURE_POWER_DOWN_LIST_LEN; i++) { + snd_soc_write(codec, capture_power_down_list[i].reg, + capture_power_down_list[i].value); + } + } else if (type == RK3190_CODEC_PLAYBACK) { +#if 0 + snd_soc_write(codec, RK3190_DAC_CTL,0x62); + for ( i = OUT_VOLUME; i >= 0; i--) + { + snd_soc_write(codec, 0xb4,i); + snd_soc_write(codec, 0xb8,i); + } + msleep(20); +#endif + for (i = 0; i < RK3190_CODEC_PLAYBACK_POWER_DOWN_LIST_LEN; i++) { + snd_soc_write(codec, playback_power_down_list[i].reg, + playback_power_down_list[i].value); + + } + } else if (type == RK3190_CODEC_INCALL) { + /*To be perfect*/ + for (i = 0; i < RK3190_CODEC_LINEIN_BYPASS_POWER_DOWN_LIST_LEN; i++) { + snd_soc_write(codec, lineIn_bypass_power_down_list[i].reg, + lineIn_bypass_power_down_list[i].value); + } + } else if (type == RK3190_CODEC_ALL) { + rk3190_reset(codec); + } + + return 0; +} + +#define RK3190_PLAYBACK_RATES (SNDRV_PCM_RATE_8000 |\ + SNDRV_PCM_RATE_16000 | \ + SNDRV_PCM_RATE_32000 | \ + SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | \ + SNDRV_PCM_RATE_96000) + +#define RK3190_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\ + SNDRV_PCM_RATE_16000 | \ + SNDRV_PCM_RATE_32000 | \ + SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | \ + SNDRV_PCM_RATE_96000) + +#define RK3190_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S20_3LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_ops rk3190_dai_ops = { + .hw_params = rk3190_hw_params, + .set_fmt = rk3190_set_dai_fmt, + .set_sysclk = rk3190_set_dai_sysclk, + .digital_mute = rk3190_digital_mute, +}; + +static struct snd_soc_dai_driver rk3190_dai[] = { + { + .name = "rk3190-hifi", + .id = RK3190_HIFI, + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 2, + .channels_max = 2, + .rates = RK3190_PLAYBACK_RATES, + .formats = RK3190_FORMATS, + }, + .capture = { + .stream_name = "HiFi Capture", + .channels_min = 2, + .channels_max = 2, + .rates = RK3190_CAPTURE_RATES, + .formats = RK3190_FORMATS, + }, + .ops = &rk3190_dai_ops, + }, + { + .name = "rk3190-voice", + .id = RK3190_VOICE, + .playback = { + .stream_name = "Voice Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RK3190_PLAYBACK_RATES, + .formats = RK3190_FORMATS, + }, + .capture = { + .stream_name = "Voice Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RK3190_CAPTURE_RATES, + .formats = RK3190_FORMATS, + }, + .ops = &rk3190_dai_ops, + }, + +}; + +static int rk3190_suspend(struct snd_soc_codec *codec, pm_message_t state) +{ + if (rk3190_for_mid) + { + rk3190_codec_power_down(RK3190_CODEC_PLAYBACK); + rk3190_codec_power_down(RK3190_CODEC_ALL); +#ifdef WITH_CAP + snd_soc_write(codec, RK3190_SELECT_CURRENT,0x3e); + snd_soc_write(codec, RK3190_SELECT_CURRENT,0x1e); +#endif + } + else + rk3190_set_bias_level(codec, SND_SOC_BIAS_OFF); + + return 0; +} + +static int rk3190_resume(struct snd_soc_codec *codec) +{ + if (!rk3190_for_mid) + rk3190_set_bias_level(codec, SND_SOC_BIAS_STANDBY); +#ifdef WITH_CAP + snd_soc_write(codec, RK3190_SELECT_CURRENT,0x1e); + snd_soc_write(codec, RK3190_SELECT_CURRENT,0x3e); +#endif + return 0; +} + +static int rk3190_probe(struct snd_soc_codec *codec) +{ + struct rk3190_codec_priv *rk3190; + struct rk3190_codec_pdata *rk3190_plt = codec->dev->platform_data; + struct platform_device *pdev = to_platform_device(codec->dev); + struct resource *res, *mem; + int ret; + unsigned int val; + + DBG("%s\n", __func__); + + rk3190 = kzalloc(sizeof(struct rk3190_codec_priv), GFP_KERNEL); + if (!rk3190) { + printk("%s : rk3190 priv kzalloc failed!\n", __func__); + return -ENOMEM; + } + + rk3190->codec = codec; + + res = pdev->resource; + rk3190->regbase_phy = res->start; + rk3190->regsize_phy = (res->end - res->start) + 1; + + mem = request_mem_region(res->start, (res->end - res->start) + 1, pdev->name); + if (!mem) + { + dev_err(&pdev->dev, "failed to request mem region for rk2928 codec\n"); + ret = -ENOENT; + goto err__; + } + + rk3190->regbase = (int)ioremap(res->start, (res->end - res->start) + 1); + if (!rk3190->regbase) { + dev_err(&pdev->dev, "cannot ioremap acodec registers\n"); + ret = -ENXIO; + goto err__; + } + + rk3190->pclk = clk_get(NULL,"pclk_acodec"); + if(IS_ERR(rk3190->pclk)) + { + dev_err(&pdev->dev, "Unable to get acodec hclk\n"); + ret = -ENXIO; + goto err__; + } + clk_enable(rk3190->pclk); + + rk3190_priv = rk3190; + + if (rk3190_priv && rk3190_plt->spk_ctl_gpio) { + gpio_request(rk3190_plt->spk_ctl_gpio, NULL); + gpio_direction_output(rk3190_plt->spk_ctl_gpio, GPIO_LOW); + rk3190->spk_ctl_gpio = rk3190_plt->spk_ctl_gpio; + } else { + printk("%s : rk3190 spk_ctl_gpio is NULL!\n", __func__); + rk3190->spk_ctl_gpio = INVALID_GPIO; + } + + if (rk3190_priv && rk3190_plt->hp_ctl_gpio) { + gpio_request(rk3190_plt->hp_ctl_gpio, NULL); + gpio_direction_output(rk3190_plt->hp_ctl_gpio, GPIO_LOW); + rk3190->hp_ctl_gpio = rk3190_plt->hp_ctl_gpio; + } else { + printk("%s : rk3190 hp_ctl_gpio is NULL!\n", __func__); + rk3190->hp_ctl_gpio = INVALID_GPIO; + } + + if (rk3190_plt->delay_time) { + rk3190->delay_time = rk3190_plt->delay_time; + } else { + printk("%s : rk3190 delay_time is NULL!\n", __func__); + rk3190->delay_time = 10; + } + + if (rk3190_plt->ear_ctl_gpio) { + gpio_request(rk3190_plt->ear_ctl_gpio, NULL); + gpio_direction_output(rk3190_plt->ear_ctl_gpio, GPIO_LOW); + rk3190->ear_ctl_gpio = rk3190_plt->ear_ctl_gpio; + } else { + printk("%s : rk3190 ear_ctl_gpio is NULL!\n", __func__); + rk3190->ear_ctl_gpio = INVALID_GPIO; + } + + ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); + if (ret != 0) { + printk("%s : Failed to set cache I/O: %d\n", __func__, ret); + goto err__; + } + + codec->hw_read = rk3190_codec_read; + codec->hw_write = (hw_write_t)rk3190_hw_write; + codec->read = rk3190_codec_read; + codec->write = rk3190_codec_write; + + rk3190_reset(codec); + + val = snd_soc_read(codec, RK3190_RESET); + if (val != rk3190_reg_defaults[RK3190_RESET]) { + printk("%s : codec register 0: %x is not a 0x00000003\n", __func__, val); + ret = -ENODEV; + goto err__; + } + + if (!rk3190_for_mid) + { + codec->dapm.bias_level = SND_SOC_BIAS_OFF; + rk3190_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + } + +#ifdef WITH_CAP + //set for capacity output,clear up noise + snd_soc_write(codec, RK3190_SELECT_CURRENT,0x1e); + snd_soc_write(codec, RK3190_SELECT_CURRENT,0x3e); +#endif + +#if 1 + // select used with internal audio codec soc_con[4] bit 7 + val = readl(RK319X_GRF_BASE+GRF_SOC_CON4); + writel(val | 0x00800080,RK319X_GRF_BASE+GRF_SOC_CON4); + val = readl(RK319X_GRF_BASE+GRF_SOC_CON4); + printk("%s : i2s used with internal audio codec val=0x%x,soc_con[4] bit 7 =1 is correct\n",__func__,val); +#endif + + /*ENABLE MICBIAS and always ON*/ +#if 1 + snd_soc_write(codec, RK3190_BIAS_CTL, 0x08); + snd_soc_write(codec, RK3190_BIAS_CTL, 0x0f); +#endif + if(rk3190_for_mid) { + snd_soc_add_codec_controls(codec, rk3190_snd_path_controls, + ARRAY_SIZE(rk3190_snd_path_controls)); + } + + return 0; + +err__: + release_mem_region(res->start,(res->end - res->start) + 1); + kfree(rk3190); + rk3190 = NULL; + rk3190_priv = NULL; + + return ret; +} + +/* power down chip */ +static int rk3190_remove(struct snd_soc_codec *codec) +{ + + DBG("%s\n", __func__); + + if (!rk3190_priv) { + printk("%s : rk3190_priv is NULL\n", __func__); + return 0; + } + + if (rk3190_priv->spk_ctl_gpio != INVALID_GPIO) + gpio_set_value(rk3190_priv->spk_ctl_gpio, GPIO_LOW); + + if (rk3190_priv->hp_ctl_gpio != INVALID_GPIO) + gpio_set_value(rk3190_priv->hp_ctl_gpio, GPIO_LOW); + + mdelay(10); + + snd_soc_write(codec, RK3190_RESET, 0xfc); + mdelay(10); + snd_soc_write(codec, RK3190_RESET, 0x3); + mdelay(10); + + if (rk3190_priv) + kfree(rk3190_priv); + + return 0; +} + +static struct snd_soc_codec_driver soc_codec_dev_rk3190 = { + .probe =rk3190_probe, + .remove =rk3190_remove, + .suspend =rk3190_suspend, + .resume = rk3190_resume, + .set_bias_level = rk3190_set_bias_level, + .reg_cache_size = ARRAY_SIZE(rk3190_reg_defaults), + .reg_word_size = sizeof(unsigned int), + .reg_cache_default = rk3190_reg_defaults, + .volatile_register = rk3190_volatile_register, + .readable_register = rk3190_codec_register, + .reg_cache_step = sizeof(unsigned int), +}; + +static int rk3190_platform_probe(struct platform_device *pdev) +{ + DBG("%s\n", __func__); + + return snd_soc_register_codec(&pdev->dev, + &soc_codec_dev_rk3190, rk3190_dai, ARRAY_SIZE(rk3190_dai)); +} + +static __devexit int rk3190_platform_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +void rk3190_platform_shutdown(struct platform_device *pdev) +{ + + DBG("%s\n", __func__); + + if (!rk3190_priv || !rk3190_priv->codec) { + printk("%s : rk3190_priv or rk3190_priv->codec is NULL\n", __func__); + return; + } + + if (rk3190_priv->spk_ctl_gpio != INVALID_GPIO) + gpio_set_value(rk3190_priv->spk_ctl_gpio, GPIO_LOW); + + if (rk3190_priv->hp_ctl_gpio != INVALID_GPIO) + gpio_set_value(rk3190_priv->hp_ctl_gpio, GPIO_LOW); + + mdelay(10); + + writel(0xfc, rk3190_priv->regbase+RK3190_RESET); + mdelay(10); + writel(0x03, rk3190_priv->regbase+RK3190_RESET); + + if (rk3190_priv) + kfree(rk3190_priv); +} + +static struct platform_driver rk3190_codec_driver = { + .driver = { + .name = "rk3190-codec", + .owner = THIS_MODULE, + }, + .probe = rk3190_platform_probe, + .remove = rk3190_platform_remove, + .shutdown = rk3190_platform_shutdown, +}; + + +static __init int rk3190_modinit(void) +{ + return platform_driver_register(&rk3190_codec_driver); +} +module_init(rk3190_modinit); + +static __exit void rk3190_exit(void) +{ + platform_driver_unregister(&rk3190_codec_driver); +} +module_exit(rk3190_exit); + +MODULE_DESCRIPTION("ASoC RK3190 driver"); +MODULE_AUTHOR("zhangjun "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/rk3190_codec.h b/sound/soc/codecs/rk3190_codec.h new file mode 100755 index 000000000000..31ac86674299 --- /dev/null +++ b/sound/soc/codecs/rk3190_codec.h @@ -0,0 +1,592 @@ +/* + * rk3190_codec.h -- RK3190 CODEC ALSA SoC audio driver + * + * Copyright 2013 Rockship + * Author: zhangjun + * + */ + +#ifndef __RK3190_CODEC_H__ +#define __RK3190_CODEC_H__ + + + +/* codec register */ +#define RK3190_CODEC_BASE (0x0) + +#define RK3190_RESET (RK3190_CODEC_BASE + 0x00) +#define RK3190_ADC_INT_CTL1 (RK3190_CODEC_BASE + 0x08) +#define RK3190_ADC_INT_CTL2 (RK3190_CODEC_BASE + 0x0c) +#define RK3190_DAC_INT_CTL1 (RK3190_CODEC_BASE + 0x10) +#define RK3190_DAC_INT_CTL2 (RK3190_CODEC_BASE + 0x14) +//#define RK3190_DAC_INT_CTL3 (RK3190_CODEC_BASE + 0x18) +#define RK3190_BIST_CTL (RK3190_CODEC_BASE + 0x1c) +#define RK3190_SELECT_CURRENT (RK3190_CODEC_BASE + 0x88) +#define RK3190_BIAS_CTL (RK3190_CODEC_BASE + 0x8c) +#define RK3190_ADC_CTL (RK3190_CODEC_BASE + 0x90) +#define RK3190_BST_CTL (RK3190_CODEC_BASE + 0x94) +#define RK3190_ALC_MUNIN_CTL (RK3190_CODEC_BASE + 0x98) +#define RK3190_ALCL_GAIN_CTL (RK3190_CODEC_BASE + 0x9c) +#define RK3190_ALCR_GAIN_CTL (RK3190_CODEC_BASE + 0xa0) +#define RK3190_ADC_ENABLE (RK3190_CODEC_BASE + 0xa4) +#define RK3190_DAC_CTL (RK3190_CODEC_BASE + 0xa8) +#define RK3190_DAC_ENABLE (RK3190_CODEC_BASE + 0xac) +#define RK3190_HPMIX_CTL (RK3190_CODEC_BASE + 0xb0) +#define RK3190_HPMIX_S_SELECT (RK3190_CODEC_BASE + 0xb4) +#define RK3190_HPOUT_CTL (RK3190_CODEC_BASE + 0xb8) +#define RK3190_HPOUTL_GAIN (RK3190_CODEC_BASE + 0xbc) +#define RK3190_HPOUTR_GAIN (RK3190_CODEC_BASE + 0xc0) +#define RK3190_PGA_AGC_CTL1 (RK3190_CODEC_BASE + 0x100) +#define RK3190_PGA_AGC_CTL2 (RK3190_CODEC_BASE + 0x104) +#define RK3190_PGA_AGC_CTL3 (RK3190_CODEC_BASE + 0x108) +#define RK3190_PGA_AGC_CTL4 (RK3190_CODEC_BASE + 0x10c) +#define RK3190_PGA_ASR_CTL (RK3190_CODEC_BASE + 0x110) +#define RK3190_PGA_AGC_MAX_H (RK3190_CODEC_BASE + 0x114) +#define RK3190_PGA_AGC_MAX_L (RK3190_CODEC_BASE + 0x118) +#define RK3190_PGA_AGC_MIN_H (RK3190_CODEC_BASE + 0x11c) +#define RK3190_PGA_AGC_MIN_L (RK3190_CODEC_BASE + 0x120) +#define RK3190_PGA_AGC_CTL5 (RK3190_CODEC_BASE + 0x124) +#if 0 +#define RK3190_PGAR_AGC_CTL1 (RK3190_CODEC_BASE + 0x140) +#define RK3190_PGAR_AGC_CTL2 (RK3190_CODEC_BASE + 0x144) +#define RK3190_PGAR_AGC_CTL3 (RK3190_CODEC_BASE + 0x148) +#define RK3190_PGAR_AGC_CTL4 (RK3190_CODEC_BASE + 0x14c) +#define RK3190_PGAR_ASR_CTL (RK3190_CODEC_BASE + 0x150) +#define RK3190_PGAR_AGC_MAX_H (RK3190_CODEC_BASE + 0x154) +#define RK3190_PGAR_AGC_MAX_L (RK3190_CODEC_BASE + 0x158) +#define RK3190_PGAR_AGC_MIN_H (RK3190_CODEC_BASE + 0x15c) +#define RK3190_PGAR_AGC_MIN_L (RK3190_CODEC_BASE + 0x160) +#define RK3190_PGAR_AGC_CTL5 (RK3190_CODEC_BASE + 0x164) +#endif + +/* ADC Interface Control 1 (0x08) */ +#define RK3190_ALRCK_POL_MASK (0x1 << 7) +#define RK3190_ALRCK_POL_SFT 7 +#define RK3190_ALRCK_POL_EN (0x1 << 7) +#define RK3190_ALRCK_POL_DIS (0x0 << 7) + +#define RK3190_ADC_VWL_MASK (0x3 << 5) +#define RK3190_ADC_VWL_SFT 5 +#define RK3190_ADC_VWL_32 (0x3 << 5) +#define RK3190_ADC_VWL_24 (0x2 << 5) +#define RK3190_ADC_VWL_20 (0x1 << 5) +#define RK3190_ADC_VWL_16 (0x0 << 5) + +#define RK3190_ADC_DF_MASK (0x3 << 3) +#define RK3190_ADC_DF_SFT 3 +#define RK3190_ADC_DF_PCM (0x3 << 3) +#define RK3190_ADC_DF_I2S (0x2 << 3) +#define RK3190_ADC_DF_LJ (0x1 << 3) +#define RK3190_ADC_DF_RJ (0x0 << 3) + +#define RK3190_ADC_SWAP_MASK (0x1 << 1) +#define RK3190_ADC_SWAP_SFT 1 +#define RK3190_ADC_SWAP_EN (0x1 << 1) +#define RK3190_ADC_SWAP_DIS (0x0 << 1) + +#define RK3190_ADC_TYPE_MASK 0x1 +#define RK3190_ADC_TYPE_SFT 0 +#define RK3190_ADC_TYPE_MONO 0x1 +#define RK3190_ADC_TYPE_STEREO 0x0 + +/* ADC Interface Control 2 (0x0c) */ +#define RK3190_I2S_MODE_MASK (0x1 << 4) +#define RK3190_I2S_MODE_SFT (4) +#define RK3190_I2S_MODE_MST (0x1 << 4) +#define RK3190_I2S_MODE_SLV (0x0 << 4) + +#define RK3190_ADC_WL_MASK (0x3 << 2) +#define RK3190_ADC_WL_SFT (2) +#define RK3190_ADC_WL_32 (0x3 << 2) +#define RK3190_ADC_WL_24 (0x2 << 2) +#define RK3190_ADC_WL_20 (0x1 << 2) +#define RK3190_ADC_WL_16 (0x0 << 2) + +#define RK3190_ADC_RST_MASK (0x1 << 1) +#define RK3190_ADC_RST_SFT 91) +#define RK3190_ADC_RST_DIS (0x1 << 1) +#define RK3190_ADC_RST_EN (0x0 << 1) + +#define RK3190_ABCLK_POL_MASK 0x1 +#define RK3190_ABCLK_POL_SFT 0 +#define RK3190_ABCLK_POL_EN 0x1 +#define RK3190_ABCLK_POL_DIS 0x0 + +/* DAC Interface Control 1 (0x10) */ +#define RK3190_DLRCK_POL_MASK (0x1 << 7) +#define RK3190_DLRCK_POL_SFT 7 +#define RK3190_DLRCK_POL_EN (0x1 << 7) +#define RK3190_DLRCK_POL_DIS (0x0 << 7) + +#define RK3190_DAC_VWL_MASK (0x3 << 5) +#define RK3190_DAC_VWL_SFT 5 +#define RK3190_DAC_VWL_32 (0x3 << 5) +#define RK3190_DAC_VWL_24 (0x2 << 5) +#define RK3190_DAC_VWL_20 (0x1 << 5) +#define RK3190_DAC_VWL_16 (0x0 << 5) + +#define RK3190_DAC_DF_MASK (0x3 << 3) +#define RK3190_DAC_DF_SFT 3 +#define RK3190_DAC_DF_PCM (0x3 << 3) +#define RK3190_DAC_DF_I2S (0x2 << 3) +#define RK3190_DAC_DF_LJ (0x1 << 3) +#define RK3190_DAC_DF_RJ (0x0 << 3) + +#define RK3190_DAC_SWAP_MASK (0x1 << 2) +#define RK3190_DAC_SWAP_SFT 2 +#define RK3190_DAC_SWAP_EN (0x1 << 2) +#define RK3190_DAC_SWAP_DIS (0x0 << 2) + +/* DAC Interface Control 2 (0x14) */ +#define RK3190_DAC_WL_MASK (0x3 << 2) +#define RK3190_DAC_WL_SFT 2 +#define RK3190_DAC_WL_32 (0x3 << 2) +#define RK3190_DAC_WL_24 (0x2 << 2) +#define RK3190_DAC_WL_20 (0x1 << 2) +#define RK3190_DAC_WL_16 (0x0 << 2) + +#define RK3190_DAC_RST_MASK (0x1 << 1) +#define RK3190_DAC_RST_SFT 1 +#define RK3190_DAC_RST_DIS (0x1 << 1) +#define RK3190_DAC_RST_EN (0x0 << 1) + +#define RK3190_DBCLK_POL_MASK 0x1 +#define RK3190_DBCLK_POL_SFT 0 +#define RK3190_DBCLK_POL_EN 0x1 +#define RK3190_DBCLK_POL_DIS 0x0 + +/* BIST MODE SELECT (0x1c) */ + +/* SELECT CURR prechagrge/discharge (0x88) */ +#define RK3190_PRE_HPOUT (0x1 << 5) +#define RK3190_DIS_HPOUT (0x0 << 5) +#define RK3190_CUR_10UA_EN (0x0 << 4) +#define RK3190_CUR_10UA_DIS (0x1 << 4) +#define RK3190_CUR_I_EN (0x0 << 3) +#define RK3190_CUR_I_DIS (0x1 << 3) +#define RK3190_CUR_2I_EN (0x0 << 2) +#define RK3190_CUR_2I_DIS (0x1 << 2) +#define RK3190_CUR_4I_EN (0x0 << 0) +#define RK3190_CUR_4I_DIS (0x3 << 0) + +/* MICBIAS (0x8c) */ +#define RK3190_MICBIAS_VOL_ENABLE (3) +#define RK3190_MICBIAS_VOL_SHT 0 +#define RK3190_MICBIAS_VOL_MSK 7 +#define RK3190_MICBIAS_VOL_MIN (0x0 << 0) +#define RK3190_MICBIAS_VOL_MAX (0x7 << 0) + +/* ADC control (0x90) */ +#define RK3190_ADC_CURRENT_ENABLE (0x1 << 6) +#define RK3190_ADC_CURRENT_DISABLE (0x0 << 6) + +#define RK3190_ADCL_REF_VOL_EN_SFT (5) +#define RK3190_ADCL_REF_VOL_EN (0x1 << 5) +#define RK3190_ADCL_REF_VOL_DIS (0x0 << 5) + +#define RK3190_ADCL_ZERO_DET_EN_SFT (4) +#define RK3190_ADCL_ZERO_DET_EN (0x1 << 4) +#define RK3190_ADCL_ZERO_DET_DIS (0x0 << 4) + +#define RK3190_ADCR_REF_VOL_EN_SFT (1) +#define RK3190_ADCR_REF_VOL_EN (0x1 << 1) +#define RK3190_ADCR_REF_VOL_DIS (0x0 << 1) + +#define RK3190_ADCR_ZERO_DET_EN_SFT (0) +#define RK3190_ADCR_ZERO_DET_EN (0x1 << 0) +#define RK3190_ADCR_ZERO_DET_DIS (0x0 << 0) + +/* BST_L BST_R CONTROL (0x94) */ +#define RK3190_BSTL_PWRD_SFT (7) +#define RK3190_BSTL_EN (0x1 << 7) +#define RK3190_BSTL_DIS (0x0 << 7) +#define RK3190_BSTL_GAIN_SHT (6) +#define RK3190_BSTL_GAIN_20 (0x1 << 6) +#define RK3190_BSTL_GAIN_0 (0x0 << 6) +#define RK3190_BSTL_MUTE_SHT (5) + +#define RK3190_BSTL_MODE_SFT (4) +#define RK3190_BSTL_MODE_SINGLE (0x1 << 4) +#define RK3190_BSTL_MODE_DIFF (0x0 << 4) + +#define RK3190_BSTR_PWRD_SFT (3) +#define RK3190_BSTR_EN (0x1 << 3) +#define RK3190_BSTR_DIS (0x0 << 3) +#define RK3190_BSTR_GAIN_SHT (2) +#define RK3190_BSTR_GAIN_20 (0x1 << 2) +#define RK3190_BSTR_GAIN_0 (0x0 << 2) +#define RK3190_BSTR_MUTE_SHT (1) + +/* MUXINL ALCL MUXINR ALCR (0x98) */ +#define RK3190_MUXINL_BSTL_SHT (7) +#define RK3190_MUXINL_BSTL_EN (0x0 << 7) +#define RK3190_MUXINL_BSTL_DIS (0x1 << 7) +#define RK3190_MUXINL_INL_SHT (6) +#define RK3190_MUXINL_INL_EN (0x0 << 6) +#define RK3190_MUXINL_INL_DIS (0x1 << 6) + +#define RK3190_ALCL_PWR_SHT (5) +#define RK3190_ALCL_EN (0x1 << 5) +#define RK3190_ALCL_DIS (0x0 << 5) +#define RK3190_ALCL_MUTE_SHT (4) + +#define RK3190_MUXINR_BSTR_SHT (3) +#define RK3190_MUXINR_BSTR_EN (0x0 << 3) +#define RK3190_MUXINR_BSTR_DIS (0x1 << 3) +#define RK3190_MUXINR_INR_SHT (2) +#define RK3190_MUXINR_INR_EN (0x0 << 2) +#define RK3190_MUXINR_INR_DIS (0x1 << 2) + +#define RK3190_ALCR_PWR_SHT (1) +#define RK3190_ALCR_EN (0x1 << 1) +#define RK3190_ALCR_DIS (0x0 << 1) +#define RK3190_ALCR_MUTE_SHT (0) + +/* ALC_L GAIN (0x9c) */ + +#define RK3190_ALCL_GAIN_SHT (0) +#define RK3190_ALCL_GAIN_MSK (0x1f) + +/* ALC_R GAIN (0xa0) */ +#define RK3190_ALCR_GAIN_SHT (0) +#define RK3190_ALCR_GAIN_MSK (0x1f) + +/* ADC ENABLE (0xa4) */ +#define RK3190_ADCL_CLK_EN_SFT (6) +#define RK3190_ADCL_CLK_EN (0x1 << 6) +#define RK3190_ADCL_CLK_DIS (0x0 << 6) + +#define RK3190_ADCL_AMP_EN_SFT (5) +#define RK3190_ADCL_AMP_EN (0x1 << 5) +#define RK3190_ADCL_AMP_DIS (0x0 << 5) + +#define RK3190_ADCL_RST_EN (0x1 << 4) +#define RK3190_ADCL_RST_DIS (0x0 << 4) + +#define RK3190_ADCR_CLK_EN_SFT (2) +#define RK3190_ADCR_CLK_EN (0x1 << 2) +#define RK3190_ADCR_CLK_DIS (0x0 << 2) + +#define RK3190_ADCR_AMP_EN_SFT (1) +#define RK3190_ADCR_AMP_EN (0x1 << 1) +#define RK3190_ADCR_AMP_DIS (0x0 << 1) + +#define RK3190_ADCR_RST_EN (0x1 << 0) +#define RK3190_ADCR_RST_DIS (0x0 << 0) + +/* DAC & VOUT Control (0xa8) */ +#define RK3190_CURRENT_EN (0x1 << 6) +#define RK3190_CURRENT_DIS (0x0 << 6) +#define RK3190_REF_VOL_DACL_EN_SFT (5) +#define RK3190_REF_VOL_DACL_EN (0x1 << 5) +#define RK3190_REF_VOL_DACL_DIS (0x0 << 5) +#define RK3190_ZO_DET_VOUTL_SFT (4) +#define RK3190_ZO_DET_VOUTL_EN (0x1 << 4) +#define RK3190_ZO_DET_VOUTL_DIS (0x0 << 4) +#define RK3190_DET_ERAPHONE_DIS (0x0 << 3) +#define RK3190_DET_ERAPHONE_EN (0x1 << 3) +#define RK3190_REF_VOL_DACR_EN_SFT (1) +#define RK3190_REF_VOL_DACR_EN (0x1 << 1) +#define RK3190_REF_VOL_DACR_DIS (0x0 << 1) +#define RK3190_ZO_DET_VOUTR_SFT (0) +#define RK3190_ZO_DET_VOUTR_EN (0x1 << 0) +#define RK3190_ZO_DET_VOUTR_DIS (0x0 << 0) + +/* DAC control (0xac) */ +#define RK3190_DACL_REF_VOL_EN_SFT (7) +#define RK3190_DACL_REF_VOL_EN (0x1 << 7) +#define RK3190_DACL_REF_VOL_DIS (0x0 << 7) + +#define RK3190_DACL_CLK_EN (0x1 << 6) +#define RK3190_DACL_CLK_DIS (0x0 << 6) + +#define RK3190_DACL_EN (0x1 << 5) +#define RK3190_DACL_DIS (0x0 << 5) + +#define RK3190_DACL_INIT (0x0 << 4) +#define RK3190_DACL_WORK (0x1 << 4) + +#define RK3190_DACR_REF_VOL_EN_SFT (3) +#define RK3190_DACR_REF_VOL_EN (0x1 << 3) +#define RK3190_DACR_REF_VOL_DIS (0x0 << 3) + +#define RK3190_DACR_CLK_EN (0x1 << 2) +#define RK3190_DACR_CLK_DIS (0x0 << 2) + +#define RK3190_DACR_EN (0x1 << 1) +#define RK3190_DACR_DIS (0x0 << 1) + +#define RK3190_DACR_INIT (0x0 << 0) +#define RK3190_DACR_WORK (0x1 << 0) + +/* HPMIXL HPMIXR Control (0xb0) */ +#define RK3190_HPMIXL_SFT (6) +#define RK3190_HPMIXL_EN (0x1 << 6) +#define RK3190_HPMIXL_DIS (0x0 << 6) +#define RK3190_HPMIXL_INIT1 (0x0 << 5) +#define RK3190_HPMIXL_WORK1 (0x1 << 5) +#define RK3190_HPMIXL_INIT2 (0x0 << 4) +#define RK3190_HPMIXL_WORK2 (0x1 << 4) +#define RK3190_HPMIXR_SFT (2) +#define RK3190_HPMIXR_EN (0x1 << 2) +#define RK3190_HPMIXR_DIS (0x0 << 2) +#define RK3190_HPMIXR_INIT1 (0x0 << 1) +#define RK3190_HPMIXR_WORK1 (0x1 << 1) +#define RK3190_HPMIXR_INIT2 (0x0 << 0) +#define RK3190_HPMIXR_WORK2 (0x1 << 0) + +/* HPMIXL Control (0xb4) */ +#define RK3190_HPMIXL_BYPASS_SFT (7) +#define RK3190_HPMIXL_SEL_ALCL_SFT (6) +#define RK3190_HPMIXL_SEL_ALCR_SFT (5) +#define RK3190_HPMIXL_SEL_DACL_SFT (4) +#define RK3190_HPMIXR_BYPASS_SFT (3) +#define RK3190_HPMIXR_SEL_ALCL_SFT (2) +#define RK3190_HPMIXR_SEL_ALCR_SFT (1) +#define RK3190_HPMIXR_SEL_DACR_SFT (0) + +/* HPOUT Control (0xb8) */ +#define RK3190_HPOUTL_PWR_SHT (7) +#define RK3190_HPOUTL_MSK (0x1 << 7) +#define RK3190_HPOUTL_EN (0x1 << 7) +#define RK3190_HPOUTL_DIS (0x0 << 7) +#define RK3190_HPOUTL_INIT_MSK (0x1 << 6) +#define RK3190_HPOUTL_INIT (0x0 << 6) +#define RK3190_HPOUTL_WORK (0x1 << 6) +#define RK3190_HPOUTL_MUTE_SHT (5) +#define RK3190_HPOUTL_MUTE_MSK (0x1 << 5) +#define RK3190_HPOUTL_MUTE_EN (0x0 << 5) +#define RK3190_HPOUTL_MUTE_DIS (0x1 << 5) +#define RK3190_HPOUTR_PWR_SHT (4) +#define RK3190_HPOUTR_MSK (0x1 << 4) +#define RK3190_HPOUTR_EN (0x1 << 4) +#define RK3190_HPOUTR_DIS (0x0 << 4) +#define RK3190_HPOUTR_INIT_MSK (0x1 << 3) +#define RK3190_HPOUTR_WORK (0x1 << 3) +#define RK3190_HPOUTR_INIT (0x0 << 3) +#define RK3190_HPOUTR_MUTE_SHT (2) +#define RK3190_HPOUTR_MUTE_MSK (0x1 << 2) +#define RK3190_HPOUTR_MUTE_EN (0x0 << 2) +#define RK3190_HPOUTR_MUTE_DIS (0x1 << 2) + +#define RK3190_HPVREF_PWR_SHT (1) +#define RK3190_HPVREF_EN (0x1 << 1) +#define RK3190_HPVREF_DIS (0x0 << 1) +#define RK3190_HPVREF_WORK (0x1 << 0) +#define RK3190_HPVREF_INIT (0x0 << 0) + +/* HPOUT GAIN (0xbc 0xc0) */ +#define RK3190_HPOUT_GAIN_SFT (0) + +/* SELECT CURR prechagrge/discharge (0xbc) */ +#define RK3190_PRE_HPOUT (0x1 << 5) +#define RK3190_DIS_HPOUT (0x0 << 5) +#define RK3190_CUR_10UA_EN (0x0 << 4) +#define RK3190_CUR_10UA_DIS (0x1 << 4) +#define RK3190_CUR_I_EN (0x0 << 3) +#define RK3190_CUR_I_DIS (0x1 << 3) +#define RK3190_CUR_2I_EN (0x0 << 2) +#define RK3190_CUR_2I_DIS (0x1 << 2) +#define RK3190_CUR_4I_EN (0x0 << 0) +#define RK3190_CUR_4I_DIS (0x3 << 0) + +/* PGA AGC control 1 (0x100) */ +#define RK3190_PGA_AGC_WAY_MASK (0x1 << 6) +#define RK3190_PGA_AGC_WAY_SFT 6 +#define RK3190_PGA_AGC_WAY_JACK (0x1 << 6) +#define RK3190_PGA_AGC_WAY_NOR (0x0 << 6) + +#define RK3190_PGA_AGC_BK_WAY_SFT 4 +#define RK3190_PGA_AGC_BK_WAY_JACK1 (0x1 << 4) +#define RK3190_PGA_AGC_BK_WAY_NOR (0x0 << 4) +#define RK3190_PGA_AGC_BK_WAY_JACK2 (0x2 << 4) +#define RK3190_PGA_AGC_BK_WAY_JACK3 (0x3 << 4) + +#define RK3190_PGA_AGC_HOLD_T_MASK 0xf +#define RK3190_PGA_AGC_HOLD_T_SFT 0 +#define RK3190_PGA_AGC_HOLD_T_1024 0xa +#define RK3190_PGA_AGC_HOLD_T_512 0x9 +#define RK3190_PGA_AGC_HOLD_T_256 0x8 +#define RK3190_PGA_AGC_HOLD_T_128 0x7 +#define RK3190_PGA_AGC_HOLD_T_64 0x6 +#define RK3190_PGA_AGC_HOLD_T_32 0x5 +#define RK3190_PGA_AGC_HOLD_T_16 0x4 +#define RK3190_PGA_AGC_HOLD_T_8 0x3 +#define RK3190_PGA_AGC_HOLD_T_4 0x2 +#define RK3190_PGA_AGC_HOLD_T_2 0x1 +#define RK3190_PGA_AGC_HOLD_T_0 0x0 + +/* PGA AGC control 2 (0x104) */ +#define RK3190_PGA_AGC_GRU_T_MASK (0xf << 4) +#define RK3190_PGA_AGC_GRU_T_SFT 4 +#define RK3190_PGA_AGC_GRU_T_512 (0xa << 4) +#define RK3190_PGA_AGC_GRU_T_256 (0x9 << 4) +#define RK3190_PGA_AGC_GRU_T_128 (0x8 << 4) +#define RK3190_PGA_AGC_GRU_T_64 (0x7 << 4) +#define RK3190_PGA_AGC_GRU_T_32 (0x6 << 4) +#define RK3190_PGA_AGC_GRU_T_16 (0x5 << 4) +#define RK3190_PGA_AGC_GRU_T_8 (0x4 << 4) +#define RK3190_PGA_AGC_GRU_T_4 (0x3 << 4) +#define RK3190_PGA_AGC_GRU_T_2 (0x2 << 4) +#define RK3190_PGA_AGC_GRU_T_1 (0x1 << 4) +#define RK3190_PGA_AGC_GRU_T_0_5 (0x0 << 4) + +#define RK3190_PGA_AGC_GRD_T_MASK 0xf +#define RK3190_PGA_AGC_GRD_T_SFT 0 +#define RK3190_PGA_AGC_GRD_T_128_32 0xa +#define RK3190_PGA_AGC_GRD_T_64_16 0x9 +#define RK3190_PGA_AGC_GRD_T_32_8 0x8 +#define RK3190_PGA_AGC_GRD_T_16_4 0x7 +#define RK3190_PGA_AGC_GRD_T_8_2 0x6 +#define RK3190_PGA_AGC_GRD_T_4_1 0x5 +#define RK3190_PGA_AGC_GRD_T_2_0_512 0x4 +#define RK3190_PGA_AGC_GRD_T_1_0_256 0x3 +#define RK3190_PGA_AGC_GRD_T_0_500_128 0x2 +#define RK3190_PGA_AGC_GRD_T_0_250_64 0x1 +#define RK3190_PGA_AGC_GRD_T_0_125_32 0x0 + +/* PGA AGC control 3 (0x108) */ +#define RK3190_PGA_AGC_MODE_MASK (0x1 << 7) +#define RK3190_PGA_AGC_MODE_SFT 7 +#define RK3190_PGA_AGC_MODE_LIMIT (0x1 << 7) +#define RK3190_PGA_AGC_MODE_NOR (0x0 << 7) + +#define RK3190_PGA_AGC_ZO_MASK (0x1 << 6) +#define RK3190_PGA_AGC_ZO_SFT 6 +#define RK3190_PGA_AGC_ZO_EN (0x1 << 6) +#define RK3190_PGA_AGC_ZO_DIS (0x0 << 6) + +#define RK3190_PGA_AGC_REC_MODE_MASK (0x1 << 5) +#define RK3190_PGA_AGC_REC_MODE_SFT 5 +#define RK3190_PGA_AGC_REC_MODE_AC (0x1 << 5) +#define RK3190_PGA_AGC_REC_MODE_RN (0x0 << 5) + +#define RK3190_PGA_AGC_FAST_D_MASK (0x1 << 4) +#define RK3190_PGA_AGC_FAST_D_SFT 4 +#define RK3190_PGA_AGC_FAST_D_EN (0x1 << 4) +#define RK3190_PGA_AGC_FAST_D_DIS (0x0 << 4) + +#define RK3190_PGA_AGC_NG_MASK (0x1 << 3) +#define RK3190_PGA_AGC_NG_SFT 3 +#define RK3190_PGA_AGC_NG_EN (0x1 << 3) +#define RK3190_PGA_AGC_NG_DIS (0x0 << 3) + +#define RK3190_PGA_AGC_NG_THR_MASK 0x7 +#define RK3190_PGA_AGC_NG_THR_SFT 0 +#define RK3190_PGA_AGC_NG_THR_N81DB 0x7 +#define RK3190_PGA_AGC_NG_THR_N75DB 0x6 +#define RK3190_PGA_AGC_NG_THR_N69DB 0x5 +#define RK3190_PGA_AGC_NG_THR_N63DB 0x4 +#define RK3190_PGA_AGC_NG_THR_N57DB 0x3 +#define RK3190_PGA_AGC_NG_THR_N51DB 0x2 +#define RK3190_PGA_AGC_NG_THR_N45DB 0x1 +#define RK3190_PGA_AGC_NG_THR_N39DB 0x0 + +/* PGA AGC Control 4 (0x10c) */ +#define RK3190_PGA_AGC_ZO_MODE_MASK (0x1 << 5) +#define RK3190_PGA_AGC_ZO_MODE_SFT 5 +#define RK3190_PGA_AGC_ZO_MODE_UWRC (0x1 << 5) +#define RK3190_PGA_AGC_ZO_MODE_UARC (0x0 << 5) + +#define RK3190_PGA_AGC_VOL_MASK 0x1f +#define RK3190_PGA_AGC_VOL_SFT 0 + +/* PGA ASR Control (0x110) */ +#define RK3190_PGA_SLOW_CLK_MASK (0x1 << 3) +#define RK3190_PGA_SLOW_CLK_SFT 3 +#define RK3190_PGA_SLOW_CLK_EN (0x1 << 3) +#define RK3190_PGA_SLOW_CLK_DIS (0x0 << 3) + +#define RK3190_PGA_ASR_MASK 0x7 +#define RK3190_PGA_ASR_SFT 0 +#define RK3190_PGA_ASR_8KHz 0x7 +#define RK3190_PGA_ASR_12KHz 0x6 +#define RK3190_PGA_ASR_16KHz 0x5 +#define RK3190_PGA_ASR_24KHz 0x4 +#define RK3190_PGA_ASR_32KHz 0x3 +#define RK3190_PGA_ASR_441KHz 0x2 +#define RK3190_PGA_ASR_48KHz 0x1 +#define RK3190_PGA_ASR_96KHz 0x0 + +/* PGA AGC Control 5 (0x124) */ +#define RK3190_PGA_AGC_MASK (0x1 << 6) +#define RK3190_PGA_AGC_SFT 6 +#define RK3190_PGA_AGC_EN (0x1 << 6) +#define RK3190_PGA_AGC_DIS (0x0 << 6) + +#define RK3190_PGA_AGC_MAX_G_MASK (0x7 << 3) +#define RK3190_PGA_AGC_MAX_G_SFT 3 +#define RK3190_PGA_AGC_MAX_G_28_5DB (0x7 << 3) +#define RK3190_PGA_AGC_MAX_G_22_5DB (0x6 << 3) +#define RK3190_PGA_AGC_MAX_G_16_5DB (0x5 << 3) +#define RK3190_PGA_AGC_MAX_G_10_5DB (0x4 << 3) +#define RK3190_PGA_AGC_MAX_G_4_5DB (0x3 << 3) +#define RK3190_PGA_AGC_MAX_G_N1_5DB (0x2 << 3) +#define RK3190_PGA_AGC_MAX_G_N7_5DB (0x1 << 3) +#define RK3190_PGA_AGC_MAX_G_N13_5DB (0x0 << 3) + +#define RK3190_PGA_AGC_MIN_G_MASK 0x7 +#define RK3190_PGA_AGC_MIN_G_SFT 0 +#define RK3190_PGA_AGC_MIN_G_24DB 0x7 +#define RK3190_PGA_AGC_MIN_G_18DB 0x6 +#define RK3190_PGA_AGC_MIN_G_12DB 0x5 +#define RK3190_PGA_AGC_MIN_G_6DB 0x4 +#define RK3190_PGA_AGC_MIN_G_0DB 0x3 +#define RK3190_PGA_AGC_MIN_G_N6DB 0x2 +#define RK3190_PGA_AGC_MIN_G_N12DB 0x1 +#define RK3190_PGA_AGC_MIN_G_N18DB 0x0 + +enum { + RK3190_HIFI, + RK3190_VOICE, +}; + +enum { + RK3190_MONO = 1, + RK3190_STEREO, +}; + +enum { + OFF, + RCV, + SPK_PATH, + HP_PATH, + HP_NO_MIC, + BT, + SPK_HP, + RING_SPK, + RING_HP, + RING_HP_NO_MIC, + RING_SPK_HP, +}; + +enum { + MIC_OFF, + Main_Mic, + Hands_Free_Mic, + BT_Sco_Mic, +}; + +struct rk3190_reg_val_typ { + unsigned int reg; + unsigned int value; +}; + +struct rk3190_init_bit_typ { + unsigned int reg; + unsigned int power_bit; + unsigned int init2_bit; + unsigned int init1_bit; + unsigned int init0_bit; +}; + +bool get_hdmi_state(void); + +struct rk3190_codec_pdata { + int spk_ctl_gpio; + int hp_ctl_gpio; + int ear_ctl_gpio; + int delay_time; +}; + +#endif //__RK3190_CODEC_H__ diff --git a/sound/soc/rk/Kconfig b/sound/soc/rk/Kconfig deleted file mode 100755 index 4cc3afb43f3b..000000000000 --- a/sound/soc/rk/Kconfig +++ /dev/null @@ -1,359 +0,0 @@ -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 deleted file mode 100755 index 1542f472dd83..000000000000 --- a/sound/soc/rk/Makefile +++ /dev/null @@ -1,67 +0,0 @@ -# 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 deleted file mode 100755 index 4ccd2fadef12..000000000000 --- a/sound/soc/rk/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 "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 deleted file mode 100755 index 097fc22442cb..000000000000 --- a/sound/soc/rk/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 "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 deleted file mode 100755 index 91d09ab2c75a..000000000000 --- a/sound/soc/rk/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/rk/rk30_i2s.c b/sound/soc/rk/rk30_i2s.c deleted file mode 100755 index 798bd770b52a..000000000000 --- a/sound/soc/rk/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 "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 deleted file mode 100644 index e6f11eb3951f..000000000000 --- a/sound/soc/rk/rk_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 "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 deleted file mode 100644 index eb77229f0d2a..000000000000 --- a/sound/soc/rk/rk_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 "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 deleted file mode 100755 index a266f5ec4cd6..000000000000 --- a/sound/soc/rk/rk_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 "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 deleted file mode 100755 index a69b1ae3b363..000000000000 --- a/sound/soc/rk/rk_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 "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 deleted file mode 100644 index 254f88c175f8..000000000000 --- a/sound/soc/rk/rk_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 "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 deleted file mode 100755 index 446977bf289e..000000000000 --- a/sound/soc/rk/rk_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 "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 deleted file mode 100644 index d1692f6e49e6..000000000000 --- a/sound/soc/rk/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 "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 deleted file mode 100755 index c93a23957b4e..000000000000 --- a/sound/soc/rk/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/rk/rk_jetta_codec.c b/sound/soc/rk/rk_jetta_codec.c deleted file mode 100755 index b120959a1b1d..000000000000 --- a/sound/soc/rk/rk_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 "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 deleted file mode 100755 index 70b0e6b54c81..000000000000 --- a/sound/soc/rk/rk_pcm.c +++ /dev/null @@ -1,690 +0,0 @@ -/* - * 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 deleted file mode 100755 index 62c92e2acba1..000000000000 --- a/sound/soc/rk/rk_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/rk/rk_rk1000codec.c b/sound/soc/rk/rk_rk1000codec.c deleted file mode 100755 index 7825020431cd..000000000000 --- a/sound/soc/rk/rk_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 "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 deleted file mode 100644 index 191aef64269c..000000000000 --- a/sound/soc/rk/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 "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 deleted file mode 100755 index a88e7284d1f0..000000000000 --- a/sound/soc/rk/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 "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 deleted file mode 100644 index fd0f97f375ad..000000000000 --- a/sound/soc/rk/rk_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 "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 deleted file mode 100755 index 33a6f830c45e..000000000000 --- a/sound/soc/rk/rk_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 "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 deleted file mode 100755 index 0a49430be7b0..000000000000 --- a/sound/soc/rk/rk_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 "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 deleted file mode 100644 index 3469e085036c..000000000000 --- a/sound/soc/rk/rk_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 "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 deleted file mode 100644 index 3d46289f54ba..000000000000 --- a/sound/soc/rk/rk_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 "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 deleted file mode 100755 index 8ddc988e1b89..000000000000 --- a/sound/soc/rk/rk_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 "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 deleted file mode 100755 index cd585f8aee8f..000000000000 --- a/sound/soc/rk/rk_rt5631_phone.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * 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 deleted file mode 100755 index 91d0f49a2659..000000000000 --- a/sound/soc/rk/rk_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 "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 deleted file mode 100755 index 6756f33fb84f..000000000000 --- a/sound/soc/rk/rk_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 "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 deleted file mode 100755 index 22387735399c..000000000000 --- a/sound/soc/rk/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 "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 deleted file mode 100755 index 68f60a360b2d..000000000000 --- a/sound/soc/rk/rk_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 "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 deleted file mode 100755 index dadc25340a67..000000000000 --- a/sound/soc/rk/rk_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 "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 deleted file mode 100755 index df0a8e65c17a..000000000000 --- a/sound/soc/rk/rk_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 "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/rockchip/Kconfig b/sound/soc/rockchip/Kconfig new file mode 100755 index 000000000000..ade75716ed03 --- /dev/null +++ b/sound/soc/rockchip/Kconfig @@ -0,0 +1,369 @@ +config SND_RK_SOC + tristate "SoC Audio for the Rockchip System-on-Chip" + depends on 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. + +config SND_RK_SOC_RK3190 + tristate "SoC I2S Audio support for rockchip - RK3190" + depends on SND_RK_SOC + select SND_RK_SOC_I2S + select SND_SOC_RK3190 + select SND_RK_CODEC_SOC_SLAVE + help + Say Y if you want to add support for SoC audio on rockchip + with the RK3190 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/rockchip/Makefile b/sound/soc/rockchip/Makefile new file mode 100755 index 000000000000..716ddef2a07e --- /dev/null +++ b/sound/soc/rockchip/Makefile @@ -0,0 +1,69 @@ +# 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-rk3190-objs := rk_rk3190.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_RK3190) += snd-soc-rk3190.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/rockchip/rk2928-card.c b/sound/soc/rockchip/rk2928-card.c new file mode 100755 index 000000000000..4ccd2fadef12 --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk29_i2s.c b/sound/soc/rockchip/rk29_i2s.c new file mode 100755 index 000000000000..097fc22442cb --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk29_i2s.h b/sound/soc/rockchip/rk29_i2s.h new file mode 100755 index 000000000000..91d09ab2c75a --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk30_i2s.c b/sound/soc/rockchip/rk30_i2s.c new file mode 100755 index 000000000000..798bd770b52a --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_aic3111.c b/sound/soc/rockchip/rk_aic3111.c new file mode 100644 index 000000000000..e6f11eb3951f --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_aic3262.c b/sound/soc/rockchip/rk_aic3262.c new file mode 100644 index 000000000000..eb77229f0d2a --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_ak4396.c b/sound/soc/rockchip/rk_ak4396.c new file mode 100755 index 000000000000..a266f5ec4cd6 --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_cs42l52.c b/sound/soc/rockchip/rk_cs42l52.c new file mode 100755 index 000000000000..a69b1ae3b363 --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_cx2070x.c b/sound/soc/rockchip/rk_cx2070x.c new file mode 100644 index 000000000000..254f88c175f8 --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_es8323.c b/sound/soc/rockchip/rk_es8323.c new file mode 100755 index 000000000000..446977bf289e --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_hdmi_i2s.c b/sound/soc/rockchip/rk_hdmi_i2s.c new file mode 100644 index 000000000000..d1692f6e49e6 --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_hdmi_spdif.c b/sound/soc/rockchip/rk_hdmi_spdif.c new file mode 100755 index 000000000000..c93a23957b4e --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_jetta_codec.c b/sound/soc/rockchip/rk_jetta_codec.c new file mode 100755 index 000000000000..b120959a1b1d --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_pcm.c b/sound/soc/rockchip/rk_pcm.c new file mode 100755 index 000000000000..70b0e6b54c81 --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_pcm.h b/sound/soc/rockchip/rk_pcm.h new file mode 100755 index 000000000000..62c92e2acba1 --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_rk1000codec.c b/sound/soc/rockchip/rk_rk1000codec.c new file mode 100755 index 000000000000..7825020431cd --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_rk3026.c b/sound/soc/rockchip/rk_rk3026.c new file mode 100644 index 000000000000..191aef64269c --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_rk3190.c b/sound/soc/rockchip/rk_rk3190.c new file mode 100755 index 000000000000..3e6e3b989b0b --- /dev/null +++ b/sound/soc/rockchip/rk_rk3190.c @@ -0,0 +1,290 @@ +/* + * rk_rk3190.c -- SoC audio for rockchip + * + * Driver for rockchip rk3190 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/rk3190_codec.h" +#include "rk29_pcm.h" +#include "rk29_i2s.h" + +#if 0 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif +#if 0 +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"), +}; +#endif +static int rk3190_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__); +#if 0 + 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); +#endif + 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 rk3190_hifi_ops = { + .hw_params = rk_hifi_hw_params, +}; + +static struct snd_soc_ops rk3190_voice_ops = { + .hw_params = rk_voice_hw_params, +}; + +static struct snd_soc_dai_link rk_dai[] = { + { + .name = "RK3190 I2S1", + .stream_name = "RK3190 PCM", + .codec_name = "rk3190-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 = "rk3190-hifi", + .init = rk3190_init, + .ops = &rk3190_hifi_ops, + }, + { + .name = "RK3190 I2S2", + .stream_name = "RK3190 PCM", + .codec_name = "rk3190-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 = "rk3190-voice", + .ops = &rk3190_voice_ops, + }, +}; + +static struct snd_soc_card snd_soc_card_rk = { + .name = "RK_RK3190", + .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/rockchip/rk_rk616.c b/sound/soc/rockchip/rk_rk616.c new file mode 100755 index 000000000000..a88e7284d1f0 --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_rt3261.c b/sound/soc/rockchip/rk_rt3261.c new file mode 100644 index 000000000000..fd0f97f375ad --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_rt5512.c b/sound/soc/rockchip/rk_rt5512.c new file mode 100755 index 000000000000..33a6f830c45e --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_rt5616.c b/sound/soc/rockchip/rk_rt5616.c new file mode 100755 index 000000000000..0a49430be7b0 --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_rt5621.c b/sound/soc/rockchip/rk_rt5621.c new file mode 100644 index 000000000000..3469e085036c --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_rt5625.c b/sound/soc/rockchip/rk_rt5625.c new file mode 100644 index 000000000000..3d46289f54ba --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_rt5631.c b/sound/soc/rockchip/rk_rt5631.c new file mode 100755 index 000000000000..8ddc988e1b89 --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_rt5631_phone.c b/sound/soc/rockchip/rk_rt5631_phone.c new file mode 100755 index 000000000000..cd585f8aee8f --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_rt5639.c b/sound/soc/rockchip/rk_rt5639.c new file mode 100755 index 000000000000..91d0f49a2659 --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_rt5640.c b/sound/soc/rockchip/rk_rt5640.c new file mode 100755 index 000000000000..6756f33fb84f --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_spdif.c b/sound/soc/rockchip/rk_spdif.c new file mode 100755 index 000000000000..22387735399c --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_wm8900.c b/sound/soc/rockchip/rk_wm8900.c new file mode 100755 index 000000000000..68f60a360b2d --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_wm8988.c b/sound/soc/rockchip/rk_wm8988.c new file mode 100755 index 000000000000..dadc25340a67 --- /dev/null +++ b/sound/soc/rockchip/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/rockchip/rk_wm8994.c b/sound/soc/rockchip/rk_wm8994.c new file mode 100755 index 000000000000..df0a8e65c17a --- /dev/null +++ b/sound/soc/rockchip/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");