From 20ccf557a0af48f8ef84f66583a9e39f95f5b0c6 Mon Sep 17 00:00:00 2001 From: yxj Date: Sat, 19 Nov 2011 09:48:34 +0800 Subject: [PATCH] support for codec rt5631 by ChenJQ --- arch/arm/configs/rk29_k97_defconfig | 47 +- arch/arm/mach-rk29/board-rk29-k97.c | 2 +- drivers/video/hdmi/hdmi-codec.c | 2 +- sound/soc/codecs/Kconfig | 4 +- sound/soc/codecs/Makefile | 4 +- sound/soc/codecs/rt5631.c | 2483 +++++++++++++-------------- sound/soc/codecs/rt5631.h | 1148 ++++++------- sound/soc/rk29/Kconfig | 10 +- sound/soc/rk29/Makefile | 4 +- sound/soc/rk29/rk29_rt5631.c | 62 +- 10 files changed, 1849 insertions(+), 1917 deletions(-) diff --git a/arch/arm/configs/rk29_k97_defconfig b/arch/arm/configs/rk29_k97_defconfig index db0d80003086..c9dc742bedad 100644 --- a/arch/arm/configs/rk29_k97_defconfig +++ b/arch/arm/configs/rk29_k97_defconfig @@ -1806,7 +1806,52 @@ CONFIG_LOGO_LINUX_CLUT224=y # CONFIG_LOGO_CHARGER_CLUT224 is not set CONFIG_SOUND=y # CONFIG_SOUND_OSS_CORE is not set -# CONFIG_SND is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_JACK=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +# CONFIG_SND_SUPPORT_OLD_API is not set +# CONFIG_SND_VERBOSE_PROCFS is not set +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +# CONFIG_SND_DRIVERS is not set +# CONFIG_SND_ARM is not set +CONFIG_SND_USB=y +# CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set +CONFIG_SND_SOC=y +# CONFIG_SND_SOC_CACHE_LZO is not set +CONFIG_SND_RK29_SOC=y +CONFIG_SND_RK29_SOC_I2S=y +# CONFIG_SND_RK29_SOC_I2S_2CH is not set +CONFIG_SND_RK29_SOC_I2S_8CH=y +# CONFIG_SND_I2S_DMA_EVENT_DYNAMIC is not set +CONFIG_SND_I2S_DMA_EVENT_STATIC=y +# CONFIG_SND_RK29_SOC_WM8988 is not set +# CONFIG_SND_RK29_SOC_WM8900 is not set +# CONFIG_SND_RK29_SOC_alc5621 is not set +CONFIG_SND_RK29_SOC_RT5631=y +# CONFIG_SND_RK29_SOC_RT5625 is not set +# CONFIG_SND_RK29_SOC_WM8994 is not set +# CONFIG_SND_RK29_SOC_CS42L52 is not set +# CONFIG_SND_RK29_CODEC_SOC_MASTER is not set +CONFIG_SND_RK29_CODEC_SOC_SLAVE=y +# CONFIG_ADJUST_VOL_BY_CODEC is not set +CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SOC_ALL_CODECS is not set +CONFIG_SND_SOC_RT5631=y # CONFIG_SOUND_PRIME is not set CONFIG_HID_SUPPORT=y CONFIG_HID=y diff --git a/arch/arm/mach-rk29/board-rk29-k97.c b/arch/arm/mach-rk29/board-rk29-k97.c index 2e5b1243e8b8..4c0493c8d479 100755 --- a/arch/arm/mach-rk29/board-rk29-k97.c +++ b/arch/arm/mach-rk29/board-rk29-k97.c @@ -1455,7 +1455,7 @@ static struct i2c_board_info __initdata board_i2c0_devices[] = { .flags = 0, }, #endif -#if defined (CONFIG_SND_SOC_alc5631) +#if defined (CONFIG_SND_SOC_RT5631) { .type = "rt5631", .addr = 0x1a, diff --git a/drivers/video/hdmi/hdmi-codec.c b/drivers/video/hdmi/hdmi-codec.c index 8a8a09e6f91d..49c824899e5e 100755 --- a/drivers/video/hdmi/hdmi-codec.c +++ b/drivers/video/hdmi/hdmi-codec.c @@ -1,5 +1,5 @@ #include -#ifdef CONFIG_SND_SOC_WM8900 +#if defined CONFIG_SND_SOC_WM8900 || defined CONFIG_SND_SOC_RT5631 /* sound/soc/codecs/wm8900.c */ extern void codec_set_spk(bool on); #else diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index bd370c66e76a..9f50f4f54a67 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -75,7 +75,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_WM8804 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8900 if I2C select SND_SOC_alc5621 if I2C - select SND_SOC_alc5631 if I2C + select SND_SOC_RT5631 if I2C select SND_SOC_RT5625 if I2C select SND_SOC_WM8903 if I2C select SND_SOC_WM8904 if I2C @@ -315,7 +315,7 @@ config SND_SOC_WM8900 config SND_SOC_alc5621 tristate -config SND_SOC_alc5631 +config SND_SOC_RT5631 tristate config SND_SOC_RT5625 diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index d4f5f1599532..b4bf7e53b76b 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -58,7 +58,7 @@ snd-soc-wm8776-objs := wm8776.o snd-soc-wm8804-objs := wm8804.o snd-soc-wm8900-objs := wm8900.o snd-soc-alc5621-objs := alc5621.o -snd-soc-alc5631-objs := rt5631.o +snd-soc-rt5631-objs := rt5631.o snd-soc-rt5625-objs := rt5625.o snd-soc-cs42l52-objs := cs42l52.o snd-soc-wm8903-objs := wm8903.o @@ -155,7 +155,7 @@ obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o obj-$(CONFIG_SND_SOC_WM8804) += snd-soc-wm8804.o obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o obj-$(CONFIG_SND_SOC_alc5621) += snd-soc-alc5621.o -obj-$(CONFIG_SND_SOC_alc5631) += snd-soc-alc5631.o +obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o obj-$(CONFIG_SND_SOC_RT5625) += snd-soc-rt5625.o obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 9b5d72587aa1..097b6cc7ef39 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -1,7 +1,7 @@ /* * rt5631.c -- RT5631 ALSA Soc Audio driver * - * Copyright 2009 Realtek Microelectronics + * Copyright 2011 Realtek Microelectronics * * Author: flove * @@ -35,189 +35,112 @@ #else #define DBG(x...) #endif - -#define RT5631_VERSION "0.02 alsa 1.0.21" -#define ALSA_SOC_VERSION "1.0.21" -static const u16 rt5631_reg[0x80]; -static int timesofbclk = 32; -module_param(timesofbclk, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); -MODULE_PARM_DESC(timeofbclk, "relationship between bclk and fs"); +#define RT5631_VERSION "0.01 alsa 1.0.24" #define RT5631_ALC_DAC_FUNC_ENA 0 //ALC functio for DAC #define RT5631_ALC_ADC_FUNC_ENA 1 //ALC function for ADC -#define RT5631_EQ_FUNC_ENA 1 #define RT5631_SPK_TIMER 1 //if enable this, MUST enable RT5631_EQ_FUNC_ENA first! - -#define VIRTUAL_POWER_CONTROL 0x90 -/* - * bit0: spkl amp power - * bit1: spkr amp power - * bit2: dmic flag - * bit[4~7] for EQ function - * bit[8] for dacl->hpl - * bit[9] for dacr->hpr - - * -*/ + struct rt5631_priv { + int codec_version; int master; int sysclk; - int dmic_used_flag; + int dmic_used_flag; + int eq_mode; + int pll_used_flag; }; #if (RT5631_SPK_TIMER == 1) static struct timer_list spk_timer; struct work_struct spk_work; static bool last_is_spk = false; // need modify. #endif -static unsigned int reg90; -static int rt5631_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int val); -static unsigned int rt5631_read(struct snd_soc_codec *codec, unsigned int reg); -#define rt5631_reset(c) rt5631_write(c, RT5631_RESET, 0) -//#define rt5631_write_mask(c, reg, val, mask) snd_soc_update_bits(c, reg, mask, val) -static int rt5631_reg_init(struct snd_soc_codec *codec); - -static struct snd_soc_device *rt5631_socdev; -/* - * read rt5631 register cache - */ -static inline unsigned int rt5631_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - if (reg < 1 || reg > (ARRAY_SIZE(rt5631_reg) + 1)) - return -1; - return cache[reg]; -} +static struct snd_soc_codec *rt5631_codec; +static const u16 rt5631_reg[0x80]; +static int timesofbclk = 32; -/* - * write rt5631 register cache - */ +module_param(timesofbclk, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(timeofbclk, "relationship between bclk and fs"); -static inline void rt5631_write_reg_cache(struct snd_soc_codec *codec, - unsigned int reg, unsigned int value) -{ - u16 *cache = codec->reg_cache; - if (reg < 0 || reg > 0x7e) - return; - cache[reg] = value; -} -static int rt5631_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int val) +static inline int rt5631_write(struct snd_soc_codec *codec, + unsigned int reg, unsigned int val) { - u8 data[3]; - - if (reg > 0x7e) { - if (reg == 0x90) - reg90 = val; - return 0; - } - - data[0] = reg; - data[1] = (0xff00 & val) >> 8; - data[2] = (0xff & val); - - if (codec->hw_write(codec->control_data, data, 3) == 3) { - rt5631_write_reg_cache(codec, reg, val); - DBG(KERN_INFO "%s reg=0x%x, val=0x%x\n", __func__, reg, val); - return 0; - } else { - DBG(KERN_ERR "%s failed\n", __func__); - return -EIO; - } + return snd_soc_write(codec, reg, val); } -static unsigned int rt5631_read(struct snd_soc_codec *codec, unsigned int reg) +static inline unsigned int rt5631_read(struct snd_soc_codec *codec, + unsigned int reg) { - u8 data[2] = {0}; - unsigned int value = 0x0; - - if (reg > 0x7e) { - if (reg == 0x90) - return reg90; - } - - data[0] = reg; - - i2c_master_reg8_recv(codec->control_data,reg,data,2,100 * 1000); - - value = (data[0]<<8) | data[1]; - - //DBG("rt5631_read reg%x=%x\n",reg,value); - - return value; + return snd_soc_read(codec, reg); } - -int rt5631_write_mask(struct snd_soc_codec *codec, unsigned int reg,unsigned int value,unsigned int mask) +static int rt5631_write_mask(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value, unsigned int mask) { - - unsigned char RetVal=0; - unsigned int CodecData; - -// DBG(KERN_INFO "rt5631_write_mask ok, reg = %x, value = %x ,mask= %x\n", reg, value,mask); + unsigned int reg_val; + int ret = 0; - if(!mask) - return 0; + if (!mask) + return 0; - if(mask!=0xffff) - { - CodecData=rt5631_read(codec,reg); - CodecData&=~mask; - CodecData|=(value&mask); - RetVal=rt5631_write(codec,reg,CodecData); - } - else - { - RetVal=rt5631_write(codec,reg,value); + if (mask != 0xffff) { + reg_val = rt5631_read(codec, reg); + reg_val &= ~mask; + reg_val |= (value & mask); + ret = rt5631_write(codec, reg, reg_val); + } else { + ret = rt5631_write(codec, reg, value); } - return RetVal; + return ret; } - -void rt5631_write_index(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) +static void rt5631_write_index(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value) { - - rt5631_write(codec,0x6a,reg); - rt5631_write(codec,0x6c,value); + rt5631_write(codec, RT5631_INDEX_ADD, reg); + rt5631_write(codec, RT5631_INDEX_DATA, value); + return; } -unsigned int rt5631_read_index(struct snd_soc_codec *codec, unsigned int reg) +static unsigned int rt5631_read_index(struct snd_soc_codec *codec, + unsigned int reg) { - unsigned int value = 0x0; - rt5631_write(codec,0x6a,reg); - value=rt5631_read(codec,0x6c); - + unsigned int value; + + rt5631_write(codec, RT5631_INDEX_ADD, reg); + value = rt5631_read(codec, RT5631_INDEX_DATA); + return value; } -void rt5631_write_index_mask(struct snd_soc_codec *codec, unsigned int reg,unsigned int value,unsigned int mask) +static void rt5631_write_index_mask(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value, unsigned int mask) { - -// unsigned char RetVal=0; - unsigned int CodecData; - -// DBG(KERN_INFO "rt5631_write_index_mask ok, reg = %x, value = %x ,mask= %x\n", reg, value,mask); + unsigned int reg_val; - if(!mask) - return; + if (!mask) + return; - if(mask!=0xffff) - { - CodecData=rt5631_read_index(codec,reg); - CodecData&=~mask; - CodecData|=(value&mask); - rt5631_write_index(codec,reg,CodecData); - } - else - { - rt5631_write_index(codec,reg,value); + if (mask != 0xffff) { + reg_val = rt5631_read_index(codec, reg); + reg_val &= ~mask; + reg_val |= (value & mask); + rt5631_write_index(codec, reg, reg_val); + } else { + rt5631_write_index(codec, reg, value); } + + return; +} + +static inline int rt5631_reset(struct snd_soc_codec *codec) +{ + return snd_soc_write(codec, RT5631_RESET, 0); } -struct rt5631_init_reg{ +struct rt5631_init_reg { u8 reg; u16 val; }; @@ -229,6 +152,21 @@ struct rt5631_init_reg{ #define DEF_VOL_SPK 0xc4 #endif +/* + * speaker channel volume select SPKMIXER, 0DB by default + * Headphone channel volume select OUTMIXER,0DB by default + * AXO1/AXO2 channel volume select OUTMIXER,0DB by default + * Record Mixer source from Mic1/Mic2 by default + * Mic1/Mic2 boost 40dB by default + * DAC_L-->OutMixer_L by default + * DAC_R-->OutMixer_R by default + * DAC-->SpeakerMixer + * Speaker volume-->SPOMixer(L-->L,R-->R) + * Speaker AMP ratio gain is 1.44X + * HP from OutMixer,speaker out from SpeakerOut Mixer + * enable HP zero cross + * change Mic1 & mic2 to differential mode + */ static struct rt5631_init_reg init_list[] = { {RT5631_SPK_OUT_VOL , (DEF_VOL_SPK<<8) | DEF_VOL_SPK}, //speaker channel volume select SPKMIXER,0DB by default @@ -264,19 +202,16 @@ static struct rt5631_init_reg init_list[] = { // {RT5631_JACK_DET_CTRL , 0x4e80}, //Jack detect for GPIO,high is HP,low is speaker {RT5631_JACK_DET_CTRL , 0x4bc0}, //Jack detect for GPIO,high is speaker,low is hp }; +#define RT5631_INIT_REG_LEN ARRAY_SIZE(init_list) -#define RT5631_INIT_REG_LEN ARRAY_SIZE(init_list) - -//************************************************************************************************* -//************************************************************************************************* -#if (RT5631_EQ_FUNC_ENA==1) -//EQ parameter -enum -{ - NORMAL=0, +/* + * EQ parameter + */ +enum { + NORMAL, CLUB, DANCE, - LIVE, + LIVE, POP, ROCK, OPPO, @@ -286,190 +221,188 @@ enum SPK_FR }; -typedef struct _HW_EQ_PRESET -{ - u16 HwEqType; - u16 EqValue[22]; - u16 HwEQCtrl; - -}HW_EQ_PRESET; - - -HW_EQ_PRESET HwEq_Preset[]={ -/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x6e*/ - {NORMAL,{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x0000}, - {CLUB ,{0x1C10,0x0000,0xC1CC,0x1E5D,0x0699,0xCD48,0x188D,0x0699,0xC3B6,0x1CD0,0x0699,0x0436,0x0000,0x0000,0x0000,0x0000},0x000E}, - {DANCE ,{0x1F2C,0x095B,0xC071,0x1F95,0x0616,0xC96E,0x1B11,0xFC91,0xDCF2,0x1194,0xFAF2,0x0436,0x0000,0x0000,0x0000,0x0000},0x000F}, - {LIVE ,{0x1EB5,0xFCB6,0xC24A,0x1DF8,0x0E7C,0xC883,0x1C10,0x0699,0xDA41,0x1561,0x0295,0x0436,0x0000,0x0000,0x0000,0x0000},0x000F}, - {POP ,{0x1EB5,0xFCB6,0xC1D4,0x1E5D,0x0E23,0xD92E,0x16E6,0xFCB6,0x0000,0x0969,0xF988,0x0436,0x0000,0x0000,0x0000,0x0000},0x000F}, - {ROCK ,{0x1EB5,0xFCB6,0xC071,0x1F95,0x0424,0xC30A,0x1D27,0xF900,0x0C5D,0x0FC7,0x0E23,0x0436,0x0000,0x0000,0x0000,0x0000},0x000F}, - {OPPO ,{0x0000,0x0000,0xCA4A,0x17F8,0x0FEC,0xCA4A,0x17F8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x000F}, - {TREBLE,{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x188D,0x1699,0x0000,0x0000,0x0000},0x0010}, - {BASS ,{0x1A43,0x0C00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},0x0001}, - {HFREQ, {0x1BBC,0x0000,0xC9A4,0x1BBC,0x0000,0x2997,0x142D,0xFCB6,0xEF01,0x1BBC,0x0000,0xE835,0x0FEC,0xC66E,0x1A29,0x1CEE},0x0014}, - {SPK_FR,{0x1CD4,0xF405,0xe0bf,0x0f9e,0xfa19,0x07CA,0x12AF,0xF805,0xE904,0x1C10,0x0000,0x1C8B,0x0000,0xc5e1,0x1afb,0x1d46},0x0090}, +struct hw_eq_preset { + u16 type; + u16 value[22]; + u16 ctrl; +}; + +/* + * EQ param reg : 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + * 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf + * EQ control reg : 0x6e + */ +struct hw_eq_preset hweq_preset[] = { + {NORMAL , {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000}, 0x0000}, + {CLUB , {0x1C10, 0x0000, 0xC1CC, 0x1E5D, 0x0699, 0xCD48, + 0x188D, 0x0699, 0xC3B6, 0x1CD0, 0x0699, 0x0436, + 0x0000, 0x0000, 0x0000, 0x0000}, 0x000E}, + {DANCE , {0x1F2C, 0x095B, 0xC071, 0x1F95, 0x0616, 0xC96E, + 0x1B11, 0xFC91, 0xDCF2, 0x1194, 0xFAF2, 0x0436, + 0x0000, 0x0000, 0x0000, 0x0000}, 0x000F}, + {LIVE , {0x1EB5, 0xFCB6, 0xC24A, 0x1DF8, 0x0E7C, 0xC883, + 0x1C10, 0x0699, 0xDA41, 0x1561, 0x0295, 0x0436, + 0x0000, 0x0000, 0x0000, 0x0000}, 0x000F}, + {POP , {0x1EB5, 0xFCB6, 0xC1D4, 0x1E5D, 0x0E23, 0xD92E, + 0x16E6, 0xFCB6, 0x0000, 0x0969, 0xF988, 0x0436, + 0x0000, 0x0000, 0x0000, 0x0000}, 0x000F}, + {ROCK , {0x1EB5, 0xFCB6, 0xC071, 0x1F95, 0x0424, 0xC30A, + 0x1D27, 0xF900, 0x0C5D, 0x0FC7, 0x0E23, 0x0436, + 0x0000, 0x0000, 0x0000, 0x0000}, 0x000F}, + {OPPO , {0x0000, 0x0000, 0xCA4A, 0x17F8, 0x0FEC, 0xCA4A, + 0x17F8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000}, 0x000F}, + {TREBLE , {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x188D, + 0x1699, 0x0000, 0x0000, 0x0000}, 0x0010}, + {BASS , {0x1A43, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000}, 0x0001}, }; -#endif -//************************************************************************************************* -//************************************************************************************************* static int rt5631_reg_init(struct snd_soc_codec *codec) { int i; - for (i = 0; i < RT5631_INIT_REG_LEN; i ++) { - rt5631_write(codec, init_list[i].reg, init_list[i].val); - } - + for (i = 0; i < RT5631_INIT_REG_LEN; i++) + rt5631_write(codec, init_list[i].reg, init_list[i].val); + return 0; } -static const char *rt5631_spol_source_sel[] = {"SPOLMIX", "MONOIN_RX", "VDAC", "DACL"}; -static const char *rt5631_spor_source_sel[] = {"SPORMIX", "MONOIN_RX", "VDAC", "DACR"}; +static const char *rt5631_spol_source_sel[] = { + "SPOLMIX", "MONOIN_RX", "VDAC", "DACL"}; +static const char *rt5631_spor_source_sel[] = { + "SPORMIX", "MONOIN_RX", "VDAC", "DACR"}; static const char *rt5631_mono_source_sel[] = {"MONOMIX", "MONOIN_RX", "VDAC"}; -static const char *rt5631_input_mode_source_sel[] = {"Single-end", "Differential"}; -static const char *rt5631_mic_boost[] = {"Bypass", "+20db", "+24db", "+30db", +static const char *rt5631_input_mode_source_sel[] = { + "Single-end", "Differential"}; +static const char *rt5631_mic_boost[] = {"Bypass", "+20db", "+24db", "+30db", "+35db", "+40db", "+44db", "+50db", "+52db"}; -#if (RT5631_EQ_FUNC_ENA==1) -static const char *rt5631_eq_sel[] = {"NORMAL", "CLUB","DANCE", "LIVE","POP", - "ROCK", "OPPO", "TREBLE", "BASS"}; -#endif +static const char *rt5631_hpl_source_sel[] = {"LEFT HPVOL", "LEFT DAC"}; +static const char *rt5631_hpr_source_sel[] = {"RIGHT HPVOL", "RIGHT DAC"}; +static const char *rt5631_eq_sel[] = {"NORMAL", "CLUB", "DANCE", "LIVE", "POP", + "ROCK", "OPPO", "TREBLE", "BASS"}; -static const char *rt5631_hpl_source_sel[] = {"LEFT HPVOL","LEFT DAC"}; -static const char *rt5631_hpr_source_sel[] = {"RIGHT HPVOL","RIGHT DAC"}; static const struct soc_enum rt5631_enum[] = { -SOC_ENUM_SINGLE(RT5631_SPK_MONO_HP_OUT_CTRL, 14, 4, rt5631_spol_source_sel), /*0*/ -SOC_ENUM_SINGLE(RT5631_SPK_MONO_HP_OUT_CTRL, 10, 4, rt5631_spor_source_sel), /*1*/ -SOC_ENUM_SINGLE(RT5631_SPK_MONO_HP_OUT_CTRL, 6, 3, rt5631_mono_source_sel), /*2*/ -SOC_ENUM_SINGLE(RT5631_MIC_CTRL_1, 15, 2, rt5631_input_mode_source_sel), /*3*/ -SOC_ENUM_SINGLE(RT5631_MIC_CTRL_1, 7, 2, rt5631_input_mode_source_sel), /*4*/ -SOC_ENUM_SINGLE(RT5631_MONO_INPUT_VOL, 15, 2, rt5631_input_mode_source_sel), /*5*/ -SOC_ENUM_SINGLE(RT5631_MIC_CTRL_2, 12, 9, rt5631_mic_boost), /*6*/ -SOC_ENUM_SINGLE(RT5631_MIC_CTRL_2, 8, 9, rt5631_mic_boost), /*7*/ -SOC_ENUM_SINGLE(RT5631_SPK_MONO_HP_OUT_CTRL, 3, 2, rt5631_hpl_source_sel), /*8*/ -SOC_ENUM_SINGLE(RT5631_SPK_MONO_HP_OUT_CTRL, 2, 2, rt5631_hpr_source_sel), /*9*/ -#if (RT5631_EQ_FUNC_ENA==1) -SOC_ENUM_SINGLE(VIRTUAL_POWER_CONTROL, 4, 9, rt5631_eq_sel), /*10*/ -#endif +SOC_ENUM_SINGLE(RT5631_SPK_MONO_HP_OUT_CTRL, 14, 4, rt5631_spol_source_sel), +SOC_ENUM_SINGLE(RT5631_SPK_MONO_HP_OUT_CTRL, 10, 4, rt5631_spor_source_sel), +SOC_ENUM_SINGLE(RT5631_SPK_MONO_HP_OUT_CTRL, 6, 3, rt5631_mono_source_sel), +SOC_ENUM_SINGLE(RT5631_MIC_CTRL_1, 15, 2, rt5631_input_mode_source_sel), +SOC_ENUM_SINGLE(RT5631_MIC_CTRL_1, 7, 2, rt5631_input_mode_source_sel), +SOC_ENUM_SINGLE(RT5631_MONO_INPUT_VOL, 15, 2, rt5631_input_mode_source_sel), +SOC_ENUM_SINGLE(RT5631_MIC_CTRL_2, 12, 9, rt5631_mic_boost), +SOC_ENUM_SINGLE(RT5631_MIC_CTRL_2, 8, 9, rt5631_mic_boost), +SOC_ENUM_SINGLE(RT5631_SPK_MONO_HP_OUT_CTRL, 3, 2, rt5631_hpl_source_sel), +SOC_ENUM_SINGLE(RT5631_SPK_MONO_HP_OUT_CTRL, 2, 2, rt5631_hpr_source_sel), +SOC_ENUM_SINGLE(0, 4, 9, rt5631_eq_sel), }; -static int rt5631_dmic_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int rt5631_dmic_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int val; + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = rt5631->dmic_used_flag; - val = rt5631_read(codec, VIRTUAL_POWER_CONTROL) & 0x0004; - val >>= 2; - ucontrol->value.integer.value[0] = val; return 0; } -static void rt5631_close_dmic(struct snd_soc_codec *codec) //disable DMic to ADC filter +static void rt5631_close_dmic(struct snd_soc_codec *codec) { - rt5631_write_mask(codec, RT5631_DIG_MIC_CTRL, DMIC_L_CH_MUTE | DMIC_R_CH_MUTE, DMIC_L_CH_MUTE_MASK | DMIC_R_CH_MUTE_MASK); - - rt5631_write_mask(codec, RT5631_DIG_MIC_CTRL, DMIC_DIS, DMIC_ENA_MASK); + rt5631_write_mask(codec, RT5631_DIG_MIC_CTRL, + DMIC_L_CH_MUTE | DMIC_R_CH_MUTE, + DMIC_L_CH_MUTE_MASK | DMIC_R_CH_MUTE_MASK); + rt5631_write_mask(codec, RT5631_DIG_MIC_CTRL, + DMIC_DIS, DMIC_ENA_MASK); + return; } -static int rt5631_dmic_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int rt5631_dmic_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int old, new; - struct rt5631_priv *rt5631 = codec->private_data; - - old = rt5631_read(codec, VIRTUAL_POWER_CONTROL) & 0x0004; - new = ucontrol->value.integer.value[0] << 2; + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); - if (old == new) + if (rt5631->dmic_used_flag == ucontrol->value.integer.value[0]) return 0; - rt5631_write_mask(codec, VIRTUAL_POWER_CONTROL, new, 0x0004); - - if (new) + if (ucontrol->value.integer.value[0]) { rt5631->dmic_used_flag = 1; - else - { + } else { rt5631_close_dmic(codec); - rt5631->dmic_used_flag=0; + rt5631->dmic_used_flag = 0; } return 0; } +static int rt5631_eq_sel_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = rt5631->eq_mode; -//************************************************************************************************* -//for EQ function -//************************************************************************************************* -#if (RT5631_EQ_FUNC_ENA==1) + return 0; +} static void rt5631_update_eqmode(struct snd_soc_codec *codec, int mode) { - u16 HwEqIndex=0; - - rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD1, 0x8380, 0x8380); + int i; - if(mode==NORMAL) - { - /*clear EQ parameter*/ - for(HwEqIndex=0;HwEqIndex<=0x0f;HwEqIndex++) - { - rt5631_write_index(codec, HwEqIndex, HwEq_Preset[mode].EqValue[HwEqIndex]); - } - - rt5631_write_mask(codec,0x6e,0x0000,0x003f); //disable Hardware LP,BP1,BP2,BP3,HP1,HP2 block Control - - rt5631_write_index_mask(codec,0x11,0x0000,0x8000); /*disable EQ block*/ + if (NORMAL == mode) { + /* In Normal mode, the EQ parameter is cleared, + * and hardware LP, BP1, BP2, BP3, HP1, HP2 + * block control and EQ block are disabled. + */ + for (i = RT5631_EQ_BW_LOP; i <= RT5631_EQ_HPF_GAIN; i++) + rt5631_write_index(codec, i, + hweq_preset[mode].value[i]); + rt5631_write_mask(codec, RT5631_EQ_CTRL, 0x0000, 0x003f); + rt5631_write_index_mask(codec, RT5631_EQ_PRE_VOL_CTRL + , 0x0000, 0x8000); + } else { + /* Fill and update EQ parameter, + * and EQ block are enabled. + */ + rt5631_write_index_mask(codec, RT5631_EQ_PRE_VOL_CTRL + , 0x8000, 0x8000); + rt5631_write(codec, RT5631_EQ_CTRL, + hweq_preset[mode].ctrl); + for (i = RT5631_EQ_BW_LOP; i <= RT5631_EQ_HPF_GAIN; i++) + rt5631_write_index(codec, i, + hweq_preset[mode].value[i]); + rt5631_write_mask(codec, RT5631_EQ_CTRL, 0x4000, 0x4000); } - else - { - rt5631_write_index_mask(codec,0x11,0x8000,0x8000); /*enable EQ block*/ - - rt5631_write(codec,0x6e,HwEq_Preset[mode].HwEQCtrl); - /*Fill EQ parameter*/ - for(HwEqIndex=0;HwEqIndex<=0x0f;HwEqIndex++) - { - rt5631_write_index(codec, HwEqIndex,HwEq_Preset[mode].EqValue[HwEqIndex]); - } - //update EQ parameter - rt5631_write_mask(codec, 0x6e,0x4000,0x4000); - } + return; } - -static int rt5631_eq_sel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int rt5631_eq_sel_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned short val; - unsigned short mask, bitmask; + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); - for (bitmask = 1; bitmask < e->max; bitmask <<= 1) - ; - if (ucontrol->value.enumerated.item[0] > e->max - 1) - return -EINVAL; - val = ucontrol->value.enumerated.item[0] << e->shift_l; - mask = (bitmask - 1) << e->shift_l; - if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) - return -EINVAL; - val |= ucontrol->value.enumerated.item[1] << e->shift_r; - mask |= (bitmask - 1) << e->shift_r; - } - - snd_soc_update_bits(codec, e->reg, mask, val); + if (rt5631->eq_mode == ucontrol->value.integer.value[0]) + return 0; - DBG( "value=%d\n", ucontrol->value.enumerated.item[0]); rt5631_update_eqmode(codec, ucontrol->value.enumerated.item[0]); + rt5631->eq_mode = ucontrol->value.integer.value[0]; + return 0; } -#endif + #if (RT5631_SPK_TIMER == 1) static void spk_work_handler(struct work_struct *work) { - struct snd_soc_device *socdev = rt5631_socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rt5631_codec; bool is_spk = (rt5631_read(codec, 0x4a)) & 0x04; //detect rt5631 reg4a[3], 1'b:SPK, 0'b:HP ; if(last_is_spk != is_spk) printk("%s---%s is in use.last is %s in use\n", __FUNCTION__,is_spk?"speaker":"headphone",last_is_spk?"speaker":"headphone"); @@ -499,62 +432,30 @@ void spk_timer_callback(unsigned long data ) if (ret) printk("Error in mod_timer\n"); } #endif -//************************************************************************************************* -//************************************************************************************************* static const struct snd_kcontrol_new rt5631_snd_controls[] = { -SOC_ENUM("MIC1 Mode Control", rt5631_enum[3]), +SOC_ENUM("MIC1 Mode Control", rt5631_enum[3]), SOC_ENUM("MIC1 Boost", rt5631_enum[6]), - SOC_ENUM("MIC2 Mode Control", rt5631_enum[4]), SOC_ENUM("MIC2 Boost", rt5631_enum[7]), SOC_ENUM("MONOIN Mode Control", rt5631_enum[5]), - SOC_DOUBLE("PCM Playback Volume", RT5631_STEREO_DAC_VOL_2, 8, 0, 255, 1), -SOC_DOUBLE("PCM Playback Switch", RT5631_STEREO_DAC_VOL_1,15, 7, 1, 1), - +SOC_DOUBLE("PCM Playback Switch", RT5631_STEREO_DAC_VOL_1, 15, 7, 1, 1), SOC_DOUBLE("MONOIN_RX Capture Volume", RT5631_MONO_INPUT_VOL, 8, 0, 31, 1), - SOC_DOUBLE("AXI Capture Volume", RT5631_AUX_IN_VOL, 8, 0, 31, 1), - SOC_SINGLE("AXO1 Playback Switch", RT5631_MONO_AXO_1_2_VOL, 15, 1, 1), SOC_SINGLE("AXO2 Playback Switch", RT5631_MONO_AXO_1_2_VOL, 7, 1, 1), SOC_DOUBLE("OUTVOL Playback Volume", RT5631_MONO_AXO_1_2_VOL, 8, 0, 31, 1), - -SOC_DOUBLE("Speaker Playback Switch", RT5631_SPK_OUT_VOL,15, 7, 1, 1), +SOC_DOUBLE("Speaker Playback Switch", RT5631_SPK_OUT_VOL, 15, 7, 1, 1), SOC_DOUBLE("Speaker Playback Volume", RT5631_SPK_OUT_VOL, 8, 0, 63, 1), - SOC_SINGLE("MONO Playback Switch", RT5631_MONO_AXO_1_2_VOL, 13, 1, 1), - -SOC_DOUBLE("HP Playback Switch", RT5631_HP_OUT_VOL,15, 7, 1, 1), +SOC_DOUBLE("HP Playback Switch", RT5631_HP_OUT_VOL, 15, 7, 1, 1), SOC_DOUBLE("HP Playback Volume", RT5631_HP_OUT_VOL, 8, 0, 63, 1), - -//SOC_SINGLE_EXT("HIFI Loopback", ),/*not finished*/ -//SOC_SINGLE_EXT("Voice Loopback", ), /*not finished*/ -SOC_SINGLE_EXT("DMIC Capture Switch", VIRTUAL_POWER_CONTROL, 2, 1, 0, +SOC_SINGLE_EXT("DMIC Capture Switch", 0, 2, 1, 0, rt5631_dmic_get, rt5631_dmic_put), - -#if (RT5631_EQ_FUNC_ENA==1) -SOC_ENUM_EXT("EQ Mode", rt5631_enum[10], snd_soc_get_enum_double, rt5631_eq_sel_put), -#endif +SOC_ENUM_EXT("EQ Mode", rt5631_enum[10], rt5631_eq_sel_get, rt5631_eq_sel_put), }; -static int rt5631_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(rt5631_snd_controls); i ++) { - - err = snd_ctl_add(codec->card, - snd_soc_cnew(&rt5631_snd_controls[i], - codec, NULL)); - if (err < 0) - return err; - } - - return 0; -} - static const struct snd_kcontrol_new rt5631_recmixl_mixer_controls[] = { SOC_DAPM_SINGLE("OUTMIXL Capture Switch", RT5631_ADC_REC_MIXER, 15, 1, 1), SOC_DAPM_SINGLE("MIC1_BST1 Capture Switch", RT5631_ADC_REC_MIXER, 14, 1, 1), @@ -569,12 +470,11 @@ SOC_DAPM_SINGLE("MIC2_BST2 Capture Switch", RT5631_ADC_REC_MIXER, 6, 1, 1), SOC_DAPM_SINGLE("OUTMIXR Capture Switch", RT5631_ADC_REC_MIXER, 7, 1, 1), }; - static const struct snd_kcontrol_new rt5631_spkmixl_mixer_controls[] = { SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_SPK_MIXER_CTRL, 15, 1, 1), -SOC_DAPM_SINGLE("MIC1_P Playback Switch", RT5631_SPK_MIXER_CTRL, 14, 1, 1), +SOC_DAPM_SINGLE("MIC1_P Playback Switch", RT5631_SPK_MIXER_CTRL, 14, 1, 1), SOC_DAPM_SINGLE("DACL Playback Switch", RT5631_SPK_MIXER_CTRL, 13, 1, 1), -SOC_DAPM_SINGLE("OUTMIXL Playback Switch", RT5631_SPK_MIXER_CTRL, 12, 1, 1) +SOC_DAPM_SINGLE("OUTMIXL Playback Switch", RT5631_SPK_MIXER_CTRL, 12, 1, 1), }; static const struct snd_kcontrol_new rt5631_spkmixr_mixer_controls[] = { @@ -593,7 +493,7 @@ SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_OUTMIXER_L_CTRL, 11, 1, 1), SOC_DAPM_SINGLE("MONOIN_RXP Playback Switch", RT5631_OUTMIXER_L_CTRL, 10, 1, 1), SOC_DAPM_SINGLE("AXILVOL Playback Switch", RT5631_OUTMIXER_L_CTRL, 9, 1, 1), SOC_DAPM_SINGLE("AXIRVOL Playback Switch", RT5631_OUTMIXER_L_CTRL, 8, 1, 1), -SOC_DAPM_SINGLE("VDAC Playback Switch", RT5631_OUTMIXER_L_CTRL, 7, 1, 1) +SOC_DAPM_SINGLE("VDAC Playback Switch", RT5631_OUTMIXER_L_CTRL, 7, 1, 1), }; static const struct snd_kcontrol_new rt5631_outmixr_mixer_controls[] = { @@ -602,60 +502,55 @@ SOC_DAPM_SINGLE("AXIRVOL Playback Switch", RT5631_OUTMIXER_R_CTRL, 8, 1, 1), SOC_DAPM_SINGLE("AXILVOL Playback Switch", RT5631_OUTMIXER_R_CTRL, 9, 1, 1), SOC_DAPM_SINGLE("MONOIN_RXN Playback Switch", RT5631_OUTMIXER_R_CTRL, 10, 1, 1), SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_OUTMIXER_R_CTRL, 11, 1, 1), -SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_OUTMIXER_R_CTRL, 12, 1, 1), +SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_OUTMIXER_R_CTRL, 12, 1, 1), SOC_DAPM_SINGLE("DACR Playback Switch", RT5631_OUTMIXER_R_CTRL, 13, 1, 1), SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_OUTMIXER_R_CTRL, 14, 1, 1), SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_OUTMIXER_R_CTRL, 15, 1, 1), }; - static const struct snd_kcontrol_new rt5631_AXO1MIX_mixer_controls[] = { SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_AXO1MIXER_CTRL, 15 , 1, 1), -SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_AXO1MIXER_CTRL, 11, 1, 1), -SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_AXO1MIXER_CTRL, 7 ,1 ,1), +SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_AXO1MIXER_CTRL, 11, 1, 1), +SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_AXO1MIXER_CTRL, 7 , 1 , 1), SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_AXO1MIXER_CTRL, 6, 1, 1), }; - static const struct snd_kcontrol_new rt5631_AXO2MIX_mixer_controls[] = { SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_AXO2MIXER_CTRL, 15, 1, 1), -SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_AXO2MIXER_CTRL, 11, 1, 1), +SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_AXO2MIXER_CTRL, 11, 1, 1), SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_AXO2MIXER_CTRL, 7, 1, 1), -SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_AXO2MIXER_CTRL, 6, 1 ,1), +SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_AXO2MIXER_CTRL, 6, 1 , 1), }; static const struct snd_kcontrol_new rt5631_spolmix_mixer_controls[] = { SOC_DAPM_SINGLE("SPKVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL, 15, 1, 1), -SOC_DAPM_SINGLE("SPKVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL, 14, 1, 1), +SOC_DAPM_SINGLE("SPKVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL, 14, 1, 1), }; - static const struct snd_kcontrol_new rt5631_spormix_mixer_controls[] = { SOC_DAPM_SINGLE("SPKVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL, 13, 1, 1), SOC_DAPM_SINGLE("SPKVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL, 12, 1, 1), }; - static const struct snd_kcontrol_new rt5631_monomix_mixer_controls[] = { SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL, 11, 1, 1), SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL, 10, 1, 1), }; - -static const struct snd_kcontrol_new rt5631_spol_mux_control = +static const struct snd_kcontrol_new rt5631_spol_mux_control = SOC_DAPM_ENUM("Route", rt5631_enum[0]); -static const struct snd_kcontrol_new rt5631_spor_mux_control = +static const struct snd_kcontrol_new rt5631_spor_mux_control = SOC_DAPM_ENUM("Route", rt5631_enum[1]); -static const struct snd_kcontrol_new rt5631_mono_mux_control = +static const struct snd_kcontrol_new rt5631_mono_mux_control = SOC_DAPM_ENUM("Route", rt5631_enum[2]); -static const struct snd_kcontrol_new rt5631_hpl_mux_control = +static const struct snd_kcontrol_new rt5631_hpl_mux_control = SOC_DAPM_ENUM("Route", rt5631_enum[8]); -static const struct snd_kcontrol_new rt5631_hpr_mux_control = +static const struct snd_kcontrol_new rt5631_hpr_mux_control = SOC_DAPM_ENUM("Route", rt5631_enum[9]); //ALC for DAC function -#if (RT5631_ALC_DAC_FUNC_ENA==1) +#if (RT5631_ALC_DAC_FUNC_ENA == 1) static void rt5631_alc_enable(struct snd_soc_codec *codec,unsigned int EnableALC) { if(EnableALC) @@ -677,323 +572,572 @@ static void rt5631_alc_enable(struct snd_soc_codec *codec,unsigned int EnableALC } #endif -static int spk_event(struct snd_soc_dapm_widget *w, + +static int spk_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; - unsigned int l, r; - - l = rt5631_read(codec, VIRTUAL_POWER_CONTROL) & 0x0001; - r = (rt5631_read(codec, VIRTUAL_POWER_CONTROL) & 0x0002) >> 1; - + static int spkl_out_enable, spkr_out_enable; + switch (event) { - case SND_SOC_DAPM_POST_PMD: - DBG("spk_event --SND_SOC_DAPM_POST_PMD\n"); - rt5631_write_mask(codec, RT5631_SPK_OUT_VOL, 0x8080, 0x8080); - - if ((l == 0) && (r == 0)) - rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD1, 0x0000, 0x1000); - - rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD4, 0x0000, 0xC000); -#if (RT5631_ALC_DAC_FUNC_ENA==1) - rt5631_alc_enable(codec,0); -#endif - - break; case SND_SOC_DAPM_POST_PMU: - DBG("spk_event --SND_SOC_DAPM_POST_PMU \n"); -#if (RT5631_ALC_DAC_FUNC_ENA==1) - rt5631_alc_enable(codec,1); + +#if (RT5631_ALC_DAC_FUNC_ENA == 1) + rt5631_alc_enable(codec, 1); #endif - if ((l != 0) || (r != 0)) - rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD1, 0x1000, 0x1000); - rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD4, 0xC000, 0xC000); - rt5631_write_mask(codec, RT5631_SPK_OUT_VOL, 0x0000, 0x8080); + + if (!spkl_out_enable && !strcmp(w->name, "SPKL Amp")) { + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD4, + PWR_SPK_L_VOL, PWR_SPK_L_VOL); + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD1, + PWR_CLASS_D, PWR_CLASS_D); + rt5631_write_mask(codec, RT5631_SPK_OUT_VOL, + 0, RT_L_MUTE); + spkl_out_enable = 1; + } + if (!spkr_out_enable && !strcmp(w->name, "SPKR Amp")) { + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD4, + PWR_SPK_R_VOL, PWR_SPK_R_VOL); + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD1, + PWR_CLASS_D, PWR_CLASS_D); + rt5631_write_mask(codec, RT5631_SPK_OUT_VOL, + 0, RT_R_MUTE); + spkr_out_enable = 1; + } break; - default: - return -EINVAL; - } - - return 0; -} + case SND_SOC_DAPM_POST_PMD: + if (spkl_out_enable && !strcmp(w->name, "SPKL Amp")) { + rt5631_write_mask(codec, RT5631_SPK_OUT_VOL, + RT_L_MUTE, RT_L_MUTE); + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD4, + 0, PWR_SPK_L_VOL); + spkl_out_enable = 0; + } + if (spkr_out_enable && !strcmp(w->name, "SPKR Amp")) { + rt5631_write_mask(codec, RT5631_SPK_OUT_VOL, + RT_R_MUTE, RT_R_MUTE); + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD4, + 0, PWR_SPK_R_VOL); + spkr_out_enable = 0; + } + if (0 == spkl_out_enable && 0 == spkr_out_enable) + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD1, + 0, PWR_CLASS_D); -static void hp_depop2(struct snd_soc_codec *codec,unsigned int EnableHPOut) -{ +#if (RT5631_ALC_DAC_FUNC_ENA == 1) + rt5631_alc_enable(codec, 0); +#endif - unsigned int SoftVol,HPZeroCross; + break; - SoftVol = rt5631_read(codec, RT5631_SOFT_VOL_CTRL); - rt5631_write(codec,RT5631_SOFT_VOL_CTRL,0); - HPZeroCross=rt5631_read(codec, RT5631_INT_ST_IRQ_CTRL_2); - rt5631_write(codec,RT5631_INT_ST_IRQ_CTRL_2,HPZeroCross&0xf7ff); //disable Zero Cross of HP - //enable HP out - if(EnableHPOut) - { - - rt5631_write_index(codec,0x56,0x303e); - - rt5631_write_mask(codec,RT5631_PWR_MANAG_ADD3,PWR_CHARGE_PUMP|PWR_HP_L_AMP|PWR_HP_R_AMP - ,PWR_CHARGE_PUMP|PWR_HP_L_AMP|PWR_HP_R_AMP); - rt5631_write(codec,RT5631_DEPOP_FUN_CTRL_1,POW_ON_SOFT_GEN|EN_DEPOP2_FOR_HP); - schedule_timeout_uninterruptible(msecs_to_jiffies(100)); - rt5631_write_mask(codec,RT5631_PWR_MANAG_ADD3,PWR_HP_DEPOP_DIS/*|PWR_HP_AMP_DRIVING*/,PWR_HP_DEPOP_DIS/*|PWR_HP_AMP_DRIVING*/); - } - else //disable HP out - { - rt5631_write_index(codec,0x56,0x303F); - rt5631_write(codec,RT5631_DEPOP_FUN_CTRL_1,POW_ON_SOFT_GEN|EN_MUTE_UNMUTE_DEPOP|PD_HPAMP_L_ST_UP|PD_HPAMP_R_ST_UP); - schedule_timeout_uninterruptible(msecs_to_jiffies(75)); - rt5631_write(codec,RT5631_DEPOP_FUN_CTRL_1,POW_ON_SOFT_GEN|PD_HPAMP_L_ST_UP|PD_HPAMP_R_ST_UP); - rt5631_write_mask(codec,RT5631_PWR_MANAG_ADD3,0,PWR_HP_DEPOP_DIS/*|PWR_HP_AMP_DRIVING*/); - rt5631_write(codec,RT5631_DEPOP_FUN_CTRL_1,POW_ON_SOFT_GEN|EN_DEPOP2_FOR_HP|PD_HPAMP_L_ST_UP|PD_HPAMP_R_ST_UP); - schedule_timeout_uninterruptible(msecs_to_jiffies(80)); - rt5631_write(codec,RT5631_DEPOP_FUN_CTRL_1,POW_ON_SOFT_GEN); - rt5631_write_mask(codec,RT5631_PWR_MANAG_ADD3,0,PWR_CHARGE_PUMP|PWR_HP_L_AMP|PWR_HP_R_AMP); + default: + return 0; } - - rt5631_write(codec,RT5631_SOFT_VOL_CTRL,SoftVol); - rt5631_write(codec,RT5631_INT_ST_IRQ_CTRL_2,HPZeroCross); + return 0; } -static void HP_Mute_Unmute_Depop(struct snd_soc_codec *codec,unsigned int EnableHPOut) + +static void hp_depop_mode2_onebit(struct snd_soc_codec *codec, int enable) { + unsigned int soft_vol, hp_zc; + + rt5631_write_mask(codec, RT5631_DEPOP_FUN_CTRL_2, 0, EN_ONE_BIT_DEPOP); + + soft_vol = rt5631_read(codec, RT5631_SOFT_VOL_CTRL); + rt5631_write(codec, RT5631_SOFT_VOL_CTRL, 0); + hp_zc = rt5631_read(codec, RT5631_INT_ST_IRQ_CTRL_2); + rt5631_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); + if (enable) { + rt5631_write_index(codec, RT5631_TEST_MODE_CTRL, 0x84c0); + rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x309f); + rt5631_write_index(codec, RT5631_CP_INTL_REG2, 0x6530); + rt5631_write(codec, RT5631_DEPOP_FUN_CTRL_2, + EN_CAP_FREE_DEPOP); + } else { + rt5631_write(codec, RT5631_DEPOP_FUN_CTRL_2, 0); + schedule_timeout_uninterruptible(msecs_to_jiffies(100)); + } - unsigned int SoftVol,HPZeroCross; - - DBG("%s: %d\n", __func__, EnableHPOut); + rt5631_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol); + rt5631_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc); - SoftVol = rt5631_read(codec, RT5631_SOFT_VOL_CTRL); - rt5631_write(codec,RT5631_SOFT_VOL_CTRL,0); - HPZeroCross=rt5631_read(codec, RT5631_INT_ST_IRQ_CTRL_2); - rt5631_write(codec,RT5631_INT_ST_IRQ_CTRL_2,HPZeroCross&0xf7ff); //disable Zero Cross of HP + return; +} - if(EnableHPOut) //unmute HP out - { +static void hp_mute_unmute_depop_onebit(struct snd_soc_codec *codec, int enable) +{ + unsigned int soft_vol, hp_zc; + + rt5631_write_mask(codec, RT5631_DEPOP_FUN_CTRL_2, 0, EN_ONE_BIT_DEPOP); + soft_vol = rt5631_read(codec, RT5631_SOFT_VOL_CTRL); + rt5631_write(codec, RT5631_SOFT_VOL_CTRL, 0); + hp_zc = rt5631_read(codec, RT5631_INT_ST_IRQ_CTRL_2); + rt5631_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); + if (enable) { schedule_timeout_uninterruptible(msecs_to_jiffies(10)); - rt5631_write_index(codec,0x56,0x302f); - rt5631_write(codec,RT5631_DEPOP_FUN_CTRL_1,POW_ON_SOFT_GEN|EN_MUTE_UNMUTE_DEPOP|EN_HP_R_M_UN_MUTE_DEPOP|EN_HP_L_M_UN_MUTE_DEPOP); - rt5631_write_mask(codec,RT5631_HP_OUT_VOL,0x0000,0x8080); - schedule_timeout_uninterruptible(msecs_to_jiffies(160)); - - } - else //mute HP out - { - rt5631_write_index(codec,0x56,0x302f); - rt5631_write(codec,RT5631_DEPOP_FUN_CTRL_1,POW_ON_SOFT_GEN|EN_MUTE_UNMUTE_DEPOP|EN_HP_R_M_UN_MUTE_DEPOP|EN_HP_L_M_UN_MUTE_DEPOP); - rt5631_write_mask(codec,RT5631_HP_OUT_VOL,0x8080,0x8080); - schedule_timeout_uninterruptible(msecs_to_jiffies(150)); + rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x307f); + rt5631_write_mask(codec, RT5631_HP_OUT_VOL, 0, + RT_L_MUTE | RT_R_MUTE); + schedule_timeout_uninterruptible(msecs_to_jiffies(300)); + + } else { + rt5631_write_mask(codec, RT5631_HP_OUT_VOL, + RT_L_MUTE | RT_R_MUTE, RT_L_MUTE | RT_R_MUTE); + schedule_timeout_uninterruptible(msecs_to_jiffies(100)); } - - rt5631_write(codec,RT5631_SOFT_VOL_CTRL,SoftVol); - rt5631_write(codec,RT5631_INT_ST_IRQ_CTRL_2,HPZeroCross); + rt5631_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol); + rt5631_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc); + return; } -static int open_hp_end_widgets(struct snd_soc_codec *codec) +static void hp_depop2(struct snd_soc_codec *codec, int enable) { - /*need to be fixed*/ - /* - * - *open hp last widget, e.g. power, switch - */ + unsigned int soft_vol, hp_zc; + + rt5631_write_mask(codec, RT5631_DEPOP_FUN_CTRL_2, + EN_ONE_BIT_DEPOP, EN_ONE_BIT_DEPOP); + soft_vol = rt5631_read(codec, RT5631_SOFT_VOL_CTRL); + rt5631_write(codec, RT5631_SOFT_VOL_CTRL, 0); + hp_zc = rt5631_read(codec, RT5631_INT_ST_IRQ_CTRL_2); + rt5631_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); + if (enable) { + rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x303e); + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD3, + PWR_CHARGE_PUMP | PWR_HP_L_AMP | PWR_HP_R_AMP, + PWR_CHARGE_PUMP | PWR_HP_L_AMP | PWR_HP_R_AMP); + rt5631_write(codec, RT5631_DEPOP_FUN_CTRL_1, + POW_ON_SOFT_GEN | EN_DEPOP2_FOR_HP); + schedule_timeout_uninterruptible(msecs_to_jiffies(100)); + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD3, + PWR_HP_DEPOP_DIS, PWR_HP_DEPOP_DIS); + } else { + rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x303F); + rt5631_write(codec, RT5631_DEPOP_FUN_CTRL_1, + POW_ON_SOFT_GEN | EN_MUTE_UNMUTE_DEPOP | + PD_HPAMP_L_ST_UP | PD_HPAMP_R_ST_UP); + schedule_timeout_uninterruptible(msecs_to_jiffies(75)); + rt5631_write(codec, RT5631_DEPOP_FUN_CTRL_1, + POW_ON_SOFT_GEN | PD_HPAMP_L_ST_UP | PD_HPAMP_R_ST_UP); + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD3, 0, + PWR_HP_DEPOP_DIS); + rt5631_write(codec, RT5631_DEPOP_FUN_CTRL_1, + POW_ON_SOFT_GEN | EN_DEPOP2_FOR_HP | + PD_HPAMP_L_ST_UP | PD_HPAMP_R_ST_UP); + schedule_timeout_uninterruptible(msecs_to_jiffies(80)); + rt5631_write(codec, RT5631_DEPOP_FUN_CTRL_1, POW_ON_SOFT_GEN); + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD3, 0, + PWR_CHARGE_PUMP | PWR_HP_L_AMP | PWR_HP_R_AMP); + } - HP_Mute_Unmute_Depop(codec,1); + rt5631_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol); + rt5631_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc); - return 0; + return; } -static int close_hp_end_widgets(struct snd_soc_codec *codec) +static void hp_mute_unmute_depop(struct snd_soc_codec *codec, int enable) { - /*need to be fixed*/ - /* - * - *close hp last widget, e.g. power, switch - */ + unsigned int soft_vol, hp_zc; + + rt5631_write_mask(codec, RT5631_DEPOP_FUN_CTRL_2, + EN_ONE_BIT_DEPOP, EN_ONE_BIT_DEPOP); + soft_vol = rt5631_read(codec, RT5631_SOFT_VOL_CTRL); + rt5631_write(codec, RT5631_SOFT_VOL_CTRL, 0); + hp_zc = rt5631_read(codec, RT5631_INT_ST_IRQ_CTRL_2); + rt5631_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); + if (enable) { + schedule_timeout_uninterruptible(msecs_to_jiffies(10)); + rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x302f); + rt5631_write(codec, RT5631_DEPOP_FUN_CTRL_1, + POW_ON_SOFT_GEN | EN_MUTE_UNMUTE_DEPOP | + EN_HP_R_M_UN_MUTE_DEPOP | EN_HP_L_M_UN_MUTE_DEPOP); + rt5631_write_mask(codec, RT5631_HP_OUT_VOL, 0, + RT_L_MUTE | RT_R_MUTE); + schedule_timeout_uninterruptible(msecs_to_jiffies(160)); + } else { + rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x302f); + rt5631_write(codec, RT5631_DEPOP_FUN_CTRL_1, + POW_ON_SOFT_GEN | EN_MUTE_UNMUTE_DEPOP | + EN_HP_R_M_UN_MUTE_DEPOP | EN_HP_L_M_UN_MUTE_DEPOP); + rt5631_write_mask(codec, RT5631_HP_OUT_VOL, + RT_L_MUTE | RT_R_MUTE, RT_L_MUTE | RT_R_MUTE); + schedule_timeout_uninterruptible(msecs_to_jiffies(150)); + } - HP_Mute_Unmute_Depop(codec,0); + rt5631_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol); + rt5631_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc); - return 0; + return; } -static int hp_event(struct snd_soc_dapm_widget *w, + +static int hp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; - unsigned int l, r; - static unsigned int hp_out_enable=0; - - l = (rt5631_read(codec, RT5631_PWR_MANAG_ADD4) & (0x01 << 11)) >> 11; - r = (rt5631_read(codec, RT5631_PWR_MANAG_ADD4) & (0x01 << 10)) >> 10; - + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + static bool hp_en; + int pu_l, pu_r; + + pu_l = rt5631_read(codec, RT5631_PWR_MANAG_ADD4) & PWR_HP_L_OUT_VOL; + pu_r = rt5631_read(codec, RT5631_PWR_MANAG_ADD4) & PWR_HP_R_OUT_VOL; switch (event) { case SND_SOC_DAPM_PRE_PMD: - DBG("hp_event --SND_SOC_DAPM_PRE_PMD\n"); - if ((l && r)&&(hp_out_enable)) - { - close_hp_end_widgets(codec); - hp_depop2(codec,0); - hp_out_enable=0; + if ((pu_l && pu_r) && hp_en) { + if (rt5631->codec_version) { + hp_mute_unmute_depop_onebit(codec, 0); + hp_depop_mode2_onebit(codec, 0); + } else { + hp_mute_unmute_depop(codec, 0); + hp_depop2(codec, 0); + } + hp_en = false; } break; + case SND_SOC_DAPM_POST_PMU: - DBG("hp_event --SND_SOC_DAPM_POST_PMU\n"); - if ((l && r)&&(!hp_out_enable)) - { - hp_depop2(codec,1); - open_hp_end_widgets(codec); - hp_out_enable=1; + if ((pu_l && pu_r) && !hp_en) { + if (rt5631->codec_version) { + hp_depop_mode2_onebit(codec, 1); + hp_mute_unmute_depop_onebit(codec, 1); + } else { + hp_depop2(codec, 1); + hp_mute_unmute_depop(codec, 1); + } + hp_en = true; } break; + default: - return 0; + break; } - + return 0; } -static int dac_to_hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) +static int dac_to_hp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; - unsigned int l, r; - static unsigned int hp_out_enable=0; - - l = (rt5631_read(codec, VIRTUAL_POWER_CONTROL) & (0x01 << 8)) >> 8; - r = (rt5631_read(codec, VIRTUAL_POWER_CONTROL) & (0x01 << 9)) >> 9; - + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + static bool hp_en; + switch (event) { case SND_SOC_DAPM_PRE_PMD: - DBG("dac_to_hp_event --SND_SOC_DAPM_PRE_PMD l=%x,r=%x,hp_out_enable=%x\n",l,r,hp_out_enable); - if ((l && r)&&(hp_out_enable)) - { - - HP_Mute_Unmute_Depop(codec,0); - hp_depop2(codec,0); - hp_out_enable=0; + if (hp_en) { + if (rt5631->codec_version) { + hp_mute_unmute_depop_onebit(codec, 0); + hp_depop_mode2_onebit(codec, 0); + } else { + hp_mute_unmute_depop(codec, 0); + hp_depop2(codec, 0); + } + hp_en = false; } break; + case SND_SOC_DAPM_POST_PMU: - DBG("dac_to_hp_event --SND_SOC_DAPM_POST_PMUl=%x,r=%x,hp_out_enable=%x\n",l,r,hp_out_enable); - if ((l && r)&&(!hp_out_enable)) - { - hp_depop2(codec,1); - HP_Mute_Unmute_Depop(codec,1); - hp_out_enable=1; + if (!hp_en) { + if (rt5631->codec_version) { + hp_depop_mode2_onebit(codec, 1); + hp_mute_unmute_depop_onebit(codec, 1); + } else { + hp_depop2(codec, 1); + hp_mute_unmute_depop(codec, 1); + } + hp_en = true; } break; + default: - return 0; + break; } - + return 0; } - -static int mic_event(struct snd_soc_dapm_widget *w, +static int mic_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; - unsigned int mic1_gain_power,mic2_gain_power; - - mic1_gain_power = (rt5631_read(codec, RT5631_PWR_MANAG_ADD2) & 0x0020) >>5; - mic2_gain_power = (rt5631_read(codec, RT5631_PWR_MANAG_ADD2) & 0x0010) >>4; - + int val_mic1, val_mic2; + + val_mic1 = rt5631_read(codec, RT5631_PWR_MANAG_ADD2) & + PWR_MIC1_BOOT_GAIN; + val_mic2 = rt5631_read(codec, RT5631_PWR_MANAG_ADD2) & + PWR_MIC2_BOOT_GAIN; switch (event) { - case SND_SOC_DAPM_POST_PMD: - DBG("mic_event --SND_SOC_DAPM_POST_PMD\n"); - - if(mic1_gain_power&&mic2_gain_power) //use stereo mic from mic1&mic2,no copy ADC channel - { - rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2, 0x0000, 0xc000); + case SND_SOC_DAPM_POST_PMU: + /* + * If microphone is stereo, need not copy ADC channel + * If mic1 is used, copy ADC left to right + * If mic2 is used, copy ADC right to left + */ + if (val_mic1 && val_mic2) + rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2, + 0x0000, 0xc000); + else if (val_mic1) + rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2, + 0x4000, 0xc000); + else if (val_mic2) + rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2, + 0x8000, 0xc000); + else + rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2, + 0x0000, 0xc000); + break; + + default: + break; } - else if(mic1_gain_power) //use mic1,copy ADC left to right - { - rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2, 0x4000, 0xc000); - } - else if(mic2_gain_power)//use mic2,copy ADC right to left - { - rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2, 0x8000, 0xc000); - } - else - { - rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2, 0x0000, 0xc000); - } + return 0; +} + +static int auxo1_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + static bool aux1_en; + + switch (event) { + case SND_SOC_DAPM_PRE_PMD: + if (aux1_en) { + rt5631_write_mask(codec, RT5631_MONO_AXO_1_2_VOL, + RT_L_MUTE, RT_L_MUTE); + aux1_en = false; + } break; + case SND_SOC_DAPM_POST_PMU: - DBG("mic_event --SND_SOC_DAPM_POST_PMU\n"); - - if(mic1_gain_power&&mic2_gain_power) //use stereo mic from mic1&mic2,no copy ADC channel - { - rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2, 0x0000, 0xc000); - } - else if(mic1_gain_power) //use mic1,copy ADC left to right - { - rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2, 0x4000, 0xc000); - } - else if(mic2_gain_power)//use mic2,copy ADC right to left - { - rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2, 0x8000, 0xc000); - } - else - { - rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2, 0x0000, 0xc000); - } - + if (!aux1_en) { + rt5631_write_mask(codec, RT5631_MONO_AXO_1_2_VOL, + 0, RT_L_MUTE); + aux1_en = true; + } break; + default: - return 0; -} + break; + } return 0; } -static const struct snd_soc_dapm_widget rt5631_dapm_widgets[] = { +static int auxo2_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + static bool aux2_en; -SND_SOC_DAPM_INPUT("MIC1"), -SND_SOC_DAPM_INPUT("MIC2"), + switch (event) { + case SND_SOC_DAPM_PRE_PMD: + if (aux2_en) { + rt5631_write_mask(codec, RT5631_MONO_AXO_1_2_VOL, + RT_R_MUTE, RT_R_MUTE); + aux2_en = false; + } + break; + + case SND_SOC_DAPM_POST_PMU: + if (!aux2_en) { + rt5631_write_mask(codec, RT5631_MONO_AXO_1_2_VOL, + 0, RT_R_MUTE); + aux2_en = true; + } + break; + + default: + break; + } + + return 0; +} + +static int mono_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + static bool mono_en; + + switch (event) { + case SND_SOC_DAPM_PRE_PMD: + if (mono_en) { + rt5631_write_mask(codec, RT5631_MONO_AXO_1_2_VOL, + MUTE_MONO, MUTE_MONO); + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD3, + 0, PWR_MONO_DEPOP_DIS); + mono_en = false; + } + break; + + case SND_SOC_DAPM_POST_PMU: + if (!mono_en) { + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD3, + PWR_MONO_DEPOP_DIS, PWR_MONO_DEPOP_DIS); + rt5631_write_mask(codec, RT5631_MONO_AXO_1_2_VOL, + 0, MUTE_MONO); + mono_en = true; + } + break; + + default: + break; + } + + return 0; +} + +/** + * config_common_power - control all common power of codec system + * @pmu: power up or not + */ +static int config_common_power(struct snd_soc_codec *codec, bool pmu) +{ + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + unsigned int mux_val; + + if (pmu) { + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD1, + PWR_MAIN_I2S_EN | PWR_DAC_REF, + PWR_MAIN_I2S_EN | PWR_DAC_REF); + mux_val = rt5631_read(codec, RT5631_SPK_MONO_HP_OUT_CTRL); + if (!(mux_val & HP_L_MUX_SEL_DAC_L)) + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD1, + PWR_DAC_L_TO_MIXER, PWR_DAC_L_TO_MIXER); + if (!(mux_val & HP_R_MUX_SEL_DAC_R)) + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD1, + PWR_DAC_R_TO_MIXER, PWR_DAC_R_TO_MIXER); + if (rt5631->pll_used_flag) + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD2, + PWR_PLL, PWR_PLL); + } else { + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD1, 0, + PWR_MAIN_I2S_EN | PWR_DAC_REF | + PWR_DAC_L_TO_MIXER | PWR_DAC_R_TO_MIXER); + if (rt5631->pll_used_flag) + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD2, + 0, PWR_PLL); + } + + return 0; +} + +static int adc_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + static bool pmu; + + switch (event) { + case SND_SOC_DAPM_POST_PMD: + if (pmu) { + config_common_power(codec, false); + pmu = false; + } + break; + + case SND_SOC_DAPM_PRE_PMU: + if (!pmu) { + config_common_power(codec, true); + pmu = true; + } + break; + + default: + break; + } + + return 0; +} + +static int dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + static bool pmu; + + switch (event) { + case SND_SOC_DAPM_POST_PMD: + if (pmu) { + config_common_power(codec, false); + pmu = false; + } + break; + + case SND_SOC_DAPM_PRE_PMU: + if (!pmu) { + config_common_power(codec, true); + pmu = true; + } + break; + + default: + break; + } + + return 0; +} + +static const struct snd_soc_dapm_widget rt5631_dapm_widgets[] = { +SND_SOC_DAPM_INPUT("MIC1"), +SND_SOC_DAPM_INPUT("MIC2"), SND_SOC_DAPM_INPUT("AXIL"), SND_SOC_DAPM_INPUT("AXIR"), SND_SOC_DAPM_INPUT("MONOIN_RXN"), SND_SOC_DAPM_INPUT("MONOIN_RXP"), +SND_SOC_DAPM_MICBIAS("Mic Bias1", RT5631_PWR_MANAG_ADD2, 3, 0), +SND_SOC_DAPM_MICBIAS("Mic Bias2", RT5631_PWR_MANAG_ADD2, 2, 0), + SND_SOC_DAPM_PGA_E("Mic1 Boost", RT5631_PWR_MANAG_ADD2, 5, 0, NULL, 0, - mic_event, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), - + mic_event, SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PGA_E("Mic2 Boost", RT5631_PWR_MANAG_ADD2, 4, 0, NULL, 0, - mic_event, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), - - -SND_SOC_DAPM_PGA("MONOIN_RXP Boost", RT5631_PWR_MANAG_ADD4, 7, 0, NULL, 0), -SND_SOC_DAPM_PGA("MONOIN_RXN Boost", RT5631_PWR_MANAG_ADD4, 6, 0, NULL, 0), - -SND_SOC_DAPM_PGA("AXIL Boost", RT5631_PWR_MANAG_ADD4, 9, 0, NULL, 0), + mic_event, SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA("MONOIN_RXP Boost", RT5631_PWR_MANAG_ADD4, 7, 0, NULL, 0), +SND_SOC_DAPM_PGA("MONOIN_RXN Boost", RT5631_PWR_MANAG_ADD4, 6, 0, NULL, 0), +SND_SOC_DAPM_PGA("AXIL Boost", RT5631_PWR_MANAG_ADD4, 9, 0, NULL, 0), SND_SOC_DAPM_PGA("AXIR Boost", RT5631_PWR_MANAG_ADD4, 8, 0, NULL, 0), SND_SOC_DAPM_MIXER("MONO_IN", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_MIXER("RECMIXL Mixer", RT5631_PWR_MANAG_ADD2, 11, 0, - &rt5631_recmixl_mixer_controls[0], ARRAY_SIZE(rt5631_recmixl_mixer_controls)), -SND_SOC_DAPM_MIXER("RECMIXR Mixer", RT5631_PWR_MANAG_ADD2, 10, 0, - &rt5631_recmixr_mixer_controls[0], ARRAY_SIZE(rt5631_recmixr_mixer_controls)), - +SND_SOC_DAPM_MIXER("RECMIXL Mixer", RT5631_PWR_MANAG_ADD2, 11, 0, + &rt5631_recmixl_mixer_controls[0], + ARRAY_SIZE(rt5631_recmixl_mixer_controls)), +SND_SOC_DAPM_MIXER("RECMIXR Mixer", RT5631_PWR_MANAG_ADD2, 10, 0, + &rt5631_recmixr_mixer_controls[0], + ARRAY_SIZE(rt5631_recmixr_mixer_controls)), SND_SOC_DAPM_MIXER("ADC Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_ADC("Left ADC", "Left ADC HIFI Capture", RT5631_PWR_MANAG_ADD1, 11, 0), -SND_SOC_DAPM_ADC("Right ADC", "Right ADC HIFI Capture", RT5631_PWR_MANAG_ADD1, 10, 0), -SND_SOC_DAPM_DAC("Left DAC", "Left DAC HIFI Playback", RT5631_PWR_MANAG_ADD1, 9, 0), -SND_SOC_DAPM_DAC("Right DAC", "Right DAC HIFI Playback", RT5631_PWR_MANAG_ADD1, 8, 0), +SND_SOC_DAPM_ADC_E("Left ADC", "Left ADC HIFI Capture", + RT5631_PWR_MANAG_ADD1, 11, 0, + adc_event, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_ADC_E("Right ADC", "Right ADC HIFI Capture", + RT5631_PWR_MANAG_ADD1, 10, 0, + adc_event, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_DAC_E("Left DAC", "Left DAC HIFI Playback", + RT5631_PWR_MANAG_ADD1, 9, 0, + dac_event, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_DAC_E("Right DAC", "Right DAC HIFI Playback", + RT5631_PWR_MANAG_ADD1, 8, 0, + dac_event, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU), SND_SOC_DAPM_DAC("Voice DAC", "Voice DAC Mono Playback", SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_PGA("Voice DAC Boost", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_MIXER("SPKMIXL Mixer", RT5631_PWR_MANAG_ADD2, 13, 0, - &rt5631_spkmixl_mixer_controls[0], ARRAY_SIZE(rt5631_spkmixl_mixer_controls)), -SND_SOC_DAPM_MIXER("OUTMIXL Mixer", RT5631_PWR_MANAG_ADD2, 15, 0, - &rt5631_outmixl_mixer_controls[0], ARRAY_SIZE(rt5631_outmixl_mixer_controls)), -SND_SOC_DAPM_MIXER("OUTMIXR Mixer", RT5631_PWR_MANAG_ADD2, 14, 0, - &rt5631_outmixr_mixer_controls[0], ARRAY_SIZE(rt5631_outmixr_mixer_controls)), -SND_SOC_DAPM_MIXER("SPKMIXR Mixer", RT5631_PWR_MANAG_ADD2, 12, 0, - &rt5631_spkmixr_mixer_controls[0], ARRAY_SIZE(rt5631_spkmixr_mixer_controls)), +SND_SOC_DAPM_MIXER("SPKMIXL Mixer", RT5631_PWR_MANAG_ADD2, 13, 0, + &rt5631_spkmixl_mixer_controls[0], + ARRAY_SIZE(rt5631_spkmixl_mixer_controls)), +SND_SOC_DAPM_MIXER("OUTMIXL Mixer", RT5631_PWR_MANAG_ADD2, 15, 0, + &rt5631_outmixl_mixer_controls[0], + ARRAY_SIZE(rt5631_outmixl_mixer_controls)), +SND_SOC_DAPM_MIXER("OUTMIXR Mixer", RT5631_PWR_MANAG_ADD2, 14, 0, + &rt5631_outmixr_mixer_controls[0], + ARRAY_SIZE(rt5631_outmixr_mixer_controls)), +SND_SOC_DAPM_MIXER("SPKMIXR Mixer", RT5631_PWR_MANAG_ADD2, 12, 0, + &rt5631_spkmixr_mixer_controls[0], + ARRAY_SIZE(rt5631_spkmixr_mixer_controls)), + SND_SOC_DAPM_PGA("Left SPK Vol", RT5631_PWR_MANAG_ADD4, 15, 0, NULL, 0), SND_SOC_DAPM_PGA("Right SPK Vol", RT5631_PWR_MANAG_ADD4, 14, 0, NULL, 0), SND_SOC_DAPM_PGA_E("Left HP Vol", RT5631_PWR_MANAG_ADD4, 11, 0, NULL, 0, @@ -1001,57 +1145,56 @@ SND_SOC_DAPM_PGA_E("Left HP Vol", RT5631_PWR_MANAG_ADD4, 11, 0, NULL, 0, SND_SOC_DAPM_PGA_E("Right HP Vol", RT5631_PWR_MANAG_ADD4, 10, 0, NULL, 0, hp_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("Left DAC_HP", VIRTUAL_POWER_CONTROL, 8, 0, NULL, 0, - dac_to_hp_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("Right DAC_HP", VIRTUAL_POWER_CONTROL,9, 0, NULL, 0, - dac_to_hp_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("Left DAC_HP", SND_SOC_NOPM, 0, 0, NULL, 0, + dac_to_hp_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("Right DAC_HP", SND_SOC_NOPM, 0, 0, NULL, 0, + dac_to_hp_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PGA("Left Out Vol", RT5631_PWR_MANAG_ADD4, 13, 0, NULL, 0), SND_SOC_DAPM_PGA("Right Out Vol", RT5631_PWR_MANAG_ADD4, 12, 0, NULL, 0), -SND_SOC_DAPM_MIXER("AXO1MIX Mixer", RT5631_PWR_MANAG_ADD3, 11, 0, - &rt5631_AXO1MIX_mixer_controls[0], ARRAY_SIZE(rt5631_AXO1MIX_mixer_controls)), -SND_SOC_DAPM_MIXER("SPOLMIX Mixer", SND_SOC_NOPM, 0, 0, - &rt5631_spolmix_mixer_controls[0], ARRAY_SIZE(rt5631_spolmix_mixer_controls)), -SND_SOC_DAPM_MIXER("MONOMIX Mixer", RT5631_PWR_MANAG_ADD3, 9, 0, - &rt5631_monomix_mixer_controls[0], ARRAY_SIZE(rt5631_monomix_mixer_controls)), -SND_SOC_DAPM_MIXER("SPORMIX Mixer", SND_SOC_NOPM, 0, 0, - &rt5631_spormix_mixer_controls[0], ARRAY_SIZE(rt5631_spormix_mixer_controls)), -SND_SOC_DAPM_MIXER("AXO2MIX Mixer", RT5631_PWR_MANAG_ADD3, 10, 0, - &rt5631_AXO2MIX_mixer_controls[0], ARRAY_SIZE(rt5631_AXO2MIX_mixer_controls)), - +SND_SOC_DAPM_MIXER_E("AXO1MIX Mixer", RT5631_PWR_MANAG_ADD3, 11, 0, + &rt5631_AXO1MIX_mixer_controls[0], + ARRAY_SIZE(rt5631_AXO1MIX_mixer_controls), + auxo1_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_MIXER("SPOLMIX Mixer", SND_SOC_NOPM, 0, 0, + &rt5631_spolmix_mixer_controls[0], + ARRAY_SIZE(rt5631_spolmix_mixer_controls)), +SND_SOC_DAPM_MIXER("MONOMIX Mixer", RT5631_PWR_MANAG_ADD3, 9, 0, + &rt5631_monomix_mixer_controls[0], + ARRAY_SIZE(rt5631_monomix_mixer_controls)), +SND_SOC_DAPM_MIXER("SPORMIX Mixer", SND_SOC_NOPM, 0, 0, + &rt5631_spormix_mixer_controls[0], + ARRAY_SIZE(rt5631_spormix_mixer_controls)), +SND_SOC_DAPM_MIXER_E("AXO2MIX Mixer", RT5631_PWR_MANAG_ADD3, 10, 0, + &rt5631_AXO2MIX_mixer_controls[0], + ARRAY_SIZE(rt5631_AXO2MIX_mixer_controls), + auxo2_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_MUX("SPOL Mux", SND_SOC_NOPM, 0, 0, &rt5631_spol_mux_control), SND_SOC_DAPM_MUX("SPOR Mux", SND_SOC_NOPM, 0, 0, &rt5631_spor_mux_control), SND_SOC_DAPM_MUX("Mono Mux", SND_SOC_NOPM, 0, 0, &rt5631_mono_mux_control), - SND_SOC_DAPM_MUX("HPL Mux", SND_SOC_NOPM, 0, 0, &rt5631_hpl_mux_control), SND_SOC_DAPM_MUX("HPR Mux", SND_SOC_NOPM, 0, 0, &rt5631_hpr_mux_control), -SND_SOC_DAPM_PGA("Mono Amp", RT5631_PWR_MANAG_ADD3, 7, 0, NULL, 0), - - -SND_SOC_DAPM_PGA_E("SPKL Amp", VIRTUAL_POWER_CONTROL, 0, 0, NULL, 0, +SND_SOC_DAPM_PGA_E("Mono Amp", RT5631_PWR_MANAG_ADD3, 7, 0, NULL, 0, + mono_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), +SND_SOC_DAPM_PGA_E("SPKL Amp", SND_SOC_NOPM, 0, 0, NULL, 0, spk_event, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("SPKR Amp", VIRTUAL_POWER_CONTROL, 1, 0, NULL, 0, +SND_SOC_DAPM_PGA_E("SPKR Amp", SND_SOC_NOPM, 1, 0, NULL, 0, spk_event, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_MICBIAS("Mic Bias1", RT5631_PWR_MANAG_ADD2, 3, 0), -SND_SOC_DAPM_MICBIAS("Mic Bias2", RT5631_PWR_MANAG_ADD2, 2, 0), - -SND_SOC_DAPM_OUTPUT("LOUT"), -SND_SOC_DAPM_OUTPUT("ROUT"), +SND_SOC_DAPM_OUTPUT("AUXO1"), +SND_SOC_DAPM_OUTPUT("AUXO2"), SND_SOC_DAPM_OUTPUT("SPOL"), SND_SOC_DAPM_OUTPUT("SPOR"), SND_SOC_DAPM_OUTPUT("HPOL"), SND_SOC_DAPM_OUTPUT("HPOR"), SND_SOC_DAPM_OUTPUT("MONO"), - }; static const struct snd_soc_dapm_route audio_map[] = { - {"Mic1 Boost", NULL, "MIC1"}, {"Mic2 Boost", NULL, "MIC2"}, {"MONOIN_RXP Boost", NULL, "MONOIN_RXP"}, @@ -1075,7 +1218,7 @@ static const struct snd_soc_dapm_route audio_map[] = { {"ADC Mixer", NULL, "RECMIXL Mixer"}, {"ADC Mixer", NULL, "RECMIXR Mixer"}, {"Left ADC", NULL, "ADC Mixer"}, - {"Right ADC", NULL,"ADC Mixer"}, + {"Right ADC", NULL, "ADC Mixer"}, {"Voice DAC Boost", NULL, "Voice DAC"}, @@ -1089,7 +1232,6 @@ static const struct snd_soc_dapm_route audio_map[] = { {"SPKMIXR Mixer", "MIC2_P Playback Switch", "MIC2"}, {"SPKMIXR Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"}, - {"OUTMIXL Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"}, {"OUTMIXL Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"}, {"OUTMIXL Mixer", "DACL Playback Switch", "Left DAC"}, @@ -1117,31 +1259,25 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Right Out Vol", NULL, "OUTMIXR Mixer"}, {"Right HP Vol", NULL, "OUTMIXR Mixer"}, - {"AXO1MIX Mixer", "MIC1_BST1 Playback Switch", "Mic1 Boost"}, {"AXO1MIX Mixer", "OUTVOLL Playback Switch", "Left Out Vol"}, {"AXO1MIX Mixer", "OUTVOLR Playback Switch", "Right Out Vol"}, {"AXO1MIX Mixer", "MIC2_BST2 Playback Switch", "Mic2 Boost"}, - {"AXO2MIX Mixer", "MIC1_BST1 Playback Switch", "Mic1 Boost"}, {"AXO2MIX Mixer", "OUTVOLL Playback Switch", "Left Out Vol"}, {"AXO2MIX Mixer", "OUTVOLR Playback Switch", "Right Out Vol"}, {"AXO2MIX Mixer", "MIC2_BST2 Playback Switch", "Mic2 Boost"}, - {"SPOLMIX Mixer", "SPKVOLL Playback Switch", "Left SPK Vol"}, {"SPOLMIX Mixer", "SPKVOLR Playback Switch", "Right SPK Vol"}, {"SPORMIX Mixer", "SPKVOLL Playback Switch", "Left SPK Vol"}, {"SPORMIX Mixer", "SPKVOLR Playback Switch", "Right SPK Vol"}, - {"MONOMIX Mixer", "OUTVOLL Playback Switch", "Left Out Vol"}, {"MONOMIX Mixer", "OUTVOLR Playback Switch", "Right Out Vol"}, - - {"SPOL Mux", "SPOLMIX", "SPOLMIX Mixer"}, {"SPOL Mux", "MONOIN_RX", "MONO_IN"}, {"SPOL Mux", "VDAC", "Voice DAC Boost"}, @@ -1151,41 +1287,41 @@ static const struct snd_soc_dapm_route audio_map[] = { {"SPOR Mux", "MONOIN_RX", "MONO_IN"}, {"SPOR Mux", "VDAC", "Voice DAC Boost"}, {"SPOR Mux", "DACR", "Right DAC"}, - + {"Mono Mux", "MONOMIX", "MONOMIX Mixer"}, {"Mono Mux", "MONOIN_RX", "MONO_IN"}, {"Mono Mux", "VDAC", "Voice DAC Boost"}, {"Right DAC_HP", "NULL", "Right DAC"}, - {"Left DAC_HP", "NULL", "Left DAC"}, - + {"Left DAC_HP", "NULL", "Left DAC"}, + {"HPL Mux", "LEFT HPVOL", "Left HP Vol"}, - {"HPL Mux", "LEFT DAC", "Left DAC_HP"}, + {"HPL Mux", "LEFT DAC", "Left DAC_HP"}, {"HPR Mux", "RIGHT HPVOL", "Right HP Vol"}, - {"HPR Mux", "RIGHT DAC", "Right DAC_HP"}, + {"HPR Mux", "RIGHT DAC", "Right DAC_HP"}, {"SPKL Amp", NULL, "SPOL Mux"}, {"SPKR Amp", NULL, "SPOR Mux"}, {"Mono Amp", NULL, "Mono Mux"}, - - {"LOUT", NULL, "AXO1MIX Mixer"}, - {"ROUT", NULL, "AXO2MIX Mixer"}, + + {"AUXO1", NULL, "AXO1MIX Mixer"}, + {"AUXO2", NULL, "AXO2MIX Mixer"}, {"SPOL", NULL, "SPKL Amp"}, {"SPOR", NULL, "SPKR Amp"}, {"HPOL", NULL, "HPL Mux"}, - {"HPOR", NULL, "HPR Mux"}, + {"HPOR", NULL, "HPR Mux"}, {"MONO", NULL, "Mono Amp"} - }; static int rt5631_add_widgets(struct snd_soc_codec *codec) { - snd_soc_dapm_new_controls(codec, rt5631_dapm_widgets, - ARRAY_SIZE(rt5631_dapm_widgets)); - snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - snd_soc_dapm_new_widgets(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; + + snd_soc_dapm_new_controls(dapm, rt5631_dapm_widgets, + ARRAY_SIZE(rt5631_dapm_widgets)); + snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); return 0; } @@ -1224,14 +1360,10 @@ static int get_vol(int max, int min, int stage_num, int stage) static void rt5631_set_volume(int vollevel) { - struct snd_soc_device *socdev; - struct snd_soc_codec *codec; + struct snd_soc_codec *codec = rt5631_codec; int tmpvol1, tmpvol2; //DBG("rt5631_set_volume = %d\n", vollevel); - - socdev =rt5631_socdev; - codec = socdev->card->codec; if (vollevel > 15) vollevel = 8; gvolume = vollevel; @@ -1256,13 +1388,9 @@ static void rt5631_set_volume(int vollevel) static void rt5631_set_eq(int on) { - struct snd_soc_device *socdev; - struct snd_soc_codec *codec; + struct snd_soc_codec *codec = rt5631_codec; unsigned int Reg0C; - socdev =rt5631_socdev; - codec = socdev->card->codec; - Reg0C = rt5631_read(codec, RT5631_STEREO_DAC_VOL_1); DBG("------- rt5631_set_eq: read Reg0C = 0x%04x\n", Reg0C); @@ -1281,15 +1409,11 @@ static void rt5631_set_eq(int on) static void rt5631_set_volume(int vollevel) { - struct snd_soc_device *socdev; - struct snd_soc_codec *codec; + struct snd_soc_codec *codec = rt5631_codec; u8 tmpvol1, tmpvol2; u16 spk_vol, hp_vol; DBG("rt5631_set_volume = %d\n", vollevel); - - socdev =rt5631_socdev; - codec = socdev->card->codec; if (vollevel > 15) vollevel = 8; gvolume = vollevel; @@ -1313,141 +1437,147 @@ static void rt5631_set_volume(int vollevel) } #endif - -struct _coeff_div{ - unsigned int mclk; //pllout or MCLK - unsigned int bclk; //master mode - unsigned int rate; - unsigned int reg_val; +struct coeff_clk_div { + u32 mclk; + u32 bclk; + u32 rate; + u16 reg_val; }; -/*PLL divisors*/ -struct _pll_div { + +/* PLL divisors yes*/ +struct pll_div { u32 pll_in; u32 pll_out; - u16 regvalue; + u16 reg_val; }; -static const struct _pll_div codec_master_pll_div[] = { - - { 2048000, 8192000, 0x0ea0}, - { 3686400, 8192000, 0x4e27}, - { 12000000, 8192000, 0x456b}, - { 13000000, 8192000, 0x495f}, - { 13100000, 8192000, 0x0320}, - { 2048000, 11289600, 0xf637}, - { 3686400, 11289600, 0x2f22}, - { 12000000, 11289600, 0x3e2f}, - { 13000000, 11289600, 0x4d5b}, - { 13100000, 11289600, 0x363b}, - { 2048000, 16384000, 0x1ea0}, - { 3686400, 16384000, 0x9e27}, - { 12000000, 16384000, 0x452b}, - { 13000000, 16384000, 0x542f}, - { 13100000, 16384000, 0x03a0}, - { 2048000, 16934400, 0xe625}, - { 3686400, 16934400, 0x9126}, - { 12000000, 16934400, 0x4d2c}, - { 13000000, 16934400, 0x742f}, - { 13100000, 16934400, 0x3c27}, - { 2048000, 22579200, 0x2aa0}, - { 3686400, 22579200, 0x2f20}, - { 12000000, 22579200, 0x7e2f}, - { 13000000, 22579200, 0x742f}, - { 13100000, 22579200, 0x3c27}, - { 2048000, 24576000, 0x2ea0}, - { 3686400, 24576000, 0xee27}, - { 12000000, 24576000, 0x2915}, - { 13000000, 24576000, 0x772e}, - { 13100000, 24576000, 0x0d20}, - { 26000000, 24576000, 0x2027}, - { 26000000, 22579200, 0x392f}, - { 24576000, 22579200, 0x0921}, - { 24576000, 24576000, 0x02a0}, +static const struct pll_div codec_master_pll_div[] = { + {2048000, 8192000, 0x0ea0}, + {3686400, 8192000, 0x4e27}, + {12000000, 8192000, 0x456b}, + {13000000, 8192000, 0x495f}, + {13100000, 8192000, 0x0320}, + {2048000, 11289600, 0xf637}, + {3686400, 11289600, 0x2f22}, + {12000000, 11289600, 0x3e2f}, + {13000000, 11289600, 0x4d5b}, + {13100000, 11289600, 0x363b}, + {2048000, 16384000, 0x1ea0}, + {3686400, 16384000, 0x9e27}, + {12000000, 16384000, 0x452b}, + {13000000, 16384000, 0x542f}, + {13100000, 16384000, 0x03a0}, + {2048000, 16934400, 0xe625}, + {3686400, 16934400, 0x9126}, + {12000000, 16934400, 0x4d2c}, + {13000000, 16934400, 0x742f}, + {13100000, 16934400, 0x3c27}, + {2048000, 22579200, 0x2aa0}, + {3686400, 22579200, 0x2f20}, + {12000000, 22579200, 0x7e2f}, + {13000000, 22579200, 0x742f}, + {13100000, 22579200, 0x3c27}, + {2048000, 24576000, 0x2ea0}, + {3686400, 24576000, 0xee27}, + {12000000, 24576000, 0x2915}, + {13000000, 24576000, 0x772e}, + {13100000, 24576000, 0x0d20}, + {26000000, 24576000, 0x2027}, + {26000000, 22579200, 0x392f}, + {24576000, 22579200, 0x0921}, + {24576000, 24576000, 0x02a0}, }; -static const struct _pll_div codec_slave_pll_div[] = { - { 256000, 4096000, 0x3ea0}, - { 352800, 5644800, 0x3ea0}, - { 512000, 8192000, 0x3ea0}, - { 705600, 11289600, 0x3ea0}, - { 1024000, 16384000, 0x3ea0}, - { 1411200, 22579200, 0x3ea0}, - { 1536000, 24576000, 0x3ea0}, - { 2048000, 16384000, 0x1ea0}, - { 2822400, 22579200, 0x1ea0}, - { 3072000, 24576000, 0x1ea0}, - { 705600, 11289600, 0x3ea0}, - { 705600, 8467200, 0x3ab0}, - { 24576000, 24576000, 0x02a0}, - { 1411200, 11289600, 0x1690}, - { 2822400, 11289600, 0x0a90}, - { 1536000, 12288000, 0x1690}, - { 3072000, 12288000, 0x0a90}, +static const struct pll_div codec_slave_pll_div[] = { + {256000, 2048000, 0x46f0}, + {256000, 4096000, 0x3ea0}, + {352800, 5644800, 0x3ea0}, + {512000, 8192000, 0x3ea0}, + {1024000, 8192000, 0x46f0}, + {705600, 11289600, 0x3ea0}, + {1024000, 16384000, 0x3ea0}, + {1411200, 22579200, 0x3ea0}, + {1536000, 24576000, 0x3ea0}, + {2048000, 16384000, 0x1ea0}, + {2822400, 22579200, 0x1ea0}, + {2822400, 45158400, 0x5ec0}, + {5644800, 45158400, 0x46f0}, + {3072000, 24576000, 0x1ea0}, + {3072000, 49152000, 0x5ec0}, + {6144000, 49152000, 0x46f0}, + {705600, 11289600, 0x3ea0}, + {705600, 8467200, 0x3ab0}, + {24576000, 24576000, 0x02a0}, + {1411200, 11289600, 0x1690}, + {2822400, 11289600, 0x0a90}, + {1536000, 12288000, 0x1690}, + {3072000, 12288000, 0x0a90}, }; -struct _coeff_div coeff_div[] = { - //sysclk is 256fs - { 2048000, 8000 * 32, 8000, 0x1000}, - { 2048000, 8000 * 64, 8000, 0x0000}, - { 2822400, 11025 * 32, 11025, 0x1000}, - { 2822400, 11025 * 64, 11025, 0x0000}, - { 4096000, 16000 * 32, 16000, 0x1000}, - { 4096000, 16000 * 64, 16000, 0x0000}, - { 5644800, 22050 * 32, 22050, 0x1000}, - { 5644800, 22050 * 64, 22050, 0x0000}, - { 8192000, 32000 * 32, 32000, 0x1000}, - { 8192000, 32000 * 64, 32000, 0x0000}, - {11289600, 44100 * 32, 44100, 0x1000}, - {11289600, 44100 * 64, 44100, 0x0000}, - {12288000, 48000 * 32, 48000, 0x1000}, - {12288000, 48000 * 64, 48000, 0x0000}, - //sysclk is 512fs - { 4096000, 8000 * 32, 8000, 0x3000}, - { 4096000, 8000 * 64, 8000, 0x2000}, - { 5644800, 11025 * 32, 11025, 0x3000}, - { 5644800, 11025 * 64, 11025, 0x2000}, - { 8192000, 16000 * 32, 16000, 0x3000}, - { 8192000, 16000 * 64, 16000, 0x2000}, - {11289600, 22050 * 32, 22050, 0x3000}, - {11289600, 22050 * 64, 22050, 0x2000}, - {16384000, 32000 * 32, 32000, 0x3000}, - {16384000, 32000 * 64, 32000, 0x2000}, - {22579200, 44100 * 32, 44100, 0x3000}, - {22579200, 44100 * 64, 44100, 0x2000}, - {24576000, 48000 * 32, 48000, 0x3000}, - {24576000, 48000 * 64, 48000, 0x2000}, - //sysclk is 24.576Mhz or 22.579200Mhz - {24576000, 8000 * 32, 8000, 0x7080}, - {24576000, 8000 * 64, 8000, 0x6080}, - {24576000, 16000 * 32, 16000, 0x5080}, - {24576000, 16000 * 64, 16000, 0x4080}, - {24576000, 24000 * 32, 24000, 0x5000}, - {24576000, 24000 * 64, 24000, 0x4000}, - {24576000, 32000 * 32, 32000, 0x3080}, - {24576000, 32000 * 64, 32000, 0x2080}, - - {22579200, 11025 * 32, 11025, 0x7000}, - {22579200, 11025 * 64, 11025, 0x6000}, - {22579200, 22050 * 32, 22050, 0x5000}, - {22579200, 22050 * 64, 22050, 0x4000}, - +struct coeff_clk_div coeff_div[] = { + /* sysclk is 256fs */ + {2048000, 8000 * 32, 8000, 0x1000}, + {2048000, 8000 * 64, 8000, 0x0000}, + {2822400, 11025 * 32, 11025, 0x1000}, + {2822400, 11025 * 64, 11025, 0x0000}, + {4096000, 16000 * 32, 16000, 0x1000}, + {4096000, 16000 * 64, 16000, 0x0000}, + {5644800, 22050 * 32, 22050, 0x1000}, + {5644800, 22050 * 64, 22050, 0x0000}, + {8192000, 32000 * 32, 32000, 0x1000}, + {8192000, 32000 * 64, 32000, 0x0000}, + {11289600, 44100 * 32, 44100, 0x1000}, + {11289600, 44100 * 64, 44100, 0x0000}, + {12288000, 48000 * 32, 48000, 0x1000}, + {12288000, 48000 * 64, 48000, 0x0000}, + {22579200, 88200 * 32, 88200, 0x1000}, + {22579200, 88200 * 64, 88200, 0x0000}, + {24576000, 96000 * 32, 96000, 0x1000}, + {24576000, 96000 * 64, 96000, 0x0000}, + /* sysclk is 512fs */ + {4096000, 8000 * 32, 8000, 0x3000}, + {4096000, 8000 * 64, 8000, 0x2000}, + {5644800, 11025 * 32, 11025, 0x3000}, + {5644800, 11025 * 64, 11025, 0x2000}, + {8192000, 16000 * 32, 16000, 0x3000}, + {8192000, 16000 * 64, 16000, 0x2000}, + {11289600, 22050 * 32, 22050, 0x3000}, + {11289600, 22050 * 64, 22050, 0x2000}, + {16384000, 32000 * 32, 32000, 0x3000}, + {16384000, 32000 * 64, 32000, 0x2000}, + {22579200, 44100 * 32, 44100, 0x3000}, + {22579200, 44100 * 64, 44100, 0x2000}, + {24576000, 48000 * 32, 48000, 0x3000}, + {24576000, 48000 * 64, 48000, 0x2000}, + {45158400, 88200 * 32, 88200, 0x3000}, + {45158400, 88200 * 64, 88200, 0x2000}, + {49152000, 96000 * 32, 96000, 0x3000}, + {49152000, 96000 * 64, 96000, 0x2000}, + /* sysclk is 24.576Mhz or 22.5792Mhz */ + {24576000, 8000 * 32, 8000, 0x7080}, + {24576000, 8000 * 64, 8000, 0x6080}, + {24576000, 16000 * 32, 16000, 0x5080}, + {24576000, 16000 * 64, 16000, 0x4080}, + {24576000, 24000 * 32, 24000, 0x5000}, + {24576000, 24000 * 64, 24000, 0x4000}, + {24576000, 32000 * 32, 32000, 0x3080}, + {24576000, 32000 * 64, 32000, 0x2080}, + {22579200, 11025 * 32, 11025, 0x7000}, + {22579200, 11025 * 64, 11025, 0x6000}, + {22579200, 22050 * 32, 22050, 0x5000}, + {22579200, 22050 * 64, 22050, 0x4000}, }; - - - static int get_coeff(int mclk, int rate, int timesofbclk) { int i; for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { - if ((coeff_div[i].mclk == mclk) - && (coeff_div[i].rate == rate) - && ((coeff_div[i].bclk / coeff_div[i].rate) == timesofbclk)) - return i; + if (coeff_div[i].mclk == mclk && coeff_div[i].rate == rate && + (coeff_div[i].bclk / coeff_div[i].rate) == timesofbclk) + return i; } - - return -1; + return -EINVAL; } static int get_coeff_in_slave_mode(int mclk, int rate) @@ -1457,221 +1587,218 @@ static int get_coeff_in_slave_mode(int mclk, int rate) static int get_coeff_in_master_mode(int mclk, int rate, int bclk) { - return get_coeff(mclk, rate, (bclk / rate)); + return get_coeff(mclk, rate, (bclk / rate)); } -static void rt5631_set_dmic_params(struct snd_soc_codec *codec, struct snd_pcm_hw_params *params) -{ -// struct rt5631_priv *rt5631 = codec->private_data; - unsigned int rate; +static void rt5631_set_dmic_params(struct snd_soc_codec *codec, + struct snd_pcm_hw_params *params) +{ + int rate; - DBG( "enter %s\n", __func__); - rt5631_write_mask(codec, RT5631_GPIO_CTRL, GPIO_PIN_FUN_SEL_GPIO_DIMC|GPIO_DMIC_FUN_SEL_DIMC - , GPIO_PIN_FUN_SEL_MASK|GPIO_DMIC_FUN_SEL_MASK); + rt5631_write_mask(codec, RT5631_GPIO_CTRL, + GPIO_PIN_FUN_SEL_GPIO_DIMC | GPIO_DMIC_FUN_SEL_DIMC, + GPIO_PIN_FUN_SEL_MASK | GPIO_DMIC_FUN_SEL_MASK); rt5631_write_mask(codec, RT5631_DIG_MIC_CTRL, DMIC_ENA, DMIC_ENA_MASK); - rt5631_write_mask(codec, RT5631_DIG_MIC_CTRL,DMIC_L_CH_LATCH_FALLING|DMIC_R_CH_LATCH_RISING - ,DMIC_L_CH_LATCH_MASK|DMIC_R_CH_LATCH_MASK); + rt5631_write_mask(codec, RT5631_DIG_MIC_CTRL, + DMIC_L_CH_LATCH_FALLING | DMIC_R_CH_LATCH_RISING, + DMIC_L_CH_LATCH_MASK|DMIC_R_CH_LATCH_MASK); rate = params_rate(params); switch (rate) { case 44100: case 48000: - rt5631_write_mask(codec, RT5631_DIG_MIC_CTRL, DMIC_CLK_CTRL_TO_32FS, DMIC_CLK_CTRL_MASK); + rt5631_write_mask(codec, RT5631_DIG_MIC_CTRL, + DMIC_CLK_CTRL_TO_32FS, DMIC_CLK_CTRL_MASK); break; + case 32000: case 22050: - rt5631_write_mask(codec, RT5631_DIG_MIC_CTRL, DMIC_CLK_CTRL_TO_64FS, DMIC_CLK_CTRL_MASK); + rt5631_write_mask(codec, RT5631_DIG_MIC_CTRL, + DMIC_CLK_CTRL_TO_64FS, DMIC_CLK_CTRL_MASK); break; + case 16000: case 11025: - case 8000: - rt5631_write_mask(codec, RT5631_DIG_MIC_CTRL, DMIC_CLK_CTRL_TO_128FS, DMIC_CLK_CTRL_MASK); + case 8000: + rt5631_write_mask(codec, RT5631_DIG_MIC_CTRL, + DMIC_CLK_CTRL_TO_128FS, DMIC_CLK_CTRL_MASK); + break; + + default: break; } - - rt5631_write_mask(codec, RT5631_DIG_MIC_CTRL, - DMIC_L_CH_UNMUTE | DMIC_R_CH_UNMUTE, DMIC_L_CH_MUTE_MASK | DMIC_R_CH_MUTE_MASK); - + + rt5631_write_mask(codec, RT5631_DIG_MIC_CTRL, + DMIC_L_CH_UNMUTE | DMIC_R_CH_UNMUTE, + DMIC_L_CH_MUTE_MASK | DMIC_R_CH_MUTE_MASK); + + return; } -static int rt5631_hifi_pcm_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) +static int rt5631_hifi_pcm_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { -// struct snd_soc_codec *codec = dai->codec; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; - struct rt5631_priv *rt5631 = codec->private_data; - int stream = substream->stream; + struct snd_soc_codec *codec = rtd->codec; + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + int stream = substream->stream, rate = params_rate(params), coeff; unsigned int iface = 0; - int rate = params_rate(params); - int coeff = 0; - - DBG( "enter %s\n", __func__); + + pr_debug("enter %s\n", __func__); if (!rt5631->master) coeff = get_coeff_in_slave_mode(rt5631->sysclk, rate); else - coeff = get_coeff_in_master_mode(rt5631->sysclk, rate, rate * timesofbclk); + coeff = get_coeff_in_master_mode(rt5631->sysclk, rate, + rate * timesofbclk); + if (coeff < 0) + pr_err("%s: get coeff err!\n", __func__); - if (coeff < 0) { - DBG(KERN_ERR "%s get_coeff err!\n", __func__); - // return -EINVAL; - } - - switch (params_format(params)) - { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x0004; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x0008; - break; - case SNDRV_PCM_FORMAT_S8: - iface |= 0x000c; - break; - default: - return -EINVAL; + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + break; + case SNDRV_PCM_FORMAT_S20_3LE: + iface |= SDP_I2S_DL_20; + break; + case SNDRV_PCM_FORMAT_S24_LE: + iface |= SDP_I2S_DL_24; + break; + case SNDRV_PCM_FORMAT_S8: + iface |= SDP_I2S_DL_8; + break; + default: + return -EINVAL; } - if (stream == SNDRV_PCM_STREAM_CAPTURE) { - if (rt5631->dmic_used_flag) //use Digital Mic + if (SNDRV_PCM_STREAM_CAPTURE == stream) { + if (rt5631->dmic_used_flag) rt5631_set_dmic_params(codec, params); } - - rt5631_write_mask(codec, RT5631_SDP_CTRL, iface, SDP_I2S_DL_MASK); - if(coeff>=0) - rt5631_write(codec, RT5631_STEREO_AD_DA_CLK_CTRL, coeff_div[coeff].reg_val); + rt5631_write_mask(codec, RT5631_SDP_CTRL, iface, SDP_I2S_DL_MASK); -// if((rt5631_read(codec,RT5631_SPK_MONO_HP_OUT_CTRL)&0x000c)==0x000c) -// rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD1, 0x83e0, 0x8380); -// else - rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD1, 0x83e0, 0x83e0); + if (coeff >= 0) + rt5631_write(codec, RT5631_STEREO_AD_DA_CLK_CTRL, + coeff_div[coeff].reg_val); - rt5631_write_mask(codec, 0x6e,0x4000,0x4000); -return 0; + return 0; } -static int rt5631_hifi_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +static int rt5631_hifi_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; - struct rt5631_priv *rt5631 = codec->private_data; - u16 iface = 0; - - DBG( "enter %s\n", __func__); + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + unsigned int iface = 0; + + pr_debug("enter %s\n", __func__); + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: rt5631->master = 1; break; case SND_SOC_DAIFMT_CBS_CFS: - iface |= (0x0001 << 15); + iface |= SDP_MODE_SEL_SLAVE; rt5631->master = 0; break; default: return -EINVAL; } - + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: break; case SND_SOC_DAIFMT_LEFT_J: - iface |= (0x0001); + iface |= SDP_I2S_DF_LEFT; break; case SND_SOC_DAIFMT_DSP_A: - iface |= (0x0002); + iface |= SDP_I2S_DF_PCM_A; break; case SND_SOC_DAIFMT_DSP_B: - iface |= (0x0003); + iface |= SDP_I2S_DF_PCM_B; break; default: return -EINVAL; } - + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: break; case SND_SOC_DAIFMT_IB_NF: - iface |= (0x0001 << 7); + iface |= SDP_I2S_BCLK_POL_CTRL; break; default: - return -EINVAL; + return -EINVAL; } - + rt5631_write(codec, RT5631_SDP_CTRL, iface); return 0; } -static int rt5631_hifi_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) + +static int rt5631_hifi_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) { struct snd_soc_codec *codec = codec_dai->codec; - struct rt5631_priv *rt5631 = codec->private_data; - - DBG( "enter %s\n", __func__); - if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) { + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + + pr_info("enter %s, syclk=%d\n", __func__, freq); + if ((freq >= (256 * 8000)) && (freq <= (512 * 96000))) { rt5631->sysclk = freq; - return 0; + return 0; } - - DBG("unsupported sysclk freq %u for audio i2s\n", freq); - DBG("Set sysclk to 24.576Mhz by default\n"); + + pr_info("unsupported sysclk freq %u for audio i2s\n", freq); + pr_info("set sysclk to 24.576Mhz by default\n"); rt5631->sysclk = 24576000; - return 0; - //return -EINVAL; + return 0; } -static int rt5631_codec_set_dai_pll(struct snd_soc_dai *codec_dai, - int pll_id, unsigned int freq_in, unsigned int freq_out) +static int rt5631_codec_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, + int source, unsigned int freq_in, unsigned int freq_out) { - struct snd_soc_codec *codec = codec_dai->codec; - struct rt5631_priv *rt5631 = codec->private_data; - int i; - int ret = -EINVAL; - - - DBG( "enter %s\n", __func__); -// rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD2, 0, PWR_PLL); + struct snd_soc_codec *codec = codec_dai->codec; + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + int i, ret = -EINVAL; + + printk(KERN_DEBUG "enter %s\n", __func__); if (!freq_in || !freq_out) return 0; - - if (rt5631->master) { - for (i = 0; i < ARRAY_SIZE(codec_master_pll_div); i ++) { - - if ((freq_in == codec_master_pll_div[i].pll_in) && (freq_out == codec_master_pll_div[i].pll_out)) { - rt5631_write(codec, RT5631_PLL_CTRL, codec_master_pll_div[i].regvalue); - rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD2, PWR_PLL, PWR_PLL); - schedule_timeout_uninterruptible(msecs_to_jiffies(20)); - rt5631_write(codec, RT5631_GLOBAL_CLK_CTRL, 0x4000); + if (rt5631->master) { + for (i = 0; i < ARRAY_SIZE(codec_master_pll_div); i++) + if (freq_in == codec_master_pll_div[i].pll_in && + freq_out == codec_master_pll_div[i].pll_out) { + rt5631_write(codec, RT5631_PLL_CTRL, + codec_master_pll_div[i].reg_val); + schedule_timeout_uninterruptible( + msecs_to_jiffies(20)); + rt5631_write(codec, RT5631_GLOBAL_CLK_CTRL, + SYSCLK_SOUR_SEL_PLL); + rt5631->pll_used_flag = 1; ret = 0; - + break; } - - } } else { - - for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i ++) { - - if ((freq_in == codec_slave_pll_div[i].pll_in) && (freq_out == codec_slave_pll_div[i].pll_out)) { - - rt5631_write(codec, RT5631_PLL_CTRL, codec_slave_pll_div[i].regvalue); - rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD2, PWR_PLL, PWR_PLL); - schedule_timeout_uninterruptible(msecs_to_jiffies(20)); - rt5631_write(codec, RT5631_GLOBAL_CLK_CTRL, 0x5000); + for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++) + if (freq_in == codec_slave_pll_div[i].pll_in && + freq_out == codec_slave_pll_div[i].pll_out) { + rt5631_write(codec, RT5631_PLL_CTRL, + codec_slave_pll_div[i].reg_val); + schedule_timeout_uninterruptible( + msecs_to_jiffies(20)); + rt5631_write(codec, RT5631_GLOBAL_CLK_CTRL, + SYSCLK_SOUR_SEL_PLL | + PLLCLK_SOUR_SEL_BITCLK); + rt5631->pll_used_flag = 1; ret = 0; - + break; } - - } } - - return 0; + + return ret; } static int rt5631_trigger(struct snd_pcm_substream *substream, int status, struct snd_soc_dai *dai) @@ -1695,497 +1822,227 @@ static int rt5631_trigger(struct snd_pcm_substream *substream, int status, struc return 0; } -static void rt5631_hifi_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai) +static ssize_t rt5631_index_reg_show(struct device *dev, + struct device_attribute *attr, char *buf) { - DBG( "enter %s\n", __func__); + #define IDX_REG_FMT "%02x: %04x\n" + #define IDX_REG_LEN 9 + unsigned int val; + int cnt = 0, i; + + cnt += sprintf(buf, "RT5631 index register\n"); + for (i = 0; i < 0x55; i++) { + if (cnt + IDX_REG_LEN >= PAGE_SIZE - 1) + break; + val = rt5631_read_index(rt5631_codec, i); + if (!val) + continue; + cnt += sprintf(buf + cnt, IDX_REG_FMT, i, val); + } + + if (cnt >= PAGE_SIZE) + cnt = PAGE_SIZE - 1; + + return cnt; } +static DEVICE_ATTR(index_reg, 0444, rt5631_index_reg_show, NULL); -//#define RT5631_STEREO_RATES (SNDRV_PCM_RATE_8000_48000) -#define RT5631_STEREO_RATES (SNDRV_PCM_RATE_44100) // zyy 20110704, playback and record use same sample rate -#define RT5631_FORMAT (SNDRV_PCM_FMTBIT_S16_LE |\ - SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE |\ +#define RT5631_STEREO_RATES SNDRV_PCM_RATE_8000_96000 +#define RT5631_FORMAT (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S8) struct snd_soc_dai_ops rt5631_ops = { - .hw_params = rt5631_hifi_pcm_params, - .set_fmt = rt5631_hifi_codec_set_dai_fmt, - .set_sysclk = rt5631_hifi_codec_set_dai_sysclk, - .set_pll = rt5631_codec_set_dai_pll, - .shutdown = rt5631_hifi_shutdown, + .hw_params = rt5631_hifi_pcm_params, + .set_fmt = rt5631_hifi_codec_set_dai_fmt, + .set_sysclk = rt5631_hifi_codec_set_dai_sysclk, + .set_pll = rt5631_codec_set_dai_pll, #if defined(CONFIG_ADJUST_VOL_BY_CODEC) - .trigger = rt5631_trigger, + .trigger = rt5631_trigger, #endif }; - -struct snd_soc_dai rt5631_dai[] = { + +struct snd_soc_dai_driver rt5631_dai[] = { { - .name = "RT5631 HIFI", - .id = 1, + .name = "RT5631 HiFi", .playback = { .stream_name = "HIFI Playback", .channels_min = 1, .channels_max = 2, .rates = RT5631_STEREO_RATES, - .formats = RT5631_FORMAT, - } , + .formats = RT5631_FORMAT, + }, .capture = { .stream_name = "HIFI Capture", .channels_min = 1, .channels_max = 2, - .rates = RT5631_STEREO_RATES, + .rates = RT5631_STEREO_RATES, .formats = RT5631_FORMAT, }, - .ops =&rt5631_ops, + .ops = &rt5631_ops, }, - - { - .name = "RT5631 Reserved", - .id = 2, - } }; - EXPORT_SYMBOL_GPL(rt5631_dai); - -static ssize_t rt5631_index_reg_show(struct device *dev, - struct device_attribute *attr, char *buf) +static int rt5631_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) { - struct snd_soc_device *socdev = dev_get_drvdata(dev); - struct snd_soc_codec *codec = socdev->card->codec; - int count = 0; - int value; - int i; - - count += sprintf(buf, "%s index register\n", codec->name); - - for (i = 0; i < 0x55; i++) { - count += sprintf(buf + count, "%2x= ", i); - if (count >= PAGE_SIZE - 1) - break; - value = rt5631_read_index(codec, i); - count += snprintf(buf + count, PAGE_SIZE - count, "0x%4x", value); - - if (count >= PAGE_SIZE - 1) - break; - - count += snprintf(buf + count, PAGE_SIZE - count, "\n"); - if (count >= PAGE_SIZE - 1) - break; - } - - if (count >= PAGE_SIZE) - count = PAGE_SIZE - 1; - - return count; - -} - -static DEVICE_ATTR(index_reg, 0444, rt5631_index_reg_show, NULL); - - -static int rt5631_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) -{ - DBG( "enter %s\n", __func__); - - DBG("rt5631_set_bias_level=%d\n",level); - switch (level) { case SND_SOC_BIAS_ON: break; + case SND_SOC_BIAS_PREPARE: - rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD3,PWR_VREF|PWR_MAIN_BIAS, PWR_VREF|PWR_MAIN_BIAS); - rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD2,0x000c, 0x000c); + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD3, + PWR_VREF | PWR_MAIN_BIAS, PWR_VREF | PWR_MAIN_BIAS); + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD2, + PWR_MICBIAS1_VOL | PWR_MICBIAS2_VOL, + PWR_MICBIAS1_VOL | PWR_MICBIAS2_VOL); break; - case SND_SOC_BIAS_STANDBY: + case SND_SOC_BIAS_STANDBY: + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD2, 0, + PWR_MICBIAS1_VOL | PWR_MICBIAS2_VOL); break; + case SND_SOC_BIAS_OFF: - rt5631_write_index(codec, 0x11,0x0000); - rt5631_write_mask(codec, RT5631_SPK_OUT_VOL ,0x8080, 0x8080); - rt5631_write_mask(codec, RT5631_HP_OUT_VOL ,0x8080, 0x8080); + rt5631_write_mask(codec, RT5631_SPK_OUT_VOL, + RT_L_MUTE | RT_R_MUTE, RT_L_MUTE | RT_R_MUTE); + rt5631_write_mask(codec, RT5631_HP_OUT_VOL, + RT_L_MUTE | RT_R_MUTE, RT_L_MUTE | RT_R_MUTE); rt5631_write(codec, RT5631_PWR_MANAG_ADD1, 0x0000); rt5631_write(codec, RT5631_PWR_MANAG_ADD2, 0x0000); rt5631_write(codec, RT5631_PWR_MANAG_ADD3, 0x0000); rt5631_write(codec, RT5631_PWR_MANAG_ADD4, 0x0000); break; - } - - codec->bias_level = level; - return 0; -} -static int rt5631_init(struct snd_soc_device *socdev) -{ - struct snd_soc_codec *codec = socdev->card->codec; - int ret; - - DBG( "enter %s\n", __func__); - codec->name = "RT5631"; - codec->owner = THIS_MODULE; - codec->read = rt5631_read; - codec->write = rt5631_write; - codec->set_bias_level = rt5631_set_bias_level; - codec->dai = rt5631_dai; - codec->num_dai = 2; - codec->reg_cache_size = ARRAY_SIZE(rt5631_reg); - codec->reg_cache_step = 1; - codec->reg_cache = kmemdup(rt5631_reg, sizeof(rt5631_reg), GFP_KERNEL); - - if (codec->reg_cache == NULL) - return -ENOMEM; - - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - DBG(KERN_ERR "rt5631: failed to create pcms\n"); - goto pcm_err; - } - - rt5631_reset(codec); - rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD3,PWR_VREF|PWR_MAIN_BIAS, PWR_VREF|PWR_MAIN_BIAS); - schedule_timeout_uninterruptible(msecs_to_jiffies(110)); - rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD3, PWR_FAST_VREF_CTRL, PWR_FAST_VREF_CTRL); - codec->bias_level = SND_SOC_BIAS_STANDBY; - schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(100)); - - rt5631_reg_init(codec); -#if defined(CONFIG_ADJUST_VOL_BY_CODEC) - rt5631_set_volume(gvolume); -#endif -#if 0 //(RT5631_EQ_FUNC_ENA==1) - rt5631_write_index_mask(codec,0x11,0x0001,0x0003); - rt5631_write_index(codec,0x12,0x0001); - rt5631_update_eqmode(codec,HFREQ); - //rt5631_update_eqmode(codec,SPK_FR); -#endif -#if (RT5631_SPK_TIMER == 1) -/* Timer module installing */ - setup_timer( &spk_timer, spk_timer_callback, 0 ); - DBG( "Starting timer to fire in 5s (%ld)\n", jiffies ); - ret = mod_timer( &spk_timer, jiffies + msecs_to_jiffies(5000) ); - if (ret) printk("Error in mod_timer\n"); - - INIT_WORK(&spk_work, spk_work_handler); -#endif - rt5631_add_controls(codec); - rt5631_add_widgets(codec); - ret = snd_soc_init_card(socdev); - if (ret < 0) { - DBG(KERN_ERR "rt5631: failed to register card!\n"); - goto card_err; + default: + break; } - DBG(KERN_INFO "rt5631 initial ok!\n"); - return 0; - - -card_err: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -pcm_err: - kfree(codec->reg_cache); - codec->reg_cache = NULL; - return ret; -} - + codec->dapm.bias_level = level; -static const struct i2c_device_id rt5631_i2c_id[] = { - {"rt5631", 0}, - {} -}; -MODULE_DEVICE_TABLE(i2c, rt5631_i2c_id); - -static int rt5631_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct snd_soc_device *socdev = rt5631_socdev; - struct snd_soc_codec *codec = socdev->card->codec; - int ret; - - DBG( "enter %s\n", __func__); - i2c_set_clientdata(i2c, codec); - codec->control_data = i2c; - - ret = rt5631_init(socdev); - if (ret < 0) - pr_err("failed to initialise rt5631!\n"); - - return ret; - - -} - -static int rt5631_i2c_remove(struct i2c_client *client) -{ - struct snd_soc_codec *codec = i2c_get_clientdata(client); - - DBG( "enter %s\n", __func__); - kfree(codec->reg_cache); return 0; } -static void rt5631_i2c_shutdown(void){ - struct snd_soc_device *socdev = rt5631_socdev; - struct snd_soc_codec *codec = socdev->card->codec; - - DBG( "enter %s\n", __func__); - rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF); -} -struct i2c_driver rt5631_i2c_driver = { - .driver = { - .name = "RT5631 I2C Codec", - .owner = THIS_MODULE, - }, - .probe = rt5631_i2c_probe, - .remove = rt5631_i2c_remove, - .shutdown = rt5631_i2c_shutdown, - .id_table = rt5631_i2c_id, -}; - - -static int rt5631_add_i2c_device(struct platform_device *pdev, - const struct rt5631_setup_data *setup) +static int rt5631_probe(struct snd_soc_codec *codec) { -#if 0 - struct i2c_board_info info; - struct i2c_adapter *adapter; - struct i2c_client *client; -#endif + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); + unsigned int val; int ret; - - DBG( "enter %s\n", __func__); - ret = i2c_add_driver(&rt5631_i2c_driver); +printk("rt5631_probe\n"); + ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); if (ret != 0) { - dev_err(&pdev->dev, "can't add i2c driver\n"); - return ret; - } - -#if 0 - memset(&info, '\0', sizeof(struct i2c_board_info)); - info.addr = setup->i2c_address; - info.platform_data = pdev; - strlcpy(info.type, "rt5631", I2C_NAME_SIZE); - - adapter = i2c_get_adapter(setup->i2c_bus); - if (!adapter) { - dev_err(&pdev->dev, "can't get i2c adapter %d\n", - setup->i2c_bus); - goto err_driver; - } - - client = i2c_new_device(adapter, &info); - i2c_put_adapter(adapter); - if (!client) { - dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", - (unsigned int)info.addr); - goto err_driver; + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; } -#endif + codec->cache_bypass = 1; - return 0; + val = rt5631_read_index(codec, RT5631_ADDA_MIXER_INTL_REG3); + if (val & 0x0002) + rt5631->codec_version = 1; + else + rt5631->codec_version = 0; -#if 0 -err_driver: - i2c_del_driver(&rt5631_i2c_driver); - return -ENODEV; -#endif - -} + rt5631_reset(codec); + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD3, + PWR_VREF | PWR_MAIN_BIAS, PWR_VREF | PWR_MAIN_BIAS); + schedule_timeout_uninterruptible(msecs_to_jiffies(80)); + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD3, PWR_FAST_VREF_CTRL, + PWR_FAST_VREF_CTRL); + rt5631_reg_init(codec); -static void rt5631_work(struct work_struct *work) -{ - struct snd_soc_codec *codec = container_of(work, struct snd_soc_codec, delayed_work.work); - - rt5631_set_bias_level(codec, codec->bias_level); -} + /* power off ClassD auto Recovery */ + if (rt5631->codec_version) + rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2, + 0x2000, 0x2000); + else + rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2, + 0, 0x2000); -static int rt5631_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct rt5631_setup_data *setup; - struct snd_soc_codec *codec; - struct rt5631_priv *rt5631; - int ret = 0; - - DBG( "enter %s\n", __func__); + codec->dapm.bias_level = SND_SOC_BIAS_STANDBY; + rt5631_codec = codec; - pr_info("RT5631 Audio Codec %s", RT5631_VERSION); +#if (RT5631_SPK_TIMER == 1) + /* Timer module installing */ + setup_timer( &spk_timer, spk_timer_callback, 0 ); + DBG( "Starting timer to fire in 5s (%ld)\n", jiffies ); + ret = mod_timer( &spk_timer, jiffies + msecs_to_jiffies(5000) ); + if (ret) printk("Error in mod_timer\n"); - if(socdev->codec_data) - { - setup = socdev->codec_data; - } + INIT_WORK(&spk_work, spk_work_handler); +#endif - codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (codec == NULL) { - return -ENOMEM; - } - - - rt5631 = kzalloc(sizeof(struct rt5631_priv), GFP_KERNEL); - if (rt5631 == NULL) { - ret = -ENOMEM; - goto priv_err; - } - codec->private_data = rt5631; - socdev->card->codec = codec; - mutex_init(&codec->mutex); - rt5631_socdev = socdev; - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - INIT_DELAYED_WORK(&codec->delayed_work, rt5631_work); - - ret = device_create_file(&pdev->dev, &dev_attr_index_reg); - if (ret < 0) - printk(KERN_WARNING "asoc: failed to add index_reg sysfs files\n"); -#if 0 - if (setup->i2c_address) { - codec->hw_write = (hw_write_t)i2c_master_send; + snd_soc_add_controls(codec, rt5631_snd_controls, + ARRAY_SIZE(rt5631_snd_controls)); + rt5631_add_widgets(codec); - ret = rt5631_add_i2c_device(pdev, setup); - } -#else - //probe i2c device driver - { - codec->hw_write = (hw_write_t)i2c_master_send; - // codec->hw_read = (hw_read_t)i2c_master_recv; - ret = rt5631_add_i2c_device(pdev, setup); - } -#endif - + ret = device_create_file(codec->dev, &dev_attr_index_reg); if (ret != 0) { - goto i2c_device_err; + dev_err(codec->dev, + "Failed to create index_reg sysfs files: %d\n", ret); + return ret; } - return 0; -i2c_device_err: - kfree(rt5631); - socdev->card->codec->private_data = NULL; + pr_info("RT5631 initial ok!\n"); -priv_err: - kfree(codec); - socdev->card->codec = NULL; - - return ret; + return 0; } -static int run_delayed_work(struct delayed_work *dwork) +static int rt5631_remove(struct snd_soc_codec *codec) { - int ret; - - ret = cancel_delayed_work(dwork); - - if (ret) { - schedule_delayed_work(dwork, 0); - flush_scheduled_work(); - } - - return ret; -} -static int rt5631_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec =socdev->card->codec; #if (RT5631_SPK_TIMER == 1) -/* Timer¡¡module¡¡uninstalling */ + /* Timer¡¡module¡¡uninstalling */ int ret; - ret = del_timer(&spk_timer); - if(ret) printk("The timer is still in use...\n"); - DBG("Timer module uninstalling\n"); + ret = del_timer(&spk_timer); + if(ret) printk("The timer is still in use...\n"); + DBG("Timer module uninstalling\n"); #endif - if (codec->control_data) - rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF); - run_delayed_work(&codec->delayed_work); - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - i2c_unregister_device(codec->control_data); - i2c_del_driver(&rt5631_i2c_driver); - kfree(codec->private_data); - kfree(codec); - + + + rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; - } -static int rt5631_suspend(struct platform_device *pdev, pm_message_t state) +static int rt5631_suspend(struct snd_soc_codec *codec, pm_message_t state) { - DBG( "enter %s\n", __func__); - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - struct snd_soc_codec *codec =socdev->card->codec; - rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int rt5631_resume(struct platform_device *pdev) +static int rt5631_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; + struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); -// int i; -// u8 data[3]; -// u16 *cache = codec->reg_cache; - -#if 1 - rt5631_reset(codec); - rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD3,PWR_VREF|PWR_MAIN_BIAS, PWR_VREF|PWR_MAIN_BIAS); + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD3, + PWR_VREF | PWR_MAIN_BIAS, PWR_VREF | PWR_MAIN_BIAS); schedule_timeout_uninterruptible(msecs_to_jiffies(110)); - rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD3, PWR_FAST_VREF_CTRL, PWR_FAST_VREF_CTRL); + rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD3, + PWR_FAST_VREF_CTRL, PWR_FAST_VREF_CTRL); rt5631_reg_init(codec); -#if defined(CONFIG_ADJUST_VOL_BY_CODEC) - rt5631_set_volume(gvolume); -#endif - DBG( "enter %s\n", __func__); - rt5631_write_mask(codec, RT5631_PWR_MANAG_ADD1, 0x83e0, 0x83e0); - -#if 0 //(RT5631_EQ_FUNC_ENA==1) - rt5631_write_index_mask(codec,0x11,0x0001,0x0003); - rt5631_write_index(codec,0x12,0x0001); - rt5631_update_eqmode(codec,HFREQ); - //rt5631_update_eqmode(codec,SPK_FR); -#endif + + /* power off ClassD auto Recovery */ + if (rt5631->codec_version) + rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2, + 0x2000, 0x2000); + else + rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2, + 0, 0x2000); + #if (RT5631_SPK_TIMER == 1) last_is_spk = !last_is_spk; //wired~, update eqmode right here by spk_timer. #endif -#else - for (i = 0; i < ARRAY_SIZE(rt5631_reg); i++) { - if (i == RT5631_RESET) - continue; - data[0] = i << 1; - data[1] = (0xff00 & cache[i]) >> 8; - data[2] = 0x00ff & cache[i]; - codec->hw_write(codec->control_data, data, 2); - } - - rt5631_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -#endif - - if (codec->suspend_bias_level == SND_SOC_BIAS_ON) { - rt5631_set_bias_level(codec, SND_SOC_BIAS_PREPARE); - codec->bias_level = SND_SOC_BIAS_ON; - schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(100)); - } - - return 0; - + return 0; } void codec_set_spk(bool on) { - struct snd_soc_device *socdev; - struct snd_soc_codec *codec; - - socdev = rt5631_socdev; + struct snd_soc_codec *codec = rt5631_codec; DBG("%s: %d\n", __func__, on); - if(!socdev) - return; - - codec = socdev->card->codec; if(!codec) return; @@ -2206,48 +2063,92 @@ void codec_set_spk(bool on) return; } -//detect short current for mic1 +/* + * detect short current for mic1 + */ int rt5631_ext_mic_detect(void) { - int CodecValue; - struct snd_soc_device *socdev = rt5631_socdev; - struct snd_soc_codec *codec = socdev->card->codec; - - rt5631_write_mask(codec, RT5631_MIC_CTRL_2,MICBIAS1_S_C_DET_ENA,MICBIAS1_S_C_DET_MASK); - // rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2,0x2000,0x2000); - CodecValue=rt5631_read(codec,RT5631_INT_ST_IRQ_CTRL_2) & 0x0001; + struct snd_soc_codec *codec = rt5631_codec; + int det; - rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2,0x0001,0x00001); - - return CodecValue; + rt5631_write_mask(codec, RT5631_MIC_CTRL_2, MICBIAS1_S_C_DET_ENA, + MICBIAS1_S_C_DET_MASK); + det = rt5631_read(codec, RT5631_INT_ST_IRQ_CTRL_2) & 0x0001; + rt5631_write_mask(codec, RT5631_INT_ST_IRQ_CTRL_2, 0x0001, 0x00001); + return det; } - EXPORT_SYMBOL_GPL(rt5631_ext_mic_detect); - -struct snd_soc_codec_device soc_codec_dev_rt5631 = -{ +static struct snd_soc_codec_driver soc_codec_dev_rt5631 = { .probe = rt5631_probe, .remove = rt5631_remove, .suspend = rt5631_suspend, .resume = rt5631_resume, + .set_bias_level = rt5631_set_bias_level, + .reg_cache_size = ARRAY_SIZE(rt5631_reg), + .reg_word_size = sizeof(u16), + .reg_cache_default = rt5631_reg, + .reg_cache_step = 1, }; -EXPORT_SYMBOL_GPL(soc_codec_dev_rt5631); +static const struct i2c_device_id rt5631_i2c_id[] = { + { "rt5631", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rt5631_i2c_id); -static int __init rt5631_modinit(void) +static int rt5631_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { - return snd_soc_register_dais(rt5631_dai, ARRAY_SIZE(rt5631_dai)); + struct rt5631_priv *rt5631; + int ret; + + pr_info("RT5631 Audio Codec %s\n", RT5631_VERSION); + + rt5631 = kzalloc(sizeof(struct rt5631_priv), GFP_KERNEL); + if (NULL == rt5631) + return -ENOMEM; + + i2c_set_clientdata(i2c, rt5631); + + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5631, + rt5631_dai, ARRAY_SIZE(rt5631_dai)); + if (ret < 0) + kfree(rt5631); + + return ret; } -static void __exit rt5631_modexit(void) +static __devexit int rt5631_i2c_remove(struct i2c_client *client) { - snd_soc_unregister_dais(rt5631_dai, ARRAY_SIZE(rt5631_dai)); + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); + return 0; } +struct i2c_driver rt5631_i2c_driver = { + .driver = { + .name = "RT5631", + .owner = THIS_MODULE, + }, + .probe = rt5631_i2c_probe, + .remove = __devexit_p(rt5631_i2c_remove), + .id_table = rt5631_i2c_id, +}; + +static int __init rt5631_modinit(void) +{ + return i2c_add_driver(&rt5631_i2c_driver); +} module_init(rt5631_modinit); + +static void __exit rt5631_modexit(void) +{ + i2c_del_driver(&rt5631_i2c_driver); +} module_exit(rt5631_modexit); + MODULE_DESCRIPTION("ASoC RT5631 driver"); -MODULE_AUTHOR("flove"); +MODULE_AUTHOR("flove "); MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/rt5631.h b/sound/soc/codecs/rt5631.h index b2e316f08d25..e9bad16e40c8 100644 --- a/sound/soc/codecs/rt5631.h +++ b/sound/soc/codecs/rt5631.h @@ -1,578 +1,570 @@ -#ifndef __RTCODEC5631_H__ -#define __RTCODEC5631_H__ - - -#define RT5631_RESET 0X00 //RESET CODEC TO DEFAULT -#define RT5631_SPK_OUT_VOL 0X02 //SPEAKER OUT VOLUME -#define RT5631_HP_OUT_VOL 0X04 //HEADPHONE OUTPUT VOLUME -#define RT5631_MONO_AXO_1_2_VOL 0X06 //MONO/AUXOUT OUTPUT VOLUME -#define RT5631_AUX_IN_VOL 0X0A //AUX IN VOLUME -#define RT5631_STEREO_DAC_VOL_1 0X0C //STEREO DAC VOLUME 1 -#define RT5631_MIC_CTRL_1 0X0E //MICROPHONE CONTROL 1 -#define RT5631_STEREO_DAC_VOL_2 0X10 //STEREO DAC VOLUME 2 -#define RT5631_ADC_CTRL_1 0X12 //STEREO ADC CONTROL 1 -#define RT5631_ADC_REC_MIXER 0X14 //ADC RECORD MIXER CONTROL -#define RT5631_ADC_CTRL_2 0X16 //STEREO ADC CONTROL 2 -#define RT5631_OUTMIXER_L_CTRL 0X1A //LEFT OUTPUT MIXER CONTROL -#define RT5631_OUTMIXER_R_CTRL 0X1C //RIGHT OUTPUT MIXER CONTROL -#define RT5631_AXO1MIXER_CTRL 0X1E //LOUT MIXER CONTROL -#define RT5631_AXO2MIXER_CTRL 0X20 //LOUT MIXER CONTROL -#define RT5631_MIC_CTRL_2 0X22 //MICROPHONE CONTROL 2 -#define RT5631_DIG_MIC_CTRL 0X24 //DIGITAL MICROPHONE CONTROL -#define RT5631_MONO_INPUT_VOL 0X26 //MONO INPUT VOLUME -#define RT5631_SPK_MIXER_CTRL 0X28 //SPEAKER MIXER CONTROL -#define RT5631_SPK_MONO_OUT_CTRL 0X2A //SPEAKER/MONO OUTPUT CONTROL -#define RT5631_SPK_MONO_HP_OUT_CTRL 0X2C //SPEAKER/MONO/HP OUTPUT CONTROL -#define RT5631_SDP_CTRL 0X34 //STEREO I2S SERIAL DATA PORT CONTROL -#define RT5631_STEREO_AD_DA_CLK_CTRL 0X38 //STEREO AD/DA CLOCK CONTROL -#define RT5631_PWR_MANAG_ADD1 0X3A //POWER MANAGMENT ADDITION 1 -#define RT5631_PWR_MANAG_ADD2 0X3B //POWER MANAGMENT ADDITION 2 -#define RT5631_PWR_MANAG_ADD3 0X3C //POWER MANAGMENT ADDITION 3 -#define RT5631_PWR_MANAG_ADD4 0X3E //POWER MANAGMENT ADDITION 4 -#define RT5631_GEN_PUR_CTRL_REG 0X40 //GENERAL PURPOSE CONTROL REGISTER -#define RT5631_GLOBAL_CLK_CTRL 0X42 //GLOBAL CLOCK CONTROL -#define RT5631_PLL_CTRL 0X44 //PLL CONTROL -#define RT5631_INT_ST_IRQ_CTRL_1 0X48 //INTERNAL STATUS AND IRQ CONTROL 1 -#define RT5631_INT_ST_IRQ_CTRL_2 0X4A //INTERNAL STATUS AND IRQ CONTROL 2 -#define RT5631_GPIO_CTRL 0X4C //GPIO OUTPUT CONTROL -#define RT5631_MISC_CTRL 0X52 //MISC CONTROL -#define RT5631_DEPOP_FUN_CTRL_1 0X54 //DE-POP FUNCTION CONTROL 1 -#define RT5631_DEPOP_FUN_CTRL_2 0X56 //DE-POP FUNCTION CONTROL 2 -#define RT5631_JACK_DET_CTRL 0X5A //JACK DETECT CONTROL REGISTER -#define RT5631_SOFT_VOL_CTRL 0X5C //SOFT VOLUME CONTROL -#define RT5631_ALC_CTRL_1 0X64 //ALC CONTROL 1 -#define RT5631_ALC_CTRL_2 0X65 //ALC CONTROL 2 -#define RT5631_ALC_CTRL_3 0X66 //ALC CONTROL 3 -#define RT5631_PSEUDO_SPATL_CTRL 0X68 //PSEUDO STEREO AND SPATIAL EFFECT CONTROL -#define RT5631_INDEX_ADD 0X6A //INDEX ADDRESS -#define RT5631_INDEX_DATA 0X6C //INDEX DATA -#define RT5631_EQ_CTRL 0X6E //EQ CONTROL -#define RT5631_VENDOR_ID1 0x7C //VENDOR ID1 -#define RT5631_VENDOR_ID2 0x7E //VENDOR ID2 - - -//global definition -#define RT_L_MUTE (0x1<<15) //MUTE LEFT CONTROL BIT -#define RT_R_MUTE (0x1<<7) //MUTE RIGHT CONTROL BIT - -//Speaker Output Control(0x02) -#define SPK_L_VOL_SEL_MASK (0x1<<14) //Speaker left channel volume input select MASK -#define SPK_L_VOL_SEL_VMID (0x0<<14) //Speaker left channel volume input select VMID -#define SPK_L_VOL_SEL_SPKMIX_L (0x1<<14) //Speaker left channel volume input select SPKMIXER LEFT -#define SPK_R_VOL_SEL_MASK (0x1<< 6) //Speaker right channel volume input select MASK -#define SPK_R_VOL_SEL_VMID (0x0<< 6) //Speaker right channel volume input select VMID -#define SPK_R_VOL_SEL_SPKMIX_R (0x1<< 6) //Speaker right channel volume input select SPKMIXER RIGHT - -//Headphone Output Control(0x04) -#define HP_L_VOL_SEL_MASK (0x1<<14) //HP left channel volume input select MASK -#define HP_L_VOL_SEL_VMID (0x0<<14) //HP left channel volume input select VMID -#define HP_L_VOL_SEL_OUTMIX_L (0x1<<14) //HP left channel volume input select OUTMIXER LEFT -#define HP_R_VOL_SEL_MASK (0x1<< 6) //HP right channel volume input select MASK -#define HP_R_VOL_SEL_VMID (0x0<< 6) //HP right channel volume input select VMID -#define HP_R_VOL_SEL_OUTMIX_R (0x1<< 6) //HP right channel volume input select OUTMIXER RIGHT - - -//Output Control for AUXOUT/MONO(0x06) -#define AUXOUT_1_VOL_SEL_MASK (0x1<<14) //LOUT channel volume input select MASK -#define AUXOUT_1_VOL_SEL_VMID (0x0<<14) //LOUT channel volume input select VMID -#define AUXOUT_1_VOL_SEL_OUTMIX_L (0x1<<14) //LOUT channel volume input select OUTMIXER LEFT -#define MUTE_MONO (0x1<<13) //Mute Mono control -#define AUXOUT_2_VOL_SEL_MASK (0x1<< 6) //ROUT channel volume input select MASK -#define AUXOUT_2_VOL_SEL_VMID (0x0<< 6) //ROUT channel volume input select VMID -#define AUXOUT_2_VOL_SEL_OUTMIX_R (0x1<< 6) //ROUT channel volume input select OUTMIXER RIGHT - - -//Microphone Input Control 1(0x0E) -#define MIC1_DIFF_INPUT_CTRL (0x1<<15) //MIC1 different input control -#define MIC2_DIFF_INPUT_CTRL (0x1<< 7) //MIC2 different input control - - -//ADC Recording Mixer Control(0x14) -#define M_OUTMIXER_L_TO_RECMIXER_L (0x1<<15) //Mute left OUTMIXER to left RECMIXER -#define M_MIC1_TO_RECMIXER_L (0x1<<14) //Mute mic1 to left RECMIXER -#define M_AXIL_TO_RECMIXER_L (0x1<<13) //Mute AXIL to left RECMIXER -#define M_MONO_IN_TO_RECMIXER_L (0x1<<12) //Mute BB_RX to left RECMIXER -#define M_OUTMIXER_R_TO_RECMIXER_R (0x1<< 7) //Mute right OUTMIXER to right RECMIXER -#define M_MIC2_TO_RECMIXER_R (0x1<< 6) //Mute mic2 to right RECMIXER -#define M_AXIR_TO_RECMIXER_R (0x1<< 5) //Mute AXIR to right RECMIXER -#define M_MONO_IN_TO_RECMIXER_R (0x1<< 4) //Mute BB_RX to right RECMIXER - -//Left Output Mixer Control(0x1A) -#define M_RECMIXER_L_TO_OUTMIXER_L (0x1<<15) //Mute Left RecMixer to Left OutMixer -#define M_RECMIXER_R_TO_OUTMIXER_L (0x1<<14) //Mute Right RecMixer to Left OutMixer -#define M_DAC_L_TO_OUTMIXER_L (0x1<<13) //Mute Left Dac to Left OutMixer -#define M_MIC1_TO_OUTMIXER_L (0x1<<12) //Mute Mic1 to Left OutMixer -#define M_MIC2_TO_OUTMIXER_L (0x1<<11) //Mute Mic2 to Left OutMixer -#define M_MONO_IN_P_TO_OUTMIXER_L (0x1<<10) //Mute MONO IN positive to Left OutMixer -#define M_AXIL_TO_OUTMIXER_L (0x1<< 9) //Mute AXIL to Left OutMixer -#define M_AXIR_TO_OUTMIXER_L (0x1<< 8) //Mute AXIR to Left OutMixer - - -//Right Output Mixer Control(0x1C) -#define M_RECMIXER_L_TO_OUTMIXER_R (0x1<<15) //Mute Left RecMixer to Right OutMixer -#define M_RECMIXER_R_TO_OUTMIXER_R (0x1<<14) //Mute Right RecMixer to Right OutMixer -#define M_DAC_R_TO_OUTMIXER_R (0x1<<13) //Mute Left Dac to Right OutMixer -#define M_MIC1_TO_OUTMIXER_R (0x1<<12) //Mute Mic1 to Right OutMixer -#define M_MIC2_TO_OUTMIXER_R (0x1<<11) //Mute Mic2 to Right OutMixer -#define M_MONO_IN_N_TO_OUTMIXER_R (0x1<<10) //Mute MONO IN Negative to Right OutMixer -#define M_AXIL_TO_OUTMIXER_R (0x1<< 9) //Mute AXIL to Right OutMixer -#define M_AXIR_TO_OUTMIXER_R (0x1<< 8) //Mute AXIR to Right OutMixer - - -//Lout Mixer Control(0x1E) -#define M_MIC1_TO_AXO1MIXER (0x1<<15) //Mute MIC1 to LOUT Mixer -#define M_MIC2_TO_AXO1MIXER (0x1<<11) //Mute MIC2 to LOUT Mixer -#define M_OUTMIXER_L_TO_AXO1MIXER (0x1<< 7) //Mute Left Output mixer to LOUT Mixer -#define M_OUTMIXER_R_TO_AXO1MIXER (0x1<< 6) //Mute Right Output mixer to LOUT Mixer - - -//Rout Mixer Control(0x20) -#define M_MIC1_TO_AXO2MIXER (0x1<<15) //Mute MIC1 to ROUT Mixer -#define M_MIC2_TO_AXO2MIXER (0x1<<11) //Mute MIC2 to ROUT Mixer -#define M_OUTMIXER_L_TO_AXO2MIXER (0x1<< 7) //Mute Left Output mixer to ROUT Mixer -#define M_OUTMIXER_R_TO_AXO2MIXER (0x1<< 6) //Mute Right Output mixer to ROUT Mixer - -//Micphone Input Control 2(0x22) -#define MIC_BIAS_90_PRECNET_AVDD 1 -#define MIC_BIAS_75_PRECNET_AVDD 2 - -#define MIC1_BOOST_CTRL_MASK (0xf<<12) -#define MIC1_BOOST_CTRL_BYPASS (0x0<<12) -#define MIC1_BOOST_CTRL_20DB (0x1<<12) -#define MIC1_BOOST_CTRL_24DB (0x2<<12) -#define MIC1_BOOST_CTRL_30DB (0x3<<12) -#define MIC1_BOOST_CTRL_35DB (0x4<<12) -#define MIC1_BOOST_CTRL_40DB (0x5<<12) -#define MIC1_BOOST_CTRL_34DB (0x6<<12) -#define MIC1_BOOST_CTRL_50DB (0x7<<12) -#define MIC1_BOOST_CTRL_52DB (0x8<<12) - -#define MIC2_BOOST_CTRL_MASK (0xf<< 8) -#define MIC2_BOOST_CTRL_BYPASS (0x0<< 8) -#define MIC2_BOOST_CTRL_20DB (0x1<< 8) -#define MIC2_BOOST_CTRL_24DB (0x2<< 8) -#define MIC2_BOOST_CTRL_30DB (0x3<< 8) -#define MIC2_BOOST_CTRL_35DB (0x4<< 8) -#define MIC2_BOOST_CTRL_40DB (0x5<< 8) -#define MIC2_BOOST_CTRL_34DB (0x6<< 8) -#define MIC2_BOOST_CTRL_50DB (0x7<< 8) -#define MIC2_BOOST_CTRL_52DB (0x8<< 8) - -#define MICBIAS1_VOLT_CTRL_MASK (0x1<< 7) -#define MICBIAS1_VOLT_CTRL_90P (0x0<< 7) -#define MICBIAS1_VOLT_CTRL_75P (0x1<< 7) - -#define MICBIAS1_S_C_DET_MASK (0x1<< 6) -#define MICBIAS1_S_C_DET_DIS (0x0<< 6) -#define MICBIAS1_S_C_DET_ENA (0x1<< 6) - -#define MICBIAS1_SHORT_CURR_DET_MASK (0x3<< 4) -#define MICBIAS1_SHORT_CURR_DET_600UA (0x0<< 4) -#define MICBIAS1_SHORT_CURR_DET_1500UA (0x1<< 4) -#define MICBIAS1_SHORT_CURR_DET_2000UA (0x2<< 4) - -#define MICBIAS2_VOLT_CTRL_MASK (0x1<< 3) -#define MICBIAS2_VOLT_CTRL_90P (0x0<< 3) -#define MICBIAS2_VOLT_CTRL_75P (0x1<< 3) - -#define MICBIAS2_S_C_DET_MASK (0x1<< 2) -#define MICBIAS2_S_C_DET_DIS (0x0<< 2) -#define MICBIAS2_S_C_DET_ENA (0x1<< 2) - -#define MICBIAS2_SHORT_CURR_DET_MASK (0x3) -#define MICBIAS2_SHORT_CURR_DET_600UA (0x0) -#define MICBIAS2_SHORT_CURR_DET_1500UA (0x1) -#define MICBIAS2_SHORT_CURR_DET_2000UA (0x2) - - -//Digital Microphone Control(0x24) -#define DMIC_ENA_MASK (0x1<<15) -#define DMIC_ENA (0x1<<15) //use DMIC to ADC Digital filter -#define DMIC_DIS (0x0<<15) //use ADC mixer to ADC Digital filter - -#define DMIC_L_CH_MUTE_MASK (0x1<<13) -#define DMIC_L_CH_UNMUTE (0x0<<13) -#define DMIC_L_CH_MUTE (0x1<<13) - -#define DMIC_R_CH_MUTE_MASK (0x1<<12) -#define DMIC_R_CH_UNMUTE (0x0<<12) -#define DMIC_R_CH_MUTE (0x1<<12) - -#define DMIC_L_CH_LATCH_MASK (0x1<< 9) -#define DMIC_L_CH_LATCH_RISING (0x1<< 9) -#define DMIC_L_CH_LATCH_FALLING (0x0<< 9) - -#define DMIC_R_CH_LATCH_MASK (0x1<< 8) -#define DMIC_R_CH_LATCH_RISING (0x1<< 8) -#define DMIC_R_CH_LATCH_FALLING (0x0<< 8) - -#define DMIC_CLK_CTRL_MASK (0x3<<4) -#define DMIC_CLK_CTRL_TO_128FS (0x0<<4) -#define DMIC_CLK_CTRL_TO_64FS (0x1<<4) -#define DMIC_CLK_CTRL_TO_32FS (0x2<<4) - - -//Speaker Mixer Control(0x28) -#define M_RECMIXER_L_TO_SPKMIXER_L (0x1<<15) //Mute Left RecMixer to Left Speaker Mixer -#define M_MIC1_P_TO_SPKMIXER_L (0x1<<14) //Mute MIC1 Positive to Left Speaker Mixer -#define M_DAC_L_TO_SPKMIXER_L (0x1<<13) //Mute Left Dac to Left Speaker Mixer -#define M_OUTMIXER_L_TO_SPKMIXER_L (0x1<<12) //Mute Left OutMixer to Left Speaker Mixer - -#define M_RECMIXER_R_TO_SPKMIXER_R (0x1<< 7) //Mute Right RecMixer to Right Speaker Mixer -#define M_MIC2_P_TO_SPKMIXER_R (0x1<< 6) //Mute MIC1 Positive to Right Speaker Mixer -#define M_DAC_R_TO_SPKMIXER_R (0x1<< 5) //Mute Right Dac to Right Speaker Mixer -#define M_OUTMIXER_R_TO_SPKMIXER_R (0x1<< 4) //Mute Right OutMixer to Right Speaker Mixer - - - -//Speaker/Mono Output Control(0x2A) -#define M_SPKVOL_L_TO_SPOL_MIXER (0x1<<15) //Mute Left Speaker Volume to SPOL Mixer -#define M_SPKVOL_R_TO_SPOL_MIXER (0x1<<14) //Mute Right Speaker Volume to SPOL Mixer -#define M_SPKVOL_L_TO_SPOR_MIXER (0x1<<13) //Mute Left Speaker Volume to SPOR Mixer -#define M_SPKVOL_R_TO_SPOR_MIXER (0x1<<12) //Mute Right Speaker Volume to SPOR Mixer -#define M_OUTVOL_L_TO_MONOMIXER (0x1<<11) //Mute Left Output Volume to Mono Mixer -#define M_OUTVOL_R_TO_MONOMIXER (0x1<<10) //Mute Right Output Volume to Mono Mixer - - -//Speaker/Mono/HP Output Control(0x2C) -#define SPK_L_MUX_SEL_MASK (0x3<<14) //Left Speaker mux select Mask -#define SPK_L_MUX_SEL_SPKMIXER_L (0x0<<14) //Left Speaker mux select Speaker mixer left -#define SPK_L_MUX_SEL_MONO_IN (0x1<<14) //Left Speaker mux select MONO input -#define SPK_L_MUX_SEL_DAC_L (0x3<<14) //Left Speaker mux select Dac left - -#define SPK_R_MUX_SEL_MASK (0x3<<10) //Right Speaker mux select Mask -#define SPK_R_MUX_SEL_SPKMIXER_R (0x0<<10) //Right Speaker mux select Speaker mixer right -#define SPK_R_MUX_SEL_MONO_IN (0x1<<10) //Right Speaker mux select MONO input -#define SPK_R_MUX_SEL_DAC_R (0x3<<10) //Right Speaker mux select Dac right - -#define MONO_MUX_SEL_MASK (0x3<< 6) //Monoout mux select Mask -#define MONO_MUX_SEL_MONOMIXER (0x0<< 6) //Monoout mux select Mono Mixer -#define MONO_MUX_SEL_MONO_IN (0x1<< 6) //Monoout mux select MONO input - -#define HP_L_MUX_SEL_MASK (0x1<< 3) //HP left mux select Mask -#define HP_L_MUX_SEL_HPVOL_L (0x0<< 3) //HP left mux select left HP output volume -#define HP_L_MUX_SEL_DAC_L (0x1<< 3) //HP left mux select Dac left channel - -#define HP_R_MUX_SEL_MASK (0x1<< 2) //HP left mux select Mask -#define HP_R_MUX_SEL_HPVOL_R (0x0<< 2) //HP left mux select left HP output volume -#define HP_R_MUX_SEL_DAC_R (0x1<< 2) //HP left mux select Dac left channel - - -//Stereo I2S Serial Data Port Control(0x34) -#define SDP_MODE_SEL_MASK (0x1<<15) //Main I2S interface select MASK -#define SDP_MODE_SEL_MASTER (0x0<<15) //Main I2S interface select MASTER MODE -#define SDP_MODE_SEL_SLAVE (0x1<<15) //Main I2S interface select SLAVE MODE - -#define SDP_ADC_CPS_SEL_MASK (0x3<<10) //ADC Compress select Mask -#define SDP_ADC_CPS_SEL_OFF (0x0<<10) //ADC Compress select OFF -#define SDP_ADC_CPS_SEL_U_LAW (0x1<<10) //ADC Compress select u_law -#define SDP_ADC_CPS_SEL_A_LAW (0x2<<10) //ADC Compress select a_law - -#define SDP_DAC_CPS_SEL_MASK (0x3<< 8) //DAC Compress select Mask -#define SDP_DAC_CPS_SEL_OFF (0x0<< 8) //DAC Compress select OFF -#define SDP_DAC_CPS_SEL_U_LAW (0x1<< 8) //DAC Compress select u_law -#define SDP_DAC_CPS_SEL_A_LAW (0x2<< 8) //DAC Compress select a_law - -#define SDP_I2S_BCLK_POL_CTRL (0x1<<7) //0:Normal 1:Invert - -#define SDP_DAC_R_INV (0x1<<6) //0:Normal 1:Invert - -#define SDP_ADC_DATA_L_R_SWAP (0x1<<5) //0:ADC data appear at left phase of LRCK - //1:ADC data appear at right phase of LRCK -#define SDP_DAC_DATA_L_R_SWAP (0x1<<4) //0:DAC data appear at left phase of LRCK - //1:DAC data appear at right phase of LRCK -//Data Length Slection -#define SDP_I2S_DL_MASK (0x3<<2) //Stereo Serial Data Length mask -#define SDP_I2S_DL_16 (0x0<<2) //16 bits -#define SDP_I2S_DL_20 (0x1<<2) //20 bits -#define SDP_I2S_DL_24 (0x2<<2) //24 bits -#define SDP_I2S_DL_8 (0x3<<2) //8 bits - -//PCM Data Format Selection -#define SDP_I2S_DF_MASK (0x3) //main i2s Data Format mask -#define SDP_I2S_DF_I2S (0x0) //I2S FORMAT -#define SDP_I2S_DF_LEFT (0x1) //Left JUSTIFIED -#define SDP_I2S_DF_PCM_A (0x2) //PCM format A -#define SDP_I2S_DF_PCM_B (0x3) //PCM format B - -//Stereo AD/DA Clock Control(0x38h) -#define I2S_PRE_DIV_MASK (0x7<<13) -#define I2S_PRE_DIV_1 (0x0<<13) //DIV 1 -#define I2S_PRE_DIV_2 (0x1<<13) //DIV 2 -#define I2S_PRE_DIV_4 (0x2<<13) //DIV 4 -#define I2S_PRE_DIV_8 (0x3<<13) //DIV 8 -#define I2S_PRE_DIV_16 (0x4<<13) //DIV 16 -#define I2S_PRE_DIV_32 (0x5<<13) //DIV 32 - -#define I2S_LRCK_SEL_N_BCLK_MASK (0x1<<12) //CLOCK RELATIVE OF BCLK AND LCRK -#define I2S_LRCK_SEL_64_BCLK (0x0<<12) //64FS -#define I2S_LRCK_SEL_32_BCLK (0x1<<12) //32FS - -#define DAC_OSR_SEL_MASK (0x3<<10) -#define DAC_OSR_SEL_128FS (0x3<<10) -#define DAC_OSR_SEL_64FS (0x3<<10) -#define DAC_OSR_SEL_32FS (0x3<<10) -#define DAC_OSR_SEL_16FS (0x3<<10) - -#define ADC_OSR_SEL_MASK (0x3<< 8) -#define ADC_OSR_SEL_128FS (0x3<< 8) -#define ADC_OSR_SEL_64FS (0x3<< 8) -#define ADC_OSR_SEL_32FS (0x3<< 8) -#define ADC_OSR_SEL_16FS (0x3<< 8) - -#define ADDA_FILTER_CLK_SEL_256FS (0<<7) //256FS -#define ADDA_FILTER_CLK_SEL_384FS (1<<7) //384FS - - - -//Power managment addition 1 (0x3A),0:Disable,1:Enable -#define PWR_MAIN_I2S_EN (0x1<<15) -#define PWR_CLASS_D (0x1<<12) -#define PWR_ADC_L_CLK (0x1<<11) -#define PWR_ADC_R_CLK (0x1<<10) -#define PWR_DAC_L_CLK (0x1<< 9) -#define PWR_DAC_R_CLK (0x1<< 8) -#define PWR_DAC_REF (0x1<< 7) -#define PWR_DAC_L_TO_MIXER (0x1<< 6) -#define PWR_DAC_R_TO_MIXER (0x1<<5) - - -//Power managment addition 2 (0x3B),0:Disable,1:Enable -#define PWR_OUTMIXER_L (0x1<<15) -#define PWR_OUTMIXER_R (0x1<<14) -#define PWR_SPKMIXER_L (0x1<<13) -#define PWR_SPKMIXER_R (0x1<<12) -#define PWR_RECMIXER_L (0x1<<11) -#define PWR_RECMIXER_R (0x1<<10) -#define PWR_MIC1_BOOT_GAIN (0x1<< 5) -#define PWR_MIC2_BOOT_GAIN (0x1<< 4) -#define PWR_MICBIAS1_VOL (0x1<< 3) -#define PWR_MICBIAS2_VOL (0x1<< 2) -#define PWR_PLL (0x1<< 1) - - -//Power managment addition 3(0x3C),0:Disable,1:Enable -#define PWR_VREF (0x1<<15) -#define PWR_FAST_VREF_CTRL (0x1<<14) -#define PWR_MAIN_BIAS (0x1<<13) -#define PWR_AXO1MIXER (0x1<<11) -#define PWR_AXO2MIXER (0x1<<10) -#define PWR_MONOMIXER (0x1<< 9) -#define PWR_MONO_DEPOP_DIS (0x1<< 8) -#define PWR_MONO_AMP_EN (0x1<< 7) -#define PWR_CHARGE_PUMP (0x1<<4) -#define PWR_HP_L_AMP (0x1<<3) -#define PWR_HP_R_AMP (0x1<<2) -#define PWR_HP_DEPOP_DIS (0x1<<1) -#define PWR_HP_AMP_DRIVING (0x1) - - -//Power managment addition 4(0x3E),0:Disable,1:Enable -#define PWR_SPK_L_VOL (0x1<<15) -#define PWR_SPK_R_VOL (0x1<<14) -#define PWR_LOUT_VOL (0x1<<13) -#define PWR_ROUT_VOL (0x1<<12) -#define PWR_HP_L_OUT_VOL (0x1<<11) -#define PWR_HP_R_OUT_VOL (0x1<<10) -#define PWR_AXIL_IN_VOL (0x1<< 9) -#define PWR_AXIR_IN_VOL (0x1<< 8) -#define PWR_MONO_IN_P_VOL (0x1<< 7) -#define PWR_MONO_IN_N_VOL (0x1<< 6) - - -//General Purpose Control Register(0x40) -#define SPK_AMP_AUTO_RATIO_EN (0x1<<15) //Speaker Amplifier Auto Ratio Gain Control - -#define SPK_AMP_RATIO_CTRL_MASK (0x7<<12) -#define SPK_AMP_RATIO_CTRL_2_34 (0x0<<12) //7.40DB -#define SPK_AMP_RATIO_CTRL_1_99 (0x1<<12) //5.99DB -#define SPK_AMP_RATIO_CTRL_1_68 (0x2<<12) //4.50DB -#define SPK_AMP_RATIO_CTRL_1_56 (0x3<<12) //3.86DB -#define SPK_AMP_RATIO_CTRL_1_44 (0x4<<12) //3.16DB -#define SPK_AMP_RATIO_CTRL_1_27 (0x5<<12) //2.10DB -#define SPK_AMP_RATIO_CTRL_1_09 (0x6<<12) //0.80DB -#define SPK_AMP_RATIO_CTRL_1_00 (0x7<<12) //0.00DB - -#define STEREO_DAC_HI_PASS_FILT_EN (0x1<<11) //Stereo DAC high pass filter enable -#define STEREO_ADC_HI_PASS_FILT_EN (0x1<<10) //Stereo ADC high pass filter enable - -#define ADC_WIND_FILT_MASK (0x3<<4) //Select ADC Wind Filter Clock type -#define ADC_WIND_FILT_8_16_32K (0x0<<4) //8/16/32k -#define ADC_WIND_FILT_11_22_44K (0x1<<4) //11/22/44k -#define ADC_WIND_FILT_12_24_48K (0x2<<4) //12/24/48k - -#define ADC_WIND_FILT_EN (0x1<<3) //Enable ADC Wind Filter - -#define ADC_WIND_CNR_FREQ_MASK (0x7<<0) //SelectADC Wind Filter Corner Frequency -#define ADC_WIND_CNR_FREQ_82_113_122 (0x0<<0) //82/113/122 Hz -#define ADC_WIND_CNR_FREQ_102_141_153 (0x1<<0) //102/141/153 Hz -#define ADC_WIND_CNR_FREQ_131_180_156 (0x2<<0) //131/180/156 Hz -#define ADC_WIND_CNR_FREQ_163_225_245 (0x3<<0) //163/225/245 Hz -#define ADC_WIND_CNR_FREQ_204_281_306 (0x4<<0) //204/281/306 Hz -#define ADC_WIND_CNR_FREQ_261_360_392 (0x5<<0) //261/360/392 Hz -#define ADC_WIND_CNR_FREQ_327_450_490 (0x6<<0) //327/450/490 Hz -#define ADC_WIND_CNR_FREQ_408_563_612 (0x7<<0) //408/563/612 Hz - - -//Global Clock Control Register(0x42) -#define SYSCLK_SOUR_SEL_MASK (0x1<<14) -#define SYSCLK_SOUR_SEL_MCLK (0x0<<14) //system Clock source from MCLK -#define SYSCLK_SOUR_SEL_PLL (0x1<<14) //system Clock source from PLL -#define SYSCLK_SOUR_SEL_PLL_TCK (0x2<<14) //system Clock source from PLL track - -#define PLLCLK_SOUR_SEL_MCLK (0x0<<12) //PLL clock source from MCLK -#define PLLCLK_SOUR_SEL_BITCLK (0x1<<12) //PLL clock source from BITCLK - -#define PLLCLK_PRE_DIV1 (0x0<<11) //DIV 1 -#define PLLCLK_PRE_DIV2 (0x1<<11) //DIV 2 - -//PLL Control(0x44) - -#define PLL_CTRL_M_VAL(m) ((m)&0xf) //M code for analog PLL -#define PLL_CTRL_K_VAL(k) (((k)&0x7)<<4) //K code for analog PLL -#define PLL_CTRL_N_VAL(n) (((n)&0xff)<<8) //N code for analog PLL - - -//GPIO Pin Configuration(0x4C) -#define GPIO_PIN_FUN_SEL_MASK (0x1<<15) -#define GPIO_PIN_FUN_SEL_IRQ (0x1<<15) //GPIO pin SELECT IRQ -#define GPIO_PIN_FUN_SEL_GPIO_DIMC (0x0<<15) //GPIO PIN SELECT GPIO_DMIC - - -#define GPIO_DMIC_FUN_SEL_MASK (0x1<<3) -#define GPIO_DMIC_FUN_SEL_DIMC (0x1<<3) //GPIO pin SELECT DMIC -#define GPIO_DMIC_FUN_SEL_GPIO (0x0<<3) //GPIO PIN SELECT GPIO - -#define GPIO_PIN_CON_MASK (0x1<<2) -#define GPIO_PIN_SET_INPUT (0x0<<2) //GPIO pin select input -#define GPIO_PIN_SET_OUTPUT (0x1<<2) //GPIO pin select output - -//De-POP function Control 1(0x54) -#define POW_ON_SOFT_GEN (0x1<<15) //POWER ON SOFT GENERATOR -#define EN_MUTE_UNMUTE_DEPOP (0x1<<14) //Enable mute/unmute depop -#define EN_DEPOP2_FOR_HP (0x1<<7) //Enable depop 2 for HP -#define PD_HPAMP_L_ST_UP (0x1<<5) //Power Down HPAMP_L Starts Up Signal -#define PD_HPAMP_R_ST_UP (0x1<<4) //Power Down HPAMP_R Starts Up Signal -#define EN_HP_L_M_UN_MUTE_DEPOP (0x1<<1) //Enable left HP mute/unmute depop -#define EN_HP_R_M_UN_MUTE_DEPOP (0x1<<0) //Enable right HP mute/unmute depop - -//De-POP Fnction Control(0x56) -#define ENA_CAP_FREE_DEPOP (0x1<<14) //enable depop for Capfree block - - -//Jack Detect Control Register(0x5A) -#define JD_USE_MASK (0x3<<14) //JD Pin select -#define JD_USE_JD2 (0x3<<14) //select JD2 -#define JD_USE_JD1 (0x2<<14) //select JD1 -#define JD_USE_GPIO (0x1<<14) //select GPIO -#define JD_OFF (0x0<<14) //off - -#define JD_HP_EN (0x1<<11) //JD trigger enable for HP -#define JD_HP_TRI_MASK (0x1<<10) //Trigger mask -#define JD_HP_TRI_HI (0x1<<10) //high trigger -#define JD_HP_TRI_LO (0x1<<10) //low trigger - -#define JD_SPK_L_EN (0x1<<9) //JD trigger enable for speaker LP/LN -#define JD_SPK_L_TRI_MASK (0x1<<8) //Trigger mask -#define JD_SPK_L_TRI_HI (0x1<<8) //high trigger -#define JD_SPK_L_TRI_LO (0x0<<8) //low trigger - -#define JD_SPK_R_EN (0x1<<7) //JD trigger enable for speaker RP/RN -#define JD_SPK_R_TRI_MASK (0x1<<6) //Trigger mask -#define JD_SPK_R_TRI_HI (0x1<<6) //high trigger -#define JD_SPK_R_TRI_LO (0x0<<6) //low trigger - -#define JD_MONO_EN (0x1<<5) //JD trigger enable for monoout -#define JD_MONO_TRI_MASK (0x1<<4) //Trigger mask -#define JD_MONO_TRI_HI (0x1<<4) //high trigger -#define JD_MONO_TRI_LO (0x0<<4) //low trigger - -#define JD_AUX_1_EN (0x1<<3) //JD trigger enable for Lout -#define JD_AUX_1_MASK (0x1<<2) //Trigger mask -#define JD_AUX_1_TRI_HI (0x1<<2) //high trigger -#define JD_AUX_1_TRI_LO (0x0<<2) //low trigger - -#define JD_AUX_2_EN (0x1<<1) //JD trigger enable for Rout - -#define JD_AUX_2_MASK (0x1<<0) //Trigger mask -#define JD_AUX_2_TRI_HI (0x1<<0) //high trigger -#define JD_AUX_2_TRI_LO (0x0<<0) //low trigger - - -////ALC CONTROL 1(0x64) -#define ALC_ATTACK_RATE_MASK (0x1F<<8) //select ALC attack rate -#define ALC_RECOVERY_RATE_MASK (0x1F<<0) //select ALC Recovery rate - - -////ALC CONTROL 2(0x65) -#define ALC_COM_NOISE_GATE_MASK (0xF<<0) //select Compensation gain for Noise gate function - - -////ALC CONTROL 3(0x66) -#define ALC_FUN_MASK (0x3<<14) //select ALC path -#define ALC_FUN_DIS (0x0<<14) //disable -#define ALC_ENA_DAC_PATH (0x1<<14) //DAC path -#define ALC_ENA_ADC_PATH (0x3<<14) //ADC path - -#define ALC_PARA_UPDATE (0x1<<13) //update ALC parameter - -#define ALC_LIMIT_LEVEL_MASK (0x1F<<8) //ALC limit level - -#define ALC_NOISE_GATE_FUN_MASK (0x1<<7) //ALC noise gate function -#define ALC_NOISE_GATE_FUN_DIS (0x0<<7) //disable -#define ALC_NOISE_GATE_FUN_ENA (0x1<<7) //enable - -#define ALC_NOISE_GATE_H_D_MASK (0x1<<6) //ALC noise gate hold data function -#define ALC_NOISE_GATE_H_D_DIS (0x0<<6) //disable -#define ALC_NOISE_GATE_H_D_ENA (0x1<<6) //enable - -//Psedueo Stereo & Spatial Effect Block Control(0x68) -#define SPATIAL_CTRL_EN (0x1<<15) //enable Spatial effect -#define ALL_PASS_FILTER_EN (0x1<<14) //enable all pass filter -#define PSEUDO_STEREO_EN (0x1<<13) //enable pseudo stereo block -#define STEREO_EXPENSION_EN (0x1<<12) //enable stereo expansion block - -#define GAIN_3D_PARA_MASK (0x3<<6) //3D gain parameter -#define GAIN_3D_PARA_1_00 (0x0<<6) //3D gain 1.0 -#define GAIN_3D_PARA_1_50 (0x1<<6) //3D gain 1.5 -#define GAIN_3D_PARA_2_00 (0x2<<6) //3D gain 2.0 - -#define RATIO_3D_MASK (0x3<<4) //3D ratio parameter -#define RATIO_3D_0_0 (0x0<<4) //3D ratio 0.0 -#define RATIO_3D_0_66 (0x1<<4) //3D ratio 0.66 -#define RATIO_3D_1_0 (0x2<<4) //3D ratio 1.0 - -#define APF_FUN_SLE_MASK (0x3<<0) //select samplerate for all pass filter -#define APF_FUN_SEL_48K (0x3<<0) //select 48k -#define APF_FUN_SEL_44_1K (0x2<<0) //select 44.1k -#define APF_FUN_SEL_32K (0x1<<0) //select 32k -#define APF_FUN_DIS (0x0<<0) //disable - - -//EQ CONTROL 1(0x6E) - -#define HW_EQ_PATH_SEL_MASK (0x1<<15) //HW EQ FUN SEL -#define HW_EQ_PATH_SEL_DAC (0x0<<15) //HW EQ FOR DAC PATH -#define HW_EQ_PATH_SEL_ADC (0x1<<15) //HW EQ FOR ADC PATH - -#define HW_EQ_UPDATE_CTRL (0x1<<14) //HW EQ Update CTRL - -#define EN_HW_EQ_HPF2 (0x1<<5) //EQ High Pass Filter 2 Control -#define EN_HW_EQ_HPF1 (0x1<<4) //EQ High Pass Filter 1 Control -#define EN_HW_EQ_BP3 (0x1<<3) //EQ Band-3 Control -#define EN_HW_EQ_BP2 (0x1<<2) //EQ Band-2 Control -#define EN_HW_EQ_BP1 (0x1<<1) //EQ Band-1 Control -#define EN_HW_EQ_LPF (0x1<<0) //EQ Low Pass Filter Control - -#define REALTEK_HWDEP 0 -struct rt5631_setup_data { - int i2c_address; - int i2c_bus; -}; - - -extern struct snd_soc_dai rt5631_dai[]; -extern struct snd_soc_codec_device soc_codec_dev_rt5631; - - -#endif //__RTCODEC5631_H__ +#ifndef __RTCODEC5631_H__ +#define __RTCODEC5631_H__ + + +#define RT5631_RESET 0x00 +#define RT5631_SPK_OUT_VOL 0x02 +#define RT5631_HP_OUT_VOL 0x04 +#define RT5631_MONO_AXO_1_2_VOL 0x06 +#define RT5631_AUX_IN_VOL 0x0A +#define RT5631_STEREO_DAC_VOL_1 0x0C +#define RT5631_MIC_CTRL_1 0x0E +#define RT5631_STEREO_DAC_VOL_2 0x10 +#define RT5631_ADC_CTRL_1 0x12 +#define RT5631_ADC_REC_MIXER 0x14 +#define RT5631_ADC_CTRL_2 0x16 +#define RT5631_OUTMIXER_L_CTRL 0x1A +#define RT5631_OUTMIXER_R_CTRL 0x1C +#define RT5631_AXO1MIXER_CTRL 0x1E +#define RT5631_AXO2MIXER_CTRL 0x20 +#define RT5631_MIC_CTRL_2 0x22 +#define RT5631_DIG_MIC_CTRL 0x24 +#define RT5631_MONO_INPUT_VOL 0x26 +#define RT5631_SPK_MIXER_CTRL 0x28 +#define RT5631_SPK_MONO_OUT_CTRL 0x2A +#define RT5631_SPK_MONO_HP_OUT_CTRL 0x2C +#define RT5631_SDP_CTRL 0x34 +#define RT5631_STEREO_AD_DA_CLK_CTRL 0x38 +#define RT5631_PWR_MANAG_ADD1 0x3A +#define RT5631_PWR_MANAG_ADD2 0x3B +#define RT5631_PWR_MANAG_ADD3 0x3C +#define RT5631_PWR_MANAG_ADD4 0x3E +#define RT5631_GEN_PUR_CTRL_REG 0x40 +#define RT5631_GLOBAL_CLK_CTRL 0x42 +#define RT5631_PLL_CTRL 0x44 +#define RT5631_INT_ST_IRQ_CTRL_1 0x48 +#define RT5631_INT_ST_IRQ_CTRL_2 0x4A +#define RT5631_GPIO_CTRL 0x4C +#define RT5631_MISC_CTRL 0x52 +#define RT5631_DEPOP_FUN_CTRL_1 0x54 +#define RT5631_DEPOP_FUN_CTRL_2 0x56 +#define RT5631_JACK_DET_CTRL 0x5A +#define RT5631_SOFT_VOL_CTRL 0x5C +#define RT5631_ALC_CTRL_1 0x64 +#define RT5631_ALC_CTRL_2 0x65 +#define RT5631_ALC_CTRL_3 0x66 +#define RT5631_PSEUDO_SPATL_CTRL 0x68 +#define RT5631_INDEX_ADD 0x6A +#define RT5631_INDEX_DATA 0x6C +#define RT5631_EQ_CTRL 0x6E +#define RT5631_VENDOR_ID1 0x7C +#define RT5631_VENDOR_ID2 0x7E + +/* Index of Codec Private Register definition */ +#define RT5631_EQ_BW_LOP 0x00 +#define RT5631_EQ_GAIN_LOP 0x01 +#define RT5631_EQ_FC_BP1 0x02 +#define RT5631_EQ_BW_BP1 0x03 +#define RT5631_EQ_GAIN_BP1 0x04 +#define RT5631_EQ_FC_BP2 0x05 +#define RT5631_EQ_BW_BP2 0x06 +#define RT5631_EQ_GAIN_BP2 0x07 +#define RT5631_EQ_FC_BP3 0x08 +#define RT5631_EQ_BW_BP3 0x09 +#define RT5631_EQ_GAIN_BP3 0x0a +#define RT5631_EQ_BW_HIP 0x0b +#define RT5631_EQ_GAIN_HIP 0x0c +#define RT5631_EQ_HPF_A1 0x0d +#define RT5631_EQ_HPF_A2 0x0e +#define RT5631_EQ_HPF_GAIN 0x0f +#define RT5631_EQ_PRE_VOL_CTRL 0x11 +#define RT5631_EQ_POST_VOL_CTRL 0x12 +#define RT5631_TEST_MODE_CTRL 0x39 +#define RT5631_CP_INTL_REG2 0x45 +#define RT5631_ADDA_MIXER_INTL_REG3 0x52 +#define RT5631_SPK_INTL_CTRL 0x56 + + +/* global definition */ +#define RT_L_MUTE (0x1 << 15) +#define RT_R_MUTE (0x1 << 7) + +/* Speaker Output Control(0x02) */ +#define SPK_L_VOL_SEL_MASK (0x1 << 14) +#define SPK_L_VOL_SEL_VMID (0x0 << 14) +#define SPK_L_VOL_SEL_SPKMIX_L (0x1 << 14) +#define SPK_R_VOL_SEL_MASK (0x1 << 6) +#define SPK_R_VOL_SEL_VMID (0x0 << 6) +#define SPK_R_VOL_SEL_SPKMIX_R (0x1 << 6) + +/* Headphone Output Control(0x04) */ +#define HP_L_VOL_SEL_MASK (0x1 << 14) +#define HP_L_VOL_SEL_VMID (0x0 << 14) +#define HP_L_VOL_SEL_OUTMIX_L (0x1 << 14) +#define HP_R_VOL_SEL_MASK (0x1 << 6) +#define HP_R_VOL_SEL_VMID (0x0 << 6) +#define HP_R_VOL_SEL_OUTMIX_R (0x1 << 6) + +/* Output Control for AUXOUT/MONO(0x06) */ +#define AUXOUT_1_VOL_SEL_MASK (0x1 << 14) +#define AUXOUT_1_VOL_SEL_VMID (0x0 << 14) +#define AUXOUT_1_VOL_SEL_OUTMIX_L (0x1 << 14) +#define MUTE_MONO (0x1 << 13) +#define AUXOUT_2_VOL_SEL_MASK (0x1 << 6) +#define AUXOUT_2_VOL_SEL_VMID (0x0 << 6) +#define AUXOUT_2_VOL_SEL_OUTMIX_R (0x1 << 6) + +/* Microphone Input Control 1(0x0E) */ +#define MIC1_DIFF_INPUT_CTRL (0x1 << 15) +#define MIC2_DIFF_INPUT_CTRL (0x1 << 7) + +/* ADC Recording Mixer Control(0x14) */ +#define M_OUTMIXER_L_TO_RECMIXER_L (0x1 << 15) +#define M_MIC1_TO_RECMIXER_L (0x1 << 14) +#define M_AXIL_TO_RECMIXER_L (0x1 << 13) +#define M_MONO_IN_TO_RECMIXER_L (0x1 << 12) +#define M_OUTMIXER_R_TO_RECMIXER_R (0x1 << 7) +#define M_MIC2_TO_RECMIXER_R (0x1 << 6) +#define M_AXIR_TO_RECMIXER_R (0x1 << 5) +#define M_MONO_IN_TO_RECMIXER_R (0x1 << 4) + +/* Left Output Mixer Control(0x1A) */ +#define M_RECMIXER_L_TO_OUTMIXER_L (0x1 << 15) +#define M_RECMIXER_R_TO_OUTMIXER_L (0x1 << 14) +#define M_DAC_L_TO_OUTMIXER_L (0x1 << 13) +#define M_MIC1_TO_OUTMIXER_L (0x1 << 12) +#define M_MIC2_TO_OUTMIXER_L (0x1 << 11) +#define M_MONO_IN_P_TO_OUTMIXER_L (0x1 << 10) +#define M_AXIL_TO_OUTMIXER_L (0x1 << 9) +#define M_AXIR_TO_OUTMIXER_L (0x1 << 8) + +/* Right Output Mixer Control(0x1C) */ +#define M_RECMIXER_L_TO_OUTMIXER_R (0x1 << 15) +#define M_RECMIXER_R_TO_OUTMIXER_R (0x1 << 14) +#define M_DAC_R_TO_OUTMIXER_R (0x1 << 13) +#define M_MIC1_TO_OUTMIXER_R (0x1 << 12) +#define M_MIC2_TO_OUTMIXER_R (0x1 << 11) +#define M_MONO_IN_N_TO_OUTMIXER_R (0x1 << 10) +#define M_AXIL_TO_OUTMIXER_R (0x1 << 9) +#define M_AXIR_TO_OUTMIXER_R (0x1 << 8) + +/* Lout Mixer Control(0x1E) */ +#define M_MIC1_TO_AXO1MIXER (0x1 << 15) +#define M_MIC2_TO_AXO1MIXER (0x1 << 11) +#define M_OUTMIXER_L_TO_AXO1MIXER (0x1 << 7) +#define M_OUTMIXER_R_TO_AXO1MIXER (0x1 << 6) + +/* Rout Mixer Control(0x20) */ +#define M_MIC1_TO_AXO2MIXER (0x1 << 15) +#define M_MIC2_TO_AXO2MIXER (0x1 << 11) +#define M_OUTMIXER_L_TO_AXO2MIXER (0x1 << 7) +#define M_OUTMIXER_R_TO_AXO2MIXER (0x1 << 6) + +/* Micphone Input Control 2(0x22) */ +#define MIC_BIAS_90_PRECNET_AVDD 1 +#define MIC_BIAS_75_PRECNET_AVDD 2 + +#define MIC1_BOOST_CTRL_MASK (0xf << 12) +#define MIC1_BOOST_CTRL_BYPASS (0x0 << 12) +#define MIC1_BOOST_CTRL_20DB (0x1 << 12) +#define MIC1_BOOST_CTRL_24DB (0x2 << 12) +#define MIC1_BOOST_CTRL_30DB (0x3 << 12) +#define MIC1_BOOST_CTRL_35DB (0x4 << 12) +#define MIC1_BOOST_CTRL_40DB (0x5 << 12) +#define MIC1_BOOST_CTRL_34DB (0x6 << 12) +#define MIC1_BOOST_CTRL_50DB (0x7 << 12) +#define MIC1_BOOST_CTRL_52DB (0x8 << 12) + +#define MIC2_BOOST_CTRL_MASK (0xf << 8) +#define MIC2_BOOST_CTRL_BYPASS (0x0 << 8) +#define MIC2_BOOST_CTRL_20DB (0x1 << 8) +#define MIC2_BOOST_CTRL_24DB (0x2 << 8) +#define MIC2_BOOST_CTRL_30DB (0x3 << 8) +#define MIC2_BOOST_CTRL_35DB (0x4 << 8) +#define MIC2_BOOST_CTRL_40DB (0x5 << 8) +#define MIC2_BOOST_CTRL_34DB (0x6 << 8) +#define MIC2_BOOST_CTRL_50DB (0x7 << 8) +#define MIC2_BOOST_CTRL_52DB (0x8 << 8) + +#define MICBIAS1_VOLT_CTRL_MASK (0x1 << 7) +#define MICBIAS1_VOLT_CTRL_90P (0x0 << 7) +#define MICBIAS1_VOLT_CTRL_75P (0x1 << 7) + +#define MICBIAS1_S_C_DET_MASK (0x1 << 6) +#define MICBIAS1_S_C_DET_DIS (0x0 << 6) +#define MICBIAS1_S_C_DET_ENA (0x1 << 6) + +#define MICBIAS1_SHORT_CURR_DET_MASK (0x3 << 4) +#define MICBIAS1_SHORT_CURR_DET_600UA (0x0 << 4) +#define MICBIAS1_SHORT_CURR_DET_1500UA (0x1 << 4) +#define MICBIAS1_SHORT_CURR_DET_2000UA (0x2 << 4) + +#define MICBIAS2_VOLT_CTRL_MASK (0x1 << 3) +#define MICBIAS2_VOLT_CTRL_90P (0x0 << 3) +#define MICBIAS2_VOLT_CTRL_75P (0x1 << 3) + +#define MICBIAS2_S_C_DET_MASK (0x1 << 2) +#define MICBIAS2_S_C_DET_DIS (0x0 << 2) +#define MICBIAS2_S_C_DET_ENA (0x1 << 2) + +#define MICBIAS2_SHORT_CURR_DET_MASK (0x3) +#define MICBIAS2_SHORT_CURR_DET_600UA (0x0) +#define MICBIAS2_SHORT_CURR_DET_1500UA (0x1) +#define MICBIAS2_SHORT_CURR_DET_2000UA (0x2) + + +/* Digital Microphone Control(0x24) */ +#define DMIC_ENA_MASK (0x1 << 15) +/* DMIC_ENA: DMIC to ADC Digital filter */ +#define DMIC_ENA (0x1 << 15) +/* DMIC_DIS: ADC mixer to ADC Digital filter */ +#define DMIC_DIS (0x0 << 15) + +#define DMIC_L_CH_MUTE_MASK (0x1 << 13) +#define DMIC_L_CH_UNMUTE (0x0 << 13) +#define DMIC_L_CH_MUTE (0x1 << 13) + +#define DMIC_R_CH_MUTE_MASK (0x1 << 12) +#define DMIC_R_CH_UNMUTE (0x0 << 12) +#define DMIC_R_CH_MUTE (0x1 << 12) + +#define DMIC_L_CH_LATCH_MASK (0x1 << 9) +#define DMIC_L_CH_LATCH_RISING (0x1 << 9) +#define DMIC_L_CH_LATCH_FALLING (0x0 << 9) + +#define DMIC_R_CH_LATCH_MASK (0x1 << 8) +#define DMIC_R_CH_LATCH_RISING (0x1 << 8) +#define DMIC_R_CH_LATCH_FALLING (0x0 << 8) + +#define DMIC_CLK_CTRL_MASK (0x3 << 4) +#define DMIC_CLK_CTRL_TO_128FS (0x0 << 4) +#define DMIC_CLK_CTRL_TO_64FS (0x1 << 4) +#define DMIC_CLK_CTRL_TO_32FS (0x2 << 4) + +/* Speaker Mixer Control(0x28) */ +#define M_RECMIXER_L_TO_SPKMIXER_L (0x1 << 15) +#define M_MIC1_P_TO_SPKMIXER_L (0x1 << 14) +#define M_DAC_L_TO_SPKMIXER_L (0x1 << 13) +#define M_OUTMIXER_L_TO_SPKMIXER_L (0x1 << 12) + +#define M_RECMIXER_R_TO_SPKMIXER_R (0x1 << 7) +#define M_MIC2_P_TO_SPKMIXER_R (0x1 << 6) +#define M_DAC_R_TO_SPKMIXER_R (0x1 << 5) +#define M_OUTMIXER_R_TO_SPKMIXER_R (0x1 << 4) + +/* Speaker/Mono Output Control(0x2A) */ +#define M_SPKVOL_L_TO_SPOL_MIXER (0x1 << 15) +#define M_SPKVOL_R_TO_SPOL_MIXER (0x1 << 14) +#define M_SPKVOL_L_TO_SPOR_MIXER (0x1 << 13) +#define M_SPKVOL_R_TO_SPOR_MIXER (0x1 << 12) +#define M_OUTVOL_L_TO_MONOMIXER (0x1 << 11) +#define M_OUTVOL_R_TO_MONOMIXER (0x1 << 10) + +/* Speaker/Mono/HP Output Control(0x2C) */ +#define SPK_L_MUX_SEL_MASK (0x3 << 14) +#define SPK_L_MUX_SEL_SPKMIXER_L (0x0 << 14) +#define SPK_L_MUX_SEL_MONO_IN (0x1 << 14) +#define SPK_L_MUX_SEL_DAC_L (0x3 << 14) + +#define SPK_R_MUX_SEL_MASK (0x3 << 10) +#define SPK_R_MUX_SEL_SPKMIXER_R (0x0 << 10) +#define SPK_R_MUX_SEL_MONO_IN (0x1 << 10) +#define SPK_R_MUX_SEL_DAC_R (0x3 << 10) + +#define MONO_MUX_SEL_MASK (0x3 << 6) +#define MONO_MUX_SEL_MONOMIXER (0x0 << 6) +#define MONO_MUX_SEL_MONO_IN (0x1 << 6) + +#define HP_L_MUX_SEL_MASK (0x1 << 3) +#define HP_L_MUX_SEL_HPVOL_L (0x0 << 3) +#define HP_L_MUX_SEL_DAC_L (0x1 << 3) + +#define HP_R_MUX_SEL_MASK (0x1 << 2) +#define HP_R_MUX_SEL_HPVOL_R (0x0 << 2) +#define HP_R_MUX_SEL_DAC_R (0x1 << 2) + +/* Stereo I2S Serial Data Port Control(0x34) */ +#define SDP_MODE_SEL_MASK (0x1 << 15) +#define SDP_MODE_SEL_MASTER (0x0 << 15) +#define SDP_MODE_SEL_SLAVE (0x1 << 15) + +#define SDP_ADC_CPS_SEL_MASK (0x3 << 10) +#define SDP_ADC_CPS_SEL_OFF (0x0 << 10) +#define SDP_ADC_CPS_SEL_U_LAW (0x1 << 10) +#define SDP_ADC_CPS_SEL_A_LAW (0x2 << 10) + +#define SDP_DAC_CPS_SEL_MASK (0x3 << 8) +#define SDP_DAC_CPS_SEL_OFF (0x0 << 8) +#define SDP_DAC_CPS_SEL_U_LAW (0x1 << 8) +#define SDP_DAC_CPS_SEL_A_LAW (0x2 << 8) +/* 0:Normal 1:Invert */ +#define SDP_I2S_BCLK_POL_CTRL (0x1 << 7) +/* 0:Normal 1:Invert */ +#define SDP_DAC_R_INV (0x1 << 6) +/* 0:ADC data appear at left phase of LRCK + * 1:ADC data appear at right phase of LRCK + */ +#define SDP_ADC_DATA_L_R_SWAP (0x1 << 5) +/* 0:DAC data appear at left phase of LRCK + * 1:DAC data appear at right phase of LRCK + */ +#define SDP_DAC_DATA_L_R_SWAP (0x1 << 4) + +/* Data Length Slection */ +#define SDP_I2S_DL_MASK (0x3 << 2) +#define SDP_I2S_DL_16 (0x0 << 2) +#define SDP_I2S_DL_20 (0x1 << 2) +#define SDP_I2S_DL_24 (0x2 << 2) +#define SDP_I2S_DL_8 (0x3 << 2) + +/* PCM Data Format Selection */ +#define SDP_I2S_DF_MASK (0x3) +#define SDP_I2S_DF_I2S (0x0) +#define SDP_I2S_DF_LEFT (0x1) +#define SDP_I2S_DF_PCM_A (0x2) +#define SDP_I2S_DF_PCM_B (0x3) + +/* Stereo AD/DA Clock Control(0x38h) */ +#define I2S_PRE_DIV_MASK (0x7 << 13) +#define I2S_PRE_DIV_1 (0x0 << 13) +#define I2S_PRE_DIV_2 (0x1 << 13) +#define I2S_PRE_DIV_4 (0x2 << 13) +#define I2S_PRE_DIV_8 (0x3 << 13) +#define I2S_PRE_DIV_16 (0x4 << 13) +#define I2S_PRE_DIV_32 (0x5 << 13) +/* CLOCK RELATIVE OF BCLK AND LCRK */ +#define I2S_LRCK_SEL_N_BCLK_MASK (0x1 << 12) +#define I2S_LRCK_SEL_64_BCLK (0x0 << 12) /* 64FS */ +#define I2S_LRCK_SEL_32_BCLK (0x1 << 12) /* 32FS */ + +#define DAC_OSR_SEL_MASK (0x3 << 10) +#define DAC_OSR_SEL_128FS (0x3 << 10) +#define DAC_OSR_SEL_64FS (0x3 << 10) +#define DAC_OSR_SEL_32FS (0x3 << 10) +#define DAC_OSR_SEL_16FS (0x3 << 10) + +#define ADC_OSR_SEL_MASK (0x3 << 8) +#define ADC_OSR_SEL_128FS (0x3 << 8) +#define ADC_OSR_SEL_64FS (0x3 << 8) +#define ADC_OSR_SEL_32FS (0x3 << 8) +#define ADC_OSR_SEL_16FS (0x3 << 8) + +#define ADDA_FILTER_CLK_SEL_256FS (0 << 7) /* 256FS */ +#define ADDA_FILTER_CLK_SEL_384FS (1 << 7) /* 384FS */ + +/* Power managment addition 1 (0x3A) */ +#define PWR_MAIN_I2S_EN (0x1 << 15) +#define PWR_CLASS_D (0x1 << 12) +#define PWR_ADC_L_CLK (0x1 << 11) +#define PWR_ADC_R_CLK (0x1 << 10) +#define PWR_DAC_L_CLK (0x1 << 9) +#define PWR_DAC_R_CLK (0x1 << 8) +#define PWR_DAC_REF (0x1 << 7) +#define PWR_DAC_L_TO_MIXER (0x1 << 6) +#define PWR_DAC_R_TO_MIXER (0x1 << 5) + +/* Power managment addition 2 (0x3B) */ +#define PWR_OUTMIXER_L (0x1 << 15) +#define PWR_OUTMIXER_R (0x1 << 14) +#define PWR_SPKMIXER_L (0x1 << 13) +#define PWR_SPKMIXER_R (0x1 << 12) +#define PWR_RECMIXER_L (0x1 << 11) +#define PWR_RECMIXER_R (0x1 << 10) +#define PWR_MIC1_BOOT_GAIN (0x1 << 5) +#define PWR_MIC2_BOOT_GAIN (0x1 << 4) +#define PWR_MICBIAS1_VOL (0x1 << 3) +#define PWR_MICBIAS2_VOL (0x1 << 2) +#define PWR_PLL (0x1 << 1) + +/* Power managment addition 3(0x3C) */ +#define PWR_VREF (0x1 << 15) +#define PWR_FAST_VREF_CTRL (0x1 << 14) +#define PWR_MAIN_BIAS (0x1 << 13) +#define PWR_AXO1MIXER (0x1 << 11) +#define PWR_AXO2MIXER (0x1 << 10) +#define PWR_MONOMIXER (0x1 << 9) +#define PWR_MONO_DEPOP_DIS (0x1 << 8) +#define PWR_MONO_AMP_EN (0x1 << 7) +#define PWR_CHARGE_PUMP (0x1 << 4) +#define PWR_HP_L_AMP (0x1 << 3) +#define PWR_HP_R_AMP (0x1 << 2) +#define PWR_HP_DEPOP_DIS (0x1 << 1) +#define PWR_HP_AMP_DRIVING (0x1) + +/* Power managment addition 4(0x3E) */ +#define PWR_SPK_L_VOL (0x1 << 15) +#define PWR_SPK_R_VOL (0x1 << 14) +#define PWR_LOUT_VOL (0x1 << 13) +#define PWR_ROUT_VOL (0x1 << 12) +#define PWR_HP_L_OUT_VOL (0x1 << 11) +#define PWR_HP_R_OUT_VOL (0x1 << 10) +#define PWR_AXIL_IN_VOL (0x1 << 9) +#define PWR_AXIR_IN_VOL (0x1 << 8) +#define PWR_MONO_IN_P_VOL (0x1 << 7) +#define PWR_MONO_IN_N_VOL (0x1 << 6) + +/* General Purpose Control Register(0x40) */ +#define SPK_AMP_AUTO_RATIO_EN (0x1 << 15) + +#define SPK_AMP_RATIO_CTRL_MASK (0x7 << 12) +#define SPK_AMP_RATIO_CTRL_2_34 (0x0 << 12) /* 7.40DB */ +#define SPK_AMP_RATIO_CTRL_1_99 (0x1 << 12) /* 5.99DB */ +#define SPK_AMP_RATIO_CTRL_1_68 (0x2 << 12) /* 4.50DB */ +#define SPK_AMP_RATIO_CTRL_1_56 (0x3 << 12) /* 3.86DB */ +#define SPK_AMP_RATIO_CTRL_1_44 (0x4 << 12) /* 3.16DB */ +#define SPK_AMP_RATIO_CTRL_1_27 (0x5 << 12) /* 2.10DB */ +#define SPK_AMP_RATIO_CTRL_1_09 (0x6 << 12) /* 0.80DB */ +#define SPK_AMP_RATIO_CTRL_1_00 (0x7 << 12) /* 0.00DB */ + +#define STEREO_DAC_HI_PASS_FILT_EN (0x1 << 11) +#define STEREO_ADC_HI_PASS_FILT_EN (0x1 << 10) +/* Select ADC Wind Filter Clock type */ +#define ADC_WIND_FILT_MASK (0x3 << 4) +#define ADC_WIND_FILT_8_16_32K (0x0 << 4) /* 8/16/32k */ +#define ADC_WIND_FILT_11_22_44K (0x1 << 4) /* 11/22/44k */ +#define ADC_WIND_FILT_12_24_48K (0x2 << 4) /* 12/24/48k */ +#define ADC_WIND_FILT_EN (0x1 << 3) +/* SelectADC Wind Filter Corner Frequency */ +#define ADC_WIND_CNR_FREQ_MASK (0x7 << 0) +#define ADC_WIND_CNR_FREQ_82_113_122 (0x0 << 0) /* 82/113/122 Hz */ +#define ADC_WIND_CNR_FREQ_102_141_153 (0x1 << 0) /* 102/141/153 Hz */ +#define ADC_WIND_CNR_FREQ_131_180_156 (0x2 << 0) /* 131/180/156 Hz */ +#define ADC_WIND_CNR_FREQ_163_225_245 (0x3 << 0) /* 163/225/245 Hz */ +#define ADC_WIND_CNR_FREQ_204_281_306 (0x4 << 0) /* 204/281/306 Hz */ +#define ADC_WIND_CNR_FREQ_261_360_392 (0x5 << 0) /* 261/360/392 Hz */ +#define ADC_WIND_CNR_FREQ_327_450_490 (0x6 << 0) /* 327/450/490 Hz */ +#define ADC_WIND_CNR_FREQ_408_563_612 (0x7 << 0) /* 408/563/612 Hz */ + +/* Global Clock Control Register(0x42) */ +#define SYSCLK_SOUR_SEL_MASK (0x1 << 14) +#define SYSCLK_SOUR_SEL_MCLK (0x0 << 14) +#define SYSCLK_SOUR_SEL_PLL (0x1 << 14) +#define SYSCLK_SOUR_SEL_PLL_TCK (0x2 << 14) + +#define PLLCLK_SOUR_SEL_MCLK (0x0 << 12) +#define PLLCLK_SOUR_SEL_BITCLK (0x1 << 12) + +#define PLLCLK_PRE_DIV1 (0x0 << 11) +#define PLLCLK_PRE_DIV2 (0x1 << 11) + +/* PLL Control(0x44) */ +#define PLL_CTRL_M_VAL(m) ((m)&0xf) +#define PLL_CTRL_K_VAL(k) (((k)&0x7) << 4) +#define PLL_CTRL_N_VAL(n) (((n)&0xff) << 8) + +/* GPIO Pin Configuration(0x4C) */ +#define GPIO_PIN_FUN_SEL_MASK (0x1 << 15) +#define GPIO_PIN_FUN_SEL_IRQ (0x1 << 15) +#define GPIO_PIN_FUN_SEL_GPIO_DIMC (0x0 << 15) + +#define GPIO_DMIC_FUN_SEL_MASK (0x1 << 3) +#define GPIO_DMIC_FUN_SEL_DIMC (0x1 << 3) /* GPIO pin SELECT DMIC */ +#define GPIO_DMIC_FUN_SEL_GPIO (0x0 << 3) /* GPIO PIN SELECT GPIO */ + +#define GPIO_PIN_CON_MASK (0x1 << 2) +#define GPIO_PIN_SET_INPUT (0x0 << 2) +#define GPIO_PIN_SET_OUTPUT (0x1 << 2) + +/* De-POP function Control 1(0x54) */ +#define POW_ON_SOFT_GEN (0x1 << 15) +#define EN_MUTE_UNMUTE_DEPOP (0x1 << 14) +#define EN_DEPOP2_FOR_HP (0x1 << 7) +/* Power Down HPAMP_L Starts Up Signal */ +#define PD_HPAMP_L_ST_UP (0x1 << 5) +/* Power Down HPAMP_R Starts Up Signal */ +#define PD_HPAMP_R_ST_UP (0x1 << 4) +/* Enable left HP mute/unmute depop */ +#define EN_HP_L_M_UN_MUTE_DEPOP (0x1 << 1) +/* Enable right HP mute/unmute depop */ +#define EN_HP_R_M_UN_MUTE_DEPOP (0x1 << 0) + +/* De-POP Fnction Control(0x56) */ +#define EN_ONE_BIT_DEPOP (0x1 << 15) +#define EN_CAP_FREE_DEPOP (0x1 << 14) + +/* Jack Detect Control Register(0x5A) */ +#define JD_USE_MASK (0x3 << 14) +#define JD_USE_JD2 (0x3 << 14) +#define JD_USE_JD1 (0x2 << 14) +#define JD_USE_GPIO (0x1 << 14) +#define JD_OFF (0x0 << 14) +/* JD trigger enable for HP */ +#define JD_HP_EN (0x1 << 11) +#define JD_HP_TRI_MASK (0x1 << 10) +#define JD_HP_TRI_HI (0x1 << 10) +#define JD_HP_TRI_LO (0x1 << 10) +/* JD trigger enable for speaker LP/LN */ +#define JD_SPK_L_EN (0x1 << 9) +#define JD_SPK_L_TRI_MASK (0x1 << 8) +#define JD_SPK_L_TRI_HI (0x1 << 8) +#define JD_SPK_L_TRI_LO (0x0 << 8) +/* JD trigger enable for speaker RP/RN */ +#define JD_SPK_R_EN (0x1 << 7) +#define JD_SPK_R_TRI_MASK (0x1 << 6) +#define JD_SPK_R_TRI_HI (0x1 << 6) +#define JD_SPK_R_TRI_LO (0x0 << 6) +/* JD trigger enable for monoout */ +#define JD_MONO_EN (0x1 << 5) +#define JD_MONO_TRI_MASK (0x1 << 4) +#define JD_MONO_TRI_HI (0x1 << 4) +#define JD_MONO_TRI_LO (0x0 << 4) +/* JD trigger enable for Lout */ +#define JD_AUX_1_EN (0x1 << 3) +#define JD_AUX_1_MASK (0x1 << 2) +#define JD_AUX_1_TRI_HI (0x1 << 2) +#define JD_AUX_1_TRI_LO (0x0 << 2) +/* JD trigger enable for Rout */ +#define JD_AUX_2_EN (0x1 << 1) +#define JD_AUX_2_MASK (0x1 << 0) +#define JD_AUX_2_TRI_HI (0x1 << 0) +#define JD_AUX_2_TRI_LO (0x0 << 0) + +/* ALC CONTROL 1(0x64) */ +#define ALC_ATTACK_RATE_MASK (0x1F << 8) +#define ALC_RECOVERY_RATE_MASK (0x1F << 0) + +/* ALC CONTROL 2(0x65) */ +/* select Compensation gain for Noise gate function */ +#define ALC_COM_NOISE_GATE_MASK (0xF << 0) + +/* ALC CONTROL 3(0x66) */ +#define ALC_FUN_MASK (0x3 << 14) +#define ALC_FUN_DIS (0x0 << 14) +#define ALC_ENA_DAC_PATH (0x1 << 14) +#define ALC_ENA_ADC_PATH (0x3 << 14) +#define ALC_PARA_UPDATE (0x1 << 13) +#define ALC_LIMIT_LEVEL_MASK (0x1F << 8) +#define ALC_NOISE_GATE_FUN_MASK (0x1 << 7) +#define ALC_NOISE_GATE_FUN_DIS (0x0 << 7) +#define ALC_NOISE_GATE_FUN_ENA (0x1 << 7) +/* ALC noise gate hold data function */ +#define ALC_NOISE_GATE_H_D_MASK (0x1 << 6) +#define ALC_NOISE_GATE_H_D_DIS (0x0 << 6) +#define ALC_NOISE_GATE_H_D_ENA (0x1 << 6) + +/* Psedueo Stereo & Spatial Effect Block Control(0x68) */ +#define SPATIAL_CTRL_EN (0x1 << 15) +#define ALL_PASS_FILTER_EN (0x1 << 14) +#define PSEUDO_STEREO_EN (0x1 << 13) +#define STEREO_EXPENSION_EN (0x1 << 12) +/* 3D gain parameter */ +#define GAIN_3D_PARA_MASK (0x3 << 6) +#define GAIN_3D_PARA_1_00 (0x0 << 6) /* 3D gain 1.0 */ +#define GAIN_3D_PARA_1_50 (0x1 << 6) /* 3D gain 1.5 */ +#define GAIN_3D_PARA_2_00 (0x2 << 6) /* 3D gain 2.0 */ +/* 3D ratio parameter */ +#define RATIO_3D_MASK (0x3 << 4) +#define RATIO_3D_0_0 (0x0 << 4) /* 3D ratio 0.0 */ +#define RATIO_3D_0_66 (0x1 << 4) /* 3D ratio 0.66 */ +#define RATIO_3D_1_0 (0x2 << 4) /* 3D ratio 1.0 */ +/* select samplerate for all pass filter */ +#define APF_FUN_SLE_MASK (0x3 << 0) +#define APF_FUN_SEL_48K (0x3 << 0) +#define APF_FUN_SEL_44_1K (0x2 << 0) +#define APF_FUN_SEL_32K (0x1 << 0) +#define APF_FUN_DIS (0x0 << 0) + +/* EQ CONTROL 1(0x6E) */ +#define HW_EQ_PATH_SEL_MASK (0x1 << 15) +#define HW_EQ_PATH_SEL_DAC (0x0 << 15) +#define HW_EQ_PATH_SEL_ADC (0x1 << 15) +#define HW_EQ_UPDATE_CTRL (0x1 << 14) + +#define EN_HW_EQ_HPF2 (0x1 << 5) +#define EN_HW_EQ_HPF1 (0x1 << 4) +#define EN_HW_EQ_BP3 (0x1 << 3) +#define EN_HW_EQ_BP2 (0x1 << 2) +#define EN_HW_EQ_BP1 (0x1 << 1) +#define EN_HW_EQ_LPF (0x1 << 0) + +#endif /* __RTCODEC5631_H__ */ diff --git a/sound/soc/rk29/Kconfig b/sound/soc/rk29/Kconfig index 2f1829bfbf69..433fb2ba9732 100755 --- a/sound/soc/rk29/Kconfig +++ b/sound/soc/rk29/Kconfig @@ -60,14 +60,14 @@ config SND_RK29_SOC_alc5621 help Say Y if you want to add support for SoC audio on rockchip with the alc5621. -config SND_RK29_SOC_alc5631 - tristate "SoC I2S Audio support for rockchip - alc5631" +config SND_RK29_SOC_RT5631 + tristate "SoC I2S Audio support for rockchip - RT5631" depends on SND_RK29_SOC && I2C_RK29 select SND_RK29_SOC_I2S - select SND_SOC_alc5631 + select SND_SOC_RT5631 help Say Y if you want to add support for SoC audio on rockchip - with the alc5631. + with the RT5631. config SND_RK29_SOC_RT5625 tristate "SoC I2S Audio support for rockchip - RT5625" @@ -105,7 +105,7 @@ config SND_RK29_SOC_RK1000 Say Y if you want to add support for SoC audio on rockchip with the RK1000. -if SND_RK29_SOC_WM8988 || SND_RK29_SOC_RK1000 || SND_RK29_SOC_WM8994 || SND_RK29_SOC_WM8900 || SND_RK29_SOC_alc5621 || SND_RK29_SOC_alc5631 || SND_RK29_SOC_RT5625 || SND_RK29_SOC_CS42L52 +if SND_RK29_SOC_WM8988 || SND_RK29_SOC_RK1000 || SND_RK29_SOC_WM8994 || SND_RK29_SOC_WM8900 || SND_RK29_SOC_alc5621 || SND_RK29_SOC_RT5631 || SND_RK29_SOC_RT5625 || SND_RK29_SOC_CS42L52 choice prompt "Set i2s type" config SND_RK29_CODEC_SOC_MASTER diff --git a/sound/soc/rk29/Makefile b/sound/soc/rk29/Makefile index f10294f7f32a..657cdab91331 100644 --- a/sound/soc/rk29/Makefile +++ b/sound/soc/rk29/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_SND_RK29_SOC_I2S) += snd-soc-rockchip-i2s.o # ROCKCHIP Machine Support snd-soc-wm8900-objs := rk29_wm8900.o snd-soc-alc5621-objs := rk29_alc5621.o -snd-soc-alc5631-objs := rk29_rt5631.o +snd-soc-rt5631-objs := rk29_rt5631.o snd-soc-rt5625-objs := rk29_rt5625.o snd-soc-cs42l52-objs := rk29_cs42l52.o snd-soc-wm8988-objs := rk29_wm8988.o @@ -19,7 +19,7 @@ obj-$(CONFIG_SND_RK29_SOC_WM8994) += snd-soc-wm8994.o obj-$(CONFIG_SND_RK29_SOC_WM8988) += snd-soc-wm8988.o obj-$(CONFIG_SND_RK29_SOC_WM8900) += snd-soc-wm8900.o obj-$(CONFIG_SND_RK29_SOC_alc5621) += snd-soc-alc5621.o -obj-$(CONFIG_SND_RK29_SOC_alc5631) += snd-soc-alc5631.o +obj-$(CONFIG_SND_RK29_SOC_RT5631) += snd-soc-rt5631.o obj-$(CONFIG_SND_RK29_SOC_RT5625) += snd-soc-rt5625.o obj-$(CONFIG_SND_RK29_SOC_RK1000) += snd-soc-rk1000.o obj-$(CONFIG_SND_RK29_SOC_CS42L52) += snd-soc-cs42l52.o diff --git a/sound/soc/rk29/rk29_rt5631.c b/sound/soc/rk29/rk29_rt5631.c index 0b93043bda4c..3cf1b5428407 100644 --- a/sound/soc/rk29/rk29_rt5631.c +++ b/sound/soc/rk29/rk29_rt5631.c @@ -34,19 +34,18 @@ 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->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + 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->ops->hw_params(substream, params, codec_dai); //by Vincent + ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); } else @@ -164,28 +163,28 @@ static const struct snd_soc_dapm_route audio_map[]={ /* * Logic for a rt5631 as connected on a rockchip board. */ -static int rk29_rt5631_init(struct snd_soc_codec *codec) +static int rk29_rt5631_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_dai *codec_dai = &codec->dai[0]; - int ret; - + 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(codec, rt5631_dapm_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(codec, audio_map, ARRAY_SIZE(audio_map)); + snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); -// snd_soc_dapm_nc_pin(codec, "HP_L"); + snd_soc_dapm_nc_pin(dapm, "HP_L"); DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); -// snd_soc_dapm_nc_pin(codec, "HP_R"); + snd_soc_dapm_nc_pin(dapm, "HP_R"); DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - snd_soc_dapm_sync(codec); + snd_soc_dapm_sync(dapm); DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - return 0; + return 0; } static struct snd_soc_ops rk29_ops = { @@ -193,32 +192,28 @@ static struct snd_soc_ops rk29_ops = { }; static struct snd_soc_dai_link rk29_dai = { - .name = "RT5631", - .stream_name = "RT5631 PCM", - .cpu_dai = &rk29_i2s_dai[0], - .codec_dai = &rt5631_dai, - .init = rk29_rt5631_init, - .ops = &rk29_ops, + .name = "RT5631", + .stream_name = "RT5631 PCM", + .codec_name = "RT5631.0-001a", + .platform_name = "rockchip-audio", + .cpu_dai_name = "rk29_i2s.0", + .codec_dai_name = "RT5631 HiFi", + .init = rk29_rt5631_init, + .ops = &rk29_ops, }; static struct snd_soc_card snd_soc_card_rk29 = { - .name = "RK29_RT5631", - .platform = &rk29_soc_platform, - .dai_link = &rk29_dai, - .num_links = 1, -}; - - -static struct snd_soc_device rk29_snd_devdata = { - .card = &snd_soc_card_rk29, - .codec_dev = &soc_codec_dev_rt5631, + .name = "RK29_RT5631", + .dai_link = &rk29_dai, + .num_links = 1, }; static struct platform_device *rk29_snd_device; static int __init audio_card_init(void) { - int ret =0; + int ret =0; + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); rk29_snd_device = platform_device_alloc("soc-audio", -1); if (!rk29_snd_device) { @@ -226,8 +221,7 @@ static int __init audio_card_init(void) ret = -ENOMEM; return ret; } - platform_set_drvdata(rk29_snd_device, &rk29_snd_devdata); - rk29_snd_devdata.dev = &rk29_snd_device->dev; + 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"); -- 2.34.1