diff options
-rw-r--r-- | arch/arm/configs/imx23evk_defconfig | 30 | ||||
-rw-r--r-- | arch/arm/mach-mx23/clock.c | 12 | ||||
-rw-r--r-- | arch/arm/mach-mx23/include/mach/dma.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-mx23/include/mach/mx23.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-mx23/include/mach/regs-audioin.h | 287 | ||||
-rw-r--r-- | arch/arm/mach-mx23/include/mach/regs-audioout.h | 518 | ||||
-rw-r--r-- | arch/arm/mach-mx23/mx23evk.c | 19 | ||||
-rw-r--r-- | arch/arm/plat-mxs/device.c | 22 | ||||
-rw-r--r-- | sound/soc/codecs/Kconfig | 4 | ||||
-rw-r--r-- | sound/soc/codecs/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/codecs/mxs-adc-codec.c | 1057 | ||||
-rw-r--r-- | sound/soc/codecs/mxs-adc-codec.h | 87 | ||||
-rw-r--r-- | sound/soc/mxs/Kconfig | 14 | ||||
-rw-r--r-- | sound/soc/mxs/Makefile | 4 | ||||
-rw-r--r-- | sound/soc/mxs/mxs-adc.c | 257 | ||||
-rw-r--r-- | sound/soc/mxs/mxs-adc.h | 21 | ||||
-rw-r--r-- | sound/soc/mxs/mxs-evk-adc.c | 91 |
17 files changed, 2428 insertions, 3 deletions
diff --git a/arch/arm/configs/imx23evk_defconfig b/arch/arm/configs/imx23evk_defconfig index fd0003083d4f..827f9af45518 100644 --- a/arch/arm/configs/imx23evk_defconfig +++ b/arch/arm/configs/imx23evk_defconfig @@ -777,7 +777,35 @@ CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set CONFIG_LOGO_LINUX_CLUT224=y -# CONFIG_SOUND is not set +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE 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_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# 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 is not set +CONFIG_SND_SOC=y +CONFIG_SND_MXS_SOC=y +CONFIG_SND_MXS_SOC_EVK_ADC=y +CONFIG_SND_MXS_SOC_ADC=y +CONFIG_SND_SOC_MXS_ADC_CODEC=y +# CONFIG_SND_SOC_ALL_CODECS is not set +# CONFIG_SOUND_PRIME is not set # CONFIG_HID_SUPPORT is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y diff --git a/arch/arm/mach-mx23/clock.c b/arch/arm/mach-mx23/clock.c index 242c7014fa62..97b005a5f9f0 100644 --- a/arch/arm/mach-mx23/clock.c +++ b/arch/arm/mach-mx23/clock.c @@ -585,6 +585,14 @@ static struct clk usb_clk = { .enable_bits = BM_DIGCTL_CTRL_USB_CLKGATE, }; +static struct clk audio_clk = { + .parent = &ref_xtal_clk, + .enable = mx23_raw_enable, + .disable = mx23_raw_disable, + .enable_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_XTAL, + .enable_bits = BM_CLKCTRL_XTAL_FILT_CLK24M_GATE, +}; + static struct clk_lookup onchip_clocks[] = { { @@ -674,6 +682,10 @@ static struct clk_lookup onchip_clocks[] = { { .con_id = "usb_clk0", .clk = &usb_clk, + }, + { + .con_id = "audio", + .clk = &audio_clk, } }; diff --git a/arch/arm/mach-mx23/include/mach/dma.h b/arch/arm/mach-mx23/include/mach/dma.h index e80353a359ef..5fc24275ab3c 100644 --- a/arch/arm/mach-mx23/include/mach/dma.h +++ b/arch/arm/mach-mx23/include/mach/dma.h @@ -38,8 +38,8 @@ enum { MXS_DMA_CHANNEL_AHB_APBH_14, MXS_DMA_CHANNEL_AHB_APBH_15, MXS_DMA_CHANNEL_AHB_APBX = 16, - MXS_DMA_CHANNEL_AHB_APBX_UART4_RX = MXS_DMA_CHANNEL_AHB_APBX, - MXS_DMA_CHANNEL_AHB_APBX_UART4_TX, + MXS_DMA_CHANNEL_AHB_APBX_AUDIOADC = MXS_DMA_CHANNEL_AHB_APBX, + MXS_DMA_CHANNEL_AHB_APBX_AUDIODAC, MXS_DMA_CHANNEL_AHB_APBX_SPDIF, MXS_DMA_CHANNEL_AHB_APBX_03, MXS_DMA_CHANNEL_AHB_APBX_SAIF0, diff --git a/arch/arm/mach-mx23/include/mach/mx23.h b/arch/arm/mach-mx23/include/mach/mx23.h index 51bfb0cce7ca..ae7f43c0744f 100644 --- a/arch/arm/mach-mx23/include/mach/mx23.h +++ b/arch/arm/mach-mx23/include/mach/mx23.h @@ -54,6 +54,8 @@ #define SAIF0_PHYS_ADDR (MX23_SOC_IO_PHYS_BASE + 0x042000) #define POWER_PHYS_ADDR (MX23_SOC_IO_PHYS_BASE + 0x044000) #define SAIF1_PHYS_ADDR (MX23_SOC_IO_PHYS_BASE + 0x046000) +#define AUDIOOUT_PHYS_ADDR (MX23_SOC_IO_PHYS_BASE + 0x048000) +#define AUDIOIN_PHYS_ADDR (MX23_SOC_IO_PHYS_BASE + 0x04c000) #define LRADC_PHYS_ADDR (MX23_SOC_IO_PHYS_BASE + 0x050000) #define SPDIF_PHYS_ADDR (MX23_SOC_IO_PHYS_BASE + 0x054000) #define RTC_PHYS_ADDR (MX23_SOC_IO_PHYS_BASE + 0x05c000) diff --git a/arch/arm/mach-mx23/include/mach/regs-audioin.h b/arch/arm/mach-mx23/include/mach/regs-audioin.h new file mode 100644 index 000000000000..1a881ce0407e --- /dev/null +++ b/arch/arm/mach-mx23/include/mach/regs-audioin.h @@ -0,0 +1,287 @@ +/* + * Freescale AUDIOIN Register Definitions + * + * Copyright 2008-2010 Freescale Semiconductor, Inc. + * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is created by xml file. Don't Edit it. + * + * Xml Revision: 1.52 + * Template revision: 26195 + */ + +#ifndef __ARCH_ARM___AUDIOIN_H +#define __ARCH_ARM___AUDIOIN_H + +#define REGS_AUDIOIN_BASE (IO_ADDRESS(AUDIOIN_PHYS_ADDR)) + +#define HW_AUDIOIN_CTRL (0x00000000) +#define HW_AUDIOIN_CTRL_SET (0x00000004) +#define HW_AUDIOIN_CTRL_CLR (0x00000008) +#define HW_AUDIOIN_CTRL_TOG (0x0000000c) + +#define BM_AUDIOIN_CTRL_SFTRST 0x80000000 +#define BM_AUDIOIN_CTRL_CLKGATE 0x40000000 +#define BP_AUDIOIN_CTRL_RSRVD3 21 +#define BM_AUDIOIN_CTRL_RSRVD3 0x3FE00000 +#define BF_AUDIOIN_CTRL_RSRVD3(v) \ + (((v) << 21) & BM_AUDIOIN_CTRL_RSRVD3) +#define BP_AUDIOIN_CTRL_DMAWAIT_COUNT 16 +#define BM_AUDIOIN_CTRL_DMAWAIT_COUNT 0x001F0000 +#define BF_AUDIOIN_CTRL_DMAWAIT_COUNT(v) \ + (((v) << 16) & BM_AUDIOIN_CTRL_DMAWAIT_COUNT) +#define BP_AUDIOIN_CTRL_RSRVD1 11 +#define BM_AUDIOIN_CTRL_RSRVD1 0x0000F800 +#define BF_AUDIOIN_CTRL_RSRVD1(v) \ + (((v) << 11) & BM_AUDIOIN_CTRL_RSRVD1) +#define BM_AUDIOIN_CTRL_LR_SWAP 0x00000400 +#define BM_AUDIOIN_CTRL_EDGE_SYNC 0x00000200 +#define BM_AUDIOIN_CTRL_INVERT_1BIT 0x00000100 +#define BM_AUDIOIN_CTRL_OFFSET_ENABLE 0x00000080 +#define BM_AUDIOIN_CTRL_HPF_ENABLE 0x00000040 +#define BM_AUDIOIN_CTRL_WORD_LENGTH 0x00000020 +#define BM_AUDIOIN_CTRL_LOOPBACK 0x00000010 +#define BM_AUDIOIN_CTRL_FIFO_UNDERFLOW_IRQ 0x00000008 +#define BM_AUDIOIN_CTRL_FIFO_OVERFLOW_IRQ 0x00000004 +#define BM_AUDIOIN_CTRL_FIFO_ERROR_IRQ_EN 0x00000002 +#define BM_AUDIOIN_CTRL_RUN 0x00000001 + +#define HW_AUDIOIN_STAT (0x00000010) +#define HW_AUDIOIN_STAT_SET (0x00000014) +#define HW_AUDIOIN_STAT_CLR (0x00000018) +#define HW_AUDIOIN_STAT_TOG (0x0000001c) + +#define BM_AUDIOIN_STAT_ADC_PRESENT 0x80000000 +#define BP_AUDIOIN_STAT_RSRVD3 0 +#define BM_AUDIOIN_STAT_RSRVD3 0x7FFFFFFF +#define BF_AUDIOIN_STAT_RSRVD3(v) \ + (((v) << 0) & BM_AUDIOIN_STAT_RSRVD3) + +#define HW_AUDIOIN_ADCSRR (0x00000020) +#define HW_AUDIOIN_ADCSRR_SET (0x00000024) +#define HW_AUDIOIN_ADCSRR_CLR (0x00000028) +#define HW_AUDIOIN_ADCSRR_TOG (0x0000002c) + +#define BM_AUDIOIN_ADCSRR_OSR 0x80000000 +#define BV_AUDIOIN_ADCSRR_OSR__OSR6 0x0 +#define BV_AUDIOIN_ADCSRR_OSR__OSR12 0x1 +#define BP_AUDIOIN_ADCSRR_BASEMULT 28 +#define BM_AUDIOIN_ADCSRR_BASEMULT 0x70000000 +#define BF_AUDIOIN_ADCSRR_BASEMULT(v) \ + (((v) << 28) & BM_AUDIOIN_ADCSRR_BASEMULT) +#define BV_AUDIOIN_ADCSRR_BASEMULT__SINGLE_RATE 0x1 +#define BV_AUDIOIN_ADCSRR_BASEMULT__DOUBLE_RATE 0x2 +#define BV_AUDIOIN_ADCSRR_BASEMULT__QUAD_RATE 0x4 +#define BM_AUDIOIN_ADCSRR_RSRVD2 0x08000000 +#define BP_AUDIOIN_ADCSRR_SRC_HOLD 24 +#define BM_AUDIOIN_ADCSRR_SRC_HOLD 0x07000000 +#define BF_AUDIOIN_ADCSRR_SRC_HOLD(v) \ + (((v) << 24) & BM_AUDIOIN_ADCSRR_SRC_HOLD) +#define BP_AUDIOIN_ADCSRR_RSRVD1 21 +#define BM_AUDIOIN_ADCSRR_RSRVD1 0x00E00000 +#define BF_AUDIOIN_ADCSRR_RSRVD1(v) \ + (((v) << 21) & BM_AUDIOIN_ADCSRR_RSRVD1) +#define BP_AUDIOIN_ADCSRR_SRC_INT 16 +#define BM_AUDIOIN_ADCSRR_SRC_INT 0x001F0000 +#define BF_AUDIOIN_ADCSRR_SRC_INT(v) \ + (((v) << 16) & BM_AUDIOIN_ADCSRR_SRC_INT) +#define BP_AUDIOIN_ADCSRR_RSRVD0 13 +#define BM_AUDIOIN_ADCSRR_RSRVD0 0x0000E000 +#define BF_AUDIOIN_ADCSRR_RSRVD0(v) \ + (((v) << 13) & BM_AUDIOIN_ADCSRR_RSRVD0) +#define BP_AUDIOIN_ADCSRR_SRC_FRAC 0 +#define BM_AUDIOIN_ADCSRR_SRC_FRAC 0x00001FFF +#define BF_AUDIOIN_ADCSRR_SRC_FRAC(v) \ + (((v) << 0) & BM_AUDIOIN_ADCSRR_SRC_FRAC) + +#define HW_AUDIOIN_ADCVOLUME (0x00000030) +#define HW_AUDIOIN_ADCVOLUME_SET (0x00000034) +#define HW_AUDIOIN_ADCVOLUME_CLR (0x00000038) +#define HW_AUDIOIN_ADCVOLUME_TOG (0x0000003c) + +#define BP_AUDIOIN_ADCVOLUME_RSRVD5 29 +#define BM_AUDIOIN_ADCVOLUME_RSRVD5 0xE0000000 +#define BF_AUDIOIN_ADCVOLUME_RSRVD5(v) \ + (((v) << 29) & BM_AUDIOIN_ADCVOLUME_RSRVD5) +#define BM_AUDIOIN_ADCVOLUME_VOLUME_UPDATE_LEFT 0x10000000 +#define BP_AUDIOIN_ADCVOLUME_RSRVD4 26 +#define BM_AUDIOIN_ADCVOLUME_RSRVD4 0x0C000000 +#define BF_AUDIOIN_ADCVOLUME_RSRVD4(v) \ + (((v) << 26) & BM_AUDIOIN_ADCVOLUME_RSRVD4) +#define BM_AUDIOIN_ADCVOLUME_EN_ZCD 0x02000000 +#define BM_AUDIOIN_ADCVOLUME_RSRVD3 0x01000000 +#define BP_AUDIOIN_ADCVOLUME_VOLUME_LEFT 16 +#define BM_AUDIOIN_ADCVOLUME_VOLUME_LEFT 0x00FF0000 +#define BF_AUDIOIN_ADCVOLUME_VOLUME_LEFT(v) \ + (((v) << 16) & BM_AUDIOIN_ADCVOLUME_VOLUME_LEFT) +#define BP_AUDIOIN_ADCVOLUME_RSRVD2 13 +#define BM_AUDIOIN_ADCVOLUME_RSRVD2 0x0000E000 +#define BF_AUDIOIN_ADCVOLUME_RSRVD2(v) \ + (((v) << 13) & BM_AUDIOIN_ADCVOLUME_RSRVD2) +#define BM_AUDIOIN_ADCVOLUME_VOLUME_UPDATE_RIGHT 0x00001000 +#define BP_AUDIOIN_ADCVOLUME_RSRVD1 8 +#define BM_AUDIOIN_ADCVOLUME_RSRVD1 0x00000F00 +#define BF_AUDIOIN_ADCVOLUME_RSRVD1(v) \ + (((v) << 8) & BM_AUDIOIN_ADCVOLUME_RSRVD1) +#define BP_AUDIOIN_ADCVOLUME_VOLUME_RIGHT 0 +#define BM_AUDIOIN_ADCVOLUME_VOLUME_RIGHT 0x000000FF +#define BF_AUDIOIN_ADCVOLUME_VOLUME_RIGHT(v) \ + (((v) << 0) & BM_AUDIOIN_ADCVOLUME_VOLUME_RIGHT) + +#define HW_AUDIOIN_ADCDEBUG (0x00000040) +#define HW_AUDIOIN_ADCDEBUG_SET (0x00000044) +#define HW_AUDIOIN_ADCDEBUG_CLR (0x00000048) +#define HW_AUDIOIN_ADCDEBUG_TOG (0x0000004c) + +#define BM_AUDIOIN_ADCDEBUG_ENABLE_ADCDMA 0x80000000 +#define BP_AUDIOIN_ADCDEBUG_RSRVD1 4 +#define BM_AUDIOIN_ADCDEBUG_RSRVD1 0x7FFFFFF0 +#define BF_AUDIOIN_ADCDEBUG_RSRVD1(v) \ + (((v) << 4) & BM_AUDIOIN_ADCDEBUG_RSRVD1) +#define BM_AUDIOIN_ADCDEBUG_ADC_DMA_REQ_HAND_SHAKE_CLK_CROSS 0x00000008 +#define BM_AUDIOIN_ADCDEBUG_SET_INTERRUPT3_HAND_SHAKE 0x00000004 +#define BM_AUDIOIN_ADCDEBUG_DMA_PREQ 0x00000002 +#define BM_AUDIOIN_ADCDEBUG_FIFO_STATUS 0x00000001 + +#define HW_AUDIOIN_ADCVOL (0x00000050) +#define HW_AUDIOIN_ADCVOL_SET (0x00000054) +#define HW_AUDIOIN_ADCVOL_CLR (0x00000058) +#define HW_AUDIOIN_ADCVOL_TOG (0x0000005c) + +#define BP_AUDIOIN_ADCVOL_RSRVD4 29 +#define BM_AUDIOIN_ADCVOL_RSRVD4 0xE0000000 +#define BF_AUDIOIN_ADCVOL_RSRVD4(v) \ + (((v) << 29) & BM_AUDIOIN_ADCVOL_RSRVD4) +#define BM_AUDIOIN_ADCVOL_VOLUME_UPDATE_PENDING 0x10000000 +#define BP_AUDIOIN_ADCVOL_RSRVD3 26 +#define BM_AUDIOIN_ADCVOL_RSRVD3 0x0C000000 +#define BF_AUDIOIN_ADCVOL_RSRVD3(v) \ + (((v) << 26) & BM_AUDIOIN_ADCVOL_RSRVD3) +#define BM_AUDIOIN_ADCVOL_EN_ADC_ZCD 0x02000000 +#define BM_AUDIOIN_ADCVOL_MUTE 0x01000000 +#define BP_AUDIOIN_ADCVOL_RSRVD2 14 +#define BM_AUDIOIN_ADCVOL_RSRVD2 0x00FFC000 +#define BF_AUDIOIN_ADCVOL_RSRVD2(v) \ + (((v) << 14) & BM_AUDIOIN_ADCVOL_RSRVD2) +#define BP_AUDIOIN_ADCVOL_SELECT_LEFT 12 +#define BM_AUDIOIN_ADCVOL_SELECT_LEFT 0x00003000 +#define BF_AUDIOIN_ADCVOL_SELECT_LEFT(v) \ + (((v) << 12) & BM_AUDIOIN_ADCVOL_SELECT_LEFT) +#define BP_AUDIOIN_ADCVOL_GAIN_LEFT 8 +#define BM_AUDIOIN_ADCVOL_GAIN_LEFT 0x00000F00 +#define BF_AUDIOIN_ADCVOL_GAIN_LEFT(v) \ + (((v) << 8) & BM_AUDIOIN_ADCVOL_GAIN_LEFT) +#define BP_AUDIOIN_ADCVOL_RSRVD1 6 +#define BM_AUDIOIN_ADCVOL_RSRVD1 0x000000C0 +#define BF_AUDIOIN_ADCVOL_RSRVD1(v) \ + (((v) << 6) & BM_AUDIOIN_ADCVOL_RSRVD1) +#define BP_AUDIOIN_ADCVOL_SELECT_RIGHT 4 +#define BM_AUDIOIN_ADCVOL_SELECT_RIGHT 0x00000030 +#define BF_AUDIOIN_ADCVOL_SELECT_RIGHT(v) \ + (((v) << 4) & BM_AUDIOIN_ADCVOL_SELECT_RIGHT) +#define BP_AUDIOIN_ADCVOL_GAIN_RIGHT 0 +#define BM_AUDIOIN_ADCVOL_GAIN_RIGHT 0x0000000F +#define BF_AUDIOIN_ADCVOL_GAIN_RIGHT(v) \ + (((v) << 0) & BM_AUDIOIN_ADCVOL_GAIN_RIGHT) + +#define HW_AUDIOIN_MICLINE (0x00000060) +#define HW_AUDIOIN_MICLINE_SET (0x00000064) +#define HW_AUDIOIN_MICLINE_CLR (0x00000068) +#define HW_AUDIOIN_MICLINE_TOG (0x0000006c) + +#define BP_AUDIOIN_MICLINE_RSRVD6 30 +#define BM_AUDIOIN_MICLINE_RSRVD6 0xC0000000 +#define BF_AUDIOIN_MICLINE_RSRVD6(v) \ + (((v) << 30) & BM_AUDIOIN_MICLINE_RSRVD6) +#define BM_AUDIOIN_MICLINE_DIVIDE_LINE1 0x20000000 +#define BM_AUDIOIN_MICLINE_DIVIDE_LINE2 0x10000000 +#define BP_AUDIOIN_MICLINE_RSRVD5 25 +#define BM_AUDIOIN_MICLINE_RSRVD5 0x0E000000 +#define BF_AUDIOIN_MICLINE_RSRVD5(v) \ + (((v) << 25) & BM_AUDIOIN_MICLINE_RSRVD5) +#define BM_AUDIOIN_MICLINE_MIC_SELECT 0x01000000 +#define BP_AUDIOIN_MICLINE_RSRVD4 22 +#define BM_AUDIOIN_MICLINE_RSRVD4 0x00C00000 +#define BF_AUDIOIN_MICLINE_RSRVD4(v) \ + (((v) << 22) & BM_AUDIOIN_MICLINE_RSRVD4) +#define BP_AUDIOIN_MICLINE_MIC_RESISTOR 20 +#define BM_AUDIOIN_MICLINE_MIC_RESISTOR 0x00300000 +#define BF_AUDIOIN_MICLINE_MIC_RESISTOR(v) \ + (((v) << 20) & BM_AUDIOIN_MICLINE_MIC_RESISTOR) +#define BM_AUDIOIN_MICLINE_RSRVD3 0x00080000 +#define BP_AUDIOIN_MICLINE_MIC_BIAS 16 +#define BM_AUDIOIN_MICLINE_MIC_BIAS 0x00070000 +#define BF_AUDIOIN_MICLINE_MIC_BIAS(v) \ + (((v) << 16) & BM_AUDIOIN_MICLINE_MIC_BIAS) +#define BP_AUDIOIN_MICLINE_RSRVD2 6 +#define BM_AUDIOIN_MICLINE_RSRVD2 0x0000FFC0 +#define BF_AUDIOIN_MICLINE_RSRVD2(v) \ + (((v) << 6) & BM_AUDIOIN_MICLINE_RSRVD2) +#define BP_AUDIOIN_MICLINE_MIC_CHOPCLK 4 +#define BM_AUDIOIN_MICLINE_MIC_CHOPCLK 0x00000030 +#define BF_AUDIOIN_MICLINE_MIC_CHOPCLK(v) \ + (((v) << 4) & BM_AUDIOIN_MICLINE_MIC_CHOPCLK) +#define BP_AUDIOIN_MICLINE_RSRVD1 2 +#define BM_AUDIOIN_MICLINE_RSRVD1 0x0000000C +#define BF_AUDIOIN_MICLINE_RSRVD1(v) \ + (((v) << 2) & BM_AUDIOIN_MICLINE_RSRVD1) +#define BP_AUDIOIN_MICLINE_MIC_GAIN 0 +#define BM_AUDIOIN_MICLINE_MIC_GAIN 0x00000003 +#define BF_AUDIOIN_MICLINE_MIC_GAIN(v) \ + (((v) << 0) & BM_AUDIOIN_MICLINE_MIC_GAIN) + +#define HW_AUDIOIN_ANACLKCTRL (0x00000070) +#define HW_AUDIOIN_ANACLKCTRL_SET (0x00000074) +#define HW_AUDIOIN_ANACLKCTRL_CLR (0x00000078) +#define HW_AUDIOIN_ANACLKCTRL_TOG (0x0000007c) + +#define BM_AUDIOIN_ANACLKCTRL_CLKGATE 0x80000000 +#define BP_AUDIOIN_ANACLKCTRL_RSRVD4 11 +#define BM_AUDIOIN_ANACLKCTRL_RSRVD4 0x7FFFF800 +#define BF_AUDIOIN_ANACLKCTRL_RSRVD4(v) \ + (((v) << 11) & BM_AUDIOIN_ANACLKCTRL_RSRVD4) +#define BM_AUDIOIN_ANACLKCTRL_DITHER_OFF 0x00000400 +#define BM_AUDIOIN_ANACLKCTRL_SLOW_DITHER 0x00000200 +#define BM_AUDIOIN_ANACLKCTRL_INVERT_ADCCLK 0x00000100 +#define BP_AUDIOIN_ANACLKCTRL_RSRVD3 6 +#define BM_AUDIOIN_ANACLKCTRL_RSRVD3 0x000000C0 +#define BF_AUDIOIN_ANACLKCTRL_RSRVD3(v) \ + (((v) << 6) & BM_AUDIOIN_ANACLKCTRL_RSRVD3) +#define BP_AUDIOIN_ANACLKCTRL_ADCCLK_SHIFT 4 +#define BM_AUDIOIN_ANACLKCTRL_ADCCLK_SHIFT 0x00000030 +#define BF_AUDIOIN_ANACLKCTRL_ADCCLK_SHIFT(v) \ + (((v) << 4) & BM_AUDIOIN_ANACLKCTRL_ADCCLK_SHIFT) +#define BM_AUDIOIN_ANACLKCTRL_RSRVD2 0x00000008 +#define BP_AUDIOIN_ANACLKCTRL_ADCDIV 0 +#define BM_AUDIOIN_ANACLKCTRL_ADCDIV 0x00000007 +#define BF_AUDIOIN_ANACLKCTRL_ADCDIV(v) \ + (((v) << 0) & BM_AUDIOIN_ANACLKCTRL_ADCDIV) + +#define HW_AUDIOIN_DATA (0x00000080) +#define HW_AUDIOIN_DATA_SET (0x00000084) +#define HW_AUDIOIN_DATA_CLR (0x00000088) +#define HW_AUDIOIN_DATA_TOG (0x0000008c) + +#define BP_AUDIOIN_DATA_HIGH 16 +#define BM_AUDIOIN_DATA_HIGH 0xFFFF0000 +#define BF_AUDIOIN_DATA_HIGH(v) \ + (((v) << 16) & BM_AUDIOIN_DATA_HIGH) +#define BP_AUDIOIN_DATA_LOW 0 +#define BM_AUDIOIN_DATA_LOW 0x0000FFFF +#define BF_AUDIOIN_DATA_LOW(v) \ + (((v) << 0) & BM_AUDIOIN_DATA_LOW) +#endif /* __ARCH_ARM___AUDIOIN_H */ diff --git a/arch/arm/mach-mx23/include/mach/regs-audioout.h b/arch/arm/mach-mx23/include/mach/regs-audioout.h new file mode 100644 index 000000000000..d751858a1327 --- /dev/null +++ b/arch/arm/mach-mx23/include/mach/regs-audioout.h @@ -0,0 +1,518 @@ +/* + * Freescale AUDIOOUT Register Definitions + * + * Copyright 2008-2010 Freescale Semiconductor, Inc. + * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is created by xml file. Don't Edit it. + * + * Xml Revision: 1.65 + * Template revision: 26195 + */ + +#ifndef __ARCH_ARM___AUDIOOUT_H +#define __ARCH_ARM___AUDIOOUT_H + +#define REGS_AUDIOOUT_BASE (IO_ADDRESS(AUDIOOUT_PHYS_ADDR)) + +#define HW_AUDIOOUT_CTRL (0x00000000) +#define HW_AUDIOOUT_CTRL_SET (0x00000004) +#define HW_AUDIOOUT_CTRL_CLR (0x00000008) +#define HW_AUDIOOUT_CTRL_TOG (0x0000000c) + +#define BM_AUDIOOUT_CTRL_SFTRST 0x80000000 +#define BM_AUDIOOUT_CTRL_CLKGATE 0x40000000 +#define BP_AUDIOOUT_CTRL_RSRVD4 21 +#define BM_AUDIOOUT_CTRL_RSRVD4 0x3FE00000 +#define BF_AUDIOOUT_CTRL_RSRVD4(v) \ + (((v) << 21) & BM_AUDIOOUT_CTRL_RSRVD4) +#define BP_AUDIOOUT_CTRL_DMAWAIT_COUNT 16 +#define BM_AUDIOOUT_CTRL_DMAWAIT_COUNT 0x001F0000 +#define BF_AUDIOOUT_CTRL_DMAWAIT_COUNT(v) \ + (((v) << 16) & BM_AUDIOOUT_CTRL_DMAWAIT_COUNT) +#define BM_AUDIOOUT_CTRL_RSRVD3 0x00008000 +#define BM_AUDIOOUT_CTRL_LR_SWAP 0x00004000 +#define BM_AUDIOOUT_CTRL_EDGE_SYNC 0x00002000 +#define BM_AUDIOOUT_CTRL_INVERT_1BIT 0x00001000 +#define BP_AUDIOOUT_CTRL_RSRVD2 10 +#define BM_AUDIOOUT_CTRL_RSRVD2 0x00000C00 +#define BF_AUDIOOUT_CTRL_RSRVD2(v) \ + (((v) << 10) & BM_AUDIOOUT_CTRL_RSRVD2) +#define BP_AUDIOOUT_CTRL_SS3D_EFFECT 8 +#define BM_AUDIOOUT_CTRL_SS3D_EFFECT 0x00000300 +#define BF_AUDIOOUT_CTRL_SS3D_EFFECT(v) \ + (((v) << 8) & BM_AUDIOOUT_CTRL_SS3D_EFFECT) +#define BM_AUDIOOUT_CTRL_RSRVD1 0x00000080 +#define BM_AUDIOOUT_CTRL_WORD_LENGTH 0x00000040 +#define BM_AUDIOOUT_CTRL_DAC_ZERO_ENABLE 0x00000020 +#define BM_AUDIOOUT_CTRL_LOOPBACK 0x00000010 +#define BM_AUDIOOUT_CTRL_FIFO_UNDERFLOW_IRQ 0x00000008 +#define BM_AUDIOOUT_CTRL_FIFO_OVERFLOW_IRQ 0x00000004 +#define BM_AUDIOOUT_CTRL_FIFO_ERROR_IRQ_EN 0x00000002 +#define BM_AUDIOOUT_CTRL_RUN 0x00000001 + +#define HW_AUDIOOUT_STAT (0x00000010) +#define HW_AUDIOOUT_STAT_SET (0x00000014) +#define HW_AUDIOOUT_STAT_CLR (0x00000018) +#define HW_AUDIOOUT_STAT_TOG (0x0000001c) + +#define BM_AUDIOOUT_STAT_DAC_PRESENT 0x80000000 +#define BP_AUDIOOUT_STAT_RSRVD1 0 +#define BM_AUDIOOUT_STAT_RSRVD1 0x7FFFFFFF +#define BF_AUDIOOUT_STAT_RSRVD1(v) \ + (((v) << 0) & BM_AUDIOOUT_STAT_RSRVD1) + +#define HW_AUDIOOUT_DACSRR (0x00000020) +#define HW_AUDIOOUT_DACSRR_SET (0x00000024) +#define HW_AUDIOOUT_DACSRR_CLR (0x00000028) +#define HW_AUDIOOUT_DACSRR_TOG (0x0000002c) + +#define BM_AUDIOOUT_DACSRR_OSR 0x80000000 +#define BV_AUDIOOUT_DACSRR_OSR__OSR6 0x0 +#define BV_AUDIOOUT_DACSRR_OSR__OSR12 0x1 +#define BP_AUDIOOUT_DACSRR_BASEMULT 28 +#define BM_AUDIOOUT_DACSRR_BASEMULT 0x70000000 +#define BF_AUDIOOUT_DACSRR_BASEMULT(v) \ + (((v) << 28) & BM_AUDIOOUT_DACSRR_BASEMULT) +#define BV_AUDIOOUT_DACSRR_BASEMULT__SINGLE_RATE 0x1 +#define BV_AUDIOOUT_DACSRR_BASEMULT__DOUBLE_RATE 0x2 +#define BV_AUDIOOUT_DACSRR_BASEMULT__QUAD_RATE 0x4 +#define BM_AUDIOOUT_DACSRR_RSRVD2 0x08000000 +#define BP_AUDIOOUT_DACSRR_SRC_HOLD 24 +#define BM_AUDIOOUT_DACSRR_SRC_HOLD 0x07000000 +#define BF_AUDIOOUT_DACSRR_SRC_HOLD(v) \ + (((v) << 24) & BM_AUDIOOUT_DACSRR_SRC_HOLD) +#define BP_AUDIOOUT_DACSRR_RSRVD1 21 +#define BM_AUDIOOUT_DACSRR_RSRVD1 0x00E00000 +#define BF_AUDIOOUT_DACSRR_RSRVD1(v) \ + (((v) << 21) & BM_AUDIOOUT_DACSRR_RSRVD1) +#define BP_AUDIOOUT_DACSRR_SRC_INT 16 +#define BM_AUDIOOUT_DACSRR_SRC_INT 0x001F0000 +#define BF_AUDIOOUT_DACSRR_SRC_INT(v) \ + (((v) << 16) & BM_AUDIOOUT_DACSRR_SRC_INT) +#define BP_AUDIOOUT_DACSRR_RSRVD0 13 +#define BM_AUDIOOUT_DACSRR_RSRVD0 0x0000E000 +#define BF_AUDIOOUT_DACSRR_RSRVD0(v) \ + (((v) << 13) & BM_AUDIOOUT_DACSRR_RSRVD0) +#define BP_AUDIOOUT_DACSRR_SRC_FRAC 0 +#define BM_AUDIOOUT_DACSRR_SRC_FRAC 0x00001FFF +#define BF_AUDIOOUT_DACSRR_SRC_FRAC(v) \ + (((v) << 0) & BM_AUDIOOUT_DACSRR_SRC_FRAC) + +#define HW_AUDIOOUT_DACVOLUME (0x00000030) +#define HW_AUDIOOUT_DACVOLUME_SET (0x00000034) +#define HW_AUDIOOUT_DACVOLUME_CLR (0x00000038) +#define HW_AUDIOOUT_DACVOLUME_TOG (0x0000003c) + +#define BP_AUDIOOUT_DACVOLUME_RSRVD4 29 +#define BM_AUDIOOUT_DACVOLUME_RSRVD4 0xE0000000 +#define BF_AUDIOOUT_DACVOLUME_RSRVD4(v) \ + (((v) << 29) & BM_AUDIOOUT_DACVOLUME_RSRVD4) +#define BM_AUDIOOUT_DACVOLUME_VOLUME_UPDATE_LEFT 0x10000000 +#define BP_AUDIOOUT_DACVOLUME_RSRVD3 26 +#define BM_AUDIOOUT_DACVOLUME_RSRVD3 0x0C000000 +#define BF_AUDIOOUT_DACVOLUME_RSRVD3(v) \ + (((v) << 26) & BM_AUDIOOUT_DACVOLUME_RSRVD3) +#define BM_AUDIOOUT_DACVOLUME_EN_ZCD 0x02000000 +#define BM_AUDIOOUT_DACVOLUME_MUTE_LEFT 0x01000000 +#define BP_AUDIOOUT_DACVOLUME_VOLUME_LEFT 16 +#define BM_AUDIOOUT_DACVOLUME_VOLUME_LEFT 0x00FF0000 +#define BF_AUDIOOUT_DACVOLUME_VOLUME_LEFT(v) \ + (((v) << 16) & BM_AUDIOOUT_DACVOLUME_VOLUME_LEFT) +#define BP_AUDIOOUT_DACVOLUME_RSRVD2 13 +#define BM_AUDIOOUT_DACVOLUME_RSRVD2 0x0000E000 +#define BF_AUDIOOUT_DACVOLUME_RSRVD2(v) \ + (((v) << 13) & BM_AUDIOOUT_DACVOLUME_RSRVD2) +#define BM_AUDIOOUT_DACVOLUME_VOLUME_UPDATE_RIGHT 0x00001000 +#define BP_AUDIOOUT_DACVOLUME_RSRVD1 9 +#define BM_AUDIOOUT_DACVOLUME_RSRVD1 0x00000E00 +#define BF_AUDIOOUT_DACVOLUME_RSRVD1(v) \ + (((v) << 9) & BM_AUDIOOUT_DACVOLUME_RSRVD1) +#define BM_AUDIOOUT_DACVOLUME_MUTE_RIGHT 0x00000100 +#define BP_AUDIOOUT_DACVOLUME_VOLUME_RIGHT 0 +#define BM_AUDIOOUT_DACVOLUME_VOLUME_RIGHT 0x000000FF +#define BF_AUDIOOUT_DACVOLUME_VOLUME_RIGHT(v) \ + (((v) << 0) & BM_AUDIOOUT_DACVOLUME_VOLUME_RIGHT) + +#define HW_AUDIOOUT_DACDEBUG (0x00000040) +#define HW_AUDIOOUT_DACDEBUG_SET (0x00000044) +#define HW_AUDIOOUT_DACDEBUG_CLR (0x00000048) +#define HW_AUDIOOUT_DACDEBUG_TOG (0x0000004c) + +#define BM_AUDIOOUT_DACDEBUG_ENABLE_DACDMA 0x80000000 +#define BP_AUDIOOUT_DACDEBUG_RSRVD2 12 +#define BM_AUDIOOUT_DACDEBUG_RSRVD2 0x7FFFF000 +#define BF_AUDIOOUT_DACDEBUG_RSRVD2(v) \ + (((v) << 12) & BM_AUDIOOUT_DACDEBUG_RSRVD2) +#define BP_AUDIOOUT_DACDEBUG_RAM_SS 8 +#define BM_AUDIOOUT_DACDEBUG_RAM_SS 0x00000F00 +#define BF_AUDIOOUT_DACDEBUG_RAM_SS(v) \ + (((v) << 8) & BM_AUDIOOUT_DACDEBUG_RAM_SS) +#define BP_AUDIOOUT_DACDEBUG_RSRVD1 6 +#define BM_AUDIOOUT_DACDEBUG_RSRVD1 0x000000C0 +#define BF_AUDIOOUT_DACDEBUG_RSRVD1(v) \ + (((v) << 6) & BM_AUDIOOUT_DACDEBUG_RSRVD1) +#define BM_AUDIOOUT_DACDEBUG_SET_INTERRUPT1_CLK_CROSS 0x00000020 +#define BM_AUDIOOUT_DACDEBUG_SET_INTERRUPT0_CLK_CROSS 0x00000010 +#define BM_AUDIOOUT_DACDEBUG_SET_INTERRUPT1_HAND_SHAKE 0x00000008 +#define BM_AUDIOOUT_DACDEBUG_SET_INTERRUPT0_HAND_SHAKE 0x00000004 +#define BM_AUDIOOUT_DACDEBUG_DMA_PREQ 0x00000002 +#define BM_AUDIOOUT_DACDEBUG_FIFO_STATUS 0x00000001 + +#define HW_AUDIOOUT_HPVOL (0x00000050) +#define HW_AUDIOOUT_HPVOL_SET (0x00000054) +#define HW_AUDIOOUT_HPVOL_CLR (0x00000058) +#define HW_AUDIOOUT_HPVOL_TOG (0x0000005c) + +#define BP_AUDIOOUT_HPVOL_RSRVD5 29 +#define BM_AUDIOOUT_HPVOL_RSRVD5 0xE0000000 +#define BF_AUDIOOUT_HPVOL_RSRVD5(v) \ + (((v) << 29) & BM_AUDIOOUT_HPVOL_RSRVD5) +#define BM_AUDIOOUT_HPVOL_VOLUME_UPDATE_PENDING 0x10000000 +#define BP_AUDIOOUT_HPVOL_RSRVD4 26 +#define BM_AUDIOOUT_HPVOL_RSRVD4 0x0C000000 +#define BF_AUDIOOUT_HPVOL_RSRVD4(v) \ + (((v) << 26) & BM_AUDIOOUT_HPVOL_RSRVD4) +#define BM_AUDIOOUT_HPVOL_EN_MSTR_ZCD 0x02000000 +#define BM_AUDIOOUT_HPVOL_MUTE 0x01000000 +#define BP_AUDIOOUT_HPVOL_RSRVD3 17 +#define BM_AUDIOOUT_HPVOL_RSRVD3 0x00FE0000 +#define BF_AUDIOOUT_HPVOL_RSRVD3(v) \ + (((v) << 17) & BM_AUDIOOUT_HPVOL_RSRVD3) +#define BM_AUDIOOUT_HPVOL_SELECT 0x00010000 +#define BM_AUDIOOUT_HPVOL_RSRVD2 0x00008000 +#define BP_AUDIOOUT_HPVOL_VOL_LEFT 8 +#define BM_AUDIOOUT_HPVOL_VOL_LEFT 0x00007F00 +#define BF_AUDIOOUT_HPVOL_VOL_LEFT(v) \ + (((v) << 8) & BM_AUDIOOUT_HPVOL_VOL_LEFT) +#define BM_AUDIOOUT_HPVOL_RSRVD1 0x00000080 +#define BP_AUDIOOUT_HPVOL_VOL_RIGHT 0 +#define BM_AUDIOOUT_HPVOL_VOL_RIGHT 0x0000007F +#define BF_AUDIOOUT_HPVOL_VOL_RIGHT(v) \ + (((v) << 0) & BM_AUDIOOUT_HPVOL_VOL_RIGHT) + +#define HW_AUDIOOUT_RESERVED (0x00000060) +#define HW_AUDIOOUT_RESERVED_SET (0x00000064) +#define HW_AUDIOOUT_RESERVED_CLR (0x00000068) +#define HW_AUDIOOUT_RESERVED_TOG (0x0000006c) + +#define BP_AUDIOOUT_RESERVED_RSRVD1 0 +#define BM_AUDIOOUT_RESERVED_RSRVD1 0xFFFFFFFF +#define BF_AUDIOOUT_RESERVED_RSRVD1(v) (v) + +#define HW_AUDIOOUT_PWRDN (0x00000070) +#define HW_AUDIOOUT_PWRDN_SET (0x00000074) +#define HW_AUDIOOUT_PWRDN_CLR (0x00000078) +#define HW_AUDIOOUT_PWRDN_TOG (0x0000007c) + +#define BP_AUDIOOUT_PWRDN_RSRVD7 25 +#define BM_AUDIOOUT_PWRDN_RSRVD7 0xFE000000 +#define BF_AUDIOOUT_PWRDN_RSRVD7(v) \ + (((v) << 25) & BM_AUDIOOUT_PWRDN_RSRVD7) +#define BM_AUDIOOUT_PWRDN_SPEAKER 0x01000000 +#define BP_AUDIOOUT_PWRDN_RSRVD6 21 +#define BM_AUDIOOUT_PWRDN_RSRVD6 0x00E00000 +#define BF_AUDIOOUT_PWRDN_RSRVD6(v) \ + (((v) << 21) & BM_AUDIOOUT_PWRDN_RSRVD6) +#define BM_AUDIOOUT_PWRDN_SELFBIAS 0x00100000 +#define BP_AUDIOOUT_PWRDN_RSRVD5 17 +#define BM_AUDIOOUT_PWRDN_RSRVD5 0x000E0000 +#define BF_AUDIOOUT_PWRDN_RSRVD5(v) \ + (((v) << 17) & BM_AUDIOOUT_PWRDN_RSRVD5) +#define BM_AUDIOOUT_PWRDN_RIGHT_ADC 0x00010000 +#define BP_AUDIOOUT_PWRDN_RSRVD4 13 +#define BM_AUDIOOUT_PWRDN_RSRVD4 0x0000E000 +#define BF_AUDIOOUT_PWRDN_RSRVD4(v) \ + (((v) << 13) & BM_AUDIOOUT_PWRDN_RSRVD4) +#define BM_AUDIOOUT_PWRDN_DAC 0x00001000 +#define BP_AUDIOOUT_PWRDN_RSRVD3 9 +#define BM_AUDIOOUT_PWRDN_RSRVD3 0x00000E00 +#define BF_AUDIOOUT_PWRDN_RSRVD3(v) \ + (((v) << 9) & BM_AUDIOOUT_PWRDN_RSRVD3) +#define BM_AUDIOOUT_PWRDN_ADC 0x00000100 +#define BP_AUDIOOUT_PWRDN_RSRVD2 5 +#define BM_AUDIOOUT_PWRDN_RSRVD2 0x000000E0 +#define BF_AUDIOOUT_PWRDN_RSRVD2(v) \ + (((v) << 5) & BM_AUDIOOUT_PWRDN_RSRVD2) +#define BM_AUDIOOUT_PWRDN_CAPLESS 0x00000010 +#define BP_AUDIOOUT_PWRDN_RSRVD1 1 +#define BM_AUDIOOUT_PWRDN_RSRVD1 0x0000000E +#define BF_AUDIOOUT_PWRDN_RSRVD1(v) \ + (((v) << 1) & BM_AUDIOOUT_PWRDN_RSRVD1) +#define BM_AUDIOOUT_PWRDN_HEADPHONE 0x00000001 + +#define HW_AUDIOOUT_REFCTRL (0x00000080) +#define HW_AUDIOOUT_REFCTRL_SET (0x00000084) +#define HW_AUDIOOUT_REFCTRL_CLR (0x00000088) +#define HW_AUDIOOUT_REFCTRL_TOG (0x0000008c) + +#define BP_AUDIOOUT_REFCTRL_RSRVD4 27 +#define BM_AUDIOOUT_REFCTRL_RSRVD4 0xF8000000 +#define BF_AUDIOOUT_REFCTRL_RSRVD4(v) \ + (((v) << 27) & BM_AUDIOOUT_REFCTRL_RSRVD4) +#define BM_AUDIOOUT_REFCTRL_FASTSETTLING 0x04000000 +#define BM_AUDIOOUT_REFCTRL_RAISE_REF 0x02000000 +#define BM_AUDIOOUT_REFCTRL_XTAL_BGR_BIAS 0x01000000 +#define BM_AUDIOOUT_REFCTRL_RSRVD3 0x00800000 +#define BP_AUDIOOUT_REFCTRL_VBG_ADJ 20 +#define BM_AUDIOOUT_REFCTRL_VBG_ADJ 0x00700000 +#define BF_AUDIOOUT_REFCTRL_VBG_ADJ(v) \ + (((v) << 20) & BM_AUDIOOUT_REFCTRL_VBG_ADJ) +#define BM_AUDIOOUT_REFCTRL_LOW_PWR 0x00080000 +#define BM_AUDIOOUT_REFCTRL_LW_REF 0x00040000 +#define BP_AUDIOOUT_REFCTRL_BIAS_CTRL 16 +#define BM_AUDIOOUT_REFCTRL_BIAS_CTRL 0x00030000 +#define BF_AUDIOOUT_REFCTRL_BIAS_CTRL(v) \ + (((v) << 16) & BM_AUDIOOUT_REFCTRL_BIAS_CTRL) +#define BM_AUDIOOUT_REFCTRL_RSRVD2 0x00008000 +#define BM_AUDIOOUT_REFCTRL_VDDXTAL_TO_VDDD 0x00004000 +#define BM_AUDIOOUT_REFCTRL_ADJ_ADC 0x00002000 +#define BM_AUDIOOUT_REFCTRL_ADJ_VAG 0x00001000 +#define BP_AUDIOOUT_REFCTRL_ADC_REFVAL 8 +#define BM_AUDIOOUT_REFCTRL_ADC_REFVAL 0x00000F00 +#define BF_AUDIOOUT_REFCTRL_ADC_REFVAL(v) \ + (((v) << 8) & BM_AUDIOOUT_REFCTRL_ADC_REFVAL) +#define BP_AUDIOOUT_REFCTRL_VAG_VAL 4 +#define BM_AUDIOOUT_REFCTRL_VAG_VAL 0x000000F0 +#define BF_AUDIOOUT_REFCTRL_VAG_VAL(v) \ + (((v) << 4) & BM_AUDIOOUT_REFCTRL_VAG_VAL) +#define BM_AUDIOOUT_REFCTRL_RSRVD1 0x00000008 +#define BP_AUDIOOUT_REFCTRL_DAC_ADJ 0 +#define BM_AUDIOOUT_REFCTRL_DAC_ADJ 0x00000007 +#define BF_AUDIOOUT_REFCTRL_DAC_ADJ(v) \ + (((v) << 0) & BM_AUDIOOUT_REFCTRL_DAC_ADJ) + +#define HW_AUDIOOUT_ANACTRL (0x00000090) +#define HW_AUDIOOUT_ANACTRL_SET (0x00000094) +#define HW_AUDIOOUT_ANACTRL_CLR (0x00000098) +#define HW_AUDIOOUT_ANACTRL_TOG (0x0000009c) + +#define BP_AUDIOOUT_ANACTRL_RSRVD8 29 +#define BM_AUDIOOUT_ANACTRL_RSRVD8 0xE0000000 +#define BF_AUDIOOUT_ANACTRL_RSRVD8(v) \ + (((v) << 29) & BM_AUDIOOUT_ANACTRL_RSRVD8) +#define BM_AUDIOOUT_ANACTRL_SHORT_CM_STS 0x10000000 +#define BP_AUDIOOUT_ANACTRL_RSRVD7 25 +#define BM_AUDIOOUT_ANACTRL_RSRVD7 0x0E000000 +#define BF_AUDIOOUT_ANACTRL_RSRVD7(v) \ + (((v) << 25) & BM_AUDIOOUT_ANACTRL_RSRVD7) +#define BM_AUDIOOUT_ANACTRL_SHORT_LR_STS 0x01000000 +#define BP_AUDIOOUT_ANACTRL_RSRVD6 22 +#define BM_AUDIOOUT_ANACTRL_RSRVD6 0x00C00000 +#define BF_AUDIOOUT_ANACTRL_RSRVD6(v) \ + (((v) << 22) & BM_AUDIOOUT_ANACTRL_RSRVD6) +#define BP_AUDIOOUT_ANACTRL_SHORTMODE_CM 20 +#define BM_AUDIOOUT_ANACTRL_SHORTMODE_CM 0x00300000 +#define BF_AUDIOOUT_ANACTRL_SHORTMODE_CM(v) \ + (((v) << 20) & BM_AUDIOOUT_ANACTRL_SHORTMODE_CM) +#define BM_AUDIOOUT_ANACTRL_RSRVD5 0x00080000 +#define BP_AUDIOOUT_ANACTRL_SHORTMODE_LR 17 +#define BM_AUDIOOUT_ANACTRL_SHORTMODE_LR 0x00060000 +#define BF_AUDIOOUT_ANACTRL_SHORTMODE_LR(v) \ + (((v) << 17) & BM_AUDIOOUT_ANACTRL_SHORTMODE_LR) +#define BP_AUDIOOUT_ANACTRL_RSRVD4 15 +#define BM_AUDIOOUT_ANACTRL_RSRVD4 0x00018000 +#define BF_AUDIOOUT_ANACTRL_RSRVD4(v) \ + (((v) << 15) & BM_AUDIOOUT_ANACTRL_RSRVD4) +#define BP_AUDIOOUT_ANACTRL_SHORT_LVLADJL 12 +#define BM_AUDIOOUT_ANACTRL_SHORT_LVLADJL 0x00007000 +#define BF_AUDIOOUT_ANACTRL_SHORT_LVLADJL(v) \ + (((v) << 12) & BM_AUDIOOUT_ANACTRL_SHORT_LVLADJL) +#define BM_AUDIOOUT_ANACTRL_RSRVD3 0x00000800 +#define BP_AUDIOOUT_ANACTRL_SHORT_LVLADJR 8 +#define BM_AUDIOOUT_ANACTRL_SHORT_LVLADJR 0x00000700 +#define BF_AUDIOOUT_ANACTRL_SHORT_LVLADJR(v) \ + (((v) << 8) & BM_AUDIOOUT_ANACTRL_SHORT_LVLADJR) +#define BP_AUDIOOUT_ANACTRL_RSRVD2 6 +#define BM_AUDIOOUT_ANACTRL_RSRVD2 0x000000C0 +#define BF_AUDIOOUT_ANACTRL_RSRVD2(v) \ + (((v) << 6) & BM_AUDIOOUT_ANACTRL_RSRVD2) +#define BM_AUDIOOUT_ANACTRL_HP_HOLD_GND 0x00000020 +#define BM_AUDIOOUT_ANACTRL_HP_CLASSAB 0x00000010 +#define BP_AUDIOOUT_ANACTRL_RSRVD1 0 +#define BM_AUDIOOUT_ANACTRL_RSRVD1 0x0000000F +#define BF_AUDIOOUT_ANACTRL_RSRVD1(v) \ + (((v) << 0) & BM_AUDIOOUT_ANACTRL_RSRVD1) + +#define HW_AUDIOOUT_TEST (0x000000a0) +#define HW_AUDIOOUT_TEST_SET (0x000000a4) +#define HW_AUDIOOUT_TEST_CLR (0x000000a8) +#define HW_AUDIOOUT_TEST_TOG (0x000000ac) + +#define BM_AUDIOOUT_TEST_RSRVD4 0x80000000 +#define BP_AUDIOOUT_TEST_HP_ANTIPOP 28 +#define BM_AUDIOOUT_TEST_HP_ANTIPOP 0x70000000 +#define BF_AUDIOOUT_TEST_HP_ANTIPOP(v) \ + (((v) << 28) & BM_AUDIOOUT_TEST_HP_ANTIPOP) +#define BM_AUDIOOUT_TEST_RSRVD3 0x08000000 +#define BM_AUDIOOUT_TEST_TM_ADCIN_TOHP 0x04000000 +#define BM_AUDIOOUT_TEST_TM_LOOP 0x02000000 +#define BM_AUDIOOUT_TEST_TM_HPCOMMON 0x01000000 +#define BP_AUDIOOUT_TEST_HP_I1_ADJ 22 +#define BM_AUDIOOUT_TEST_HP_I1_ADJ 0x00C00000 +#define BF_AUDIOOUT_TEST_HP_I1_ADJ(v) \ + (((v) << 22) & BM_AUDIOOUT_TEST_HP_I1_ADJ) +#define BP_AUDIOOUT_TEST_HP_IALL_ADJ 20 +#define BM_AUDIOOUT_TEST_HP_IALL_ADJ 0x00300000 +#define BF_AUDIOOUT_TEST_HP_IALL_ADJ(v) \ + (((v) << 20) & BM_AUDIOOUT_TEST_HP_IALL_ADJ) +#define BP_AUDIOOUT_TEST_RSRVD2 14 +#define BM_AUDIOOUT_TEST_RSRVD2 0x000FC000 +#define BF_AUDIOOUT_TEST_RSRVD2(v) \ + (((v) << 14) & BM_AUDIOOUT_TEST_RSRVD2) +#define BM_AUDIOOUT_TEST_VAG_CLASSA 0x00002000 +#define BM_AUDIOOUT_TEST_VAG_DOUBLE_I 0x00001000 +#define BP_AUDIOOUT_TEST_RSRVD1 4 +#define BM_AUDIOOUT_TEST_RSRVD1 0x00000FF0 +#define BF_AUDIOOUT_TEST_RSRVD1(v) \ + (((v) << 4) & BM_AUDIOOUT_TEST_RSRVD1) +#define BM_AUDIOOUT_TEST_ADCTODAC_LOOP 0x00000008 +#define BM_AUDIOOUT_TEST_DAC_CLASSA 0x00000004 +#define BM_AUDIOOUT_TEST_DAC_DOUBLE_I 0x00000002 +#define BM_AUDIOOUT_TEST_DAC_DIS_RTZ 0x00000001 + +#define HW_AUDIOOUT_BISTCTRL (0x000000b0) +#define HW_AUDIOOUT_BISTCTRL_SET (0x000000b4) +#define HW_AUDIOOUT_BISTCTRL_CLR (0x000000b8) +#define HW_AUDIOOUT_BISTCTRL_TOG (0x000000bc) + +#define BP_AUDIOOUT_BISTCTRL_RSVD0 4 +#define BM_AUDIOOUT_BISTCTRL_RSVD0 0xFFFFFFF0 +#define BF_AUDIOOUT_BISTCTRL_RSVD0(v) \ + (((v) << 4) & BM_AUDIOOUT_BISTCTRL_RSVD0) +#define BM_AUDIOOUT_BISTCTRL_FAIL 0x00000008 +#define BM_AUDIOOUT_BISTCTRL_PASS 0x00000004 +#define BM_AUDIOOUT_BISTCTRL_DONE 0x00000002 +#define BM_AUDIOOUT_BISTCTRL_START 0x00000001 + +#define HW_AUDIOOUT_BISTSTAT0 (0x000000c0) +#define HW_AUDIOOUT_BISTSTAT0_SET (0x000000c4) +#define HW_AUDIOOUT_BISTSTAT0_CLR (0x000000c8) +#define HW_AUDIOOUT_BISTSTAT0_TOG (0x000000cc) + +#define BP_AUDIOOUT_BISTSTAT0_RSVD0 24 +#define BM_AUDIOOUT_BISTSTAT0_RSVD0 0xFF000000 +#define BF_AUDIOOUT_BISTSTAT0_RSVD0(v) \ + (((v) << 24) & BM_AUDIOOUT_BISTSTAT0_RSVD0) +#define BP_AUDIOOUT_BISTSTAT0_DATA 0 +#define BM_AUDIOOUT_BISTSTAT0_DATA 0x00FFFFFF +#define BF_AUDIOOUT_BISTSTAT0_DATA(v) \ + (((v) << 0) & BM_AUDIOOUT_BISTSTAT0_DATA) + +#define HW_AUDIOOUT_BISTSTAT1 (0x000000d0) +#define HW_AUDIOOUT_BISTSTAT1_SET (0x000000d4) +#define HW_AUDIOOUT_BISTSTAT1_CLR (0x000000d8) +#define HW_AUDIOOUT_BISTSTAT1_TOG (0x000000dc) + +#define BP_AUDIOOUT_BISTSTAT1_RSVD1 29 +#define BM_AUDIOOUT_BISTSTAT1_RSVD1 0xE0000000 +#define BF_AUDIOOUT_BISTSTAT1_RSVD1(v) \ + (((v) << 29) & BM_AUDIOOUT_BISTSTAT1_RSVD1) +#define BP_AUDIOOUT_BISTSTAT1_STATE 24 +#define BM_AUDIOOUT_BISTSTAT1_STATE 0x1F000000 +#define BF_AUDIOOUT_BISTSTAT1_STATE(v) \ + (((v) << 24) & BM_AUDIOOUT_BISTSTAT1_STATE) +#define BP_AUDIOOUT_BISTSTAT1_RSVD0 8 +#define BM_AUDIOOUT_BISTSTAT1_RSVD0 0x00FFFF00 +#define BF_AUDIOOUT_BISTSTAT1_RSVD0(v) \ + (((v) << 8) & BM_AUDIOOUT_BISTSTAT1_RSVD0) +#define BP_AUDIOOUT_BISTSTAT1_ADDR 0 +#define BM_AUDIOOUT_BISTSTAT1_ADDR 0x000000FF +#define BF_AUDIOOUT_BISTSTAT1_ADDR(v) \ + (((v) << 0) & BM_AUDIOOUT_BISTSTAT1_ADDR) + +#define HW_AUDIOOUT_ANACLKCTRL (0x000000e0) +#define HW_AUDIOOUT_ANACLKCTRL_SET (0x000000e4) +#define HW_AUDIOOUT_ANACLKCTRL_CLR (0x000000e8) +#define HW_AUDIOOUT_ANACLKCTRL_TOG (0x000000ec) + +#define BM_AUDIOOUT_ANACLKCTRL_CLKGATE 0x80000000 +#define BP_AUDIOOUT_ANACLKCTRL_RSRVD3 5 +#define BM_AUDIOOUT_ANACLKCTRL_RSRVD3 0x7FFFFFE0 +#define BF_AUDIOOUT_ANACLKCTRL_RSRVD3(v) \ + (((v) << 5) & BM_AUDIOOUT_ANACLKCTRL_RSRVD3) +#define BM_AUDIOOUT_ANACLKCTRL_INVERT_DACCLK 0x00000010 +#define BM_AUDIOOUT_ANACLKCTRL_RSRVD2 0x00000008 +#define BP_AUDIOOUT_ANACLKCTRL_DACDIV 0 +#define BM_AUDIOOUT_ANACLKCTRL_DACDIV 0x00000007 +#define BF_AUDIOOUT_ANACLKCTRL_DACDIV(v) \ + (((v) << 0) & BM_AUDIOOUT_ANACLKCTRL_DACDIV) + +#define HW_AUDIOOUT_DATA (0x000000f0) +#define HW_AUDIOOUT_DATA_SET (0x000000f4) +#define HW_AUDIOOUT_DATA_CLR (0x000000f8) +#define HW_AUDIOOUT_DATA_TOG (0x000000fc) + +#define BP_AUDIOOUT_DATA_HIGH 16 +#define BM_AUDIOOUT_DATA_HIGH 0xFFFF0000 +#define BF_AUDIOOUT_DATA_HIGH(v) \ + (((v) << 16) & BM_AUDIOOUT_DATA_HIGH) +#define BP_AUDIOOUT_DATA_LOW 0 +#define BM_AUDIOOUT_DATA_LOW 0x0000FFFF +#define BF_AUDIOOUT_DATA_LOW(v) \ + (((v) << 0) & BM_AUDIOOUT_DATA_LOW) + +#define HW_AUDIOOUT_SPEAKERCTRL (0x00000100) +#define HW_AUDIOOUT_SPEAKERCTRL_SET (0x00000104) +#define HW_AUDIOOUT_SPEAKERCTRL_CLR (0x00000108) +#define HW_AUDIOOUT_SPEAKERCTRL_TOG (0x0000010c) + +#define BP_AUDIOOUT_SPEAKERCTRL_RSRVD2 25 +#define BM_AUDIOOUT_SPEAKERCTRL_RSRVD2 0xFE000000 +#define BF_AUDIOOUT_SPEAKERCTRL_RSRVD2(v) \ + (((v) << 25) & BM_AUDIOOUT_SPEAKERCTRL_RSRVD2) +#define BM_AUDIOOUT_SPEAKERCTRL_MUTE 0x01000000 +#define BP_AUDIOOUT_SPEAKERCTRL_I1_ADJ 22 +#define BM_AUDIOOUT_SPEAKERCTRL_I1_ADJ 0x00C00000 +#define BF_AUDIOOUT_SPEAKERCTRL_I1_ADJ(v) \ + (((v) << 22) & BM_AUDIOOUT_SPEAKERCTRL_I1_ADJ) +#define BP_AUDIOOUT_SPEAKERCTRL_IALL_ADJ 20 +#define BM_AUDIOOUT_SPEAKERCTRL_IALL_ADJ 0x00300000 +#define BF_AUDIOOUT_SPEAKERCTRL_IALL_ADJ(v) \ + (((v) << 20) & BM_AUDIOOUT_SPEAKERCTRL_IALL_ADJ) +#define BP_AUDIOOUT_SPEAKERCTRL_RSRVD1 16 +#define BM_AUDIOOUT_SPEAKERCTRL_RSRVD1 0x000F0000 +#define BF_AUDIOOUT_SPEAKERCTRL_RSRVD1(v) \ + (((v) << 16) & BM_AUDIOOUT_SPEAKERCTRL_RSRVD1) +#define BP_AUDIOOUT_SPEAKERCTRL_POSDRIVER 14 +#define BM_AUDIOOUT_SPEAKERCTRL_POSDRIVER 0x0000C000 +#define BF_AUDIOOUT_SPEAKERCTRL_POSDRIVER(v) \ + (((v) << 14) & BM_AUDIOOUT_SPEAKERCTRL_POSDRIVER) +#define BP_AUDIOOUT_SPEAKERCTRL_NEGDRIVER 12 +#define BM_AUDIOOUT_SPEAKERCTRL_NEGDRIVER 0x00003000 +#define BF_AUDIOOUT_SPEAKERCTRL_NEGDRIVER(v) \ + (((v) << 12) & BM_AUDIOOUT_SPEAKERCTRL_NEGDRIVER) +#define BP_AUDIOOUT_SPEAKERCTRL_RSRVD0 0 +#define BM_AUDIOOUT_SPEAKERCTRL_RSRVD0 0x00000FFF +#define BF_AUDIOOUT_SPEAKERCTRL_RSRVD0(v) \ + (((v) << 0) & BM_AUDIOOUT_SPEAKERCTRL_RSRVD0) + +#define HW_AUDIOOUT_VERSION (0x00000200) + +#define BP_AUDIOOUT_VERSION_MAJOR 24 +#define BM_AUDIOOUT_VERSION_MAJOR 0xFF000000 +#define BF_AUDIOOUT_VERSION_MAJOR(v) \ + (((v) << 24) & BM_AUDIOOUT_VERSION_MAJOR) +#define BP_AUDIOOUT_VERSION_MINOR 16 +#define BM_AUDIOOUT_VERSION_MINOR 0x00FF0000 +#define BF_AUDIOOUT_VERSION_MINOR(v) \ + (((v) << 16) & BM_AUDIOOUT_VERSION_MINOR) +#define BP_AUDIOOUT_VERSION_STEP 0 +#define BM_AUDIOOUT_VERSION_STEP 0x0000FFFF +#define BF_AUDIOOUT_VERSION_STEP(v) \ + (((v) << 0) & BM_AUDIOOUT_VERSION_STEP) +#endif /* __ARCH_ARM___AUDIOOUT_H */ diff --git a/arch/arm/mach-mx23/mx23evk.c b/arch/arm/mach-mx23/mx23evk.c index f3d20de5c6b5..edc75c1d23ca 100644 --- a/arch/arm/mach-mx23/mx23evk.c +++ b/arch/arm/mach-mx23/mx23evk.c @@ -39,11 +39,30 @@ static void __init fixup_board(struct machine_desc *desc, struct tag *tags, mx23_set_input_clk(24000000, 24000000, 32000, 50000000); } +#if defined(CONFIG_SND_MXS_SOC_ADC) || defined(CONFIG_SND_MXS_SOC_ADC_MODULE) +static void __init mx23evk_init_adc(void) +{ + struct platform_device *pdev; + pdev = mxs_get_device("mxs-adc", 0); + if (pdev == NULL) + return; + mxs_add_device(pdev, 3); +} +#else +static void __init mx23evk_init_adc(void) +{ + +} +#endif + + static void __init mx23evk_device_init(void) { /* Add mx23evk special code */ + mx23evk_init_adc(); } + static void __init mx23evk_init_machine(void) { mx23_pinctrl_init(); diff --git a/arch/arm/plat-mxs/device.c b/arch/arm/plat-mxs/device.c index 58f483b5f1a2..88c477cfd05e 100644 --- a/arch/arm/plat-mxs/device.c +++ b/arch/arm/plat-mxs/device.c @@ -412,6 +412,18 @@ static struct platform_device mxs_spdif[] = { }; #endif +#if defined(CONFIG_SND_MXS_SOC_ADC) || \ + defined(CONFIG_SND_MXS_SOC_ADC_MODULE) +static struct platform_device mxs_adc = { + .name = "mxs-adc-audio", + .id = 0, + .dev = { + .release = mxs_nop_release, + }, +}; +#endif + + static struct mxs_dev_lookup dev_lookup[] = { #if defined(CONFIG_SERIAL_MXS_DUART) || \ defined(CONFIG_SERIAL_MXS_DUART_MODULE) @@ -586,6 +598,16 @@ static struct mxs_dev_lookup dev_lookup[] = { .pdev = mxs_spdif, }, #endif + +#if defined(CONFIG_SND_MXS_SOC_ADC) || \ + defined(CONFIG_SND_MXS_SOC_ADC_MODULE) + { + .name = "mxs-adc", + .size = 1, + .pdev = &mxs_adc, + }, +#endif + }; struct platform_device *mxs_get_device(char *name, int id) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 893ad3bea214..4362689dd639 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -197,6 +197,10 @@ config SND_SOC_STMP3XXX_SPDIF tristate depends on SND_SOC +config SND_SOC_MXS_ADC_CODEC + tristate + depends on SND_SOC + config SND_SOC_BLUETOOTH tristate depends on SND_SOC diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 0b997cf20e75..8add6333d7c5 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -41,6 +41,7 @@ snd-soc-stmp378x-codec-objs := stmp378x_codec.o snd-soc-stmp3xxx-spdif-objs := stmp3xxx_spdif.o snd-soc-bluetooth-objs := bluetooth.o snd-soc-mxs-spdif-objs := mxs_spdif.o +snd-soc-mxs-adc-objs := mxs-adc-codec.o obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o @@ -85,3 +86,4 @@ obj-$(CONFIG_SND_SOC_STMP378X_CODEC) += snd-soc-stmp378x-codec.o obj-$(CONFIG_SND_SOC_STMP3XXX_SPDIF) += snd-soc-stmp3xxx-spdif.o obj-$(CONFIG_SND_SOC_BLUETOOTH) += snd-soc-bluetooth.o obj-$(CONFIG_SND_SOC_MXS_SPDIF) += snd-soc-mxs-spdif.o +obj-$(CONFIG_SND_SOC_MXS_ADC_CODEC) += snd-soc-mxs-adc.o diff --git a/sound/soc/codecs/mxs-adc-codec.c b/sound/soc/codecs/mxs-adc-codec.c new file mode 100644 index 000000000000..3499975875cb --- /dev/null +++ b/sound/soc/codecs/mxs-adc-codec.c @@ -0,0 +1,1057 @@ +/* + * ALSA codec for Freescale MXS ADC/DAC Audio + * + * Author: Vladislav Buzov <vbuzov@embeddedalley.com> + * + * Copyright 2008-2010 Freescale Semiconductor, Inc. + * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/pm.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/interrupt.h> + +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> +#include <sound/initval.h> +#include <asm/dma.h> + +#include <mach/dma.h> +#include <asm/mach-types.h> +#include <mach/hardware.h> +#include <mach/regs-audioin.h> +#include <mach/regs-audioout.h> + +#include "mxs-adc-codec.h" + +#define BV_AUDIOIN_ADCVOL_SELECT__MIC 0x00 /* missing define */ + +#ifndef BF +#define BF(value, field) (((value) << BP_##field) & BM_##field) +#endif + +struct mxs_codec_priv { + struct clk *clk; + struct snd_soc_codec codec; +}; + +/* + * ALSA API + */ +static void __iomem *adc_regmap[] = { + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_STAT, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_DACSRR, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_DACVOLUME, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_DACDEBUG, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_HPVOL, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_PWRDN, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_REFCTRL, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_ANACTRL, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_TEST, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_BISTCTRL, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_BISTSTAT0, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_BISTSTAT1, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_ANACLKCTRL, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_DATA, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_SPEAKERCTRL, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_VERSION, + REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL, + REGS_AUDIOIN_BASE + HW_AUDIOIN_STAT, + REGS_AUDIOIN_BASE + HW_AUDIOIN_ADCSRR, + REGS_AUDIOIN_BASE + HW_AUDIOIN_ADCVOLUME, + REGS_AUDIOIN_BASE + HW_AUDIOIN_ADCDEBUG, + REGS_AUDIOIN_BASE + HW_AUDIOIN_ADCVOL, + REGS_AUDIOIN_BASE + HW_AUDIOIN_MICLINE, + REGS_AUDIOIN_BASE + HW_AUDIOIN_ANACLKCTRL, + REGS_AUDIOIN_BASE + HW_AUDIOIN_DATA, +}; + +static u16 mxs_audio_regs[ADC_REGNUM]; + +static u8 dac_volumn_control_word[] = { + 0x37, 0x5e, 0x7e, 0x8e, + 0x9e, 0xae, 0xb6, 0xbe, + 0xc6, 0xce, 0xd6, 0xde, + 0xe6, 0xee, 0xf6, 0xfe, +}; + +/* + * ALSA core supports only 16 bit registers. It means we have to simulate it + * by virtually splitting a 32bit ADC/DAC registers into two halves + * high (bits 31:16) and low (bits 15:0). The routins abow detects which part + * of 32bit register is accessed. + */ +static void mxs_codec_write_cache(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value) +{ + u16 *cache = codec->reg_cache; + if (reg < ADC_REGNUM) + cache[reg] = value; +} + +static int mxs_codec_write(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value) +{ + unsigned int reg_val; + unsigned int mask = 0xffff; + + if (reg >= ADC_REGNUM) + return -EIO; + + mxs_codec_write_cache(codec, reg, value); + + if (reg & 0x1) { + mask <<= 16; + value <<= 16; + } + + reg_val = __raw_readl(adc_regmap[reg >> 1]); + reg_val = (reg_val & ~mask) | value; + __raw_writel(reg_val, adc_regmap[reg >> 1]); + + return 0; +} + +static unsigned int mxs_codec_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + unsigned int reg_val; + + if (reg >= ADC_REGNUM) + return -1; + + reg_val = __raw_readl(adc_regmap[reg >> 1]); + if (reg & 1) + reg_val >>= 16; + + return reg_val & 0xffff; +} + +static unsigned int mxs_codec_read_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + if (reg >= ADC_REGNUM) + return -EINVAL; + return cache[reg]; +} + +static void mxs_codec_sync_reg_cache(struct snd_soc_codec *codec) +{ + int reg; + for (reg = 0; reg < ADC_REGNUM; reg += 1) + mxs_codec_write_cache(codec, reg, + mxs_codec_read(codec, reg)); +} + +static int mxs_codec_restore_reg(struct snd_soc_codec *codec, + unsigned int reg) +{ + unsigned int cached_val, hw_val; + + cached_val = mxs_codec_read_cache(codec, reg); + hw_val = mxs_codec_read(codec, reg); + + if (hw_val != cached_val) + return mxs_codec_write(codec, reg, cached_val); + + return 0; +} + +static int dac_info_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0xf; + return 0; +} + +static int dac_get_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int reg, l, r; + int i; + + reg = __raw_readl(REGS_AUDIOOUT_BASE + HW_AUDIOOUT_DACVOLUME); + + l = (reg & BM_AUDIOOUT_DACVOLUME_VOLUME_LEFT) >> + BP_AUDIOOUT_DACVOLUME_VOLUME_LEFT; + r = (reg & BM_AUDIOOUT_DACVOLUME_VOLUME_RIGHT) >> + BP_AUDIOOUT_DACVOLUME_VOLUME_RIGHT; + /*Left channel */ + i = 0; + while (i < 16) { + if (l == dac_volumn_control_word[i]) { + ucontrol->value.integer.value[0] = i; + break; + } + i++; + } + if (i == 16) + ucontrol->value.integer.value[0] = i; + /*Right channel */ + i = 0; + while (i < 16) { + if (r == dac_volumn_control_word[i]) { + ucontrol->value.integer.value[1] = i; + break; + } + i++; + } + if (i == 16) + ucontrol->value.integer.value[1] = i; + + return 0; +} + +static int dac_put_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int reg, l, r; + int i; + + i = ucontrol->value.integer.value[0]; + l = dac_volumn_control_word[i]; + /*Get dac volume for left channel */ + reg = BF(l, AUDIOOUT_DACVOLUME_VOLUME_LEFT); + + i = ucontrol->value.integer.value[1]; + r = dac_volumn_control_word[i]; + /*Get dac volume for right channel */ + reg = reg | BF(r, AUDIOOUT_DACVOLUME_VOLUME_RIGHT); + + /*Clear left/right dac volume */ + __raw_writel(BM_AUDIOOUT_DACVOLUME_VOLUME_LEFT | + BM_AUDIOOUT_DACVOLUME_VOLUME_RIGHT, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_DACVOLUME_CLR); + __raw_writel(reg, REGS_AUDIOOUT_BASE + HW_AUDIOOUT_DACVOLUME_SET); + + return 0; +} + +static const char *mxs_codec_adc_input_sel[] = + { "Mic", "Line In 1", "Head Phone", "Line In 2" }; + +static const char *mxs_codec_hp_output_sel[] = { "DAC Out", "Line In 1" }; + +static const char *mxs_codec_adc_3d_sel[] = + { "Off", "Low", "Medium", "High" }; + +static const struct soc_enum mxs_codec_enum[] = { + SOC_ENUM_SINGLE(ADC_ADCVOL_L, 12, 4, mxs_codec_adc_input_sel), + SOC_ENUM_SINGLE(ADC_ADCVOL_L, 4, 4, mxs_codec_adc_input_sel), + SOC_ENUM_SINGLE(DAC_HPVOL_H, 0, 2, mxs_codec_hp_output_sel), + SOC_ENUM_SINGLE(DAC_CTRL_L, 8, 4, mxs_codec_adc_3d_sel), +}; + +/* Codec controls */ +static const struct snd_kcontrol_new mxs_snd_controls[] = { + /* Playback Volume */ + {.iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "DAC Playback Volume", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = dac_info_volsw, + .get = dac_get_volsw, + .put = dac_put_volsw, + }, + + SOC_DOUBLE_R("DAC Playback Switch", + DAC_VOLUME_H, DAC_VOLUME_L, 8, 0x01, 1), + SOC_DOUBLE("HP Playback Volume", DAC_HPVOL_L, 8, 0, 0x7F, 1), + SOC_SINGLE("HP Playback Switch", DAC_HPVOL_H, 8, 0x1, 1), + SOC_SINGLE("Speaker Playback Switch", DAC_SPEAKERCTRL_H, 8, 0x1, 1), + + /* Capture Volume */ + SOC_DOUBLE_R("ADC Capture Volume", + ADC_VOLUME_H, ADC_VOLUME_L, 0, 0xFF, 0), + SOC_DOUBLE("ADC PGA Capture Volume", ADC_ADCVOL_L, 8, 0, 0x0F, 0), + SOC_SINGLE("ADC PGA Capture Switch", ADC_ADCVOL_H, 8, 0x1, 1), + SOC_SINGLE("Mic PGA Capture Volume", ADC_MICLINE_L, 0, 0x03, 0), + + /* Virtual 3D effect */ + SOC_ENUM("3D effect", mxs_codec_enum[3]), +}; + +/* Left ADC Mux */ +static const struct snd_kcontrol_new mxs_left_adc_controls = +SOC_DAPM_ENUM("Route", mxs_codec_enum[0]); + +/* Right ADC Mux */ +static const struct snd_kcontrol_new mxs_right_adc_controls = +SOC_DAPM_ENUM("Route", mxs_codec_enum[1]); + +/* Head Phone Mux */ +static const struct snd_kcontrol_new mxs_hp_controls = +SOC_DAPM_ENUM("Route", mxs_codec_enum[2]); + +static const struct snd_soc_dapm_widget mxs_codec_widgets[] = { + + SND_SOC_DAPM_ADC("Left ADC", "Left Capture", DAC_PWRDN_L, 8, 1), + SND_SOC_DAPM_ADC("Right ADC", "Right Capture", DAC_PWRDN_H, 0, 1), + + SND_SOC_DAPM_DAC("DAC", "Playback", DAC_PWRDN_L, 12, 1), + + SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0, + &mxs_left_adc_controls), + SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0, + &mxs_right_adc_controls), + SND_SOC_DAPM_MUX("HP Mux", SND_SOC_NOPM, 0, 0, + &mxs_hp_controls), + + SND_SOC_DAPM_PGA("HP_AMP", DAC_PWRDN_L, 0, 1, NULL, 0), + + SND_SOC_DAPM_PGA("HP_CAPLESS", DAC_PWRDN_L, 4, 1, NULL, 0), + + SND_SOC_DAPM_PGA("SPK_AMP", DAC_PWRDN_H, 8, 1, NULL, 0), + + SND_SOC_DAPM_INPUT("LINE1L"), + SND_SOC_DAPM_INPUT("LINE1R"), + SND_SOC_DAPM_INPUT("LINE2L"), + SND_SOC_DAPM_INPUT("LINE2R"), + SND_SOC_DAPM_INPUT("MIC"), + + SND_SOC_DAPM_OUTPUT("SPEAKER"), + SND_SOC_DAPM_OUTPUT("HPL"), + SND_SOC_DAPM_OUTPUT("HPR"), +}; + +static const struct snd_soc_dapm_route intercon[] = { + + /* Left ADC Mux */ + {"Left ADC Mux", "Mic", "MIC"}, + {"Left ADC Mux", "Line In 1", "LINE1L"}, + {"Left ADC Mux", "Line In 2", "LINE2L"}, + {"Left ADC Mux", "Head Phone", "HPL"}, + + /* Right ADC Mux */ + {"Right ADC Mux", "Mic", "MIC"}, + {"Right ADC Mux", "Line In 1", "LINE1R"}, + {"Right ADC Mux", "Line In 2", "LINE2R"}, + {"Right ADC Mux", "Head Phone", "HPR"}, + + /* ADC */ + {"Left ADC", NULL, "Left ADC Mux"}, + {"Right ADC", NULL, "Right ADC Mux"}, + + /* HP Mux */ + {"HP Mux", "DAC Out", "DAC"}, + {"HP Mux", "Line In 1", "LINE1L"}, + {"HP Mux", "Line In 1", "LINE1R"}, + + /* HP output */ + {"HP_CAPLESS", NULL, "HP Mux"}, + {"HP_AMP", NULL, "HP_CAPLESS"}, + {"HPR", NULL, "HP_AMP"}, + {"HPL", NULL, "HP_AMP"}, + + /* Speaker amp */ + {"SPK_AMP", NULL, "DAC"}, + {"SPEAKER", NULL, "SPK_AMP"}, +}; + +static int mxs_codec_add_widgets(struct snd_soc_codec *codec) +{ + int ret = 0; + + snd_soc_dapm_new_controls(codec, mxs_codec_widgets, + ARRAY_SIZE(mxs_codec_widgets)); + + if (ret) { + dev_err(codec->dev, "dapm control register failed\n"); + return ret; + } + /* set up audio path interconnects */ + snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); + + if (ret) { + dev_err(codec->dev, "DAPM route register failed\n"); + return ret; + } + + return snd_soc_dapm_new_widgets(codec); +} + +struct dac_srr { + u32 rate; + u32 basemult; + u32 src_hold; + u32 src_int; + u32 src_frac; +}; + +static struct dac_srr srr_values[] = { + {192000, 0x4, 0x0, 0x0F, 0x13FF}, + {176400, 0x4, 0x0, 0x11, 0x0037}, + {128000, 0x4, 0x0, 0x17, 0x0E00}, + {96000, 0x2, 0x0, 0x0F, 0x13FF}, + {88200, 0x2, 0x0, 0x11, 0x0037}, + {64000, 0x2, 0x0, 0x17, 0x0E00}, + {48000, 0x1, 0x0, 0x0F, 0x13FF}, + {44100, 0x1, 0x0, 0x11, 0x0037}, + {32000, 0x1, 0x0, 0x17, 0x0E00}, + {24000, 0x1, 0x1, 0x0F, 0x13FF}, + {22050, 0x1, 0x1, 0x11, 0x0037}, + {16000, 0x1, 0x1, 0x17, 0x0E00}, + {12000, 0x1, 0x3, 0x0F, 0x13FF}, + {11025, 0x1, 0x3, 0x11, 0x0037}, + {8000, 0x1, 0x3, 0x17, 0x0E00} +}; + +static inline int get_srr_values(int rate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(srr_values); i++) + if (srr_values[i].rate == rate) + return i; + + return -1; +} + +static int mxs_codec_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_device *socdev = rtd->socdev; + struct snd_soc_codec *codec = socdev->card->codec; + int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0; + int i; + u32 srr_value = 0; + u32 src_hold = 0; + + i = get_srr_values(params_rate(params)); + if (i < 0) + dev_warn(socdev->dev, "%s doesn't support rate %d\n", + codec->name, params_rate(params)); + else { + src_hold = srr_values[i].src_hold; + + srr_value = + BF(srr_values[i].basemult, AUDIOOUT_DACSRR_BASEMULT) | + BF(srr_values[i].src_int, AUDIOOUT_DACSRR_SRC_INT) | + BF(srr_values[i].src_frac, AUDIOOUT_DACSRR_SRC_FRAC) | + BF(src_hold, AUDIOOUT_DACSRR_SRC_HOLD); + + if (playback) + __raw_writel(srr_value, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_DACSRR); + else + __raw_writel(srr_value, + REGS_AUDIOIN_BASE + HW_AUDIOIN_ADCSRR); + } + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + if (playback) + __raw_writel(BM_AUDIOOUT_CTRL_WORD_LENGTH, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL_SET); + else + __raw_writel(BM_AUDIOIN_CTRL_WORD_LENGTH, + REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL_SET); + + break; + + case SNDRV_PCM_FORMAT_S32_LE: + if (playback) + __raw_writel(BM_AUDIOOUT_CTRL_WORD_LENGTH, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL_CLR); + else + __raw_writel(BM_AUDIOIN_CTRL_WORD_LENGTH, + REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL_CLR); + + break; + + default: + dev_warn(socdev->dev, "%s doesn't support format %d\n", + codec->name, params_format(params)); + + } + + return 0; +} + +static int mxs_codec_dig_mute(struct snd_soc_dai *dai, int mute) +{ + u32 dac_mask = BM_AUDIOOUT_DACVOLUME_MUTE_LEFT | + BM_AUDIOOUT_DACVOLUME_MUTE_RIGHT; + + if (mute) { + __raw_writel(dac_mask, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_DACVOLUME_SET); + __raw_writel(BM_AUDIOOUT_HPVOL_MUTE, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_HPVOL_SET); + __raw_writel(BM_AUDIOOUT_SPEAKERCTRL_MUTE, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_SPEAKERCTRL_SET); + } else { + __raw_writel(dac_mask, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_DACVOLUME_CLR); + __raw_writel(BM_AUDIOOUT_HPVOL_MUTE, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_HPVOL_CLR); + __raw_writel(BM_AUDIOOUT_SPEAKERCTRL_MUTE, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_SPEAKERCTRL_CLR); + } + return 0; +} + +/* + * Codec initialization + */ +#define VAG_BASE_VALUE ((1400/2 - 625)/25) +static void mxs_codec_dac_set_vag(void) +{ + u32 refctrl_val = __raw_readl(REGS_AUDIOOUT_BASE + HW_AUDIOOUT_REFCTRL); + + refctrl_val &= ~(BM_AUDIOOUT_REFCTRL_VAG_VAL); + refctrl_val &= ~(BM_AUDIOOUT_REFCTRL_VBG_ADJ); + refctrl_val |= BF(VAG_BASE_VALUE, AUDIOOUT_REFCTRL_VAG_VAL) | + BM_AUDIOOUT_REFCTRL_ADJ_VAG | + BF(0xF, AUDIOOUT_REFCTRL_ADC_REFVAL) | + BM_AUDIOOUT_REFCTRL_ADJ_ADC | + BF(0x3, AUDIOOUT_REFCTRL_VBG_ADJ) | BM_AUDIOOUT_REFCTRL_RAISE_REF; + + __raw_writel(refctrl_val, REGS_AUDIOOUT_BASE + HW_AUDIOOUT_REFCTRL); +} + +static void +mxs_codec_dac_power_on(struct mxs_codec_priv *mxs_adc) +{ + /* Ungate DAC clocks */ + __raw_writel(BM_AUDIOOUT_CTRL_CLKGATE, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL_CLR); + __raw_writel(BM_AUDIOOUT_ANACLKCTRL_CLKGATE, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_ANACLKCTRL_CLR); + + /* 16 bit word length */ + __raw_writel(BM_AUDIOOUT_CTRL_WORD_LENGTH, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL_SET); + + /* Update DAC volume over zero crossings */ + __raw_writel(BM_AUDIOOUT_DACVOLUME_EN_ZCD, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_DACVOLUME_SET); + /* Mute DAC */ + __raw_writel(BM_AUDIOOUT_DACVOLUME_MUTE_LEFT | + BM_AUDIOOUT_DACVOLUME_MUTE_RIGHT, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_DACVOLUME_SET); + + /* Update HP volume over zero crossings */ + __raw_writel(BM_AUDIOOUT_HPVOL_EN_MSTR_ZCD, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_HPVOL_SET); + + /* Prepare powering up HP output */ + __raw_writel(BM_AUDIOOUT_ANACTRL_HP_HOLD_GND, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_ANACTRL_SET); + /*__raw_writel(BF(0x2, RTC_PERSISTENT0_SPARE_ANALOG), + REGS_RTC_BASE + HW_RTC_PERSISTENT0_SET);*/ + __raw_writel(BM_AUDIOOUT_ANACTRL_HP_CLASSAB, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_ANACTRL_SET); + __raw_writel(BM_AUDIOOUT_ANACTRL_HP_HOLD_GND, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_ANACTRL_CLR); + /* Mute HP output */ + __raw_writel(BM_AUDIOOUT_HPVOL_MUTE, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_HPVOL_SET); + + /* Mute speaker amp */ + __raw_writel(BM_AUDIOOUT_SPEAKERCTRL_MUTE, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_SPEAKERCTRL_SET); +} + +static void +mxs_codec_dac_power_down(struct mxs_codec_priv *mxs_adc) +{ + /* Disable class AB */ + __raw_writel(BM_AUDIOOUT_ANACTRL_HP_CLASSAB, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_ANACTRL_CLR); + + /* Set hold to ground */ + __raw_writel(BM_AUDIOOUT_ANACTRL_HP_HOLD_GND, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_ANACTRL_SET); + + /* Mute HP output */ + __raw_writel(BM_AUDIOOUT_HPVOL_MUTE, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_HPVOL_SET); + /* Power down HP output */ + __raw_writel(BM_AUDIOOUT_PWRDN_HEADPHONE, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_PWRDN_SET); + + /* Mute speaker amp */ + __raw_writel(BM_AUDIOOUT_SPEAKERCTRL_MUTE, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_SPEAKERCTRL_SET); + /* Power down speaker amp */ + __raw_writel(BM_AUDIOOUT_PWRDN_SPEAKER, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_PWRDN_SET); + + /* Mute DAC */ + __raw_writel(BM_AUDIOOUT_DACVOLUME_MUTE_LEFT | + BM_AUDIOOUT_DACVOLUME_MUTE_RIGHT, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_DACVOLUME_SET); + /* Power down DAC */ + __raw_writel(BM_AUDIOOUT_PWRDN_DAC, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_PWRDN_SET); + + /* Gate DAC clocks */ + __raw_writel(BM_AUDIOOUT_ANACLKCTRL_CLKGATE, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_ANACLKCTRL_SET); + __raw_writel(BM_AUDIOOUT_CTRL_CLKGATE, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL_SET); +} + +static void +mxs_codec_adc_power_on(struct mxs_codec_priv *mxs_adc) +{ + u32 reg; + + /* Ungate ADC clocks */ + __raw_writel(BM_AUDIOIN_CTRL_CLKGATE, + REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL_CLR); + __raw_writel(BM_AUDIOIN_ANACLKCTRL_CLKGATE, + REGS_AUDIOIN_BASE + HW_AUDIOIN_ANACLKCTRL_CLR); + + /* 16 bit word length */ + __raw_writel(BM_AUDIOIN_CTRL_WORD_LENGTH, + REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL_SET); + + /* Unmute ADC channels */ + __raw_writel(BM_AUDIOIN_ADCVOL_MUTE, + REGS_AUDIOIN_BASE + HW_AUDIOIN_ADCVOL_CLR); + + /* + * The MUTE_LEFT and MUTE_RIGHT fields need to be cleared. + * They aren't presented in the datasheet, so this is hardcode. + */ + __raw_writel(0x01000100, REGS_AUDIOIN_BASE + HW_AUDIOIN_ADCVOLUME_CLR); + + /* Set the Input channel gain 3dB */ + __raw_writel(BM_AUDIOIN_ADCVOL_GAIN_LEFT, + REGS_AUDIOIN_BASE + HW_AUDIOIN_ADCVOL_CLR); + __raw_writel(BM_AUDIOIN_ADCVOL_GAIN_RIGHT, + REGS_AUDIOIN_BASE + HW_AUDIOIN_ADCVOL_CLR); + __raw_writel(BF(2, AUDIOIN_ADCVOL_GAIN_LEFT), + REGS_AUDIOIN_BASE + HW_AUDIOIN_ADCVOL_SET); + __raw_writel(BF(2, AUDIOIN_ADCVOL_GAIN_RIGHT), + REGS_AUDIOIN_BASE + HW_AUDIOIN_ADCVOL_SET); + + /* Select default input - Microphone */ + __raw_writel(BM_AUDIOIN_ADCVOL_SELECT_LEFT, + REGS_AUDIOIN_BASE + HW_AUDIOIN_ADCVOL_CLR); + __raw_writel(BM_AUDIOIN_ADCVOL_SELECT_RIGHT, + REGS_AUDIOIN_BASE + HW_AUDIOIN_ADCVOL_CLR); + __raw_writel(BF + (BV_AUDIOIN_ADCVOL_SELECT__MIC, + AUDIOIN_ADCVOL_SELECT_LEFT), + REGS_AUDIOIN_BASE + HW_AUDIOIN_ADCVOL_SET); + __raw_writel(BF + (BV_AUDIOIN_ADCVOL_SELECT__MIC, + AUDIOIN_ADCVOL_SELECT_RIGHT), + REGS_AUDIOIN_BASE + HW_AUDIOIN_ADCVOL_SET); + + /* Supply bias voltage to microphone */ + __raw_writel(BF(2, AUDIOIN_MICLINE_MIC_RESISTOR), + REGS_AUDIOIN_BASE + HW_AUDIOIN_MICLINE_SET); + __raw_writel(BM_AUDIOIN_MICLINE_MIC_SELECT, + REGS_AUDIOIN_BASE + HW_AUDIOIN_MICLINE_SET); + + /* Set max ADC volume */ + reg = __raw_readl(REGS_AUDIOIN_BASE + HW_AUDIOIN_ADCVOLUME); + reg &= ~BM_AUDIOIN_ADCVOLUME_VOLUME_LEFT; + reg &= ~BM_AUDIOIN_ADCVOLUME_VOLUME_RIGHT; + reg |= BF(ADC_VOLUME_MAX, AUDIOIN_ADCVOLUME_VOLUME_LEFT); + reg |= BF(ADC_VOLUME_MAX, AUDIOIN_ADCVOLUME_VOLUME_RIGHT); + __raw_writel(reg, REGS_AUDIOIN_BASE + HW_AUDIOIN_ADCVOLUME); +} + +static void +mxs_codec_adc_power_down(struct mxs_codec_priv *mxs_adc) +{ + /* Mute ADC channels */ + __raw_writel(BM_AUDIOIN_ADCVOL_MUTE, + REGS_AUDIOIN_BASE + HW_AUDIOIN_ADCVOL_SET); + + /* Power Down ADC */ + __raw_writel(BM_AUDIOOUT_PWRDN_ADC | BM_AUDIOOUT_PWRDN_RIGHT_ADC, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_PWRDN_SET); + + /* Gate ADC clocks */ + __raw_writel(BM_AUDIOIN_CTRL_CLKGATE, + REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL_SET); + __raw_writel(BM_AUDIOIN_ANACLKCTRL_CLKGATE, + REGS_AUDIOIN_BASE + HW_AUDIOIN_ANACLKCTRL_SET); + + /* Disable bias voltage to microphone */ + __raw_writel(BF(0, AUDIOIN_MICLINE_MIC_RESISTOR), + REGS_AUDIOIN_BASE + HW_AUDIOIN_MICLINE_SET); +} + +static void mxs_codec_dac_enable(struct mxs_codec_priv *mxs_adc) +{ + /* Move DAC codec out of reset */ + __raw_writel(BM_AUDIOOUT_CTRL_SFTRST, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL_CLR); + + /* Reduce analog power */ + __raw_writel(BM_AUDIOOUT_TEST_HP_I1_ADJ, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_TEST_CLR); + __raw_writel(BF(0x1, AUDIOOUT_TEST_HP_I1_ADJ), + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_TEST_SET); + __raw_writel(BM_AUDIOOUT_REFCTRL_LOW_PWR, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_REFCTRL_SET); + __raw_writel(BM_AUDIOOUT_REFCTRL_XTAL_BGR_BIAS, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_REFCTRL_SET); + __raw_writel(BM_AUDIOOUT_REFCTRL_BIAS_CTRL, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_REFCTRL_CLR); + __raw_writel(BF(0x1, AUDIOOUT_REFCTRL_BIAS_CTRL), + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_REFCTRL_CLR); + + /* Set Vag value */ + mxs_codec_dac_set_vag(); + + /* Power on DAC codec */ + mxs_codec_dac_power_on(mxs_adc); +} + +static void mxs_codec_dac_disable(struct mxs_codec_priv *mxs_adc) +{ + mxs_codec_dac_power_down(mxs_adc); +} + +static void mxs_codec_adc_enable(struct mxs_codec_priv *mxs_adc) +{ + /* Move ADC codec out of reset */ + __raw_writel(BM_AUDIOIN_CTRL_SFTRST, + REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL_CLR); + + /* Power on ADC codec */ + mxs_codec_adc_power_on(mxs_adc); +} + +static void mxs_codec_adc_disable(struct mxs_codec_priv *mxs_adc) +{ + mxs_codec_adc_power_down(mxs_adc); +} + +static void mxs_codec_startup(struct snd_soc_codec *codec) +{ + struct mxs_codec_priv *mxs_adc = codec->private_data; + + /* Soft reset DAC block */ + __raw_writel(BM_AUDIOOUT_CTRL_SFTRST, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL_SET); + while (!(__raw_readl(REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL) + & BM_AUDIOOUT_CTRL_CLKGATE)){ + } + + /* Soft reset ADC block */ + __raw_writel(BM_AUDIOIN_CTRL_SFTRST, + REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL_SET); + while (!(__raw_readl(REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL) + & BM_AUDIOIN_CTRL_CLKGATE)){ + } + + mxs_codec_dac_enable(mxs_adc); + mxs_codec_adc_enable(mxs_adc); + + /*Sync regs and cache */ + mxs_codec_sync_reg_cache(codec); + + snd_soc_add_controls(codec, mxs_snd_controls, + ARRAY_SIZE(mxs_snd_controls)); + + mxs_codec_add_widgets(codec); +} + +static void mxs_codec_stop(struct snd_soc_codec *codec) +{ + struct mxs_codec_priv *mxs_adc = codec->private_data; + mxs_codec_dac_disable(mxs_adc); + mxs_codec_adc_disable(mxs_adc); +} + +#define MXS_ADC_RATES SNDRV_PCM_RATE_8000_192000 +#define MXS_ADC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_ops mxs_dai_ops = { + .hw_params = mxs_codec_hw_params, + .digital_mute = mxs_codec_dig_mute, +}; + +struct snd_soc_dai mxs_codec_dai = { + .name = "mxs adc/dac", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = MXS_ADC_RATES, + .formats = MXS_ADC_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 2, + .rates = MXS_ADC_RATES, + .formats = MXS_ADC_FORMATS, + }, + .ops = &mxs_dai_ops, +}; +EXPORT_SYMBOL_GPL(mxs_codec_dai); + +static struct snd_soc_codec *mxs_codec; + +static int mxs_codec_probe(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec; + int ret = 0; + + socdev->card->codec = mxs_codec; + codec = mxs_codec; + + /* register pcms */ + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + if (ret < 0) { + dev_err(codec->dev, "failed to create pcms\n"); + return ret; + } + + mxs_codec_startup(codec); + + /* Register the socdev */ + ret = snd_soc_init_card(socdev); + if (ret < 0) { + dev_err(codec->dev, "failed to register card\n"); + snd_soc_dapm_free(socdev); + snd_soc_free_pcms(socdev); + return ret; + } + + return 0; +} + +static int mxs_codec_remove(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->card->codec; + + mxs_codec_stop(codec); + + snd_soc_dapm_free(socdev); + snd_soc_free_pcms(socdev); + + return 0; +} + +#ifdef CONFIG_PM +static int mxs_codec_suspend(struct platform_device *pdev, + pm_message_t state) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->card->codec; + struct mxs_codec_priv *mxs_adc; + int ret = -EINVAL; + + if (codec == NULL) + goto out; + + mxs_adc = codec->private_data; + + mxs_codec_dac_disable(mxs_adc); + mxs_codec_adc_disable(mxs_adc); + clk_disable(mxs_adc->clk); + ret = 0; + +out: + return ret; +} + +static int mxs_codec_resume(struct platform_device *pdev) +{ + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->card->codec; + struct mxs_codec_priv *mxs_adc; + int ret = -EINVAL; + + if (codec == NULL) + goto out; + + mxs_adc = codec->private_data; + clk_enable(mxs_adc->clk); + + /* Soft reset DAC block */ + __raw_writel(BM_AUDIOOUT_CTRL_SFTRST, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL_SET); + while (! + (__raw_readl(REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL) + & BM_AUDIOOUT_CTRL_CLKGATE)){ + } + + /* Soft reset ADC block */ + __raw_writel(BM_AUDIOIN_CTRL_SFTRST, + REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL_SET); + while (! + (__raw_readl(REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL) + & BM_AUDIOIN_CTRL_CLKGATE)){ + } + + mxs_codec_dac_enable(mxs_adc); + mxs_codec_adc_enable(mxs_adc); + + /*restore registers relevant to amixer controls */ + mxs_codec_restore_reg(codec, DAC_CTRL_L); + mxs_codec_restore_reg(codec, DAC_VOLUME_L); + mxs_codec_restore_reg(codec, DAC_VOLUME_H); + mxs_codec_restore_reg(codec, DAC_HPVOL_L); + mxs_codec_restore_reg(codec, DAC_HPVOL_H); + mxs_codec_restore_reg(codec, DAC_SPEAKERCTRL_H); + mxs_codec_restore_reg(codec, ADC_VOLUME_L); + mxs_codec_restore_reg(codec, ADC_VOLUME_H); + mxs_codec_restore_reg(codec, ADC_ADCVOL_L); + mxs_codec_restore_reg(codec, ADC_ADCVOL_H); + mxs_codec_restore_reg(codec, ADC_MICLINE_L); + + ret = 0; + +out: + return ret; +} +#else +#define mxs_codec_suspend NULL +#define mxs_codec_resume NULL +#endif /* CONFIG_PM */ + +struct snd_soc_codec_device soc_codec_dev_mxs = { + .probe = mxs_codec_probe, + .remove = mxs_codec_remove, + .suspend = mxs_codec_suspend, + .resume = mxs_codec_resume, +}; +EXPORT_SYMBOL_GPL(soc_codec_dev_mxs); + +/* codec register, unregister function */ +static int __init mxs_codec_audio_probe(struct platform_device *pdev) +{ + struct mxs_codec_priv *mxs_adc; + struct snd_soc_codec *codec; + int ret = 0; + + dev_info(&pdev->dev, + "MXS ADC/DAC Audio Codec \n"); + + mxs_adc = kzalloc(sizeof(struct mxs_codec_priv), GFP_KERNEL); + if (mxs_adc == NULL) + return -ENOMEM; + + codec = &mxs_adc->codec; + codec->dev = &pdev->dev; + codec->name = "mxs adc/dac"; + codec->owner = THIS_MODULE; + codec->private_data = mxs_adc; + codec->read = mxs_codec_read; + codec->write = mxs_codec_write; + codec->dai = &mxs_codec_dai; + codec->num_dai = 1; + codec->reg_cache_size = sizeof(mxs_audio_regs) >> 1; + codec->reg_cache_step = 1; + codec->reg_cache = (void *)&mxs_audio_regs; + + platform_set_drvdata(pdev, mxs_adc); + + mxs_codec = codec; + + mutex_init(&codec->mutex); + INIT_LIST_HEAD(&codec->dapm_widgets); + INIT_LIST_HEAD(&codec->dapm_paths); + + /* Turn on audio clock */ + mxs_adc->clk = clk_get(&pdev->dev, "audio"); + if (IS_ERR(mxs_adc->clk)) { + ret = PTR_ERR(mxs_adc->clk); + dev_err(&pdev->dev, "%s: Clocks initialization failed\n", + __func__); + goto clk_err; + } + clk_enable(mxs_adc->clk); + + ret = snd_soc_register_codec(codec); + if (ret) { + dev_err(&pdev->dev, "failed to register card\n"); + goto card_err; + } + + ret = snd_soc_register_dai(&mxs_codec_dai); + if (ret) { + dev_err(&pdev->dev, "failed to register codec dai\n"); + goto dai_err; + } + + return 0; + +dai_err: + snd_soc_unregister_codec(codec); +card_err: + clk_disable(mxs_adc->clk); + clk_put(mxs_adc->clk); +clk_err: + kfree(mxs_adc); + return ret; +} + +static int __devexit mxs_codec_audio_remove(struct platform_device *pdev) +{ + struct mxs_codec_priv *mxs_adc = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = &mxs_adc->codec; + + snd_soc_unregister_codec(codec); + + clk_disable(mxs_adc->clk); + clk_put(mxs_adc->clk); + + kfree(mxs_adc); + + return 0; +} + +struct platform_driver mxs_codec_audio_driver = { + .driver = { + .name = "mxs-adc-audio", + }, + .probe = mxs_codec_audio_probe, + .remove = __devexit_p(mxs_codec_audio_remove), +}; + +static int __init mxs_codec_init(void) +{ + return platform_driver_register(&mxs_codec_audio_driver); +} + +static void __exit mxs_codec_exit(void) +{ + return platform_driver_unregister(&mxs_codec_audio_driver); +} + +module_init(mxs_codec_init); +module_exit(mxs_codec_exit); + +MODULE_DESCRIPTION("MXS ADC/DAC codec"); +MODULE_AUTHOR("Vladislav Buzov"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/mxs-adc-codec.h b/sound/soc/codecs/mxs-adc-codec.h new file mode 100644 index 000000000000..129c1c7bdf66 --- /dev/null +++ b/sound/soc/codecs/mxs-adc-codec.h @@ -0,0 +1,87 @@ +/* + * ALSA codec for Freescale MXS ADC/DAC Audio + * + * Author: Vladislav Buzov <vbuzov@embeddedalley.com> + * + * Copyright 2008-2010 Freescale Semiconductor, Inc. + * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#ifndef __MXS_ADC_CODEC_H +#define __MXS_ADC_CODEC_H + +#define DAC_CTRL_L 0 +#define DAC_CTRL_H 1 +#define DAC_STAT_L 2 +#define DAC_STAT_H 3 +#define DAC_SRR_L 4 +#define DAC_VOLUME_L 6 +#define DAC_VOLUME_H 7 +#define DAC_DEBUG_L 8 +#define DAC_DEBUG_H 9 +#define DAC_HPVOL_L 10 +#define DAC_HPVOL_H 11 +#define DAC_PWRDN_L 12 +#define DAC_PWRDN_H 13 +#define DAC_REFCTRL_L 14 +#define DAC_REFCTRL_H 15 +#define DAC_ANACTRL_L 16 +#define DAC_ANACTRL_H 17 +#define DAC_TEST_L 18 +#define DAC_TEST_H 19 +#define DAC_BISTCTRL_L 20 +#define DAC_BISTCTRL_H 21 +#define DAC_BISTSTAT0_L 22 +#define DAC_BISTSTAT0_H 23 +#define DAC_BISTSTAT1_L 24 +#define DAC_BISTSTAT1_H 25 +#define DAC_ANACLKCTRL_L 26 +#define DAC_ANACLKCTRL_H 27 +#define DAC_DATA_L 28 +#define DAC_DATA_H 29 +#define DAC_SPEAKERCTRL_L 30 +#define DAC_SPEAKERCTRL_H 31 +#define DAC_VERSION_L 32 +#define DAC_VERSION_H 33 +#define ADC_CTRL_L 34 +#define ADC_CTRL_H 35 +#define ADC_STAT_L 36 +#define ADC_STAT_H 37 +#define ADC_SRR_L 38 +#define ADC_SRR_H 39 +#define ADC_VOLUME_L 40 +#define ADC_VOLUME_H 41 +#define ADC_DEBUG_L 42 +#define ADC_DEBUG_H 43 +#define ADC_ADCVOL_L 44 +#define ADC_ADCVOL_H 45 +#define ADC_MICLINE_L 46 +#define ADC_MICLINE_H 47 +#define ADC_ANACLKCTRL_L 48 +#define ADC_ANACLKCTRL_H 49 +#define ADC_DATA_L 50 +#define ADC_DATA_H 51 + +#define ADC_REGNUM 52 + +#define DAC_VOLUME_MIN 0x37 +#define DAC_VOLUME_MAX 0xFE +#define ADC_VOLUME_MIN 0x37 +#define ADC_VOLUME_MAX 0xFE +#define HP_VOLUME_MAX 0x0 +#define HP_VOLUME_MIN 0x7F +#define LO_VOLUME_MAX 0x0 +#define LO_VOLUME_MIN 0x1F + +extern struct snd_soc_dai mxs_codec_dai; +extern struct snd_soc_codec_device soc_codec_dev_mxs; + +#endif /* __MXS_ADC_CODEC_H */ diff --git a/sound/soc/mxs/Kconfig b/sound/soc/mxs/Kconfig index 12e95ab6dce4..d4dc2b795eb0 100644 --- a/sound/soc/mxs/Kconfig +++ b/sound/soc/mxs/Kconfig @@ -18,6 +18,14 @@ config SND_MXS_SOC_EVK_DEVB Say Y if you want to add support for SoC audio on MXS EVK development board with the sgtl5000 codec. +config SND_MXS_SOC_EVK_ADC + tristate "SoC Audio support for MXS-EVK ADC/DAC" + depends on SND_MXS_SOC && ARCH_MX23 + select SND_SOC_MXS_ADC_CODEC + help + Say Y if you want to add support for SoC audio on MXS EVK development + board with ADC/DAC audio interface. + config SND_MXS_SOC_DAI tristate "MXS Digital Audio Interface SAIF" default y @@ -38,6 +46,12 @@ config SND_MXS_SOC_SAIF1_SELECT help Enable MXS SAIF1 Module +config SND_MXS_SOC_ADC + tristate "MXS ADC/DAC Audio Interface" + default y + depends on SND_MXS_SOC_EVK_ADC + help + Enable MXS ADC/DAC Audio Interface config SND_MXS_SOC_EVK_DEVB_SPDIF tristate "SoC SPDIF support for MXS EVK Development Board" diff --git a/sound/soc/mxs/Makefile b/sound/soc/mxs/Makefile index 6a8ce0ef8d93..971c622a34fb 100644 --- a/sound/soc/mxs/Makefile +++ b/sound/soc/mxs/Makefile @@ -4,9 +4,13 @@ snd-soc-mxs-dai-objs := mxs-dai.o snd-soc-mxs-spdif-dai-objs := mxs-spdif-dai.o snd-soc-mxs-devb-objs := mxs-devb.o snd-soc-mxs-devb-spdif-objs := mxs-devb-spdif.o +snd-soc-mxs-adc-objs := mxs-adc.o +snd-soc-mxs-evk-adc-objs := mxs-evk-adc.o obj-$(CONFIG_SND_MXS_SOC) += snd-soc-mxs.o obj-$(CONFIG_SND_MXS_SOC_DAI) += snd-soc-mxs-dai.o obj-$(CONFIG_SND_MXS_SOC_SPDIF_DAI) += snd-soc-mxs-spdif-dai.o obj-$(CONFIG_SND_MXS_SOC_EVK_DEVB) += snd-soc-mxs-devb.o obj-$(CONFIG_SND_MXS_SOC_EVK_DEVB_SPDIF) += snd-soc-mxs-devb-spdif.o +obj-$(CONFIG_SND_MXS_SOC_ADC) += snd-soc-mxs-adc.o +obj-$(CONFIG_SND_MXS_SOC_EVK_ADC) += snd-soc-mxs-evk-adc.o diff --git a/sound/soc/mxs/mxs-adc.c b/sound/soc/mxs/mxs-adc.c new file mode 100644 index 000000000000..a6b843bf7f9e --- /dev/null +++ b/sound/soc/mxs/mxs-adc.c @@ -0,0 +1,257 @@ +/* + * ASoC Audio Layer for Freescale MXS ADC/DAC + * + * Author: Vladislav Buzov <vbuzov@embeddedalley.com> + * + * Copyright 2008-2010 Freescale Semiconductor, Inc. + * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/dma-mapping.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <mach/dma.h> +#include <asm/mach-types.h> +#include <mach/hardware.h> +#include <mach/regs-audioin.h> +#include <mach/regs-audioout.h> + +#include "mxs-pcm.h" + +#define MXS_ADC_RATES SNDRV_PCM_RATE_8000_192000 +#define MXS_ADC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +struct mxs_pcm_dma_params mxs_audio_in = { + .name = "mxs-audio-in", + .dma_ch = MXS_DMA_CHANNEL_AHB_APBX_AUDIOADC, + .irq = IRQ_ADC_DMA, +}; + +struct mxs_pcm_dma_params mxs_audio_out = { + .name = "mxs-audio-out", + .dma_ch = MXS_DMA_CHANNEL_AHB_APBX_AUDIODAC, + .irq = IRQ_DAC_DMA, +}; + +static irqreturn_t mxs_err_irq(int irq, void *dev_id) +{ + struct snd_pcm_substream *substream = dev_id; + int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0; + u32 ctrl_reg; + u32 overflow_mask; + u32 underflow_mask; + + if (playback) { + ctrl_reg = __raw_readl(REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL); + underflow_mask = BM_AUDIOOUT_CTRL_FIFO_UNDERFLOW_IRQ; + overflow_mask = BM_AUDIOOUT_CTRL_FIFO_OVERFLOW_IRQ; + } else { + ctrl_reg = __raw_readl(REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL); + underflow_mask = BM_AUDIOIN_CTRL_FIFO_UNDERFLOW_IRQ; + overflow_mask = BM_AUDIOIN_CTRL_FIFO_OVERFLOW_IRQ; + } + + if (ctrl_reg & underflow_mask) { + printk(KERN_DEBUG "%s underflow detected\n", + playback ? "DAC" : "ADC"); + + if (playback) + __raw_writel( + BM_AUDIOOUT_CTRL_FIFO_UNDERFLOW_IRQ, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL_CLR); + else + __raw_writel( + BM_AUDIOIN_CTRL_FIFO_UNDERFLOW_IRQ, + REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL_CLR); + + } else if (ctrl_reg & overflow_mask) { + printk(KERN_DEBUG "%s overflow detected\n", + playback ? "DAC" : "ADC"); + + if (playback) + __raw_writel( + BM_AUDIOOUT_CTRL_FIFO_OVERFLOW_IRQ, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL_CLR); + else + __raw_writel(BM_AUDIOIN_CTRL_FIFO_OVERFLOW_IRQ, + REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL_CLR); + } else + printk(KERN_WARNING "Unknown DAC error interrupt\n"); + + return IRQ_HANDLED; +} + +static int mxs_adc_trigger(struct snd_pcm_substream *substream, + int cmd, + struct snd_soc_dai *dai) +{ + int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0; + int ret = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + if (playback) + __raw_writel(BM_AUDIOOUT_CTRL_RUN, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL_SET); + else + __raw_writel(BM_AUDIOIN_CTRL_RUN, + REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL_SET); + break; + + case SNDRV_PCM_TRIGGER_STOP: + if (playback) + __raw_writel(BM_AUDIOOUT_CTRL_RUN, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL_CLR); + else + __raw_writel(BM_AUDIOIN_CTRL_RUN, + REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL_CLR); + break; + + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int mxs_adc_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0; + int irq; + int ret; + + if (playback) { + irq = IRQ_DAC_ERROR; + cpu_dai->dma_data = &mxs_audio_out; + } else { + irq = IRQ_ADC_ERROR; + cpu_dai->dma_data = &mxs_audio_in; + } + + ret = request_irq(irq, mxs_err_irq, 0, "MXS DAC/ADC Error", + substream); + if (ret) { + printk(KERN_ERR "%s: Unable to request ADC/DAC error irq %d\n", + __func__, IRQ_DAC_ERROR); + return ret; + } + + /* Enable error interrupt */ + if (playback) { + __raw_writel(BM_AUDIOOUT_CTRL_FIFO_OVERFLOW_IRQ, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL_CLR); + __raw_writel(BM_AUDIOOUT_CTRL_FIFO_UNDERFLOW_IRQ, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL_CLR); + __raw_writel(BM_AUDIOOUT_CTRL_FIFO_ERROR_IRQ_EN, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL_SET); + } else { + __raw_writel(BM_AUDIOIN_CTRL_FIFO_OVERFLOW_IRQ, + REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL_CLR); + __raw_writel(BM_AUDIOIN_CTRL_FIFO_UNDERFLOW_IRQ, + REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL_CLR); + __raw_writel(BM_AUDIOIN_CTRL_FIFO_ERROR_IRQ_EN, + REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL_SET); + } + + return 0; +} + +static void mxs_adc_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0; + + /* Disable error interrupt */ + if (playback) { + __raw_writel(BM_AUDIOOUT_CTRL_FIFO_ERROR_IRQ_EN, + REGS_AUDIOOUT_BASE + HW_AUDIOOUT_CTRL_CLR); + free_irq(IRQ_DAC_ERROR, substream); + } else { + __raw_writel(BM_AUDIOIN_CTRL_FIFO_ERROR_IRQ_EN, + REGS_AUDIOIN_BASE + HW_AUDIOIN_CTRL_CLR); + free_irq(IRQ_ADC_ERROR, substream); + } +} + +#ifdef CONFIG_PM +static int mxs_adc_suspend(struct snd_soc_dai *cpu_dai) +{ + return 0; +} + +static int mxs_adc_resume(struct snd_soc_dai *cpu_dai) +{ + return 0; +} +#else +#define mxs_adc_suspend NULL +#define mxs_adc_resume NULL +#endif /* CONFIG_PM */ + +struct snd_soc_dai_ops mxs_adc_dai_ops = { + .startup = mxs_adc_startup, + .shutdown = mxs_adc_shutdown, + .trigger = mxs_adc_trigger, +}; + +struct snd_soc_dai mxs_adc_dai = { + .name = "mxs adc/dac", + .id = 0, + .suspend = mxs_adc_suspend, + .resume = mxs_adc_resume, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = MXS_ADC_RATES, + .formats = MXS_ADC_FORMATS, + }, + .capture = { + .channels_min = 2, + .channels_max = 2, + .rates = MXS_ADC_RATES, + .formats = MXS_ADC_FORMATS, + }, + .ops = &mxs_adc_dai_ops, +}; +EXPORT_SYMBOL_GPL(mxs_adc_dai); + +static int __init mxs_adc_dai_init(void) +{ + return snd_soc_register_dai(&mxs_adc_dai); +} + +static void __exit mxs_adc_dai_exit(void) +{ + snd_soc_unregister_dai(&mxs_adc_dai); +} +module_init(mxs_adc_dai_init); +module_exit(mxs_adc_dai_exit); + +MODULE_AUTHOR("Vladislav Buzov"); +MODULE_DESCRIPTION("MXS ADC/DAC DAI"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/mxs/mxs-adc.h b/sound/soc/mxs/mxs-adc.h new file mode 100644 index 000000000000..b922c14cb894 --- /dev/null +++ b/sound/soc/mxs/mxs-adc.h @@ -0,0 +1,21 @@ +/* + * ASoC Audio Layer for Freescale MXS ADC/DAC + * + * Author: Vladislav Buzov <vbuzov@embeddedalley.com> + * + * Copyright 2008-2010 Freescale Semiconductor, Inc. + * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#ifndef _MXS_ADC_H +#define _MXS_ADC_H +extern struct snd_soc_dai mxs_adc_dai; +#endif diff --git a/sound/soc/mxs/mxs-evk-adc.c b/sound/soc/mxs/mxs-evk-adc.c new file mode 100644 index 000000000000..bd1ed6bf691f --- /dev/null +++ b/sound/soc/mxs/mxs-evk-adc.c @@ -0,0 +1,91 @@ +/* + * ASoC driver for Freescale MXS EVK board + * + * Author: Vladislav Buzov <vbuzov@embeddedalley.com> + * + * Copyright 2008-2010 Freescale Semiconductor, Inc. + * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/timer.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/soc.h> +#include <sound/soc-dapm.h> + +#include <asm/mach-types.h> +#include <asm/dma.h> +#include <mach/hardware.h> + +#include "../codecs/mxs-adc-codec.h" +#include "mxs-adc.h" +#include "mxs-pcm.h" + +/* mxs evk dac/adc audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link mxs_evk_codec_dai = { + .name = "MXS ADC/DAC", + .stream_name = "MXS ADC/DAC", + .cpu_dai = &mxs_adc_dai, + .codec_dai = &mxs_codec_dai, +}; + +/* mxs evk audio machine driver */ +static struct snd_soc_card snd_soc_card_mxs_evk = { + .name = "MXS EVK", + .platform = &mxs_soc_platform, + .dai_link = &mxs_evk_codec_dai, + .num_links = 1, +}; + +/* mxs evk audio subsystem */ +static struct snd_soc_device mxs_evk_snd_devdata = { + .card = &snd_soc_card_mxs_evk, + .codec_dev = &soc_codec_dev_mxs, +}; + +static struct platform_device *mxs_evk_snd_device; + +static int __init mxs_evk_adc_init(void) +{ + int ret = 0; + + mxs_evk_snd_device = platform_device_alloc("soc-audio", 0); + if (!mxs_evk_snd_device) + return -ENOMEM; + + platform_set_drvdata(mxs_evk_snd_device, + &mxs_evk_snd_devdata); + mxs_evk_snd_devdata.dev = &mxs_evk_snd_device->dev; + mxs_evk_snd_device->dev.platform_data = + &mxs_evk_snd_devdata; + + ret = platform_device_add(mxs_evk_snd_device); + if (ret) + platform_device_put(mxs_evk_snd_device); + + return ret; +} + +static void __exit mxs_evk_adc_exit(void) +{ + platform_device_unregister(mxs_evk_snd_device); +} + +module_init(mxs_evk_adc_init); +module_exit(mxs_evk_adc_exit); + +MODULE_AUTHOR("Vladislav Buzov"); +MODULE_DESCRIPTION("MXS EVK board ADC/DAC driver"); +MODULE_LICENSE("GPL"); |