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"
obj-$(CONFIG_SND_SOC) += tegra/
obj-$(CONFIG_SND_SOC) += txx9/
obj-$(CONFIG_SND_SOC) += ux500/
+obj-$(CONFIG_SND_SOC) += rockchip/
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
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
--- /dev/null
+/*
+ * rk3190_codec.c -- RK3190 CODEC ALSA SoC audio driver
+ *
+ * Copyright 2013 Rockchip
+ * Author: zhangjun <showy.zhang@rock-chips.com>
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <asm/io.h>
+#include <mach/board.h>
+#include <mach/io.h>
+#include <mach/iomux.h>
+#include <mach/cru.h>
+#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 <showy.zhang@rock-chips.com>");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * rk3190_codec.h -- RK3190 CODEC ALSA SoC audio driver
+ *
+ * Copyright 2013 Rockship
+ * Author: zhangjun <showy.zhang@rock-chips.com>
+ *
+ */
+
+#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__
+++ /dev/null
-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
-
+++ /dev/null
-# 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
+++ /dev/null
-/*
- * 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 <linux/delay.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-
-#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");
+++ /dev/null
-/*
- * 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 <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/version.h>
-
-#include <asm/dma.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
-#include <sound/soc.h>
-#include <asm/io.h>
-
-#include <mach/hardware.h>
-#include <mach/board.h>
-#include <mach/rk29_iomap.h>
-#include <mach/rk29-dma-pl330.h>
-#include <mach/iomux.h>
-#include <mach/cru.h>
-
-#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 <linux/proc_fs.h>
-#include <linux/seq_file.h>
-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 */
-
+++ /dev/null
-/*
- * 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 <linux/version.h>
-
-#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 */
-
+++ /dev/null
-/*
- * 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 <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/version.h>
-
-#include <asm/dma.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
-#include <sound/soc.h>
-#include <asm/io.h>
-
-#include <mach/board.h>
-#include <mach/hardware.h>
-#include <mach/io.h>
-#include <mach/gpio.h>
-#include <mach/iomux.h>
-#include <mach/dma-pl330.h>
-#include <linux/spinlock.h>
-
-#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 <linux/proc_fs.h>
-#include <linux/seq_file.h>
-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 */
-
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#include <mach/rk29_iomap.h>
-#include <mach/gpio.h>
-#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");
+++ /dev/null
-/*
- * 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 <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/i2c/twl.h>
-#include <linux/regulator/consumer.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <sound/jack.h>
-#include <linux/switch.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-
-#include <asm/mach-types.h>
-#include <linux/module.h>
-#include <linux/device.h>
-
-#include <asm/io.h>
-#include <mach/hardware.h>
-#include "../codecs/wm8994.h"
-#include "rk_pcm.h"
-#include "rk29_i2s.h"
-#include <linux/clk.h>
-#include <linux/mfd/tlv320aic3262-registers.h>
-#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");
-
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#include "rk_pcm.h"
-#include "rk29_i2s.h"
-
-#include <mach/gpio.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=-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");
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <linux/clk.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#include <mach/rk29_iomap.h>
-#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");
-
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#include <sound/jack.h>
-#include <linux/delay.h>
-#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 <showy.zhang@rock-chips.com>");
-MODULE_LICENSE("GPL");
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-//#include <mach/rk29_iomap.h>
-//#include <linux/tchip_sysinf.h>
-#include "../codecs/es8323.h"
-#include "rk_pcm.h"
-#include "rk29_i2s.h"
-
-#include <mach/gpio.h>
-#ifdef CONFIG_MACH_RK_FAC
-#include <plat/config.h>
-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");
-
+++ /dev/null
-/*
- * rk_hdmi_i2s.c -- HDMI i2s audio for rockchip
- *
- * Copyright 2013 Rockship
- * Author: chenjq <chenjq@rock-chips.com>
- */
-
-#include <linux/clk.h>
-#include <sound/soc.h>
-#include <mach/iomux.h>
-
-#include "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");
+++ /dev/null
-/*$_FOR_ROCKCHIP_RBOX_$*/
-/*$_rbox_$_modify_$_huangzhibao for spdif output*/
-
-/*
- * smdk_spdif.c -- S/PDIF audio for SMDK
- *
- * Copyright 2010 Samsung Electronics Co. Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- */
-
-#include <linux/clk.h>
-
-#include <sound/soc.h>
-
-#include <mach/iomux.h>
-
-#if 0
-#define RK_SPDIF_DBG(x...) printk(KERN_INFO "rk_hdmi_spdif:"x)
-#else
-#define RK_SPDIF_DBG(x...) do { } while (0)
-#endif
-
-
-static int set_audio_clock_rate(unsigned long pll_rate,
- unsigned long audio_rate)
-{
- struct clk *hclk_spdif, *sclk_spdif;
-
-#if defined (CONFIG_ARCH_RK30) || (CONFIG_ARCH_RK3188)
- hclk_spdif = clk_get(NULL, "hclk_spdif");
- if (IS_ERR(hclk_spdif)) {
- printk(KERN_ERR "spdif:failed to get hclk_spdif\n");
- return -ENOENT;
- }
-
- clk_set_rate(hclk_spdif, pll_rate);
- clk_put(hclk_spdif);
-#endif
-
- sclk_spdif = clk_get(NULL, "spdif");
- if (IS_ERR(sclk_spdif)) {
- printk(KERN_ERR "spdif:failed to get sclk_spdif\n");
- return -ENOENT;
- }
-
- clk_set_rate(sclk_spdif, audio_rate);
- clk_put(sclk_spdif);
-
- return 0;
-}
-
-static int rk_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- unsigned long pll_out, rclk_rate;
- int ret, ratio;
-
- RK_SPDIF_DBG("spdif:Entered %s\n", __func__);
-
- switch (params_rate(params)) {
- case 44100:
- pll_out = 11289600;
- break;
- case 32000:
- pll_out = 8192000;
- break;
- case 48000:
- pll_out = 12288000;
- break;
- case 96000:
- pll_out = 24576000;
- break;
- default:
- printk("rk_spdif: params not support\n");
- return -EINVAL;
- }
-
- ratio = 256;
- rclk_rate = params_rate(params) * ratio;
-
- /* Set audio source clock rates */
- ret = set_audio_clock_rate(pll_out, rclk_rate);
- if (ret < 0)
- return ret;
-
- /* Set S/PDIF uses internal source clock */
- //ret = snd_soc_dai_set_sysclk(cpu_dai, SND_SOC_SPDIF_INT_MCLK,
- //rclk_rate, SND_SOC_CLOCK_IN);
- //if (ret < 0)
- //return ret;
-
- return ret;
-}
-
-static struct snd_soc_ops rk_spdif_ops = {
- .hw_params = rk_hw_params,
-};
-
-static struct snd_soc_dai_link rk_dai = {
- .name = "SPDIF",
- .stream_name = "SPDIF PCM Playback",
- .platform_name = "rockchip-audio",
- .cpu_dai_name = "rk-spdif",
- .codec_dai_name = "dit-hifi",
- .codec_name = "spdif-dit",
- .ops = &rk_spdif_ops,
-};
-
-static struct snd_soc_card rk_spdif = {
- .name = "ROCKCHIP-SPDIF",
- .dai_link = &rk_dai,
- .num_links = 1,
-};
-
-static struct platform_device *rk_snd_spdif_dit_device;
-static struct platform_device *rk_snd_spdif_device;
-
-static int __init rk_spdif_init(void)
-{
- int ret;
-
- RK_SPDIF_DBG("Entered %s\n", __func__);
-
- rk_snd_spdif_dit_device = platform_device_alloc("spdif-dit", -1);
- if (!rk_snd_spdif_dit_device){
- printk("spdif:platform_device_alloc spdif-dit\n");
- return -ENOMEM;
- }
-
- ret = platform_device_add(rk_snd_spdif_dit_device);
- if (ret)
- goto err1;
-
- rk_snd_spdif_device = platform_device_alloc("soc-audio", -3);
- if (!rk_snd_spdif_device) {
- printk("spdif:platform_device_alloc rk_soc-audio\n");
- ret = -ENOMEM;
- goto err2;
- }
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
- platform_set_drvdata(rk_snd_spdif_device, &rk_spdif);
-#else
- platform_set_drvdata(rk_snd_spdif_device, &rk_spdif);
- rk_spdif.dev = &rk_snd_spdif_device->dev;
-#endif
-
- //platform_set_drvdata(rk_snd_spdif_device, &rk_spdif);
-
- ret = platform_device_add(rk_snd_spdif_device);
- if (ret)
- goto err3;
-
- RK_SPDIF_DBG("rk_spdif_init ok\n");
- return ret;
-err3:
- platform_device_put(rk_snd_spdif_device);
-err2:
- platform_device_del(rk_snd_spdif_dit_device);
-err1:
- platform_device_put(rk_snd_spdif_dit_device);
-
- return ret;
-}
-
-static void __exit rk_spdif_exit(void)
-{
- platform_device_unregister(rk_snd_spdif_device);
- platform_device_unregister(rk_snd_spdif_dit_device);
-}
-
-//using late_initcall to make sure spdif is after board codec. added by zxg.
-//module_init(rk_spdif_init);
-late_initcall(rk_spdif_init);
-module_exit(rk_spdif_exit);
-
-MODULE_AUTHOR("hzb, <hzb@rock-chips.com>");
-MODULE_DESCRIPTION("ALSA SoC RK+S/PDIF");
-MODULE_LICENSE("GPL");
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#include "../codecs/rk610_codec.h"
-#include "rk_pcm.h"
-#include "rk29_i2s.h"
-#ifdef CONFIG_MACH_RK_FAC
-#include <plat/config.h>
-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");
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-
-#include <asm/dma.h>
-#include <mach/hardware.h>
-#include <mach/dma-pl330.h>
-
-#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");
-
+++ /dev/null
-/*
- * 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 <mach/hardware.h>
-
-#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 */
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#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");
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#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");
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#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");
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-
-#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");
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#include <sound/jack.h>
-#include <linux/delay.h>
-#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 <cy_huang@richtek.com>");
-MODULE_LICENSE("GPL");
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#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");
-
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#include <mach/rk29_iomap.h>
-#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");
+++ /dev/null
-/*\r
- * rk29_rt5625.c -- SoC audio for rockchip\r
- *\r
- * Driver for rockchip rt5625 audio\r
- *\r
- * This program is free software; you can redistribute it and/or modify it\r
- * under the terms of the GNU General Public License as published by the\r
- * Free Software Foundation; either version 2 of the License, or (at your\r
- * option) any later version.\r
- *\r
- *\r
- */\r
-\r
-#include <linux/module.h>\r
-#include <linux/device.h>\r
-#include <sound/core.h>\r
-#include <sound/pcm.h>\r
-#include <sound/soc.h>\r
-#include <sound/soc-dapm.h>\r
-#include <asm/io.h>\r
-#include <mach/hardware.h>\r
-#include <mach/rk29_iomap.h>\r
-#include "../codecs/rt5625.h"\r
-#include "rk_pcm.h"\r
-#include "rk29_i2s.h"\r
-\r
-#if 1\r
-#define DBG(x...) printk(KERN_INFO x)\r
-#else\r
-#define DBG(x...)\r
-#endif\r
-\r
-static int rk29_hw_params(struct snd_pcm_substream *substream,\r
- struct snd_pcm_hw_params *params)\r
-{\r
- struct snd_soc_pcm_runtime *rtd = substream->private_data;\r
- struct snd_soc_dai *codec_dai = rtd->codec_dai;\r
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;\r
- unsigned int pll_out = 0;\r
- int ret;\r
-\r
- DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); \r
- /*by Vincent Hsiung for EQ Vol Change*/\r
- #define HW_PARAMS_FLAG_EQVOL_ON 0x21\r
- #define HW_PARAMS_FLAG_EQVOL_OFF 0x22\r
- if (codec_dai->driver->ops->hw_params && ((params->flags == HW_PARAMS_FLAG_EQVOL_ON) || (params->flags == HW_PARAMS_FLAG_EQVOL_OFF)))\r
- {\r
- ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent\r
- DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);\r
- } else {\r
- \r
- /* set codec DAI configuration */\r
- #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) \r
-\r
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |\r
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);\r
- #endif \r
- #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) \r
-\r
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |\r
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); \r
- #endif\r
- if (ret < 0)\r
- return ret; \r
-\r
- /* set cpu DAI configuration */\r
- #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) \r
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |\r
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);\r
- #endif \r
- #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) \r
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |\r
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); \r
- #endif \r
- if (ret < 0)\r
- return ret;\r
- }\r
-\r
- switch(params_rate(params)) {\r
- case 8000:\r
- case 16000:\r
- case 24000:\r
- case 32000:\r
- case 48000:\r
- pll_out = 12288000;\r
- break;\r
- case 11025:\r
- case 22050:\r
- case 44100:\r
- pll_out = 11289600;\r
- break;\r
- default:\r
- DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));\r
- return -EINVAL;\r
- break;\r
- }\r
-\r
- DBG("Enter:%s, %d, rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));\r
-\r
- /*Set the system clk for codec*/\r
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN);\r
- if (ret < 0)\r
- {\r
- DBG("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); \r
- return ret;\r
- }\r
-\r
- snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);\r
- snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (pll_out/4)/params_rate(params)-1);\r
- snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3);\r
-\r
- DBG("Enter:%s, %d, pll_out/4/params_rate(params) = %d \n", __FUNCTION__, __LINE__, (pll_out/4)/params_rate(params));\r
- \r
- return 0;\r
-}\r
-\r
-static int rt5625_voice_hw_params(struct snd_pcm_substream *substream,\r
- struct snd_pcm_hw_params *params)\r
-{\r
- struct snd_soc_pcm_runtime *rtd = substream->private_data;\r
- struct snd_soc_dai *codec_dai = rtd->codec_dai;\r
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;\r
- unsigned int pll_out = 0;\r
- int ret;\r
-\r
- DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); \r
- \r
- /* set codec DAI configuration */\r
- //#if defined (CONFIG_SND_CODEC_SOC_SLAVE) \r
- DBG("Enter::%s----codec slave\n",__FUNCTION__);\r
-\r
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |\r
- SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS);\r
- /*#endif\r
- //#if defined (CONFIG_SND_CODEC_SOC_MASTER) \r
- DBG("Enter::%s----codec master\n",__FUNCTION__);\r
-\r
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |\r
- SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM ); \r
- #endif*/\r
-\r
- switch(params_rate(params)) {\r
- case 8000:\r
- case 16000:\r
- case 24000:\r
- case 32000:\r
- case 48000:\r
- pll_out = 12288000;\r
- break;\r
- case 11025:\r
- case 22050:\r
- case 44100:\r
- pll_out = 11289600;\r
- break;\r
- default:\r
- DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));\r
- return -EINVAL;\r
- break;\r
- }\r
-\r
- snd_soc_dai_set_pll(codec_dai, RT5625_PLL_MCLK_TO_VSYSCLK, 0, pll_out, 24576000);\r
-\r
- /*Set the system clk for codec*/\r
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, 24576000, SND_SOC_CLOCK_IN);\r
-\r
- if (ret < 0) {\r
- printk("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); \r
- return ret;\r
- }\r
-\r
- ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);\r
- \r
- return 0;\r
-}\r
-\r
-static struct snd_soc_ops rk29_ops = {\r
- .hw_params = rk29_hw_params,\r
-};\r
-\r
-static struct snd_soc_ops rt5625_voice_ops = {\r
- .hw_params = rt5625_voice_hw_params,\r
-};\r
-\r
-static struct snd_soc_dai_link rk29_dai[] = {\r
- {\r
- .name = "RT5625 I2S1",\r
- .stream_name = "RT5625 PCM",\r
- .codec_name = "rt5625.0-001f",\r
- .platform_name = "rockchip-audio",\r
- .cpu_dai_name = "rk_i2s.0",\r
- .codec_dai_name = "rt5625-aif1",\r
- .ops = &rk29_ops,\r
- },\r
- {\r
- .name = "RT5625 I2S2",\r
- .stream_name = "RT5625 PCM",\r
- .codec_name = "rt5625.0-001f",\r
- .platform_name = "rockchip-audio",\r
- .cpu_dai_name = "rk_i2s.0",\r
- .codec_dai_name = "rt5625-aif2",\r
- .ops = &rt5625_voice_ops,\r
- },\r
-};\r
-\r
-static struct snd_soc_card snd_soc_card_rk29 = {\r
- .name = "RK_RT5625",\r
- .dai_link = rk29_dai,\r
- .num_links = 2,\r
-};\r
-\r
-static struct platform_device *rk29_snd_device;\r
-\r
-static int __init audio_card_init(void)\r
-{\r
- int ret =0;\r
-\r
- DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);\r
-\r
- rk29_snd_device = platform_device_alloc("soc-audio", -1);\r
- if (!rk29_snd_device) {\r
- printk("platform device allocation failed\n");\r
- return -ENOMEM;\r
- }\r
-\r
- platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29);\r
- ret = platform_device_add(rk29_snd_device);\r
- if (ret) {\r
- printk("platform device add failed\n");\r
-\r
- platform_device_put(rk29_snd_device);\r
- return ret;\r
- }\r
- \r
- return ret;\r
-}\r
-\r
-static void __exit audio_card_exit(void)\r
-{\r
- platform_device_unregister(rk29_snd_device);\r
-}\r
-\r
-module_init(audio_card_init);\r
-module_exit(audio_card_exit);\r
-/* Module information */\r
-MODULE_AUTHOR("rockchip");\r
-MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");\r
-MODULE_LICENSE("GPL");\r
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#include "../codecs/rt5631.h"
-#include "rk_pcm.h"
-#include "rk29_i2s.h"
-
-#ifdef CONFIG_MACH_RK_FAC
-#include <plat/config.h>
-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");
-
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#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");
-
+++ /dev/null
-/*\r
- * rk29_rt5625.c -- SoC audio for rockchip\r
- *\r
- * Driver for rockchip rt5625 audio\r
- *\r
- * This program is free software; you can redistribute it and/or modify it\r
- * under the terms of the GNU General Public License as published by the\r
- * Free Software Foundation; either version 2 of the License, or (at your\r
- * option) any later version.\r
- *\r
- *\r
- */\r
-\r
-#include <linux/module.h>\r
-#include <linux/device.h>\r
-#include <sound/core.h>\r
-#include <sound/pcm.h>\r
-#include <sound/soc.h>\r
-#include <sound/soc-dapm.h>\r
-#include <asm/io.h>\r
-#include <mach/hardware.h>\r
-\r
-#include "../codecs/rt3261.h"\r
-#include "rk_pcm.h"\r
-#include "rk29_i2s.h"\r
-\r
-#if 1\r
-#define DBG(x...) printk(KERN_INFO x)\r
-#else\r
-#define DBG(x...)\r
-#endif\r
-\r
-static int rk29_hw_params(struct snd_pcm_substream *substream,\r
- struct snd_pcm_hw_params *params)\r
-{\r
- struct snd_soc_pcm_runtime *rtd = substream->private_data;\r
- struct snd_soc_dai *codec_dai = rtd->codec_dai;\r
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;\r
- unsigned int pll_out = 0;\r
- int ret;\r
-\r
- DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); \r
- /*by Vincent Hsiung for EQ Vol Change*/\r
- #define HW_PARAMS_FLAG_EQVOL_ON 0x21\r
- #define HW_PARAMS_FLAG_EQVOL_OFF 0x22\r
- if (codec_dai->driver->ops->hw_params && ((params->flags == HW_PARAMS_FLAG_EQVOL_ON) || (params->flags == HW_PARAMS_FLAG_EQVOL_OFF)))\r
- {\r
- ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent\r
- DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);\r
- } else {\r
- \r
- /* set codec DAI configuration */\r
- #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) \r
-\r
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |\r
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);\r
- #endif \r
- #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) \r
-\r
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |\r
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); \r
- #endif\r
- if (ret < 0)\r
- return ret; \r
-\r
- /* set cpu DAI configuration */\r
- #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) \r
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |\r
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);\r
- #endif \r
- #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) \r
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |\r
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); \r
- #endif \r
- if (ret < 0)\r
- return ret;\r
- }\r
-\r
- switch(params_rate(params)) {\r
- case 8000:\r
- case 16000:\r
- case 24000:\r
- case 32000:\r
- case 48000:\r
- pll_out = 12288000;\r
- break;\r
- case 11025:\r
- case 22050:\r
- case 44100:\r
- pll_out = 11289600;\r
- break;\r
- default:\r
- DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));\r
- return -EINVAL;\r
- break;\r
- }\r
-\r
- DBG("Enter:%s, %d, rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));\r
-\r
- /*Set the system clk for codec*/\r
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN);\r
- if (ret < 0)\r
- {\r
- DBG("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); \r
- return ret;\r
- }\r
-\r
- snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);\r
- snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (pll_out/4)/params_rate(params)-1);\r
- snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3);\r
-\r
- DBG("Enter:%s, %d, pll_out/4/params_rate(params) = %d \n", __FUNCTION__, __LINE__, (pll_out/4)/params_rate(params));\r
- \r
- return 0;\r
-}\r
-\r
-static int rt3261_voice_hw_params(struct snd_pcm_substream *substream,\r
- struct snd_pcm_hw_params *params)\r
-{\r
- struct snd_soc_pcm_runtime *rtd = substream->private_data;\r
- struct snd_soc_dai *codec_dai = rtd->codec_dai;\r
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;\r
- unsigned int pll_out = 0;\r
- int ret;\r
-\r
- DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); \r
- \r
- /* set codec DAI configuration */\r
- //#if defined (CONFIG_SND_CODEC_SOC_SLAVE) \r
- DBG("Enter::%s----codec slave\n",__FUNCTION__);\r
-\r
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |\r
- SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS);\r
- /*#endif\r
- //#if defined (CONFIG_SND_CODEC_SOC_MASTER) \r
- DBG("Enter::%s----codec master\n",__FUNCTION__);\r
-\r
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |\r
- SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM ); \r
- #endif*/\r
-\r
- switch(params_rate(params)) {\r
- case 8000:\r
- case 16000:\r
- case 24000:\r
- case 32000:\r
- case 48000:\r
- pll_out = 12288000;\r
- break;\r
- case 11025:\r
- case 22050:\r
- case 44100:\r
- pll_out = 11289600;\r
- break;\r
- default:\r
- DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));\r
- return -EINVAL;\r
- break;\r
- }\r
-\r
- //snd_soc_dai_set_pll(codec_dai, RT5625_PLL_MCLK_TO_VSYSCLK, 0, pll_out, 24576000);???????\r
-\r
- /*Set the system clk for codec*/\r
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, 24576000, SND_SOC_CLOCK_IN);\r
-\r
- if (ret < 0) {\r
- printk("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); \r
- return ret;\r
- }\r
-\r
- ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);\r
- \r
- return 0;\r
-}\r
-\r
-static struct snd_soc_ops rk29_ops = {\r
- .hw_params = rk29_hw_params,\r
-};\r
-\r
-static struct snd_soc_ops rt5639_voice_ops = {\r
- .hw_params = rt3261_voice_hw_params,\r
-};\r
-\r
-static struct snd_soc_dai_link rk29_dai[] = {\r
- {\r
- .name = "RT5639 I2S1",\r
- .stream_name = "RT5639 PCM",\r
- .codec_name = "rt5639.0-001c",\r
- .platform_name = "rockchip-audio",\r
- .cpu_dai_name = "rk_i2s.0",\r
- .codec_dai_name = "rt5639-aif1",\r
- .ops = &rk29_ops,\r
- },\r
- {\r
- .name = "RT5639 I2S2",\r
- .stream_name = "RT5639 PCM",\r
- .codec_name = "rt5639.0-001c",\r
- .platform_name = "rockchip-audio",\r
- .cpu_dai_name = "rk_i2s.0",\r
- .codec_dai_name = "rt5639-aif2",\r
- .ops = &rt5639_voice_ops,\r
- },\r
-};\r
-\r
-static struct snd_soc_card snd_soc_card_rk29 = {\r
- .name = "RK_RT5639",\r
- .dai_link = rk29_dai,\r
- .num_links = 2,\r
-};\r
-\r
-static struct platform_device *rk29_snd_device;\r
-\r
-static int __init audio_card_init(void)\r
-{\r
- int ret =0;\r
-\r
- DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);\r
-\r
- rk29_snd_device = platform_device_alloc("soc-audio", -1);\r
- if (!rk29_snd_device) {\r
- printk("platform device allocation failed\n");\r
- return -ENOMEM;\r
- }\r
-\r
- platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29);\r
- ret = platform_device_add(rk29_snd_device);\r
- if (ret) {\r
- printk("platform device add failed\n");\r
-\r
- platform_device_put(rk29_snd_device);\r
- return ret;\r
- }\r
- \r
- return ret;\r
-}\r
-\r
-static void __exit audio_card_exit(void)\r
-{\r
- platform_device_unregister(rk29_snd_device);\r
-}\r
-\r
-module_init(audio_card_init); \r
-module_exit(audio_card_exit);\r
-/* Module information */\r
-MODULE_AUTHOR("rockchip");\r
-MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");\r
-MODULE_LICENSE("GPL");\r
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-
-#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");
+++ /dev/null
-/*$_FOR_ROCKCHIP_RBOX_$*/
-/*$_rbox_$_modify_$_huangzhibao for spdif output*/
-
-/* sound/soc/rockchip/spdif.c
- *
- * ALSA SoC Audio Layer - rockchip S/PDIF Controller driver
- *
- * Copyright (c) 2010 rockchip Electronics Co. Ltd
- * http://www.rockchip.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/version.h>
-
-#include <asm/dma.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
-#include <sound/soc.h>
-#include <asm/io.h>
-
-#include <mach/board.h>
-#include <mach/hardware.h>
-#include <mach/io.h>
-#include <mach/gpio.h>
-#include <mach/iomux.h>
-
-#if defined (CONFIG_ARCH_RK29)
-#include <mach/rk29-dma-pl330.h>
-#endif
-
-#if defined (CONFIG_ARCH_RK30)
-#include <mach/dma-pl330.h>
-#endif
-
-#if defined (CONFIG_ARCH_RK3188)
-#include <mach/dma-pl330.h>
-#endif
-
-#include "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, <sw.youn@rockchip.com>");
-MODULE_DESCRIPTION("rockchip S/PDIF Controller Driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:rockchip-spdif");
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#include <mach/rk29_iomap.h>
-#include "../codecs/wm8900.h"
-#include "rk_pcm.h"
-#include "rk29_i2s.h"
-#include <linux/clk.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;
-#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");
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#include <mach/rk29_iomap.h>
-#include "../codecs/wm8988.h"
-#include "rk_pcm.h"
-#include "rk29_i2s.h"
-
-#include <mach/gpio.h>
-
-#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");
+++ /dev/null
-/*
- * 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 <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <asm/io.h>
-#include <mach/hardware.h>
-#include "../codecs/wm8994.h"
-#include "rk_pcm.h"
-#include "rk29_i2s.h"
-#include <linux/clk.h>
-
-#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");
--- /dev/null
+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
+
--- /dev/null
+# 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
--- /dev/null
+/*
+ * 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 <linux/delay.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#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");
--- /dev/null
+/*
+ * 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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/version.h>
+
+#include <asm/dma.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <asm/io.h>
+
+#include <mach/hardware.h>
+#include <mach/board.h>
+#include <mach/rk29_iomap.h>
+#include <mach/rk29-dma-pl330.h>
+#include <mach/iomux.h>
+#include <mach/cru.h>
+
+#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 <linux/proc_fs.h>
+#include <linux/seq_file.h>
+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 */
+
--- /dev/null
+/*
+ * 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 <linux/version.h>
+
+#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 */
+
--- /dev/null
+/*
+ * 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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/version.h>
+
+#include <asm/dma.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <asm/io.h>
+
+#include <mach/board.h>
+#include <mach/hardware.h>
+#include <mach/io.h>
+#include <mach/gpio.h>
+#include <mach/iomux.h>
+#include <mach/dma-pl330.h>
+#include <linux/spinlock.h>
+
+#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 <linux/proc_fs.h>
+#include <linux/seq_file.h>
+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 */
+
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <mach/rk29_iomap.h>
+#include <mach/gpio.h>
+#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");
--- /dev/null
+/*
+ * 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 <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/i2c/twl.h>
+#include <linux/regulator/consumer.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+#include <linux/switch.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <linux/module.h>
+#include <linux/device.h>
+
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include "../codecs/wm8994.h"
+#include "rk_pcm.h"
+#include "rk29_i2s.h"
+#include <linux/clk.h>
+#include <linux/mfd/tlv320aic3262-registers.h>
+#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");
+
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include "rk_pcm.h"
+#include "rk29_i2s.h"
+
+#include <mach/gpio.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=-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");
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <mach/rk29_iomap.h>
+#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");
+
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <sound/jack.h>
+#include <linux/delay.h>
+#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 <showy.zhang@rock-chips.com>");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+//#include <mach/rk29_iomap.h>
+//#include <linux/tchip_sysinf.h>
+#include "../codecs/es8323.h"
+#include "rk_pcm.h"
+#include "rk29_i2s.h"
+
+#include <mach/gpio.h>
+#ifdef CONFIG_MACH_RK_FAC
+#include <plat/config.h>
+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");
+
--- /dev/null
+/*
+ * rk_hdmi_i2s.c -- HDMI i2s audio for rockchip
+ *
+ * Copyright 2013 Rockship
+ * Author: chenjq <chenjq@rock-chips.com>
+ */
+
+#include <linux/clk.h>
+#include <sound/soc.h>
+#include <mach/iomux.h>
+
+#include "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");
--- /dev/null
+/*$_FOR_ROCKCHIP_RBOX_$*/
+/*$_rbox_$_modify_$_huangzhibao for spdif output*/
+
+/*
+ * smdk_spdif.c -- S/PDIF audio for SMDK
+ *
+ * Copyright 2010 Samsung Electronics Co. Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/clk.h>
+
+#include <sound/soc.h>
+
+#include <mach/iomux.h>
+
+#if 0
+#define RK_SPDIF_DBG(x...) printk(KERN_INFO "rk_hdmi_spdif:"x)
+#else
+#define RK_SPDIF_DBG(x...) do { } while (0)
+#endif
+
+
+static int set_audio_clock_rate(unsigned long pll_rate,
+ unsigned long audio_rate)
+{
+ struct clk *hclk_spdif, *sclk_spdif;
+
+#if defined (CONFIG_ARCH_RK30) || (CONFIG_ARCH_RK3188)
+ hclk_spdif = clk_get(NULL, "hclk_spdif");
+ if (IS_ERR(hclk_spdif)) {
+ printk(KERN_ERR "spdif:failed to get hclk_spdif\n");
+ return -ENOENT;
+ }
+
+ clk_set_rate(hclk_spdif, pll_rate);
+ clk_put(hclk_spdif);
+#endif
+
+ sclk_spdif = clk_get(NULL, "spdif");
+ if (IS_ERR(sclk_spdif)) {
+ printk(KERN_ERR "spdif:failed to get sclk_spdif\n");
+ return -ENOENT;
+ }
+
+ clk_set_rate(sclk_spdif, audio_rate);
+ clk_put(sclk_spdif);
+
+ return 0;
+}
+
+static int rk_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ unsigned long pll_out, rclk_rate;
+ int ret, ratio;
+
+ RK_SPDIF_DBG("spdif:Entered %s\n", __func__);
+
+ switch (params_rate(params)) {
+ case 44100:
+ pll_out = 11289600;
+ break;
+ case 32000:
+ pll_out = 8192000;
+ break;
+ case 48000:
+ pll_out = 12288000;
+ break;
+ case 96000:
+ pll_out = 24576000;
+ break;
+ default:
+ printk("rk_spdif: params not support\n");
+ return -EINVAL;
+ }
+
+ ratio = 256;
+ rclk_rate = params_rate(params) * ratio;
+
+ /* Set audio source clock rates */
+ ret = set_audio_clock_rate(pll_out, rclk_rate);
+ if (ret < 0)
+ return ret;
+
+ /* Set S/PDIF uses internal source clock */
+ //ret = snd_soc_dai_set_sysclk(cpu_dai, SND_SOC_SPDIF_INT_MCLK,
+ //rclk_rate, SND_SOC_CLOCK_IN);
+ //if (ret < 0)
+ //return ret;
+
+ return ret;
+}
+
+static struct snd_soc_ops rk_spdif_ops = {
+ .hw_params = rk_hw_params,
+};
+
+static struct snd_soc_dai_link rk_dai = {
+ .name = "SPDIF",
+ .stream_name = "SPDIF PCM Playback",
+ .platform_name = "rockchip-audio",
+ .cpu_dai_name = "rk-spdif",
+ .codec_dai_name = "dit-hifi",
+ .codec_name = "spdif-dit",
+ .ops = &rk_spdif_ops,
+};
+
+static struct snd_soc_card rk_spdif = {
+ .name = "ROCKCHIP-SPDIF",
+ .dai_link = &rk_dai,
+ .num_links = 1,
+};
+
+static struct platform_device *rk_snd_spdif_dit_device;
+static struct platform_device *rk_snd_spdif_device;
+
+static int __init rk_spdif_init(void)
+{
+ int ret;
+
+ RK_SPDIF_DBG("Entered %s\n", __func__);
+
+ rk_snd_spdif_dit_device = platform_device_alloc("spdif-dit", -1);
+ if (!rk_snd_spdif_dit_device){
+ printk("spdif:platform_device_alloc spdif-dit\n");
+ return -ENOMEM;
+ }
+
+ ret = platform_device_add(rk_snd_spdif_dit_device);
+ if (ret)
+ goto err1;
+
+ rk_snd_spdif_device = platform_device_alloc("soc-audio", -3);
+ if (!rk_snd_spdif_device) {
+ printk("spdif:platform_device_alloc rk_soc-audio\n");
+ ret = -ENOMEM;
+ goto err2;
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+ platform_set_drvdata(rk_snd_spdif_device, &rk_spdif);
+#else
+ platform_set_drvdata(rk_snd_spdif_device, &rk_spdif);
+ rk_spdif.dev = &rk_snd_spdif_device->dev;
+#endif
+
+ //platform_set_drvdata(rk_snd_spdif_device, &rk_spdif);
+
+ ret = platform_device_add(rk_snd_spdif_device);
+ if (ret)
+ goto err3;
+
+ RK_SPDIF_DBG("rk_spdif_init ok\n");
+ return ret;
+err3:
+ platform_device_put(rk_snd_spdif_device);
+err2:
+ platform_device_del(rk_snd_spdif_dit_device);
+err1:
+ platform_device_put(rk_snd_spdif_dit_device);
+
+ return ret;
+}
+
+static void __exit rk_spdif_exit(void)
+{
+ platform_device_unregister(rk_snd_spdif_device);
+ platform_device_unregister(rk_snd_spdif_dit_device);
+}
+
+//using late_initcall to make sure spdif is after board codec. added by zxg.
+//module_init(rk_spdif_init);
+late_initcall(rk_spdif_init);
+module_exit(rk_spdif_exit);
+
+MODULE_AUTHOR("hzb, <hzb@rock-chips.com>");
+MODULE_DESCRIPTION("ALSA SoC RK+S/PDIF");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include "../codecs/rk610_codec.h"
+#include "rk_pcm.h"
+#include "rk29_i2s.h"
+#ifdef CONFIG_MACH_RK_FAC
+#include <plat/config.h>
+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");
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <asm/dma.h>
+#include <mach/hardware.h>
+#include <mach/dma-pl330.h>
+
+#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");
+
--- /dev/null
+/*
+ * 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 <mach/hardware.h>
+
+#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 */
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#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");
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#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");
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#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");
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#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");
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+
+#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");
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <sound/jack.h>
+#include <linux/delay.h>
+#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 <cy_huang@richtek.com>");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#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");
+
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <mach/rk29_iomap.h>
+#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");
--- /dev/null
+/*\r
+ * rk29_rt5625.c -- SoC audio for rockchip\r
+ *\r
+ * Driver for rockchip rt5625 audio\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify it\r
+ * under the terms of the GNU General Public License as published by the\r
+ * Free Software Foundation; either version 2 of the License, or (at your\r
+ * option) any later version.\r
+ *\r
+ *\r
+ */\r
+\r
+#include <linux/module.h>\r
+#include <linux/device.h>\r
+#include <sound/core.h>\r
+#include <sound/pcm.h>\r
+#include <sound/soc.h>\r
+#include <sound/soc-dapm.h>\r
+#include <asm/io.h>\r
+#include <mach/hardware.h>\r
+#include <mach/rk29_iomap.h>\r
+#include "../codecs/rt5625.h"\r
+#include "rk_pcm.h"\r
+#include "rk29_i2s.h"\r
+\r
+#if 1\r
+#define DBG(x...) printk(KERN_INFO x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+static int rk29_hw_params(struct snd_pcm_substream *substream,\r
+ struct snd_pcm_hw_params *params)\r
+{\r
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;\r
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;\r
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;\r
+ unsigned int pll_out = 0;\r
+ int ret;\r
+\r
+ DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); \r
+ /*by Vincent Hsiung for EQ Vol Change*/\r
+ #define HW_PARAMS_FLAG_EQVOL_ON 0x21\r
+ #define HW_PARAMS_FLAG_EQVOL_OFF 0x22\r
+ if (codec_dai->driver->ops->hw_params && ((params->flags == HW_PARAMS_FLAG_EQVOL_ON) || (params->flags == HW_PARAMS_FLAG_EQVOL_OFF)))\r
+ {\r
+ ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent\r
+ DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);\r
+ } else {\r
+ \r
+ /* set codec DAI configuration */\r
+ #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) \r
+\r
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |\r
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);\r
+ #endif \r
+ #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) \r
+\r
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |\r
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); \r
+ #endif\r
+ if (ret < 0)\r
+ return ret; \r
+\r
+ /* set cpu DAI configuration */\r
+ #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) \r
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |\r
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);\r
+ #endif \r
+ #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) \r
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |\r
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); \r
+ #endif \r
+ if (ret < 0)\r
+ return ret;\r
+ }\r
+\r
+ switch(params_rate(params)) {\r
+ case 8000:\r
+ case 16000:\r
+ case 24000:\r
+ case 32000:\r
+ case 48000:\r
+ pll_out = 12288000;\r
+ break;\r
+ case 11025:\r
+ case 22050:\r
+ case 44100:\r
+ pll_out = 11289600;\r
+ break;\r
+ default:\r
+ DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));\r
+ return -EINVAL;\r
+ break;\r
+ }\r
+\r
+ DBG("Enter:%s, %d, rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));\r
+\r
+ /*Set the system clk for codec*/\r
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN);\r
+ if (ret < 0)\r
+ {\r
+ DBG("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); \r
+ return ret;\r
+ }\r
+\r
+ snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);\r
+ snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (pll_out/4)/params_rate(params)-1);\r
+ snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3);\r
+\r
+ DBG("Enter:%s, %d, pll_out/4/params_rate(params) = %d \n", __FUNCTION__, __LINE__, (pll_out/4)/params_rate(params));\r
+ \r
+ return 0;\r
+}\r
+\r
+static int rt5625_voice_hw_params(struct snd_pcm_substream *substream,\r
+ struct snd_pcm_hw_params *params)\r
+{\r
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;\r
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;\r
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;\r
+ unsigned int pll_out = 0;\r
+ int ret;\r
+\r
+ DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); \r
+ \r
+ /* set codec DAI configuration */\r
+ //#if defined (CONFIG_SND_CODEC_SOC_SLAVE) \r
+ DBG("Enter::%s----codec slave\n",__FUNCTION__);\r
+\r
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |\r
+ SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS);\r
+ /*#endif\r
+ //#if defined (CONFIG_SND_CODEC_SOC_MASTER) \r
+ DBG("Enter::%s----codec master\n",__FUNCTION__);\r
+\r
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |\r
+ SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM ); \r
+ #endif*/\r
+\r
+ switch(params_rate(params)) {\r
+ case 8000:\r
+ case 16000:\r
+ case 24000:\r
+ case 32000:\r
+ case 48000:\r
+ pll_out = 12288000;\r
+ break;\r
+ case 11025:\r
+ case 22050:\r
+ case 44100:\r
+ pll_out = 11289600;\r
+ break;\r
+ default:\r
+ DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));\r
+ return -EINVAL;\r
+ break;\r
+ }\r
+\r
+ snd_soc_dai_set_pll(codec_dai, RT5625_PLL_MCLK_TO_VSYSCLK, 0, pll_out, 24576000);\r
+\r
+ /*Set the system clk for codec*/\r
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 24576000, SND_SOC_CLOCK_IN);\r
+\r
+ if (ret < 0) {\r
+ printk("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); \r
+ return ret;\r
+ }\r
+\r
+ ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);\r
+ \r
+ return 0;\r
+}\r
+\r
+static struct snd_soc_ops rk29_ops = {\r
+ .hw_params = rk29_hw_params,\r
+};\r
+\r
+static struct snd_soc_ops rt5625_voice_ops = {\r
+ .hw_params = rt5625_voice_hw_params,\r
+};\r
+\r
+static struct snd_soc_dai_link rk29_dai[] = {\r
+ {\r
+ .name = "RT5625 I2S1",\r
+ .stream_name = "RT5625 PCM",\r
+ .codec_name = "rt5625.0-001f",\r
+ .platform_name = "rockchip-audio",\r
+ .cpu_dai_name = "rk_i2s.0",\r
+ .codec_dai_name = "rt5625-aif1",\r
+ .ops = &rk29_ops,\r
+ },\r
+ {\r
+ .name = "RT5625 I2S2",\r
+ .stream_name = "RT5625 PCM",\r
+ .codec_name = "rt5625.0-001f",\r
+ .platform_name = "rockchip-audio",\r
+ .cpu_dai_name = "rk_i2s.0",\r
+ .codec_dai_name = "rt5625-aif2",\r
+ .ops = &rt5625_voice_ops,\r
+ },\r
+};\r
+\r
+static struct snd_soc_card snd_soc_card_rk29 = {\r
+ .name = "RK_RT5625",\r
+ .dai_link = rk29_dai,\r
+ .num_links = 2,\r
+};\r
+\r
+static struct platform_device *rk29_snd_device;\r
+\r
+static int __init audio_card_init(void)\r
+{\r
+ int ret =0;\r
+\r
+ DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);\r
+\r
+ rk29_snd_device = platform_device_alloc("soc-audio", -1);\r
+ if (!rk29_snd_device) {\r
+ printk("platform device allocation failed\n");\r
+ return -ENOMEM;\r
+ }\r
+\r
+ platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29);\r
+ ret = platform_device_add(rk29_snd_device);\r
+ if (ret) {\r
+ printk("platform device add failed\n");\r
+\r
+ platform_device_put(rk29_snd_device);\r
+ return ret;\r
+ }\r
+ \r
+ return ret;\r
+}\r
+\r
+static void __exit audio_card_exit(void)\r
+{\r
+ platform_device_unregister(rk29_snd_device);\r
+}\r
+\r
+module_init(audio_card_init);\r
+module_exit(audio_card_exit);\r
+/* Module information */\r
+MODULE_AUTHOR("rockchip");\r
+MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");\r
+MODULE_LICENSE("GPL");\r
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include "../codecs/rt5631.h"
+#include "rk_pcm.h"
+#include "rk29_i2s.h"
+
+#ifdef CONFIG_MACH_RK_FAC
+#include <plat/config.h>
+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");
+
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#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");
+
--- /dev/null
+/*\r
+ * rk29_rt5625.c -- SoC audio for rockchip\r
+ *\r
+ * Driver for rockchip rt5625 audio\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify it\r
+ * under the terms of the GNU General Public License as published by the\r
+ * Free Software Foundation; either version 2 of the License, or (at your\r
+ * option) any later version.\r
+ *\r
+ *\r
+ */\r
+\r
+#include <linux/module.h>\r
+#include <linux/device.h>\r
+#include <sound/core.h>\r
+#include <sound/pcm.h>\r
+#include <sound/soc.h>\r
+#include <sound/soc-dapm.h>\r
+#include <asm/io.h>\r
+#include <mach/hardware.h>\r
+\r
+#include "../codecs/rt3261.h"\r
+#include "rk_pcm.h"\r
+#include "rk29_i2s.h"\r
+\r
+#if 1\r
+#define DBG(x...) printk(KERN_INFO x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+static int rk29_hw_params(struct snd_pcm_substream *substream,\r
+ struct snd_pcm_hw_params *params)\r
+{\r
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;\r
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;\r
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;\r
+ unsigned int pll_out = 0;\r
+ int ret;\r
+\r
+ DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); \r
+ /*by Vincent Hsiung for EQ Vol Change*/\r
+ #define HW_PARAMS_FLAG_EQVOL_ON 0x21\r
+ #define HW_PARAMS_FLAG_EQVOL_OFF 0x22\r
+ if (codec_dai->driver->ops->hw_params && ((params->flags == HW_PARAMS_FLAG_EQVOL_ON) || (params->flags == HW_PARAMS_FLAG_EQVOL_OFF)))\r
+ {\r
+ ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent\r
+ DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);\r
+ } else {\r
+ \r
+ /* set codec DAI configuration */\r
+ #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) \r
+\r
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |\r
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);\r
+ #endif \r
+ #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) \r
+\r
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |\r
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); \r
+ #endif\r
+ if (ret < 0)\r
+ return ret; \r
+\r
+ /* set cpu DAI configuration */\r
+ #if defined (CONFIG_SND_RK_CODEC_SOC_SLAVE) \r
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |\r
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);\r
+ #endif \r
+ #if defined (CONFIG_SND_RK_CODEC_SOC_MASTER) \r
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |\r
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); \r
+ #endif \r
+ if (ret < 0)\r
+ return ret;\r
+ }\r
+\r
+ switch(params_rate(params)) {\r
+ case 8000:\r
+ case 16000:\r
+ case 24000:\r
+ case 32000:\r
+ case 48000:\r
+ pll_out = 12288000;\r
+ break;\r
+ case 11025:\r
+ case 22050:\r
+ case 44100:\r
+ pll_out = 11289600;\r
+ break;\r
+ default:\r
+ DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));\r
+ return -EINVAL;\r
+ break;\r
+ }\r
+\r
+ DBG("Enter:%s, %d, rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));\r
+\r
+ /*Set the system clk for codec*/\r
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN);\r
+ if (ret < 0)\r
+ {\r
+ DBG("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); \r
+ return ret;\r
+ }\r
+\r
+ snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);\r
+ snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (pll_out/4)/params_rate(params)-1);\r
+ snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3);\r
+\r
+ DBG("Enter:%s, %d, pll_out/4/params_rate(params) = %d \n", __FUNCTION__, __LINE__, (pll_out/4)/params_rate(params));\r
+ \r
+ return 0;\r
+}\r
+\r
+static int rt3261_voice_hw_params(struct snd_pcm_substream *substream,\r
+ struct snd_pcm_hw_params *params)\r
+{\r
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;\r
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;\r
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;\r
+ unsigned int pll_out = 0;\r
+ int ret;\r
+\r
+ DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); \r
+ \r
+ /* set codec DAI configuration */\r
+ //#if defined (CONFIG_SND_CODEC_SOC_SLAVE) \r
+ DBG("Enter::%s----codec slave\n",__FUNCTION__);\r
+\r
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |\r
+ SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS);\r
+ /*#endif\r
+ //#if defined (CONFIG_SND_CODEC_SOC_MASTER) \r
+ DBG("Enter::%s----codec master\n",__FUNCTION__);\r
+\r
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |\r
+ SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM ); \r
+ #endif*/\r
+\r
+ switch(params_rate(params)) {\r
+ case 8000:\r
+ case 16000:\r
+ case 24000:\r
+ case 32000:\r
+ case 48000:\r
+ pll_out = 12288000;\r
+ break;\r
+ case 11025:\r
+ case 22050:\r
+ case 44100:\r
+ pll_out = 11289600;\r
+ break;\r
+ default:\r
+ DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params));\r
+ return -EINVAL;\r
+ break;\r
+ }\r
+\r
+ //snd_soc_dai_set_pll(codec_dai, RT5625_PLL_MCLK_TO_VSYSCLK, 0, pll_out, 24576000);???????\r
+\r
+ /*Set the system clk for codec*/\r
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 24576000, SND_SOC_CLOCK_IN);\r
+\r
+ if (ret < 0) {\r
+ printk("rk29_hw_params_rt5625:failed to set the sysclk for codec side\n"); \r
+ return ret;\r
+ }\r
+\r
+ ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);\r
+ \r
+ return 0;\r
+}\r
+\r
+static struct snd_soc_ops rk29_ops = {\r
+ .hw_params = rk29_hw_params,\r
+};\r
+\r
+static struct snd_soc_ops rt5639_voice_ops = {\r
+ .hw_params = rt3261_voice_hw_params,\r
+};\r
+\r
+static struct snd_soc_dai_link rk29_dai[] = {\r
+ {\r
+ .name = "RT5639 I2S1",\r
+ .stream_name = "RT5639 PCM",\r
+ .codec_name = "rt5639.0-001c",\r
+ .platform_name = "rockchip-audio",\r
+ .cpu_dai_name = "rk_i2s.0",\r
+ .codec_dai_name = "rt5639-aif1",\r
+ .ops = &rk29_ops,\r
+ },\r
+ {\r
+ .name = "RT5639 I2S2",\r
+ .stream_name = "RT5639 PCM",\r
+ .codec_name = "rt5639.0-001c",\r
+ .platform_name = "rockchip-audio",\r
+ .cpu_dai_name = "rk_i2s.0",\r
+ .codec_dai_name = "rt5639-aif2",\r
+ .ops = &rt5639_voice_ops,\r
+ },\r
+};\r
+\r
+static struct snd_soc_card snd_soc_card_rk29 = {\r
+ .name = "RK_RT5639",\r
+ .dai_link = rk29_dai,\r
+ .num_links = 2,\r
+};\r
+\r
+static struct platform_device *rk29_snd_device;\r
+\r
+static int __init audio_card_init(void)\r
+{\r
+ int ret =0;\r
+\r
+ DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);\r
+\r
+ rk29_snd_device = platform_device_alloc("soc-audio", -1);\r
+ if (!rk29_snd_device) {\r
+ printk("platform device allocation failed\n");\r
+ return -ENOMEM;\r
+ }\r
+\r
+ platform_set_drvdata(rk29_snd_device, &snd_soc_card_rk29);\r
+ ret = platform_device_add(rk29_snd_device);\r
+ if (ret) {\r
+ printk("platform device add failed\n");\r
+\r
+ platform_device_put(rk29_snd_device);\r
+ return ret;\r
+ }\r
+ \r
+ return ret;\r
+}\r
+\r
+static void __exit audio_card_exit(void)\r
+{\r
+ platform_device_unregister(rk29_snd_device);\r
+}\r
+\r
+module_init(audio_card_init); \r
+module_exit(audio_card_exit);\r
+/* Module information */\r
+MODULE_AUTHOR("rockchip");\r
+MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");\r
+MODULE_LICENSE("GPL");\r
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+
+#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");
--- /dev/null
+/*$_FOR_ROCKCHIP_RBOX_$*/
+/*$_rbox_$_modify_$_huangzhibao for spdif output*/
+
+/* sound/soc/rockchip/spdif.c
+ *
+ * ALSA SoC Audio Layer - rockchip S/PDIF Controller driver
+ *
+ * Copyright (c) 2010 rockchip Electronics Co. Ltd
+ * http://www.rockchip.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/version.h>
+
+#include <asm/dma.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <asm/io.h>
+
+#include <mach/board.h>
+#include <mach/hardware.h>
+#include <mach/io.h>
+#include <mach/gpio.h>
+#include <mach/iomux.h>
+
+#if defined (CONFIG_ARCH_RK29)
+#include <mach/rk29-dma-pl330.h>
+#endif
+
+#if defined (CONFIG_ARCH_RK30)
+#include <mach/dma-pl330.h>
+#endif
+
+#if defined (CONFIG_ARCH_RK3188)
+#include <mach/dma-pl330.h>
+#endif
+
+#include "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, <sw.youn@rockchip.com>");
+MODULE_DESCRIPTION("rockchip S/PDIF Controller Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:rockchip-spdif");
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <mach/rk29_iomap.h>
+#include "../codecs/wm8900.h"
+#include "rk_pcm.h"
+#include "rk29_i2s.h"
+#include <linux/clk.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;
+#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");
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <mach/rk29_iomap.h>
+#include "../codecs/wm8988.h"
+#include "rk_pcm.h"
+#include "rk29_i2s.h"
+
+#include <mach/gpio.h>
+
+#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");
--- /dev/null
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include "../codecs/wm8994.h"
+#include "rk_pcm.h"
+#include "rk29_i2s.h"
+#include <linux/clk.h>
+
+#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");