diff --git a/[refs] b/[refs] index 3d87b75d9a0c..072e603e1c6c 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 6a90d536feeccb2c84a2831252b1ed4642684da3 +refs/heads/master: c12abc012e18b362204345c323536f228d65c4db diff --git a/trunk/arch/arm/plat-omap/include/mach/mcbsp.h b/trunk/arch/arm/plat-omap/include/mach/mcbsp.h index bb154ea76769..57249bb1e9bc 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); -void omap_mcbsp_stop(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_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 efa0e0111f38..a3d2313460b3 100644 --- a/trunk/arch/arm/plat-omap/mcbsp.c +++ b/trunk/arch/arm/plat-omap/mcbsp.c @@ -328,14 +328,15 @@ void omap_mcbsp_free(unsigned int id) EXPORT_SYMBOL(omap_mcbsp_free); /* - * Here we start the McBSP, by enabling the sample - * generator, both transmitter and receivers, - * and the frame sync. + * 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. */ -void omap_mcbsp_start(unsigned int id) +void omap_mcbsp_start(unsigned int id, int tx, int rx) { struct omap_mcbsp *mcbsp; void __iomem *io_base; + int idle; u16 w; if (!omap_mcbsp_check_valid_id(id)) { @@ -348,32 +349,40 @@ void omap_mcbsp_start(unsigned int id) mcbsp->rx_word_length = (OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7; mcbsp->tx_word_length = (OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7; - /* Start the sample generator */ - w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6)); + 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)); + } /* Enable transmitter and receiver */ w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w | 1); + OMAP_MCBSP_WRITE(io_base, SPCR2, w | (tx & 1)); w = OMAP_MCBSP_READ(io_base, SPCR1); - OMAP_MCBSP_WRITE(io_base, SPCR1, w | 1); + OMAP_MCBSP_WRITE(io_base, SPCR1, w | (rx & 1)); udelay(100); - /* Start frame sync */ - w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7)); + if (idle) { + /* 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) +void omap_mcbsp_stop(unsigned int id, int tx, int rx) { struct omap_mcbsp *mcbsp; void __iomem *io_base; + int idle; u16 w; if (!omap_mcbsp_check_valid_id(id)) { @@ -386,15 +395,20 @@ void omap_mcbsp_stop(unsigned int id) /* Reset transmitter */ w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1)); + OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(tx & 1)); /* Reset receiver */ w = OMAP_MCBSP_READ(io_base, SPCR1); - OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~(1)); + OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~(rx & 1)); - /* Reset the sample rate generator */ - w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6)); + idle = !((OMAP_MCBSP_READ(io_base, SPCR2) | + OMAP_MCBSP_READ(io_base, SPCR1)) & 1); + + if (idle) { + /* 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-dapm.h b/trunk/include/sound/soc-dapm.h index 35814ced2d22..ec8a45f9a069 100644 --- a/trunk/include/sound/soc-dapm.h +++ b/trunk/include/sound/soc-dapm.h @@ -279,7 +279,6 @@ int snd_soc_dapm_add_routes(struct snd_soc_codec *codec, /* dapm events */ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, char *stream, int event); -void snd_soc_dapm_shutdown(struct snd_soc_device *socdev); /* dapm sys fs - used by the core */ int snd_soc_dapm_sys_add(struct device *dev); diff --git a/trunk/include/sound/soc.h b/trunk/include/sound/soc.h index 55b330937260..cf6111d72b17 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, \ @@ -213,12 +191,6 @@ int snd_soc_register_platform(struct snd_soc_platform *platform); 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); - -#ifdef CONFIG_PM -int snd_soc_suspend_device(struct device *dev); -int snd_soc_resume_device(struct device *dev); -#endif /* pcm <-> DAI connect */ void snd_soc_free_pcms(struct snd_soc_device *socdev); @@ -244,9 +216,9 @@ void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, /* codec register bit access */ int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg, - unsigned int mask, unsigned int value); + unsigned short mask, unsigned short value); int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg, - unsigned int mask, unsigned int value); + unsigned short mask, unsigned short value); int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, struct snd_ac97_bus_ops *ops, int num); @@ -384,8 +356,6 @@ struct snd_soc_codec { int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); 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; @@ -399,6 +369,8 @@ struct snd_soc_codec { enum snd_soc_bias_level bias_level; enum snd_soc_bias_level suspend_bias_level; struct delayed_work delayed_work; + struct list_head up_list; + struct list_head down_list; /* codec DAI's */ struct snd_soc_dai *dai; diff --git a/trunk/include/sound/uda1380.h b/trunk/include/sound/uda1380.h deleted file mode 100644 index 381319c7000c..000000000000 --- a/trunk/include/sound/uda1380.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * UDA1380 ALSA SoC Codec driver - * - * Copyright 2009 Philipp Zabel - * - * 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 __UDA1380_H -#define __UDA1380_H - -struct uda1380_platform_data { - int gpio_power; - int gpio_reset; - int dac_clk; -#define UDA1380_DAC_CLK_SYSCLK 0 -#define UDA1380_DAC_CLK_WSPLL 1 -}; - -#endif /* __UDA1380_H */ 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/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-ad73311.c b/trunk/sound/soc/blackfin/bf5xx-ad73311.c index 9825b71d0e28..edfbdc024e66 100644 --- a/trunk/sound/soc/blackfin/bf5xx-ad73311.c +++ b/trunk/sound/soc/blackfin/bf5xx-ad73311.c @@ -203,23 +203,23 @@ static struct snd_soc_device bf5xx_ad73311_snd_devdata = { .codec_dev = &soc_codec_dev_ad73311, }; -static struct platform_device *bf5xx_ad73311_snd_device; +static struct platform_device *bf52x_ad73311_snd_device; static int __init bf5xx_ad73311_init(void) { int ret; pr_debug("%s enter\n", __func__); - bf5xx_ad73311_snd_device = platform_device_alloc("soc-audio", -1); - if (!bf5xx_ad73311_snd_device) + bf52x_ad73311_snd_device = platform_device_alloc("soc-audio", -1); + if (!bf52x_ad73311_snd_device) return -ENOMEM; - platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311_snd_devdata); - bf5xx_ad73311_snd_devdata.dev = &bf5xx_ad73311_snd_device->dev; - ret = platform_device_add(bf5xx_ad73311_snd_device); + platform_set_drvdata(bf52x_ad73311_snd_device, &bf5xx_ad73311_snd_devdata); + bf5xx_ad73311_snd_devdata.dev = &bf52x_ad73311_snd_device->dev; + ret = platform_device_add(bf52x_ad73311_snd_device); if (ret) - platform_device_put(bf5xx_ad73311_snd_device); + platform_device_put(bf52x_ad73311_snd_device); return ret; } @@ -227,7 +227,7 @@ static int __init bf5xx_ad73311_init(void) static void __exit bf5xx_ad73311_exit(void) { pr_debug("%s enter\n", __func__); - platform_device_unregister(bf5xx_ad73311_snd_device); + platform_device_unregister(bf52x_ad73311_snd_device); } module_init(bf5xx_ad73311_init); 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-ssm2602.c b/trunk/sound/soc/blackfin/bf5xx-ssm2602.c index 3a00fa4dbe6d..bc0cdded7116 100644 --- a/trunk/sound/soc/blackfin/bf5xx-ssm2602.c +++ b/trunk/sound/soc/blackfin/bf5xx-ssm2602.c @@ -148,24 +148,24 @@ static struct snd_soc_device bf5xx_ssm2602_snd_devdata = { .codec_data = &bf5xx_ssm2602_setup, }; -static struct platform_device *bf5xx_ssm2602_snd_device; +static struct platform_device *bf52x_ssm2602_snd_device; static int __init bf5xx_ssm2602_init(void) { int ret; pr_debug("%s enter\n", __func__); - bf5xx_ssm2602_snd_device = platform_device_alloc("soc-audio", -1); - if (!bf5xx_ssm2602_snd_device) + bf52x_ssm2602_snd_device = platform_device_alloc("soc-audio", -1); + if (!bf52x_ssm2602_snd_device) return -ENOMEM; - platform_set_drvdata(bf5xx_ssm2602_snd_device, + platform_set_drvdata(bf52x_ssm2602_snd_device, &bf5xx_ssm2602_snd_devdata); - bf5xx_ssm2602_snd_devdata.dev = &bf5xx_ssm2602_snd_device->dev; - ret = platform_device_add(bf5xx_ssm2602_snd_device); + bf5xx_ssm2602_snd_devdata.dev = &bf52x_ssm2602_snd_device->dev; + ret = platform_device_add(bf52x_ssm2602_snd_device); if (ret) - platform_device_put(bf5xx_ssm2602_snd_device); + platform_device_put(bf52x_ssm2602_snd_device); return ret; } @@ -173,7 +173,7 @@ static int __init bf5xx_ssm2602_init(void) static void __exit bf5xx_ssm2602_exit(void) { pr_debug("%s enter\n", __func__); - platform_device_unregister(bf5xx_ssm2602_snd_device); + platform_device_unregister(bf52x_ssm2602_snd_device); } module_init(bf5xx_ssm2602_init); 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..bbc97fd76648 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 @@ -32,22 +30,18 @@ config SND_SOC_ALL_CODECS select SND_SOC_WM8350 if MFD_WM8350 select SND_SOC_WM8400 if MFD_WM8400 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8523 if I2C select SND_SOC_WM8580 if I2C select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI 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 select SND_SOC_WM8960 if I2C - select SND_SOC_WM8961 if I2C 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 +62,6 @@ config SND_SOC_AC97_CODEC tristate select SND_AC97_CODEC -config SND_SOC_AD1938 - tristate - config SND_SOC_AD1980 tristate @@ -95,9 +86,6 @@ config SND_SOC_CS4270_VD33_ERRATA bool depends on SND_SOC_CS4270 -config SND_SOC_CX20442 - tristate - config SND_SOC_L3 tristate @@ -141,9 +129,6 @@ config SND_SOC_WM8400 config SND_SOC_WM8510 tristate -config SND_SOC_WM8523 - tristate - config SND_SOC_WM8580 tristate @@ -159,9 +144,6 @@ config SND_SOC_WM8750 config SND_SOC_WM8753 tristate -config SND_SOC_WM8776 - tristate - config SND_SOC_WM8900 tristate @@ -174,9 +156,6 @@ config SND_SOC_WM8940 config SND_SOC_WM8960 tristate -config SND_SOC_WM8961 - tristate - config SND_SOC_WM8971 tristate @@ -186,9 +165,6 @@ config SND_SOC_WM8988 config SND_SOC_WM8990 tristate -config SND_SOC_WM8993 - tristate - config SND_SOC_WM9081 tristate @@ -200,7 +176,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..8b7530546f4d 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 @@ -20,38 +18,29 @@ snd-soc-uda1380-objs := uda1380.o snd-soc-wm8350-objs := wm8350.o snd-soc-wm8400-objs := wm8400.o snd-soc-wm8510-objs := wm8510.o -snd-soc-wm8523-objs := wm8523.o snd-soc-wm8580-objs := wm8580.o 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 snd-soc-wm8960-objs := wm8960.o -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 @@ -66,26 +55,19 @@ obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o -obj-$(CONFIG_SND_SOC_WM8523) += snd-soc-wm8523.o obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o 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 obj-$(CONFIG_SND_SOC_WM8940) += snd-soc-wm8940.o 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/twl4030.c b/trunk/sound/soc/codecs/twl4030.c index 818fb37bd7f7..4dbb853eef5a 100644 --- a/trunk/sound/soc/codecs/twl4030.c +++ b/trunk/sound/soc/codecs/twl4030.c @@ -620,9 +620,6 @@ static int handsfreerpga_event(struct snd_soc_dapm_widget *w, static void headset_ramp(struct snd_soc_codec *codec, int ramp) { - struct snd_soc_device *socdev = codec->socdev; - struct twl4030_setup_data *setup = socdev->codec_data; - unsigned char hs_gain, hs_pop; struct twl4030_priv *twl4030 = codec->private_data; /* Base values for ramp delay calculation: 2^19 - 2^26 */ @@ -632,17 +629,6 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET); hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); - /* Enable external mute control, this dramatically reduces - * the pop-noise */ - if (setup && setup->hs_extmute) { - if (setup->set_hs_extmute) { - setup->set_hs_extmute(1); - } else { - hs_pop |= TWL4030_EXTMUTE; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); - } - } - if (ramp) { /* Headset ramp-up according to the TRM */ hs_pop |= TWL4030_VMID_EN; @@ -650,9 +636,6 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) twl4030_write(codec, TWL4030_REG_HS_GAIN_SET, hs_gain); hs_pop |= TWL4030_RAMP_EN; twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); - /* Wait ramp delay time + 1, so the VMID can settle */ - mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] / - twl4030->sysclk) + 1); } else { /* Headset ramp-down _not_ according to * the TRM, but in a way that it is working */ @@ -669,16 +652,6 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) hs_pop &= ~TWL4030_VMID_EN; twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); } - - /* Disable external mute */ - if (setup && setup->hs_extmute) { - if (setup->set_hs_extmute) { - setup->set_hs_extmute(0); - } else { - hs_pop &= ~TWL4030_EXTMUTE; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); - } - } } static int headsetlpga_event(struct snd_soc_dapm_widget *w, @@ -739,19 +712,7 @@ static int bypass_event(struct snd_soc_dapm_widget *w, reg = twl4030_read_reg_cache(w->codec, m->reg); - /* - * bypass_state[0:3] - analog HiFi bypass - * bypass_state[4] - analog voice bypass - * bypass_state[5] - digital voice bypass - * bypass_state[6:7] - digital HiFi bypass - */ - if (m->reg == TWL4030_REG_VSTPGA) { - /* Voice digital bypass */ - if (reg) - twl4030->bypass_state |= (1 << 5); - else - twl4030->bypass_state &= ~(1 << 5); - } else if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) { + if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) { /* Analog bypass */ if (reg & (1 << m->shift)) twl4030->bypass_state |= @@ -765,6 +726,12 @@ static int bypass_event(struct snd_soc_dapm_widget *w, twl4030->bypass_state |= (1 << 4); else twl4030->bypass_state &= ~(1 << 4); + } else if (m->reg == TWL4030_REG_VSTPGA) { + /* Voice digital bypass */ + if (reg) + twl4030->bypass_state |= (1 << 5); + else + twl4030->bypass_state &= ~(1 << 5); } else { /* Digital bypass */ if (reg & (0x7 << m->shift)) @@ -957,7 +924,7 @@ static const struct soc_enum twl4030_op_modes_enum = ARRAY_SIZE(twl4030_op_modes_texts), twl4030_op_modes_texts); -static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, +int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); @@ -1038,16 +1005,6 @@ static DECLARE_TLV_DB_SCALE(digital_capture_tlv, 0, 100, 0); */ static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0); -/* AVADC clock priority */ -static const char *twl4030_avadc_clk_priority_texts[] = { - "Voice high priority", "HiFi high priority" -}; - -static const struct soc_enum twl4030_avadc_clk_priority_enum = - SOC_ENUM_SINGLE(TWL4030_REG_AVADC_CTL, 2, - ARRAY_SIZE(twl4030_avadc_clk_priority_texts), - twl4030_avadc_clk_priority_texts); - static const char *twl4030_rampdelay_texts[] = { "27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms", "437/323/218 ms", "874/645/437 ms", "1748/1291/874 ms", @@ -1149,8 +1106,6 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = { SOC_DOUBLE_TLV("Analog Capture Volume", TWL4030_REG_ANAMIC_GAIN, 0, 3, 5, 0, input_gain_tlv), - SOC_ENUM("AVADC Clock Priority", twl4030_avadc_clk_priority_enum), - SOC_ENUM("HS ramp delay", twl4030_rampdelay_enum), SOC_ENUM("Vibra H-bridge mode", twl4030_vibradirmode_enum), @@ -1285,14 +1240,14 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { /* HandsfreeL/R */ SND_SOC_DAPM_MUX("HandsfreeL Mux", SND_SOC_NOPM, 0, 0, &twl4030_dapm_handsfreel_control), - SND_SOC_DAPM_SWITCH("HandsfreeL", SND_SOC_NOPM, 0, 0, + SND_SOC_DAPM_SWITCH("HandsfreeL Switch", SND_SOC_NOPM, 0, 0, &twl4030_dapm_handsfreelmute_control), SND_SOC_DAPM_PGA_E("HandsfreeL PGA", SND_SOC_NOPM, 0, 0, NULL, 0, handsfreelpga_event, SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MUX("HandsfreeR Mux", SND_SOC_NOPM, 5, 0, &twl4030_dapm_handsfreer_control), - SND_SOC_DAPM_SWITCH("HandsfreeR", SND_SOC_NOPM, 0, 0, + SND_SOC_DAPM_SWITCH("HandsfreeR Switch", SND_SOC_NOPM, 0, 0, &twl4030_dapm_handsfreermute_control), SND_SOC_DAPM_PGA_E("HandsfreeR PGA", SND_SOC_NOPM, 0, 0, NULL, 0, handsfreerpga_event, @@ -1404,15 +1359,15 @@ static const struct snd_soc_dapm_route intercon[] = { {"HandsfreeL Mux", "AudioL1", "Analog L1 Playback Mixer"}, {"HandsfreeL Mux", "AudioL2", "Analog L2 Playback Mixer"}, {"HandsfreeL Mux", "AudioR2", "Analog R2 Playback Mixer"}, - {"HandsfreeL", "Switch", "HandsfreeL Mux"}, - {"HandsfreeL PGA", NULL, "HandsfreeL"}, + {"HandsfreeL Switch", "Switch", "HandsfreeL Mux"}, + {"HandsfreeL PGA", NULL, "HandsfreeL Switch"}, /* HandsfreeR */ {"HandsfreeR Mux", "Voice", "Analog Voice Playback Mixer"}, {"HandsfreeR Mux", "AudioR1", "Analog R1 Playback Mixer"}, {"HandsfreeR Mux", "AudioR2", "Analog R2 Playback Mixer"}, {"HandsfreeR Mux", "AudioL2", "Analog L2 Playback Mixer"}, - {"HandsfreeR", "Switch", "HandsfreeR Mux"}, - {"HandsfreeR PGA", NULL, "HandsfreeR"}, + {"HandsfreeR Switch", "Switch", "HandsfreeR Mux"}, + {"HandsfreeR PGA", NULL, "HandsfreeR Switch"}, /* Vibra */ {"Vibra Mux", "AudioL1", "DAC Left1"}, {"Vibra Mux", "AudioR1", "DAC Right1"}, @@ -1654,6 +1609,8 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, /* If the substream has 4 channel, do the necessary setup */ if (params_channels(params) == 4) { + u8 format, mode; + format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF); mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE); @@ -1849,19 +1806,6 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int twl4030_set_tristate(struct snd_soc_dai *dai, int tristate) -{ - struct snd_soc_codec *codec = dai->codec; - u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF); - - if (tristate) - reg |= TWL4030_AIF_TRI_EN; - else - reg &= ~TWL4030_AIF_TRI_EN; - - return twl4030_write(codec, TWL4030_REG_AUDIO_IF, reg); -} - /* In case of voice mode, the RX1 L(VRX) for downlink and the TX2 L/R * (VTXL, VTXR) for uplink has to be enabled/disabled. */ static void twl4030_voice_enable(struct snd_soc_codec *codec, int direction, @@ -2004,7 +1948,7 @@ static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai, /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBS_CFM: format &= ~(TWL4030_VIF_SLAVE_EN); break; case SND_SOC_DAIFMT_CBS_CFS: @@ -2036,19 +1980,6 @@ static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate) -{ - struct snd_soc_codec *codec = dai->codec; - u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_VOICE_IF); - - if (tristate) - reg |= TWL4030_VIF_TRI_EN; - else - reg &= ~TWL4030_VIF_TRI_EN; - - return twl4030_write(codec, TWL4030_REG_VOICE_IF, reg); -} - #define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) #define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) @@ -2058,7 +1989,6 @@ static struct snd_soc_dai_ops twl4030_dai_ops = { .hw_params = twl4030_hw_params, .set_sysclk = twl4030_set_dai_sysclk, .set_fmt = twl4030_set_dai_fmt, - .set_tristate = twl4030_set_tristate, }; static struct snd_soc_dai_ops twl4030_dai_voice_ops = { @@ -2067,7 +1997,6 @@ static struct snd_soc_dai_ops twl4030_dai_voice_ops = { .hw_params = twl4030_voice_hw_params, .set_sysclk = twl4030_voice_set_dai_sysclk, .set_fmt = twl4030_voice_set_dai_fmt, - .set_tristate = twl4030_voice_set_tristate, }; struct snd_soc_dai twl4030_dai[] = { diff --git a/trunk/sound/soc/codecs/twl4030.h b/trunk/sound/soc/codecs/twl4030.h index 2b4bfa23f985..fe5f395d9e4f 100644 --- a/trunk/sound/soc/codecs/twl4030.h +++ b/trunk/sound/soc/codecs/twl4030.h @@ -274,8 +274,6 @@ extern struct snd_soc_codec_device soc_codec_dev_twl4030; struct twl4030_setup_data { unsigned int ramp_delay_value; unsigned int sysclk; - unsigned int hs_extmute:1; - void (*set_hs_extmute)(int mute); }; #endif /* End of __TWL4030_AUDIO_H__ */ diff --git a/trunk/sound/soc/codecs/uda1380.c b/trunk/sound/soc/codecs/uda1380.c index 92ec03442154..5b21594e0e58 100644 --- a/trunk/sound/soc/codecs/uda1380.c +++ b/trunk/sound/soc/codecs/uda1380.c @@ -5,7 +5,9 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * Copyright (c) 2007-2009 Philipp Zabel + * Copyright (c) 2007 Philipp Zabel + * Improved support for DAPM and audio routing/mixing capabilities, + * added TLV support. * * Modified by Richard Purdie to fit into SoC * codec model. @@ -17,32 +19,26 @@ #include #include #include +#include #include #include -#include +#include #include #include #include #include #include #include +#include #include #include #include -#include #include "uda1380.h" +static struct work_struct uda1380_work; static struct snd_soc_codec *uda1380_codec; -/* codec private data */ -struct uda1380_priv { - struct snd_soc_codec codec; - u16 reg_cache[UDA1380_CACHEREGNUM]; - unsigned int dac_clk; - struct work_struct work; -}; - /* * uda1380 register cache */ @@ -477,7 +473,6 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; - struct uda1380_priv *uda1380 = codec->private_data; int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); switch (cmd) { @@ -485,13 +480,13 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: uda1380_write_reg_cache(codec, UDA1380_MIXER, mixer & ~R14_SILENCE); - schedule_work(&uda1380->work); + schedule_work(&uda1380_work); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: uda1380_write_reg_cache(codec, UDA1380_MIXER, mixer | R14_SILENCE); - schedule_work(&uda1380->work); + schedule_work(&uda1380_work); break; } return 0; @@ -675,33 +670,44 @@ static int uda1380_resume(struct platform_device *pdev) return 0; } -static int uda1380_probe(struct platform_device *pdev) +/* + * initialise the UDA1380 driver + * register mixer and dsp interfaces with the kernel + */ +static int uda1380_init(struct snd_soc_device *socdev, int dac_clk) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - struct uda1380_platform_data *pdata; + struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; - if (uda1380_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } + codec->name = "UDA1380"; + codec->owner = THIS_MODULE; + codec->read = uda1380_read_reg_cache; + codec->write = uda1380_write; + codec->set_bias_level = uda1380_set_bias_level; + codec->dai = uda1380_dai; + codec->num_dai = ARRAY_SIZE(uda1380_dai); + codec->reg_cache = kmemdup(uda1380_reg, sizeof(uda1380_reg), + GFP_KERNEL); + if (codec->reg_cache == NULL) + return -ENOMEM; + codec->reg_cache_size = ARRAY_SIZE(uda1380_reg); + codec->reg_cache_step = 1; + uda1380_reset(codec); - socdev->card->codec = uda1380_codec; - codec = uda1380_codec; - pdata = codec->dev->platform_data; + uda1380_codec = codec; + INIT_WORK(&uda1380_work, uda1380_flush_work); /* 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); + pr_err("uda1380: failed to create pcms\n"); goto pcm_err; } /* power on device */ uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* set clock input */ - switch (pdata->dac_clk) { + switch (dac_clk) { case UDA1380_DAC_CLK_SYSCLK: uda1380_write(codec, UDA1380_CLK, 0); break; @@ -710,12 +716,13 @@ static int uda1380_probe(struct platform_device *pdev) break; } + /* uda1380 init */ snd_soc_add_controls(codec, uda1380_snd_controls, ARRAY_SIZE(uda1380_snd_controls)); uda1380_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { - dev_err(codec->dev, "failed to register card: %d\n", ret); + pr_err("uda1380: failed to register card\n"); goto card_err; } @@ -725,201 +732,165 @@ static int uda1380_probe(struct platform_device *pdev) snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); pcm_err: + kfree(codec->reg_cache); return ret; } -/* power down chip */ -static int uda1380_remove(struct platform_device *pdev) +static struct snd_soc_device *uda1380_socdev; + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + +static int uda1380_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_device *socdev = uda1380_socdev; + struct uda1380_setup_data *setup = socdev->codec_data; struct snd_soc_codec *codec = socdev->card->codec; + int ret; - if (codec->control_data) - uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); + i2c_set_clientdata(i2c, codec); + codec->control_data = i2c; - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); + ret = uda1380_init(socdev, setup->dac_clk); + if (ret < 0) + pr_err("uda1380: failed to initialise UDA1380\n"); - return 0; + return ret; } -struct snd_soc_codec_device soc_codec_dev_uda1380 = { - .probe = uda1380_probe, - .remove = uda1380_remove, - .suspend = uda1380_suspend, - .resume = uda1380_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380); - -static int uda1380_register(struct uda1380_priv *uda1380) +static int uda1380_i2c_remove(struct i2c_client *client) { - int ret, i; - struct snd_soc_codec *codec = &uda1380->codec; - struct uda1380_platform_data *pdata = codec->dev->platform_data; - - if (uda1380_codec) { - dev_err(codec->dev, "Another UDA1380 is registered\n"); - return -EINVAL; - } - - if (!pdata || !pdata->gpio_power || !pdata->gpio_reset) - return -EINVAL; - - ret = gpio_request(pdata->gpio_power, "uda1380 power"); - if (ret) - goto err_out; - ret = gpio_request(pdata->gpio_reset, "uda1380 reset"); - if (ret) - goto err_gpio; - - gpio_direction_output(pdata->gpio_power, 1); - - /* we may need to have the clock running here - pH5 */ - gpio_direction_output(pdata->gpio_reset, 1); - udelay(5); - gpio_set_value(pdata->gpio_reset, 0); + struct snd_soc_codec *codec = i2c_get_clientdata(client); + kfree(codec->reg_cache); + return 0; +} - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); +static const struct i2c_device_id uda1380_i2c_id[] = { + { "uda1380", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id); - codec->private_data = uda1380; - codec->name = "UDA1380"; - codec->owner = THIS_MODULE; - codec->read = uda1380_read_reg_cache; - codec->write = uda1380_write; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = uda1380_set_bias_level; - codec->dai = uda1380_dai; - codec->num_dai = ARRAY_SIZE(uda1380_dai); - codec->reg_cache_size = ARRAY_SIZE(uda1380_reg); - codec->reg_cache = &uda1380->reg_cache; - codec->reg_cache_step = 1; +static struct i2c_driver uda1380_i2c_driver = { + .driver = { + .name = "UDA1380 I2C Codec", + .owner = THIS_MODULE, + }, + .probe = uda1380_i2c_probe, + .remove = uda1380_i2c_remove, + .id_table = uda1380_i2c_id, +}; - memcpy(codec->reg_cache, uda1380_reg, sizeof(uda1380_reg)); +static int uda1380_add_i2c_device(struct platform_device *pdev, + const struct uda1380_setup_data *setup) +{ + struct i2c_board_info info; + struct i2c_adapter *adapter; + struct i2c_client *client; + int ret; - ret = uda1380_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - goto err_reset; + ret = i2c_add_driver(&uda1380_i2c_driver); + if (ret != 0) { + dev_err(&pdev->dev, "can't add i2c driver\n"); + return ret; } - INIT_WORK(&uda1380->work, uda1380_flush_work); - - for (i = 0; i < ARRAY_SIZE(uda1380_dai); i++) - uda1380_dai[i].dev = codec->dev; + memset(&info, 0, sizeof(struct i2c_board_info)); + info.addr = setup->i2c_address; + strlcpy(info.type, "uda1380", I2C_NAME_SIZE); - uda1380_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err_reset; + adapter = i2c_get_adapter(setup->i2c_bus); + if (!adapter) { + dev_err(&pdev->dev, "can't get i2c adapter %d\n", + setup->i2c_bus); + goto err_driver; } - ret = snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); - goto err_dai; + client = i2c_new_device(adapter, &info); + i2c_put_adapter(adapter); + if (!client) { + dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", + (unsigned int)info.addr); + goto err_driver; } return 0; -err_dai: - snd_soc_unregister_codec(codec); -err_reset: - gpio_set_value(pdata->gpio_power, 0); - gpio_free(pdata->gpio_reset); -err_gpio: - gpio_free(pdata->gpio_power); -err_out: - return ret; -} - -static void uda1380_unregister(struct uda1380_priv *uda1380) -{ - struct snd_soc_codec *codec = &uda1380->codec; - struct uda1380_platform_data *pdata = codec->dev->platform_data; - - snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); - snd_soc_unregister_codec(&uda1380->codec); - - gpio_set_value(pdata->gpio_power, 0); - gpio_free(pdata->gpio_reset); - gpio_free(pdata->gpio_power); - - kfree(uda1380); - uda1380_codec = NULL; +err_driver: + i2c_del_driver(&uda1380_i2c_driver); + return -ENODEV; } +#endif -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int uda1380_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int uda1380_probe(struct platform_device *pdev) { - struct uda1380_priv *uda1380; + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct uda1380_setup_data *setup; struct snd_soc_codec *codec; int ret; - uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL); - if (uda1380 == NULL) + setup = socdev->codec_data; + codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (codec == NULL) return -ENOMEM; - codec = &uda1380->codec; - codec->hw_write = (hw_write_t)i2c_master_send; + socdev->card->codec = codec; + mutex_init(&codec->mutex); + INIT_LIST_HEAD(&codec->dapm_widgets); + INIT_LIST_HEAD(&codec->dapm_paths); - i2c_set_clientdata(i2c, uda1380); - codec->control_data = i2c; + uda1380_socdev = socdev; + ret = -ENODEV; - codec->dev = &i2c->dev; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + if (setup->i2c_address) { + codec->hw_write = (hw_write_t)i2c_master_send; + ret = uda1380_add_i2c_device(pdev, setup); + } +#endif - ret = uda1380_register(uda1380); if (ret != 0) - kfree(uda1380); - + kfree(codec); return ret; } -static int __devexit uda1380_i2c_remove(struct i2c_client *i2c) +/* power down chip */ +static int uda1380_remove(struct platform_device *pdev) { - struct uda1380_priv *uda1380 = i2c_get_clientdata(i2c); - uda1380_unregister(uda1380); + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->card->codec; + + if (codec->control_data) + uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); + + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + i2c_unregister_device(codec->control_data); + i2c_del_driver(&uda1380_i2c_driver); +#endif + kfree(codec); + return 0; } -static const struct i2c_device_id uda1380_i2c_id[] = { - { "uda1380", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id); - -static struct i2c_driver uda1380_i2c_driver = { - .driver = { - .name = "UDA1380 I2C Codec", - .owner = THIS_MODULE, - }, - .probe = uda1380_i2c_probe, - .remove = __devexit_p(uda1380_i2c_remove), - .id_table = uda1380_i2c_id, +struct snd_soc_codec_device soc_codec_dev_uda1380 = { + .probe = uda1380_probe, + .remove = uda1380_remove, + .suspend = uda1380_suspend, + .resume = uda1380_resume, }; -#endif +EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380); static int __init uda1380_modinit(void) { - int ret; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&uda1380_i2c_driver); - if (ret != 0) - pr_err("Failed to register UDA1380 I2C driver: %d\n", ret); -#endif - return 0; + return snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); } module_init(uda1380_modinit); static void __exit uda1380_exit(void) { -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&uda1380_i2c_driver); -#endif + snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); } module_exit(uda1380_exit); diff --git a/trunk/sound/soc/codecs/uda1380.h b/trunk/sound/soc/codecs/uda1380.h index 9cefa8a54770..c55c17a52a12 100644 --- a/trunk/sound/soc/codecs/uda1380.h +++ b/trunk/sound/soc/codecs/uda1380.h @@ -72,6 +72,14 @@ #define R22_SKIP_DCFIL 0x0002 #define R23_AGC_EN 0x0001 +struct uda1380_setup_data { + int i2c_bus; + unsigned short i2c_address; + int dac_clk; +#define UDA1380_DAC_CLK_SYSCLK 0 +#define UDA1380_DAC_CLK_WSPLL 1 +}; + #define UDA1380_DAI_DUPLEX 0 /* playback and capture on single DAI */ #define UDA1380_DAI_PLAYBACK 1 /* playback DAI */ #define UDA1380_DAI_CAPTURE 2 /* capture DAI */ diff --git a/trunk/sound/soc/codecs/wm8350.c b/trunk/sound/soc/codecs/wm8350.c index 4ded0e3a35e0..e7348d341b76 100644 --- a/trunk/sound/soc/codecs/wm8350.c +++ b/trunk/sound/soc/codecs/wm8350.c @@ -406,6 +406,7 @@ static const char *wm8350_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" }; static const char *wm8350_dacmutem[] = { "Normal", "Soft" }; static const char *wm8350_dacmutes[] = { "Fast", "Slow" }; +static const char *wm8350_dacfilter[] = { "Normal", "Sloping" }; static const char *wm8350_adcfilter[] = { "None", "High Pass" }; static const char *wm8350_adchp[] = { "44.1kHz", "8kHz", "16kHz", "32kHz" }; static const char *wm8350_lr[] = { "Left", "Right" }; @@ -415,6 +416,7 @@ static const struct soc_enum wm8350_enum[] = { SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 0, 4, wm8350_pol), SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 14, 2, wm8350_dacmutem), SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 13, 2, wm8350_dacmutes), + SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 12, 2, wm8350_dacfilter), SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 15, 2, wm8350_adcfilter), SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 8, 4, wm8350_adchp), SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 0, 4, wm8350_pol), @@ -442,9 +444,10 @@ static const struct snd_kcontrol_new wm8350_snd_controls[] = { 0, 255, 0, dac_pcm_tlv), SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]), SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]), - SOC_ENUM("Capture PCM Filter", wm8350_enum[4]), - SOC_ENUM("Capture PCM HP Filter", wm8350_enum[5]), - SOC_ENUM("Capture ADC Inversion", wm8350_enum[6]), + SOC_ENUM("Playback PCM Filter", wm8350_enum[4]), + SOC_ENUM("Capture PCM Filter", wm8350_enum[5]), + SOC_ENUM("Capture PCM HP Filter", wm8350_enum[6]), + SOC_ENUM("Capture ADC Inversion", wm8350_enum[7]), SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume", WM8350_ADC_DIGITAL_VOLUME_L, WM8350_ADC_DIGITAL_VOLUME_R, @@ -990,7 +993,6 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai) { struct snd_soc_codec *codec = codec_dai->codec; - struct wm8350 *wm8350 = codec->control_data; u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) & ~WM8350_AIF_WL_MASK; @@ -1010,19 +1012,6 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream, } wm8350_codec_write(codec, WM8350_AI_FORMATING, iface); - - /* The sloping stopband filter is recommended for use with - * lower sample rates to improve performance. - */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (params_rate(params) < 24000) - wm8350_set_bits(wm8350, WM8350_DAC_MUTE_VOLUME, - WM8350_DAC_SB_FILT); - else - wm8350_clear_bits(wm8350, WM8350_DAC_MUTE_VOLUME, - WM8350_DAC_SB_FILT); - } - return 0; } @@ -1671,21 +1660,6 @@ static int __devexit wm8350_codec_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int wm8350_codec_suspend(struct platform_device *pdev, pm_message_t m) -{ - return snd_soc_suspend_device(&pdev->dev); -} - -static int wm8350_codec_resume(struct platform_device *pdev) -{ - return snd_soc_resume_device(&pdev->dev); -} -#else -#define wm8350_codec_suspend NULL -#define wm8350_codec_resume NULL -#endif - static struct platform_driver wm8350_codec_driver = { .driver = { .name = "wm8350-codec", @@ -1693,8 +1667,6 @@ static struct platform_driver wm8350_codec_driver = { }, .probe = wm8350_codec_probe, .remove = __devexit_p(wm8350_codec_remove), - .suspend = wm8350_codec_suspend, - .resume = wm8350_codec_resume, }; static __init int wm8350_init(void) diff --git a/trunk/sound/soc/codecs/wm8400.c b/trunk/sound/soc/codecs/wm8400.c index b9ef4d915221..502eefac1ecd 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); @@ -1558,21 +1553,6 @@ static int __exit wm8400_codec_remove(struct platform_device *dev) return 0; } -#ifdef CONFIG_PM -static int wm8400_pdev_suspend(struct platform_device *pdev, pm_message_t msg) -{ - return snd_soc_suspend_device(&pdev->dev); -} - -static int wm8400_pdev_resume(struct platform_device *pdev) -{ - return snd_soc_resume_device(&pdev->dev); -} -#else -#define wm8400_pdev_suspend NULL -#define wm8400_pdev_resume NULL -#endif - static struct platform_driver wm8400_codec_driver = { .driver = { .name = "wm8400-codec", @@ -1580,8 +1560,6 @@ static struct platform_driver wm8400_codec_driver = { }, .probe = wm8400_codec_probe, .remove = __exit_p(wm8400_codec_remove), - .suspend = wm8400_pdev_suspend, - .resume = wm8400_pdev_resume, }; static int __init wm8400_codec_init(void) diff --git a/trunk/sound/soc/codecs/wm8510.c b/trunk/sound/soc/codecs/wm8510.c index 261d4cb75964..c8b8dba85890 100644 --- a/trunk/sound/soc/codecs/wm8510.c +++ b/trunk/sound/soc/codecs/wm8510.c @@ -577,7 +577,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); diff --git a/trunk/sound/soc/codecs/wm8523.c b/trunk/sound/soc/codecs/wm8523.c deleted file mode 100644 index 3b499ae7ce6c..000000000000 --- a/trunk/sound/soc/codecs/wm8523.c +++ /dev/null @@ -1,755 +0,0 @@ -/* - * wm8523.c -- WM8523 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 "wm8523.h" - -static struct snd_soc_codec *wm8523_codec; -struct snd_soc_codec_device soc_codec_dev_wm8523; - -#define WM8523_NUM_SUPPLIES 2 -static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { - "AVDD", - "LINEVDD", -}; - -#define WM8523_NUM_RATES 7 - -/* codec private data */ -struct wm8523_priv { - struct snd_soc_codec codec; - u16 reg_cache[WM8523_REGISTER_COUNT]; - struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; - unsigned int sysclk; - unsigned int rate_constraint_list[WM8523_NUM_RATES]; - struct snd_pcm_hw_constraint_list rate_constraint; -}; - -static const u16 wm8523_reg[WM8523_REGISTER_COUNT] = { - 0x8523, /* R0 - DEVICE_ID */ - 0x0001, /* R1 - REVISION */ - 0x0000, /* R2 - PSCTRL1 */ - 0x1812, /* R3 - AIF_CTRL1 */ - 0x0000, /* R4 - AIF_CTRL2 */ - 0x0001, /* R5 - DAC_CTRL3 */ - 0x0190, /* R6 - DAC_GAINL */ - 0x0190, /* R7 - DAC_GAINR */ - 0x0000, /* R8 - ZERO_DETECT */ -}; - -static int wm8523_volatile(unsigned int reg) -{ - switch (reg) { - case WM8523_DEVICE_ID: - case WM8523_REVISION: - return 1; - default: - return 0; - } -} - -static int wm8523_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - struct wm8523_priv *wm8523 = codec->private_data; - u8 data[3]; - - BUG_ON(reg > WM8523_MAX_REGISTER); - - data[0] = reg; - data[1] = (value >> 8) & 0x00ff; - data[2] = value & 0x00ff; - - if (!wm8523_volatile(reg)) - wm8523->reg_cache[reg] = value; - if (codec->hw_write(codec->control_data, data, 3) == 3) - return 0; - else - return -EIO; -} - -static int wm8523_reset(struct snd_soc_codec *codec) -{ - return wm8523_write(codec, WM8523_DEVICE_ID, 0); -} - -static unsigned int wm8523_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 unsigned int wm8523_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *reg_cache = codec->reg_cache; - - BUG_ON(reg > WM8523_MAX_REGISTER); - - if (wm8523_volatile(reg)) - return wm8523_read_hw(codec, reg); - else - return reg_cache[reg]; -} - -static const DECLARE_TLV_DB_SCALE(dac_tlv, -10000, 25, 0); - -static const char *wm8523_zd_count_text[] = { - "1024", - "2048", -}; - -static const struct soc_enum wm8523_zc_count = - SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text); - -static const struct snd_kcontrol_new wm8523_snd_controls[] = { -SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR, - 0, 448, 0, dac_tlv), -SOC_SINGLE("ZC Switch", WM8523_DAC_CTRL3, 4, 1, 0), -SOC_SINGLE("Playback Deemphasis Switch", WM8523_AIF_CTRL1, 8, 1, 0), -SOC_DOUBLE("Playback Switch", WM8523_DAC_CTRL3, 2, 3, 1, 1), -SOC_SINGLE("Volume Ramp Up Switch", WM8523_DAC_CTRL3, 1, 1, 0), -SOC_SINGLE("Volume Ramp Down Switch", WM8523_DAC_CTRL3, 0, 1, 0), -SOC_ENUM("Zero Detect Count", wm8523_zc_count), -}; - -static const struct snd_soc_dapm_widget wm8523_dapm_widgets[] = { -SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_OUTPUT("LINEVOUTL"), -SND_SOC_DAPM_OUTPUT("LINEVOUTR"), -}; - -static const struct snd_soc_dapm_route intercon[] = { - { "LINEVOUTL", NULL, "DAC" }, - { "LINEVOUTR", NULL, "DAC" }, -}; - -static int wm8523_add_widgets(struct snd_soc_codec *codec) -{ - snd_soc_dapm_new_controls(codec, wm8523_dapm_widgets, - ARRAY_SIZE(wm8523_dapm_widgets)); - - snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); - - snd_soc_dapm_new_widgets(codec); - return 0; -} - -static struct { - int value; - int ratio; -} lrclk_ratios[WM8523_NUM_RATES] = { - { 1, 128 }, - { 2, 192 }, - { 3, 256 }, - { 4, 384 }, - { 5, 512 }, - { 6, 768 }, - { 7, 1152 }, -}; - -static int wm8523_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8523_priv *wm8523 = codec->private_data; - - /* The set of sample rates that can be supported depends on the - * MCLK supplied to the CODEC - enforce this. - */ - if (!wm8523->sysclk) { - dev_err(codec->dev, - "No MCLK configured, call set_sysclk() on init\n"); - return -EINVAL; - } - - return 0; - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &wm8523->rate_constraint); - - return 0; -} - -static int wm8523_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; - struct wm8523_priv *wm8523 = codec->private_data; - int i; - u16 aifctrl1 = wm8523_read(codec, WM8523_AIF_CTRL1); - u16 aifctrl2 = wm8523_read(codec, WM8523_AIF_CTRL2); - - /* Find a supported LRCLK ratio */ - for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { - if (wm8523->sysclk / params_rate(params) == - lrclk_ratios[i].ratio) - break; - } - - /* Should never happen, should be handled by constraints */ - if (i == ARRAY_SIZE(lrclk_ratios)) { - dev_err(codec->dev, "MCLK/fs ratio %d unsupported\n", - wm8523->sysclk / params_rate(params)); - return -EINVAL; - } - - aifctrl2 &= ~WM8523_SR_MASK; - aifctrl2 |= lrclk_ratios[i].value; - - aifctrl1 &= ~WM8523_WL_MASK; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - aifctrl1 |= 0x8; - break; - case SNDRV_PCM_FORMAT_S24_LE: - aifctrl1 |= 0x10; - break; - case SNDRV_PCM_FORMAT_S32_LE: - aifctrl1 |= 0x18; - break; - } - - wm8523_write(codec, WM8523_AIF_CTRL1, aifctrl1); - wm8523_write(codec, WM8523_AIF_CTRL2, aifctrl2); - - return 0; -} - -static int wm8523_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8523_priv *wm8523 = codec->private_data; - unsigned int val; - int i; - - wm8523->sysclk = freq; - - wm8523->rate_constraint.count = 0; - for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { - val = freq / lrclk_ratios[i].ratio; - /* Check that it's a standard rate since core can't - * cope with others and having the odd rates confuses - * constraint matching. - */ - switch (val) { - case 8000: - case 11025: - case 16000: - case 22050: - case 32000: - case 44100: - case 48000: - case 64000: - case 88200: - case 96000: - case 176400: - case 192000: - dev_dbg(codec->dev, "Supported sample rate: %dHz\n", - val); - wm8523->rate_constraint_list[i] = val; - wm8523->rate_constraint.count++; - break; - default: - dev_dbg(codec->dev, "Skipping sample rate: %dHz\n", - val); - } - } - - /* Need at least one supported rate... */ - if (wm8523->rate_constraint.count == 0) - return -EINVAL; - - return 0; -} - - -static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 aifctrl1 = wm8523_read(codec, WM8523_AIF_CTRL1); - - aifctrl1 &= ~(WM8523_BCLK_INV_MASK | WM8523_LRCLK_INV_MASK | - WM8523_FMT_MASK | WM8523_AIF_MSTR_MASK); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - aifctrl1 |= WM8523_AIF_MSTR; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - aifctrl1 |= 0x0002; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - aifctrl1 |= 0x0001; - break; - case SND_SOC_DAIFMT_DSP_A: - aifctrl1 |= 0x0003; - break; - case SND_SOC_DAIFMT_DSP_B: - aifctrl1 |= 0x0023; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - aifctrl1 |= WM8523_BCLK_INV | WM8523_LRCLK_INV; - break; - case SND_SOC_DAIFMT_IB_NF: - aifctrl1 |= WM8523_BCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: - aifctrl1 |= WM8523_LRCLK_INV; - break; - default: - return -EINVAL; - } - - wm8523_write(codec, WM8523_AIF_CTRL1, aifctrl1); - - return 0; -} - -static int wm8523_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8523_priv *wm8523 = codec->private_data; - int ret, i; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - /* Full power on */ - snd_soc_update_bits(codec, WM8523_PSCTRL1, - WM8523_SYS_ENA_MASK, 3); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->bias_level == SND_SOC_BIAS_OFF) { - ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), - wm8523->supplies); - if (ret != 0) { - dev_err(codec->dev, - "Failed to enable supplies: %d\n", - ret); - return ret; - } - - /* Initial power up */ - snd_soc_update_bits(codec, WM8523_PSCTRL1, - WM8523_SYS_ENA_MASK, 1); - - /* Sync back default/cached values */ - for (i = WM8523_AIF_CTRL1; - i < WM8523_MAX_REGISTER; i++) - wm8523_write(codec, i, wm8523->reg_cache[i]); - - - msleep(100); - } - - /* Power up to mute */ - snd_soc_update_bits(codec, WM8523_PSCTRL1, - WM8523_SYS_ENA_MASK, 2); - - break; - - case SND_SOC_BIAS_OFF: - /* The chip runs through the power down sequence for us. */ - snd_soc_update_bits(codec, WM8523_PSCTRL1, - WM8523_SYS_ENA_MASK, 0); - msleep(100); - - regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), - wm8523->supplies); - break; - } - codec->bias_level = level; - return 0; -} - -#define WM8523_RATES SNDRV_PCM_RATE_8000_192000 - -#define WM8523_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 wm8523_dai_ops = { - .startup = wm8523_startup, - .hw_params = wm8523_hw_params, - .set_sysclk = wm8523_set_dai_sysclk, - .set_fmt = wm8523_set_dai_fmt, -}; - -struct snd_soc_dai wm8523_dai = { - .name = "WM8523", - .playback = { - .stream_name = "Playback", - .channels_min = 2, /* Mono modes not yet supported */ - .channels_max = 2, - .rates = WM8523_RATES, - .formats = WM8523_FORMATS, - }, - .ops = &wm8523_dai_ops, -}; -EXPORT_SYMBOL_GPL(wm8523_dai); - -#ifdef CONFIG_PM -static int wm8523_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; - - wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8523_resume(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} -#else -#define wm8523_suspend NULL -#define wm8523_resume NULL -#endif - -static int wm8523_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (wm8523_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8523_codec; - codec = wm8523_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, wm8523_snd_controls, - ARRAY_SIZE(wm8523_snd_controls)); - wm8523_add_widgets(codec); - 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; -} - -static int wm8523_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_wm8523 = { - .probe = wm8523_probe, - .remove = wm8523_remove, - .suspend = wm8523_suspend, - .resume = wm8523_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8523); - -static int wm8523_register(struct wm8523_priv *wm8523) -{ - int ret; - struct snd_soc_codec *codec = &wm8523->codec; - int i; - - if (wm8523_codec) { - dev_err(codec->dev, "Another WM8523 is registered\n"); - return -EINVAL; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->private_data = wm8523; - codec->name = "WM8523"; - codec->owner = THIS_MODULE; - codec->read = wm8523_read; - codec->write = wm8523_write; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8523_set_bias_level; - codec->dai = &wm8523_dai; - codec->num_dai = 1; - codec->reg_cache_size = WM8523_REGISTER_COUNT; - codec->reg_cache = &wm8523->reg_cache; - - wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; - wm8523->rate_constraint.count = - ARRAY_SIZE(wm8523->rate_constraint_list); - - memcpy(codec->reg_cache, wm8523_reg, sizeof(wm8523_reg)); - - for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) - wm8523->supplies[i].supply = wm8523_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8523->supplies), - wm8523->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), - wm8523->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_get; - } - - ret = wm8523_read(codec, WM8523_DEVICE_ID); - if (ret < 0) { - dev_err(codec->dev, "Failed to read ID register\n"); - goto err_enable; - } - if (ret != wm8523_reg[WM8523_DEVICE_ID]) { - dev_err(codec->dev, "Device is not a WM8523, ID is %x\n", ret); - ret = -EINVAL; - goto err_enable; - } - - ret = wm8523_read(codec, WM8523_REVISION); - if (ret < 0) { - dev_err(codec->dev, "Failed to read revision register\n"); - goto err_enable; - } - dev_info(codec->dev, "revision %c\n", - (ret & WM8523_CHIP_REV_MASK) + 'A'); - - ret = wm8523_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - goto err_enable; - } - - wm8523_dai.dev = codec->dev; - - /* Change some default settings - latch VU and enable ZC */ - wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; - wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; - - wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Bias level configuration will have done an extra enable */ - regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); - - wm8523_codec = 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(&wm8523_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); - return ret; - } - - return 0; - -err_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); -err_get: - regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); -err: - kfree(wm8523); - return ret; -} - -static void wm8523_unregister(struct wm8523_priv *wm8523) -{ - wm8523_set_bias_level(&wm8523->codec, SND_SOC_BIAS_OFF); - regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); - snd_soc_unregister_dai(&wm8523_dai); - snd_soc_unregister_codec(&wm8523->codec); - kfree(wm8523); - wm8523_codec = NULL; -} - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8523_priv *wm8523; - struct snd_soc_codec *codec; - - wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL); - if (wm8523 == NULL) - return -ENOMEM; - - codec = &wm8523->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - - i2c_set_clientdata(i2c, wm8523); - codec->control_data = i2c; - - codec->dev = &i2c->dev; - - return wm8523_register(wm8523); -} - -static __devexit int wm8523_i2c_remove(struct i2c_client *client) -{ - struct wm8523_priv *wm8523 = i2c_get_clientdata(client); - wm8523_unregister(wm8523); - return 0; -} - -#ifdef CONFIG_PM -static int wm8523_i2c_suspend(struct i2c_client *i2c, pm_message_t msg) -{ - return snd_soc_suspend_device(&i2c->dev); -} - -static int wm8523_i2c_resume(struct i2c_client *i2c) -{ - return snd_soc_resume_device(&i2c->dev); -} -#else -#define wm8523_i2c_suspend NULL -#define wm8523_i2c_resume NULL -#endif - -static const struct i2c_device_id wm8523_i2c_id[] = { - { "wm8523", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id); - -static struct i2c_driver wm8523_i2c_driver = { - .driver = { - .name = "WM8523", - .owner = THIS_MODULE, - }, - .probe = wm8523_i2c_probe, - .remove = __devexit_p(wm8523_i2c_remove), - .suspend = wm8523_i2c_suspend, - .resume = wm8523_i2c_resume, - .id_table = wm8523_i2c_id, -}; -#endif - -static int __init wm8523_modinit(void) -{ - int ret; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8523_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8523 I2C driver: %d\n", - ret); - } -#endif - return 0; -} -module_init(wm8523_modinit); - -static void __exit wm8523_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8523_i2c_driver); -#endif -} -module_exit(wm8523_exit); - -MODULE_DESCRIPTION("ASoC WM8523 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/codecs/wm8523.h b/trunk/sound/soc/codecs/wm8523.h deleted file mode 100644 index 1aa9ce3e1357..000000000000 --- a/trunk/sound/soc/codecs/wm8523.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * wm8523.h -- WM8423 ASoC driver - * - * Copyright 2009 Wolfson Microelectronics, plc - * - * Author: Mark Brown - * - * Based on wm8753.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 _WM8523_H -#define _WM8523_H - -/* - * Register values. - */ -#define WM8523_DEVICE_ID 0x00 -#define WM8523_REVISION 0x01 -#define WM8523_PSCTRL1 0x02 -#define WM8523_AIF_CTRL1 0x03 -#define WM8523_AIF_CTRL2 0x04 -#define WM8523_DAC_CTRL3 0x05 -#define WM8523_DAC_GAINL 0x06 -#define WM8523_DAC_GAINR 0x07 -#define WM8523_ZERO_DETECT 0x08 - -#define WM8523_REGISTER_COUNT 9 -#define WM8523_MAX_REGISTER 0x08 - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - DEVICE_ID - */ -#define WM8523_CHIP_ID_MASK 0xFFFF /* CHIP_ID - [15:0] */ -#define WM8523_CHIP_ID_SHIFT 0 /* CHIP_ID - [15:0] */ -#define WM8523_CHIP_ID_WIDTH 16 /* CHIP_ID - [15:0] */ - -/* - * R1 (0x01) - REVISION - */ -#define WM8523_CHIP_REV_MASK 0x0007 /* CHIP_REV - [2:0] */ -#define WM8523_CHIP_REV_SHIFT 0 /* CHIP_REV - [2:0] */ -#define WM8523_CHIP_REV_WIDTH 3 /* CHIP_REV - [2:0] */ - -/* - * R2 (0x02) - PSCTRL1 - */ -#define WM8523_SYS_ENA_MASK 0x0003 /* SYS_ENA - [1:0] */ -#define WM8523_SYS_ENA_SHIFT 0 /* SYS_ENA - [1:0] */ -#define WM8523_SYS_ENA_WIDTH 2 /* SYS_ENA - [1:0] */ - -/* - * R3 (0x03) - AIF_CTRL1 - */ -#define WM8523_TDM_MODE_MASK 0x1800 /* TDM_MODE - [12:11] */ -#define WM8523_TDM_MODE_SHIFT 11 /* TDM_MODE - [12:11] */ -#define WM8523_TDM_MODE_WIDTH 2 /* TDM_MODE - [12:11] */ -#define WM8523_TDM_SLOT_MASK 0x0600 /* TDM_SLOT - [10:9] */ -#define WM8523_TDM_SLOT_SHIFT 9 /* TDM_SLOT - [10:9] */ -#define WM8523_TDM_SLOT_WIDTH 2 /* TDM_SLOT - [10:9] */ -#define WM8523_DEEMPH 0x0100 /* DEEMPH */ -#define WM8523_DEEMPH_MASK 0x0100 /* DEEMPH */ -#define WM8523_DEEMPH_SHIFT 8 /* DEEMPH */ -#define WM8523_DEEMPH_WIDTH 1 /* DEEMPH */ -#define WM8523_AIF_MSTR 0x0080 /* AIF_MSTR */ -#define WM8523_AIF_MSTR_MASK 0x0080 /* AIF_MSTR */ -#define WM8523_AIF_MSTR_SHIFT 7 /* AIF_MSTR */ -#define WM8523_AIF_MSTR_WIDTH 1 /* AIF_MSTR */ -#define WM8523_LRCLK_INV 0x0040 /* LRCLK_INV */ -#define WM8523_LRCLK_INV_MASK 0x0040 /* LRCLK_INV */ -#define WM8523_LRCLK_INV_SHIFT 6 /* LRCLK_INV */ -#define WM8523_LRCLK_INV_WIDTH 1 /* LRCLK_INV */ -#define WM8523_BCLK_INV 0x0020 /* BCLK_INV */ -#define WM8523_BCLK_INV_MASK 0x0020 /* BCLK_INV */ -#define WM8523_BCLK_INV_SHIFT 5 /* BCLK_INV */ -#define WM8523_BCLK_INV_WIDTH 1 /* BCLK_INV */ -#define WM8523_WL_MASK 0x0018 /* WL - [4:3] */ -#define WM8523_WL_SHIFT 3 /* WL - [4:3] */ -#define WM8523_WL_WIDTH 2 /* WL - [4:3] */ -#define WM8523_FMT_MASK 0x0007 /* FMT - [2:0] */ -#define WM8523_FMT_SHIFT 0 /* FMT - [2:0] */ -#define WM8523_FMT_WIDTH 3 /* FMT - [2:0] */ - -/* - * R4 (0x04) - AIF_CTRL2 - */ -#define WM8523_DAC_OP_MUX_MASK 0x00C0 /* DAC_OP_MUX - [7:6] */ -#define WM8523_DAC_OP_MUX_SHIFT 6 /* DAC_OP_MUX - [7:6] */ -#define WM8523_DAC_OP_MUX_WIDTH 2 /* DAC_OP_MUX - [7:6] */ -#define WM8523_BCLKDIV_MASK 0x0038 /* BCLKDIV - [5:3] */ -#define WM8523_BCLKDIV_SHIFT 3 /* BCLKDIV - [5:3] */ -#define WM8523_BCLKDIV_WIDTH 3 /* BCLKDIV - [5:3] */ -#define WM8523_SR_MASK 0x0007 /* SR - [2:0] */ -#define WM8523_SR_SHIFT 0 /* SR - [2:0] */ -#define WM8523_SR_WIDTH 3 /* SR - [2:0] */ - -/* - * R5 (0x05) - DAC_CTRL3 - */ -#define WM8523_ZC 0x0010 /* ZC */ -#define WM8523_ZC_MASK 0x0010 /* ZC */ -#define WM8523_ZC_SHIFT 4 /* ZC */ -#define WM8523_ZC_WIDTH 1 /* ZC */ -#define WM8523_DACR 0x0008 /* DACR */ -#define WM8523_DACR_MASK 0x0008 /* DACR */ -#define WM8523_DACR_SHIFT 3 /* DACR */ -#define WM8523_DACR_WIDTH 1 /* DACR */ -#define WM8523_DACL 0x0004 /* DACL */ -#define WM8523_DACL_MASK 0x0004 /* DACL */ -#define WM8523_DACL_SHIFT 2 /* DACL */ -#define WM8523_DACL_WIDTH 1 /* DACL */ -#define WM8523_VOL_UP_RAMP 0x0002 /* VOL_UP_RAMP */ -#define WM8523_VOL_UP_RAMP_MASK 0x0002 /* VOL_UP_RAMP */ -#define WM8523_VOL_UP_RAMP_SHIFT 1 /* VOL_UP_RAMP */ -#define WM8523_VOL_UP_RAMP_WIDTH 1 /* VOL_UP_RAMP */ -#define WM8523_VOL_DOWN_RAMP 0x0001 /* VOL_DOWN_RAMP */ -#define WM8523_VOL_DOWN_RAMP_MASK 0x0001 /* VOL_DOWN_RAMP */ -#define WM8523_VOL_DOWN_RAMP_SHIFT 0 /* VOL_DOWN_RAMP */ -#define WM8523_VOL_DOWN_RAMP_WIDTH 1 /* VOL_DOWN_RAMP */ - -/* - * R6 (0x06) - DAC_GAINL - */ -#define WM8523_DACL_VU 0x0200 /* DACL_VU */ -#define WM8523_DACL_VU_MASK 0x0200 /* DACL_VU */ -#define WM8523_DACL_VU_SHIFT 9 /* DACL_VU */ -#define WM8523_DACL_VU_WIDTH 1 /* DACL_VU */ -#define WM8523_DACL_VOL_MASK 0x01FF /* DACL_VOL - [8:0] */ -#define WM8523_DACL_VOL_SHIFT 0 /* DACL_VOL - [8:0] */ -#define WM8523_DACL_VOL_WIDTH 9 /* DACL_VOL - [8:0] */ - -/* - * R7 (0x07) - DAC_GAINR - */ -#define WM8523_DACR_VU 0x0200 /* DACR_VU */ -#define WM8523_DACR_VU_MASK 0x0200 /* DACR_VU */ -#define WM8523_DACR_VU_SHIFT 9 /* DACR_VU */ -#define WM8523_DACR_VU_WIDTH 1 /* DACR_VU */ -#define WM8523_DACR_VOL_MASK 0x01FF /* DACR_VOL - [8:0] */ -#define WM8523_DACR_VOL_SHIFT 0 /* DACR_VOL - [8:0] */ -#define WM8523_DACR_VOL_WIDTH 9 /* DACR_VOL - [8:0] */ - -/* - * R8 (0x08) - ZERO_DETECT - */ -#define WM8523_ZD_COUNT_MASK 0x0003 /* ZD_COUNT - [1:0] */ -#define WM8523_ZD_COUNT_SHIFT 0 /* ZD_COUNT - [1:0] */ -#define WM8523_ZD_COUNT_WIDTH 2 /* ZD_COUNT - [1:0] */ - -extern struct snd_soc_dai wm8523_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8523; - -#endif diff --git a/trunk/sound/soc/codecs/wm8580.c b/trunk/sound/soc/codecs/wm8580.c index 97b9ed95d289..86c4b24db817 100644 --- a/trunk/sound/soc/codecs/wm8580.c +++ b/trunk/sound/soc/codecs/wm8580.c @@ -24,8 +24,6 @@ #include #include #include -#include - #include #include #include @@ -189,22 +187,15 @@ struct pll_state { unsigned int out; }; -#define WM8580_NUM_SUPPLIES 3 -static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = { - "AVDD", - "DVDD", - "PVDD", -}; - /* codec private data */ struct wm8580_priv { struct snd_soc_codec codec; - struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; u16 reg_cache[WM8580_MAX_REGISTER + 1]; struct pll_state a; struct pll_state b; }; + /* * read wm8580 register cache */ @@ -931,28 +922,11 @@ static int wm8580_register(struct wm8580_priv *wm8580) memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg)); - for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) - wm8580->supplies[i].supply = wm8580_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8580->supplies), - wm8580->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), - wm8580->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_regulator_get; - } - /* Get the codec into a known state */ ret = wm8580_write(codec, WM8580_RESET, 0); if (ret != 0) { dev_err(codec->dev, "Failed to reset codec: %d\n", ret); - goto err_regulator_enable; + goto err; } for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++) @@ -965,7 +939,7 @@ static int wm8580_register(struct wm8580_priv *wm8580) ret = snd_soc_register_codec(codec); if (ret != 0) { dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err_regulator_enable; + goto err; } ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); @@ -978,10 +952,6 @@ static int wm8580_register(struct wm8580_priv *wm8580) err_codec: snd_soc_unregister_codec(codec); -err_regulator_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); -err_regulator_get: - regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); err: kfree(wm8580); return ret; @@ -992,8 +962,6 @@ static void wm8580_unregister(struct wm8580_priv *wm8580) wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF); snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); snd_soc_unregister_codec(&wm8580->codec); - regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); - regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); kfree(wm8580); wm8580_codec = NULL; } @@ -1027,21 +995,6 @@ static int wm8580_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int wm8580_i2c_suspend(struct i2c_client *client, pm_message_t msg) -{ - return snd_soc_suspend_device(&client->dev); -} - -static int wm8580_i2c_resume(struct i2c_client *client) -{ - return snd_soc_resume_device(&client->dev); -} -#else -#define wm8580_i2c_suspend NULL -#define wm8580_i2c_resume NULL -#endif - static const struct i2c_device_id wm8580_i2c_id[] = { { "wm8580", 0 }, { } @@ -1055,8 +1008,6 @@ static struct i2c_driver wm8580_i2c_driver = { }, .probe = wm8580_i2c_probe, .remove = wm8580_i2c_remove, - .suspend = wm8580_i2c_suspend, - .resume = wm8580_i2c_resume, .id_table = wm8580_i2c_id, }; #endif diff --git a/trunk/sound/soc/codecs/wm8731.c b/trunk/sound/soc/codecs/wm8731.c index 156002852078..7a205876ef4f 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" @@ -114,26 +113,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), @@ -464,11 +457,9 @@ struct snd_soc_dai wm8731_dai = { .rates = WM8731_RATES, .formats = WM8731_FORMATS,}, .ops = &wm8731_dai_ops, - .symmetric_rates = 1, }; EXPORT_SYMBOL_GPL(wm8731_dai); -#ifdef CONFIG_PM static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); @@ -497,10 +488,6 @@ static int wm8731_resume(struct platform_device *pdev) wm8731_set_bias_level(codec, codec->suspend_bias_level); return 0; } -#else -#define wm8731_suspend NULL -#define wm8731_resume NULL -#endif static int wm8731_probe(struct platform_device *pdev) { @@ -568,8 +555,7 @@ static int wm8731_register(struct wm8731_priv *wm8731) if (wm8731_codec) { dev_err(codec->dev, "Another WM8731 is registered\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } mutex_init(&codec->mutex); @@ -592,8 +578,8 @@ static int wm8731_register(struct wm8731_priv *wm8731) ret = wm8731_reset(codec); if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset: %d\n", ret); - goto err; + dev_err(codec->dev, "Failed to issue reset\n"); + return ret; } wm8731_dai.dev = codec->dev; @@ -619,23 +605,17 @@ static int wm8731_register(struct wm8731_priv *wm8731) ret = snd_soc_register_codec(codec); if (ret != 0) { dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; + return ret; } ret = snd_soc_register_dai(&wm8731_dai); if (ret != 0) { dev_err(codec->dev, "Failed to register DAI: %d\n", ret); snd_soc_unregister_codec(codec); - goto err_codec; + return ret; } return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - kfree(wm8731); - return ret; } static void wm8731_unregister(struct wm8731_priv *wm8731) @@ -700,21 +680,6 @@ static int __devexit wm8731_spi_remove(struct spi_device *spi) return 0; } -#ifdef CONFIG_PM -static int wm8731_spi_suspend(struct spi_device *spi, pm_message_t msg) -{ - return snd_soc_suspend_device(&spi->dev); -} - -static int wm8731_spi_resume(struct spi_device *spi) -{ - return snd_soc_resume_device(&spi->dev); -} -#else -#define wm8731_spi_suspend NULL -#define wm8731_spi_resume NULL -#endif - static struct spi_driver wm8731_spi_driver = { .driver = { .name = "wm8731", @@ -722,8 +687,6 @@ static struct spi_driver wm8731_spi_driver = { .owner = THIS_MODULE, }, .probe = wm8731_spi_probe, - .suspend = wm8731_spi_suspend, - .resume = wm8731_spi_resume, .remove = __devexit_p(wm8731_spi_remove), }; #endif /* CONFIG_SPI_MASTER */ @@ -757,21 +720,6 @@ static __devexit int wm8731_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int wm8731_i2c_suspend(struct i2c_client *i2c, pm_message_t msg) -{ - return snd_soc_suspend_device(&i2c->dev); -} - -static int wm8731_i2c_resume(struct i2c_client *i2c) -{ - return snd_soc_resume_device(&i2c->dev); -} -#else -#define wm8731_i2c_suspend NULL -#define wm8731_i2c_resume NULL -#endif - static const struct i2c_device_id wm8731_i2c_id[] = { { "wm8731", 0 }, { } @@ -785,8 +733,6 @@ static struct i2c_driver wm8731_i2c_driver = { }, .probe = wm8731_i2c_probe, .remove = __devexit_p(wm8731_i2c_remove), - .suspend = wm8731_i2c_suspend, - .resume = wm8731_i2c_resume, .id_table = wm8731_i2c_id, }; #endif diff --git a/trunk/sound/soc/codecs/wm8753.c b/trunk/sound/soc/codecs/wm8753.c index d80d414cfbbd..49c4b2898aff 100644 --- a/trunk/sound/soc/codecs/wm8753.c +++ b/trunk/sound/soc/codecs/wm8753.c @@ -1766,21 +1766,6 @@ static int wm8753_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int wm8753_i2c_suspend(struct i2c_client *client, pm_message_t msg) -{ - return snd_soc_suspend_device(&client->dev); -} - -static int wm8753_i2c_resume(struct i2c_client *client) -{ - return snd_soc_resume_device(&client->dev); -} -#else -#define wm8753_i2c_suspend NULL -#define wm8753_i2c_resume NULL -#endif - static const struct i2c_device_id wm8753_i2c_id[] = { { "wm8753", 0 }, { } @@ -1794,8 +1779,6 @@ static struct i2c_driver wm8753_i2c_driver = { }, .probe = wm8753_i2c_probe, .remove = wm8753_i2c_remove, - .suspend = wm8753_i2c_suspend, - .resume = wm8753_i2c_resume, .id_table = wm8753_i2c_id, }; #endif @@ -1851,22 +1834,6 @@ static int __devexit wm8753_spi_remove(struct spi_device *spi) return 0; } -#ifdef CONFIG_PM -static int wm8753_spi_suspend(struct spi_device *spi, pm_message_t msg) -{ - return snd_soc_suspend_device(&spi->dev); -} - -static int wm8753_spi_resume(struct spi_device *spi) -{ - return snd_soc_resume_device(&spi->dev); -} - -#else -#define wm8753_spi_suspend NULL -#define wm8753_spi_resume NULL -#endif - static struct spi_driver wm8753_spi_driver = { .driver = { .name = "wm8753", @@ -1875,8 +1842,6 @@ static struct spi_driver wm8753_spi_driver = { }, .probe = wm8753_spi_probe, .remove = __devexit_p(wm8753_spi_remove), - .suspend = wm8753_spi_suspend, - .resume = wm8753_spi_resume, }; #endif 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/wm8900.c b/trunk/sound/soc/codecs/wm8900.c index ac308993ac5a..3c78945244b8 100644 --- a/trunk/sound/soc/codecs/wm8900.c +++ b/trunk/sound/soc/codecs/wm8900.c @@ -116,7 +116,6 @@ #define WM8900_REG_CLOCKING2_DAC_CLKDIV 0x1c #define WM8900_REG_DACCTRL_MUTE 0x004 -#define WM8900_REG_DACCTRL_DAC_SB_FILT 0x100 #define WM8900_REG_DACCTRL_AIF_LRCLKRATE 0x400 #define WM8900_REG_AUDIO3_ADCLRC_DIR 0x0800 @@ -440,6 +439,7 @@ SOC_SINGLE("DAC Soft Mute Switch", WM8900_REG_DACCTRL, 6, 1, 1), SOC_ENUM("DAC Mute Rate", dac_mute_rate), SOC_SINGLE("DAC Mono Switch", WM8900_REG_DACCTRL, 9, 1, 0), SOC_ENUM("DAC Deemphasis", dac_deemphasis), +SOC_SINGLE("DAC Sloping Stopband Filter Switch", WM8900_REG_DACCTRL, 8, 1, 0), SOC_SINGLE("DAC Sigma-Delta Modulator Clock Switch", WM8900_REG_DACCTRL, 12, 1, 0), @@ -743,17 +743,6 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream, wm8900_write(codec, WM8900_REG_AUDIO1, reg); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - reg = wm8900_read(codec, WM8900_REG_DACCTRL); - - if (params_rate(params) <= 24000) - reg |= WM8900_REG_DACCTRL_DAC_SB_FILT; - else - reg &= ~WM8900_REG_DACCTRL_DAC_SB_FILT; - - wm8900_write(codec, WM8900_REG_DACCTRL, reg); - } - return 0; } @@ -1399,21 +1388,6 @@ static __devexit int wm8900_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int wm8900_i2c_suspend(struct i2c_client *client, pm_message_t msg) -{ - return snd_soc_suspend_device(&client->dev); -} - -static int wm8900_i2c_resume(struct i2c_client *client) -{ - return snd_soc_resume_device(&client->dev); -} -#else -#define wm8900_i2c_suspend NULL -#define wm8900_i2c_resume NULL -#endif - static const struct i2c_device_id wm8900_i2c_id[] = { { "wm8900", 0 }, { } @@ -1427,8 +1401,6 @@ static struct i2c_driver wm8900_i2c_driver = { }, .probe = wm8900_i2c_probe, .remove = __devexit_p(wm8900_i2c_remove), - .suspend = wm8900_i2c_suspend, - .resume = wm8900_i2c_resume, .id_table = wm8900_i2c_id, }; diff --git a/trunk/sound/soc/codecs/wm8903.c b/trunk/sound/soc/codecs/wm8903.c index c9baeae3e275..e8d2e3e14c45 100644 --- a/trunk/sound/soc/codecs/wm8903.c +++ b/trunk/sound/soc/codecs/wm8903.c @@ -715,6 +715,8 @@ SOC_ENUM("DAC Soft Mute Rate", soft_mute), SOC_ENUM("DAC Mute Mode", mute_mode), SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0), SOC_ENUM("DAC De-emphasis", dac_deemphasis), +SOC_SINGLE("DAC Sloping Stopband Filter Switch", + WM8903_DAC_DIGITAL_1, 11, 1, 0), SOC_ENUM("DAC Companding Mode", dac_companding), SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0), @@ -1371,19 +1373,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, u16 aif3 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_3); u16 clock0 = wm8903_read(codec, WM8903_CLOCK_RATES_0); u16 clock1 = wm8903_read(codec, WM8903_CLOCK_RATES_1); - u16 dac_digital1 = wm8903_read(codec, WM8903_DAC_DIGITAL_1); if (substream == wm8903->slave_substream) { dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n"); return 0; } - /* Enable sloping stopband filter for low sample rates */ - if (fs <= 24000) - dac_digital1 |= WM8903_DAC_SB_FILT; - else - dac_digital1 &= ~WM8903_DAC_SB_FILT; - /* Configure sample rate logic for DSP - choose nearest rate */ dsp_config = 0; best_val = abs(sample_rates[dsp_config].rate - fs); @@ -1508,7 +1503,6 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, wm8903_write(codec, WM8903_AUDIO_INTERFACE_1, aif1); wm8903_write(codec, WM8903_AUDIO_INTERFACE_2, aif2); wm8903_write(codec, WM8903_AUDIO_INTERFACE_3, aif3); - wm8903_write(codec, WM8903_DAC_DIGITAL_1, dac_digital1); return 0; } @@ -1727,21 +1721,6 @@ static __devexit int wm8903_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int wm8903_i2c_suspend(struct i2c_client *client, pm_message_t msg) -{ - return snd_soc_suspend_device(&client->dev); -} - -static int wm8903_i2c_resume(struct i2c_client *client) -{ - return snd_soc_resume_device(&client->dev); -} -#else -#define wm8903_i2c_suspend NULL -#define wm8903_i2c_resume NULL -#endif - /* i2c codec control layer */ static const struct i2c_device_id wm8903_i2c_id[] = { { "wm8903", 0 }, @@ -1756,8 +1735,6 @@ static struct i2c_driver wm8903_i2c_driver = { }, .probe = wm8903_i2c_probe, .remove = __devexit_p(wm8903_i2c_remove), - .suspend = wm8903_i2c_suspend, - .resume = wm8903_i2c_resume, .id_table = wm8903_i2c_id, }; diff --git a/trunk/sound/soc/codecs/wm8940.c b/trunk/sound/soc/codecs/wm8940.c index b69210a77423..b8e17d6bc1f7 100644 --- a/trunk/sound/soc/codecs/wm8940.c +++ b/trunk/sound/soc/codecs/wm8940.c @@ -916,21 +916,6 @@ static int __devexit wm8940_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int wm8940_i2c_suspend(struct i2c_client *client, pm_message_t msg) -{ - return snd_soc_suspend_device(&client->dev); -} - -static int wm8940_i2c_resume(struct i2c_client *client) -{ - return snd_soc_resume_device(&client->dev); -} -#else -#define wm8940_i2c_suspend NULL -#define wm8940_i2c_resume NULL -#endif - static const struct i2c_device_id wm8940_i2c_id[] = { { "wm8940", 0 }, { } @@ -944,8 +929,6 @@ static struct i2c_driver wm8940_i2c_driver = { }, .probe = wm8940_i2c_probe, .remove = __devexit_p(wm8940_i2c_remove), - .suspend = wm8940_i2c_suspend, - .resume = wm8940_i2c_resume, .id_table = wm8940_i2c_id, }; diff --git a/trunk/sound/soc/codecs/wm8960.c b/trunk/sound/soc/codecs/wm8960.c index d1769e6c0c44..e224d8add170 100644 --- a/trunk/sound/soc/codecs/wm8960.c +++ b/trunk/sound/soc/codecs/wm8960.c @@ -810,8 +810,7 @@ static int wm8960_register(struct wm8960_priv *wm8960) if (wm8960_codec) { dev_err(codec->dev, "Another WM8960 is registered\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } if (!pdata) { @@ -844,7 +843,7 @@ static int wm8960_register(struct wm8960_priv *wm8960) ret = wm8960_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); - goto err; + return ret; } wm8960_dai.dev = codec->dev; @@ -878,22 +877,17 @@ static int wm8960_register(struct wm8960_priv *wm8960) ret = snd_soc_register_codec(codec); if (ret != 0) { dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; + return ret; } ret = snd_soc_register_dai(&wm8960_dai); if (ret != 0) { dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; + snd_soc_unregister_codec(codec); + return ret; } return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - kfree(wm8960); - return ret; } static void wm8960_unregister(struct wm8960_priv *wm8960) @@ -933,21 +927,6 @@ static __devexit int wm8960_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int wm8960_i2c_suspend(struct i2c_client *client, pm_message_t msg) -{ - return snd_soc_suspend_device(&client->dev); -} - -static int wm8960_i2c_resume(struct i2c_client *client) -{ - return snd_soc_resume_device(&client->dev); -} -#else -#define wm8960_i2c_suspend NULL -#define wm8960_i2c_resume NULL -#endif - static const struct i2c_device_id wm8960_i2c_id[] = { { "wm8960", 0 }, { } @@ -961,8 +940,6 @@ static struct i2c_driver wm8960_i2c_driver = { }, .probe = wm8960_i2c_probe, .remove = __devexit_p(wm8960_i2c_remove), - .suspend = wm8960_i2c_suspend, - .resume = wm8960_i2c_resume, .id_table = wm8960_i2c_id, }; diff --git a/trunk/sound/soc/codecs/wm8961.c b/trunk/sound/soc/codecs/wm8961.c deleted file mode 100644 index bd1af92a122f..000000000000 --- a/trunk/sound/soc/codecs/wm8961.c +++ /dev/null @@ -1,1326 +0,0 @@ -/* - * wm8961.c -- WM8961 ALSA SoC Audio driver - * - * 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. - * - * Currently unimplemented features: - * - ALC - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8961.h" - -#define WM8961_MAX_REGISTER 0xFC - -static u16 wm8961_reg_defaults[] = { - 0x009F, /* R0 - Left Input volume */ - 0x009F, /* R1 - Right Input volume */ - 0x0000, /* R2 - LOUT1 volume */ - 0x0000, /* R3 - ROUT1 volume */ - 0x0020, /* R4 - Clocking1 */ - 0x0008, /* R5 - ADC & DAC Control 1 */ - 0x0000, /* R6 - ADC & DAC Control 2 */ - 0x000A, /* R7 - Audio Interface 0 */ - 0x01F4, /* R8 - Clocking2 */ - 0x0000, /* R9 - Audio Interface 1 */ - 0x00FF, /* R10 - Left DAC volume */ - 0x00FF, /* R11 - Right DAC volume */ - 0x0000, /* R12 */ - 0x0000, /* R13 */ - 0x0040, /* R14 - Audio Interface 2 */ - 0x0000, /* R15 - Software Reset */ - 0x0000, /* R16 */ - 0x007B, /* R17 - ALC1 */ - 0x0000, /* R18 - ALC2 */ - 0x0032, /* R19 - ALC3 */ - 0x0000, /* R20 - Noise Gate */ - 0x00C0, /* R21 - Left ADC volume */ - 0x00C0, /* R22 - Right ADC volume */ - 0x0120, /* R23 - Additional control(1) */ - 0x0000, /* R24 - Additional control(2) */ - 0x0000, /* R25 - Pwr Mgmt (1) */ - 0x0000, /* R26 - Pwr Mgmt (2) */ - 0x0000, /* R27 - Additional Control (3) */ - 0x0000, /* R28 - Anti-pop */ - 0x0000, /* R29 */ - 0x005F, /* R30 - Clocking 3 */ - 0x0000, /* R31 */ - 0x0000, /* R32 - ADCL signal path */ - 0x0000, /* R33 - ADCR signal path */ - 0x0000, /* R34 */ - 0x0000, /* R35 */ - 0x0000, /* R36 */ - 0x0000, /* R37 */ - 0x0000, /* R38 */ - 0x0000, /* R39 */ - 0x0000, /* R40 - LOUT2 volume */ - 0x0000, /* R41 - ROUT2 volume */ - 0x0000, /* R42 */ - 0x0000, /* R43 */ - 0x0000, /* R44 */ - 0x0000, /* R45 */ - 0x0000, /* R46 */ - 0x0000, /* R47 - Pwr Mgmt (3) */ - 0x0023, /* R48 - Additional Control (4) */ - 0x0000, /* R49 - Class D Control 1 */ - 0x0000, /* R50 */ - 0x0003, /* R51 - Class D Control 2 */ - 0x0000, /* R52 */ - 0x0000, /* R53 */ - 0x0000, /* R54 */ - 0x0000, /* R55 */ - 0x0106, /* R56 - Clocking 4 */ - 0x0000, /* R57 - DSP Sidetone 0 */ - 0x0000, /* R58 - DSP Sidetone 1 */ - 0x0000, /* R59 */ - 0x0000, /* R60 - DC Servo 0 */ - 0x0000, /* R61 - DC Servo 1 */ - 0x0000, /* R62 */ - 0x015E, /* R63 - DC Servo 3 */ - 0x0010, /* R64 */ - 0x0010, /* R65 - DC Servo 5 */ - 0x0000, /* R66 */ - 0x0001, /* R67 */ - 0x0003, /* R68 - Analogue PGA Bias */ - 0x0000, /* R69 - Analogue HP 0 */ - 0x0060, /* R70 */ - 0x01FB, /* R71 - Analogue HP 2 */ - 0x0000, /* R72 - Charge Pump 1 */ - 0x0065, /* R73 */ - 0x005F, /* R74 */ - 0x0059, /* R75 */ - 0x006B, /* R76 */ - 0x0038, /* R77 */ - 0x000C, /* R78 */ - 0x000A, /* R79 */ - 0x006B, /* R80 */ - 0x0000, /* R81 */ - 0x0000, /* R82 - Charge Pump B */ - 0x0087, /* R83 */ - 0x0000, /* R84 */ - 0x005C, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 - Write Sequencer 1 */ - 0x0000, /* R88 - Write Sequencer 2 */ - 0x0000, /* R89 - Write Sequencer 3 */ - 0x0000, /* R90 - Write Sequencer 4 */ - 0x0000, /* R91 - Write Sequencer 5 */ - 0x0000, /* R92 - Write Sequencer 6 */ - 0x0000, /* R93 - Write Sequencer 7 */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 */ - 0x0000, /* R97 */ - 0x0000, /* R98 */ - 0x0000, /* R99 */ - 0x0000, /* R100 */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x0000, /* R104 */ - 0x0000, /* R105 */ - 0x0000, /* R106 */ - 0x0000, /* R107 */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 */ - 0x0000, /* R112 */ - 0x0000, /* R113 */ - 0x0000, /* R114 */ - 0x0000, /* R115 */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x0000, /* R128 */ - 0x0000, /* R129 */ - 0x0000, /* R130 */ - 0x0000, /* R131 */ - 0x0000, /* R132 */ - 0x0000, /* R133 */ - 0x0000, /* R134 */ - 0x0000, /* R135 */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0000, /* R140 */ - 0x0000, /* R141 */ - 0x0000, /* R142 */ - 0x0000, /* R143 */ - 0x0000, /* R144 */ - 0x0000, /* R145 */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x0000, /* R152 */ - 0x0000, /* R153 */ - 0x0000, /* R154 */ - 0x0000, /* R155 */ - 0x0000, /* R156 */ - 0x0000, /* R157 */ - 0x0000, /* R158 */ - 0x0000, /* R159 */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 */ - 0x0000, /* R164 */ - 0x0000, /* R165 */ - 0x0000, /* R166 */ - 0x0000, /* R167 */ - 0x0000, /* R168 */ - 0x0000, /* R169 */ - 0x0000, /* R170 */ - 0x0000, /* R171 */ - 0x0000, /* R172 */ - 0x0000, /* R173 */ - 0x0000, /* R174 */ - 0x0000, /* R175 */ - 0x0000, /* R176 */ - 0x0000, /* R177 */ - 0x0000, /* R178 */ - 0x0000, /* R179 */ - 0x0000, /* R180 */ - 0x0000, /* R181 */ - 0x0000, /* R182 */ - 0x0000, /* R183 */ - 0x0000, /* R184 */ - 0x0000, /* R185 */ - 0x0000, /* R186 */ - 0x0000, /* R187 */ - 0x0000, /* R188 */ - 0x0000, /* R189 */ - 0x0000, /* R190 */ - 0x0000, /* R191 */ - 0x0000, /* R192 */ - 0x0000, /* R193 */ - 0x0000, /* R194 */ - 0x0000, /* R195 */ - 0x0030, /* R196 */ - 0x0006, /* R197 */ - 0x0000, /* R198 */ - 0x0060, /* R199 */ - 0x0000, /* R200 */ - 0x003F, /* R201 */ - 0x0000, /* R202 */ - 0x0000, /* R203 */ - 0x0000, /* R204 */ - 0x0001, /* R205 */ - 0x0000, /* R206 */ - 0x0181, /* R207 */ - 0x0005, /* R208 */ - 0x0008, /* R209 */ - 0x0008, /* R210 */ - 0x0000, /* R211 */ - 0x013B, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 */ - 0x0000, /* R216 */ - 0x0070, /* R217 */ - 0x0000, /* R218 */ - 0x0000, /* R219 */ - 0x0000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0003, /* R223 */ - 0x0000, /* R224 */ - 0x0000, /* R225 */ - 0x0001, /* R226 */ - 0x0008, /* R227 */ - 0x0000, /* R228 */ - 0x0000, /* R229 */ - 0x0000, /* R230 */ - 0x0000, /* R231 */ - 0x0004, /* R232 */ - 0x0000, /* R233 */ - 0x0000, /* R234 */ - 0x0000, /* R235 */ - 0x0000, /* R236 */ - 0x0000, /* R237 */ - 0x0080, /* R238 */ - 0x0000, /* R239 */ - 0x0000, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0000, /* R243 */ - 0x0000, /* R244 */ - 0x0052, /* R245 */ - 0x0110, /* R246 */ - 0x0040, /* R247 */ - 0x0000, /* R248 */ - 0x0030, /* R249 */ - 0x0000, /* R250 */ - 0x0000, /* R251 */ - 0x0001, /* R252 - General test 1 */ -}; - -struct wm8961_priv { - struct snd_soc_codec codec; - int sysclk; - u16 reg_cache[WM8961_MAX_REGISTER]; -}; - -static int wm8961_reg_is_volatile(int reg) -{ - switch (reg) { - case WM8961_WRITE_SEQUENCER_7: - case WM8961_DC_SERVO_1: - return 1; - - default: - return 0; - } -} - -static unsigned int wm8961_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - BUG_ON(reg > WM8961_MAX_REGISTER); - return cache[reg]; -} - -static unsigned int wm8961_read_hw(struct snd_soc_codec *codec, u8 reg) -{ - struct i2c_msg xfer[2]; - u16 data; - int ret; - struct i2c_client *client = codec->control_data; - - BUG_ON(reg > WM8961_MAX_REGISTER); - - /* Write register */ - xfer[0].addr = client->addr; - xfer[0].flags = 0; - xfer[0].len = 1; - xfer[0].buf = ® - - /* Read data */ - xfer[1].addr = client->addr; - xfer[1].flags = I2C_M_RD; - xfer[1].len = 2; - xfer[1].buf = (u8 *)&data; - - ret = i2c_transfer(client->adapter, xfer, 2); - if (ret != 2) { - dev_err(&client->dev, "i2c_transfer() returned %d\n", ret); - return 0; - } - - return (data >> 8) | ((data & 0xff) << 8); -} - -static unsigned int wm8961_read(struct snd_soc_codec *codec, unsigned int reg) -{ - if (wm8961_reg_is_volatile(reg)) - return wm8961_read_hw(codec, reg); - else - return wm8961_read_reg_cache(codec, reg); -} - -static int wm8961_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u16 *cache = codec->reg_cache; - u8 data[3]; - - BUG_ON(reg > WM8961_MAX_REGISTER); - - if (!wm8961_reg_is_volatile(reg)) - cache[reg] = value; - - data[0] = reg; - data[1] = value >> 8; - data[2] = value & 0x00ff; - - if (codec->hw_write(codec->control_data, data, 3) == 3) - return 0; - else - return -EIO; -} - -static int wm8961_reset(struct snd_soc_codec *codec) -{ - return wm8961_write(codec, WM8961_SOFTWARE_RESET, 0); -} - -/* - * The headphone output supports special anti-pop sequences giving - * silent power up and power down. - */ -static int wm8961_hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - u16 hp_reg = wm8961_read(codec, WM8961_ANALOGUE_HP_0); - u16 cp_reg = wm8961_read(codec, WM8961_CHARGE_PUMP_1); - u16 pwr_reg = wm8961_read(codec, WM8961_PWR_MGMT_2); - u16 dcs_reg = wm8961_read(codec, WM8961_DC_SERVO_1); - int timeout = 500; - - if (event & SND_SOC_DAPM_POST_PMU) { - /* Make sure the output is shorted */ - hp_reg &= ~(WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT); - wm8961_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Enable the charge pump */ - cp_reg |= WM8961_CP_ENA; - wm8961_write(codec, WM8961_CHARGE_PUMP_1, cp_reg); - mdelay(5); - - /* Enable the PGA */ - pwr_reg |= WM8961_LOUT1_PGA | WM8961_ROUT1_PGA; - wm8961_write(codec, WM8961_PWR_MGMT_2, pwr_reg); - - /* Enable the amplifier */ - hp_reg |= WM8961_HPR_ENA | WM8961_HPL_ENA; - wm8961_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Second stage enable */ - hp_reg |= WM8961_HPR_ENA_DLY | WM8961_HPL_ENA_DLY; - wm8961_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Enable the DC servo & trigger startup */ - dcs_reg |= - WM8961_DCS_ENA_CHAN_HPR | WM8961_DCS_TRIG_STARTUP_HPR | - WM8961_DCS_ENA_CHAN_HPL | WM8961_DCS_TRIG_STARTUP_HPL; - dev_dbg(codec->dev, "Enabling DC servo\n"); - - wm8961_write(codec, WM8961_DC_SERVO_1, dcs_reg); - do { - msleep(1); - dcs_reg = wm8961_read(codec, WM8961_DC_SERVO_1); - } while (--timeout && - dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR | - WM8961_DCS_TRIG_STARTUP_HPL)); - if (dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR | - WM8961_DCS_TRIG_STARTUP_HPL)) - dev_err(codec->dev, "DC servo timed out\n"); - else - dev_dbg(codec->dev, "DC servo startup complete\n"); - - /* Enable the output stage */ - hp_reg |= WM8961_HPR_ENA_OUTP | WM8961_HPL_ENA_OUTP; - wm8961_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Remove the short on the output stage */ - hp_reg |= WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT; - wm8961_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - } - - if (event & SND_SOC_DAPM_PRE_PMD) { - /* Short the output */ - hp_reg &= ~(WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT); - wm8961_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Disable the output stage */ - hp_reg &= ~(WM8961_HPR_ENA_OUTP | WM8961_HPL_ENA_OUTP); - wm8961_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Disable DC offset cancellation */ - dcs_reg &= ~(WM8961_DCS_ENA_CHAN_HPR | - WM8961_DCS_ENA_CHAN_HPL); - wm8961_write(codec, WM8961_DC_SERVO_1, dcs_reg); - - /* Finish up */ - hp_reg &= ~(WM8961_HPR_ENA_DLY | WM8961_HPR_ENA | - WM8961_HPL_ENA_DLY | WM8961_HPL_ENA); - wm8961_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Disable the PGA */ - pwr_reg &= ~(WM8961_LOUT1_PGA | WM8961_ROUT1_PGA); - wm8961_write(codec, WM8961_PWR_MGMT_2, pwr_reg); - - /* Disable the charge pump */ - dev_dbg(codec->dev, "Disabling charge pump\n"); - wm8961_write(codec, WM8961_CHARGE_PUMP_1, - cp_reg & ~WM8961_CP_ENA); - } - - return 0; -} - -static int wm8961_spk_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - u16 pwr_reg = wm8961_read(codec, WM8961_PWR_MGMT_2); - u16 spk_reg = wm8961_read(codec, WM8961_CLASS_D_CONTROL_1); - - if (event & SND_SOC_DAPM_POST_PMU) { - /* Enable the PGA */ - pwr_reg |= WM8961_SPKL_PGA | WM8961_SPKR_PGA; - wm8961_write(codec, WM8961_PWR_MGMT_2, pwr_reg); - - /* Enable the amplifier */ - spk_reg |= WM8961_SPKL_ENA | WM8961_SPKR_ENA; - wm8961_write(codec, WM8961_CLASS_D_CONTROL_1, spk_reg); - } - - if (event & SND_SOC_DAPM_PRE_PMD) { - /* Enable the amplifier */ - spk_reg &= ~(WM8961_SPKL_ENA | WM8961_SPKR_ENA); - wm8961_write(codec, WM8961_CLASS_D_CONTROL_1, spk_reg); - - /* Enable the PGA */ - pwr_reg &= ~(WM8961_SPKL_PGA | WM8961_SPKR_PGA); - wm8961_write(codec, WM8961_PWR_MGMT_2, pwr_reg); - } - - return 0; -} - -static const char *adc_hpf_text[] = { - "Hi-fi", "Voice 1", "Voice 2", "Voice 3", -}; - -static const struct soc_enum adc_hpf = - SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_2, 7, 4, adc_hpf_text); - -static const char *dac_deemph_text[] = { - "None", "32kHz", "44.1kHz", "48kHz", -}; - -static const struct soc_enum dac_deemph = - SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_1, 1, 4, dac_deemph_text); - -static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); -static const DECLARE_TLV_DB_SCALE(hp_sec_tlv, -700, 100, 0); -static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1); -static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0); -static unsigned int boost_tlv[] = { - TLV_DB_RANGE_HEAD(4), - 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), - 1, 1, TLV_DB_SCALE_ITEM(13, 0, 0), - 2, 2, TLV_DB_SCALE_ITEM(20, 0, 0), - 3, 3, TLV_DB_SCALE_ITEM(29, 0, 0), -}; -static const DECLARE_TLV_DB_SCALE(pga_tlv, -2325, 75, 0); - -static const struct snd_kcontrol_new wm8961_snd_controls[] = { -SOC_DOUBLE_R_TLV("Headphone Volume", WM8961_LOUT1_VOLUME, WM8961_ROUT1_VOLUME, - 0, 127, 0, out_tlv), -SOC_DOUBLE_TLV("Headphone Secondary Volume", WM8961_ANALOGUE_HP_2, - 6, 3, 7, 0, hp_sec_tlv), -SOC_DOUBLE_R("Headphone ZC Switch", WM8961_LOUT1_VOLUME, WM8961_ROUT1_VOLUME, - 7, 1, 0), - -SOC_DOUBLE_R_TLV("Speaker Volume", WM8961_LOUT2_VOLUME, WM8961_ROUT2_VOLUME, - 0, 127, 0, out_tlv), -SOC_DOUBLE_R("Speaker ZC Switch", WM8961_LOUT2_VOLUME, WM8961_ROUT2_VOLUME, - 7, 1, 0), -SOC_SINGLE("Speaker AC Gain", WM8961_CLASS_D_CONTROL_2, 0, 7, 0), - -SOC_SINGLE("DAC x128 OSR Switch", WM8961_ADC_DAC_CONTROL_2, 0, 1, 0), -SOC_ENUM("DAC Deemphasis", dac_deemph), -SOC_SINGLE("DAC Soft Mute Switch", WM8961_ADC_DAC_CONTROL_2, 3, 1, 0), - -SOC_DOUBLE_R_TLV("Sidetone Volume", WM8961_DSP_SIDETONE_0, - WM8961_DSP_SIDETONE_1, 4, 12, 0, sidetone_tlv), - -SOC_SINGLE("ADC High Pass Filter Switch", WM8961_ADC_DAC_CONTROL_1, 0, 1, 0), -SOC_ENUM("ADC High Pass Filter Mode", adc_hpf), - -SOC_DOUBLE_R_TLV("Capture Volume", - WM8961_LEFT_ADC_VOLUME, WM8961_RIGHT_ADC_VOLUME, - 1, 119, 0, adc_tlv), -SOC_DOUBLE_R_TLV("Capture Boost Volume", - WM8961_ADCL_SIGNAL_PATH, WM8961_ADCR_SIGNAL_PATH, - 4, 3, 0, boost_tlv), -SOC_DOUBLE_R_TLV("Capture PGA Volume", - WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME, - 0, 62, 0, pga_tlv), -SOC_DOUBLE_R("Capture PGA ZC Switch", - WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME, - 6, 1, 1), -SOC_DOUBLE_R("Capture PGA Switch", - WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME, - 7, 1, 1), -}; - -static const char *sidetone_text[] = { - "None", "Left", "Right" -}; - -static const struct soc_enum dacl_sidetone = - SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_0, 2, 3, sidetone_text); - -static const struct soc_enum dacr_sidetone = - SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_1, 2, 3, sidetone_text); - -static const struct snd_kcontrol_new dacl_mux = - SOC_DAPM_ENUM("DACL Sidetone", dacl_sidetone); - -static const struct snd_kcontrol_new dacr_mux = - SOC_DAPM_ENUM("DACR Sidetone", dacr_sidetone); - -static const struct snd_soc_dapm_widget wm8961_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("LINPUT"), -SND_SOC_DAPM_INPUT("RINPUT"), - -SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8961_CLOCKING2, 4, 0, NULL, 0), - -SND_SOC_DAPM_PGA("Left Input", WM8961_PWR_MGMT_1, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right Input", WM8961_PWR_MGMT_1, 4, 0, NULL, 0), - -SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", WM8961_PWR_MGMT_1, 3, 0), -SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", WM8961_PWR_MGMT_1, 2, 0), - -SND_SOC_DAPM_MICBIAS("MICBIAS", WM8961_PWR_MGMT_1, 1, 0), - -SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &dacl_mux), -SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &dacr_mux), - -SND_SOC_DAPM_DAC("DACL", "HiFi Playback", WM8961_PWR_MGMT_2, 8, 0), -SND_SOC_DAPM_DAC("DACR", "HiFi Playback", WM8961_PWR_MGMT_2, 7, 0), - -/* Handle as a mono path for DCS */ -SND_SOC_DAPM_PGA_E("Headphone Output", SND_SOC_NOPM, - 4, 0, NULL, 0, wm8961_hp_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), -SND_SOC_DAPM_PGA_E("Speaker Output", SND_SOC_NOPM, - 4, 0, NULL, 0, wm8961_spk_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - -SND_SOC_DAPM_OUTPUT("HP_L"), -SND_SOC_DAPM_OUTPUT("HP_R"), -SND_SOC_DAPM_OUTPUT("SPK_LN"), -SND_SOC_DAPM_OUTPUT("SPK_LP"), -SND_SOC_DAPM_OUTPUT("SPK_RN"), -SND_SOC_DAPM_OUTPUT("SPK_RP"), -}; - - -static const struct snd_soc_dapm_route audio_paths[] = { - { "DACL", NULL, "CLK_DSP" }, - { "DACL", NULL, "DACL Sidetone" }, - { "DACR", NULL, "CLK_DSP" }, - { "DACR", NULL, "DACR Sidetone" }, - - { "DACL Sidetone", "Left", "ADCL" }, - { "DACL Sidetone", "Right", "ADCR" }, - - { "DACR Sidetone", "Left", "ADCL" }, - { "DACR Sidetone", "Right", "ADCR" }, - - { "HP_L", NULL, "Headphone Output" }, - { "HP_R", NULL, "Headphone Output" }, - { "Headphone Output", NULL, "DACL" }, - { "Headphone Output", NULL, "DACR" }, - - { "SPK_LN", NULL, "Speaker Output" }, - { "SPK_LP", NULL, "Speaker Output" }, - { "SPK_RN", NULL, "Speaker Output" }, - { "SPK_RP", NULL, "Speaker Output" }, - - { "Speaker Output", NULL, "DACL" }, - { "Speaker Output", NULL, "DACR" }, - - { "ADCL", NULL, "Left Input" }, - { "ADCL", NULL, "CLK_DSP" }, - { "ADCR", NULL, "Right Input" }, - { "ADCR", NULL, "CLK_DSP" }, - - { "Left Input", NULL, "LINPUT" }, - { "Right Input", NULL, "RINPUT" }, - -}; - -/* Values for CLK_SYS_RATE */ -static struct { - int ratio; - u16 val; -} wm8961_clk_sys_ratio[] = { - { 64, 0 }, - { 128, 1 }, - { 192, 2 }, - { 256, 3 }, - { 384, 4 }, - { 512, 5 }, - { 768, 6 }, - { 1024, 7 }, - { 1408, 8 }, - { 1536, 9 }, -}; - -/* Values for SAMPLE_RATE */ -static struct { - int rate; - u16 val; -} wm8961_srate[] = { - { 48000, 0 }, - { 44100, 0 }, - { 32000, 1 }, - { 22050, 2 }, - { 24000, 2 }, - { 16000, 3 }, - { 11250, 4 }, - { 12000, 4 }, - { 8000, 5 }, -}; - -static int wm8961_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 wm8961_priv *wm8961 = codec->private_data; - int i, best, target, fs; - u16 reg; - - fs = params_rate(params); - - if (!wm8961->sysclk) { - dev_err(codec->dev, "MCLK has not been specified\n"); - return -EINVAL; - } - - /* Find the closest sample rate for the filters */ - best = 0; - for (i = 0; i < ARRAY_SIZE(wm8961_srate); i++) { - if (abs(wm8961_srate[i].rate - fs) < - abs(wm8961_srate[best].rate - fs)) - best = i; - } - reg = wm8961_read(codec, WM8961_ADDITIONAL_CONTROL_3); - reg &= ~WM8961_SAMPLE_RATE_MASK; - reg |= wm8961_srate[best].val; - wm8961_write(codec, WM8961_ADDITIONAL_CONTROL_3, reg); - dev_dbg(codec->dev, "Selected SRATE %dHz for %dHz\n", - wm8961_srate[best].rate, fs); - - /* Select a CLK_SYS/fs ratio equal to or higher than required */ - target = wm8961->sysclk / fs; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && target < 64) { - dev_err(codec->dev, - "SYSCLK must be at least 64*fs for DAC\n"); - return -EINVAL; - } - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && target < 256) { - dev_err(codec->dev, - "SYSCLK must be at least 256*fs for ADC\n"); - return -EINVAL; - } - - for (i = 0; i < ARRAY_SIZE(wm8961_clk_sys_ratio); i++) { - if (wm8961_clk_sys_ratio[i].ratio >= target) - break; - } - if (i == ARRAY_SIZE(wm8961_clk_sys_ratio)) { - dev_err(codec->dev, "Unable to generate CLK_SYS_RATE\n"); - return -EINVAL; - } - dev_dbg(codec->dev, "Selected CLK_SYS_RATE of %d for %d/%d=%d\n", - wm8961_clk_sys_ratio[i].ratio, wm8961->sysclk, fs, - wm8961->sysclk / fs); - - reg = wm8961_read(codec, WM8961_CLOCKING_4); - reg &= ~WM8961_CLK_SYS_RATE_MASK; - reg |= wm8961_clk_sys_ratio[i].val << WM8961_CLK_SYS_RATE_SHIFT; - wm8961_write(codec, WM8961_CLOCKING_4, reg); - - reg = wm8961_read(codec, WM8961_AUDIO_INTERFACE_0); - reg &= ~WM8961_WL_MASK; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - reg |= 1 << WM8961_WL_SHIFT; - break; - case SNDRV_PCM_FORMAT_S24_LE: - reg |= 2 << WM8961_WL_SHIFT; - break; - case SNDRV_PCM_FORMAT_S32_LE: - reg |= 3 << WM8961_WL_SHIFT; - break; - default: - return -EINVAL; - } - wm8961_write(codec, WM8961_AUDIO_INTERFACE_0, reg); - - /* Sloping stop-band filter is recommended for <= 24kHz */ - reg = wm8961_read(codec, WM8961_ADC_DAC_CONTROL_2); - if (fs <= 24000) - reg |= WM8961_DACSLOPE; - else - reg &= WM8961_DACSLOPE; - wm8961_write(codec, WM8961_ADC_DAC_CONTROL_2, reg); - - return 0; -} - -static int wm8961_set_sysclk(struct snd_soc_dai *dai, int clk_id, - unsigned int freq, - int dir) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8961_priv *wm8961 = codec->private_data; - u16 reg = wm8961_read(codec, WM8961_CLOCKING1); - - if (freq > 33000000) { - dev_err(codec->dev, "MCLK must be <33MHz\n"); - return -EINVAL; - } - - if (freq > 16500000) { - dev_dbg(codec->dev, "Using MCLK/2 for %dHz MCLK\n", freq); - reg |= WM8961_MCLKDIV; - freq /= 2; - } else { - dev_dbg(codec->dev, "Using MCLK/1 for %dHz MCLK\n", freq); - reg &= WM8961_MCLKDIV; - } - - wm8961_write(codec, WM8961_CLOCKING1, reg); - - wm8961->sysclk = freq; - - return 0; -} - -static int wm8961_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - u16 aif = wm8961_read(codec, WM8961_AUDIO_INTERFACE_0); - - aif &= ~(WM8961_BCLKINV | WM8961_LRP | - WM8961_MS | WM8961_FORMAT_MASK); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - aif |= WM8961_MS; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_RIGHT_J: - break; - - case SND_SOC_DAIFMT_LEFT_J: - aif |= 1; - break; - - case SND_SOC_DAIFMT_I2S: - aif |= 2; - break; - - case SND_SOC_DAIFMT_DSP_B: - aif |= WM8961_LRP; - case SND_SOC_DAIFMT_DSP_A: - aif |= 3; - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - case SND_SOC_DAIFMT_IB_NF: - break; - default: - return -EINVAL; - } - break; - - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_NB_IF: - aif |= WM8961_LRP; - break; - case SND_SOC_DAIFMT_IB_NF: - aif |= WM8961_BCLKINV; - break; - case SND_SOC_DAIFMT_IB_IF: - aif |= WM8961_BCLKINV | WM8961_LRP; - break; - default: - return -EINVAL; - } - - return wm8961_write(codec, WM8961_AUDIO_INTERFACE_0, aif); -} - -static int wm8961_set_tristate(struct snd_soc_dai *dai, int tristate) -{ - struct snd_soc_codec *codec = dai->codec; - u16 reg = wm8961_read(codec, WM8961_ADDITIONAL_CONTROL_2); - - if (tristate) - reg |= WM8961_TRIS; - else - reg &= ~WM8961_TRIS; - - return wm8961_write(codec, WM8961_ADDITIONAL_CONTROL_2, reg); -} - -static int wm8961_digital_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 reg = wm8961_read(codec, WM8961_ADC_DAC_CONTROL_1); - - if (mute) - reg |= WM8961_DACMU; - else - reg &= ~WM8961_DACMU; - - msleep(17); - - return wm8961_write(codec, WM8961_ADC_DAC_CONTROL_1, reg); -} - -static int wm8961_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) -{ - struct snd_soc_codec *codec = dai->codec; - u16 reg; - - switch (div_id) { - case WM8961_BCLK: - reg = wm8961_read(codec, WM8961_CLOCKING2); - reg &= ~WM8961_BCLKDIV_MASK; - reg |= div; - wm8961_write(codec, WM8961_CLOCKING2, reg); - break; - - case WM8961_LRCLK: - reg = wm8961_read(codec, WM8961_AUDIO_INTERFACE_2); - reg &= ~WM8961_LRCLK_RATE_MASK; - reg |= div; - wm8961_write(codec, WM8961_AUDIO_INTERFACE_2, reg); - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int wm8961_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u16 reg; - - /* This is all slightly unusual since we have no bypass paths - * and the output amplifier structure means we can just slam - * the biases straight up rather than having to ramp them - * slowly. - */ - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - if (codec->bias_level == SND_SOC_BIAS_STANDBY) { - /* Enable bias generation */ - reg = wm8961_read(codec, WM8961_ANTI_POP); - reg |= WM8961_BUFIOEN | WM8961_BUFDCOPEN; - wm8961_write(codec, WM8961_ANTI_POP, reg); - - /* VMID=2*50k, VREF */ - reg = wm8961_read(codec, WM8961_PWR_MGMT_1); - reg &= ~WM8961_VMIDSEL_MASK; - reg |= (1 << WM8961_VMIDSEL_SHIFT) | WM8961_VREF; - wm8961_write(codec, WM8961_PWR_MGMT_1, reg); - } - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->bias_level == SND_SOC_BIAS_PREPARE) { - /* VREF off */ - reg = wm8961_read(codec, WM8961_PWR_MGMT_1); - reg &= ~WM8961_VREF; - wm8961_write(codec, WM8961_PWR_MGMT_1, reg); - - /* Bias generation off */ - reg = wm8961_read(codec, WM8961_ANTI_POP); - reg &= ~(WM8961_BUFIOEN | WM8961_BUFDCOPEN); - wm8961_write(codec, WM8961_ANTI_POP, reg); - - /* VMID off */ - reg = wm8961_read(codec, WM8961_PWR_MGMT_1); - reg &= ~WM8961_VMIDSEL_MASK; - wm8961_write(codec, WM8961_PWR_MGMT_1, reg); - } - break; - - case SND_SOC_BIAS_OFF: - break; - } - - codec->bias_level = level; - - return 0; -} - - -#define WM8961_RATES SNDRV_PCM_RATE_8000_48000 - -#define WM8961_FORMATS \ - (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_LE) - -static struct snd_soc_dai_ops wm8961_dai_ops = { - .hw_params = wm8961_hw_params, - .set_sysclk = wm8961_set_sysclk, - .set_fmt = wm8961_set_fmt, - .digital_mute = wm8961_digital_mute, - .set_tristate = wm8961_set_tristate, - .set_clkdiv = wm8961_set_clkdiv, -}; - -struct snd_soc_dai wm8961_dai = { - .name = "WM8961", - .playback = { - .stream_name = "HiFi Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8961_RATES, - .formats = WM8961_FORMATS,}, - .capture = { - .stream_name = "HiFi Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8961_RATES, - .formats = WM8961_FORMATS,}, - .ops = &wm8961_dai_ops, -}; -EXPORT_SYMBOL_GPL(wm8961_dai); - - -static struct snd_soc_codec *wm8961_codec; - -static int wm8961_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (wm8961_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8961_codec; - codec = wm8961_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, wm8961_snd_controls, - ARRAY_SIZE(wm8961_snd_controls)); - snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets, - ARRAY_SIZE(wm8961_dapm_widgets)); - snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); - snd_soc_dapm_new_widgets(codec); - - 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; -} - -static int wm8961_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 wm8961_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; - - wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int wm8961_resume(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - u16 *reg_cache = codec->reg_cache; - int i; - - for (i = 0; i < codec->reg_cache_size; i++) { - if (i == WM8961_SOFTWARE_RESET) - continue; - - wm8961_write(codec, i, reg_cache[i]); - } - - wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} -#else -#define wm8961_suspend NULL -#define wm8961_resume NULL -#endif - -struct snd_soc_codec_device soc_codec_dev_wm8961 = { - .probe = wm8961_probe, - .remove = wm8961_remove, - .suspend = wm8961_suspend, - .resume = wm8961_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8961); - -static int wm8961_register(struct wm8961_priv *wm8961) -{ - struct snd_soc_codec *codec = &wm8961->codec; - int ret; - u16 reg; - - if (wm8961_codec) { - dev_err(codec->dev, "Another WM8961 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 = wm8961; - codec->name = "WM8961"; - codec->owner = THIS_MODULE; - codec->read = wm8961_read; - codec->write = wm8961_write; - codec->dai = &wm8961_dai; - codec->num_dai = 1; - codec->reg_cache_size = ARRAY_SIZE(wm8961->reg_cache); - codec->reg_cache = &wm8961->reg_cache; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8961_set_bias_level; - - memcpy(codec->reg_cache, wm8961_reg_defaults, - sizeof(wm8961_reg_defaults)); - - reg = wm8961_read_hw(codec, WM8961_SOFTWARE_RESET); - if (reg != 0x1801) { - dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg); - ret = -EINVAL; - goto err; - } - - reg = wm8961_read_hw(codec, WM8961_RIGHT_INPUT_VOLUME); - dev_info(codec->dev, "WM8961 family %d revision %c\n", - (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT, - ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT) - + 'A'); - - ret = wm8961_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - return ret; - } - - /* Enable class W */ - reg = wm8961_read(codec, WM8961_CHARGE_PUMP_B); - reg |= WM8961_CP_DYN_PWR_MASK; - wm8961_write(codec, WM8961_CHARGE_PUMP_B, reg); - - /* Latch volume update bits (right channel only, we always - * write both out) and default ZC on. */ - reg = wm8961_read(codec, WM8961_ROUT1_VOLUME); - wm8961_write(codec, WM8961_ROUT1_VOLUME, - reg | WM8961_LO1ZC | WM8961_OUT1VU); - wm8961_write(codec, WM8961_LOUT1_VOLUME, reg | WM8961_LO1ZC); - reg = wm8961_read(codec, WM8961_ROUT2_VOLUME); - wm8961_write(codec, WM8961_ROUT2_VOLUME, - reg | WM8961_SPKRZC | WM8961_SPKVU); - wm8961_write(codec, WM8961_LOUT2_VOLUME, reg | WM8961_SPKLZC); - - reg = wm8961_read(codec, WM8961_RIGHT_ADC_VOLUME); - wm8961_write(codec, WM8961_RIGHT_ADC_VOLUME, reg | WM8961_ADCVU); - reg = wm8961_read(codec, WM8961_RIGHT_INPUT_VOLUME); - wm8961_write(codec, WM8961_RIGHT_INPUT_VOLUME, reg | WM8961_IPVU); - - /* Use soft mute by default */ - reg = wm8961_read(codec, WM8961_ADC_DAC_CONTROL_2); - reg |= WM8961_DACSMM; - wm8961_write(codec, WM8961_ADC_DAC_CONTROL_2, reg); - - /* Use automatic clocking mode by default; for now this is all - * we support. - */ - reg = wm8961_read(codec, WM8961_CLOCKING_3); - reg &= ~WM8961_MANUAL_MODE; - wm8961_write(codec, WM8961_CLOCKING_3, reg); - - wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - wm8961_dai.dev = codec->dev; - - wm8961_codec = 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(&wm8961_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); - return ret; - } - - return 0; - -err: - kfree(wm8961); - return ret; -} - -static void wm8961_unregister(struct wm8961_priv *wm8961) -{ - wm8961_set_bias_level(&wm8961->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dai(&wm8961_dai); - snd_soc_unregister_codec(&wm8961->codec); - kfree(wm8961); - wm8961_codec = NULL; -} - -static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8961_priv *wm8961; - struct snd_soc_codec *codec; - - wm8961 = kzalloc(sizeof(struct wm8961_priv), GFP_KERNEL); - if (wm8961 == NULL) - return -ENOMEM; - - codec = &wm8961->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - - i2c_set_clientdata(i2c, wm8961); - codec->control_data = i2c; - - codec->dev = &i2c->dev; - - return wm8961_register(wm8961); -} - -static __devexit int wm8961_i2c_remove(struct i2c_client *client) -{ - struct wm8961_priv *wm8961 = i2c_get_clientdata(client); - wm8961_unregister(wm8961); - return 0; -} - -#ifdef CONFIG_PM -static int wm8961_i2c_suspend(struct i2c_client *client, pm_message_t state) -{ - return snd_soc_suspend_device(&client->dev); -} - -static int wm8961_i2c_resume(struct i2c_client *client) -{ - return snd_soc_resume_device(&client->dev); -} -#else -#define wm8961_i2c_suspend NULL -#define wm8961_i2c_resume NULL -#endif - -static const struct i2c_device_id wm8961_i2c_id[] = { - { "wm8961", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id); - -static struct i2c_driver wm8961_i2c_driver = { - .driver = { - .name = "wm8961", - .owner = THIS_MODULE, - }, - .probe = wm8961_i2c_probe, - .remove = __devexit_p(wm8961_i2c_remove), - .suspend = wm8961_i2c_suspend, - .resume = wm8961_i2c_resume, - .id_table = wm8961_i2c_id, -}; - -static int __init wm8961_modinit(void) -{ - int ret; - - ret = i2c_add_driver(&wm8961_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8961 I2C driver: %d\n", - ret); - } - - return ret; -} -module_init(wm8961_modinit); - -static void __exit wm8961_exit(void) -{ - i2c_del_driver(&wm8961_i2c_driver); -} -module_exit(wm8961_exit); - - -MODULE_DESCRIPTION("ASoC WM8961 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/codecs/wm8961.h b/trunk/sound/soc/codecs/wm8961.h deleted file mode 100644 index 5513bfd720d6..000000000000 --- a/trunk/sound/soc/codecs/wm8961.h +++ /dev/null @@ -1,866 +0,0 @@ -/* - * wm8961.h -- WM8961 Soc Audio driver - * - * 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 _WM8961_H -#define _WM8961_H - -#include - -extern struct snd_soc_codec_device soc_codec_dev_wm8961; -extern struct snd_soc_dai wm8961_dai; - -#define WM8961_BCLK 1 -#define WM8961_LRCLK 2 - -#define WM8961_BCLK_DIV_1 0 -#define WM8961_BCLK_DIV_1_5 1 -#define WM8961_BCLK_DIV_2 2 -#define WM8961_BCLK_DIV_3 3 -#define WM8961_BCLK_DIV_4 4 -#define WM8961_BCLK_DIV_5_5 5 -#define WM8961_BCLK_DIV_6 6 -#define WM8961_BCLK_DIV_8 7 -#define WM8961_BCLK_DIV_11 8 -#define WM8961_BCLK_DIV_12 9 -#define WM8961_BCLK_DIV_16 10 -#define WM8961_BCLK_DIV_24 11 -#define WM8961_BCLK_DIV_32 13 - - -/* - * Register values. - */ -#define WM8961_LEFT_INPUT_VOLUME 0x00 -#define WM8961_RIGHT_INPUT_VOLUME 0x01 -#define WM8961_LOUT1_VOLUME 0x02 -#define WM8961_ROUT1_VOLUME 0x03 -#define WM8961_CLOCKING1 0x04 -#define WM8961_ADC_DAC_CONTROL_1 0x05 -#define WM8961_ADC_DAC_CONTROL_2 0x06 -#define WM8961_AUDIO_INTERFACE_0 0x07 -#define WM8961_CLOCKING2 0x08 -#define WM8961_AUDIO_INTERFACE_1 0x09 -#define WM8961_LEFT_DAC_VOLUME 0x0A -#define WM8961_RIGHT_DAC_VOLUME 0x0B -#define WM8961_AUDIO_INTERFACE_2 0x0E -#define WM8961_SOFTWARE_RESET 0x0F -#define WM8961_ALC1 0x11 -#define WM8961_ALC2 0x12 -#define WM8961_ALC3 0x13 -#define WM8961_NOISE_GATE 0x14 -#define WM8961_LEFT_ADC_VOLUME 0x15 -#define WM8961_RIGHT_ADC_VOLUME 0x16 -#define WM8961_ADDITIONAL_CONTROL_1 0x17 -#define WM8961_ADDITIONAL_CONTROL_2 0x18 -#define WM8961_PWR_MGMT_1 0x19 -#define WM8961_PWR_MGMT_2 0x1A -#define WM8961_ADDITIONAL_CONTROL_3 0x1B -#define WM8961_ANTI_POP 0x1C -#define WM8961_CLOCKING_3 0x1E -#define WM8961_ADCL_SIGNAL_PATH 0x20 -#define WM8961_ADCR_SIGNAL_PATH 0x21 -#define WM8961_LOUT2_VOLUME 0x28 -#define WM8961_ROUT2_VOLUME 0x29 -#define WM8961_PWR_MGMT_3 0x2F -#define WM8961_ADDITIONAL_CONTROL_4 0x30 -#define WM8961_CLASS_D_CONTROL_1 0x31 -#define WM8961_CLASS_D_CONTROL_2 0x33 -#define WM8961_CLOCKING_4 0x38 -#define WM8961_DSP_SIDETONE_0 0x39 -#define WM8961_DSP_SIDETONE_1 0x3A -#define WM8961_DC_SERVO_0 0x3C -#define WM8961_DC_SERVO_1 0x3D -#define WM8961_DC_SERVO_3 0x3F -#define WM8961_DC_SERVO_5 0x41 -#define WM8961_ANALOGUE_PGA_BIAS 0x44 -#define WM8961_ANALOGUE_HP_0 0x45 -#define WM8961_ANALOGUE_HP_2 0x47 -#define WM8961_CHARGE_PUMP_1 0x48 -#define WM8961_CHARGE_PUMP_B 0x52 -#define WM8961_WRITE_SEQUENCER_1 0x57 -#define WM8961_WRITE_SEQUENCER_2 0x58 -#define WM8961_WRITE_SEQUENCER_3 0x59 -#define WM8961_WRITE_SEQUENCER_4 0x5A -#define WM8961_WRITE_SEQUENCER_5 0x5B -#define WM8961_WRITE_SEQUENCER_6 0x5C -#define WM8961_WRITE_SEQUENCER_7 0x5D -#define WM8961_GENERAL_TEST_1 0xFC - - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - Left Input volume - */ -#define WM8961_IPVU 0x0100 /* IPVU */ -#define WM8961_IPVU_MASK 0x0100 /* IPVU */ -#define WM8961_IPVU_SHIFT 8 /* IPVU */ -#define WM8961_IPVU_WIDTH 1 /* IPVU */ -#define WM8961_LINMUTE 0x0080 /* LINMUTE */ -#define WM8961_LINMUTE_MASK 0x0080 /* LINMUTE */ -#define WM8961_LINMUTE_SHIFT 7 /* LINMUTE */ -#define WM8961_LINMUTE_WIDTH 1 /* LINMUTE */ -#define WM8961_LIZC 0x0040 /* LIZC */ -#define WM8961_LIZC_MASK 0x0040 /* LIZC */ -#define WM8961_LIZC_SHIFT 6 /* LIZC */ -#define WM8961_LIZC_WIDTH 1 /* LIZC */ -#define WM8961_LINVOL_MASK 0x003F /* LINVOL - [5:0] */ -#define WM8961_LINVOL_SHIFT 0 /* LINVOL - [5:0] */ -#define WM8961_LINVOL_WIDTH 6 /* LINVOL - [5:0] */ - -/* - * R1 (0x01) - Right Input volume - */ -#define WM8961_DEVICE_ID_MASK 0xF000 /* DEVICE_ID - [15:12] */ -#define WM8961_DEVICE_ID_SHIFT 12 /* DEVICE_ID - [15:12] */ -#define WM8961_DEVICE_ID_WIDTH 4 /* DEVICE_ID - [15:12] */ -#define WM8961_CHIP_REV_MASK 0x0E00 /* CHIP_REV - [11:9] */ -#define WM8961_CHIP_REV_SHIFT 9 /* CHIP_REV - [11:9] */ -#define WM8961_CHIP_REV_WIDTH 3 /* CHIP_REV - [11:9] */ -#define WM8961_IPVU 0x0100 /* IPVU */ -#define WM8961_IPVU_MASK 0x0100 /* IPVU */ -#define WM8961_IPVU_SHIFT 8 /* IPVU */ -#define WM8961_IPVU_WIDTH 1 /* IPVU */ -#define WM8961_RINMUTE 0x0080 /* RINMUTE */ -#define WM8961_RINMUTE_MASK 0x0080 /* RINMUTE */ -#define WM8961_RINMUTE_SHIFT 7 /* RINMUTE */ -#define WM8961_RINMUTE_WIDTH 1 /* RINMUTE */ -#define WM8961_RIZC 0x0040 /* RIZC */ -#define WM8961_RIZC_MASK 0x0040 /* RIZC */ -#define WM8961_RIZC_SHIFT 6 /* RIZC */ -#define WM8961_RIZC_WIDTH 1 /* RIZC */ -#define WM8961_RINVOL_MASK 0x003F /* RINVOL - [5:0] */ -#define WM8961_RINVOL_SHIFT 0 /* RINVOL - [5:0] */ -#define WM8961_RINVOL_WIDTH 6 /* RINVOL - [5:0] */ - -/* - * R2 (0x02) - LOUT1 volume - */ -#define WM8961_OUT1VU 0x0100 /* OUT1VU */ -#define WM8961_OUT1VU_MASK 0x0100 /* OUT1VU */ -#define WM8961_OUT1VU_SHIFT 8 /* OUT1VU */ -#define WM8961_OUT1VU_WIDTH 1 /* OUT1VU */ -#define WM8961_LO1ZC 0x0080 /* LO1ZC */ -#define WM8961_LO1ZC_MASK 0x0080 /* LO1ZC */ -#define WM8961_LO1ZC_SHIFT 7 /* LO1ZC */ -#define WM8961_LO1ZC_WIDTH 1 /* LO1ZC */ -#define WM8961_LOUT1VOL_MASK 0x007F /* LOUT1VOL - [6:0] */ -#define WM8961_LOUT1VOL_SHIFT 0 /* LOUT1VOL - [6:0] */ -#define WM8961_LOUT1VOL_WIDTH 7 /* LOUT1VOL - [6:0] */ - -/* - * R3 (0x03) - ROUT1 volume - */ -#define WM8961_OUT1VU 0x0100 /* OUT1VU */ -#define WM8961_OUT1VU_MASK 0x0100 /* OUT1VU */ -#define WM8961_OUT1VU_SHIFT 8 /* OUT1VU */ -#define WM8961_OUT1VU_WIDTH 1 /* OUT1VU */ -#define WM8961_RO1ZC 0x0080 /* RO1ZC */ -#define WM8961_RO1ZC_MASK 0x0080 /* RO1ZC */ -#define WM8961_RO1ZC_SHIFT 7 /* RO1ZC */ -#define WM8961_RO1ZC_WIDTH 1 /* RO1ZC */ -#define WM8961_ROUT1VOL_MASK 0x007F /* ROUT1VOL - [6:0] */ -#define WM8961_ROUT1VOL_SHIFT 0 /* ROUT1VOL - [6:0] */ -#define WM8961_ROUT1VOL_WIDTH 7 /* ROUT1VOL - [6:0] */ - -/* - * R4 (0x04) - Clocking1 - */ -#define WM8961_ADCDIV_MASK 0x01C0 /* ADCDIV - [8:6] */ -#define WM8961_ADCDIV_SHIFT 6 /* ADCDIV - [8:6] */ -#define WM8961_ADCDIV_WIDTH 3 /* ADCDIV - [8:6] */ -#define WM8961_DACDIV_MASK 0x0038 /* DACDIV - [5:3] */ -#define WM8961_DACDIV_SHIFT 3 /* DACDIV - [5:3] */ -#define WM8961_DACDIV_WIDTH 3 /* DACDIV - [5:3] */ -#define WM8961_MCLKDIV 0x0004 /* MCLKDIV */ -#define WM8961_MCLKDIV_MASK 0x0004 /* MCLKDIV */ -#define WM8961_MCLKDIV_SHIFT 2 /* MCLKDIV */ -#define WM8961_MCLKDIV_WIDTH 1 /* MCLKDIV */ - -/* - * R5 (0x05) - ADC & DAC Control 1 - */ -#define WM8961_ADCPOL_MASK 0x0060 /* ADCPOL - [6:5] */ -#define WM8961_ADCPOL_SHIFT 5 /* ADCPOL - [6:5] */ -#define WM8961_ADCPOL_WIDTH 2 /* ADCPOL - [6:5] */ -#define WM8961_DACMU 0x0008 /* DACMU */ -#define WM8961_DACMU_MASK 0x0008 /* DACMU */ -#define WM8961_DACMU_SHIFT 3 /* DACMU */ -#define WM8961_DACMU_WIDTH 1 /* DACMU */ -#define WM8961_DEEMPH_MASK 0x0006 /* DEEMPH - [2:1] */ -#define WM8961_DEEMPH_SHIFT 1 /* DEEMPH - [2:1] */ -#define WM8961_DEEMPH_WIDTH 2 /* DEEMPH - [2:1] */ -#define WM8961_ADCHPD 0x0001 /* ADCHPD */ -#define WM8961_ADCHPD_MASK 0x0001 /* ADCHPD */ -#define WM8961_ADCHPD_SHIFT 0 /* ADCHPD */ -#define WM8961_ADCHPD_WIDTH 1 /* ADCHPD */ - -/* - * R6 (0x06) - ADC & DAC Control 2 - */ -#define WM8961_ADC_HPF_CUT_MASK 0x0180 /* ADC_HPF_CUT - [8:7] */ -#define WM8961_ADC_HPF_CUT_SHIFT 7 /* ADC_HPF_CUT - [8:7] */ -#define WM8961_ADC_HPF_CUT_WIDTH 2 /* ADC_HPF_CUT - [8:7] */ -#define WM8961_DACPOL_MASK 0x0060 /* DACPOL - [6:5] */ -#define WM8961_DACPOL_SHIFT 5 /* DACPOL - [6:5] */ -#define WM8961_DACPOL_WIDTH 2 /* DACPOL - [6:5] */ -#define WM8961_DACSMM 0x0008 /* DACSMM */ -#define WM8961_DACSMM_MASK 0x0008 /* DACSMM */ -#define WM8961_DACSMM_SHIFT 3 /* DACSMM */ -#define WM8961_DACSMM_WIDTH 1 /* DACSMM */ -#define WM8961_DACMR 0x0004 /* DACMR */ -#define WM8961_DACMR_MASK 0x0004 /* DACMR */ -#define WM8961_DACMR_SHIFT 2 /* DACMR */ -#define WM8961_DACMR_WIDTH 1 /* DACMR */ -#define WM8961_DACSLOPE 0x0002 /* DACSLOPE */ -#define WM8961_DACSLOPE_MASK 0x0002 /* DACSLOPE */ -#define WM8961_DACSLOPE_SHIFT 1 /* DACSLOPE */ -#define WM8961_DACSLOPE_WIDTH 1 /* DACSLOPE */ -#define WM8961_DAC_OSR128 0x0001 /* DAC_OSR128 */ -#define WM8961_DAC_OSR128_MASK 0x0001 /* DAC_OSR128 */ -#define WM8961_DAC_OSR128_SHIFT 0 /* DAC_OSR128 */ -#define WM8961_DAC_OSR128_WIDTH 1 /* DAC_OSR128 */ - -/* - * R7 (0x07) - Audio Interface 0 - */ -#define WM8961_ALRSWAP 0x0100 /* ALRSWAP */ -#define WM8961_ALRSWAP_MASK 0x0100 /* ALRSWAP */ -#define WM8961_ALRSWAP_SHIFT 8 /* ALRSWAP */ -#define WM8961_ALRSWAP_WIDTH 1 /* ALRSWAP */ -#define WM8961_BCLKINV 0x0080 /* BCLKINV */ -#define WM8961_BCLKINV_MASK 0x0080 /* BCLKINV */ -#define WM8961_BCLKINV_SHIFT 7 /* BCLKINV */ -#define WM8961_BCLKINV_WIDTH 1 /* BCLKINV */ -#define WM8961_MS 0x0040 /* MS */ -#define WM8961_MS_MASK 0x0040 /* MS */ -#define WM8961_MS_SHIFT 6 /* MS */ -#define WM8961_MS_WIDTH 1 /* MS */ -#define WM8961_DLRSWAP 0x0020 /* DLRSWAP */ -#define WM8961_DLRSWAP_MASK 0x0020 /* DLRSWAP */ -#define WM8961_DLRSWAP_SHIFT 5 /* DLRSWAP */ -#define WM8961_DLRSWAP_WIDTH 1 /* DLRSWAP */ -#define WM8961_LRP 0x0010 /* LRP */ -#define WM8961_LRP_MASK 0x0010 /* LRP */ -#define WM8961_LRP_SHIFT 4 /* LRP */ -#define WM8961_LRP_WIDTH 1 /* LRP */ -#define WM8961_WL_MASK 0x000C /* WL - [3:2] */ -#define WM8961_WL_SHIFT 2 /* WL - [3:2] */ -#define WM8961_WL_WIDTH 2 /* WL - [3:2] */ -#define WM8961_FORMAT_MASK 0x0003 /* FORMAT - [1:0] */ -#define WM8961_FORMAT_SHIFT 0 /* FORMAT - [1:0] */ -#define WM8961_FORMAT_WIDTH 2 /* FORMAT - [1:0] */ - -/* - * R8 (0x08) - Clocking2 - */ -#define WM8961_DCLKDIV_MASK 0x01C0 /* DCLKDIV - [8:6] */ -#define WM8961_DCLKDIV_SHIFT 6 /* DCLKDIV - [8:6] */ -#define WM8961_DCLKDIV_WIDTH 3 /* DCLKDIV - [8:6] */ -#define WM8961_CLK_SYS_ENA 0x0020 /* CLK_SYS_ENA */ -#define WM8961_CLK_SYS_ENA_MASK 0x0020 /* CLK_SYS_ENA */ -#define WM8961_CLK_SYS_ENA_SHIFT 5 /* CLK_SYS_ENA */ -#define WM8961_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */ -#define WM8961_CLK_DSP_ENA 0x0010 /* CLK_DSP_ENA */ -#define WM8961_CLK_DSP_ENA_MASK 0x0010 /* CLK_DSP_ENA */ -#define WM8961_CLK_DSP_ENA_SHIFT 4 /* CLK_DSP_ENA */ -#define WM8961_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */ -#define WM8961_BCLKDIV_MASK 0x000F /* BCLKDIV - [3:0] */ -#define WM8961_BCLKDIV_SHIFT 0 /* BCLKDIV - [3:0] */ -#define WM8961_BCLKDIV_WIDTH 4 /* BCLKDIV - [3:0] */ - -/* - * R9 (0x09) - Audio Interface 1 - */ -#define WM8961_DACCOMP_MASK 0x0018 /* DACCOMP - [4:3] */ -#define WM8961_DACCOMP_SHIFT 3 /* DACCOMP - [4:3] */ -#define WM8961_DACCOMP_WIDTH 2 /* DACCOMP - [4:3] */ -#define WM8961_ADCCOMP_MASK 0x0006 /* ADCCOMP - [2:1] */ -#define WM8961_ADCCOMP_SHIFT 1 /* ADCCOMP - [2:1] */ -#define WM8961_ADCCOMP_WIDTH 2 /* ADCCOMP - [2:1] */ -#define WM8961_LOOPBACK 0x0001 /* LOOPBACK */ -#define WM8961_LOOPBACK_MASK 0x0001 /* LOOPBACK */ -#define WM8961_LOOPBACK_SHIFT 0 /* LOOPBACK */ -#define WM8961_LOOPBACK_WIDTH 1 /* LOOPBACK */ - -/* - * R10 (0x0A) - Left DAC volume - */ -#define WM8961_DACVU 0x0100 /* DACVU */ -#define WM8961_DACVU_MASK 0x0100 /* DACVU */ -#define WM8961_DACVU_SHIFT 8 /* DACVU */ -#define WM8961_DACVU_WIDTH 1 /* DACVU */ -#define WM8961_LDACVOL_MASK 0x00FF /* LDACVOL - [7:0] */ -#define WM8961_LDACVOL_SHIFT 0 /* LDACVOL - [7:0] */ -#define WM8961_LDACVOL_WIDTH 8 /* LDACVOL - [7:0] */ - -/* - * R11 (0x0B) - Right DAC volume - */ -#define WM8961_DACVU 0x0100 /* DACVU */ -#define WM8961_DACVU_MASK 0x0100 /* DACVU */ -#define WM8961_DACVU_SHIFT 8 /* DACVU */ -#define WM8961_DACVU_WIDTH 1 /* DACVU */ -#define WM8961_RDACVOL_MASK 0x00FF /* RDACVOL - [7:0] */ -#define WM8961_RDACVOL_SHIFT 0 /* RDACVOL - [7:0] */ -#define WM8961_RDACVOL_WIDTH 8 /* RDACVOL - [7:0] */ - -/* - * R14 (0x0E) - Audio Interface 2 - */ -#define WM8961_LRCLK_RATE_MASK 0x01FF /* LRCLK_RATE - [8:0] */ -#define WM8961_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [8:0] */ -#define WM8961_LRCLK_RATE_WIDTH 9 /* LRCLK_RATE - [8:0] */ - -/* - * R15 (0x0F) - Software Reset - */ -#define WM8961_SW_RST_DEV_ID1_MASK 0xFFFF /* SW_RST_DEV_ID1 - [15:0] */ -#define WM8961_SW_RST_DEV_ID1_SHIFT 0 /* SW_RST_DEV_ID1 - [15:0] */ -#define WM8961_SW_RST_DEV_ID1_WIDTH 16 /* SW_RST_DEV_ID1 - [15:0] */ - -/* - * R17 (0x11) - ALC1 - */ -#define WM8961_ALCSEL_MASK 0x0180 /* ALCSEL - [8:7] */ -#define WM8961_ALCSEL_SHIFT 7 /* ALCSEL - [8:7] */ -#define WM8961_ALCSEL_WIDTH 2 /* ALCSEL - [8:7] */ -#define WM8961_MAXGAIN_MASK 0x0070 /* MAXGAIN - [6:4] */ -#define WM8961_MAXGAIN_SHIFT 4 /* MAXGAIN - [6:4] */ -#define WM8961_MAXGAIN_WIDTH 3 /* MAXGAIN - [6:4] */ -#define WM8961_ALCL_MASK 0x000F /* ALCL - [3:0] */ -#define WM8961_ALCL_SHIFT 0 /* ALCL - [3:0] */ -#define WM8961_ALCL_WIDTH 4 /* ALCL - [3:0] */ - -/* - * R18 (0x12) - ALC2 - */ -#define WM8961_ALCZC 0x0080 /* ALCZC */ -#define WM8961_ALCZC_MASK 0x0080 /* ALCZC */ -#define WM8961_ALCZC_SHIFT 7 /* ALCZC */ -#define WM8961_ALCZC_WIDTH 1 /* ALCZC */ -#define WM8961_MINGAIN_MASK 0x0070 /* MINGAIN - [6:4] */ -#define WM8961_MINGAIN_SHIFT 4 /* MINGAIN - [6:4] */ -#define WM8961_MINGAIN_WIDTH 3 /* MINGAIN - [6:4] */ -#define WM8961_HLD_MASK 0x000F /* HLD - [3:0] */ -#define WM8961_HLD_SHIFT 0 /* HLD - [3:0] */ -#define WM8961_HLD_WIDTH 4 /* HLD - [3:0] */ - -/* - * R19 (0x13) - ALC3 - */ -#define WM8961_ALCMODE 0x0100 /* ALCMODE */ -#define WM8961_ALCMODE_MASK 0x0100 /* ALCMODE */ -#define WM8961_ALCMODE_SHIFT 8 /* ALCMODE */ -#define WM8961_ALCMODE_WIDTH 1 /* ALCMODE */ -#define WM8961_DCY_MASK 0x00F0 /* DCY - [7:4] */ -#define WM8961_DCY_SHIFT 4 /* DCY - [7:4] */ -#define WM8961_DCY_WIDTH 4 /* DCY - [7:4] */ -#define WM8961_ATK_MASK 0x000F /* ATK - [3:0] */ -#define WM8961_ATK_SHIFT 0 /* ATK - [3:0] */ -#define WM8961_ATK_WIDTH 4 /* ATK - [3:0] */ - -/* - * R20 (0x14) - Noise Gate - */ -#define WM8961_NGTH_MASK 0x00F8 /* NGTH - [7:3] */ -#define WM8961_NGTH_SHIFT 3 /* NGTH - [7:3] */ -#define WM8961_NGTH_WIDTH 5 /* NGTH - [7:3] */ -#define WM8961_NGG 0x0002 /* NGG */ -#define WM8961_NGG_MASK 0x0002 /* NGG */ -#define WM8961_NGG_SHIFT 1 /* NGG */ -#define WM8961_NGG_WIDTH 1 /* NGG */ -#define WM8961_NGAT 0x0001 /* NGAT */ -#define WM8961_NGAT_MASK 0x0001 /* NGAT */ -#define WM8961_NGAT_SHIFT 0 /* NGAT */ -#define WM8961_NGAT_WIDTH 1 /* NGAT */ - -/* - * R21 (0x15) - Left ADC volume - */ -#define WM8961_ADCVU 0x0100 /* ADCVU */ -#define WM8961_ADCVU_MASK 0x0100 /* ADCVU */ -#define WM8961_ADCVU_SHIFT 8 /* ADCVU */ -#define WM8961_ADCVU_WIDTH 1 /* ADCVU */ -#define WM8961_LADCVOL_MASK 0x00FF /* LADCVOL - [7:0] */ -#define WM8961_LADCVOL_SHIFT 0 /* LADCVOL - [7:0] */ -#define WM8961_LADCVOL_WIDTH 8 /* LADCVOL - [7:0] */ - -/* - * R22 (0x16) - Right ADC volume - */ -#define WM8961_ADCVU 0x0100 /* ADCVU */ -#define WM8961_ADCVU_MASK 0x0100 /* ADCVU */ -#define WM8961_ADCVU_SHIFT 8 /* ADCVU */ -#define WM8961_ADCVU_WIDTH 1 /* ADCVU */ -#define WM8961_RADCVOL_MASK 0x00FF /* RADCVOL - [7:0] */ -#define WM8961_RADCVOL_SHIFT 0 /* RADCVOL - [7:0] */ -#define WM8961_RADCVOL_WIDTH 8 /* RADCVOL - [7:0] */ - -/* - * R23 (0x17) - Additional control(1) - */ -#define WM8961_TSDEN 0x0100 /* TSDEN */ -#define WM8961_TSDEN_MASK 0x0100 /* TSDEN */ -#define WM8961_TSDEN_SHIFT 8 /* TSDEN */ -#define WM8961_TSDEN_WIDTH 1 /* TSDEN */ -#define WM8961_DMONOMIX 0x0010 /* DMONOMIX */ -#define WM8961_DMONOMIX_MASK 0x0010 /* DMONOMIX */ -#define WM8961_DMONOMIX_SHIFT 4 /* DMONOMIX */ -#define WM8961_DMONOMIX_WIDTH 1 /* DMONOMIX */ -#define WM8961_TOEN 0x0001 /* TOEN */ -#define WM8961_TOEN_MASK 0x0001 /* TOEN */ -#define WM8961_TOEN_SHIFT 0 /* TOEN */ -#define WM8961_TOEN_WIDTH 1 /* TOEN */ - -/* - * R24 (0x18) - Additional control(2) - */ -#define WM8961_TRIS 0x0008 /* TRIS */ -#define WM8961_TRIS_MASK 0x0008 /* TRIS */ -#define WM8961_TRIS_SHIFT 3 /* TRIS */ -#define WM8961_TRIS_WIDTH 1 /* TRIS */ - -/* - * R25 (0x19) - Pwr Mgmt (1) - */ -#define WM8961_VMIDSEL_MASK 0x0180 /* VMIDSEL - [8:7] */ -#define WM8961_VMIDSEL_SHIFT 7 /* VMIDSEL - [8:7] */ -#define WM8961_VMIDSEL_WIDTH 2 /* VMIDSEL - [8:7] */ -#define WM8961_VREF 0x0040 /* VREF */ -#define WM8961_VREF_MASK 0x0040 /* VREF */ -#define WM8961_VREF_SHIFT 6 /* VREF */ -#define WM8961_VREF_WIDTH 1 /* VREF */ -#define WM8961_AINL 0x0020 /* AINL */ -#define WM8961_AINL_MASK 0x0020 /* AINL */ -#define WM8961_AINL_SHIFT 5 /* AINL */ -#define WM8961_AINL_WIDTH 1 /* AINL */ -#define WM8961_AINR 0x0010 /* AINR */ -#define WM8961_AINR_MASK 0x0010 /* AINR */ -#define WM8961_AINR_SHIFT 4 /* AINR */ -#define WM8961_AINR_WIDTH 1 /* AINR */ -#define WM8961_ADCL 0x0008 /* ADCL */ -#define WM8961_ADCL_MASK 0x0008 /* ADCL */ -#define WM8961_ADCL_SHIFT 3 /* ADCL */ -#define WM8961_ADCL_WIDTH 1 /* ADCL */ -#define WM8961_ADCR 0x0004 /* ADCR */ -#define WM8961_ADCR_MASK 0x0004 /* ADCR */ -#define WM8961_ADCR_SHIFT 2 /* ADCR */ -#define WM8961_ADCR_WIDTH 1 /* ADCR */ -#define WM8961_MICB 0x0002 /* MICB */ -#define WM8961_MICB_MASK 0x0002 /* MICB */ -#define WM8961_MICB_SHIFT 1 /* MICB */ -#define WM8961_MICB_WIDTH 1 /* MICB */ - -/* - * R26 (0x1A) - Pwr Mgmt (2) - */ -#define WM8961_DACL 0x0100 /* DACL */ -#define WM8961_DACL_MASK 0x0100 /* DACL */ -#define WM8961_DACL_SHIFT 8 /* DACL */ -#define WM8961_DACL_WIDTH 1 /* DACL */ -#define WM8961_DACR 0x0080 /* DACR */ -#define WM8961_DACR_MASK 0x0080 /* DACR */ -#define WM8961_DACR_SHIFT 7 /* DACR */ -#define WM8961_DACR_WIDTH 1 /* DACR */ -#define WM8961_LOUT1_PGA 0x0040 /* LOUT1_PGA */ -#define WM8961_LOUT1_PGA_MASK 0x0040 /* LOUT1_PGA */ -#define WM8961_LOUT1_PGA_SHIFT 6 /* LOUT1_PGA */ -#define WM8961_LOUT1_PGA_WIDTH 1 /* LOUT1_PGA */ -#define WM8961_ROUT1_PGA 0x0020 /* ROUT1_PGA */ -#define WM8961_ROUT1_PGA_MASK 0x0020 /* ROUT1_PGA */ -#define WM8961_ROUT1_PGA_SHIFT 5 /* ROUT1_PGA */ -#define WM8961_ROUT1_PGA_WIDTH 1 /* ROUT1_PGA */ -#define WM8961_SPKL_PGA 0x0010 /* SPKL_PGA */ -#define WM8961_SPKL_PGA_MASK 0x0010 /* SPKL_PGA */ -#define WM8961_SPKL_PGA_SHIFT 4 /* SPKL_PGA */ -#define WM8961_SPKL_PGA_WIDTH 1 /* SPKL_PGA */ -#define WM8961_SPKR_PGA 0x0008 /* SPKR_PGA */ -#define WM8961_SPKR_PGA_MASK 0x0008 /* SPKR_PGA */ -#define WM8961_SPKR_PGA_SHIFT 3 /* SPKR_PGA */ -#define WM8961_SPKR_PGA_WIDTH 1 /* SPKR_PGA */ - -/* - * R27 (0x1B) - Additional Control (3) - */ -#define WM8961_SAMPLE_RATE_MASK 0x0007 /* SAMPLE_RATE - [2:0] */ -#define WM8961_SAMPLE_RATE_SHIFT 0 /* SAMPLE_RATE - [2:0] */ -#define WM8961_SAMPLE_RATE_WIDTH 3 /* SAMPLE_RATE - [2:0] */ - -/* - * R28 (0x1C) - Anti-pop - */ -#define WM8961_BUFDCOPEN 0x0010 /* BUFDCOPEN */ -#define WM8961_BUFDCOPEN_MASK 0x0010 /* BUFDCOPEN */ -#define WM8961_BUFDCOPEN_SHIFT 4 /* BUFDCOPEN */ -#define WM8961_BUFDCOPEN_WIDTH 1 /* BUFDCOPEN */ -#define WM8961_BUFIOEN 0x0008 /* BUFIOEN */ -#define WM8961_BUFIOEN_MASK 0x0008 /* BUFIOEN */ -#define WM8961_BUFIOEN_SHIFT 3 /* BUFIOEN */ -#define WM8961_BUFIOEN_WIDTH 1 /* BUFIOEN */ -#define WM8961_SOFT_ST 0x0004 /* SOFT_ST */ -#define WM8961_SOFT_ST_MASK 0x0004 /* SOFT_ST */ -#define WM8961_SOFT_ST_SHIFT 2 /* SOFT_ST */ -#define WM8961_SOFT_ST_WIDTH 1 /* SOFT_ST */ - -/* - * R30 (0x1E) - Clocking 3 - */ -#define WM8961_CLK_TO_DIV_MASK 0x0180 /* CLK_TO_DIV - [8:7] */ -#define WM8961_CLK_TO_DIV_SHIFT 7 /* CLK_TO_DIV - [8:7] */ -#define WM8961_CLK_TO_DIV_WIDTH 2 /* CLK_TO_DIV - [8:7] */ -#define WM8961_CLK_256K_DIV_MASK 0x007E /* CLK_256K_DIV - [6:1] */ -#define WM8961_CLK_256K_DIV_SHIFT 1 /* CLK_256K_DIV - [6:1] */ -#define WM8961_CLK_256K_DIV_WIDTH 6 /* CLK_256K_DIV - [6:1] */ -#define WM8961_MANUAL_MODE 0x0001 /* MANUAL_MODE */ -#define WM8961_MANUAL_MODE_MASK 0x0001 /* MANUAL_MODE */ -#define WM8961_MANUAL_MODE_SHIFT 0 /* MANUAL_MODE */ -#define WM8961_MANUAL_MODE_WIDTH 1 /* MANUAL_MODE */ - -/* - * R32 (0x20) - ADCL signal path - */ -#define WM8961_LMICBOOST_MASK 0x0030 /* LMICBOOST - [5:4] */ -#define WM8961_LMICBOOST_SHIFT 4 /* LMICBOOST - [5:4] */ -#define WM8961_LMICBOOST_WIDTH 2 /* LMICBOOST - [5:4] */ - -/* - * R33 (0x21) - ADCR signal path - */ -#define WM8961_RMICBOOST_MASK 0x0030 /* RMICBOOST - [5:4] */ -#define WM8961_RMICBOOST_SHIFT 4 /* RMICBOOST - [5:4] */ -#define WM8961_RMICBOOST_WIDTH 2 /* RMICBOOST - [5:4] */ - -/* - * R40 (0x28) - LOUT2 volume - */ -#define WM8961_SPKVU 0x0100 /* SPKVU */ -#define WM8961_SPKVU_MASK 0x0100 /* SPKVU */ -#define WM8961_SPKVU_SHIFT 8 /* SPKVU */ -#define WM8961_SPKVU_WIDTH 1 /* SPKVU */ -#define WM8961_SPKLZC 0x0080 /* SPKLZC */ -#define WM8961_SPKLZC_MASK 0x0080 /* SPKLZC */ -#define WM8961_SPKLZC_SHIFT 7 /* SPKLZC */ -#define WM8961_SPKLZC_WIDTH 1 /* SPKLZC */ -#define WM8961_SPKLVOL_MASK 0x007F /* SPKLVOL - [6:0] */ -#define WM8961_SPKLVOL_SHIFT 0 /* SPKLVOL - [6:0] */ -#define WM8961_SPKLVOL_WIDTH 7 /* SPKLVOL - [6:0] */ - -/* - * R41 (0x29) - ROUT2 volume - */ -#define WM8961_SPKVU 0x0100 /* SPKVU */ -#define WM8961_SPKVU_MASK 0x0100 /* SPKVU */ -#define WM8961_SPKVU_SHIFT 8 /* SPKVU */ -#define WM8961_SPKVU_WIDTH 1 /* SPKVU */ -#define WM8961_SPKRZC 0x0080 /* SPKRZC */ -#define WM8961_SPKRZC_MASK 0x0080 /* SPKRZC */ -#define WM8961_SPKRZC_SHIFT 7 /* SPKRZC */ -#define WM8961_SPKRZC_WIDTH 1 /* SPKRZC */ -#define WM8961_SPKRVOL_MASK 0x007F /* SPKRVOL - [6:0] */ -#define WM8961_SPKRVOL_SHIFT 0 /* SPKRVOL - [6:0] */ -#define WM8961_SPKRVOL_WIDTH 7 /* SPKRVOL - [6:0] */ - -/* - * R47 (0x2F) - Pwr Mgmt (3) - */ -#define WM8961_TEMP_SHUT 0x0002 /* TEMP_SHUT */ -#define WM8961_TEMP_SHUT_MASK 0x0002 /* TEMP_SHUT */ -#define WM8961_TEMP_SHUT_SHIFT 1 /* TEMP_SHUT */ -#define WM8961_TEMP_SHUT_WIDTH 1 /* TEMP_SHUT */ -#define WM8961_TEMP_WARN 0x0001 /* TEMP_WARN */ -#define WM8961_TEMP_WARN_MASK 0x0001 /* TEMP_WARN */ -#define WM8961_TEMP_WARN_SHIFT 0 /* TEMP_WARN */ -#define WM8961_TEMP_WARN_WIDTH 1 /* TEMP_WARN */ - -/* - * R48 (0x30) - Additional Control (4) - */ -#define WM8961_TSENSEN 0x0002 /* TSENSEN */ -#define WM8961_TSENSEN_MASK 0x0002 /* TSENSEN */ -#define WM8961_TSENSEN_SHIFT 1 /* TSENSEN */ -#define WM8961_TSENSEN_WIDTH 1 /* TSENSEN */ -#define WM8961_MBSEL 0x0001 /* MBSEL */ -#define WM8961_MBSEL_MASK 0x0001 /* MBSEL */ -#define WM8961_MBSEL_SHIFT 0 /* MBSEL */ -#define WM8961_MBSEL_WIDTH 1 /* MBSEL */ - -/* - * R49 (0x31) - Class D Control 1 - */ -#define WM8961_SPKR_ENA 0x0080 /* SPKR_ENA */ -#define WM8961_SPKR_ENA_MASK 0x0080 /* SPKR_ENA */ -#define WM8961_SPKR_ENA_SHIFT 7 /* SPKR_ENA */ -#define WM8961_SPKR_ENA_WIDTH 1 /* SPKR_ENA */ -#define WM8961_SPKL_ENA 0x0040 /* SPKL_ENA */ -#define WM8961_SPKL_ENA_MASK 0x0040 /* SPKL_ENA */ -#define WM8961_SPKL_ENA_SHIFT 6 /* SPKL_ENA */ -#define WM8961_SPKL_ENA_WIDTH 1 /* SPKL_ENA */ - -/* - * R51 (0x33) - Class D Control 2 - */ -#define WM8961_CLASSD_ACGAIN_MASK 0x0007 /* CLASSD_ACGAIN - [2:0] */ -#define WM8961_CLASSD_ACGAIN_SHIFT 0 /* CLASSD_ACGAIN - [2:0] */ -#define WM8961_CLASSD_ACGAIN_WIDTH 3 /* CLASSD_ACGAIN - [2:0] */ - -/* - * R56 (0x38) - Clocking 4 - */ -#define WM8961_CLK_DCS_DIV_MASK 0x01E0 /* CLK_DCS_DIV - [8:5] */ -#define WM8961_CLK_DCS_DIV_SHIFT 5 /* CLK_DCS_DIV - [8:5] */ -#define WM8961_CLK_DCS_DIV_WIDTH 4 /* CLK_DCS_DIV - [8:5] */ -#define WM8961_CLK_SYS_RATE_MASK 0x001E /* CLK_SYS_RATE - [4:1] */ -#define WM8961_CLK_SYS_RATE_SHIFT 1 /* CLK_SYS_RATE - [4:1] */ -#define WM8961_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [4:1] */ - -/* - * R57 (0x39) - DSP Sidetone 0 - */ -#define WM8961_ADCR_DAC_SVOL_MASK 0x00F0 /* ADCR_DAC_SVOL - [7:4] */ -#define WM8961_ADCR_DAC_SVOL_SHIFT 4 /* ADCR_DAC_SVOL - [7:4] */ -#define WM8961_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [7:4] */ -#define WM8961_ADC_TO_DACR_MASK 0x000C /* ADC_TO_DACR - [3:2] */ -#define WM8961_ADC_TO_DACR_SHIFT 2 /* ADC_TO_DACR - [3:2] */ -#define WM8961_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [3:2] */ - -/* - * R58 (0x3A) - DSP Sidetone 1 - */ -#define WM8961_ADCL_DAC_SVOL_MASK 0x00F0 /* ADCL_DAC_SVOL - [7:4] */ -#define WM8961_ADCL_DAC_SVOL_SHIFT 4 /* ADCL_DAC_SVOL - [7:4] */ -#define WM8961_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [7:4] */ -#define WM8961_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */ -#define WM8961_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */ -#define WM8961_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */ - -/* - * R60 (0x3C) - DC Servo 0 - */ -#define WM8961_DCS_ENA_CHAN_INL 0x0080 /* DCS_ENA_CHAN_INL */ -#define WM8961_DCS_ENA_CHAN_INL_MASK 0x0080 /* DCS_ENA_CHAN_INL */ -#define WM8961_DCS_ENA_CHAN_INL_SHIFT 7 /* DCS_ENA_CHAN_INL */ -#define WM8961_DCS_ENA_CHAN_INL_WIDTH 1 /* DCS_ENA_CHAN_INL */ -#define WM8961_DCS_TRIG_STARTUP_INL 0x0040 /* DCS_TRIG_STARTUP_INL */ -#define WM8961_DCS_TRIG_STARTUP_INL_MASK 0x0040 /* DCS_TRIG_STARTUP_INL */ -#define WM8961_DCS_TRIG_STARTUP_INL_SHIFT 6 /* DCS_TRIG_STARTUP_INL */ -#define WM8961_DCS_TRIG_STARTUP_INL_WIDTH 1 /* DCS_TRIG_STARTUP_INL */ -#define WM8961_DCS_TRIG_SERIES_INL 0x0010 /* DCS_TRIG_SERIES_INL */ -#define WM8961_DCS_TRIG_SERIES_INL_MASK 0x0010 /* DCS_TRIG_SERIES_INL */ -#define WM8961_DCS_TRIG_SERIES_INL_SHIFT 4 /* DCS_TRIG_SERIES_INL */ -#define WM8961_DCS_TRIG_SERIES_INL_WIDTH 1 /* DCS_TRIG_SERIES_INL */ -#define WM8961_DCS_ENA_CHAN_INR 0x0008 /* DCS_ENA_CHAN_INR */ -#define WM8961_DCS_ENA_CHAN_INR_MASK 0x0008 /* DCS_ENA_CHAN_INR */ -#define WM8961_DCS_ENA_CHAN_INR_SHIFT 3 /* DCS_ENA_CHAN_INR */ -#define WM8961_DCS_ENA_CHAN_INR_WIDTH 1 /* DCS_ENA_CHAN_INR */ -#define WM8961_DCS_TRIG_STARTUP_INR 0x0004 /* DCS_TRIG_STARTUP_INR */ -#define WM8961_DCS_TRIG_STARTUP_INR_MASK 0x0004 /* DCS_TRIG_STARTUP_INR */ -#define WM8961_DCS_TRIG_STARTUP_INR_SHIFT 2 /* DCS_TRIG_STARTUP_INR */ -#define WM8961_DCS_TRIG_STARTUP_INR_WIDTH 1 /* DCS_TRIG_STARTUP_INR */ -#define WM8961_DCS_TRIG_SERIES_INR 0x0001 /* DCS_TRIG_SERIES_INR */ -#define WM8961_DCS_TRIG_SERIES_INR_MASK 0x0001 /* DCS_TRIG_SERIES_INR */ -#define WM8961_DCS_TRIG_SERIES_INR_SHIFT 0 /* DCS_TRIG_SERIES_INR */ -#define WM8961_DCS_TRIG_SERIES_INR_WIDTH 1 /* DCS_TRIG_SERIES_INR */ - -/* - * R61 (0x3D) - DC Servo 1 - */ -#define WM8961_DCS_ENA_CHAN_HPL 0x0080 /* DCS_ENA_CHAN_HPL */ -#define WM8961_DCS_ENA_CHAN_HPL_MASK 0x0080 /* DCS_ENA_CHAN_HPL */ -#define WM8961_DCS_ENA_CHAN_HPL_SHIFT 7 /* DCS_ENA_CHAN_HPL */ -#define WM8961_DCS_ENA_CHAN_HPL_WIDTH 1 /* DCS_ENA_CHAN_HPL */ -#define WM8961_DCS_TRIG_STARTUP_HPL 0x0040 /* DCS_TRIG_STARTUP_HPL */ -#define WM8961_DCS_TRIG_STARTUP_HPL_MASK 0x0040 /* DCS_TRIG_STARTUP_HPL */ -#define WM8961_DCS_TRIG_STARTUP_HPL_SHIFT 6 /* DCS_TRIG_STARTUP_HPL */ -#define WM8961_DCS_TRIG_STARTUP_HPL_WIDTH 1 /* DCS_TRIG_STARTUP_HPL */ -#define WM8961_DCS_TRIG_SERIES_HPL 0x0010 /* DCS_TRIG_SERIES_HPL */ -#define WM8961_DCS_TRIG_SERIES_HPL_MASK 0x0010 /* DCS_TRIG_SERIES_HPL */ -#define WM8961_DCS_TRIG_SERIES_HPL_SHIFT 4 /* DCS_TRIG_SERIES_HPL */ -#define WM8961_DCS_TRIG_SERIES_HPL_WIDTH 1 /* DCS_TRIG_SERIES_HPL */ -#define WM8961_DCS_ENA_CHAN_HPR 0x0008 /* DCS_ENA_CHAN_HPR */ -#define WM8961_DCS_ENA_CHAN_HPR_MASK 0x0008 /* DCS_ENA_CHAN_HPR */ -#define WM8961_DCS_ENA_CHAN_HPR_SHIFT 3 /* DCS_ENA_CHAN_HPR */ -#define WM8961_DCS_ENA_CHAN_HPR_WIDTH 1 /* DCS_ENA_CHAN_HPR */ -#define WM8961_DCS_TRIG_STARTUP_HPR 0x0004 /* DCS_TRIG_STARTUP_HPR */ -#define WM8961_DCS_TRIG_STARTUP_HPR_MASK 0x0004 /* DCS_TRIG_STARTUP_HPR */ -#define WM8961_DCS_TRIG_STARTUP_HPR_SHIFT 2 /* DCS_TRIG_STARTUP_HPR */ -#define WM8961_DCS_TRIG_STARTUP_HPR_WIDTH 1 /* DCS_TRIG_STARTUP_HPR */ -#define WM8961_DCS_TRIG_SERIES_HPR 0x0001 /* DCS_TRIG_SERIES_HPR */ -#define WM8961_DCS_TRIG_SERIES_HPR_MASK 0x0001 /* DCS_TRIG_SERIES_HPR */ -#define WM8961_DCS_TRIG_SERIES_HPR_SHIFT 0 /* DCS_TRIG_SERIES_HPR */ -#define WM8961_DCS_TRIG_SERIES_HPR_WIDTH 1 /* DCS_TRIG_SERIES_HPR */ - -/* - * R63 (0x3F) - DC Servo 3 - */ -#define WM8961_DCS_FILT_BW_SERIES_MASK 0x0030 /* DCS_FILT_BW_SERIES - [5:4] */ -#define WM8961_DCS_FILT_BW_SERIES_SHIFT 4 /* DCS_FILT_BW_SERIES - [5:4] */ -#define WM8961_DCS_FILT_BW_SERIES_WIDTH 2 /* DCS_FILT_BW_SERIES - [5:4] */ - -/* - * R65 (0x41) - DC Servo 5 - */ -#define WM8961_DCS_SERIES_NO_HP_MASK 0x007F /* DCS_SERIES_NO_HP - [6:0] */ -#define WM8961_DCS_SERIES_NO_HP_SHIFT 0 /* DCS_SERIES_NO_HP - [6:0] */ -#define WM8961_DCS_SERIES_NO_HP_WIDTH 7 /* DCS_SERIES_NO_HP - [6:0] */ - -/* - * R68 (0x44) - Analogue PGA Bias - */ -#define WM8961_HP_PGAS_BIAS_MASK 0x0007 /* HP_PGAS_BIAS - [2:0] */ -#define WM8961_HP_PGAS_BIAS_SHIFT 0 /* HP_PGAS_BIAS - [2:0] */ -#define WM8961_HP_PGAS_BIAS_WIDTH 3 /* HP_PGAS_BIAS - [2:0] */ - -/* - * R69 (0x45) - Analogue HP 0 - */ -#define WM8961_HPL_RMV_SHORT 0x0080 /* HPL_RMV_SHORT */ -#define WM8961_HPL_RMV_SHORT_MASK 0x0080 /* HPL_RMV_SHORT */ -#define WM8961_HPL_RMV_SHORT_SHIFT 7 /* HPL_RMV_SHORT */ -#define WM8961_HPL_RMV_SHORT_WIDTH 1 /* HPL_RMV_SHORT */ -#define WM8961_HPL_ENA_OUTP 0x0040 /* HPL_ENA_OUTP */ -#define WM8961_HPL_ENA_OUTP_MASK 0x0040 /* HPL_ENA_OUTP */ -#define WM8961_HPL_ENA_OUTP_SHIFT 6 /* HPL_ENA_OUTP */ -#define WM8961_HPL_ENA_OUTP_WIDTH 1 /* HPL_ENA_OUTP */ -#define WM8961_HPL_ENA_DLY 0x0020 /* HPL_ENA_DLY */ -#define WM8961_HPL_ENA_DLY_MASK 0x0020 /* HPL_ENA_DLY */ -#define WM8961_HPL_ENA_DLY_SHIFT 5 /* HPL_ENA_DLY */ -#define WM8961_HPL_ENA_DLY_WIDTH 1 /* HPL_ENA_DLY */ -#define WM8961_HPL_ENA 0x0010 /* HPL_ENA */ -#define WM8961_HPL_ENA_MASK 0x0010 /* HPL_ENA */ -#define WM8961_HPL_ENA_SHIFT 4 /* HPL_ENA */ -#define WM8961_HPL_ENA_WIDTH 1 /* HPL_ENA */ -#define WM8961_HPR_RMV_SHORT 0x0008 /* HPR_RMV_SHORT */ -#define WM8961_HPR_RMV_SHORT_MASK 0x0008 /* HPR_RMV_SHORT */ -#define WM8961_HPR_RMV_SHORT_SHIFT 3 /* HPR_RMV_SHORT */ -#define WM8961_HPR_RMV_SHORT_WIDTH 1 /* HPR_RMV_SHORT */ -#define WM8961_HPR_ENA_OUTP 0x0004 /* HPR_ENA_OUTP */ -#define WM8961_HPR_ENA_OUTP_MASK 0x0004 /* HPR_ENA_OUTP */ -#define WM8961_HPR_ENA_OUTP_SHIFT 2 /* HPR_ENA_OUTP */ -#define WM8961_HPR_ENA_OUTP_WIDTH 1 /* HPR_ENA_OUTP */ -#define WM8961_HPR_ENA_DLY 0x0002 /* HPR_ENA_DLY */ -#define WM8961_HPR_ENA_DLY_MASK 0x0002 /* HPR_ENA_DLY */ -#define WM8961_HPR_ENA_DLY_SHIFT 1 /* HPR_ENA_DLY */ -#define WM8961_HPR_ENA_DLY_WIDTH 1 /* HPR_ENA_DLY */ -#define WM8961_HPR_ENA 0x0001 /* HPR_ENA */ -#define WM8961_HPR_ENA_MASK 0x0001 /* HPR_ENA */ -#define WM8961_HPR_ENA_SHIFT 0 /* HPR_ENA */ -#define WM8961_HPR_ENA_WIDTH 1 /* HPR_ENA */ - -/* - * R71 (0x47) - Analogue HP 2 - */ -#define WM8961_HPL_VOL_MASK 0x01C0 /* HPL_VOL - [8:6] */ -#define WM8961_HPL_VOL_SHIFT 6 /* HPL_VOL - [8:6] */ -#define WM8961_HPL_VOL_WIDTH 3 /* HPL_VOL - [8:6] */ -#define WM8961_HPR_VOL_MASK 0x0038 /* HPR_VOL - [5:3] */ -#define WM8961_HPR_VOL_SHIFT 3 /* HPR_VOL - [5:3] */ -#define WM8961_HPR_VOL_WIDTH 3 /* HPR_VOL - [5:3] */ -#define WM8961_HP_BIAS_BOOST_MASK 0x0007 /* HP_BIAS_BOOST - [2:0] */ -#define WM8961_HP_BIAS_BOOST_SHIFT 0 /* HP_BIAS_BOOST - [2:0] */ -#define WM8961_HP_BIAS_BOOST_WIDTH 3 /* HP_BIAS_BOOST - [2:0] */ - -/* - * R72 (0x48) - Charge Pump 1 - */ -#define WM8961_CP_ENA 0x0001 /* CP_ENA */ -#define WM8961_CP_ENA_MASK 0x0001 /* CP_ENA */ -#define WM8961_CP_ENA_SHIFT 0 /* CP_ENA */ -#define WM8961_CP_ENA_WIDTH 1 /* CP_ENA */ - -/* - * R82 (0x52) - Charge Pump B - */ -#define WM8961_CP_DYN_PWR_MASK 0x0003 /* CP_DYN_PWR - [1:0] */ -#define WM8961_CP_DYN_PWR_SHIFT 0 /* CP_DYN_PWR - [1:0] */ -#define WM8961_CP_DYN_PWR_WIDTH 2 /* CP_DYN_PWR - [1:0] */ - -/* - * R87 (0x57) - Write Sequencer 1 - */ -#define WM8961_WSEQ_ENA 0x0020 /* WSEQ_ENA */ -#define WM8961_WSEQ_ENA_MASK 0x0020 /* WSEQ_ENA */ -#define WM8961_WSEQ_ENA_SHIFT 5 /* WSEQ_ENA */ -#define WM8961_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */ -#define WM8961_WSEQ_WRITE_INDEX_MASK 0x001F /* WSEQ_WRITE_INDEX - [4:0] */ -#define WM8961_WSEQ_WRITE_INDEX_SHIFT 0 /* WSEQ_WRITE_INDEX - [4:0] */ -#define WM8961_WSEQ_WRITE_INDEX_WIDTH 5 /* WSEQ_WRITE_INDEX - [4:0] */ - -/* - * R88 (0x58) - Write Sequencer 2 - */ -#define WM8961_WSEQ_EOS 0x0100 /* WSEQ_EOS */ -#define WM8961_WSEQ_EOS_MASK 0x0100 /* WSEQ_EOS */ -#define WM8961_WSEQ_EOS_SHIFT 8 /* WSEQ_EOS */ -#define WM8961_WSEQ_EOS_WIDTH 1 /* WSEQ_EOS */ -#define WM8961_WSEQ_ADDR_MASK 0x00FF /* WSEQ_ADDR - [7:0] */ -#define WM8961_WSEQ_ADDR_SHIFT 0 /* WSEQ_ADDR - [7:0] */ -#define WM8961_WSEQ_ADDR_WIDTH 8 /* WSEQ_ADDR - [7:0] */ - -/* - * R89 (0x59) - Write Sequencer 3 - */ -#define WM8961_WSEQ_DATA_MASK 0x00FF /* WSEQ_DATA - [7:0] */ -#define WM8961_WSEQ_DATA_SHIFT 0 /* WSEQ_DATA - [7:0] */ -#define WM8961_WSEQ_DATA_WIDTH 8 /* WSEQ_DATA - [7:0] */ - -/* - * R90 (0x5A) - Write Sequencer 4 - */ -#define WM8961_WSEQ_ABORT 0x0100 /* WSEQ_ABORT */ -#define WM8961_WSEQ_ABORT_MASK 0x0100 /* WSEQ_ABORT */ -#define WM8961_WSEQ_ABORT_SHIFT 8 /* WSEQ_ABORT */ -#define WM8961_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */ -#define WM8961_WSEQ_START 0x0080 /* WSEQ_START */ -#define WM8961_WSEQ_START_MASK 0x0080 /* WSEQ_START */ -#define WM8961_WSEQ_START_SHIFT 7 /* WSEQ_START */ -#define WM8961_WSEQ_START_WIDTH 1 /* WSEQ_START */ -#define WM8961_WSEQ_START_INDEX_MASK 0x003F /* WSEQ_START_INDEX - [5:0] */ -#define WM8961_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [5:0] */ -#define WM8961_WSEQ_START_INDEX_WIDTH 6 /* WSEQ_START_INDEX - [5:0] */ - -/* - * R91 (0x5B) - Write Sequencer 5 - */ -#define WM8961_WSEQ_DATA_WIDTH_MASK 0x0070 /* WSEQ_DATA_WIDTH - [6:4] */ -#define WM8961_WSEQ_DATA_WIDTH_SHIFT 4 /* WSEQ_DATA_WIDTH - [6:4] */ -#define WM8961_WSEQ_DATA_WIDTH_WIDTH 3 /* WSEQ_DATA_WIDTH - [6:4] */ -#define WM8961_WSEQ_DATA_START_MASK 0x000F /* WSEQ_DATA_START - [3:0] */ -#define WM8961_WSEQ_DATA_START_SHIFT 0 /* WSEQ_DATA_START - [3:0] */ -#define WM8961_WSEQ_DATA_START_WIDTH 4 /* WSEQ_DATA_START - [3:0] */ - -/* - * R92 (0x5C) - Write Sequencer 6 - */ -#define WM8961_WSEQ_DELAY_MASK 0x000F /* WSEQ_DELAY - [3:0] */ -#define WM8961_WSEQ_DELAY_SHIFT 0 /* WSEQ_DELAY - [3:0] */ -#define WM8961_WSEQ_DELAY_WIDTH 4 /* WSEQ_DELAY - [3:0] */ - -/* - * R93 (0x5D) - Write Sequencer 7 - */ -#define WM8961_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */ -#define WM8961_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */ -#define WM8961_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */ -#define WM8961_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */ - -/* - * R252 (0xFC) - General test 1 - */ -#define WM8961_ARA_ENA 0x0002 /* ARA_ENA */ -#define WM8961_ARA_ENA_MASK 0x0002 /* ARA_ENA */ -#define WM8961_ARA_ENA_SHIFT 1 /* ARA_ENA */ -#define WM8961_ARA_ENA_WIDTH 1 /* ARA_ENA */ -#define WM8961_AUTO_INC 0x0001 /* AUTO_INC */ -#define WM8961_AUTO_INC_MASK 0x0001 /* AUTO_INC */ -#define WM8961_AUTO_INC_SHIFT 0 /* AUTO_INC */ -#define WM8961_AUTO_INC_WIDTH 1 /* AUTO_INC */ - -#endif diff --git a/trunk/sound/soc/codecs/wm8988.c b/trunk/sound/soc/codecs/wm8988.c index 6f15acd10489..c05f71803aa8 100644 --- a/trunk/sound/soc/codecs/wm8988.c +++ b/trunk/sound/soc/codecs/wm8988.c @@ -902,7 +902,7 @@ static int wm8988_register(struct wm8988_priv *wm8988) ret = wm8988_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); - goto err; + return ret; } /* set the update bits (we always update left then right) */ @@ -926,20 +926,18 @@ static int wm8988_register(struct wm8988_priv *wm8988) ret = snd_soc_register_codec(codec); if (ret != 0) { dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; + return ret; } ret = snd_soc_register_dai(&wm8988_dai); if (ret != 0) { dev_err(codec->dev, "Failed to register DAI: %d\n", ret); snd_soc_unregister_codec(codec); - goto err_codec; + return ret; } return 0; -err_codec: - snd_soc_unregister_codec(codec); err: kfree(wm8988); return ret; @@ -983,21 +981,6 @@ static int wm8988_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int wm8988_i2c_suspend(struct i2c_client *client, pm_message_t msg) -{ - return snd_soc_suspend_device(&client->dev); -} - -static int wm8988_i2c_resume(struct i2c_client *client) -{ - return snd_soc_resume_device(&client->dev); -} -#else -#define wm8988_i2c_suspend NULL -#define wm8988_i2c_resume NULL -#endif - static const struct i2c_device_id wm8988_i2c_id[] = { { "wm8988", 0 }, { } @@ -1011,8 +994,6 @@ static struct i2c_driver wm8988_i2c_driver = { }, .probe = wm8988_i2c_probe, .remove = wm8988_i2c_remove, - .suspend = wm8988_i2c_suspend, - .resume = wm8988_i2c_resume, .id_table = wm8988_i2c_id, }; #endif @@ -1070,21 +1051,6 @@ static int __devexit wm8988_spi_remove(struct spi_device *spi) return 0; } -#ifdef CONFIG_PM -static int wm8988_spi_suspend(struct spi_device *spi, pm_message_t msg) -{ - return snd_soc_suspend_device(&spi->dev); -} - -static int wm8988_spi_resume(struct spi_device *spi) -{ - return snd_soc_resume_device(&spi->dev); -} -#else -#define wm8988_spi_suspend NULL -#define wm8988_spi_resume NULL -#endif - static struct spi_driver wm8988_spi_driver = { .driver = { .name = "wm8988", @@ -1093,8 +1059,6 @@ static struct spi_driver wm8988_spi_driver = { }, .probe = wm8988_spi_probe, .remove = __devexit_p(wm8988_spi_remove), - .suspend = wm8988_spi_suspend, - .resume = wm8988_spi_resume, }; #endif 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..86fc57e25f97 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; } @@ -1500,21 +1492,6 @@ static __devexit int wm9081_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int wm9081_i2c_suspend(struct i2c_client *client, pm_message_t msg) -{ - return snd_soc_suspend_device(&client->dev); -} - -static int wm9081_i2c_resume(struct i2c_client *client) -{ - return snd_soc_resume_device(&client->dev); -} -#else -#define wm9081_i2c_suspend NULL -#define wm9081_i2c_resume NULL -#endif - static const struct i2c_device_id wm9081_i2c_id[] = { { "wm9081", 0 }, { } @@ -1528,8 +1505,6 @@ static struct i2c_driver wm9081_i2c_driver = { }, .probe = wm9081_i2c_probe, .remove = __devexit_p(wm9081_i2c_remove), - .suspend = wm9081_i2c_suspend, - .resume = wm9081_i2c_resume, .id_table = wm9081_i2c_id, }; 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..b1ea52fc83c7 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" @@ -65,7 +63,6 @@ #define DAVINCI_MCBSP_RCR_RWDLEN1(v) ((v) << 5) #define DAVINCI_MCBSP_RCR_RFRLEN1(v) ((v) << 8) #define DAVINCI_MCBSP_RCR_RDATDLY(v) ((v) << 16) -#define DAVINCI_MCBSP_RCR_RFIG (1 << 18) #define DAVINCI_MCBSP_RCR_RWDLEN2(v) ((v) << 21) #define DAVINCI_MCBSP_XCR_XWDLEN1(v) ((v) << 5) @@ -88,6 +85,14 @@ #define DAVINCI_MCBSP_PCR_FSRM (1 << 10) #define DAVINCI_MCBSP_PCR_FSXM (1 << 11) +#define MOD_REG_BIT(val, mask, set) do { \ + if (set) { \ + val |= mask; \ + } else { \ + val &= ~mask; \ + } \ +} while (0) + enum { DAVINCI_MCBSP_WORD_8 = 0, DAVINCI_MCBSP_WORD_12, @@ -107,10 +112,6 @@ static struct davinci_pcm_dma_params davinci_i2s_pcm_in = { struct davinci_mcbsp_dev { void __iomem *base; -#define MOD_DSP_A 0 -#define MOD_DSP_B 1 - int mode; - u32 pcr; struct clk *clk; struct davinci_pcm_dma_params *dma_params[2]; }; @@ -126,100 +127,96 @@ static inline u32 davinci_mcbsp_read_reg(struct davinci_mcbsp_dev *dev, int reg) return __raw_readl(dev->base + reg); } -static void toggle_clock(struct davinci_mcbsp_dev *dev, int playback) -{ - u32 m = playback ? DAVINCI_MCBSP_PCR_CLKXP : DAVINCI_MCBSP_PCR_CLKRP; - /* The clock needs to toggle to complete reset. - * So, fake it by toggling the clk polarity. - */ - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr ^ m); - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr); -} - -static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev, - struct snd_pcm_substream *substream) +static void davinci_mcbsp_start(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_platform *platform = socdev->card->platform; - int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - u32 spcr; - u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST; - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - if (spcr & mask) { - /* start off disabled */ - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, - spcr & ~mask); - toggle_clock(dev, playback); - } - if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM | - DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) { - /* Start the sample generator */ - spcr |= DAVINCI_MCBSP_SPCR_GRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - } + u32 w; + int ret; - if (playback) { + /* Start the sample generator and enable transmitter/receiver */ + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { /* Stop the DMA to avoid data loss */ /* while the transmitter is out of reset to handle XSYNCERR */ if (platform->pcm_ops->trigger) { - int ret = platform->pcm_ops->trigger(substream, + ret = platform->pcm_ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP); if (ret < 0) printk(KERN_DEBUG "Playback DMA stop failed\n"); } /* Enable the transmitter */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr |= DAVINCI_MCBSP_SPCR_XRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); /* wait for any unexpected frame sync error to occur */ udelay(100); /* Disable the transmitter to clear any outstanding XSYNCERR */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr &= ~DAVINCI_MCBSP_SPCR_XRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - toggle_clock(dev, playback); + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); /* Restart the DMA */ if (platform->pcm_ops->trigger) { - int ret = platform->pcm_ops->trigger(substream, + ret = platform->pcm_ops->trigger(substream, SNDRV_PCM_TRIGGER_START); if (ret < 0) printk(KERN_DEBUG "Playback DMA start failed\n"); } - } + /* Enable the transmitter */ + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); - /* Enable transmitter or receiver */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr |= mask; + } else { - if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM)) { - /* Start frame sync */ - spcr |= DAVINCI_MCBSP_SPCR_FRST; + /* Enable the reciever */ + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); } - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); + + + /* Start frame sync */ + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_FRST, 1); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); } -static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback) +static void davinci_mcbsp_stop(struct snd_pcm_substream *substream) { - u32 spcr; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; + u32 w; /* Reset transmitter/receiver and sample rate/frame sync generators */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr &= ~(DAVINCI_MCBSP_SPCR_GRST | DAVINCI_MCBSP_SPCR_FRST); - spcr &= playback ? ~DAVINCI_MCBSP_SPCR_XRST : ~DAVINCI_MCBSP_SPCR_RRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - toggle_clock(dev, playback); + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST | + DAVINCI_MCBSP_SPCR_FRST, 0); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0); + else + MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 0); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); } static int davinci_i2s_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *cpu_dai) + struct snd_soc_dai *dai) { - struct davinci_mcbsp_dev *dev = cpu_dai->private_data; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; + cpu_dai->dma_data = dev->dma_params[substream->stream]; + return 0; } @@ -231,11 +228,12 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, struct davinci_mcbsp_dev *dev = cpu_dai->private_data; unsigned int pcr; unsigned int srgr; + unsigned int rcr; + unsigned int xcr; srgr = DAVINCI_MCBSP_SRGR_FSGM | DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) | DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1); - /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: /* cpu is master */ @@ -260,8 +258,11 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, return -EINVAL; } - /* interface format */ + rcr = DAVINCI_MCBSP_RCR_RFRLEN1(1); + xcr = DAVINCI_MCBSP_XCR_XFIG | DAVINCI_MCBSP_XCR_XFRLEN1(1); switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_B: + break; case SND_SOC_DAIFMT_I2S: /* Davinci doesn't support TRUE I2S, but some codecs will have * the left and right channels contiguous. This allows @@ -281,10 +282,8 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, */ fmt ^= SND_SOC_DAIFMT_NB_IF; case SND_SOC_DAIFMT_DSP_A: - dev->mode = MOD_DSP_A; - break; - case SND_SOC_DAIFMT_DSP_B: - dev->mode = MOD_DSP_B; + rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1); + xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1); break; default: printk(KERN_ERR "%s:bad format\n", __func__); @@ -344,8 +343,9 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, return -EINVAL; } davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); - dev->pcr = pcr; davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr); return 0; } @@ -353,40 +353,31 @@ 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; - u32 spcr; + u32 w; /* general line settings */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - spcr |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); + w |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE; + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); } else { - spcr |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); + w |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE; + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); } i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); - srgr = DAVINCI_MCBSP_SRGR_FSGM; - srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1); + w = DAVINCI_MCBSP_SRGR_FSGM; + MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1), 1); i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS); - srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1); - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); + MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1), 1); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w); - rcr = DAVINCI_MCBSP_RCR_RFIG; - xcr = DAVINCI_MCBSP_XCR_XFIG; - if (dev->mode == MOD_DSP_B) { - rcr |= DAVINCI_MCBSP_RCR_RDATDLY(0); - xcr |= DAVINCI_MCBSP_XCR_XDATDLY(0); - } else { - rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1); - xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1); - } /* Determine xfer data type */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: @@ -406,30 +397,18 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(1); - xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(1); - - rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) | - DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length); - xcr |= DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) | - DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length); + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG); + MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) | + DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr); - else - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr); - return 0; -} + } else { + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG); + MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) | + DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w); -static int davinci_i2s_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct davinci_mcbsp_dev *dev = dai->private_data; - int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - davinci_mcbsp_stop(dev, playback); - if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) { - /* codec is master */ - davinci_mcbsp_start(dev, substream); } return 0; } @@ -437,72 +416,35 @@ 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; int ret = 0; - int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) - return 0; /* return if codec is master */ switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - davinci_mcbsp_start(dev, substream); + davinci_mcbsp_start(substream); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - davinci_mcbsp_stop(dev, playback); + davinci_mcbsp_stop(substream); break; default: ret = -EINVAL; } - return ret; -} -static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct davinci_mcbsp_dev *dev = dai->private_data; - int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - davinci_mcbsp_stop(dev, playback); + return ret; } -#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 +466,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 +476,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 +498,62 @@ 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, + .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..f0a2d4071998 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)) diff --git a/trunk/sound/soc/fsl/mpc5200_psc_ac97.c b/trunk/sound/soc/fsl/mpc5200_psc_ac97.c index c4ae3e096bb9..7eb549985d49 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 @@ -113,7 +112,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..b771238662b6 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 @@ -80,11 +72,4 @@ config SND_OMAP_SOC_OMAP3_BEAGLE help Say Y if you want to add support for SoC audio on the Beagleboard. -config SND_OMAP_SOC_ZOOM2 - tristate "SoC Audio support for Zoom2" - depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_ZOOM2 - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for Soc audio on Zoom2 board. diff --git a/trunk/sound/soc/omap/Makefile b/trunk/sound/soc/omap/Makefile index 02d69471dcb5..a37f49862389 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 @@ -15,10 +14,8 @@ snd-soc-omap3evm-objs := omap3evm.o snd-soc-sdp3430-objs := sdp3430.o snd-soc-omap3pandora-objs := omap3pandora.o 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 @@ -26,4 +23,3 @@ obj-$(CONFIG_MACH_OMAP3EVM) += snd-soc-omap3evm.o obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o -obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.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 a5d46a7b196a..6a837ffd5d0b 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; + int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (!mcbsp_data->active++) - omap_mcbsp_start(mcbsp_data->bus_id); + mcbsp_data->active++; + omap_mcbsp_start(mcbsp_data->bus_id, play, !play); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (!--mcbsp_data->active) - omap_mcbsp_stop(mcbsp_data->bus_id); + omap_mcbsp_stop(mcbsp_data->bus_id, play, !play); + mcbsp_data->active--; 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..b719e5db4f57 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, @@ -100,7 +96,7 @@ static int sdp3430_hw_voice_params(struct snd_pcm_substream *substream, ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM); + SND_SOC_DAIFMT_CBS_CFM); if (ret) { printk(KERN_ERR "can't set codec DAI configuration\n"); return ret; @@ -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/omap/zoom2.c b/trunk/sound/soc/omap/zoom2.c deleted file mode 100644 index f90b45f56220..000000000000 --- a/trunk/sound/soc/omap/zoom2.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * zoom2.c -- SoC audio for Zoom2 - * - * Author: Misael Lopez Cruz - * - * 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 -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" -#include "../codecs/twl4030.h" - -#define ZOOM2_HEADSET_MUX_GPIO (OMAP_MAX_GPIO_LINES + 15) -#define ZOOM2_HEADSET_EXTMUTE_GPIO 153 - -static int zoom2_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; - int ret; - - /* 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) { - printk(KERN_ERR "can't set codec DAI configuration\n"); - 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) { - printk(KERN_ERR "can't set cpu DAI configuration\n"); - return ret; - } - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops zoom2_ops = { - .hw_params = zoom2_hw_params, -}; - -static int zoom2_hw_voice_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; - int ret; - - /* Set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (ret) { - printk(KERN_ERR "can't set codec DAI configuration\n"); - return ret; - } - - /* Set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, - SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) { - printk(KERN_ERR "can't set cpu DAI configuration\n"); - return ret; - } - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops zoom2_voice_ops = { - .hw_params = zoom2_hw_voice_params, -}; - -/* Zoom2 machine DAPM */ -static const struct snd_soc_dapm_widget zoom2_twl4030_dapm_widgets[] = { - SND_SOC_DAPM_MIC("Ext Mic", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_HP("Headset Stereophone", NULL), - SND_SOC_DAPM_LINE("Aux In", NULL), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /* External Mics: MAINMIC, SUBMIC with bias*/ - {"MAINMIC", NULL, "Mic Bias 1"}, - {"SUBMIC", NULL, "Mic Bias 2"}, - {"Mic Bias 1", NULL, "Ext Mic"}, - {"Mic Bias 2", NULL, "Ext Mic"}, - - /* External Speakers: HFL, HFR */ - {"Ext Spk", NULL, "HFL"}, - {"Ext Spk", NULL, "HFR"}, - - /* Headset Stereophone: HSOL, HSOR */ - {"Headset Stereophone", NULL, "HSOL"}, - {"Headset Stereophone", NULL, "HSOR"}, - - /* Headset Mic: HSMIC with bias */ - {"HSMIC", NULL, "Headset Mic Bias"}, - {"Headset Mic Bias", NULL, "Headset Mic"}, - - /* Aux In: AUXL, AUXR */ - {"Aux In", NULL, "AUXL"}, - {"Aux In", NULL, "AUXR"}, -}; - -static int zoom2_twl4030_init(struct snd_soc_codec *codec) -{ - int ret; - - /* Add Zoom2 specific widgets */ - ret = snd_soc_dapm_new_controls(codec, zoom2_twl4030_dapm_widgets, - ARRAY_SIZE(zoom2_twl4030_dapm_widgets)); - if (ret) - return ret; - - /* Set up Zoom2 specific audio path audio_map */ - snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - - /* Zoom2 connected pins */ - snd_soc_dapm_enable_pin(codec, "Ext Mic"); - snd_soc_dapm_enable_pin(codec, "Ext Spk"); - snd_soc_dapm_enable_pin(codec, "Headset Mic"); - snd_soc_dapm_enable_pin(codec, "Headset Stereophone"); - snd_soc_dapm_enable_pin(codec, "Aux In"); - - /* TWL4030 not connected pins */ - snd_soc_dapm_nc_pin(codec, "CARKITMIC"); - snd_soc_dapm_nc_pin(codec, "DIGIMIC0"); - snd_soc_dapm_nc_pin(codec, "DIGIMIC1"); - - snd_soc_dapm_nc_pin(codec, "OUTL"); - snd_soc_dapm_nc_pin(codec, "OUTR"); - snd_soc_dapm_nc_pin(codec, "EARPIECE"); - snd_soc_dapm_nc_pin(codec, "PREDRIVEL"); - snd_soc_dapm_nc_pin(codec, "PREDRIVER"); - snd_soc_dapm_nc_pin(codec, "CARKITL"); - snd_soc_dapm_nc_pin(codec, "CARKITR"); - - ret = snd_soc_dapm_sync(codec); - - return ret; -} - -static int zoom2_twl4030_voice_init(struct snd_soc_codec *codec) -{ - unsigned short reg; - - /* Enable voice interface */ - reg = codec->read(codec, TWL4030_REG_VOICE_IF); - reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN; - codec->write(codec, TWL4030_REG_VOICE_IF, reg); - - return 0; -} - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link zoom2_dai[] = { - { - .name = "TWL4030 I2S", - .stream_name = "TWL4030 Audio", - .cpu_dai = &omap_mcbsp_dai[0], - .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], - .init = zoom2_twl4030_init, - .ops = &zoom2_ops, - }, - { - .name = "TWL4030 PCM", - .stream_name = "TWL4030 Voice", - .cpu_dai = &omap_mcbsp_dai[1], - .codec_dai = &twl4030_dai[TWL4030_DAI_VOICE], - .init = zoom2_twl4030_voice_init, - .ops = &zoom2_voice_ops, - }, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_zoom2 = { - .name = "Zoom2", - .platform = &omap_soc_platform, - .dai_link = zoom2_dai, - .num_links = ARRAY_SIZE(zoom2_dai), -}; - -/* EXTMUTE callback function */ -void zoom2_set_hs_extmute(int mute) -{ - gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute); -} - -/* twl4030 setup */ -static struct twl4030_setup_data twl4030_setup = { - .ramp_delay_value = 3, /* 161 ms */ - .sysclk = 26000, - .hs_extmute = 1, - .set_hs_extmute = zoom2_set_hs_extmute, -}; - -/* Audio subsystem */ -static struct snd_soc_device zoom2_snd_devdata = { - .card = &snd_soc_zoom2, - .codec_dev = &soc_codec_dev_twl4030, - .codec_data = &twl4030_setup, -}; - -static struct platform_device *zoom2_snd_device; - -static int __init zoom2_soc_init(void) -{ - int ret; - - if (!machine_is_omap_zoom2()) { - pr_debug("Not Zoom2!\n"); - return -ENODEV; - } - printk(KERN_INFO "Zoom2 SoC init\n"); - - zoom2_snd_device = platform_device_alloc("soc-audio", -1); - if (!zoom2_snd_device) { - printk(KERN_ERR "Platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(zoom2_snd_device, &zoom2_snd_devdata); - zoom2_snd_devdata.dev = &zoom2_snd_device->dev; - *(unsigned int *)zoom2_dai[0].cpu_dai->private_data = 1; /* McBSP2 */ - *(unsigned int *)zoom2_dai[1].cpu_dai->private_data = 2; /* McBSP3 */ - - ret = platform_device_add(zoom2_snd_device); - if (ret) - goto err1; - - BUG_ON(gpio_request(ZOOM2_HEADSET_MUX_GPIO, "hs_mux") < 0); - gpio_direction_output(ZOOM2_HEADSET_MUX_GPIO, 0); - - BUG_ON(gpio_request(ZOOM2_HEADSET_EXTMUTE_GPIO, "ext_mute") < 0); - gpio_direction_output(ZOOM2_HEADSET_EXTMUTE_GPIO, 0); - - return 0; - -err1: - printk(KERN_ERR "Unable to add platform device\n"); - platform_device_put(zoom2_snd_device); - - return ret; -} -module_init(zoom2_soc_init); - -static void __exit zoom2_soc_exit(void) -{ - gpio_free(ZOOM2_HEADSET_MUX_GPIO); - gpio_free(ZOOM2_HEADSET_EXTMUTE_GPIO); - - platform_device_unregister(zoom2_snd_device); -} -module_exit(zoom2_soc_exit); - -MODULE_AUTHOR("Misael Lopez Cruz "); -MODULE_DESCRIPTION("ALSA SoC Zoom2"); -MODULE_LICENSE("GPL"); - diff --git a/trunk/sound/soc/pxa/magician.c b/trunk/sound/soc/pxa/magician.c index 8889cd371608..326955dea36c 100644 --- a/trunk/sound/soc/pxa/magician.c +++ b/trunk/sound/soc/pxa/magician.c @@ -20,14 +20,12 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include @@ -449,47 +447,34 @@ static struct snd_soc_card snd_soc_card_magician = { .platform = &pxa2xx_soc_platform, }; +/* magician audio private data */ +static struct uda1380_setup_data magician_uda1380_setup = { + .i2c_address = 0x18, + .dac_clk = UDA1380_DAC_CLK_WSPLL, +}; + /* magician audio subsystem */ static struct snd_soc_device magician_snd_devdata = { .card = &snd_soc_card_magician, .codec_dev = &soc_codec_dev_uda1380, + .codec_data = &magician_uda1380_setup, }; static struct platform_device *magician_snd_device; -/* - * FIXME: move into magician board file once merged into the pxa tree - */ -static struct uda1380_platform_data uda1380_info = { - .gpio_power = EGPIO_MAGICIAN_CODEC_POWER, - .gpio_reset = EGPIO_MAGICIAN_CODEC_RESET, - .dac_clk = UDA1380_DAC_CLK_WSPLL, -}; - -static struct i2c_board_info i2c_board_info[] = { - { - I2C_BOARD_INFO("uda1380", 0x18), - .platform_data = &uda1380_info, - }, -}; - static int __init magician_init(void) { int ret; - struct i2c_adapter *adapter; - struct i2c_client *client; if (!machine_is_magician()) return -ENODEV; - adapter = i2c_get_adapter(0); - if (!adapter) - return -ENODEV; - client = i2c_new_device(adapter, i2c_board_info); - i2c_put_adapter(adapter); - if (!client) - return -ENODEV; - + ret = gpio_request(EGPIO_MAGICIAN_CODEC_POWER, "CODEC_POWER"); + if (ret) + goto err_request_power; + ret = gpio_request(EGPIO_MAGICIAN_CODEC_RESET, "CODEC_RESET"); + if (ret) + goto err_request_reset; ret = gpio_request(EGPIO_MAGICIAN_SPK_POWER, "SPK_POWER"); if (ret) goto err_request_spk; @@ -506,8 +491,14 @@ static int __init magician_init(void) if (ret) goto err_request_in_sel1; + gpio_set_value(EGPIO_MAGICIAN_CODEC_POWER, 1); gpio_set_value(EGPIO_MAGICIAN_IN_SEL0, 0); + /* we may need to have the clock running here - pH5 */ + gpio_set_value(EGPIO_MAGICIAN_CODEC_RESET, 1); + udelay(5); + gpio_set_value(EGPIO_MAGICIAN_CODEC_RESET, 0); + magician_snd_device = platform_device_alloc("soc-audio", -1); if (!magician_snd_device) { ret = -ENOMEM; @@ -535,6 +526,10 @@ static int __init magician_init(void) err_request_ep: gpio_free(EGPIO_MAGICIAN_SPK_POWER); err_request_spk: + gpio_free(EGPIO_MAGICIAN_CODEC_RESET); +err_request_reset: + gpio_free(EGPIO_MAGICIAN_CODEC_POWER); +err_request_power: return ret; } @@ -545,12 +540,15 @@ static void __exit magician_exit(void) gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, 0); gpio_set_value(EGPIO_MAGICIAN_EP_POWER, 0); gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, 0); + gpio_set_value(EGPIO_MAGICIAN_CODEC_POWER, 0); gpio_free(EGPIO_MAGICIAN_IN_SEL1); gpio_free(EGPIO_MAGICIAN_IN_SEL0); gpio_free(EGPIO_MAGICIAN_MIC_POWER); gpio_free(EGPIO_MAGICIAN_EP_POWER); gpio_free(EGPIO_MAGICIAN_SPK_POWER); + gpio_free(EGPIO_MAGICIAN_CODEC_RESET); + gpio_free(EGPIO_MAGICIAN_CODEC_POWER); } module_init(magician_init); 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/pxa/pxa-ssp.c b/trunk/sound/soc/pxa/pxa-ssp.c index e22c5cef8fec..19c45409d94c 100644 --- a/trunk/sound/soc/pxa/pxa-ssp.c +++ b/trunk/sound/soc/pxa/pxa-ssp.c @@ -457,27 +457,31 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, return -EINVAL; } - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - sspsp |= SSPSP_SFRMP; - break; - case SND_SOC_DAIFMT_NB_IF: - break; - case SND_SOC_DAIFMT_IB_IF: - sspsp |= SSPSP_SCMODE(2); - break; - case SND_SOC_DAIFMT_IB_NF: - sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP; - break; - default: - return -EINVAL; - } + ssp_write_reg(ssp, SSCR0, sscr0); + ssp_write_reg(ssp, SSCR1, sscr1); + ssp_write_reg(ssp, SSPSP, sspsp); switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: sscr0 |= SSCR0_PSP; sscr1 |= SSCR1_RWOT | SSCR1_TRAIL; + /* See hw_params() */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + sspsp |= SSPSP_SFRMP; + break; + case SND_SOC_DAIFMT_NB_IF: + break; + case SND_SOC_DAIFMT_IB_IF: + sspsp |= SSPSP_SCMODE(2); + break; + case SND_SOC_DAIFMT_IB_NF: + sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP; + break; + default: + return -EINVAL; + } break; case SND_SOC_DAIFMT_DSP_A: @@ -485,6 +489,22 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, case SND_SOC_DAIFMT_DSP_B: sscr0 |= SSCR0_MOD | SSCR0_PSP; sscr1 |= SSCR1_TRAIL | SSCR1_RWOT; + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + sspsp |= SSPSP_SFRMP; + break; + case SND_SOC_DAIFMT_NB_IF: + break; + case SND_SOC_DAIFMT_IB_IF: + sspsp |= SSPSP_SCMODE(2); + break; + case SND_SOC_DAIFMT_IB_NF: + sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP; + break; + default: + return -EINVAL; + } break; default: 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-core.c b/trunk/sound/soc/soc-core.c index fb8d7a766155..1d70829464ef 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 @@ -620,9 +619,8 @@ static struct snd_pcm_ops soc_pcm_ops = { #ifdef CONFIG_PM /* powers down audio subsystem for suspend */ -static int soc_suspend(struct device *dev) +static int soc_suspend(struct platform_device *pdev, pm_message_t state) { - struct platform_device *pdev = to_platform_device(dev); struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_card *card = socdev->card; struct snd_soc_platform *platform = card->platform; @@ -658,7 +656,7 @@ static int soc_suspend(struct device *dev) snd_pcm_suspend_all(card->dai_link[i].pcm); if (card->suspend_pre) - card->suspend_pre(pdev, PMSG_SUSPEND); + card->suspend_pre(pdev, state); for (i = 0; i < card->num_links; i++) { struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; @@ -684,7 +682,7 @@ static int soc_suspend(struct device *dev) } if (codec_dev->suspend) - codec_dev->suspend(pdev, PMSG_SUSPEND); + codec_dev->suspend(pdev, state); for (i = 0; i < card->num_links; i++) { struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; @@ -693,7 +691,7 @@ static int soc_suspend(struct device *dev) } if (card->suspend_post) - card->suspend_post(pdev, PMSG_SUSPEND); + card->suspend_post(pdev, state); return 0; } @@ -767,9 +765,8 @@ static void soc_resume_deferred(struct work_struct *work) } /* powers up audio subsystem after a suspend */ -static int soc_resume(struct device *dev) +static int soc_resume(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev); 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[0].cpu_dai; @@ -791,44 +788,6 @@ static int soc_resume(struct device *dev) return 0; } -/** - * snd_soc_suspend_device: Notify core of device suspend - * - * @dev: Device being suspended. - * - * In order to ensure that the entire audio subsystem is suspended in a - * coordinated fashion ASoC devices should suspend themselves when - * called by ASoC. When the standard kernel suspend process asks the - * device to suspend it should call this function to initiate a suspend - * of the entire ASoC card. - * - * \note Currently this function is stubbed out. - */ -int snd_soc_suspend_device(struct device *dev) -{ - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_suspend_device); - -/** - * snd_soc_resume_device: Notify core of device resume - * - * @dev: Device being resumed. - * - * In order to ensure that the entire audio subsystem is resumed in a - * coordinated fashion ASoC devices should resume themselves when called - * by ASoC. When the standard kernel resume process asks the device - * to resume it should call this function. Once all the components of - * the card have notified that they are ready to be resumed the card - * will be resumed. - * - * \note Currently this function is stubbed out. - */ -int snd_soc_resume_device(struct device *dev) -{ - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_resume_device); #else #define soc_suspend NULL #define soc_resume NULL @@ -1022,39 +981,16 @@ static int soc_remove(struct platform_device *pdev) return 0; } -static int soc_poweroff(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_card *card = socdev->card; - - if (!card->instantiated) - return 0; - - /* Flush out pmdown_time work - we actually do want to run it - * now, we're shutting down so no imminent restart. */ - run_delayed_work(&card->delayed_work); - - snd_soc_dapm_shutdown(socdev); - - return 0; -} - -static struct dev_pm_ops soc_pm_ops = { - .suspend = soc_suspend, - .resume = soc_resume, - .poweroff = soc_poweroff, -}; - /* ASoC platform driver */ static struct platform_driver soc_driver = { .driver = { .name = "soc-audio", .owner = THIS_MODULE, - .pm = &soc_pm_ops, }, .probe = soc_probe, .remove = soc_remove, + .suspend = soc_suspend, + .resume = soc_resume, }; /* create a new pcm */ @@ -1126,23 +1062,6 @@ static int soc_new_pcm(struct snd_soc_device *socdev, return ret; } -/** - * snd_soc_codec_volatile_register: Report if a register is volatile. - * - * @codec: CODEC to query. - * @reg: Register to query. - * - * Boolean function indiciating if a CODEC register is volatile. - */ -int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg) -{ - if (codec->volatile_register) - return codec->volatile_register(reg); - else - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register); - /* codec register dump */ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) { @@ -1156,9 +1075,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; @@ -1348,10 +1264,10 @@ EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); * Returns 1 for change else 0. */ int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg, - unsigned int mask, unsigned int value) + unsigned short mask, unsigned short value) { int change; - unsigned int old, new; + unsigned short old, new; mutex_lock(&io_mutex); old = snd_soc_read(codec, reg); @@ -1378,10 +1294,10 @@ EXPORT_SYMBOL_GPL(snd_soc_update_bits); * Returns 1 for change else 0. */ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg, - unsigned int mask, unsigned int value) + unsigned short mask, unsigned short value) { int change; - unsigned int old, new; + unsigned short old, new; mutex_lock(&io_mutex); old = snd_soc_read(codec, reg); @@ -1465,11 +1381,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); @@ -1673,7 +1586,7 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, bitmask; + unsigned short val, bitmask; for (bitmask = 1; bitmask < e->max; bitmask <<= 1) ; @@ -1702,8 +1615,8 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val; - unsigned int mask, bitmask; + unsigned short val; + unsigned short mask, bitmask; for (bitmask = 1; bitmask < e->max; bitmask <<= 1) ; @@ -1739,7 +1652,7 @@ int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int reg_val, val, mux; + unsigned short reg_val, val, mux; reg_val = snd_soc_read(codec, e->reg); val = (reg_val >> e->shift_l) & e->mask; @@ -1778,8 +1691,8 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val; - unsigned int mask; + unsigned short val; + unsigned short mask; if (ucontrol->value.enumerated.item[0] > e->max - 1) return -EINVAL; @@ -1939,7 +1852,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, int max = mc->max; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; - unsigned int val, val2, val_mask; + unsigned short val, val2, val_mask; val = (ucontrol->value.integer.value[0] & mask); if (invert) @@ -2005,7 +1918,7 @@ int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol, unsigned int reg2 = mc->rreg; unsigned int shift = mc->shift; int max = mc->max; - unsigned int mask = (1 << fls(max)) - 1; + unsigned int mask = (1<invert; ucontrol->value.integer.value[0] = @@ -2045,7 +1958,7 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol, unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; int err; - unsigned int val, val2, val_mask; + unsigned short val, val2, val_mask; val_mask = mask << shift; val = (ucontrol->value.integer.value[0] & mask); @@ -2137,7 +2050,7 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); unsigned int reg = mc->reg; int min = mc->min; - unsigned int val; + unsigned short val; val = (ucontrol->value.integer.value[0]+min) & 0xff; val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8; diff --git a/trunk/sound/soc/soc-dapm.c b/trunk/sound/soc/soc-dapm.c index c68c204a48ad..21c69074aa17 100644 --- a/trunk/sound/soc/soc-dapm.c +++ b/trunk/sound/soc/soc-dapm.c @@ -52,37 +52,19 @@ /* dapm power sequences - make this per codec in the future */ static int dapm_up_seq[] = { - [snd_soc_dapm_pre] = 0, - [snd_soc_dapm_supply] = 1, - [snd_soc_dapm_micbias] = 2, - [snd_soc_dapm_mic] = 3, - [snd_soc_dapm_mux] = 4, - [snd_soc_dapm_value_mux] = 4, - [snd_soc_dapm_dac] = 5, - [snd_soc_dapm_mixer] = 6, - [snd_soc_dapm_mixer_named_ctl] = 6, - [snd_soc_dapm_pga] = 7, - [snd_soc_dapm_adc] = 8, - [snd_soc_dapm_hp] = 9, - [snd_soc_dapm_spk] = 10, - [snd_soc_dapm_post] = 11, + snd_soc_dapm_pre, snd_soc_dapm_supply, snd_soc_dapm_micbias, + snd_soc_dapm_mic, snd_soc_dapm_mux, snd_soc_dapm_value_mux, + snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl, + snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, + snd_soc_dapm_post }; static int dapm_down_seq[] = { - [snd_soc_dapm_pre] = 0, - [snd_soc_dapm_adc] = 1, - [snd_soc_dapm_hp] = 2, - [snd_soc_dapm_spk] = 3, - [snd_soc_dapm_pga] = 4, - [snd_soc_dapm_mixer_named_ctl] = 5, - [snd_soc_dapm_mixer] = 5, - [snd_soc_dapm_dac] = 6, - [snd_soc_dapm_mic] = 7, - [snd_soc_dapm_micbias] = 8, - [snd_soc_dapm_mux] = 9, - [snd_soc_dapm_value_mux] = 9, - [snd_soc_dapm_supply] = 10, - [snd_soc_dapm_post] = 11, + snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, + snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer, + snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias, + snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_supply, + snd_soc_dapm_post }; static void pop_wait(u32 pop_time) @@ -286,7 +268,7 @@ static int dapm_connect_mixer(struct snd_soc_codec *codec, static int dapm_update_bits(struct snd_soc_dapm_widget *widget) { int change, power; - unsigned int old, new; + unsigned short old, new; struct snd_soc_codec *codec = widget->codec; /* check for valid widgets */ @@ -707,211 +689,53 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w) return power; } -static int dapm_seq_compare(struct snd_soc_dapm_widget *a, - struct snd_soc_dapm_widget *b, - int sort[]) -{ - if (sort[a->id] != sort[b->id]) - return sort[a->id] - sort[b->id]; - if (a->reg != b->reg) - return a->reg - b->reg; - - return 0; -} - -/* Insert a widget in order into a DAPM power sequence. */ -static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget, - struct list_head *list, - int sort[]) -{ - struct snd_soc_dapm_widget *w; - - list_for_each_entry(w, list, power_list) - if (dapm_seq_compare(new_widget, w, sort) < 0) { - list_add_tail(&new_widget->power_list, &w->power_list); - return; - } - - list_add_tail(&new_widget->power_list, list); -} - -/* Apply the coalesced changes from a DAPM sequence */ -static void dapm_seq_run_coalesced(struct snd_soc_codec *codec, - struct list_head *pending) +/* + * Scan a single DAPM widget for a complete audio path and update the + * power status appropriately. + */ +static int dapm_power_widget(struct snd_soc_codec *codec, int event, + struct snd_soc_dapm_widget *w) { - struct snd_soc_dapm_widget *w; - int reg, power, ret; - unsigned int value = 0; - unsigned int mask = 0; - unsigned int cur_mask; - - reg = list_first_entry(pending, struct snd_soc_dapm_widget, - power_list)->reg; + int ret; - list_for_each_entry(w, pending, power_list) { - cur_mask = 1 << w->shift; - BUG_ON(reg != w->reg); + switch (w->id) { + case snd_soc_dapm_pre: + if (!w->event) + return 0; - if (w->invert) - power = !w->power; - else - power = w->power; - - mask |= cur_mask; - if (power) - value |= cur_mask; - - pop_dbg(codec->pop_time, - "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n", - w->name, reg, value, mask); - - /* power up pre event */ - if (w->power && w->event && - (w->event_flags & SND_SOC_DAPM_PRE_PMU)) { - pop_dbg(codec->pop_time, "pop test : %s PRE_PMU\n", - w->name); - ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU); + if (event == SND_SOC_DAPM_STREAM_START) { + ret = w->event(w, + NULL, SND_SOC_DAPM_PRE_PMU); if (ret < 0) - pr_err("%s: pre event failed: %d\n", - w->name, ret); - } - - /* power down pre event */ - if (!w->power && w->event && - (w->event_flags & SND_SOC_DAPM_PRE_PMD)) { - pop_dbg(codec->pop_time, "pop test : %s PRE_PMD\n", - w->name); - ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD); + return ret; + } else if (event == SND_SOC_DAPM_STREAM_STOP) { + ret = w->event(w, + NULL, SND_SOC_DAPM_PRE_PMD); if (ret < 0) - pr_err("%s: pre event failed: %d\n", - w->name, ret); + return ret; } + return 0; - /* Lower PGA volume to reduce pops */ - if (w->id == snd_soc_dapm_pga && !w->power) - dapm_set_pga(w, w->power); - } - - if (reg >= 0) { - pop_dbg(codec->pop_time, - "pop test : Applying 0x%x/0x%x to %x in %dms\n", - value, mask, reg, codec->pop_time); - pop_wait(codec->pop_time); - snd_soc_update_bits(codec, reg, mask, value); - } - - list_for_each_entry(w, pending, power_list) { - /* Raise PGA volume to reduce pops */ - if (w->id == snd_soc_dapm_pga && w->power) - dapm_set_pga(w, w->power); + case snd_soc_dapm_post: + if (!w->event) + return 0; - /* power up post event */ - if (w->power && w->event && - (w->event_flags & SND_SOC_DAPM_POST_PMU)) { - pop_dbg(codec->pop_time, "pop test : %s POST_PMU\n", - w->name); + if (event == SND_SOC_DAPM_STREAM_START) { ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMU); if (ret < 0) - pr_err("%s: post event failed: %d\n", - w->name, ret); - } - - /* power down post event */ - if (!w->power && w->event && - (w->event_flags & SND_SOC_DAPM_POST_PMD)) { - pop_dbg(codec->pop_time, "pop test : %s POST_PMD\n", - w->name); - ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD); + return ret; + } else if (event == SND_SOC_DAPM_STREAM_STOP) { + ret = w->event(w, + NULL, SND_SOC_DAPM_POST_PMD); if (ret < 0) - pr_err("%s: post event failed: %d\n", - w->name, ret); - } - } -} - -/* Apply a DAPM power sequence. - * - * We walk over a pre-sorted list of widgets to apply power to. In - * order to minimise the number of writes to the device required - * multiple widgets will be updated in a single write where possible. - * Currently anything that requires more than a single write is not - * handled. - */ -static void dapm_seq_run(struct snd_soc_codec *codec, struct list_head *list, - int event, int sort[]) -{ - struct snd_soc_dapm_widget *w, *n; - LIST_HEAD(pending); - int cur_sort = -1; - int cur_reg = SND_SOC_NOPM; - int ret; - - list_for_each_entry_safe(w, n, list, power_list) { - ret = 0; - - /* Do we need to apply any queued changes? */ - if (sort[w->id] != cur_sort || w->reg != cur_reg) { - if (!list_empty(&pending)) - dapm_seq_run_coalesced(codec, &pending); - - INIT_LIST_HEAD(&pending); - cur_sort = -1; - cur_reg = SND_SOC_NOPM; - } - - switch (w->id) { - case snd_soc_dapm_pre: - if (!w->event) - list_for_each_entry_safe_continue(w, n, list, - power_list); - - if (event == SND_SOC_DAPM_STREAM_START) - ret = w->event(w, - NULL, SND_SOC_DAPM_PRE_PMU); - else if (event == SND_SOC_DAPM_STREAM_STOP) - ret = w->event(w, - NULL, SND_SOC_DAPM_PRE_PMD); - break; - - case snd_soc_dapm_post: - if (!w->event) - list_for_each_entry_safe_continue(w, n, list, - power_list); - - if (event == SND_SOC_DAPM_STREAM_START) - ret = w->event(w, - NULL, SND_SOC_DAPM_POST_PMU); - else if (event == SND_SOC_DAPM_STREAM_STOP) - ret = w->event(w, - NULL, SND_SOC_DAPM_POST_PMD); - break; - - case snd_soc_dapm_input: - case snd_soc_dapm_output: - case snd_soc_dapm_hp: - case snd_soc_dapm_mic: - case snd_soc_dapm_line: - case snd_soc_dapm_spk: - /* No register support currently */ - ret = dapm_generic_apply_power(w); - break; - - default: - /* Queue it up for application */ - cur_sort = sort[w->id]; - cur_reg = w->reg; - list_move(&w->power_list, &pending); - break; + return ret; } + return 0; - if (ret < 0) - pr_err("Failed to apply widget power: %d\n", - ret); + default: + return dapm_generic_apply_power(w); } - - if (!list_empty(&pending)) - dapm_seq_run_coalesced(codec, &pending); } /* @@ -927,22 +751,23 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) { struct snd_soc_device *socdev = codec->socdev; struct snd_soc_dapm_widget *w; - LIST_HEAD(up_list); - LIST_HEAD(down_list); int ret = 0; - int power; + int i, power; int sys_power = 0; + INIT_LIST_HEAD(&codec->up_list); + INIT_LIST_HEAD(&codec->down_list); + /* Check which widgets we need to power and store them in * lists indicating if they should be powered up or down. */ list_for_each_entry(w, &codec->dapm_widgets, list) { switch (w->id) { case snd_soc_dapm_pre: - dapm_seq_insert(w, &down_list, dapm_down_seq); + list_add_tail(&codec->down_list, &w->power_list); break; case snd_soc_dapm_post: - dapm_seq_insert(w, &up_list, dapm_up_seq); + list_add_tail(&codec->up_list, &w->power_list); break; default: @@ -957,9 +782,10 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) continue; if (power) - dapm_seq_insert(w, &up_list, dapm_up_seq); + list_add_tail(&w->power_list, &codec->up_list); else - dapm_seq_insert(w, &down_list, dapm_down_seq); + list_add_tail(&w->power_list, + &codec->down_list); w->power = power; break; @@ -976,10 +802,32 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) } /* Power down widgets first; try to avoid amplifying pops. */ - dapm_seq_run(codec, &down_list, event, dapm_down_seq); + for (i = 0; i < ARRAY_SIZE(dapm_down_seq); i++) { + list_for_each_entry(w, &codec->down_list, power_list) { + /* is widget in stream order */ + if (w->id != dapm_down_seq[i]) + continue; + + ret = dapm_power_widget(codec, event, w); + if (ret != 0) + pr_err("Failed to power down %s: %d\n", + w->name, ret); + } + } /* Now power up. */ - dapm_seq_run(codec, &up_list, event, dapm_up_seq); + for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) { + list_for_each_entry(w, &codec->up_list, power_list) { + /* is widget in stream order */ + if (w->id != dapm_up_seq[i]) + continue; + + ret = dapm_power_widget(codec, event, w); + if (ret != 0) + pr_err("Failed to power up %s: %d\n", + w->name, ret); + } + } /* If we just powered the last thing off drop to standby bias */ if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) { @@ -997,9 +845,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 +1138,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) { @@ -1527,7 +1372,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, int max = mc->max; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; - unsigned int val, val2, val_mask; + unsigned short val, val2, val_mask; int ret; val = (ucontrol->value.integer.value[0] & mask); @@ -1591,7 +1436,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, bitmask; + unsigned short val, bitmask; for (bitmask = 1; bitmask < e->max; bitmask <<= 1) ; @@ -1619,8 +1464,8 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, mux; - unsigned int mask, bitmask; + unsigned short val, mux; + unsigned short mask, bitmask; int ret = 0; for (bitmask = 1; bitmask < e->max; bitmask <<= 1) @@ -1678,7 +1523,7 @@ int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int reg_val, val, mux; + unsigned short reg_val, val, mux; reg_val = snd_soc_read(widget->codec, e->reg); val = (reg_val >> e->shift_l) & e->mask; @@ -1718,8 +1563,8 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, mux; - unsigned int mask; + unsigned short val, mux; + unsigned short mask; int ret = 0; if (ucontrol->value.enumerated.item[0] > e->max - 1) @@ -2035,36 +1880,6 @@ void snd_soc_dapm_free(struct snd_soc_device *socdev) } EXPORT_SYMBOL_GPL(snd_soc_dapm_free); -/* - * snd_soc_dapm_shutdown - callback for system shutdown - */ -void snd_soc_dapm_shutdown(struct snd_soc_device *socdev) -{ - struct snd_soc_codec *codec = socdev->card->codec; - struct snd_soc_dapm_widget *w; - LIST_HEAD(down_list); - int powerdown = 0; - - list_for_each_entry(w, &codec->dapm_widgets, list) { - if (w->power) { - dapm_seq_insert(w, &down_list, dapm_down_seq); - w->power = 0; - powerdown = 1; - } - } - - /* If there were no widgets to power down we're already in - * standby. - */ - if (powerdown) { - snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_PREPARE); - dapm_seq_run(codec, &down_list, 0, dapm_down_seq); - snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_STANDBY); - } - - snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF); -} - /* Module information */ MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk"); MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC"); 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; diff --git a/trunk/sound/soc/txx9/txx9aclc.c b/trunk/sound/soc/txx9/txx9aclc.c index efed64b8b026..938a58a5a244 100644 --- a/trunk/sound/soc/txx9/txx9aclc.c +++ b/trunk/sound/soc/txx9/txx9aclc.c @@ -297,17 +297,15 @@ static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, static bool filter(struct dma_chan *chan, void *param) { struct txx9aclc_dmadata *dmadata = param; - char *devname; - bool found = false; + char devname[20 + 2]; /* FIXME: old BUS_ID_SIZE + 2 */ - devname = kasprintf(GFP_KERNEL, "%s.%d", dmadata->dma_res->name, + snprintf(devname, sizeof(devname), "%s.%d", dmadata->dma_res->name, (int)dmadata->dma_res->start); if (strcmp(dev_name(chan->device->dev), devname) == 0) { chan->private = &dmadata->dma_slave; - found = true; + return true; } - kfree(devname); - return found; + return false; } static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,