diff --git a/[refs] b/[refs] index 61697c736bd9..d60021c84901 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: b9b5cc26d0b3a9b361cc56c3a3b0d6f819b9195f +refs/heads/master: 17a52fd60a0a0e617ed94aadb1b19751a8fa219e diff --git a/trunk/arch/arm/plat-omap/include/mach/mcbsp.h b/trunk/arch/arm/plat-omap/include/mach/mcbsp.h index 57249bb1e9bc..bb154ea76769 100644 --- a/trunk/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/trunk/arch/arm/plat-omap/include/mach/mcbsp.h @@ -387,8 +387,8 @@ void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config, void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config); int omap_mcbsp_request(unsigned int id); void omap_mcbsp_free(unsigned int id); -void omap_mcbsp_start(unsigned int id, int tx, int rx); -void omap_mcbsp_stop(unsigned int id, int tx, int rx); +void omap_mcbsp_start(unsigned int id); +void omap_mcbsp_stop(unsigned int id); void omap_mcbsp_xmit_word(unsigned int id, u32 word); u32 omap_mcbsp_recv_word(unsigned int id); diff --git a/trunk/arch/arm/plat-omap/mcbsp.c b/trunk/arch/arm/plat-omap/mcbsp.c index a3d2313460b3..efa0e0111f38 100644 --- a/trunk/arch/arm/plat-omap/mcbsp.c +++ b/trunk/arch/arm/plat-omap/mcbsp.c @@ -328,15 +328,14 @@ void omap_mcbsp_free(unsigned int id) EXPORT_SYMBOL(omap_mcbsp_free); /* - * Here we start the McBSP, by enabling transmitter, receiver or both. - * If no transmitter or receiver is active prior calling, then sample-rate - * generator and frame sync are started. + * Here we start the McBSP, by enabling the sample + * generator, both transmitter and receivers, + * and the frame sync. */ -void omap_mcbsp_start(unsigned int id, int tx, int rx) +void omap_mcbsp_start(unsigned int id) { struct omap_mcbsp *mcbsp; void __iomem *io_base; - int idle; u16 w; if (!omap_mcbsp_check_valid_id(id)) { @@ -349,40 +348,32 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx) mcbsp->rx_word_length = (OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7; mcbsp->tx_word_length = (OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7; - idle = !((OMAP_MCBSP_READ(io_base, SPCR2) | - OMAP_MCBSP_READ(io_base, SPCR1)) & 1); - - if (idle) { - /* Start the sample generator */ - w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6)); - } + /* Start the sample generator */ + w = OMAP_MCBSP_READ(io_base, SPCR2); + OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6)); /* Enable transmitter and receiver */ w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w | (tx & 1)); + OMAP_MCBSP_WRITE(io_base, SPCR2, w | 1); w = OMAP_MCBSP_READ(io_base, SPCR1); - OMAP_MCBSP_WRITE(io_base, SPCR1, w | (rx & 1)); + OMAP_MCBSP_WRITE(io_base, SPCR1, w | 1); udelay(100); - if (idle) { - /* Start frame sync */ - w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7)); - } + /* Start frame sync */ + w = OMAP_MCBSP_READ(io_base, SPCR2); + OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7)); /* Dump McBSP Regs */ omap_mcbsp_dump_reg(id); } EXPORT_SYMBOL(omap_mcbsp_start); -void omap_mcbsp_stop(unsigned int id, int tx, int rx) +void omap_mcbsp_stop(unsigned int id) { struct omap_mcbsp *mcbsp; void __iomem *io_base; - int idle; u16 w; if (!omap_mcbsp_check_valid_id(id)) { @@ -395,20 +386,15 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx) /* Reset transmitter */ w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(tx & 1)); + OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1)); /* Reset receiver */ w = OMAP_MCBSP_READ(io_base, SPCR1); - OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~(rx & 1)); - - idle = !((OMAP_MCBSP_READ(io_base, SPCR2) | - OMAP_MCBSP_READ(io_base, SPCR1)) & 1); + OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~(1)); - if (idle) { - /* Reset the sample rate generator */ - w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6)); - } + /* Reset the sample rate generator */ + w = OMAP_MCBSP_READ(io_base, SPCR2); + OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6)); } EXPORT_SYMBOL(omap_mcbsp_stop); diff --git a/trunk/include/linux/tty.h b/trunk/include/linux/tty.h index 26af9816391f..1488d8c81aac 100644 --- a/trunk/include/linux/tty.h +++ b/trunk/include/linux/tty.h @@ -23,7 +23,7 @@ */ #define NR_UNIX98_PTY_DEFAULT 4096 /* Default maximum for Unix98 ptys */ #define NR_UNIX98_PTY_MAX (1 << MINORBITS) /* Absolute limit */ -#define NR_LDISCS 20 +#define NR_LDISCS 19 /* line disciplines */ #define N_TTY 0 @@ -47,8 +47,6 @@ #define N_SLCAN 17 /* Serial / USB serial CAN Adaptors */ #define N_PPS 18 /* Pulse per Second */ -#define N_AMSDELTA 19 /* codec control over modem, board specific */ - /* * This character is the same as _POSIX_VDISABLE: it cannot be used as * a c_cc[] character, but indicates that a particular special character diff --git a/trunk/include/sound/ac97_codec.h b/trunk/include/sound/ac97_codec.h index 9b1c0985480c..251fc1cd5002 100644 --- a/trunk/include/sound/ac97_codec.h +++ b/trunk/include/sound/ac97_codec.h @@ -642,10 +642,4 @@ int snd_ac97_pcm_double_rate_rules(struct snd_pcm_runtime *runtime); /* ad hoc AC97 device driver access */ extern struct bus_type ac97_bus_type; -/* AC97 platform_data adding function */ -static inline void snd_ac97_dev_add_pdata(struct snd_ac97 *ac97, void *data) -{ - ac97->dev.platform_data = data; -} - #endif /* __SOUND_AC97_CODEC_H */ diff --git a/trunk/include/sound/soc-dai.h b/trunk/include/sound/soc-dai.h index 25d62ac53fc5..352d7eee9b6d 100644 --- a/trunk/include/sound/soc-dai.h +++ b/trunk/include/sound/soc-dai.h @@ -27,8 +27,8 @@ struct snd_pcm_substream; #define SND_SOC_DAIFMT_I2S 0 /* I2S mode */ #define SND_SOC_DAIFMT_RIGHT_J 1 /* Right Justified mode */ #define SND_SOC_DAIFMT_LEFT_J 2 /* Left Justified mode */ -#define SND_SOC_DAIFMT_DSP_A 3 /* L data MSB after FRM LRC */ -#define SND_SOC_DAIFMT_DSP_B 4 /* L data MSB during FRM LRC */ +#define SND_SOC_DAIFMT_DSP_A 3 /* L data msb after FRM LRC */ +#define SND_SOC_DAIFMT_DSP_B 4 /* L data msb during FRM LRC */ #define SND_SOC_DAIFMT_AC97 5 /* AC97 */ /* left and right justified also known as MSB and LSB respectively */ @@ -38,7 +38,7 @@ struct snd_pcm_substream; /* * DAI Clock gating. * - * DAI bit clocks can be be gated (disabled) when the DAI is not + * DAI bit clocks can be be gated (disabled) when not the DAI is not * sending or receiving PCM data in a frame. This can be used to save power. */ #define SND_SOC_DAIFMT_CONT (0 << 4) /* continuous clock */ @@ -51,21 +51,21 @@ struct snd_pcm_substream; * format. */ #define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bit clock + frame */ -#define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal BCLK + inv FRM */ -#define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert BCLK + nor FRM */ -#define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert BCLK + FRM */ +#define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal bclk + inv frm */ +#define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert bclk + nor frm */ +#define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert bclk + frm */ /* * DAI hardware clock masters. * * This is wrt the codec, the inverse is true for the interface - * i.e. if the codec is clk and FRM master then the interface is + * i.e. if the codec is clk and frm master then the interface is * clk and frame slave. */ -#define SND_SOC_DAIFMT_CBM_CFM (0 << 12) /* codec clk & FRM master */ -#define SND_SOC_DAIFMT_CBS_CFM (1 << 12) /* codec clk slave & FRM master */ +#define SND_SOC_DAIFMT_CBM_CFM (0 << 12) /* codec clk & frm master */ +#define SND_SOC_DAIFMT_CBS_CFM (1 << 12) /* codec clk slave & frm master */ #define SND_SOC_DAIFMT_CBM_CFS (2 << 12) /* codec clk master & frame slave */ -#define SND_SOC_DAIFMT_CBS_CFS (3 << 12) /* codec clk & FRM slave */ +#define SND_SOC_DAIFMT_CBS_CFS (3 << 12) /* codec clk & frm slave */ #define SND_SOC_DAIFMT_FORMAT_MASK 0x000f #define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0 @@ -116,12 +116,12 @@ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute); /* * Digital Audio Interface. * - * Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97 - * operations and capabilities. Codec and platform drivers will register this + * Describes the Digital Audio Interface in terms of it's ALSA, DAI and AC97 + * operations an capabilities. Codec and platfom drivers will register a this * structure for every DAI they have. * * This structure covers the clocking, formating and ALSA operations for each - * interface. + * interface a */ struct snd_soc_dai_ops { /* @@ -179,7 +179,6 @@ struct snd_soc_dai { int ac97_control; struct device *dev; - void *ac97_pdata; /* platform_data for the ac97 codec */ /* DAI callbacks */ int (*probe)(struct platform_device *pdev, diff --git a/trunk/include/sound/soc.h b/trunk/include/sound/soc.h index 55b330937260..27409dd41ae9 100644 --- a/trunk/include/sound/soc.h +++ b/trunk/include/sound/soc.h @@ -135,28 +135,6 @@ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) } -#define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\ - xhandler_get, xhandler_put, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ - SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw, \ - .get = xhandler_get, .put = xhandler_put, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .shift = shift_left, .rshift = shift_right, \ - .max = xmax, .invert = xinvert} } -#define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\ - xhandler_get, xhandler_put, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ - SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_2r, \ - .get = xhandler_get, .put = xhandler_put, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ - .max = xmax, .invert = xinvert} } #define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_bool_ext, \ @@ -214,6 +192,8 @@ void snd_soc_unregister_platform(struct snd_soc_platform *platform); int snd_soc_register_codec(struct snd_soc_codec *codec); void snd_soc_unregister_codec(struct snd_soc_codec *codec); int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg); +int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, + int addr_bits, int data_bits); #ifdef CONFIG_PM int snd_soc_suspend_device(struct device *dev); @@ -385,7 +365,6 @@ struct snd_soc_codec { int (*display_register)(struct snd_soc_codec *, char *, size_t, unsigned int); int (*volatile_register)(unsigned int); - int (*readable_register)(unsigned int); hw_write_t hw_write; hw_read_t hw_read; void *reg_cache; diff --git a/trunk/include/sound/wm8993.h b/trunk/include/sound/wm8993.h deleted file mode 100644 index 9c661f2f8cda..000000000000 --- a/trunk/include/sound/wm8993.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * linux/sound/wm8993.h -- Platform data for WM8993 - * - * Copyright 2009 Wolfson Microelectronics. PLC. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __LINUX_SND_WM8993_H -#define __LINUX_SND_WM8993_H - -/* Note that EQ1 only contains the enable/disable bit so will be - ignored but is included for simplicity. - */ -struct wm8993_retune_mobile_setting { - const char *name; - unsigned int rate; - u16 config[24]; -}; - -struct wm8993_platform_data { - struct wm8993_retune_mobile_setting *retune_configs; - int num_retune_configs; - - /* LINEOUT can be differential or single ended */ - unsigned int lineout1_diff:1; - unsigned int lineout2_diff:1; - - /* Common mode feedback */ - unsigned int lineout1fb:1; - unsigned int lineout2fb:1; - - /* Microphone biases: 0=0.9*AVDD1 1=0.65*AVVD1 */ - unsigned int micbias1_lvl:1; - unsigned int micbias2_lvl:1; - - /* Jack detect threashold levels, see datasheet for values */ - unsigned int jd_scthr:2; - unsigned int jd_thr:2; -}; - -#endif diff --git a/trunk/sound/arm/pxa2xx-pcm-lib.c b/trunk/sound/arm/pxa2xx-pcm-lib.c index 6205f37d547c..108b643229ba 100644 --- a/trunk/sound/arm/pxa2xx-pcm-lib.c +++ b/trunk/sound/arm/pxa2xx-pcm-lib.c @@ -75,7 +75,7 @@ int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream) { struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; - if (rtd && rtd->params && rtd->params->drcmr) + if (rtd && rtd->params) *rtd->params->drcmr = 0; snd_pcm_set_runtime_buffer(substream, NULL); diff --git a/trunk/sound/soc/Makefile b/trunk/sound/soc/Makefile index 6f1e28de23cf..4eaf48aab0fa 100644 --- a/trunk/sound/soc/Makefile +++ b/trunk/sound/soc/Makefile @@ -1,4 +1,4 @@ -snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o +snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o obj-$(CONFIG_SND_SOC) += snd-soc-core.o obj-$(CONFIG_SND_SOC) += codecs/ diff --git a/trunk/sound/soc/atmel/sam9g20_wm8731.c b/trunk/sound/soc/atmel/sam9g20_wm8731.c index 130b12118d4f..173a239a541c 100644 --- a/trunk/sound/soc/atmel/sam9g20_wm8731.c +++ b/trunk/sound/soc/atmel/sam9g20_wm8731.c @@ -56,32 +56,133 @@ #define MCLK_RATE 12000000 -/* - * As shipped the board does not have inputs. However, it is relatively - * straightforward to modify the board to hook them up so support is left - * in the driver. - */ -#undef ENABLE_MIC_INPUT - static struct clk *mclk; +static int at91sam9g20ek_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + int ret; + + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, + MCLK_RATE, SND_SOC_CLOCK_IN); + if (ret < 0) { + clk_disable(mclk); + return ret; + } + + return 0; +} + +static void at91sam9g20ek_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + + dev_dbg(rtd->socdev->dev, "shutdown"); +} + static int at91sam9g20ek_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 atmel_ssc_info *ssc_p = cpu_dai->private_data; + struct ssc_device *ssc = ssc_p->ssc; int ret; + unsigned int rate; + int cmr_div, period; + + if (ssc == NULL) { + printk(KERN_INFO "at91sam9g20ek_hw_params: ssc is NULL!\n"); + return -EINVAL; + } + /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); if (ret < 0) return ret; /* set cpu DAI configuration */ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) + return ret; + + /* + * The SSC clock dividers depend on the sample rate. The CMR.DIV + * field divides the system master clock MCK to drive the SSC TK + * signal which provides the codec BCLK. The TCMR.PERIOD and + * RCMR.PERIOD fields further divide the BCLK signal to drive + * the SSC TF and RF signals which provide the codec DACLRC and + * ADCLRC clocks. + * + * The dividers were determined through trial and error, where a + * CMR.DIV value is chosen such that the resulting BCLK value is + * divisible, or almost divisible, by (2 * sample rate), and then + * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1. + */ + rate = params_rate(params); + + switch (rate) { + case 8000: + cmr_div = 55; /* BCLK = 133MHz/(2*55) = 1.209MHz */ + period = 74; /* LRC = BCLK/(2*(74+1)) ~= 8060,6Hz */ + break; + case 11025: + cmr_div = 67; /* BCLK = 133MHz/(2*60) = 1.108MHz */ + period = 45; /* LRC = BCLK/(2*(49+1)) = 11083,3Hz */ + break; + case 16000: + cmr_div = 63; /* BCLK = 133MHz/(2*63) = 1.055MHz */ + period = 32; /* LRC = BCLK/(2*(32+1)) = 15993,2Hz */ + break; + case 22050: + cmr_div = 52; /* BCLK = 133MHz/(2*52) = 1.278MHz */ + period = 28; /* LRC = BCLK/(2*(28+1)) = 22049Hz */ + break; + case 32000: + cmr_div = 66; /* BCLK = 133MHz/(2*66) = 1.007MHz */ + period = 15; /* LRC = BCLK/(2*(15+1)) = 31486,742Hz */ + break; + case 44100: + cmr_div = 29; /* BCLK = 133MHz/(2*29) = 2.293MHz */ + period = 25; /* LRC = BCLK/(2*(25+1)) = 44098Hz */ + break; + case 48000: + cmr_div = 33; /* BCLK = 133MHz/(2*33) = 2.015MHz */ + period = 20; /* LRC = BCLK/(2*(20+1)) = 47979,79Hz */ + break; + case 88200: + cmr_div = 29; /* BCLK = 133MHz/(2*29) = 2.293MHz */ + period = 12; /* LRC = BCLK/(2*(12+1)) = 88196Hz */ + break; + case 96000: + cmr_div = 23; /* BCLK = 133MHz/(2*23) = 2.891MHz */ + period = 14; /* LRC = BCLK/(2*(14+1)) = 96376Hz */ + break; + default: + printk(KERN_WARNING "unsupported rate %d" + " on at91sam9g20ek board\n", rate); + return -EINVAL; + } + + /* set the MCK divider for BCLK */ + ret = snd_soc_dai_set_clkdiv(cpu_dai, ATMEL_SSC_CMR_DIV, cmr_div); + if (ret < 0) + return ret; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + /* set the BCLK divider for DACLRC */ + ret = snd_soc_dai_set_clkdiv(cpu_dai, + ATMEL_SSC_TCMR_PERIOD, period); + } else { + /* set the BCLK divider for ADCLRC */ + ret = snd_soc_dai_set_clkdiv(cpu_dai, + ATMEL_SSC_RCMR_PERIOD, period); + } if (ret < 0) return ret; @@ -89,7 +190,9 @@ static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream, } static struct snd_soc_ops at91sam9g20ek_ops = { + .startup = at91sam9g20ek_startup, .hw_params = at91sam9g20ek_hw_params, + .shutdown = at91sam9g20ek_shutdown, }; static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card, @@ -138,20 +241,10 @@ static const struct snd_soc_dapm_route intercon[] = { */ static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec) { - struct snd_soc_dai *codec_dai = &codec->dai[0]; - int ret; - printk(KERN_DEBUG "at91sam9g20ek_wm8731 " ": at91sam9g20ek_wm8731_init() called\n"); - ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, - MCLK_RATE, SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret); - return ret; - } - /* Add specific widgets */ snd_soc_dapm_new_controls(codec, at91sam9g20ek_dapm_widgets, ARRAY_SIZE(at91sam9g20ek_dapm_widgets)); @@ -162,13 +255,8 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec) snd_soc_dapm_nc_pin(codec, "RLINEIN"); snd_soc_dapm_nc_pin(codec, "LLINEIN"); -#ifdef ENABLE_MIC_INPUT - snd_soc_dapm_enable_pin(codec, "Int Mic"); -#else - snd_soc_dapm_nc_pin(codec, "Int Mic"); -#endif - /* always connected */ + snd_soc_dapm_enable_pin(codec, "Int Mic"); snd_soc_dapm_enable_pin(codec, "Ext Spk"); snd_soc_dapm_sync(codec); diff --git a/trunk/sound/soc/blackfin/Kconfig b/trunk/sound/soc/blackfin/Kconfig index 8a4de4de30f2..811596f4c092 100644 --- a/trunk/sound/soc/blackfin/Kconfig +++ b/trunk/sound/soc/blackfin/Kconfig @@ -7,15 +7,6 @@ config SND_BF5XX_I2S mode (supports single stereo In/Out). You will also need to select the audio interfaces to support below. -config SND_BF5XX_TDM - tristate "SoC I2S(TDM mode) Audio for the ADI BF5xx chip" - depends on (BLACKFIN && SND_SOC) - help - Say Y or M if you want to add support for codecs attached to - the Blackfin SPORT (synchronous serial ports) interface in TDM - mode. - You will also need to select the audio interfaces to support below. - config SND_BF5XX_SOC_SSM2602 tristate "SoC SSM2602 Audio support for BF52x ezkit" depends on SND_BF5XX_I2S @@ -78,10 +69,6 @@ config SND_BF5XX_SOC_I2S tristate select SND_BF5XX_SOC_SPORT -config SND_BF5XX_SOC_TDM - tristate - select SND_BF5XX_SOC_SPORT - config SND_BF5XX_SOC_AC97 tristate select AC97_BUS @@ -96,17 +83,9 @@ config SND_BF5XX_SOC_AD1980 help Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT. -config SND_BF5XX_SOC_AD1938 - tristate "SoC AD1938 Audio support for Blackfin" - depends on SND_BF5XX_TDM - select SND_BF5XX_SOC_TDM - select SND_SOC_AD1938 - help - Say Y if you want to add support for AD1938 codec on Blackfin. - config SND_BF5XX_SPORT_NUM int "Set a SPORT for Sound chip" - depends on (SND_BF5XX_I2S || SND_BF5XX_AC97 || SND_BF5XX_TDM) + depends on (SND_BF5XX_I2S || SND_BF5XX_AC97) range 0 3 if BF54x range 0 1 if !BF54x default 0 diff --git a/trunk/sound/soc/blackfin/Makefile b/trunk/sound/soc/blackfin/Makefile index f4d760741fab..97bb37a6359c 100644 --- a/trunk/sound/soc/blackfin/Makefile +++ b/trunk/sound/soc/blackfin/Makefile @@ -1,27 +1,21 @@ # Blackfin Platform Support snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o -snd-bf5xx-tdm-objs := bf5xx-tdm-pcm.o snd-soc-bf5xx-sport-objs := bf5xx-sport.o snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o -snd-soc-bf5xx-tdm-objs := bf5xx-tdm.o obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o -obj-$(CONFIG_SND_BF5XX_TDM) += snd-bf5xx-tdm.o obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o -obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o # Blackfin Machine Support snd-ad1980-objs := bf5xx-ad1980.o snd-ssm2602-objs := bf5xx-ssm2602.o snd-ad73311-objs := bf5xx-ad73311.o -snd-ad1938-objs := bf5xx-ad1938.o obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o -obj-$(CONFIG_SND_BF5XX_SOC_AD1938) += snd-ad1938.o diff --git a/trunk/sound/soc/blackfin/bf5xx-ac97.c b/trunk/sound/soc/blackfin/bf5xx-ac97.c index 2758b9017a7f..b1ed423fabd5 100644 --- a/trunk/sound/soc/blackfin/bf5xx-ac97.c +++ b/trunk/sound/soc/blackfin/bf5xx-ac97.c @@ -277,24 +277,28 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai) if (!dai->active) return 0; - ret = sport_set_multichannel(sport, 16, 0x1F, 1); + ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1); if (ret) { pr_err("SPORT is busy!\n"); return -EBUSY; } - ret = sport_config_rx(sport, IRFS, 0xF, 0, (16*16-1)); + ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1)); if (ret) { pr_err("SPORT is busy!\n"); return -EBUSY; } - ret = sport_config_tx(sport, ITFS, 0xF, 0, (16*16-1)); + ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1)); if (ret) { pr_err("SPORT is busy!\n"); return -EBUSY; } + if (dai->capture.active) + sport_rx_start(sport); + if (dai->playback.active) + sport_tx_start(sport); return 0; } diff --git a/trunk/sound/soc/blackfin/bf5xx-ad1938.c b/trunk/sound/soc/blackfin/bf5xx-ad1938.c deleted file mode 100644 index 08269e91810c..000000000000 --- a/trunk/sound/soc/blackfin/bf5xx-ad1938.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * File: sound/soc/blackfin/bf5xx-ad1938.c - * Author: Barry Song - * - * Created: Thur June 4 2009 - * Description: Board driver for ad1938 sound chip - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../codecs/ad1938.h" -#include "bf5xx-sport.h" - -#include "bf5xx-tdm-pcm.h" -#include "bf5xx-tdm.h" - -static struct snd_soc_card bf5xx_ad1938; - -static int bf5xx_ad1938_startup(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - - cpu_dai->private_data = sport_handle; - return 0; -} - -static int bf5xx_ad1938_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - int ret = 0; - /* set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) - return ret; - - /* set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) - return ret; - - /* set codec DAI slots, 8 channels, all channels are enabled */ - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xFF, 8); - if (ret < 0) - return ret; - - return 0; -} - -static struct snd_soc_ops bf5xx_ad1938_ops = { - .startup = bf5xx_ad1938_startup, - .hw_params = bf5xx_ad1938_hw_params, -}; - -static struct snd_soc_dai_link bf5xx_ad1938_dai = { - .name = "ad1938", - .stream_name = "AD1938", - .cpu_dai = &bf5xx_tdm_dai, - .codec_dai = &ad1938_dai, - .ops = &bf5xx_ad1938_ops, -}; - -static struct snd_soc_card bf5xx_ad1938 = { - .name = "bf5xx_ad1938", - .platform = &bf5xx_tdm_soc_platform, - .dai_link = &bf5xx_ad1938_dai, - .num_links = 1, -}; - -static struct snd_soc_device bf5xx_ad1938_snd_devdata = { - .card = &bf5xx_ad1938, - .codec_dev = &soc_codec_dev_ad1938, -}; - -static struct platform_device *bfxx_ad1938_snd_device; - -static int __init bf5xx_ad1938_init(void) -{ - int ret; - - bfxx_ad1938_snd_device = platform_device_alloc("soc-audio", -1); - if (!bfxx_ad1938_snd_device) - return -ENOMEM; - - platform_set_drvdata(bfxx_ad1938_snd_device, &bf5xx_ad1938_snd_devdata); - bf5xx_ad1938_snd_devdata.dev = &bfxx_ad1938_snd_device->dev; - ret = platform_device_add(bfxx_ad1938_snd_device); - - if (ret) - platform_device_put(bfxx_ad1938_snd_device); - - return ret; -} - -static void __exit bf5xx_ad1938_exit(void) -{ - platform_device_unregister(bfxx_ad1938_snd_device); -} - -module_init(bf5xx_ad1938_init); -module_exit(bf5xx_ad1938_exit); - -/* Module information */ -MODULE_AUTHOR("Barry Song"); -MODULE_DESCRIPTION("ALSA SoC AD1938 board driver"); -MODULE_LICENSE("GPL"); - diff --git a/trunk/sound/soc/blackfin/bf5xx-i2s.c b/trunk/sound/soc/blackfin/bf5xx-i2s.c index 876abade27e1..af06904bab0f 100644 --- a/trunk/sound/soc/blackfin/bf5xx-i2s.c +++ b/trunk/sound/soc/blackfin/bf5xx-i2s.c @@ -259,18 +259,22 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai) if (!dai->active) return 0; - ret = sport_config_rx(sport, RFSR | RCKFE, RSFSE|0x1f, 0, 0); + ret = sport_config_rx(sport_handle, RFSR | RCKFE, RSFSE|0x1f, 0, 0); if (ret) { pr_err("SPORT is busy!\n"); return -EBUSY; } - ret = sport_config_tx(sport, TFSR | TCKFE, TSFSE|0x1f, 0, 0); + ret = sport_config_tx(sport_handle, TFSR | TCKFE, TSFSE|0x1f, 0, 0); if (ret) { pr_err("SPORT is busy!\n"); return -EBUSY; } + if (dai->capture.active) + sport_rx_start(sport); + if (dai->playback.active) + sport_tx_start(sport); return 0; } diff --git a/trunk/sound/soc/blackfin/bf5xx-tdm-pcm.c b/trunk/sound/soc/blackfin/bf5xx-tdm-pcm.c deleted file mode 100644 index ccb5e823bd18..000000000000 --- a/trunk/sound/soc/blackfin/bf5xx-tdm-pcm.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * File: sound/soc/blackfin/bf5xx-tdm-pcm.c - * Author: Barry Song - * - * Created: Tue June 06 2009 - * Description: DMA driver for tdm codec - * - * Modified: - * Copyright 2009 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "bf5xx-tdm-pcm.h" -#include "bf5xx-tdm.h" -#include "bf5xx-sport.h" - -#define PCM_BUFFER_MAX 0x10000 -#define FRAGMENT_SIZE_MIN (4*1024) -#define FRAGMENTS_MIN 2 -#define FRAGMENTS_MAX 32 - -static void bf5xx_dma_irq(void *data) -{ - struct snd_pcm_substream *pcm = data; - snd_pcm_period_elapsed(pcm); -} - -static const struct snd_pcm_hardware bf5xx_pcm_hardware = { - .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_RESUME), - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = SNDRV_PCM_RATE_48000, - .channels_min = 2, - .channels_max = 8, - .buffer_bytes_max = PCM_BUFFER_MAX, - .period_bytes_min = FRAGMENT_SIZE_MIN, - .period_bytes_max = PCM_BUFFER_MAX/2, - .periods_min = FRAGMENTS_MIN, - .periods_max = FRAGMENTS_MAX, -}; - -static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - size_t size = bf5xx_pcm_hardware.buffer_bytes_max; - snd_pcm_lib_malloc_pages(substream, size * 4); - - return 0; -} - -static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) -{ - snd_pcm_lib_free_pages(substream); - - return 0; -} - -static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sport_device *sport = runtime->private_data; - int fragsize_bytes = frames_to_bytes(runtime, runtime->period_size); - - fragsize_bytes /= runtime->channels; - /* inflate the fragsize to match the dma width of SPORT */ - fragsize_bytes *= 8; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - sport_set_tx_callback(sport, bf5xx_dma_irq, substream); - sport_config_tx_dma(sport, runtime->dma_area, - runtime->periods, fragsize_bytes); - } else { - sport_set_rx_callback(sport, bf5xx_dma_irq, substream); - sport_config_rx_dma(sport, runtime->dma_area, - runtime->periods, fragsize_bytes); - } - - return 0; -} - -static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sport_device *sport = runtime->private_data; - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - sport_tx_start(sport); - else - sport_rx_start(sport); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - sport_tx_stop(sport); - else - sport_rx_stop(sport); - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sport_device *sport = runtime->private_data; - unsigned int diff; - snd_pcm_uframes_t frames; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - diff = sport_curr_offset_tx(sport); - frames = diff / (8*4); /* 32 bytes per frame */ - } else { - diff = sport_curr_offset_rx(sport); - frames = diff / (8*4); - } - return frames; -} - -static int bf5xx_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int ret = 0; - - snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); - - ret = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) - goto out; - - if (sport_handle != NULL) - runtime->private_data = sport_handle; - else { - pr_err("sport_handle is NULL\n"); - ret = -ENODEV; - } -out: - return ret; -} - -static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count) -{ - unsigned int *src; - unsigned int *dst; - int i; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - src = buf; - dst = (unsigned int *)substream->runtime->dma_area; - - dst += pos * 8; - while (count--) { - for (i = 0; i < substream->runtime->channels; i++) - *(dst + i) = *src++; - dst += 8; - } - } else { - src = (unsigned int *)substream->runtime->dma_area; - dst = buf; - - src += pos * 8; - while (count--) { - for (i = 0; i < substream->runtime->channels; i++) - *dst++ = *(src+i); - src += 8; - } - } - - return 0; -} - -static int bf5xx_pcm_silence(struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count) -{ - unsigned char *buf = substream->runtime->dma_area; - buf += pos * 8 * 4; - memset(buf, '\0', count * 8 * 4); - - return 0; -} - - -struct snd_pcm_ops bf5xx_pcm_tdm_ops = { - .open = bf5xx_pcm_open, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = bf5xx_pcm_hw_params, - .hw_free = bf5xx_pcm_hw_free, - .prepare = bf5xx_pcm_prepare, - .trigger = bf5xx_pcm_trigger, - .pointer = bf5xx_pcm_pointer, - .copy = bf5xx_pcm_copy, - .silence = bf5xx_pcm_silence, -}; - -static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = bf5xx_pcm_hardware.buffer_bytes_max; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_coherent(pcm->card->dev, size * 4, - &buf->addr, GFP_KERNEL); - if (!buf->area) { - pr_err("Failed to allocate dma memory \ - Please increase uncached DMA memory region\n"); - return -ENOMEM; - } - buf->bytes = size; - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - sport_handle->tx_buf = buf->area; - else - sport_handle->rx_buf = buf->area; - - return 0; -} - -static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - dma_free_coherent(NULL, buf->bytes, buf->area, 0); - buf->area = NULL; - } - if (sport_handle) - sport_done(sport_handle); -} - -static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); - -static int bf5xx_pcm_tdm_new(struct snd_card *card, struct snd_soc_dai *dai, - struct snd_pcm *pcm) -{ - int ret = 0; - - if (!card->dev->dma_mask) - card->dev->dma_mask = &bf5xx_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - - if (dai->playback.channels_min) { - ret = bf5xx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - goto out; - } - - if (dai->capture.channels_min) { - ret = bf5xx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - goto out; - } -out: - return ret; -} - -struct snd_soc_platform bf5xx_tdm_soc_platform = { - .name = "bf5xx-audio", - .pcm_ops = &bf5xx_pcm_tdm_ops, - .pcm_new = bf5xx_pcm_tdm_new, - .pcm_free = bf5xx_pcm_free_dma_buffers, -}; -EXPORT_SYMBOL_GPL(bf5xx_tdm_soc_platform); - -static int __init bfin_pcm_tdm_init(void) -{ - return snd_soc_register_platform(&bf5xx_tdm_soc_platform); -} -module_init(bfin_pcm_tdm_init); - -static void __exit bfin_pcm_tdm_exit(void) -{ - snd_soc_unregister_platform(&bf5xx_tdm_soc_platform); -} -module_exit(bfin_pcm_tdm_exit); - -MODULE_AUTHOR("Barry Song"); -MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module"); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/blackfin/bf5xx-tdm-pcm.h b/trunk/sound/soc/blackfin/bf5xx-tdm-pcm.h deleted file mode 100644 index ddc5047df88c..000000000000 --- a/trunk/sound/soc/blackfin/bf5xx-tdm-pcm.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * sound/soc/blackfin/bf5xx-tdm-pcm.h -- ALSA PCM interface for the Blackfin - * - * Copyright 2009 Analog Device Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _BF5XX_TDM_PCM_H -#define _BF5XX_TDM_PCM_H - -struct bf5xx_pcm_dma_params { - char *name; /* stream identifier */ -}; - -/* platform data */ -extern struct snd_soc_platform bf5xx_tdm_soc_platform; - -#endif diff --git a/trunk/sound/soc/blackfin/bf5xx-tdm.c b/trunk/sound/soc/blackfin/bf5xx-tdm.c deleted file mode 100644 index 3096badf09a5..000000000000 --- a/trunk/sound/soc/blackfin/bf5xx-tdm.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * File: sound/soc/blackfin/bf5xx-tdm.c - * Author: Barry Song - * - * Created: Thurs June 04 2009 - * Description: Blackfin I2S(TDM) CPU DAI driver - * Even though TDM mode can be as part of I2S DAI, but there - * are so much difference in configuration and data flow, - * it's very ugly to integrate I2S and TDM into a module - * - * Modified: - * Copyright 2009 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "bf5xx-sport.h" -#include "bf5xx-tdm.h" - -struct bf5xx_tdm_port { - u16 tcr1; - u16 rcr1; - u16 tcr2; - u16 rcr2; - int configured; -}; - -static struct bf5xx_tdm_port bf5xx_tdm; -static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; - -static struct sport_param sport_params[2] = { - { - .dma_rx_chan = CH_SPORT0_RX, - .dma_tx_chan = CH_SPORT0_TX, - .err_irq = IRQ_SPORT0_ERROR, - .regs = (struct sport_register *)SPORT0_TCR1, - }, - { - .dma_rx_chan = CH_SPORT1_RX, - .dma_tx_chan = CH_SPORT1_TX, - .err_irq = IRQ_SPORT1_ERROR, - .regs = (struct sport_register *)SPORT1_TCR1, - } -}; - -/* - * Setting the TFS pin selector for SPORT 0 based on whether the selected - * port id F or G. If the port is F then no conflict should exist for the - * TFS. When Port G is selected and EMAC then there is a conflict between - * the PHY interrupt line and TFS. Current settings prevent the conflict - * by ignoring the TFS pin when Port G is selected. This allows both - * ssm2602 using Port G and EMAC concurrently. - */ -#ifdef CONFIG_BF527_SPORT0_PORTF -#define LOCAL_SPORT0_TFS (P_SPORT0_TFS) -#else -#define LOCAL_SPORT0_TFS (0) -#endif - -static u16 sport_req[][7] = { {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, - P_SPORT0_DRPRI, P_SPORT0_RSCLK, LOCAL_SPORT0_TFS, 0}, - {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, P_SPORT1_DRPRI, - P_SPORT1_RSCLK, P_SPORT1_TFS, 0} }; - -static int bf5xx_tdm_set_dai_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - int ret = 0; - - /* interface format:support TDM,slave mode */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - break; - default: - printk(KERN_ERR "%s: Unknown DAI format type\n", __func__); - ret = -EINVAL; - break; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - break; - case SND_SOC_DAIFMT_CBS_CFS: - case SND_SOC_DAIFMT_CBM_CFS: - case SND_SOC_DAIFMT_CBS_CFM: - ret = -EINVAL; - break; - default: - printk(KERN_ERR "%s: Unknown DAI master type\n", __func__); - ret = -EINVAL; - break; - } - - return ret; -} - -static int bf5xx_tdm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - int ret = 0; - - bf5xx_tdm.tcr2 &= ~0x1f; - bf5xx_tdm.rcr2 &= ~0x1f; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S32_LE: - bf5xx_tdm.tcr2 |= 31; - bf5xx_tdm.rcr2 |= 31; - sport_handle->wdsize = 4; - break; - /* at present, we only support 32bit transfer */ - default: - pr_err("not supported PCM format yet\n"); - return -EINVAL; - break; - } - - if (!bf5xx_tdm.configured) { - /* - * TX and RX are not independent,they are enabled at the - * same time, even if only one side is running. So, we - * need to configure both of them at the time when the first - * stream is opened. - * - * CPU DAI:slave mode. - */ - ret = sport_config_rx(sport_handle, bf5xx_tdm.rcr1, - bf5xx_tdm.rcr2, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - return -EBUSY; - } - - ret = sport_config_tx(sport_handle, bf5xx_tdm.tcr1, - bf5xx_tdm.tcr2, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - return -EBUSY; - } - - bf5xx_tdm.configured = 1; - } - - return 0; -} - -static void bf5xx_tdm_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - /* No active stream, SPORT is allowed to be configured again. */ - if (!dai->active) - bf5xx_tdm.configured = 0; -} - -#ifdef CONFIG_PM -static int bf5xx_tdm_suspend(struct snd_soc_dai *dai) -{ - struct sport_device *sport = - (struct sport_device *)dai->private_data; - - if (!dai->active) - return 0; - if (dai->capture.active) - sport_rx_stop(sport); - if (dai->playback.active) - sport_tx_stop(sport); - return 0; -} - -static int bf5xx_tdm_resume(struct snd_soc_dai *dai) -{ - int ret; - struct sport_device *sport = - (struct sport_device *)dai->private_data; - - if (!dai->active) - return 0; - - ret = sport_set_multichannel(sport, 8, 0xFF, 1); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - } - - ret = sport_config_rx(sport, IRFS, 0x1F, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - } - - ret = sport_config_tx(sport, ITFS, 0x1F, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - } - - return 0; -} - -#else -#define bf5xx_tdm_suspend NULL -#define bf5xx_tdm_resume NULL -#endif - -static struct snd_soc_dai_ops bf5xx_tdm_dai_ops = { - .hw_params = bf5xx_tdm_hw_params, - .set_fmt = bf5xx_tdm_set_dai_fmt, - .shutdown = bf5xx_tdm_shutdown, -}; - -struct snd_soc_dai bf5xx_tdm_dai = { - .name = "bf5xx-tdm", - .id = 0, - .suspend = bf5xx_tdm_suspend, - .resume = bf5xx_tdm_resume, - .playback = { - .channels_min = 2, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S32_LE,}, - .capture = { - .channels_min = 2, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S32_LE,}, - .ops = &bf5xx_tdm_dai_ops, -}; -EXPORT_SYMBOL_GPL(bf5xx_tdm_dai); - -static int __devinit bfin_tdm_probe(struct platform_device *pdev) -{ - int ret = 0; - - if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { - pr_err("Requesting Peripherals failed\n"); - return -EFAULT; - } - - /* request DMA for SPORT */ - sport_handle = sport_init(&sport_params[sport_num], 4, \ - 8 * sizeof(u32), NULL); - if (!sport_handle) { - peripheral_free_list(&sport_req[sport_num][0]); - return -ENODEV; - } - - /* SPORT works in TDM mode */ - ret = sport_set_multichannel(sport_handle, 8, 0xFF, 1); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - goto sport_config_err; - } - - ret = sport_config_rx(sport_handle, IRFS, 0x1F, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - goto sport_config_err; - } - - ret = sport_config_tx(sport_handle, ITFS, 0x1F, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - goto sport_config_err; - } - - ret = snd_soc_register_dai(&bf5xx_tdm_dai); - if (ret) { - pr_err("Failed to register DAI: %d\n", ret); - goto sport_config_err; - } - return 0; - -sport_config_err: - peripheral_free_list(&sport_req[sport_num][0]); - return ret; -} - -static int __devexit bfin_tdm_remove(struct platform_device *pdev) -{ - peripheral_free_list(&sport_req[sport_num][0]); - snd_soc_unregister_dai(&bf5xx_tdm_dai); - - return 0; -} - -static struct platform_driver bfin_tdm_driver = { - .probe = bfin_tdm_probe, - .remove = __devexit_p(bfin_tdm_remove), - .driver = { - .name = "bfin-tdm", - .owner = THIS_MODULE, - }, -}; - -static int __init bfin_tdm_init(void) -{ - return platform_driver_register(&bfin_tdm_driver); -} -module_init(bfin_tdm_init); - -static void __exit bfin_tdm_exit(void) -{ - platform_driver_unregister(&bfin_tdm_driver); -} -module_exit(bfin_tdm_exit); - -/* Module information */ -MODULE_AUTHOR("Barry Song"); -MODULE_DESCRIPTION("TDM driver for ADI Blackfin"); -MODULE_LICENSE("GPL"); - diff --git a/trunk/sound/soc/blackfin/bf5xx-tdm.h b/trunk/sound/soc/blackfin/bf5xx-tdm.h deleted file mode 100644 index 618ec3d90cd4..000000000000 --- a/trunk/sound/soc/blackfin/bf5xx-tdm.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * sound/soc/blackfin/bf5xx-tdm.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _BF5XX_TDM_H -#define _BF5XX_TDM_H - -extern struct snd_soc_dai bf5xx_tdm_dai; - -#endif diff --git a/trunk/sound/soc/codecs/Kconfig b/trunk/sound/soc/codecs/Kconfig index 31a6d2111ed0..68ea5b6648df 100644 --- a/trunk/sound/soc/codecs/Kconfig +++ b/trunk/sound/soc/codecs/Kconfig @@ -12,13 +12,11 @@ config SND_SOC_ALL_CODECS tristate "Build all ASoC CODEC drivers" select SND_SOC_L3 select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS - select SND_SOC_AD1938 if SPI_MASTER select SND_SOC_AD1980 if SND_SOC_AC97_BUS select SND_SOC_AD73311 if I2C select SND_SOC_AK4104 if SPI_MASTER select SND_SOC_AK4535 if I2C select SND_SOC_CS4270 if I2C - select SND_SOC_MAX9877 if I2C select SND_SOC_PCM3008 select SND_SOC_SPDIF select SND_SOC_SSM2602 if I2C @@ -38,7 +36,6 @@ config SND_SOC_ALL_CODECS select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8900 if I2C select SND_SOC_WM8903 if I2C select SND_SOC_WM8940 if I2C @@ -47,7 +44,6 @@ config SND_SOC_ALL_CODECS select SND_SOC_WM8971 if I2C select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8990 if I2C - select SND_SOC_WM8993 if I2C select SND_SOC_WM9081 if I2C select SND_SOC_WM9705 if SND_SOC_AC97_BUS select SND_SOC_WM9712 if SND_SOC_AC97_BUS @@ -68,9 +64,6 @@ config SND_SOC_AC97_CODEC tristate select SND_AC97_CODEC -config SND_SOC_AD1938 - tristate - config SND_SOC_AD1980 tristate @@ -95,9 +88,6 @@ config SND_SOC_CS4270_VD33_ERRATA bool depends on SND_SOC_CS4270 -config SND_SOC_CX20442 - tristate - config SND_SOC_L3 tristate @@ -159,9 +149,6 @@ config SND_SOC_WM8750 config SND_SOC_WM8753 tristate -config SND_SOC_WM8776 - tristate - config SND_SOC_WM8900 tristate @@ -186,9 +173,6 @@ config SND_SOC_WM8988 config SND_SOC_WM8990 tristate -config SND_SOC_WM8993 - tristate - config SND_SOC_WM9081 tristate @@ -200,7 +184,3 @@ config SND_SOC_WM9712 config SND_SOC_WM9713 tristate - -# Amp -config SND_SOC_MAX9877 - tristate diff --git a/trunk/sound/soc/codecs/Makefile b/trunk/sound/soc/codecs/Makefile index 78dce5d3fa22..8ce28a34e8e9 100644 --- a/trunk/sound/soc/codecs/Makefile +++ b/trunk/sound/soc/codecs/Makefile @@ -1,11 +1,9 @@ snd-soc-ac97-objs := ac97.o -snd-soc-ad1938-objs := ad1938.o snd-soc-ad1980-objs := ad1980.o snd-soc-ad73311-objs := ad73311.o snd-soc-ak4104-objs := ak4104.o snd-soc-ak4535-objs := ak4535.o snd-soc-cs4270-objs := cs4270.o -snd-soc-cx20442-objs := cx20442.o snd-soc-l3-objs := l3.o snd-soc-pcm3008-objs := pcm3008.o snd-soc-spdif-objs := spdif_transciever.o @@ -26,7 +24,6 @@ snd-soc-wm8728-objs := wm8728.o snd-soc-wm8731-objs := wm8731.o snd-soc-wm8750-objs := wm8750.o snd-soc-wm8753-objs := wm8753.o -snd-soc-wm8776-objs := wm8776.o snd-soc-wm8900-objs := wm8900.o snd-soc-wm8903-objs := wm8903.o snd-soc-wm8940-objs := wm8940.o @@ -35,23 +32,17 @@ snd-soc-wm8961-objs := wm8961.o snd-soc-wm8971-objs := wm8971.o snd-soc-wm8988-objs := wm8988.o snd-soc-wm8990-objs := wm8990.o -snd-soc-wm8993-objs := wm8993.o snd-soc-wm9081-objs := wm9081.o snd-soc-wm9705-objs := wm9705.o snd-soc-wm9712-objs := wm9712.o snd-soc-wm9713-objs := wm9713.o -# Amp -snd-soc-max9877-objs := max9877.o - obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o -obj-$(CONFIG_SND_SOC_AD1938) += snd-soc-ad1938.o obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o -obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o @@ -72,7 +63,6 @@ obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o -obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o @@ -81,11 +71,7 @@ obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o obj-$(CONFIG_SND_SOC_WM8961) += snd-soc-wm8961.o obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o -obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o - -# Amp -obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o diff --git a/trunk/sound/soc/codecs/ad1938.c b/trunk/sound/soc/codecs/ad1938.c deleted file mode 100644 index aafda743fc8f..000000000000 --- a/trunk/sound/soc/codecs/ad1938.c +++ /dev/null @@ -1,668 +0,0 @@ -/* - * File: sound/soc/codecs/ad1938.c - * Author: Barry Song - * - * Created: June 04 2009 - * Description: Driver for AD1938 sound chip - * - * Modified: - * Copyright 2009 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ad1938.h" - -/* codec private data */ -struct ad1938_priv { - struct snd_soc_codec codec; - u8 reg_cache[AD1938_NUM_REGS]; -}; - -static struct snd_soc_codec *ad1938_codec; -struct snd_soc_codec_device soc_codec_dev_ad1938; -static int ad1938_register(struct ad1938_priv *ad1938); -static void ad1938_unregister(struct ad1938_priv *ad1938); - -/* - * AD1938 volume/mute/de-emphasis etc. controls - */ -static const char *ad1938_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"}; - -static const struct soc_enum ad1938_deemp_enum = - SOC_ENUM_SINGLE(AD1938_DAC_CTRL2, 1, 4, ad1938_deemp); - -static const struct snd_kcontrol_new ad1938_snd_controls[] = { - /* DAC volume control */ - SOC_DOUBLE_R("DAC1 Volume", AD1938_DAC_L1_VOL, - AD1938_DAC_R1_VOL, 0, 0xFF, 1), - SOC_DOUBLE_R("DAC2 Volume", AD1938_DAC_L2_VOL, - AD1938_DAC_R2_VOL, 0, 0xFF, 1), - SOC_DOUBLE_R("DAC3 Volume", AD1938_DAC_L3_VOL, - AD1938_DAC_R3_VOL, 0, 0xFF, 1), - SOC_DOUBLE_R("DAC4 Volume", AD1938_DAC_L4_VOL, - AD1938_DAC_R4_VOL, 0, 0xFF, 1), - - /* ADC switch control */ - SOC_DOUBLE("ADC1 Switch", AD1938_ADC_CTRL0, AD1938_ADCL1_MUTE, - AD1938_ADCR1_MUTE, 1, 1), - SOC_DOUBLE("ADC2 Switch", AD1938_ADC_CTRL0, AD1938_ADCL2_MUTE, - AD1938_ADCR2_MUTE, 1, 1), - - /* DAC switch control */ - SOC_DOUBLE("DAC1 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL1_MUTE, - AD1938_DACR1_MUTE, 1, 1), - SOC_DOUBLE("DAC2 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL2_MUTE, - AD1938_DACR2_MUTE, 1, 1), - SOC_DOUBLE("DAC3 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL3_MUTE, - AD1938_DACR3_MUTE, 1, 1), - SOC_DOUBLE("DAC4 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL4_MUTE, - AD1938_DACR4_MUTE, 1, 1), - - /* ADC high-pass filter */ - SOC_SINGLE("ADC High Pass Filter Switch", AD1938_ADC_CTRL0, - AD1938_ADC_HIGHPASS_FILTER, 1, 0), - - /* DAC de-emphasis */ - SOC_ENUM("Playback Deemphasis", ad1938_deemp_enum), -}; - -static const struct snd_soc_dapm_widget ad1938_dapm_widgets[] = { - SND_SOC_DAPM_DAC("DAC", "Playback", AD1938_DAC_CTRL0, 0, 1), - SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1938_ADC_CTRL0, 0, 1, NULL, 0), -}; - -static const struct snd_soc_dapm_route audio_paths[] = { - { "DAC", NULL, "ADC_PWR" }, - { "ADC", NULL, "ADC_PWR" }, -}; - -/* - * DAI ops entries - */ - -static int ad1938_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - int reg; - - reg = codec->read(codec, AD1938_DAC_CTRL2); - reg = (mute > 0) ? reg | AD1938_DAC_MASTER_MUTE : reg & - (~AD1938_DAC_MASTER_MUTE); - codec->write(codec, AD1938_DAC_CTRL2, reg); - - return 0; -} - -static inline int ad1938_pll_powerctrl(struct snd_soc_codec *codec, int cmd) -{ - int reg = codec->read(codec, AD1938_PLL_CLK_CTRL0); - reg = (cmd > 0) ? reg & (~AD1938_PLL_POWERDOWN) : reg | - AD1938_PLL_POWERDOWN; - codec->write(codec, AD1938_PLL_CLK_CTRL0, reg); - - return 0; -} - -static int ad1938_set_tdm_slot(struct snd_soc_dai *dai, - unsigned int mask, int slots) -{ - struct snd_soc_codec *codec = dai->codec; - int dac_reg = codec->read(codec, AD1938_DAC_CTRL1); - int adc_reg = codec->read(codec, AD1938_ADC_CTRL2); - - dac_reg &= ~AD1938_DAC_CHAN_MASK; - adc_reg &= ~AD1938_ADC_CHAN_MASK; - - switch (slots) { - case 2: - dac_reg |= AD1938_DAC_2_CHANNELS << AD1938_DAC_CHAN_SHFT; - adc_reg |= AD1938_ADC_2_CHANNELS << AD1938_ADC_CHAN_SHFT; - break; - case 4: - dac_reg |= AD1938_DAC_4_CHANNELS << AD1938_DAC_CHAN_SHFT; - adc_reg |= AD1938_ADC_4_CHANNELS << AD1938_ADC_CHAN_SHFT; - break; - case 8: - dac_reg |= AD1938_DAC_8_CHANNELS << AD1938_DAC_CHAN_SHFT; - adc_reg |= AD1938_ADC_8_CHANNELS << AD1938_ADC_CHAN_SHFT; - break; - case 16: - dac_reg |= AD1938_DAC_16_CHANNELS << AD1938_DAC_CHAN_SHFT; - adc_reg |= AD1938_ADC_16_CHANNELS << AD1938_ADC_CHAN_SHFT; - break; - default: - return -EINVAL; - } - - codec->write(codec, AD1938_DAC_CTRL1, dac_reg); - codec->write(codec, AD1938_ADC_CTRL2, adc_reg); - - return 0; -} - -static int ad1938_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int adc_reg, dac_reg; - - adc_reg = codec->read(codec, AD1938_ADC_CTRL2); - dac_reg = codec->read(codec, AD1938_DAC_CTRL1); - - /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S - * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A) - */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - adc_reg &= ~AD1938_ADC_SERFMT_MASK; - adc_reg |= AD1938_ADC_SERFMT_TDM; - break; - case SND_SOC_DAIFMT_DSP_A: - adc_reg &= ~AD1938_ADC_SERFMT_MASK; - adc_reg |= AD1938_ADC_SERFMT_AUX; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */ - adc_reg &= ~AD1938_ADC_LEFT_HIGH; - adc_reg &= ~AD1938_ADC_BCLK_INV; - dac_reg &= ~AD1938_DAC_LEFT_HIGH; - dac_reg &= ~AD1938_DAC_BCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */ - adc_reg |= AD1938_ADC_LEFT_HIGH; - adc_reg &= ~AD1938_ADC_BCLK_INV; - dac_reg |= AD1938_DAC_LEFT_HIGH; - dac_reg &= ~AD1938_DAC_BCLK_INV; - break; - case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */ - adc_reg &= ~AD1938_ADC_LEFT_HIGH; - adc_reg |= AD1938_ADC_BCLK_INV; - dac_reg &= ~AD1938_DAC_LEFT_HIGH; - dac_reg |= AD1938_DAC_BCLK_INV; - break; - - case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */ - adc_reg |= AD1938_ADC_LEFT_HIGH; - adc_reg |= AD1938_ADC_BCLK_INV; - dac_reg |= AD1938_DAC_LEFT_HIGH; - dac_reg |= AD1938_DAC_BCLK_INV; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */ - adc_reg |= AD1938_ADC_LCR_MASTER; - adc_reg |= AD1938_ADC_BCLK_MASTER; - dac_reg |= AD1938_DAC_LCR_MASTER; - dac_reg |= AD1938_DAC_BCLK_MASTER; - break; - case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & frm master */ - adc_reg |= AD1938_ADC_LCR_MASTER; - adc_reg &= ~AD1938_ADC_BCLK_MASTER; - dac_reg |= AD1938_DAC_LCR_MASTER; - dac_reg &= ~AD1938_DAC_BCLK_MASTER; - break; - case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */ - adc_reg &= ~AD1938_ADC_LCR_MASTER; - adc_reg |= AD1938_ADC_BCLK_MASTER; - dac_reg &= ~AD1938_DAC_LCR_MASTER; - dac_reg |= AD1938_DAC_BCLK_MASTER; - break; - case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */ - adc_reg &= ~AD1938_ADC_LCR_MASTER; - adc_reg &= ~AD1938_ADC_BCLK_MASTER; - dac_reg &= ~AD1938_DAC_LCR_MASTER; - dac_reg &= ~AD1938_DAC_BCLK_MASTER; - break; - default: - return -EINVAL; - } - - codec->write(codec, AD1938_ADC_CTRL2, adc_reg); - codec->write(codec, AD1938_DAC_CTRL1, dac_reg); - - return 0; -} - -static int ad1938_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - int word_len = 0, reg = 0; - - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - word_len = 3; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - word_len = 1; - break; - case SNDRV_PCM_FORMAT_S24_LE: - case SNDRV_PCM_FORMAT_S32_LE: - word_len = 0; - break; - } - - reg = codec->read(codec, AD1938_DAC_CTRL2); - reg = (reg & (~AD1938_DAC_WORD_LEN_MASK)) | word_len; - codec->write(codec, AD1938_DAC_CTRL2, reg); - - reg = codec->read(codec, AD1938_ADC_CTRL1); - reg = (reg & (~AD1938_ADC_WORD_LEN_MASK)) | word_len; - codec->write(codec, AD1938_ADC_CTRL1, reg); - - return 0; -} - -static int ad1938_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - ad1938_pll_powerctrl(codec, 1); - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - case SND_SOC_BIAS_OFF: - ad1938_pll_powerctrl(codec, 0); - break; - } - codec->bias_level = level; - return 0; -} - -/* - * interface to read/write ad1938 register - */ - -#define AD1938_SPI_ADDR 0x4 -#define AD1938_SPI_READ 0x1 -#define AD1938_SPI_BUFLEN 3 - -/* - * write to the ad1938 register space - */ - -static int ad1938_write_reg(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 *reg_cache = codec->reg_cache; - int ret = 0; - - if (value != reg_cache[reg]) { - uint8_t buf[AD1938_SPI_BUFLEN]; - struct spi_transfer t = { - .tx_buf = buf, - .len = AD1938_SPI_BUFLEN, - }; - struct spi_message m; - - buf[0] = AD1938_SPI_ADDR << 1; - buf[1] = reg; - buf[2] = value; - spi_message_init(&m); - spi_message_add_tail(&t, &m); - ret = spi_sync(codec->control_data, &m); - if (ret == 0) - reg_cache[reg] = value; - } - - return ret; -} - -/* - * read from the ad1938 register space cache - */ - -static unsigned int ad1938_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u8 *reg_cache = codec->reg_cache; - - if (reg >= codec->reg_cache_size) - return -EINVAL; - - return reg_cache[reg]; -} - -/* - * read from the ad1938 register space - */ - -static unsigned int ad1938_read_reg(struct snd_soc_codec *codec, - unsigned int reg) -{ - char w_buf[AD1938_SPI_BUFLEN]; - char r_buf[AD1938_SPI_BUFLEN]; - int ret; - - struct spi_transfer t = { - .tx_buf = w_buf, - .rx_buf = r_buf, - .len = AD1938_SPI_BUFLEN, - }; - struct spi_message m; - - w_buf[0] = (AD1938_SPI_ADDR << 1) | AD1938_SPI_READ; - w_buf[1] = reg; - w_buf[2] = 0; - - spi_message_init(&m); - spi_message_add_tail(&t, &m); - ret = spi_sync(codec->control_data, &m); - if (ret == 0) - return r_buf[2]; - else - return -EIO; -} - -static int ad1938_fill_cache(struct snd_soc_codec *codec) -{ - int i; - u8 *reg_cache = codec->reg_cache; - struct spi_device *spi = codec->control_data; - - for (i = 0; i < codec->reg_cache_size; i++) { - int ret = ad1938_read_reg(codec, i); - if (ret == -EIO) { - dev_err(&spi->dev, "AD1938 SPI read failure\n"); - return ret; - } - reg_cache[i] = ret; - } - - return 0; -} - -static int __devinit ad1938_spi_probe(struct spi_device *spi) -{ - struct snd_soc_codec *codec; - struct ad1938_priv *ad1938; - - ad1938 = kzalloc(sizeof(struct ad1938_priv), GFP_KERNEL); - if (ad1938 == NULL) - return -ENOMEM; - - codec = &ad1938->codec; - codec->control_data = spi; - codec->dev = &spi->dev; - - dev_set_drvdata(&spi->dev, ad1938); - - return ad1938_register(ad1938); -} - -static int __devexit ad1938_spi_remove(struct spi_device *spi) -{ - struct ad1938_priv *ad1938 = dev_get_drvdata(&spi->dev); - - ad1938_unregister(ad1938); - return 0; -} - -static struct spi_driver ad1938_spi_driver = { - .driver = { - .name = "ad1938-spi", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - .probe = ad1938_spi_probe, - .remove = __devexit_p(ad1938_spi_remove), -}; - -static struct snd_soc_dai_ops ad1938_dai_ops = { - .hw_params = ad1938_hw_params, - .digital_mute = ad1938_mute, - .set_tdm_slot = ad1938_set_tdm_slot, - .set_fmt = ad1938_set_dai_fmt, -}; - -/* codec DAI instance */ -struct snd_soc_dai ad1938_dai = { - .name = "AD1938", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 4, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, - }, - .ops = &ad1938_dai_ops, -}; -EXPORT_SYMBOL_GPL(ad1938_dai); - -static int ad1938_register(struct ad1938_priv *ad1938) -{ - int ret; - struct snd_soc_codec *codec = &ad1938->codec; - - if (ad1938_codec) { - dev_err(codec->dev, "Another ad1938 is registered\n"); - return -EINVAL; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - codec->private_data = ad1938; - codec->reg_cache = ad1938->reg_cache; - codec->reg_cache_size = AD1938_NUM_REGS; - codec->name = "AD1938"; - codec->owner = THIS_MODULE; - codec->dai = &ad1938_dai; - codec->num_dai = 1; - codec->write = ad1938_write_reg; - codec->read = ad1938_read_reg_cache; - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - ad1938_dai.dev = codec->dev; - ad1938_codec = codec; - - /* default setting for ad1938 */ - - /* unmute dac channels */ - codec->write(codec, AD1938_DAC_CHNL_MUTE, 0x0); - /* de-emphasis: 48kHz, powedown dac */ - codec->write(codec, AD1938_DAC_CTRL2, 0x1A); - /* powerdown dac, dac in tdm mode */ - codec->write(codec, AD1938_DAC_CTRL0, 0x41); - /* high-pass filter enable */ - codec->write(codec, AD1938_ADC_CTRL0, 0x3); - /* sata delay=1, adc aux mode */ - codec->write(codec, AD1938_ADC_CTRL1, 0x43); - /* pll input: mclki/xi */ - codec->write(codec, AD1938_PLL_CLK_CTRL0, 0x9D); - codec->write(codec, AD1938_PLL_CLK_CTRL1, 0x04); - - ad1938_fill_cache(codec); - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - return ret; - } - - ret = snd_soc_register_dai(&ad1938_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); - return ret; - } - - return 0; -} - -static void ad1938_unregister(struct ad1938_priv *ad1938) -{ - ad1938_set_bias_level(&ad1938->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dai(&ad1938_dai); - snd_soc_unregister_codec(&ad1938->codec); - kfree(ad1938); - ad1938_codec = NULL; -} - -static int ad1938_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (ad1938_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = ad1938_codec; - codec = ad1938_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: %d\n", ret); - goto pcm_err; - } - - snd_soc_add_controls(codec, ad1938_snd_controls, - ARRAY_SIZE(ad1938_snd_controls)); - snd_soc_dapm_new_controls(codec, ad1938_dapm_widgets, - ARRAY_SIZE(ad1938_dapm_widgets)); - snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); - snd_soc_dapm_new_widgets(codec); - - ad1938_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - ret = snd_soc_init_card(socdev); - if (ret < 0) { - dev_err(codec->dev, "failed to register card: %d\n", ret); - goto card_err; - } - - return ret; - -card_err: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -pcm_err: - return ret; -} - -/* power down chip */ -static int ad1938_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -#ifdef CONFIG_PM -static int ad1938_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; - - ad1938_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int ad1938_resume(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec->suspend_bias_level == SND_SOC_BIAS_ON) - ad1938_set_bias_level(codec, SND_SOC_BIAS_ON); - - return 0; -} -#else -#define ad1938_suspend NULL -#define ad1938_resume NULL -#endif - -struct snd_soc_codec_device soc_codec_dev_ad1938 = { - .probe = ad1938_probe, - .remove = ad1938_remove, - .suspend = ad1938_suspend, - .resume = ad1938_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_ad1938); - -static int __init ad1938_init(void) -{ - int ret; - - ret = spi_register_driver(&ad1938_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register ad1938 SPI driver: %d\n", - ret); - } - - return ret; -} -module_init(ad1938_init); - -static void __exit ad1938_exit(void) -{ - spi_unregister_driver(&ad1938_spi_driver); -} -module_exit(ad1938_exit); - -MODULE_DESCRIPTION("ASoC ad1938 driver"); -MODULE_AUTHOR("Barry Song "); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/codecs/ad1938.h b/trunk/sound/soc/codecs/ad1938.h deleted file mode 100644 index fe3c48cd2d5b..000000000000 --- a/trunk/sound/soc/codecs/ad1938.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * File: sound/soc/codecs/ad1836.h - * Based on: - * Author: Barry Song - * - * Created: May 25, 2009 - * Description: definitions for AD1938 registers - * - * Modified: - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __AD1938_H__ -#define __AD1938_H__ - -#define AD1938_PLL_CLK_CTRL0 0 -#define AD1938_PLL_POWERDOWN 0x01 -#define AD1938_PLL_CLK_CTRL1 1 -#define AD1938_DAC_CTRL0 2 -#define AD1938_DAC_POWERDOWN 0x01 -#define AD1938_DAC_SERFMT_MASK 0xC0 -#define AD1938_DAC_SERFMT_STEREO (0 << 6) -#define AD1938_DAC_SERFMT_TDM (1 << 6) -#define AD1938_DAC_CTRL1 3 -#define AD1938_DAC_2_CHANNELS 0 -#define AD1938_DAC_4_CHANNELS 1 -#define AD1938_DAC_8_CHANNELS 2 -#define AD1938_DAC_16_CHANNELS 3 -#define AD1938_DAC_CHAN_SHFT 1 -#define AD1938_DAC_CHAN_MASK (3 << AD1938_DAC_CHAN_SHFT) -#define AD1938_DAC_LCR_MASTER (1 << 4) -#define AD1938_DAC_BCLK_MASTER (1 << 5) -#define AD1938_DAC_LEFT_HIGH (1 << 3) -#define AD1938_DAC_BCLK_INV (1 << 7) -#define AD1938_DAC_CTRL2 4 -#define AD1938_DAC_WORD_LEN_MASK 0xC -#define AD1938_DAC_MASTER_MUTE 1 -#define AD1938_DAC_CHNL_MUTE 5 -#define AD1938_DACL1_MUTE 0 -#define AD1938_DACR1_MUTE 1 -#define AD1938_DACL2_MUTE 2 -#define AD1938_DACR2_MUTE 3 -#define AD1938_DACL3_MUTE 4 -#define AD1938_DACR3_MUTE 5 -#define AD1938_DACL4_MUTE 6 -#define AD1938_DACR4_MUTE 7 -#define AD1938_DAC_L1_VOL 6 -#define AD1938_DAC_R1_VOL 7 -#define AD1938_DAC_L2_VOL 8 -#define AD1938_DAC_R2_VOL 9 -#define AD1938_DAC_L3_VOL 10 -#define AD1938_DAC_R3_VOL 11 -#define AD1938_DAC_L4_VOL 12 -#define AD1938_DAC_R4_VOL 13 -#define AD1938_ADC_CTRL0 14 -#define AD1938_ADC_POWERDOWN 0x01 -#define AD1938_ADC_HIGHPASS_FILTER 1 -#define AD1938_ADCL1_MUTE 2 -#define AD1938_ADCR1_MUTE 3 -#define AD1938_ADCL2_MUTE 4 -#define AD1938_ADCR2_MUTE 5 -#define AD1938_ADC_CTRL1 15 -#define AD1938_ADC_SERFMT_MASK 0x60 -#define AD1938_ADC_SERFMT_STEREO (0 << 5) -#define AD1938_ADC_SERFMT_TDM (1 << 2) -#define AD1938_ADC_SERFMT_AUX (2 << 5) -#define AD1938_ADC_WORD_LEN_MASK 0x3 -#define AD1938_ADC_CTRL2 16 -#define AD1938_ADC_2_CHANNELS 0 -#define AD1938_ADC_4_CHANNELS 1 -#define AD1938_ADC_8_CHANNELS 2 -#define AD1938_ADC_16_CHANNELS 3 -#define AD1938_ADC_CHAN_SHFT 4 -#define AD1938_ADC_CHAN_MASK (3 << AD1938_ADC_CHAN_SHFT) -#define AD1938_ADC_LCR_MASTER (1 << 3) -#define AD1938_ADC_BCLK_MASTER (1 << 6) -#define AD1938_ADC_LEFT_HIGH (1 << 2) -#define AD1938_ADC_BCLK_INV (1 << 1) - -#define AD1938_NUM_REGS 17 - -extern struct snd_soc_dai ad1938_dai; -extern struct snd_soc_codec_device soc_codec_dev_ad1938; -#endif diff --git a/trunk/sound/soc/codecs/ak4535.c b/trunk/sound/soc/codecs/ak4535.c index 0abec0d29a96..dd3380202766 100644 --- a/trunk/sound/soc/codecs/ak4535.c +++ b/trunk/sound/soc/codecs/ak4535.c @@ -59,6 +59,21 @@ static inline unsigned int ak4535_read_reg_cache(struct snd_soc_codec *codec, return cache[reg]; } +static inline unsigned int ak4535_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + u8 data; + data = reg; + + if (codec->hw_write(codec->control_data, &data, 1) != 1) + return -EIO; + + if (codec->hw_read(codec->control_data, &data, 1) != 1) + return -EIO; + + return data; +}; + /* * write ak4535 register cache */ @@ -620,6 +635,7 @@ static int ak4535_probe(struct platform_device *pdev) #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { codec->hw_write = (hw_write_t)i2c_master_send; + codec->hw_read = (hw_read_t)i2c_master_recv; ret = ak4535_add_i2c_device(pdev, setup); } #endif diff --git a/trunk/sound/soc/codecs/cs4270.c b/trunk/sound/soc/codecs/cs4270.c index ca1e24a8f12a..a32b8226c8a4 100644 --- a/trunk/sound/soc/codecs/cs4270.c +++ b/trunk/sound/soc/codecs/cs4270.c @@ -806,30 +806,15 @@ static int cs4270_i2c_suspend(struct i2c_client *client, pm_message_t mesg) { struct cs4270_private *cs4270 = i2c_get_clientdata(client); struct snd_soc_codec *codec = &cs4270->codec; + int reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL; - return snd_soc_suspend_device(codec->dev); + return snd_soc_write(codec, CS4270_PWRCTL, reg); } static int cs4270_i2c_resume(struct i2c_client *client) { struct cs4270_private *cs4270 = i2c_get_clientdata(client); struct snd_soc_codec *codec = &cs4270->codec; - - return snd_soc_resume_device(codec->dev); -} - -static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) -{ - struct snd_soc_codec *codec = cs4270_codec; - int reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL; - - return snd_soc_write(codec, CS4270_PWRCTL, reg); -} - -static int cs4270_soc_resume(struct platform_device *pdev) -{ - struct snd_soc_codec *codec = cs4270_codec; - struct i2c_client *i2c_client = codec->control_data; int reg; /* In case the device was put to hard reset during sleep, we need to @@ -840,7 +825,7 @@ static int cs4270_soc_resume(struct platform_device *pdev) for (reg = CS4270_FIRSTREG; reg <= CS4270_LASTREG; reg++) { u8 val = snd_soc_read(codec, reg); - if (i2c_smbus_write_byte_data(i2c_client, reg, val)) { + if (i2c_smbus_write_byte_data(client, reg, val)) { dev_err(codec->dev, "i2c write failed\n"); return -EIO; } @@ -855,8 +840,6 @@ static int cs4270_soc_resume(struct platform_device *pdev) #else #define cs4270_i2c_suspend NULL #define cs4270_i2c_resume NULL -#define cs4270_soc_suspend NULL -#define cs4270_soc_resume NULL #endif /* CONFIG_PM */ /* @@ -885,9 +868,7 @@ static struct i2c_driver cs4270_i2c_driver = { */ struct snd_soc_codec_device soc_codec_device_cs4270 = { .probe = cs4270_probe, - .remove = cs4270_remove, - .suspend = cs4270_soc_suspend, - .resume = cs4270_soc_resume, + .remove = cs4270_remove }; EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); diff --git a/trunk/sound/soc/codecs/cx20442.c b/trunk/sound/soc/codecs/cx20442.c deleted file mode 100644 index 38eac9c866e1..000000000000 --- a/trunk/sound/soc/codecs/cx20442.c +++ /dev/null @@ -1,501 +0,0 @@ -/* - * cx20442.c -- CX20442 ALSA Soc Audio driver - * - * Copyright 2009 Janusz Krzysztofik - * - * Initially based on sound/soc/codecs/wm8400.c - * Copyright 2008, 2009 Wolfson Microelectronics PLC. - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include - -#include -#include -#include - -#include "cx20442.h" - - -struct cx20442_priv { - struct snd_soc_codec codec; - u8 reg_cache[1]; -}; - -#define CX20442_PM 0x0 - -#define CX20442_TELIN 0 -#define CX20442_TELOUT 1 -#define CX20442_MIC 2 -#define CX20442_SPKOUT 3 -#define CX20442_AGC 4 - -static const struct snd_soc_dapm_widget cx20442_dapm_widgets[] = { - SND_SOC_DAPM_OUTPUT("TELOUT"), - SND_SOC_DAPM_OUTPUT("SPKOUT"), - SND_SOC_DAPM_OUTPUT("AGCOUT"), - - SND_SOC_DAPM_MIXER("SPKOUT Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - - SND_SOC_DAPM_PGA("TELOUT Amp", CX20442_PM, CX20442_TELOUT, 0, NULL, 0), - SND_SOC_DAPM_PGA("SPKOUT Amp", CX20442_PM, CX20442_SPKOUT, 0, NULL, 0), - SND_SOC_DAPM_PGA("SPKOUT AGC", CX20442_PM, CX20442_AGC, 0, NULL, 0), - - SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), - - SND_SOC_DAPM_MIXER("Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - - SND_SOC_DAPM_MICBIAS("TELIN Bias", CX20442_PM, CX20442_TELIN, 0), - SND_SOC_DAPM_MICBIAS("MIC Bias", CX20442_PM, CX20442_MIC, 0), - - SND_SOC_DAPM_PGA("MIC AGC", CX20442_PM, CX20442_AGC, 0, NULL, 0), - - SND_SOC_DAPM_INPUT("TELIN"), - SND_SOC_DAPM_INPUT("MIC"), - SND_SOC_DAPM_INPUT("AGCIN"), -}; - -static const struct snd_soc_dapm_route cx20442_audio_map[] = { - {"TELOUT", NULL, "TELOUT Amp"}, - - {"SPKOUT", NULL, "SPKOUT Mixer"}, - {"SPKOUT Mixer", NULL, "SPKOUT Amp"}, - - {"TELOUT Amp", NULL, "DAC"}, - {"SPKOUT Amp", NULL, "DAC"}, - - {"SPKOUT Mixer", NULL, "SPKOUT AGC"}, - {"SPKOUT AGC", NULL, "AGCIN"}, - - {"AGCOUT", NULL, "MIC AGC"}, - {"MIC AGC", NULL, "MIC"}, - - {"MIC Bias", NULL, "MIC"}, - {"Input Mixer", NULL, "MIC Bias"}, - - {"TELIN Bias", NULL, "TELIN"}, - {"Input Mixer", NULL, "TELIN Bias"}, - - {"ADC", NULL, "Input Mixer"}, -}; - -static int cx20442_add_widgets(struct snd_soc_codec *codec) -{ - snd_soc_dapm_new_controls(codec, cx20442_dapm_widgets, - ARRAY_SIZE(cx20442_dapm_widgets)); - - snd_soc_dapm_add_routes(codec, cx20442_audio_map, - ARRAY_SIZE(cx20442_audio_map)); - - snd_soc_dapm_new_widgets(codec); - return 0; -} - -static unsigned int cx20442_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u8 *reg_cache = codec->reg_cache; - - if (reg >= codec->reg_cache_size) - return -EINVAL; - - return reg_cache[reg]; -} - -enum v253_vls { - V253_VLS_NONE = 0, - V253_VLS_T, - V253_VLS_L, - V253_VLS_LT, - V253_VLS_S, - V253_VLS_ST, - V253_VLS_M, - V253_VLS_MST, - V253_VLS_S1, - V253_VLS_S1T, - V253_VLS_MS1T, - V253_VLS_M1, - V253_VLS_M1ST, - V253_VLS_M1S1T, - V253_VLS_H, - V253_VLS_HT, - V253_VLS_MS, - V253_VLS_MS1, - V253_VLS_M1S, - V253_VLS_M1S1, - V253_VLS_TEST, -}; - -static int cx20442_pm_to_v253_vls(u8 value) -{ - switch (value & ~(1 << CX20442_AGC)) { - case 0: - return V253_VLS_T; - case (1 << CX20442_SPKOUT): - case (1 << CX20442_MIC): - case (1 << CX20442_SPKOUT) | (1 << CX20442_MIC): - return V253_VLS_M1S1; - case (1 << CX20442_TELOUT): - case (1 << CX20442_TELIN): - case (1 << CX20442_TELOUT) | (1 << CX20442_TELIN): - return V253_VLS_L; - case (1 << CX20442_TELOUT) | (1 << CX20442_MIC): - return V253_VLS_NONE; - } - return -EINVAL; -} -static int cx20442_pm_to_v253_vsp(u8 value) -{ - switch (value & ~(1 << CX20442_AGC)) { - case (1 << CX20442_SPKOUT): - case (1 << CX20442_MIC): - case (1 << CX20442_SPKOUT) | (1 << CX20442_MIC): - return (bool)(value & (1 << CX20442_AGC)); - } - return (value & (1 << CX20442_AGC)) ? -EINVAL : 0; -} - -static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 *reg_cache = codec->reg_cache; - int vls, vsp, old, len; - char buf[18]; - - if (reg >= codec->reg_cache_size) - return -EINVAL; - - /* hw_write and control_data pointers required for talking to the modem - * are expected to be set by the line discipline initialization code */ - if (!codec->hw_write || !codec->control_data) - return -EIO; - - old = reg_cache[reg]; - reg_cache[reg] = value; - - vls = cx20442_pm_to_v253_vls(value); - if (vls < 0) - return vls; - - vsp = cx20442_pm_to_v253_vsp(value); - if (vsp < 0) - return vsp; - - if ((vls == V253_VLS_T) || - (vls == cx20442_pm_to_v253_vls(old))) { - if (vsp == cx20442_pm_to_v253_vsp(old)) - return 0; - len = snprintf(buf, ARRAY_SIZE(buf), "at+vsp=%d\r", vsp); - } else if (vsp == cx20442_pm_to_v253_vsp(old)) - len = snprintf(buf, ARRAY_SIZE(buf), "at+vls=%d\r", vls); - else - len = snprintf(buf, ARRAY_SIZE(buf), - "at+vls=%d;+vsp=%d\r", vls, vsp); - - if (unlikely(len > (ARRAY_SIZE(buf) - 1))) - return -ENOMEM; - - dev_dbg(codec->dev, "%s: %s\n", __func__, buf); - if (codec->hw_write(codec->control_data, buf, len) != len) - return -EIO; - - return 0; -} - - -/* Moved up here as line discipline referres it during initialization */ -static struct snd_soc_codec *cx20442_codec; - - -/* - * Line discpline related code - * - * Any of the callback functions below can be used in two ways: - * 1) registerd by a machine driver as one of line discipline operations, - * 2) called from a machine's provided line discipline callback function - * in case when extra machine specific code must be run as well. - */ - -/* Modem init: echo off, digital speaker off, quiet off, voice mode */ -static const char *v253_init = "ate0m0q0+fclass=8\r"; - -/* Line discipline .open() */ -static int v253_open(struct tty_struct *tty) -{ - struct snd_soc_codec *codec = cx20442_codec; - int ret, len = strlen(v253_init); - - /* Doesn't make sense without write callback */ - if (!tty->ops->write) - return -EINVAL; - - /* Pass the codec structure address for use by other ldisc callbacks */ - tty->disc_data = codec; - - if (tty->ops->write(tty, v253_init, len) != len) { - ret = -EIO; - goto err; - } - /* Actual setup will be performed after the modem responds. */ - return 0; -err: - tty->disc_data = NULL; - return ret; -} - -/* Line discipline .close() */ -static void v253_close(struct tty_struct *tty) -{ - struct snd_soc_codec *codec = tty->disc_data; - - tty->disc_data = NULL; - - if (!codec) - return; - - /* Prevent the codec driver from further accessing the modem */ - codec->hw_write = NULL; - codec->control_data = NULL; - codec->pop_time = 0; -} - -/* Line discipline .hangup() */ -static int v253_hangup(struct tty_struct *tty) -{ - v253_close(tty); - return 0; -} - -/* Line discipline .receive_buf() */ -static void v253_receive(struct tty_struct *tty, - const unsigned char *cp, char *fp, int count) -{ - struct snd_soc_codec *codec = tty->disc_data; - - if (!codec) - return; - - if (!codec->control_data) { - /* First modem response, complete setup procedure */ - - /* Set up codec driver access to modem controls */ - codec->control_data = tty; - codec->hw_write = (hw_write_t)tty->ops->write; - codec->pop_time = 1; - } -} - -/* Line discipline .write_wakeup() */ -static void v253_wakeup(struct tty_struct *tty) -{ -} - -struct tty_ldisc_ops v253_ops = { - .magic = TTY_LDISC_MAGIC, - .name = "cx20442", - .owner = THIS_MODULE, - .open = v253_open, - .close = v253_close, - .hangup = v253_hangup, - .receive_buf = v253_receive, - .write_wakeup = v253_wakeup, -}; -EXPORT_SYMBOL_GPL(v253_ops); - - -/* - * Codec DAI - */ - -struct snd_soc_dai cx20442_dai = { - .name = "CX20442", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, -}; -EXPORT_SYMBOL_GPL(cx20442_dai); - -static int cx20442_codec_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret; - - if (!cx20442_codec) { - dev_err(&pdev->dev, "cx20442 not yet discovered\n"); - return -ENODEV; - } - codec = cx20442_codec; - - socdev->card->codec = codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(&pdev->dev, "failed to create pcms\n"); - goto pcm_err; - } - - cx20442_add_widgets(codec); - - ret = snd_soc_init_card(socdev); - if (ret < 0) { - dev_err(&pdev->dev, "failed to register card\n"); - goto card_err; - } - - return ret; - -card_err: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -pcm_err: - return ret; -} - -/* power down chip */ -static int cx20442_codec_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device cx20442_codec_dev = { - .probe = cx20442_codec_probe, - .remove = cx20442_codec_remove, -}; -EXPORT_SYMBOL_GPL(cx20442_codec_dev); - -static int cx20442_register(struct cx20442_priv *cx20442) -{ - struct snd_soc_codec *codec = &cx20442->codec; - int ret; - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->name = "CX20442"; - codec->owner = THIS_MODULE; - codec->private_data = cx20442; - - codec->dai = &cx20442_dai; - codec->num_dai = 1; - - codec->reg_cache = &cx20442->reg_cache; - codec->reg_cache_size = ARRAY_SIZE(cx20442->reg_cache); - codec->read = cx20442_read_reg_cache; - codec->write = cx20442_write; - - codec->bias_level = SND_SOC_BIAS_OFF; - - cx20442_dai.dev = codec->dev; - - cx20442_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; - } - - ret = snd_soc_register_dai(&cx20442_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } - - return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - cx20442_codec = NULL; - kfree(cx20442); - return ret; -} - -static void cx20442_unregister(struct cx20442_priv *cx20442) -{ - snd_soc_unregister_dai(&cx20442_dai); - snd_soc_unregister_codec(&cx20442->codec); - - cx20442_codec = NULL; - kfree(cx20442); -} - -static int cx20442_platform_probe(struct platform_device *pdev) -{ - struct cx20442_priv *cx20442; - struct snd_soc_codec *codec; - - cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL); - if (cx20442 == NULL) - return -ENOMEM; - - codec = &cx20442->codec; - - codec->control_data = NULL; - codec->hw_write = NULL; - codec->pop_time = 0; - - codec->dev = &pdev->dev; - platform_set_drvdata(pdev, cx20442); - - return cx20442_register(cx20442); -} - -static int __exit cx20442_platform_remove(struct platform_device *pdev) -{ - struct cx20442_priv *cx20442 = platform_get_drvdata(pdev); - - cx20442_unregister(cx20442); - return 0; -} - -static struct platform_driver cx20442_platform_driver = { - .driver = { - .name = "cx20442", - .owner = THIS_MODULE, - }, - .probe = cx20442_platform_probe, - .remove = __exit_p(cx20442_platform_remove), -}; - -static int __init cx20442_init(void) -{ - return platform_driver_register(&cx20442_platform_driver); -} -module_init(cx20442_init); - -static void __exit cx20442_exit(void) -{ - platform_driver_unregister(&cx20442_platform_driver); -} -module_exit(cx20442_exit); - -MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver"); -MODULE_AUTHOR("Janusz Krzysztofik"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:cx20442"); diff --git a/trunk/sound/soc/codecs/cx20442.h b/trunk/sound/soc/codecs/cx20442.h deleted file mode 100644 index 688a5eb62e17..000000000000 --- a/trunk/sound/soc/codecs/cx20442.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * cx20442.h -- audio driver for CX20442 - * - * Copyright 2009 Janusz Krzysztofik - * - * 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. - * - */ - -#ifndef _CX20442_CODEC_H -#define _CX20442_CODEC_H - -extern struct snd_soc_dai cx20442_dai; -extern struct snd_soc_codec_device cx20442_codec_dev; -extern struct tty_ldisc_ops v253_ops; - -#endif diff --git a/trunk/sound/soc/codecs/max9877.c b/trunk/sound/soc/codecs/max9877.c deleted file mode 100644 index 9e7e964a5fa3..000000000000 --- a/trunk/sound/soc/codecs/max9877.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * max9877.c -- amp driver for max9877 - * - * Copyright (C) 2009 Samsung Electronics Co.Ltd - * Author: Joonyoung Shim - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include -#include -#include -#include -#include - -#include "max9877.h" - -static struct i2c_client *i2c; - -static u8 max9877_regs[5] = { 0x40, 0x00, 0x00, 0x00, 0x49 }; - -static void max9877_write_regs(void) -{ - unsigned int i; - u8 data[6]; - - data[0] = MAX9877_INPUT_MODE; - for (i = 0; i < ARRAY_SIZE(max9877_regs); i++) - data[i + 1] = max9877_regs[i]; - - if (i2c_master_send(i2c, data, 6) != 6) - dev_err(&i2c->dev, "i2c write failed\n"); -} - -static int max9877_get_reg(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - unsigned int mask = mc->max; - unsigned int invert = mc->invert; - - ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask; - - if (invert) - ucontrol->value.integer.value[0] = - mask - ucontrol->value.integer.value[0]; - - return 0; -} - -static int max9877_set_reg(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - unsigned int mask = mc->max; - unsigned int invert = mc->invert; - unsigned int val = (ucontrol->value.integer.value[0] & mask); - - if (invert) - val = mask - val; - - if (((max9877_regs[reg] >> shift) & mask) == val) - return 0; - - max9877_regs[reg] &= ~(mask << shift); - max9877_regs[reg] |= val << shift; - max9877_write_regs(); - - return 1; -} - -static int max9877_get_2reg(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - unsigned int shift = mc->shift; - unsigned int mask = mc->max; - - ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask; - ucontrol->value.integer.value[1] = (max9877_regs[reg2] >> shift) & mask; - - return 0; -} - -static int max9877_set_2reg(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - unsigned int shift = mc->shift; - unsigned int mask = mc->max; - unsigned int val = (ucontrol->value.integer.value[0] & mask); - unsigned int val2 = (ucontrol->value.integer.value[1] & mask); - unsigned int change = 1; - - if (((max9877_regs[reg] >> shift) & mask) == val) - change = 0; - - if (((max9877_regs[reg2] >> shift) & mask) == val2) - change = 0; - - if (change) { - max9877_regs[reg] &= ~(mask << shift); - max9877_regs[reg] |= val << shift; - max9877_regs[reg2] &= ~(mask << shift); - max9877_regs[reg2] |= val2 << shift; - max9877_write_regs(); - } - - return change; -} - -static int max9877_get_out_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u8 value = max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK; - - if (value) - value -= 1; - - ucontrol->value.integer.value[0] = value; - return 0; -} - -static int max9877_set_out_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u8 value = ucontrol->value.integer.value[0]; - - value += 1; - - if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK) == value) - return 0; - - max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OUTMODE_MASK; - max9877_regs[MAX9877_OUTPUT_MODE] |= value; - max9877_write_regs(); - return 1; -} - -static int max9877_get_osc_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u8 value = (max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK); - - value = value >> MAX9877_OSC_OFFSET; - - ucontrol->value.integer.value[0] = value; - return 0; -} - -static int max9877_set_osc_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u8 value = ucontrol->value.integer.value[0]; - - value = value << MAX9877_OSC_OFFSET; - if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK) == value) - return 0; - - max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OSC_MASK; - max9877_regs[MAX9877_OUTPUT_MODE] |= value; - max9877_write_regs(); - return 1; -} - -static const unsigned int max9877_pgain_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 1, TLV_DB_SCALE_ITEM(0, 900, 0), - 2, 2, TLV_DB_SCALE_ITEM(2000, 0, 0), -}; - -static const unsigned int max9877_output_tlv[] = { - TLV_DB_RANGE_HEAD(4), - 0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1), - 8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0), - 16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0), - 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0), -}; - -static const char *max9877_out_mode[] = { - "INA -> SPK", - "INA -> HP", - "INA -> SPK and HP", - "INB -> SPK", - "INB -> HP", - "INB -> SPK and HP", - "INA + INB -> SPK", - "INA + INB -> HP", - "INA + INB -> SPK and HP", -}; - -static const char *max9877_osc_mode[] = { - "1176KHz", - "1100KHz", - "700KHz", -}; - -static const struct soc_enum max9877_enum[] = { - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_out_mode), max9877_out_mode), - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_osc_mode), max9877_osc_mode), -}; - -static const struct snd_kcontrol_new max9877_controls[] = { - SOC_SINGLE_EXT_TLV("MAX9877 PGAINA Playback Volume", - MAX9877_INPUT_MODE, 0, 2, 0, - max9877_get_reg, max9877_set_reg, max9877_pgain_tlv), - SOC_SINGLE_EXT_TLV("MAX9877 PGAINB Playback Volume", - MAX9877_INPUT_MODE, 2, 2, 0, - max9877_get_reg, max9877_set_reg, max9877_pgain_tlv), - SOC_SINGLE_EXT_TLV("MAX9877 Amp Speaker Playback Volume", - MAX9877_SPK_VOLUME, 0, 31, 0, - max9877_get_reg, max9877_set_reg, max9877_output_tlv), - SOC_DOUBLE_R_EXT_TLV("MAX9877 Amp HP Playback Volume", - MAX9877_HPL_VOLUME, MAX9877_HPR_VOLUME, 0, 31, 0, - max9877_get_2reg, max9877_set_2reg, max9877_output_tlv), - SOC_SINGLE_EXT("MAX9877 INB Stereo Switch", - MAX9877_INPUT_MODE, 4, 1, 1, - max9877_get_reg, max9877_set_reg), - SOC_SINGLE_EXT("MAX9877 INA Stereo Switch", - MAX9877_INPUT_MODE, 5, 1, 1, - max9877_get_reg, max9877_set_reg), - SOC_SINGLE_EXT("MAX9877 Zero-crossing detection Switch", - MAX9877_INPUT_MODE, 6, 1, 0, - max9877_get_reg, max9877_set_reg), - SOC_SINGLE_EXT("MAX9877 Bypass Mode Switch", - MAX9877_OUTPUT_MODE, 6, 1, 0, - max9877_get_reg, max9877_set_reg), - SOC_SINGLE_EXT("MAX9877 Shutdown Mode Switch", - MAX9877_OUTPUT_MODE, 7, 1, 1, - max9877_get_reg, max9877_set_reg), - SOC_ENUM_EXT("MAX9877 Output Mode", max9877_enum[0], - max9877_get_out_mode, max9877_set_out_mode), - SOC_ENUM_EXT("MAX9877 Oscillator Mode", max9877_enum[1], - max9877_get_osc_mode, max9877_set_osc_mode), -}; - -/* This function is called from ASoC machine driver */ -int max9877_add_controls(struct snd_soc_codec *codec) -{ - return snd_soc_add_controls(codec, max9877_controls, - ARRAY_SIZE(max9877_controls)); -} -EXPORT_SYMBOL_GPL(max9877_add_controls); - -static int __devinit max9877_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - i2c = client; - - max9877_write_regs(); - - return 0; -} - -static __devexit int max9877_i2c_remove(struct i2c_client *client) -{ - i2c = NULL; - - return 0; -} - -static const struct i2c_device_id max9877_i2c_id[] = { - { "max9877", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, max9877_i2c_id); - -static struct i2c_driver max9877_i2c_driver = { - .driver = { - .name = "max9877", - .owner = THIS_MODULE, - }, - .probe = max9877_i2c_probe, - .remove = __devexit_p(max9877_i2c_remove), - .id_table = max9877_i2c_id, -}; - -static int __init max9877_init(void) -{ - return i2c_add_driver(&max9877_i2c_driver); -} -module_init(max9877_init); - -static void __exit max9877_exit(void) -{ - i2c_del_driver(&max9877_i2c_driver); -} -module_exit(max9877_exit); - -MODULE_DESCRIPTION("ASoC MAX9877 amp driver"); -MODULE_AUTHOR("Joonyoung Shim "); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/codecs/max9877.h b/trunk/sound/soc/codecs/max9877.h deleted file mode 100644 index 6da72290ac58..000000000000 --- a/trunk/sound/soc/codecs/max9877.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * max9877.h -- amp driver for max9877 - * - * Copyright (C) 2009 Samsung Electronics Co.Ltd - * Author: Joonyoung Shim - * - * 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. - * - */ - -#ifndef _MAX9877_H -#define _MAX9877_H - -#define MAX9877_INPUT_MODE 0x00 -#define MAX9877_SPK_VOLUME 0x01 -#define MAX9877_HPL_VOLUME 0x02 -#define MAX9877_HPR_VOLUME 0x03 -#define MAX9877_OUTPUT_MODE 0x04 - -/* MAX9877_INPUT_MODE */ -#define MAX9877_INB (1 << 4) -#define MAX9877_INA (1 << 5) -#define MAX9877_ZCD (1 << 6) - -/* MAX9877_OUTPUT_MODE */ -#define MAX9877_OUTMODE_MASK (15 << 0) -#define MAX9877_OSC_MASK (3 << 4) -#define MAX9877_OSC_OFFSET 4 -#define MAX9877_BYPASS (1 << 6) -#define MAX9877_SHDN (1 << 7) - -extern int max9877_add_controls(struct snd_soc_codec *codec); - -#endif diff --git a/trunk/sound/soc/codecs/spdif_transciever.c b/trunk/sound/soc/codecs/spdif_transciever.c index a63191141052..218b33adad90 100644 --- a/trunk/sound/soc/codecs/spdif_transciever.c +++ b/trunk/sound/soc/codecs/spdif_transciever.c @@ -21,8 +21,6 @@ #include "spdif_transciever.h" -MODULE_LICENSE("GPL"); - #define STUB_RATES SNDRV_PCM_RATE_8000_96000 #define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE @@ -36,7 +34,6 @@ struct snd_soc_dai dit_stub_dai = { .formats = STUB_FORMATS, }, }; -EXPORT_SYMBOL_GPL(dit_stub_dai); static int spdif_dit_probe(struct platform_device *pdev) { diff --git a/trunk/sound/soc/codecs/stac9766.c b/trunk/sound/soc/codecs/stac9766.c index befc6488c39a..8ad4b7b3e3ba 100644 --- a/trunk/sound/soc/codecs/stac9766.c +++ b/trunk/sound/soc/codecs/stac9766.c @@ -149,7 +149,7 @@ static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, stac9766_ac97_write(codec, AC97_INT_PAGING, 1); return 0; } - if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) + if (reg / 2 > ARRAY_SIZE(stac9766_reg)) return -EIO; soc_ac97_ops.write(codec->ac97, reg, val); @@ -168,7 +168,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, stac9766_ac97_write(codec, AC97_INT_PAGING, 1); return val; } - if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) + if (reg / 2 > ARRAY_SIZE(stac9766_reg)) return -EIO; if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || diff --git a/trunk/sound/soc/codecs/tlv320aic3x.c b/trunk/sound/soc/codecs/tlv320aic3x.c index cb0d1bf34b57..ab099f482487 100644 --- a/trunk/sound/soc/codecs/tlv320aic3x.c +++ b/trunk/sound/soc/codecs/tlv320aic3x.c @@ -767,7 +767,6 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; u8 data, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; u16 pll_d = 1; - u8 reg; /* select data word length */ data = @@ -802,16 +801,8 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, pll_q &= 0xf; aic3x_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT); aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV); - /* disable PLL if it is bypassed */ - reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); - aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg & ~PLL_ENABLE); - - } else { + } else aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV); - /* enable PLL when it is used */ - reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); - aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg | PLL_ENABLE); - } /* Route Left DAC to left channel input and * right DAC to right channel input */ diff --git a/trunk/sound/soc/codecs/wm8400.c b/trunk/sound/soc/codecs/wm8400.c index b9ef4d915221..0bf903f27564 100644 --- a/trunk/sound/soc/codecs/wm8400.c +++ b/trunk/sound/soc/codecs/wm8400.c @@ -1022,15 +1022,10 @@ static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, if (freq_in == wm8400->fll_in && freq_out == wm8400->fll_out) return 0; - if (freq_out) { + if (freq_out != 0) { ret = fll_factors(wm8400, &factors, freq_in, freq_out); if (ret != 0) return ret; - } else { - /* Bodge GCC 4.4.0 uninitialised variable warning - it - * doesn't seem capable of working out that we exit if - * freq_out is 0 before any of the uses. */ - memset(&factors, 0, sizeof(factors)); } wm8400->fll_out = freq_out; @@ -1045,7 +1040,7 @@ static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, reg &= ~WM8400_FLL_OSC_ENA; wm8400_write(codec, WM8400_FLL_CONTROL_1, reg); - if (!freq_out) + if (freq_out == 0) return 0; reg &= ~(WM8400_FLL_REF_FREQ | WM8400_FLL_FRATIO_MASK); diff --git a/trunk/sound/soc/codecs/wm8510.c b/trunk/sound/soc/codecs/wm8510.c index 261d4cb75964..7a169bff86f9 100644 --- a/trunk/sound/soc/codecs/wm8510.c +++ b/trunk/sound/soc/codecs/wm8510.c @@ -58,55 +58,7 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = { #define WM8510_POWER1_BIASEN 0x08 #define WM8510_POWER1_BUFIOEN 0x10 -/* - * read wm8510 register cache - */ -static inline unsigned int wm8510_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - if (reg == WM8510_RESET) - return 0; - if (reg >= WM8510_CACHEREGNUM) - return -1; - return cache[reg]; -} - -/* - * write wm8510 register cache - */ -static inline void wm8510_write_reg_cache(struct snd_soc_codec *codec, - u16 reg, unsigned int value) -{ - u16 *cache = codec->reg_cache; - if (reg >= WM8510_CACHEREGNUM) - return; - cache[reg] = value; -} - -/* - * write to the WM8510 register space - */ -static int wm8510_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 data[2]; - - /* data is - * D15..D9 WM8510 register offset - * D8...D0 register data - */ - data[0] = (reg << 1) | ((value >> 8) & 0x0001); - data[1] = value & 0x00ff; - - wm8510_write_reg_cache(codec, reg, value); - if (codec->hw_write(codec->control_data, data, 2) == 2) - return 0; - else - return -EIO; -} - -#define wm8510_reset(c) wm8510_write(c, WM8510_RESET, 0) +#define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0) static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; @@ -327,27 +279,27 @@ static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, if (freq_in == 0 || freq_out == 0) { /* Clock CODEC directly from MCLK */ - reg = wm8510_read_reg_cache(codec, WM8510_CLOCK); - wm8510_write(codec, WM8510_CLOCK, reg & 0x0ff); + reg = snd_soc_read(codec, WM8510_CLOCK); + snd_soc_write(codec, WM8510_CLOCK, reg & 0x0ff); /* Turn off PLL */ - reg = wm8510_read_reg_cache(codec, WM8510_POWER1); - wm8510_write(codec, WM8510_POWER1, reg & 0x1df); + reg = snd_soc_read(codec, WM8510_POWER1); + snd_soc_write(codec, WM8510_POWER1, reg & 0x1df); return 0; } pll_factors(freq_out*4, freq_in); - wm8510_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n); - wm8510_write(codec, WM8510_PLLK1, pll_div.k >> 18); - wm8510_write(codec, WM8510_PLLK2, (pll_div.k >> 9) & 0x1ff); - wm8510_write(codec, WM8510_PLLK3, pll_div.k & 0x1ff); - reg = wm8510_read_reg_cache(codec, WM8510_POWER1); - wm8510_write(codec, WM8510_POWER1, reg | 0x020); + snd_soc_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n); + snd_soc_write(codec, WM8510_PLLK1, pll_div.k >> 18); + snd_soc_write(codec, WM8510_PLLK2, (pll_div.k >> 9) & 0x1ff); + snd_soc_write(codec, WM8510_PLLK3, pll_div.k & 0x1ff); + reg = snd_soc_read(codec, WM8510_POWER1); + snd_soc_write(codec, WM8510_POWER1, reg | 0x020); /* Run CODEC from PLL instead of MCLK */ - reg = wm8510_read_reg_cache(codec, WM8510_CLOCK); - wm8510_write(codec, WM8510_CLOCK, reg | 0x100); + reg = snd_soc_read(codec, WM8510_CLOCK); + snd_soc_write(codec, WM8510_CLOCK, reg | 0x100); return 0; } @@ -363,24 +315,24 @@ static int wm8510_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8510_OPCLKDIV: - reg = wm8510_read_reg_cache(codec, WM8510_GPIO) & 0x1cf; - wm8510_write(codec, WM8510_GPIO, reg | div); + reg = snd_soc_read(codec, WM8510_GPIO) & 0x1cf; + snd_soc_write(codec, WM8510_GPIO, reg | div); break; case WM8510_MCLKDIV: - reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x11f; - wm8510_write(codec, WM8510_CLOCK, reg | div); + reg = snd_soc_read(codec, WM8510_CLOCK) & 0x11f; + snd_soc_write(codec, WM8510_CLOCK, reg | div); break; case WM8510_ADCCLK: - reg = wm8510_read_reg_cache(codec, WM8510_ADC) & 0x1f7; - wm8510_write(codec, WM8510_ADC, reg | div); + reg = snd_soc_read(codec, WM8510_ADC) & 0x1f7; + snd_soc_write(codec, WM8510_ADC, reg | div); break; case WM8510_DACCLK: - reg = wm8510_read_reg_cache(codec, WM8510_DAC) & 0x1f7; - wm8510_write(codec, WM8510_DAC, reg | div); + reg = snd_soc_read(codec, WM8510_DAC) & 0x1f7; + snd_soc_write(codec, WM8510_DAC, reg | div); break; case WM8510_BCLKDIV: - reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1e3; - wm8510_write(codec, WM8510_CLOCK, reg | div); + reg = snd_soc_read(codec, WM8510_CLOCK) & 0x1e3; + snd_soc_write(codec, WM8510_CLOCK, reg | div); break; default: return -EINVAL; @@ -394,7 +346,7 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai, { struct snd_soc_codec *codec = codec_dai->codec; u16 iface = 0; - u16 clk = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1fe; + u16 clk = snd_soc_read(codec, WM8510_CLOCK) & 0x1fe; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -441,8 +393,8 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - wm8510_write(codec, WM8510_IFACE, iface); - wm8510_write(codec, WM8510_CLOCK, clk); + snd_soc_write(codec, WM8510_IFACE, iface); + snd_soc_write(codec, WM8510_CLOCK, clk); return 0; } @@ -453,8 +405,8 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; - u16 iface = wm8510_read_reg_cache(codec, WM8510_IFACE) & 0x19f; - u16 adn = wm8510_read_reg_cache(codec, WM8510_ADD) & 0x1f1; + u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f; + u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1; /* bit size */ switch (params_format(params)) { @@ -493,20 +445,20 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, break; } - wm8510_write(codec, WM8510_IFACE, iface); - wm8510_write(codec, WM8510_ADD, adn); + snd_soc_write(codec, WM8510_IFACE, iface); + snd_soc_write(codec, WM8510_ADD, adn); return 0; } static int wm8510_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = wm8510_read_reg_cache(codec, WM8510_DAC) & 0xffbf; + u16 mute_reg = snd_soc_read(codec, WM8510_DAC) & 0xffbf; if (mute) - wm8510_write(codec, WM8510_DAC, mute_reg | 0x40); + snd_soc_write(codec, WM8510_DAC, mute_reg | 0x40); else - wm8510_write(codec, WM8510_DAC, mute_reg); + snd_soc_write(codec, WM8510_DAC, mute_reg); return 0; } @@ -514,13 +466,13 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute) static int wm8510_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 power1 = wm8510_read_reg_cache(codec, WM8510_POWER1) & ~0x3; + u16 power1 = snd_soc_read(codec, WM8510_POWER1) & ~0x3; switch (level) { case SND_SOC_BIAS_ON: case SND_SOC_BIAS_PREPARE: power1 |= 0x1; /* VMID 50k */ - wm8510_write(codec, WM8510_POWER1, power1); + snd_soc_write(codec, WM8510_POWER1, power1); break; case SND_SOC_BIAS_STANDBY: @@ -528,18 +480,18 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec, if (codec->bias_level == SND_SOC_BIAS_OFF) { /* Initial cap charge at VMID 5k */ - wm8510_write(codec, WM8510_POWER1, power1 | 0x3); + snd_soc_write(codec, WM8510_POWER1, power1 | 0x3); mdelay(100); } power1 |= 0x2; /* VMID 500k */ - wm8510_write(codec, WM8510_POWER1, power1); + snd_soc_write(codec, WM8510_POWER1, power1); break; case SND_SOC_BIAS_OFF: - wm8510_write(codec, WM8510_POWER1, 0); - wm8510_write(codec, WM8510_POWER2, 0); - wm8510_write(codec, WM8510_POWER3, 0); + snd_soc_write(codec, WM8510_POWER1, 0); + snd_soc_write(codec, WM8510_POWER2, 0); + snd_soc_write(codec, WM8510_POWER3, 0); break; } @@ -577,7 +529,6 @@ struct snd_soc_dai wm8510_dai = { .rates = WM8510_RATES, .formats = WM8510_FORMATS,}, .ops = &wm8510_dai_ops, - .symmetric_rates = 1, }; EXPORT_SYMBOL_GPL(wm8510_dai); @@ -620,8 +571,6 @@ static int wm8510_init(struct snd_soc_device *socdev) codec->name = "WM8510"; codec->owner = THIS_MODULE; - codec->read = wm8510_read_reg_cache; - codec->write = wm8510_write; codec->set_bias_level = wm8510_set_bias_level; codec->dai = &wm8510_dai; codec->num_dai = 1; @@ -631,13 +580,20 @@ static int wm8510_init(struct snd_soc_device *socdev) if (codec->reg_cache == NULL) return -ENOMEM; + ret = snd_soc_codec_set_cache_io(codec, 7, 9); + if (ret < 0) { + printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", + ret); + goto err; + } + wm8510_reset(codec); /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { printk(KERN_ERR "wm8510: failed to create pcms\n"); - goto pcm_err; + goto err; } /* power on device */ @@ -656,7 +612,7 @@ static int wm8510_init(struct snd_soc_device *socdev) card_err: snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); -pcm_err: +err: kfree(codec->reg_cache); return ret; } diff --git a/trunk/sound/soc/codecs/wm8728.c b/trunk/sound/soc/codecs/wm8728.c index e7ff2121ede9..66da44b08d35 100644 --- a/trunk/sound/soc/codecs/wm8728.c +++ b/trunk/sound/soc/codecs/wm8728.c @@ -43,45 +43,6 @@ static const u16 wm8728_reg_defaults[] = { 0x100, }; -static inline unsigned int wm8728_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults)); - return cache[reg]; -} - -static inline void wm8728_write_reg_cache(struct snd_soc_codec *codec, - u16 reg, unsigned int value) -{ - u16 *cache = codec->reg_cache; - BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults)); - cache[reg] = value; -} - -/* - * write to the WM8728 register space - */ -static int wm8728_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 data[2]; - - /* data is - * D15..D9 WM8728 register offset - * D8...D0 register data - */ - data[0] = (reg << 1) | ((value >> 8) & 0x0001); - data[1] = value & 0x00ff; - - wm8728_write_reg_cache(codec, reg, value); - - if (codec->hw_write(codec->control_data, data, 2) == 2) - return 0; - else - return -EIO; -} - static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); static const struct snd_kcontrol_new wm8728_snd_controls[] = { @@ -121,12 +82,12 @@ static int wm8728_add_widgets(struct snd_soc_codec *codec) static int wm8728_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); + u16 mute_reg = snd_soc_read(codec, WM8728_DACCTL); if (mute) - wm8728_write(codec, WM8728_DACCTL, mute_reg | 1); + snd_soc_write(codec, WM8728_DACCTL, mute_reg | 1); else - wm8728_write(codec, WM8728_DACCTL, mute_reg & ~1); + snd_soc_write(codec, WM8728_DACCTL, mute_reg & ~1); return 0; } @@ -138,7 +99,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; - u16 dac = wm8728_read_reg_cache(codec, WM8728_DACCTL); + u16 dac = snd_soc_read(codec, WM8728_DACCTL); dac &= ~0x18; @@ -155,7 +116,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - wm8728_write(codec, WM8728_DACCTL, dac); + snd_soc_write(codec, WM8728_DACCTL, dac); return 0; } @@ -164,7 +125,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = wm8728_read_reg_cache(codec, WM8728_IFCTL); + u16 iface = snd_soc_read(codec, WM8728_IFCTL); /* Currently only I2S is supported by the driver, though the * hardware is more flexible. @@ -204,7 +165,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - wm8728_write(codec, WM8728_IFCTL, iface); + snd_soc_write(codec, WM8728_IFCTL, iface); return 0; } @@ -220,19 +181,19 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_STANDBY: if (codec->bias_level == SND_SOC_BIAS_OFF) { /* Power everything up... */ - reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); - wm8728_write(codec, WM8728_DACCTL, reg & ~0x4); + reg = snd_soc_read(codec, WM8728_DACCTL); + snd_soc_write(codec, WM8728_DACCTL, reg & ~0x4); /* ..then sync in the register cache. */ for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++) - wm8728_write(codec, i, - wm8728_read_reg_cache(codec, i)); + snd_soc_write(codec, i, + snd_soc_read(codec, i)); } break; case SND_SOC_BIAS_OFF: - reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); - wm8728_write(codec, WM8728_DACCTL, reg | 0x4); + reg = snd_soc_read(codec, WM8728_DACCTL); + snd_soc_write(codec, WM8728_DACCTL, reg | 0x4); break; } codec->bias_level = level; @@ -294,8 +255,6 @@ static int wm8728_init(struct snd_soc_device *socdev) codec->name = "WM8728"; codec->owner = THIS_MODULE; - codec->read = wm8728_read_reg_cache; - codec->write = wm8728_write; codec->set_bias_level = wm8728_set_bias_level; codec->dai = &wm8728_dai; codec->num_dai = 1; @@ -307,11 +266,18 @@ static int wm8728_init(struct snd_soc_device *socdev) if (codec->reg_cache == NULL) return -ENOMEM; + ret = snd_soc_codec_set_cache_io(codec, 7, 9); + if (ret < 0) { + printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", + ret); + goto err; + } + /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { printk(KERN_ERR "wm8728: failed to create pcms\n"); - goto pcm_err; + goto err; } /* power on device */ @@ -331,7 +297,7 @@ static int wm8728_init(struct snd_soc_device *socdev) card_err: snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); -pcm_err: +err: kfree(codec->reg_cache); return ret; } diff --git a/trunk/sound/soc/codecs/wm8731.c b/trunk/sound/soc/codecs/wm8731.c index 156002852078..4eb84ff691b3 100644 --- a/trunk/sound/soc/codecs/wm8731.c +++ b/trunk/sound/soc/codecs/wm8731.c @@ -26,7 +26,6 @@ #include #include #include -#include #include "wm8731.h" @@ -51,60 +50,12 @@ static int wm8731_spi_write(struct spi_device *spi, const char *data, int len); * There is no point in caching the reset register */ static const u16 wm8731_reg[WM8731_CACHEREGNUM] = { - 0x0097, 0x0097, 0x0079, 0x0079, - 0x000a, 0x0008, 0x009f, 0x000a, - 0x0000, 0x0000 + 0x0097, 0x0097, 0x0079, 0x0079, + 0x000a, 0x0008, 0x009f, 0x000a, + 0x0000, 0x0000 }; -/* - * read wm8731 register cache - */ -static inline unsigned int wm8731_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - if (reg == WM8731_RESET) - return 0; - if (reg >= WM8731_CACHEREGNUM) - return -1; - return cache[reg]; -} - -/* - * write wm8731 register cache - */ -static inline void wm8731_write_reg_cache(struct snd_soc_codec *codec, - u16 reg, unsigned int value) -{ - u16 *cache = codec->reg_cache; - if (reg >= WM8731_CACHEREGNUM) - return; - cache[reg] = value; -} - -/* - * write to the WM8731 register space - */ -static int wm8731_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 data[2]; - - /* data is - * D15..D9 WM8731 register offset - * D8...D0 register data - */ - data[0] = (reg << 1) | ((value >> 8) & 0x0001); - data[1] = value & 0x00ff; - - wm8731_write_reg_cache(codec, reg, value); - if (codec->hw_write(codec->control_data, data, 2) == 2) - return 0; - else - return -EIO; -} - -#define wm8731_reset(c) wm8731_write(c, WM8731_RESET, 0) +#define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0) static const char *wm8731_input_select[] = {"Line In", "Mic"}; static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; @@ -114,26 +65,20 @@ static const struct soc_enum wm8731_enum[] = { SOC_ENUM_SINGLE(WM8731_APDIGI, 1, 4, wm8731_deemph), }; -static const DECLARE_TLV_DB_SCALE(in_tlv, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -1500, 300, 0); -static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); - static const struct snd_kcontrol_new wm8731_snd_controls[] = { -SOC_DOUBLE_R_TLV("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V, - 0, 127, 0, out_tlv), +SOC_DOUBLE_R("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V, + 0, 127, 0), SOC_DOUBLE_R("Master Playback ZC Switch", WM8731_LOUT1V, WM8731_ROUT1V, 7, 1, 0), -SOC_DOUBLE_R_TLV("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0, - in_tlv), +SOC_DOUBLE_R("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0), SOC_DOUBLE_R("Line Capture Switch", WM8731_LINVOL, WM8731_RINVOL, 7, 1, 1), SOC_SINGLE("Mic Boost (+20dB)", WM8731_APANA, 0, 1, 0), -SOC_SINGLE("Mic Capture Switch", WM8731_APANA, 1, 1, 1), +SOC_SINGLE("Capture Mic Switch", WM8731_APANA, 1, 1, 1), -SOC_SINGLE_TLV("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1, - sidetone_tlv), +SOC_SINGLE("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1), SOC_SINGLE("ADC High Pass Filter Switch", WM8731_APDIGI, 0, 1, 1), SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0), @@ -267,12 +212,12 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; struct wm8731_priv *wm8731 = codec->private_data; - u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3; + u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3; int i = get_coeff(wm8731->sysclk, params_rate(params)); u16 srate = (coeff_div[i].sr << 2) | (coeff_div[i].bosr << 1) | coeff_div[i].usb; - wm8731_write(codec, WM8731_SRATE, srate); + snd_soc_write(codec, WM8731_SRATE, srate); /* bit size */ switch (params_format(params)) { @@ -286,7 +231,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, break; } - wm8731_write(codec, WM8731_IFACE, iface); + snd_soc_write(codec, WM8731_IFACE, iface); return 0; } @@ -298,7 +243,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = socdev->card->codec; /* set active */ - wm8731_write(codec, WM8731_ACTIVE, 0x0001); + snd_soc_write(codec, WM8731_ACTIVE, 0x0001); return 0; } @@ -313,19 +258,19 @@ static void wm8731_shutdown(struct snd_pcm_substream *substream, /* deactivate */ if (!codec->active) { udelay(50); - wm8731_write(codec, WM8731_ACTIVE, 0x0); + snd_soc_write(codec, WM8731_ACTIVE, 0x0); } } static int wm8731_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = wm8731_read_reg_cache(codec, WM8731_APDIGI) & 0xfff7; + u16 mute_reg = snd_soc_read(codec, WM8731_APDIGI) & 0xfff7; if (mute) - wm8731_write(codec, WM8731_APDIGI, mute_reg | 0x8); + snd_soc_write(codec, WM8731_APDIGI, mute_reg | 0x8); else - wm8731_write(codec, WM8731_APDIGI, mute_reg); + snd_soc_write(codec, WM8731_APDIGI, mute_reg); return 0; } @@ -403,7 +348,7 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai, } /* set iface */ - wm8731_write(codec, WM8731_IFACE, iface); + snd_soc_write(codec, WM8731_IFACE, iface); return 0; } @@ -419,12 +364,12 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: /* Clear PWROFF, gate CLKOUT, everything else as-is */ - reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f; - wm8731_write(codec, WM8731_PWR, reg | 0x0040); + reg = snd_soc_read(codec, WM8731_PWR) & 0xff7f; + snd_soc_write(codec, WM8731_PWR, reg | 0x0040); break; case SND_SOC_BIAS_OFF: - wm8731_write(codec, WM8731_ACTIVE, 0x0); - wm8731_write(codec, WM8731_PWR, 0xffff); + snd_soc_write(codec, WM8731_ACTIVE, 0x0); + snd_soc_write(codec, WM8731_PWR, 0xffff); break; } codec->bias_level = level; @@ -464,7 +409,6 @@ struct snd_soc_dai wm8731_dai = { .rates = WM8731_RATES, .formats = WM8731_FORMATS,}, .ops = &wm8731_dai_ops, - .symmetric_rates = 1, }; EXPORT_SYMBOL_GPL(wm8731_dai); @@ -474,7 +418,7 @@ static int wm8731_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; - wm8731_write(codec, WM8731_ACTIVE, 0x0); + snd_soc_write(codec, WM8731_ACTIVE, 0x0); wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } @@ -564,7 +508,6 @@ static int wm8731_register(struct wm8731_priv *wm8731) { int ret; struct snd_soc_codec *codec = &wm8731->codec; - u16 reg; if (wm8731_codec) { dev_err(codec->dev, "Another WM8731 is registered\n"); @@ -579,8 +522,6 @@ static int wm8731_register(struct wm8731_priv *wm8731) codec->private_data = wm8731; codec->name = "WM8731"; codec->owner = THIS_MODULE; - codec->read = wm8731_read_reg_cache; - codec->write = wm8731_write; codec->bias_level = SND_SOC_BIAS_OFF; codec->set_bias_level = wm8731_set_bias_level; codec->dai = &wm8731_dai; @@ -590,6 +531,12 @@ static int wm8731_register(struct wm8731_priv *wm8731) memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg)); + ret = snd_soc_codec_set_cache_io(codec, 7, 9); + if (ret < 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + goto err; + } + ret = wm8731_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset: %d\n", ret); @@ -601,18 +548,13 @@ static int wm8731_register(struct wm8731_priv *wm8731) wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Latch the update bits */ - reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V); - wm8731_write(codec, WM8731_LOUT1V, reg & ~0x0100); - reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V); - wm8731_write(codec, WM8731_ROUT1V, reg & ~0x0100); - reg = wm8731_read_reg_cache(codec, WM8731_LINVOL); - wm8731_write(codec, WM8731_LINVOL, reg & ~0x0100); - reg = wm8731_read_reg_cache(codec, WM8731_RINVOL); - wm8731_write(codec, WM8731_RINVOL, reg & ~0x0100); + snd_soc_update_bits(codec, WM8731_LOUT1V, 0x100, 0); + snd_soc_update_bits(codec, WM8731_ROUT1V, 0x100, 0); + snd_soc_update_bits(codec, WM8731_LINVOL, 0x100, 0); + snd_soc_update_bits(codec, WM8731_RINVOL, 0x100, 0); /* Disable bypass path by default */ - reg = wm8731_read_reg_cache(codec, WM8731_APANA); - wm8731_write(codec, WM8731_APANA, reg & ~0x4); + snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0); wm8731_codec = codec; diff --git a/trunk/sound/soc/codecs/wm8750.c b/trunk/sound/soc/codecs/wm8750.c index b64509b01a49..ed09043181e1 100644 --- a/trunk/sound/soc/codecs/wm8750.c +++ b/trunk/sound/soc/codecs/wm8750.c @@ -55,50 +55,7 @@ static const u16 wm8750_reg[] = { 0x0079, 0x0079, 0x0079, /* 40 */ }; -/* - * read wm8750 register cache - */ -static inline unsigned int wm8750_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - if (reg > WM8750_CACHE_REGNUM) - return -1; - return cache[reg]; -} - -/* - * write wm8750 register cache - */ -static inline void wm8750_write_reg_cache(struct snd_soc_codec *codec, - unsigned int reg, unsigned int value) -{ - u16 *cache = codec->reg_cache; - if (reg > WM8750_CACHE_REGNUM) - return; - cache[reg] = value; -} - -static int wm8750_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 data[2]; - - /* data is - * D15..D9 WM8753 register offset - * D8...D0 register data - */ - data[0] = (reg << 1) | ((value >> 8) & 0x0001); - data[1] = value & 0x00ff; - - wm8750_write_reg_cache(codec, reg, value); - if (codec->hw_write(codec->control_data, data, 2) == 2) - return 0; - else - return -EIO; -} - -#define wm8750_reset(c) wm8750_write(c, WM8750_RESET, 0) +#define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0) /* * WM8750 Controls @@ -594,7 +551,7 @@ static int wm8750_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - wm8750_write(codec, WM8750_IFACE, iface); + snd_soc_write(codec, WM8750_IFACE, iface); return 0; } @@ -606,8 +563,8 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; struct wm8750_priv *wm8750 = codec->private_data; - u16 iface = wm8750_read_reg_cache(codec, WM8750_IFACE) & 0x1f3; - u16 srate = wm8750_read_reg_cache(codec, WM8750_SRATE) & 0x1c0; + u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3; + u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0; int coeff = get_coeff(wm8750->sysclk, params_rate(params)); /* bit size */ @@ -626,9 +583,9 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, } /* set iface & srate */ - wm8750_write(codec, WM8750_IFACE, iface); + snd_soc_write(codec, WM8750_IFACE, iface); if (coeff >= 0) - wm8750_write(codec, WM8750_SRATE, srate | + snd_soc_write(codec, WM8750_SRATE, srate | (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); return 0; @@ -637,35 +594,35 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, static int wm8750_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = wm8750_read_reg_cache(codec, WM8750_ADCDAC) & 0xfff7; + u16 mute_reg = snd_soc_read(codec, WM8750_ADCDAC) & 0xfff7; if (mute) - wm8750_write(codec, WM8750_ADCDAC, mute_reg | 0x8); + snd_soc_write(codec, WM8750_ADCDAC, mute_reg | 0x8); else - wm8750_write(codec, WM8750_ADCDAC, mute_reg); + snd_soc_write(codec, WM8750_ADCDAC, mute_reg); return 0; } static int wm8750_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 pwr_reg = wm8750_read_reg_cache(codec, WM8750_PWR1) & 0xfe3e; + u16 pwr_reg = snd_soc_read(codec, WM8750_PWR1) & 0xfe3e; switch (level) { case SND_SOC_BIAS_ON: /* set vmid to 50k and unmute dac */ - wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x00c0); + snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x00c0); break; case SND_SOC_BIAS_PREPARE: /* set vmid to 5k for quick power up */ - wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x01c1); + snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1); break; case SND_SOC_BIAS_STANDBY: /* mute dac and set vmid to 500k, enable VREF */ - wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x0141); + snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x0141); break; case SND_SOC_BIAS_OFF: - wm8750_write(codec, WM8750_PWR1, 0x0001); + snd_soc_write(codec, WM8750_PWR1, 0x0001); break; } codec->bias_level = level; @@ -761,8 +718,6 @@ static int wm8750_init(struct snd_soc_device *socdev) codec->name = "WM8750"; codec->owner = THIS_MODULE; - codec->read = wm8750_read_reg_cache; - codec->write = wm8750_write; codec->set_bias_level = wm8750_set_bias_level; codec->dai = &wm8750_dai; codec->num_dai = 1; @@ -771,13 +726,23 @@ static int wm8750_init(struct snd_soc_device *socdev) if (codec->reg_cache == NULL) return -ENOMEM; - wm8750_reset(codec); + ret = snd_soc_codec_set_cache_io(codec, 7, 9); + if (ret < 0) { + printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret); + goto err; + } + + ret = wm8750_reset(codec); + if (ret < 0) { + printk(KERN_ERR "wm8750: failed to reset: %d\n", ret); + goto err; + } /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { printk(KERN_ERR "wm8750: failed to create pcms\n"); - goto pcm_err; + goto err; } /* charge output caps */ @@ -786,22 +751,22 @@ static int wm8750_init(struct snd_soc_device *socdev) schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000)); /* set the update bits */ - reg = wm8750_read_reg_cache(codec, WM8750_LDAC); - wm8750_write(codec, WM8750_LDAC, reg | 0x0100); - reg = wm8750_read_reg_cache(codec, WM8750_RDAC); - wm8750_write(codec, WM8750_RDAC, reg | 0x0100); - reg = wm8750_read_reg_cache(codec, WM8750_LOUT1V); - wm8750_write(codec, WM8750_LOUT1V, reg | 0x0100); - reg = wm8750_read_reg_cache(codec, WM8750_ROUT1V); - wm8750_write(codec, WM8750_ROUT1V, reg | 0x0100); - reg = wm8750_read_reg_cache(codec, WM8750_LOUT2V); - wm8750_write(codec, WM8750_LOUT2V, reg | 0x0100); - reg = wm8750_read_reg_cache(codec, WM8750_ROUT2V); - wm8750_write(codec, WM8750_ROUT2V, reg | 0x0100); - reg = wm8750_read_reg_cache(codec, WM8750_LINVOL); - wm8750_write(codec, WM8750_LINVOL, reg | 0x0100); - reg = wm8750_read_reg_cache(codec, WM8750_RINVOL); - wm8750_write(codec, WM8750_RINVOL, reg | 0x0100); + reg = snd_soc_read(codec, WM8750_LDAC); + snd_soc_write(codec, WM8750_LDAC, reg | 0x0100); + reg = snd_soc_read(codec, WM8750_RDAC); + snd_soc_write(codec, WM8750_RDAC, reg | 0x0100); + reg = snd_soc_read(codec, WM8750_LOUT1V); + snd_soc_write(codec, WM8750_LOUT1V, reg | 0x0100); + reg = snd_soc_read(codec, WM8750_ROUT1V); + snd_soc_write(codec, WM8750_ROUT1V, reg | 0x0100); + reg = snd_soc_read(codec, WM8750_LOUT2V); + snd_soc_write(codec, WM8750_LOUT2V, reg | 0x0100); + reg = snd_soc_read(codec, WM8750_ROUT2V); + snd_soc_write(codec, WM8750_ROUT2V, reg | 0x0100); + reg = snd_soc_read(codec, WM8750_LINVOL); + snd_soc_write(codec, WM8750_LINVOL, reg | 0x0100); + reg = snd_soc_read(codec, WM8750_RINVOL); + snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100); snd_soc_add_controls(codec, wm8750_snd_controls, ARRAY_SIZE(wm8750_snd_controls)); @@ -816,7 +781,7 @@ static int wm8750_init(struct snd_soc_device *socdev) card_err: snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); -pcm_err: +err: kfree(codec->reg_cache); return ret; } diff --git a/trunk/sound/soc/codecs/wm8753.c b/trunk/sound/soc/codecs/wm8753.c index d80d414cfbbd..370f7df03628 100644 --- a/trunk/sound/soc/codecs/wm8753.c +++ b/trunk/sound/soc/codecs/wm8753.c @@ -79,7 +79,7 @@ static const u16 wm8753_reg[] = { 0x0097, 0x0097, 0x0000, 0x0004, 0x0000, 0x0083, 0x0024, 0x01ba, 0x0000, 0x0083, 0x0024, 0x01ba, - 0x0000, 0x0000, 0x0000 + 0x0000, 0x0000 }; /* codec private data */ @@ -1660,11 +1660,11 @@ static int wm8753_register(struct wm8753_priv *wm8753) codec->set_bias_level = wm8753_set_bias_level; codec->dai = wm8753_dai; codec->num_dai = 2; - codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache) + 1; + codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache); codec->reg_cache = &wm8753->reg_cache; codec->private_data = wm8753; - memcpy(codec->reg_cache, wm8753_reg, sizeof(wm8753->reg_cache)); + memcpy(codec->reg_cache, wm8753_reg, sizeof(codec->reg_cache)); INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); ret = wm8753_reset(codec); diff --git a/trunk/sound/soc/codecs/wm8776.c b/trunk/sound/soc/codecs/wm8776.c deleted file mode 100644 index ee12bf824a40..000000000000 --- a/trunk/sound/soc/codecs/wm8776.c +++ /dev/null @@ -1,781 +0,0 @@ -/* - * wm8776.c -- WM8776 ALSA SoC Audio driver - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * TODO: Input ALC/limiter support - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8776.h" - -static struct snd_soc_codec *wm8776_codec; -struct snd_soc_codec_device soc_codec_dev_wm8776; - -/* codec private data */ -struct wm8776_priv { - struct snd_soc_codec codec; - u16 reg_cache[WM8776_CACHEREGNUM]; - int sysclk[2]; -}; - -#ifdef CONFIG_SPI_MASTER -static int wm8776_spi_write(struct spi_device *spi, const char *data, int len); -#endif - -static const u16 wm8776_reg[WM8776_CACHEREGNUM] = { - 0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */ - 0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */ - 0x22, 0x22, 0x22, 0x08, 0xcf, /* 14 */ - 0xcf, 0x7b, 0x00, 0x32, 0x00, /* 19 */ - 0xa6, 0x01, 0x01 -}; - -/* - * read wm8776 register cache - */ -static inline unsigned int wm8776_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - if (reg >= WM8776_CACHEREGNUM) - return -1; - return cache[reg]; -} - -/* - * write wm8776 register cache - */ -static inline void wm8776_write_reg_cache(struct snd_soc_codec *codec, - u16 reg, unsigned int value) -{ - u16 *cache = codec->reg_cache; - if (reg >= WM8776_CACHEREGNUM) - return; - cache[reg] = value; -} - -/* - * write to the WM8776 register space - */ -static int wm8776_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 data[2]; - - data[0] = (reg << 1) | ((value >> 8) & 0x0001); - data[1] = value & 0x00ff; - - wm8776_write_reg_cache(codec, reg, value); - if (codec->hw_write(codec->control_data, data, 2) == 2) - return 0; - else - return -EIO; -} - -static int wm8776_reset(struct snd_soc_codec *codec) -{ - return wm8776_write(codec, WM8776_RESET, 0); -} - -static const DECLARE_TLV_DB_SCALE(hp_tlv, -12100, 100, 1); -static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); -static const DECLARE_TLV_DB_SCALE(adc_tlv, -10350, 50, 1); - -static const struct snd_kcontrol_new wm8776_snd_controls[] = { -SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8776_HPLVOL, WM8776_HPRVOL, - 0, 127, 0, hp_tlv), -SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8776_DACLVOL, WM8776_DACRVOL, - 0, 255, 0, dac_tlv), -SOC_SINGLE("Digital Playback ZC Switch", WM8776_DACCTRL1, 0, 1, 0), - -SOC_SINGLE("Deemphasis Switch", WM8776_DACCTRL2, 0, 1, 0), - -SOC_DOUBLE_R_TLV("Capture Volume", WM8776_ADCLVOL, WM8776_ADCRVOL, - 0, 255, 0, adc_tlv), -SOC_DOUBLE("Capture Switch", WM8776_ADCMUX, 7, 6, 1, 1), -SOC_DOUBLE_R("Capture ZC Switch", WM8776_ADCLVOL, WM8776_ADCRVOL, 8, 1, 0), -SOC_SINGLE("Capture HPF Switch", WM8776_ADCIFCTRL, 8, 1, 1), -}; - -static const struct snd_kcontrol_new inmix_controls[] = { -SOC_DAPM_SINGLE("AIN1 Switch", WM8776_ADCMUX, 0, 1, 0), -SOC_DAPM_SINGLE("AIN2 Switch", WM8776_ADCMUX, 1, 1, 0), -SOC_DAPM_SINGLE("AIN3 Switch", WM8776_ADCMUX, 2, 1, 0), -SOC_DAPM_SINGLE("AIN4 Switch", WM8776_ADCMUX, 3, 1, 0), -SOC_DAPM_SINGLE("AIN5 Switch", WM8776_ADCMUX, 4, 1, 0), -}; - -static const struct snd_kcontrol_new outmix_controls[] = { -SOC_DAPM_SINGLE("DAC Switch", WM8776_OUTMUX, 0, 1, 0), -SOC_DAPM_SINGLE("AUX Switch", WM8776_OUTMUX, 1, 1, 0), -SOC_DAPM_SINGLE("Bypass Switch", WM8776_OUTMUX, 2, 1, 0), -}; - -static const struct snd_soc_dapm_widget wm8776_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("AUX"), -SND_SOC_DAPM_INPUT("AUX"), - -SND_SOC_DAPM_INPUT("AIN1"), -SND_SOC_DAPM_INPUT("AIN2"), -SND_SOC_DAPM_INPUT("AIN3"), -SND_SOC_DAPM_INPUT("AIN4"), -SND_SOC_DAPM_INPUT("AIN5"), - -SND_SOC_DAPM_MIXER("Input Mixer", WM8776_PWRDOWN, 6, 1, - inmix_controls, ARRAY_SIZE(inmix_controls)), - -SND_SOC_DAPM_ADC("ADC", "Capture", WM8776_PWRDOWN, 1, 1), -SND_SOC_DAPM_DAC("DAC", "Playback", WM8776_PWRDOWN, 2, 1), - -SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0, - outmix_controls, ARRAY_SIZE(outmix_controls)), - -SND_SOC_DAPM_PGA("Headphone PGA", WM8776_PWRDOWN, 3, 1, NULL, 0), - -SND_SOC_DAPM_OUTPUT("VOUT"), - -SND_SOC_DAPM_OUTPUT("HPOUTL"), -SND_SOC_DAPM_OUTPUT("HPOUTR"), -}; - -static const struct snd_soc_dapm_route routes[] = { - { "Input Mixer", "AIN1 Switch", "AIN1" }, - { "Input Mixer", "AIN2 Switch", "AIN2" }, - { "Input Mixer", "AIN3 Switch", "AIN3" }, - { "Input Mixer", "AIN4 Switch", "AIN4" }, - { "Input Mixer", "AIN5 Switch", "AIN5" }, - - { "ADC", NULL, "Input Mixer" }, - - { "Output Mixer", "DAC Switch", "DAC" }, - { "Output Mixer", "AUX Switch", "AUX" }, - { "Output Mixer", "Bypass Switch", "Input Mixer" }, - - { "VOUT", NULL, "Output Mixer" }, - - { "Headphone PGA", NULL, "Output Mixer" }, - - { "HPOUTL", NULL, "Headphone PGA" }, - { "HPOUTR", NULL, "Headphone PGA" }, -}; - -static int wm8776_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - int reg, iface, master; - - switch (dai->id) { - case WM8776_DAI_DAC: - reg = WM8776_DACIFCTRL; - master = 0x80; - break; - case WM8776_DAI_ADC: - reg = WM8776_ADCIFCTRL; - master = 0x100; - break; - default: - return -EINVAL; - } - - iface = 0; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - break; - case SND_SOC_DAIFMT_CBS_CFS: - master = 0; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x0002; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x0001; - break; - /* FIXME: CHECK A/B */ - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x0003; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= 0x0007; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0x00c; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x008; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x004; - break; - default: - return -EINVAL; - } - - /* Finally, write out the values */ - snd_soc_update_bits(codec, reg, 0xf, iface); - snd_soc_update_bits(codec, WM8776_MSTRCTRL, 0x180, master); - - return 0; -} - -static int mclk_ratios[] = { - 128, - 192, - 256, - 384, - 512, - 768, -}; - -static int wm8776_hw_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 wm8776_priv *wm8776 = codec->private_data; - int iface_reg, iface; - int ratio_shift, master; - int i; - - iface = 0; - - switch (dai->id) { - case WM8776_DAI_DAC: - iface_reg = WM8776_DACIFCTRL; - master = 0x80; - ratio_shift = 4; - break; - case WM8776_DAI_ADC: - iface_reg = WM8776_ADCIFCTRL; - master = 0x100; - ratio_shift = 0; - break; - default: - return -EINVAL; - } - - - /* Set word length */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x10; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x20; - break; - case SNDRV_PCM_FORMAT_S32_LE: - iface |= 0x30; - break; - } - - /* Only need to set MCLK/LRCLK ratio if we're master */ - if (snd_soc_read(codec, WM8776_MSTRCTRL) & master) { - for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) { - if (wm8776->sysclk[dai->id] / params_rate(params) - == mclk_ratios[i]) - break; - } - - if (i == ARRAY_SIZE(mclk_ratios)) { - dev_err(codec->dev, - "Unable to configure MCLK ratio %d/%d\n", - wm8776->sysclk[dai->id], params_rate(params)); - return -EINVAL; - } - - dev_dbg(codec->dev, "MCLK is %dfs\n", mclk_ratios[i]); - - snd_soc_update_bits(codec, WM8776_MSTRCTRL, - 0x7 << ratio_shift, i << ratio_shift); - } else { - dev_dbg(codec->dev, "DAI in slave mode\n"); - } - - snd_soc_update_bits(codec, iface_reg, 0x30, iface); - - return 0; -} - -static int wm8776_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - - return snd_soc_write(codec, WM8776_DACMUTE, !!mute); -} - -static int wm8776_set_sysclk(struct snd_soc_dai *dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8776_priv *wm8776 = codec->private_data; - - BUG_ON(dai->id >= ARRAY_SIZE(wm8776->sysclk)); - - wm8776->sysclk[dai->id] = freq; - - return 0; -} - -static int wm8776_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - if (codec->bias_level == SND_SOC_BIAS_OFF) { - /* Disable the global powerdown; DAPM does the rest */ - snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0); - } - - break; - case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 1); - break; - } - - codec->bias_level = level; - return 0; -} - -#define WM8776_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ - SNDRV_PCM_RATE_96000) - - -#define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static struct snd_soc_dai_ops wm8776_dac_ops = { - .digital_mute = wm8776_mute, - .hw_params = wm8776_hw_params, - .set_fmt = wm8776_set_fmt, - .set_sysclk = wm8776_set_sysclk, -}; - -static struct snd_soc_dai_ops wm8776_adc_ops = { - .hw_params = wm8776_hw_params, - .set_fmt = wm8776_set_fmt, - .set_sysclk = wm8776_set_sysclk, -}; - -struct snd_soc_dai wm8776_dai[] = { - { - .name = "WM8776 Playback", - .id = WM8776_DAI_DAC, - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = WM8776_RATES, - .formats = WM8776_FORMATS, - }, - .ops = &wm8776_dac_ops, - }, - { - .name = "WM8776 Capture", - .id = WM8776_DAI_ADC, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = WM8776_RATES, - .formats = WM8776_FORMATS, - }, - .ops = &wm8776_adc_ops, - }, -}; -EXPORT_SYMBOL_GPL(wm8776_dai); - -#ifdef CONFIG_PM -static int wm8776_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; - - wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int wm8776_resume(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8776_reg); i++) { - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } - - wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} -#else -#define wm8776_suspend NULL -#define wm8776_resume NULL -#endif - -static int wm8776_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (wm8776_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8776_codec; - codec = wm8776_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: %d\n", ret); - goto pcm_err; - } - - snd_soc_add_controls(codec, wm8776_snd_controls, - ARRAY_SIZE(wm8776_snd_controls)); - snd_soc_dapm_new_controls(codec, wm8776_dapm_widgets, - ARRAY_SIZE(wm8776_dapm_widgets)); - snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes)); - - ret = snd_soc_init_card(socdev); - if (ret < 0) { - dev_err(codec->dev, "failed to register card: %d\n", ret); - goto card_err; - } - - return ret; - -card_err: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -pcm_err: - return ret; -} - -/* power down chip */ -static int wm8776_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8776 = { - .probe = wm8776_probe, - .remove = wm8776_remove, - .suspend = wm8776_suspend, - .resume = wm8776_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8776); - -static int wm8776_register(struct wm8776_priv *wm8776) -{ - int ret, i; - struct snd_soc_codec *codec = &wm8776->codec; - - if (wm8776_codec) { - dev_err(codec->dev, "Another WM8776 is registered\n"); - ret = -EINVAL; - goto err; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->private_data = wm8776; - codec->name = "WM8776"; - codec->owner = THIS_MODULE; - codec->read = wm8776_read_reg_cache; - codec->write = wm8776_write; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8776_set_bias_level; - codec->dai = wm8776_dai; - codec->num_dai = ARRAY_SIZE(wm8776_dai); - codec->reg_cache_size = WM8776_CACHEREGNUM; - codec->reg_cache = &wm8776->reg_cache; - - memcpy(codec->reg_cache, wm8776_reg, sizeof(wm8776_reg)); - - for (i = 0; i < ARRAY_SIZE(wm8776_dai); i++) - wm8776_dai[i].dev = codec->dev; - - ret = wm8776_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset: %d\n", ret); - goto err; - } - - wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Latch the update bits; right channel only since we always - * update both. */ - snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100); - - wm8776_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; - } - - ret = snd_soc_register_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai)); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); - goto err_codec; - } - - return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - kfree(wm8776); - return ret; -} - -static void wm8776_unregister(struct wm8776_priv *wm8776) -{ - wm8776_set_bias_level(&wm8776->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai)); - snd_soc_unregister_codec(&wm8776->codec); - kfree(wm8776); - wm8776_codec = NULL; -} - -#if defined(CONFIG_SPI_MASTER) -static int wm8776_spi_write(struct spi_device *spi, const char *data, int len) -{ - struct spi_transfer t; - struct spi_message m; - u8 msg[2]; - - if (len <= 0) - return 0; - - msg[0] = data[0]; - msg[1] = data[1]; - - spi_message_init(&m); - memset(&t, 0, (sizeof t)); - - t.tx_buf = &msg[0]; - t.len = len; - - spi_message_add_tail(&t, &m); - spi_sync(spi, &m); - - return len; -} - -static int __devinit wm8776_spi_probe(struct spi_device *spi) -{ - struct snd_soc_codec *codec; - struct wm8776_priv *wm8776; - - wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL); - if (wm8776 == NULL) - return -ENOMEM; - - codec = &wm8776->codec; - codec->control_data = spi; - codec->hw_write = (hw_write_t)wm8776_spi_write; - codec->dev = &spi->dev; - - dev_set_drvdata(&spi->dev, wm8776); - - return wm8776_register(wm8776); -} - -static int __devexit wm8776_spi_remove(struct spi_device *spi) -{ - struct wm8776_priv *wm8776 = dev_get_drvdata(&spi->dev); - - wm8776_unregister(wm8776); - - return 0; -} - -#ifdef CONFIG_PM -static int wm8776_spi_suspend(struct spi_device *spi, pm_message_t msg) -{ - return snd_soc_suspend_device(&spi->dev); -} - -static int wm8776_spi_resume(struct spi_device *spi) -{ - return snd_soc_resume_device(&spi->dev); -} -#else -#define wm8776_spi_suspend NULL -#define wm8776_spi_resume NULL -#endif - -static struct spi_driver wm8776_spi_driver = { - .driver = { - .name = "wm8776", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - .probe = wm8776_spi_probe, - .suspend = wm8776_spi_suspend, - .resume = wm8776_spi_resume, - .remove = __devexit_p(wm8776_spi_remove), -}; -#endif /* CONFIG_SPI_MASTER */ - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8776_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8776_priv *wm8776; - struct snd_soc_codec *codec; - - wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL); - if (wm8776 == NULL) - return -ENOMEM; - - codec = &wm8776->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - - i2c_set_clientdata(i2c, wm8776); - codec->control_data = i2c; - - codec->dev = &i2c->dev; - - return wm8776_register(wm8776); -} - -static __devexit int wm8776_i2c_remove(struct i2c_client *client) -{ - struct wm8776_priv *wm8776 = i2c_get_clientdata(client); - wm8776_unregister(wm8776); - return 0; -} - -#ifdef CONFIG_PM -static int wm8776_i2c_suspend(struct i2c_client *i2c, pm_message_t msg) -{ - return snd_soc_suspend_device(&i2c->dev); -} - -static int wm8776_i2c_resume(struct i2c_client *i2c) -{ - return snd_soc_resume_device(&i2c->dev); -} -#else -#define wm8776_i2c_suspend NULL -#define wm8776_i2c_resume NULL -#endif - -static const struct i2c_device_id wm8776_i2c_id[] = { - { "wm8776", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id); - -static struct i2c_driver wm8776_i2c_driver = { - .driver = { - .name = "wm8776", - .owner = THIS_MODULE, - }, - .probe = wm8776_i2c_probe, - .remove = __devexit_p(wm8776_i2c_remove), - .suspend = wm8776_i2c_suspend, - .resume = wm8776_i2c_resume, - .id_table = wm8776_i2c_id, -}; -#endif - -static int __init wm8776_modinit(void) -{ - int ret; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8776_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8776 I2C driver: %d\n", - ret); - } -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&wm8776_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8776 SPI driver: %d\n", - ret); - } -#endif - return 0; -} -module_init(wm8776_modinit); - -static void __exit wm8776_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8776_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&wm8776_spi_driver); -#endif -} -module_exit(wm8776_exit); - -MODULE_DESCRIPTION("ASoC WM8776 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/codecs/wm8776.h b/trunk/sound/soc/codecs/wm8776.h deleted file mode 100644 index 6606d25d2d83..000000000000 --- a/trunk/sound/soc/codecs/wm8776.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * wm8776.h -- WM8776 ASoC driver - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8776_H -#define _WM8776_H - -/* Registers */ - -#define WM8776_HPLVOL 0x00 -#define WM8776_HPRVOL 0x01 -#define WM8776_HPMASTER 0x02 -#define WM8776_DACLVOL 0x03 -#define WM8776_DACRVOL 0x04 -#define WM8776_DACMASTER 0x05 -#define WM8776_PHASESWAP 0x06 -#define WM8776_DACCTRL1 0x07 -#define WM8776_DACMUTE 0x08 -#define WM8776_DACCTRL2 0x09 -#define WM8776_DACIFCTRL 0x0a -#define WM8776_ADCIFCTRL 0x0b -#define WM8776_MSTRCTRL 0x0c -#define WM8776_PWRDOWN 0x0d -#define WM8776_ADCLVOL 0x0e -#define WM8776_ADCRVOL 0x0f -#define WM8776_ALCCTRL1 0x10 -#define WM8776_ALCCTRL2 0x11 -#define WM8776_ALCCTRL3 0x12 -#define WM8776_NOISEGATE 0x13 -#define WM8776_LIMITER 0x14 -#define WM8776_ADCMUX 0x15 -#define WM8776_OUTMUX 0x16 -#define WM8776_RESET 0x17 - -#define WM8776_CACHEREGNUM 0x17 - -#define WM8776_DAI_DAC 0 -#define WM8776_DAI_ADC 1 - -extern struct snd_soc_dai wm8776_dai[]; -extern struct snd_soc_codec_device soc_codec_dev_wm8776; - -#endif diff --git a/trunk/sound/soc/codecs/wm8960.c b/trunk/sound/soc/codecs/wm8960.c index d1769e6c0c44..c529ffcfe5d8 100644 --- a/trunk/sound/soc/codecs/wm8960.c +++ b/trunk/sound/soc/codecs/wm8960.c @@ -69,61 +69,7 @@ struct wm8960_priv { struct snd_soc_codec codec; }; -/* - * read wm8960 register cache - */ -static inline unsigned int wm8960_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - if (reg == WM8960_RESET) - return 0; - if (reg >= WM8960_CACHEREGNUM) - return -1; - return cache[reg]; -} - -/* - * write wm8960 register cache - */ -static inline void wm8960_write_reg_cache(struct snd_soc_codec *codec, - u16 reg, unsigned int value) -{ - u16 *cache = codec->reg_cache; - if (reg >= WM8960_CACHEREGNUM) - return; - cache[reg] = value; -} - -static inline unsigned int wm8960_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - return wm8960_read_reg_cache(codec, reg); -} - -/* - * write to the WM8960 register space - */ -static int wm8960_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 data[2]; - - /* data is - * D15..D9 WM8960 register offset - * D8...D0 register data - */ - data[0] = (reg << 1) | ((value >> 8) & 0x0001); - data[1] = value & 0x00ff; - - wm8960_write_reg_cache(codec, reg, value); - if (codec->hw_write(codec->control_data, data, 2) == 2) - return 0; - else - return -EIO; -} - -#define wm8960_reset(c) wm8960_write(c, WM8960_RESET, 0) +#define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0) /* enumerated controls */ static const char *wm8960_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; @@ -420,7 +366,7 @@ static int wm8960_set_dai_fmt(struct snd_soc_dai *codec_dai, } /* set iface */ - wm8960_write(codec, WM8960_IFACE1, iface); + snd_soc_write(codec, WM8960_IFACE1, iface); return 0; } @@ -431,7 +377,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; - u16 iface = wm8960_read(codec, WM8960_IFACE1) & 0xfff3; + u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; /* bit size */ switch (params_format(params)) { @@ -446,19 +392,19 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, } /* set iface */ - wm8960_write(codec, WM8960_IFACE1, iface); + snd_soc_write(codec, WM8960_IFACE1, iface); return 0; } static int wm8960_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = wm8960_read(codec, WM8960_DACCTL1) & 0xfff7; + u16 mute_reg = snd_soc_read(codec, WM8960_DACCTL1) & 0xfff7; if (mute) - wm8960_write(codec, WM8960_DACCTL1, mute_reg | 0x8); + snd_soc_write(codec, WM8960_DACCTL1, mute_reg | 0x8); else - wm8960_write(codec, WM8960_DACCTL1, mute_reg); + snd_soc_write(codec, WM8960_DACCTL1, mute_reg); return 0; } @@ -474,16 +420,16 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_PREPARE: /* Set VMID to 2x50k */ - reg = wm8960_read(codec, WM8960_POWER1); + reg = snd_soc_read(codec, WM8960_POWER1); reg &= ~0x180; reg |= 0x80; - wm8960_write(codec, WM8960_POWER1, reg); + snd_soc_write(codec, WM8960_POWER1, reg); break; case SND_SOC_BIAS_STANDBY: if (codec->bias_level == SND_SOC_BIAS_OFF) { /* Enable anti-pop features */ - wm8960_write(codec, WM8960_APOP1, + snd_soc_write(codec, WM8960_APOP1, WM8960_POBCTRL | WM8960_SOFT_ST | WM8960_BUFDCOPEN | WM8960_BUFIOEN); @@ -491,43 +437,43 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec, reg = WM8960_DISOP; if (pdata) reg |= pdata->dres << 4; - wm8960_write(codec, WM8960_APOP2, reg); + snd_soc_write(codec, WM8960_APOP2, reg); msleep(400); - wm8960_write(codec, WM8960_APOP2, 0); + snd_soc_write(codec, WM8960_APOP2, 0); /* Enable & ramp VMID at 2x50k */ - reg = wm8960_read(codec, WM8960_POWER1); + reg = snd_soc_read(codec, WM8960_POWER1); reg |= 0x80; - wm8960_write(codec, WM8960_POWER1, reg); + snd_soc_write(codec, WM8960_POWER1, reg); msleep(100); /* Enable VREF */ - wm8960_write(codec, WM8960_POWER1, reg | WM8960_VREF); + snd_soc_write(codec, WM8960_POWER1, reg | WM8960_VREF); /* Disable anti-pop features */ - wm8960_write(codec, WM8960_APOP1, WM8960_BUFIOEN); + snd_soc_write(codec, WM8960_APOP1, WM8960_BUFIOEN); } /* Set VMID to 2x250k */ - reg = wm8960_read(codec, WM8960_POWER1); + reg = snd_soc_read(codec, WM8960_POWER1); reg &= ~0x180; reg |= 0x100; - wm8960_write(codec, WM8960_POWER1, reg); + snd_soc_write(codec, WM8960_POWER1, reg); break; case SND_SOC_BIAS_OFF: /* Enable anti-pop features */ - wm8960_write(codec, WM8960_APOP1, + snd_soc_write(codec, WM8960_APOP1, WM8960_POBCTRL | WM8960_SOFT_ST | WM8960_BUFDCOPEN | WM8960_BUFIOEN); /* Disable VMID and VREF, let them discharge */ - wm8960_write(codec, WM8960_POWER1, 0); + snd_soc_write(codec, WM8960_POWER1, 0); msleep(600); - wm8960_write(codec, WM8960_APOP1, 0); + snd_soc_write(codec, WM8960_APOP1, 0); break; } @@ -610,33 +556,33 @@ static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, /* Disable the PLL: even if we are changing the frequency the * PLL needs to be disabled while we do so. */ - wm8960_write(codec, WM8960_CLOCK1, - wm8960_read(codec, WM8960_CLOCK1) & ~1); - wm8960_write(codec, WM8960_POWER2, - wm8960_read(codec, WM8960_POWER2) & ~1); + snd_soc_write(codec, WM8960_CLOCK1, + snd_soc_read(codec, WM8960_CLOCK1) & ~1); + snd_soc_write(codec, WM8960_POWER2, + snd_soc_read(codec, WM8960_POWER2) & ~1); if (!freq_in || !freq_out) return 0; - reg = wm8960_read(codec, WM8960_PLL1) & ~0x3f; + reg = snd_soc_read(codec, WM8960_PLL1) & ~0x3f; reg |= pll_div.pre_div << 4; reg |= pll_div.n; if (pll_div.k) { reg |= 0x20; - wm8960_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f); - wm8960_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff); - wm8960_write(codec, WM8960_PLL4, pll_div.k & 0x1ff); + snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f); + snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff); + snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0x1ff); } - wm8960_write(codec, WM8960_PLL1, reg); + snd_soc_write(codec, WM8960_PLL1, reg); /* Turn it on */ - wm8960_write(codec, WM8960_POWER2, - wm8960_read(codec, WM8960_POWER2) | 1); + snd_soc_write(codec, WM8960_POWER2, + snd_soc_read(codec, WM8960_POWER2) | 1); msleep(250); - wm8960_write(codec, WM8960_CLOCK1, - wm8960_read(codec, WM8960_CLOCK1) | 1); + snd_soc_write(codec, WM8960_CLOCK1, + snd_soc_read(codec, WM8960_CLOCK1) | 1); return 0; } @@ -649,28 +595,28 @@ static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8960_SYSCLKSEL: - reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1fe; - wm8960_write(codec, WM8960_CLOCK1, reg | div); + reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1fe; + snd_soc_write(codec, WM8960_CLOCK1, reg | div); break; case WM8960_SYSCLKDIV: - reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1f9; - wm8960_write(codec, WM8960_CLOCK1, reg | div); + reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1f9; + snd_soc_write(codec, WM8960_CLOCK1, reg | div); break; case WM8960_DACDIV: - reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1c7; - wm8960_write(codec, WM8960_CLOCK1, reg | div); + reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1c7; + snd_soc_write(codec, WM8960_CLOCK1, reg | div); break; case WM8960_OPCLKDIV: - reg = wm8960_read(codec, WM8960_PLL1) & 0x03f; - wm8960_write(codec, WM8960_PLL1, reg | div); + reg = snd_soc_read(codec, WM8960_PLL1) & 0x03f; + snd_soc_write(codec, WM8960_PLL1, reg | div); break; case WM8960_DCLKDIV: - reg = wm8960_read(codec, WM8960_CLOCK2) & 0x03f; - wm8960_write(codec, WM8960_CLOCK2, reg | div); + reg = snd_soc_read(codec, WM8960_CLOCK2) & 0x03f; + snd_soc_write(codec, WM8960_CLOCK2, reg | div); break; case WM8960_TOCLKSEL: - reg = wm8960_read(codec, WM8960_ADDCTL1) & 0x1fd; - wm8960_write(codec, WM8960_ADDCTL1, reg | div); + reg = snd_soc_read(codec, WM8960_ADDCTL1) & 0x1fd; + snd_soc_write(codec, WM8960_ADDCTL1, reg | div); break; default: return -EINVAL; @@ -830,8 +776,6 @@ static int wm8960_register(struct wm8960_priv *wm8960) codec->private_data = wm8960; codec->name = "WM8960"; codec->owner = THIS_MODULE; - codec->read = wm8960_read_reg_cache; - codec->write = wm8960_write; codec->bias_level = SND_SOC_BIAS_OFF; codec->set_bias_level = wm8960_set_bias_level; codec->dai = &wm8960_dai; @@ -841,6 +785,12 @@ static int wm8960_register(struct wm8960_priv *wm8960) memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg)); + ret = snd_soc_codec_set_cache_io(codec, 7, 9); + if (ret < 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + goto err; + } + ret = wm8960_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); @@ -852,26 +802,26 @@ static int wm8960_register(struct wm8960_priv *wm8960) wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Latch the update bits */ - reg = wm8960_read(codec, WM8960_LINVOL); - wm8960_write(codec, WM8960_LINVOL, reg | 0x100); - reg = wm8960_read(codec, WM8960_RINVOL); - wm8960_write(codec, WM8960_RINVOL, reg | 0x100); - reg = wm8960_read(codec, WM8960_LADC); - wm8960_write(codec, WM8960_LADC, reg | 0x100); - reg = wm8960_read(codec, WM8960_RADC); - wm8960_write(codec, WM8960_RADC, reg | 0x100); - reg = wm8960_read(codec, WM8960_LDAC); - wm8960_write(codec, WM8960_LDAC, reg | 0x100); - reg = wm8960_read(codec, WM8960_RDAC); - wm8960_write(codec, WM8960_RDAC, reg | 0x100); - reg = wm8960_read(codec, WM8960_LOUT1); - wm8960_write(codec, WM8960_LOUT1, reg | 0x100); - reg = wm8960_read(codec, WM8960_ROUT1); - wm8960_write(codec, WM8960_ROUT1, reg | 0x100); - reg = wm8960_read(codec, WM8960_LOUT2); - wm8960_write(codec, WM8960_LOUT2, reg | 0x100); - reg = wm8960_read(codec, WM8960_ROUT2); - wm8960_write(codec, WM8960_ROUT2, reg | 0x100); + reg = snd_soc_read(codec, WM8960_LINVOL); + snd_soc_write(codec, WM8960_LINVOL, reg | 0x100); + reg = snd_soc_read(codec, WM8960_RINVOL); + snd_soc_write(codec, WM8960_RINVOL, reg | 0x100); + reg = snd_soc_read(codec, WM8960_LADC); + snd_soc_write(codec, WM8960_LADC, reg | 0x100); + reg = snd_soc_read(codec, WM8960_RADC); + snd_soc_write(codec, WM8960_RADC, reg | 0x100); + reg = snd_soc_read(codec, WM8960_LDAC); + snd_soc_write(codec, WM8960_LDAC, reg | 0x100); + reg = snd_soc_read(codec, WM8960_RDAC); + snd_soc_write(codec, WM8960_RDAC, reg | 0x100); + reg = snd_soc_read(codec, WM8960_LOUT1); + snd_soc_write(codec, WM8960_LOUT1, reg | 0x100); + reg = snd_soc_read(codec, WM8960_ROUT1); + snd_soc_write(codec, WM8960_ROUT1, reg | 0x100); + reg = snd_soc_read(codec, WM8960_LOUT2); + snd_soc_write(codec, WM8960_LOUT2, reg | 0x100); + reg = snd_soc_read(codec, WM8960_ROUT2); + snd_soc_write(codec, WM8960_ROUT2, reg | 0x100); wm8960_codec = codec; diff --git a/trunk/sound/soc/codecs/wm8971.c b/trunk/sound/soc/codecs/wm8971.c index 032dca22dbd3..53f3bc90ea0c 100644 --- a/trunk/sound/soc/codecs/wm8971.c +++ b/trunk/sound/soc/codecs/wm8971.c @@ -59,44 +59,7 @@ static const u16 wm8971_reg[] = { 0x0079, 0x0079, 0x0079, /* 40 */ }; -static inline unsigned int wm8971_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - if (reg < WM8971_REG_COUNT) - return cache[reg]; - - return -1; -} - -static inline void wm8971_write_reg_cache(struct snd_soc_codec *codec, - unsigned int reg, unsigned int value) -{ - u16 *cache = codec->reg_cache; - if (reg < WM8971_REG_COUNT) - cache[reg] = value; -} - -static int wm8971_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 data[2]; - - /* data is - * D15..D9 WM8753 register offset - * D8...D0 register data - */ - data[0] = (reg << 1) | ((value >> 8) & 0x0001); - data[1] = value & 0x00ff; - - wm8971_write_reg_cache (codec, reg, value); - if (codec->hw_write(codec->control_data, data, 2) == 2) - return 0; - else - return -EIO; -} - -#define wm8971_reset(c) wm8971_write(c, WM8971_RESET, 0) +#define wm8971_reset(c) snd_soc_write(c, WM8971_RESET, 0) /* WM8971 Controls */ static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" }; @@ -521,7 +484,7 @@ static int wm8971_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - wm8971_write(codec, WM8971_IFACE, iface); + snd_soc_write(codec, WM8971_IFACE, iface); return 0; } @@ -533,8 +496,8 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; struct wm8971_priv *wm8971 = codec->private_data; - u16 iface = wm8971_read_reg_cache(codec, WM8971_IFACE) & 0x1f3; - u16 srate = wm8971_read_reg_cache(codec, WM8971_SRATE) & 0x1c0; + u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3; + u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0; int coeff = get_coeff(wm8971->sysclk, params_rate(params)); /* bit size */ @@ -553,9 +516,9 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, } /* set iface & srate */ - wm8971_write(codec, WM8971_IFACE, iface); + snd_soc_write(codec, WM8971_IFACE, iface); if (coeff >= 0) - wm8971_write(codec, WM8971_SRATE, srate | + snd_soc_write(codec, WM8971_SRATE, srate | (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); return 0; @@ -564,33 +527,33 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, static int wm8971_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = wm8971_read_reg_cache(codec, WM8971_ADCDAC) & 0xfff7; + u16 mute_reg = snd_soc_read(codec, WM8971_ADCDAC) & 0xfff7; if (mute) - wm8971_write(codec, WM8971_ADCDAC, mute_reg | 0x8); + snd_soc_write(codec, WM8971_ADCDAC, mute_reg | 0x8); else - wm8971_write(codec, WM8971_ADCDAC, mute_reg); + snd_soc_write(codec, WM8971_ADCDAC, mute_reg); return 0; } static int wm8971_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 pwr_reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; + u16 pwr_reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; switch (level) { case SND_SOC_BIAS_ON: /* set vmid to 50k and unmute dac */ - wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x00c1); + snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x00c1); break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: /* mute dac and set vmid to 500k, enable VREF */ - wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x0140); + snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140); break; case SND_SOC_BIAS_OFF: - wm8971_write(codec, WM8971_PWR1, 0x0001); + snd_soc_write(codec, WM8971_PWR1, 0x0001); break; } codec->bias_level = level; @@ -667,8 +630,8 @@ static int wm8971_resume(struct platform_device *pdev) /* charge wm8971 caps */ if (codec->suspend_bias_level == SND_SOC_BIAS_ON) { - reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; - wm8971_write(codec, WM8971_PWR1, reg | 0x01c0); + reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; + snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0); codec->bias_level = SND_SOC_BIAS_ON; queue_delayed_work(wm8971_workq, &codec->delayed_work, msecs_to_jiffies(1000)); @@ -684,8 +647,6 @@ static int wm8971_init(struct snd_soc_device *socdev) codec->name = "WM8971"; codec->owner = THIS_MODULE; - codec->read = wm8971_read_reg_cache; - codec->write = wm8971_write; codec->set_bias_level = wm8971_set_bias_level; codec->dai = &wm8971_dai; codec->reg_cache_size = ARRAY_SIZE(wm8971_reg); @@ -695,42 +656,48 @@ static int wm8971_init(struct snd_soc_device *socdev) if (codec->reg_cache == NULL) return -ENOMEM; + ret = snd_soc_codec_set_cache_io(codec, 7, 9); + if (ret < 0) { + printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); + goto err; + } + wm8971_reset(codec); /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { printk(KERN_ERR "wm8971: failed to create pcms\n"); - goto pcm_err; + goto err; } /* charge output caps - set vmid to 5k for quick power up */ - reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; - wm8971_write(codec, WM8971_PWR1, reg | 0x01c0); + reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; + snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0); codec->bias_level = SND_SOC_BIAS_STANDBY; queue_delayed_work(wm8971_workq, &codec->delayed_work, msecs_to_jiffies(1000)); /* set the update bits */ - reg = wm8971_read_reg_cache(codec, WM8971_LDAC); - wm8971_write(codec, WM8971_LDAC, reg | 0x0100); - reg = wm8971_read_reg_cache(codec, WM8971_RDAC); - wm8971_write(codec, WM8971_RDAC, reg | 0x0100); - - reg = wm8971_read_reg_cache(codec, WM8971_LOUT1V); - wm8971_write(codec, WM8971_LOUT1V, reg | 0x0100); - reg = wm8971_read_reg_cache(codec, WM8971_ROUT1V); - wm8971_write(codec, WM8971_ROUT1V, reg | 0x0100); - - reg = wm8971_read_reg_cache(codec, WM8971_LOUT2V); - wm8971_write(codec, WM8971_LOUT2V, reg | 0x0100); - reg = wm8971_read_reg_cache(codec, WM8971_ROUT2V); - wm8971_write(codec, WM8971_ROUT2V, reg | 0x0100); - - reg = wm8971_read_reg_cache(codec, WM8971_LINVOL); - wm8971_write(codec, WM8971_LINVOL, reg | 0x0100); - reg = wm8971_read_reg_cache(codec, WM8971_RINVOL); - wm8971_write(codec, WM8971_RINVOL, reg | 0x0100); + reg = snd_soc_read(codec, WM8971_LDAC); + snd_soc_write(codec, WM8971_LDAC, reg | 0x0100); + reg = snd_soc_read(codec, WM8971_RDAC); + snd_soc_write(codec, WM8971_RDAC, reg | 0x0100); + + reg = snd_soc_read(codec, WM8971_LOUT1V); + snd_soc_write(codec, WM8971_LOUT1V, reg | 0x0100); + reg = snd_soc_read(codec, WM8971_ROUT1V); + snd_soc_write(codec, WM8971_ROUT1V, reg | 0x0100); + + reg = snd_soc_read(codec, WM8971_LOUT2V); + snd_soc_write(codec, WM8971_LOUT2V, reg | 0x0100); + reg = snd_soc_read(codec, WM8971_ROUT2V); + snd_soc_write(codec, WM8971_ROUT2V, reg | 0x0100); + + reg = snd_soc_read(codec, WM8971_LINVOL); + snd_soc_write(codec, WM8971_LINVOL, reg | 0x0100); + reg = snd_soc_read(codec, WM8971_RINVOL); + snd_soc_write(codec, WM8971_RINVOL, reg | 0x0100); snd_soc_add_controls(codec, wm8971_snd_controls, ARRAY_SIZE(wm8971_snd_controls)); @@ -745,7 +712,7 @@ static int wm8971_init(struct snd_soc_device *socdev) card_err: snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); -pcm_err: +err: kfree(codec->reg_cache); return ret; } diff --git a/trunk/sound/soc/codecs/wm8988.c b/trunk/sound/soc/codecs/wm8988.c index 6f15acd10489..7d5b807bdb48 100644 --- a/trunk/sound/soc/codecs/wm8988.c +++ b/trunk/sound/soc/codecs/wm8988.c @@ -57,50 +57,7 @@ struct wm8988_priv { }; -/* - * read wm8988 register cache - */ -static inline unsigned int wm8988_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - if (reg > WM8988_NUM_REG) - return -1; - return cache[reg]; -} - -/* - * write wm8988 register cache - */ -static inline void wm8988_write_reg_cache(struct snd_soc_codec *codec, - unsigned int reg, unsigned int value) -{ - u16 *cache = codec->reg_cache; - if (reg > WM8988_NUM_REG) - return; - cache[reg] = value; -} - -static int wm8988_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 data[2]; - - /* data is - * D15..D9 WM8753 register offset - * D8...D0 register data - */ - data[0] = (reg << 1) | ((value >> 8) & 0x0001); - data[1] = value & 0x00ff; - - wm8988_write_reg_cache(codec, reg, value); - if (codec->hw_write(codec->control_data, data, 2) == 2) - return 0; - else - return -EIO; -} - -#define wm8988_reset(c) wm8988_write(c, WM8988_RESET, 0) +#define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0) /* * WM8988 Controls @@ -226,15 +183,15 @@ static int wm8988_lrc_control(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; - u16 adctl2 = wm8988_read_reg_cache(codec, WM8988_ADCTL2); + u16 adctl2 = snd_soc_read(codec, WM8988_ADCTL2); /* Use the DAC to gate LRC if active, otherwise use ADC */ - if (wm8988_read_reg_cache(codec, WM8988_PWR2) & 0x180) + if (snd_soc_read(codec, WM8988_PWR2) & 0x180) adctl2 &= ~0x4; else adctl2 |= 0x4; - return wm8988_write(codec, WM8988_ADCTL2, adctl2); + return snd_soc_write(codec, WM8988_ADCTL2, adctl2); } static const char *wm8988_line_texts[] = { @@ -619,7 +576,7 @@ static int wm8988_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - wm8988_write(codec, WM8988_IFACE, iface); + snd_soc_write(codec, WM8988_IFACE, iface); return 0; } @@ -653,8 +610,8 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; struct wm8988_priv *wm8988 = codec->private_data; - u16 iface = wm8988_read_reg_cache(codec, WM8988_IFACE) & 0x1f3; - u16 srate = wm8988_read_reg_cache(codec, WM8988_SRATE) & 0x180; + u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3; + u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180; int coeff; coeff = get_coeff(wm8988->sysclk, params_rate(params)); @@ -685,9 +642,9 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, } /* set iface & srate */ - wm8988_write(codec, WM8988_IFACE, iface); + snd_soc_write(codec, WM8988_IFACE, iface); if (coeff >= 0) - wm8988_write(codec, WM8988_SRATE, srate | + snd_soc_write(codec, WM8988_SRATE, srate | (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); return 0; @@ -696,19 +653,19 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, static int wm8988_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = wm8988_read_reg_cache(codec, WM8988_ADCDAC) & 0xfff7; + u16 mute_reg = snd_soc_read(codec, WM8988_ADCDAC) & 0xfff7; if (mute) - wm8988_write(codec, WM8988_ADCDAC, mute_reg | 0x8); + snd_soc_write(codec, WM8988_ADCDAC, mute_reg | 0x8); else - wm8988_write(codec, WM8988_ADCDAC, mute_reg); + snd_soc_write(codec, WM8988_ADCDAC, mute_reg); return 0; } static int wm8988_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 pwr_reg = wm8988_read_reg_cache(codec, WM8988_PWR1) & ~0x1c1; + u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1; switch (level) { case SND_SOC_BIAS_ON: @@ -716,24 +673,24 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_PREPARE: /* VREF, VMID=2x50k, digital enabled */ - wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x00c0); + snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x00c0); break; case SND_SOC_BIAS_STANDBY: if (codec->bias_level == SND_SOC_BIAS_OFF) { /* VREF, VMID=2x5k */ - wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x1c1); + snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1); /* Charge caps */ msleep(100); } /* VREF, VMID=2*500k, digital stopped */ - wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x0141); + snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x0141); break; case SND_SOC_BIAS_OFF: - wm8988_write(codec, WM8988_PWR1, 0x0000); + snd_soc_write(codec, WM8988_PWR1, 0x0000); break; } codec->bias_level = level; @@ -887,8 +844,6 @@ static int wm8988_register(struct wm8988_priv *wm8988) codec->private_data = wm8988; codec->name = "WM8988"; codec->owner = THIS_MODULE; - codec->read = wm8988_read_reg_cache; - codec->write = wm8988_write; codec->dai = &wm8988_dai; codec->num_dai = 1; codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache); @@ -899,6 +854,12 @@ static int wm8988_register(struct wm8988_priv *wm8988) memcpy(codec->reg_cache, wm8988_reg, sizeof(wm8988_reg)); + ret = snd_soc_codec_set_cache_io(codec, 7, 9); + if (ret < 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + goto err; + } + ret = wm8988_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); @@ -906,16 +867,16 @@ static int wm8988_register(struct wm8988_priv *wm8988) } /* set the update bits (we always update left then right) */ - reg = wm8988_read_reg_cache(codec, WM8988_RADC); - wm8988_write(codec, WM8988_RADC, reg | 0x100); - reg = wm8988_read_reg_cache(codec, WM8988_RDAC); - wm8988_write(codec, WM8988_RDAC, reg | 0x0100); - reg = wm8988_read_reg_cache(codec, WM8988_ROUT1V); - wm8988_write(codec, WM8988_ROUT1V, reg | 0x0100); - reg = wm8988_read_reg_cache(codec, WM8988_ROUT2V); - wm8988_write(codec, WM8988_ROUT2V, reg | 0x0100); - reg = wm8988_read_reg_cache(codec, WM8988_RINVOL); - wm8988_write(codec, WM8988_RINVOL, reg | 0x0100); + reg = snd_soc_read(codec, WM8988_RADC); + snd_soc_write(codec, WM8988_RADC, reg | 0x100); + reg = snd_soc_read(codec, WM8988_RDAC); + snd_soc_write(codec, WM8988_RDAC, reg | 0x0100); + reg = snd_soc_read(codec, WM8988_ROUT1V); + snd_soc_write(codec, WM8988_ROUT1V, reg | 0x0100); + reg = snd_soc_read(codec, WM8988_ROUT2V); + snd_soc_write(codec, WM8988_ROUT2V, reg | 0x0100); + reg = snd_soc_read(codec, WM8988_RINVOL); + snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100); wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY); diff --git a/trunk/sound/soc/codecs/wm8993.c b/trunk/sound/soc/codecs/wm8993.c deleted file mode 100644 index e246ca079897..000000000000 --- a/trunk/sound/soc/codecs/wm8993.c +++ /dev/null @@ -1,2206 +0,0 @@ -/* - * wm8993.c -- WM8993 ALSA SoC audio driver - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8993.h" - -static u16 wm8993_reg_defaults[WM8993_REGISTER_COUNT] = { - 0x8993, /* R0 - Software Reset */ - 0x0000, /* R1 - Power Management (1) */ - 0x6000, /* R2 - Power Management (2) */ - 0x0000, /* R3 - Power Management (3) */ - 0x4050, /* R4 - Audio Interface (1) */ - 0x4000, /* R5 - Audio Interface (2) */ - 0x01C8, /* R6 - Clocking 1 */ - 0x0000, /* R7 - Clocking 2 */ - 0x0000, /* R8 - Audio Interface (3) */ - 0x0040, /* R9 - Audio Interface (4) */ - 0x0004, /* R10 - DAC CTRL */ - 0x00C0, /* R11 - Left DAC Digital Volume */ - 0x00C0, /* R12 - Right DAC Digital Volume */ - 0x0000, /* R13 - Digital Side Tone */ - 0x0300, /* R14 - ADC CTRL */ - 0x00C0, /* R15 - Left ADC Digital Volume */ - 0x00C0, /* R16 - Right ADC Digital Volume */ - 0x0000, /* R17 */ - 0x0000, /* R18 - GPIO CTRL 1 */ - 0x0010, /* R19 - GPIO1 */ - 0x0000, /* R20 - IRQ_DEBOUNCE */ - 0x0000, /* R21 */ - 0x8000, /* R22 - GPIOCTRL 2 */ - 0x0800, /* R23 - GPIO_POL */ - 0x008B, /* R24 - Left Line Input 1&2 Volume */ - 0x008B, /* R25 - Left Line Input 3&4 Volume */ - 0x008B, /* R26 - Right Line Input 1&2 Volume */ - 0x008B, /* R27 - Right Line Input 3&4 Volume */ - 0x006D, /* R28 - Left Output Volume */ - 0x006D, /* R29 - Right Output Volume */ - 0x0066, /* R30 - Line Outputs Volume */ - 0x0020, /* R31 - HPOUT2 Volume */ - 0x0079, /* R32 - Left OPGA Volume */ - 0x0079, /* R33 - Right OPGA Volume */ - 0x0003, /* R34 - SPKMIXL Attenuation */ - 0x0003, /* R35 - SPKMIXR Attenuation */ - 0x0011, /* R36 - SPKOUT Mixers */ - 0x0100, /* R37 - SPKOUT Boost */ - 0x0079, /* R38 - Speaker Volume Left */ - 0x0079, /* R39 - Speaker Volume Right */ - 0x0000, /* R40 - Input Mixer2 */ - 0x0000, /* R41 - Input Mixer3 */ - 0x0000, /* R42 - Input Mixer4 */ - 0x0000, /* R43 - Input Mixer5 */ - 0x0000, /* R44 - Input Mixer6 */ - 0x0000, /* R45 - Output Mixer1 */ - 0x0000, /* R46 - Output Mixer2 */ - 0x0000, /* R47 - Output Mixer3 */ - 0x0000, /* R48 - Output Mixer4 */ - 0x0000, /* R49 - Output Mixer5 */ - 0x0000, /* R50 - Output Mixer6 */ - 0x0000, /* R51 - HPOUT2 Mixer */ - 0x0000, /* R52 - Line Mixer1 */ - 0x0000, /* R53 - Line Mixer2 */ - 0x0000, /* R54 - Speaker Mixer */ - 0x0000, /* R55 - Additional Control */ - 0x0000, /* R56 - AntiPOP1 */ - 0x0000, /* R57 - AntiPOP2 */ - 0x0000, /* R58 - MICBIAS */ - 0x0000, /* R59 */ - 0x0000, /* R60 - FLL Control 1 */ - 0x0000, /* R61 - FLL Control 2 */ - 0x0000, /* R62 - FLL Control 3 */ - 0x2EE0, /* R63 - FLL Control 4 */ - 0x0002, /* R64 - FLL Control 5 */ - 0x2287, /* R65 - Clocking 3 */ - 0x025F, /* R66 - Clocking 4 */ - 0x0000, /* R67 - MW Slave Control */ - 0x0000, /* R68 */ - 0x0002, /* R69 - Bus Control 1 */ - 0x0000, /* R70 - Write Sequencer 0 */ - 0x0000, /* R71 - Write Sequencer 1 */ - 0x0000, /* R72 - Write Sequencer 2 */ - 0x0000, /* R73 - Write Sequencer 3 */ - 0x0000, /* R74 - Write Sequencer 4 */ - 0x0000, /* R75 - Write Sequencer 5 */ - 0x1F25, /* R76 - Charge Pump 1 */ - 0x0000, /* R77 */ - 0x0000, /* R78 */ - 0x0000, /* R79 */ - 0x0000, /* R80 */ - 0x0000, /* R81 - Class W 0 */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 - DC Servo 0 */ - 0x054A, /* R85 - DC Servo 1 */ - 0x0000, /* R86 */ - 0x0000, /* R87 - DC Servo 3 */ - 0x0000, /* R88 - DC Servo Readback 0 */ - 0x0000, /* R89 - DC Servo Readback 1 */ - 0x0000, /* R90 - DC Servo Readback 2 */ - 0x0000, /* R91 */ - 0x0000, /* R92 */ - 0x0000, /* R93 */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0100, /* R96 - Analogue HP 0 */ - 0x0000, /* R97 */ - 0x0000, /* R98 - EQ1 */ - 0x000C, /* R99 - EQ2 */ - 0x000C, /* R100 - EQ3 */ - 0x000C, /* R101 - EQ4 */ - 0x000C, /* R102 - EQ5 */ - 0x000C, /* R103 - EQ6 */ - 0x0FCA, /* R104 - EQ7 */ - 0x0400, /* R105 - EQ8 */ - 0x00D8, /* R106 - EQ9 */ - 0x1EB5, /* R107 - EQ10 */ - 0xF145, /* R108 - EQ11 */ - 0x0B75, /* R109 - EQ12 */ - 0x01C5, /* R110 - EQ13 */ - 0x1C58, /* R111 - EQ14 */ - 0xF373, /* R112 - EQ15 */ - 0x0A54, /* R113 - EQ16 */ - 0x0558, /* R114 - EQ17 */ - 0x168E, /* R115 - EQ18 */ - 0xF829, /* R116 - EQ19 */ - 0x07AD, /* R117 - EQ20 */ - 0x1103, /* R118 - EQ21 */ - 0x0564, /* R119 - EQ22 */ - 0x0559, /* R120 - EQ23 */ - 0x4000, /* R121 - EQ24 */ - 0x0000, /* R122 - Digital Pulls */ - 0x0F08, /* R123 - DRC Control 1 */ - 0x0000, /* R124 - DRC Control 2 */ - 0x0080, /* R125 - DRC Control 3 */ - 0x0000, /* R126 - DRC Control 4 */ -}; - -static struct { - int ratio; - int clk_sys_rate; -} clk_sys_rates[] = { - { 64, 0 }, - { 128, 1 }, - { 192, 2 }, - { 256, 3 }, - { 384, 4 }, - { 512, 5 }, - { 768, 6 }, - { 1024, 7 }, - { 1408, 8 }, - { 1536, 9 }, -}; - -static struct { - int rate; - int sample_rate; -} sample_rates[] = { - { 8000, 0 }, - { 11025, 1 }, - { 12000, 1 }, - { 16000, 2 }, - { 22050, 3 }, - { 24000, 3 }, - { 32000, 4 }, - { 44100, 5 }, - { 48000, 5 }, -}; - -static struct { - int div; /* *10 due to .5s */ - int bclk_div; -} bclk_divs[] = { - { 10, 0 }, - { 15, 1 }, - { 20, 2 }, - { 30, 3 }, - { 40, 4 }, - { 55, 5 }, - { 60, 6 }, - { 80, 7 }, - { 110, 8 }, - { 120, 9 }, - { 160, 10 }, - { 220, 11 }, - { 240, 12 }, - { 320, 13 }, - { 440, 14 }, - { 480, 15 }, -}; - -struct wm8993_priv { - u16 reg_cache[WM8993_REGISTER_COUNT]; - struct wm8993_platform_data pdata; - struct snd_soc_codec codec; - int master; - int sysclk_source; - unsigned int mclk_rate; - unsigned int sysclk_rate; - unsigned int fs; - unsigned int bclk; - int class_w_users; - unsigned int fll_fref; - unsigned int fll_fout; -}; - -static unsigned int wm8993_read_hw(struct snd_soc_codec *codec, u8 reg) -{ - struct i2c_msg xfer[2]; - u16 data; - int ret; - struct i2c_client *i2c = codec->control_data; - - /* Write register */ - xfer[0].addr = i2c->addr; - xfer[0].flags = 0; - xfer[0].len = 1; - xfer[0].buf = ® - - /* Read data */ - xfer[1].addr = i2c->addr; - xfer[1].flags = I2C_M_RD; - xfer[1].len = 2; - xfer[1].buf = (u8 *)&data; - - ret = i2c_transfer(i2c->adapter, xfer, 2); - if (ret != 2) { - dev_err(codec->dev, "Failed to read 0x%x: %d\n", reg, ret); - return 0; - } - - return (data >> 8) | ((data & 0xff) << 8); -} - -static int wm8993_volatile(unsigned int reg) -{ - switch (reg) { - case WM8993_SOFTWARE_RESET: - case WM8993_DC_SERVO_0: - case WM8993_DC_SERVO_READBACK_0: - case WM8993_DC_SERVO_READBACK_1: - case WM8993_DC_SERVO_READBACK_2: - return 1; - default: - return 0; - } -} - -static unsigned int wm8993_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *reg_cache = codec->reg_cache; - - BUG_ON(reg > WM8993_MAX_REGISTER); - - if (wm8993_volatile(reg)) - return wm8993_read_hw(codec, reg); - else - return reg_cache[reg]; -} - -static int wm8993_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u16 *reg_cache = codec->reg_cache; - u8 data[3]; - int ret; - - BUG_ON(reg > WM8993_MAX_REGISTER); - - /* data is - * D15..D9 WM8993 register offset - * D8...D0 register data - */ - data[0] = reg; - data[1] = value >> 8; - data[2] = value & 0x00ff; - - if (!wm8993_volatile(reg)) - reg_cache[reg] = value; - - ret = codec->hw_write(codec->control_data, data, 3); - - if (ret == 3) - return 0; - if (ret < 0) - return ret; - return -EIO; -} - -struct _fll_div { - u16 fll_fratio; - u16 fll_outdiv; - u16 fll_clk_ref_div; - u16 n; - u16 k; -}; - -/* The size in bits of the FLL divide multiplied by 10 - * to allow rounding later */ -#define FIXED_FLL_SIZE ((1 << 16) * 10) - -static struct { - unsigned int min; - unsigned int max; - u16 fll_fratio; - int ratio; -} fll_fratios[] = { - { 0, 64000, 4, 16 }, - { 64000, 128000, 3, 8 }, - { 128000, 256000, 2, 4 }, - { 256000, 1000000, 1, 2 }, - { 1000000, 13500000, 0, 1 }, -}; - -static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, - unsigned int Fout) -{ - u64 Kpart; - unsigned int K, Ndiv, Nmod, target; - unsigned int div; - int i; - - /* Fref must be <=13.5MHz */ - div = 1; - fll_div->fll_clk_ref_div = 0; - while ((Fref / div) > 13500000) { - div *= 2; - fll_div->fll_clk_ref_div++; - - if (div > 8) { - pr_err("Can't scale %dMHz input down to <=13.5MHz\n", - Fref); - return -EINVAL; - } - } - - pr_debug("Fref=%u Fout=%u\n", Fref, Fout); - - /* Apply the division for our remaining calculations */ - Fref /= div; - - /* Fvco should be 90-100MHz; don't check the upper bound */ - div = 0; - target = Fout * 2; - while (target < 90000000) { - div++; - target *= 2; - if (div > 7) { - pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n", - Fout); - return -EINVAL; - } - } - fll_div->fll_outdiv = div; - - pr_debug("Fvco=%dHz\n", target); - - /* Find an appropraite FLL_FRATIO and factor it out of the target */ - for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { - if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { - fll_div->fll_fratio = fll_fratios[i].fll_fratio; - target /= fll_fratios[i].ratio; - break; - } - } - if (i == ARRAY_SIZE(fll_fratios)) { - pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref); - return -EINVAL; - } - - /* Now, calculate N.K */ - Ndiv = target / Fref; - - fll_div->n = Ndiv; - Nmod = target % Fref; - pr_debug("Nmod=%d\n", Nmod); - - /* Calculate fractional part - scale up so we can round. */ - Kpart = FIXED_FLL_SIZE * (long long)Nmod; - - do_div(Kpart, Fref); - - K = Kpart & 0xFFFFFFFF; - - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - fll_div->k = K / 10; - - pr_debug("N=%x K=%x FLL_FRATIO=%x FLL_OUTDIV=%x FLL_CLK_REF_DIV=%x\n", - fll_div->n, fll_div->k, - fll_div->fll_fratio, fll_div->fll_outdiv, - fll_div->fll_clk_ref_div); - - return 0; -} - -static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, - unsigned int Fref, unsigned int Fout) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8993_priv *wm8993 = codec->private_data; - u16 reg1, reg4, reg5; - struct _fll_div fll_div; - int ret; - - /* Any change? */ - if (Fref == wm8993->fll_fref && Fout == wm8993->fll_fout) - return 0; - - /* Disable the FLL */ - if (Fout == 0) { - dev_dbg(codec->dev, "FLL disabled\n"); - wm8993->fll_fref = 0; - wm8993->fll_fout = 0; - - reg1 = wm8993_read(codec, WM8993_FLL_CONTROL_1); - reg1 &= ~WM8993_FLL_ENA; - wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1); - - return 0; - } - - ret = fll_factors(&fll_div, Fref, Fout); - if (ret != 0) - return ret; - - reg5 = wm8993_read(codec, WM8993_FLL_CONTROL_5); - reg5 &= ~WM8993_FLL_CLK_SRC_MASK; - - switch (fll_id) { - case WM8993_FLL_MCLK: - break; - - case WM8993_FLL_LRCLK: - reg5 |= 1; - break; - - case WM8993_FLL_BCLK: - reg5 |= 2; - break; - - default: - dev_err(codec->dev, "Unknown FLL ID %d\n", fll_id); - return -EINVAL; - } - - /* Any FLL configuration change requires that the FLL be - * disabled first. */ - reg1 = wm8993_read(codec, WM8993_FLL_CONTROL_1); - reg1 &= ~WM8993_FLL_ENA; - wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1); - - /* Apply the configuration */ - if (fll_div.k) - reg1 |= WM8993_FLL_FRAC_MASK; - else - reg1 &= ~WM8993_FLL_FRAC_MASK; - wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1); - - wm8993_write(codec, WM8993_FLL_CONTROL_2, - (fll_div.fll_outdiv << WM8993_FLL_OUTDIV_SHIFT) | - (fll_div.fll_fratio << WM8993_FLL_FRATIO_SHIFT)); - wm8993_write(codec, WM8993_FLL_CONTROL_3, fll_div.k); - - reg4 = wm8993_read(codec, WM8993_FLL_CONTROL_4); - reg4 &= ~WM8993_FLL_N_MASK; - reg4 |= fll_div.n << WM8993_FLL_N_SHIFT; - wm8993_write(codec, WM8993_FLL_CONTROL_4, reg4); - - reg5 &= ~WM8993_FLL_CLK_REF_DIV_MASK; - reg5 |= fll_div.fll_clk_ref_div << WM8993_FLL_CLK_REF_DIV_SHIFT; - wm8993_write(codec, WM8993_FLL_CONTROL_5, reg5); - - /* Enable the FLL */ - wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1 | WM8993_FLL_ENA); - - dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout); - - wm8993->fll_fref = Fref; - wm8993->fll_fout = Fout; - - return 0; -} - -static int configure_clock(struct snd_soc_codec *codec) -{ - struct wm8993_priv *wm8993 = codec->private_data; - unsigned int reg; - - /* This should be done on init() for bypass paths */ - switch (wm8993->sysclk_source) { - case WM8993_SYSCLK_MCLK: - dev_dbg(codec->dev, "Using %dHz MCLK\n", wm8993->mclk_rate); - - reg = wm8993_read(codec, WM8993_CLOCKING_2); - reg &= ~WM8993_SYSCLK_SRC; - if (wm8993->mclk_rate > 13500000) { - reg |= WM8993_MCLK_DIV; - wm8993->sysclk_rate = wm8993->mclk_rate / 2; - } else { - reg &= ~WM8993_MCLK_DIV; - wm8993->sysclk_rate = wm8993->mclk_rate; - } - reg &= ~WM8993_MCLK_DIV; - reg &= ~(WM8993_MCLK_DIV | WM8993_SYSCLK_SRC); - wm8993_write(codec, WM8993_CLOCKING_2, reg); - break; - - case WM8993_SYSCLK_FLL: - dev_dbg(codec->dev, "Using %dHz FLL clock\n", - wm8993->fll_fout); - - reg = wm8993_read(codec, WM8993_CLOCKING_2); - reg |= WM8993_SYSCLK_SRC; - if (wm8993->fll_fout > 13500000) { - reg |= WM8993_MCLK_DIV; - wm8993->sysclk_rate = wm8993->fll_fout / 2; - } else { - reg &= ~WM8993_MCLK_DIV; - wm8993->sysclk_rate = wm8993->fll_fout; - } - wm8993_write(codec, WM8993_CLOCKING_2, reg); - break; - - default: - dev_err(codec->dev, "System clock not configured\n"); - return -EINVAL; - } - - dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm8993->sysclk_rate); - - return 0; -} - -static void wait_for_dc_servo(struct snd_soc_codec *codec, int mask) -{ - unsigned int reg; - int count = 0; - - dev_dbg(codec->dev, "Waiting for DC servo...\n"); - do { - count++; - msleep(1); - reg = wm8993_read(codec, WM8993_DC_SERVO_READBACK_0); - dev_dbg(codec->dev, "DC servo status: %x\n", reg); - } while ((reg & WM8993_DCS_CAL_COMPLETE_MASK) - != WM8993_DCS_CAL_COMPLETE_MASK && count < 1000); - - if ((reg & WM8993_DCS_CAL_COMPLETE_MASK) - != WM8993_DCS_CAL_COMPLETE_MASK) - dev_err(codec->dev, "Timed out waiting for DC Servo\n"); -} - -static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1650, 150, 0); -static const DECLARE_TLV_DB_SCALE(inmix_sw_tlv, 0, 3000, 0); -static const DECLARE_TLV_DB_SCALE(inmix_tlv, -1500, 300, 1); -static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0); -static const DECLARE_TLV_DB_SCALE(drc_comp_threash, -4500, 75, 0); -static const DECLARE_TLV_DB_SCALE(drc_comp_amp, -2250, 75, 0); -static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0); -static const unsigned int drc_max_tlv[] = { - TLV_DB_RANGE_HEAD(4), - 0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0), - 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0), -}; -static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0); -static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -1800, 300, 0); -static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); -static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); -static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0); -static const DECLARE_TLV_DB_SCALE(earpiece_tlv, -600, 600, 0); -static const DECLARE_TLV_DB_SCALE(outmix_tlv, -2100, 300, 0); -static const DECLARE_TLV_DB_SCALE(spkmix_tlv, -300, 300, 0); -static const DECLARE_TLV_DB_SCALE(spkmixout_tlv, -1800, 600, 1); -static const DECLARE_TLV_DB_SCALE(outpga_tlv, -5700, 100, 0); -static const unsigned int spkboost_tlv[] = { - TLV_DB_RANGE_HEAD(7), - 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), - 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), -}; -static const DECLARE_TLV_DB_SCALE(line_tlv, -600, 600, 0); - -static const char *speaker_ref_text[] = { - "SPKVDD/2", - "VMID", -}; - -static const struct soc_enum speaker_ref = - SOC_ENUM_SINGLE(WM8993_SPEAKER_MIXER, 8, 2, speaker_ref_text); - -static const char *speaker_mode_text[] = { - "Class D", - "Class AB", -}; - -static const struct soc_enum speaker_mode = - SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text); - -static const char *dac_deemph_text[] = { - "None", - "32kHz", - "44.1kHz", - "48kHz", -}; - -static const struct soc_enum dac_deemph = - SOC_ENUM_SINGLE(WM8993_DAC_CTRL, 4, 4, dac_deemph_text); - -static const char *adc_hpf_text[] = { - "Hi-Fi", - "Voice 1", - "Voice 2", - "Voice 3", -}; - -static const struct soc_enum adc_hpf = - SOC_ENUM_SINGLE(WM8993_ADC_CTRL, 5, 4, adc_hpf_text); - -static const char *drc_path_text[] = { - "ADC", - "DAC" -}; - -static const struct soc_enum drc_path = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 14, 2, drc_path_text); - -static const char *drc_r0_text[] = { - "1", - "1/2", - "1/4", - "1/8", - "1/16", - "0", -}; - -static const struct soc_enum drc_r0 = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 8, 6, drc_r0_text); - -static const char *drc_r1_text[] = { - "1", - "1/2", - "1/4", - "1/8", - "0", -}; - -static const struct soc_enum drc_r1 = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_4, 13, 5, drc_r1_text); - -static const char *drc_attack_text[] = { - "Reserved", - "181us", - "363us", - "726us", - "1.45ms", - "2.9ms", - "5.8ms", - "11.6ms", - "23.2ms", - "46.4ms", - "92.8ms", - "185.6ms", -}; - -static const struct soc_enum drc_attack = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 12, 12, drc_attack_text); - -static const char *drc_decay_text[] = { - "186ms", - "372ms", - "743ms", - "1.49s", - "2.97ms", - "5.94ms", - "11.89ms", - "23.78ms", - "47.56ms", -}; - -static const struct soc_enum drc_decay = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 8, 9, drc_decay_text); - -static const char *drc_ff_text[] = { - "5 samples", - "9 samples", -}; - -static const struct soc_enum drc_ff = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 7, 2, drc_ff_text); - -static const char *drc_qr_rate_text[] = { - "0.725ms", - "1.45ms", - "5.8ms", -}; - -static const struct soc_enum drc_qr_rate = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 0, 3, drc_qr_rate_text); - -static const char *drc_smooth_text[] = { - "Low", - "Medium", - "High", -}; - -static const struct soc_enum drc_smooth = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 4, 3, drc_smooth_text); - - -/* - * Update the DC servo calibration on gain changes - */ -static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int ret; - - ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); - - /* Only need to do this if the outputs are active */ - if (wm8993_read(codec, WM8993_POWER_MANAGEMENT_1) - & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA)) - snd_soc_update_bits(codec, - WM8993_DC_SERVO_0, - WM8993_DCS_TRIG_SINGLE_0 | - WM8993_DCS_TRIG_SINGLE_1, - WM8993_DCS_TRIG_SINGLE_0 | - WM8993_DCS_TRIG_SINGLE_1); - - return ret; -} - -static const struct snd_kcontrol_new wm8993_snd_controls[] = { -SOC_SINGLE_TLV("IN1L Volume", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 0, 31, 0, - inpga_tlv), -SOC_SINGLE("IN1L Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 1), -SOC_SINGLE("IN1L ZC Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 0), - -SOC_SINGLE_TLV("IN1R Volume", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 0, 31, 0, - inpga_tlv), -SOC_SINGLE("IN1R Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 1), -SOC_SINGLE("IN1R ZC Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 0), - - -SOC_SINGLE_TLV("IN2L Volume", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 0, 31, 0, - inpga_tlv), -SOC_SINGLE("IN2L Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 1), -SOC_SINGLE("IN2L ZC Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 0), - -SOC_SINGLE_TLV("IN2R Volume", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 0, 31, 0, - inpga_tlv), -SOC_SINGLE("IN2R Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 1), -SOC_SINGLE("IN2R ZC Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 0), - -SOC_SINGLE_TLV("MIXINL IN2L Volume", WM8993_INPUT_MIXER3, 7, 1, 0, - inmix_sw_tlv), -SOC_SINGLE_TLV("MIXINL IN1L Volume", WM8993_INPUT_MIXER3, 4, 1, 0, - inmix_sw_tlv), -SOC_SINGLE_TLV("MIXINL Output Record Volume", WM8993_INPUT_MIXER3, 0, 7, 0, - inmix_tlv), -SOC_SINGLE_TLV("MIXINL IN1LP Volume", WM8993_INPUT_MIXER5, 6, 7, 0, inmix_tlv), -SOC_SINGLE_TLV("MIXINL Direct Voice Volume", WM8993_INPUT_MIXER5, 0, 6, 0, - inmix_tlv), - -SOC_SINGLE_TLV("MIXINR IN2R Volume", WM8993_INPUT_MIXER4, 7, 1, 0, - inmix_sw_tlv), -SOC_SINGLE_TLV("MIXINR IN1R Volume", WM8993_INPUT_MIXER4, 4, 1, 0, - inmix_sw_tlv), -SOC_SINGLE_TLV("MIXINR Output Record Volume", WM8993_INPUT_MIXER4, 0, 7, 0, - inmix_tlv), -SOC_SINGLE_TLV("MIXINR IN1RP Volume", WM8993_INPUT_MIXER6, 6, 7, 0, inmix_tlv), -SOC_SINGLE_TLV("MIXINR Direct Voice Volume", WM8993_INPUT_MIXER6, 0, 6, 0, - inmix_tlv), - -SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8993_DIGITAL_SIDE_TONE, - 5, 9, 12, 0, sidetone_tlv), - -SOC_SINGLE("DRC Switch", WM8993_DRC_CONTROL_1, 15, 1, 0), -SOC_ENUM("DRC Path", drc_path), -SOC_SINGLE_TLV("DRC Compressor Threashold Volume", WM8993_DRC_CONTROL_2, - 2, 60, 1, drc_comp_threash), -SOC_SINGLE_TLV("DRC Compressor Amplitude Volume", WM8993_DRC_CONTROL_3, - 11, 30, 1, drc_comp_amp), -SOC_ENUM("DRC R0", drc_r0), -SOC_ENUM("DRC R1", drc_r1), -SOC_SINGLE_TLV("DRC Minimum Volume", WM8993_DRC_CONTROL_1, 2, 3, 1, - drc_min_tlv), -SOC_SINGLE_TLV("DRC Maximum Volume", WM8993_DRC_CONTROL_1, 0, 3, 0, - drc_max_tlv), -SOC_ENUM("DRC Attack Rate", drc_attack), -SOC_ENUM("DRC Decay Rate", drc_decay), -SOC_ENUM("DRC FF Delay", drc_ff), -SOC_SINGLE("DRC Anti-clip Switch", WM8993_DRC_CONTROL_1, 9, 1, 0), -SOC_SINGLE("DRC Quick Release Switch", WM8993_DRC_CONTROL_1, 10, 1, 0), -SOC_SINGLE_TLV("DRC Quick Release Volume", WM8993_DRC_CONTROL_3, 2, 3, 0, - drc_qr_tlv), -SOC_ENUM("DRC Quick Release Rate", drc_qr_rate), -SOC_SINGLE("DRC Smoothing Switch", WM8993_DRC_CONTROL_1, 11, 1, 0), -SOC_SINGLE("DRC Smoothing Hysteresis Switch", WM8993_DRC_CONTROL_1, 8, 1, 0), -SOC_ENUM("DRC Smoothing Hysteresis Threashold", drc_smooth), -SOC_SINGLE_TLV("DRC Startup Volume", WM8993_DRC_CONTROL_4, 8, 18, 0, - drc_startup_tlv), - -SOC_SINGLE("EQ Switch", WM8993_EQ1, 0, 1, 0), - -SOC_DOUBLE_R_TLV("Capture Volume", WM8993_LEFT_ADC_DIGITAL_VOLUME, - WM8993_RIGHT_ADC_DIGITAL_VOLUME, 1, 96, 0, digital_tlv), -SOC_SINGLE("ADC High Pass Filter Switch", WM8993_ADC_CTRL, 8, 1, 0), -SOC_ENUM("ADC High Pass Filter Mode", adc_hpf), - -SOC_DOUBLE_R_TLV("Playback Volume", WM8993_LEFT_DAC_DIGITAL_VOLUME, - WM8993_RIGHT_DAC_DIGITAL_VOLUME, 1, 96, 0, digital_tlv), -SOC_SINGLE_TLV("Playback Boost Volume", WM8993_AUDIO_INTERFACE_2, 10, 3, 0, - dac_boost_tlv), -SOC_ENUM("DAC Deemphasis", dac_deemph), - -SOC_SINGLE_TLV("Left Output Mixer IN2RN Volume", WM8993_OUTPUT_MIXER5, 6, 7, 1, - outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer IN2LN Volume", WM8993_OUTPUT_MIXER3, 6, 7, 1, - outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer IN2LP Volume", WM8993_OUTPUT_MIXER3, 9, 7, 1, - outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer IN1L Volume", WM8993_OUTPUT_MIXER3, 0, 7, 1, - outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer IN1R Volume", WM8993_OUTPUT_MIXER3, 3, 7, 1, - outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer Right Input Volume", - WM8993_OUTPUT_MIXER5, 3, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer Left Input Volume", - WM8993_OUTPUT_MIXER5, 0, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer DAC Volume", WM8993_OUTPUT_MIXER5, 9, 7, 1, - outmix_tlv), - -SOC_SINGLE_TLV("Right Output Mixer IN2LN Volume", - WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer IN2RN Volume", - WM8993_OUTPUT_MIXER4, 6, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer IN1L Volume", - WM8993_OUTPUT_MIXER4, 3, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer IN1R Volume", - WM8993_OUTPUT_MIXER4, 0, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer IN2RP Volume", - WM8993_OUTPUT_MIXER4, 9, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer Left Input Volume", - WM8993_OUTPUT_MIXER6, 3, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer Right Input Volume", - WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer DAC Volume", - WM8993_OUTPUT_MIXER6, 9, 7, 1, outmix_tlv), - -SOC_DOUBLE_R_TLV("Output Volume", WM8993_LEFT_OPGA_VOLUME, - WM8993_RIGHT_OPGA_VOLUME, 0, 63, 0, outpga_tlv), -SOC_DOUBLE_R("Output Switch", WM8993_LEFT_OPGA_VOLUME, - WM8993_RIGHT_OPGA_VOLUME, 6, 1, 0), -SOC_DOUBLE_R("Output ZC Switch", WM8993_LEFT_OPGA_VOLUME, - WM8993_RIGHT_OPGA_VOLUME, 7, 1, 0), - -SOC_SINGLE("Earpiece Switch", WM8993_HPOUT2_VOLUME, 5, 1, 1), -SOC_SINGLE_TLV("Earpiece Volume", WM8993_HPOUT2_VOLUME, 4, 1, 1, earpiece_tlv), - -SOC_SINGLE_TLV("SPKL Input Volume", WM8993_SPKMIXL_ATTENUATION, - 5, 1, 1, spkmix_tlv), -SOC_SINGLE_TLV("SPKL IN1LP Volume", WM8993_SPKMIXL_ATTENUATION, - 4, 1, 1, spkmix_tlv), -SOC_SINGLE_TLV("SPKL Output Volume", WM8993_SPKMIXL_ATTENUATION, - 3, 1, 1, spkmix_tlv), -SOC_SINGLE_TLV("SPKL DAC Volume", WM8993_SPKMIXL_ATTENUATION, - 2, 1, 1, spkmix_tlv), - -SOC_SINGLE_TLV("SPKR Input Volume", WM8993_SPKMIXR_ATTENUATION, - 5, 1, 1, spkmix_tlv), -SOC_SINGLE_TLV("SPKR IN1RP Volume", WM8993_SPKMIXR_ATTENUATION, - 4, 1, 1, spkmix_tlv), -SOC_SINGLE_TLV("SPKR Output Volume", WM8993_SPKMIXR_ATTENUATION, - 3, 1, 1, spkmix_tlv), -SOC_SINGLE_TLV("SPKR DAC Volume", WM8993_SPKMIXR_ATTENUATION, - 2, 1, 1, spkmix_tlv), - -SOC_DOUBLE_R_TLV("Speaker Mixer Volume", - WM8993_SPKMIXL_ATTENUATION, WM8993_SPKMIXR_ATTENUATION, - 0, 3, 1, spkmixout_tlv), -SOC_DOUBLE_R_TLV("Speaker Volume", - WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT, - 0, 63, 0, outpga_tlv), -SOC_DOUBLE_R("Speaker Switch", - WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT, - 6, 1, 0), -SOC_DOUBLE_R("Speaker ZC Switch", - WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT, - 7, 1, 0), -SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 0, 3, 7, 0, - spkboost_tlv), -SOC_ENUM("Speaker Reference", speaker_ref), -SOC_ENUM("Speaker Mode", speaker_mode), - -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Headphone Volume", - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | - SNDRV_CTL_ELEM_ACCESS_READWRITE, - .tlv.p = outpga_tlv, - .info = snd_soc_info_volsw_2r, - .get = snd_soc_get_volsw_2r, .put = wm8993_put_dc_servo, - .private_value = (unsigned long)&(struct soc_mixer_control) { - .reg = WM8993_LEFT_OUTPUT_VOLUME, - .rreg = WM8993_RIGHT_OUTPUT_VOLUME, - .shift = 0, .max = 63 - }, -}, -SOC_DOUBLE_R("Headphone Switch", WM8993_LEFT_OUTPUT_VOLUME, - WM8993_RIGHT_OUTPUT_VOLUME, 6, 1, 0), -SOC_DOUBLE_R("Headphone ZC Switch", WM8993_LEFT_OUTPUT_VOLUME, - WM8993_RIGHT_OUTPUT_VOLUME, 7, 1, 0), - -SOC_SINGLE("LINEOUT1N Switch", WM8993_LINE_OUTPUTS_VOLUME, 6, 1, 1), -SOC_SINGLE("LINEOUT1P Switch", WM8993_LINE_OUTPUTS_VOLUME, 5, 1, 1), -SOC_SINGLE_TLV("LINEOUT1 Volume", WM8993_LINE_OUTPUTS_VOLUME, 4, 1, 1, - line_tlv), - -SOC_SINGLE("LINEOUT2N Switch", WM8993_LINE_OUTPUTS_VOLUME, 2, 1, 1), -SOC_SINGLE("LINEOUT2P Switch", WM8993_LINE_OUTPUTS_VOLUME, 1, 1, 1), -SOC_SINGLE_TLV("LINEOUT2 Volume", WM8993_LINE_OUTPUTS_VOLUME, 0, 1, 1, - line_tlv), -}; - -static const struct snd_kcontrol_new wm8993_eq_controls[] = { -SOC_SINGLE_TLV("EQ1 Volume", WM8993_EQ2, 0, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ2 Volume", WM8993_EQ3, 0, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ3 Volume", WM8993_EQ4, 0, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ4 Volume", WM8993_EQ5, 0, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ5 Volume", WM8993_EQ6, 0, 24, 0, eq_tlv), -}; - -static int wm8993_earpiece_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *control, int event) -{ - struct snd_soc_codec *codec = w->codec; - u16 reg = wm8993_read(codec, WM8993_ANTIPOP1) & ~WM8993_HPOUT2_IN_ENA; - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - reg |= WM8993_HPOUT2_IN_ENA; - wm8993_write(codec, WM8993_ANTIPOP1, reg); - udelay(50); - break; - - case SND_SOC_DAPM_POST_PMD: - wm8993_write(codec, WM8993_ANTIPOP1, reg); - break; - - default: - BUG(); - break; - } - - return 0; -} - -static int clk_sys_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - return configure_clock(codec); - - case SND_SOC_DAPM_POST_PMD: - break; - } - - return 0; -} - -/* - * When used with DAC outputs only the WM8993 charge pump supports - * operation in class W mode, providing very low power consumption - * when used with digital sources. Enable and disable this mode - * automatically depending on the mixer configuration. - * - * Currently the only supported paths are the direct DAC->headphone - * paths (which provide minimum power consumption anyway). - */ -static int wm8993_class_w_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); - struct snd_soc_codec *codec = widget->codec; - struct wm8993_priv *wm8993 = codec->private_data; - int ret; - - /* Turn it off if we're using the main output mixer */ - if (ucontrol->value.integer.value[0] == 0) { - if (wm8993->class_w_users == 0) { - dev_dbg(codec->dev, "Disabling Class W\n"); - snd_soc_update_bits(codec, WM8993_CLASS_W_0, - WM8993_CP_DYN_FREQ | - WM8993_CP_DYN_V, - 0); - } - wm8993->class_w_users++; - } - - /* Implement the change */ - ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol); - - /* Enable it if we're using the direct DAC path */ - if (ucontrol->value.integer.value[0] == 1) { - if (wm8993->class_w_users == 1) { - dev_dbg(codec->dev, "Enabling Class W\n"); - snd_soc_update_bits(codec, WM8993_CLASS_W_0, - WM8993_CP_DYN_FREQ | - WM8993_CP_DYN_V, - WM8993_CP_DYN_FREQ | - WM8993_CP_DYN_V); - } - wm8993->class_w_users--; - } - - dev_dbg(codec->dev, "Indirect DAC use count now %d\n", - wm8993->class_w_users); - - return ret; -} - -#define SOC_DAPM_ENUM_W(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_enum_double, \ - .get = snd_soc_dapm_get_enum_double, \ - .put = wm8993_class_w_put, \ - .private_value = (unsigned long)&xenum } - -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 reg = wm8993_read(codec, WM8993_ANALOGUE_HP_0); - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1, - WM8993_CP_ENA, WM8993_CP_ENA); - - msleep(5); - - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA, - WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA); - - reg |= WM8993_HPOUT1L_DLY | WM8993_HPOUT1R_DLY; - wm8993_write(codec, WM8993_ANALOGUE_HP_0, reg); - - /* Start the DC servo */ - snd_soc_update_bits(codec, WM8993_DC_SERVO_0, - WM8993_DCS_ENA_CHAN_0 | - WM8993_DCS_ENA_CHAN_1 | - WM8993_DCS_TRIG_STARTUP_1 | - WM8993_DCS_TRIG_STARTUP_0, - WM8993_DCS_ENA_CHAN_0 | - WM8993_DCS_ENA_CHAN_1 | - WM8993_DCS_TRIG_STARTUP_1 | - WM8993_DCS_TRIG_STARTUP_0); - wait_for_dc_servo(codec, WM8993_DCS_TRIG_STARTUP_0 | - WM8993_DCS_TRIG_STARTUP_1); - snd_soc_update_bits(codec, WM8993_DC_SERVO_1, - WM8993_DCS_TIMER_PERIOD_01_MASK, 0xa); - - reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | - WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; - wm8993_write(codec, WM8993_ANALOGUE_HP_0, reg); - break; - - case SND_SOC_DAPM_PRE_PMD: - reg &= ~(WM8993_HPOUT1L_RMV_SHORT | - WM8993_HPOUT1L_DLY | - WM8993_HPOUT1L_OUTP | - WM8993_HPOUT1R_RMV_SHORT | - WM8993_HPOUT1R_DLY | - WM8993_HPOUT1R_OUTP); - - snd_soc_update_bits(codec, WM8993_DC_SERVO_1, - WM8993_DCS_TIMER_PERIOD_01_MASK, 0); - snd_soc_update_bits(codec, WM8993_DC_SERVO_0, - WM8993_DCS_ENA_CHAN_0 | - WM8993_DCS_ENA_CHAN_1, 0); - - wm8993_write(codec, WM8993_ANALOGUE_HP_0, reg); - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA, - 0); - - snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1, - WM8993_CP_ENA, 0); - break; - } - - return 0; -} - -static const struct snd_kcontrol_new in1l_pga[] = { -SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0), -SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0), -}; - -static const struct snd_kcontrol_new in1r_pga[] = { -SOC_DAPM_SINGLE("IN1RP Switch", WM8993_INPUT_MIXER2, 1, 1, 0), -SOC_DAPM_SINGLE("IN1RN Switch", WM8993_INPUT_MIXER2, 0, 1, 0), -}; - -static const struct snd_kcontrol_new in2l_pga[] = { -SOC_DAPM_SINGLE("IN2LP Switch", WM8993_INPUT_MIXER2, 7, 1, 0), -SOC_DAPM_SINGLE("IN2LN Switch", WM8993_INPUT_MIXER2, 6, 1, 0), -}; - -static const struct snd_kcontrol_new in2r_pga[] = { -SOC_DAPM_SINGLE("IN2RP Switch", WM8993_INPUT_MIXER2, 3, 1, 0), -SOC_DAPM_SINGLE("IN2RN Switch", WM8993_INPUT_MIXER2, 2, 1, 0), -}; - -static const struct snd_kcontrol_new mixinl[] = { -SOC_DAPM_SINGLE("IN2L Switch", WM8993_INPUT_MIXER3, 8, 1, 0), -SOC_DAPM_SINGLE("IN1L Switch", WM8993_INPUT_MIXER3, 5, 1, 0), -}; - -static const struct snd_kcontrol_new mixinr[] = { -SOC_DAPM_SINGLE("IN2R Switch", WM8993_INPUT_MIXER4, 8, 1, 0), -SOC_DAPM_SINGLE("IN1R Switch", WM8993_INPUT_MIXER4, 5, 1, 0), -}; - -static const struct snd_kcontrol_new left_output_mixer[] = { -SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER1, 7, 1, 0), -SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER1, 6, 1, 0), -SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER1, 5, 1, 0), -SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER1, 4, 1, 0), -SOC_DAPM_SINGLE("IN2LP Switch", WM8993_OUTPUT_MIXER1, 1, 1, 0), -SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER1, 3, 1, 0), -SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER1, 2, 1, 0), -SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER1, 0, 1, 0), -}; - -static const struct snd_kcontrol_new right_output_mixer[] = { -SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER2, 7, 1, 0), -SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER2, 6, 1, 0), -SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER2, 5, 1, 0), -SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER2, 4, 1, 0), -SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER2, 3, 1, 0), -SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER2, 2, 1, 0), -SOC_DAPM_SINGLE("IN2RP Switch", WM8993_OUTPUT_MIXER2, 1, 1, 0), -SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER2, 0, 1, 0), -}; - -static const struct snd_kcontrol_new earpiece_mixer[] = { -SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_HPOUT2_MIXER, 5, 1, 0), -SOC_DAPM_SINGLE("Left Output Switch", WM8993_HPOUT2_MIXER, 4, 1, 0), -SOC_DAPM_SINGLE("Right Output Switch", WM8993_HPOUT2_MIXER, 3, 1, 0), -}; - -static const struct snd_kcontrol_new left_speaker_mixer[] = { -SOC_DAPM_SINGLE("Input Switch", WM8993_SPEAKER_MIXER, 7, 1, 0), -SOC_DAPM_SINGLE("IN1LP Switch", WM8993_SPEAKER_MIXER, 5, 1, 0), -SOC_DAPM_SINGLE("Output Switch", WM8993_SPEAKER_MIXER, 3, 1, 0), -SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 6, 1, 0), -}; - -static const struct snd_kcontrol_new right_speaker_mixer[] = { -SOC_DAPM_SINGLE("Input Switch", WM8993_SPEAKER_MIXER, 6, 1, 0), -SOC_DAPM_SINGLE("IN1RP Switch", WM8993_SPEAKER_MIXER, 4, 1, 0), -SOC_DAPM_SINGLE("Output Switch", WM8993_SPEAKER_MIXER, 2, 1, 0), -SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 0, 1, 0), -}; - -static const struct snd_kcontrol_new left_speaker_boost[] = { -SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 5, 1, 0), -SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 4, 1, 0), -SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 3, 1, 0), -}; - -static const struct snd_kcontrol_new right_speaker_boost[] = { -SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 2, 1, 0), -SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 1, 1, 0), -SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 0, 1, 0), -}; - -static const char *hp_mux_text[] = { - "Mixer", - "DAC", -}; - -static const struct soc_enum hpl_enum = - SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER1, 8, 2, hp_mux_text); - -static const struct snd_kcontrol_new hpl_mux = - SOC_DAPM_ENUM_W("Left Headphone Mux", hpl_enum); - -static const struct soc_enum hpr_enum = - SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER2, 8, 2, hp_mux_text); - -static const struct snd_kcontrol_new hpr_mux = - SOC_DAPM_ENUM_W("Right Headphone Mux", hpr_enum); - -static const struct snd_kcontrol_new line1_mix[] = { -SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER1, 2, 1, 0), -SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER1, 1, 1, 0), -SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER1, 0, 1, 0), -}; - -static const struct snd_kcontrol_new line1n_mix[] = { -SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 6, 1, 0), -SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER1, 5, 1, 0), -}; - -static const struct snd_kcontrol_new line1p_mix[] = { -SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0), -}; - -static const struct snd_kcontrol_new line2_mix[] = { -SOC_DAPM_SINGLE("IN2R Switch", WM8993_LINE_MIXER2, 2, 1, 0), -SOC_DAPM_SINGLE("IN2L Switch", WM8993_LINE_MIXER2, 1, 1, 0), -SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0), -}; - -static const struct snd_kcontrol_new line2n_mix[] = { -SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 6, 1, 0), -SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 5, 1, 0), -}; - -static const struct snd_kcontrol_new line2p_mix[] = { -SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 0, 1, 0), -}; - -static const struct snd_soc_dapm_widget wm8993_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("IN1LN"), -SND_SOC_DAPM_INPUT("IN1LP"), -SND_SOC_DAPM_INPUT("IN2LN"), -SND_SOC_DAPM_INPUT("IN2LP/VXRN"), -SND_SOC_DAPM_INPUT("IN1RN"), -SND_SOC_DAPM_INPUT("IN1RP"), -SND_SOC_DAPM_INPUT("IN2RN"), -SND_SOC_DAPM_INPUT("IN2RP/VXRP"), - -SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8993_BUS_CONTROL_1, 1, 0, clk_sys_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), -SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0), - -SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0), -SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0), - -SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0, - in1l_pga, ARRAY_SIZE(in1l_pga)), -SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0, - in1r_pga, ARRAY_SIZE(in1r_pga)), - -SND_SOC_DAPM_MIXER("IN2L PGA", WM8993_POWER_MANAGEMENT_2, 7, 0, - in2l_pga, ARRAY_SIZE(in2l_pga)), -SND_SOC_DAPM_MIXER("IN2R PGA", WM8993_POWER_MANAGEMENT_2, 5, 0, - in2r_pga, ARRAY_SIZE(in2r_pga)), - -/* Dummy widgets to represent differential paths */ -SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), - -SND_SOC_DAPM_MIXER("MIXINL", WM8993_POWER_MANAGEMENT_2, 9, 0, - mixinl, ARRAY_SIZE(mixinl)), -SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0, - mixinr, ARRAY_SIZE(mixinr)), - -SND_SOC_DAPM_ADC("ADCL", "Capture", WM8993_POWER_MANAGEMENT_2, 1, 0), -SND_SOC_DAPM_ADC("ADCR", "Capture", WM8993_POWER_MANAGEMENT_2, 0, 0), - -SND_SOC_DAPM_DAC("DACL", "Playback", WM8993_POWER_MANAGEMENT_3, 1, 0), -SND_SOC_DAPM_DAC("DACR", "Playback", WM8993_POWER_MANAGEMENT_3, 0, 0), - -SND_SOC_DAPM_MIXER("Left Output Mixer", WM8993_POWER_MANAGEMENT_3, 5, 0, - left_output_mixer, ARRAY_SIZE(left_output_mixer)), -SND_SOC_DAPM_MIXER("Right Output Mixer", WM8993_POWER_MANAGEMENT_3, 4, 0, - right_output_mixer, ARRAY_SIZE(right_output_mixer)), - -SND_SOC_DAPM_PGA("Left Output PGA", WM8993_POWER_MANAGEMENT_3, 7, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right Output PGA", WM8993_POWER_MANAGEMENT_3, 6, 0, NULL, 0), - -SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0, - earpiece_mixer, ARRAY_SIZE(earpiece_mixer)), -SND_SOC_DAPM_PGA_E("Earpiece Driver", WM8993_POWER_MANAGEMENT_1, 11, 0, - NULL, 0, wm8993_earpiece_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - -SND_SOC_DAPM_MIXER("SPKL", WM8993_POWER_MANAGEMENT_3, 8, 0, - left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), -SND_SOC_DAPM_MIXER("SPKR", WM8993_POWER_MANAGEMENT_3, 9, 0, - right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), - -SND_SOC_DAPM_MIXER("SPKL Boost", SND_SOC_NOPM, 0, 0, - left_speaker_boost, ARRAY_SIZE(left_speaker_boost)), -SND_SOC_DAPM_MIXER("SPKR Boost", SND_SOC_NOPM, 0, 0, - right_speaker_boost, ARRAY_SIZE(right_speaker_boost)), - -SND_SOC_DAPM_PGA("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0, - NULL, 0), -SND_SOC_DAPM_PGA("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0, - NULL, 0), - -SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), -SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), -SND_SOC_DAPM_PGA_E("Headphone PGA", SND_SOC_NOPM, 0, 0, - NULL, 0, - hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - -SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0, - line1_mix, ARRAY_SIZE(line1_mix)), -SND_SOC_DAPM_MIXER("LINEOUT2 Mixer", SND_SOC_NOPM, 0, 0, - line2_mix, ARRAY_SIZE(line2_mix)), - -SND_SOC_DAPM_MIXER("LINEOUT1N Mixer", SND_SOC_NOPM, 0, 0, - line1n_mix, ARRAY_SIZE(line1n_mix)), -SND_SOC_DAPM_MIXER("LINEOUT1P Mixer", SND_SOC_NOPM, 0, 0, - line1p_mix, ARRAY_SIZE(line1p_mix)), -SND_SOC_DAPM_MIXER("LINEOUT2N Mixer", SND_SOC_NOPM, 0, 0, - line2n_mix, ARRAY_SIZE(line2n_mix)), -SND_SOC_DAPM_MIXER("LINEOUT2P Mixer", SND_SOC_NOPM, 0, 0, - line2p_mix, ARRAY_SIZE(line2p_mix)), - -SND_SOC_DAPM_PGA("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0, - NULL, 0), -SND_SOC_DAPM_PGA("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0, - NULL, 0), -SND_SOC_DAPM_PGA("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0, - NULL, 0), -SND_SOC_DAPM_PGA("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0, - NULL, 0), - -SND_SOC_DAPM_OUTPUT("SPKOUTLP"), -SND_SOC_DAPM_OUTPUT("SPKOUTLN"), -SND_SOC_DAPM_OUTPUT("SPKOUTRP"), -SND_SOC_DAPM_OUTPUT("SPKOUTRN"), -SND_SOC_DAPM_OUTPUT("HPOUT1L"), -SND_SOC_DAPM_OUTPUT("HPOUT1R"), -SND_SOC_DAPM_OUTPUT("HPOUT2P"), -SND_SOC_DAPM_OUTPUT("HPOUT2N"), -SND_SOC_DAPM_OUTPUT("LINEOUT1P"), -SND_SOC_DAPM_OUTPUT("LINEOUT1N"), -SND_SOC_DAPM_OUTPUT("LINEOUT2P"), -SND_SOC_DAPM_OUTPUT("LINEOUT2N"), -}; - -static const struct snd_soc_dapm_route routes[] = { - { "IN1L PGA", "IN1LP Switch", "IN1LP" }, - { "IN1L PGA", "IN1LN Switch", "IN1LN" }, - - { "IN1R PGA", "IN1RP Switch", "IN1RP" }, - { "IN1R PGA", "IN1RN Switch", "IN1RN" }, - - { "IN2L PGA", "IN2LP Switch", "IN2LP/VXRN" }, - { "IN2L PGA", "IN2LN Switch", "IN2LN" }, - - { "IN2R PGA", "IN2RP Switch", "IN2RP/VXRP" }, - { "IN2R PGA", "IN2RN Switch", "IN2RN" }, - - { "Direct Voice", NULL, "IN2LP/VXRN" }, - { "Direct Voice", NULL, "IN2RP/VXRP" }, - - { "MIXINL", "IN1L Switch", "IN1L PGA" }, - { "MIXINL", "IN2L Switch", "IN2L PGA" }, - { "MIXINL", NULL, "Direct Voice" }, - { "MIXINL", NULL, "IN1LP" }, - { "MIXINL", NULL, "Left Output Mixer" }, - - { "MIXINR", "IN1R Switch", "IN1R PGA" }, - { "MIXINR", "IN2R Switch", "IN2R PGA" }, - { "MIXINR", NULL, "Direct Voice" }, - { "MIXINR", NULL, "IN1RP" }, - { "MIXINR", NULL, "Right Output Mixer" }, - - { "ADCL", NULL, "MIXINL" }, - { "ADCL", NULL, "CLK_SYS" }, - { "ADCL", NULL, "CLK_DSP" }, - { "ADCR", NULL, "MIXINR" }, - { "ADCR", NULL, "CLK_SYS" }, - { "ADCR", NULL, "CLK_DSP" }, - - { "DACL", NULL, "CLK_SYS" }, - { "DACL", NULL, "CLK_DSP" }, - { "DACR", NULL, "CLK_SYS" }, - { "DACR", NULL, "CLK_DSP" }, - - { "Left Output Mixer", "Left Input Switch", "MIXINL" }, - { "Left Output Mixer", "Right Input Switch", "MIXINR" }, - { "Left Output Mixer", "IN2RN Switch", "IN2RN" }, - { "Left Output Mixer", "IN2LN Switch", "IN2LN" }, - { "Left Output Mixer", "IN2LP Switch", "IN2LP/VXRN" }, - { "Left Output Mixer", "IN1L Switch", "IN1L PGA" }, - { "Left Output Mixer", "IN1R Switch", "IN1R PGA" }, - { "Left Output Mixer", "DAC Switch", "DACL" }, - - { "Right Output Mixer", "Left Input Switch", "MIXINL" }, - { "Right Output Mixer", "Right Input Switch", "MIXINR" }, - { "Right Output Mixer", "IN2LN Switch", "IN2LN" }, - { "Right Output Mixer", "IN2RN Switch", "IN2RN" }, - { "Right Output Mixer", "IN2RP Switch", "IN2RP/VXRP" }, - { "Right Output Mixer", "IN1L Switch", "IN1L PGA" }, - { "Right Output Mixer", "IN1R Switch", "IN1R PGA" }, - { "Right Output Mixer", "DAC Switch", "DACR" }, - - { "Left Output PGA", NULL, "Left Output Mixer" }, - { "Left Output PGA", NULL, "CLK_SYS" }, - { "Left Output PGA", NULL, "TOCLK" }, - - { "Right Output PGA", NULL, "Right Output Mixer" }, - { "Right Output PGA", NULL, "CLK_SYS" }, - { "Right Output PGA", NULL, "TOCLK" }, - - { "Earpiece Mixer", "Direct Voice Switch", "Direct Voice" }, - { "Earpiece Mixer", "Left Output Switch", "Left Output PGA" }, - { "Earpiece Mixer", "Right Output Switch", "Right Output PGA" }, - - { "Earpiece Driver", NULL, "Earpiece Mixer" }, - { "HPOUT2N", NULL, "Earpiece Driver" }, - { "HPOUT2P", NULL, "Earpiece Driver" }, - - { "SPKL", "Input Switch", "MIXINL" }, - { "SPKL", "IN1LP Switch", "IN1LP" }, - { "SPKL", "Output Switch", "Left Output Mixer" }, - { "SPKL", "DAC Switch", "DACL" }, - { "SPKL", NULL, "CLK_SYS" }, - { "SPKL", NULL, "TOCLK" }, - - { "SPKR", "Input Switch", "MIXINR" }, - { "SPKR", "IN1RP Switch", "IN1RP" }, - { "SPKR", "Output Switch", "Right Output Mixer" }, - { "SPKR", "DAC Switch", "DACR" }, - { "SPKR", NULL, "CLK_SYS" }, - { "SPKR", NULL, "TOCLK" }, - - { "SPKL Boost", "Direct Voice Switch", "Direct Voice" }, - { "SPKL Boost", "SPKL Switch", "SPKL" }, - { "SPKL Boost", "SPKR Switch", "SPKR" }, - - { "SPKR Boost", "Direct Voice Switch", "Direct Voice" }, - { "SPKR Boost", "SPKR Switch", "SPKR" }, - { "SPKR Boost", "SPKL Switch", "SPKL" }, - - { "SPKL Driver", NULL, "SPKL Boost" }, - { "SPKL Driver", NULL, "CLK_SYS" }, - - { "SPKR Driver", NULL, "SPKR Boost" }, - { "SPKR Driver", NULL, "CLK_SYS" }, - - { "SPKOUTLP", NULL, "SPKL Driver" }, - { "SPKOUTLN", NULL, "SPKL Driver" }, - { "SPKOUTRP", NULL, "SPKR Driver" }, - { "SPKOUTRN", NULL, "SPKR Driver" }, - - { "Left Headphone Mux", "DAC", "DACL" }, - { "Left Headphone Mux", "Mixer", "Left Output Mixer" }, - { "Right Headphone Mux", "DAC", "DACR" }, - { "Right Headphone Mux", "Mixer", "Right Output Mixer" }, - - { "Headphone PGA", NULL, "Left Headphone Mux" }, - { "Headphone PGA", NULL, "Right Headphone Mux" }, - { "Headphone PGA", NULL, "CLK_SYS" }, - { "Headphone PGA", NULL, "TOCLK" }, - - { "HPOUT1L", NULL, "Headphone PGA" }, - { "HPOUT1R", NULL, "Headphone PGA" }, - - { "LINEOUT1N", NULL, "LINEOUT1N Driver" }, - { "LINEOUT1P", NULL, "LINEOUT1P Driver" }, - { "LINEOUT2N", NULL, "LINEOUT2N Driver" }, - { "LINEOUT2P", NULL, "LINEOUT2P Driver" }, -}; - -static const struct snd_soc_dapm_route lineout1_diff_routes[] = { - { "LINEOUT1 Mixer", "IN1L Switch", "IN1L PGA" }, - { "LINEOUT1 Mixer", "IN1R Switch", "IN1R PGA" }, - { "LINEOUT1 Mixer", "Output Switch", "Left Output Mixer" }, - - { "LINEOUT1N Driver", NULL, "LINEOUT1 Mixer" }, - { "LINEOUT1P Driver", NULL, "LINEOUT1 Mixer" }, -}; - -static const struct snd_soc_dapm_route lineout1_se_routes[] = { - { "LINEOUT1N Mixer", "Left Output Switch", "Left Output Mixer" }, - { "LINEOUT1N Mixer", "Right Output Switch", "Left Output Mixer" }, - - { "LINEOUT1P Mixer", "Left Output Switch", "Left Output Mixer" }, - - { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" }, - { "LINEOUT1P Driver", NULL, "LINEOUT1P Mixer" }, -}; - -static const struct snd_soc_dapm_route lineout2_diff_routes[] = { - { "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" }, - { "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" }, - { "LINEOUT2 Mixer", "Output Switch", "Right Output Mixer" }, - - { "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" }, - { "LINEOUT2P Driver", NULL, "LINEOUT2 Mixer" }, -}; - -static const struct snd_soc_dapm_route lineout2_se_routes[] = { - { "LINEOUT2N Mixer", "Left Output Switch", "Left Output Mixer" }, - { "LINEOUT2N Mixer", "Right Output Switch", "Left Output Mixer" }, - - { "LINEOUT2P Mixer", "Right Output Switch", "Right Output Mixer" }, - - { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" }, - { "LINEOUT2P Driver", NULL, "LINEOUT2P Mixer" }, -}; - -static int wm8993_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8993_priv *wm8993 = codec->private_data; - - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - /* VMID=2*40k */ - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_VMID_SEL_MASK, 0x2); - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_2, - WM8993_TSHUT_ENA, WM8993_TSHUT_ENA); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->bias_level == SND_SOC_BIAS_OFF) { - /* Bring up VMID with fast soft start */ - snd_soc_update_bits(codec, WM8993_ANTIPOP2, - WM8993_STARTUP_BIAS_ENA | - WM8993_VMID_BUF_ENA | - WM8993_VMID_RAMP_MASK | - WM8993_BIAS_SRC, - WM8993_STARTUP_BIAS_ENA | - WM8993_VMID_BUF_ENA | - WM8993_VMID_RAMP_MASK | - WM8993_BIAS_SRC); - - /* If either line output is single ended we - * need the VMID buffer */ - if (!wm8993->pdata.lineout1_diff || - !wm8993->pdata.lineout2_diff) - snd_soc_update_bits(codec, WM8993_ANTIPOP1, - WM8993_LINEOUT_VMID_BUF_ENA, - WM8993_LINEOUT_VMID_BUF_ENA); - - /* VMID=2*40k */ - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_VMID_SEL_MASK | - WM8993_BIAS_ENA, - WM8993_BIAS_ENA | 0x2); - msleep(32); - - /* Switch to normal bias */ - snd_soc_update_bits(codec, WM8993_ANTIPOP2, - WM8993_BIAS_SRC | - WM8993_STARTUP_BIAS_ENA, 0); - } - - /* VMID=2*240k */ - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_VMID_SEL_MASK, 0x4); - - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_2, - WM8993_TSHUT_ENA, 0); - break; - - case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, WM8993_ANTIPOP1, - WM8993_LINEOUT_VMID_BUF_ENA, 0); - - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_VMID_SEL_MASK | WM8993_BIAS_ENA, - 0); - break; - } - - codec->bias_level = level; - - return 0; -} - -static int wm8993_set_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8993_priv *wm8993 = codec->private_data; - - switch (clk_id) { - case WM8993_SYSCLK_MCLK: - wm8993->mclk_rate = freq; - case WM8993_SYSCLK_FLL: - wm8993->sysclk_source = clk_id; - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int wm8993_set_dai_fmt(struct snd_soc_dai *dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8993_priv *wm8993 = codec->private_data; - unsigned int aif1 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_1); - unsigned int aif4 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_4); - - aif1 &= ~(WM8993_BCLK_DIR | WM8993_AIF_BCLK_INV | - WM8993_AIF_LRCLK_INV | WM8993_AIF_FMT_MASK); - aif4 &= ~WM8993_LRCLK_DIR; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - wm8993->master = 0; - break; - case SND_SOC_DAIFMT_CBS_CFM: - aif4 |= WM8993_LRCLK_DIR; - wm8993->master = 1; - break; - case SND_SOC_DAIFMT_CBM_CFS: - aif1 |= WM8993_BCLK_DIR; - wm8993->master = 1; - break; - case SND_SOC_DAIFMT_CBM_CFM: - aif1 |= WM8993_BCLK_DIR; - aif4 |= WM8993_LRCLK_DIR; - wm8993->master = 1; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_B: - aif1 |= WM8993_AIF_LRCLK_INV; - case SND_SOC_DAIFMT_DSP_A: - aif1 |= 0x18; - break; - case SND_SOC_DAIFMT_I2S: - aif1 |= 0x10; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - aif1 |= 0x8; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - /* frame inversion not valid for DSP modes */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - aif1 |= WM8993_AIF_BCLK_INV; - break; - default: - return -EINVAL; - } - break; - - case SND_SOC_DAIFMT_I2S: - case SND_SOC_DAIFMT_RIGHT_J: - case SND_SOC_DAIFMT_LEFT_J: - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - aif1 |= WM8993_AIF_BCLK_INV | WM8993_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_IB_NF: - aif1 |= WM8993_AIF_BCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: - aif1 |= WM8993_AIF_LRCLK_INV; - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - wm8993_write(codec, WM8993_AUDIO_INTERFACE_1, aif1); - wm8993_write(codec, WM8993_AUDIO_INTERFACE_4, aif4); - - return 0; -} - -static int wm8993_hw_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 wm8993_priv *wm8993 = codec->private_data; - int ret, i, best, best_val, cur_val; - unsigned int clocking1, clocking3, aif1, aif4; - - clocking1 = wm8993_read(codec, WM8993_CLOCKING_1); - clocking1 &= ~WM8993_BCLK_DIV_MASK; - - clocking3 = wm8993_read(codec, WM8993_CLOCKING_3); - clocking3 &= ~(WM8993_CLK_SYS_RATE_MASK | WM8993_SAMPLE_RATE_MASK); - - aif1 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_1); - aif1 &= ~WM8993_AIF_WL_MASK; - - aif4 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_4); - aif4 &= ~WM8993_LRCLK_RATE_MASK; - - /* What BCLK do we need? */ - wm8993->fs = params_rate(params); - wm8993->bclk = 2 * wm8993->fs; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - wm8993->bclk *= 16; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - wm8993->bclk *= 20; - aif1 |= 0x8; - break; - case SNDRV_PCM_FORMAT_S24_LE: - wm8993->bclk *= 24; - aif1 |= 0x10; - break; - case SNDRV_PCM_FORMAT_S32_LE: - wm8993->bclk *= 32; - aif1 |= 0x18; - break; - default: - return -EINVAL; - } - - dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm8993->bclk); - - ret = configure_clock(codec); - if (ret != 0) - return ret; - - /* Select nearest CLK_SYS_RATE */ - best = 0; - best_val = abs((wm8993->sysclk_rate / clk_sys_rates[0].ratio) - - wm8993->fs); - for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) { - cur_val = abs((wm8993->sysclk_rate / - clk_sys_rates[i].ratio) - wm8993->fs);; - if (cur_val < best_val) { - best = i; - best_val = cur_val; - } - } - dev_dbg(codec->dev, "Selected CLK_SYS_RATIO of %d\n", - clk_sys_rates[best].ratio); - clocking3 |= (clk_sys_rates[best].clk_sys_rate - << WM8993_CLK_SYS_RATE_SHIFT); - - /* SAMPLE_RATE */ - best = 0; - best_val = abs(wm8993->fs - sample_rates[0].rate); - for (i = 1; i < ARRAY_SIZE(sample_rates); i++) { - /* Closest match */ - cur_val = abs(wm8993->fs - sample_rates[i].rate); - if (cur_val < best_val) { - best = i; - best_val = cur_val; - } - } - dev_dbg(codec->dev, "Selected SAMPLE_RATE of %dHz\n", - sample_rates[best].rate); - clocking3 |= (sample_rates[best].sample_rate - << WM8993_SAMPLE_RATE_SHIFT); - - /* BCLK_DIV */ - best = 0; - best_val = INT_MAX; - for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { - cur_val = ((wm8993->sysclk_rate * 10) / bclk_divs[i].div) - - wm8993->bclk; - if (cur_val < 0) /* Table is sorted */ - break; - if (cur_val < best_val) { - best = i; - best_val = cur_val; - } - } - wm8993->bclk = (wm8993->sysclk_rate * 10) / bclk_divs[best].div; - dev_dbg(codec->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n", - bclk_divs[best].div, wm8993->bclk); - clocking1 |= bclk_divs[best].bclk_div << WM8993_BCLK_DIV_SHIFT; - - /* LRCLK is a simple fraction of BCLK */ - dev_dbg(codec->dev, "LRCLK_RATE is %d\n", wm8993->bclk / wm8993->fs); - aif4 |= wm8993->bclk / wm8993->fs; - - wm8993_write(codec, WM8993_CLOCKING_1, clocking1); - wm8993_write(codec, WM8993_CLOCKING_3, clocking3); - wm8993_write(codec, WM8993_AUDIO_INTERFACE_1, aif1); - wm8993_write(codec, WM8993_AUDIO_INTERFACE_4, aif4); - - /* ReTune Mobile? */ - if (wm8993->pdata.num_retune_configs) { - u16 eq1 = wm8993_read(codec, WM8993_EQ1); - struct wm8993_retune_mobile_setting *s; - - best = 0; - best_val = abs(wm8993->pdata.retune_configs[0].rate - - wm8993->fs); - for (i = 0; i < wm8993->pdata.num_retune_configs; i++) { - cur_val = abs(wm8993->pdata.retune_configs[i].rate - - wm8993->fs); - if (cur_val < best_val) { - best_val = cur_val; - best = i; - } - } - s = &wm8993->pdata.retune_configs[best]; - - dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n", - s->name, s->rate); - - /* Disable EQ while we reconfigure */ - snd_soc_update_bits(codec, WM8993_EQ1, WM8993_EQ_ENA, 0); - - for (i = 1; i < ARRAY_SIZE(s->config); i++) - wm8993_write(codec, WM8993_EQ1 + i, s->config[i]); - - snd_soc_update_bits(codec, WM8993_EQ1, WM8993_EQ_ENA, eq1); - } - - return 0; -} - -static int wm8993_digital_mute(struct snd_soc_dai *codec_dai, int mute) -{ - struct snd_soc_codec *codec = codec_dai->codec; - unsigned int reg; - - reg = wm8993_read(codec, WM8993_DAC_CTRL); - - if (mute) - reg |= WM8993_DAC_MUTE; - else - reg &= ~WM8993_DAC_MUTE; - - wm8993_write(codec, WM8993_DAC_CTRL, reg); - - return 0; -} - -static struct snd_soc_dai_ops wm8993_ops = { - .set_sysclk = wm8993_set_sysclk, - .set_fmt = wm8993_set_dai_fmt, - .hw_params = wm8993_hw_params, - .digital_mute = wm8993_digital_mute, - .set_pll = wm8993_set_fll, -}; - -#define WM8993_RATES SNDRV_PCM_RATE_8000_48000 - -#define WM8993_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ - SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE |\ - SNDRV_PCM_FMTBIT_S32_LE) - -struct snd_soc_dai wm8993_dai = { - .name = "WM8993", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8993_RATES, - .formats = WM8993_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8993_RATES, - .formats = WM8993_FORMATS, - }, - .ops = &wm8993_ops, - .symmetric_rates = 1, -}; -EXPORT_SYMBOL_GPL(wm8993_dai); - -static struct snd_soc_codec *wm8993_codec; - -static int wm8993_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - struct wm8993_priv *wm8993; - int ret = 0; - - if (!wm8993_codec) { - dev_err(&pdev->dev, "I2C device not yet probed\n"); - goto err; - } - - socdev->card->codec = wm8993_codec; - codec = wm8993_codec; - wm8993 = codec->private_data; - - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms\n"); - goto err; - } - - snd_soc_add_controls(codec, wm8993_snd_controls, - ARRAY_SIZE(wm8993_snd_controls)); - if (wm8993->pdata.num_retune_configs != 0) { - dev_dbg(codec->dev, "Using ReTune Mobile\n"); - } else { - dev_dbg(codec->dev, "No ReTune Mobile, using normal EQ\n"); - snd_soc_add_controls(codec, wm8993_eq_controls, - ARRAY_SIZE(wm8993_eq_controls)); - } - - snd_soc_dapm_new_controls(codec, wm8993_dapm_widgets, - ARRAY_SIZE(wm8993_dapm_widgets)); - - snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes)); - - if (wm8993->pdata.lineout1_diff) - snd_soc_dapm_add_routes(codec, - lineout1_diff_routes, - ARRAY_SIZE(lineout1_diff_routes)); - else - snd_soc_dapm_add_routes(codec, - lineout1_se_routes, - ARRAY_SIZE(lineout1_se_routes)); - - if (wm8993->pdata.lineout2_diff) - snd_soc_dapm_add_routes(codec, - lineout2_diff_routes, - ARRAY_SIZE(lineout2_diff_routes)); - else - snd_soc_dapm_add_routes(codec, - lineout2_se_routes, - ARRAY_SIZE(lineout2_se_routes)); - - snd_soc_dapm_new_widgets(codec); - - ret = snd_soc_init_card(socdev); - if (ret < 0) { - dev_err(codec->dev, "failed to register card\n"); - goto card_err; - } - - return ret; - -card_err: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -err: - return ret; -} - -static int wm8993_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8993 = { - .probe = wm8993_probe, - .remove = wm8993_remove, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8993); - -static int wm8993_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8993_priv *wm8993; - struct snd_soc_codec *codec; - unsigned int val; - int ret; - - if (wm8993_codec) { - dev_err(&i2c->dev, "A WM8993 is already registered\n"); - return -EINVAL; - } - - wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL); - if (wm8993 == NULL) - return -ENOMEM; - - codec = &wm8993->codec; - if (i2c->dev.platform_data) - memcpy(&wm8993->pdata, i2c->dev.platform_data, - sizeof(wm8993->pdata)); - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->name = "WM8993"; - codec->read = wm8993_read; - codec->write = wm8993_write; - codec->hw_write = (hw_write_t)i2c_master_send; - codec->reg_cache = wm8993->reg_cache; - codec->reg_cache_size = ARRAY_SIZE(wm8993->reg_cache); - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8993_set_bias_level; - codec->dai = &wm8993_dai; - codec->num_dai = 1; - codec->private_data = wm8993; - - memcpy(wm8993->reg_cache, wm8993_reg_defaults, - sizeof(wm8993->reg_cache)); - - i2c_set_clientdata(i2c, wm8993); - codec->control_data = i2c; - wm8993_codec = codec; - - codec->dev = &i2c->dev; - - val = wm8993_read_hw(codec, WM8993_SOFTWARE_RESET); - if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) { - dev_err(codec->dev, "Invalid ID register value %x\n", val); - ret = -EINVAL; - goto err; - } - - ret = wm8993_write(codec, WM8993_SOFTWARE_RESET, 0xffff); - if (ret != 0) - goto err; - - /* By default we're using the output mixers */ - wm8993->class_w_users = 2; - - /* Latch volume update bits and default ZC on */ - snd_soc_update_bits(codec, WM8993_LEFT_LINE_INPUT_1_2_VOLUME, - WM8993_IN1_VU, WM8993_IN1_VU); - snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, - WM8993_IN1_VU, WM8993_IN1_VU); - snd_soc_update_bits(codec, WM8993_LEFT_LINE_INPUT_3_4_VOLUME, - WM8993_IN2_VU, WM8993_IN2_VU); - snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, - WM8993_IN2_VU, WM8993_IN2_VU); - - snd_soc_update_bits(codec, WM8993_SPEAKER_VOLUME_RIGHT, - WM8993_SPKOUT_VU, WM8993_SPKOUT_VU); - - snd_soc_update_bits(codec, WM8993_LEFT_OUTPUT_VOLUME, - WM8993_HPOUT1L_ZC, WM8993_HPOUT1L_ZC); - snd_soc_update_bits(codec, WM8993_RIGHT_OUTPUT_VOLUME, - WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC, - WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC); - - snd_soc_update_bits(codec, WM8993_LEFT_OPGA_VOLUME, - WM8993_MIXOUTL_ZC, WM8993_MIXOUTL_ZC); - snd_soc_update_bits(codec, WM8993_RIGHT_OPGA_VOLUME, - WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU, - WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU); - - snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, - WM8993_DAC_VU, WM8993_DAC_VU); - snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME, - WM8993_ADC_VU, WM8993_ADC_VU); - - /* Manualy manage the HPOUT sequencing for independent stereo - * control. */ - snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, - WM8993_HPOUT1_AUTO_PU, 0); - - /* Use automatic clock configuration */ - snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0); - - if (!wm8993->pdata.lineout1_diff) - snd_soc_update_bits(codec, WM8993_LINE_MIXER1, - WM8993_LINEOUT1_MODE, - WM8993_LINEOUT1_MODE); - if (!wm8993->pdata.lineout2_diff) - snd_soc_update_bits(codec, WM8993_LINE_MIXER2, - WM8993_LINEOUT2_MODE, - WM8993_LINEOUT2_MODE); - - if (wm8993->pdata.lineout1fb) - snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL, - WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB); - - if (wm8993->pdata.lineout2fb) - snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL, - WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB); - - /* Apply the microphone bias/detection configuration - the - * platform data is directly applicable to the register. */ - snd_soc_update_bits(codec, WM8993_MICBIAS, - WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK | - WM8993_MICB1_LVL | WM8993_MICB2_LVL, - wm8993->pdata.jd_scthr << WM8993_JD_SCTHR_SHIFT | - wm8993->pdata.jd_thr << WM8993_JD_THR_SHIFT | - wm8993->pdata.micbias1_lvl | - wm8993->pdata.micbias1_lvl << 1); - - ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - if (ret != 0) - goto err; - - wm8993_dai.dev = codec->dev; - - ret = snd_soc_register_dai(&wm8993_dai); - if (ret != 0) - goto err_bias; - - ret = snd_soc_register_codec(codec); - - return 0; - -err_bias: - wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); -err: - wm8993_codec = NULL; - kfree(wm8993); - return ret; -} - -static int wm8993_i2c_remove(struct i2c_client *client) -{ - struct wm8993_priv *wm8993 = i2c_get_clientdata(client); - - snd_soc_unregister_codec(&wm8993->codec); - snd_soc_unregister_dai(&wm8993_dai); - - wm8993_set_bias_level(&wm8993->codec, SND_SOC_BIAS_OFF); - kfree(wm8993); - - return 0; -} - -static const struct i2c_device_id wm8993_i2c_id[] = { - { "wm8993", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id); - -static struct i2c_driver wm8993_i2c_driver = { - .driver = { - .name = "WM8993", - .owner = THIS_MODULE, - }, - .probe = wm8993_i2c_probe, - .remove = wm8993_i2c_remove, - .id_table = wm8993_i2c_id, -}; - - -static int __init wm8993_modinit(void) -{ - int ret; - - ret = i2c_add_driver(&wm8993_i2c_driver); - if (ret != 0) - pr_err("WM8993: Unable to register I2C driver: %d\n", ret); - - return ret; -} -module_init(wm8993_modinit); - -static void __exit wm8993_exit(void) -{ - i2c_del_driver(&wm8993_i2c_driver); -} -module_exit(wm8993_exit); - - -MODULE_DESCRIPTION("ASoC WM8993 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/codecs/wm8993.h b/trunk/sound/soc/codecs/wm8993.h deleted file mode 100644 index 30e71ca88dad..000000000000 --- a/trunk/sound/soc/codecs/wm8993.h +++ /dev/null @@ -1,2132 +0,0 @@ -#ifndef WM8993_H -#define WM8993_H - -extern struct snd_soc_dai wm8993_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8993; - -#define WM8993_SYSCLK_MCLK 1 -#define WM8993_SYSCLK_FLL 2 - -#define WM8993_FLL_MCLK 1 -#define WM8993_FLL_BCLK 2 -#define WM8993_FLL_LRCLK 3 - -/* - * Register values. - */ -#define WM8993_SOFTWARE_RESET 0x00 -#define WM8993_POWER_MANAGEMENT_1 0x01 -#define WM8993_POWER_MANAGEMENT_2 0x02 -#define WM8993_POWER_MANAGEMENT_3 0x03 -#define WM8993_AUDIO_INTERFACE_1 0x04 -#define WM8993_AUDIO_INTERFACE_2 0x05 -#define WM8993_CLOCKING_1 0x06 -#define WM8993_CLOCKING_2 0x07 -#define WM8993_AUDIO_INTERFACE_3 0x08 -#define WM8993_AUDIO_INTERFACE_4 0x09 -#define WM8993_DAC_CTRL 0x0A -#define WM8993_LEFT_DAC_DIGITAL_VOLUME 0x0B -#define WM8993_RIGHT_DAC_DIGITAL_VOLUME 0x0C -#define WM8993_DIGITAL_SIDE_TONE 0x0D -#define WM8993_ADC_CTRL 0x0E -#define WM8993_LEFT_ADC_DIGITAL_VOLUME 0x0F -#define WM8993_RIGHT_ADC_DIGITAL_VOLUME 0x10 -#define WM8993_GPIO_CTRL_1 0x12 -#define WM8993_GPIO1 0x13 -#define WM8993_IRQ_DEBOUNCE 0x14 -#define WM8993_GPIOCTRL_2 0x16 -#define WM8993_GPIO_POL 0x17 -#define WM8993_LEFT_LINE_INPUT_1_2_VOLUME 0x18 -#define WM8993_LEFT_LINE_INPUT_3_4_VOLUME 0x19 -#define WM8993_RIGHT_LINE_INPUT_1_2_VOLUME 0x1A -#define WM8993_RIGHT_LINE_INPUT_3_4_VOLUME 0x1B -#define WM8993_LEFT_OUTPUT_VOLUME 0x1C -#define WM8993_RIGHT_OUTPUT_VOLUME 0x1D -#define WM8993_LINE_OUTPUTS_VOLUME 0x1E -#define WM8993_HPOUT2_VOLUME 0x1F -#define WM8993_LEFT_OPGA_VOLUME 0x20 -#define WM8993_RIGHT_OPGA_VOLUME 0x21 -#define WM8993_SPKMIXL_ATTENUATION 0x22 -#define WM8993_SPKMIXR_ATTENUATION 0x23 -#define WM8993_SPKOUT_MIXERS 0x24 -#define WM8993_SPKOUT_BOOST 0x25 -#define WM8993_SPEAKER_VOLUME_LEFT 0x26 -#define WM8993_SPEAKER_VOLUME_RIGHT 0x27 -#define WM8993_INPUT_MIXER2 0x28 -#define WM8993_INPUT_MIXER3 0x29 -#define WM8993_INPUT_MIXER4 0x2A -#define WM8993_INPUT_MIXER5 0x2B -#define WM8993_INPUT_MIXER6 0x2C -#define WM8993_OUTPUT_MIXER1 0x2D -#define WM8993_OUTPUT_MIXER2 0x2E -#define WM8993_OUTPUT_MIXER3 0x2F -#define WM8993_OUTPUT_MIXER4 0x30 -#define WM8993_OUTPUT_MIXER5 0x31 -#define WM8993_OUTPUT_MIXER6 0x32 -#define WM8993_HPOUT2_MIXER 0x33 -#define WM8993_LINE_MIXER1 0x34 -#define WM8993_LINE_MIXER2 0x35 -#define WM8993_SPEAKER_MIXER 0x36 -#define WM8993_ADDITIONAL_CONTROL 0x37 -#define WM8993_ANTIPOP1 0x38 -#define WM8993_ANTIPOP2 0x39 -#define WM8993_MICBIAS 0x3A -#define WM8993_FLL_CONTROL_1 0x3C -#define WM8993_FLL_CONTROL_2 0x3D -#define WM8993_FLL_CONTROL_3 0x3E -#define WM8993_FLL_CONTROL_4 0x3F -#define WM8993_FLL_CONTROL_5 0x40 -#define WM8993_CLOCKING_3 0x41 -#define WM8993_CLOCKING_4 0x42 -#define WM8993_MW_SLAVE_CONTROL 0x43 -#define WM8993_BUS_CONTROL_1 0x45 -#define WM8993_WRITE_SEQUENCER_0 0x46 -#define WM8993_WRITE_SEQUENCER_1 0x47 -#define WM8993_WRITE_SEQUENCER_2 0x48 -#define WM8993_WRITE_SEQUENCER_3 0x49 -#define WM8993_WRITE_SEQUENCER_4 0x4A -#define WM8993_WRITE_SEQUENCER_5 0x4B -#define WM8993_CHARGE_PUMP_1 0x4C -#define WM8993_CLASS_W_0 0x51 -#define WM8993_DC_SERVO_0 0x54 -#define WM8993_DC_SERVO_1 0x55 -#define WM8993_DC_SERVO_3 0x57 -#define WM8993_DC_SERVO_READBACK_0 0x58 -#define WM8993_DC_SERVO_READBACK_1 0x59 -#define WM8993_DC_SERVO_READBACK_2 0x5A -#define WM8993_ANALOGUE_HP_0 0x60 -#define WM8993_EQ1 0x62 -#define WM8993_EQ2 0x63 -#define WM8993_EQ3 0x64 -#define WM8993_EQ4 0x65 -#define WM8993_EQ5 0x66 -#define WM8993_EQ6 0x67 -#define WM8993_EQ7 0x68 -#define WM8993_EQ8 0x69 -#define WM8993_EQ9 0x6A -#define WM8993_EQ10 0x6B -#define WM8993_EQ11 0x6C -#define WM8993_EQ12 0x6D -#define WM8993_EQ13 0x6E -#define WM8993_EQ14 0x6F -#define WM8993_EQ15 0x70 -#define WM8993_EQ16 0x71 -#define WM8993_EQ17 0x72 -#define WM8993_EQ18 0x73 -#define WM8993_EQ19 0x74 -#define WM8993_EQ20 0x75 -#define WM8993_EQ21 0x76 -#define WM8993_EQ22 0x77 -#define WM8993_EQ23 0x78 -#define WM8993_EQ24 0x79 -#define WM8993_DIGITAL_PULLS 0x7A -#define WM8993_DRC_CONTROL_1 0x7B -#define WM8993_DRC_CONTROL_2 0x7C -#define WM8993_DRC_CONTROL_3 0x7D -#define WM8993_DRC_CONTROL_4 0x7E - -#define WM8993_REGISTER_COUNT 0x7F -#define WM8993_MAX_REGISTER 0x7E - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - Software Reset - */ -#define WM8993_SW_RESET_MASK 0xFFFF /* SW_RESET - [15:0] */ -#define WM8993_SW_RESET_SHIFT 0 /* SW_RESET - [15:0] */ -#define WM8993_SW_RESET_WIDTH 16 /* SW_RESET - [15:0] */ - -/* - * R1 (0x01) - Power Management (1) - */ -#define WM8993_SPKOUTR_ENA 0x2000 /* SPKOUTR_ENA */ -#define WM8993_SPKOUTR_ENA_MASK 0x2000 /* SPKOUTR_ENA */ -#define WM8993_SPKOUTR_ENA_SHIFT 13 /* SPKOUTR_ENA */ -#define WM8993_SPKOUTR_ENA_WIDTH 1 /* SPKOUTR_ENA */ -#define WM8993_SPKOUTL_ENA 0x1000 /* SPKOUTL_ENA */ -#define WM8993_SPKOUTL_ENA_MASK 0x1000 /* SPKOUTL_ENA */ -#define WM8993_SPKOUTL_ENA_SHIFT 12 /* SPKOUTL_ENA */ -#define WM8993_SPKOUTL_ENA_WIDTH 1 /* SPKOUTL_ENA */ -#define WM8993_HPOUT2_ENA 0x0800 /* HPOUT2_ENA */ -#define WM8993_HPOUT2_ENA_MASK 0x0800 /* HPOUT2_ENA */ -#define WM8993_HPOUT2_ENA_SHIFT 11 /* HPOUT2_ENA */ -#define WM8993_HPOUT2_ENA_WIDTH 1 /* HPOUT2_ENA */ -#define WM8993_HPOUT1L_ENA 0x0200 /* HPOUT1L_ENA */ -#define WM8993_HPOUT1L_ENA_MASK 0x0200 /* HPOUT1L_ENA */ -#define WM8993_HPOUT1L_ENA_SHIFT 9 /* HPOUT1L_ENA */ -#define WM8993_HPOUT1L_ENA_WIDTH 1 /* HPOUT1L_ENA */ -#define WM8993_HPOUT1R_ENA 0x0100 /* HPOUT1R_ENA */ -#define WM8993_HPOUT1R_ENA_MASK 0x0100 /* HPOUT1R_ENA */ -#define WM8993_HPOUT1R_ENA_SHIFT 8 /* HPOUT1R_ENA */ -#define WM8993_HPOUT1R_ENA_WIDTH 1 /* HPOUT1R_ENA */ -#define WM8993_MICB2_ENA 0x0020 /* MICB2_ENA */ -#define WM8993_MICB2_ENA_MASK 0x0020 /* MICB2_ENA */ -#define WM8993_MICB2_ENA_SHIFT 5 /* MICB2_ENA */ -#define WM8993_MICB2_ENA_WIDTH 1 /* MICB2_ENA */ -#define WM8993_MICB1_ENA 0x0010 /* MICB1_ENA */ -#define WM8993_MICB1_ENA_MASK 0x0010 /* MICB1_ENA */ -#define WM8993_MICB1_ENA_SHIFT 4 /* MICB1_ENA */ -#define WM8993_MICB1_ENA_WIDTH 1 /* MICB1_ENA */ -#define WM8993_VMID_SEL_MASK 0x0006 /* VMID_SEL - [2:1] */ -#define WM8993_VMID_SEL_SHIFT 1 /* VMID_SEL - [2:1] */ -#define WM8993_VMID_SEL_WIDTH 2 /* VMID_SEL - [2:1] */ -#define WM8993_BIAS_ENA 0x0001 /* BIAS_ENA */ -#define WM8993_BIAS_ENA_MASK 0x0001 /* BIAS_ENA */ -#define WM8993_BIAS_ENA_SHIFT 0 /* BIAS_ENA */ -#define WM8993_BIAS_ENA_WIDTH 1 /* BIAS_ENA */ - -/* - * R2 (0x02) - Power Management (2) - */ -#define WM8993_TSHUT_ENA 0x4000 /* TSHUT_ENA */ -#define WM8993_TSHUT_ENA_MASK 0x4000 /* TSHUT_ENA */ -#define WM8993_TSHUT_ENA_SHIFT 14 /* TSHUT_ENA */ -#define WM8993_TSHUT_ENA_WIDTH 1 /* TSHUT_ENA */ -#define WM8993_TSHUT_OPDIS 0x2000 /* TSHUT_OPDIS */ -#define WM8993_TSHUT_OPDIS_MASK 0x2000 /* TSHUT_OPDIS */ -#define WM8993_TSHUT_OPDIS_SHIFT 13 /* TSHUT_OPDIS */ -#define WM8993_TSHUT_OPDIS_WIDTH 1 /* TSHUT_OPDIS */ -#define WM8993_OPCLK_ENA 0x0800 /* OPCLK_ENA */ -#define WM8993_OPCLK_ENA_MASK 0x0800 /* OPCLK_ENA */ -#define WM8993_OPCLK_ENA_SHIFT 11 /* OPCLK_ENA */ -#define WM8993_OPCLK_ENA_WIDTH 1 /* OPCLK_ENA */ -#define WM8993_MIXINL_ENA 0x0200 /* MIXINL_ENA */ -#define WM8993_MIXINL_ENA_MASK 0x0200 /* MIXINL_ENA */ -#define WM8993_MIXINL_ENA_SHIFT 9 /* MIXINL_ENA */ -#define WM8993_MIXINL_ENA_WIDTH 1 /* MIXINL_ENA */ -#define WM8993_MIXINR_ENA 0x0100 /* MIXINR_ENA */ -#define WM8993_MIXINR_ENA_MASK 0x0100 /* MIXINR_ENA */ -#define WM8993_MIXINR_ENA_SHIFT 8 /* MIXINR_ENA */ -#define WM8993_MIXINR_ENA_WIDTH 1 /* MIXINR_ENA */ -#define WM8993_IN2L_ENA 0x0080 /* IN2L_ENA */ -#define WM8993_IN2L_ENA_MASK 0x0080 /* IN2L_ENA */ -#define WM8993_IN2L_ENA_SHIFT 7 /* IN2L_ENA */ -#define WM8993_IN2L_ENA_WIDTH 1 /* IN2L_ENA */ -#define WM8993_IN1L_ENA 0x0040 /* IN1L_ENA */ -#define WM8993_IN1L_ENA_MASK 0x0040 /* IN1L_ENA */ -#define WM8993_IN1L_ENA_SHIFT 6 /* IN1L_ENA */ -#define WM8993_IN1L_ENA_WIDTH 1 /* IN1L_ENA */ -#define WM8993_IN2R_ENA 0x0020 /* IN2R_ENA */ -#define WM8993_IN2R_ENA_MASK 0x0020 /* IN2R_ENA */ -#define WM8993_IN2R_ENA_SHIFT 5 /* IN2R_ENA */ -#define WM8993_IN2R_ENA_WIDTH 1 /* IN2R_ENA */ -#define WM8993_IN1R_ENA 0x0010 /* IN1R_ENA */ -#define WM8993_IN1R_ENA_MASK 0x0010 /* IN1R_ENA */ -#define WM8993_IN1R_ENA_SHIFT 4 /* IN1R_ENA */ -#define WM8993_IN1R_ENA_WIDTH 1 /* IN1R_ENA */ -#define WM8993_ADCL_ENA 0x0002 /* ADCL_ENA */ -#define WM8993_ADCL_ENA_MASK 0x0002 /* ADCL_ENA */ -#define WM8993_ADCL_ENA_SHIFT 1 /* ADCL_ENA */ -#define WM8993_ADCL_ENA_WIDTH 1 /* ADCL_ENA */ -#define WM8993_ADCR_ENA 0x0001 /* ADCR_ENA */ -#define WM8993_ADCR_ENA_MASK 0x0001 /* ADCR_ENA */ -#define WM8993_ADCR_ENA_SHIFT 0 /* ADCR_ENA */ -#define WM8993_ADCR_ENA_WIDTH 1 /* ADCR_ENA */ - -/* - * R3 (0x03) - Power Management (3) - */ -#define WM8993_LINEOUT1N_ENA 0x2000 /* LINEOUT1N_ENA */ -#define WM8993_LINEOUT1N_ENA_MASK 0x2000 /* LINEOUT1N_ENA */ -#define WM8993_LINEOUT1N_ENA_SHIFT 13 /* LINEOUT1N_ENA */ -#define WM8993_LINEOUT1N_ENA_WIDTH 1 /* LINEOUT1N_ENA */ -#define WM8993_LINEOUT1P_ENA 0x1000 /* LINEOUT1P_ENA */ -#define WM8993_LINEOUT1P_ENA_MASK 0x1000 /* LINEOUT1P_ENA */ -#define WM8993_LINEOUT1P_ENA_SHIFT 12 /* LINEOUT1P_ENA */ -#define WM8993_LINEOUT1P_ENA_WIDTH 1 /* LINEOUT1P_ENA */ -#define WM8993_LINEOUT2N_ENA 0x0800 /* LINEOUT2N_ENA */ -#define WM8993_LINEOUT2N_ENA_MASK 0x0800 /* LINEOUT2N_ENA */ -#define WM8993_LINEOUT2N_ENA_SHIFT 11 /* LINEOUT2N_ENA */ -#define WM8993_LINEOUT2N_ENA_WIDTH 1 /* LINEOUT2N_ENA */ -#define WM8993_LINEOUT2P_ENA 0x0400 /* LINEOUT2P_ENA */ -#define WM8993_LINEOUT2P_ENA_MASK 0x0400 /* LINEOUT2P_ENA */ -#define WM8993_LINEOUT2P_ENA_SHIFT 10 /* LINEOUT2P_ENA */ -#define WM8993_LINEOUT2P_ENA_WIDTH 1 /* LINEOUT2P_ENA */ -#define WM8993_SPKRVOL_ENA 0x0200 /* SPKRVOL_ENA */ -#define WM8993_SPKRVOL_ENA_MASK 0x0200 /* SPKRVOL_ENA */ -#define WM8993_SPKRVOL_ENA_SHIFT 9 /* SPKRVOL_ENA */ -#define WM8993_SPKRVOL_ENA_WIDTH 1 /* SPKRVOL_ENA */ -#define WM8993_SPKLVOL_ENA 0x0100 /* SPKLVOL_ENA */ -#define WM8993_SPKLVOL_ENA_MASK 0x0100 /* SPKLVOL_ENA */ -#define WM8993_SPKLVOL_ENA_SHIFT 8 /* SPKLVOL_ENA */ -#define WM8993_SPKLVOL_ENA_WIDTH 1 /* SPKLVOL_ENA */ -#define WM8993_MIXOUTLVOL_ENA 0x0080 /* MIXOUTLVOL_ENA */ -#define WM8993_MIXOUTLVOL_ENA_MASK 0x0080 /* MIXOUTLVOL_ENA */ -#define WM8993_MIXOUTLVOL_ENA_SHIFT 7 /* MIXOUTLVOL_ENA */ -#define WM8993_MIXOUTLVOL_ENA_WIDTH 1 /* MIXOUTLVOL_ENA */ -#define WM8993_MIXOUTRVOL_ENA 0x0040 /* MIXOUTRVOL_ENA */ -#define WM8993_MIXOUTRVOL_ENA_MASK 0x0040 /* MIXOUTRVOL_ENA */ -#define WM8993_MIXOUTRVOL_ENA_SHIFT 6 /* MIXOUTRVOL_ENA */ -#define WM8993_MIXOUTRVOL_ENA_WIDTH 1 /* MIXOUTRVOL_ENA */ -#define WM8993_MIXOUTL_ENA 0x0020 /* MIXOUTL_ENA */ -#define WM8993_MIXOUTL_ENA_MASK 0x0020 /* MIXOUTL_ENA */ -#define WM8993_MIXOUTL_ENA_SHIFT 5 /* MIXOUTL_ENA */ -#define WM8993_MIXOUTL_ENA_WIDTH 1 /* MIXOUTL_ENA */ -#define WM8993_MIXOUTR_ENA 0x0010 /* MIXOUTR_ENA */ -#define WM8993_MIXOUTR_ENA_MASK 0x0010 /* MIXOUTR_ENA */ -#define WM8993_MIXOUTR_ENA_SHIFT 4 /* MIXOUTR_ENA */ -#define WM8993_MIXOUTR_ENA_WIDTH 1 /* MIXOUTR_ENA */ -#define WM8993_DACL_ENA 0x0002 /* DACL_ENA */ -#define WM8993_DACL_ENA_MASK 0x0002 /* DACL_ENA */ -#define WM8993_DACL_ENA_SHIFT 1 /* DACL_ENA */ -#define WM8993_DACL_ENA_WIDTH 1 /* DACL_ENA */ -#define WM8993_DACR_ENA 0x0001 /* DACR_ENA */ -#define WM8993_DACR_ENA_MASK 0x0001 /* DACR_ENA */ -#define WM8993_DACR_ENA_SHIFT 0 /* DACR_ENA */ -#define WM8993_DACR_ENA_WIDTH 1 /* DACR_ENA */ - -/* - * R4 (0x04) - Audio Interface (1) - */ -#define WM8993_AIFADCL_SRC 0x8000 /* AIFADCL_SRC */ -#define WM8993_AIFADCL_SRC_MASK 0x8000 /* AIFADCL_SRC */ -#define WM8993_AIFADCL_SRC_SHIFT 15 /* AIFADCL_SRC */ -#define WM8993_AIFADCL_SRC_WIDTH 1 /* AIFADCL_SRC */ -#define WM8993_AIFADCR_SRC 0x4000 /* AIFADCR_SRC */ -#define WM8993_AIFADCR_SRC_MASK 0x4000 /* AIFADCR_SRC */ -#define WM8993_AIFADCR_SRC_SHIFT 14 /* AIFADCR_SRC */ -#define WM8993_AIFADCR_SRC_WIDTH 1 /* AIFADCR_SRC */ -#define WM8993_AIFADC_TDM 0x2000 /* AIFADC_TDM */ -#define WM8993_AIFADC_TDM_MASK 0x2000 /* AIFADC_TDM */ -#define WM8993_AIFADC_TDM_SHIFT 13 /* AIFADC_TDM */ -#define WM8993_AIFADC_TDM_WIDTH 1 /* AIFADC_TDM */ -#define WM8993_AIFADC_TDM_CHAN 0x1000 /* AIFADC_TDM_CHAN */ -#define WM8993_AIFADC_TDM_CHAN_MASK 0x1000 /* AIFADC_TDM_CHAN */ -#define WM8993_AIFADC_TDM_CHAN_SHIFT 12 /* AIFADC_TDM_CHAN */ -#define WM8993_AIFADC_TDM_CHAN_WIDTH 1 /* AIFADC_TDM_CHAN */ -#define WM8993_BCLK_DIR 0x0200 /* BCLK_DIR */ -#define WM8993_BCLK_DIR_MASK 0x0200 /* BCLK_DIR */ -#define WM8993_BCLK_DIR_SHIFT 9 /* BCLK_DIR */ -#define WM8993_BCLK_DIR_WIDTH 1 /* BCLK_DIR */ -#define WM8993_AIF_BCLK_INV 0x0100 /* AIF_BCLK_INV */ -#define WM8993_AIF_BCLK_INV_MASK 0x0100 /* AIF_BCLK_INV */ -#define WM8993_AIF_BCLK_INV_SHIFT 8 /* AIF_BCLK_INV */ -#define WM8993_AIF_BCLK_INV_WIDTH 1 /* AIF_BCLK_INV */ -#define WM8993_AIF_LRCLK_INV 0x0080 /* AIF_LRCLK_INV */ -#define WM8993_AIF_LRCLK_INV_MASK 0x0080 /* AIF_LRCLK_INV */ -#define WM8993_AIF_LRCLK_INV_SHIFT 7 /* AIF_LRCLK_INV */ -#define WM8993_AIF_LRCLK_INV_WIDTH 1 /* AIF_LRCLK_INV */ -#define WM8993_AIF_WL_MASK 0x0060 /* AIF_WL - [6:5] */ -#define WM8993_AIF_WL_SHIFT 5 /* AIF_WL - [6:5] */ -#define WM8993_AIF_WL_WIDTH 2 /* AIF_WL - [6:5] */ -#define WM8993_AIF_FMT_MASK 0x0018 /* AIF_FMT - [4:3] */ -#define WM8993_AIF_FMT_SHIFT 3 /* AIF_FMT - [4:3] */ -#define WM8993_AIF_FMT_WIDTH 2 /* AIF_FMT - [4:3] */ - -/* - * R5 (0x05) - Audio Interface (2) - */ -#define WM8993_AIFDACL_SRC 0x8000 /* AIFDACL_SRC */ -#define WM8993_AIFDACL_SRC_MASK 0x8000 /* AIFDACL_SRC */ -#define WM8993_AIFDACL_SRC_SHIFT 15 /* AIFDACL_SRC */ -#define WM8993_AIFDACL_SRC_WIDTH 1 /* AIFDACL_SRC */ -#define WM8993_AIFDACR_SRC 0x4000 /* AIFDACR_SRC */ -#define WM8993_AIFDACR_SRC_MASK 0x4000 /* AIFDACR_SRC */ -#define WM8993_AIFDACR_SRC_SHIFT 14 /* AIFDACR_SRC */ -#define WM8993_AIFDACR_SRC_WIDTH 1 /* AIFDACR_SRC */ -#define WM8993_AIFDAC_TDM 0x2000 /* AIFDAC_TDM */ -#define WM8993_AIFDAC_TDM_MASK 0x2000 /* AIFDAC_TDM */ -#define WM8993_AIFDAC_TDM_SHIFT 13 /* AIFDAC_TDM */ -#define WM8993_AIFDAC_TDM_WIDTH 1 /* AIFDAC_TDM */ -#define WM8993_AIFDAC_TDM_CHAN 0x1000 /* AIFDAC_TDM_CHAN */ -#define WM8993_AIFDAC_TDM_CHAN_MASK 0x1000 /* AIFDAC_TDM_CHAN */ -#define WM8993_AIFDAC_TDM_CHAN_SHIFT 12 /* AIFDAC_TDM_CHAN */ -#define WM8993_AIFDAC_TDM_CHAN_WIDTH 1 /* AIFDAC_TDM_CHAN */ -#define WM8993_DAC_BOOST_MASK 0x0C00 /* DAC_BOOST - [11:10] */ -#define WM8993_DAC_BOOST_SHIFT 10 /* DAC_BOOST - [11:10] */ -#define WM8993_DAC_BOOST_WIDTH 2 /* DAC_BOOST - [11:10] */ -#define WM8993_DAC_COMP 0x0010 /* DAC_COMP */ -#define WM8993_DAC_COMP_MASK 0x0010 /* DAC_COMP */ -#define WM8993_DAC_COMP_SHIFT 4 /* DAC_COMP */ -#define WM8993_DAC_COMP_WIDTH 1 /* DAC_COMP */ -#define WM8993_DAC_COMPMODE 0x0008 /* DAC_COMPMODE */ -#define WM8993_DAC_COMPMODE_MASK 0x0008 /* DAC_COMPMODE */ -#define WM8993_DAC_COMPMODE_SHIFT 3 /* DAC_COMPMODE */ -#define WM8993_DAC_COMPMODE_WIDTH 1 /* DAC_COMPMODE */ -#define WM8993_ADC_COMP 0x0004 /* ADC_COMP */ -#define WM8993_ADC_COMP_MASK 0x0004 /* ADC_COMP */ -#define WM8993_ADC_COMP_SHIFT 2 /* ADC_COMP */ -#define WM8993_ADC_COMP_WIDTH 1 /* ADC_COMP */ -#define WM8993_ADC_COMPMODE 0x0002 /* ADC_COMPMODE */ -#define WM8993_ADC_COMPMODE_MASK 0x0002 /* ADC_COMPMODE */ -#define WM8993_ADC_COMPMODE_SHIFT 1 /* ADC_COMPMODE */ -#define WM8993_ADC_COMPMODE_WIDTH 1 /* ADC_COMPMODE */ -#define WM8993_LOOPBACK 0x0001 /* LOOPBACK */ -#define WM8993_LOOPBACK_MASK 0x0001 /* LOOPBACK */ -#define WM8993_LOOPBACK_SHIFT 0 /* LOOPBACK */ -#define WM8993_LOOPBACK_WIDTH 1 /* LOOPBACK */ - -/* - * R6 (0x06) - Clocking 1 - */ -#define WM8993_TOCLK_RATE 0x8000 /* TOCLK_RATE */ -#define WM8993_TOCLK_RATE_MASK 0x8000 /* TOCLK_RATE */ -#define WM8993_TOCLK_RATE_SHIFT 15 /* TOCLK_RATE */ -#define WM8993_TOCLK_RATE_WIDTH 1 /* TOCLK_RATE */ -#define WM8993_TOCLK_ENA 0x4000 /* TOCLK_ENA */ -#define WM8993_TOCLK_ENA_MASK 0x4000 /* TOCLK_ENA */ -#define WM8993_TOCLK_ENA_SHIFT 14 /* TOCLK_ENA */ -#define WM8993_TOCLK_ENA_WIDTH 1 /* TOCLK_ENA */ -#define WM8993_OPCLK_DIV_MASK 0x1E00 /* OPCLK_DIV - [12:9] */ -#define WM8993_OPCLK_DIV_SHIFT 9 /* OPCLK_DIV - [12:9] */ -#define WM8993_OPCLK_DIV_WIDTH 4 /* OPCLK_DIV - [12:9] */ -#define WM8993_DCLK_DIV_MASK 0x01C0 /* DCLK_DIV - [8:6] */ -#define WM8993_DCLK_DIV_SHIFT 6 /* DCLK_DIV - [8:6] */ -#define WM8993_DCLK_DIV_WIDTH 3 /* DCLK_DIV - [8:6] */ -#define WM8993_BCLK_DIV_MASK 0x001E /* BCLK_DIV - [4:1] */ -#define WM8993_BCLK_DIV_SHIFT 1 /* BCLK_DIV - [4:1] */ -#define WM8993_BCLK_DIV_WIDTH 4 /* BCLK_DIV - [4:1] */ - -/* - * R7 (0x07) - Clocking 2 - */ -#define WM8993_MCLK_SRC 0x8000 /* MCLK_SRC */ -#define WM8993_MCLK_SRC_MASK 0x8000 /* MCLK_SRC */ -#define WM8993_MCLK_SRC_SHIFT 15 /* MCLK_SRC */ -#define WM8993_MCLK_SRC_WIDTH 1 /* MCLK_SRC */ -#define WM8993_SYSCLK_SRC 0x4000 /* SYSCLK_SRC */ -#define WM8993_SYSCLK_SRC_MASK 0x4000 /* SYSCLK_SRC */ -#define WM8993_SYSCLK_SRC_SHIFT 14 /* SYSCLK_SRC */ -#define WM8993_SYSCLK_SRC_WIDTH 1 /* SYSCLK_SRC */ -#define WM8993_MCLK_DIV 0x1000 /* MCLK_DIV */ -#define WM8993_MCLK_DIV_MASK 0x1000 /* MCLK_DIV */ -#define WM8993_MCLK_DIV_SHIFT 12 /* MCLK_DIV */ -#define WM8993_MCLK_DIV_WIDTH 1 /* MCLK_DIV */ -#define WM8993_MCLK_INV 0x0400 /* MCLK_INV */ -#define WM8993_MCLK_INV_MASK 0x0400 /* MCLK_INV */ -#define WM8993_MCLK_INV_SHIFT 10 /* MCLK_INV */ -#define WM8993_MCLK_INV_WIDTH 1 /* MCLK_INV */ -#define WM8993_ADC_DIV_MASK 0x00E0 /* ADC_DIV - [7:5] */ -#define WM8993_ADC_DIV_SHIFT 5 /* ADC_DIV - [7:5] */ -#define WM8993_ADC_DIV_WIDTH 3 /* ADC_DIV - [7:5] */ -#define WM8993_DAC_DIV_MASK 0x001C /* DAC_DIV - [4:2] */ -#define WM8993_DAC_DIV_SHIFT 2 /* DAC_DIV - [4:2] */ -#define WM8993_DAC_DIV_WIDTH 3 /* DAC_DIV - [4:2] */ - -/* - * R8 (0x08) - Audio Interface (3) - */ -#define WM8993_AIF_MSTR1 0x8000 /* AIF_MSTR1 */ -#define WM8993_AIF_MSTR1_MASK 0x8000 /* AIF_MSTR1 */ -#define WM8993_AIF_MSTR1_SHIFT 15 /* AIF_MSTR1 */ -#define WM8993_AIF_MSTR1_WIDTH 1 /* AIF_MSTR1 */ - -/* - * R9 (0x09) - Audio Interface (4) - */ -#define WM8993_AIF_TRIS 0x2000 /* AIF_TRIS */ -#define WM8993_AIF_TRIS_MASK 0x2000 /* AIF_TRIS */ -#define WM8993_AIF_TRIS_SHIFT 13 /* AIF_TRIS */ -#define WM8993_AIF_TRIS_WIDTH 1 /* AIF_TRIS */ -#define WM8993_LRCLK_DIR 0x0800 /* LRCLK_DIR */ -#define WM8993_LRCLK_DIR_MASK 0x0800 /* LRCLK_DIR */ -#define WM8993_LRCLK_DIR_SHIFT 11 /* LRCLK_DIR */ -#define WM8993_LRCLK_DIR_WIDTH 1 /* LRCLK_DIR */ -#define WM8993_LRCLK_RATE_MASK 0x07FF /* LRCLK_RATE - [10:0] */ -#define WM8993_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [10:0] */ -#define WM8993_LRCLK_RATE_WIDTH 11 /* LRCLK_RATE - [10:0] */ - -/* - * R10 (0x0A) - DAC CTRL - */ -#define WM8993_DAC_OSR128 0x2000 /* DAC_OSR128 */ -#define WM8993_DAC_OSR128_MASK 0x2000 /* DAC_OSR128 */ -#define WM8993_DAC_OSR128_SHIFT 13 /* DAC_OSR128 */ -#define WM8993_DAC_OSR128_WIDTH 1 /* DAC_OSR128 */ -#define WM8993_DAC_MONO 0x0200 /* DAC_MONO */ -#define WM8993_DAC_MONO_MASK 0x0200 /* DAC_MONO */ -#define WM8993_DAC_MONO_SHIFT 9 /* DAC_MONO */ -#define WM8993_DAC_MONO_WIDTH 1 /* DAC_MONO */ -#define WM8993_DAC_SB_FILT 0x0100 /* DAC_SB_FILT */ -#define WM8993_DAC_SB_FILT_MASK 0x0100 /* DAC_SB_FILT */ -#define WM8993_DAC_SB_FILT_SHIFT 8 /* DAC_SB_FILT */ -#define WM8993_DAC_SB_FILT_WIDTH 1 /* DAC_SB_FILT */ -#define WM8993_DAC_MUTERATE 0x0080 /* DAC_MUTERATE */ -#define WM8993_DAC_MUTERATE_MASK 0x0080 /* DAC_MUTERATE */ -#define WM8993_DAC_MUTERATE_SHIFT 7 /* DAC_MUTERATE */ -#define WM8993_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */ -#define WM8993_DAC_UNMUTE_RAMP 0x0040 /* DAC_UNMUTE_RAMP */ -#define WM8993_DAC_UNMUTE_RAMP_MASK 0x0040 /* DAC_UNMUTE_RAMP */ -#define WM8993_DAC_UNMUTE_RAMP_SHIFT 6 /* DAC_UNMUTE_RAMP */ -#define WM8993_DAC_UNMUTE_RAMP_WIDTH 1 /* DAC_UNMUTE_RAMP */ -#define WM8993_DEEMPH_MASK 0x0030 /* DEEMPH - [5:4] */ -#define WM8993_DEEMPH_SHIFT 4 /* DEEMPH - [5:4] */ -#define WM8993_DEEMPH_WIDTH 2 /* DEEMPH - [5:4] */ -#define WM8993_DAC_MUTE 0x0004 /* DAC_MUTE */ -#define WM8993_DAC_MUTE_MASK 0x0004 /* DAC_MUTE */ -#define WM8993_DAC_MUTE_SHIFT 2 /* DAC_MUTE */ -#define WM8993_DAC_MUTE_WIDTH 1 /* DAC_MUTE */ -#define WM8993_DACL_DATINV 0x0002 /* DACL_DATINV */ -#define WM8993_DACL_DATINV_MASK 0x0002 /* DACL_DATINV */ -#define WM8993_DACL_DATINV_SHIFT 1 /* DACL_DATINV */ -#define WM8993_DACL_DATINV_WIDTH 1 /* DACL_DATINV */ -#define WM8993_DACR_DATINV 0x0001 /* DACR_DATINV */ -#define WM8993_DACR_DATINV_MASK 0x0001 /* DACR_DATINV */ -#define WM8993_DACR_DATINV_SHIFT 0 /* DACR_DATINV */ -#define WM8993_DACR_DATINV_WIDTH 1 /* DACR_DATINV */ - -/* - * R11 (0x0B) - Left DAC Digital Volume - */ -#define WM8993_DAC_VU 0x0100 /* DAC_VU */ -#define WM8993_DAC_VU_MASK 0x0100 /* DAC_VU */ -#define WM8993_DAC_VU_SHIFT 8 /* DAC_VU */ -#define WM8993_DAC_VU_WIDTH 1 /* DAC_VU */ -#define WM8993_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */ -#define WM8993_DACL_VOL_SHIFT 0 /* DACL_VOL - [7:0] */ -#define WM8993_DACL_VOL_WIDTH 8 /* DACL_VOL - [7:0] */ - -/* - * R12 (0x0C) - Right DAC Digital Volume - */ -#define WM8993_DAC_VU 0x0100 /* DAC_VU */ -#define WM8993_DAC_VU_MASK 0x0100 /* DAC_VU */ -#define WM8993_DAC_VU_SHIFT 8 /* DAC_VU */ -#define WM8993_DAC_VU_WIDTH 1 /* DAC_VU */ -#define WM8993_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */ -#define WM8993_DACR_VOL_SHIFT 0 /* DACR_VOL - [7:0] */ -#define WM8993_DACR_VOL_WIDTH 8 /* DACR_VOL - [7:0] */ - -/* - * R13 (0x0D) - Digital Side Tone - */ -#define WM8993_ADCL_DAC_SVOL_MASK 0x1E00 /* ADCL_DAC_SVOL - [12:9] */ -#define WM8993_ADCL_DAC_SVOL_SHIFT 9 /* ADCL_DAC_SVOL - [12:9] */ -#define WM8993_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [12:9] */ -#define WM8993_ADCR_DAC_SVOL_MASK 0x01E0 /* ADCR_DAC_SVOL - [8:5] */ -#define WM8993_ADCR_DAC_SVOL_SHIFT 5 /* ADCR_DAC_SVOL - [8:5] */ -#define WM8993_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [8:5] */ -#define WM8993_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */ -#define WM8993_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */ -#define WM8993_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */ -#define WM8993_ADC_TO_DACR_MASK 0x0003 /* ADC_TO_DACR - [1:0] */ -#define WM8993_ADC_TO_DACR_SHIFT 0 /* ADC_TO_DACR - [1:0] */ -#define WM8993_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [1:0] */ - -/* - * R14 (0x0E) - ADC CTRL - */ -#define WM8993_ADC_OSR128 0x0200 /* ADC_OSR128 */ -#define WM8993_ADC_OSR128_MASK 0x0200 /* ADC_OSR128 */ -#define WM8993_ADC_OSR128_SHIFT 9 /* ADC_OSR128 */ -#define WM8993_ADC_OSR128_WIDTH 1 /* ADC_OSR128 */ -#define WM8993_ADC_HPF 0x0100 /* ADC_HPF */ -#define WM8993_ADC_HPF_MASK 0x0100 /* ADC_HPF */ -#define WM8993_ADC_HPF_SHIFT 8 /* ADC_HPF */ -#define WM8993_ADC_HPF_WIDTH 1 /* ADC_HPF */ -#define WM8993_ADC_HPF_CUT_MASK 0x0060 /* ADC_HPF_CUT - [6:5] */ -#define WM8993_ADC_HPF_CUT_SHIFT 5 /* ADC_HPF_CUT - [6:5] */ -#define WM8993_ADC_HPF_CUT_WIDTH 2 /* ADC_HPF_CUT - [6:5] */ -#define WM8993_ADCL_DATINV 0x0002 /* ADCL_DATINV */ -#define WM8993_ADCL_DATINV_MASK 0x0002 /* ADCL_DATINV */ -#define WM8993_ADCL_DATINV_SHIFT 1 /* ADCL_DATINV */ -#define WM8993_ADCL_DATINV_WIDTH 1 /* ADCL_DATINV */ -#define WM8993_ADCR_DATINV 0x0001 /* ADCR_DATINV */ -#define WM8993_ADCR_DATINV_MASK 0x0001 /* ADCR_DATINV */ -#define WM8993_ADCR_DATINV_SHIFT 0 /* ADCR_DATINV */ -#define WM8993_ADCR_DATINV_WIDTH 1 /* ADCR_DATINV */ - -/* - * R15 (0x0F) - Left ADC Digital Volume - */ -#define WM8993_ADC_VU 0x0100 /* ADC_VU */ -#define WM8993_ADC_VU_MASK 0x0100 /* ADC_VU */ -#define WM8993_ADC_VU_SHIFT 8 /* ADC_VU */ -#define WM8993_ADC_VU_WIDTH 1 /* ADC_VU */ -#define WM8993_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */ -#define WM8993_ADCL_VOL_SHIFT 0 /* ADCL_VOL - [7:0] */ -#define WM8993_ADCL_VOL_WIDTH 8 /* ADCL_VOL - [7:0] */ - -/* - * R16 (0x10) - Right ADC Digital Volume - */ -#define WM8993_ADC_VU 0x0100 /* ADC_VU */ -#define WM8993_ADC_VU_MASK 0x0100 /* ADC_VU */ -#define WM8993_ADC_VU_SHIFT 8 /* ADC_VU */ -#define WM8993_ADC_VU_WIDTH 1 /* ADC_VU */ -#define WM8993_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */ -#define WM8993_ADCR_VOL_SHIFT 0 /* ADCR_VOL - [7:0] */ -#define WM8993_ADCR_VOL_WIDTH 8 /* ADCR_VOL - [7:0] */ - -/* - * R18 (0x12) - GPIO CTRL 1 - */ -#define WM8993_JD2_SC_EINT 0x8000 /* JD2_SC_EINT */ -#define WM8993_JD2_SC_EINT_MASK 0x8000 /* JD2_SC_EINT */ -#define WM8993_JD2_SC_EINT_SHIFT 15 /* JD2_SC_EINT */ -#define WM8993_JD2_SC_EINT_WIDTH 1 /* JD2_SC_EINT */ -#define WM8993_JD2_EINT 0x4000 /* JD2_EINT */ -#define WM8993_JD2_EINT_MASK 0x4000 /* JD2_EINT */ -#define WM8993_JD2_EINT_SHIFT 14 /* JD2_EINT */ -#define WM8993_JD2_EINT_WIDTH 1 /* JD2_EINT */ -#define WM8993_WSEQ_EINT 0x2000 /* WSEQ_EINT */ -#define WM8993_WSEQ_EINT_MASK 0x2000 /* WSEQ_EINT */ -#define WM8993_WSEQ_EINT_SHIFT 13 /* WSEQ_EINT */ -#define WM8993_WSEQ_EINT_WIDTH 1 /* WSEQ_EINT */ -#define WM8993_IRQ 0x1000 /* IRQ */ -#define WM8993_IRQ_MASK 0x1000 /* IRQ */ -#define WM8993_IRQ_SHIFT 12 /* IRQ */ -#define WM8993_IRQ_WIDTH 1 /* IRQ */ -#define WM8993_TEMPOK_EINT 0x0800 /* TEMPOK_EINT */ -#define WM8993_TEMPOK_EINT_MASK 0x0800 /* TEMPOK_EINT */ -#define WM8993_TEMPOK_EINT_SHIFT 11 /* TEMPOK_EINT */ -#define WM8993_TEMPOK_EINT_WIDTH 1 /* TEMPOK_EINT */ -#define WM8993_JD1_SC_EINT 0x0400 /* JD1_SC_EINT */ -#define WM8993_JD1_SC_EINT_MASK 0x0400 /* JD1_SC_EINT */ -#define WM8993_JD1_SC_EINT_SHIFT 10 /* JD1_SC_EINT */ -#define WM8993_JD1_SC_EINT_WIDTH 1 /* JD1_SC_EINT */ -#define WM8993_JD1_EINT 0x0200 /* JD1_EINT */ -#define WM8993_JD1_EINT_MASK 0x0200 /* JD1_EINT */ -#define WM8993_JD1_EINT_SHIFT 9 /* JD1_EINT */ -#define WM8993_JD1_EINT_WIDTH 1 /* JD1_EINT */ -#define WM8993_FLL_LOCK_EINT 0x0100 /* FLL_LOCK_EINT */ -#define WM8993_FLL_LOCK_EINT_MASK 0x0100 /* FLL_LOCK_EINT */ -#define WM8993_FLL_LOCK_EINT_SHIFT 8 /* FLL_LOCK_EINT */ -#define WM8993_FLL_LOCK_EINT_WIDTH 1 /* FLL_LOCK_EINT */ -#define WM8993_GPI8_EINT 0x0080 /* GPI8_EINT */ -#define WM8993_GPI8_EINT_MASK 0x0080 /* GPI8_EINT */ -#define WM8993_GPI8_EINT_SHIFT 7 /* GPI8_EINT */ -#define WM8993_GPI8_EINT_WIDTH 1 /* GPI8_EINT */ -#define WM8993_GPI7_EINT 0x0040 /* GPI7_EINT */ -#define WM8993_GPI7_EINT_MASK 0x0040 /* GPI7_EINT */ -#define WM8993_GPI7_EINT_SHIFT 6 /* GPI7_EINT */ -#define WM8993_GPI7_EINT_WIDTH 1 /* GPI7_EINT */ -#define WM8993_GPIO1_EINT 0x0001 /* GPIO1_EINT */ -#define WM8993_GPIO1_EINT_MASK 0x0001 /* GPIO1_EINT */ -#define WM8993_GPIO1_EINT_SHIFT 0 /* GPIO1_EINT */ -#define WM8993_GPIO1_EINT_WIDTH 1 /* GPIO1_EINT */ - -/* - * R19 (0x13) - GPIO1 - */ -#define WM8993_GPIO1_PU 0x0020 /* GPIO1_PU */ -#define WM8993_GPIO1_PU_MASK 0x0020 /* GPIO1_PU */ -#define WM8993_GPIO1_PU_SHIFT 5 /* GPIO1_PU */ -#define WM8993_GPIO1_PU_WIDTH 1 /* GPIO1_PU */ -#define WM8993_GPIO1_PD 0x0010 /* GPIO1_PD */ -#define WM8993_GPIO1_PD_MASK 0x0010 /* GPIO1_PD */ -#define WM8993_GPIO1_PD_SHIFT 4 /* GPIO1_PD */ -#define WM8993_GPIO1_PD_WIDTH 1 /* GPIO1_PD */ -#define WM8993_GPIO1_SEL_MASK 0x000F /* GPIO1_SEL - [3:0] */ -#define WM8993_GPIO1_SEL_SHIFT 0 /* GPIO1_SEL - [3:0] */ -#define WM8993_GPIO1_SEL_WIDTH 4 /* GPIO1_SEL - [3:0] */ - -/* - * R20 (0x14) - IRQ_DEBOUNCE - */ -#define WM8993_JD2_SC_DB 0x8000 /* JD2_SC_DB */ -#define WM8993_JD2_SC_DB_MASK 0x8000 /* JD2_SC_DB */ -#define WM8993_JD2_SC_DB_SHIFT 15 /* JD2_SC_DB */ -#define WM8993_JD2_SC_DB_WIDTH 1 /* JD2_SC_DB */ -#define WM8993_JD2_DB 0x4000 /* JD2_DB */ -#define WM8993_JD2_DB_MASK 0x4000 /* JD2_DB */ -#define WM8993_JD2_DB_SHIFT 14 /* JD2_DB */ -#define WM8993_JD2_DB_WIDTH 1 /* JD2_DB */ -#define WM8993_WSEQ_DB 0x2000 /* WSEQ_DB */ -#define WM8993_WSEQ_DB_MASK 0x2000 /* WSEQ_DB */ -#define WM8993_WSEQ_DB_SHIFT 13 /* WSEQ_DB */ -#define WM8993_WSEQ_DB_WIDTH 1 /* WSEQ_DB */ -#define WM8993_TEMPOK_DB 0x0800 /* TEMPOK_DB */ -#define WM8993_TEMPOK_DB_MASK 0x0800 /* TEMPOK_DB */ -#define WM8993_TEMPOK_DB_SHIFT 11 /* TEMPOK_DB */ -#define WM8993_TEMPOK_DB_WIDTH 1 /* TEMPOK_DB */ -#define WM8993_JD1_SC_DB 0x0400 /* JD1_SC_DB */ -#define WM8993_JD1_SC_DB_MASK 0x0400 /* JD1_SC_DB */ -#define WM8993_JD1_SC_DB_SHIFT 10 /* JD1_SC_DB */ -#define WM8993_JD1_SC_DB_WIDTH 1 /* JD1_SC_DB */ -#define WM8993_JD1_DB 0x0200 /* JD1_DB */ -#define WM8993_JD1_DB_MASK 0x0200 /* JD1_DB */ -#define WM8993_JD1_DB_SHIFT 9 /* JD1_DB */ -#define WM8993_JD1_DB_WIDTH 1 /* JD1_DB */ -#define WM8993_FLL_LOCK_DB 0x0100 /* FLL_LOCK_DB */ -#define WM8993_FLL_LOCK_DB_MASK 0x0100 /* FLL_LOCK_DB */ -#define WM8993_FLL_LOCK_DB_SHIFT 8 /* FLL_LOCK_DB */ -#define WM8993_FLL_LOCK_DB_WIDTH 1 /* FLL_LOCK_DB */ -#define WM8993_GPI8_DB 0x0080 /* GPI8_DB */ -#define WM8993_GPI8_DB_MASK 0x0080 /* GPI8_DB */ -#define WM8993_GPI8_DB_SHIFT 7 /* GPI8_DB */ -#define WM8993_GPI8_DB_WIDTH 1 /* GPI8_DB */ -#define WM8993_GPI7_DB 0x0008 /* GPI7_DB */ -#define WM8993_GPI7_DB_MASK 0x0008 /* GPI7_DB */ -#define WM8993_GPI7_DB_SHIFT 3 /* GPI7_DB */ -#define WM8993_GPI7_DB_WIDTH 1 /* GPI7_DB */ -#define WM8993_GPIO1_DB 0x0001 /* GPIO1_DB */ -#define WM8993_GPIO1_DB_MASK 0x0001 /* GPIO1_DB */ -#define WM8993_GPIO1_DB_SHIFT 0 /* GPIO1_DB */ -#define WM8993_GPIO1_DB_WIDTH 1 /* GPIO1_DB */ - -/* - * R22 (0x16) - GPIOCTRL 2 - */ -#define WM8993_IM_JD2_EINT 0x2000 /* IM_JD2_EINT */ -#define WM8993_IM_JD2_EINT_MASK 0x2000 /* IM_JD2_EINT */ -#define WM8993_IM_JD2_EINT_SHIFT 13 /* IM_JD2_EINT */ -#define WM8993_IM_JD2_EINT_WIDTH 1 /* IM_JD2_EINT */ -#define WM8993_IM_JD2_SC_EINT 0x1000 /* IM_JD2_SC_EINT */ -#define WM8993_IM_JD2_SC_EINT_MASK 0x1000 /* IM_JD2_SC_EINT */ -#define WM8993_IM_JD2_SC_EINT_SHIFT 12 /* IM_JD2_SC_EINT */ -#define WM8993_IM_JD2_SC_EINT_WIDTH 1 /* IM_JD2_SC_EINT */ -#define WM8993_IM_TEMPOK_EINT 0x0800 /* IM_TEMPOK_EINT */ -#define WM8993_IM_TEMPOK_EINT_MASK 0x0800 /* IM_TEMPOK_EINT */ -#define WM8993_IM_TEMPOK_EINT_SHIFT 11 /* IM_TEMPOK_EINT */ -#define WM8993_IM_TEMPOK_EINT_WIDTH 1 /* IM_TEMPOK_EINT */ -#define WM8993_IM_JD1_SC_EINT 0x0400 /* IM_JD1_SC_EINT */ -#define WM8993_IM_JD1_SC_EINT_MASK 0x0400 /* IM_JD1_SC_EINT */ -#define WM8993_IM_JD1_SC_EINT_SHIFT 10 /* IM_JD1_SC_EINT */ -#define WM8993_IM_JD1_SC_EINT_WIDTH 1 /* IM_JD1_SC_EINT */ -#define WM8993_IM_JD1_EINT 0x0200 /* IM_JD1_EINT */ -#define WM8993_IM_JD1_EINT_MASK 0x0200 /* IM_JD1_EINT */ -#define WM8993_IM_JD1_EINT_SHIFT 9 /* IM_JD1_EINT */ -#define WM8993_IM_JD1_EINT_WIDTH 1 /* IM_JD1_EINT */ -#define WM8993_IM_FLL_LOCK_EINT 0x0100 /* IM_FLL_LOCK_EINT */ -#define WM8993_IM_FLL_LOCK_EINT_MASK 0x0100 /* IM_FLL_LOCK_EINT */ -#define WM8993_IM_FLL_LOCK_EINT_SHIFT 8 /* IM_FLL_LOCK_EINT */ -#define WM8993_IM_FLL_LOCK_EINT_WIDTH 1 /* IM_FLL_LOCK_EINT */ -#define WM8993_IM_GPI8_EINT 0x0040 /* IM_GPI8_EINT */ -#define WM8993_IM_GPI8_EINT_MASK 0x0040 /* IM_GPI8_EINT */ -#define WM8993_IM_GPI8_EINT_SHIFT 6 /* IM_GPI8_EINT */ -#define WM8993_IM_GPI8_EINT_WIDTH 1 /* IM_GPI8_EINT */ -#define WM8993_IM_GPIO1_EINT 0x0020 /* IM_GPIO1_EINT */ -#define WM8993_IM_GPIO1_EINT_MASK 0x0020 /* IM_GPIO1_EINT */ -#define WM8993_IM_GPIO1_EINT_SHIFT 5 /* IM_GPIO1_EINT */ -#define WM8993_IM_GPIO1_EINT_WIDTH 1 /* IM_GPIO1_EINT */ -#define WM8993_GPI8_ENA 0x0010 /* GPI8_ENA */ -#define WM8993_GPI8_ENA_MASK 0x0010 /* GPI8_ENA */ -#define WM8993_GPI8_ENA_SHIFT 4 /* GPI8_ENA */ -#define WM8993_GPI8_ENA_WIDTH 1 /* GPI8_ENA */ -#define WM8993_IM_GPI7_EINT 0x0004 /* IM_GPI7_EINT */ -#define WM8993_IM_GPI7_EINT_MASK 0x0004 /* IM_GPI7_EINT */ -#define WM8993_IM_GPI7_EINT_SHIFT 2 /* IM_GPI7_EINT */ -#define WM8993_IM_GPI7_EINT_WIDTH 1 /* IM_GPI7_EINT */ -#define WM8993_IM_WSEQ_EINT 0x0002 /* IM_WSEQ_EINT */ -#define WM8993_IM_WSEQ_EINT_MASK 0x0002 /* IM_WSEQ_EINT */ -#define WM8993_IM_WSEQ_EINT_SHIFT 1 /* IM_WSEQ_EINT */ -#define WM8993_IM_WSEQ_EINT_WIDTH 1 /* IM_WSEQ_EINT */ -#define WM8993_GPI7_ENA 0x0001 /* GPI7_ENA */ -#define WM8993_GPI7_ENA_MASK 0x0001 /* GPI7_ENA */ -#define WM8993_GPI7_ENA_SHIFT 0 /* GPI7_ENA */ -#define WM8993_GPI7_ENA_WIDTH 1 /* GPI7_ENA */ - -/* - * R23 (0x17) - GPIO_POL - */ -#define WM8993_JD2_SC_POL 0x8000 /* JD2_SC_POL */ -#define WM8993_JD2_SC_POL_MASK 0x8000 /* JD2_SC_POL */ -#define WM8993_JD2_SC_POL_SHIFT 15 /* JD2_SC_POL */ -#define WM8993_JD2_SC_POL_WIDTH 1 /* JD2_SC_POL */ -#define WM8993_JD2_POL 0x4000 /* JD2_POL */ -#define WM8993_JD2_POL_MASK 0x4000 /* JD2_POL */ -#define WM8993_JD2_POL_SHIFT 14 /* JD2_POL */ -#define WM8993_JD2_POL_WIDTH 1 /* JD2_POL */ -#define WM8993_WSEQ_POL 0x2000 /* WSEQ_POL */ -#define WM8993_WSEQ_POL_MASK 0x2000 /* WSEQ_POL */ -#define WM8993_WSEQ_POL_SHIFT 13 /* WSEQ_POL */ -#define WM8993_WSEQ_POL_WIDTH 1 /* WSEQ_POL */ -#define WM8993_IRQ_POL 0x1000 /* IRQ_POL */ -#define WM8993_IRQ_POL_MASK 0x1000 /* IRQ_POL */ -#define WM8993_IRQ_POL_SHIFT 12 /* IRQ_POL */ -#define WM8993_IRQ_POL_WIDTH 1 /* IRQ_POL */ -#define WM8993_TEMPOK_POL 0x0800 /* TEMPOK_POL */ -#define WM8993_TEMPOK_POL_MASK 0x0800 /* TEMPOK_POL */ -#define WM8993_TEMPOK_POL_SHIFT 11 /* TEMPOK_POL */ -#define WM8993_TEMPOK_POL_WIDTH 1 /* TEMPOK_POL */ -#define WM8993_JD1_SC_POL 0x0400 /* JD1_SC_POL */ -#define WM8993_JD1_SC_POL_MASK 0x0400 /* JD1_SC_POL */ -#define WM8993_JD1_SC_POL_SHIFT 10 /* JD1_SC_POL */ -#define WM8993_JD1_SC_POL_WIDTH 1 /* JD1_SC_POL */ -#define WM8993_JD1_POL 0x0200 /* JD1_POL */ -#define WM8993_JD1_POL_MASK 0x0200 /* JD1_POL */ -#define WM8993_JD1_POL_SHIFT 9 /* JD1_POL */ -#define WM8993_JD1_POL_WIDTH 1 /* JD1_POL */ -#define WM8993_FLL_LOCK_POL 0x0100 /* FLL_LOCK_POL */ -#define WM8993_FLL_LOCK_POL_MASK 0x0100 /* FLL_LOCK_POL */ -#define WM8993_FLL_LOCK_POL_SHIFT 8 /* FLL_LOCK_POL */ -#define WM8993_FLL_LOCK_POL_WIDTH 1 /* FLL_LOCK_POL */ -#define WM8993_GPI8_POL 0x0080 /* GPI8_POL */ -#define WM8993_GPI8_POL_MASK 0x0080 /* GPI8_POL */ -#define WM8993_GPI8_POL_SHIFT 7 /* GPI8_POL */ -#define WM8993_GPI8_POL_WIDTH 1 /* GPI8_POL */ -#define WM8993_GPI7_POL 0x0040 /* GPI7_POL */ -#define WM8993_GPI7_POL_MASK 0x0040 /* GPI7_POL */ -#define WM8993_GPI7_POL_SHIFT 6 /* GPI7_POL */ -#define WM8993_GPI7_POL_WIDTH 1 /* GPI7_POL */ -#define WM8993_GPIO1_POL 0x0001 /* GPIO1_POL */ -#define WM8993_GPIO1_POL_MASK 0x0001 /* GPIO1_POL */ -#define WM8993_GPIO1_POL_SHIFT 0 /* GPIO1_POL */ -#define WM8993_GPIO1_POL_WIDTH 1 /* GPIO1_POL */ - -/* - * R24 (0x18) - Left Line Input 1&2 Volume - */ -#define WM8993_IN1_VU 0x0100 /* IN1_VU */ -#define WM8993_IN1_VU_MASK 0x0100 /* IN1_VU */ -#define WM8993_IN1_VU_SHIFT 8 /* IN1_VU */ -#define WM8993_IN1_VU_WIDTH 1 /* IN1_VU */ -#define WM8993_IN1L_MUTE 0x0080 /* IN1L_MUTE */ -#define WM8993_IN1L_MUTE_MASK 0x0080 /* IN1L_MUTE */ -#define WM8993_IN1L_MUTE_SHIFT 7 /* IN1L_MUTE */ -#define WM8993_IN1L_MUTE_WIDTH 1 /* IN1L_MUTE */ -#define WM8993_IN1L_ZC 0x0040 /* IN1L_ZC */ -#define WM8993_IN1L_ZC_MASK 0x0040 /* IN1L_ZC */ -#define WM8993_IN1L_ZC_SHIFT 6 /* IN1L_ZC */ -#define WM8993_IN1L_ZC_WIDTH 1 /* IN1L_ZC */ -#define WM8993_IN1L_VOL_MASK 0x001F /* IN1L_VOL - [4:0] */ -#define WM8993_IN1L_VOL_SHIFT 0 /* IN1L_VOL - [4:0] */ -#define WM8993_IN1L_VOL_WIDTH 5 /* IN1L_VOL - [4:0] */ - -/* - * R25 (0x19) - Left Line Input 3&4 Volume - */ -#define WM8993_IN2_VU 0x0100 /* IN2_VU */ -#define WM8993_IN2_VU_MASK 0x0100 /* IN2_VU */ -#define WM8993_IN2_VU_SHIFT 8 /* IN2_VU */ -#define WM8993_IN2_VU_WIDTH 1 /* IN2_VU */ -#define WM8993_IN2L_MUTE 0x0080 /* IN2L_MUTE */ -#define WM8993_IN2L_MUTE_MASK 0x0080 /* IN2L_MUTE */ -#define WM8993_IN2L_MUTE_SHIFT 7 /* IN2L_MUTE */ -#define WM8993_IN2L_MUTE_WIDTH 1 /* IN2L_MUTE */ -#define WM8993_IN2L_ZC 0x0040 /* IN2L_ZC */ -#define WM8993_IN2L_ZC_MASK 0x0040 /* IN2L_ZC */ -#define WM8993_IN2L_ZC_SHIFT 6 /* IN2L_ZC */ -#define WM8993_IN2L_ZC_WIDTH 1 /* IN2L_ZC */ -#define WM8993_IN2L_VOL_MASK 0x001F /* IN2L_VOL - [4:0] */ -#define WM8993_IN2L_VOL_SHIFT 0 /* IN2L_VOL - [4:0] */ -#define WM8993_IN2L_VOL_WIDTH 5 /* IN2L_VOL - [4:0] */ - -/* - * R26 (0x1A) - Right Line Input 1&2 Volume - */ -#define WM8993_IN1_VU 0x0100 /* IN1_VU */ -#define WM8993_IN1_VU_MASK 0x0100 /* IN1_VU */ -#define WM8993_IN1_VU_SHIFT 8 /* IN1_VU */ -#define WM8993_IN1_VU_WIDTH 1 /* IN1_VU */ -#define WM8993_IN1R_MUTE 0x0080 /* IN1R_MUTE */ -#define WM8993_IN1R_MUTE_MASK 0x0080 /* IN1R_MUTE */ -#define WM8993_IN1R_MUTE_SHIFT 7 /* IN1R_MUTE */ -#define WM8993_IN1R_MUTE_WIDTH 1 /* IN1R_MUTE */ -#define WM8993_IN1R_ZC 0x0040 /* IN1R_ZC */ -#define WM8993_IN1R_ZC_MASK 0x0040 /* IN1R_ZC */ -#define WM8993_IN1R_ZC_SHIFT 6 /* IN1R_ZC */ -#define WM8993_IN1R_ZC_WIDTH 1 /* IN1R_ZC */ -#define WM8993_IN1R_VOL_MASK 0x001F /* IN1R_VOL - [4:0] */ -#define WM8993_IN1R_VOL_SHIFT 0 /* IN1R_VOL - [4:0] */ -#define WM8993_IN1R_VOL_WIDTH 5 /* IN1R_VOL - [4:0] */ - -/* - * R27 (0x1B) - Right Line Input 3&4 Volume - */ -#define WM8993_IN2_VU 0x0100 /* IN2_VU */ -#define WM8993_IN2_VU_MASK 0x0100 /* IN2_VU */ -#define WM8993_IN2_VU_SHIFT 8 /* IN2_VU */ -#define WM8993_IN2_VU_WIDTH 1 /* IN2_VU */ -#define WM8993_IN2R_MUTE 0x0080 /* IN2R_MUTE */ -#define WM8993_IN2R_MUTE_MASK 0x0080 /* IN2R_MUTE */ -#define WM8993_IN2R_MUTE_SHIFT 7 /* IN2R_MUTE */ -#define WM8993_IN2R_MUTE_WIDTH 1 /* IN2R_MUTE */ -#define WM8993_IN2R_ZC 0x0040 /* IN2R_ZC */ -#define WM8993_IN2R_ZC_MASK 0x0040 /* IN2R_ZC */ -#define WM8993_IN2R_ZC_SHIFT 6 /* IN2R_ZC */ -#define WM8993_IN2R_ZC_WIDTH 1 /* IN2R_ZC */ -#define WM8993_IN2R_VOL_MASK 0x001F /* IN2R_VOL - [4:0] */ -#define WM8993_IN2R_VOL_SHIFT 0 /* IN2R_VOL - [4:0] */ -#define WM8993_IN2R_VOL_WIDTH 5 /* IN2R_VOL - [4:0] */ - -/* - * R28 (0x1C) - Left Output Volume - */ -#define WM8993_HPOUT1_VU 0x0100 /* HPOUT1_VU */ -#define WM8993_HPOUT1_VU_MASK 0x0100 /* HPOUT1_VU */ -#define WM8993_HPOUT1_VU_SHIFT 8 /* HPOUT1_VU */ -#define WM8993_HPOUT1_VU_WIDTH 1 /* HPOUT1_VU */ -#define WM8993_HPOUT1L_ZC 0x0080 /* HPOUT1L_ZC */ -#define WM8993_HPOUT1L_ZC_MASK 0x0080 /* HPOUT1L_ZC */ -#define WM8993_HPOUT1L_ZC_SHIFT 7 /* HPOUT1L_ZC */ -#define WM8993_HPOUT1L_ZC_WIDTH 1 /* HPOUT1L_ZC */ -#define WM8993_HPOUT1L_MUTE_N 0x0040 /* HPOUT1L_MUTE_N */ -#define WM8993_HPOUT1L_MUTE_N_MASK 0x0040 /* HPOUT1L_MUTE_N */ -#define WM8993_HPOUT1L_MUTE_N_SHIFT 6 /* HPOUT1L_MUTE_N */ -#define WM8993_HPOUT1L_MUTE_N_WIDTH 1 /* HPOUT1L_MUTE_N */ -#define WM8993_HPOUT1L_VOL_MASK 0x003F /* HPOUT1L_VOL - [5:0] */ -#define WM8993_HPOUT1L_VOL_SHIFT 0 /* HPOUT1L_VOL - [5:0] */ -#define WM8993_HPOUT1L_VOL_WIDTH 6 /* HPOUT1L_VOL - [5:0] */ - -/* - * R29 (0x1D) - Right Output Volume - */ -#define WM8993_HPOUT1_VU 0x0100 /* HPOUT1_VU */ -#define WM8993_HPOUT1_VU_MASK 0x0100 /* HPOUT1_VU */ -#define WM8993_HPOUT1_VU_SHIFT 8 /* HPOUT1_VU */ -#define WM8993_HPOUT1_VU_WIDTH 1 /* HPOUT1_VU */ -#define WM8993_HPOUT1R_ZC 0x0080 /* HPOUT1R_ZC */ -#define WM8993_HPOUT1R_ZC_MASK 0x0080 /* HPOUT1R_ZC */ -#define WM8993_HPOUT1R_ZC_SHIFT 7 /* HPOUT1R_ZC */ -#define WM8993_HPOUT1R_ZC_WIDTH 1 /* HPOUT1R_ZC */ -#define WM8993_HPOUT1R_MUTE_N 0x0040 /* HPOUT1R_MUTE_N */ -#define WM8993_HPOUT1R_MUTE_N_MASK 0x0040 /* HPOUT1R_MUTE_N */ -#define WM8993_HPOUT1R_MUTE_N_SHIFT 6 /* HPOUT1R_MUTE_N */ -#define WM8993_HPOUT1R_MUTE_N_WIDTH 1 /* HPOUT1R_MUTE_N */ -#define WM8993_HPOUT1R_VOL_MASK 0x003F /* HPOUT1R_VOL - [5:0] */ -#define WM8993_HPOUT1R_VOL_SHIFT 0 /* HPOUT1R_VOL - [5:0] */ -#define WM8993_HPOUT1R_VOL_WIDTH 6 /* HPOUT1R_VOL - [5:0] */ - -/* - * R30 (0x1E) - Line Outputs Volume - */ -#define WM8993_LINEOUT1N_MUTE 0x0040 /* LINEOUT1N_MUTE */ -#define WM8993_LINEOUT1N_MUTE_MASK 0x0040 /* LINEOUT1N_MUTE */ -#define WM8993_LINEOUT1N_MUTE_SHIFT 6 /* LINEOUT1N_MUTE */ -#define WM8993_LINEOUT1N_MUTE_WIDTH 1 /* LINEOUT1N_MUTE */ -#define WM8993_LINEOUT1P_MUTE 0x0020 /* LINEOUT1P_MUTE */ -#define WM8993_LINEOUT1P_MUTE_MASK 0x0020 /* LINEOUT1P_MUTE */ -#define WM8993_LINEOUT1P_MUTE_SHIFT 5 /* LINEOUT1P_MUTE */ -#define WM8993_LINEOUT1P_MUTE_WIDTH 1 /* LINEOUT1P_MUTE */ -#define WM8993_LINEOUT1_VOL 0x0010 /* LINEOUT1_VOL */ -#define WM8993_LINEOUT1_VOL_MASK 0x0010 /* LINEOUT1_VOL */ -#define WM8993_LINEOUT1_VOL_SHIFT 4 /* LINEOUT1_VOL */ -#define WM8993_LINEOUT1_VOL_WIDTH 1 /* LINEOUT1_VOL */ -#define WM8993_LINEOUT2N_MUTE 0x0004 /* LINEOUT2N_MUTE */ -#define WM8993_LINEOUT2N_MUTE_MASK 0x0004 /* LINEOUT2N_MUTE */ -#define WM8993_LINEOUT2N_MUTE_SHIFT 2 /* LINEOUT2N_MUTE */ -#define WM8993_LINEOUT2N_MUTE_WIDTH 1 /* LINEOUT2N_MUTE */ -#define WM8993_LINEOUT2P_MUTE 0x0002 /* LINEOUT2P_MUTE */ -#define WM8993_LINEOUT2P_MUTE_MASK 0x0002 /* LINEOUT2P_MUTE */ -#define WM8993_LINEOUT2P_MUTE_SHIFT 1 /* LINEOUT2P_MUTE */ -#define WM8993_LINEOUT2P_MUTE_WIDTH 1 /* LINEOUT2P_MUTE */ -#define WM8993_LINEOUT2_VOL 0x0001 /* LINEOUT2_VOL */ -#define WM8993_LINEOUT2_VOL_MASK 0x0001 /* LINEOUT2_VOL */ -#define WM8993_LINEOUT2_VOL_SHIFT 0 /* LINEOUT2_VOL */ -#define WM8993_LINEOUT2_VOL_WIDTH 1 /* LINEOUT2_VOL */ - -/* - * R31 (0x1F) - HPOUT2 Volume - */ -#define WM8993_HPOUT2_MUTE 0x0020 /* HPOUT2_MUTE */ -#define WM8993_HPOUT2_MUTE_MASK 0x0020 /* HPOUT2_MUTE */ -#define WM8993_HPOUT2_MUTE_SHIFT 5 /* HPOUT2_MUTE */ -#define WM8993_HPOUT2_MUTE_WIDTH 1 /* HPOUT2_MUTE */ -#define WM8993_HPOUT2_VOL 0x0010 /* HPOUT2_VOL */ -#define WM8993_HPOUT2_VOL_MASK 0x0010 /* HPOUT2_VOL */ -#define WM8993_HPOUT2_VOL_SHIFT 4 /* HPOUT2_VOL */ -#define WM8993_HPOUT2_VOL_WIDTH 1 /* HPOUT2_VOL */ - -/* - * R32 (0x20) - Left OPGA Volume - */ -#define WM8993_MIXOUT_VU 0x0100 /* MIXOUT_VU */ -#define WM8993_MIXOUT_VU_MASK 0x0100 /* MIXOUT_VU */ -#define WM8993_MIXOUT_VU_SHIFT 8 /* MIXOUT_VU */ -#define WM8993_MIXOUT_VU_WIDTH 1 /* MIXOUT_VU */ -#define WM8993_MIXOUTL_ZC 0x0080 /* MIXOUTL_ZC */ -#define WM8993_MIXOUTL_ZC_MASK 0x0080 /* MIXOUTL_ZC */ -#define WM8993_MIXOUTL_ZC_SHIFT 7 /* MIXOUTL_ZC */ -#define WM8993_MIXOUTL_ZC_WIDTH 1 /* MIXOUTL_ZC */ -#define WM8993_MIXOUTL_MUTE_N 0x0040 /* MIXOUTL_MUTE_N */ -#define WM8993_MIXOUTL_MUTE_N_MASK 0x0040 /* MIXOUTL_MUTE_N */ -#define WM8993_MIXOUTL_MUTE_N_SHIFT 6 /* MIXOUTL_MUTE_N */ -#define WM8993_MIXOUTL_MUTE_N_WIDTH 1 /* MIXOUTL_MUTE_N */ -#define WM8993_MIXOUTL_VOL_MASK 0x003F /* MIXOUTL_VOL - [5:0] */ -#define WM8993_MIXOUTL_VOL_SHIFT 0 /* MIXOUTL_VOL - [5:0] */ -#define WM8993_MIXOUTL_VOL_WIDTH 6 /* MIXOUTL_VOL - [5:0] */ - -/* - * R33 (0x21) - Right OPGA Volume - */ -#define WM8993_MIXOUT_VU 0x0100 /* MIXOUT_VU */ -#define WM8993_MIXOUT_VU_MASK 0x0100 /* MIXOUT_VU */ -#define WM8993_MIXOUT_VU_SHIFT 8 /* MIXOUT_VU */ -#define WM8993_MIXOUT_VU_WIDTH 1 /* MIXOUT_VU */ -#define WM8993_MIXOUTR_ZC 0x0080 /* MIXOUTR_ZC */ -#define WM8993_MIXOUTR_ZC_MASK 0x0080 /* MIXOUTR_ZC */ -#define WM8993_MIXOUTR_ZC_SHIFT 7 /* MIXOUTR_ZC */ -#define WM8993_MIXOUTR_ZC_WIDTH 1 /* MIXOUTR_ZC */ -#define WM8993_MIXOUTR_MUTE_N 0x0040 /* MIXOUTR_MUTE_N */ -#define WM8993_MIXOUTR_MUTE_N_MASK 0x0040 /* MIXOUTR_MUTE_N */ -#define WM8993_MIXOUTR_MUTE_N_SHIFT 6 /* MIXOUTR_MUTE_N */ -#define WM8993_MIXOUTR_MUTE_N_WIDTH 1 /* MIXOUTR_MUTE_N */ -#define WM8993_MIXOUTR_VOL_MASK 0x003F /* MIXOUTR_VOL - [5:0] */ -#define WM8993_MIXOUTR_VOL_SHIFT 0 /* MIXOUTR_VOL - [5:0] */ -#define WM8993_MIXOUTR_VOL_WIDTH 6 /* MIXOUTR_VOL - [5:0] */ - -/* - * R34 (0x22) - SPKMIXL Attenuation - */ -#define WM8993_MIXINL_SPKMIXL_VOL 0x0020 /* MIXINL_SPKMIXL_VOL */ -#define WM8993_MIXINL_SPKMIXL_VOL_MASK 0x0020 /* MIXINL_SPKMIXL_VOL */ -#define WM8993_MIXINL_SPKMIXL_VOL_SHIFT 5 /* MIXINL_SPKMIXL_VOL */ -#define WM8993_MIXINL_SPKMIXL_VOL_WIDTH 1 /* MIXINL_SPKMIXL_VOL */ -#define WM8993_IN1LP_SPKMIXL_VOL 0x0010 /* IN1LP_SPKMIXL_VOL */ -#define WM8993_IN1LP_SPKMIXL_VOL_MASK 0x0010 /* IN1LP_SPKMIXL_VOL */ -#define WM8993_IN1LP_SPKMIXL_VOL_SHIFT 4 /* IN1LP_SPKMIXL_VOL */ -#define WM8993_IN1LP_SPKMIXL_VOL_WIDTH 1 /* IN1LP_SPKMIXL_VOL */ -#define WM8993_MIXOUTL_SPKMIXL_VOL 0x0008 /* MIXOUTL_SPKMIXL_VOL */ -#define WM8993_MIXOUTL_SPKMIXL_VOL_MASK 0x0008 /* MIXOUTL_SPKMIXL_VOL */ -#define WM8993_MIXOUTL_SPKMIXL_VOL_SHIFT 3 /* MIXOUTL_SPKMIXL_VOL */ -#define WM8993_MIXOUTL_SPKMIXL_VOL_WIDTH 1 /* MIXOUTL_SPKMIXL_VOL */ -#define WM8993_DACL_SPKMIXL_VOL 0x0004 /* DACL_SPKMIXL_VOL */ -#define WM8993_DACL_SPKMIXL_VOL_MASK 0x0004 /* DACL_SPKMIXL_VOL */ -#define WM8993_DACL_SPKMIXL_VOL_SHIFT 2 /* DACL_SPKMIXL_VOL */ -#define WM8993_DACL_SPKMIXL_VOL_WIDTH 1 /* DACL_SPKMIXL_VOL */ -#define WM8993_SPKMIXL_VOL_MASK 0x0003 /* SPKMIXL_VOL - [1:0] */ -#define WM8993_SPKMIXL_VOL_SHIFT 0 /* SPKMIXL_VOL - [1:0] */ -#define WM8993_SPKMIXL_VOL_WIDTH 2 /* SPKMIXL_VOL - [1:0] */ - -/* - * R35 (0x23) - SPKMIXR Attenuation - */ -#define WM8993_SPKOUT_CLASSAB_MODE 0x0100 /* SPKOUT_CLASSAB_MODE */ -#define WM8993_SPKOUT_CLASSAB_MODE_MASK 0x0100 /* SPKOUT_CLASSAB_MODE */ -#define WM8993_SPKOUT_CLASSAB_MODE_SHIFT 8 /* SPKOUT_CLASSAB_MODE */ -#define WM8993_SPKOUT_CLASSAB_MODE_WIDTH 1 /* SPKOUT_CLASSAB_MODE */ -#define WM8993_MIXINR_SPKMIXR_VOL 0x0020 /* MIXINR_SPKMIXR_VOL */ -#define WM8993_MIXINR_SPKMIXR_VOL_MASK 0x0020 /* MIXINR_SPKMIXR_VOL */ -#define WM8993_MIXINR_SPKMIXR_VOL_SHIFT 5 /* MIXINR_SPKMIXR_VOL */ -#define WM8993_MIXINR_SPKMIXR_VOL_WIDTH 1 /* MIXINR_SPKMIXR_VOL */ -#define WM8993_IN1RP_SPKMIXR_VOL 0x0010 /* IN1RP_SPKMIXR_VOL */ -#define WM8993_IN1RP_SPKMIXR_VOL_MASK 0x0010 /* IN1RP_SPKMIXR_VOL */ -#define WM8993_IN1RP_SPKMIXR_VOL_SHIFT 4 /* IN1RP_SPKMIXR_VOL */ -#define WM8993_IN1RP_SPKMIXR_VOL_WIDTH 1 /* IN1RP_SPKMIXR_VOL */ -#define WM8993_MIXOUTR_SPKMIXR_VOL 0x0008 /* MIXOUTR_SPKMIXR_VOL */ -#define WM8993_MIXOUTR_SPKMIXR_VOL_MASK 0x0008 /* MIXOUTR_SPKMIXR_VOL */ -#define WM8993_MIXOUTR_SPKMIXR_VOL_SHIFT 3 /* MIXOUTR_SPKMIXR_VOL */ -#define WM8993_MIXOUTR_SPKMIXR_VOL_WIDTH 1 /* MIXOUTR_SPKMIXR_VOL */ -#define WM8993_DACR_SPKMIXR_VOL 0x0004 /* DACR_SPKMIXR_VOL */ -#define WM8993_DACR_SPKMIXR_VOL_MASK 0x0004 /* DACR_SPKMIXR_VOL */ -#define WM8993_DACR_SPKMIXR_VOL_SHIFT 2 /* DACR_SPKMIXR_VOL */ -#define WM8993_DACR_SPKMIXR_VOL_WIDTH 1 /* DACR_SPKMIXR_VOL */ -#define WM8993_SPKMIXR_VOL_MASK 0x0003 /* SPKMIXR_VOL - [1:0] */ -#define WM8993_SPKMIXR_VOL_SHIFT 0 /* SPKMIXR_VOL - [1:0] */ -#define WM8993_SPKMIXR_VOL_WIDTH 2 /* SPKMIXR_VOL - [1:0] */ - -/* - * R36 (0x24) - SPKOUT Mixers - */ -#define WM8993_VRX_TO_SPKOUTL 0x0020 /* VRX_TO_SPKOUTL */ -#define WM8993_VRX_TO_SPKOUTL_MASK 0x0020 /* VRX_TO_SPKOUTL */ -#define WM8993_VRX_TO_SPKOUTL_SHIFT 5 /* VRX_TO_SPKOUTL */ -#define WM8993_VRX_TO_SPKOUTL_WIDTH 1 /* VRX_TO_SPKOUTL */ -#define WM8993_SPKMIXL_TO_SPKOUTL 0x0010 /* SPKMIXL_TO_SPKOUTL */ -#define WM8993_SPKMIXL_TO_SPKOUTL_MASK 0x0010 /* SPKMIXL_TO_SPKOUTL */ -#define WM8993_SPKMIXL_TO_SPKOUTL_SHIFT 4 /* SPKMIXL_TO_SPKOUTL */ -#define WM8993_SPKMIXL_TO_SPKOUTL_WIDTH 1 /* SPKMIXL_TO_SPKOUTL */ -#define WM8993_SPKMIXR_TO_SPKOUTL 0x0008 /* SPKMIXR_TO_SPKOUTL */ -#define WM8993_SPKMIXR_TO_SPKOUTL_MASK 0x0008 /* SPKMIXR_TO_SPKOUTL */ -#define WM8993_SPKMIXR_TO_SPKOUTL_SHIFT 3 /* SPKMIXR_TO_SPKOUTL */ -#define WM8993_SPKMIXR_TO_SPKOUTL_WIDTH 1 /* SPKMIXR_TO_SPKOUTL */ -#define WM8993_VRX_TO_SPKOUTR 0x0004 /* VRX_TO_SPKOUTR */ -#define WM8993_VRX_TO_SPKOUTR_MASK 0x0004 /* VRX_TO_SPKOUTR */ -#define WM8993_VRX_TO_SPKOUTR_SHIFT 2 /* VRX_TO_SPKOUTR */ -#define WM8993_VRX_TO_SPKOUTR_WIDTH 1 /* VRX_TO_SPKOUTR */ -#define WM8993_SPKMIXL_TO_SPKOUTR 0x0002 /* SPKMIXL_TO_SPKOUTR */ -#define WM8993_SPKMIXL_TO_SPKOUTR_MASK 0x0002 /* SPKMIXL_TO_SPKOUTR */ -#define WM8993_SPKMIXL_TO_SPKOUTR_SHIFT 1 /* SPKMIXL_TO_SPKOUTR */ -#define WM8993_SPKMIXL_TO_SPKOUTR_WIDTH 1 /* SPKMIXL_TO_SPKOUTR */ -#define WM8993_SPKMIXR_TO_SPKOUTR 0x0001 /* SPKMIXR_TO_SPKOUTR */ -#define WM8993_SPKMIXR_TO_SPKOUTR_MASK 0x0001 /* SPKMIXR_TO_SPKOUTR */ -#define WM8993_SPKMIXR_TO_SPKOUTR_SHIFT 0 /* SPKMIXR_TO_SPKOUTR */ -#define WM8993_SPKMIXR_TO_SPKOUTR_WIDTH 1 /* SPKMIXR_TO_SPKOUTR */ - -/* - * R37 (0x25) - SPKOUT Boost - */ -#define WM8993_SPKOUTL_BOOST_MASK 0x0038 /* SPKOUTL_BOOST - [5:3] */ -#define WM8993_SPKOUTL_BOOST_SHIFT 3 /* SPKOUTL_BOOST - [5:3] */ -#define WM8993_SPKOUTL_BOOST_WIDTH 3 /* SPKOUTL_BOOST - [5:3] */ -#define WM8993_SPKOUTR_BOOST_MASK 0x0007 /* SPKOUTR_BOOST - [2:0] */ -#define WM8993_SPKOUTR_BOOST_SHIFT 0 /* SPKOUTR_BOOST - [2:0] */ -#define WM8993_SPKOUTR_BOOST_WIDTH 3 /* SPKOUTR_BOOST - [2:0] */ - -/* - * R38 (0x26) - Speaker Volume Left - */ -#define WM8993_SPKOUT_VU 0x0100 /* SPKOUT_VU */ -#define WM8993_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */ -#define WM8993_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */ -#define WM8993_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */ -#define WM8993_SPKOUTL_ZC 0x0080 /* SPKOUTL_ZC */ -#define WM8993_SPKOUTL_ZC_MASK 0x0080 /* SPKOUTL_ZC */ -#define WM8993_SPKOUTL_ZC_SHIFT 7 /* SPKOUTL_ZC */ -#define WM8993_SPKOUTL_ZC_WIDTH 1 /* SPKOUTL_ZC */ -#define WM8993_SPKOUTL_MUTE_N 0x0040 /* SPKOUTL_MUTE_N */ -#define WM8993_SPKOUTL_MUTE_N_MASK 0x0040 /* SPKOUTL_MUTE_N */ -#define WM8993_SPKOUTL_MUTE_N_SHIFT 6 /* SPKOUTL_MUTE_N */ -#define WM8993_SPKOUTL_MUTE_N_WIDTH 1 /* SPKOUTL_MUTE_N */ -#define WM8993_SPKOUTL_VOL_MASK 0x003F /* SPKOUTL_VOL - [5:0] */ -#define WM8993_SPKOUTL_VOL_SHIFT 0 /* SPKOUTL_VOL - [5:0] */ -#define WM8993_SPKOUTL_VOL_WIDTH 6 /* SPKOUTL_VOL - [5:0] */ - -/* - * R39 (0x27) - Speaker Volume Right - */ -#define WM8993_SPKOUT_VU 0x0100 /* SPKOUT_VU */ -#define WM8993_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */ -#define WM8993_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */ -#define WM8993_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */ -#define WM8993_SPKOUTR_ZC 0x0080 /* SPKOUTR_ZC */ -#define WM8993_SPKOUTR_ZC_MASK 0x0080 /* SPKOUTR_ZC */ -#define WM8993_SPKOUTR_ZC_SHIFT 7 /* SPKOUTR_ZC */ -#define WM8993_SPKOUTR_ZC_WIDTH 1 /* SPKOUTR_ZC */ -#define WM8993_SPKOUTR_MUTE_N 0x0040 /* SPKOUTR_MUTE_N */ -#define WM8993_SPKOUTR_MUTE_N_MASK 0x0040 /* SPKOUTR_MUTE_N */ -#define WM8993_SPKOUTR_MUTE_N_SHIFT 6 /* SPKOUTR_MUTE_N */ -#define WM8993_SPKOUTR_MUTE_N_WIDTH 1 /* SPKOUTR_MUTE_N */ -#define WM8993_SPKOUTR_VOL_MASK 0x003F /* SPKOUTR_VOL - [5:0] */ -#define WM8993_SPKOUTR_VOL_SHIFT 0 /* SPKOUTR_VOL - [5:0] */ -#define WM8993_SPKOUTR_VOL_WIDTH 6 /* SPKOUTR_VOL - [5:0] */ - -/* - * R40 (0x28) - Input Mixer2 - */ -#define WM8993_IN2LP_TO_IN2L 0x0080 /* IN2LP_TO_IN2L */ -#define WM8993_IN2LP_TO_IN2L_MASK 0x0080 /* IN2LP_TO_IN2L */ -#define WM8993_IN2LP_TO_IN2L_SHIFT 7 /* IN2LP_TO_IN2L */ -#define WM8993_IN2LP_TO_IN2L_WIDTH 1 /* IN2LP_TO_IN2L */ -#define WM8993_IN2LN_TO_IN2L 0x0040 /* IN2LN_TO_IN2L */ -#define WM8993_IN2LN_TO_IN2L_MASK 0x0040 /* IN2LN_TO_IN2L */ -#define WM8993_IN2LN_TO_IN2L_SHIFT 6 /* IN2LN_TO_IN2L */ -#define WM8993_IN2LN_TO_IN2L_WIDTH 1 /* IN2LN_TO_IN2L */ -#define WM8993_IN1LP_TO_IN1L 0x0020 /* IN1LP_TO_IN1L */ -#define WM8993_IN1LP_TO_IN1L_MASK 0x0020 /* IN1LP_TO_IN1L */ -#define WM8993_IN1LP_TO_IN1L_SHIFT 5 /* IN1LP_TO_IN1L */ -#define WM8993_IN1LP_TO_IN1L_WIDTH 1 /* IN1LP_TO_IN1L */ -#define WM8993_IN1LN_TO_IN1L 0x0010 /* IN1LN_TO_IN1L */ -#define WM8993_IN1LN_TO_IN1L_MASK 0x0010 /* IN1LN_TO_IN1L */ -#define WM8993_IN1LN_TO_IN1L_SHIFT 4 /* IN1LN_TO_IN1L */ -#define WM8993_IN1LN_TO_IN1L_WIDTH 1 /* IN1LN_TO_IN1L */ -#define WM8993_IN2RP_TO_IN2R 0x0008 /* IN2RP_TO_IN2R */ -#define WM8993_IN2RP_TO_IN2R_MASK 0x0008 /* IN2RP_TO_IN2R */ -#define WM8993_IN2RP_TO_IN2R_SHIFT 3 /* IN2RP_TO_IN2R */ -#define WM8993_IN2RP_TO_IN2R_WIDTH 1 /* IN2RP_TO_IN2R */ -#define WM8993_IN2RN_TO_IN2R 0x0004 /* IN2RN_TO_IN2R */ -#define WM8993_IN2RN_TO_IN2R_MASK 0x0004 /* IN2RN_TO_IN2R */ -#define WM8993_IN2RN_TO_IN2R_SHIFT 2 /* IN2RN_TO_IN2R */ -#define WM8993_IN2RN_TO_IN2R_WIDTH 1 /* IN2RN_TO_IN2R */ -#define WM8993_IN1RP_TO_IN1R 0x0002 /* IN1RP_TO_IN1R */ -#define WM8993_IN1RP_TO_IN1R_MASK 0x0002 /* IN1RP_TO_IN1R */ -#define WM8993_IN1RP_TO_IN1R_SHIFT 1 /* IN1RP_TO_IN1R */ -#define WM8993_IN1RP_TO_IN1R_WIDTH 1 /* IN1RP_TO_IN1R */ -#define WM8993_IN1RN_TO_IN1R 0x0001 /* IN1RN_TO_IN1R */ -#define WM8993_IN1RN_TO_IN1R_MASK 0x0001 /* IN1RN_TO_IN1R */ -#define WM8993_IN1RN_TO_IN1R_SHIFT 0 /* IN1RN_TO_IN1R */ -#define WM8993_IN1RN_TO_IN1R_WIDTH 1 /* IN1RN_TO_IN1R */ - -/* - * R41 (0x29) - Input Mixer3 - */ -#define WM8993_IN2L_TO_MIXINL 0x0100 /* IN2L_TO_MIXINL */ -#define WM8993_IN2L_TO_MIXINL_MASK 0x0100 /* IN2L_TO_MIXINL */ -#define WM8993_IN2L_TO_MIXINL_SHIFT 8 /* IN2L_TO_MIXINL */ -#define WM8993_IN2L_TO_MIXINL_WIDTH 1 /* IN2L_TO_MIXINL */ -#define WM8993_IN2L_MIXINL_VOL 0x0080 /* IN2L_MIXINL_VOL */ -#define WM8993_IN2L_MIXINL_VOL_MASK 0x0080 /* IN2L_MIXINL_VOL */ -#define WM8993_IN2L_MIXINL_VOL_SHIFT 7 /* IN2L_MIXINL_VOL */ -#define WM8993_IN2L_MIXINL_VOL_WIDTH 1 /* IN2L_MIXINL_VOL */ -#define WM8993_IN1L_TO_MIXINL 0x0020 /* IN1L_TO_MIXINL */ -#define WM8993_IN1L_TO_MIXINL_MASK 0x0020 /* IN1L_TO_MIXINL */ -#define WM8993_IN1L_TO_MIXINL_SHIFT 5 /* IN1L_TO_MIXINL */ -#define WM8993_IN1L_TO_MIXINL_WIDTH 1 /* IN1L_TO_MIXINL */ -#define WM8993_IN1L_MIXINL_VOL 0x0010 /* IN1L_MIXINL_VOL */ -#define WM8993_IN1L_MIXINL_VOL_MASK 0x0010 /* IN1L_MIXINL_VOL */ -#define WM8993_IN1L_MIXINL_VOL_SHIFT 4 /* IN1L_MIXINL_VOL */ -#define WM8993_IN1L_MIXINL_VOL_WIDTH 1 /* IN1L_MIXINL_VOL */ -#define WM8993_MIXOUTL_MIXINL_VOL_MASK 0x0007 /* MIXOUTL_MIXINL_VOL - [2:0] */ -#define WM8993_MIXOUTL_MIXINL_VOL_SHIFT 0 /* MIXOUTL_MIXINL_VOL - [2:0] */ -#define WM8993_MIXOUTL_MIXINL_VOL_WIDTH 3 /* MIXOUTL_MIXINL_VOL - [2:0] */ - -/* - * R42 (0x2A) - Input Mixer4 - */ -#define WM8993_IN2R_TO_MIXINR 0x0100 /* IN2R_TO_MIXINR */ -#define WM8993_IN2R_TO_MIXINR_MASK 0x0100 /* IN2R_TO_MIXINR */ -#define WM8993_IN2R_TO_MIXINR_SHIFT 8 /* IN2R_TO_MIXINR */ -#define WM8993_IN2R_TO_MIXINR_WIDTH 1 /* IN2R_TO_MIXINR */ -#define WM8993_IN2R_MIXINR_VOL 0x0080 /* IN2R_MIXINR_VOL */ -#define WM8993_IN2R_MIXINR_VOL_MASK 0x0080 /* IN2R_MIXINR_VOL */ -#define WM8993_IN2R_MIXINR_VOL_SHIFT 7 /* IN2R_MIXINR_VOL */ -#define WM8993_IN2R_MIXINR_VOL_WIDTH 1 /* IN2R_MIXINR_VOL */ -#define WM8993_IN1R_TO_MIXINR 0x0020 /* IN1R_TO_MIXINR */ -#define WM8993_IN1R_TO_MIXINR_MASK 0x0020 /* IN1R_TO_MIXINR */ -#define WM8993_IN1R_TO_MIXINR_SHIFT 5 /* IN1R_TO_MIXINR */ -#define WM8993_IN1R_TO_MIXINR_WIDTH 1 /* IN1R_TO_MIXINR */ -#define WM8993_IN1R_MIXINR_VOL 0x0010 /* IN1R_MIXINR_VOL */ -#define WM8993_IN1R_MIXINR_VOL_MASK 0x0010 /* IN1R_MIXINR_VOL */ -#define WM8993_IN1R_MIXINR_VOL_SHIFT 4 /* IN1R_MIXINR_VOL */ -#define WM8993_IN1R_MIXINR_VOL_WIDTH 1 /* IN1R_MIXINR_VOL */ -#define WM8993_MIXOUTR_MIXINR_VOL_MASK 0x0007 /* MIXOUTR_MIXINR_VOL - [2:0] */ -#define WM8993_MIXOUTR_MIXINR_VOL_SHIFT 0 /* MIXOUTR_MIXINR_VOL - [2:0] */ -#define WM8993_MIXOUTR_MIXINR_VOL_WIDTH 3 /* MIXOUTR_MIXINR_VOL - [2:0] */ - -/* - * R43 (0x2B) - Input Mixer5 - */ -#define WM8993_IN1LP_MIXINL_VOL_MASK 0x01C0 /* IN1LP_MIXINL_VOL - [8:6] */ -#define WM8993_IN1LP_MIXINL_VOL_SHIFT 6 /* IN1LP_MIXINL_VOL - [8:6] */ -#define WM8993_IN1LP_MIXINL_VOL_WIDTH 3 /* IN1LP_MIXINL_VOL - [8:6] */ -#define WM8993_VRX_MIXINL_VOL_MASK 0x0007 /* VRX_MIXINL_VOL - [2:0] */ -#define WM8993_VRX_MIXINL_VOL_SHIFT 0 /* VRX_MIXINL_VOL - [2:0] */ -#define WM8993_VRX_MIXINL_VOL_WIDTH 3 /* VRX_MIXINL_VOL - [2:0] */ - -/* - * R44 (0x2C) - Input Mixer6 - */ -#define WM8993_IN1RP_MIXINR_VOL_MASK 0x01C0 /* IN1RP_MIXINR_VOL - [8:6] */ -#define WM8993_IN1RP_MIXINR_VOL_SHIFT 6 /* IN1RP_MIXINR_VOL - [8:6] */ -#define WM8993_IN1RP_MIXINR_VOL_WIDTH 3 /* IN1RP_MIXINR_VOL - [8:6] */ -#define WM8993_VRX_MIXINR_VOL_MASK 0x0007 /* VRX_MIXINR_VOL - [2:0] */ -#define WM8993_VRX_MIXINR_VOL_SHIFT 0 /* VRX_MIXINR_VOL - [2:0] */ -#define WM8993_VRX_MIXINR_VOL_WIDTH 3 /* VRX_MIXINR_VOL - [2:0] */ - -/* - * R45 (0x2D) - Output Mixer1 - */ -#define WM8993_DACL_TO_HPOUT1L 0x0100 /* DACL_TO_HPOUT1L */ -#define WM8993_DACL_TO_HPOUT1L_MASK 0x0100 /* DACL_TO_HPOUT1L */ -#define WM8993_DACL_TO_HPOUT1L_SHIFT 8 /* DACL_TO_HPOUT1L */ -#define WM8993_DACL_TO_HPOUT1L_WIDTH 1 /* DACL_TO_HPOUT1L */ -#define WM8993_MIXINR_TO_MIXOUTL 0x0080 /* MIXINR_TO_MIXOUTL */ -#define WM8993_MIXINR_TO_MIXOUTL_MASK 0x0080 /* MIXINR_TO_MIXOUTL */ -#define WM8993_MIXINR_TO_MIXOUTL_SHIFT 7 /* MIXINR_TO_MIXOUTL */ -#define WM8993_MIXINR_TO_MIXOUTL_WIDTH 1 /* MIXINR_TO_MIXOUTL */ -#define WM8993_MIXINL_TO_MIXOUTL 0x0040 /* MIXINL_TO_MIXOUTL */ -#define WM8993_MIXINL_TO_MIXOUTL_MASK 0x0040 /* MIXINL_TO_MIXOUTL */ -#define WM8993_MIXINL_TO_MIXOUTL_SHIFT 6 /* MIXINL_TO_MIXOUTL */ -#define WM8993_MIXINL_TO_MIXOUTL_WIDTH 1 /* MIXINL_TO_MIXOUTL */ -#define WM8993_IN2RN_TO_MIXOUTL 0x0020 /* IN2RN_TO_MIXOUTL */ -#define WM8993_IN2RN_TO_MIXOUTL_MASK 0x0020 /* IN2RN_TO_MIXOUTL */ -#define WM8993_IN2RN_TO_MIXOUTL_SHIFT 5 /* IN2RN_TO_MIXOUTL */ -#define WM8993_IN2RN_TO_MIXOUTL_WIDTH 1 /* IN2RN_TO_MIXOUTL */ -#define WM8993_IN2LN_TO_MIXOUTL 0x0010 /* IN2LN_TO_MIXOUTL */ -#define WM8993_IN2LN_TO_MIXOUTL_MASK 0x0010 /* IN2LN_TO_MIXOUTL */ -#define WM8993_IN2LN_TO_MIXOUTL_SHIFT 4 /* IN2LN_TO_MIXOUTL */ -#define WM8993_IN2LN_TO_MIXOUTL_WIDTH 1 /* IN2LN_TO_MIXOUTL */ -#define WM8993_IN1R_TO_MIXOUTL 0x0008 /* IN1R_TO_MIXOUTL */ -#define WM8993_IN1R_TO_MIXOUTL_MASK 0x0008 /* IN1R_TO_MIXOUTL */ -#define WM8993_IN1R_TO_MIXOUTL_SHIFT 3 /* IN1R_TO_MIXOUTL */ -#define WM8993_IN1R_TO_MIXOUTL_WIDTH 1 /* IN1R_TO_MIXOUTL */ -#define WM8993_IN1L_TO_MIXOUTL 0x0004 /* IN1L_TO_MIXOUTL */ -#define WM8993_IN1L_TO_MIXOUTL_MASK 0x0004 /* IN1L_TO_MIXOUTL */ -#define WM8993_IN1L_TO_MIXOUTL_SHIFT 2 /* IN1L_TO_MIXOUTL */ -#define WM8993_IN1L_TO_MIXOUTL_WIDTH 1 /* IN1L_TO_MIXOUTL */ -#define WM8993_IN2LP_TO_MIXOUTL 0x0002 /* IN2LP_TO_MIXOUTL */ -#define WM8993_IN2LP_TO_MIXOUTL_MASK 0x0002 /* IN2LP_TO_MIXOUTL */ -#define WM8993_IN2LP_TO_MIXOUTL_SHIFT 1 /* IN2LP_TO_MIXOUTL */ -#define WM8993_IN2LP_TO_MIXOUTL_WIDTH 1 /* IN2LP_TO_MIXOUTL */ -#define WM8993_DACL_TO_MIXOUTL 0x0001 /* DACL_TO_MIXOUTL */ -#define WM8993_DACL_TO_MIXOUTL_MASK 0x0001 /* DACL_TO_MIXOUTL */ -#define WM8993_DACL_TO_MIXOUTL_SHIFT 0 /* DACL_TO_MIXOUTL */ -#define WM8993_DACL_TO_MIXOUTL_WIDTH 1 /* DACL_TO_MIXOUTL */ - -/* - * R46 (0x2E) - Output Mixer2 - */ -#define WM8993_DACR_TO_HPOUT1R 0x0100 /* DACR_TO_HPOUT1R */ -#define WM8993_DACR_TO_HPOUT1R_MASK 0x0100 /* DACR_TO_HPOUT1R */ -#define WM8993_DACR_TO_HPOUT1R_SHIFT 8 /* DACR_TO_HPOUT1R */ -#define WM8993_DACR_TO_HPOUT1R_WIDTH 1 /* DACR_TO_HPOUT1R */ -#define WM8993_MIXINL_TO_MIXOUTR 0x0080 /* MIXINL_TO_MIXOUTR */ -#define WM8993_MIXINL_TO_MIXOUTR_MASK 0x0080 /* MIXINL_TO_MIXOUTR */ -#define WM8993_MIXINL_TO_MIXOUTR_SHIFT 7 /* MIXINL_TO_MIXOUTR */ -#define WM8993_MIXINL_TO_MIXOUTR_WIDTH 1 /* MIXINL_TO_MIXOUTR */ -#define WM8993_MIXINR_TO_MIXOUTR 0x0040 /* MIXINR_TO_MIXOUTR */ -#define WM8993_MIXINR_TO_MIXOUTR_MASK 0x0040 /* MIXINR_TO_MIXOUTR */ -#define WM8993_MIXINR_TO_MIXOUTR_SHIFT 6 /* MIXINR_TO_MIXOUTR */ -#define WM8993_MIXINR_TO_MIXOUTR_WIDTH 1 /* MIXINR_TO_MIXOUTR */ -#define WM8993_IN2LN_TO_MIXOUTR 0x0020 /* IN2LN_TO_MIXOUTR */ -#define WM8993_IN2LN_TO_MIXOUTR_MASK 0x0020 /* IN2LN_TO_MIXOUTR */ -#define WM8993_IN2LN_TO_MIXOUTR_SHIFT 5 /* IN2LN_TO_MIXOUTR */ -#define WM8993_IN2LN_TO_MIXOUTR_WIDTH 1 /* IN2LN_TO_MIXOUTR */ -#define WM8993_IN2RN_TO_MIXOUTR 0x0010 /* IN2RN_TO_MIXOUTR */ -#define WM8993_IN2RN_TO_MIXOUTR_MASK 0x0010 /* IN2RN_TO_MIXOUTR */ -#define WM8993_IN2RN_TO_MIXOUTR_SHIFT 4 /* IN2RN_TO_MIXOUTR */ -#define WM8993_IN2RN_TO_MIXOUTR_WIDTH 1 /* IN2RN_TO_MIXOUTR */ -#define WM8993_IN1L_TO_MIXOUTR 0x0008 /* IN1L_TO_MIXOUTR */ -#define WM8993_IN1L_TO_MIXOUTR_MASK 0x0008 /* IN1L_TO_MIXOUTR */ -#define WM8993_IN1L_TO_MIXOUTR_SHIFT 3 /* IN1L_TO_MIXOUTR */ -#define WM8993_IN1L_TO_MIXOUTR_WIDTH 1 /* IN1L_TO_MIXOUTR */ -#define WM8993_IN1R_TO_MIXOUTR 0x0004 /* IN1R_TO_MIXOUTR */ -#define WM8993_IN1R_TO_MIXOUTR_MASK 0x0004 /* IN1R_TO_MIXOUTR */ -#define WM8993_IN1R_TO_MIXOUTR_SHIFT 2 /* IN1R_TO_MIXOUTR */ -#define WM8993_IN1R_TO_MIXOUTR_WIDTH 1 /* IN1R_TO_MIXOUTR */ -#define WM8993_IN2RP_TO_MIXOUTR 0x0002 /* IN2RP_TO_MIXOUTR */ -#define WM8993_IN2RP_TO_MIXOUTR_MASK 0x0002 /* IN2RP_TO_MIXOUTR */ -#define WM8993_IN2RP_TO_MIXOUTR_SHIFT 1 /* IN2RP_TO_MIXOUTR */ -#define WM8993_IN2RP_TO_MIXOUTR_WIDTH 1 /* IN2RP_TO_MIXOUTR */ -#define WM8993_DACR_TO_MIXOUTR 0x0001 /* DACR_TO_MIXOUTR */ -#define WM8993_DACR_TO_MIXOUTR_MASK 0x0001 /* DACR_TO_MIXOUTR */ -#define WM8993_DACR_TO_MIXOUTR_SHIFT 0 /* DACR_TO_MIXOUTR */ -#define WM8993_DACR_TO_MIXOUTR_WIDTH 1 /* DACR_TO_MIXOUTR */ - -/* - * R47 (0x2F) - Output Mixer3 - */ -#define WM8993_IN2LP_MIXOUTL_VOL_MASK 0x0E00 /* IN2LP_MIXOUTL_VOL - [11:9] */ -#define WM8993_IN2LP_MIXOUTL_VOL_SHIFT 9 /* IN2LP_MIXOUTL_VOL - [11:9] */ -#define WM8993_IN2LP_MIXOUTL_VOL_WIDTH 3 /* IN2LP_MIXOUTL_VOL - [11:9] */ -#define WM8993_IN2LN_MIXOUTL_VOL_MASK 0x01C0 /* IN2LN_MIXOUTL_VOL - [8:6] */ -#define WM8993_IN2LN_MIXOUTL_VOL_SHIFT 6 /* IN2LN_MIXOUTL_VOL - [8:6] */ -#define WM8993_IN2LN_MIXOUTL_VOL_WIDTH 3 /* IN2LN_MIXOUTL_VOL - [8:6] */ -#define WM8993_IN1R_MIXOUTL_VOL_MASK 0x0038 /* IN1R_MIXOUTL_VOL - [5:3] */ -#define WM8993_IN1R_MIXOUTL_VOL_SHIFT 3 /* IN1R_MIXOUTL_VOL - [5:3] */ -#define WM8993_IN1R_MIXOUTL_VOL_WIDTH 3 /* IN1R_MIXOUTL_VOL - [5:3] */ -#define WM8993_IN1L_MIXOUTL_VOL_MASK 0x0007 /* IN1L_MIXOUTL_VOL - [2:0] */ -#define WM8993_IN1L_MIXOUTL_VOL_SHIFT 0 /* IN1L_MIXOUTL_VOL - [2:0] */ -#define WM8993_IN1L_MIXOUTL_VOL_WIDTH 3 /* IN1L_MIXOUTL_VOL - [2:0] */ - -/* - * R48 (0x30) - Output Mixer4 - */ -#define WM8993_IN2RP_MIXOUTR_VOL_MASK 0x0E00 /* IN2RP_MIXOUTR_VOL - [11:9] */ -#define WM8993_IN2RP_MIXOUTR_VOL_SHIFT 9 /* IN2RP_MIXOUTR_VOL - [11:9] */ -#define WM8993_IN2RP_MIXOUTR_VOL_WIDTH 3 /* IN2RP_MIXOUTR_VOL - [11:9] */ -#define WM8993_IN2RN_MIXOUTR_VOL_MASK 0x01C0 /* IN2RN_MIXOUTR_VOL - [8:6] */ -#define WM8993_IN2RN_MIXOUTR_VOL_SHIFT 6 /* IN2RN_MIXOUTR_VOL - [8:6] */ -#define WM8993_IN2RN_MIXOUTR_VOL_WIDTH 3 /* IN2RN_MIXOUTR_VOL - [8:6] */ -#define WM8993_IN1L_MIXOUTR_VOL_MASK 0x0038 /* IN1L_MIXOUTR_VOL - [5:3] */ -#define WM8993_IN1L_MIXOUTR_VOL_SHIFT 3 /* IN1L_MIXOUTR_VOL - [5:3] */ -#define WM8993_IN1L_MIXOUTR_VOL_WIDTH 3 /* IN1L_MIXOUTR_VOL - [5:3] */ -#define WM8993_IN1R_MIXOUTR_VOL_MASK 0x0007 /* IN1R_MIXOUTR_VOL - [2:0] */ -#define WM8993_IN1R_MIXOUTR_VOL_SHIFT 0 /* IN1R_MIXOUTR_VOL - [2:0] */ -#define WM8993_IN1R_MIXOUTR_VOL_WIDTH 3 /* IN1R_MIXOUTR_VOL - [2:0] */ - -/* - * R49 (0x31) - Output Mixer5 - */ -#define WM8993_DACL_MIXOUTL_VOL_MASK 0x0E00 /* DACL_MIXOUTL_VOL - [11:9] */ -#define WM8993_DACL_MIXOUTL_VOL_SHIFT 9 /* DACL_MIXOUTL_VOL - [11:9] */ -#define WM8993_DACL_MIXOUTL_VOL_WIDTH 3 /* DACL_MIXOUTL_VOL - [11:9] */ -#define WM8993_IN2RN_MIXOUTL_VOL_MASK 0x01C0 /* IN2RN_MIXOUTL_VOL - [8:6] */ -#define WM8993_IN2RN_MIXOUTL_VOL_SHIFT 6 /* IN2RN_MIXOUTL_VOL - [8:6] */ -#define WM8993_IN2RN_MIXOUTL_VOL_WIDTH 3 /* IN2RN_MIXOUTL_VOL - [8:6] */ -#define WM8993_MIXINR_MIXOUTL_VOL_MASK 0x0038 /* MIXINR_MIXOUTL_VOL - [5:3] */ -#define WM8993_MIXINR_MIXOUTL_VOL_SHIFT 3 /* MIXINR_MIXOUTL_VOL - [5:3] */ -#define WM8993_MIXINR_MIXOUTL_VOL_WIDTH 3 /* MIXINR_MIXOUTL_VOL - [5:3] */ -#define WM8993_MIXINL_MIXOUTL_VOL_MASK 0x0007 /* MIXINL_MIXOUTL_VOL - [2:0] */ -#define WM8993_MIXINL_MIXOUTL_VOL_SHIFT 0 /* MIXINL_MIXOUTL_VOL - [2:0] */ -#define WM8993_MIXINL_MIXOUTL_VOL_WIDTH 3 /* MIXINL_MIXOUTL_VOL - [2:0] */ - -/* - * R50 (0x32) - Output Mixer6 - */ -#define WM8993_DACR_MIXOUTR_VOL_MASK 0x0E00 /* DACR_MIXOUTR_VOL - [11:9] */ -#define WM8993_DACR_MIXOUTR_VOL_SHIFT 9 /* DACR_MIXOUTR_VOL - [11:9] */ -#define WM8993_DACR_MIXOUTR_VOL_WIDTH 3 /* DACR_MIXOUTR_VOL - [11:9] */ -#define WM8993_IN2LN_MIXOUTR_VOL_MASK 0x01C0 /* IN2LN_MIXOUTR_VOL - [8:6] */ -#define WM8993_IN2LN_MIXOUTR_VOL_SHIFT 6 /* IN2LN_MIXOUTR_VOL - [8:6] */ -#define WM8993_IN2LN_MIXOUTR_VOL_WIDTH 3 /* IN2LN_MIXOUTR_VOL - [8:6] */ -#define WM8993_MIXINL_MIXOUTR_VOL_MASK 0x0038 /* MIXINL_MIXOUTR_VOL - [5:3] */ -#define WM8993_MIXINL_MIXOUTR_VOL_SHIFT 3 /* MIXINL_MIXOUTR_VOL - [5:3] */ -#define WM8993_MIXINL_MIXOUTR_VOL_WIDTH 3 /* MIXINL_MIXOUTR_VOL - [5:3] */ -#define WM8993_MIXINR_MIXOUTR_VOL_MASK 0x0007 /* MIXINR_MIXOUTR_VOL - [2:0] */ -#define WM8993_MIXINR_MIXOUTR_VOL_SHIFT 0 /* MIXINR_MIXOUTR_VOL - [2:0] */ -#define WM8993_MIXINR_MIXOUTR_VOL_WIDTH 3 /* MIXINR_MIXOUTR_VOL - [2:0] */ - -/* - * R51 (0x33) - HPOUT2 Mixer - */ -#define WM8993_VRX_TO_HPOUT2 0x0020 /* VRX_TO_HPOUT2 */ -#define WM8993_VRX_TO_HPOUT2_MASK 0x0020 /* VRX_TO_HPOUT2 */ -#define WM8993_VRX_TO_HPOUT2_SHIFT 5 /* VRX_TO_HPOUT2 */ -#define WM8993_VRX_TO_HPOUT2_WIDTH 1 /* VRX_TO_HPOUT2 */ -#define WM8993_MIXOUTLVOL_TO_HPOUT2 0x0010 /* MIXOUTLVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTLVOL_TO_HPOUT2_MASK 0x0010 /* MIXOUTLVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTLVOL_TO_HPOUT2_SHIFT 4 /* MIXOUTLVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTLVOL_TO_HPOUT2_WIDTH 1 /* MIXOUTLVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTRVOL_TO_HPOUT2 0x0008 /* MIXOUTRVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTRVOL_TO_HPOUT2_MASK 0x0008 /* MIXOUTRVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTRVOL_TO_HPOUT2_SHIFT 3 /* MIXOUTRVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTRVOL_TO_HPOUT2_WIDTH 1 /* MIXOUTRVOL_TO_HPOUT2 */ - -/* - * R52 (0x34) - Line Mixer1 - */ -#define WM8993_MIXOUTL_TO_LINEOUT1N 0x0040 /* MIXOUTL_TO_LINEOUT1N */ -#define WM8993_MIXOUTL_TO_LINEOUT1N_MASK 0x0040 /* MIXOUTL_TO_LINEOUT1N */ -#define WM8993_MIXOUTL_TO_LINEOUT1N_SHIFT 6 /* MIXOUTL_TO_LINEOUT1N */ -#define WM8993_MIXOUTL_TO_LINEOUT1N_WIDTH 1 /* MIXOUTL_TO_LINEOUT1N */ -#define WM8993_MIXOUTR_TO_LINEOUT1N 0x0020 /* MIXOUTR_TO_LINEOUT1N */ -#define WM8993_MIXOUTR_TO_LINEOUT1N_MASK 0x0020 /* MIXOUTR_TO_LINEOUT1N */ -#define WM8993_MIXOUTR_TO_LINEOUT1N_SHIFT 5 /* MIXOUTR_TO_LINEOUT1N */ -#define WM8993_MIXOUTR_TO_LINEOUT1N_WIDTH 1 /* MIXOUTR_TO_LINEOUT1N */ -#define WM8993_LINEOUT1_MODE 0x0010 /* LINEOUT1_MODE */ -#define WM8993_LINEOUT1_MODE_MASK 0x0010 /* LINEOUT1_MODE */ -#define WM8993_LINEOUT1_MODE_SHIFT 4 /* LINEOUT1_MODE */ -#define WM8993_LINEOUT1_MODE_WIDTH 1 /* LINEOUT1_MODE */ -#define WM8993_IN1R_TO_LINEOUT1P 0x0004 /* IN1R_TO_LINEOUT1P */ -#define WM8993_IN1R_TO_LINEOUT1P_MASK 0x0004 /* IN1R_TO_LINEOUT1P */ -#define WM8993_IN1R_TO_LINEOUT1P_SHIFT 2 /* IN1R_TO_LINEOUT1P */ -#define WM8993_IN1R_TO_LINEOUT1P_WIDTH 1 /* IN1R_TO_LINEOUT1P */ -#define WM8993_IN1L_TO_LINEOUT1P 0x0002 /* IN1L_TO_LINEOUT1P */ -#define WM8993_IN1L_TO_LINEOUT1P_MASK 0x0002 /* IN1L_TO_LINEOUT1P */ -#define WM8993_IN1L_TO_LINEOUT1P_SHIFT 1 /* IN1L_TO_LINEOUT1P */ -#define WM8993_IN1L_TO_LINEOUT1P_WIDTH 1 /* IN1L_TO_LINEOUT1P */ -#define WM8993_MIXOUTL_TO_LINEOUT1P 0x0001 /* MIXOUTL_TO_LINEOUT1P */ -#define WM8993_MIXOUTL_TO_LINEOUT1P_MASK 0x0001 /* MIXOUTL_TO_LINEOUT1P */ -#define WM8993_MIXOUTL_TO_LINEOUT1P_SHIFT 0 /* MIXOUTL_TO_LINEOUT1P */ -#define WM8993_MIXOUTL_TO_LINEOUT1P_WIDTH 1 /* MIXOUTL_TO_LINEOUT1P */ - -/* - * R53 (0x35) - Line Mixer2 - */ -#define WM8993_MIXOUTR_TO_LINEOUT2N 0x0040 /* MIXOUTR_TO_LINEOUT2N */ -#define WM8993_MIXOUTR_TO_LINEOUT2N_MASK 0x0040 /* MIXOUTR_TO_LINEOUT2N */ -#define WM8993_MIXOUTR_TO_LINEOUT2N_SHIFT 6 /* MIXOUTR_TO_LINEOUT2N */ -#define WM8993_MIXOUTR_TO_LINEOUT2N_WIDTH 1 /* MIXOUTR_TO_LINEOUT2N */ -#define WM8993_MIXOUTL_TO_LINEOUT2N 0x0020 /* MIXOUTL_TO_LINEOUT2N */ -#define WM8993_MIXOUTL_TO_LINEOUT2N_MASK 0x0020 /* MIXOUTL_TO_LINEOUT2N */ -#define WM8993_MIXOUTL_TO_LINEOUT2N_SHIFT 5 /* MIXOUTL_TO_LINEOUT2N */ -#define WM8993_MIXOUTL_TO_LINEOUT2N_WIDTH 1 /* MIXOUTL_TO_LINEOUT2N */ -#define WM8993_LINEOUT2_MODE 0x0010 /* LINEOUT2_MODE */ -#define WM8993_LINEOUT2_MODE_MASK 0x0010 /* LINEOUT2_MODE */ -#define WM8993_LINEOUT2_MODE_SHIFT 4 /* LINEOUT2_MODE */ -#define WM8993_LINEOUT2_MODE_WIDTH 1 /* LINEOUT2_MODE */ -#define WM8993_IN1L_TO_LINEOUT2P 0x0004 /* IN1L_TO_LINEOUT2P */ -#define WM8993_IN1L_TO_LINEOUT2P_MASK 0x0004 /* IN1L_TO_LINEOUT2P */ -#define WM8993_IN1L_TO_LINEOUT2P_SHIFT 2 /* IN1L_TO_LINEOUT2P */ -#define WM8993_IN1L_TO_LINEOUT2P_WIDTH 1 /* IN1L_TO_LINEOUT2P */ -#define WM8993_IN1R_TO_LINEOUT2P 0x0002 /* IN1R_TO_LINEOUT2P */ -#define WM8993_IN1R_TO_LINEOUT2P_MASK 0x0002 /* IN1R_TO_LINEOUT2P */ -#define WM8993_IN1R_TO_LINEOUT2P_SHIFT 1 /* IN1R_TO_LINEOUT2P */ -#define WM8993_IN1R_TO_LINEOUT2P_WIDTH 1 /* IN1R_TO_LINEOUT2P */ -#define WM8993_MIXOUTR_TO_LINEOUT2P 0x0001 /* MIXOUTR_TO_LINEOUT2P */ -#define WM8993_MIXOUTR_TO_LINEOUT2P_MASK 0x0001 /* MIXOUTR_TO_LINEOUT2P */ -#define WM8993_MIXOUTR_TO_LINEOUT2P_SHIFT 0 /* MIXOUTR_TO_LINEOUT2P */ -#define WM8993_MIXOUTR_TO_LINEOUT2P_WIDTH 1 /* MIXOUTR_TO_LINEOUT2P */ - -/* - * R54 (0x36) - Speaker Mixer - */ -#define WM8993_SPKAB_REF_SEL 0x0100 /* SPKAB_REF_SEL */ -#define WM8993_SPKAB_REF_SEL_MASK 0x0100 /* SPKAB_REF_SEL */ -#define WM8993_SPKAB_REF_SEL_SHIFT 8 /* SPKAB_REF_SEL */ -#define WM8993_SPKAB_REF_SEL_WIDTH 1 /* SPKAB_REF_SEL */ -#define WM8993_MIXINL_TO_SPKMIXL 0x0080 /* MIXINL_TO_SPKMIXL */ -#define WM8993_MIXINL_TO_SPKMIXL_MASK 0x0080 /* MIXINL_TO_SPKMIXL */ -#define WM8993_MIXINL_TO_SPKMIXL_SHIFT 7 /* MIXINL_TO_SPKMIXL */ -#define WM8993_MIXINL_TO_SPKMIXL_WIDTH 1 /* MIXINL_TO_SPKMIXL */ -#define WM8993_MIXINR_TO_SPKMIXR 0x0040 /* MIXINR_TO_SPKMIXR */ -#define WM8993_MIXINR_TO_SPKMIXR_MASK 0x0040 /* MIXINR_TO_SPKMIXR */ -#define WM8993_MIXINR_TO_SPKMIXR_SHIFT 6 /* MIXINR_TO_SPKMIXR */ -#define WM8993_MIXINR_TO_SPKMIXR_WIDTH 1 /* MIXINR_TO_SPKMIXR */ -#define WM8993_IN1LP_TO_SPKMIXL 0x0020 /* IN1LP_TO_SPKMIXL */ -#define WM8993_IN1LP_TO_SPKMIXL_MASK 0x0020 /* IN1LP_TO_SPKMIXL */ -#define WM8993_IN1LP_TO_SPKMIXL_SHIFT 5 /* IN1LP_TO_SPKMIXL */ -#define WM8993_IN1LP_TO_SPKMIXL_WIDTH 1 /* IN1LP_TO_SPKMIXL */ -#define WM8993_IN1RP_TO_SPKMIXR 0x0010 /* IN1RP_TO_SPKMIXR */ -#define WM8993_IN1RP_TO_SPKMIXR_MASK 0x0010 /* IN1RP_TO_SPKMIXR */ -#define WM8993_IN1RP_TO_SPKMIXR_SHIFT 4 /* IN1RP_TO_SPKMIXR */ -#define WM8993_IN1RP_TO_SPKMIXR_WIDTH 1 /* IN1RP_TO_SPKMIXR */ -#define WM8993_MIXOUTL_TO_SPKMIXL 0x0008 /* MIXOUTL_TO_SPKMIXL */ -#define WM8993_MIXOUTL_TO_SPKMIXL_MASK 0x0008 /* MIXOUTL_TO_SPKMIXL */ -#define WM8993_MIXOUTL_TO_SPKMIXL_SHIFT 3 /* MIXOUTL_TO_SPKMIXL */ -#define WM8993_MIXOUTL_TO_SPKMIXL_WIDTH 1 /* MIXOUTL_TO_SPKMIXL */ -#define WM8993_MIXOUTR_TO_SPKMIXR 0x0004 /* MIXOUTR_TO_SPKMIXR */ -#define WM8993_MIXOUTR_TO_SPKMIXR_MASK 0x0004 /* MIXOUTR_TO_SPKMIXR */ -#define WM8993_MIXOUTR_TO_SPKMIXR_SHIFT 2 /* MIXOUTR_TO_SPKMIXR */ -#define WM8993_MIXOUTR_TO_SPKMIXR_WIDTH 1 /* MIXOUTR_TO_SPKMIXR */ -#define WM8993_DACL_TO_SPKMIXL 0x0002 /* DACL_TO_SPKMIXL */ -#define WM8993_DACL_TO_SPKMIXL_MASK 0x0002 /* DACL_TO_SPKMIXL */ -#define WM8993_DACL_TO_SPKMIXL_SHIFT 1 /* DACL_TO_SPKMIXL */ -#define WM8993_DACL_TO_SPKMIXL_WIDTH 1 /* DACL_TO_SPKMIXL */ -#define WM8993_DACR_TO_SPKMIXR 0x0001 /* DACR_TO_SPKMIXR */ -#define WM8993_DACR_TO_SPKMIXR_MASK 0x0001 /* DACR_TO_SPKMIXR */ -#define WM8993_DACR_TO_SPKMIXR_SHIFT 0 /* DACR_TO_SPKMIXR */ -#define WM8993_DACR_TO_SPKMIXR_WIDTH 1 /* DACR_TO_SPKMIXR */ - -/* - * R55 (0x37) - Additional Control - */ -#define WM8993_LINEOUT1_FB 0x0080 /* LINEOUT1_FB */ -#define WM8993_LINEOUT1_FB_MASK 0x0080 /* LINEOUT1_FB */ -#define WM8993_LINEOUT1_FB_SHIFT 7 /* LINEOUT1_FB */ -#define WM8993_LINEOUT1_FB_WIDTH 1 /* LINEOUT1_FB */ -#define WM8993_LINEOUT2_FB 0x0040 /* LINEOUT2_FB */ -#define WM8993_LINEOUT2_FB_MASK 0x0040 /* LINEOUT2_FB */ -#define WM8993_LINEOUT2_FB_SHIFT 6 /* LINEOUT2_FB */ -#define WM8993_LINEOUT2_FB_WIDTH 1 /* LINEOUT2_FB */ -#define WM8993_VROI 0x0001 /* VROI */ -#define WM8993_VROI_MASK 0x0001 /* VROI */ -#define WM8993_VROI_SHIFT 0 /* VROI */ -#define WM8993_VROI_WIDTH 1 /* VROI */ - -/* - * R56 (0x38) - AntiPOP1 - */ -#define WM8993_LINEOUT_VMID_BUF_ENA 0x0080 /* LINEOUT_VMID_BUF_ENA */ -#define WM8993_LINEOUT_VMID_BUF_ENA_MASK 0x0080 /* LINEOUT_VMID_BUF_ENA */ -#define WM8993_LINEOUT_VMID_BUF_ENA_SHIFT 7 /* LINEOUT_VMID_BUF_ENA */ -#define WM8993_LINEOUT_VMID_BUF_ENA_WIDTH 1 /* LINEOUT_VMID_BUF_ENA */ -#define WM8993_HPOUT2_IN_ENA 0x0040 /* HPOUT2_IN_ENA */ -#define WM8993_HPOUT2_IN_ENA_MASK 0x0040 /* HPOUT2_IN_ENA */ -#define WM8993_HPOUT2_IN_ENA_SHIFT 6 /* HPOUT2_IN_ENA */ -#define WM8993_HPOUT2_IN_ENA_WIDTH 1 /* HPOUT2_IN_ENA */ -#define WM8993_LINEOUT1_DISCH 0x0020 /* LINEOUT1_DISCH */ -#define WM8993_LINEOUT1_DISCH_MASK 0x0020 /* LINEOUT1_DISCH */ -#define WM8993_LINEOUT1_DISCH_SHIFT 5 /* LINEOUT1_DISCH */ -#define WM8993_LINEOUT1_DISCH_WIDTH 1 /* LINEOUT1_DISCH */ -#define WM8993_LINEOUT2_DISCH 0x0010 /* LINEOUT2_DISCH */ -#define WM8993_LINEOUT2_DISCH_MASK 0x0010 /* LINEOUT2_DISCH */ -#define WM8993_LINEOUT2_DISCH_SHIFT 4 /* LINEOUT2_DISCH */ -#define WM8993_LINEOUT2_DISCH_WIDTH 1 /* LINEOUT2_DISCH */ - -/* - * R57 (0x39) - AntiPOP2 - */ -#define WM8993_VMID_RAMP_MASK 0x0060 /* VMID_RAMP - [6:5] */ -#define WM8993_VMID_RAMP_SHIFT 5 /* VMID_RAMP - [6:5] */ -#define WM8993_VMID_RAMP_WIDTH 2 /* VMID_RAMP - [6:5] */ -#define WM8993_VMID_BUF_ENA 0x0008 /* VMID_BUF_ENA */ -#define WM8993_VMID_BUF_ENA_MASK 0x0008 /* VMID_BUF_ENA */ -#define WM8993_VMID_BUF_ENA_SHIFT 3 /* VMID_BUF_ENA */ -#define WM8993_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */ -#define WM8993_STARTUP_BIAS_ENA 0x0004 /* STARTUP_BIAS_ENA */ -#define WM8993_STARTUP_BIAS_ENA_MASK 0x0004 /* STARTUP_BIAS_ENA */ -#define WM8993_STARTUP_BIAS_ENA_SHIFT 2 /* STARTUP_BIAS_ENA */ -#define WM8993_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */ -#define WM8993_BIAS_SRC 0x0002 /* BIAS_SRC */ -#define WM8993_BIAS_SRC_MASK 0x0002 /* BIAS_SRC */ -#define WM8993_BIAS_SRC_SHIFT 1 /* BIAS_SRC */ -#define WM8993_BIAS_SRC_WIDTH 1 /* BIAS_SRC */ -#define WM8993_VMID_DISCH 0x0001 /* VMID_DISCH */ -#define WM8993_VMID_DISCH_MASK 0x0001 /* VMID_DISCH */ -#define WM8993_VMID_DISCH_SHIFT 0 /* VMID_DISCH */ -#define WM8993_VMID_DISCH_WIDTH 1 /* VMID_DISCH */ - -/* - * R58 (0x3A) - MICBIAS - */ -#define WM8993_JD_SCTHR_MASK 0x00C0 /* JD_SCTHR - [7:6] */ -#define WM8993_JD_SCTHR_SHIFT 6 /* JD_SCTHR - [7:6] */ -#define WM8993_JD_SCTHR_WIDTH 2 /* JD_SCTHR - [7:6] */ -#define WM8993_JD_THR_MASK 0x0030 /* JD_THR - [5:4] */ -#define WM8993_JD_THR_SHIFT 4 /* JD_THR - [5:4] */ -#define WM8993_JD_THR_WIDTH 2 /* JD_THR - [5:4] */ -#define WM8993_JD_ENA 0x0004 /* JD_ENA */ -#define WM8993_JD_ENA_MASK 0x0004 /* JD_ENA */ -#define WM8993_JD_ENA_SHIFT 2 /* JD_ENA */ -#define WM8993_JD_ENA_WIDTH 1 /* JD_ENA */ -#define WM8993_MICB2_LVL 0x0002 /* MICB2_LVL */ -#define WM8993_MICB2_LVL_MASK 0x0002 /* MICB2_LVL */ -#define WM8993_MICB2_LVL_SHIFT 1 /* MICB2_LVL */ -#define WM8993_MICB2_LVL_WIDTH 1 /* MICB2_LVL */ -#define WM8993_MICB1_LVL 0x0001 /* MICB1_LVL */ -#define WM8993_MICB1_LVL_MASK 0x0001 /* MICB1_LVL */ -#define WM8993_MICB1_LVL_SHIFT 0 /* MICB1_LVL */ -#define WM8993_MICB1_LVL_WIDTH 1 /* MICB1_LVL */ - -/* - * R60 (0x3C) - FLL Control 1 - */ -#define WM8993_FLL_FRAC 0x0004 /* FLL_FRAC */ -#define WM8993_FLL_FRAC_MASK 0x0004 /* FLL_FRAC */ -#define WM8993_FLL_FRAC_SHIFT 2 /* FLL_FRAC */ -#define WM8993_FLL_FRAC_WIDTH 1 /* FLL_FRAC */ -#define WM8993_FLL_OSC_ENA 0x0002 /* FLL_OSC_ENA */ -#define WM8993_FLL_OSC_ENA_MASK 0x0002 /* FLL_OSC_ENA */ -#define WM8993_FLL_OSC_ENA_SHIFT 1 /* FLL_OSC_ENA */ -#define WM8993_FLL_OSC_ENA_WIDTH 1 /* FLL_OSC_ENA */ -#define WM8993_FLL_ENA 0x0001 /* FLL_ENA */ -#define WM8993_FLL_ENA_MASK 0x0001 /* FLL_ENA */ -#define WM8993_FLL_ENA_SHIFT 0 /* FLL_ENA */ -#define WM8993_FLL_ENA_WIDTH 1 /* FLL_ENA */ - -/* - * R61 (0x3D) - FLL Control 2 - */ -#define WM8993_FLL_OUTDIV_MASK 0x0700 /* FLL_OUTDIV - [10:8] */ -#define WM8993_FLL_OUTDIV_SHIFT 8 /* FLL_OUTDIV - [10:8] */ -#define WM8993_FLL_OUTDIV_WIDTH 3 /* FLL_OUTDIV - [10:8] */ -#define WM8993_FLL_CTRL_RATE_MASK 0x0070 /* FLL_CTRL_RATE - [6:4] */ -#define WM8993_FLL_CTRL_RATE_SHIFT 4 /* FLL_CTRL_RATE - [6:4] */ -#define WM8993_FLL_CTRL_RATE_WIDTH 3 /* FLL_CTRL_RATE - [6:4] */ -#define WM8993_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */ -#define WM8993_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */ -#define WM8993_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */ - -/* - * R62 (0x3E) - FLL Control 3 - */ -#define WM8993_FLL_K_MASK 0xFFFF /* FLL_K - [15:0] */ -#define WM8993_FLL_K_SHIFT 0 /* FLL_K - [15:0] */ -#define WM8993_FLL_K_WIDTH 16 /* FLL_K - [15:0] */ - -/* - * R63 (0x3F) - FLL Control 4 - */ -#define WM8993_FLL_N_MASK 0x7FE0 /* FLL_N - [14:5] */ -#define WM8993_FLL_N_SHIFT 5 /* FLL_N - [14:5] */ -#define WM8993_FLL_N_WIDTH 10 /* FLL_N - [14:5] */ -#define WM8993_FLL_GAIN_MASK 0x000F /* FLL_GAIN - [3:0] */ -#define WM8993_FLL_GAIN_SHIFT 0 /* FLL_GAIN - [3:0] */ -#define WM8993_FLL_GAIN_WIDTH 4 /* FLL_GAIN - [3:0] */ - -/* - * R64 (0x40) - FLL Control 5 - */ -#define WM8993_FLL_FRC_NCO_VAL_MASK 0x1F80 /* FLL_FRC_NCO_VAL - [12:7] */ -#define WM8993_FLL_FRC_NCO_VAL_SHIFT 7 /* FLL_FRC_NCO_VAL - [12:7] */ -#define WM8993_FLL_FRC_NCO_VAL_WIDTH 6 /* FLL_FRC_NCO_VAL - [12:7] */ -#define WM8993_FLL_FRC_NCO 0x0040 /* FLL_FRC_NCO */ -#define WM8993_FLL_FRC_NCO_MASK 0x0040 /* FLL_FRC_NCO */ -#define WM8993_FLL_FRC_NCO_SHIFT 6 /* FLL_FRC_NCO */ -#define WM8993_FLL_FRC_NCO_WIDTH 1 /* FLL_FRC_NCO */ -#define WM8993_FLL_CLK_REF_DIV_MASK 0x0018 /* FLL_CLK_REF_DIV - [4:3] */ -#define WM8993_FLL_CLK_REF_DIV_SHIFT 3 /* FLL_CLK_REF_DIV - [4:3] */ -#define WM8993_FLL_CLK_REF_DIV_WIDTH 2 /* FLL_CLK_REF_DIV - [4:3] */ -#define WM8993_FLL_CLK_SRC_MASK 0x0003 /* FLL_CLK_SRC - [1:0] */ -#define WM8993_FLL_CLK_SRC_SHIFT 0 /* FLL_CLK_SRC - [1:0] */ -#define WM8993_FLL_CLK_SRC_WIDTH 2 /* FLL_CLK_SRC - [1:0] */ - -/* - * R65 (0x41) - Clocking 3 - */ -#define WM8993_CLK_DCS_DIV_MASK 0x3C00 /* CLK_DCS_DIV - [13:10] */ -#define WM8993_CLK_DCS_DIV_SHIFT 10 /* CLK_DCS_DIV - [13:10] */ -#define WM8993_CLK_DCS_DIV_WIDTH 4 /* CLK_DCS_DIV - [13:10] */ -#define WM8993_SAMPLE_RATE_MASK 0x0380 /* SAMPLE_RATE - [9:7] */ -#define WM8993_SAMPLE_RATE_SHIFT 7 /* SAMPLE_RATE - [9:7] */ -#define WM8993_SAMPLE_RATE_WIDTH 3 /* SAMPLE_RATE - [9:7] */ -#define WM8993_CLK_SYS_RATE_MASK 0x001E /* CLK_SYS_RATE - [4:1] */ -#define WM8993_CLK_SYS_RATE_SHIFT 1 /* CLK_SYS_RATE - [4:1] */ -#define WM8993_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [4:1] */ -#define WM8993_CLK_DSP_ENA 0x0001 /* CLK_DSP_ENA */ -#define WM8993_CLK_DSP_ENA_MASK 0x0001 /* CLK_DSP_ENA */ -#define WM8993_CLK_DSP_ENA_SHIFT 0 /* CLK_DSP_ENA */ -#define WM8993_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */ - -/* - * R66 (0x42) - Clocking 4 - */ -#define WM8993_DAC_DIV4 0x0200 /* DAC_DIV4 */ -#define WM8993_DAC_DIV4_MASK 0x0200 /* DAC_DIV4 */ -#define WM8993_DAC_DIV4_SHIFT 9 /* DAC_DIV4 */ -#define WM8993_DAC_DIV4_WIDTH 1 /* DAC_DIV4 */ -#define WM8993_CLK_256K_DIV_MASK 0x007E /* CLK_256K_DIV - [6:1] */ -#define WM8993_CLK_256K_DIV_SHIFT 1 /* CLK_256K_DIV - [6:1] */ -#define WM8993_CLK_256K_DIV_WIDTH 6 /* CLK_256K_DIV - [6:1] */ -#define WM8993_SR_MODE 0x0001 /* SR_MODE */ -#define WM8993_SR_MODE_MASK 0x0001 /* SR_MODE */ -#define WM8993_SR_MODE_SHIFT 0 /* SR_MODE */ -#define WM8993_SR_MODE_WIDTH 1 /* SR_MODE */ - -/* - * R67 (0x43) - MW Slave Control - */ -#define WM8993_MASK_WRITE_ENA 0x0001 /* MASK_WRITE_ENA */ -#define WM8993_MASK_WRITE_ENA_MASK 0x0001 /* MASK_WRITE_ENA */ -#define WM8993_MASK_WRITE_ENA_SHIFT 0 /* MASK_WRITE_ENA */ -#define WM8993_MASK_WRITE_ENA_WIDTH 1 /* MASK_WRITE_ENA */ - -/* - * R69 (0x45) - Bus Control 1 - */ -#define WM8993_CLK_SYS_ENA 0x0002 /* CLK_SYS_ENA */ -#define WM8993_CLK_SYS_ENA_MASK 0x0002 /* CLK_SYS_ENA */ -#define WM8993_CLK_SYS_ENA_SHIFT 1 /* CLK_SYS_ENA */ -#define WM8993_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */ - -/* - * R70 (0x46) - Write Sequencer 0 - */ -#define WM8993_WSEQ_ENA 0x0100 /* WSEQ_ENA */ -#define WM8993_WSEQ_ENA_MASK 0x0100 /* WSEQ_ENA */ -#define WM8993_WSEQ_ENA_SHIFT 8 /* WSEQ_ENA */ -#define WM8993_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */ -#define WM8993_WSEQ_WRITE_INDEX_MASK 0x001F /* WSEQ_WRITE_INDEX - [4:0] */ -#define WM8993_WSEQ_WRITE_INDEX_SHIFT 0 /* WSEQ_WRITE_INDEX - [4:0] */ -#define WM8993_WSEQ_WRITE_INDEX_WIDTH 5 /* WSEQ_WRITE_INDEX - [4:0] */ - -/* - * R71 (0x47) - Write Sequencer 1 - */ -#define WM8993_WSEQ_DATA_WIDTH_MASK 0x7000 /* WSEQ_DATA_WIDTH - [14:12] */ -#define WM8993_WSEQ_DATA_WIDTH_SHIFT 12 /* WSEQ_DATA_WIDTH - [14:12] */ -#define WM8993_WSEQ_DATA_WIDTH_WIDTH 3 /* WSEQ_DATA_WIDTH - [14:12] */ -#define WM8993_WSEQ_DATA_START_MASK 0x0F00 /* WSEQ_DATA_START - [11:8] */ -#define WM8993_WSEQ_DATA_START_SHIFT 8 /* WSEQ_DATA_START - [11:8] */ -#define WM8993_WSEQ_DATA_START_WIDTH 4 /* WSEQ_DATA_START - [11:8] */ -#define WM8993_WSEQ_ADDR_MASK 0x00FF /* WSEQ_ADDR - [7:0] */ -#define WM8993_WSEQ_ADDR_SHIFT 0 /* WSEQ_ADDR - [7:0] */ -#define WM8993_WSEQ_ADDR_WIDTH 8 /* WSEQ_ADDR - [7:0] */ - -/* - * R72 (0x48) - Write Sequencer 2 - */ -#define WM8993_WSEQ_EOS 0x4000 /* WSEQ_EOS */ -#define WM8993_WSEQ_EOS_MASK 0x4000 /* WSEQ_EOS */ -#define WM8993_WSEQ_EOS_SHIFT 14 /* WSEQ_EOS */ -#define WM8993_WSEQ_EOS_WIDTH 1 /* WSEQ_EOS */ -#define WM8993_WSEQ_DELAY_MASK 0x0F00 /* WSEQ_DELAY - [11:8] */ -#define WM8993_WSEQ_DELAY_SHIFT 8 /* WSEQ_DELAY - [11:8] */ -#define WM8993_WSEQ_DELAY_WIDTH 4 /* WSEQ_DELAY - [11:8] */ -#define WM8993_WSEQ_DATA_MASK 0x00FF /* WSEQ_DATA - [7:0] */ -#define WM8993_WSEQ_DATA_SHIFT 0 /* WSEQ_DATA - [7:0] */ -#define WM8993_WSEQ_DATA_WIDTH 8 /* WSEQ_DATA - [7:0] */ - -/* - * R73 (0x49) - Write Sequencer 3 - */ -#define WM8993_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */ -#define WM8993_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */ -#define WM8993_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */ -#define WM8993_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */ -#define WM8993_WSEQ_START 0x0100 /* WSEQ_START */ -#define WM8993_WSEQ_START_MASK 0x0100 /* WSEQ_START */ -#define WM8993_WSEQ_START_SHIFT 8 /* WSEQ_START */ -#define WM8993_WSEQ_START_WIDTH 1 /* WSEQ_START */ -#define WM8993_WSEQ_START_INDEX_MASK 0x003F /* WSEQ_START_INDEX - [5:0] */ -#define WM8993_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [5:0] */ -#define WM8993_WSEQ_START_INDEX_WIDTH 6 /* WSEQ_START_INDEX - [5:0] */ - -/* - * R74 (0x4A) - Write Sequencer 4 - */ -#define WM8993_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */ -#define WM8993_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */ -#define WM8993_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */ -#define WM8993_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */ - -/* - * R75 (0x4B) - Write Sequencer 5 - */ -#define WM8993_WSEQ_CURRENT_INDEX_MASK 0x003F /* WSEQ_CURRENT_INDEX - [5:0] */ -#define WM8993_WSEQ_CURRENT_INDEX_SHIFT 0 /* WSEQ_CURRENT_INDEX - [5:0] */ -#define WM8993_WSEQ_CURRENT_INDEX_WIDTH 6 /* WSEQ_CURRENT_INDEX - [5:0] */ - -/* - * R76 (0x4C) - Charge Pump 1 - */ -#define WM8993_CP_ENA 0x8000 /* CP_ENA */ -#define WM8993_CP_ENA_MASK 0x8000 /* CP_ENA */ -#define WM8993_CP_ENA_SHIFT 15 /* CP_ENA */ -#define WM8993_CP_ENA_WIDTH 1 /* CP_ENA */ - -/* - * R81 (0x51) - Class W 0 - */ -#define WM8993_CP_DYN_FREQ 0x0002 /* CP_DYN_FREQ */ -#define WM8993_CP_DYN_FREQ_MASK 0x0002 /* CP_DYN_FREQ */ -#define WM8993_CP_DYN_FREQ_SHIFT 1 /* CP_DYN_FREQ */ -#define WM8993_CP_DYN_FREQ_WIDTH 1 /* CP_DYN_FREQ */ -#define WM8993_CP_DYN_V 0x0001 /* CP_DYN_V */ -#define WM8993_CP_DYN_V_MASK 0x0001 /* CP_DYN_V */ -#define WM8993_CP_DYN_V_SHIFT 0 /* CP_DYN_V */ -#define WM8993_CP_DYN_V_WIDTH 1 /* CP_DYN_V */ - -/* - * R84 (0x54) - DC Servo 0 - */ -#define WM8993_DCS_TRIG_SINGLE_1 0x2000 /* DCS_TRIG_SINGLE_1 */ -#define WM8993_DCS_TRIG_SINGLE_1_MASK 0x2000 /* DCS_TRIG_SINGLE_1 */ -#define WM8993_DCS_TRIG_SINGLE_1_SHIFT 13 /* DCS_TRIG_SINGLE_1 */ -#define WM8993_DCS_TRIG_SINGLE_1_WIDTH 1 /* DCS_TRIG_SINGLE_1 */ -#define WM8993_DCS_TRIG_SINGLE_0 0x1000 /* DCS_TRIG_SINGLE_0 */ -#define WM8993_DCS_TRIG_SINGLE_0_MASK 0x1000 /* DCS_TRIG_SINGLE_0 */ -#define WM8993_DCS_TRIG_SINGLE_0_SHIFT 12 /* DCS_TRIG_SINGLE_0 */ -#define WM8993_DCS_TRIG_SINGLE_0_WIDTH 1 /* DCS_TRIG_SINGLE_0 */ -#define WM8993_DCS_TRIG_SERIES_1 0x0200 /* DCS_TRIG_SERIES_1 */ -#define WM8993_DCS_TRIG_SERIES_1_MASK 0x0200 /* DCS_TRIG_SERIES_1 */ -#define WM8993_DCS_TRIG_SERIES_1_SHIFT 9 /* DCS_TRIG_SERIES_1 */ -#define WM8993_DCS_TRIG_SERIES_1_WIDTH 1 /* DCS_TRIG_SERIES_1 */ -#define WM8993_DCS_TRIG_SERIES_0 0x0100 /* DCS_TRIG_SERIES_0 */ -#define WM8993_DCS_TRIG_SERIES_0_MASK 0x0100 /* DCS_TRIG_SERIES_0 */ -#define WM8993_DCS_TRIG_SERIES_0_SHIFT 8 /* DCS_TRIG_SERIES_0 */ -#define WM8993_DCS_TRIG_SERIES_0_WIDTH 1 /* DCS_TRIG_SERIES_0 */ -#define WM8993_DCS_TRIG_STARTUP_1 0x0020 /* DCS_TRIG_STARTUP_1 */ -#define WM8993_DCS_TRIG_STARTUP_1_MASK 0x0020 /* DCS_TRIG_STARTUP_1 */ -#define WM8993_DCS_TRIG_STARTUP_1_SHIFT 5 /* DCS_TRIG_STARTUP_1 */ -#define WM8993_DCS_TRIG_STARTUP_1_WIDTH 1 /* DCS_TRIG_STARTUP_1 */ -#define WM8993_DCS_TRIG_STARTUP_0 0x0010 /* DCS_TRIG_STARTUP_0 */ -#define WM8993_DCS_TRIG_STARTUP_0_MASK 0x0010 /* DCS_TRIG_STARTUP_0 */ -#define WM8993_DCS_TRIG_STARTUP_0_SHIFT 4 /* DCS_TRIG_STARTUP_0 */ -#define WM8993_DCS_TRIG_STARTUP_0_WIDTH 1 /* DCS_TRIG_STARTUP_0 */ -#define WM8993_DCS_TRIG_DAC_WR_1 0x0008 /* DCS_TRIG_DAC_WR_1 */ -#define WM8993_DCS_TRIG_DAC_WR_1_MASK 0x0008 /* DCS_TRIG_DAC_WR_1 */ -#define WM8993_DCS_TRIG_DAC_WR_1_SHIFT 3 /* DCS_TRIG_DAC_WR_1 */ -#define WM8993_DCS_TRIG_DAC_WR_1_WIDTH 1 /* DCS_TRIG_DAC_WR_1 */ -#define WM8993_DCS_TRIG_DAC_WR_0 0x0004 /* DCS_TRIG_DAC_WR_0 */ -#define WM8993_DCS_TRIG_DAC_WR_0_MASK 0x0004 /* DCS_TRIG_DAC_WR_0 */ -#define WM8993_DCS_TRIG_DAC_WR_0_SHIFT 2 /* DCS_TRIG_DAC_WR_0 */ -#define WM8993_DCS_TRIG_DAC_WR_0_WIDTH 1 /* DCS_TRIG_DAC_WR_0 */ -#define WM8993_DCS_ENA_CHAN_1 0x0002 /* DCS_ENA_CHAN_1 */ -#define WM8993_DCS_ENA_CHAN_1_MASK 0x0002 /* DCS_ENA_CHAN_1 */ -#define WM8993_DCS_ENA_CHAN_1_SHIFT 1 /* DCS_ENA_CHAN_1 */ -#define WM8993_DCS_ENA_CHAN_1_WIDTH 1 /* DCS_ENA_CHAN_1 */ -#define WM8993_DCS_ENA_CHAN_0 0x0001 /* DCS_ENA_CHAN_0 */ -#define WM8993_DCS_ENA_CHAN_0_MASK 0x0001 /* DCS_ENA_CHAN_0 */ -#define WM8993_DCS_ENA_CHAN_0_SHIFT 0 /* DCS_ENA_CHAN_0 */ -#define WM8993_DCS_ENA_CHAN_0_WIDTH 1 /* DCS_ENA_CHAN_0 */ - -/* - * R85 (0x55) - DC Servo 1 - */ -#define WM8993_DCS_SERIES_NO_01_MASK 0x0FE0 /* DCS_SERIES_NO_01 - [11:5] */ -#define WM8993_DCS_SERIES_NO_01_SHIFT 5 /* DCS_SERIES_NO_01 - [11:5] */ -#define WM8993_DCS_SERIES_NO_01_WIDTH 7 /* DCS_SERIES_NO_01 - [11:5] */ -#define WM8993_DCS_TIMER_PERIOD_01_MASK 0x000F /* DCS_TIMER_PERIOD_01 - [3:0] */ -#define WM8993_DCS_TIMER_PERIOD_01_SHIFT 0 /* DCS_TIMER_PERIOD_01 - [3:0] */ -#define WM8993_DCS_TIMER_PERIOD_01_WIDTH 4 /* DCS_TIMER_PERIOD_01 - [3:0] */ - -/* - * R87 (0x57) - DC Servo 3 - */ -#define WM8993_DCS_DAC_WR_VAL_1_MASK 0xFF00 /* DCS_DAC_WR_VAL_1 - [15:8] */ -#define WM8993_DCS_DAC_WR_VAL_1_SHIFT 8 /* DCS_DAC_WR_VAL_1 - [15:8] */ -#define WM8993_DCS_DAC_WR_VAL_1_WIDTH 8 /* DCS_DAC_WR_VAL_1 - [15:8] */ -#define WM8993_DCS_DAC_WR_VAL_0_MASK 0x00FF /* DCS_DAC_WR_VAL_0 - [7:0] */ -#define WM8993_DCS_DAC_WR_VAL_0_SHIFT 0 /* DCS_DAC_WR_VAL_0 - [7:0] */ -#define WM8993_DCS_DAC_WR_VAL_0_WIDTH 8 /* DCS_DAC_WR_VAL_0 - [7:0] */ - -/* - * R88 (0x58) - DC Servo Readback 0 - */ -#define WM8993_DCS_DATAPATH_BUSY 0x4000 /* DCS_DATAPATH_BUSY */ -#define WM8993_DCS_DATAPATH_BUSY_MASK 0x4000 /* DCS_DATAPATH_BUSY */ -#define WM8993_DCS_DATAPATH_BUSY_SHIFT 14 /* DCS_DATAPATH_BUSY */ -#define WM8993_DCS_DATAPATH_BUSY_WIDTH 1 /* DCS_DATAPATH_BUSY */ -#define WM8993_DCS_CHANNEL_MASK 0x3000 /* DCS_CHANNEL - [13:12] */ -#define WM8993_DCS_CHANNEL_SHIFT 12 /* DCS_CHANNEL - [13:12] */ -#define WM8993_DCS_CHANNEL_WIDTH 2 /* DCS_CHANNEL - [13:12] */ -#define WM8993_DCS_CAL_COMPLETE_MASK 0x0300 /* DCS_CAL_COMPLETE - [9:8] */ -#define WM8993_DCS_CAL_COMPLETE_SHIFT 8 /* DCS_CAL_COMPLETE - [9:8] */ -#define WM8993_DCS_CAL_COMPLETE_WIDTH 2 /* DCS_CAL_COMPLETE - [9:8] */ -#define WM8993_DCS_DAC_WR_COMPLETE_MASK 0x0030 /* DCS_DAC_WR_COMPLETE - [5:4] */ -#define WM8993_DCS_DAC_WR_COMPLETE_SHIFT 4 /* DCS_DAC_WR_COMPLETE - [5:4] */ -#define WM8993_DCS_DAC_WR_COMPLETE_WIDTH 2 /* DCS_DAC_WR_COMPLETE - [5:4] */ -#define WM8993_DCS_STARTUP_COMPLETE_MASK 0x0003 /* DCS_STARTUP_COMPLETE - [1:0] */ -#define WM8993_DCS_STARTUP_COMPLETE_SHIFT 0 /* DCS_STARTUP_COMPLETE - [1:0] */ -#define WM8993_DCS_STARTUP_COMPLETE_WIDTH 2 /* DCS_STARTUP_COMPLETE - [1:0] */ - -/* - * R89 (0x59) - DC Servo Readback 1 - */ -#define WM8993_DCS_INTEG_CHAN_1_MASK 0x00FF /* DCS_INTEG_CHAN_1 - [7:0] */ -#define WM8993_DCS_INTEG_CHAN_1_SHIFT 0 /* DCS_INTEG_CHAN_1 - [7:0] */ -#define WM8993_DCS_INTEG_CHAN_1_WIDTH 8 /* DCS_INTEG_CHAN_1 - [7:0] */ - -/* - * R90 (0x5A) - DC Servo Readback 2 - */ -#define WM8993_DCS_INTEG_CHAN_0_MASK 0x00FF /* DCS_INTEG_CHAN_0 - [7:0] */ -#define WM8993_DCS_INTEG_CHAN_0_SHIFT 0 /* DCS_INTEG_CHAN_0 - [7:0] */ -#define WM8993_DCS_INTEG_CHAN_0_WIDTH 8 /* DCS_INTEG_CHAN_0 - [7:0] */ - -/* - * R96 (0x60) - Analogue HP 0 - */ -#define WM8993_HPOUT1_AUTO_PU 0x0100 /* HPOUT1_AUTO_PU */ -#define WM8993_HPOUT1_AUTO_PU_MASK 0x0100 /* HPOUT1_AUTO_PU */ -#define WM8993_HPOUT1_AUTO_PU_SHIFT 8 /* HPOUT1_AUTO_PU */ -#define WM8993_HPOUT1_AUTO_PU_WIDTH 1 /* HPOUT1_AUTO_PU */ -#define WM8993_HPOUT1L_RMV_SHORT 0x0080 /* HPOUT1L_RMV_SHORT */ -#define WM8993_HPOUT1L_RMV_SHORT_MASK 0x0080 /* HPOUT1L_RMV_SHORT */ -#define WM8993_HPOUT1L_RMV_SHORT_SHIFT 7 /* HPOUT1L_RMV_SHORT */ -#define WM8993_HPOUT1L_RMV_SHORT_WIDTH 1 /* HPOUT1L_RMV_SHORT */ -#define WM8993_HPOUT1L_OUTP 0x0040 /* HPOUT1L_OUTP */ -#define WM8993_HPOUT1L_OUTP_MASK 0x0040 /* HPOUT1L_OUTP */ -#define WM8993_HPOUT1L_OUTP_SHIFT 6 /* HPOUT1L_OUTP */ -#define WM8993_HPOUT1L_OUTP_WIDTH 1 /* HPOUT1L_OUTP */ -#define WM8993_HPOUT1L_DLY 0x0020 /* HPOUT1L_DLY */ -#define WM8993_HPOUT1L_DLY_MASK 0x0020 /* HPOUT1L_DLY */ -#define WM8993_HPOUT1L_DLY_SHIFT 5 /* HPOUT1L_DLY */ -#define WM8993_HPOUT1L_DLY_WIDTH 1 /* HPOUT1L_DLY */ -#define WM8993_HPOUT1R_RMV_SHORT 0x0008 /* HPOUT1R_RMV_SHORT */ -#define WM8993_HPOUT1R_RMV_SHORT_MASK 0x0008 /* HPOUT1R_RMV_SHORT */ -#define WM8993_HPOUT1R_RMV_SHORT_SHIFT 3 /* HPOUT1R_RMV_SHORT */ -#define WM8993_HPOUT1R_RMV_SHORT_WIDTH 1 /* HPOUT1R_RMV_SHORT */ -#define WM8993_HPOUT1R_OUTP 0x0004 /* HPOUT1R_OUTP */ -#define WM8993_HPOUT1R_OUTP_MASK 0x0004 /* HPOUT1R_OUTP */ -#define WM8993_HPOUT1R_OUTP_SHIFT 2 /* HPOUT1R_OUTP */ -#define WM8993_HPOUT1R_OUTP_WIDTH 1 /* HPOUT1R_OUTP */ -#define WM8993_HPOUT1R_DLY 0x0002 /* HPOUT1R_DLY */ -#define WM8993_HPOUT1R_DLY_MASK 0x0002 /* HPOUT1R_DLY */ -#define WM8993_HPOUT1R_DLY_SHIFT 1 /* HPOUT1R_DLY */ -#define WM8993_HPOUT1R_DLY_WIDTH 1 /* HPOUT1R_DLY */ - -/* - * R98 (0x62) - EQ1 - */ -#define WM8993_EQ_ENA 0x0001 /* EQ_ENA */ -#define WM8993_EQ_ENA_MASK 0x0001 /* EQ_ENA */ -#define WM8993_EQ_ENA_SHIFT 0 /* EQ_ENA */ -#define WM8993_EQ_ENA_WIDTH 1 /* EQ_ENA */ - -/* - * R99 (0x63) - EQ2 - */ -#define WM8993_EQ_B1_GAIN_MASK 0x001F /* EQ_B1_GAIN - [4:0] */ -#define WM8993_EQ_B1_GAIN_SHIFT 0 /* EQ_B1_GAIN - [4:0] */ -#define WM8993_EQ_B1_GAIN_WIDTH 5 /* EQ_B1_GAIN - [4:0] */ - -/* - * R100 (0x64) - EQ3 - */ -#define WM8993_EQ_B2_GAIN_MASK 0x001F /* EQ_B2_GAIN - [4:0] */ -#define WM8993_EQ_B2_GAIN_SHIFT 0 /* EQ_B2_GAIN - [4:0] */ -#define WM8993_EQ_B2_GAIN_WIDTH 5 /* EQ_B2_GAIN - [4:0] */ - -/* - * R101 (0x65) - EQ4 - */ -#define WM8993_EQ_B3_GAIN_MASK 0x001F /* EQ_B3_GAIN - [4:0] */ -#define WM8993_EQ_B3_GAIN_SHIFT 0 /* EQ_B3_GAIN - [4:0] */ -#define WM8993_EQ_B3_GAIN_WIDTH 5 /* EQ_B3_GAIN - [4:0] */ - -/* - * R102 (0x66) - EQ5 - */ -#define WM8993_EQ_B4_GAIN_MASK 0x001F /* EQ_B4_GAIN - [4:0] */ -#define WM8993_EQ_B4_GAIN_SHIFT 0 /* EQ_B4_GAIN - [4:0] */ -#define WM8993_EQ_B4_GAIN_WIDTH 5 /* EQ_B4_GAIN - [4:0] */ - -/* - * R103 (0x67) - EQ6 - */ -#define WM8993_EQ_B5_GAIN_MASK 0x001F /* EQ_B5_GAIN - [4:0] */ -#define WM8993_EQ_B5_GAIN_SHIFT 0 /* EQ_B5_GAIN - [4:0] */ -#define WM8993_EQ_B5_GAIN_WIDTH 5 /* EQ_B5_GAIN - [4:0] */ - -/* - * R104 (0x68) - EQ7 - */ -#define WM8993_EQ_B1_A_MASK 0xFFFF /* EQ_B1_A - [15:0] */ -#define WM8993_EQ_B1_A_SHIFT 0 /* EQ_B1_A - [15:0] */ -#define WM8993_EQ_B1_A_WIDTH 16 /* EQ_B1_A - [15:0] */ - -/* - * R105 (0x69) - EQ8 - */ -#define WM8993_EQ_B1_B_MASK 0xFFFF /* EQ_B1_B - [15:0] */ -#define WM8993_EQ_B1_B_SHIFT 0 /* EQ_B1_B - [15:0] */ -#define WM8993_EQ_B1_B_WIDTH 16 /* EQ_B1_B - [15:0] */ - -/* - * R106 (0x6A) - EQ9 - */ -#define WM8993_EQ_B1_PG_MASK 0xFFFF /* EQ_B1_PG - [15:0] */ -#define WM8993_EQ_B1_PG_SHIFT 0 /* EQ_B1_PG - [15:0] */ -#define WM8993_EQ_B1_PG_WIDTH 16 /* EQ_B1_PG - [15:0] */ - -/* - * R107 (0x6B) - EQ10 - */ -#define WM8993_EQ_B2_A_MASK 0xFFFF /* EQ_B2_A - [15:0] */ -#define WM8993_EQ_B2_A_SHIFT 0 /* EQ_B2_A - [15:0] */ -#define WM8993_EQ_B2_A_WIDTH 16 /* EQ_B2_A - [15:0] */ - -/* - * R108 (0x6C) - EQ11 - */ -#define WM8993_EQ_B2_B_MASK 0xFFFF /* EQ_B2_B - [15:0] */ -#define WM8993_EQ_B2_B_SHIFT 0 /* EQ_B2_B - [15:0] */ -#define WM8993_EQ_B2_B_WIDTH 16 /* EQ_B2_B - [15:0] */ - -/* - * R109 (0x6D) - EQ12 - */ -#define WM8993_EQ_B2_C_MASK 0xFFFF /* EQ_B2_C - [15:0] */ -#define WM8993_EQ_B2_C_SHIFT 0 /* EQ_B2_C - [15:0] */ -#define WM8993_EQ_B2_C_WIDTH 16 /* EQ_B2_C - [15:0] */ - -/* - * R110 (0x6E) - EQ13 - */ -#define WM8993_EQ_B2_PG_MASK 0xFFFF /* EQ_B2_PG - [15:0] */ -#define WM8993_EQ_B2_PG_SHIFT 0 /* EQ_B2_PG - [15:0] */ -#define WM8993_EQ_B2_PG_WIDTH 16 /* EQ_B2_PG - [15:0] */ - -/* - * R111 (0x6F) - EQ14 - */ -#define WM8993_EQ_B3_A_MASK 0xFFFF /* EQ_B3_A - [15:0] */ -#define WM8993_EQ_B3_A_SHIFT 0 /* EQ_B3_A - [15:0] */ -#define WM8993_EQ_B3_A_WIDTH 16 /* EQ_B3_A - [15:0] */ - -/* - * R112 (0x70) - EQ15 - */ -#define WM8993_EQ_B3_B_MASK 0xFFFF /* EQ_B3_B - [15:0] */ -#define WM8993_EQ_B3_B_SHIFT 0 /* EQ_B3_B - [15:0] */ -#define WM8993_EQ_B3_B_WIDTH 16 /* EQ_B3_B - [15:0] */ - -/* - * R113 (0x71) - EQ16 - */ -#define WM8993_EQ_B3_C_MASK 0xFFFF /* EQ_B3_C - [15:0] */ -#define WM8993_EQ_B3_C_SHIFT 0 /* EQ_B3_C - [15:0] */ -#define WM8993_EQ_B3_C_WIDTH 16 /* EQ_B3_C - [15:0] */ - -/* - * R114 (0x72) - EQ17 - */ -#define WM8993_EQ_B3_PG_MASK 0xFFFF /* EQ_B3_PG - [15:0] */ -#define WM8993_EQ_B3_PG_SHIFT 0 /* EQ_B3_PG - [15:0] */ -#define WM8993_EQ_B3_PG_WIDTH 16 /* EQ_B3_PG - [15:0] */ - -/* - * R115 (0x73) - EQ18 - */ -#define WM8993_EQ_B4_A_MASK 0xFFFF /* EQ_B4_A - [15:0] */ -#define WM8993_EQ_B4_A_SHIFT 0 /* EQ_B4_A - [15:0] */ -#define WM8993_EQ_B4_A_WIDTH 16 /* EQ_B4_A - [15:0] */ - -/* - * R116 (0x74) - EQ19 - */ -#define WM8993_EQ_B4_B_MASK 0xFFFF /* EQ_B4_B - [15:0] */ -#define WM8993_EQ_B4_B_SHIFT 0 /* EQ_B4_B - [15:0] */ -#define WM8993_EQ_B4_B_WIDTH 16 /* EQ_B4_B - [15:0] */ - -/* - * R117 (0x75) - EQ20 - */ -#define WM8993_EQ_B4_C_MASK 0xFFFF /* EQ_B4_C - [15:0] */ -#define WM8993_EQ_B4_C_SHIFT 0 /* EQ_B4_C - [15:0] */ -#define WM8993_EQ_B4_C_WIDTH 16 /* EQ_B4_C - [15:0] */ - -/* - * R118 (0x76) - EQ21 - */ -#define WM8993_EQ_B4_PG_MASK 0xFFFF /* EQ_B4_PG - [15:0] */ -#define WM8993_EQ_B4_PG_SHIFT 0 /* EQ_B4_PG - [15:0] */ -#define WM8993_EQ_B4_PG_WIDTH 16 /* EQ_B4_PG - [15:0] */ - -/* - * R119 (0x77) - EQ22 - */ -#define WM8993_EQ_B5_A_MASK 0xFFFF /* EQ_B5_A - [15:0] */ -#define WM8993_EQ_B5_A_SHIFT 0 /* EQ_B5_A - [15:0] */ -#define WM8993_EQ_B5_A_WIDTH 16 /* EQ_B5_A - [15:0] */ - -/* - * R120 (0x78) - EQ23 - */ -#define WM8993_EQ_B5_B_MASK 0xFFFF /* EQ_B5_B - [15:0] */ -#define WM8993_EQ_B5_B_SHIFT 0 /* EQ_B5_B - [15:0] */ -#define WM8993_EQ_B5_B_WIDTH 16 /* EQ_B5_B - [15:0] */ - -/* - * R121 (0x79) - EQ24 - */ -#define WM8993_EQ_B5_PG_MASK 0xFFFF /* EQ_B5_PG - [15:0] */ -#define WM8993_EQ_B5_PG_SHIFT 0 /* EQ_B5_PG - [15:0] */ -#define WM8993_EQ_B5_PG_WIDTH 16 /* EQ_B5_PG - [15:0] */ - -/* - * R122 (0x7A) - Digital Pulls - */ -#define WM8993_MCLK_PU 0x0080 /* MCLK_PU */ -#define WM8993_MCLK_PU_MASK 0x0080 /* MCLK_PU */ -#define WM8993_MCLK_PU_SHIFT 7 /* MCLK_PU */ -#define WM8993_MCLK_PU_WIDTH 1 /* MCLK_PU */ -#define WM8993_MCLK_PD 0x0040 /* MCLK_PD */ -#define WM8993_MCLK_PD_MASK 0x0040 /* MCLK_PD */ -#define WM8993_MCLK_PD_SHIFT 6 /* MCLK_PD */ -#define WM8993_MCLK_PD_WIDTH 1 /* MCLK_PD */ -#define WM8993_DACDAT_PU 0x0020 /* DACDAT_PU */ -#define WM8993_DACDAT_PU_MASK 0x0020 /* DACDAT_PU */ -#define WM8993_DACDAT_PU_SHIFT 5 /* DACDAT_PU */ -#define WM8993_DACDAT_PU_WIDTH 1 /* DACDAT_PU */ -#define WM8993_DACDAT_PD 0x0010 /* DACDAT_PD */ -#define WM8993_DACDAT_PD_MASK 0x0010 /* DACDAT_PD */ -#define WM8993_DACDAT_PD_SHIFT 4 /* DACDAT_PD */ -#define WM8993_DACDAT_PD_WIDTH 1 /* DACDAT_PD */ -#define WM8993_LRCLK_PU 0x0008 /* LRCLK_PU */ -#define WM8993_LRCLK_PU_MASK 0x0008 /* LRCLK_PU */ -#define WM8993_LRCLK_PU_SHIFT 3 /* LRCLK_PU */ -#define WM8993_LRCLK_PU_WIDTH 1 /* LRCLK_PU */ -#define WM8993_LRCLK_PD 0x0004 /* LRCLK_PD */ -#define WM8993_LRCLK_PD_MASK 0x0004 /* LRCLK_PD */ -#define WM8993_LRCLK_PD_SHIFT 2 /* LRCLK_PD */ -#define WM8993_LRCLK_PD_WIDTH 1 /* LRCLK_PD */ -#define WM8993_BCLK_PU 0x0002 /* BCLK_PU */ -#define WM8993_BCLK_PU_MASK 0x0002 /* BCLK_PU */ -#define WM8993_BCLK_PU_SHIFT 1 /* BCLK_PU */ -#define WM8993_BCLK_PU_WIDTH 1 /* BCLK_PU */ -#define WM8993_BCLK_PD 0x0001 /* BCLK_PD */ -#define WM8993_BCLK_PD_MASK 0x0001 /* BCLK_PD */ -#define WM8993_BCLK_PD_SHIFT 0 /* BCLK_PD */ -#define WM8993_BCLK_PD_WIDTH 1 /* BCLK_PD */ - -/* - * R123 (0x7B) - DRC Control 1 - */ -#define WM8993_DRC_ENA 0x8000 /* DRC_ENA */ -#define WM8993_DRC_ENA_MASK 0x8000 /* DRC_ENA */ -#define WM8993_DRC_ENA_SHIFT 15 /* DRC_ENA */ -#define WM8993_DRC_ENA_WIDTH 1 /* DRC_ENA */ -#define WM8993_DRC_DAC_PATH 0x4000 /* DRC_DAC_PATH */ -#define WM8993_DRC_DAC_PATH_MASK 0x4000 /* DRC_DAC_PATH */ -#define WM8993_DRC_DAC_PATH_SHIFT 14 /* DRC_DAC_PATH */ -#define WM8993_DRC_DAC_PATH_WIDTH 1 /* DRC_DAC_PATH */ -#define WM8993_DRC_SMOOTH_ENA 0x0800 /* DRC_SMOOTH_ENA */ -#define WM8993_DRC_SMOOTH_ENA_MASK 0x0800 /* DRC_SMOOTH_ENA */ -#define WM8993_DRC_SMOOTH_ENA_SHIFT 11 /* DRC_SMOOTH_ENA */ -#define WM8993_DRC_SMOOTH_ENA_WIDTH 1 /* DRC_SMOOTH_ENA */ -#define WM8993_DRC_QR_ENA 0x0400 /* DRC_QR_ENA */ -#define WM8993_DRC_QR_ENA_MASK 0x0400 /* DRC_QR_ENA */ -#define WM8993_DRC_QR_ENA_SHIFT 10 /* DRC_QR_ENA */ -#define WM8993_DRC_QR_ENA_WIDTH 1 /* DRC_QR_ENA */ -#define WM8993_DRC_ANTICLIP_ENA 0x0200 /* DRC_ANTICLIP_ENA */ -#define WM8993_DRC_ANTICLIP_ENA_MASK 0x0200 /* DRC_ANTICLIP_ENA */ -#define WM8993_DRC_ANTICLIP_ENA_SHIFT 9 /* DRC_ANTICLIP_ENA */ -#define WM8993_DRC_ANTICLIP_ENA_WIDTH 1 /* DRC_ANTICLIP_ENA */ -#define WM8993_DRC_HYST_ENA 0x0100 /* DRC_HYST_ENA */ -#define WM8993_DRC_HYST_ENA_MASK 0x0100 /* DRC_HYST_ENA */ -#define WM8993_DRC_HYST_ENA_SHIFT 8 /* DRC_HYST_ENA */ -#define WM8993_DRC_HYST_ENA_WIDTH 1 /* DRC_HYST_ENA */ -#define WM8993_DRC_THRESH_HYST_MASK 0x0030 /* DRC_THRESH_HYST - [5:4] */ -#define WM8993_DRC_THRESH_HYST_SHIFT 4 /* DRC_THRESH_HYST - [5:4] */ -#define WM8993_DRC_THRESH_HYST_WIDTH 2 /* DRC_THRESH_HYST - [5:4] */ -#define WM8993_DRC_MINGAIN_MASK 0x000C /* DRC_MINGAIN - [3:2] */ -#define WM8993_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [3:2] */ -#define WM8993_DRC_MINGAIN_WIDTH 2 /* DRC_MINGAIN - [3:2] */ -#define WM8993_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */ -#define WM8993_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */ -#define WM8993_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */ - -/* - * R124 (0x7C) - DRC Control 2 - */ -#define WM8993_DRC_ATTACK_RATE_MASK 0xF000 /* DRC_ATTACK_RATE - [15:12] */ -#define WM8993_DRC_ATTACK_RATE_SHIFT 12 /* DRC_ATTACK_RATE - [15:12] */ -#define WM8993_DRC_ATTACK_RATE_WIDTH 4 /* DRC_ATTACK_RATE - [15:12] */ -#define WM8993_DRC_DECAY_RATE_MASK 0x0F00 /* DRC_DECAY_RATE - [11:8] */ -#define WM8993_DRC_DECAY_RATE_SHIFT 8 /* DRC_DECAY_RATE - [11:8] */ -#define WM8993_DRC_DECAY_RATE_WIDTH 4 /* DRC_DECAY_RATE - [11:8] */ -#define WM8993_DRC_THRESH_COMP_MASK 0x00FC /* DRC_THRESH_COMP - [7:2] */ -#define WM8993_DRC_THRESH_COMP_SHIFT 2 /* DRC_THRESH_COMP - [7:2] */ -#define WM8993_DRC_THRESH_COMP_WIDTH 6 /* DRC_THRESH_COMP - [7:2] */ - -/* - * R125 (0x7D) - DRC Control 3 - */ -#define WM8993_DRC_AMP_COMP_MASK 0xF800 /* DRC_AMP_COMP - [15:11] */ -#define WM8993_DRC_AMP_COMP_SHIFT 11 /* DRC_AMP_COMP - [15:11] */ -#define WM8993_DRC_AMP_COMP_WIDTH 5 /* DRC_AMP_COMP - [15:11] */ -#define WM8993_DRC_R0_SLOPE_COMP_MASK 0x0700 /* DRC_R0_SLOPE_COMP - [10:8] */ -#define WM8993_DRC_R0_SLOPE_COMP_SHIFT 8 /* DRC_R0_SLOPE_COMP - [10:8] */ -#define WM8993_DRC_R0_SLOPE_COMP_WIDTH 3 /* DRC_R0_SLOPE_COMP - [10:8] */ -#define WM8993_DRC_FF_DELAY 0x0080 /* DRC_FF_DELAY */ -#define WM8993_DRC_FF_DELAY_MASK 0x0080 /* DRC_FF_DELAY */ -#define WM8993_DRC_FF_DELAY_SHIFT 7 /* DRC_FF_DELAY */ -#define WM8993_DRC_FF_DELAY_WIDTH 1 /* DRC_FF_DELAY */ -#define WM8993_DRC_THRESH_QR_MASK 0x000C /* DRC_THRESH_QR - [3:2] */ -#define WM8993_DRC_THRESH_QR_SHIFT 2 /* DRC_THRESH_QR - [3:2] */ -#define WM8993_DRC_THRESH_QR_WIDTH 2 /* DRC_THRESH_QR - [3:2] */ -#define WM8993_DRC_RATE_QR_MASK 0x0003 /* DRC_RATE_QR - [1:0] */ -#define WM8993_DRC_RATE_QR_SHIFT 0 /* DRC_RATE_QR - [1:0] */ -#define WM8993_DRC_RATE_QR_WIDTH 2 /* DRC_RATE_QR - [1:0] */ - -/* - * R126 (0x7E) - DRC Control 4 - */ -#define WM8993_DRC_R1_SLOPE_COMP_MASK 0xE000 /* DRC_R1_SLOPE_COMP - [15:13] */ -#define WM8993_DRC_R1_SLOPE_COMP_SHIFT 13 /* DRC_R1_SLOPE_COMP - [15:13] */ -#define WM8993_DRC_R1_SLOPE_COMP_WIDTH 3 /* DRC_R1_SLOPE_COMP - [15:13] */ -#define WM8993_DRC_STARTUP_GAIN_MASK 0x1F00 /* DRC_STARTUP_GAIN - [12:8] */ -#define WM8993_DRC_STARTUP_GAIN_SHIFT 8 /* DRC_STARTUP_GAIN - [12:8] */ -#define WM8993_DRC_STARTUP_GAIN_WIDTH 5 /* DRC_STARTUP_GAIN - [12:8] */ - -#endif diff --git a/trunk/sound/soc/codecs/wm9081.c b/trunk/sound/soc/codecs/wm9081.c index 156f2a4a5930..dbe20597d872 100644 --- a/trunk/sound/soc/codecs/wm9081.c +++ b/trunk/sound/soc/codecs/wm9081.c @@ -707,10 +707,6 @@ static int configure_clock(struct snd_soc_codec *codec) target > 3000000) break; } - - if (i == ARRAY_SIZE(clk_sys_rates)) - return -EINVAL; - } else if (wm9081->fs) { for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) { new_sysclk = clk_sys_rates[i].ratio @@ -718,10 +714,6 @@ static int configure_clock(struct snd_soc_codec *codec) if (new_sysclk > 3000000) break; } - - if (i == ARRAY_SIZE(clk_sys_rates)) - return -EINVAL; - } else { new_sysclk = 12288000; } diff --git a/trunk/sound/soc/davinci/Kconfig b/trunk/sound/soc/davinci/Kconfig index 6802dd5e4731..411a710be660 100644 --- a/trunk/sound/soc/davinci/Kconfig +++ b/trunk/sound/soc/davinci/Kconfig @@ -9,9 +9,6 @@ config SND_DAVINCI_SOC config SND_DAVINCI_SOC_I2S tristate -config SND_DAVINCI_SOC_MCASP - tristate - config SND_DAVINCI_SOC_EVM tristate "SoC Audio support for DaVinci DM6446 or DM355 EVM" depends on SND_DAVINCI_SOC @@ -22,16 +19,6 @@ config SND_DAVINCI_SOC_EVM Say Y if you want to add support for SoC audio on TI DaVinci DM6446 or DM355 EVM platforms. -config SND_DM6467_SOC_EVM - tristate "SoC Audio support for DaVinci DM6467 EVM" - depends on SND_DAVINCI_SOC && MACH_DAVINCI_DM6467_EVM - select SND_DAVINCI_SOC_MCASP - select SND_SOC_TLV320AIC3X - select SND_SOC_SPDIF - - help - Say Y if you want to add support for SoC audio on TI - config SND_DAVINCI_SOC_SFFSDR tristate "SoC Audio support for SFFSDR" depends on SND_DAVINCI_SOC && MACH_SFFSDR diff --git a/trunk/sound/soc/davinci/Makefile b/trunk/sound/soc/davinci/Makefile index 67be54f3a3a5..ca8bae1fc3f6 100644 --- a/trunk/sound/soc/davinci/Makefile +++ b/trunk/sound/soc/davinci/Makefile @@ -1,16 +1,13 @@ # DAVINCI Platform Support snd-soc-davinci-objs := davinci-pcm.o snd-soc-davinci-i2s-objs := davinci-i2s.o -snd-soc-davinci-mcasp-objs:= davinci-mcasp.o obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o -obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o # DAVINCI Machine Support snd-soc-evm-objs := davinci-evm.o snd-soc-sffsdr-objs := davinci-sffsdr.o obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o -obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o obj-$(CONFIG_SND_DAVINCI_SOC_SFFSDR) += snd-soc-sffsdr.o diff --git a/trunk/sound/soc/davinci/davinci-evm.c b/trunk/sound/soc/davinci/davinci-evm.c index f3bb6f60f205..58fd1cbedd88 100644 --- a/trunk/sound/soc/davinci/davinci-evm.c +++ b/trunk/sound/soc/davinci/davinci-evm.c @@ -27,10 +27,9 @@ #include #include "../codecs/tlv320aic3x.h" -#include "../codecs/spdif_transciever.h" #include "davinci-pcm.h" #include "davinci-i2s.h" -#include "davinci-mcasp.h" + #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) @@ -44,7 +43,7 @@ static int evm_hw_params(struct snd_pcm_substream *substream, unsigned sysclk; /* ASP1 on DM355 EVM is clocked by an external oscillator */ - if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm()) + if (machine_is_davinci_dm355_evm()) sysclk = 27000000; /* ASP0 in DM6446 EVM is clocked by U55, as configured by @@ -145,24 +144,6 @@ static struct snd_soc_dai_link evm_dai = { .ops = &evm_ops, }; -static struct snd_soc_dai_link dm6467_evm_dai[] = { - { - .name = "TLV320AIC3X", - .stream_name = "AIC3X", - .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_I2S_DAI], - .codec_dai = &aic3x_dai, - .init = evm_aic3x_init, - .ops = &evm_ops, - }, - { - .name = "McASP", - .stream_name = "spdif", - .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_DIT_DAI], - .codec_dai = &dit_stub_dai, - .ops = &evm_ops, - }, -}; - /* davinci-evm audio machine driver */ static struct snd_soc_card snd_soc_card_evm = { .name = "DaVinci EVM", @@ -171,26 +152,12 @@ static struct snd_soc_card snd_soc_card_evm = { .num_links = 1, }; -/* davinci dm6467 evm audio machine driver */ -static struct snd_soc_card dm6467_snd_soc_card_evm = { - .name = "DaVinci DM6467 EVM", - .platform = &davinci_soc_platform, - .dai_link = dm6467_evm_dai, - .num_links = ARRAY_SIZE(dm6467_evm_dai), -}; - /* evm audio private data */ static struct aic3x_setup_data evm_aic3x_setup = { .i2c_bus = 1, .i2c_address = 0x1b, }; -/* dm6467 evm audio private data */ -static struct aic3x_setup_data dm6467_evm_aic3x_setup = { - .i2c_bus = 1, - .i2c_address = 0x18, -}; - /* evm audio subsystem */ static struct snd_soc_device evm_snd_devdata = { .card = &snd_soc_card_evm, @@ -198,30 +165,60 @@ static struct snd_soc_device evm_snd_devdata = { .codec_data = &evm_aic3x_setup, }; -/* evm audio subsystem */ -static struct snd_soc_device dm6467_evm_snd_devdata = { - .card = &dm6467_snd_soc_card_evm, - .codec_dev = &soc_codec_dev_aic3x, - .codec_data = &dm6467_evm_aic3x_setup, +/* DM6446 EVM uses ASP0; line-out is a pair of RCA jacks */ +static struct resource evm_snd_resources[] = { + { + .start = DAVINCI_ASP0_BASE, + .end = DAVINCI_ASP0_BASE + SZ_8K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct evm_snd_platform_data evm_snd_data = { + .tx_dma_ch = DAVINCI_DMA_ASP0_TX, + .rx_dma_ch = DAVINCI_DMA_ASP0_RX, +}; + +/* DM335 EVM uses ASP1; line-out is a stereo mini-jack */ +static struct resource dm335evm_snd_resources[] = { + { + .start = DAVINCI_ASP1_BASE, + .end = DAVINCI_ASP1_BASE + SZ_8K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct evm_snd_platform_data dm335evm_snd_data = { + .tx_dma_ch = DAVINCI_DMA_ASP1_TX, + .rx_dma_ch = DAVINCI_DMA_ASP1_RX, }; static struct platform_device *evm_snd_device; static int __init evm_init(void) { - struct snd_soc_device *evm_snd_dev_data; + struct resource *resources; + unsigned num_resources; + struct evm_snd_platform_data *data; int index; int ret; if (machine_is_davinci_evm()) { - evm_snd_dev_data = &evm_snd_devdata; + davinci_cfg_reg(DM644X_MCBSP); + + resources = evm_snd_resources; + num_resources = ARRAY_SIZE(evm_snd_resources); + data = &evm_snd_data; index = 0; } else if (machine_is_davinci_dm355_evm()) { - evm_snd_dev_data = &evm_snd_devdata; + /* we don't use ASP1 IRQs, or we'd need to mux them ... */ + davinci_cfg_reg(DM355_EVT8_ASP1_TX); + davinci_cfg_reg(DM355_EVT9_ASP1_RX); + + resources = dm335evm_snd_resources; + num_resources = ARRAY_SIZE(dm335evm_snd_resources); + data = &dm335evm_snd_data; index = 1; - } else if (machine_is_davinci_dm6467_evm()) { - evm_snd_dev_data = &dm6467_evm_snd_devdata; - index = 0; } else return -EINVAL; @@ -229,8 +226,17 @@ static int __init evm_init(void) if (!evm_snd_device) return -ENOMEM; - platform_set_drvdata(evm_snd_device, evm_snd_dev_data); - evm_snd_dev_data->dev = &evm_snd_device->dev; + platform_set_drvdata(evm_snd_device, &evm_snd_devdata); + evm_snd_devdata.dev = &evm_snd_device->dev; + platform_device_add_data(evm_snd_device, data, sizeof(*data)); + + ret = platform_device_add_resources(evm_snd_device, resources, + num_resources); + if (ret) { + platform_device_put(evm_snd_device); + return ret; + } + ret = platform_device_add(evm_snd_device); if (ret) platform_device_put(evm_snd_device); diff --git a/trunk/sound/soc/davinci/davinci-i2s.c b/trunk/sound/soc/davinci/davinci-i2s.c index 2a56fb78f67a..88ccef79a5eb 100644 --- a/trunk/sound/soc/davinci/davinci-i2s.c +++ b/trunk/sound/soc/davinci/davinci-i2s.c @@ -22,8 +22,6 @@ #include #include -#include - #include "davinci-pcm.h" @@ -353,8 +351,9 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct davinci_pcm_dma_params *dma_params = dai->dma_data; - struct davinci_mcbsp_dev *dev = dai->private_data; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct davinci_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data; + struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; struct snd_interval *i = NULL; int mcbsp_word_length; unsigned int rcr, xcr, srgr; @@ -424,7 +423,8 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, static int davinci_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct davinci_mcbsp_dev *dev = dai->private_data; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); davinci_mcbsp_stop(dev, playback); if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) { @@ -437,7 +437,8 @@ static int davinci_i2s_prepare(struct snd_pcm_substream *substream, static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct davinci_mcbsp_dev *dev = dai->private_data; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; int ret = 0; int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) @@ -463,46 +464,21 @@ static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd, static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct davinci_mcbsp_dev *dev = dai->private_data; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); davinci_mcbsp_stop(dev, playback); } -#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 - -static struct snd_soc_dai_ops davinci_i2s_dai_ops = { - .startup = davinci_i2s_startup, - .shutdown = davinci_i2s_shutdown, - .prepare = davinci_i2s_prepare, - .trigger = davinci_i2s_trigger, - .hw_params = davinci_i2s_hw_params, - .set_fmt = davinci_i2s_set_dai_fmt, - -}; - -struct snd_soc_dai davinci_i2s_dai = { - .name = "davinci-i2s", - .id = 0, - .playback = { - .channels_min = 2, - .channels_max = 2, - .rates = DAVINCI_I2S_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .capture = { - .channels_min = 2, - .channels_max = 2, - .rates = DAVINCI_I2S_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &davinci_i2s_dai_ops, - -}; -EXPORT_SYMBOL_GPL(davinci_i2s_dai); - -static int davinci_i2s_probe(struct platform_device *pdev) +static int davinci_i2s_probe(struct platform_device *pdev, + struct snd_soc_dai *dai) { - struct snd_platform_data *pdata = pdev->dev.platform_data; + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_card *card = socdev->card; + struct snd_soc_dai *cpu_dai = card->dai_link->cpu_dai; struct davinci_mcbsp_dev *dev; - struct resource *mem, *ioarea, *res; + struct resource *mem, *ioarea; + struct evm_snd_platform_data *pdata; int ret; mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -524,6 +500,8 @@ static int davinci_i2s_probe(struct platform_device *pdev) goto err_release_region; } + cpu_dai->private_data = dev; + dev->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(dev->clk)) { ret = -ENODEV; @@ -532,37 +510,18 @@ static int davinci_i2s_probe(struct platform_device *pdev) clk_enable(dev->clk); dev->base = (void __iomem *)IO_ADDRESS(mem->start); + pdata = pdev->dev.platform_data; dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &davinci_i2s_pcm_out; + dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->channel = pdata->tx_dma_ch; dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->dma_addr = (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DXR_REG); dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &davinci_i2s_pcm_in; + dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->channel = pdata->rx_dma_ch; dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->dma_addr = (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DRR_REG); - /* first TX, then RX */ - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!res) { - dev_err(&pdev->dev, "no DMA resource\n"); - ret = -ENXIO; - goto err_free_mem; - } - dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->channel = res->start; - - res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (!res) { - dev_err(&pdev->dev, "no DMA resource\n"); - ret = -ENXIO; - goto err_free_mem; - } - dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->channel = res->start; - - davinci_i2s_dai.private_data = dev; - ret = snd_soc_register_dai(&davinci_i2s_dai); - if (ret != 0) - goto err_free_mem; - return 0; err_free_mem: @@ -573,40 +532,64 @@ static int davinci_i2s_probe(struct platform_device *pdev) return ret; } -static int davinci_i2s_remove(struct platform_device *pdev) +static void davinci_i2s_remove(struct platform_device *pdev, + struct snd_soc_dai *dai) { - struct davinci_mcbsp_dev *dev = davinci_i2s_dai.private_data; + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_card *card = socdev->card; + struct snd_soc_dai *cpu_dai = card->dai_link->cpu_dai; + struct davinci_mcbsp_dev *dev = cpu_dai->private_data; struct resource *mem; - snd_soc_unregister_dai(&davinci_i2s_dai); clk_disable(dev->clk); clk_put(dev->clk); dev->clk = NULL; + kfree(dev); + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(mem->start, (mem->end - mem->start) + 1); - - return 0; } -static struct platform_driver davinci_mcbsp_driver = { - .probe = davinci_i2s_probe, - .remove = davinci_i2s_remove, - .driver = { - .name = "davinci-asp", - .owner = THIS_MODULE, - }, +#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 + +static struct snd_soc_dai_ops davinci_i2s_dai_ops = { + .startup = davinci_i2s_startup, + .shutdown = davinci_i2s_shutdown, + .prepare = davinci_i2s_prepare, + .trigger = davinci_i2s_trigger, + .hw_params = davinci_i2s_hw_params, + .set_fmt = davinci_i2s_set_dai_fmt, +}; + +struct snd_soc_dai davinci_i2s_dai = { + .name = "davinci-i2s", + .id = 0, + .probe = davinci_i2s_probe, + .remove = davinci_i2s_remove, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = DAVINCI_I2S_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .capture = { + .channels_min = 2, + .channels_max = 2, + .rates = DAVINCI_I2S_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .ops = &davinci_i2s_dai_ops, }; +EXPORT_SYMBOL_GPL(davinci_i2s_dai); static int __init davinci_i2s_init(void) { - return platform_driver_register(&davinci_mcbsp_driver); + return snd_soc_register_dai(&davinci_i2s_dai); } module_init(davinci_i2s_init); static void __exit davinci_i2s_exit(void) { - platform_driver_unregister(&davinci_mcbsp_driver); + snd_soc_unregister_dai(&davinci_i2s_dai); } module_exit(davinci_i2s_exit); diff --git a/trunk/sound/soc/davinci/davinci-mcasp.c b/trunk/sound/soc/davinci/davinci-mcasp.c deleted file mode 100644 index f0c034771062..000000000000 --- a/trunk/sound/soc/davinci/davinci-mcasp.c +++ /dev/null @@ -1,874 +0,0 @@ -/* - * ALSA SoC McASP Audio Layer for TI DAVINCI processor - * - * Multi-channel Audio Serial Port Driver - * - * Author: Nirmal Pandey , - * Suresh Rajashekara - * Steve Chen - * - * Copyright: (C) 2009 MontaVista Software, Inc., - * Copyright: (C) 2009 Texas Instruments, India - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "davinci-pcm.h" -#include "davinci-mcasp.h" - -/* - * McASP register definitions - */ -#define DAVINCI_MCASP_PID_REG 0x00 -#define DAVINCI_MCASP_PWREMUMGT_REG 0x04 - -#define DAVINCI_MCASP_PFUNC_REG 0x10 -#define DAVINCI_MCASP_PDIR_REG 0x14 -#define DAVINCI_MCASP_PDOUT_REG 0x18 -#define DAVINCI_MCASP_PDSET_REG 0x1c - -#define DAVINCI_MCASP_PDCLR_REG 0x20 - -#define DAVINCI_MCASP_TLGC_REG 0x30 -#define DAVINCI_MCASP_TLMR_REG 0x34 - -#define DAVINCI_MCASP_GBLCTL_REG 0x44 -#define DAVINCI_MCASP_AMUTE_REG 0x48 -#define DAVINCI_MCASP_LBCTL_REG 0x4c - -#define DAVINCI_MCASP_TXDITCTL_REG 0x50 - -#define DAVINCI_MCASP_GBLCTLR_REG 0x60 -#define DAVINCI_MCASP_RXMASK_REG 0x64 -#define DAVINCI_MCASP_RXFMT_REG 0x68 -#define DAVINCI_MCASP_RXFMCTL_REG 0x6c - -#define DAVINCI_MCASP_ACLKRCTL_REG 0x70 -#define DAVINCI_MCASP_AHCLKRCTL_REG 0x74 -#define DAVINCI_MCASP_RXTDM_REG 0x78 -#define DAVINCI_MCASP_EVTCTLR_REG 0x7c - -#define DAVINCI_MCASP_RXSTAT_REG 0x80 -#define DAVINCI_MCASP_RXTDMSLOT_REG 0x84 -#define DAVINCI_MCASP_RXCLKCHK_REG 0x88 -#define DAVINCI_MCASP_REVTCTL_REG 0x8c - -#define DAVINCI_MCASP_GBLCTLX_REG 0xa0 -#define DAVINCI_MCASP_TXMASK_REG 0xa4 -#define DAVINCI_MCASP_TXFMT_REG 0xa8 -#define DAVINCI_MCASP_TXFMCTL_REG 0xac - -#define DAVINCI_MCASP_ACLKXCTL_REG 0xb0 -#define DAVINCI_MCASP_AHCLKXCTL_REG 0xb4 -#define DAVINCI_MCASP_TXTDM_REG 0xb8 -#define DAVINCI_MCASP_EVTCTLX_REG 0xbc - -#define DAVINCI_MCASP_TXSTAT_REG 0xc0 -#define DAVINCI_MCASP_TXTDMSLOT_REG 0xc4 -#define DAVINCI_MCASP_TXCLKCHK_REG 0xc8 -#define DAVINCI_MCASP_XEVTCTL_REG 0xcc - -/* Left(even TDM Slot) Channel Status Register File */ -#define DAVINCI_MCASP_DITCSRA_REG 0x100 -/* Right(odd TDM slot) Channel Status Register File */ -#define DAVINCI_MCASP_DITCSRB_REG 0x118 -/* Left(even TDM slot) User Data Register File */ -#define DAVINCI_MCASP_DITUDRA_REG 0x130 -/* Right(odd TDM Slot) User Data Register File */ -#define DAVINCI_MCASP_DITUDRB_REG 0x148 - -/* Serializer n Control Register */ -#define DAVINCI_MCASP_XRSRCTL_BASE_REG 0x180 -#define DAVINCI_MCASP_XRSRCTL_REG(n) (DAVINCI_MCASP_XRSRCTL_BASE_REG + \ - (n << 2)) - -/* Transmit Buffer for Serializer n */ -#define DAVINCI_MCASP_TXBUF_REG 0x200 -/* Receive Buffer for Serializer n */ -#define DAVINCI_MCASP_RXBUF_REG 0x280 - - -/* - * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management - * Register Bits - */ -#define MCASP_FREE BIT(0) -#define MCASP_SOFT BIT(1) - -/* - * DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits - */ -#define AXR(n) (1<private_data; - cpu_dai->dma_data = dev->dma_params[substream->stream]; - return 0; -} - -static void mcasp_start_rx(struct davinci_audio_dev *dev) -{ - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR); - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0); - - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0); - - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); -} - -static void mcasp_start_tx(struct davinci_audio_dev *dev) -{ - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); - - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); -} - -static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream) -{ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - mcasp_start_tx(dev); - else - mcasp_start_rx(dev); -} - -static void mcasp_stop_rx(struct davinci_audio_dev *dev) -{ - mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, 0); - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); -} - -static void mcasp_stop_tx(struct davinci_audio_dev *dev) -{ - mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); -} - -static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream) -{ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - mcasp_stop_tx(dev); - else - mcasp_stop_rx(dev); -} - -static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - struct davinci_audio_dev *dev = cpu_dai->private_data; - void __iomem *base = dev->base; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - /* codec is clock and frame slave */ - mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); - mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); - - mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); - mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); - - mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x7 << 26)); - break; - - case SND_SOC_DAIFMT_CBM_CFM: - /* codec is clock and frame master */ - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); - mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); - - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); - mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); - - mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, (0x3f << 26)); - break; - - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_IB_NF: - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - - mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); - break; - - case SND_SOC_DAIFMT_NB_IF: - mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); - break; - - case SND_SOC_DAIFMT_IB_IF: - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - - mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); - break; - - case SND_SOC_DAIFMT_NB_NF: - mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int davinci_config_channel_size(struct davinci_audio_dev *dev, - int channel_size) -{ - u32 fmt = 0; - - switch (channel_size) { - case DAVINCI_AUDIO_WORD_8: - fmt = 0x03; - break; - - case DAVINCI_AUDIO_WORD_12: - fmt = 0x05; - break; - - case DAVINCI_AUDIO_WORD_16: - fmt = 0x07; - break; - - case DAVINCI_AUDIO_WORD_20: - fmt = 0x09; - break; - - case DAVINCI_AUDIO_WORD_24: - fmt = 0x0B; - break; - - case DAVINCI_AUDIO_WORD_28: - fmt = 0x0D; - break; - - case DAVINCI_AUDIO_WORD_32: - fmt = 0x0F; - break; - - default: - return -EINVAL; - } - - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, - RXSSZ(fmt), RXSSZ(0x0F)); - mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, - TXSSZ(fmt), TXSSZ(0x0F)); - return 0; -} - -static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) -{ - int i; - - /* Default configuration */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); - - /* All PINS as McASP */ - mcasp_set_reg(dev->base + DAVINCI_MCASP_PFUNC_REG, 0x00000000); - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); - mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, - TXDATADMADIS); - } else { - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); - mcasp_clr_bits(dev->base + DAVINCI_MCASP_REVTCTL_REG, - RXDATADMADIS); - } - - for (i = 0; i < dev->num_serializer; i++) { - mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i), - dev->serial_dir[i]); - if (dev->serial_dir[i] == TX_MODE) - mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, - AXR(i)); - else if (dev->serial_dir[i] == RX_MODE) - mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, - AXR(i)); - } -} - -static void davinci_hw_param(struct davinci_audio_dev *dev, int stream) -{ - int i, active_slots; - u32 mask = 0; - - active_slots = (dev->tdm_slots > 31) ? 32 : dev->tdm_slots; - for (i = 0; i < active_slots; i++) - mask |= (1 << i); - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* bit stream is MSB first with no delay */ - /* DSP_B mode */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, - AHCLKXE); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask); - mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD); - - if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32)) - mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, - FSXMOD(dev->tdm_slots), FSXMOD(0x1FF)); - else - printk(KERN_ERR "playback tdm slot %d not supported\n", - dev->tdm_slots); - - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0xFFFFFFFF); - mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); - } else { - /* bit stream is MSB first with no delay */ - /* DSP_B mode */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD); - mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, - AHCLKRE); - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask); - - if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32)) - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, - FSRMOD(dev->tdm_slots), FSRMOD(0x1FF)); - else - printk(KERN_ERR "capture tdm slot %d not supported\n", - dev->tdm_slots); - - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, 0xFFFFFFFF); - mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); - } -} - -/* S/PDIF */ -static void davinci_hw_dit_param(struct davinci_audio_dev *dev) -{ - /* Set the PDIR for Serialiser as output */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AFSX); - - /* TXMASK for 24 bits */ - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0x00FFFFFF); - - /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 - and LSB first */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, - TXROT(6) | TXSSZ(15)); - - /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */ - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXFMCTL_REG, - AFSXE | FSXMOD(0x180)); - - /* Set the TX tdm : for all the slots */ - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF); - - /* Set the TX clock controls : div = 1 and internal */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, - ACLKXE | TX_ASYNC); - - mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); - - /* Only 44100 and 48000 are valid, both have the same setting */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3)); - - /* Enable the DIT */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_TXDITCTL_REG, DITEN); -} - -static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *cpu_dai) -{ - struct davinci_audio_dev *dev = cpu_dai->private_data; - struct davinci_pcm_dma_params *dma_params = - dev->dma_params[substream->stream]; - int word_length; - - davinci_hw_common_param(dev, substream->stream); - - if (dev->op_mode == DAVINCI_MCASP_DIT_MODE) - davinci_hw_dit_param(dev); - else - davinci_hw_param(dev, substream->stream); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S8: - dma_params->data_type = 1; - word_length = DAVINCI_AUDIO_WORD_8; - break; - - case SNDRV_PCM_FORMAT_S16_LE: - dma_params->data_type = 2; - word_length = DAVINCI_AUDIO_WORD_16; - break; - - case SNDRV_PCM_FORMAT_S32_LE: - dma_params->data_type = 4; - word_length = DAVINCI_AUDIO_WORD_32; - break; - - default: - printk(KERN_WARNING "davinci-mcasp: unsupported PCM format"); - return -EINVAL; - } - davinci_config_channel_size(dev, word_length); - - return 0; -} - -static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *cpu_dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct davinci_audio_dev *dev = rtd->dai->cpu_dai->private_data; - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - davinci_mcasp_start(dev, substream->stream); - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - davinci_mcasp_stop(dev, substream->stream); - break; - - default: - ret = -EINVAL; - } - - return ret; -} - -static struct snd_soc_dai_ops davinci_mcasp_dai_ops = { - .startup = davinci_mcasp_startup, - .trigger = davinci_mcasp_trigger, - .hw_params = davinci_mcasp_hw_params, - .set_fmt = davinci_mcasp_set_dai_fmt, - -}; - -struct snd_soc_dai davinci_mcasp_dai[] = { - { - .name = "davinci-i2s", - .id = 0, - .playback = { - .channels_min = 2, - .channels_max = 2, - .rates = DAVINCI_MCASP_RATES, - .formats = SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE, - }, - .capture = { - .channels_min = 2, - .channels_max = 2, - .rates = DAVINCI_MCASP_RATES, - .formats = SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE, - }, - .ops = &davinci_mcasp_dai_ops, - - }, - { - .name = "davinci-dit", - .id = 1, - .playback = { - .channels_min = 1, - .channels_max = 384, - .rates = DAVINCI_MCASP_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .ops = &davinci_mcasp_dai_ops, - }, - -}; -EXPORT_SYMBOL_GPL(davinci_mcasp_dai); - -static int davinci_mcasp_probe(struct platform_device *pdev) -{ - struct davinci_pcm_dma_params *dma_data; - struct resource *mem, *ioarea, *res; - struct snd_platform_data *pdata; - struct davinci_audio_dev *dev; - int count = 0; - int ret = 0; - - dev = kzalloc(sizeof(struct davinci_audio_dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; - - dma_data = kzalloc(sizeof(struct davinci_pcm_dma_params) * 2, - GFP_KERNEL); - if (!dma_data) { - ret = -ENOMEM; - goto err_release_dev; - } - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "no mem resource?\n"); - ret = -ENODEV; - goto err_release_data; - } - - ioarea = request_mem_region(mem->start, - (mem->end - mem->start) + 1, pdev->name); - if (!ioarea) { - dev_err(&pdev->dev, "Audio region already claimed\n"); - ret = -EBUSY; - goto err_release_data; - } - - pdata = pdev->dev.platform_data; - dev->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(dev->clk)) { - ret = -ENODEV; - goto err_release_region; - } - - clk_enable(dev->clk); - - dev->base = (void __iomem *)IO_ADDRESS(mem->start); - dev->op_mode = pdata->op_mode; - dev->tdm_slots = pdata->tdm_slots; - dev->num_serializer = pdata->num_serializer; - dev->serial_dir = pdata->serial_dir; - dev->codec_fmt = pdata->codec_fmt; - - dma_data[count].name = "I2S PCM Stereo out"; - dma_data[count].eventq_no = pdata->eventq_no; - dma_data[count].dma_addr = (dma_addr_t) (pdata->tx_dma_offset + - io_v2p(dev->base)); - dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &dma_data[count]; - - /* first TX, then RX */ - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!res) { - dev_err(&pdev->dev, "no DMA resource\n"); - goto err_release_region; - } - - dma_data[count].channel = res->start; - count++; - dma_data[count].name = "I2S PCM Stereo in"; - dma_data[count].eventq_no = pdata->eventq_no; - dma_data[count].dma_addr = (dma_addr_t)(pdata->rx_dma_offset + - io_v2p(dev->base)); - dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &dma_data[count]; - - res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (!res) { - dev_err(&pdev->dev, "no DMA resource\n"); - goto err_release_region; - } - - dma_data[count].channel = res->start; - davinci_mcasp_dai[pdev->id].private_data = dev; - davinci_mcasp_dai[pdev->id].dev = &pdev->dev; - ret = snd_soc_register_dai(&davinci_mcasp_dai[pdev->id]); - - if (ret != 0) - goto err_release_region; - return 0; - -err_release_region: - release_mem_region(mem->start, (mem->end - mem->start) + 1); -err_release_data: - kfree(dma_data); -err_release_dev: - kfree(dev); - - return ret; -} - -static int davinci_mcasp_remove(struct platform_device *pdev) -{ - struct davinci_pcm_dma_params *dma_data; - struct davinci_audio_dev *dev; - struct resource *mem; - - snd_soc_unregister_dai(&davinci_mcasp_dai[pdev->id]); - dev = davinci_mcasp_dai[pdev->id].private_data; - clk_disable(dev->clk); - clk_put(dev->clk); - dev->clk = NULL; - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(mem->start, (mem->end - mem->start) + 1); - - dma_data = dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; - kfree(dma_data); - kfree(dev); - - return 0; -} - -static struct platform_driver davinci_mcasp_driver = { - .probe = davinci_mcasp_probe, - .remove = davinci_mcasp_remove, - .driver = { - .name = "davinci-mcasp", - .owner = THIS_MODULE, - }, -}; - -static int __init davinci_mcasp_init(void) -{ - return platform_driver_register(&davinci_mcasp_driver); -} -module_init(davinci_mcasp_init); - -static void __exit davinci_mcasp_exit(void) -{ - platform_driver_unregister(&davinci_mcasp_driver); -} -module_exit(davinci_mcasp_exit); - -MODULE_AUTHOR("Steve Chen"); -MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface"); -MODULE_LICENSE("GPL"); - diff --git a/trunk/sound/soc/davinci/davinci-mcasp.h b/trunk/sound/soc/davinci/davinci-mcasp.h deleted file mode 100644 index 36b71047a06c..000000000000 --- a/trunk/sound/soc/davinci/davinci-mcasp.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * ALSA SoC McASP Audio Layer for TI DAVINCI processor - * - * MCASP related definitions - * - * Author: Nirmal Pandey , - * Suresh Rajashekara - * Steve Chen - * - * Copyright: (C) 2009 MontaVista Software, Inc., - * Copyright: (C) 2009 Texas Instruments, India - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef DAVINCI_MCASP_H -#define DAVINCI_MCASP_H - -#include -#include -#include "davinci-pcm.h" - -extern struct snd_soc_dai davinci_mcasp_dai[]; - -#define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000 -#define DAVINCI_MCASP_I2S_DAI 0 -#define DAVINCI_MCASP_DIT_DAI 1 - -enum { - DAVINCI_AUDIO_WORD_8 = 0, - DAVINCI_AUDIO_WORD_12, - DAVINCI_AUDIO_WORD_16, - DAVINCI_AUDIO_WORD_20, - DAVINCI_AUDIO_WORD_24, - DAVINCI_AUDIO_WORD_32, - DAVINCI_AUDIO_WORD_28, /* This is only valid for McASP */ -}; - -struct davinci_audio_dev { - void __iomem *base; - int sample_rate; - struct clk *clk; - struct davinci_pcm_dma_params *dma_params[2]; - unsigned int codec_fmt; - - /* McASP specific data */ - int tdm_slots; - u8 op_mode; - u8 num_serializer; - u8 *serial_dir; -}; - -#endif /* DAVINCI_MCASP_H */ diff --git a/trunk/sound/soc/davinci/davinci-pcm.c b/trunk/sound/soc/davinci/davinci-pcm.c index ab43a539c11d..a05996588489 100644 --- a/trunk/sound/soc/davinci/davinci-pcm.c +++ b/trunk/sound/soc/davinci/davinci-pcm.c @@ -206,7 +206,6 @@ static int davinci_pcm_prepare(struct snd_pcm_substream *substream) /* Copy self-linked parameter RAM entry into master channel */ edma_read_slot(prtd->slave_lch, &temp); edma_write_slot(prtd->master_lch, &temp); - davinci_pcm_enqueue_dma(substream); return 0; } @@ -244,11 +243,6 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream) int ret = 0; snd_soc_set_runtime_hwparams(substream, &davinci_pcm_hardware); - /* ensure that buffer size is a multiple of period size */ - ret = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) - return ret; prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL); if (prtd == NULL) diff --git a/trunk/sound/soc/davinci/davinci-pcm.h b/trunk/sound/soc/davinci/davinci-pcm.h index eb4287faa3d5..62cb4eb07e34 100644 --- a/trunk/sound/soc/davinci/davinci-pcm.h +++ b/trunk/sound/soc/davinci/davinci-pcm.h @@ -12,19 +12,17 @@ #ifndef _DAVINCI_PCM_H #define _DAVINCI_PCM_H -#include -#include - - struct davinci_pcm_dma_params { - char *name; /* stream identifier */ - int channel; /* sync dma channel ID */ - dma_addr_t dma_addr; /* device physical address for DMA */ - enum dma_event_q eventq_no; /* event queue number */ - unsigned char data_type; /* xfer data type */ - unsigned char convert_mono_stereo; + char *name; /* stream identifier */ + int channel; /* sync dma channel ID */ + dma_addr_t dma_addr; /* device physical address for DMA */ + unsigned int data_type; /* xfer data type */ }; +struct evm_snd_platform_data { + int tx_dma_ch; + int rx_dma_ch; +}; extern struct snd_soc_platform davinci_soc_platform; diff --git a/trunk/sound/soc/fsl/mpc5200_dma.c b/trunk/sound/soc/fsl/mpc5200_dma.c index 9ff62e3a9b1d..efec33a1c5bd 100644 --- a/trunk/sound/soc/fsl/mpc5200_dma.c +++ b/trunk/sound/soc/fsl/mpc5200_dma.c @@ -69,23 +69,6 @@ static void psc_dma_bcom_enqueue_next_buffer(struct psc_dma_stream *s) static void psc_dma_bcom_enqueue_tx(struct psc_dma_stream *s) { - if (s->appl_ptr > s->runtime->control->appl_ptr) { - /* - * In this case s->runtime->control->appl_ptr has wrapped around. - * Play the data to the end of the boundary, then wrap our own - * appl_ptr back around. - */ - while (s->appl_ptr < s->runtime->boundary) { - if (bcom_queue_full(s->bcom_task)) - return; - - s->appl_ptr += s->period_size; - - psc_dma_bcom_enqueue_next_buffer(s); - } - s->appl_ptr -= s->runtime->boundary; - } - while (s->appl_ptr < s->runtime->control->appl_ptr) { if (bcom_queue_full(s->bcom_task)) @@ -473,7 +456,6 @@ int mpc5200_audio_dma_create(struct of_device *op) return -ENODEV; spin_lock_init(&psc_dma->lock); - mutex_init(&psc_dma->mutex); psc_dma->id = be32_to_cpu(*prop); psc_dma->irq = irq; psc_dma->psc_regs = regs; diff --git a/trunk/sound/soc/fsl/mpc5200_dma.h b/trunk/sound/soc/fsl/mpc5200_dma.h index 8d396bb9d9fe..2000803f06a7 100644 --- a/trunk/sound/soc/fsl/mpc5200_dma.h +++ b/trunk/sound/soc/fsl/mpc5200_dma.h @@ -55,7 +55,6 @@ struct psc_dma { unsigned int irq; struct device *dev; spinlock_t lock; - struct mutex mutex; u32 sicr; uint sysclk; int imr; diff --git a/trunk/sound/soc/fsl/mpc5200_psc_ac97.c b/trunk/sound/soc/fsl/mpc5200_psc_ac97.c index c4ae3e096bb9..794a247b3eb5 100644 --- a/trunk/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/trunk/sound/soc/fsl/mpc5200_psc_ac97.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -35,20 +34,13 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg) int status; unsigned int val; - mutex_lock(&psc_dma->mutex); - /* Wait for command send status zero = ready */ status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) & MPC52xx_PSC_SR_CMDSEND), 100, 0); if (status == 0) { pr_err("timeout on ac97 bus (rdy)\n"); - mutex_unlock(&psc_dma->mutex); return -ENODEV; } - - /* Force clear the data valid bit */ - in_be32(&psc_dma->psc_regs->ac97_data); - /* Send the read */ out_be32(&psc_dma->psc_regs->ac97_cmd, (1<<31) | ((reg & 0x7f) << 24)); @@ -58,19 +50,16 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg) if (status == 0) { pr_err("timeout on ac97 read (val) %x\n", in_be16(&psc_dma->psc_regs->sr_csr.status)); - mutex_unlock(&psc_dma->mutex); return -ENODEV; } /* Get the data */ val = in_be32(&psc_dma->psc_regs->ac97_data); if (((val >> 24) & 0x7f) != reg) { pr_err("reg echo error on ac97 read\n"); - mutex_unlock(&psc_dma->mutex); return -ENODEV; } val = (val >> 8) & 0xffff; - mutex_unlock(&psc_dma->mutex); return (unsigned short) val; } @@ -79,21 +68,16 @@ static void psc_ac97_write(struct snd_ac97 *ac97, { int status; - mutex_lock(&psc_dma->mutex); - /* Wait for command status zero = ready */ status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) & MPC52xx_PSC_SR_CMDSEND), 100, 0); if (status == 0) { pr_err("timeout on ac97 bus (write)\n"); - goto out; + return; } /* Write data */ out_be32(&psc_dma->psc_regs->ac97_cmd, ((reg & 0x7f) << 24) | (val << 8)); - - out: - mutex_unlock(&psc_dma->mutex); } static void psc_ac97_warm_reset(struct snd_ac97 *ac97) @@ -113,7 +97,7 @@ static void psc_ac97_cold_reset(struct snd_ac97 *ac97) out_8(®s->op1, MPC52xx_PSC_OP_RES); udelay(10); out_8(®s->op0, MPC52xx_PSC_OP_RES); - msleep(1); + udelay(50); psc_ac97_warm_reset(ac97); } diff --git a/trunk/sound/soc/omap/Kconfig b/trunk/sound/soc/omap/Kconfig index 2dee9839be86..a5a90e594535 100644 --- a/trunk/sound/soc/omap/Kconfig +++ b/trunk/sound/soc/omap/Kconfig @@ -15,14 +15,6 @@ config SND_OMAP_SOC_N810 help Say Y if you want to add support for SoC audio on Nokia N810. -config SND_OMAP_SOC_AMS_DELTA - tristate "SoC Audio support for Amstrad E3 (Delta) videophone" - depends on SND_OMAP_SOC && MACH_AMS_DELTA - select SND_OMAP_SOC_MCBSP - select SND_SOC_CX20442 - help - Say Y if you want to add support for SoC audio on Amstrad Delta. - config SND_OMAP_SOC_OSK5912 tristate "SoC Audio support for omap osk5912" depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C diff --git a/trunk/sound/soc/omap/Makefile b/trunk/sound/soc/omap/Makefile index 02d69471dcb5..fefc48f02bd3 100644 --- a/trunk/sound/soc/omap/Makefile +++ b/trunk/sound/soc/omap/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o # OMAP Machine Support snd-soc-n810-objs := n810.o -snd-soc-ams-delta-objs := ams-delta.o snd-soc-osk5912-objs := osk5912.o snd-soc-overo-objs := overo.o snd-soc-omap2evm-objs := omap2evm.o @@ -18,7 +17,6 @@ snd-soc-omap3beagle-objs := omap3beagle.o snd-soc-zoom2-objs := zoom2.o obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o -obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o diff --git a/trunk/sound/soc/omap/ams-delta.c b/trunk/sound/soc/omap/ams-delta.c deleted file mode 100644 index 4f35b1f18cb9..000000000000 --- a/trunk/sound/soc/omap/ams-delta.c +++ /dev/null @@ -1,646 +0,0 @@ -/* - * ams-delta.c -- SoC audio for Amstrad E3 (Delta) videophone - * - * Copyright (C) 2009 Janusz Krzysztofik - * - * Initially based on sound/soc/omap/osk5912.x - * Copyright (C) 2008 Mistral Solutions - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include - -#include -#include - -#include - -#include -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" -#include "../codecs/cx20442.h" - - -/* Board specific DAPM widgets */ - const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = { - /* Handset */ - SND_SOC_DAPM_MIC("Mouthpiece", NULL), - SND_SOC_DAPM_HP("Earpiece", NULL), - /* Handsfree/Speakerphone */ - SND_SOC_DAPM_MIC("Microphone", NULL), - SND_SOC_DAPM_SPK("Speaker", NULL), -}; - -/* How they are connected to codec pins */ -static const struct snd_soc_dapm_route ams_delta_audio_map[] = { - {"TELIN", NULL, "Mouthpiece"}, - {"Earpiece", NULL, "TELOUT"}, - - {"MIC", NULL, "Microphone"}, - {"Speaker", NULL, "SPKOUT"}, -}; - -/* - * Controls, functional after the modem line discipline is activated. - */ - -/* Virtual switch: audio input/output constellations */ -static const char *ams_delta_audio_mode[] = - {"Mixed", "Handset", "Handsfree", "Speakerphone"}; - -/* Selection <-> pin translation */ -#define AMS_DELTA_MOUTHPIECE 0 -#define AMS_DELTA_EARPIECE 1 -#define AMS_DELTA_MICROPHONE 2 -#define AMS_DELTA_SPEAKER 3 -#define AMS_DELTA_AGC 4 - -#define AMS_DELTA_MIXED ((1 << AMS_DELTA_EARPIECE) | \ - (1 << AMS_DELTA_MICROPHONE)) -#define AMS_DELTA_HANDSET ((1 << AMS_DELTA_MOUTHPIECE) | \ - (1 << AMS_DELTA_EARPIECE)) -#define AMS_DELTA_HANDSFREE ((1 << AMS_DELTA_MICROPHONE) | \ - (1 << AMS_DELTA_SPEAKER)) -#define AMS_DELTA_SPEAKERPHONE (AMS_DELTA_HANDSFREE | (1 << AMS_DELTA_AGC)) - -unsigned short ams_delta_audio_mode_pins[] = { - AMS_DELTA_MIXED, - AMS_DELTA_HANDSET, - AMS_DELTA_HANDSFREE, - AMS_DELTA_SPEAKERPHONE, -}; - -static unsigned short ams_delta_audio_agc; - -static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct soc_enum *control = (struct soc_enum *)kcontrol->private_value; - unsigned short pins; - int pin, changed = 0; - - /* Refuse any mode changes if we are not able to control the codec. */ - if (!codec->control_data) - return -EUNATCH; - - if (ucontrol->value.enumerated.item[0] >= control->max) - return -EINVAL; - - mutex_lock(&codec->mutex); - - /* Translate selection to bitmap */ - pins = ams_delta_audio_mode_pins[ucontrol->value.enumerated.item[0]]; - - /* Setup pins after corresponding bits if changed */ - pin = !!(pins & (1 << AMS_DELTA_MOUTHPIECE)); - if (pin != snd_soc_dapm_get_pin_status(codec, "Mouthpiece")) { - changed = 1; - if (pin) - snd_soc_dapm_enable_pin(codec, "Mouthpiece"); - else - snd_soc_dapm_disable_pin(codec, "Mouthpiece"); - } - pin = !!(pins & (1 << AMS_DELTA_EARPIECE)); - if (pin != snd_soc_dapm_get_pin_status(codec, "Earpiece")) { - changed = 1; - if (pin) - snd_soc_dapm_enable_pin(codec, "Earpiece"); - else - snd_soc_dapm_disable_pin(codec, "Earpiece"); - } - pin = !!(pins & (1 << AMS_DELTA_MICROPHONE)); - if (pin != snd_soc_dapm_get_pin_status(codec, "Microphone")) { - changed = 1; - if (pin) - snd_soc_dapm_enable_pin(codec, "Microphone"); - else - snd_soc_dapm_disable_pin(codec, "Microphone"); - } - pin = !!(pins & (1 << AMS_DELTA_SPEAKER)); - if (pin != snd_soc_dapm_get_pin_status(codec, "Speaker")) { - changed = 1; - if (pin) - snd_soc_dapm_enable_pin(codec, "Speaker"); - else - snd_soc_dapm_disable_pin(codec, "Speaker"); - } - pin = !!(pins & (1 << AMS_DELTA_AGC)); - if (pin != ams_delta_audio_agc) { - ams_delta_audio_agc = pin; - changed = 1; - if (pin) - snd_soc_dapm_enable_pin(codec, "AGCIN"); - else - snd_soc_dapm_disable_pin(codec, "AGCIN"); - } - if (changed) - snd_soc_dapm_sync(codec); - - mutex_unlock(&codec->mutex); - - return changed; -} - -static int ams_delta_get_audio_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned short pins, mode; - - pins = ((snd_soc_dapm_get_pin_status(codec, "Mouthpiece") << - AMS_DELTA_MOUTHPIECE) | - (snd_soc_dapm_get_pin_status(codec, "Earpiece") << - AMS_DELTA_EARPIECE)); - if (pins) - pins |= (snd_soc_dapm_get_pin_status(codec, "Microphone") << - AMS_DELTA_MICROPHONE); - else - pins = ((snd_soc_dapm_get_pin_status(codec, "Microphone") << - AMS_DELTA_MICROPHONE) | - (snd_soc_dapm_get_pin_status(codec, "Speaker") << - AMS_DELTA_SPEAKER) | - (ams_delta_audio_agc << AMS_DELTA_AGC)); - - for (mode = 0; mode < ARRAY_SIZE(ams_delta_audio_mode); mode++) - if (pins == ams_delta_audio_mode_pins[mode]) - break; - - if (mode >= ARRAY_SIZE(ams_delta_audio_mode)) - return -EINVAL; - - ucontrol->value.enumerated.item[0] = mode; - - return 0; -} - -static const struct soc_enum ams_delta_audio_enum[] = { - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ams_delta_audio_mode), - ams_delta_audio_mode), -}; - -static const struct snd_kcontrol_new ams_delta_audio_controls[] = { - SOC_ENUM_EXT("Audio Mode", ams_delta_audio_enum[0], - ams_delta_get_audio_mode, ams_delta_set_audio_mode), -}; - -/* Hook switch */ -static struct snd_soc_jack ams_delta_hook_switch; -static struct snd_soc_jack_gpio ams_delta_hook_switch_gpios[] = { - { - .gpio = 4, - .name = "hook_switch", - .report = SND_JACK_HEADSET, - .invert = 1, - .debounce_time = 150, - } -}; - -/* After we are able to control the codec over the modem, - * the hook switch can be used for dynamic DAPM reconfiguration. */ -static struct snd_soc_jack_pin ams_delta_hook_switch_pins[] = { - /* Handset */ - { - .pin = "Mouthpiece", - .mask = SND_JACK_MICROPHONE, - }, - { - .pin = "Earpiece", - .mask = SND_JACK_HEADPHONE, - }, - /* Handsfree */ - { - .pin = "Microphone", - .mask = SND_JACK_MICROPHONE, - .invert = 1, - }, - { - .pin = "Speaker", - .mask = SND_JACK_HEADPHONE, - .invert = 1, - }, -}; - - -/* - * Modem line discipline, required for making above controls functional. - * Activated from userspace with ldattach, possibly invoked from udev rule. - */ - -/* To actually apply any modem controlled configuration changes to the codec, - * we must connect codec DAI pins to the modem for a moment. Be carefull not - * to interfere with our digital mute function that shares the same hardware. */ -static struct timer_list cx81801_timer; -static bool cx81801_cmd_pending; -static bool ams_delta_muted; -static DEFINE_SPINLOCK(ams_delta_lock); - -static void cx81801_timeout(unsigned long data) -{ - int muted; - - spin_lock(&ams_delta_lock); - cx81801_cmd_pending = 0; - muted = ams_delta_muted; - spin_unlock(&ams_delta_lock); - - /* Reconnect the codec DAI back from the modem to the CPU DAI - * only if digital mute still off */ - if (!muted) - ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0); -} - -/* Line discipline .open() */ -static int cx81801_open(struct tty_struct *tty) -{ - return v253_ops.open(tty); -} - -/* Line discipline .close() */ -static void cx81801_close(struct tty_struct *tty) -{ - struct snd_soc_codec *codec = tty->disc_data; - - del_timer_sync(&cx81801_timer); - - v253_ops.close(tty); - - /* Prevent the hook switch from further changing the DAPM pins */ - INIT_LIST_HEAD(&ams_delta_hook_switch.pins); - - /* Revert back to default audio input/output constellation */ - snd_soc_dapm_disable_pin(codec, "Mouthpiece"); - snd_soc_dapm_enable_pin(codec, "Earpiece"); - snd_soc_dapm_enable_pin(codec, "Microphone"); - snd_soc_dapm_disable_pin(codec, "Speaker"); - snd_soc_dapm_disable_pin(codec, "AGCIN"); - snd_soc_dapm_sync(codec); -} - -/* Line discipline .hangup() */ -static int cx81801_hangup(struct tty_struct *tty) -{ - cx81801_close(tty); - return 0; -} - -/* Line discipline .recieve_buf() */ -static void cx81801_receive(struct tty_struct *tty, - const unsigned char *cp, char *fp, int count) -{ - struct snd_soc_codec *codec = tty->disc_data; - const unsigned char *c; - int apply, ret; - - if (!codec->control_data) { - /* First modem response, complete setup procedure */ - - /* Initialize timer used for config pulse generation */ - setup_timer(&cx81801_timer, cx81801_timeout, 0); - - v253_ops.receive_buf(tty, cp, fp, count); - - /* Link hook switch to DAPM pins */ - ret = snd_soc_jack_add_pins(&ams_delta_hook_switch, - ARRAY_SIZE(ams_delta_hook_switch_pins), - ams_delta_hook_switch_pins); - if (ret) - dev_warn(codec->socdev->card->dev, - "Failed to link hook switch to DAPM pins, " - "will continue with hook switch unlinked.\n"); - - return; - } - - v253_ops.receive_buf(tty, cp, fp, count); - - for (c = &cp[count - 1]; c >= cp; c--) { - if (*c != '\r') - continue; - /* Complete modem response received, apply config to codec */ - - spin_lock_bh(&ams_delta_lock); - mod_timer(&cx81801_timer, jiffies + msecs_to_jiffies(150)); - apply = !ams_delta_muted && !cx81801_cmd_pending; - cx81801_cmd_pending = 1; - spin_unlock_bh(&ams_delta_lock); - - /* Apply config pulse by connecting the codec to the modem - * if not already done */ - if (apply) - ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, - AMS_DELTA_LATCH2_MODEM_CODEC); - break; - } -} - -/* Line discipline .write_wakeup() */ -static void cx81801_wakeup(struct tty_struct *tty) -{ - v253_ops.write_wakeup(tty); -} - -static struct tty_ldisc_ops cx81801_ops = { - .magic = TTY_LDISC_MAGIC, - .name = "cx81801", - .owner = THIS_MODULE, - .open = cx81801_open, - .close = cx81801_close, - .hangup = cx81801_hangup, - .receive_buf = cx81801_receive, - .write_wakeup = cx81801_wakeup, -}; - - -/* - * Even if not very usefull, the sound card can still work without any of the - * above functonality activated. You can still control its audio input/output - * constellation and speakerphone gain from userspace by issueing AT commands - * over the modem port. - */ - -static int ams_delta_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - - /* Set cpu DAI configuration */ - return snd_soc_dai_set_fmt(rtd->dai->cpu_dai, - SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); -} - -static struct snd_soc_ops ams_delta_ops = { - .hw_params = ams_delta_hw_params, -}; - - -/* Board specific codec bias level control */ -static int ams_delta_set_bias_level(struct snd_soc_card *card, - enum snd_soc_bias_level level) -{ - struct snd_soc_codec *codec = card->codec; - - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - case SND_SOC_BIAS_STANDBY: - if (codec->bias_level == SND_SOC_BIAS_OFF) - ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_NRESET, - AMS_DELTA_LATCH2_MODEM_NRESET); - break; - case SND_SOC_BIAS_OFF: - if (codec->bias_level != SND_SOC_BIAS_OFF) - ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_NRESET, - 0); - } - codec->bias_level = level; - - return 0; -} - -/* Digital mute implemented using modem/CPU multiplexer. - * Shares hardware with codec config pulse generation */ -static bool ams_delta_muted = 1; - -static int ams_delta_digital_mute(struct snd_soc_dai *dai, int mute) -{ - int apply; - - if (ams_delta_muted == mute) - return 0; - - spin_lock_bh(&ams_delta_lock); - ams_delta_muted = mute; - apply = !cx81801_cmd_pending; - spin_unlock_bh(&ams_delta_lock); - - if (apply) - ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, - mute ? AMS_DELTA_LATCH2_MODEM_CODEC : 0); - return 0; -} - -/* Our codec DAI probably doesn't have its own .ops structure */ -static struct snd_soc_dai_ops ams_delta_dai_ops = { - .digital_mute = ams_delta_digital_mute, -}; - -/* Will be used if the codec ever has its own digital_mute function */ -static int ams_delta_startup(struct snd_pcm_substream *substream) -{ - return ams_delta_digital_mute(NULL, 0); -} - -static void ams_delta_shutdown(struct snd_pcm_substream *substream) -{ - ams_delta_digital_mute(NULL, 1); -} - - -/* - * Card initialization - */ - -static int ams_delta_cx20442_init(struct snd_soc_codec *codec) -{ - struct snd_soc_dai *codec_dai = codec->dai; - struct snd_soc_card *card = codec->socdev->card; - int ret; - /* Codec is ready, now add/activate board specific controls */ - - /* Set up digital mute if not provided by the codec */ - if (!codec_dai->ops) { - codec_dai->ops = &ams_delta_dai_ops; - } else if (!codec_dai->ops->digital_mute) { - codec_dai->ops->digital_mute = ams_delta_digital_mute; - } else { - ams_delta_ops.startup = ams_delta_startup; - ams_delta_ops.shutdown = ams_delta_shutdown; - } - - /* Set codec bias level */ - ams_delta_set_bias_level(card, SND_SOC_BIAS_STANDBY); - - /* Add hook switch - can be used to control the codec from userspace - * even if line discipline fails */ - ret = snd_soc_jack_new(card, "hook_switch", - SND_JACK_HEADSET, &ams_delta_hook_switch); - if (ret) - dev_warn(card->dev, - "Failed to allocate resources for hook switch, " - "will continue without one.\n"); - else { - ret = snd_soc_jack_add_gpios(&ams_delta_hook_switch, - ARRAY_SIZE(ams_delta_hook_switch_gpios), - ams_delta_hook_switch_gpios); - if (ret) - dev_warn(card->dev, - "Failed to set up hook switch GPIO line, " - "will continue with hook switch inactive.\n"); - } - - /* Register optional line discipline for over the modem control */ - ret = tty_register_ldisc(N_AMSDELTA, &cx81801_ops); - if (ret) { - dev_warn(card->dev, - "Failed to register line discipline, " - "will continue without any controls.\n"); - return 0; - } - - /* Add board specific DAPM widgets and routes */ - ret = snd_soc_dapm_new_controls(codec, ams_delta_dapm_widgets, - ARRAY_SIZE(ams_delta_dapm_widgets)); - if (ret) { - dev_warn(card->dev, - "Failed to register DAPM controls, " - "will continue without any.\n"); - return 0; - } - - ret = snd_soc_dapm_add_routes(codec, ams_delta_audio_map, - ARRAY_SIZE(ams_delta_audio_map)); - if (ret) { - dev_warn(card->dev, - "Failed to set up DAPM routes, " - "will continue with codec default map.\n"); - return 0; - } - - /* Set up initial pin constellation */ - snd_soc_dapm_disable_pin(codec, "Mouthpiece"); - snd_soc_dapm_enable_pin(codec, "Earpiece"); - snd_soc_dapm_enable_pin(codec, "Microphone"); - snd_soc_dapm_disable_pin(codec, "Speaker"); - snd_soc_dapm_disable_pin(codec, "AGCIN"); - snd_soc_dapm_disable_pin(codec, "AGCOUT"); - snd_soc_dapm_sync(codec); - - /* Add virtual switch */ - ret = snd_soc_add_controls(codec, ams_delta_audio_controls, - ARRAY_SIZE(ams_delta_audio_controls)); - if (ret) - dev_warn(card->dev, - "Failed to register audio mode control, " - "will continue without it.\n"); - - return 0; -} - -/* DAI glue - connects codec <--> CPU */ -static struct snd_soc_dai_link ams_delta_dai_link = { - .name = "CX20442", - .stream_name = "CX20442", - .cpu_dai = &omap_mcbsp_dai[0], - .codec_dai = &cx20442_dai, - .init = ams_delta_cx20442_init, - .ops = &ams_delta_ops, -}; - -/* Audio card driver */ -static struct snd_soc_card ams_delta_audio_card = { - .name = "AMS_DELTA", - .platform = &omap_soc_platform, - .dai_link = &ams_delta_dai_link, - .num_links = 1, - .set_bias_level = ams_delta_set_bias_level, -}; - -/* Audio subsystem */ -static struct snd_soc_device ams_delta_snd_soc_device = { - .card = &ams_delta_audio_card, - .codec_dev = &cx20442_codec_dev, -}; - -/* Module init/exit */ -static struct platform_device *ams_delta_audio_platform_device; -static struct platform_device *cx20442_platform_device; - -static int __init ams_delta_module_init(void) -{ - int ret; - - if (!(machine_is_ams_delta())) - return -ENODEV; - - ams_delta_audio_platform_device = - platform_device_alloc("soc-audio", -1); - if (!ams_delta_audio_platform_device) - return -ENOMEM; - - platform_set_drvdata(ams_delta_audio_platform_device, - &ams_delta_snd_soc_device); - ams_delta_snd_soc_device.dev = &ams_delta_audio_platform_device->dev; - *(unsigned int *)ams_delta_dai_link.cpu_dai->private_data = OMAP_MCBSP1; - - ret = platform_device_add(ams_delta_audio_platform_device); - if (ret) - goto err; - - /* - * Codec platform device could be registered from elsewhere (board?), - * but I do it here as it makes sense only if used with the card. - */ - cx20442_platform_device = platform_device_register_simple("cx20442", - -1, NULL, 0); - return 0; -err: - platform_device_put(ams_delta_audio_platform_device); - return ret; -} -module_init(ams_delta_module_init); - -static void __exit ams_delta_module_exit(void) -{ - struct snd_soc_codec *codec; - struct tty_struct *tty; - - if (ams_delta_audio_card.codec) { - codec = ams_delta_audio_card.codec; - - if (codec->control_data) { - tty = codec->control_data; - - tty_hangup(tty); - } - } - - if (tty_unregister_ldisc(N_AMSDELTA) != 0) - dev_warn(&ams_delta_audio_platform_device->dev, - "failed to unregister AMSDELTA line discipline\n"); - - snd_soc_jack_free_gpios(&ams_delta_hook_switch, - ARRAY_SIZE(ams_delta_hook_switch_gpios), - ams_delta_hook_switch_gpios); - - /* Keep modem power on */ - ams_delta_set_bias_level(&ams_delta_audio_card, SND_SOC_BIAS_STANDBY); - - platform_device_unregister(cx20442_platform_device); - platform_device_unregister(ams_delta_audio_platform_device); -} -module_exit(ams_delta_module_exit); - -MODULE_AUTHOR("Janusz Krzysztofik "); -MODULE_DESCRIPTION("ALSA SoC driver for Amstrad E3 (Delta) videophone"); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/omap/omap-mcbsp.c b/trunk/sound/soc/omap/omap-mcbsp.c index 6a837ffd5d0b..a5d46a7b196a 100644 --- a/trunk/sound/soc/omap/omap-mcbsp.c +++ b/trunk/sound/soc/omap/omap-mcbsp.c @@ -183,21 +183,21 @@ static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); - int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); + int err = 0; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - mcbsp_data->active++; - omap_mcbsp_start(mcbsp_data->bus_id, play, !play); + if (!mcbsp_data->active++) + omap_mcbsp_start(mcbsp_data->bus_id); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - omap_mcbsp_stop(mcbsp_data->bus_id, play, !play); - mcbsp_data->active--; + if (!--mcbsp_data->active) + omap_mcbsp_stop(mcbsp_data->bus_id); break; default: err = -EINVAL; diff --git a/trunk/sound/soc/omap/omap-pcm.c b/trunk/sound/soc/omap/omap-pcm.c index c3c931d4537a..84a1950880eb 100644 --- a/trunk/sound/soc/omap/omap-pcm.c +++ b/trunk/sound/soc/omap/omap-pcm.c @@ -330,7 +330,7 @@ static void omap_pcm_free_dma_buffers(struct snd_pcm *pcm) } } -static int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, +int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, struct snd_pcm *pcm) { int ret = 0; diff --git a/trunk/sound/soc/omap/sdp3430.c b/trunk/sound/soc/omap/sdp3430.c index f7e5b7488c35..c51594d8fd13 100644 --- a/trunk/sound/soc/omap/sdp3430.c +++ b/trunk/sound/soc/omap/sdp3430.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -40,9 +39,6 @@ #include "omap-pcm.h" #include "../codecs/twl4030.h" -#define TWL4030_INTBR_PMBR1 0x0D -#define EXTMUTE(value) (value << 2) - static struct snd_soc_card snd_soc_sdp3430; static int sdp3430_hw_params(struct snd_pcm_substream *substream, @@ -284,7 +280,6 @@ static struct snd_soc_card snd_soc_sdp3430 = { static struct twl4030_setup_data twl4030_setup = { .ramp_delay_value = 3, .sysclk = 26000, - .hs_extmute = 1, }; /* Audio subsystem */ @@ -317,10 +312,6 @@ static int __init sdp3430_soc_init(void) *(unsigned int *)sdp3430_dai[0].cpu_dai->private_data = 1; /* McBSP2 */ *(unsigned int *)sdp3430_dai[1].cpu_dai->private_data = 2; /* McBSP3 */ - /* Set TWL4030 GPIO6 as EXTMUTE signal */ - twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, EXTMUTE(0x02), - TWL4030_MODULE_INTBR); - ret = platform_device_add(sdp3430_snd_device); if (ret) goto err1; diff --git a/trunk/sound/soc/pxa/palm27x.c b/trunk/sound/soc/pxa/palm27x.c index 1f96e3227be5..e6102fda0a7f 100644 --- a/trunk/sound/soc/pxa/palm27x.c +++ b/trunk/sound/soc/pxa/palm27x.c @@ -17,12 +17,13 @@ #include #include #include +#include +#include #include #include #include #include -#include #include #include @@ -32,31 +33,90 @@ #include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" -static struct snd_soc_jack hs_jack; +static int palm27x_jack_func = 1; +static int palm27x_spk_func = 1; +static int palm27x_ep_gpio = -1; -/* Headphones jack detection DAPM pins */ -static struct snd_soc_jack_pin hs_jack_pins[] = { - { - .pin = "Headphone Jack", - .mask = SND_JACK_HEADPHONE, - }, -}; +static void palm27x_ext_control(struct snd_soc_codec *codec) +{ + if (!palm27x_spk_func) + snd_soc_dapm_enable_pin(codec, "Speaker"); + else + snd_soc_dapm_disable_pin(codec, "Speaker"); -/* Headphones jack detection gpios */ -static struct snd_soc_jack_gpio hs_jack_gpios[] = { - [0] = { - /* gpio is set on per-platform basis */ - .name = "hp-gpio", - .report = SND_JACK_HEADPHONE, - .debounce_time = 200, - }, + if (!palm27x_jack_func) + snd_soc_dapm_enable_pin(codec, "Headphone Jack"); + else + snd_soc_dapm_disable_pin(codec, "Headphone Jack"); + + snd_soc_dapm_sync(codec); +} + +static int palm27x_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->socdev->card->codec; + + /* check the jack status at stream startup */ + palm27x_ext_control(codec); + return 0; +} + +static struct snd_soc_ops palm27x_ops = { + .startup = palm27x_startup, }; -/* Palm27x machine dapm widgets */ +static irqreturn_t palm27x_interrupt(int irq, void *v) +{ + palm27x_spk_func = gpio_get_value(palm27x_ep_gpio); + palm27x_jack_func = !palm27x_spk_func; + return IRQ_HANDLED; +} + +static int palm27x_get_jack(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = palm27x_jack_func; + return 0; +} + +static int palm27x_set_jack(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + + if (palm27x_jack_func == ucontrol->value.integer.value[0]) + return 0; + + palm27x_jack_func = ucontrol->value.integer.value[0]; + palm27x_ext_control(codec); + return 1; +} + +static int palm27x_get_spk(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = palm27x_spk_func; + return 0; +} + +static int palm27x_set_spk(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + + if (palm27x_spk_func == ucontrol->value.integer.value[0]) + return 0; + + palm27x_spk_func = ucontrol->value.integer.value[0]; + palm27x_ext_control(codec); + return 1; +} + +/* PalmTX machine dapm widgets */ static const struct snd_soc_dapm_widget palm27x_dapm_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_SPK("Ext. Speaker", NULL), - SND_SOC_DAPM_MIC("Ext. Microphone", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), }; /* PalmTX audio map */ @@ -66,66 +126,46 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Headphone Jack", NULL, "HPOUTR"}, /* ext speaker connected to ROUT2, LOUT2 */ - {"Ext. Speaker", NULL, "LOUT2"}, - {"Ext. Speaker", NULL, "ROUT2"}, + {"Speaker", NULL, "LOUT2"}, + {"Speaker", NULL, "ROUT2"}, +}; - /* mic connected to MIC1 */ - {"Ext. Microphone", NULL, "MIC1"}, +static const char *jack_function[] = {"Headphone", "Off"}; +static const char *spk_function[] = {"On", "Off"}; +static const struct soc_enum palm27x_enum[] = { + SOC_ENUM_SINGLE_EXT(2, jack_function), + SOC_ENUM_SINGLE_EXT(2, spk_function), }; -static struct snd_soc_card palm27x_asoc; +static const struct snd_kcontrol_new palm27x_controls[] = { + SOC_ENUM_EXT("Jack Function", palm27x_enum[0], palm27x_get_jack, + palm27x_set_jack), + SOC_ENUM_EXT("Speaker Function", palm27x_enum[1], palm27x_get_spk, + palm27x_set_spk), +}; static int palm27x_ac97_init(struct snd_soc_codec *codec) { int err; - /* add palm27x specific widgets */ - err = snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets, - ARRAY_SIZE(palm27x_dapm_widgets)); - if (err) - return err; - - /* set up palm27x specific audio path audio_map */ - err = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - if (err) - return err; - - /* connected pins */ - if (machine_is_palmld()) - snd_soc_dapm_enable_pin(codec, "MIC1"); - snd_soc_dapm_enable_pin(codec, "HPOUTL"); - snd_soc_dapm_enable_pin(codec, "HPOUTR"); - snd_soc_dapm_enable_pin(codec, "LOUT2"); - snd_soc_dapm_enable_pin(codec, "ROUT2"); - - /* not connected pins */ snd_soc_dapm_nc_pin(codec, "OUT3"); snd_soc_dapm_nc_pin(codec, "MONOOUT"); - snd_soc_dapm_nc_pin(codec, "LINEINL"); - snd_soc_dapm_nc_pin(codec, "LINEINR"); - snd_soc_dapm_nc_pin(codec, "PCBEEP"); - snd_soc_dapm_nc_pin(codec, "PHONE"); - snd_soc_dapm_nc_pin(codec, "MIC2"); - - err = snd_soc_dapm_sync(codec); - if (err) - return err; - /* Jack detection API stuff */ - err = snd_soc_jack_new(&palm27x_asoc, "Headphone Jack", - SND_JACK_HEADPHONE, &hs_jack); - if (err) + /* add palm27x specific controls */ + err = snd_soc_add_controls(codec, palm27x_controls, + ARRAY_SIZE(palm27x_controls)); + if (err < 0) return err; - err = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), - hs_jack_pins); - if (err) - return err; + /* add palm27x specific widgets */ + snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets, + ARRAY_SIZE(palm27x_dapm_widgets)); - err = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios), - hs_jack_gpios); + /* set up palm27x specific audio path audio_map */ + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - return err; + snd_soc_dapm_sync(codec); + return 0; } static struct snd_soc_dai_link palm27x_dai[] = { @@ -135,12 +175,14 @@ static struct snd_soc_dai_link palm27x_dai[] = { .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], .init = palm27x_ac97_init, + .ops = &palm27x_ops, }, { .name = "AC97 Aux", .stream_name = "AC97 Aux", .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], + .ops = &palm27x_ops, }, }; @@ -166,17 +208,27 @@ static int palm27x_asoc_probe(struct platform_device *pdev) machine_is_palmld() || machine_is_palmte2())) return -ENODEV; - if (!pdev->dev.platform_data) { - dev_err(&pdev->dev, "please supply platform_data\n"); - return -ENODEV; - } - - hs_jack_gpios[0].gpio = ((struct palm27x_asoc_info *) + if (pdev->dev.platform_data) + palm27x_ep_gpio = ((struct palm27x_asoc_info *) (pdev->dev.platform_data))->jack_gpio; + ret = gpio_request(palm27x_ep_gpio, "Headphone Jack"); + if (ret) + return ret; + ret = gpio_direction_input(palm27x_ep_gpio); + if (ret) + goto err_alloc; + + if (request_irq(gpio_to_irq(palm27x_ep_gpio), palm27x_interrupt, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "Headphone jack", NULL)) + goto err_alloc; + palm27x_snd_device = platform_device_alloc("soc-audio", -1); - if (!palm27x_snd_device) - return -ENOMEM; + if (!palm27x_snd_device) { + ret = -ENOMEM; + goto err_dev; + } platform_set_drvdata(palm27x_snd_device, &palm27x_snd_devdata); palm27x_snd_devdata.dev = &palm27x_snd_device->dev; @@ -189,12 +241,18 @@ static int palm27x_asoc_probe(struct platform_device *pdev) put_device: platform_device_put(palm27x_snd_device); +err_dev: + free_irq(gpio_to_irq(palm27x_ep_gpio), NULL); +err_alloc: + gpio_free(palm27x_ep_gpio); return ret; } static int __devexit palm27x_asoc_remove(struct platform_device *pdev) { + free_irq(gpio_to_irq(palm27x_ep_gpio), NULL); + gpio_free(palm27x_ep_gpio); platform_device_unregister(palm27x_snd_device); return 0; } diff --git a/trunk/sound/soc/s3c24xx/Kconfig b/trunk/sound/soc/s3c24xx/Kconfig index 808de5c5caa7..df494d1e346f 100644 --- a/trunk/sound/soc/s3c24xx/Kconfig +++ b/trunk/sound/soc/s3c24xx/Kconfig @@ -38,15 +38,6 @@ config SND_S3C24XX_SOC_NEO1973_WM8753 Say Y if you want to add support for SoC audio on smdk2440 with the WM8753. -config SND_S3C24XX_SOC_NEO1973_GTA02_WM8753 - tristate "Audio support for the Openmoko Neo FreeRunner (GTA02)" - depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA02 - select SND_S3C24XX_SOC_I2S - select SND_SOC_WM8753 - help - This driver provides audio support for the Openmoko Neo FreeRunner - smartphone. - config SND_S3C24XX_SOC_JIVE_WM8750 tristate "SoC I2S Audio support for Jive" depends on SND_S3C24XX_SOC && MACH_JIVE @@ -66,7 +57,7 @@ config SND_S3C24XX_SOC_SMDK2443_WM9710 config SND_S3C24XX_SOC_LN2440SBC_ALC650 tristate "SoC AC97 Audio support for LN2440SBC - ALC650" - depends on SND_S3C24XX_SOC && ARCH_S3C2410 + depends on SND_S3C24XX_SOC select SND_S3C2443_SOC_AC97 select SND_SOC_AC97_CODEC help @@ -75,7 +66,7 @@ config SND_S3C24XX_SOC_LN2440SBC_ALC650 config SND_S3C24XX_SOC_S3C24XX_UDA134X tristate "SoC I2S Audio support UDA134X wired to a S3C24XX" - depends on SND_S3C24XX_SOC && ARCH_S3C2410 + depends on SND_S3C24XX_SOC select SND_S3C24XX_SOC_I2S select SND_SOC_L3 select SND_SOC_UDA134X diff --git a/trunk/sound/soc/s3c24xx/Makefile b/trunk/sound/soc/s3c24xx/Makefile index eb219b016499..07a93a2ebe5f 100644 --- a/trunk/sound/soc/s3c24xx/Makefile +++ b/trunk/sound/soc/s3c24xx/Makefile @@ -16,14 +16,12 @@ obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o # S3C24XX Machine Support snd-soc-jive-wm8750-objs := jive_wm8750.o snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o -snd-soc-neo1973-gta02-wm8753-objs := neo1973_gta02_wm8753.o snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o -obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_GTA02_WM8753) += snd-soc-neo1973-gta02-wm8753.o obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o diff --git a/trunk/sound/soc/s3c24xx/neo1973_gta02_wm8753.c b/trunk/sound/soc/s3c24xx/neo1973_gta02_wm8753.c deleted file mode 100644 index 0c52e36ddd87..000000000000 --- a/trunk/sound/soc/s3c24xx/neo1973_gta02_wm8753.c +++ /dev/null @@ -1,498 +0,0 @@ -/* - * neo1973_gta02_wm8753.c -- SoC audio for Openmoko Freerunner(GTA02) - * - * Copyright 2007 Openmoko Inc - * Author: Graeme Gregory - * Copyright 2007 Wolfson Microelectronics PLC. - * Author: Graeme Gregory - * Copyright 2009 Wolfson Microelectronics - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include "../codecs/wm8753.h" -#include "s3c24xx-pcm.h" -#include "s3c24xx-i2s.h" - -static struct snd_soc_card neo1973_gta02; - -static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - unsigned int pll_out = 0, bclk = 0; - int ret = 0; - unsigned long iis_clkrate; - - iis_clkrate = s3c24xx_i2s_get_clockrate(); - - switch (params_rate(params)) { - case 8000: - case 16000: - pll_out = 12288000; - break; - case 48000: - bclk = WM8753_BCLK_DIV_4; - pll_out = 12288000; - break; - case 96000: - bclk = WM8753_BCLK_DIV_2; - pll_out = 12288000; - break; - case 11025: - bclk = WM8753_BCLK_DIV_16; - pll_out = 11289600; - break; - case 22050: - bclk = WM8753_BCLK_DIV_8; - pll_out = 11289600; - break; - case 44100: - bclk = WM8753_BCLK_DIV_4; - pll_out = 11289600; - break; - case 88200: - bclk = WM8753_BCLK_DIV_2; - pll_out = 11289600; - break; - } - - /* set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) - return ret; - - /* set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, - SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) - return ret; - - /* set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out, - SND_SOC_CLOCK_IN); - if (ret < 0) - return ret; - - /* set MCLK division for sample rate */ - ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, - S3C2410_IISMOD_32FS); - if (ret < 0) - return ret; - - /* set codec BCLK division for sample rate */ - ret = snd_soc_dai_set_clkdiv(codec_dai, - WM8753_BCLKDIV, bclk); - if (ret < 0) - return ret; - - /* set prescaler division for sample rate */ - ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER, - S3C24XX_PRESCALE(4, 4)); - if (ret < 0) - return ret; - - /* codec PLL input is PCLK/4 */ - ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, - iis_clkrate / 4, pll_out); - if (ret < 0) - return ret; - - return 0; -} - -static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - - /* disable the PLL */ - return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0); -} - -/* - * Neo1973 WM8753 HiFi DAI opserations. - */ -static struct snd_soc_ops neo1973_gta02_hifi_ops = { - .hw_params = neo1973_gta02_hifi_hw_params, - .hw_free = neo1973_gta02_hifi_hw_free, -}; - -static int neo1973_gta02_voice_hw_params( - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - unsigned int pcmdiv = 0; - int ret = 0; - unsigned long iis_clkrate; - - iis_clkrate = s3c24xx_i2s_get_clockrate(); - - if (params_rate(params) != 8000) - return -EINVAL; - if (params_channels(params) != 1) - return -EINVAL; - - pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */ - - /* todo: gg check mode (DSP_B) against CSR datasheet */ - /* set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - if (ret < 0) - return ret; - - /* set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK, - 12288000, SND_SOC_CLOCK_IN); - if (ret < 0) - return ret; - - /* set codec PCM division for sample rate */ - ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV, - pcmdiv); - if (ret < 0) - return ret; - - /* configue and enable PLL for 12.288MHz output */ - ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, - iis_clkrate / 4, 12288000); - if (ret < 0) - return ret; - - return 0; -} - -static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - - /* disable the PLL */ - return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0); -} - -static struct snd_soc_ops neo1973_gta02_voice_ops = { - .hw_params = neo1973_gta02_voice_hw_params, - .hw_free = neo1973_gta02_voice_hw_free, -}; - -#define LM4853_AMP 1 -#define LM4853_SPK 2 - -static u8 lm4853_state; - -/* This has no effect, it exists only to maintain compatibility with - * existing ALSA state files. - */ -static int lm4853_set_state(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int val = ucontrol->value.integer.value[0]; - - if (val) - lm4853_state |= LM4853_AMP; - else - lm4853_state &= ~LM4853_AMP; - - return 0; -} - -static int lm4853_get_state(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = lm4853_state & LM4853_AMP; - - return 0; -} - -static int lm4853_set_spk(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int val = ucontrol->value.integer.value[0]; - - if (val) { - lm4853_state |= LM4853_SPK; - gpio_set_value(GTA02_GPIO_HP_IN, 0); - } else { - lm4853_state &= ~LM4853_SPK; - gpio_set_value(GTA02_GPIO_HP_IN, 1); - } - - return 0; -} - -static int lm4853_get_spk(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = (lm4853_state & LM4853_SPK) >> 1; - - return 0; -} - -static int lm4853_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, - int event) -{ - gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(value)); - - return 0; -} - -static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = { - SND_SOC_DAPM_SPK("Stereo Out", lm4853_event), - SND_SOC_DAPM_LINE("GSM Line Out", NULL), - SND_SOC_DAPM_LINE("GSM Line In", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_MIC("Handset Mic", NULL), - SND_SOC_DAPM_SPK("Handset Spk", NULL), -}; - - -/* example machine audio_mapnections */ -static const struct snd_soc_dapm_route audio_map[] = { - - /* Connections to the lm4853 amp */ - {"Stereo Out", NULL, "LOUT1"}, - {"Stereo Out", NULL, "ROUT1"}, - - /* Connections to the GSM Module */ - {"GSM Line Out", NULL, "MONO1"}, - {"GSM Line Out", NULL, "MONO2"}, - {"RXP", NULL, "GSM Line In"}, - {"RXN", NULL, "GSM Line In"}, - - /* Connections to Headset */ - {"MIC1", NULL, "Mic Bias"}, - {"Mic Bias", NULL, "Headset Mic"}, - - /* Call Mic */ - {"MIC2", NULL, "Mic Bias"}, - {"MIC2N", NULL, "Mic Bias"}, - {"Mic Bias", NULL, "Handset Mic"}, - - /* Call Speaker */ - {"Handset Spk", NULL, "LOUT2"}, - {"Handset Spk", NULL, "ROUT2"}, - - /* Connect the ALC pins */ - {"ACIN", NULL, "ACOP"}, -}; - -static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = { - SOC_DAPM_PIN_SWITCH("Stereo Out"), - SOC_DAPM_PIN_SWITCH("GSM Line Out"), - SOC_DAPM_PIN_SWITCH("GSM Line In"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Handset Mic"), - SOC_DAPM_PIN_SWITCH("Handset Spk"), - - /* This has no effect, it exists only to maintain compatibility with - * existing ALSA state files. - */ - SOC_SINGLE_EXT("Amp State Switch", 6, 0, 1, 0, - lm4853_get_state, - lm4853_set_state), - SOC_SINGLE_EXT("Amp Spk Switch", 7, 0, 1, 0, - lm4853_get_spk, - lm4853_set_spk), -}; - -/* - * This is an example machine initialisation for a wm8753 connected to a - * neo1973 GTA02. - */ -static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) -{ - int err; - - /* set up NC codec pins */ - snd_soc_dapm_nc_pin(codec, "OUT3"); - snd_soc_dapm_nc_pin(codec, "OUT4"); - snd_soc_dapm_nc_pin(codec, "LINE1"); - snd_soc_dapm_nc_pin(codec, "LINE2"); - - /* Add neo1973 gta02 specific widgets */ - snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets, - ARRAY_SIZE(wm8753_dapm_widgets)); - - /* add neo1973 gta02 specific controls */ - err = snd_soc_add_controls(codec, wm8753_neo1973_gta02_controls, - ARRAY_SIZE(wm8753_neo1973_gta02_controls)); - - if (err < 0) - return err; - - /* set up neo1973 gta02 specific audio path audio_map */ - snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - - /* set endpoints to default off mode */ - snd_soc_dapm_disable_pin(codec, "Stereo Out"); - snd_soc_dapm_disable_pin(codec, "GSM Line Out"); - snd_soc_dapm_disable_pin(codec, "GSM Line In"); - snd_soc_dapm_disable_pin(codec, "Headset Mic"); - snd_soc_dapm_disable_pin(codec, "Handset Mic"); - snd_soc_dapm_disable_pin(codec, "Handset Spk"); - - snd_soc_dapm_sync(codec); - - return 0; -} - -/* - * BT Codec DAI - */ -static struct snd_soc_dai bt_dai = { - .name = "Bluetooth", - .id = 0, - .playback = { - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .capture = { - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, -}; - -static struct snd_soc_dai_link neo1973_gta02_dai[] = { -{ /* Hifi Playback - for similatious use with voice below */ - .name = "WM8753", - .stream_name = "WM8753 HiFi", - .cpu_dai = &s3c24xx_i2s_dai, - .codec_dai = &wm8753_dai[WM8753_DAI_HIFI], - .init = neo1973_gta02_wm8753_init, - .ops = &neo1973_gta02_hifi_ops, -}, -{ /* Voice via BT */ - .name = "Bluetooth", - .stream_name = "Voice", - .cpu_dai = &bt_dai, - .codec_dai = &wm8753_dai[WM8753_DAI_VOICE], - .ops = &neo1973_gta02_voice_ops, -}, -}; - -static struct snd_soc_card neo1973_gta02 = { - .name = "neo1973-gta02", - .platform = &s3c24xx_soc_platform, - .dai_link = neo1973_gta02_dai, - .num_links = ARRAY_SIZE(neo1973_gta02_dai), -}; - -static struct snd_soc_device neo1973_gta02_snd_devdata = { - .card = &neo1973_gta02, - .codec_dev = &soc_codec_dev_wm8753, -}; - -static struct platform_device *neo1973_gta02_snd_device; - -static int __init neo1973_gta02_init(void) -{ - int ret; - - if (!machine_is_neo1973_gta02()) { - printk(KERN_INFO - "Only GTA02 is supported by this ASoC driver\n"); - return -ENODEV; - } - - /* register bluetooth DAI here */ - ret = snd_soc_register_dai(&bt_dai); - if (ret) - return ret; - - neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1); - if (!neo1973_gta02_snd_device) - return -ENOMEM; - - platform_set_drvdata(neo1973_gta02_snd_device, - &neo1973_gta02_snd_devdata); - neo1973_gta02_snd_devdata.dev = &neo1973_gta02_snd_device->dev; - ret = platform_device_add(neo1973_gta02_snd_device); - - if (ret) { - platform_device_put(neo1973_gta02_snd_device); - return ret; - } - - /* Initialise GPIOs used by amp */ - ret = gpio_request(GTA02_GPIO_HP_IN, "GTA02_HP_IN"); - if (ret) { - pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_HP_IN); - goto err_unregister_device; - } - - ret = gpio_direction_output(GTA02_GPIO_AMP_HP_IN, 1); - if (ret) { - pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN); - goto err_free_gpio_hp_in; - } - - ret = gpio_request(GTA02_GPIO_AMP_SHUT, "GTA02_AMP_SHUT"); - if (ret) { - pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_AMP_SHUT); - goto err_free_gpio_hp_in; - } - - ret = gpio_direction_output(GTA02_GPIO_AMP_SHUT, 1); - if (ret) { - pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_AMP_SHUT); - goto err_free_gpio_amp_shut; - } - - return 0; - -err_free_gpio_amp_shut: - gpio_free(GTA02_GPIO_AMP_SHUT); -err_free_gpio_hp_in: - gpio_free(GTA02_GPIO_HP_IN); -err_unregister_device: - platform_device_unregister(neo1973_gta02_snd_device); - return ret; -} -module_init(neo1973_gta02_init); - -static void __exit neo1973_gta02_exit(void) -{ - snd_soc_unregister_dai(&bt_dai); - platform_device_unregister(neo1973_gta02_snd_device); - gpio_free(GTA02_GPIO_HP_IN); - gpio_free(GTA02_GPIO_AMP_SHUT); -} -module_exit(neo1973_gta02_exit); - -/* Module information */ -MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org"); -MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 GTA02"); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/soc-cache.c b/trunk/sound/soc/soc-cache.c new file mode 100644 index 000000000000..4eb4333a0efb --- /dev/null +++ b/trunk/sound/soc/soc-cache.c @@ -0,0 +1,105 @@ +/* + * soc-cache.c -- ASoC register cache helpers + * + * Copyright 2009 Wolfson Microelectronics PLC. + * + * Author: Mark Brown + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include + +static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + if (reg >= codec->reg_cache_size) + return -1; + return cache[reg]; +} + +static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + u16 *cache = codec->reg_cache; + u8 data[2]; + int ret; + + BUG_ON(codec->volatile_register); + + data[0] = (reg << 1) | ((value >> 8) & 0x0001); + data[1] = value & 0x00ff; + + if (reg < codec->reg_cache_size) + cache[reg] = value; + ret = codec->hw_write(codec->control_data, data, 2); + if (ret == 2) + return 0; + if (ret < 0) + return ret; + else + return -EIO; +} + + +static struct { + int addr_bits; + int data_bits; + int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); + unsigned int (*read)(struct snd_soc_codec *, unsigned int); +} io_types[] = { + { 7, 9, snd_soc_7_9_write, snd_soc_7_9_read }, +}; + +/** + * snd_soc_codec_set_cache_io: Set up standard I/O functions. + * + * @codec: CODEC to configure. + * @type: Type of cache. + * @addr_bits: Number of bits of register address data. + * @data_bits: Number of bits of data per register. + * + * Register formats are frequently shared between many I2C and SPI + * devices. In order to promote code reuse the ASoC core provides + * some standard implementations of CODEC read and write operations + * which can be set up using this function. + * + * The caller is responsible for allocating and initialising the + * actual cache. + * + * Note that at present this code cannot be used by CODECs with + * volatile registers. + */ +int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, + int addr_bits, int data_bits) +{ + int i; + + /* We don't support volatile registers yet - refactoring of + * the hw_read operation will be required to do so. */ + if (codec->volatile_register) { + printk(KERN_ERR "Volatile registers not yet supported\n"); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(io_types); i++) + if (io_types[i].addr_bits == addr_bits && + io_types[i].data_bits == data_bits) + break; + if (i == ARRAY_SIZE(io_types)) { + printk(KERN_ERR + "No I/O functions for %d bit address %d bit data\n", + addr_bits, data_bits); + return -EINVAL; + } + + codec->write = io_types[i].write; + codec->read = io_types[i].read; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); diff --git a/trunk/sound/soc/soc-core.c b/trunk/sound/soc/soc-core.c index fb8d7a766155..8bf49a4e664a 100644 --- a/trunk/sound/soc/soc-core.c +++ b/trunk/sound/soc/soc-core.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -1156,9 +1155,6 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) count += sprintf(buf, "%s registers\n", codec->name); for (i = 0; i < codec->reg_cache_size; i += step) { - if (codec->readable_register && !codec->readable_register(i)) - continue; - count += sprintf(buf + count, "%2x: ", i); if (count >= PAGE_SIZE - 1) break; @@ -1465,11 +1461,8 @@ int snd_soc_init_card(struct snd_soc_device *socdev) continue; } } - if (card->dai_link[i].codec_dai->ac97_control) { + if (card->dai_link[i].codec_dai->ac97_control) ac97 = 1; - snd_ac97_dev_add_pdata(codec->ac97, - card->dai_link[i].cpu_dai->ac97_pdata); - } } snprintf(codec->card->shortname, sizeof(codec->card->shortname), "%s", card->name); diff --git a/trunk/sound/soc/soc-dapm.c b/trunk/sound/soc/soc-dapm.c index c68c204a48ad..5157ec110cfa 100644 --- a/trunk/sound/soc/soc-dapm.c +++ b/trunk/sound/soc/soc-dapm.c @@ -997,9 +997,6 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) pr_err("Failed to apply active bias: %d\n", ret); } - pop_dbg(codec->pop_time, "DAPM sequencing finished, waiting %dms\n", - codec->pop_time); - return 0; } @@ -1293,8 +1290,8 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, if (wsink->id == snd_soc_dapm_input) { if (wsource->id == snd_soc_dapm_micbias || wsource->id == snd_soc_dapm_mic || - wsource->id == snd_soc_dapm_line || - wsource->id == snd_soc_dapm_output) + wsink->id == snd_soc_dapm_line || + wsink->id == snd_soc_dapm_output) wsink->ext = 1; } if (wsource->id == snd_soc_dapm_output) { diff --git a/trunk/sound/soc/soc-jack.c b/trunk/sound/soc/soc-jack.c index 1d455ab79490..28346fb2e70c 100644 --- a/trunk/sound/soc/soc-jack.c +++ b/trunk/sound/soc/soc-jack.c @@ -73,15 +73,14 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) oldstatus = jack->status; jack->status &= ~mask; - jack->status |= status & mask; + jack->status |= status; - /* The DAPM sync is expensive enough to be worth skipping. - * However, empty mask means pin synchronization is desired. */ - if (mask && (jack->status == oldstatus)) + /* The DAPM sync is expensive enough to be worth skipping */ + if (jack->status == oldstatus) goto out; list_for_each_entry(pin, &jack->pins, list) { - enable = pin->mask & jack->status; + enable = pin->mask & status; if (pin->invert) enable = !enable; @@ -221,9 +220,6 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, if (ret) goto err; - INIT_WORK(&gpios[i].work, gpio_work); - gpios[i].jack = jack; - ret = request_irq(gpio_to_irq(gpios[i].gpio), gpio_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, @@ -232,13 +228,8 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, if (ret) goto err; -#ifdef CONFIG_GPIO_SYSFS - /* Expose GPIO value over sysfs for diagnostic purposes */ - gpio_export(gpios[i].gpio, false); -#endif - - /* Update initial jack status */ - snd_soc_jack_gpio_detect(&gpios[i]); + INIT_WORK(&gpios[i].work, gpio_work); + gpios[i].jack = jack; } return 0; @@ -267,9 +258,6 @@ void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, int i; for (i = 0; i < count; i++) { -#ifdef CONFIG_GPIO_SYSFS - gpio_unexport(gpios[i].gpio); -#endif free_irq(gpio_to_irq(gpios[i].gpio), &gpios[i]); gpio_free(gpios[i].gpio); gpios[i].jack = NULL;