aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-07-19 02:03:20 -0400
committerTakashi Iwai <tiwai@suse.de>2012-07-19 02:03:20 -0400
commit4609ed6b1f0ab9f11a9d0361573b53d9d057c440 (patch)
tree802119cc6ddea286bc03d56431286ac52166352e
parent639aa4bd58582f3015ae5621b7e9e754dcb58e6b (diff)
parent409b78cc17a4a3d07a541037575da648ced99437 (diff)
Merge tag 'asoc-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-next
ASoC: Updates for 3.6 This has been a pretty quiet release - very little activity in framework terms, mostly just a few new drivers and updates: - Added the ability to add and remove DAPM paths dynamically, mostly for reparenting on clock changes. - New machine drivers for Marvell Brownstone, ST-Ericsson Ux500 reference platform and ttc-dkp. - New CPU drivers for Blackfin BF6xx SPORTs in I2S mode, Marvell MMP, Synopsis Designware I2S controllers, and SPEAr DMA and S/PDIF - New CODEC drivers for Dialog DA732x, ST STA529, ST-Ericsson AB8500, TI Isabelle and Wolfson Microelectronics WM5102 and WM5110
-rw-r--r--MAINTAINERS2
-rw-r--r--arch/arm/mach-ux500/board-mop500.c14
-rw-r--r--include/linux/dmaengine.h6
-rw-r--r--include/linux/mfd/abx500/ab8500-codec.h52
-rw-r--r--include/linux/mfd/abx500/ab8500.h2
-rw-r--r--include/linux/platform_data/mmp_audio.h22
-rw-r--r--include/sound/designware_i2s.h69
-rw-r--r--include/sound/dmaengine_pcm.h1
-rw-r--r--include/sound/pcm.h11
-rw-r--r--include/sound/soc-dapm.h12
-rw-r--r--include/sound/soc.h77
-rw-r--r--include/sound/spear_dma.h35
-rw-r--r--include/sound/spear_spdif.h29
-rw-r--r--sound/soc/Kconfig1
-rw-r--r--sound/soc/Makefile1
-rw-r--r--sound/soc/blackfin/Kconfig21
-rw-r--r--sound/soc/blackfin/Makefile4
-rw-r--r--sound/soc/blackfin/bf6xx-i2s.c234
-rw-r--r--sound/soc/blackfin/bf6xx-sport.c422
-rw-r--r--sound/soc/blackfin/bf6xx-sport.h82
-rw-r--r--sound/soc/codecs/Kconfig31
-rw-r--r--sound/soc/codecs/Makefile19
-rw-r--r--sound/soc/codecs/ab8500-codec.c2522
-rw-r--r--sound/soc/codecs/ab8500-codec.h590
-rw-r--r--sound/soc/codecs/ac97.c6
-rw-r--r--sound/soc/codecs/arizona.c937
-rw-r--r--sound/soc/codecs/arizona.h159
-rw-r--r--sound/soc/codecs/cs42l52.c19
-rw-r--r--sound/soc/codecs/cs42l73.c20
-rw-r--r--sound/soc/codecs/da732x.c1627
-rw-r--r--sound/soc/codecs/da732x.h133
-rw-r--r--sound/soc/codecs/da732x_reg.h654
-rw-r--r--sound/soc/codecs/isabelle.c1176
-rw-r--r--sound/soc/codecs/isabelle.h143
-rw-r--r--sound/soc/codecs/lm49453.c3
-rw-r--r--sound/soc/codecs/max98095.c5
-rw-r--r--sound/soc/codecs/ml26124.c5
-rw-r--r--sound/soc/codecs/spdif_receiver.c67
-rw-r--r--sound/soc/codecs/sta529.c442
-rw-r--r--sound/soc/codecs/tlv320aic3x.c40
-rw-r--r--sound/soc/codecs/tlv320aic3x.h27
-rw-r--r--sound/soc/codecs/twl6040.c2
-rw-r--r--sound/soc/codecs/wm1250-ev1.c7
-rw-r--r--sound/soc/codecs/wm2000.c32
-rw-r--r--sound/soc/codecs/wm5100-tables.c2
-rw-r--r--sound/soc/codecs/wm5100.c11
-rw-r--r--sound/soc/codecs/wm5102.c903
-rw-r--r--sound/soc/codecs/wm5102.h21
-rw-r--r--sound/soc/codecs/wm5110.c950
-rw-r--r--sound/soc/codecs/wm5110.h21
-rw-r--r--sound/soc/codecs/wm8350.c22
-rw-r--r--sound/soc/codecs/wm8400.c2
-rw-r--r--sound/soc/codecs/wm8580.c2
-rw-r--r--sound/soc/codecs/wm8731.c1
-rw-r--r--sound/soc/codecs/wm8741.c2
-rw-r--r--sound/soc/codecs/wm8753.c2
-rw-r--r--sound/soc/codecs/wm8776.c2
-rw-r--r--sound/soc/codecs/wm8804.c2
-rw-r--r--sound/soc/codecs/wm8903.c316
-rw-r--r--sound/soc/codecs/wm8904.c272
-rw-r--r--sound/soc/codecs/wm8960.c2
-rw-r--r--sound/soc/codecs/wm8961.c2
-rw-r--r--sound/soc/codecs/wm8962.c8
-rw-r--r--sound/soc/codecs/wm8993.c2
-rw-r--r--sound/soc/codecs/wm8994.c46
-rw-r--r--sound/soc/codecs/wm8996.c587
-rw-r--r--sound/soc/codecs/wm9081.c2
-rw-r--r--sound/soc/codecs/wm9090.c2
-rw-r--r--sound/soc/codecs/wm9712.c2
-rw-r--r--sound/soc/codecs/wm9713.c2
-rw-r--r--sound/soc/codecs/wm_hubs.c2
-rw-r--r--sound/soc/dwc/Kconfig9
-rw-r--r--sound/soc/dwc/Makefile3
-rw-r--r--sound/soc/dwc/designware_i2s.c455
-rw-r--r--sound/soc/ep93xx/ep93xx-pcm.c2
-rw-r--r--sound/soc/fsl/imx-audmux.c2
-rw-r--r--sound/soc/fsl/imx-audmux.h1
-rw-r--r--sound/soc/fsl/imx-mc13783.c49
-rw-r--r--sound/soc/fsl/imx-pcm-dma.c2
-rw-r--r--sound/soc/fsl/imx-sgtl5000.c3
-rw-r--r--sound/soc/mxs/mxs-pcm.c2
-rw-r--r--sound/soc/mxs/mxs-sgtl5000.c2
-rw-r--r--sound/soc/pxa/Kconfig42
-rw-r--r--sound/soc/pxa/Makefile8
-rw-r--r--sound/soc/pxa/brownstone.c174
-rw-r--r--sound/soc/pxa/mmp-pcm.c297
-rw-r--r--sound/soc/pxa/mmp-sspa.c480
-rw-r--r--sound/soc/pxa/mmp-sspa.h92
-rw-r--r--sound/soc/pxa/ttc-dkb.c173
-rw-r--r--sound/soc/samsung/littlemill.c7
-rw-r--r--sound/soc/samsung/s3c2412-i2s.c10
-rw-r--r--sound/soc/samsung/s3c24xx-i2s.c10
-rw-r--r--sound/soc/samsung/smdk_wm8994.c36
-rw-r--r--sound/soc/sh/fsi.c48
-rw-r--r--sound/soc/soc-core.c328
-rw-r--r--sound/soc/soc-dapm.c164
-rw-r--r--sound/soc/soc-dmaengine-pcm.c33
-rw-r--r--sound/soc/soc-io.c15
-rw-r--r--sound/soc/soc-pcm.c12
-rw-r--r--sound/soc/spear/spdif_in.c297
-rw-r--r--sound/soc/spear/spdif_in_regs.h60
-rw-r--r--sound/soc/spear/spdif_out.c389
-rw-r--r--sound/soc/spear/spdif_out_regs.h79
-rw-r--r--sound/soc/spear/spear_pcm.c214
-rw-r--r--sound/soc/tegra/Kconfig3
-rw-r--r--sound/soc/tegra/tegra20_i2s.c94
-rw-r--r--sound/soc/tegra/tegra20_i2s.h1
-rw-r--r--sound/soc/tegra/tegra20_spdif.c36
-rw-r--r--sound/soc/tegra/tegra20_spdif.h1
-rw-r--r--sound/soc/tegra/tegra30_i2s.c85
-rw-r--r--sound/soc/tegra/tegra30_i2s.h1
-rw-r--r--sound/soc/tegra/tegra_alc5632.c32
-rw-r--r--sound/soc/tegra/tegra_pcm.c115
-rw-r--r--sound/soc/tegra/tegra_pcm.h2
-rw-r--r--sound/soc/tegra/tegra_wm8753.c8
-rw-r--r--sound/soc/tegra/tegra_wm8903.c259
-rw-r--r--sound/soc/tegra/trimslice.c30
-rw-r--r--sound/soc/ux500/Kconfig18
-rw-r--r--sound/soc/ux500/Makefile6
-rw-r--r--sound/soc/ux500/mop500.c113
-rw-r--r--sound/soc/ux500/mop500_ab8500.c431
-rw-r--r--sound/soc/ux500/mop500_ab8500.h22
-rw-r--r--sound/soc/ux500/ux500_msp_dai.c2
-rw-r--r--sound/soc/ux500/ux500_msp_i2s.c2
-rw-r--r--sound/soc/ux500/ux500_pcm.c318
-rw-r--r--sound/soc/ux500/ux500_pcm.h35
126 files changed, 16719 insertions, 1344 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index eb22272b211..02f114ac0be 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6747,9 +6747,11 @@ F: include/linux/tifm.h
6747 6747
6748TI LM49xxx FAMILY ASoC CODEC DRIVERS 6748TI LM49xxx FAMILY ASoC CODEC DRIVERS
6749M: M R Swami Reddy <mr.swami.reddy@ti.com> 6749M: M R Swami Reddy <mr.swami.reddy@ti.com>
6750M: Vishwas A Deshpande <vishwas.a.deshpande@ti.com>
6750L: alsa-devel@alsa-project.org (moderated for non-subscribers) 6751L: alsa-devel@alsa-project.org (moderated for non-subscribers)
6751S: Maintained 6752S: Maintained
6752F: sound/soc/codecs/lm49453* 6753F: sound/soc/codecs/lm49453*
6754F: sound/soc/codecs/isabelle*
6753 6755
6754TI TWL4030 SERIES SOC CODEC DRIVER 6756TI TWL4030 SERIES SOC CODEC DRIVER
6755M: Peter Ujfalusi <peter.ujfalusi@ti.com> 6757M: Peter Ujfalusi <peter.ujfalusi@ti.com>
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index 1509a3cb583..10ddfaf17f3 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -25,6 +25,7 @@
25#include <linux/mfd/tc3589x.h> 25#include <linux/mfd/tc3589x.h>
26#include <linux/mfd/tps6105x.h> 26#include <linux/mfd/tps6105x.h>
27#include <linux/mfd/abx500/ab8500-gpio.h> 27#include <linux/mfd/abx500/ab8500-gpio.h>
28#include <linux/mfd/abx500/ab8500-codec.h>
28#include <linux/leds-lp5521.h> 29#include <linux/leds-lp5521.h>
29#include <linux/input.h> 30#include <linux/input.h>
30#include <linux/smsc911x.h> 31#include <linux/smsc911x.h>
@@ -97,6 +98,18 @@ static struct ab8500_gpio_platform_data ab8500_gpio_pdata = {
97 0x7A, 0x00, 0x00}, 98 0x7A, 0x00, 0x00},
98}; 99};
99 100
101/* ab8500-codec */
102static struct ab8500_codec_platform_data ab8500_codec_pdata = {
103 .amics = {
104 .mic1_type = AMIC_TYPE_DIFFERENTIAL,
105 .mic2_type = AMIC_TYPE_DIFFERENTIAL,
106 .mic1a_micbias = AMIC_MICBIAS_VAMIC1,
107 .mic1b_micbias = AMIC_MICBIAS_VAMIC1,
108 .mic2_micbias = AMIC_MICBIAS_VAMIC2
109 },
110 .ear_cmv = EAR_CMV_0_95V
111};
112
100static struct gpio_keys_button snowball_key_array[] = { 113static struct gpio_keys_button snowball_key_array[] = {
101 { 114 {
102 .gpio = 32, 115 .gpio = 32,
@@ -195,6 +208,7 @@ static struct ab8500_platform_data ab8500_platdata = {
195 .regulator = ab8500_regulators, 208 .regulator = ab8500_regulators,
196 .num_regulator = ARRAY_SIZE(ab8500_regulators), 209 .num_regulator = ARRAY_SIZE(ab8500_regulators),
197 .gpio = &ab8500_gpio_pdata, 210 .gpio = &ab8500_gpio_pdata,
211 .codec = &ab8500_codec_pdata,
198}; 212};
199 213
200static struct resource ab8500_resources[] = { 214static struct resource ab8500_resources[] = {
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 56377df3912..cc0756a35ae 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -670,6 +670,12 @@ static inline int dmaengine_resume(struct dma_chan *chan)
670 return dmaengine_device_control(chan, DMA_RESUME, 0); 670 return dmaengine_device_control(chan, DMA_RESUME, 0);
671} 671}
672 672
673static inline enum dma_status dmaengine_tx_status(struct dma_chan *chan,
674 dma_cookie_t cookie, struct dma_tx_state *state)
675{
676 return chan->device->device_tx_status(chan, cookie, state);
677}
678
673static inline dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc) 679static inline dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc)
674{ 680{
675 return desc->tx_submit(desc); 681 return desc->tx_submit(desc);
diff --git a/include/linux/mfd/abx500/ab8500-codec.h b/include/linux/mfd/abx500/ab8500-codec.h
new file mode 100644
index 00000000000..dc6529202cd
--- /dev/null
+++ b/include/linux/mfd/abx500/ab8500-codec.h
@@ -0,0 +1,52 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2012
3 *
4 * Author: Ola Lilja <ola.o.lilja@stericsson.com>
5 * for ST-Ericsson.
6 *
7 * License terms:
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published
11 * by the Free Software Foundation.
12 */
13
14#ifndef AB8500_CORE_CODEC_H
15#define AB8500_CORE_CODEC_H
16
17/* Mic-types */
18enum amic_type {
19 AMIC_TYPE_SINGLE_ENDED,
20 AMIC_TYPE_DIFFERENTIAL
21};
22
23/* Mic-biases */
24enum amic_micbias {
25 AMIC_MICBIAS_VAMIC1,
26 AMIC_MICBIAS_VAMIC2
27};
28
29/* Bias-voltage */
30enum ear_cm_voltage {
31 EAR_CMV_0_95V,
32 EAR_CMV_1_10V,
33 EAR_CMV_1_27V,
34 EAR_CMV_1_58V
35};
36
37/* Analog microphone settings */
38struct amic_settings {
39 enum amic_type mic1_type;
40 enum amic_type mic2_type;
41 enum amic_micbias mic1a_micbias;
42 enum amic_micbias mic1b_micbias;
43 enum amic_micbias mic2_micbias;
44};
45
46/* Platform data structure for the audio-parts of the AB8500 */
47struct ab8500_codec_platform_data {
48 struct amic_settings amics;
49 enum ear_cm_voltage ear_cmv;
50};
51
52#endif
diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h
index 91dd3ef63e9..bc9b84b60ec 100644
--- a/include/linux/mfd/abx500/ab8500.h
+++ b/include/linux/mfd/abx500/ab8500.h
@@ -266,6 +266,7 @@ struct ab8500 {
266struct regulator_reg_init; 266struct regulator_reg_init;
267struct regulator_init_data; 267struct regulator_init_data;
268struct ab8500_gpio_platform_data; 268struct ab8500_gpio_platform_data;
269struct ab8500_codec_platform_data;
269 270
270/** 271/**
271 * struct ab8500_platform_data - AB8500 platform data 272 * struct ab8500_platform_data - AB8500 platform data
@@ -284,6 +285,7 @@ struct ab8500_platform_data {
284 int num_regulator; 285 int num_regulator;
285 struct regulator_init_data *regulator; 286 struct regulator_init_data *regulator;
286 struct ab8500_gpio_platform_data *gpio; 287 struct ab8500_gpio_platform_data *gpio;
288 struct ab8500_codec_platform_data *codec;
287}; 289};
288 290
289extern int __devinit ab8500_init(struct ab8500 *ab8500, 291extern int __devinit ab8500_init(struct ab8500 *ab8500,
diff --git a/include/linux/platform_data/mmp_audio.h b/include/linux/platform_data/mmp_audio.h
new file mode 100644
index 00000000000..0f25d165abd
--- /dev/null
+++ b/include/linux/platform_data/mmp_audio.h
@@ -0,0 +1,22 @@
1/*
2 * MMP Platform AUDIO Management
3 *
4 * Copyright (c) 2011 Marvell Semiconductors Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 */
11
12#ifndef MMP_AUDIO_H
13#define MMP_AUDIO_H
14
15struct mmp_audio_platdata {
16 u32 period_max_capture;
17 u32 buffer_max_capture;
18 u32 period_max_playback;
19 u32 buffer_max_playback;
20};
21
22#endif /* MMP_AUDIO_H */
diff --git a/include/sound/designware_i2s.h b/include/sound/designware_i2s.h
new file mode 100644
index 00000000000..26f406e0f67
--- /dev/null
+++ b/include/sound/designware_i2s.h
@@ -0,0 +1,69 @@
1/*
2 * Copyright (ST) 2012 Rajeev Kumar (rajeev-dlh.kumar@st.com)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 */
19
20#ifndef __SOUND_DESIGNWARE_I2S_H
21#define __SOUND_DESIGNWARE_I2S_H
22
23#include <linux/dmaengine.h>
24#include <linux/types.h>
25
26/*
27 * struct i2s_clk_config_data - represent i2s clk configuration data
28 * @chan_nr: number of channel
29 * @data_width: number of bits per sample (8/16/24/32 bit)
30 * @sample_rate: sampling frequency (8Khz, 16Khz, 32Khz, 44Khz, 48Khz)
31 */
32struct i2s_clk_config_data {
33 int chan_nr;
34 u32 data_width;
35 u32 sample_rate;
36};
37
38struct i2s_platform_data {
39 #define DWC_I2S_PLAY (1 << 0)
40 #define DWC_I2S_RECORD (1 << 1)
41 unsigned int cap;
42 int channel;
43 u32 snd_fmts;
44 u32 snd_rates;
45
46 void *play_dma_data;
47 void *capture_dma_data;
48 bool (*filter)(struct dma_chan *chan, void *slave);
49 int (*i2s_clk_cfg)(struct i2s_clk_config_data *config);
50};
51
52struct i2s_dma_data {
53 void *data;
54 dma_addr_t addr;
55 u32 max_burst;
56 enum dma_slave_buswidth addr_width;
57 bool (*filter)(struct dma_chan *chan, void *slave);
58};
59
60/* I2S DMA registers */
61#define I2S_RXDMA 0x01C0
62#define I2S_TXDMA 0x01C8
63
64#define TWO_CHANNEL_SUPPORT 2 /* up to 2.0 */
65#define FOUR_CHANNEL_SUPPORT 4 /* up to 3.1 */
66#define SIX_CHANNEL_SUPPORT 6 /* up to 5.1 */
67#define EIGHT_CHANNEL_SUPPORT 8 /* up to 7.1 */
68
69#endif /* __SOUND_DESIGNWARE_I2S_H */
diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
index a8fcaa6d531..b877334bbb0 100644
--- a/include/sound/dmaengine_pcm.h
+++ b/include/sound/dmaengine_pcm.h
@@ -39,6 +39,7 @@ int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
39 const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config); 39 const struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config);
40int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd); 40int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
41snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream); 41snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream);
42snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream);
42 43
43int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, 44int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
44 dma_filter_fn filter_fn, void *filter_data); 45 dma_filter_fn filter_fn, void *filter_data);
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index e91e6047ca6..c75c0d1a85e 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -1074,4 +1074,15 @@ static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max)
1074 1074
1075const char *snd_pcm_format_name(snd_pcm_format_t format); 1075const char *snd_pcm_format_name(snd_pcm_format_t format);
1076 1076
1077/**
1078 * Get a string naming the direction of a stream
1079 */
1080static inline const char *snd_pcm_stream_str(struct snd_pcm_substream *substream)
1081{
1082 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1083 return "Playback";
1084 else
1085 return "Capture";
1086}
1087
1077#endif /* __SOUND_PCM_H */ 1088#endif /* __SOUND_PCM_H */
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index e3833d9f191..abe373d57ad 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -229,6 +229,10 @@ struct device;
229{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \ 229{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \
230 .shift = wshift, .invert = winvert, \ 230 .shift = wshift, .invert = winvert, \
231 .event = wevent, .event_flags = wflags} 231 .event = wevent, .event_flags = wflags}
232#define SND_SOC_DAPM_CLOCK_SUPPLY(wname) \
233{ .id = snd_soc_dapm_clock_supply, .name = wname, \
234 .reg = SND_SOC_NOPM, .event = dapm_clock_event, \
235 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }
232 236
233/* generic widgets */ 237/* generic widgets */
234#define SND_SOC_DAPM_REG(wid, wname, wreg, wshift, wmask, won_val, woff_val) \ 238#define SND_SOC_DAPM_REG(wid, wname, wreg, wshift, wmask, won_val, woff_val) \
@@ -245,6 +249,7 @@ struct device;
245 .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \ 249 .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \
246 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD } 250 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }
247 251
252
248/* dapm kcontrol types */ 253/* dapm kcontrol types */
249#define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \ 254#define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \
250{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 255{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -327,6 +332,8 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
327 struct snd_kcontrol *kcontrol, int event); 332 struct snd_kcontrol *kcontrol, int event);
328int dapm_regulator_event(struct snd_soc_dapm_widget *w, 333int dapm_regulator_event(struct snd_soc_dapm_widget *w,
329 struct snd_kcontrol *kcontrol, int event); 334 struct snd_kcontrol *kcontrol, int event);
335int dapm_clock_event(struct snd_soc_dapm_widget *w,
336 struct snd_kcontrol *kcontrol, int event);
330 337
331/* dapm controls */ 338/* dapm controls */
332int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, 339int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
@@ -367,6 +374,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm);
367void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm); 374void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm);
368int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, 375int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
369 const struct snd_soc_dapm_route *route, int num); 376 const struct snd_soc_dapm_route *route, int num);
377int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm,
378 const struct snd_soc_dapm_route *route, int num);
370int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm, 379int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
371 const struct snd_soc_dapm_route *route, int num); 380 const struct snd_soc_dapm_route *route, int num);
372 381
@@ -432,6 +441,7 @@ enum snd_soc_dapm_type {
432 snd_soc_dapm_post, /* machine specific post widget - exec last */ 441 snd_soc_dapm_post, /* machine specific post widget - exec last */
433 snd_soc_dapm_supply, /* power/clock supply */ 442 snd_soc_dapm_supply, /* power/clock supply */
434 snd_soc_dapm_regulator_supply, /* external regulator */ 443 snd_soc_dapm_regulator_supply, /* external regulator */
444 snd_soc_dapm_clock_supply, /* external clock */
435 snd_soc_dapm_aif_in, /* audio interface input */ 445 snd_soc_dapm_aif_in, /* audio interface input */
436 snd_soc_dapm_aif_out, /* audio interface output */ 446 snd_soc_dapm_aif_out, /* audio interface output */
437 snd_soc_dapm_siggen, /* signal generator */ 447 snd_soc_dapm_siggen, /* signal generator */
@@ -537,6 +547,8 @@ struct snd_soc_dapm_widget {
537 struct list_head dirty; 547 struct list_head dirty;
538 int inputs; 548 int inputs;
539 int outputs; 549 int outputs;
550
551 struct clk *clk;
540}; 552};
541 553
542struct snd_soc_dapm_update { 554struct snd_soc_dapm_update {
diff --git a/include/sound/soc.h b/include/sound/soc.h
index c703871f5f6..e063380f63a 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -42,11 +42,22 @@
42 ((unsigned long)&(struct soc_mixer_control) \ 42 ((unsigned long)&(struct soc_mixer_control) \
43 {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ 43 {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
44 .max = xmax, .platform_max = xmax, .invert = xinvert}) 44 .max = xmax, .platform_max = xmax, .invert = xinvert})
45#define SOC_DOUBLE_R_RANGE_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \
46 ((unsigned long)&(struct soc_mixer_control) \
47 {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
48 .min = xmin, .max = xmax, .platform_max = xmax, .invert = xinvert})
45#define SOC_SINGLE(xname, reg, shift, max, invert) \ 49#define SOC_SINGLE(xname, reg, shift, max, invert) \
46{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 50{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
47 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ 51 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
48 .put = snd_soc_put_volsw, \ 52 .put = snd_soc_put_volsw, \
49 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } 53 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
54#define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \
55{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
56 .info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \
57 .put = snd_soc_put_volsw_range, \
58 .private_value = (unsigned long)&(struct soc_mixer_control) \
59 {.reg = xreg, .shift = xshift, .min = xmin,\
60 .max = xmax, .platform_max = xmax, .invert = xinvert} }
50#define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ 61#define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
51{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 62{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
52 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ 63 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
@@ -67,6 +78,16 @@
67 {.reg = xreg, .rreg = xreg, \ 78 {.reg = xreg, .rreg = xreg, \
68 .shift = xshift, .rshift = xshift, \ 79 .shift = xshift, .rshift = xshift, \
69 .max = xmax, .min = xmin} } 80 .max = xmax, .min = xmin} }
81#define SOC_SINGLE_RANGE_TLV(xname, xreg, xshift, xmin, xmax, xinvert, tlv_array) \
82{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
83 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
84 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
85 .tlv.p = (tlv_array), \
86 .info = snd_soc_info_volsw_range, \
87 .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \
88 .private_value = (unsigned long)&(struct soc_mixer_control) \
89 {.reg = xreg, .shift = xshift, .min = xmin,\
90 .max = xmax, .platform_max = xmax, .invert = xinvert} }
70#define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \ 91#define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \
71{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ 92{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
72 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ 93 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
@@ -79,6 +100,13 @@
79 .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ 100 .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
80 .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ 101 .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
81 xmax, xinvert) } 102 xmax, xinvert) }
103#define SOC_DOUBLE_R_RANGE(xname, reg_left, reg_right, xshift, xmin, \
104 xmax, xinvert) \
105{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
106 .info = snd_soc_info_volsw_range, \
107 .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \
108 .private_value = SOC_DOUBLE_R_RANGE_VALUE(reg_left, reg_right, \
109 xshift, xmin, xmax, xinvert) }
82#define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \ 110#define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \
83{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ 111{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
84 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ 112 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
@@ -97,6 +125,16 @@
97 .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ 125 .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
98 .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ 126 .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
99 xmax, xinvert) } 127 xmax, xinvert) }
128#define SOC_DOUBLE_R_RANGE_TLV(xname, reg_left, reg_right, xshift, xmin, \
129 xmax, xinvert, tlv_array) \
130{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
131 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
132 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
133 .tlv.p = (tlv_array), \
134 .info = snd_soc_info_volsw_range, \
135 .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \
136 .private_value = SOC_DOUBLE_R_RANGE_VALUE(reg_left, reg_right, \
137 xshift, xmin, xmax, xinvert) }
100#define SOC_DOUBLE_R_SX_TLV(xname, xreg, xrreg, xshift, xmin, xmax, tlv_array) \ 138#define SOC_DOUBLE_R_SX_TLV(xname, xreg, xrreg, xshift, xmin, xmax, tlv_array) \
101{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 139{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
102 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ 140 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
@@ -460,6 +498,12 @@ int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol,
460 struct snd_ctl_elem_value *ucontrol); 498 struct snd_ctl_elem_value *ucontrol);
461int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, 499int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
462 struct snd_ctl_elem_value *ucontrol); 500 struct snd_ctl_elem_value *ucontrol);
501int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol,
502 struct snd_ctl_elem_info *uinfo);
503int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
504 struct snd_ctl_elem_value *ucontrol);
505int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
506 struct snd_ctl_elem_value *ucontrol);
463int snd_soc_limit_volume(struct snd_soc_codec *codec, 507int snd_soc_limit_volume(struct snd_soc_codec *codec,
464 const char *name, int max); 508 const char *name, int max);
465int snd_soc_bytes_info(struct snd_kcontrol *kcontrol, 509int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
@@ -785,13 +829,36 @@ struct snd_soc_dai_link {
785 /* config - must be set by machine driver */ 829 /* config - must be set by machine driver */
786 const char *name; /* Codec name */ 830 const char *name; /* Codec name */
787 const char *stream_name; /* Stream name */ 831 const char *stream_name; /* Stream name */
788 const char *codec_name; /* for multi-codec */ 832 /*
789 const struct device_node *codec_of_node; 833 * You MAY specify the link's CPU-side device, either by device name,
790 const char *platform_name; /* for multi-platform */ 834 * or by DT/OF node, but not both. If this information is omitted,
791 const struct device_node *platform_of_node; 835 * the CPU-side DAI is matched using .cpu_dai_name only, which hence
836 * must be globally unique. These fields are currently typically used
837 * only for codec to codec links, or systems using device tree.
838 */
839 const char *cpu_name;
840 const struct device_node *cpu_of_node;
841 /*
842 * You MAY specify the DAI name of the CPU DAI. If this information is
843 * omitted, the CPU-side DAI is matched using .cpu_name/.cpu_of_node
844 * only, which only works well when that device exposes a single DAI.
845 */
792 const char *cpu_dai_name; 846 const char *cpu_dai_name;
793 const struct device_node *cpu_dai_of_node; 847 /*
848 * You MUST specify the link's codec, either by device name, or by
849 * DT/OF node, but not both.
850 */
851 const char *codec_name;
852 const struct device_node *codec_of_node;
853 /* You MUST specify the DAI name within the codec */
794 const char *codec_dai_name; 854 const char *codec_dai_name;
855 /*
856 * You MAY specify the link's platform/PCM/DMA driver, either by
857 * device name, or by DT/OF node, but not both. Some forms of link
858 * do not need a platform.
859 */
860 const char *platform_name;
861 const struct device_node *platform_of_node;
795 int be_id; /* optional ID for machine driver BE identification */ 862 int be_id; /* optional ID for machine driver BE identification */
796 863
797 const struct snd_soc_pcm_stream *params; 864 const struct snd_soc_pcm_stream *params;
diff --git a/include/sound/spear_dma.h b/include/sound/spear_dma.h
new file mode 100644
index 00000000000..1b365bfdfb3
--- /dev/null
+++ b/include/sound/spear_dma.h
@@ -0,0 +1,35 @@
1/*
2* linux/spear_dma.h
3*
4* Copyright (ST) 2012 Rajeev Kumar (rajeev-dlh.kumar@st.com)
5*
6* This program is free software; you can redistribute it and/or modify
7* it under the terms of the GNU General Public License as published by
8* the Free Software Foundation; either version 2 of the License, or
9* (at your option) any later version.
10*
11* This program is distributed in the hope that it will be useful,
12* but WITHOUT ANY WARRANTY; without even the implied warranty of
13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14* GNU General Public License for more details.
15*
16* You should have received a copy of the GNU General Public License
17* along with this program; if not, write to the Free Software
18* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19*
20*/
21
22#ifndef SPEAR_DMA_H
23#define SPEAR_DMA_H
24
25#include <linux/dmaengine.h>
26
27struct spear_dma_data {
28 void *data;
29 dma_addr_t addr;
30 u32 max_burst;
31 enum dma_slave_buswidth addr_width;
32 bool (*filter)(struct dma_chan *chan, void *slave);
33};
34
35#endif /* SPEAR_DMA_H */
diff --git a/include/sound/spear_spdif.h b/include/sound/spear_spdif.h
new file mode 100644
index 00000000000..a12f3969561
--- /dev/null
+++ b/include/sound/spear_spdif.h
@@ -0,0 +1,29 @@
1/*
2 * Copyright (ST) 2012 Vipin Kumar (vipin.kumar@st.com)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19#ifndef __SOUND_SPDIF_H
20#define __SOUND_SPDIF_H
21
22struct spear_spdif_platform_data {
23 /* DMA params */
24 void *dma_params;
25 bool (*filter)(struct dma_chan *chan, void *slave);
26 void (*reset_perip)(void);
27};
28
29#endif /* SOUND_SPDIF_H */
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 40b2ad1bb1c..c5de0a84566 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -33,6 +33,7 @@ source "sound/soc/atmel/Kconfig"
33source "sound/soc/au1x/Kconfig" 33source "sound/soc/au1x/Kconfig"
34source "sound/soc/blackfin/Kconfig" 34source "sound/soc/blackfin/Kconfig"
35source "sound/soc/davinci/Kconfig" 35source "sound/soc/davinci/Kconfig"
36source "sound/soc/dwc/Kconfig"
36source "sound/soc/ep93xx/Kconfig" 37source "sound/soc/ep93xx/Kconfig"
37source "sound/soc/fsl/Kconfig" 38source "sound/soc/fsl/Kconfig"
38source "sound/soc/jz4740/Kconfig" 39source "sound/soc/jz4740/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 70990f4017f..00a555a743b 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_SND_SOC) += atmel/
11obj-$(CONFIG_SND_SOC) += au1x/ 11obj-$(CONFIG_SND_SOC) += au1x/
12obj-$(CONFIG_SND_SOC) += blackfin/ 12obj-$(CONFIG_SND_SOC) += blackfin/
13obj-$(CONFIG_SND_SOC) += davinci/ 13obj-$(CONFIG_SND_SOC) += davinci/
14obj-$(CONFIG_SND_SOC) += dwc/
14obj-$(CONFIG_SND_SOC) += ep93xx/ 15obj-$(CONFIG_SND_SOC) += ep93xx/
15obj-$(CONFIG_SND_SOC) += fsl/ 16obj-$(CONFIG_SND_SOC) += fsl/
16obj-$(CONFIG_SND_SOC) += jz4740/ 17obj-$(CONFIG_SND_SOC) += jz4740/
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
index 9f6bc55fc39..16b88f5c26e 100644
--- a/sound/soc/blackfin/Kconfig
+++ b/sound/soc/blackfin/Kconfig
@@ -1,7 +1,8 @@
1config SND_BF5XX_I2S 1config SND_BF5XX_I2S
2 tristate "SoC I2S Audio for the ADI BF5xx chip" 2 tristate "SoC I2S Audio for the ADI Blackfin chip"
3 depends on BLACKFIN 3 depends on BLACKFIN
4 select SND_BF5XX_SOC_SPORT 4 select SND_BF5XX_SOC_SPORT if !BF60x
5 select SND_BF6XX_SOC_SPORT if BF60x
5 help 6 help
6 Say Y or M if you want to add support for codecs attached to 7 Say Y or M if you want to add support for codecs attached to
7 the Blackfin SPORT (synchronous serial ports) interface in I2S 8 the Blackfin SPORT (synchronous serial ports) interface in I2S
@@ -9,12 +10,14 @@ config SND_BF5XX_I2S
9 You will also need to select the audio interfaces to support below. 10 You will also need to select the audio interfaces to support below.
10 11
11config SND_BF5XX_SOC_SSM2602 12config SND_BF5XX_SOC_SSM2602
12 tristate "SoC SSM2602 Audio support for BF52x ezkit" 13 tristate "SoC SSM2602 Audio Codec Add-On Card support"
13 depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) 14 depends on SND_BF5XX_I2S && (SPI_MASTER || I2C)
14 select SND_BF5XX_SOC_I2S 15 select SND_BF5XX_SOC_I2S if !BF60x
16 select SND_BF6XX_SOC_I2S if BF60x
15 select SND_SOC_SSM2602 17 select SND_SOC_SSM2602
16 help 18 help
17 Say Y if you want to add support for SoC audio on BF527-EZKIT. 19 Say Y if you want to add support for the Analog Devices
20 SSM2602 Audio Codec Add-On Card.
18 21
19config SND_SOC_BFIN_EVAL_ADAU1701 22config SND_SOC_BFIN_EVAL_ADAU1701
20 tristate "Support for the EVAL-ADAU1701MINIZ board on Blackfin eval boards" 23 tristate "Support for the EVAL-ADAU1701MINIZ board on Blackfin eval boards"
@@ -162,9 +165,15 @@ config SND_BF5XX_SOC_AD1980
162config SND_BF5XX_SOC_SPORT 165config SND_BF5XX_SOC_SPORT
163 tristate 166 tristate
164 167
168config SND_BF6XX_SOC_SPORT
169 tristate
170
165config SND_BF5XX_SOC_I2S 171config SND_BF5XX_SOC_I2S
166 tristate 172 tristate
167 173
174config SND_BF6XX_SOC_I2S
175 tristate
176
168config SND_BF5XX_SOC_TDM 177config SND_BF5XX_SOC_TDM
169 tristate 178 tristate
170 179
@@ -173,7 +182,7 @@ config SND_BF5XX_SOC_AC97
173 182
174config SND_BF5XX_SPORT_NUM 183config SND_BF5XX_SPORT_NUM
175 int "Set a SPORT for Sound chip" 184 int "Set a SPORT for Sound chip"
176 depends on (SND_BF5XX_I2S || SND_BF5XX_AC97 || SND_BF5XX_TDM) 185 depends on (SND_BF5XX_SOC_SPORT || SND_BF6XX_SOC_SPORT)
177 range 0 3 if BF54x 186 range 0 3 if BF54x
178 range 0 1 if !BF54x 187 range 0 1 if !BF54x
179 default 0 188 default 0
diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile
index 1bf86ccaa8d..6fea1f4cbee 100644
--- a/sound/soc/blackfin/Makefile
+++ b/sound/soc/blackfin/Makefile
@@ -3,16 +3,20 @@ snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o
3snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o 3snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o
4snd-bf5xx-tdm-objs := bf5xx-tdm-pcm.o 4snd-bf5xx-tdm-objs := bf5xx-tdm-pcm.o
5snd-soc-bf5xx-sport-objs := bf5xx-sport.o 5snd-soc-bf5xx-sport-objs := bf5xx-sport.o
6snd-soc-bf6xx-sport-objs := bf6xx-sport.o
6snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o 7snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o
7snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o 8snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o
9snd-soc-bf6xx-i2s-objs := bf6xx-i2s.o
8snd-soc-bf5xx-tdm-objs := bf5xx-tdm.o 10snd-soc-bf5xx-tdm-objs := bf5xx-tdm.o
9 11
10obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o 12obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o
11obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o 13obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o
12obj-$(CONFIG_SND_BF5XX_TDM) += snd-bf5xx-tdm.o 14obj-$(CONFIG_SND_BF5XX_TDM) += snd-bf5xx-tdm.o
13obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o 15obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o
16obj-$(CONFIG_SND_BF6XX_SOC_SPORT) += snd-soc-bf6xx-sport.o
14obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o 17obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o
15obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o 18obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o
19obj-$(CONFIG_SND_BF6XX_SOC_I2S) += snd-soc-bf6xx-i2s.o
16obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o 20obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o
17 21
18# Blackfin Machine Support 22# Blackfin Machine Support
diff --git a/sound/soc/blackfin/bf6xx-i2s.c b/sound/soc/blackfin/bf6xx-i2s.c
new file mode 100644
index 00000000000..c3c2466d3a4
--- /dev/null
+++ b/sound/soc/blackfin/bf6xx-i2s.c
@@ -0,0 +1,234 @@
1/*
2 * bf6xx-i2s.c - Analog Devices BF6XX i2s interface driver
3 *
4 * Copyright (c) 2012 Analog Devices Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#include <linux/device.h>
21#include <linux/init.h>
22#include <linux/module.h>
23#include <linux/platform_device.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include <sound/soc.h>
27#include <sound/soc-dai.h>
28
29#include "bf6xx-sport.h"
30
31struct sport_params param;
32
33static int bfin_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
34 unsigned int fmt)
35{
36 struct sport_device *sport = snd_soc_dai_get_drvdata(cpu_dai);
37 struct device *dev = &sport->pdev->dev;
38 int ret = 0;
39
40 param.spctl &= ~(SPORT_CTL_OPMODE | SPORT_CTL_CKRE | SPORT_CTL_FSR
41 | SPORT_CTL_LFS | SPORT_CTL_LAFS);
42 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
43 case SND_SOC_DAIFMT_I2S:
44 param.spctl |= SPORT_CTL_OPMODE | SPORT_CTL_CKRE
45 | SPORT_CTL_LFS;
46 break;
47 case SND_SOC_DAIFMT_DSP_A:
48 param.spctl |= SPORT_CTL_FSR;
49 break;
50 case SND_SOC_DAIFMT_LEFT_J:
51 param.spctl |= SPORT_CTL_OPMODE | SPORT_CTL_LFS
52 | SPORT_CTL_LAFS;
53 break;
54 default:
55 dev_err(dev, "%s: Unknown DAI format type\n", __func__);
56 ret = -EINVAL;
57 break;
58 }
59
60 param.spctl &= ~(SPORT_CTL_ICLK | SPORT_CTL_IFS);
61 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
62 case SND_SOC_DAIFMT_CBM_CFM:
63 break;
64 case SND_SOC_DAIFMT_CBS_CFS:
65 case SND_SOC_DAIFMT_CBM_CFS:
66 case SND_SOC_DAIFMT_CBS_CFM:
67 ret = -EINVAL;
68 break;
69 default:
70 dev_err(dev, "%s: Unknown DAI master type\n", __func__);
71 ret = -EINVAL;
72 break;
73 }
74
75 return ret;
76}
77
78static int bfin_i2s_hw_params(struct snd_pcm_substream *substream,
79 struct snd_pcm_hw_params *params,
80 struct snd_soc_dai *dai)
81{
82 struct sport_device *sport = snd_soc_dai_get_drvdata(dai);
83 struct device *dev = &sport->pdev->dev;
84 int ret = 0;
85
86 param.spctl &= ~SPORT_CTL_SLEN;
87 switch (params_format(params)) {
88 case SNDRV_PCM_FORMAT_S8:
89 param.spctl |= 0x70;
90 sport->wdsize = 1;
91 case SNDRV_PCM_FORMAT_S16_LE:
92 param.spctl |= 0xf0;
93 sport->wdsize = 2;
94 break;
95 case SNDRV_PCM_FORMAT_S24_LE:
96 param.spctl |= 0x170;
97 sport->wdsize = 3;
98 break;
99 case SNDRV_PCM_FORMAT_S32_LE:
100 param.spctl |= 0x1f0;
101 sport->wdsize = 4;
102 break;
103 }
104
105 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
106 ret = sport_set_tx_params(sport, &param);
107 if (ret) {
108 dev_err(dev, "SPORT tx is busy!\n");
109 return ret;
110 }
111 } else {
112 ret = sport_set_rx_params(sport, &param);
113 if (ret) {
114 dev_err(dev, "SPORT rx is busy!\n");
115 return ret;
116 }
117 }
118 return 0;
119}
120
121#ifdef CONFIG_PM
122static int bfin_i2s_suspend(struct snd_soc_dai *dai)
123{
124 struct sport_device *sport = snd_soc_dai_get_drvdata(dai);
125
126 if (dai->capture_active)
127 sport_rx_stop(sport);
128 if (dai->playback_active)
129 sport_tx_stop(sport);
130 return 0;
131}
132
133static int bfin_i2s_resume(struct snd_soc_dai *dai)
134{
135 struct sport_device *sport = snd_soc_dai_get_drvdata(dai);
136 struct device *dev = &sport->pdev->dev;
137 int ret;
138
139 ret = sport_set_tx_params(sport, &param);
140 if (ret) {
141 dev_err(dev, "SPORT tx is busy!\n");
142 return ret;
143 }
144 ret = sport_set_rx_params(sport, &param);
145 if (ret) {
146 dev_err(dev, "SPORT rx is busy!\n");
147 return ret;
148 }
149
150 return 0;
151}
152
153#else
154#define bfin_i2s_suspend NULL
155#define bfin_i2s_resume NULL
156#endif
157
158#define BFIN_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
159 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
160 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
161 SNDRV_PCM_RATE_96000)
162
163#define BFIN_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
164 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
165
166static struct snd_soc_dai_ops bfin_i2s_dai_ops = {
167 .hw_params = bfin_i2s_hw_params,
168 .set_fmt = bfin_i2s_set_dai_fmt,
169};
170
171static struct snd_soc_dai_driver bfin_i2s_dai = {
172 .suspend = bfin_i2s_suspend,
173 .resume = bfin_i2s_resume,
174 .playback = {
175 .channels_min = 1,
176 .channels_max = 2,
177 .rates = BFIN_I2S_RATES,
178 .formats = BFIN_I2S_FORMATS,
179 },
180 .capture = {
181 .channels_min = 1,
182 .channels_max = 2,
183 .rates = BFIN_I2S_RATES,
184 .formats = BFIN_I2S_FORMATS,
185 },
186 .ops = &bfin_i2s_dai_ops,
187};
188
189static int __devinit bfin_i2s_probe(struct platform_device *pdev)
190{
191 struct sport_device *sport;
192 struct device *dev = &pdev->dev;
193 int ret;
194
195 sport = sport_create(pdev);
196 if (!sport)
197 return -ENODEV;
198
199 /* register with the ASoC layers */
200 ret = snd_soc_register_dai(dev, &bfin_i2s_dai);
201 if (ret) {
202 dev_err(dev, "Failed to register DAI: %d\n", ret);
203 sport_delete(sport);
204 return ret;
205 }
206 platform_set_drvdata(pdev, sport);
207
208 return 0;
209}
210
211static int __devexit bfin_i2s_remove(struct platform_device *pdev)
212{
213 struct sport_device *sport = platform_get_drvdata(pdev);
214
215 snd_soc_unregister_dai(&pdev->dev);
216 sport_delete(sport);
217
218 return 0;
219}
220
221static struct platform_driver bfin_i2s_driver = {
222 .probe = bfin_i2s_probe,
223 .remove = __devexit_p(bfin_i2s_remove),
224 .driver = {
225 .name = "bfin-i2s",
226 .owner = THIS_MODULE,
227 },
228};
229
230module_platform_driver(bfin_i2s_driver);
231
232MODULE_DESCRIPTION("Analog Devices BF6XX i2s interface driver");
233MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
234MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/blackfin/bf6xx-sport.c b/sound/soc/blackfin/bf6xx-sport.c
new file mode 100644
index 00000000000..318c5ba5360
--- /dev/null
+++ b/sound/soc/blackfin/bf6xx-sport.c
@@ -0,0 +1,422 @@
1/*
2 * bf6xx_sport.c Analog Devices BF6XX SPORT driver
3 *
4 * Copyright (c) 2012 Analog Devices Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#include <linux/device.h>
21#include <linux/dma-mapping.h>
22#include <linux/interrupt.h>
23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/slab.h>
26
27#include <asm/blackfin.h>
28#include <asm/dma.h>
29#include <asm/portmux.h>
30
31#include "bf6xx-sport.h"
32
33int sport_set_tx_params(struct sport_device *sport,
34 struct sport_params *params)
35{
36 if (sport->tx_regs->spctl & SPORT_CTL_SPENPRI)
37 return -EBUSY;
38 sport->tx_regs->spctl = params->spctl | SPORT_CTL_SPTRAN;
39 sport->tx_regs->div = params->div;
40 SSYNC();
41 return 0;
42}
43EXPORT_SYMBOL(sport_set_tx_params);
44
45int sport_set_rx_params(struct sport_device *sport,
46 struct sport_params *params)
47{
48 if (sport->rx_regs->spctl & SPORT_CTL_SPENPRI)
49 return -EBUSY;
50 sport->rx_regs->spctl = params->spctl & ~SPORT_CTL_SPTRAN;
51 sport->rx_regs->div = params->div;
52 SSYNC();
53 return 0;
54}
55EXPORT_SYMBOL(sport_set_rx_params);
56
57static int compute_wdsize(size_t wdsize)
58{
59 switch (wdsize) {
60 case 1:
61 return WDSIZE_8 | PSIZE_8;
62 case 2:
63 return WDSIZE_16 | PSIZE_16;
64 default:
65 return WDSIZE_32 | PSIZE_32;
66 }
67}
68
69void sport_tx_start(struct sport_device *sport)
70{
71 set_dma_next_desc_addr(sport->tx_dma_chan, sport->tx_desc);
72 set_dma_config(sport->tx_dma_chan, DMAFLOW_LIST | DI_EN
73 | compute_wdsize(sport->wdsize) | NDSIZE_6);
74 enable_dma(sport->tx_dma_chan);
75 sport->tx_regs->spctl |= SPORT_CTL_SPENPRI;
76 SSYNC();
77}
78EXPORT_SYMBOL(sport_tx_start);
79
80void sport_rx_start(struct sport_device *sport)
81{
82 set_dma_next_desc_addr(sport->rx_dma_chan, sport->rx_desc);
83 set_dma_config(sport->rx_dma_chan, DMAFLOW_LIST | DI_EN | WNR
84 | compute_wdsize(sport->wdsize) | NDSIZE_6);
85 enable_dma(sport->rx_dma_chan);
86 sport->rx_regs->spctl |= SPORT_CTL_SPENPRI;
87 SSYNC();
88}
89EXPORT_SYMBOL(sport_rx_start);
90
91void sport_tx_stop(struct sport_device *sport)
92{
93 sport->tx_regs->spctl &= ~SPORT_CTL_SPENPRI;
94 SSYNC();
95 disable_dma(sport->tx_dma_chan);
96}
97EXPORT_SYMBOL(sport_tx_stop);
98
99void sport_rx_stop(struct sport_device *sport)
100{
101 sport->rx_regs->spctl &= ~SPORT_CTL_SPENPRI;
102 SSYNC();
103 disable_dma(sport->rx_dma_chan);
104}
105EXPORT_SYMBOL(sport_rx_stop);
106
107void sport_set_tx_callback(struct sport_device *sport,
108 void (*tx_callback)(void *), void *tx_data)
109{
110 sport->tx_callback = tx_callback;
111 sport->tx_data = tx_data;
112}
113EXPORT_SYMBOL(sport_set_tx_callback);
114
115void sport_set_rx_callback(struct sport_device *sport,
116 void (*rx_callback)(void *), void *rx_data)
117{
118 sport->rx_callback = rx_callback;
119 sport->rx_data = rx_data;
120}
121EXPORT_SYMBOL(sport_set_rx_callback);
122
123static void setup_desc(struct dmasg *desc, void *buf, int fragcount,
124 size_t fragsize, unsigned int cfg,
125 unsigned int count, size_t wdsize)
126{
127
128 int i;
129
130 for (i = 0; i < fragcount; ++i) {
131 desc[i].next_desc_addr = &(desc[i + 1]);
132 desc[i].start_addr = (unsigned long)buf + i*fragsize;
133 desc[i].cfg = cfg;
134 desc[i].x_count = count;
135 desc[i].x_modify = wdsize;
136 desc[i].y_count = 0;
137 desc[i].y_modify = 0;
138 }
139
140 /* make circular */
141 desc[fragcount-1].next_desc_addr = desc;
142}
143
144int sport_config_tx_dma(struct sport_device *sport, void *buf,
145 int fragcount, size_t fragsize)
146{
147 unsigned int count;
148 unsigned int cfg;
149 dma_addr_t addr;
150
151 count = fragsize/sport->wdsize;
152
153 if (sport->tx_desc)
154 dma_free_coherent(NULL, sport->tx_desc_size,
155 sport->tx_desc, 0);
156
157 sport->tx_desc = dma_alloc_coherent(NULL,
158 fragcount * sizeof(struct dmasg), &addr, 0);
159 sport->tx_desc_size = fragcount * sizeof(struct dmasg);
160 if (!sport->tx_desc)
161 return -ENOMEM;
162
163 sport->tx_buf = buf;
164 sport->tx_fragsize = fragsize;
165 sport->tx_frags = fragcount;
166 cfg = DMAFLOW_LIST | DI_EN | compute_wdsize(sport->wdsize) | NDSIZE_6;
167
168 setup_desc(sport->tx_desc, buf, fragcount, fragsize,
169 cfg|DMAEN, count, sport->wdsize);
170
171 return 0;
172}
173EXPORT_SYMBOL(sport_config_tx_dma);
174
175int sport_config_rx_dma(struct sport_device *sport, void *buf,
176 int fragcount, size_t fragsize)
177{
178 unsigned int count;
179 unsigned int cfg;
180 dma_addr_t addr;
181
182 count = fragsize/sport->wdsize;
183
184 if (sport->rx_desc)
185 dma_free_coherent(NULL, sport->rx_desc_size,
186 sport->rx_desc, 0);
187
188 sport->rx_desc = dma_alloc_coherent(NULL,
189 fragcount * sizeof(struct dmasg), &addr, 0);
190 sport->rx_desc_size = fragcount * sizeof(struct dmasg);
191 if (!sport->rx_desc)
192 return -ENOMEM;
193
194 sport->rx_buf = buf;
195 sport->rx_fragsize = fragsize;
196 sport->rx_frags = fragcount;
197 cfg = DMAFLOW_LIST | DI_EN | compute_wdsize(sport->wdsize)
198 | WNR | NDSIZE_6;
199
200 setup_desc(sport->rx_desc, buf, fragcount, fragsize,
201 cfg|DMAEN, count, sport->wdsize);
202
203 return 0;
204}
205EXPORT_SYMBOL(sport_config_rx_dma);
206
207unsigned long sport_curr_offset_tx(struct sport_device *sport)
208{
209 unsigned long curr = get_dma_curr_addr(sport->tx_dma_chan);
210
211 return (unsigned char *)curr - sport->tx_buf;
212}
213EXPORT_SYMBOL(sport_curr_offset_tx);
214
215unsigned long sport_curr_offset_rx(struct sport_device *sport)
216{
217 unsigned long curr = get_dma_curr_addr(sport->rx_dma_chan);
218
219 return (unsigned char *)curr - sport->rx_buf;
220}
221EXPORT_SYMBOL(sport_curr_offset_rx);
222
223static irqreturn_t sport_tx_irq(int irq, void *dev_id)
224{
225 struct sport_device *sport = dev_id;
226 static unsigned long status;
227
228 status = get_dma_curr_irqstat(sport->tx_dma_chan);
229 if (status & (DMA_DONE|DMA_ERR)) {
230 clear_dma_irqstat(sport->tx_dma_chan);
231 SSYNC();
232 }
233 if (sport->tx_callback)
234 sport->tx_callback(sport->tx_data);
235 return IRQ_HANDLED;
236}
237
238static irqreturn_t sport_rx_irq(int irq, void *dev_id)
239{
240 struct sport_device *sport = dev_id;
241 unsigned long status;
242
243 status = get_dma_curr_irqstat(sport->rx_dma_chan);
244 if (status & (DMA_DONE|DMA_ERR)) {
245 clear_dma_irqstat(sport->rx_dma_chan);
246 SSYNC();
247 }
248 if (sport->rx_callback)
249 sport->rx_callback(sport->rx_data);
250 return IRQ_HANDLED;
251}
252
253static irqreturn_t sport_err_irq(int irq, void *dev_id)
254{
255 struct sport_device *sport = dev_id;
256 struct device *dev = &sport->pdev->dev;
257
258 if (sport->tx_regs->spctl & SPORT_CTL_DERRPRI)
259 dev_err(dev, "sport error: TUVF\n");
260 if (sport->rx_regs->spctl & SPORT_CTL_DERRPRI)
261 dev_err(dev, "sport error: ROVF\n");
262
263 return IRQ_HANDLED;
264}
265
266static int sport_get_resource(struct sport_device *sport)
267{
268 struct platform_device *pdev = sport->pdev;
269 struct device *dev = &pdev->dev;
270 struct bfin_snd_platform_data *pdata = dev->platform_data;
271 struct resource *res;
272
273 if (!pdata) {
274 dev_err(dev, "No platform data\n");
275 return -ENODEV;
276 }
277 sport->pin_req = pdata->pin_req;
278
279 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
280 if (!res) {
281 dev_err(dev, "No tx MEM resource\n");
282 return -ENODEV;
283 }
284 sport->tx_regs = (struct sport_register *)res->start;
285
286 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
287 if (!res) {
288 dev_err(dev, "No rx MEM resource\n");
289 return -ENODEV;
290 }
291 sport->rx_regs = (struct sport_register *)res->start;
292
293 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
294 if (!res) {
295 dev_err(dev, "No tx DMA resource\n");
296 return -ENODEV;
297 }
298 sport->tx_dma_chan = res->start;
299
300 res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
301 if (!res) {
302 dev_err(dev, "No rx DMA resource\n");
303 return -ENODEV;
304 }
305 sport->rx_dma_chan = res->start;
306
307 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
308 if (!res) {
309 dev_err(dev, "No tx error irq resource\n");
310 return -ENODEV;
311 }
312 sport->tx_err_irq = res->start;
313
314 res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
315 if (!res) {
316 dev_err(dev, "No rx error irq resource\n");
317 return -ENODEV;
318 }
319 sport->rx_err_irq = res->start;
320
321 return 0;
322}
323
324static int sport_request_resource(struct sport_device *sport)
325{
326 struct device *dev = &sport->pdev->dev;
327 int ret;
328
329 ret = peripheral_request_list(sport->pin_req, "soc-audio");
330 if (ret) {
331 dev_err(dev, "Unable to request sport pin\n");
332 return ret;
333 }
334
335 ret = request_dma(sport->tx_dma_chan, "SPORT TX Data");
336 if (ret) {
337 dev_err(dev, "Unable to allocate DMA channel for sport tx\n");
338 goto err_tx_dma;
339 }
340 set_dma_callback(sport->tx_dma_chan, sport_tx_irq, sport);
341
342 ret = request_dma(sport->rx_dma_chan, "SPORT RX Data");
343 if (ret) {
344 dev_err(dev, "Unable to allocate DMA channel for sport rx\n");
345 goto err_rx_dma;
346 }
347 set_dma_callback(sport->rx_dma_chan, sport_rx_irq, sport);
348
349 ret = request_irq(sport->tx_err_irq, sport_err_irq,
350 0, "SPORT TX ERROR", sport);
351 if (ret) {
352 dev_err(dev, "Unable to allocate tx error IRQ for sport\n");
353 goto err_tx_irq;
354 }
355
356 ret = request_irq(sport->rx_err_irq, sport_err_irq,
357 0, "SPORT RX ERROR", sport);
358 if (ret) {
359 dev_err(dev, "Unable to allocate rx error IRQ for sport\n");
360 goto err_rx_irq;
361 }
362
363 return 0;
364err_rx_irq:
365 free_irq(sport->tx_err_irq, sport);
366err_tx_irq:
367 free_dma(sport->rx_dma_chan);
368err_rx_dma:
369 free_dma(sport->tx_dma_chan);
370err_tx_dma:
371 peripheral_free_list(sport->pin_req);
372 return ret;
373}
374
375static void sport_free_resource(struct sport_device *sport)
376{
377 free_irq(sport->rx_err_irq, sport);
378 free_irq(sport->tx_err_irq, sport);
379 free_dma(sport->rx_dma_chan);
380 free_dma(sport->tx_dma_chan);
381 peripheral_free_list(sport->pin_req);
382}
383
384struct sport_device *sport_create(struct platform_device *pdev)
385{
386 struct device *dev = &pdev->dev;
387 struct sport_device *sport;
388 int ret;
389
390 sport = kzalloc(sizeof(*sport), GFP_KERNEL);
391 if (!sport) {
392 dev_err(dev, "Unable to allocate memory for sport device\n");
393 return NULL;
394 }
395 sport->pdev = pdev;
396
397 ret = sport_get_resource(sport);
398 if (ret) {
399 kfree(sport);
400 return NULL;
401 }
402
403 ret = sport_request_resource(sport);
404 if (ret) {
405 kfree(sport);
406 return NULL;
407 }
408
409 dev_dbg(dev, "SPORT create success\n");
410 return sport;
411}
412EXPORT_SYMBOL(sport_create);
413
414void sport_delete(struct sport_device *sport)
415{
416 sport_free_resource(sport);
417}
418EXPORT_SYMBOL(sport_delete);
419
420MODULE_DESCRIPTION("Analog Devices BF6XX SPORT driver");
421MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
422MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/blackfin/bf6xx-sport.h b/sound/soc/blackfin/bf6xx-sport.h
new file mode 100644
index 00000000000..307d193cfce
--- /dev/null
+++ b/sound/soc/blackfin/bf6xx-sport.h
@@ -0,0 +1,82 @@
1/*
2 * bf6xx_sport - Analog Devices BF6XX SPORT driver
3 *
4 * Copyright (c) 2012 Analog Devices Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#ifndef _BF6XX_SPORT_H_
21#define _BF6XX_SPORT_H_
22
23#include <linux/platform_device.h>
24#include <asm/bfin_sport3.h>
25
26struct sport_device {
27 struct platform_device *pdev;
28 const unsigned short *pin_req;
29 struct sport_register *tx_regs;
30 struct sport_register *rx_regs;
31 int tx_dma_chan;
32 int rx_dma_chan;
33 int tx_err_irq;
34 int rx_err_irq;
35
36 void (*tx_callback)(void *data);
37 void *tx_data;
38 void (*rx_callback)(void *data);
39 void *rx_data;
40
41 struct dmasg *tx_desc;
42 struct dmasg *rx_desc;
43 unsigned int tx_desc_size;
44 unsigned int rx_desc_size;
45 unsigned char *tx_buf;
46 unsigned char *rx_buf;
47 unsigned int tx_fragsize;
48 unsigned int rx_fragsize;
49 unsigned int tx_frags;
50 unsigned int rx_frags;
51 unsigned int wdsize;
52};
53
54struct sport_params {
55 u32 spctl;
56 u32 div;
57};
58
59struct sport_device *sport_create(struct platform_device *pdev);
60void sport_delete(struct sport_device *sport);
61int sport_set_tx_params(struct sport_device *sport,
62 struct sport_params *params);
63int sport_set_rx_params(struct sport_device *sport,
64 struct sport_params *params);
65void sport_tx_start(struct sport_device *sport);
66void sport_rx_start(struct sport_device *sport);
67void sport_tx_stop(struct sport_device *sport);
68void sport_rx_stop(struct sport_device *sport);
69void sport_set_tx_callback(struct sport_device *sport,
70 void (*tx_callback)(void *), void *tx_data);
71void sport_set_rx_callback(struct sport_device *sport,
72 void (*rx_callback)(void *), void *rx_data);
73int sport_config_tx_dma(struct sport_device *sport, void *buf,
74 int fragcount, size_t fragsize);
75int sport_config_rx_dma(struct sport_device *sport, void *buf,
76 int fragcount, size_t fragsize);
77unsigned long sport_curr_offset_tx(struct sport_device *sport);
78unsigned long sport_curr_offset_rx(struct sport_device *sport);
79
80
81
82#endif
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 1e1613a438d..9f8e8594aeb 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -12,6 +12,7 @@ config SND_SOC_ALL_CODECS
12 tristate "Build all ASoC CODEC drivers" 12 tristate "Build all ASoC CODEC drivers"
13 select SND_SOC_88PM860X if MFD_88PM860X 13 select SND_SOC_88PM860X if MFD_88PM860X
14 select SND_SOC_L3 14 select SND_SOC_L3
15 select SND_SOC_AB8500_CODEC if ABX500_CORE
15 select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS 16 select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
16 select SND_SOC_AD1836 if SPI_MASTER 17 select SND_SOC_AD1836 if SPI_MASTER
17 select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI 18 select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI
@@ -35,7 +36,9 @@ config SND_SOC_ALL_CODECS
35 select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI 36 select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
36 select SND_SOC_CX20442 37 select SND_SOC_CX20442
37 select SND_SOC_DA7210 if I2C 38 select SND_SOC_DA7210 if I2C
39 select SND_SOC_DA732X if I2C
38 select SND_SOC_DFBMCS320 40 select SND_SOC_DFBMCS320
41 select SND_SOC_ISABELLE if I2C
39 select SND_SOC_JZ4740_CODEC 42 select SND_SOC_JZ4740_CODEC
40 select SND_SOC_LM4857 if I2C 43 select SND_SOC_LM4857 if I2C
41 select SND_SOC_LM49453 if I2C 44 select SND_SOC_LM49453 if I2C
@@ -54,6 +57,7 @@ config SND_SOC_ALL_CODECS
54 select SND_SOC_SPDIF 57 select SND_SOC_SPDIF
55 select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI 58 select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI
56 select SND_SOC_STA32X if I2C 59 select SND_SOC_STA32X if I2C
60 select SND_SOC_STA529 if I2C
57 select SND_SOC_STAC9766 if SND_SOC_AC97_BUS 61 select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
58 select SND_SOC_TLV320AIC23 if I2C 62 select SND_SOC_TLV320AIC23 if I2C
59 select SND_SOC_TLV320AIC26 if SPI_MASTER 63 select SND_SOC_TLV320AIC26 if SPI_MASTER
@@ -70,6 +74,8 @@ config SND_SOC_ALL_CODECS
70 select SND_SOC_WM2000 if I2C 74 select SND_SOC_WM2000 if I2C
71 select SND_SOC_WM2200 if I2C 75 select SND_SOC_WM2200 if I2C
72 select SND_SOC_WM5100 if I2C 76 select SND_SOC_WM5100 if I2C
77 select SND_SOC_WM5102 if MFD_WM5102
78 select SND_SOC_WM5110 if MFD_WM5110
73 select SND_SOC_WM8350 if MFD_WM8350 79 select SND_SOC_WM8350 if MFD_WM8350
74 select SND_SOC_WM8400 if MFD_WM8400 80 select SND_SOC_WM8400 if MFD_WM8400
75 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI 81 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI
@@ -126,11 +132,21 @@ config SND_SOC_ALL_CODECS
126config SND_SOC_88PM860X 132config SND_SOC_88PM860X
127 tristate 133 tristate
128 134
135config SND_SOC_ARIZONA
136 tristate
137 default y if SND_SOC_WM5102=y
138 default y if SND_SOC_WM5110=y
139 default m if SND_SOC_WM5102=m
140 default m if SND_SOC_WM5110=m
141
129config SND_SOC_WM_HUBS 142config SND_SOC_WM_HUBS
130 tristate 143 tristate
131 default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y 144 default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y
132 default m if SND_SOC_WM8993=m || SND_SOC_WM8994=m 145 default m if SND_SOC_WM8993=m || SND_SOC_WM8994=m
133 146
147config SND_SOC_AB8500_CODEC
148 tristate
149
134config SND_SOC_AC97_CODEC 150config SND_SOC_AC97_CODEC
135 tristate 151 tristate
136 select SND_AC97_CODEC 152 select SND_AC97_CODEC
@@ -219,12 +235,18 @@ config SND_SOC_L3
219config SND_SOC_DA7210 235config SND_SOC_DA7210
220 tristate 236 tristate
221 237
238config SND_SOC_DA732X
239 tristate
240
222config SND_SOC_DFBMCS320 241config SND_SOC_DFBMCS320
223 tristate 242 tristate
224 243
225config SND_SOC_DMIC 244config SND_SOC_DMIC
226 tristate 245 tristate
227 246
247config SND_SOC_ISABELLE
248 tristate
249
228config SND_SOC_LM49453 250config SND_SOC_LM49453
229 tristate 251 tristate
230 252
@@ -266,6 +288,9 @@ config SND_SOC_SSM2602
266config SND_SOC_STA32X 288config SND_SOC_STA32X
267 tristate 289 tristate
268 290
291config SND_SOC_STA529
292 tristate
293
269config SND_SOC_STAC9766 294config SND_SOC_STAC9766
270 tristate 295 tristate
271 296
@@ -313,6 +338,12 @@ config SND_SOC_WM2200
313config SND_SOC_WM5100 338config SND_SOC_WM5100
314 tristate 339 tristate
315 340
341config SND_SOC_WM5102
342 tristate
343
344config SND_SOC_WM5110
345 tristate
346
316config SND_SOC_WM8350 347config SND_SOC_WM8350
317 tristate 348 tristate
318 349
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index fc27fec3948..34148bb59c6 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -1,4 +1,5 @@
1snd-soc-88pm860x-objs := 88pm860x-codec.o 1snd-soc-88pm860x-objs := 88pm860x-codec.o
2snd-soc-ab8500-codec-objs := ab8500-codec.o
2snd-soc-ac97-objs := ac97.o 3snd-soc-ac97-objs := ac97.o
3snd-soc-ad1836-objs := ad1836.o 4snd-soc-ad1836-objs := ad1836.o
4snd-soc-ad193x-objs := ad193x.o 5snd-soc-ad193x-objs := ad193x.o
@@ -13,6 +14,7 @@ snd-soc-ak4535-objs := ak4535.o
13snd-soc-ak4641-objs := ak4641.o 14snd-soc-ak4641-objs := ak4641.o
14snd-soc-ak4642-objs := ak4642.o 15snd-soc-ak4642-objs := ak4642.o
15snd-soc-ak4671-objs := ak4671.o 16snd-soc-ak4671-objs := ak4671.o
17snd-soc-arizona-objs := arizona.o
16snd-soc-cq93vc-objs := cq93vc.o 18snd-soc-cq93vc-objs := cq93vc.o
17snd-soc-cs42l51-objs := cs42l51.o 19snd-soc-cs42l51-objs := cs42l51.o
18snd-soc-cs42l52-objs := cs42l52.o 20snd-soc-cs42l52-objs := cs42l52.o
@@ -21,8 +23,10 @@ snd-soc-cs4270-objs := cs4270.o
21snd-soc-cs4271-objs := cs4271.o 23snd-soc-cs4271-objs := cs4271.o
22snd-soc-cx20442-objs := cx20442.o 24snd-soc-cx20442-objs := cx20442.o
23snd-soc-da7210-objs := da7210.o 25snd-soc-da7210-objs := da7210.o
26snd-soc-da732x-objs := da732x.o
24snd-soc-dfbmcs320-objs := dfbmcs320.o 27snd-soc-dfbmcs320-objs := dfbmcs320.o
25snd-soc-dmic-objs := dmic.o 28snd-soc-dmic-objs := dmic.o
29snd-soc-isabelle-objs := isabelle.o
26snd-soc-jz4740-codec-objs := jz4740.o 30snd-soc-jz4740-codec-objs := jz4740.o
27snd-soc-l3-objs := l3.o 31snd-soc-l3-objs := l3.o
28snd-soc-lm4857-objs := lm4857.o 32snd-soc-lm4857-objs := lm4857.o
@@ -41,9 +45,11 @@ snd-soc-alc5623-objs := alc5623.o
41snd-soc-alc5632-objs := alc5632.o 45snd-soc-alc5632-objs := alc5632.o
42snd-soc-sigmadsp-objs := sigmadsp.o 46snd-soc-sigmadsp-objs := sigmadsp.o
43snd-soc-sn95031-objs := sn95031.o 47snd-soc-sn95031-objs := sn95031.o
44snd-soc-spdif-objs := spdif_transciever.o 48snd-soc-spdif-tx-objs := spdif_transciever.o
49snd-soc-spdif-rx-objs := spdif_receiver.o
45snd-soc-ssm2602-objs := ssm2602.o 50snd-soc-ssm2602-objs := ssm2602.o
46snd-soc-sta32x-objs := sta32x.o 51snd-soc-sta32x-objs := sta32x.o
52snd-soc-sta529-objs := sta529.o
47snd-soc-stac9766-objs := stac9766.o 53snd-soc-stac9766-objs := stac9766.o
48snd-soc-tlv320aic23-objs := tlv320aic23.o 54snd-soc-tlv320aic23-objs := tlv320aic23.o
49snd-soc-tlv320aic26-objs := tlv320aic26.o 55snd-soc-tlv320aic26-objs := tlv320aic26.o
@@ -59,6 +65,8 @@ snd-soc-wm1250-ev1-objs := wm1250-ev1.o
59snd-soc-wm2000-objs := wm2000.o 65snd-soc-wm2000-objs := wm2000.o
60snd-soc-wm2200-objs := wm2200.o 66snd-soc-wm2200-objs := wm2200.o
61snd-soc-wm5100-objs := wm5100.o wm5100-tables.o 67snd-soc-wm5100-objs := wm5100.o wm5100-tables.o
68snd-soc-wm5102-objs := wm5102.o
69snd-soc-wm5110-objs := wm5110.o
62snd-soc-wm8350-objs := wm8350.o 70snd-soc-wm8350-objs := wm8350.o
63snd-soc-wm8400-objs := wm8400.o 71snd-soc-wm8400-objs := wm8400.o
64snd-soc-wm8510-objs := wm8510.o 72snd-soc-wm8510-objs := wm8510.o
@@ -108,6 +116,7 @@ snd-soc-max9877-objs := max9877.o
108snd-soc-tpa6130a2-objs := tpa6130a2.o 116snd-soc-tpa6130a2-objs := tpa6130a2.o
109 117
110obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o 118obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o
119obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o
111obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o 120obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
112obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o 121obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o
113obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o 122obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o
@@ -124,6 +133,7 @@ obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o
124obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o 133obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o
125obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o 134obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o
126obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o 135obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o
136obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o
127obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o 137obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
128obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o 138obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o
129obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o 139obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o
@@ -132,8 +142,10 @@ obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
132obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o 142obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o
133obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o 143obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
134obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o 144obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
145obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o
135obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o 146obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o
136obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o 147obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
148obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o
137obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o 149obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
138obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o 150obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
139obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o 151obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
@@ -150,9 +162,10 @@ obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
150obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o 162obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
151obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o 163obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
152obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o 164obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o
153obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o 165obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o
154obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o 166obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
155obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o 167obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o
168obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o
156obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o 169obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
157obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o 170obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
158obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o 171obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
@@ -168,6 +181,8 @@ obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
168obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o 181obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o
169obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o 182obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o
170obj-$(CONFIG_SND_SOC_WM5100) += snd-soc-wm5100.o 183obj-$(CONFIG_SND_SOC_WM5100) += snd-soc-wm5100.o
184obj-$(CONFIG_SND_SOC_WM5102) += snd-soc-wm5102.o
185obj-$(CONFIG_SND_SOC_WM5110) += snd-soc-wm5110.o
171obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o 186obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o
172obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o 187obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o
173obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o 188obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c
new file mode 100644
index 00000000000..3c795921c5f
--- /dev/null
+++ b/sound/soc/codecs/ab8500-codec.c
@@ -0,0 +1,2522 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2012
3 *
4 * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
5 * Kristoffer Karlsson <kristoffer.karlsson@stericsson.com>,
6 * Roger Nilsson <roger.xr.nilsson@stericsson.com>,
7 * for ST-Ericsson.
8 *
9 * Based on the early work done by:
10 * Mikko J. Lehto <mikko.lehto@symbio.com>,
11 * Mikko Sarmanne <mikko.sarmanne@symbio.com>,
12 * Jarmo K. Kuronen <jarmo.kuronen@symbio.com>,
13 * for ST-Ericsson.
14 *
15 * License terms:
16 *
17 * This program is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License version 2 as published
19 * by the Free Software Foundation.
20 */
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/device.h>
25#include <linux/slab.h>
26#include <linux/moduleparam.h>
27#include <linux/init.h>
28#include <linux/delay.h>
29#include <linux/pm.h>
30#include <linux/platform_device.h>
31#include <linux/mutex.h>
32#include <linux/mfd/abx500/ab8500.h>
33#include <linux/mfd/abx500.h>
34#include <linux/mfd/abx500/ab8500-sysctrl.h>
35#include <linux/mfd/abx500/ab8500-codec.h>
36#include <linux/regulator/consumer.h>
37
38#include <sound/core.h>
39#include <sound/pcm.h>
40#include <sound/pcm_params.h>
41#include <sound/initval.h>
42#include <sound/soc.h>
43#include <sound/soc-dapm.h>
44#include <sound/tlv.h>
45
46#include "ab8500-codec.h"
47
48/* Macrocell value definitions */
49#define CLK_32K_OUT2_DISABLE 0x01
50#define INACTIVE_RESET_AUDIO 0x02
51#define ENABLE_AUDIO_CLK_TO_AUDIO_BLK 0x10
52#define ENABLE_VINTCORE12_SUPPLY 0x04
53#define GPIO27_DIR_OUTPUT 0x04
54#define GPIO29_DIR_OUTPUT 0x10
55#define GPIO31_DIR_OUTPUT 0x40
56
57/* Macrocell register definitions */
58#define AB8500_CTRL3_REG 0x0200
59#define AB8500_GPIO_DIR4_REG 0x1013
60
61/* Nr of FIR/IIR-coeff banks in ANC-block */
62#define AB8500_NR_OF_ANC_COEFF_BANKS 2
63
64/* Minimum duration to keep ANC IIR Init bit high or
65low before proceeding with the configuration sequence */
66#define AB8500_ANC_SM_DELAY 2000
67
68#define AB8500_FILTER_CONTROL(xname, xcount, xmin, xmax) \
69{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
70 .info = filter_control_info, \
71 .get = filter_control_get, .put = filter_control_put, \
72 .private_value = (unsigned long)&(struct filter_control) \
73 {.count = xcount, .min = xmin, .max = xmax} }
74
75struct filter_control {
76 long min, max;
77 unsigned int count;
78 long value[128];
79};
80
81/* Sidetone states */
82static const char * const enum_sid_state[] = {
83 "Unconfigured",
84 "Apply FIR",
85 "FIR is configured",
86};
87enum sid_state {
88 SID_UNCONFIGURED = 0,
89 SID_APPLY_FIR = 1,
90 SID_FIR_CONFIGURED = 2,
91};
92
93static const char * const enum_anc_state[] = {
94 "Unconfigured",
95 "Apply FIR and IIR",
96 "FIR and IIR are configured",
97 "Apply FIR",
98 "FIR is configured",
99 "Apply IIR",
100 "IIR is configured"
101};
102enum anc_state {
103 ANC_UNCONFIGURED = 0,
104 ANC_APPLY_FIR_IIR = 1,
105 ANC_FIR_IIR_CONFIGURED = 2,
106 ANC_APPLY_FIR = 3,
107 ANC_FIR_CONFIGURED = 4,
108 ANC_APPLY_IIR = 5,
109 ANC_IIR_CONFIGURED = 6
110};
111
112/* Analog microphones */
113enum amic_idx {
114 AMIC_IDX_1A,
115 AMIC_IDX_1B,
116 AMIC_IDX_2
117};
118
119struct ab8500_codec_drvdata_dbg {
120 struct regulator *vaud;
121 struct regulator *vamic1;
122 struct regulator *vamic2;
123 struct regulator *vdmic;
124};
125
126/* Private data for AB8500 device-driver */
127struct ab8500_codec_drvdata {
128 /* Sidetone */
129 long *sid_fir_values;
130 enum sid_state sid_status;
131
132 /* ANC */
133 struct mutex anc_lock;
134 long *anc_fir_values;
135 long *anc_iir_values;
136 enum anc_state anc_status;
137};
138
139static inline const char *amic_micbias_str(enum amic_micbias micbias)
140{
141 switch (micbias) {
142 case AMIC_MICBIAS_VAMIC1:
143 return "VAMIC1";
144 case AMIC_MICBIAS_VAMIC2:
145 return "VAMIC2";
146 default:
147 return "Unknown";
148 }
149}
150
151static inline const char *amic_type_str(enum amic_type type)
152{
153 switch (type) {
154 case AMIC_TYPE_DIFFERENTIAL:
155 return "DIFFERENTIAL";
156 case AMIC_TYPE_SINGLE_ENDED:
157 return "SINGLE ENDED";
158 default:
159 return "Unknown";
160 }
161}
162
163/*
164 * Read'n'write functions
165 */
166
167/* Read a register from the audio-bank of AB8500 */
168static unsigned int ab8500_codec_read_reg(struct snd_soc_codec *codec,
169 unsigned int reg)
170{
171 int status;
172 unsigned int value = 0;
173
174 u8 value8;
175 status = abx500_get_register_interruptible(codec->dev, AB8500_AUDIO,
176 reg, &value8);
177 if (status < 0) {
178 dev_err(codec->dev,
179 "%s: ERROR: Register (0x%02x:0x%02x) read failed (%d).\n",
180 __func__, (u8)AB8500_AUDIO, (u8)reg, status);
181 } else {
182 dev_dbg(codec->dev,
183 "%s: Read 0x%02x from register 0x%02x:0x%02x\n",
184 __func__, value8, (u8)AB8500_AUDIO, (u8)reg);
185 value = (unsigned int)value8;
186 }
187
188 return value;
189}
190
191/* Write to a register in the audio-bank of AB8500 */
192static int ab8500_codec_write_reg(struct snd_soc_codec *codec,
193 unsigned int reg, unsigned int value)
194{
195 int status;
196
197 status = abx500_set_register_interruptible(codec->dev, AB8500_AUDIO,
198 reg, value);
199 if (status < 0)
200 dev_err(codec->dev,
201 "%s: ERROR: Register (%02x:%02x) write failed (%d).\n",
202 __func__, (u8)AB8500_AUDIO, (u8)reg, status);
203 else
204 dev_dbg(codec->dev,
205 "%s: Wrote 0x%02x into register %02x:%02x\n",
206 __func__, (u8)value, (u8)AB8500_AUDIO, (u8)reg);
207
208 return status;
209}
210
211/*
212 * Controls - DAPM
213 */
214
215/* Earpiece */
216
217/* Earpiece source selector */
218static const char * const enum_ear_lineout_source[] = {"Headset Left",
219 "Speaker Left"};
220static SOC_ENUM_SINGLE_DECL(dapm_enum_ear_lineout_source, AB8500_DMICFILTCONF,
221 AB8500_DMICFILTCONF_DA3TOEAR, enum_ear_lineout_source);
222static const struct snd_kcontrol_new dapm_ear_lineout_source =
223 SOC_DAPM_ENUM("Earpiece or LineOut Mono Source",
224 dapm_enum_ear_lineout_source);
225
226/* LineOut */
227
228/* LineOut source selector */
229static const char * const enum_lineout_source[] = {"Mono Path", "Stereo Path"};
230static SOC_ENUM_DOUBLE_DECL(dapm_enum_lineout_source, AB8500_ANACONF5,
231 AB8500_ANACONF5_HSLDACTOLOL,
232 AB8500_ANACONF5_HSRDACTOLOR, enum_lineout_source);
233static const struct snd_kcontrol_new dapm_lineout_source[] = {
234 SOC_DAPM_ENUM("LineOut Source", dapm_enum_lineout_source),
235};
236
237/* Handsfree */
238
239/* Speaker Left - ANC selector */
240static const char * const enum_HFx_sel[] = {"Audio Path", "ANC"};
241static SOC_ENUM_SINGLE_DECL(dapm_enum_HFl_sel, AB8500_DIGMULTCONF2,
242 AB8500_DIGMULTCONF2_HFLSEL, enum_HFx_sel);
243static const struct snd_kcontrol_new dapm_HFl_select[] = {
244 SOC_DAPM_ENUM("Speaker Left Source", dapm_enum_HFl_sel),
245};
246
247/* Speaker Right - ANC selector */
248static SOC_ENUM_SINGLE_DECL(dapm_enum_HFr_sel, AB8500_DIGMULTCONF2,
249 AB8500_DIGMULTCONF2_HFRSEL, enum_HFx_sel);
250static const struct snd_kcontrol_new dapm_HFr_select[] = {
251 SOC_DAPM_ENUM("Speaker Right Source", dapm_enum_HFr_sel),
252};
253
254/* Mic 1 */
255
256/* Mic 1 - Mic 1a or 1b selector */
257static const char * const enum_mic1ab_sel[] = {"Mic 1b", "Mic 1a"};
258static SOC_ENUM_SINGLE_DECL(dapm_enum_mic1ab_sel, AB8500_ANACONF3,
259 AB8500_ANACONF3_MIC1SEL, enum_mic1ab_sel);
260static const struct snd_kcontrol_new dapm_mic1ab_mux[] = {
261 SOC_DAPM_ENUM("Mic 1a or 1b Select", dapm_enum_mic1ab_sel),
262};
263
264/* Mic 1 - AD3 - Mic 1 or DMic 3 selector */
265static const char * const enum_ad3_sel[] = {"Mic 1", "DMic 3"};
266static SOC_ENUM_SINGLE_DECL(dapm_enum_ad3_sel, AB8500_DIGMULTCONF1,
267 AB8500_DIGMULTCONF1_AD3SEL, enum_ad3_sel);
268static const struct snd_kcontrol_new dapm_ad3_select[] = {
269 SOC_DAPM_ENUM("AD3 Source Select", dapm_enum_ad3_sel),
270};
271
272/* Mic 1 - AD6 - Mic 1 or DMic 6 selector */
273static const char * const enum_ad6_sel[] = {"Mic 1", "DMic 6"};
274static SOC_ENUM_SINGLE_DECL(dapm_enum_ad6_sel, AB8500_DIGMULTCONF1,
275 AB8500_DIGMULTCONF1_AD6SEL, enum_ad6_sel);
276static const struct snd_kcontrol_new dapm_ad6_select[] = {
277 SOC_DAPM_ENUM("AD6 Source Select", dapm_enum_ad6_sel),
278};
279
280/* Mic 2 */
281
282/* Mic 2 - AD5 - Mic 2 or DMic 5 selector */
283static const char * const enum_ad5_sel[] = {"Mic 2", "DMic 5"};
284static SOC_ENUM_SINGLE_DECL(dapm_enum_ad5_sel, AB8500_DIGMULTCONF1,
285 AB8500_DIGMULTCONF1_AD5SEL, enum_ad5_sel);
286static const struct snd_kcontrol_new dapm_ad5_select[] = {
287 SOC_DAPM_ENUM("AD5 Source Select", dapm_enum_ad5_sel),
288};
289
290/* LineIn */
291
292/* LineIn left - AD1 - LineIn Left or DMic 1 selector */
293static const char * const enum_ad1_sel[] = {"LineIn Left", "DMic 1"};
294static SOC_ENUM_SINGLE_DECL(dapm_enum_ad1_sel, AB8500_DIGMULTCONF1,
295 AB8500_DIGMULTCONF1_AD1SEL, enum_ad1_sel);
296static const struct snd_kcontrol_new dapm_ad1_select[] = {
297 SOC_DAPM_ENUM("AD1 Source Select", dapm_enum_ad1_sel),
298};
299
300/* LineIn right - Mic 2 or LineIn Right selector */
301static const char * const enum_mic2lr_sel[] = {"Mic 2", "LineIn Right"};
302static SOC_ENUM_SINGLE_DECL(dapm_enum_mic2lr_sel, AB8500_ANACONF3,
303 AB8500_ANACONF3_LINRSEL, enum_mic2lr_sel);
304static const struct snd_kcontrol_new dapm_mic2lr_select[] = {
305 SOC_DAPM_ENUM("Mic 2 or LINR Select", dapm_enum_mic2lr_sel),
306};
307
308/* LineIn right - AD2 - LineIn Right or DMic2 selector */
309static const char * const enum_ad2_sel[] = {"LineIn Right", "DMic 2"};
310static SOC_ENUM_SINGLE_DECL(dapm_enum_ad2_sel, AB8500_DIGMULTCONF1,
311 AB8500_DIGMULTCONF1_AD2SEL, enum_ad2_sel);
312static const struct snd_kcontrol_new dapm_ad2_select[] = {
313 SOC_DAPM_ENUM("AD2 Source Select", dapm_enum_ad2_sel),
314};
315
316
317/* ANC */
318
319static const char * const enum_anc_in_sel[] = {"Mic 1 / DMic 6",
320 "Mic 2 / DMic 5"};
321static SOC_ENUM_SINGLE_DECL(dapm_enum_anc_in_sel, AB8500_DMICFILTCONF,
322 AB8500_DMICFILTCONF_ANCINSEL, enum_anc_in_sel);
323static const struct snd_kcontrol_new dapm_anc_in_select[] = {
324 SOC_DAPM_ENUM("ANC Source", dapm_enum_anc_in_sel),
325};
326
327/* ANC - Enable/Disable */
328static const struct snd_kcontrol_new dapm_anc_enable[] = {
329 SOC_DAPM_SINGLE("Switch", AB8500_ANCCONF1,
330 AB8500_ANCCONF1_ENANC, 0, 0),
331};
332
333/* ANC to Earpiece - Mute */
334static const struct snd_kcontrol_new dapm_anc_ear_mute[] = {
335 SOC_DAPM_SINGLE("Switch", AB8500_DIGMULTCONF1,
336 AB8500_DIGMULTCONF1_ANCSEL, 1, 0),
337};
338
339
340
341/* Sidetone left */
342
343/* Sidetone left - Input selector */
344static const char * const enum_stfir1_in_sel[] = {
345 "LineIn Left", "LineIn Right", "Mic 1", "Headset Left"
346};
347static SOC_ENUM_SINGLE_DECL(dapm_enum_stfir1_in_sel, AB8500_DIGMULTCONF2,
348 AB8500_DIGMULTCONF2_FIRSID1SEL, enum_stfir1_in_sel);
349static const struct snd_kcontrol_new dapm_stfir1_in_select[] = {
350 SOC_DAPM_ENUM("Sidetone Left Source", dapm_enum_stfir1_in_sel),
351};
352
353/* Sidetone right path */
354
355/* Sidetone right - Input selector */
356static const char * const enum_stfir2_in_sel[] = {
357 "LineIn Right", "Mic 1", "DMic 4", "Headset Right"
358};
359static SOC_ENUM_SINGLE_DECL(dapm_enum_stfir2_in_sel, AB8500_DIGMULTCONF2,
360 AB8500_DIGMULTCONF2_FIRSID2SEL, enum_stfir2_in_sel);
361static const struct snd_kcontrol_new dapm_stfir2_in_select[] = {
362 SOC_DAPM_ENUM("Sidetone Right Source", dapm_enum_stfir2_in_sel),
363};
364
365/* Vibra */
366
367static const char * const enum_pwm2vibx[] = {"Audio Path", "PWM Generator"};
368
369static SOC_ENUM_SINGLE_DECL(dapm_enum_pwm2vib1, AB8500_PWMGENCONF1,
370 AB8500_PWMGENCONF1_PWMTOVIB1, enum_pwm2vibx);
371
372static const struct snd_kcontrol_new dapm_pwm2vib1[] = {
373 SOC_DAPM_ENUM("Vibra 1 Controller", dapm_enum_pwm2vib1),
374};
375
376static SOC_ENUM_SINGLE_DECL(dapm_enum_pwm2vib2, AB8500_PWMGENCONF1,
377 AB8500_PWMGENCONF1_PWMTOVIB2, enum_pwm2vibx);
378
379static const struct snd_kcontrol_new dapm_pwm2vib2[] = {
380 SOC_DAPM_ENUM("Vibra 2 Controller", dapm_enum_pwm2vib2),
381};
382
383/*
384 * DAPM-widgets
385 */
386
387static const struct snd_soc_dapm_widget ab8500_dapm_widgets[] = {
388
389 /* Clocks */
390 SND_SOC_DAPM_CLOCK_SUPPLY("audioclk"),
391
392 /* Regulators */
393 SND_SOC_DAPM_REGULATOR_SUPPLY("V-AUD", 0),
394 SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC1", 0),
395 SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC2", 0),
396 SND_SOC_DAPM_REGULATOR_SUPPLY("V-DMIC", 0),
397
398 /* Power */
399 SND_SOC_DAPM_SUPPLY("Audio Power",
400 AB8500_POWERUP, AB8500_POWERUP_POWERUP, 0,
401 NULL, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
402 SND_SOC_DAPM_SUPPLY("Audio Analog Power",
403 AB8500_POWERUP, AB8500_POWERUP_ENANA, 0,
404 NULL, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
405
406 /* Main supply node */
407 SND_SOC_DAPM_SUPPLY("Main Supply", SND_SOC_NOPM, 0, 0,
408 NULL, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
409
410 /* DA/AD */
411
412 SND_SOC_DAPM_INPUT("ADC Input"),
413 SND_SOC_DAPM_ADC("ADC", "ab8500_0c", SND_SOC_NOPM, 0, 0),
414
415 SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
416 SND_SOC_DAPM_OUTPUT("DAC Output"),
417
418 SND_SOC_DAPM_AIF_IN("DA_IN1", NULL, 0, SND_SOC_NOPM, 0, 0),
419 SND_SOC_DAPM_AIF_IN("DA_IN2", NULL, 0, SND_SOC_NOPM, 0, 0),
420 SND_SOC_DAPM_AIF_IN("DA_IN3", NULL, 0, SND_SOC_NOPM, 0, 0),
421 SND_SOC_DAPM_AIF_IN("DA_IN4", NULL, 0, SND_SOC_NOPM, 0, 0),
422 SND_SOC_DAPM_AIF_IN("DA_IN5", NULL, 0, SND_SOC_NOPM, 0, 0),
423 SND_SOC_DAPM_AIF_IN("DA_IN6", NULL, 0, SND_SOC_NOPM, 0, 0),
424 SND_SOC_DAPM_AIF_OUT("AD_OUT1", NULL, 0, SND_SOC_NOPM, 0, 0),
425 SND_SOC_DAPM_AIF_OUT("AD_OUT2", NULL, 0, SND_SOC_NOPM, 0, 0),
426 SND_SOC_DAPM_AIF_OUT("AD_OUT3", NULL, 0, SND_SOC_NOPM, 0, 0),
427 SND_SOC_DAPM_AIF_OUT("AD_OUT4", NULL, 0, SND_SOC_NOPM, 0, 0),
428 SND_SOC_DAPM_AIF_OUT("AD_OUT57", NULL, 0, SND_SOC_NOPM, 0, 0),
429 SND_SOC_DAPM_AIF_OUT("AD_OUT68", NULL, 0, SND_SOC_NOPM, 0, 0),
430
431 /* Headset path */
432
433 SND_SOC_DAPM_SUPPLY("Charge Pump", AB8500_ANACONF5,
434 AB8500_ANACONF5_ENCPHS, 0, NULL, 0),
435
436 SND_SOC_DAPM_DAC("DA1 Enable", "ab8500_0p",
437 AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA1, 0),
438 SND_SOC_DAPM_DAC("DA2 Enable", "ab8500_0p",
439 AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA2, 0),
440
441 SND_SOC_DAPM_PGA("HSL Digital Volume", SND_SOC_NOPM, 0, 0,
442 NULL, 0),
443 SND_SOC_DAPM_PGA("HSR Digital Volume", SND_SOC_NOPM, 0, 0,
444 NULL, 0),
445
446 SND_SOC_DAPM_DAC("HSL DAC", "ab8500_0p",
447 AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACHSL, 0),
448 SND_SOC_DAPM_DAC("HSR DAC", "ab8500_0p",
449 AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACHSR, 0),
450 SND_SOC_DAPM_MIXER("HSL DAC Mute", AB8500_MUTECONF,
451 AB8500_MUTECONF_MUTDACHSL, 1,
452 NULL, 0),
453 SND_SOC_DAPM_MIXER("HSR DAC Mute", AB8500_MUTECONF,
454 AB8500_MUTECONF_MUTDACHSR, 1,
455 NULL, 0),
456 SND_SOC_DAPM_DAC("HSL DAC Driver", "ab8500_0p",
457 AB8500_ANACONF3, AB8500_ANACONF3_ENDRVHSL, 0),
458 SND_SOC_DAPM_DAC("HSR DAC Driver", "ab8500_0p",
459 AB8500_ANACONF3, AB8500_ANACONF3_ENDRVHSR, 0),
460
461 SND_SOC_DAPM_MIXER("HSL Mute",
462 AB8500_MUTECONF, AB8500_MUTECONF_MUTHSL, 1,
463 NULL, 0),
464 SND_SOC_DAPM_MIXER("HSR Mute",
465 AB8500_MUTECONF, AB8500_MUTECONF_MUTHSR, 1,
466 NULL, 0),
467 SND_SOC_DAPM_MIXER("HSL Enable",
468 AB8500_ANACONF4, AB8500_ANACONF4_ENHSL, 0,
469 NULL, 0),
470 SND_SOC_DAPM_MIXER("HSR Enable",
471 AB8500_ANACONF4, AB8500_ANACONF4_ENHSR, 0,
472 NULL, 0),
473 SND_SOC_DAPM_PGA("HSL Volume",
474 SND_SOC_NOPM, 0, 0,
475 NULL, 0),
476 SND_SOC_DAPM_PGA("HSR Volume",
477 SND_SOC_NOPM, 0, 0,
478 NULL, 0),
479
480 SND_SOC_DAPM_OUTPUT("Headset Left"),
481 SND_SOC_DAPM_OUTPUT("Headset Right"),
482
483 /* LineOut path */
484
485 SND_SOC_DAPM_MUX("LineOut Source",
486 SND_SOC_NOPM, 0, 0, dapm_lineout_source),
487
488 SND_SOC_DAPM_MIXER("LOL Disable HFL",
489 AB8500_ANACONF4, AB8500_ANACONF4_ENHFL, 1,
490 NULL, 0),
491 SND_SOC_DAPM_MIXER("LOR Disable HFR",
492 AB8500_ANACONF4, AB8500_ANACONF4_ENHFR, 1,
493 NULL, 0),
494
495 SND_SOC_DAPM_MIXER("LOL Enable",
496 AB8500_ANACONF5, AB8500_ANACONF5_ENLOL, 0,
497 NULL, 0),
498 SND_SOC_DAPM_MIXER("LOR Enable",
499 AB8500_ANACONF5, AB8500_ANACONF5_ENLOR, 0,
500 NULL, 0),
501
502 SND_SOC_DAPM_OUTPUT("LineOut Left"),
503 SND_SOC_DAPM_OUTPUT("LineOut Right"),
504
505 /* Earpiece path */
506
507 SND_SOC_DAPM_MUX("Earpiece or LineOut Mono Source",
508 SND_SOC_NOPM, 0, 0, &dapm_ear_lineout_source),
509 SND_SOC_DAPM_MIXER("EAR DAC",
510 AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACEAR, 0,
511 NULL, 0),
512 SND_SOC_DAPM_MIXER("EAR Mute",
513 AB8500_MUTECONF, AB8500_MUTECONF_MUTEAR, 1,
514 NULL, 0),
515 SND_SOC_DAPM_MIXER("EAR Enable",
516 AB8500_ANACONF4, AB8500_ANACONF4_ENEAR, 0,
517 NULL, 0),
518
519 SND_SOC_DAPM_OUTPUT("Earpiece"),
520
521 /* Handsfree path */
522
523 SND_SOC_DAPM_MIXER("DA3 Channel Volume",
524 AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA3, 0,
525 NULL, 0),
526 SND_SOC_DAPM_MIXER("DA4 Channel Volume",
527 AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA4, 0,
528 NULL, 0),
529 SND_SOC_DAPM_MUX("Speaker Left Source",
530 SND_SOC_NOPM, 0, 0, dapm_HFl_select),
531 SND_SOC_DAPM_MUX("Speaker Right Source",
532 SND_SOC_NOPM, 0, 0, dapm_HFr_select),
533 SND_SOC_DAPM_MIXER("HFL DAC", AB8500_DAPATHCONF,
534 AB8500_DAPATHCONF_ENDACHFL, 0,
535 NULL, 0),
536 SND_SOC_DAPM_MIXER("HFR DAC",
537 AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACHFR, 0,
538 NULL, 0),
539 SND_SOC_DAPM_MIXER("DA4 or ANC path to HfR",
540 AB8500_DIGMULTCONF2, AB8500_DIGMULTCONF2_DATOHFREN, 0,
541 NULL, 0),
542 SND_SOC_DAPM_MIXER("DA3 or ANC path to HfL",
543 AB8500_DIGMULTCONF2, AB8500_DIGMULTCONF2_DATOHFLEN, 0,
544 NULL, 0),
545 SND_SOC_DAPM_MIXER("HFL Enable",
546 AB8500_ANACONF4, AB8500_ANACONF4_ENHFL, 0,
547 NULL, 0),
548 SND_SOC_DAPM_MIXER("HFR Enable",
549 AB8500_ANACONF4, AB8500_ANACONF4_ENHFR, 0,
550 NULL, 0),
551
552 SND_SOC_DAPM_OUTPUT("Speaker Left"),
553 SND_SOC_DAPM_OUTPUT("Speaker Right"),
554
555 /* Vibrator path */
556
557 SND_SOC_DAPM_INPUT("PWMGEN1"),
558 SND_SOC_DAPM_INPUT("PWMGEN2"),
559
560 SND_SOC_DAPM_MIXER("DA5 Channel Volume",
561 AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA5, 0,
562 NULL, 0),
563 SND_SOC_DAPM_MIXER("DA6 Channel Volume",
564 AB8500_DAPATHENA, AB8500_DAPATHENA_ENDA6, 0,
565 NULL, 0),
566 SND_SOC_DAPM_MIXER("VIB1 DAC",
567 AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACVIB1, 0,
568 NULL, 0),
569 SND_SOC_DAPM_MIXER("VIB2 DAC",
570 AB8500_DAPATHCONF, AB8500_DAPATHCONF_ENDACVIB2, 0,
571 NULL, 0),
572 SND_SOC_DAPM_MUX("Vibra 1 Controller",
573 SND_SOC_NOPM, 0, 0, dapm_pwm2vib1),
574 SND_SOC_DAPM_MUX("Vibra 2 Controller",
575 SND_SOC_NOPM, 0, 0, dapm_pwm2vib2),
576 SND_SOC_DAPM_MIXER("VIB1 Enable",
577 AB8500_ANACONF4, AB8500_ANACONF4_ENVIB1, 0,
578 NULL, 0),
579 SND_SOC_DAPM_MIXER("VIB2 Enable",
580 AB8500_ANACONF4, AB8500_ANACONF4_ENVIB2, 0,
581 NULL, 0),
582
583 SND_SOC_DAPM_OUTPUT("Vibra 1"),
584 SND_SOC_DAPM_OUTPUT("Vibra 2"),
585
586 /* Mic 1 */
587
588 SND_SOC_DAPM_INPUT("Mic 1"),
589
590 SND_SOC_DAPM_MUX("Mic 1a or 1b Select",
591 SND_SOC_NOPM, 0, 0, dapm_mic1ab_mux),
592 SND_SOC_DAPM_MIXER("MIC1 Mute",
593 AB8500_ANACONF2, AB8500_ANACONF2_MUTMIC1, 1,
594 NULL, 0),
595 SND_SOC_DAPM_MIXER("MIC1A V-AMICx Enable",
596 AB8500_ANACONF2, AB8500_ANACONF2_ENMIC1, 0,
597 NULL, 0),
598 SND_SOC_DAPM_MIXER("MIC1B V-AMICx Enable",
599 AB8500_ANACONF2, AB8500_ANACONF2_ENMIC1, 0,
600 NULL, 0),
601 SND_SOC_DAPM_MIXER("MIC1 ADC",
602 AB8500_ANACONF3, AB8500_ANACONF3_ENADCMIC, 0,
603 NULL, 0),
604 SND_SOC_DAPM_MUX("AD3 Source Select",
605 SND_SOC_NOPM, 0, 0, dapm_ad3_select),
606 SND_SOC_DAPM_MIXER("AD3 Channel Volume",
607 SND_SOC_NOPM, 0, 0,
608 NULL, 0),
609 SND_SOC_DAPM_MIXER("AD3 Enable",
610 AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD34, 0,
611 NULL, 0),
612
613 /* Mic 2 */
614
615 SND_SOC_DAPM_INPUT("Mic 2"),
616
617 SND_SOC_DAPM_MIXER("MIC2 Mute",
618 AB8500_ANACONF2, AB8500_ANACONF2_MUTMIC2, 1,
619 NULL, 0),
620 SND_SOC_DAPM_MIXER("MIC2 V-AMICx Enable", AB8500_ANACONF2,
621 AB8500_ANACONF2_ENMIC2, 0,
622 NULL, 0),
623
624 /* LineIn */
625
626 SND_SOC_DAPM_INPUT("LineIn Left"),
627 SND_SOC_DAPM_INPUT("LineIn Right"),
628
629 SND_SOC_DAPM_MIXER("LINL Mute",
630 AB8500_ANACONF2, AB8500_ANACONF2_MUTLINL, 1,
631 NULL, 0),
632 SND_SOC_DAPM_MIXER("LINR Mute",
633 AB8500_ANACONF2, AB8500_ANACONF2_MUTLINR, 1,
634 NULL, 0),
635 SND_SOC_DAPM_MIXER("LINL Enable", AB8500_ANACONF2,
636 AB8500_ANACONF2_ENLINL, 0,
637 NULL, 0),
638 SND_SOC_DAPM_MIXER("LINR Enable", AB8500_ANACONF2,
639 AB8500_ANACONF2_ENLINR, 0,
640 NULL, 0),
641
642 /* LineIn Bypass path */
643 SND_SOC_DAPM_MIXER("LINL to HSL Volume",
644 SND_SOC_NOPM, 0, 0,
645 NULL, 0),
646 SND_SOC_DAPM_MIXER("LINR to HSR Volume",
647 SND_SOC_NOPM, 0, 0,
648 NULL, 0),
649
650 /* LineIn, Mic 2 */
651 SND_SOC_DAPM_MUX("Mic 2 or LINR Select",
652 SND_SOC_NOPM, 0, 0, dapm_mic2lr_select),
653 SND_SOC_DAPM_MIXER("LINL ADC", AB8500_ANACONF3,
654 AB8500_ANACONF3_ENADCLINL, 0,
655 NULL, 0),
656 SND_SOC_DAPM_MIXER("LINR ADC", AB8500_ANACONF3,
657 AB8500_ANACONF3_ENADCLINR, 0,
658 NULL, 0),
659 SND_SOC_DAPM_MUX("AD1 Source Select",
660 SND_SOC_NOPM, 0, 0, dapm_ad1_select),
661 SND_SOC_DAPM_MUX("AD2 Source Select",
662 SND_SOC_NOPM, 0, 0, dapm_ad2_select),
663 SND_SOC_DAPM_MIXER("AD1 Channel Volume",
664 SND_SOC_NOPM, 0, 0,
665 NULL, 0),
666 SND_SOC_DAPM_MIXER("AD2 Channel Volume",
667 SND_SOC_NOPM, 0, 0,
668 NULL, 0),
669
670 SND_SOC_DAPM_MIXER("AD12 Enable",
671 AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD12, 0,
672 NULL, 0),
673
674 /* HD Capture path */
675
676 SND_SOC_DAPM_MUX("AD5 Source Select",
677 SND_SOC_NOPM, 0, 0, dapm_ad5_select),
678 SND_SOC_DAPM_MUX("AD6 Source Select",
679 SND_SOC_NOPM, 0, 0, dapm_ad6_select),
680 SND_SOC_DAPM_MIXER("AD5 Channel Volume",
681 SND_SOC_NOPM, 0, 0,
682 NULL, 0),
683 SND_SOC_DAPM_MIXER("AD6 Channel Volume",
684 SND_SOC_NOPM, 0, 0,
685 NULL, 0),
686 SND_SOC_DAPM_MIXER("AD57 Enable",
687 AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD5768, 0,
688 NULL, 0),
689 SND_SOC_DAPM_MIXER("AD68 Enable",
690 AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD5768, 0,
691 NULL, 0),
692
693 /* Digital Microphone path */
694
695 SND_SOC_DAPM_INPUT("DMic 1"),
696 SND_SOC_DAPM_INPUT("DMic 2"),
697 SND_SOC_DAPM_INPUT("DMic 3"),
698 SND_SOC_DAPM_INPUT("DMic 4"),
699 SND_SOC_DAPM_INPUT("DMic 5"),
700 SND_SOC_DAPM_INPUT("DMic 6"),
701
702 SND_SOC_DAPM_MIXER("DMIC1",
703 AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC1, 0,
704 NULL, 0),
705 SND_SOC_DAPM_MIXER("DMIC2",
706 AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC2, 0,
707 NULL, 0),
708 SND_SOC_DAPM_MIXER("DMIC3",
709 AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC3, 0,
710 NULL, 0),
711 SND_SOC_DAPM_MIXER("DMIC4",
712 AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC4, 0,
713 NULL, 0),
714 SND_SOC_DAPM_MIXER("DMIC5",
715 AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC5, 0,
716 NULL, 0),
717 SND_SOC_DAPM_MIXER("DMIC6",
718 AB8500_DIGMICCONF, AB8500_DIGMICCONF_ENDMIC6, 0,
719 NULL, 0),
720 SND_SOC_DAPM_MIXER("AD4 Channel Volume",
721 SND_SOC_NOPM, 0, 0,
722 NULL, 0),
723 SND_SOC_DAPM_MIXER("AD4 Enable",
724 AB8500_ADPATHENA, AB8500_ADPATHENA_ENAD34,
725 0, NULL, 0),
726
727 /* Acoustical Noise Cancellation path */
728
729 SND_SOC_DAPM_INPUT("ANC Configure Input"),
730 SND_SOC_DAPM_OUTPUT("ANC Configure Output"),
731
732 SND_SOC_DAPM_MUX("ANC Source",
733 SND_SOC_NOPM, 0, 0,
734 dapm_anc_in_select),
735 SND_SOC_DAPM_SWITCH("ANC",
736 SND_SOC_NOPM, 0, 0,
737 dapm_anc_enable),
738 SND_SOC_DAPM_SWITCH("ANC to Earpiece",
739 SND_SOC_NOPM, 0, 0,
740 dapm_anc_ear_mute),
741
742 /* Sidetone Filter path */
743
744 SND_SOC_DAPM_MUX("Sidetone Left Source",
745 SND_SOC_NOPM, 0, 0,
746 dapm_stfir1_in_select),
747 SND_SOC_DAPM_MUX("Sidetone Right Source",
748 SND_SOC_NOPM, 0, 0,
749 dapm_stfir2_in_select),
750 SND_SOC_DAPM_MIXER("STFIR1 Control",
751 SND_SOC_NOPM, 0, 0,
752 NULL, 0),
753 SND_SOC_DAPM_MIXER("STFIR2 Control",
754 SND_SOC_NOPM, 0, 0,
755 NULL, 0),
756 SND_SOC_DAPM_MIXER("STFIR1 Volume",
757 SND_SOC_NOPM, 0, 0,
758 NULL, 0),
759 SND_SOC_DAPM_MIXER("STFIR2 Volume",
760 SND_SOC_NOPM, 0, 0,
761 NULL, 0),
762};
763
764/*
765 * DAPM-routes
766 */
767static const struct snd_soc_dapm_route ab8500_dapm_routes[] = {
768 /* Power AB8500 audio-block when AD/DA is active */
769 {"Main Supply", NULL, "V-AUD"},
770 {"Main Supply", NULL, "audioclk"},
771 {"Main Supply", NULL, "Audio Power"},
772 {"Main Supply", NULL, "Audio Analog Power"},
773
774 {"DAC", NULL, "ab8500_0p"},
775 {"DAC", NULL, "Main Supply"},
776 {"ADC", NULL, "ab8500_0c"},
777 {"ADC", NULL, "Main Supply"},
778
779 /* ANC Configure */
780 {"ANC Configure Input", NULL, "Main Supply"},
781 {"ANC Configure Output", NULL, "ANC Configure Input"},
782
783 /* AD/DA */
784 {"ADC", NULL, "ADC Input"},
785 {"DAC Output", NULL, "DAC"},
786
787 /* Powerup charge pump if DA1/2 is in use */
788
789 {"DA_IN1", NULL, "ab8500_0p"},
790 {"DA_IN1", NULL, "Charge Pump"},
791 {"DA_IN2", NULL, "ab8500_0p"},
792 {"DA_IN2", NULL, "Charge Pump"},
793
794 /* Headset path */
795
796 {"DA1 Enable", NULL, "DA_IN1"},
797 {"DA2 Enable", NULL, "DA_IN2"},
798
799 {"HSL Digital Volume", NULL, "DA1 Enable"},
800 {"HSR Digital Volume", NULL, "DA2 Enable"},
801
802 {"HSL DAC", NULL, "HSL Digital Volume"},
803 {"HSR DAC", NULL, "HSR Digital Volume"},
804
805 {"HSL DAC Mute", NULL, "HSL DAC"},
806 {"HSR DAC Mute", NULL, "HSR DAC"},
807
808 {"HSL DAC Driver", NULL, "HSL DAC Mute"},
809 {"HSR DAC Driver", NULL, "HSR DAC Mute"},
810
811 {"HSL Mute", NULL, "HSL DAC Driver"},
812 {"HSR Mute", NULL, "HSR DAC Driver"},
813
814 {"HSL Enable", NULL, "HSL Mute"},
815 {"HSR Enable", NULL, "HSR Mute"},
816
817 {"HSL Volume", NULL, "HSL Enable"},
818 {"HSR Volume", NULL, "HSR Enable"},
819
820 {"Headset Left", NULL, "HSL Volume"},
821 {"Headset Right", NULL, "HSR Volume"},
822
823 /* HF or LineOut path */
824
825 {"DA_IN3", NULL, "ab8500_0p"},
826 {"DA3 Channel Volume", NULL, "DA_IN3"},
827 {"DA_IN4", NULL, "ab8500_0p"},
828 {"DA4 Channel Volume", NULL, "DA_IN4"},
829
830 {"Speaker Left Source", "Audio Path", "DA3 Channel Volume"},
831 {"Speaker Right Source", "Audio Path", "DA4 Channel Volume"},
832
833 {"DA3 or ANC path to HfL", NULL, "Speaker Left Source"},
834 {"DA4 or ANC path to HfR", NULL, "Speaker Right Source"},
835
836 /* HF path */
837
838 {"HFL DAC", NULL, "DA3 or ANC path to HfL"},
839 {"HFR DAC", NULL, "DA4 or ANC path to HfR"},
840
841 {"HFL Enable", NULL, "HFL DAC"},
842 {"HFR Enable", NULL, "HFR DAC"},
843
844 {"Speaker Left", NULL, "HFL Enable"},
845 {"Speaker Right", NULL, "HFR Enable"},
846
847 /* Earpiece path */
848
849 {"Earpiece or LineOut Mono Source", "Headset Left",
850 "HSL Digital Volume"},
851 {"Earpiece or LineOut Mono Source", "Speaker Left",
852 "DA3 or ANC path to HfL"},
853
854 {"EAR DAC", NULL, "Earpiece or LineOut Mono Source"},
855
856 {"EAR Mute", NULL, "EAR DAC"},
857
858 {"EAR Enable", NULL, "EAR Mute"},
859
860 {"Earpiece", NULL, "EAR Enable"},
861
862 /* LineOut path stereo */
863
864 {"LineOut Source", "Stereo Path", "HSL DAC Driver"},
865 {"LineOut Source", "Stereo Path", "HSR DAC Driver"},
866
867 /* LineOut path mono */
868
869 {"LineOut Source", "Mono Path", "EAR DAC"},
870
871 /* LineOut path */
872
873 {"LOL Disable HFL", NULL, "LineOut Source"},
874 {"LOR Disable HFR", NULL, "LineOut Source"},
875
876 {"LOL Enable", NULL, "LOL Disable HFL"},
877 {"LOR Enable", NULL, "LOR Disable HFR"},
878
879 {"LineOut Left", NULL, "LOL Enable"},
880 {"LineOut Right", NULL, "LOR Enable"},
881
882 /* Vibrator path */
883
884 {"DA_IN5", NULL, "ab8500_0p"},
885 {"DA5 Channel Volume", NULL, "DA_IN5"},
886 {"DA_IN6", NULL, "ab8500_0p"},
887 {"DA6 Channel Volume", NULL, "DA_IN6"},
888
889 {"VIB1 DAC", NULL, "DA5 Channel Volume"},
890 {"VIB2 DAC", NULL, "DA6 Channel Volume"},
891
892 {"Vibra 1 Controller", "Audio Path", "VIB1 DAC"},
893 {"Vibra 2 Controller", "Audio Path", "VIB2 DAC"},
894 {"Vibra 1 Controller", "PWM Generator", "PWMGEN1"},
895 {"Vibra 2 Controller", "PWM Generator", "PWMGEN2"},
896
897 {"VIB1 Enable", NULL, "Vibra 1 Controller"},
898 {"VIB2 Enable", NULL, "Vibra 2 Controller"},
899
900 {"Vibra 1", NULL, "VIB1 Enable"},
901 {"Vibra 2", NULL, "VIB2 Enable"},
902
903
904 /* Mic 2 */
905
906 {"MIC2 V-AMICx Enable", NULL, "Mic 2"},
907
908 /* LineIn */
909 {"LINL Mute", NULL, "LineIn Left"},
910 {"LINR Mute", NULL, "LineIn Right"},
911
912 {"LINL Enable", NULL, "LINL Mute"},
913 {"LINR Enable", NULL, "LINR Mute"},
914
915 /* LineIn, Mic 2 */
916 {"Mic 2 or LINR Select", "LineIn Right", "LINR Enable"},
917 {"Mic 2 or LINR Select", "Mic 2", "MIC2 V-AMICx Enable"},
918
919 {"LINL ADC", NULL, "LINL Enable"},
920 {"LINR ADC", NULL, "Mic 2 or LINR Select"},
921
922 {"AD1 Source Select", "LineIn Left", "LINL ADC"},
923 {"AD2 Source Select", "LineIn Right", "LINR ADC"},
924
925 {"AD1 Channel Volume", NULL, "AD1 Source Select"},
926 {"AD2 Channel Volume", NULL, "AD2 Source Select"},
927
928 {"AD12 Enable", NULL, "AD1 Channel Volume"},
929 {"AD12 Enable", NULL, "AD2 Channel Volume"},
930
931 {"AD_OUT1", NULL, "ab8500_0c"},
932 {"AD_OUT1", NULL, "AD12 Enable"},
933 {"AD_OUT2", NULL, "ab8500_0c"},
934 {"AD_OUT2", NULL, "AD12 Enable"},
935
936 /* Mic 1 */
937
938 {"MIC1 Mute", NULL, "Mic 1"},
939
940 {"MIC1A V-AMICx Enable", NULL, "MIC1 Mute"},
941 {"MIC1B V-AMICx Enable", NULL, "MIC1 Mute"},
942
943 {"Mic 1a or 1b Select", "Mic 1a", "MIC1A V-AMICx Enable"},
944 {"Mic 1a or 1b Select", "Mic 1b", "MIC1B V-AMICx Enable"},
945
946 {"MIC1 ADC", NULL, "Mic 1a or 1b Select"},
947
948 {"AD3 Source Select", "Mic 1", "MIC1 ADC"},
949
950 {"AD3 Channel Volume", NULL, "AD3 Source Select"},
951
952 {"AD3 Enable", NULL, "AD3 Channel Volume"},
953
954 {"AD_OUT3", NULL, "ab8500_0c"},
955 {"AD_OUT3", NULL, "AD3 Enable"},
956
957 /* HD Capture path */
958
959 {"AD5 Source Select", "Mic 2", "LINR ADC"},
960 {"AD6 Source Select", "Mic 1", "MIC1 ADC"},
961
962 {"AD5 Channel Volume", NULL, "AD5 Source Select"},
963 {"AD6 Channel Volume", NULL, "AD6 Source Select"},
964
965 {"AD57 Enable", NULL, "AD5 Channel Volume"},
966 {"AD68 Enable", NULL, "AD6 Channel Volume"},
967
968 {"AD_OUT57", NULL, "ab8500_0c"},
969 {"AD_OUT57", NULL, "AD57 Enable"},
970 {"AD_OUT68", NULL, "ab8500_0c"},
971 {"AD_OUT68", NULL, "AD68 Enable"},
972
973 /* Digital Microphone path */
974
975 {"DMic 1", NULL, "V-DMIC"},
976 {"DMic 2", NULL, "V-DMIC"},
977 {"DMic 3", NULL, "V-DMIC"},
978 {"DMic 4", NULL, "V-DMIC"},
979 {"DMic 5", NULL, "V-DMIC"},
980 {"DMic 6", NULL, "V-DMIC"},
981
982 {"AD1 Source Select", NULL, "DMic 1"},
983 {"AD2 Source Select", NULL, "DMic 2"},
984 {"AD3 Source Select", NULL, "DMic 3"},
985 {"AD5 Source Select", NULL, "DMic 5"},
986 {"AD6 Source Select", NULL, "DMic 6"},
987
988 {"AD4 Channel Volume", NULL, "DMic 4"},
989 {"AD4 Enable", NULL, "AD4 Channel Volume"},
990
991 {"AD_OUT4", NULL, "ab8500_0c"},
992 {"AD_OUT4", NULL, "AD4 Enable"},
993
994 /* LineIn Bypass path */
995
996 {"LINL to HSL Volume", NULL, "LINL Enable"},
997 {"LINR to HSR Volume", NULL, "LINR Enable"},
998
999 {"HSL DAC Driver", NULL, "LINL to HSL Volume"},
1000 {"HSR DAC Driver", NULL, "LINR to HSR Volume"},
1001
1002 /* ANC path (Acoustic Noise Cancellation) */
1003
1004 {"ANC Source", "Mic 2 / DMic 5", "AD5 Channel Volume"},
1005 {"ANC Source", "Mic 1 / DMic 6", "AD6 Channel Volume"},
1006
1007 {"ANC", "Switch", "ANC Source"},
1008
1009 {"Speaker Left Source", "ANC", "ANC"},
1010 {"Speaker Right Source", "ANC", "ANC"},
1011 {"ANC to Earpiece", "Switch", "ANC"},
1012
1013 {"HSL Digital Volume", NULL, "ANC to Earpiece"},
1014
1015 /* Sidetone Filter path */
1016
1017 {"Sidetone Left Source", "LineIn Left", "AD12 Enable"},
1018 {"Sidetone Left Source", "LineIn Right", "AD12 Enable"},
1019 {"Sidetone Left Source", "Mic 1", "AD3 Enable"},
1020 {"Sidetone Left Source", "Headset Left", "DA_IN1"},
1021 {"Sidetone Right Source", "LineIn Right", "AD12 Enable"},
1022 {"Sidetone Right Source", "Mic 1", "AD3 Enable"},
1023 {"Sidetone Right Source", "DMic 4", "AD4 Enable"},
1024 {"Sidetone Right Source", "Headset Right", "DA_IN2"},
1025
1026 {"STFIR1 Control", NULL, "Sidetone Left Source"},
1027 {"STFIR2 Control", NULL, "Sidetone Right Source"},
1028
1029 {"STFIR1 Volume", NULL, "STFIR1 Control"},
1030 {"STFIR2 Volume", NULL, "STFIR2 Control"},
1031
1032 {"DA1 Enable", NULL, "STFIR1 Volume"},
1033 {"DA2 Enable", NULL, "STFIR2 Volume"},
1034};
1035
1036static const struct snd_soc_dapm_route ab8500_dapm_routes_mic1a_vamicx[] = {
1037 {"MIC1A V-AMICx Enable", NULL, "V-AMIC1"},
1038 {"MIC1A V-AMICx Enable", NULL, "V-AMIC2"},
1039};
1040
1041static const struct snd_soc_dapm_route ab8500_dapm_routes_mic1b_vamicx[] = {
1042 {"MIC1B V-AMICx Enable", NULL, "V-AMIC1"},
1043 {"MIC1B V-AMICx Enable", NULL, "V-AMIC2"},
1044};
1045
1046static const struct snd_soc_dapm_route ab8500_dapm_routes_mic2_vamicx[] = {
1047 {"MIC2 V-AMICx Enable", NULL, "V-AMIC1"},
1048 {"MIC2 V-AMICx Enable", NULL, "V-AMIC2"},
1049};
1050
1051/* ANC FIR-coefficients configuration sequence */
1052static void anc_fir(struct snd_soc_codec *codec,
1053 unsigned int bnk, unsigned int par, unsigned int val)
1054{
1055 if (par == 0 && bnk == 0)
1056 snd_soc_update_bits(codec, AB8500_ANCCONF1,
1057 BIT(AB8500_ANCCONF1_ANCFIRUPDATE),
1058 BIT(AB8500_ANCCONF1_ANCFIRUPDATE));
1059
1060 snd_soc_write(codec, AB8500_ANCCONF5, val >> 8 & 0xff);
1061 snd_soc_write(codec, AB8500_ANCCONF6, val & 0xff);
1062
1063 if (par == AB8500_ANC_FIR_COEFFS - 1 && bnk == 1)
1064 snd_soc_update_bits(codec, AB8500_ANCCONF1,
1065 BIT(AB8500_ANCCONF1_ANCFIRUPDATE), 0);
1066}
1067
1068/* ANC IIR-coefficients configuration sequence */
1069static void anc_iir(struct snd_soc_codec *codec, unsigned int bnk,
1070 unsigned int par, unsigned int val)
1071{
1072 if (par == 0) {
1073 if (bnk == 0) {
1074 snd_soc_update_bits(codec, AB8500_ANCCONF1,
1075 BIT(AB8500_ANCCONF1_ANCIIRINIT),
1076 BIT(AB8500_ANCCONF1_ANCIIRINIT));
1077 usleep_range(AB8500_ANC_SM_DELAY, AB8500_ANC_SM_DELAY);
1078 snd_soc_update_bits(codec, AB8500_ANCCONF1,
1079 BIT(AB8500_ANCCONF1_ANCIIRINIT), 0);
1080 usleep_range(AB8500_ANC_SM_DELAY, AB8500_ANC_SM_DELAY);
1081 } else {
1082 snd_soc_update_bits(codec, AB8500_ANCCONF1,
1083 BIT(AB8500_ANCCONF1_ANCIIRUPDATE),
1084 BIT(AB8500_ANCCONF1_ANCIIRUPDATE));
1085 }
1086 } else if (par > 3) {
1087 snd_soc_write(codec, AB8500_ANCCONF7, 0);
1088 snd_soc_write(codec, AB8500_ANCCONF8, val >> 16 & 0xff);
1089 }
1090
1091 snd_soc_write(codec, AB8500_ANCCONF7, val >> 8 & 0xff);
1092 snd_soc_write(codec, AB8500_ANCCONF8, val & 0xff);
1093
1094 if (par == AB8500_ANC_IIR_COEFFS - 1 && bnk == 1)
1095 snd_soc_update_bits(codec, AB8500_ANCCONF1,
1096 BIT(AB8500_ANCCONF1_ANCIIRUPDATE), 0);
1097}
1098
1099/* ANC IIR-/FIR-coefficients configuration sequence */
1100static void anc_configure(struct snd_soc_codec *codec,
1101 bool apply_fir, bool apply_iir)
1102{
1103 struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
1104 unsigned int bnk, par, val;
1105
1106 dev_dbg(codec->dev, "%s: Enter.\n", __func__);
1107
1108 if (apply_fir)
1109 snd_soc_update_bits(codec, AB8500_ANCCONF1,
1110 BIT(AB8500_ANCCONF1_ENANC), 0);
1111
1112 snd_soc_update_bits(codec, AB8500_ANCCONF1,
1113 BIT(AB8500_ANCCONF1_ENANC), BIT(AB8500_ANCCONF1_ENANC));
1114
1115 if (apply_fir)
1116 for (bnk = 0; bnk < AB8500_NR_OF_ANC_COEFF_BANKS; bnk++)
1117 for (par = 0; par < AB8500_ANC_FIR_COEFFS; par++) {
1118 val = snd_soc_read(codec,
1119 drvdata->anc_fir_values[par]);
1120 anc_fir(codec, bnk, par, val);
1121 }
1122
1123 if (apply_iir)
1124 for (bnk = 0; bnk < AB8500_NR_OF_ANC_COEFF_BANKS; bnk++)
1125 for (par = 0; par < AB8500_ANC_IIR_COEFFS; par++) {
1126 val = snd_soc_read(codec,
1127 drvdata->anc_iir_values[par]);
1128 anc_iir(codec, bnk, par, val);
1129 }
1130
1131 dev_dbg(codec->dev, "%s: Exit.\n", __func__);
1132}
1133
1134/*
1135 * Control-events
1136 */
1137
1138static int sid_status_control_get(struct snd_kcontrol *kcontrol,
1139 struct snd_ctl_elem_value *ucontrol)
1140{
1141 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1142 struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
1143
1144 mutex_lock(&codec->mutex);
1145 ucontrol->value.integer.value[0] = drvdata->sid_status;
1146 mutex_unlock(&codec->mutex);
1147
1148 return 0;
1149}
1150
1151/* Write sidetone FIR-coefficients configuration sequence */
1152static int sid_status_control_put(struct snd_kcontrol *kcontrol,
1153 struct snd_ctl_elem_value *ucontrol)
1154{
1155 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1156 struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
1157 unsigned int param, sidconf, val;
1158 int status = 1;
1159
1160 dev_dbg(codec->dev, "%s: Enter\n", __func__);
1161
1162 if (ucontrol->value.integer.value[0] != SID_APPLY_FIR) {
1163 dev_err(codec->dev,
1164 "%s: ERROR: This control supports '%s' only!\n",
1165 __func__, enum_sid_state[SID_APPLY_FIR]);
1166 return -EIO;
1167 }
1168
1169 mutex_lock(&codec->mutex);
1170
1171 sidconf = snd_soc_read(codec, AB8500_SIDFIRCONF);
1172 if (((sidconf & BIT(AB8500_SIDFIRCONF_FIRSIDBUSY)) != 0)) {
1173 if ((sidconf & BIT(AB8500_SIDFIRCONF_ENFIRSIDS)) == 0) {
1174 dev_err(codec->dev, "%s: Sidetone busy while off!\n",
1175 __func__);
1176 status = -EPERM;
1177 } else {
1178 status = -EBUSY;
1179 }
1180 goto out;
1181 }
1182
1183 snd_soc_write(codec, AB8500_SIDFIRADR, 0);
1184
1185 for (param = 0; param < AB8500_SID_FIR_COEFFS; param++) {
1186 val = snd_soc_read(codec, drvdata->sid_fir_values[param]);
1187 snd_soc_write(codec, AB8500_SIDFIRCOEF1, val >> 8 & 0xff);
1188 snd_soc_write(codec, AB8500_SIDFIRCOEF2, val & 0xff);
1189 }
1190
1191 snd_soc_update_bits(codec, AB8500_SIDFIRADR,
1192 BIT(AB8500_SIDFIRADR_FIRSIDSET),
1193 BIT(AB8500_SIDFIRADR_FIRSIDSET));
1194 snd_soc_update_bits(codec, AB8500_SIDFIRADR,
1195 BIT(AB8500_SIDFIRADR_FIRSIDSET), 0);
1196
1197 drvdata->sid_status = SID_FIR_CONFIGURED;
1198
1199out:
1200 mutex_unlock(&codec->mutex);
1201
1202 dev_dbg(codec->dev, "%s: Exit\n", __func__);
1203
1204 return status;
1205}
1206
1207static int anc_status_control_get(struct snd_kcontrol *kcontrol,
1208 struct snd_ctl_elem_value *ucontrol)
1209{
1210 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1211 struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
1212
1213 mutex_lock(&codec->mutex);
1214 ucontrol->value.integer.value[0] = drvdata->anc_status;
1215 mutex_unlock(&codec->mutex);
1216
1217 return 0;
1218}
1219
1220static int anc_status_control_put(struct snd_kcontrol *kcontrol,
1221 struct snd_ctl_elem_value *ucontrol)
1222{
1223 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1224 struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
1225 struct device *dev = codec->dev;
1226 bool apply_fir, apply_iir;
1227 int req, status;
1228
1229 dev_dbg(dev, "%s: Enter.\n", __func__);
1230
1231 mutex_lock(&drvdata->anc_lock);
1232
1233 req = ucontrol->value.integer.value[0];
1234 if (req != ANC_APPLY_FIR_IIR && req != ANC_APPLY_FIR &&
1235 req != ANC_APPLY_IIR) {
1236 dev_err(dev, "%s: ERROR: Unsupported status to set '%s'!\n",
1237 __func__, enum_anc_state[req]);
1238 status = -EINVAL;
1239 goto cleanup;
1240 }
1241 apply_fir = req == ANC_APPLY_FIR || req == ANC_APPLY_FIR_IIR;
1242 apply_iir = req == ANC_APPLY_IIR || req == ANC_APPLY_FIR_IIR;
1243
1244 status = snd_soc_dapm_force_enable_pin(&codec->dapm,
1245 "ANC Configure Input");
1246 if (status < 0) {
1247 dev_err(dev,
1248 "%s: ERROR: Failed to enable power (status = %d)!\n",
1249 __func__, status);
1250 goto cleanup;
1251 }
1252 snd_soc_dapm_sync(&codec->dapm);
1253
1254 mutex_lock(&codec->mutex);
1255 anc_configure(codec, apply_fir, apply_iir);
1256 mutex_unlock(&codec->mutex);
1257
1258 if (apply_fir) {
1259 if (drvdata->anc_status == ANC_IIR_CONFIGURED)
1260 drvdata->anc_status = ANC_FIR_IIR_CONFIGURED;
1261 else if (drvdata->anc_status != ANC_FIR_IIR_CONFIGURED)
1262 drvdata->anc_status = ANC_FIR_CONFIGURED;
1263 }
1264 if (apply_iir) {
1265 if (drvdata->anc_status == ANC_FIR_CONFIGURED)
1266 drvdata->anc_status = ANC_FIR_IIR_CONFIGURED;
1267 else if (drvdata->anc_status != ANC_FIR_IIR_CONFIGURED)
1268 drvdata->anc_status = ANC_IIR_CONFIGURED;
1269 }
1270
1271 status = snd_soc_dapm_disable_pin(&codec->dapm, "ANC Configure Input");
1272 snd_soc_dapm_sync(&codec->dapm);
1273
1274cleanup:
1275 mutex_unlock(&drvdata->anc_lock);
1276
1277 if (status < 0)
1278 dev_err(dev, "%s: Unable to configure ANC! (status = %d)\n",
1279 __func__, status);
1280
1281 dev_dbg(dev, "%s: Exit.\n", __func__);
1282
1283 return (status < 0) ? status : 1;
1284}
1285
1286static int filter_control_info(struct snd_kcontrol *kcontrol,
1287 struct snd_ctl_elem_info *uinfo)
1288{
1289 struct filter_control *fc =
1290 (struct filter_control *)kcontrol->private_value;
1291
1292 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1293 uinfo->count = fc->count;
1294 uinfo->value.integer.min = fc->min;
1295 uinfo->value.integer.max = fc->max;
1296
1297 return 0;
1298}
1299
1300static int filter_control_get(struct snd_kcontrol *kcontrol,
1301 struct snd_ctl_elem_value *ucontrol)
1302{
1303 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1304 struct filter_control *fc =
1305 (struct filter_control *)kcontrol->private_value;
1306 unsigned int i;
1307
1308 mutex_lock(&codec->mutex);
1309 for (i = 0; i < fc->count; i++)
1310 ucontrol->value.integer.value[i] = fc->value[i];
1311 mutex_unlock(&codec->mutex);
1312
1313 return 0;
1314}
1315
1316static int filter_control_put(struct snd_kcontrol *kcontrol,
1317 struct snd_ctl_elem_value *ucontrol)
1318{
1319 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1320 struct filter_control *fc =
1321 (struct filter_control *)kcontrol->private_value;
1322 unsigned int i;
1323
1324 mutex_lock(&codec->mutex);
1325 for (i = 0; i < fc->count; i++)
1326 fc->value[i] = ucontrol->value.integer.value[i];
1327 mutex_unlock(&codec->mutex);
1328
1329 return 0;
1330}
1331
1332/*
1333 * Controls - Non-DAPM ASoC
1334 */
1335
1336static DECLARE_TLV_DB_SCALE(adx_dig_gain_tlv, -3200, 100, 1);
1337/* -32dB = Mute */
1338
1339static DECLARE_TLV_DB_SCALE(dax_dig_gain_tlv, -6300, 100, 1);
1340/* -63dB = Mute */
1341
1342static DECLARE_TLV_DB_SCALE(hs_ear_dig_gain_tlv, -100, 100, 1);
1343/* -1dB = Mute */
1344
1345static const unsigned int hs_gain_tlv[] = {
1346 TLV_DB_RANGE_HEAD(2),
1347 0, 3, TLV_DB_SCALE_ITEM(-3200, 400, 0),
1348 4, 15, TLV_DB_SCALE_ITEM(-1800, 200, 0),
1349};
1350
1351static DECLARE_TLV_DB_SCALE(mic_gain_tlv, 0, 100, 0);
1352
1353static DECLARE_TLV_DB_SCALE(lin_gain_tlv, -1000, 200, 0);
1354
1355static DECLARE_TLV_DB_SCALE(lin2hs_gain_tlv, -3800, 200, 1);
1356/* -38dB = Mute */
1357
1358static const char * const enum_hsfadspeed[] = {"2ms", "0.5ms", "10.6ms",
1359 "5ms"};
1360static SOC_ENUM_SINGLE_DECL(soc_enum_hsfadspeed,
1361 AB8500_DIGMICCONF, AB8500_DIGMICCONF_HSFADSPEED, enum_hsfadspeed);
1362
1363static const char * const enum_envdetthre[] = {
1364 "250mV", "300mV", "350mV", "400mV",
1365 "450mV", "500mV", "550mV", "600mV",
1366 "650mV", "700mV", "750mV", "800mV",
1367 "850mV", "900mV", "950mV", "1.00V" };
1368static SOC_ENUM_SINGLE_DECL(soc_enum_envdeththre,
1369 AB8500_ENVCPCONF, AB8500_ENVCPCONF_ENVDETHTHRE, enum_envdetthre);
1370static SOC_ENUM_SINGLE_DECL(soc_enum_envdetlthre,
1371 AB8500_ENVCPCONF, AB8500_ENVCPCONF_ENVDETLTHRE, enum_envdetthre);
1372static const char * const enum_envdettime[] = {
1373 "26.6us", "53.2us", "106us", "213us",
1374 "426us", "851us", "1.70ms", "3.40ms",
1375 "6.81ms", "13.6ms", "27.2ms", "54.5ms",
1376 "109ms", "218ms", "436ms", "872ms" };
1377static SOC_ENUM_SINGLE_DECL(soc_enum_envdettime,
1378 AB8500_SIGENVCONF, AB8500_SIGENVCONF_ENVDETTIME, enum_envdettime);
1379
1380static const char * const enum_sinc31[] = {"Sinc 3", "Sinc 1"};
1381static SOC_ENUM_SINGLE_DECL(soc_enum_hsesinc, AB8500_HSLEARDIGGAIN,
1382 AB8500_HSLEARDIGGAIN_HSSINC1, enum_sinc31);
1383
1384static const char * const enum_fadespeed[] = {"1ms", "4ms", "8ms", "16ms"};
1385static SOC_ENUM_SINGLE_DECL(soc_enum_fadespeed, AB8500_HSRDIGGAIN,
1386 AB8500_HSRDIGGAIN_FADESPEED, enum_fadespeed);
1387
1388/* Earpiece */
1389
1390static const char * const enum_lowpow[] = {"Normal", "Low Power"};
1391static SOC_ENUM_SINGLE_DECL(soc_enum_eardaclowpow, AB8500_ANACONF1,
1392 AB8500_ANACONF1_EARDACLOWPOW, enum_lowpow);
1393static SOC_ENUM_SINGLE_DECL(soc_enum_eardrvlowpow, AB8500_ANACONF1,
1394 AB8500_ANACONF1_EARDRVLOWPOW, enum_lowpow);
1395
1396static const char * const enum_av_mode[] = {"Audio", "Voice"};
1397static SOC_ENUM_DOUBLE_DECL(soc_enum_ad12voice, AB8500_ADFILTCONF,
1398 AB8500_ADFILTCONF_AD1VOICE, AB8500_ADFILTCONF_AD2VOICE, enum_av_mode);
1399static SOC_ENUM_DOUBLE_DECL(soc_enum_ad34voice, AB8500_ADFILTCONF,
1400 AB8500_ADFILTCONF_AD3VOICE, AB8500_ADFILTCONF_AD4VOICE, enum_av_mode);
1401
1402/* DA */
1403
1404static SOC_ENUM_SINGLE_DECL(soc_enum_da12voice,
1405 AB8500_DASLOTCONF1, AB8500_DASLOTCONF1_DA12VOICE,
1406 enum_av_mode);
1407static SOC_ENUM_SINGLE_DECL(soc_enum_da34voice,
1408 AB8500_DASLOTCONF3, AB8500_DASLOTCONF3_DA34VOICE,
1409 enum_av_mode);
1410static SOC_ENUM_SINGLE_DECL(soc_enum_da56voice,
1411 AB8500_DASLOTCONF5, AB8500_DASLOTCONF5_DA56VOICE,
1412 enum_av_mode);
1413
1414static const char * const enum_da2hslr[] = {"Sidetone", "Audio Path"};
1415static SOC_ENUM_DOUBLE_DECL(soc_enum_da2hslr, AB8500_DIGMULTCONF1,
1416 AB8500_DIGMULTCONF1_DATOHSLEN,
1417 AB8500_DIGMULTCONF1_DATOHSREN, enum_da2hslr);
1418
1419static const char * const enum_sinc53[] = {"Sinc 5", "Sinc 3"};
1420static SOC_ENUM_DOUBLE_DECL(soc_enum_dmic12sinc, AB8500_DMICFILTCONF,
1421 AB8500_DMICFILTCONF_DMIC1SINC3,
1422 AB8500_DMICFILTCONF_DMIC2SINC3, enum_sinc53);
1423static SOC_ENUM_DOUBLE_DECL(soc_enum_dmic34sinc, AB8500_DMICFILTCONF,
1424 AB8500_DMICFILTCONF_DMIC3SINC3,
1425 AB8500_DMICFILTCONF_DMIC4SINC3, enum_sinc53);
1426static SOC_ENUM_DOUBLE_DECL(soc_enum_dmic56sinc, AB8500_DMICFILTCONF,
1427 AB8500_DMICFILTCONF_DMIC5SINC3,
1428 AB8500_DMICFILTCONF_DMIC6SINC3, enum_sinc53);
1429
1430/* Digital interface - DA from slot mapping */
1431static const char * const enum_da_from_slot_map[] = {"SLOT0",
1432 "SLOT1",
1433 "SLOT2",
1434 "SLOT3",
1435 "SLOT4",
1436 "SLOT5",
1437 "SLOT6",
1438 "SLOT7",
1439 "SLOT8",
1440 "SLOT9",
1441 "SLOT10",
1442 "SLOT11",
1443 "SLOT12",
1444 "SLOT13",
1445 "SLOT14",
1446 "SLOT15",
1447 "SLOT16",
1448 "SLOT17",
1449 "SLOT18",
1450 "SLOT19",
1451 "SLOT20",
1452 "SLOT21",
1453 "SLOT22",
1454 "SLOT23",
1455 "SLOT24",
1456 "SLOT25",
1457 "SLOT26",
1458 "SLOT27",
1459 "SLOT28",
1460 "SLOT29",
1461 "SLOT30",
1462 "SLOT31"};
1463static SOC_ENUM_SINGLE_DECL(soc_enum_da1slotmap,
1464 AB8500_DASLOTCONF1, AB8500_DASLOTCONFX_SLTODAX_SHIFT,
1465 enum_da_from_slot_map);
1466static SOC_ENUM_SINGLE_DECL(soc_enum_da2slotmap,
1467 AB8500_DASLOTCONF2, AB8500_DASLOTCONFX_SLTODAX_SHIFT,
1468 enum_da_from_slot_map);
1469static SOC_ENUM_SINGLE_DECL(soc_enum_da3slotmap,
1470 AB8500_DASLOTCONF3, AB8500_DASLOTCONFX_SLTODAX_SHIFT,
1471 enum_da_from_slot_map);
1472static SOC_ENUM_SINGLE_DECL(soc_enum_da4slotmap,
1473 AB8500_DASLOTCONF4, AB8500_DASLOTCONFX_SLTODAX_SHIFT,
1474 enum_da_from_slot_map);
1475static SOC_ENUM_SINGLE_DECL(soc_enum_da5slotmap,
1476 AB8500_DASLOTCONF5, AB8500_DASLOTCONFX_SLTODAX_SHIFT,
1477 enum_da_from_slot_map);
1478static SOC_ENUM_SINGLE_DECL(soc_enum_da6slotmap,
1479 AB8500_DASLOTCONF6, AB8500_DASLOTCONFX_SLTODAX_SHIFT,
1480 enum_da_from_slot_map);
1481static SOC_ENUM_SINGLE_DECL(soc_enum_da7slotmap,
1482 AB8500_DASLOTCONF7, AB8500_DASLOTCONFX_SLTODAX_SHIFT,
1483 enum_da_from_slot_map);
1484static SOC_ENUM_SINGLE_DECL(soc_enum_da8slotmap,
1485 AB8500_DASLOTCONF8, AB8500_DASLOTCONFX_SLTODAX_SHIFT,
1486 enum_da_from_slot_map);
1487
1488/* Digital interface - AD to slot mapping */
1489static const char * const enum_ad_to_slot_map[] = {"AD_OUT1",
1490 "AD_OUT2",
1491 "AD_OUT3",
1492 "AD_OUT4",
1493 "AD_OUT5",
1494 "AD_OUT6",
1495 "AD_OUT7",
1496 "AD_OUT8",
1497 "zeroes",
1498 "tristate"};
1499static SOC_ENUM_SINGLE_DECL(soc_enum_adslot0map,
1500 AB8500_ADSLOTSEL1, AB8500_ADSLOTSELX_EVEN_SHIFT,
1501 enum_ad_to_slot_map);
1502static SOC_ENUM_SINGLE_DECL(soc_enum_adslot1map,
1503 AB8500_ADSLOTSEL1, AB8500_ADSLOTSELX_ODD_SHIFT,
1504 enum_ad_to_slot_map);
1505static SOC_ENUM_SINGLE_DECL(soc_enum_adslot2map,
1506 AB8500_ADSLOTSEL2, AB8500_ADSLOTSELX_EVEN_SHIFT,
1507 enum_ad_to_slot_map);
1508static SOC_ENUM_SINGLE_DECL(soc_enum_adslot3map,
1509 AB8500_ADSLOTSEL2, AB8500_ADSLOTSELX_ODD_SHIFT,
1510 enum_ad_to_slot_map);
1511static SOC_ENUM_SINGLE_DECL(soc_enum_adslot4map,
1512 AB8500_ADSLOTSEL3, AB8500_ADSLOTSELX_EVEN_SHIFT,
1513 enum_ad_to_slot_map);
1514static SOC_ENUM_SINGLE_DECL(soc_enum_adslot5map,
1515 AB8500_ADSLOTSEL3, AB8500_ADSLOTSELX_ODD_SHIFT,
1516 enum_ad_to_slot_map);
1517static SOC_ENUM_SINGLE_DECL(soc_enum_adslot6map,
1518 AB8500_ADSLOTSEL4, AB8500_ADSLOTSELX_EVEN_SHIFT,
1519 enum_ad_to_slot_map);
1520static SOC_ENUM_SINGLE_DECL(soc_enum_adslot7map,
1521 AB8500_ADSLOTSEL4, AB8500_ADSLOTSELX_ODD_SHIFT,
1522 enum_ad_to_slot_map);
1523static SOC_ENUM_SINGLE_DECL(soc_enum_adslot8map,
1524 AB8500_ADSLOTSEL5, AB8500_ADSLOTSELX_EVEN_SHIFT,
1525 enum_ad_to_slot_map);
1526static SOC_ENUM_SINGLE_DECL(soc_enum_adslot9map,
1527 AB8500_ADSLOTSEL5, AB8500_ADSLOTSELX_ODD_SHIFT,
1528 enum_ad_to_slot_map);
1529static SOC_ENUM_SINGLE_DECL(soc_enum_adslot10map,
1530 AB8500_ADSLOTSEL6, AB8500_ADSLOTSELX_EVEN_SHIFT,
1531 enum_ad_to_slot_map);
1532static SOC_ENUM_SINGLE_DECL(soc_enum_adslot11map,
1533 AB8500_ADSLOTSEL6, AB8500_ADSLOTSELX_ODD_SHIFT,
1534 enum_ad_to_slot_map);
1535static SOC_ENUM_SINGLE_DECL(soc_enum_adslot12map,
1536 AB8500_ADSLOTSEL7, AB8500_ADSLOTSELX_EVEN_SHIFT,
1537 enum_ad_to_slot_map);
1538static SOC_ENUM_SINGLE_DECL(soc_enum_adslot13map,
1539 AB8500_ADSLOTSEL7, AB8500_ADSLOTSELX_ODD_SHIFT,
1540 enum_ad_to_slot_map);
1541static SOC_ENUM_SINGLE_DECL(soc_enum_adslot14map,
1542 AB8500_ADSLOTSEL8, AB8500_ADSLOTSELX_EVEN_SHIFT,
1543 enum_ad_to_slot_map);
1544static SOC_ENUM_SINGLE_DECL(soc_enum_adslot15map,
1545 AB8500_ADSLOTSEL8, AB8500_ADSLOTSELX_ODD_SHIFT,
1546 enum_ad_to_slot_map);
1547static SOC_ENUM_SINGLE_DECL(soc_enum_adslot16map,
1548 AB8500_ADSLOTSEL9, AB8500_ADSLOTSELX_EVEN_SHIFT,
1549 enum_ad_to_slot_map);
1550static SOC_ENUM_SINGLE_DECL(soc_enum_adslot17map,
1551 AB8500_ADSLOTSEL9, AB8500_ADSLOTSELX_ODD_SHIFT,
1552 enum_ad_to_slot_map);
1553static SOC_ENUM_SINGLE_DECL(soc_enum_adslot18map,
1554 AB8500_ADSLOTSEL10, AB8500_ADSLOTSELX_EVEN_SHIFT,
1555 enum_ad_to_slot_map);
1556static SOC_ENUM_SINGLE_DECL(soc_enum_adslot19map,
1557 AB8500_ADSLOTSEL10, AB8500_ADSLOTSELX_ODD_SHIFT,
1558 enum_ad_to_slot_map);
1559static SOC_ENUM_SINGLE_DECL(soc_enum_adslot20map,
1560 AB8500_ADSLOTSEL11, AB8500_ADSLOTSELX_EVEN_SHIFT,
1561 enum_ad_to_slot_map);
1562static SOC_ENUM_SINGLE_DECL(soc_enum_adslot21map,
1563 AB8500_ADSLOTSEL11, AB8500_ADSLOTSELX_ODD_SHIFT,
1564 enum_ad_to_slot_map);
1565static SOC_ENUM_SINGLE_DECL(soc_enum_adslot22map,
1566 AB8500_ADSLOTSEL12, AB8500_ADSLOTSELX_EVEN_SHIFT,
1567 enum_ad_to_slot_map);
1568static SOC_ENUM_SINGLE_DECL(soc_enum_adslot23map,
1569 AB8500_ADSLOTSEL12, AB8500_ADSLOTSELX_ODD_SHIFT,
1570 enum_ad_to_slot_map);
1571static SOC_ENUM_SINGLE_DECL(soc_enum_adslot24map,
1572 AB8500_ADSLOTSEL13, AB8500_ADSLOTSELX_EVEN_SHIFT,
1573 enum_ad_to_slot_map);
1574static SOC_ENUM_SINGLE_DECL(soc_enum_adslot25map,
1575 AB8500_ADSLOTSEL13, AB8500_ADSLOTSELX_ODD_SHIFT,
1576 enum_ad_to_slot_map);
1577static SOC_ENUM_SINGLE_DECL(soc_enum_adslot26map,
1578 AB8500_ADSLOTSEL14, AB8500_ADSLOTSELX_EVEN_SHIFT,
1579 enum_ad_to_slot_map);
1580static SOC_ENUM_SINGLE_DECL(soc_enum_adslot27map,
1581 AB8500_ADSLOTSEL14, AB8500_ADSLOTSELX_ODD_SHIFT,
1582 enum_ad_to_slot_map);
1583static SOC_ENUM_SINGLE_DECL(soc_enum_adslot28map,
1584 AB8500_ADSLOTSEL15, AB8500_ADSLOTSELX_EVEN_SHIFT,
1585 enum_ad_to_slot_map);
1586static SOC_ENUM_SINGLE_DECL(soc_enum_adslot29map,
1587 AB8500_ADSLOTSEL15, AB8500_ADSLOTSELX_ODD_SHIFT,
1588 enum_ad_to_slot_map);
1589static SOC_ENUM_SINGLE_DECL(soc_enum_adslot30map,
1590 AB8500_ADSLOTSEL16, AB8500_ADSLOTSELX_EVEN_SHIFT,
1591 enum_ad_to_slot_map);
1592static SOC_ENUM_SINGLE_DECL(soc_enum_adslot31map,
1593 AB8500_ADSLOTSEL16, AB8500_ADSLOTSELX_ODD_SHIFT,
1594 enum_ad_to_slot_map);
1595
1596/* Digital interface - Burst mode */
1597static const char * const enum_mask[] = {"Unmasked", "Masked"};
1598static SOC_ENUM_SINGLE_DECL(soc_enum_bfifomask,
1599 AB8500_FIFOCONF1, AB8500_FIFOCONF1_BFIFOMASK,
1600 enum_mask);
1601static const char * const enum_bitclk0[] = {"19_2_MHz", "38_4_MHz"};
1602static SOC_ENUM_SINGLE_DECL(soc_enum_bfifo19m2,
1603 AB8500_FIFOCONF1, AB8500_FIFOCONF1_BFIFO19M2,
1604 enum_bitclk0);
1605static const char * const enum_slavemaster[] = {"Slave", "Master"};
1606static SOC_ENUM_SINGLE_DECL(soc_enum_bfifomast,
1607 AB8500_FIFOCONF3, AB8500_FIFOCONF3_BFIFOMAST_SHIFT,
1608 enum_slavemaster);
1609
1610/* Sidetone */
1611static SOC_ENUM_SINGLE_EXT_DECL(soc_enum_sidstate, enum_sid_state);
1612
1613/* ANC */
1614static SOC_ENUM_SINGLE_EXT_DECL(soc_enum_ancstate, enum_anc_state);
1615
1616static struct snd_kcontrol_new ab8500_ctrls[] = {
1617 /* Charge pump */
1618 SOC_ENUM("Charge Pump High Threshold For Low Voltage",
1619 soc_enum_envdeththre),
1620 SOC_ENUM("Charge Pump Low Threshold For Low Voltage",
1621 soc_enum_envdetlthre),
1622 SOC_SINGLE("Charge Pump Envelope Detection Switch",
1623 AB8500_SIGENVCONF, AB8500_SIGENVCONF_ENVDETCPEN,
1624 1, 0),
1625 SOC_ENUM("Charge Pump Envelope Detection Decay Time",
1626 soc_enum_envdettime),
1627
1628 /* Headset */
1629 SOC_ENUM("Headset Mode", soc_enum_da12voice),
1630 SOC_SINGLE("Headset High Pass Switch",
1631 AB8500_ANACONF1, AB8500_ANACONF1_HSHPEN,
1632 1, 0),
1633 SOC_SINGLE("Headset Low Power Switch",
1634 AB8500_ANACONF1, AB8500_ANACONF1_HSLOWPOW,
1635 1, 0),
1636 SOC_SINGLE("Headset DAC Low Power Switch",
1637 AB8500_ANACONF1, AB8500_ANACONF1_DACLOWPOW1,
1638 1, 0),
1639 SOC_SINGLE("Headset DAC Drv Low Power Switch",
1640 AB8500_ANACONF1, AB8500_ANACONF1_DACLOWPOW0,
1641 1, 0),
1642 SOC_ENUM("Headset Fade Speed", soc_enum_hsfadspeed),
1643 SOC_ENUM("Headset Source", soc_enum_da2hslr),
1644 SOC_ENUM("Headset Filter", soc_enum_hsesinc),
1645 SOC_DOUBLE_R_TLV("Headset Master Volume",
1646 AB8500_DADIGGAIN1, AB8500_DADIGGAIN2,
1647 0, AB8500_DADIGGAINX_DAXGAIN_MAX, 1, dax_dig_gain_tlv),
1648 SOC_DOUBLE_R_TLV("Headset Digital Volume",
1649 AB8500_HSLEARDIGGAIN, AB8500_HSRDIGGAIN,
1650 0, AB8500_HSLEARDIGGAIN_HSLDGAIN_MAX, 1, hs_ear_dig_gain_tlv),
1651 SOC_DOUBLE_TLV("Headset Volume",
1652 AB8500_ANAGAIN3,
1653 AB8500_ANAGAIN3_HSLGAIN, AB8500_ANAGAIN3_HSRGAIN,
1654 AB8500_ANAGAIN3_HSXGAIN_MAX, 1, hs_gain_tlv),
1655
1656 /* Earpiece */
1657 SOC_ENUM("Earpiece DAC Mode",
1658 soc_enum_eardaclowpow),
1659 SOC_ENUM("Earpiece DAC Drv Mode",
1660 soc_enum_eardrvlowpow),
1661
1662 /* HandsFree */
1663 SOC_ENUM("HF Mode", soc_enum_da34voice),
1664 SOC_SINGLE("HF and Headset Swap Switch",
1665 AB8500_DASLOTCONF1, AB8500_DASLOTCONF1_SWAPDA12_34,
1666 1, 0),
1667 SOC_DOUBLE("HF Low EMI Mode Switch",
1668 AB8500_CLASSDCONF1,
1669 AB8500_CLASSDCONF1_HFLSWAPEN, AB8500_CLASSDCONF1_HFRSWAPEN,
1670 1, 0),
1671 SOC_DOUBLE("HF FIR Bypass Switch",
1672 AB8500_CLASSDCONF2,
1673 AB8500_CLASSDCONF2_FIRBYP0, AB8500_CLASSDCONF2_FIRBYP1,
1674 1, 0),
1675 SOC_DOUBLE("HF High Volume Switch",
1676 AB8500_CLASSDCONF2,
1677 AB8500_CLASSDCONF2_HIGHVOLEN0, AB8500_CLASSDCONF2_HIGHVOLEN1,
1678 1, 0),
1679 SOC_SINGLE("HF L and R Bridge Switch",
1680 AB8500_CLASSDCONF1, AB8500_CLASSDCONF1_PARLHF,
1681 1, 0),
1682 SOC_DOUBLE_R_TLV("HF Master Volume",
1683 AB8500_DADIGGAIN3, AB8500_DADIGGAIN4,
1684 0, AB8500_DADIGGAINX_DAXGAIN_MAX, 1, dax_dig_gain_tlv),
1685
1686 /* Vibra */
1687 SOC_DOUBLE("Vibra High Volume Switch",
1688 AB8500_CLASSDCONF2,
1689 AB8500_CLASSDCONF2_HIGHVOLEN2, AB8500_CLASSDCONF2_HIGHVOLEN3,
1690 1, 0),
1691 SOC_DOUBLE("Vibra Low EMI Mode Switch",
1692 AB8500_CLASSDCONF1,
1693 AB8500_CLASSDCONF1_VIB1SWAPEN, AB8500_CLASSDCONF1_VIB2SWAPEN,
1694 1, 0),
1695 SOC_DOUBLE("Vibra FIR Bypass Switch",
1696 AB8500_CLASSDCONF2,
1697 AB8500_CLASSDCONF2_FIRBYP2, AB8500_CLASSDCONF2_FIRBYP3,
1698 1, 0),
1699 SOC_ENUM("Vibra Mode", soc_enum_da56voice),
1700 SOC_DOUBLE_R("Vibra PWM Duty Cycle N",
1701 AB8500_PWMGENCONF3, AB8500_PWMGENCONF5,
1702 AB8500_PWMGENCONFX_PWMVIBXDUTCYC,
1703 AB8500_PWMGENCONFX_PWMVIBXDUTCYC_MAX, 0),
1704 SOC_DOUBLE_R("Vibra PWM Duty Cycle P",
1705 AB8500_PWMGENCONF2, AB8500_PWMGENCONF4,
1706 AB8500_PWMGENCONFX_PWMVIBXDUTCYC,
1707 AB8500_PWMGENCONFX_PWMVIBXDUTCYC_MAX, 0),
1708 SOC_SINGLE("Vibra 1 and 2 Bridge Switch",
1709 AB8500_CLASSDCONF1, AB8500_CLASSDCONF1_PARLVIB,
1710 1, 0),
1711 SOC_DOUBLE_R_TLV("Vibra Master Volume",
1712 AB8500_DADIGGAIN5, AB8500_DADIGGAIN6,
1713 0, AB8500_DADIGGAINX_DAXGAIN_MAX, 1, dax_dig_gain_tlv),
1714
1715 /* HandsFree, Vibra */
1716 SOC_SINGLE("ClassD High Pass Volume",
1717 AB8500_CLASSDCONF3, AB8500_CLASSDCONF3_DITHHPGAIN,
1718 AB8500_CLASSDCONF3_DITHHPGAIN_MAX, 0),
1719 SOC_SINGLE("ClassD White Volume",
1720 AB8500_CLASSDCONF3, AB8500_CLASSDCONF3_DITHWGAIN,
1721 AB8500_CLASSDCONF3_DITHWGAIN_MAX, 0),
1722
1723 /* Mic 1, Mic 2, LineIn */
1724 SOC_DOUBLE_R_TLV("Mic Master Volume",
1725 AB8500_ADDIGGAIN3, AB8500_ADDIGGAIN4,
1726 0, AB8500_ADDIGGAINX_ADXGAIN_MAX, 1, adx_dig_gain_tlv),
1727
1728 /* Mic 1 */
1729 SOC_SINGLE_TLV("Mic 1",
1730 AB8500_ANAGAIN1,
1731 AB8500_ANAGAINX_MICXGAIN,
1732 AB8500_ANAGAINX_MICXGAIN_MAX, 0, mic_gain_tlv),
1733 SOC_SINGLE("Mic 1 Low Power Switch",
1734 AB8500_ANAGAIN1, AB8500_ANAGAINX_LOWPOWMICX,
1735 1, 0),
1736
1737 /* Mic 2 */
1738 SOC_DOUBLE("Mic High Pass Switch",
1739 AB8500_ADFILTCONF,
1740 AB8500_ADFILTCONF_AD3NH, AB8500_ADFILTCONF_AD4NH,
1741 1, 1),
1742 SOC_ENUM("Mic Mode", soc_enum_ad34voice),
1743 SOC_ENUM("Mic Filter", soc_enum_dmic34sinc),
1744 SOC_SINGLE_TLV("Mic 2",
1745 AB8500_ANAGAIN2,
1746 AB8500_ANAGAINX_MICXGAIN,
1747 AB8500_ANAGAINX_MICXGAIN_MAX, 0, mic_gain_tlv),
1748 SOC_SINGLE("Mic 2 Low Power Switch",
1749 AB8500_ANAGAIN2, AB8500_ANAGAINX_LOWPOWMICX,
1750 1, 0),
1751
1752 /* LineIn */
1753 SOC_DOUBLE("LineIn High Pass Switch",
1754 AB8500_ADFILTCONF,
1755 AB8500_ADFILTCONF_AD1NH, AB8500_ADFILTCONF_AD2NH,
1756 1, 1),
1757 SOC_ENUM("LineIn Filter", soc_enum_dmic12sinc),
1758 SOC_ENUM("LineIn Mode", soc_enum_ad12voice),
1759 SOC_DOUBLE_R_TLV("LineIn Master Volume",
1760 AB8500_ADDIGGAIN1, AB8500_ADDIGGAIN2,
1761 0, AB8500_ADDIGGAINX_ADXGAIN_MAX, 1, adx_dig_gain_tlv),
1762 SOC_DOUBLE_TLV("LineIn",
1763 AB8500_ANAGAIN4,
1764 AB8500_ANAGAIN4_LINLGAIN, AB8500_ANAGAIN4_LINRGAIN,
1765 AB8500_ANAGAIN4_LINXGAIN_MAX, 0, lin_gain_tlv),
1766 SOC_DOUBLE_R_TLV("LineIn to Headset Volume",
1767 AB8500_DIGLINHSLGAIN, AB8500_DIGLINHSRGAIN,
1768 AB8500_DIGLINHSXGAIN_LINTOHSXGAIN,
1769 AB8500_DIGLINHSXGAIN_LINTOHSXGAIN_MAX,
1770 1, lin2hs_gain_tlv),
1771
1772 /* DMic */
1773 SOC_ENUM("DMic Filter", soc_enum_dmic56sinc),
1774 SOC_DOUBLE_R_TLV("DMic Master Volume",
1775 AB8500_ADDIGGAIN5, AB8500_ADDIGGAIN6,
1776 0, AB8500_ADDIGGAINX_ADXGAIN_MAX, 1, adx_dig_gain_tlv),
1777
1778 /* Digital gains */
1779 SOC_ENUM("Digital Gain Fade Speed", soc_enum_fadespeed),
1780
1781 /* Analog loopback */
1782 SOC_DOUBLE_R_TLV("Analog Loopback Volume",
1783 AB8500_ADDIGLOOPGAIN1, AB8500_ADDIGLOOPGAIN2,
1784 0, AB8500_ADDIGLOOPGAINX_ADXLBGAIN_MAX, 1, dax_dig_gain_tlv),
1785
1786 /* Digital interface - DA from slot mapping */
1787 SOC_ENUM("Digital Interface DA 1 From Slot Map", soc_enum_da1slotmap),
1788 SOC_ENUM("Digital Interface DA 2 From Slot Map", soc_enum_da2slotmap),
1789 SOC_ENUM("Digital Interface DA 3 From Slot Map", soc_enum_da3slotmap),
1790 SOC_ENUM("Digital Interface DA 4 From Slot Map", soc_enum_da4slotmap),
1791 SOC_ENUM("Digital Interface DA 5 From Slot Map", soc_enum_da5slotmap),
1792 SOC_ENUM("Digital Interface DA 6 From Slot Map", soc_enum_da6slotmap),
1793 SOC_ENUM("Digital Interface DA 7 From Slot Map", soc_enum_da7slotmap),
1794 SOC_ENUM("Digital Interface DA 8 From Slot Map", soc_enum_da8slotmap),
1795
1796 /* Digital interface - AD to slot mapping */
1797 SOC_ENUM("Digital Interface AD To Slot 0 Map", soc_enum_adslot0map),
1798 SOC_ENUM("Digital Interface AD To Slot 1 Map", soc_enum_adslot1map),
1799 SOC_ENUM("Digital Interface AD To Slot 2 Map", soc_enum_adslot2map),
1800 SOC_ENUM("Digital Interface AD To Slot 3 Map", soc_enum_adslot3map),
1801 SOC_ENUM("Digital Interface AD To Slot 4 Map", soc_enum_adslot4map),
1802 SOC_ENUM("Digital Interface AD To Slot 5 Map", soc_enum_adslot5map),
1803 SOC_ENUM("Digital Interface AD To Slot 6 Map", soc_enum_adslot6map),
1804 SOC_ENUM("Digital Interface AD To Slot 7 Map", soc_enum_adslot7map),
1805 SOC_ENUM("Digital Interface AD To Slot 8 Map", soc_enum_adslot8map),
1806 SOC_ENUM("Digital Interface AD To Slot 9 Map", soc_enum_adslot9map),
1807 SOC_ENUM("Digital Interface AD To Slot 10 Map", soc_enum_adslot10map),
1808 SOC_ENUM("Digital Interface AD To Slot 11 Map", soc_enum_adslot11map),
1809 SOC_ENUM("Digital Interface AD To Slot 12 Map", soc_enum_adslot12map),
1810 SOC_ENUM("Digital Interface AD To Slot 13 Map", soc_enum_adslot13map),
1811 SOC_ENUM("Digital Interface AD To Slot 14 Map", soc_enum_adslot14map),
1812 SOC_ENUM("Digital Interface AD To Slot 15 Map", soc_enum_adslot15map),
1813 SOC_ENUM("Digital Interface AD To Slot 16 Map", soc_enum_adslot16map),
1814 SOC_ENUM("Digital Interface AD To Slot 17 Map", soc_enum_adslot17map),
1815 SOC_ENUM("Digital Interface AD To Slot 18 Map", soc_enum_adslot18map),
1816 SOC_ENUM("Digital Interface AD To Slot 19 Map", soc_enum_adslot19map),
1817 SOC_ENUM("Digital Interface AD To Slot 20 Map", soc_enum_adslot20map),
1818 SOC_ENUM("Digital Interface AD To Slot 21 Map", soc_enum_adslot21map),
1819 SOC_ENUM("Digital Interface AD To Slot 22 Map", soc_enum_adslot22map),
1820 SOC_ENUM("Digital Interface AD To Slot 23 Map", soc_enum_adslot23map),
1821 SOC_ENUM("Digital Interface AD To Slot 24 Map", soc_enum_adslot24map),
1822 SOC_ENUM("Digital Interface AD To Slot 25 Map", soc_enum_adslot25map),
1823 SOC_ENUM("Digital Interface AD To Slot 26 Map", soc_enum_adslot26map),
1824 SOC_ENUM("Digital Interface AD To Slot 27 Map", soc_enum_adslot27map),
1825 SOC_ENUM("Digital Interface AD To Slot 28 Map", soc_enum_adslot28map),
1826 SOC_ENUM("Digital Interface AD To Slot 29 Map", soc_enum_adslot29map),
1827 SOC_ENUM("Digital Interface AD To Slot 30 Map", soc_enum_adslot30map),
1828 SOC_ENUM("Digital Interface AD To Slot 31 Map", soc_enum_adslot31map),
1829
1830 /* Digital interface - Loopback */
1831 SOC_SINGLE("Digital Interface AD 1 Loopback Switch",
1832 AB8500_DASLOTCONF1, AB8500_DASLOTCONF1_DAI7TOADO1,
1833 1, 0),
1834 SOC_SINGLE("Digital Interface AD 2 Loopback Switch",
1835 AB8500_DASLOTCONF2, AB8500_DASLOTCONF2_DAI8TOADO2,
1836 1, 0),
1837 SOC_SINGLE("Digital Interface AD 3 Loopback Switch",
1838 AB8500_DASLOTCONF3, AB8500_DASLOTCONF3_DAI7TOADO3,
1839 1, 0),
1840 SOC_SINGLE("Digital Interface AD 4 Loopback Switch",
1841 AB8500_DASLOTCONF4, AB8500_DASLOTCONF4_DAI8TOADO4,
1842 1, 0),
1843 SOC_SINGLE("Digital Interface AD 5 Loopback Switch",
1844 AB8500_DASLOTCONF5, AB8500_DASLOTCONF5_DAI7TOADO5,
1845 1, 0),
1846 SOC_SINGLE("Digital Interface AD 6 Loopback Switch",
1847 AB8500_DASLOTCONF6, AB8500_DASLOTCONF6_DAI8TOADO6,
1848 1, 0),
1849 SOC_SINGLE("Digital Interface AD 7 Loopback Switch",
1850 AB8500_DASLOTCONF7, AB8500_DASLOTCONF7_DAI8TOADO7,
1851 1, 0),
1852 SOC_SINGLE("Digital Interface AD 8 Loopback Switch",
1853 AB8500_DASLOTCONF8, AB8500_DASLOTCONF8_DAI7TOADO8,
1854 1, 0),
1855
1856 /* Digital interface - Burst FIFO */
1857 SOC_SINGLE("Digital Interface 0 FIFO Enable Switch",
1858 AB8500_DIGIFCONF3, AB8500_DIGIFCONF3_IF0BFIFOEN,
1859 1, 0),
1860 SOC_ENUM("Burst FIFO Mask", soc_enum_bfifomask),
1861 SOC_ENUM("Burst FIFO Bit-clock Frequency", soc_enum_bfifo19m2),
1862 SOC_SINGLE("Burst FIFO Threshold",
1863 AB8500_FIFOCONF1, AB8500_FIFOCONF1_BFIFOINT_SHIFT,
1864 AB8500_FIFOCONF1_BFIFOINT_MAX, 0),
1865 SOC_SINGLE("Burst FIFO Length",
1866 AB8500_FIFOCONF2, AB8500_FIFOCONF2_BFIFOTX_SHIFT,
1867 AB8500_FIFOCONF2_BFIFOTX_MAX, 0),
1868 SOC_SINGLE("Burst FIFO EOS Extra Slots",
1869 AB8500_FIFOCONF3, AB8500_FIFOCONF3_BFIFOEXSL_SHIFT,
1870 AB8500_FIFOCONF3_BFIFOEXSL_MAX, 0),
1871 SOC_SINGLE("Burst FIFO FS Extra Bit-clocks",
1872 AB8500_FIFOCONF3, AB8500_FIFOCONF3_PREBITCLK0_SHIFT,
1873 AB8500_FIFOCONF3_PREBITCLK0_MAX, 0),
1874 SOC_ENUM("Burst FIFO Interface Mode", soc_enum_bfifomast),
1875
1876 SOC_SINGLE("Burst FIFO Interface Switch",
1877 AB8500_FIFOCONF3, AB8500_FIFOCONF3_BFIFORUN_SHIFT,
1878 1, 0),
1879 SOC_SINGLE("Burst FIFO Switch Frame Number",
1880 AB8500_FIFOCONF4, AB8500_FIFOCONF4_BFIFOFRAMSW_SHIFT,
1881 AB8500_FIFOCONF4_BFIFOFRAMSW_MAX, 0),
1882 SOC_SINGLE("Burst FIFO Wake Up Delay",
1883 AB8500_FIFOCONF5, AB8500_FIFOCONF5_BFIFOWAKEUP_SHIFT,
1884 AB8500_FIFOCONF5_BFIFOWAKEUP_MAX, 0),
1885 SOC_SINGLE("Burst FIFO Samples In FIFO",
1886 AB8500_FIFOCONF6, AB8500_FIFOCONF6_BFIFOSAMPLE_SHIFT,
1887 AB8500_FIFOCONF6_BFIFOSAMPLE_MAX, 0),
1888
1889 /* ANC */
1890 SOC_ENUM_EXT("ANC Status", soc_enum_ancstate,
1891 anc_status_control_get, anc_status_control_put),
1892 SOC_SINGLE_XR_SX("ANC Warp Delay Shift",
1893 AB8500_ANCCONF2, 1, AB8500_ANCCONF2_SHIFT,
1894 AB8500_ANCCONF2_MIN, AB8500_ANCCONF2_MAX, 0),
1895 SOC_SINGLE_XR_SX("ANC FIR Output Shift",
1896 AB8500_ANCCONF3, 1, AB8500_ANCCONF3_SHIFT,
1897 AB8500_ANCCONF3_MIN, AB8500_ANCCONF3_MAX, 0),
1898 SOC_SINGLE_XR_SX("ANC IIR Output Shift",
1899 AB8500_ANCCONF4, 1, AB8500_ANCCONF4_SHIFT,
1900 AB8500_ANCCONF4_MIN, AB8500_ANCCONF4_MAX, 0),
1901 SOC_SINGLE_XR_SX("ANC Warp Delay",
1902 AB8500_ANCCONF9, 2, AB8500_ANC_WARP_DELAY_SHIFT,
1903 AB8500_ANC_WARP_DELAY_MIN, AB8500_ANC_WARP_DELAY_MAX, 0),
1904
1905 /* Sidetone */
1906 SOC_ENUM_EXT("Sidetone Status", soc_enum_sidstate,
1907 sid_status_control_get, sid_status_control_put),
1908 SOC_SINGLE_STROBE("Sidetone Reset",
1909 AB8500_SIDFIRADR, AB8500_SIDFIRADR_FIRSIDSET, 0),
1910};
1911
1912static struct snd_kcontrol_new ab8500_filter_controls[] = {
1913 AB8500_FILTER_CONTROL("ANC FIR Coefficients", AB8500_ANC_FIR_COEFFS,
1914 AB8500_ANC_FIR_COEFF_MIN, AB8500_ANC_FIR_COEFF_MAX),
1915 AB8500_FILTER_CONTROL("ANC IIR Coefficients", AB8500_ANC_IIR_COEFFS,
1916 AB8500_ANC_IIR_COEFF_MIN, AB8500_ANC_IIR_COEFF_MAX),
1917 AB8500_FILTER_CONTROL("Sidetone FIR Coefficients",
1918 AB8500_SID_FIR_COEFFS, AB8500_SID_FIR_COEFF_MIN,
1919 AB8500_SID_FIR_COEFF_MAX)
1920};
1921enum ab8500_filter {
1922 AB8500_FILTER_ANC_FIR = 0,
1923 AB8500_FILTER_ANC_IIR = 1,
1924 AB8500_FILTER_SID_FIR = 2,
1925};
1926
1927/*
1928 * Extended interface for codec-driver
1929 */
1930
1931static int ab8500_audio_init_audioblock(struct snd_soc_codec *codec)
1932{
1933 int status;
1934
1935 dev_dbg(codec->dev, "%s: Enter.\n", __func__);
1936
1937 /* Reset audio-registers and disable 32kHz-clock output 2 */
1938 status = ab8500_sysctrl_write(AB8500_STW4500CTRL3,
1939 AB8500_STW4500CTRL3_CLK32KOUT2DIS |
1940 AB8500_STW4500CTRL3_RESETAUDN,
1941 AB8500_STW4500CTRL3_RESETAUDN);
1942 if (status < 0)
1943 return status;
1944
1945 return 0;
1946}
1947
1948static int ab8500_audio_setup_mics(struct snd_soc_codec *codec,
1949 struct amic_settings *amics)
1950{
1951 u8 value8;
1952 unsigned int value;
1953 int status;
1954 const struct snd_soc_dapm_route *route;
1955
1956 dev_dbg(codec->dev, "%s: Enter.\n", __func__);
1957
1958 /* Set DMic-clocks to outputs */
1959 status = abx500_get_register_interruptible(codec->dev, (u8)AB8500_MISC,
1960 (u8)AB8500_GPIO_DIR4_REG,
1961 &value8);
1962 if (status < 0)
1963 return status;
1964 value = value8 | GPIO27_DIR_OUTPUT | GPIO29_DIR_OUTPUT |
1965 GPIO31_DIR_OUTPUT;
1966 status = abx500_set_register_interruptible(codec->dev,
1967 (u8)AB8500_MISC,
1968 (u8)AB8500_GPIO_DIR4_REG,
1969 value);
1970 if (status < 0)
1971 return status;
1972
1973 /* Attach regulators to AMic DAPM-paths */
1974 dev_dbg(codec->dev, "%s: Mic 1a regulator: %s\n", __func__,
1975 amic_micbias_str(amics->mic1a_micbias));
1976 route = &ab8500_dapm_routes_mic1a_vamicx[amics->mic1a_micbias];
1977 status = snd_soc_dapm_add_routes(&codec->dapm, route, 1);
1978 dev_dbg(codec->dev, "%s: Mic 1b regulator: %s\n", __func__,
1979 amic_micbias_str(amics->mic1b_micbias));
1980 route = &ab8500_dapm_routes_mic1b_vamicx[amics->mic1b_micbias];
1981 status |= snd_soc_dapm_add_routes(&codec->dapm, route, 1);
1982 dev_dbg(codec->dev, "%s: Mic 2 regulator: %s\n", __func__,
1983 amic_micbias_str(amics->mic2_micbias));
1984 route = &ab8500_dapm_routes_mic2_vamicx[amics->mic2_micbias];
1985 status |= snd_soc_dapm_add_routes(&codec->dapm, route, 1);
1986 if (status < 0) {
1987 dev_err(codec->dev,
1988 "%s: Failed to add AMic-regulator DAPM-routes (%d).\n",
1989 __func__, status);
1990 return status;
1991 }
1992
1993 /* Set AMic-configuration */
1994 dev_dbg(codec->dev, "%s: Mic 1 mic-type: %s\n", __func__,
1995 amic_type_str(amics->mic1_type));
1996 snd_soc_update_bits(codec, AB8500_ANAGAIN1, AB8500_ANAGAINX_ENSEMICX,
1997 amics->mic1_type == AMIC_TYPE_DIFFERENTIAL ?
1998 0 : AB8500_ANAGAINX_ENSEMICX);
1999 dev_dbg(codec->dev, "%s: Mic 2 mic-type: %s\n", __func__,
2000 amic_type_str(amics->mic2_type));
2001 snd_soc_update_bits(codec, AB8500_ANAGAIN2, AB8500_ANAGAINX_ENSEMICX,
2002 amics->mic2_type == AMIC_TYPE_DIFFERENTIAL ?
2003 0 : AB8500_ANAGAINX_ENSEMICX);
2004
2005 return 0;
2006}
2007EXPORT_SYMBOL_GPL(ab8500_audio_setup_mics);
2008
2009static int ab8500_audio_set_ear_cmv(struct snd_soc_codec *codec,
2010 enum ear_cm_voltage ear_cmv)
2011{
2012 char *cmv_str;
2013
2014 switch (ear_cmv) {
2015 case EAR_CMV_0_95V:
2016 cmv_str = "0.95V";
2017 break;
2018 case EAR_CMV_1_10V:
2019 cmv_str = "1.10V";
2020 break;
2021 case EAR_CMV_1_27V:
2022 cmv_str = "1.27V";
2023 break;
2024 case EAR_CMV_1_58V:
2025 cmv_str = "1.58V";
2026 break;
2027 default:
2028 dev_err(codec->dev,
2029 "%s: Unknown earpiece CM-voltage (%d)!\n",
2030 __func__, (int)ear_cmv);
2031 return -EINVAL;
2032 }
2033 dev_dbg(codec->dev, "%s: Earpiece CM-voltage: %s\n", __func__,
2034 cmv_str);
2035 snd_soc_update_bits(codec, AB8500_ANACONF1, AB8500_ANACONF1_EARSELCM,
2036 ear_cmv);
2037
2038 return 0;
2039}
2040EXPORT_SYMBOL_GPL(ab8500_audio_set_ear_cmv);
2041
2042static int ab8500_audio_set_bit_delay(struct snd_soc_dai *dai,
2043 unsigned int delay)
2044{
2045 unsigned int mask, val;
2046 struct snd_soc_codec *codec = dai->codec;
2047
2048 mask = BIT(AB8500_DIGIFCONF2_IF0DEL);
2049 val = 0;
2050
2051 switch (delay) {
2052 case 0:
2053 break;
2054 case 1:
2055 val |= BIT(AB8500_DIGIFCONF2_IF0DEL);
2056 break;
2057 default:
2058 dev_err(dai->codec->dev,
2059 "%s: ERROR: Unsupported bit-delay (0x%x)!\n",
2060 __func__, delay);
2061 return -EINVAL;
2062 }
2063
2064 dev_dbg(dai->codec->dev, "%s: IF0 Bit-delay: %d bits.\n",
2065 __func__, delay);
2066 snd_soc_update_bits(codec, AB8500_DIGIFCONF2, mask, val);
2067
2068 return 0;
2069}
2070
2071/* Gates clocking according format mask */
2072static int ab8500_codec_set_dai_clock_gate(struct snd_soc_codec *codec,
2073 unsigned int fmt)
2074{
2075 unsigned int mask;
2076 unsigned int val;
2077
2078 mask = BIT(AB8500_DIGIFCONF1_ENMASTGEN) |
2079 BIT(AB8500_DIGIFCONF1_ENFSBITCLK0);
2080
2081 val = BIT(AB8500_DIGIFCONF1_ENMASTGEN);
2082
2083 switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
2084 case SND_SOC_DAIFMT_CONT: /* continuous clock */
2085 dev_dbg(codec->dev, "%s: IF0 Clock is continuous.\n",
2086 __func__);
2087 val |= BIT(AB8500_DIGIFCONF1_ENFSBITCLK0);
2088 break;
2089 case SND_SOC_DAIFMT_GATED: /* clock is gated */
2090 dev_dbg(codec->dev, "%s: IF0 Clock is gated.\n",
2091 __func__);
2092 break;
2093 default:
2094 dev_err(codec->dev,
2095 "%s: ERROR: Unsupported clock mask (0x%x)!\n",
2096 __func__, fmt & SND_SOC_DAIFMT_CLOCK_MASK);
2097 return -EINVAL;
2098 }
2099
2100 snd_soc_update_bits(codec, AB8500_DIGIFCONF1, mask, val);
2101
2102 return 0;
2103}
2104
2105static int ab8500_codec_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2106{
2107 unsigned int mask;
2108 unsigned int val;
2109 struct snd_soc_codec *codec = dai->codec;
2110 int status;
2111
2112 dev_dbg(codec->dev, "%s: Enter (fmt = 0x%x)\n", __func__, fmt);
2113
2114 mask = BIT(AB8500_DIGIFCONF3_IF1DATOIF0AD) |
2115 BIT(AB8500_DIGIFCONF3_IF1CLKTOIF0CLK) |
2116 BIT(AB8500_DIGIFCONF3_IF0BFIFOEN) |
2117 BIT(AB8500_DIGIFCONF3_IF0MASTER);
2118 val = 0;
2119
2120 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
2121 case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & FRM master */
2122 dev_dbg(dai->codec->dev,
2123 "%s: IF0 Master-mode: AB8500 master.\n", __func__);
2124 val |= BIT(AB8500_DIGIFCONF3_IF0MASTER);
2125 break;
2126 case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & FRM slave */
2127 dev_dbg(dai->codec->dev,
2128 "%s: IF0 Master-mode: AB8500 slave.\n", __func__);
2129 break;
2130 case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & FRM master */
2131 case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */
2132 dev_err(dai->codec->dev,
2133 "%s: ERROR: The device is either a master or a slave.\n",
2134 __func__);
2135 default:
2136 dev_err(dai->codec->dev,
2137 "%s: ERROR: Unsupporter master mask 0x%x\n",
2138 __func__, fmt & SND_SOC_DAIFMT_MASTER_MASK);
2139 return -EINVAL;
2140 break;
2141 }
2142
2143 snd_soc_update_bits(codec, AB8500_DIGIFCONF3, mask, val);
2144
2145 /* Set clock gating */
2146 status = ab8500_codec_set_dai_clock_gate(codec, fmt);
2147 if (status) {
2148 dev_err(dai->codec->dev,
2149 "%s: ERRROR: Failed to set clock gate (%d).\n",
2150 __func__, status);
2151 return status;
2152 }
2153
2154 /* Setting data transfer format */
2155
2156 mask = BIT(AB8500_DIGIFCONF2_IF0FORMAT0) |
2157 BIT(AB8500_DIGIFCONF2_IF0FORMAT1) |
2158 BIT(AB8500_DIGIFCONF2_FSYNC0P) |
2159 BIT(AB8500_DIGIFCONF2_BITCLK0P);
2160 val = 0;
2161
2162 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
2163 case SND_SOC_DAIFMT_I2S: /* I2S mode */
2164 dev_dbg(dai->codec->dev, "%s: IF0 Protocol: I2S\n", __func__);
2165 val |= BIT(AB8500_DIGIFCONF2_IF0FORMAT1);
2166 ab8500_audio_set_bit_delay(dai, 0);
2167 break;
2168
2169 case SND_SOC_DAIFMT_DSP_A: /* L data MSB after FRM LRC */
2170 dev_dbg(dai->codec->dev,
2171 "%s: IF0 Protocol: DSP A (TDM)\n", __func__);
2172 val |= BIT(AB8500_DIGIFCONF2_IF0FORMAT0);
2173 ab8500_audio_set_bit_delay(dai, 1);
2174 break;
2175
2176 case SND_SOC_DAIFMT_DSP_B: /* L data MSB during FRM LRC */
2177 dev_dbg(dai->codec->dev,
2178 "%s: IF0 Protocol: DSP B (TDM)\n", __func__);
2179 val |= BIT(AB8500_DIGIFCONF2_IF0FORMAT0);
2180 ab8500_audio_set_bit_delay(dai, 0);
2181 break;
2182
2183 default:
2184 dev_err(dai->codec->dev,
2185 "%s: ERROR: Unsupported format (0x%x)!\n",
2186 __func__, fmt & SND_SOC_DAIFMT_FORMAT_MASK);
2187 return -EINVAL;
2188 }
2189
2190 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
2191 case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */
2192 dev_dbg(dai->codec->dev,
2193 "%s: IF0: Normal bit clock, normal frame\n",
2194 __func__);
2195 break;
2196 case SND_SOC_DAIFMT_NB_IF: /* normal BCLK + inv FRM */
2197 dev_dbg(dai->codec->dev,
2198 "%s: IF0: Normal bit clock, inverted frame\n",
2199 __func__);
2200 val |= BIT(AB8500_DIGIFCONF2_FSYNC0P);
2201 break;
2202 case SND_SOC_DAIFMT_IB_NF: /* invert BCLK + nor FRM */
2203 dev_dbg(dai->codec->dev,
2204 "%s: IF0: Inverted bit clock, normal frame\n",
2205 __func__);
2206 val |= BIT(AB8500_DIGIFCONF2_BITCLK0P);
2207 break;
2208 case SND_SOC_DAIFMT_IB_IF: /* invert BCLK + FRM */
2209 dev_dbg(dai->codec->dev,
2210 "%s: IF0: Inverted bit clock, inverted frame\n",
2211 __func__);
2212 val |= BIT(AB8500_DIGIFCONF2_FSYNC0P);
2213 val |= BIT(AB8500_DIGIFCONF2_BITCLK0P);
2214 break;
2215 default:
2216 dev_err(dai->codec->dev,
2217 "%s: ERROR: Unsupported INV mask 0x%x\n",
2218 __func__, fmt & SND_SOC_DAIFMT_INV_MASK);
2219 return -EINVAL;
2220 }
2221
2222 snd_soc_update_bits(codec, AB8500_DIGIFCONF2, mask, val);
2223
2224 return 0;
2225}
2226
2227static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
2228 unsigned int tx_mask, unsigned int rx_mask,
2229 int slots, int slot_width)
2230{
2231 struct snd_soc_codec *codec = dai->codec;
2232 unsigned int val, mask, slots_active;
2233
2234 mask = BIT(AB8500_DIGIFCONF2_IF0WL0) |
2235 BIT(AB8500_DIGIFCONF2_IF0WL1);
2236 val = 0;
2237
2238 switch (slot_width) {
2239 case 16:
2240 break;
2241 case 20:
2242 val |= BIT(AB8500_DIGIFCONF2_IF0WL0);
2243 break;
2244 case 24:
2245 val |= BIT(AB8500_DIGIFCONF2_IF0WL1);
2246 break;
2247 case 32:
2248 val |= BIT(AB8500_DIGIFCONF2_IF0WL1) |
2249 BIT(AB8500_DIGIFCONF2_IF0WL0);
2250 break;
2251 default:
2252 dev_err(dai->codec->dev, "%s: Unsupported slot-width 0x%x\n",
2253 __func__, slot_width);
2254 return -EINVAL;
2255 }
2256
2257 dev_dbg(dai->codec->dev, "%s: IF0 slot-width: %d bits.\n",
2258 __func__, slot_width);
2259 snd_soc_update_bits(codec, AB8500_DIGIFCONF2, mask, val);
2260
2261 /* Setup TDM clocking according to slot count */
2262 dev_dbg(dai->codec->dev, "%s: Slots, total: %d\n", __func__, slots);
2263 mask = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS0) |
2264 BIT(AB8500_DIGIFCONF1_IF0BITCLKOS1);
2265 switch (slots) {
2266 case 2:
2267 val = AB8500_MASK_NONE;
2268 break;
2269 case 4:
2270 val = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS0);
2271 break;
2272 case 8:
2273 val = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS1);
2274 break;
2275 case 16:
2276 val = BIT(AB8500_DIGIFCONF1_IF0BITCLKOS0) |
2277 BIT(AB8500_DIGIFCONF1_IF0BITCLKOS1);
2278 break;
2279 default:
2280 dev_err(dai->codec->dev,
2281 "%s: ERROR: Unsupported number of slots (%d)!\n",
2282 __func__, slots);
2283 return -EINVAL;
2284 }
2285 snd_soc_update_bits(codec, AB8500_DIGIFCONF1, mask, val);
2286
2287 /* Setup TDM DA according to active tx slots */
2288 mask = AB8500_DASLOTCONFX_SLTODAX_MASK;
2289 slots_active = hweight32(tx_mask);
2290 dev_dbg(dai->codec->dev, "%s: Slots, active, TX: %d\n", __func__,
2291 slots_active);
2292 switch (slots_active) {
2293 case 0:
2294 break;
2295 case 1:
2296 /* Slot 9 -> DA_IN1 & DA_IN3 */
2297 snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 11);
2298 snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 11);
2299 snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11);
2300 snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11);
2301 break;
2302 case 2:
2303 /* Slot 9 -> DA_IN1 & DA_IN3, Slot 11 -> DA_IN2 & DA_IN4 */
2304 snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 9);
2305 snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 9);
2306 snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11);
2307 snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11);
2308
2309 break;
2310 case 8:
2311 dev_dbg(dai->codec->dev,
2312 "%s: In 8-channel mode DA-from-slot mapping is set manually.",
2313 __func__);
2314 break;
2315 default:
2316 dev_err(dai->codec->dev,
2317 "%s: Unsupported number of active TX-slots (%d)!\n",
2318 __func__, slots_active);
2319 return -EINVAL;
2320 }
2321
2322 /* Setup TDM AD according to active RX-slots */
2323 slots_active = hweight32(rx_mask);
2324 dev_dbg(dai->codec->dev, "%s: Slots, active, RX: %d\n", __func__,
2325 slots_active);
2326 switch (slots_active) {
2327 case 0:
2328 break;
2329 case 1:
2330 /* AD_OUT3 -> slot 0 & 1 */
2331 snd_soc_update_bits(codec, AB8500_ADSLOTSEL1, AB8500_MASK_ALL,
2332 AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN |
2333 AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD);
2334 break;
2335 case 2:
2336 /* AD_OUT3 -> slot 0, AD_OUT2 -> slot 1 */
2337 snd_soc_update_bits(codec,
2338 AB8500_ADSLOTSEL1,
2339 AB8500_MASK_ALL,
2340 AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN |
2341 AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD);
2342 break;
2343 case 8:
2344 dev_dbg(dai->codec->dev,
2345 "%s: In 8-channel mode AD-to-slot mapping is set manually.",
2346 __func__);
2347 break;
2348 default:
2349 dev_err(dai->codec->dev,
2350 "%s: Unsupported number of active RX-slots (%d)!\n",
2351 __func__, slots_active);
2352 return -EINVAL;
2353 }
2354
2355 return 0;
2356}
2357
2358struct snd_soc_dai_driver ab8500_codec_dai[] = {
2359 {
2360 .name = "ab8500-codec-dai.0",
2361 .id = 0,
2362 .playback = {
2363 .stream_name = "ab8500_0p",
2364 .channels_min = 1,
2365 .channels_max = 8,
2366 .rates = AB8500_SUPPORTED_RATE,
2367 .formats = AB8500_SUPPORTED_FMT,
2368 },
2369 .ops = (struct snd_soc_dai_ops[]) {
2370 {
2371 .set_tdm_slot = ab8500_codec_set_dai_tdm_slot,
2372 .set_fmt = ab8500_codec_set_dai_fmt,
2373 }
2374 },
2375 .symmetric_rates = 1
2376 },
2377 {
2378 .name = "ab8500-codec-dai.1",
2379 .id = 1,
2380 .capture = {
2381 .stream_name = "ab8500_0c",
2382 .channels_min = 1,
2383 .channels_max = 8,
2384 .rates = AB8500_SUPPORTED_RATE,
2385 .formats = AB8500_SUPPORTED_FMT,
2386 },
2387 .ops = (struct snd_soc_dai_ops[]) {
2388 {
2389 .set_tdm_slot = ab8500_codec_set_dai_tdm_slot,
2390 .set_fmt = ab8500_codec_set_dai_fmt,
2391 }
2392 },
2393 .symmetric_rates = 1
2394 }
2395};
2396
2397static int ab8500_codec_probe(struct snd_soc_codec *codec)
2398{
2399 struct device *dev = codec->dev;
2400 struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(dev);
2401 struct ab8500_platform_data *pdata;
2402 struct filter_control *fc;
2403 int status;
2404
2405 dev_dbg(dev, "%s: Enter.\n", __func__);
2406
2407 /* Setup AB8500 according to board-settings */
2408 pdata = (struct ab8500_platform_data *)dev_get_platdata(dev->parent);
2409 status = ab8500_audio_setup_mics(codec, &pdata->codec->amics);
2410 if (status < 0) {
2411 pr_err("%s: Failed to setup mics (%d)!\n", __func__, status);
2412 return status;
2413 }
2414 status = ab8500_audio_set_ear_cmv(codec, pdata->codec->ear_cmv);
2415 if (status < 0) {
2416 pr_err("%s: Failed to set earpiece CM-voltage (%d)!\n",
2417 __func__, status);
2418 return status;
2419 }
2420
2421 status = ab8500_audio_init_audioblock(codec);
2422 if (status < 0) {
2423 dev_err(dev, "%s: failed to init audio-block (%d)!\n",
2424 __func__, status);
2425 return status;
2426 }
2427
2428 /* Override HW-defaults */
2429 ab8500_codec_write_reg(codec,
2430 AB8500_ANACONF5,
2431 BIT(AB8500_ANACONF5_HSAUTOEN));
2432 ab8500_codec_write_reg(codec,
2433 AB8500_SHORTCIRCONF,
2434 BIT(AB8500_SHORTCIRCONF_HSZCDDIS));
2435
2436 /* Add filter controls */
2437 status = snd_soc_add_codec_controls(codec, ab8500_filter_controls,
2438 ARRAY_SIZE(ab8500_filter_controls));
2439 if (status < 0) {
2440 dev_err(dev,
2441 "%s: failed to add ab8500 filter controls (%d).\n",
2442 __func__, status);
2443 return status;
2444 }
2445 fc = (struct filter_control *)
2446 &ab8500_filter_controls[AB8500_FILTER_ANC_FIR].private_value;
2447 drvdata->anc_fir_values = (long *)fc->value;
2448 fc = (struct filter_control *)
2449 &ab8500_filter_controls[AB8500_FILTER_ANC_IIR].private_value;
2450 drvdata->anc_iir_values = (long *)fc->value;
2451 fc = (struct filter_control *)
2452 &ab8500_filter_controls[AB8500_FILTER_SID_FIR].private_value;
2453 drvdata->sid_fir_values = (long *)fc->value;
2454
2455 (void)snd_soc_dapm_disable_pin(&codec->dapm, "ANC Configure Input");
2456
2457 mutex_init(&drvdata->anc_lock);
2458
2459 return status;
2460}
2461
2462static struct snd_soc_codec_driver ab8500_codec_driver = {
2463 .probe = ab8500_codec_probe,
2464 .read = ab8500_codec_read_reg,
2465 .write = ab8500_codec_write_reg,
2466 .reg_word_size = sizeof(u8),
2467 .controls = ab8500_ctrls,
2468 .num_controls = ARRAY_SIZE(ab8500_ctrls),
2469 .dapm_widgets = ab8500_dapm_widgets,
2470 .num_dapm_widgets = ARRAY_SIZE(ab8500_dapm_widgets),
2471 .dapm_routes = ab8500_dapm_routes,
2472 .num_dapm_routes = ARRAY_SIZE(ab8500_dapm_routes),
2473};
2474
2475static int __devinit ab8500_codec_driver_probe(struct platform_device *pdev)
2476{
2477 int status;
2478 struct ab8500_codec_drvdata *drvdata;
2479
2480 dev_dbg(&pdev->dev, "%s: Enter.\n", __func__);
2481
2482 /* Create driver private-data struct */
2483 drvdata = devm_kzalloc(&pdev->dev, sizeof(struct ab8500_codec_drvdata),
2484 GFP_KERNEL);
2485 drvdata->sid_status = SID_UNCONFIGURED;
2486 drvdata->anc_status = ANC_UNCONFIGURED;
2487 dev_set_drvdata(&pdev->dev, drvdata);
2488
2489 dev_dbg(&pdev->dev, "%s: Register codec.\n", __func__);
2490 status = snd_soc_register_codec(&pdev->dev, &ab8500_codec_driver,
2491 ab8500_codec_dai,
2492 ARRAY_SIZE(ab8500_codec_dai));
2493 if (status < 0)
2494 dev_err(&pdev->dev,
2495 "%s: Error: Failed to register codec (%d).\n",
2496 __func__, status);
2497
2498 return status;
2499}
2500
2501static int __devexit ab8500_codec_driver_remove(struct platform_device *pdev)
2502{
2503 dev_info(&pdev->dev, "%s Enter.\n", __func__);
2504
2505 snd_soc_unregister_codec(&pdev->dev);
2506
2507 return 0;
2508}
2509
2510static struct platform_driver ab8500_codec_platform_driver = {
2511 .driver = {
2512 .name = "ab8500-codec",
2513 .owner = THIS_MODULE,
2514 },
2515 .probe = ab8500_codec_driver_probe,
2516 .remove = __devexit_p(ab8500_codec_driver_remove),
2517 .suspend = NULL,
2518 .resume = NULL,
2519};
2520module_platform_driver(ab8500_codec_platform_driver);
2521
2522MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/ab8500-codec.h b/sound/soc/codecs/ab8500-codec.h
new file mode 100644
index 00000000000..114f69a0c62
--- /dev/null
+++ b/sound/soc/codecs/ab8500-codec.h
@@ -0,0 +1,590 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2012
3 *
4 * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
5 * Kristoffer Karlsson <kristoffer.karlsson@stericsson.com>,
6 * Roger Nilsson <roger.xr.nilsson@stericsson.com>,
7 * for ST-Ericsson.
8 *
9 * Based on the early work done by:
10 * Mikko J. Lehto <mikko.lehto@symbio.com>,
11 * Mikko Sarmanne <mikko.sarmanne@symbio.com>,
12 * for ST-Ericsson.
13 *
14 * License terms:
15 *
16 * This program is free software; you can redistribute it and/or modify it
17 * under the terms of the GNU General Public License version 2 as published
18 * by the Free Software Foundation.
19 */
20
21#ifndef AB8500_CODEC_REGISTERS_H
22#define AB8500_CODEC_REGISTERS_H
23
24#define AB8500_SUPPORTED_RATE (SNDRV_PCM_RATE_48000)
25#define AB8500_SUPPORTED_FMT (SNDRV_PCM_FMTBIT_S16_LE)
26
27/* AB8500 audio bank (0x0d) register definitions */
28
29#define AB8500_POWERUP 0x00
30#define AB8500_AUDSWRESET 0x01
31#define AB8500_ADPATHENA 0x02
32#define AB8500_DAPATHENA 0x03
33#define AB8500_ANACONF1 0x04
34#define AB8500_ANACONF2 0x05
35#define AB8500_DIGMICCONF 0x06
36#define AB8500_ANACONF3 0x07
37#define AB8500_ANACONF4 0x08
38#define AB8500_DAPATHCONF 0x09
39#define AB8500_MUTECONF 0x0A
40#define AB8500_SHORTCIRCONF 0x0B
41#define AB8500_ANACONF5 0x0C
42#define AB8500_ENVCPCONF 0x0D
43#define AB8500_SIGENVCONF 0x0E
44#define AB8500_PWMGENCONF1 0x0F
45#define AB8500_PWMGENCONF2 0x10
46#define AB8500_PWMGENCONF3 0x11
47#define AB8500_PWMGENCONF4 0x12
48#define AB8500_PWMGENCONF5 0x13
49#define AB8500_ANAGAIN1 0x14
50#define AB8500_ANAGAIN2 0x15
51#define AB8500_ANAGAIN3 0x16
52#define AB8500_ANAGAIN4 0x17
53#define AB8500_DIGLINHSLGAIN 0x18
54#define AB8500_DIGLINHSRGAIN 0x19
55#define AB8500_ADFILTCONF 0x1A
56#define AB8500_DIGIFCONF1 0x1B
57#define AB8500_DIGIFCONF2 0x1C
58#define AB8500_DIGIFCONF3 0x1D
59#define AB8500_DIGIFCONF4 0x1E
60#define AB8500_ADSLOTSEL1 0x1F
61#define AB8500_ADSLOTSEL2 0x20
62#define AB8500_ADSLOTSEL3 0x21
63#define AB8500_ADSLOTSEL4 0x22
64#define AB8500_ADSLOTSEL5 0x23
65#define AB8500_ADSLOTSEL6 0x24
66#define AB8500_ADSLOTSEL7 0x25
67#define AB8500_ADSLOTSEL8 0x26
68#define AB8500_ADSLOTSEL9 0x27
69#define AB8500_ADSLOTSEL10 0x28
70#define AB8500_ADSLOTSEL11 0x29
71#define AB8500_ADSLOTSEL12 0x2A
72#define AB8500_ADSLOTSEL13 0x2B
73#define AB8500_ADSLOTSEL14 0x2C
74#define AB8500_ADSLOTSEL15 0x2D
75#define AB8500_ADSLOTSEL16 0x2E
76#define AB8500_ADSLOTHIZCTRL1 0x2F
77#define AB8500_ADSLOTHIZCTRL2 0x30
78#define AB8500_ADSLOTHIZCTRL3 0x31
79#define AB8500_ADSLOTHIZCTRL4 0x32
80#define AB8500_DASLOTCONF1 0x33
81#define AB8500_DASLOTCONF2 0x34
82#define AB8500_DASLOTCONF3 0x35
83#define AB8500_DASLOTCONF4 0x36
84#define AB8500_DASLOTCONF5 0x37
85#define AB8500_DASLOTCONF6 0x38
86#define AB8500_DASLOTCONF7 0x39
87#define AB8500_DASLOTCONF8 0x3A
88#define AB8500_CLASSDCONF1 0x3B
89#define AB8500_CLASSDCONF2 0x3C
90#define AB8500_CLASSDCONF3 0x3D
91#define AB8500_DMICFILTCONF 0x3E
92#define AB8500_DIGMULTCONF1 0x3F
93#define AB8500_DIGMULTCONF2 0x40
94#define AB8500_ADDIGGAIN1 0x41
95#define AB8500_ADDIGGAIN2 0x42
96#define AB8500_ADDIGGAIN3 0x43
97#define AB8500_ADDIGGAIN4 0x44
98#define AB8500_ADDIGGAIN5 0x45
99#define AB8500_ADDIGGAIN6 0x46
100#define AB8500_DADIGGAIN1 0x47
101#define AB8500_DADIGGAIN2 0x48
102#define AB8500_DADIGGAIN3 0x49
103#define AB8500_DADIGGAIN4 0x4A
104#define AB8500_DADIGGAIN5 0x4B
105#define AB8500_DADIGGAIN6 0x4C
106#define AB8500_ADDIGLOOPGAIN1 0x4D
107#define AB8500_ADDIGLOOPGAIN2 0x4E
108#define AB8500_HSLEARDIGGAIN 0x4F
109#define AB8500_HSRDIGGAIN 0x50
110#define AB8500_SIDFIRGAIN1 0x51
111#define AB8500_SIDFIRGAIN2 0x52
112#define AB8500_ANCCONF1 0x53
113#define AB8500_ANCCONF2 0x54
114#define AB8500_ANCCONF3 0x55
115#define AB8500_ANCCONF4 0x56
116#define AB8500_ANCCONF5 0x57
117#define AB8500_ANCCONF6 0x58
118#define AB8500_ANCCONF7 0x59
119#define AB8500_ANCCONF8 0x5A
120#define AB8500_ANCCONF9 0x5B
121#define AB8500_ANCCONF10 0x5C
122#define AB8500_ANCCONF11 0x5D
123#define AB8500_ANCCONF12 0x5E
124#define AB8500_ANCCONF13 0x5F
125#define AB8500_ANCCONF14 0x60
126#define AB8500_SIDFIRADR 0x61
127#define AB8500_SIDFIRCOEF1 0x62
128#define AB8500_SIDFIRCOEF2 0x63
129#define AB8500_SIDFIRCONF 0x64
130#define AB8500_AUDINTMASK1 0x65
131#define AB8500_AUDINTSOURCE1 0x66
132#define AB8500_AUDINTMASK2 0x67
133#define AB8500_AUDINTSOURCE2 0x68
134#define AB8500_FIFOCONF1 0x69
135#define AB8500_FIFOCONF2 0x6A
136#define AB8500_FIFOCONF3 0x6B
137#define AB8500_FIFOCONF4 0x6C
138#define AB8500_FIFOCONF5 0x6D
139#define AB8500_FIFOCONF6 0x6E
140#define AB8500_AUDREV 0x6F
141
142#define AB8500_FIRST_REG AB8500_POWERUP
143#define AB8500_LAST_REG AB8500_AUDREV
144#define AB8500_CACHEREGNUM (AB8500_LAST_REG + 1)
145
146#define AB8500_MASK_ALL 0xFF
147#define AB8500_MASK_NONE 0x00
148
149/* AB8500_POWERUP */
150#define AB8500_POWERUP_POWERUP 7
151#define AB8500_POWERUP_ENANA 3
152
153/* AB8500_AUDSWRESET */
154#define AB8500_AUDSWRESET_SWRESET 7
155
156/* AB8500_ADPATHENA */
157#define AB8500_ADPATHENA_ENAD12 7
158#define AB8500_ADPATHENA_ENAD34 5
159#define AB8500_ADPATHENA_ENAD5768 3
160
161/* AB8500_DAPATHENA */
162#define AB8500_DAPATHENA_ENDA1 7
163#define AB8500_DAPATHENA_ENDA2 6
164#define AB8500_DAPATHENA_ENDA3 5
165#define AB8500_DAPATHENA_ENDA4 4
166#define AB8500_DAPATHENA_ENDA5 3
167#define AB8500_DAPATHENA_ENDA6 2
168
169/* AB8500_ANACONF1 */
170#define AB8500_ANACONF1_HSLOWPOW 7
171#define AB8500_ANACONF1_DACLOWPOW1 6
172#define AB8500_ANACONF1_DACLOWPOW0 5
173#define AB8500_ANACONF1_EARDACLOWPOW 4
174#define AB8500_ANACONF1_EARSELCM 2
175#define AB8500_ANACONF1_HSHPEN 1
176#define AB8500_ANACONF1_EARDRVLOWPOW 0
177
178/* AB8500_ANACONF2 */
179#define AB8500_ANACONF2_ENMIC1 7
180#define AB8500_ANACONF2_ENMIC2 6
181#define AB8500_ANACONF2_ENLINL 5
182#define AB8500_ANACONF2_ENLINR 4
183#define AB8500_ANACONF2_MUTMIC1 3
184#define AB8500_ANACONF2_MUTMIC2 2
185#define AB8500_ANACONF2_MUTLINL 1
186#define AB8500_ANACONF2_MUTLINR 0
187
188/* AB8500_DIGMICCONF */
189#define AB8500_DIGMICCONF_ENDMIC1 7
190#define AB8500_DIGMICCONF_ENDMIC2 6
191#define AB8500_DIGMICCONF_ENDMIC3 5
192#define AB8500_DIGMICCONF_ENDMIC4 4
193#define AB8500_DIGMICCONF_ENDMIC5 3
194#define AB8500_DIGMICCONF_ENDMIC6 2
195#define AB8500_DIGMICCONF_HSFADSPEED 0
196
197/* AB8500_ANACONF3 */
198#define AB8500_ANACONF3_MIC1SEL 7
199#define AB8500_ANACONF3_LINRSEL 6
200#define AB8500_ANACONF3_ENDRVHSL 5
201#define AB8500_ANACONF3_ENDRVHSR 4
202#define AB8500_ANACONF3_ENADCMIC 2
203#define AB8500_ANACONF3_ENADCLINL 1
204#define AB8500_ANACONF3_ENADCLINR 0
205
206/* AB8500_ANACONF4 */
207#define AB8500_ANACONF4_DISPDVSS 7
208#define AB8500_ANACONF4_ENEAR 6
209#define AB8500_ANACONF4_ENHSL 5
210#define AB8500_ANACONF4_ENHSR 4
211#define AB8500_ANACONF4_ENHFL 3
212#define AB8500_ANACONF4_ENHFR 2
213#define AB8500_ANACONF4_ENVIB1 1
214#define AB8500_ANACONF4_ENVIB2 0
215
216/* AB8500_DAPATHCONF */
217#define AB8500_DAPATHCONF_ENDACEAR 6
218#define AB8500_DAPATHCONF_ENDACHSL 5
219#define AB8500_DAPATHCONF_ENDACHSR 4
220#define AB8500_DAPATHCONF_ENDACHFL 3
221#define AB8500_DAPATHCONF_ENDACHFR 2
222#define AB8500_DAPATHCONF_ENDACVIB1 1
223#define AB8500_DAPATHCONF_ENDACVIB2 0
224
225/* AB8500_MUTECONF */
226#define AB8500_MUTECONF_MUTEAR 6
227#define AB8500_MUTECONF_MUTHSL 5
228#define AB8500_MUTECONF_MUTHSR 4
229#define AB8500_MUTECONF_MUTDACEAR 2
230#define AB8500_MUTECONF_MUTDACHSL 1
231#define AB8500_MUTECONF_MUTDACHSR 0
232
233/* AB8500_SHORTCIRCONF */
234#define AB8500_SHORTCIRCONF_ENSHORTPWD 7
235#define AB8500_SHORTCIRCONF_EARSHORTDIS 6
236#define AB8500_SHORTCIRCONF_HSSHORTDIS 5
237#define AB8500_SHORTCIRCONF_HSPULLDEN 4
238#define AB8500_SHORTCIRCONF_HSOSCEN 2
239#define AB8500_SHORTCIRCONF_HSFADDIS 1
240#define AB8500_SHORTCIRCONF_HSZCDDIS 0
241/* Zero cross should be disabled */
242
243/* AB8500_ANACONF5 */
244#define AB8500_ANACONF5_ENCPHS 7
245#define AB8500_ANACONF5_HSLDACTOLOL 5
246#define AB8500_ANACONF5_HSRDACTOLOR 4
247#define AB8500_ANACONF5_ENLOL 3
248#define AB8500_ANACONF5_ENLOR 2
249#define AB8500_ANACONF5_HSAUTOEN 0
250
251/* AB8500_ENVCPCONF */
252#define AB8500_ENVCPCONF_ENVDETHTHRE 4
253#define AB8500_ENVCPCONF_ENVDETLTHRE 0
254#define AB8500_ENVCPCONF_ENVDETHTHRE_MAX 0x0F
255#define AB8500_ENVCPCONF_ENVDETLTHRE_MAX 0x0F
256
257/* AB8500_SIGENVCONF */
258#define AB8500_SIGENVCONF_CPLVEN 5
259#define AB8500_SIGENVCONF_ENVDETCPEN 4
260#define AB8500_SIGENVCONF_ENVDETTIME 0
261#define AB8500_SIGENVCONF_ENVDETTIME_MAX 0x0F
262
263/* AB8500_PWMGENCONF1 */
264#define AB8500_PWMGENCONF1_PWMTOVIB1 7
265#define AB8500_PWMGENCONF1_PWMTOVIB2 6
266#define AB8500_PWMGENCONF1_PWM1CTRL 5
267#define AB8500_PWMGENCONF1_PWM2CTRL 4
268#define AB8500_PWMGENCONF1_PWM1NCTRL 3
269#define AB8500_PWMGENCONF1_PWM1PCTRL 2
270#define AB8500_PWMGENCONF1_PWM2NCTRL 1
271#define AB8500_PWMGENCONF1_PWM2PCTRL 0
272
273/* AB8500_PWMGENCONF2 */
274/* AB8500_PWMGENCONF3 */
275/* AB8500_PWMGENCONF4 */
276/* AB8500_PWMGENCONF5 */
277#define AB8500_PWMGENCONFX_PWMVIBXPOL 7
278#define AB8500_PWMGENCONFX_PWMVIBXDUTCYC 0
279#define AB8500_PWMGENCONFX_PWMVIBXDUTCYC_MAX 0x64
280
281/* AB8500_ANAGAIN1 */
282/* AB8500_ANAGAIN2 */
283#define AB8500_ANAGAINX_ENSEMICX 7
284#define AB8500_ANAGAINX_LOWPOWMICX 6
285#define AB8500_ANAGAINX_MICXGAIN 0
286#define AB8500_ANAGAINX_MICXGAIN_MAX 0x1F
287
288/* AB8500_ANAGAIN3 */
289#define AB8500_ANAGAIN3_HSLGAIN 4
290#define AB8500_ANAGAIN3_HSRGAIN 0
291#define AB8500_ANAGAIN3_HSXGAIN_MAX 0x0F
292
293/* AB8500_ANAGAIN4 */
294#define AB8500_ANAGAIN4_LINLGAIN 4
295#define AB8500_ANAGAIN4_LINRGAIN 0
296#define AB8500_ANAGAIN4_LINXGAIN_MAX 0x0F
297
298/* AB8500_DIGLINHSLGAIN */
299/* AB8500_DIGLINHSRGAIN */
300#define AB8500_DIGLINHSXGAIN_LINTOHSXGAIN 0
301#define AB8500_DIGLINHSXGAIN_LINTOHSXGAIN_MAX 0x13
302
303/* AB8500_ADFILTCONF */
304#define AB8500_ADFILTCONF_AD1NH 7
305#define AB8500_ADFILTCONF_AD2NH 6
306#define AB8500_ADFILTCONF_AD3NH 5
307#define AB8500_ADFILTCONF_AD4NH 4
308#define AB8500_ADFILTCONF_AD1VOICE 3
309#define AB8500_ADFILTCONF_AD2VOICE 2
310#define AB8500_ADFILTCONF_AD3VOICE 1
311#define AB8500_ADFILTCONF_AD4VOICE 0
312
313/* AB8500_DIGIFCONF1 */
314#define AB8500_DIGIFCONF1_ENMASTGEN 7
315#define AB8500_DIGIFCONF1_IF1BITCLKOS1 6
316#define AB8500_DIGIFCONF1_IF1BITCLKOS0 5
317#define AB8500_DIGIFCONF1_ENFSBITCLK1 4
318#define AB8500_DIGIFCONF1_IF0BITCLKOS1 2
319#define AB8500_DIGIFCONF1_IF0BITCLKOS0 1
320#define AB8500_DIGIFCONF1_ENFSBITCLK0 0
321
322/* AB8500_DIGIFCONF2 */
323#define AB8500_DIGIFCONF2_FSYNC0P 6
324#define AB8500_DIGIFCONF2_BITCLK0P 5
325#define AB8500_DIGIFCONF2_IF0DEL 4
326#define AB8500_DIGIFCONF2_IF0FORMAT1 3
327#define AB8500_DIGIFCONF2_IF0FORMAT0 2
328#define AB8500_DIGIFCONF2_IF0WL1 1
329#define AB8500_DIGIFCONF2_IF0WL0 0
330
331/* AB8500_DIGIFCONF3 */
332#define AB8500_DIGIFCONF3_IF0DATOIF1AD 7
333#define AB8500_DIGIFCONF3_IF0CLKTOIF1CLK 6
334#define AB8500_DIGIFCONF3_IF1MASTER 5
335#define AB8500_DIGIFCONF3_IF1DATOIF0AD 3
336#define AB8500_DIGIFCONF3_IF1CLKTOIF0CLK 2
337#define AB8500_DIGIFCONF3_IF0MASTER 1
338#define AB8500_DIGIFCONF3_IF0BFIFOEN 0
339
340/* AB8500_DIGIFCONF4 */
341#define AB8500_DIGIFCONF4_FSYNC1P 6
342#define AB8500_DIGIFCONF4_BITCLK1P 5
343#define AB8500_DIGIFCONF4_IF1DEL 4
344#define AB8500_DIGIFCONF4_IF1FORMAT1 3
345#define AB8500_DIGIFCONF4_IF1FORMAT0 2
346#define AB8500_DIGIFCONF4_IF1WL1 1
347#define AB8500_DIGIFCONF4_IF1WL0 0
348
349/* AB8500_ADSLOTSELX */
350#define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_ODD 0x00
351#define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD 0x01
352#define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD 0x02
353#define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_ODD 0x03
354#define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_ODD 0x04
355#define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_ODD 0x05
356#define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_ODD 0x06
357#define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_ODD 0x07
358#define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_ODD 0x08
359#define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_ODD 0x0F
360#define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_EVEN 0x00
361#define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_EVEN 0x10
362#define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN 0x20
363#define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_EVEN 0x30
364#define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_EVEN 0x40
365#define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_EVEN 0x50
366#define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_EVEN 0x60
367#define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_EVEN 0x70
368#define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_EVEN 0x80
369#define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_EVEN 0xF0
370#define AB8500_ADSLOTSELX_EVEN_SHIFT 0
371#define AB8500_ADSLOTSELX_ODD_SHIFT 4
372
373/* AB8500_ADSLOTHIZCTRL1 */
374/* AB8500_ADSLOTHIZCTRL2 */
375/* AB8500_ADSLOTHIZCTRL3 */
376/* AB8500_ADSLOTHIZCTRL4 */
377/* AB8500_DASLOTCONF1 */
378#define AB8500_DASLOTCONF1_DA12VOICE 7
379#define AB8500_DASLOTCONF1_SWAPDA12_34 6
380#define AB8500_DASLOTCONF1_DAI7TOADO1 5
381
382/* AB8500_DASLOTCONF2 */
383#define AB8500_DASLOTCONF2_DAI8TOADO2 5
384
385/* AB8500_DASLOTCONF3 */
386#define AB8500_DASLOTCONF3_DA34VOICE 7
387#define AB8500_DASLOTCONF3_DAI7TOADO3 5
388
389/* AB8500_DASLOTCONF4 */
390#define AB8500_DASLOTCONF4_DAI8TOADO4 5
391
392/* AB8500_DASLOTCONF5 */
393#define AB8500_DASLOTCONF5_DA56VOICE 7
394#define AB8500_DASLOTCONF5_DAI7TOADO5 5
395
396/* AB8500_DASLOTCONF6 */
397#define AB8500_DASLOTCONF6_DAI8TOADO6 5
398
399/* AB8500_DASLOTCONF7 */
400#define AB8500_DASLOTCONF7_DAI8TOADO7 5
401
402/* AB8500_DASLOTCONF8 */
403#define AB8500_DASLOTCONF8_DAI7TOADO8 5
404
405#define AB8500_DASLOTCONFX_SLTODAX_SHIFT 0
406#define AB8500_DASLOTCONFX_SLTODAX_MASK 0x1F
407
408/* AB8500_CLASSDCONF1 */
409#define AB8500_CLASSDCONF1_PARLHF 7
410#define AB8500_CLASSDCONF1_PARLVIB 6
411#define AB8500_CLASSDCONF1_VIB1SWAPEN 3
412#define AB8500_CLASSDCONF1_VIB2SWAPEN 2
413#define AB8500_CLASSDCONF1_HFLSWAPEN 1
414#define AB8500_CLASSDCONF1_HFRSWAPEN 0
415
416/* AB8500_CLASSDCONF2 */
417#define AB8500_CLASSDCONF2_FIRBYP3 7
418#define AB8500_CLASSDCONF2_FIRBYP2 6
419#define AB8500_CLASSDCONF2_FIRBYP1 5
420#define AB8500_CLASSDCONF2_FIRBYP0 4
421#define AB8500_CLASSDCONF2_HIGHVOLEN3 3
422#define AB8500_CLASSDCONF2_HIGHVOLEN2 2
423#define AB8500_CLASSDCONF2_HIGHVOLEN1 1
424#define AB8500_CLASSDCONF2_HIGHVOLEN0 0
425
426/* AB8500_CLASSDCONF3 */
427#define AB8500_CLASSDCONF3_DITHHPGAIN 4
428#define AB8500_CLASSDCONF3_DITHHPGAIN_MAX 0x0A
429#define AB8500_CLASSDCONF3_DITHWGAIN 0
430#define AB8500_CLASSDCONF3_DITHWGAIN_MAX 0x0A
431
432/* AB8500_DMICFILTCONF */
433#define AB8500_DMICFILTCONF_ANCINSEL 7
434#define AB8500_DMICFILTCONF_DA3TOEAR 6
435#define AB8500_DMICFILTCONF_DMIC1SINC3 5
436#define AB8500_DMICFILTCONF_DMIC2SINC3 4
437#define AB8500_DMICFILTCONF_DMIC3SINC3 3
438#define AB8500_DMICFILTCONF_DMIC4SINC3 2
439#define AB8500_DMICFILTCONF_DMIC5SINC3 1
440#define AB8500_DMICFILTCONF_DMIC6SINC3 0
441
442/* AB8500_DIGMULTCONF1 */
443#define AB8500_DIGMULTCONF1_DATOHSLEN 7
444#define AB8500_DIGMULTCONF1_DATOHSREN 6
445#define AB8500_DIGMULTCONF1_AD1SEL 5
446#define AB8500_DIGMULTCONF1_AD2SEL 4
447#define AB8500_DIGMULTCONF1_AD3SEL 3
448#define AB8500_DIGMULTCONF1_AD5SEL 2
449#define AB8500_DIGMULTCONF1_AD6SEL 1
450#define AB8500_DIGMULTCONF1_ANCSEL 0
451
452/* AB8500_DIGMULTCONF2 */
453#define AB8500_DIGMULTCONF2_DATOHFREN 7
454#define AB8500_DIGMULTCONF2_DATOHFLEN 6
455#define AB8500_DIGMULTCONF2_HFRSEL 5
456#define AB8500_DIGMULTCONF2_HFLSEL 4
457#define AB8500_DIGMULTCONF2_FIRSID1SEL 2
458#define AB8500_DIGMULTCONF2_FIRSID2SEL 0
459
460/* AB8500_ADDIGGAIN1 */
461/* AB8500_ADDIGGAIN2 */
462/* AB8500_ADDIGGAIN3 */
463/* AB8500_ADDIGGAIN4 */
464/* AB8500_ADDIGGAIN5 */
465/* AB8500_ADDIGGAIN6 */
466#define AB8500_ADDIGGAINX_FADEDISADX 6
467#define AB8500_ADDIGGAINX_ADXGAIN_MAX 0x3F
468
469/* AB8500_DADIGGAIN1 */
470/* AB8500_DADIGGAIN2 */
471/* AB8500_DADIGGAIN3 */
472/* AB8500_DADIGGAIN4 */
473/* AB8500_DADIGGAIN5 */
474/* AB8500_DADIGGAIN6 */
475#define AB8500_DADIGGAINX_FADEDISDAX 6
476#define AB8500_DADIGGAINX_DAXGAIN_MAX 0x3F
477
478/* AB8500_ADDIGLOOPGAIN1 */
479/* AB8500_ADDIGLOOPGAIN2 */
480#define AB8500_ADDIGLOOPGAINX_FADEDISADXL 6
481#define AB8500_ADDIGLOOPGAINX_ADXLBGAIN_MAX 0x3F
482
483/* AB8500_HSLEARDIGGAIN */
484#define AB8500_HSLEARDIGGAIN_HSSINC1 7
485#define AB8500_HSLEARDIGGAIN_FADEDISHSL 4
486#define AB8500_HSLEARDIGGAIN_HSLDGAIN_MAX 0x09
487
488/* AB8500_HSRDIGGAIN */
489#define AB8500_HSRDIGGAIN_FADESPEED 6
490#define AB8500_HSRDIGGAIN_FADEDISHSR 4
491#define AB8500_HSRDIGGAIN_HSRDGAIN_MAX 0x09
492
493/* AB8500_SIDFIRGAIN1 */
494/* AB8500_SIDFIRGAIN2 */
495#define AB8500_SIDFIRGAINX_FIRSIDXGAIN_MAX 0x1F
496
497/* AB8500_ANCCONF1 */
498#define AB8500_ANCCONF1_ANCIIRUPDATE 3
499#define AB8500_ANCCONF1_ENANC 2
500#define AB8500_ANCCONF1_ANCIIRINIT 1
501#define AB8500_ANCCONF1_ANCFIRUPDATE 0
502
503/* AB8500_ANCCONF2 */
504#define AB8500_ANCCONF2_SHIFT 5
505#define AB8500_ANCCONF2_MIN -0x10
506#define AB8500_ANCCONF2_MAX 0xF
507
508/* AB8500_ANCCONF3 */
509#define AB8500_ANCCONF3_SHIFT 5
510#define AB8500_ANCCONF3_MIN -0x10
511#define AB8500_ANCCONF3_MAX 0xF
512
513/* AB8500_ANCCONF4 */
514#define AB8500_ANCCONF4_SHIFT 5
515#define AB8500_ANCCONF4_MIN -0x10
516#define AB8500_ANCCONF4_MAX 0xF
517
518/* AB8500_ANC_FIR_COEFFS */
519#define AB8500_ANC_FIR_COEFF_MIN -0x8000
520#define AB8500_ANC_FIR_COEFF_MAX 0x7FFF
521#define AB8500_ANC_FIR_COEFFS 15
522
523/* AB8500_ANC_IIR_COEFFS */
524#define AB8500_ANC_IIR_COEFF_MIN -0x800000
525#define AB8500_ANC_IIR_COEFF_MAX 0x7FFFFF
526#define AB8500_ANC_IIR_COEFFS 24
527/* AB8500_ANC_WARP_DELAY */
528#define AB8500_ANC_WARP_DELAY_SHIFT 16
529#define AB8500_ANC_WARP_DELAY_MIN 0x0000
530#define AB8500_ANC_WARP_DELAY_MAX 0xFFFF
531
532/* AB8500_ANCCONF11 */
533/* AB8500_ANCCONF12 */
534/* AB8500_ANCCONF13 */
535/* AB8500_ANCCONF14 */
536
537/* AB8500_SIDFIRADR */
538#define AB8500_SIDFIRADR_FIRSIDSET 7
539#define AB8500_SIDFIRADR_ADDRESS_SHIFT 0
540#define AB8500_SIDFIRADR_ADDRESS_MAX 0x7F
541
542/* AB8500_SIDFIRCOEF1 */
543/* AB8500_SIDFIRCOEF2 */
544#define AB8500_SID_FIR_COEFF_MIN 0
545#define AB8500_SID_FIR_COEFF_MAX 0xFFFF
546#define AB8500_SID_FIR_COEFFS 128
547
548/* AB8500_SIDFIRCONF */
549#define AB8500_SIDFIRCONF_ENFIRSIDS 2
550#define AB8500_SIDFIRCONF_FIRSIDSTOIF1 1
551#define AB8500_SIDFIRCONF_FIRSIDBUSY 0
552
553/* AB8500_AUDINTMASK1 */
554/* AB8500_AUDINTSOURCE1 */
555/* AB8500_AUDINTMASK2 */
556/* AB8500_AUDINTSOURCE2 */
557
558/* AB8500_FIFOCONF1 */
559#define AB8500_FIFOCONF1_BFIFOMASK 0x80
560#define AB8500_FIFOCONF1_BFIFO19M2 0x40
561#define AB8500_FIFOCONF1_BFIFOINT_SHIFT 0
562#define AB8500_FIFOCONF1_BFIFOINT_MAX 0x3F
563
564/* AB8500_FIFOCONF2 */
565#define AB8500_FIFOCONF2_BFIFOTX_SHIFT 0
566#define AB8500_FIFOCONF2_BFIFOTX_MAX 0xFF
567
568/* AB8500_FIFOCONF3 */
569#define AB8500_FIFOCONF3_BFIFOEXSL_SHIFT 5
570#define AB8500_FIFOCONF3_BFIFOEXSL_MAX 0x5
571#define AB8500_FIFOCONF3_PREBITCLK0_SHIFT 2
572#define AB8500_FIFOCONF3_PREBITCLK0_MAX 0x7
573#define AB8500_FIFOCONF3_BFIFOMAST_SHIFT 1
574#define AB8500_FIFOCONF3_BFIFORUN_SHIFT 0
575
576/* AB8500_FIFOCONF4 */
577#define AB8500_FIFOCONF4_BFIFOFRAMSW_SHIFT 0
578#define AB8500_FIFOCONF4_BFIFOFRAMSW_MAX 0xFF
579
580/* AB8500_FIFOCONF5 */
581#define AB8500_FIFOCONF5_BFIFOWAKEUP_SHIFT 0
582#define AB8500_FIFOCONF5_BFIFOWAKEUP_MAX 0xFF
583
584/* AB8500_FIFOCONF6 */
585#define AB8500_FIFOCONF6_BFIFOSAMPLE_SHIFT 0
586#define AB8500_FIFOCONF6_BFIFOSAMPLE_MAX 0xFF
587
588/* AB8500_AUDREV */
589
590#endif
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index 2023c749f23..ea06b834a7d 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -91,11 +91,6 @@ static int ac97_soc_probe(struct snd_soc_codec *codec)
91 return 0; 91 return 0;
92} 92}
93 93
94static int ac97_soc_remove(struct snd_soc_codec *codec)
95{
96 return 0;
97}
98
99#ifdef CONFIG_PM 94#ifdef CONFIG_PM
100static int ac97_soc_suspend(struct snd_soc_codec *codec) 95static int ac97_soc_suspend(struct snd_soc_codec *codec)
101{ 96{
@@ -119,7 +114,6 @@ static struct snd_soc_codec_driver soc_codec_dev_ac97 = {
119 .write = ac97_write, 114 .write = ac97_write,
120 .read = ac97_read, 115 .read = ac97_read,
121 .probe = ac97_soc_probe, 116 .probe = ac97_soc_probe,
122 .remove = ac97_soc_remove,
123 .suspend = ac97_soc_suspend, 117 .suspend = ac97_soc_suspend,
124 .resume = ac97_soc_resume, 118 .resume = ac97_soc_resume,
125}; 119};
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
new file mode 100644
index 00000000000..5c9cacaf2d5
--- /dev/null
+++ b/sound/soc/codecs/arizona.c
@@ -0,0 +1,937 @@
1/*
2 * arizona.c - Wolfson Arizona class device shared support
3 *
4 * Copyright 2012 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/gcd.h>
14#include <linux/module.h>
15#include <linux/pm_runtime.h>
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18#include <sound/tlv.h>
19
20#include <linux/mfd/arizona/core.h>
21#include <linux/mfd/arizona/registers.h>
22
23#include "arizona.h"
24
25#define ARIZONA_AIF_BCLK_CTRL 0x00
26#define ARIZONA_AIF_TX_PIN_CTRL 0x01
27#define ARIZONA_AIF_RX_PIN_CTRL 0x02
28#define ARIZONA_AIF_RATE_CTRL 0x03
29#define ARIZONA_AIF_FORMAT 0x04
30#define ARIZONA_AIF_TX_BCLK_RATE 0x05
31#define ARIZONA_AIF_RX_BCLK_RATE 0x06
32#define ARIZONA_AIF_FRAME_CTRL_1 0x07
33#define ARIZONA_AIF_FRAME_CTRL_2 0x08
34#define ARIZONA_AIF_FRAME_CTRL_3 0x09
35#define ARIZONA_AIF_FRAME_CTRL_4 0x0A
36#define ARIZONA_AIF_FRAME_CTRL_5 0x0B
37#define ARIZONA_AIF_FRAME_CTRL_6 0x0C
38#define ARIZONA_AIF_FRAME_CTRL_7 0x0D
39#define ARIZONA_AIF_FRAME_CTRL_8 0x0E
40#define ARIZONA_AIF_FRAME_CTRL_9 0x0F
41#define ARIZONA_AIF_FRAME_CTRL_10 0x10
42#define ARIZONA_AIF_FRAME_CTRL_11 0x11
43#define ARIZONA_AIF_FRAME_CTRL_12 0x12
44#define ARIZONA_AIF_FRAME_CTRL_13 0x13
45#define ARIZONA_AIF_FRAME_CTRL_14 0x14
46#define ARIZONA_AIF_FRAME_CTRL_15 0x15
47#define ARIZONA_AIF_FRAME_CTRL_16 0x16
48#define ARIZONA_AIF_FRAME_CTRL_17 0x17
49#define ARIZONA_AIF_FRAME_CTRL_18 0x18
50#define ARIZONA_AIF_TX_ENABLES 0x19
51#define ARIZONA_AIF_RX_ENABLES 0x1A
52#define ARIZONA_AIF_FORCE_WRITE 0x1B
53
54#define arizona_fll_err(_fll, fmt, ...) \
55 dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
56#define arizona_fll_warn(_fll, fmt, ...) \
57 dev_warn(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
58#define arizona_fll_dbg(_fll, fmt, ...) \
59 dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
60
61#define arizona_aif_err(_dai, fmt, ...) \
62 dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
63#define arizona_aif_warn(_dai, fmt, ...) \
64 dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
65#define arizona_aif_dbg(_dai, fmt, ...) \
66 dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
67
68const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
69 "None",
70 "Tone Generator 1",
71 "Tone Generator 2",
72 "Haptics",
73 "AEC",
74 "Mic Mute Mixer",
75 "Noise Generator",
76 "IN1L",
77 "IN1R",
78 "IN2L",
79 "IN2R",
80 "IN3L",
81 "IN3R",
82 "IN4L",
83 "IN4R",
84 "AIF1RX1",
85 "AIF1RX2",
86 "AIF1RX3",
87 "AIF1RX4",
88 "AIF1RX5",
89 "AIF1RX6",
90 "AIF1RX7",
91 "AIF1RX8",
92 "AIF2RX1",
93 "AIF2RX2",
94 "AIF3RX1",
95 "AIF3RX2",
96 "SLIMRX1",
97 "SLIMRX2",
98 "SLIMRX3",
99 "SLIMRX4",
100 "SLIMRX5",
101 "SLIMRX6",
102 "SLIMRX7",
103 "SLIMRX8",
104 "EQ1",
105 "EQ2",
106 "EQ3",
107 "EQ4",
108 "DRC1L",
109 "DRC1R",
110 "DRC2L",
111 "DRC2R",
112 "LHPF1",
113 "LHPF2",
114 "LHPF3",
115 "LHPF4",
116 "DSP1.1",
117 "DSP1.2",
118 "DSP1.3",
119 "DSP1.4",
120 "DSP1.5",
121 "DSP1.6",
122 "ASRC1L",
123 "ASRC1R",
124 "ASRC2L",
125 "ASRC2R",
126};
127EXPORT_SYMBOL_GPL(arizona_mixer_texts);
128
129int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
130 0x00, /* None */
131 0x04, /* Tone */
132 0x05,
133 0x06, /* Haptics */
134 0x08, /* AEC */
135 0x0c, /* Noise mixer */
136 0x0d, /* Comfort noise */
137 0x10, /* IN1L */
138 0x11,
139 0x12,
140 0x13,
141 0x14,
142 0x15,
143 0x16,
144 0x17,
145 0x20, /* AIF1RX1 */
146 0x21,
147 0x22,
148 0x23,
149 0x24,
150 0x25,
151 0x26,
152 0x27,
153 0x28, /* AIF2RX1 */
154 0x29,
155 0x30, /* AIF3RX1 */
156 0x31,
157 0x38, /* SLIMRX1 */
158 0x39,
159 0x3a,
160 0x3b,
161 0x3c,
162 0x3d,
163 0x3e,
164 0x3f,
165 0x50, /* EQ1 */
166 0x51,
167 0x52,
168 0x53,
169 0x58, /* DRC1L */
170 0x59,
171 0x5a,
172 0x5b,
173 0x60, /* LHPF1 */
174 0x61,
175 0x62,
176 0x63,
177 0x68, /* DSP1.1 */
178 0x69,
179 0x6a,
180 0x6b,
181 0x6c,
182 0x6d,
183 0x90, /* ASRC1L */
184 0x91,
185 0x92,
186 0x93,
187};
188EXPORT_SYMBOL_GPL(arizona_mixer_values);
189
190const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
191EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
192
193static const char *arizona_lhpf_mode_text[] = {
194 "Low-pass", "High-pass"
195};
196
197const struct soc_enum arizona_lhpf1_mode =
198 SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2,
199 arizona_lhpf_mode_text);
200EXPORT_SYMBOL_GPL(arizona_lhpf1_mode);
201
202const struct soc_enum arizona_lhpf2_mode =
203 SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2,
204 arizona_lhpf_mode_text);
205EXPORT_SYMBOL_GPL(arizona_lhpf2_mode);
206
207const struct soc_enum arizona_lhpf3_mode =
208 SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2,
209 arizona_lhpf_mode_text);
210EXPORT_SYMBOL_GPL(arizona_lhpf3_mode);
211
212const struct soc_enum arizona_lhpf4_mode =
213 SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2,
214 arizona_lhpf_mode_text);
215EXPORT_SYMBOL_GPL(arizona_lhpf4_mode);
216
217int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
218 int event)
219{
220 return 0;
221}
222EXPORT_SYMBOL_GPL(arizona_in_ev);
223
224int arizona_out_ev(struct snd_soc_dapm_widget *w,
225 struct snd_kcontrol *kcontrol,
226 int event)
227{
228 return 0;
229}
230EXPORT_SYMBOL_GPL(arizona_out_ev);
231
232int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
233 int source, unsigned int freq, int dir)
234{
235 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
236 struct arizona *arizona = priv->arizona;
237 char *name;
238 unsigned int reg;
239 unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK;
240 unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
241 unsigned int *clk;
242
243 switch (clk_id) {
244 case ARIZONA_CLK_SYSCLK:
245 name = "SYSCLK";
246 reg = ARIZONA_SYSTEM_CLOCK_1;
247 clk = &priv->sysclk;
248 mask |= ARIZONA_SYSCLK_FRAC;
249 break;
250 case ARIZONA_CLK_ASYNCCLK:
251 name = "ASYNCCLK";
252 reg = ARIZONA_ASYNC_CLOCK_1;
253 clk = &priv->asyncclk;
254 break;
255 default:
256 return -EINVAL;
257 }
258
259 switch (freq) {
260 case 5644800:
261 case 6144000:
262 break;
263 case 11289600:
264 case 12288000:
265 val |= 1 << ARIZONA_SYSCLK_FREQ_SHIFT;
266 break;
267 case 22579200:
268 case 24576000:
269 val |= 2 << ARIZONA_SYSCLK_FREQ_SHIFT;
270 break;
271 case 45158400:
272 case 49152000:
273 val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT;
274 break;
275 default:
276 return -EINVAL;
277 }
278
279 *clk = freq;
280
281 if (freq % 6144000)
282 val |= ARIZONA_SYSCLK_FRAC;
283
284 dev_dbg(arizona->dev, "%s set to %uHz", name, freq);
285
286 return regmap_update_bits(arizona->regmap, reg, mask, val);
287}
288EXPORT_SYMBOL_GPL(arizona_set_sysclk);
289
290static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
291{
292 struct snd_soc_codec *codec = dai->codec;
293 int lrclk, bclk, mode, base;
294
295 base = dai->driver->base;
296
297 lrclk = 0;
298 bclk = 0;
299
300 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
301 case SND_SOC_DAIFMT_DSP_A:
302 mode = 0;
303 break;
304 case SND_SOC_DAIFMT_DSP_B:
305 mode = 1;
306 break;
307 case SND_SOC_DAIFMT_I2S:
308 mode = 2;
309 break;
310 case SND_SOC_DAIFMT_LEFT_J:
311 mode = 3;
312 break;
313 default:
314 arizona_aif_err(dai, "Unsupported DAI format %d\n",
315 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
316 return -EINVAL;
317 }
318
319 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
320 case SND_SOC_DAIFMT_CBS_CFS:
321 break;
322 case SND_SOC_DAIFMT_CBS_CFM:
323 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
324 break;
325 case SND_SOC_DAIFMT_CBM_CFS:
326 bclk |= ARIZONA_AIF1_BCLK_MSTR;
327 break;
328 case SND_SOC_DAIFMT_CBM_CFM:
329 bclk |= ARIZONA_AIF1_BCLK_MSTR;
330 lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
331 break;
332 default:
333 arizona_aif_err(dai, "Unsupported master mode %d\n",
334 fmt & SND_SOC_DAIFMT_MASTER_MASK);
335 return -EINVAL;
336 }
337
338 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
339 case SND_SOC_DAIFMT_NB_NF:
340 break;
341 case SND_SOC_DAIFMT_IB_IF:
342 bclk |= ARIZONA_AIF1_BCLK_INV;
343 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
344 break;
345 case SND_SOC_DAIFMT_IB_NF:
346 bclk |= ARIZONA_AIF1_BCLK_INV;
347 break;
348 case SND_SOC_DAIFMT_NB_IF:
349 lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
350 break;
351 default:
352 return -EINVAL;
353 }
354
355 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
356 ARIZONA_AIF1_BCLK_INV | ARIZONA_AIF1_BCLK_MSTR,
357 bclk);
358 snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_PIN_CTRL,
359 ARIZONA_AIF1TX_LRCLK_INV |
360 ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
361 snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_PIN_CTRL,
362 ARIZONA_AIF1RX_LRCLK_INV |
363 ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
364 snd_soc_update_bits(codec, base + ARIZONA_AIF_FORMAT,
365 ARIZONA_AIF1_FMT_MASK, mode);
366
367 return 0;
368}
369
370static const int arizona_48k_bclk_rates[] = {
371 -1,
372 48000,
373 64000,
374 96000,
375 128000,
376 192000,
377 256000,
378 384000,
379 512000,
380 768000,
381 1024000,
382 1536000,
383 2048000,
384 3072000,
385 4096000,
386 6144000,
387 8192000,
388 12288000,
389 24576000,
390};
391
392static const unsigned int arizona_48k_rates[] = {
393 12000,
394 24000,
395 48000,
396 96000,
397 192000,
398 384000,
399 768000,
400 4000,
401 8000,
402 16000,
403 32000,
404 64000,
405 128000,
406 256000,
407 512000,
408};
409
410static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = {
411 .count = ARRAY_SIZE(arizona_48k_rates),
412 .list = arizona_48k_rates,
413};
414
415static const int arizona_44k1_bclk_rates[] = {
416 -1,
417 44100,
418 58800,
419 88200,
420 117600,
421 177640,
422 235200,
423 352800,
424 470400,
425 705600,
426 940800,
427 1411200,
428 1881600,
429 2882400,
430 3763200,
431 5644800,
432 7526400,
433 11289600,
434 22579200,
435};
436
437static const unsigned int arizona_44k1_rates[] = {
438 11025,
439 22050,
440 44100,
441 88200,
442 176400,
443 352800,
444 705600,
445};
446
447static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = {
448 .count = ARRAY_SIZE(arizona_44k1_rates),
449 .list = arizona_44k1_rates,
450};
451
452static int arizona_sr_vals[] = {
453 0,
454 12000,
455 24000,
456 48000,
457 96000,
458 192000,
459 384000,
460 768000,
461 0,
462 11025,
463 22050,
464 44100,
465 88200,
466 176400,
467 352800,
468 705600,
469 4000,
470 8000,
471 16000,
472 32000,
473 64000,
474 128000,
475 256000,
476 512000,
477};
478
479static int arizona_startup(struct snd_pcm_substream *substream,
480 struct snd_soc_dai *dai)
481{
482 struct snd_soc_codec *codec = dai->codec;
483 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
484 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
485 const struct snd_pcm_hw_constraint_list *constraint;
486 unsigned int base_rate;
487
488 switch (dai_priv->clk) {
489 case ARIZONA_CLK_SYSCLK:
490 base_rate = priv->sysclk;
491 break;
492 case ARIZONA_CLK_ASYNCCLK:
493 base_rate = priv->asyncclk;
494 break;
495 default:
496 return 0;
497 }
498
499 if (base_rate % 8000)
500 constraint = &arizona_44k1_constraint;
501 else
502 constraint = &arizona_48k_constraint;
503
504 return snd_pcm_hw_constraint_list(substream->runtime, 0,
505 SNDRV_PCM_HW_PARAM_RATE,
506 constraint);
507}
508
509static int arizona_hw_params(struct snd_pcm_substream *substream,
510 struct snd_pcm_hw_params *params,
511 struct snd_soc_dai *dai)
512{
513 struct snd_soc_codec *codec = dai->codec;
514 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
515 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
516 int base = dai->driver->base;
517 const int *rates;
518 int i;
519 int bclk, lrclk, wl, frame, sr_val;
520
521 if (params_rate(params) % 8000)
522 rates = &arizona_44k1_bclk_rates[0];
523 else
524 rates = &arizona_48k_bclk_rates[0];
525
526 for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
527 if (rates[i] >= snd_soc_params_to_bclk(params) &&
528 rates[i] % params_rate(params) == 0) {
529 bclk = i;
530 break;
531 }
532 }
533 if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) {
534 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
535 params_rate(params));
536 return -EINVAL;
537 }
538
539 for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
540 if (arizona_sr_vals[i] == params_rate(params))
541 break;
542 if (i == ARRAY_SIZE(arizona_sr_vals)) {
543 arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
544 params_rate(params));
545 return -EINVAL;
546 }
547 sr_val = i;
548
549 lrclk = snd_soc_params_to_bclk(params) / params_rate(params);
550
551 arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
552 rates[bclk], rates[bclk] / lrclk);
553
554 wl = snd_pcm_format_width(params_format(params));
555 frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
556
557 /*
558 * We will need to be more flexible than this in future,
559 * currently we use a single sample rate for SYSCLK.
560 */
561 switch (dai_priv->clk) {
562 case ARIZONA_CLK_SYSCLK:
563 snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
564 ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
565 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
566 ARIZONA_AIF1_RATE_MASK, 0);
567 break;
568 case ARIZONA_CLK_ASYNCCLK:
569 snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
570 ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val);
571 snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
572 ARIZONA_AIF1_RATE_MASK, 8);
573 break;
574 default:
575 arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
576 return -EINVAL;
577 }
578
579 snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
580 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
581 snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE,
582 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
583 snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE,
584 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
585 snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1,
586 ARIZONA_AIF1TX_WL_MASK |
587 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
588 snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2,
589 ARIZONA_AIF1RX_WL_MASK |
590 ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
591
592 return 0;
593}
594
595static const char *arizona_dai_clk_str(int clk_id)
596{
597 switch (clk_id) {
598 case ARIZONA_CLK_SYSCLK:
599 return "SYSCLK";
600 case ARIZONA_CLK_ASYNCCLK:
601 return "ASYNCCLK";
602 default:
603 return "Unknown clock";
604 }
605}
606
607static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
608 int clk_id, unsigned int freq, int dir)
609{
610 struct snd_soc_codec *codec = dai->codec;
611 struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
612 struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
613 struct snd_soc_dapm_route routes[2];
614
615 switch (clk_id) {
616 case ARIZONA_CLK_SYSCLK:
617 case ARIZONA_CLK_ASYNCCLK:
618 break;
619 default:
620 return -EINVAL;
621 }
622
623 if (clk_id == dai_priv->clk)
624 return 0;
625
626 if (dai->active) {
627 dev_err(codec->dev, "Can't change clock on active DAI %d\n",
628 dai->id);
629 return -EBUSY;
630 }
631
632 memset(&routes, 0, sizeof(routes));
633 routes[0].sink = dai->driver->capture.stream_name;
634 routes[1].sink = dai->driver->playback.stream_name;
635
636 routes[0].source = arizona_dai_clk_str(dai_priv->clk);
637 routes[1].source = arizona_dai_clk_str(dai_priv->clk);
638 snd_soc_dapm_del_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
639
640 routes[0].source = arizona_dai_clk_str(clk_id);
641 routes[1].source = arizona_dai_clk_str(clk_id);
642 snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes));
643
644 return snd_soc_dapm_sync(&codec->dapm);
645}
646
647const struct snd_soc_dai_ops arizona_dai_ops = {
648 .startup = arizona_startup,
649 .set_fmt = arizona_set_fmt,
650 .hw_params = arizona_hw_params,
651 .set_sysclk = arizona_dai_set_sysclk,
652};
653EXPORT_SYMBOL_GPL(arizona_dai_ops);
654
655int arizona_init_dai(struct arizona_priv *priv, int id)
656{
657 struct arizona_dai_priv *dai_priv = &priv->dai[id];
658
659 dai_priv->clk = ARIZONA_CLK_SYSCLK;
660
661 return 0;
662}
663EXPORT_SYMBOL_GPL(arizona_init_dai);
664
665static irqreturn_t arizona_fll_lock(int irq, void *data)
666{
667 struct arizona_fll *fll = data;
668
669 arizona_fll_dbg(fll, "Locked\n");
670
671 complete(&fll->lock);
672
673 return IRQ_HANDLED;
674}
675
676static irqreturn_t arizona_fll_clock_ok(int irq, void *data)
677{
678 struct arizona_fll *fll = data;
679
680 arizona_fll_dbg(fll, "clock OK\n");
681
682 complete(&fll->ok);
683
684 return IRQ_HANDLED;
685}
686
687static struct {
688 unsigned int min;
689 unsigned int max;
690 u16 fratio;
691 int ratio;
692} fll_fratios[] = {
693 { 0, 64000, 4, 16 },
694 { 64000, 128000, 3, 8 },
695 { 128000, 256000, 2, 4 },
696 { 256000, 1000000, 1, 2 },
697 { 1000000, 13500000, 0, 1 },
698};
699
700struct arizona_fll_cfg {
701 int n;
702 int theta;
703 int lambda;
704 int refdiv;
705 int outdiv;
706 int fratio;
707};
708
709static int arizona_calc_fll(struct arizona_fll *fll,
710 struct arizona_fll_cfg *cfg,
711 unsigned int Fref,
712 unsigned int Fout)
713{
714 unsigned int target, div, gcd_fll;
715 int i, ratio;
716
717 arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout);
718
719 /* Fref must be <=13.5MHz */
720 div = 1;
721 cfg->refdiv = 0;
722 while ((Fref / div) > 13500000) {
723 div *= 2;
724 cfg->refdiv++;
725
726 if (div > 8) {
727 arizona_fll_err(fll,
728 "Can't scale %dMHz in to <=13.5MHz\n",
729 Fref);
730 return -EINVAL;
731 }
732 }
733
734 /* Apply the division for our remaining calculations */
735 Fref /= div;
736
737 /* Fvco should be over the targt; don't check the upper bound */
738 div = 1;
739 while (Fout * div < 90000000 * fll->vco_mult) {
740 div++;
741 if (div > 7) {
742 arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
743 Fout);
744 return -EINVAL;
745 }
746 }
747 target = Fout * div / fll->vco_mult;
748 cfg->outdiv = div;
749
750 arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
751
752 /* Find an appropraite FLL_FRATIO and factor it out of the target */
753 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
754 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
755 cfg->fratio = fll_fratios[i].fratio;
756 ratio = fll_fratios[i].ratio;
757 break;
758 }
759 }
760 if (i == ARRAY_SIZE(fll_fratios)) {
761 arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
762 Fref);
763 return -EINVAL;
764 }
765
766 cfg->n = target / (ratio * Fref);
767
768 if (target % Fref) {
769 gcd_fll = gcd(target, ratio * Fref);
770 arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
771
772 cfg->theta = (target - (cfg->n * ratio * Fref))
773 / gcd_fll;
774 cfg->lambda = (ratio * Fref) / gcd_fll;
775 } else {
776 cfg->theta = 0;
777 cfg->lambda = 0;
778 }
779
780 arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
781 cfg->n, cfg->theta, cfg->lambda);
782 arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",
783 cfg->fratio, cfg->fratio, cfg->outdiv, cfg->refdiv);
784
785 return 0;
786
787}
788
789static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
790 struct arizona_fll_cfg *cfg, int source)
791{
792 regmap_update_bits(arizona->regmap, base + 3,
793 ARIZONA_FLL1_THETA_MASK, cfg->theta);
794 regmap_update_bits(arizona->regmap, base + 4,
795 ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
796 regmap_update_bits(arizona->regmap, base + 5,
797 ARIZONA_FLL1_FRATIO_MASK,
798 cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
799 regmap_update_bits(arizona->regmap, base + 6,
800 ARIZONA_FLL1_CLK_REF_DIV_MASK |
801 ARIZONA_FLL1_CLK_REF_SRC_MASK,
802 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
803 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
804
805 regmap_update_bits(arizona->regmap, base + 2,
806 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
807 ARIZONA_FLL1_CTRL_UPD | cfg->n);
808}
809
810int arizona_set_fll(struct arizona_fll *fll, int source,
811 unsigned int Fref, unsigned int Fout)
812{
813 struct arizona *arizona = fll->arizona;
814 struct arizona_fll_cfg cfg, sync;
815 unsigned int reg, val;
816 int syncsrc;
817 bool ena;
818 int ret;
819
820 ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
821 if (ret != 0) {
822 arizona_fll_err(fll, "Failed to read current state: %d\n",
823 ret);
824 return ret;
825 }
826 ena = reg & ARIZONA_FLL1_ENA;
827
828 if (Fout) {
829 /* Do we have a 32kHz reference? */
830 regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
831 switch (val & ARIZONA_CLK_32K_SRC_MASK) {
832 case ARIZONA_CLK_SRC_MCLK1:
833 case ARIZONA_CLK_SRC_MCLK2:
834 syncsrc = val & ARIZONA_CLK_32K_SRC_MASK;
835 break;
836 default:
837 syncsrc = -1;
838 }
839
840 if (source == syncsrc)
841 syncsrc = -1;
842
843 if (syncsrc >= 0) {
844 ret = arizona_calc_fll(fll, &sync, Fref, Fout);
845 if (ret != 0)
846 return ret;
847
848 ret = arizona_calc_fll(fll, &cfg, 32768, Fout);
849 if (ret != 0)
850 return ret;
851 } else {
852 ret = arizona_calc_fll(fll, &cfg, Fref, Fout);
853 if (ret != 0)
854 return ret;
855 }
856 } else {
857 regmap_update_bits(arizona->regmap, fll->base + 1,
858 ARIZONA_FLL1_ENA, 0);
859 regmap_update_bits(arizona->regmap, fll->base + 0x11,
860 ARIZONA_FLL1_SYNC_ENA, 0);
861
862 if (ena)
863 pm_runtime_put_autosuspend(arizona->dev);
864
865 return 0;
866 }
867
868 regmap_update_bits(arizona->regmap, fll->base + 5,
869 ARIZONA_FLL1_OUTDIV_MASK,
870 cfg.outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
871
872 if (syncsrc >= 0) {
873 arizona_apply_fll(arizona, fll->base, &cfg, syncsrc);
874 arizona_apply_fll(arizona, fll->base + 0x10, &sync, source);
875 } else {
876 arizona_apply_fll(arizona, fll->base, &cfg, source);
877 }
878
879 if (!ena)
880 pm_runtime_get(arizona->dev);
881
882 /* Clear any pending completions */
883 try_wait_for_completion(&fll->ok);
884
885 regmap_update_bits(arizona->regmap, fll->base + 1,
886 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
887 if (syncsrc >= 0)
888 regmap_update_bits(arizona->regmap, fll->base + 0x11,
889 ARIZONA_FLL1_SYNC_ENA,
890 ARIZONA_FLL1_SYNC_ENA);
891
892 ret = wait_for_completion_timeout(&fll->ok,
893 msecs_to_jiffies(25));
894 if (ret == 0)
895 arizona_fll_warn(fll, "Timed out waiting for lock\n");
896
897 return 0;
898}
899EXPORT_SYMBOL_GPL(arizona_set_fll);
900
901int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
902 int ok_irq, struct arizona_fll *fll)
903{
904 int ret;
905
906 init_completion(&fll->lock);
907 init_completion(&fll->ok);
908
909 fll->id = id;
910 fll->base = base;
911 fll->arizona = arizona;
912
913 snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
914 snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
915 "FLL%d clock OK", id);
916
917 ret = arizona_request_irq(arizona, lock_irq, fll->lock_name,
918 arizona_fll_lock, fll);
919 if (ret != 0) {
920 dev_err(arizona->dev, "Failed to get FLL%d lock IRQ: %d\n",
921 id, ret);
922 }
923
924 ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name,
925 arizona_fll_clock_ok, fll);
926 if (ret != 0) {
927 dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n",
928 id, ret);
929 }
930
931 return 0;
932}
933EXPORT_SYMBOL_GPL(arizona_init_fll);
934
935MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
936MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
937MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
new file mode 100644
index 00000000000..59caca8865e
--- /dev/null
+++ b/sound/soc/codecs/arizona.h
@@ -0,0 +1,159 @@
1/*
2 * arizona.h - Wolfson Arizona class device shared support
3 *
4 * Copyright 2012 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef _ASOC_ARIZONA_H
14#define _ASOC_ARIZONA_H
15
16#include <linux/completion.h>
17
18#include <sound/soc.h>
19
20#define ARIZONA_CLK_SYSCLK 1
21#define ARIZONA_CLK_ASYNCCLK 2
22
23#define ARIZONA_CLK_SRC_MCLK1 0x0
24#define ARIZONA_CLK_SRC_MCLK2 0x1
25#define ARIZONA_CLK_SRC_FLL1 0x4
26#define ARIZONA_CLK_SRC_FLL2 0x5
27#define ARIZONA_CLK_SRC_AIF1BCLK 0x8
28#define ARIZONA_CLK_SRC_AIF2BCLK 0x9
29#define ARIZONA_CLK_SRC_AIF3BCLK 0xa
30
31#define ARIZONA_FLL_SRC_MCLK1 0
32#define ARIZONA_FLL_SRC_MCLK2 1
33#define ARIZONA_FLL_SRC_SLIMCLK 2
34#define ARIZONA_FLL_SRC_FLL1 3
35#define ARIZONA_FLL_SRC_FLL2 4
36#define ARIZONA_FLL_SRC_AIF1BCLK 5
37#define ARIZONA_FLL_SRC_AIF2BCLK 6
38#define ARIZONA_FLL_SRC_AIF3BCLK 7
39#define ARIZONA_FLL_SRC_AIF1LRCLK 8
40#define ARIZONA_FLL_SRC_AIF2LRCLK 9
41#define ARIZONA_FLL_SRC_AIF3LRCLK 10
42
43#define ARIZONA_MIXER_VOL_MASK 0x00FE
44#define ARIZONA_MIXER_VOL_SHIFT 1
45#define ARIZONA_MIXER_VOL_WIDTH 7
46
47#define ARIZONA_MAX_DAI 3
48
49struct arizona;
50
51struct arizona_dai_priv {
52 int clk;
53};
54
55struct arizona_priv {
56 struct arizona *arizona;
57 int sysclk;
58 int asyncclk;
59 struct arizona_dai_priv dai[ARIZONA_MAX_DAI];
60};
61
62#define ARIZONA_NUM_MIXER_INPUTS 57
63
64extern const unsigned int arizona_mixer_tlv[];
65extern const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS];
66extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
67
68#define ARIZONA_MIXER_CONTROLS(name, base) \
69 SOC_SINGLE_RANGE_TLV(name " Input 1 Volume", base + 1, \
70 ARIZONA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \
71 arizona_mixer_tlv), \
72 SOC_SINGLE_RANGE_TLV(name " Input 2 Volume", base + 3, \
73 ARIZONA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \
74 arizona_mixer_tlv), \
75 SOC_SINGLE_RANGE_TLV(name " Input 3 Volume", base + 5, \
76 ARIZONA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \
77 arizona_mixer_tlv), \
78 SOC_SINGLE_RANGE_TLV(name " Input 4 Volume", base + 7, \
79 ARIZONA_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \
80 arizona_mixer_tlv)
81
82#define ARIZONA_MUX_ENUM_DECL(name, reg) \
83 SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, \
84 arizona_mixer_texts, arizona_mixer_values)
85
86#define ARIZONA_MUX_CTL_DECL(name) \
87 const struct snd_kcontrol_new name##_mux = \
88 SOC_DAPM_VALUE_ENUM("Route", name##_enum)
89
90#define ARIZONA_MIXER_ENUMS(name, base_reg) \
91 static ARIZONA_MUX_ENUM_DECL(name##_in1_enum, base_reg); \
92 static ARIZONA_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2); \
93 static ARIZONA_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4); \
94 static ARIZONA_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6); \
95 static ARIZONA_MUX_CTL_DECL(name##_in1); \
96 static ARIZONA_MUX_CTL_DECL(name##_in2); \
97 static ARIZONA_MUX_CTL_DECL(name##_in3); \
98 static ARIZONA_MUX_CTL_DECL(name##_in4)
99
100#define ARIZONA_MUX(name, ctrl) \
101 SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
102
103#define ARIZONA_MIXER_WIDGETS(name, name_str) \
104 ARIZONA_MUX(name_str " Input 1", &name##_in1_mux), \
105 ARIZONA_MUX(name_str " Input 2", &name##_in2_mux), \
106 ARIZONA_MUX(name_str " Input 3", &name##_in3_mux), \
107 ARIZONA_MUX(name_str " Input 4", &name##_in4_mux), \
108 SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
109
110#define ARIZONA_MIXER_ROUTES(widget, name) \
111 { widget, NULL, name " Mixer" }, \
112 { name " Mixer", NULL, name " Input 1" }, \
113 { name " Mixer", NULL, name " Input 2" }, \
114 { name " Mixer", NULL, name " Input 3" }, \
115 { name " Mixer", NULL, name " Input 4" }, \
116 ARIZONA_MIXER_INPUT_ROUTES(name " Input 1"), \
117 ARIZONA_MIXER_INPUT_ROUTES(name " Input 2"), \
118 ARIZONA_MIXER_INPUT_ROUTES(name " Input 3"), \
119 ARIZONA_MIXER_INPUT_ROUTES(name " Input 4")
120
121extern const struct soc_enum arizona_lhpf1_mode;
122extern const struct soc_enum arizona_lhpf2_mode;
123extern const struct soc_enum arizona_lhpf3_mode;
124extern const struct soc_enum arizona_lhpf4_mode;
125
126extern int arizona_in_ev(struct snd_soc_dapm_widget *w,
127 struct snd_kcontrol *kcontrol,
128 int event);
129extern int arizona_out_ev(struct snd_soc_dapm_widget *w,
130 struct snd_kcontrol *kcontrol,
131 int event);
132
133extern int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
134 int source, unsigned int freq, int dir);
135
136extern const struct snd_soc_dai_ops arizona_dai_ops;
137
138#define ARIZONA_FLL_NAME_LEN 20
139
140struct arizona_fll {
141 struct arizona *arizona;
142 int id;
143 unsigned int base;
144 unsigned int vco_mult;
145 struct completion lock;
146 struct completion ok;
147
148 char lock_name[ARIZONA_FLL_NAME_LEN];
149 char clock_ok_name[ARIZONA_FLL_NAME_LEN];
150};
151
152extern int arizona_init_fll(struct arizona *arizona, int id, int base,
153 int lock_irq, int ok_irq, struct arizona_fll *fll);
154extern int arizona_set_fll(struct arizona_fll *fll, int source,
155 unsigned int Fref, unsigned int Fout);
156
157extern int arizona_init_dai(struct arizona_priv *priv, int dai);
158
159#endif
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
index a7109413aef..628daf6a1d9 100644
--- a/sound/soc/codecs/cs42l52.c
+++ b/sound/soc/codecs/cs42l52.c
@@ -14,7 +14,6 @@
14 14
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/moduleparam.h> 16#include <linux/moduleparam.h>
17#include <linux/version.h>
18#include <linux/kernel.h> 17#include <linux/kernel.h>
19#include <linux/init.h> 18#include <linux/init.h>
20#include <linux/delay.h> 19#include <linux/delay.h>
@@ -1217,11 +1216,11 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
1217 return -ENOMEM; 1216 return -ENOMEM;
1218 cs42l52->dev = &i2c_client->dev; 1217 cs42l52->dev = &i2c_client->dev;
1219 1218
1220 cs42l52->regmap = regmap_init_i2c(i2c_client, &cs42l52_regmap); 1219 cs42l52->regmap = devm_regmap_init_i2c(i2c_client, &cs42l52_regmap);
1221 if (IS_ERR(cs42l52->regmap)) { 1220 if (IS_ERR(cs42l52->regmap)) {
1222 ret = PTR_ERR(cs42l52->regmap); 1221 ret = PTR_ERR(cs42l52->regmap);
1223 dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); 1222 dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
1224 goto err; 1223 return ret;
1225 } 1224 }
1226 1225
1227 i2c_set_clientdata(i2c_client, cs42l52); 1226 i2c_set_clientdata(i2c_client, cs42l52);
@@ -1243,7 +1242,7 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
1243 dev_err(&i2c_client->dev, 1242 dev_err(&i2c_client->dev,
1244 "CS42L52 Device ID (%X). Expected %X\n", 1243 "CS42L52 Device ID (%X). Expected %X\n",
1245 devid, CS42L52_CHIP_ID); 1244 devid, CS42L52_CHIP_ID);
1246 goto err_regmap; 1245 return ret;
1247 } 1246 }
1248 1247
1249 regcache_cache_only(cs42l52->regmap, true); 1248 regcache_cache_only(cs42l52->regmap, true);
@@ -1251,23 +1250,13 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
1251 ret = snd_soc_register_codec(&i2c_client->dev, 1250 ret = snd_soc_register_codec(&i2c_client->dev,
1252 &soc_codec_dev_cs42l52, &cs42l52_dai, 1); 1251 &soc_codec_dev_cs42l52, &cs42l52_dai, 1);
1253 if (ret < 0) 1252 if (ret < 0)
1254 goto err_regmap; 1253 return ret;
1255 return 0; 1254 return 0;
1256
1257err_regmap:
1258 regmap_exit(cs42l52->regmap);
1259
1260err:
1261 return ret;
1262} 1255}
1263 1256
1264static int cs42l52_i2c_remove(struct i2c_client *client) 1257static int cs42l52_i2c_remove(struct i2c_client *client)
1265{ 1258{
1266 struct cs42l52_private *cs42l52 = i2c_get_clientdata(client);
1267
1268 snd_soc_unregister_codec(&client->dev); 1259 snd_soc_unregister_codec(&client->dev);
1269 regmap_exit(cs42l52->regmap);
1270
1271 return 0; 1260 return 0;
1272} 1261}
1273 1262
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
index e0d45fdaa75..2c08c4cb465 100644
--- a/sound/soc/codecs/cs42l73.c
+++ b/sound/soc/codecs/cs42l73.c
@@ -1362,11 +1362,11 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client,
1362 1362
1363 i2c_set_clientdata(i2c_client, cs42l73); 1363 i2c_set_clientdata(i2c_client, cs42l73);
1364 1364
1365 cs42l73->regmap = regmap_init_i2c(i2c_client, &cs42l73_regmap); 1365 cs42l73->regmap = devm_regmap_init_i2c(i2c_client, &cs42l73_regmap);
1366 if (IS_ERR(cs42l73->regmap)) { 1366 if (IS_ERR(cs42l73->regmap)) {
1367 ret = PTR_ERR(cs42l73->regmap); 1367 ret = PTR_ERR(cs42l73->regmap);
1368 dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); 1368 dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
1369 goto err; 1369 return ret;
1370 } 1370 }
1371 /* initialize codec */ 1371 /* initialize codec */
1372 ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, &reg); 1372 ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, &reg);
@@ -1384,13 +1384,13 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client,
1384 dev_err(&i2c_client->dev, 1384 dev_err(&i2c_client->dev,
1385 "CS42L73 Device ID (%X). Expected %X\n", 1385 "CS42L73 Device ID (%X). Expected %X\n",
1386 devid, CS42L73_DEVID); 1386 devid, CS42L73_DEVID);
1387 goto err_regmap; 1387 return ret;
1388 } 1388 }
1389 1389
1390 ret = regmap_read(cs42l73->regmap, CS42L73_REVID, &reg); 1390 ret = regmap_read(cs42l73->regmap, CS42L73_REVID, &reg);
1391 if (ret < 0) { 1391 if (ret < 0) {
1392 dev_err(&i2c_client->dev, "Get Revision ID failed\n"); 1392 dev_err(&i2c_client->dev, "Get Revision ID failed\n");
1393 goto err_regmap; 1393 return ret;;
1394 } 1394 }
1395 1395
1396 dev_info(&i2c_client->dev, 1396 dev_info(&i2c_client->dev,
@@ -1402,23 +1402,13 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client,
1402 &soc_codec_dev_cs42l73, cs42l73_dai, 1402 &soc_codec_dev_cs42l73, cs42l73_dai,
1403 ARRAY_SIZE(cs42l73_dai)); 1403 ARRAY_SIZE(cs42l73_dai));
1404 if (ret < 0) 1404 if (ret < 0)
1405 goto err_regmap; 1405 return ret;
1406 return 0; 1406 return 0;
1407
1408err_regmap:
1409 regmap_exit(cs42l73->regmap);
1410
1411err:
1412 return ret;
1413} 1407}
1414 1408
1415static __devexit int cs42l73_i2c_remove(struct i2c_client *client) 1409static __devexit int cs42l73_i2c_remove(struct i2c_client *client)
1416{ 1410{
1417 struct cs42l73_private *cs42l73 = i2c_get_clientdata(client);
1418
1419 snd_soc_unregister_codec(&client->dev); 1411 snd_soc_unregister_codec(&client->dev);
1420 regmap_exit(cs42l73->regmap);
1421
1422 return 0; 1412 return 0;
1423} 1413}
1424 1414
diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c
new file mode 100644
index 00000000000..01be2a320e2
--- /dev/null
+++ b/sound/soc/codecs/da732x.c
@@ -0,0 +1,1627 @@
1/*
2 * da732x.c --- Dialog DA732X ALSA SoC Audio Driver
3 *
4 * Copyright (C) 2012 Dialog Semiconductor GmbH
5 *
6 * Author: Michal Hajduk <Michal.Hajduk@diasemi.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/init.h>
16#include <linux/delay.h>
17#include <linux/pm.h>
18#include <linux/i2c.h>
19#include <linux/regmap.h>
20#include <linux/platform_device.h>
21#include <linux/slab.h>
22#include <linux/sysfs.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28#include <sound/initval.h>
29#include <sound/tlv.h>
30#include <asm/div64.h>
31
32#include "da732x.h"
33#include "da732x_reg.h"
34
35
36struct da732x_priv {
37 struct regmap *regmap;
38 struct snd_soc_codec *codec;
39
40 unsigned int sysclk;
41 bool pll_en;
42};
43
44/*
45 * da732x register cache - default settings
46 */
47static struct reg_default da732x_reg_cache[] = {
48 { DA732X_REG_REF1 , 0x02 },
49 { DA732X_REG_BIAS_EN , 0x80 },
50 { DA732X_REG_BIAS1 , 0x00 },
51 { DA732X_REG_BIAS2 , 0x00 },
52 { DA732X_REG_BIAS3 , 0x00 },
53 { DA732X_REG_BIAS4 , 0x00 },
54 { DA732X_REG_MICBIAS2 , 0x00 },
55 { DA732X_REG_MICBIAS1 , 0x00 },
56 { DA732X_REG_MICDET , 0x00 },
57 { DA732X_REG_MIC1_PRE , 0x01 },
58 { DA732X_REG_MIC1 , 0x40 },
59 { DA732X_REG_MIC2_PRE , 0x01 },
60 { DA732X_REG_MIC2 , 0x40 },
61 { DA732X_REG_AUX1L , 0x75 },
62 { DA732X_REG_AUX1R , 0x75 },
63 { DA732X_REG_MIC3_PRE , 0x01 },
64 { DA732X_REG_MIC3 , 0x40 },
65 { DA732X_REG_INP_PINBIAS , 0x00 },
66 { DA732X_REG_INP_ZC_EN , 0x00 },
67 { DA732X_REG_INP_MUX , 0x50 },
68 { DA732X_REG_HP_DET , 0x00 },
69 { DA732X_REG_HPL_DAC_OFFSET , 0x00 },
70 { DA732X_REG_HPL_DAC_OFF_CNTL , 0x00 },
71 { DA732X_REG_HPL_OUT_OFFSET , 0x00 },
72 { DA732X_REG_HPL , 0x40 },
73 { DA732X_REG_HPL_VOL , 0x0F },
74 { DA732X_REG_HPR_DAC_OFFSET , 0x00 },
75 { DA732X_REG_HPR_DAC_OFF_CNTL , 0x00 },
76 { DA732X_REG_HPR_OUT_OFFSET , 0x00 },
77 { DA732X_REG_HPR , 0x40 },
78 { DA732X_REG_HPR_VOL , 0x0F },
79 { DA732X_REG_LIN2 , 0x4F },
80 { DA732X_REG_LIN3 , 0x4F },
81 { DA732X_REG_LIN4 , 0x4F },
82 { DA732X_REG_OUT_ZC_EN , 0x00 },
83 { DA732X_REG_HP_LIN1_GNDSEL , 0x00 },
84 { DA732X_REG_CP_HP1 , 0x0C },
85 { DA732X_REG_CP_HP2 , 0x03 },
86 { DA732X_REG_CP_CTRL1 , 0x00 },
87 { DA732X_REG_CP_CTRL2 , 0x99 },
88 { DA732X_REG_CP_CTRL3 , 0x25 },
89 { DA732X_REG_CP_LEVEL_MASK , 0x3F },
90 { DA732X_REG_CP_DET , 0x00 },
91 { DA732X_REG_CP_STATUS , 0x00 },
92 { DA732X_REG_CP_THRESH1 , 0x00 },
93 { DA732X_REG_CP_THRESH2 , 0x00 },
94 { DA732X_REG_CP_THRESH3 , 0x00 },
95 { DA732X_REG_CP_THRESH4 , 0x00 },
96 { DA732X_REG_CP_THRESH5 , 0x00 },
97 { DA732X_REG_CP_THRESH6 , 0x00 },
98 { DA732X_REG_CP_THRESH7 , 0x00 },
99 { DA732X_REG_CP_THRESH8 , 0x00 },
100 { DA732X_REG_PLL_DIV_LO , 0x00 },
101 { DA732X_REG_PLL_DIV_MID , 0x00 },
102 { DA732X_REG_PLL_DIV_HI , 0x00 },
103 { DA732X_REG_PLL_CTRL , 0x02 },
104 { DA732X_REG_CLK_CTRL , 0xaa },
105 { DA732X_REG_CLK_DSP , 0x07 },
106 { DA732X_REG_CLK_EN1 , 0x00 },
107 { DA732X_REG_CLK_EN2 , 0x00 },
108 { DA732X_REG_CLK_EN3 , 0x00 },
109 { DA732X_REG_CLK_EN4 , 0x00 },
110 { DA732X_REG_CLK_EN5 , 0x00 },
111 { DA732X_REG_AIF_MCLK , 0x00 },
112 { DA732X_REG_AIFA1 , 0x02 },
113 { DA732X_REG_AIFA2 , 0x00 },
114 { DA732X_REG_AIFA3 , 0x08 },
115 { DA732X_REG_AIFB1 , 0x02 },
116 { DA732X_REG_AIFB2 , 0x00 },
117 { DA732X_REG_AIFB3 , 0x08 },
118 { DA732X_REG_PC_CTRL , 0xC0 },
119 { DA732X_REG_DATA_ROUTE , 0x00 },
120 { DA732X_REG_DSP_CTRL , 0x00 },
121 { DA732X_REG_CIF_CTRL2 , 0x00 },
122 { DA732X_REG_HANDSHAKE , 0x00 },
123 { DA732X_REG_SPARE1_OUT , 0x00 },
124 { DA732X_REG_SPARE2_OUT , 0x00 },
125 { DA732X_REG_SPARE1_IN , 0x00 },
126 { DA732X_REG_ADC1_PD , 0x00 },
127 { DA732X_REG_ADC1_HPF , 0x00 },
128 { DA732X_REG_ADC1_SEL , 0x00 },
129 { DA732X_REG_ADC1_EQ12 , 0x00 },
130 { DA732X_REG_ADC1_EQ34 , 0x00 },
131 { DA732X_REG_ADC1_EQ5 , 0x00 },
132 { DA732X_REG_ADC2_PD , 0x00 },
133 { DA732X_REG_ADC2_HPF , 0x00 },
134 { DA732X_REG_ADC2_SEL , 0x00 },
135 { DA732X_REG_ADC2_EQ12 , 0x00 },
136 { DA732X_REG_ADC2_EQ34 , 0x00 },
137 { DA732X_REG_ADC2_EQ5 , 0x00 },
138 { DA732X_REG_DAC1_HPF , 0x00 },
139 { DA732X_REG_DAC1_L_VOL , 0x00 },
140 { DA732X_REG_DAC1_R_VOL , 0x00 },
141 { DA732X_REG_DAC1_SEL , 0x00 },
142 { DA732X_REG_DAC1_SOFTMUTE , 0x00 },
143 { DA732X_REG_DAC1_EQ12 , 0x00 },
144 { DA732X_REG_DAC1_EQ34 , 0x00 },
145 { DA732X_REG_DAC1_EQ5 , 0x00 },
146 { DA732X_REG_DAC2_HPF , 0x00 },
147 { DA732X_REG_DAC2_L_VOL , 0x00 },
148 { DA732X_REG_DAC2_R_VOL , 0x00 },
149 { DA732X_REG_DAC2_SEL , 0x00 },
150 { DA732X_REG_DAC2_SOFTMUTE , 0x00 },
151 { DA732X_REG_DAC2_EQ12 , 0x00 },
152 { DA732X_REG_DAC2_EQ34 , 0x00 },
153 { DA732X_REG_DAC2_EQ5 , 0x00 },
154 { DA732X_REG_DAC3_HPF , 0x00 },
155 { DA732X_REG_DAC3_VOL , 0x00 },
156 { DA732X_REG_DAC3_SEL , 0x00 },
157 { DA732X_REG_DAC3_SOFTMUTE , 0x00 },
158 { DA732X_REG_DAC3_EQ12 , 0x00 },
159 { DA732X_REG_DAC3_EQ34 , 0x00 },
160 { DA732X_REG_DAC3_EQ5 , 0x00 },
161 { DA732X_REG_BIQ_BYP , 0x00 },
162 { DA732X_REG_DMA_CMD , 0x00 },
163 { DA732X_REG_DMA_ADDR0 , 0x00 },
164 { DA732X_REG_DMA_ADDR1 , 0x00 },
165 { DA732X_REG_DMA_DATA0 , 0x00 },
166 { DA732X_REG_DMA_DATA1 , 0x00 },
167 { DA732X_REG_DMA_DATA2 , 0x00 },
168 { DA732X_REG_DMA_DATA3 , 0x00 },
169 { DA732X_REG_UNLOCK , 0x00 },
170};
171
172static inline int da732x_get_input_div(struct snd_soc_codec *codec, int sysclk)
173{
174 int val;
175 int ret;
176
177 if (sysclk < DA732X_MCLK_10MHZ) {
178 val = DA732X_MCLK_RET_0_10MHZ;
179 ret = DA732X_MCLK_VAL_0_10MHZ;
180 } else if ((sysclk >= DA732X_MCLK_10MHZ) &&
181 (sysclk < DA732X_MCLK_20MHZ)) {
182 val = DA732X_MCLK_RET_10_20MHZ;
183 ret = DA732X_MCLK_VAL_10_20MHZ;
184 } else if ((sysclk >= DA732X_MCLK_20MHZ) &&
185 (sysclk < DA732X_MCLK_40MHZ)) {
186 val = DA732X_MCLK_RET_20_40MHZ;
187 ret = DA732X_MCLK_VAL_20_40MHZ;
188 } else if ((sysclk >= DA732X_MCLK_40MHZ) &&
189 (sysclk <= DA732X_MCLK_54MHZ)) {
190 val = DA732X_MCLK_RET_40_54MHZ;
191 ret = DA732X_MCLK_VAL_40_54MHZ;
192 } else {
193 return -EINVAL;
194 }
195
196 snd_soc_write(codec, DA732X_REG_PLL_CTRL, val);
197
198 return ret;
199}
200
201static void da732x_set_charge_pump(struct snd_soc_codec *codec, int state)
202{
203 switch (state) {
204 case DA732X_ENABLE_CP:
205 snd_soc_write(codec, DA732X_REG_CLK_EN2, DA732X_CP_CLK_EN);
206 snd_soc_write(codec, DA732X_REG_CP_HP2, DA732X_HP_CP_EN |
207 DA732X_HP_CP_REG | DA732X_HP_CP_PULSESKIP);
208 snd_soc_write(codec, DA732X_REG_CP_CTRL1, DA732X_CP_EN |
209 DA732X_CP_CTRL_CPVDD1);
210 snd_soc_write(codec, DA732X_REG_CP_CTRL2,
211 DA732X_CP_MANAGE_MAGNITUDE | DA732X_CP_BOOST);
212 snd_soc_write(codec, DA732X_REG_CP_CTRL3, DA732X_CP_1MHZ);
213 break;
214 case DA732X_DISABLE_CP:
215 snd_soc_write(codec, DA732X_REG_CLK_EN2, DA732X_CP_CLK_DIS);
216 snd_soc_write(codec, DA732X_REG_CP_HP2, DA732X_HP_CP_DIS);
217 snd_soc_write(codec, DA732X_REG_CP_CTRL1, DA723X_CP_DIS);
218 break;
219 default:
220 pr_err(KERN_ERR "Wrong charge pump state\n");
221 break;
222 }
223}
224
225static const DECLARE_TLV_DB_SCALE(mic_boost_tlv, DA732X_MIC_PRE_VOL_DB_MIN,
226 DA732X_MIC_PRE_VOL_DB_INC, 0);
227
228static const DECLARE_TLV_DB_SCALE(mic_pga_tlv, DA732X_MIC_VOL_DB_MIN,
229 DA732X_MIC_VOL_DB_INC, 0);
230
231static const DECLARE_TLV_DB_SCALE(aux_pga_tlv, DA732X_AUX_VOL_DB_MIN,
232 DA732X_AUX_VOL_DB_INC, 0);
233
234static const DECLARE_TLV_DB_SCALE(hp_pga_tlv, DA732X_HP_VOL_DB_MIN,
235 DA732X_AUX_VOL_DB_INC, 0);
236
237static const DECLARE_TLV_DB_SCALE(lin2_pga_tlv, DA732X_LIN2_VOL_DB_MIN,
238 DA732X_LIN2_VOL_DB_INC, 0);
239
240static const DECLARE_TLV_DB_SCALE(lin3_pga_tlv, DA732X_LIN3_VOL_DB_MIN,
241 DA732X_LIN3_VOL_DB_INC, 0);
242
243static const DECLARE_TLV_DB_SCALE(lin4_pga_tlv, DA732X_LIN4_VOL_DB_MIN,
244 DA732X_LIN4_VOL_DB_INC, 0);
245
246static const DECLARE_TLV_DB_SCALE(adc_pga_tlv, DA732X_ADC_VOL_DB_MIN,
247 DA732X_ADC_VOL_DB_INC, 0);
248
249static const DECLARE_TLV_DB_SCALE(dac_pga_tlv, DA732X_DAC_VOL_DB_MIN,
250 DA732X_DAC_VOL_DB_INC, 0);
251
252static const DECLARE_TLV_DB_SCALE(eq_band_pga_tlv, DA732X_EQ_BAND_VOL_DB_MIN,
253 DA732X_EQ_BAND_VOL_DB_INC, 0);
254
255static const DECLARE_TLV_DB_SCALE(eq_overall_tlv, DA732X_EQ_OVERALL_VOL_DB_MIN,
256 DA732X_EQ_OVERALL_VOL_DB_INC, 0);
257
258/* High Pass Filter */
259static const char *da732x_hpf_mode[] = {
260 "Disable", "Music", "Voice",
261};
262
263static const char *da732x_hpf_music[] = {
264 "1.8Hz", "3.75Hz", "7.5Hz", "15Hz",
265};
266
267static const char *da732x_hpf_voice[] = {
268 "2.5Hz", "25Hz", "50Hz", "100Hz",
269 "150Hz", "200Hz", "300Hz", "400Hz"
270};
271
272static const struct soc_enum da732x_dac1_hpf_mode_enum[] = {
273 SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT,
274 DA732X_HPF_MODE_MAX, da732x_hpf_mode)
275};
276
277static const struct soc_enum da732x_dac2_hpf_mode_enum[] = {
278 SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT,
279 DA732X_HPF_MODE_MAX, da732x_hpf_mode)
280};
281
282static const struct soc_enum da732x_dac3_hpf_mode_enum[] = {
283 SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT,
284 DA732X_HPF_MODE_MAX, da732x_hpf_mode)
285};
286
287static const struct soc_enum da732x_adc1_hpf_mode_enum[] = {
288 SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT,
289 DA732X_HPF_MODE_MAX, da732x_hpf_mode)
290};
291
292static const struct soc_enum da732x_adc2_hpf_mode_enum[] = {
293 SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT,
294 DA732X_HPF_MODE_MAX, da732x_hpf_mode)
295};
296
297static const struct soc_enum da732x_dac1_hp_filter_enum[] = {
298 SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT,
299 DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
300};
301
302static const struct soc_enum da732x_dac2_hp_filter_enum[] = {
303 SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT,
304 DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
305};
306
307static const struct soc_enum da732x_dac3_hp_filter_enum[] = {
308 SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT,
309 DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
310};
311
312static const struct soc_enum da732x_adc1_hp_filter_enum[] = {
313 SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT,
314 DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
315};
316
317static const struct soc_enum da732x_adc2_hp_filter_enum[] = {
318 SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT,
319 DA732X_HPF_MUSIC_MAX, da732x_hpf_music)
320};
321
322static const struct soc_enum da732x_dac1_voice_filter_enum[] = {
323 SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT,
324 DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
325};
326
327static const struct soc_enum da732x_dac2_voice_filter_enum[] = {
328 SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT,
329 DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
330};
331
332static const struct soc_enum da732x_dac3_voice_filter_enum[] = {
333 SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT,
334 DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
335};
336
337static const struct soc_enum da732x_adc1_voice_filter_enum[] = {
338 SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT,
339 DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
340};
341
342static const struct soc_enum da732x_adc2_voice_filter_enum[] = {
343 SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT,
344 DA732X_HPF_VOICE_MAX, da732x_hpf_voice)
345};
346
347
348static int da732x_hpf_set(struct snd_kcontrol *kcontrol,
349 struct snd_ctl_elem_value *ucontrol)
350{
351 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
352 struct soc_enum *enum_ctrl = (struct soc_enum *)kcontrol->private_value;
353 unsigned int reg = enum_ctrl->reg;
354 unsigned int sel = ucontrol->value.integer.value[0];
355 unsigned int bits;
356
357 switch (sel) {
358 case DA732X_HPF_DISABLED:
359 bits = DA732X_HPF_DIS;
360 break;
361 case DA732X_HPF_VOICE:
362 bits = DA732X_HPF_VOICE_EN;
363 break;
364 case DA732X_HPF_MUSIC:
365 bits = DA732X_HPF_MUSIC_EN;
366 break;
367 default:
368 return -EINVAL;
369 }
370
371 snd_soc_update_bits(codec, reg, DA732X_HPF_MASK, bits);
372
373 return 0;
374}
375
376static int da732x_hpf_get(struct snd_kcontrol *kcontrol,
377 struct snd_ctl_elem_value *ucontrol)
378{
379 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
380 struct soc_enum *enum_ctrl = (struct soc_enum *)kcontrol->private_value;
381 unsigned int reg = enum_ctrl->reg;
382 int val;
383
384 val = snd_soc_read(codec, reg) & DA732X_HPF_MASK;
385
386 switch (val) {
387 case DA732X_HPF_VOICE_EN:
388 ucontrol->value.integer.value[0] = DA732X_HPF_VOICE;
389 break;
390 case DA732X_HPF_MUSIC_EN:
391 ucontrol->value.integer.value[0] = DA732X_HPF_MUSIC;
392 break;
393 default:
394 ucontrol->value.integer.value[0] = DA732X_HPF_DISABLED;
395 break;
396 }
397
398 return 0;
399}
400
401static const struct snd_kcontrol_new da732x_snd_controls[] = {
402 /* Input PGAs */
403 SOC_SINGLE_RANGE_TLV("MIC1 Boost Volume", DA732X_REG_MIC1_PRE,
404 DA732X_MICBOOST_SHIFT, DA732X_MICBOOST_MIN,
405 DA732X_MICBOOST_MAX, 0, mic_boost_tlv),
406 SOC_SINGLE_RANGE_TLV("MIC2 Boost Volume", DA732X_REG_MIC2_PRE,
407 DA732X_MICBOOST_SHIFT, DA732X_MICBOOST_MIN,
408 DA732X_MICBOOST_MAX, 0, mic_boost_tlv),
409 SOC_SINGLE_RANGE_TLV("MIC3 Boost Volume", DA732X_REG_MIC3_PRE,
410 DA732X_MICBOOST_SHIFT, DA732X_MICBOOST_MIN,
411 DA732X_MICBOOST_MAX, 0, mic_boost_tlv),
412
413 /* MICs */
414 SOC_SINGLE("MIC1 Switch", DA732X_REG_MIC1, DA732X_MIC_MUTE_SHIFT,
415 DA732X_SWITCH_MAX, DA732X_INVERT),
416 SOC_SINGLE_RANGE_TLV("MIC1 Volume", DA732X_REG_MIC1,
417 DA732X_MIC_VOL_SHIFT, DA732X_MIC_VOL_VAL_MIN,
418 DA732X_MIC_VOL_VAL_MAX, 0, mic_pga_tlv),
419 SOC_SINGLE("MIC2 Switch", DA732X_REG_MIC2, DA732X_MIC_MUTE_SHIFT,
420 DA732X_SWITCH_MAX, DA732X_INVERT),
421 SOC_SINGLE_RANGE_TLV("MIC2 Volume", DA732X_REG_MIC2,
422 DA732X_MIC_VOL_SHIFT, DA732X_MIC_VOL_VAL_MIN,
423 DA732X_MIC_VOL_VAL_MAX, 0, mic_pga_tlv),
424 SOC_SINGLE("MIC3 Switch", DA732X_REG_MIC3, DA732X_MIC_MUTE_SHIFT,
425 DA732X_SWITCH_MAX, DA732X_INVERT),
426 SOC_SINGLE_RANGE_TLV("MIC3 Volume", DA732X_REG_MIC3,
427 DA732X_MIC_VOL_SHIFT, DA732X_MIC_VOL_VAL_MIN,
428 DA732X_MIC_VOL_VAL_MAX, 0, mic_pga_tlv),
429
430 /* AUXs */
431 SOC_SINGLE("AUX1L Switch", DA732X_REG_AUX1L, DA732X_AUX_MUTE_SHIFT,
432 DA732X_SWITCH_MAX, DA732X_INVERT),
433 SOC_SINGLE_TLV("AUX1L Volume", DA732X_REG_AUX1L,
434 DA732X_AUX_VOL_SHIFT, DA732X_AUX_VOL_VAL_MAX,
435 DA732X_NO_INVERT, aux_pga_tlv),
436 SOC_SINGLE("AUX1R Switch", DA732X_REG_AUX1R, DA732X_AUX_MUTE_SHIFT,
437 DA732X_SWITCH_MAX, DA732X_INVERT),
438 SOC_SINGLE_TLV("AUX1R Volume", DA732X_REG_AUX1R,
439 DA732X_AUX_VOL_SHIFT, DA732X_AUX_VOL_VAL_MAX,
440 DA732X_NO_INVERT, aux_pga_tlv),
441
442 /* ADCs */
443 SOC_DOUBLE_TLV("ADC1 Volume", DA732X_REG_ADC1_SEL,
444 DA732X_ADCL_VOL_SHIFT, DA732X_ADCR_VOL_SHIFT,
445 DA732X_ADC_VOL_VAL_MAX, DA732X_INVERT, adc_pga_tlv),
446
447 SOC_DOUBLE_TLV("ADC2 Volume", DA732X_REG_ADC2_SEL,
448 DA732X_ADCL_VOL_SHIFT, DA732X_ADCR_VOL_SHIFT,
449 DA732X_ADC_VOL_VAL_MAX, DA732X_INVERT, adc_pga_tlv),
450
451 /* DACs */
452 SOC_DOUBLE("Digital Playback DAC12 Switch", DA732X_REG_DAC1_SEL,
453 DA732X_DACL_MUTE_SHIFT, DA732X_DACR_MUTE_SHIFT,
454 DA732X_SWITCH_MAX, DA732X_INVERT),
455 SOC_DOUBLE_R_TLV("Digital Playback DAC12 Volume", DA732X_REG_DAC1_L_VOL,
456 DA732X_REG_DAC1_R_VOL, DA732X_DAC_VOL_SHIFT,
457 DA732X_DAC_VOL_VAL_MAX, DA732X_INVERT, dac_pga_tlv),
458 SOC_SINGLE("Digital Playback DAC3 Switch", DA732X_REG_DAC2_SEL,
459 DA732X_DACL_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT),
460 SOC_SINGLE_TLV("Digital Playback DAC3 Volume", DA732X_REG_DAC2_L_VOL,
461 DA732X_DAC_VOL_SHIFT, DA732X_DAC_VOL_VAL_MAX,
462 DA732X_INVERT, dac_pga_tlv),
463 SOC_SINGLE("Digital Playback DAC4 Switch", DA732X_REG_DAC2_SEL,
464 DA732X_DACR_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT),
465 SOC_SINGLE_TLV("Digital Playback DAC4 Volume", DA732X_REG_DAC2_R_VOL,
466 DA732X_DAC_VOL_SHIFT, DA732X_DAC_VOL_VAL_MAX,
467 DA732X_INVERT, dac_pga_tlv),
468 SOC_SINGLE("Digital Playback DAC5 Switch", DA732X_REG_DAC3_SEL,
469 DA732X_DACL_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT),
470 SOC_SINGLE_TLV("Digital Playback DAC5 Volume", DA732X_REG_DAC3_VOL,
471 DA732X_DAC_VOL_SHIFT, DA732X_DAC_VOL_VAL_MAX,
472 DA732X_INVERT, dac_pga_tlv),
473
474 /* High Pass Filters */
475 SOC_ENUM_EXT("DAC1 High Pass Filter Mode",
476 da732x_dac1_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set),
477 SOC_ENUM("DAC1 High Pass Filter", da732x_dac1_hp_filter_enum),
478 SOC_ENUM("DAC1 Voice Filter", da732x_dac1_voice_filter_enum),
479
480 SOC_ENUM_EXT("DAC2 High Pass Filter Mode",
481 da732x_dac2_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set),
482 SOC_ENUM("DAC2 High Pass Filter", da732x_dac2_hp_filter_enum),
483 SOC_ENUM("DAC2 Voice Filter", da732x_dac2_voice_filter_enum),
484
485 SOC_ENUM_EXT("DAC3 High Pass Filter Mode",
486 da732x_dac3_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set),
487 SOC_ENUM("DAC3 High Pass Filter", da732x_dac3_hp_filter_enum),
488 SOC_ENUM("DAC3 Filter Mode", da732x_dac3_voice_filter_enum),
489
490 SOC_ENUM_EXT("ADC1 High Pass Filter Mode",
491 da732x_adc1_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set),
492 SOC_ENUM("ADC1 High Pass Filter", da732x_adc1_hp_filter_enum),
493 SOC_ENUM("ADC1 Voice Filter", da732x_adc1_voice_filter_enum),
494
495 SOC_ENUM_EXT("ADC2 High Pass Filter Mode",
496 da732x_adc2_hpf_mode_enum, da732x_hpf_get, da732x_hpf_set),
497 SOC_ENUM("ADC2 High Pass Filter", da732x_adc2_hp_filter_enum),
498 SOC_ENUM("ADC2 Voice Filter", da732x_adc2_voice_filter_enum),
499
500 /* Equalizers */
501 SOC_SINGLE("ADC1 EQ Switch", DA732X_REG_ADC1_EQ5,
502 DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT),
503 SOC_SINGLE_TLV("ADC1 EQ Band 1 Volume", DA732X_REG_ADC1_EQ12,
504 DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX,
505 DA732X_INVERT, eq_band_pga_tlv),
506 SOC_SINGLE_TLV("ADC1 EQ Band 2 Volume", DA732X_REG_ADC1_EQ12,
507 DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX,
508 DA732X_INVERT, eq_band_pga_tlv),
509 SOC_SINGLE_TLV("ADC1 EQ Band 3 Volume", DA732X_REG_ADC1_EQ34,
510 DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX,
511 DA732X_INVERT, eq_band_pga_tlv),
512 SOC_SINGLE_TLV("ADC1 EQ Band 4 Volume", DA732X_REG_ADC1_EQ34,
513 DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX,
514 DA732X_INVERT, eq_band_pga_tlv),
515 SOC_SINGLE_TLV("ADC1 EQ Band 5 Volume", DA732X_REG_ADC1_EQ5,
516 DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX,
517 DA732X_INVERT, eq_band_pga_tlv),
518 SOC_SINGLE_TLV("ADC1 EQ Overall Volume", DA732X_REG_ADC1_EQ5,
519 DA732X_EQ_OVERALL_SHIFT, DA732X_EQ_OVERALL_VOL_VAL_MAX,
520 DA732X_INVERT, eq_overall_tlv),
521
522 SOC_SINGLE("ADC2 EQ Switch", DA732X_REG_ADC2_EQ5,
523 DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT),
524 SOC_SINGLE_TLV("ADC2 EQ Band 1 Volume", DA732X_REG_ADC2_EQ12,
525 DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX,
526 DA732X_INVERT, eq_band_pga_tlv),
527 SOC_SINGLE_TLV("ADC2 EQ Band 2 Volume", DA732X_REG_ADC2_EQ12,
528 DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX,
529 DA732X_INVERT, eq_band_pga_tlv),
530 SOC_SINGLE_TLV("ADC2 EQ Band 3 Volume", DA732X_REG_ADC2_EQ34,
531 DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX,
532 DA732X_INVERT, eq_band_pga_tlv),
533 SOC_SINGLE_TLV("ACD2 EQ Band 4 Volume", DA732X_REG_ADC2_EQ34,
534 DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX,
535 DA732X_INVERT, eq_band_pga_tlv),
536 SOC_SINGLE_TLV("ACD2 EQ Band 5 Volume", DA732X_REG_ADC2_EQ5,
537 DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX,
538 DA732X_INVERT, eq_band_pga_tlv),
539 SOC_SINGLE_TLV("ADC2 EQ Overall Volume", DA732X_REG_ADC1_EQ5,
540 DA732X_EQ_OVERALL_SHIFT, DA732X_EQ_OVERALL_VOL_VAL_MAX,
541 DA732X_INVERT, eq_overall_tlv),
542
543 SOC_SINGLE("DAC1 EQ Switch", DA732X_REG_DAC1_EQ5,
544 DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT),
545 SOC_SINGLE_TLV("DAC1 EQ Band 1 Volume", DA732X_REG_DAC1_EQ12,
546 DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX,
547 DA732X_INVERT, eq_band_pga_tlv),
548 SOC_SINGLE_TLV("DAC1 EQ Band 2 Volume", DA732X_REG_DAC1_EQ12,
549 DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX,
550 DA732X_INVERT, eq_band_pga_tlv),
551 SOC_SINGLE_TLV("DAC1 EQ Band 3 Volume", DA732X_REG_DAC1_EQ34,
552 DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX,
553 DA732X_INVERT, eq_band_pga_tlv),
554 SOC_SINGLE_TLV("DAC1 EQ Band 4 Volume", DA732X_REG_DAC1_EQ34,
555 DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX,
556 DA732X_INVERT, eq_band_pga_tlv),
557 SOC_SINGLE_TLV("DAC1 EQ Band 5 Volume", DA732X_REG_DAC1_EQ5,
558 DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX,
559 DA732X_INVERT, eq_band_pga_tlv),
560
561 SOC_SINGLE("DAC2 EQ Switch", DA732X_REG_DAC2_EQ5,
562 DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT),
563 SOC_SINGLE_TLV("DAC2 EQ Band 1 Volume", DA732X_REG_DAC2_EQ12,
564 DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX,
565 DA732X_INVERT, eq_band_pga_tlv),
566 SOC_SINGLE_TLV("DAC2 EQ Band 2 Volume", DA732X_REG_DAC2_EQ12,
567 DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX,
568 DA732X_INVERT, eq_band_pga_tlv),
569 SOC_SINGLE_TLV("DAC2 EQ Band 3 Volume", DA732X_REG_DAC2_EQ34,
570 DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX,
571 DA732X_INVERT, eq_band_pga_tlv),
572 SOC_SINGLE_TLV("DAC2 EQ Band 4 Volume", DA732X_REG_DAC2_EQ34,
573 DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX,
574 DA732X_INVERT, eq_band_pga_tlv),
575 SOC_SINGLE_TLV("DAC2 EQ Band 5 Volume", DA732X_REG_DAC2_EQ5,
576 DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX,
577 DA732X_INVERT, eq_band_pga_tlv),
578
579 SOC_SINGLE("DAC3 EQ Switch", DA732X_REG_DAC3_EQ5,
580 DA732X_EQ_EN_SHIFT, DA732X_EQ_EN_MAX, DA732X_NO_INVERT),
581 SOC_SINGLE_TLV("DAC3 EQ Band 1 Volume", DA732X_REG_DAC3_EQ12,
582 DA732X_EQ_BAND1_SHIFT, DA732X_EQ_VOL_VAL_MAX,
583 DA732X_INVERT, eq_band_pga_tlv),
584 SOC_SINGLE_TLV("DAC3 EQ Band 2 Volume", DA732X_REG_DAC3_EQ12,
585 DA732X_EQ_BAND2_SHIFT, DA732X_EQ_VOL_VAL_MAX,
586 DA732X_INVERT, eq_band_pga_tlv),
587 SOC_SINGLE_TLV("DAC3 EQ Band 3 Volume", DA732X_REG_DAC3_EQ34,
588 DA732X_EQ_BAND3_SHIFT, DA732X_EQ_VOL_VAL_MAX,
589 DA732X_INVERT, eq_band_pga_tlv),
590 SOC_SINGLE_TLV("DAC3 EQ Band 4 Volume", DA732X_REG_DAC3_EQ34,
591 DA732X_EQ_BAND4_SHIFT, DA732X_EQ_VOL_VAL_MAX,
592 DA732X_INVERT, eq_band_pga_tlv),
593 SOC_SINGLE_TLV("DAC3 EQ Band 5 Volume", DA732X_REG_DAC3_EQ5,
594 DA732X_EQ_BAND5_SHIFT, DA732X_EQ_VOL_VAL_MAX,
595 DA732X_INVERT, eq_band_pga_tlv),
596
597 /* Lineout 2 Reciever*/
598 SOC_SINGLE("Lineout 2 Switch", DA732X_REG_LIN2, DA732X_LOUT_MUTE_SHIFT,
599 DA732X_SWITCH_MAX, DA732X_INVERT),
600 SOC_SINGLE_TLV("Lineout 2 Volume", DA732X_REG_LIN2,
601 DA732X_LOUT_VOL_SHIFT, DA732X_LOUT_VOL_VAL_MAX,
602 DA732X_NO_INVERT, lin2_pga_tlv),
603
604 /* Lineout 3 SPEAKER*/
605 SOC_SINGLE("Lineout 3 Switch", DA732X_REG_LIN3, DA732X_LOUT_MUTE_SHIFT,
606 DA732X_SWITCH_MAX, DA732X_INVERT),
607 SOC_SINGLE_TLV("Lineout 3 Volume", DA732X_REG_LIN3,
608 DA732X_LOUT_VOL_SHIFT, DA732X_LOUT_VOL_VAL_MAX,
609 DA732X_NO_INVERT, lin3_pga_tlv),
610
611 /* Lineout 4 */
612 SOC_SINGLE("Lineout 4 Switch", DA732X_REG_LIN4, DA732X_LOUT_MUTE_SHIFT,
613 DA732X_SWITCH_MAX, DA732X_INVERT),
614 SOC_SINGLE_TLV("Lineout 4 Volume", DA732X_REG_LIN4,
615 DA732X_LOUT_VOL_SHIFT, DA732X_LOUT_VOL_VAL_MAX,
616 DA732X_NO_INVERT, lin4_pga_tlv),
617
618 /* Headphones */
619 SOC_DOUBLE_R("Headphone Switch", DA732X_REG_HPR, DA732X_REG_HPL,
620 DA732X_HP_MUTE_SHIFT, DA732X_SWITCH_MAX, DA732X_INVERT),
621 SOC_DOUBLE_R_TLV("Headphone Volume", DA732X_REG_HPL_VOL,
622 DA732X_REG_HPR_VOL, DA732X_HP_VOL_SHIFT,
623 DA732X_HP_VOL_VAL_MAX, DA732X_NO_INVERT, hp_pga_tlv),
624};
625
626static int da732x_adc_event(struct snd_soc_dapm_widget *w,
627 struct snd_kcontrol *kcontrol, int event)
628{
629 struct snd_soc_codec *codec = w->codec;
630
631 switch (event) {
632 case SND_SOC_DAPM_POST_PMU:
633 switch (w->reg) {
634 case DA732X_REG_ADC1_PD:
635 snd_soc_update_bits(codec, DA732X_REG_CLK_EN3,
636 DA732X_ADCA_BB_CLK_EN,
637 DA732X_ADCA_BB_CLK_EN);
638 break;
639 case DA732X_REG_ADC2_PD:
640 snd_soc_update_bits(codec, DA732X_REG_CLK_EN3,
641 DA732X_ADCC_BB_CLK_EN,
642 DA732X_ADCC_BB_CLK_EN);
643 break;
644 default:
645 return -EINVAL;
646 }
647
648 snd_soc_update_bits(codec, w->reg, DA732X_ADC_RST_MASK,
649 DA732X_ADC_SET_ACT);
650 snd_soc_update_bits(codec, w->reg, DA732X_ADC_PD_MASK,
651 DA732X_ADC_ON);
652 break;
653 case SND_SOC_DAPM_POST_PMD:
654 snd_soc_update_bits(codec, w->reg, DA732X_ADC_PD_MASK,
655 DA732X_ADC_OFF);
656 snd_soc_update_bits(codec, w->reg, DA732X_ADC_RST_MASK,
657 DA732X_ADC_SET_RST);
658
659 switch (w->reg) {
660 case DA732X_REG_ADC1_PD:
661 snd_soc_update_bits(codec, DA732X_REG_CLK_EN3,
662 DA732X_ADCA_BB_CLK_EN, 0);
663 break;
664 case DA732X_REG_ADC2_PD:
665 snd_soc_update_bits(codec, DA732X_REG_CLK_EN3,
666 DA732X_ADCC_BB_CLK_EN, 0);
667 break;
668 default:
669 return -EINVAL;
670 }
671
672 break;
673 default:
674 return -EINVAL;
675 }
676
677 return 0;
678}
679
680static int da732x_out_pga_event(struct snd_soc_dapm_widget *w,
681 struct snd_kcontrol *kcontrol, int event)
682{
683 struct snd_soc_codec *codec = w->codec;
684
685 switch (event) {
686 case SND_SOC_DAPM_POST_PMU:
687 snd_soc_update_bits(codec, w->reg,
688 (1 << w->shift) | DA732X_OUT_HIZ_EN,
689 (1 << w->shift) | DA732X_OUT_HIZ_EN);
690 break;
691 case SND_SOC_DAPM_POST_PMD:
692 snd_soc_update_bits(codec, w->reg,
693 (1 << w->shift) | DA732X_OUT_HIZ_EN,
694 (1 << w->shift) | DA732X_OUT_HIZ_DIS);
695 break;
696 default:
697 return -EINVAL;
698 }
699
700 return 0;
701}
702
703static const char *adcl_text[] = {
704 "AUX1L", "MIC1"
705};
706
707static const char *adcr_text[] = {
708 "AUX1R", "MIC2", "MIC3"
709};
710
711static const char *enable_text[] = {
712 "Disabled",
713 "Enabled"
714};
715
716/* ADC1LMUX */
717static const struct soc_enum adc1l_enum =
718 SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT,
719 DA732X_ADCL_MUX_MAX, adcl_text);
720static const struct snd_kcontrol_new adc1l_mux =
721 SOC_DAPM_ENUM("ADC Route", adc1l_enum);
722
723/* ADC1RMUX */
724static const struct soc_enum adc1r_enum =
725 SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT,
726 DA732X_ADCR_MUX_MAX, adcr_text);
727static const struct snd_kcontrol_new adc1r_mux =
728 SOC_DAPM_ENUM("ADC Route", adc1r_enum);
729
730/* ADC2LMUX */
731static const struct soc_enum adc2l_enum =
732 SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT,
733 DA732X_ADCL_MUX_MAX, adcl_text);
734static const struct snd_kcontrol_new adc2l_mux =
735 SOC_DAPM_ENUM("ADC Route", adc2l_enum);
736
737/* ADC2RMUX */
738static const struct soc_enum adc2r_enum =
739 SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT,
740 DA732X_ADCR_MUX_MAX, adcr_text);
741
742static const struct snd_kcontrol_new adc2r_mux =
743 SOC_DAPM_ENUM("ADC Route", adc2r_enum);
744
745static const struct soc_enum da732x_hp_left_output =
746 SOC_ENUM_SINGLE(DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT,
747 DA732X_DAC_EN_MAX, enable_text);
748
749static const struct snd_kcontrol_new hpl_mux =
750 SOC_DAPM_ENUM("HPL Switch", da732x_hp_left_output);
751
752static const struct soc_enum da732x_hp_right_output =
753 SOC_ENUM_SINGLE(DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT,
754 DA732X_DAC_EN_MAX, enable_text);
755
756static const struct snd_kcontrol_new hpr_mux =
757 SOC_DAPM_ENUM("HPR Switch", da732x_hp_right_output);
758
759static const struct soc_enum da732x_speaker_output =
760 SOC_ENUM_SINGLE(DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT,
761 DA732X_DAC_EN_MAX, enable_text);
762
763static const struct snd_kcontrol_new spk_mux =
764 SOC_DAPM_ENUM("SPK Switch", da732x_speaker_output);
765
766static const struct soc_enum da732x_lout4_output =
767 SOC_ENUM_SINGLE(DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT,
768 DA732X_DAC_EN_MAX, enable_text);
769
770static const struct snd_kcontrol_new lout4_mux =
771 SOC_DAPM_ENUM("LOUT4 Switch", da732x_lout4_output);
772
773static const struct soc_enum da732x_lout2_output =
774 SOC_ENUM_SINGLE(DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT,
775 DA732X_DAC_EN_MAX, enable_text);
776
777static const struct snd_kcontrol_new lout2_mux =
778 SOC_DAPM_ENUM("LOUT2 Switch", da732x_lout2_output);
779
780static const struct snd_soc_dapm_widget da732x_dapm_widgets[] = {
781 /* Supplies */
782 SND_SOC_DAPM_SUPPLY("ADC1 Supply", DA732X_REG_ADC1_PD, 0,
783 DA732X_NO_INVERT, da732x_adc_event,
784 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
785 SND_SOC_DAPM_SUPPLY("ADC2 Supply", DA732X_REG_ADC2_PD, 0,
786 DA732X_NO_INVERT, da732x_adc_event,
787 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
788 SND_SOC_DAPM_SUPPLY("DAC1 CLK", DA732X_REG_CLK_EN4,
789 DA732X_DACA_BB_CLK_SHIFT, DA732X_NO_INVERT,
790 NULL, 0),
791 SND_SOC_DAPM_SUPPLY("DAC2 CLK", DA732X_REG_CLK_EN4,
792 DA732X_DACC_BB_CLK_SHIFT, DA732X_NO_INVERT,
793 NULL, 0),
794 SND_SOC_DAPM_SUPPLY("DAC3 CLK", DA732X_REG_CLK_EN5,
795 DA732X_DACE_BB_CLK_SHIFT, DA732X_NO_INVERT,
796 NULL, 0),
797
798 /* Micbias */
799 SND_SOC_DAPM_SUPPLY("MICBIAS1", DA732X_REG_MICBIAS1,
800 DA732X_MICBIAS_EN_SHIFT,
801 DA732X_NO_INVERT, NULL, 0),
802 SND_SOC_DAPM_SUPPLY("MICBIAS2", DA732X_REG_MICBIAS2,
803 DA732X_MICBIAS_EN_SHIFT,
804 DA732X_NO_INVERT, NULL, 0),
805
806 /* Inputs */
807 SND_SOC_DAPM_INPUT("MIC1"),
808 SND_SOC_DAPM_INPUT("MIC2"),
809 SND_SOC_DAPM_INPUT("MIC3"),
810 SND_SOC_DAPM_INPUT("AUX1L"),
811 SND_SOC_DAPM_INPUT("AUX1R"),
812
813 /* Outputs */
814 SND_SOC_DAPM_OUTPUT("HPL"),
815 SND_SOC_DAPM_OUTPUT("HPR"),
816 SND_SOC_DAPM_OUTPUT("LOUTL"),
817 SND_SOC_DAPM_OUTPUT("LOUTR"),
818 SND_SOC_DAPM_OUTPUT("ClassD"),
819
820 /* ADCs */
821 SND_SOC_DAPM_ADC("ADC1L", NULL, DA732X_REG_ADC1_SEL,
822 DA732X_ADCL_EN_SHIFT, DA732X_NO_INVERT),
823 SND_SOC_DAPM_ADC("ADC1R", NULL, DA732X_REG_ADC1_SEL,
824 DA732X_ADCR_EN_SHIFT, DA732X_NO_INVERT),
825 SND_SOC_DAPM_ADC("ADC2L", NULL, DA732X_REG_ADC2_SEL,
826 DA732X_ADCL_EN_SHIFT, DA732X_NO_INVERT),
827 SND_SOC_DAPM_ADC("ADC2R", NULL, DA732X_REG_ADC2_SEL,
828 DA732X_ADCR_EN_SHIFT, DA732X_NO_INVERT),
829
830 /* DACs */
831 SND_SOC_DAPM_DAC("DAC1L", NULL, DA732X_REG_DAC1_SEL,
832 DA732X_DACL_EN_SHIFT, DA732X_NO_INVERT),
833 SND_SOC_DAPM_DAC("DAC1R", NULL, DA732X_REG_DAC1_SEL,
834 DA732X_DACR_EN_SHIFT, DA732X_NO_INVERT),
835 SND_SOC_DAPM_DAC("DAC2L", NULL, DA732X_REG_DAC2_SEL,
836 DA732X_DACL_EN_SHIFT, DA732X_NO_INVERT),
837 SND_SOC_DAPM_DAC("DAC2R", NULL, DA732X_REG_DAC2_SEL,
838 DA732X_DACR_EN_SHIFT, DA732X_NO_INVERT),
839 SND_SOC_DAPM_DAC("DAC3", NULL, DA732X_REG_DAC3_SEL,
840 DA732X_DACL_EN_SHIFT, DA732X_NO_INVERT),
841
842 /* Input Pgas */
843 SND_SOC_DAPM_PGA("MIC1 PGA", DA732X_REG_MIC1, DA732X_MIC_EN_SHIFT,
844 0, NULL, 0),
845 SND_SOC_DAPM_PGA("MIC2 PGA", DA732X_REG_MIC2, DA732X_MIC_EN_SHIFT,
846 0, NULL, 0),
847 SND_SOC_DAPM_PGA("MIC3 PGA", DA732X_REG_MIC3, DA732X_MIC_EN_SHIFT,
848 0, NULL, 0),
849 SND_SOC_DAPM_PGA("AUX1L PGA", DA732X_REG_AUX1L, DA732X_AUX_EN_SHIFT,
850 0, NULL, 0),
851 SND_SOC_DAPM_PGA("AUX1R PGA", DA732X_REG_AUX1R, DA732X_AUX_EN_SHIFT,
852 0, NULL, 0),
853
854 SND_SOC_DAPM_PGA_E("HP Left", DA732X_REG_HPL, DA732X_HP_OUT_EN_SHIFT,
855 0, NULL, 0, da732x_out_pga_event,
856 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
857 SND_SOC_DAPM_PGA_E("HP Right", DA732X_REG_HPR, DA732X_HP_OUT_EN_SHIFT,
858 0, NULL, 0, da732x_out_pga_event,
859 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
860 SND_SOC_DAPM_PGA_E("LIN2", DA732X_REG_LIN2, DA732X_LIN_OUT_EN_SHIFT,
861 0, NULL, 0, da732x_out_pga_event,
862 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
863 SND_SOC_DAPM_PGA_E("LIN3", DA732X_REG_LIN3, DA732X_LIN_OUT_EN_SHIFT,
864 0, NULL, 0, da732x_out_pga_event,
865 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
866 SND_SOC_DAPM_PGA_E("LIN4", DA732X_REG_LIN4, DA732X_LIN_OUT_EN_SHIFT,
867 0, NULL, 0, da732x_out_pga_event,
868 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
869
870 /* MUXs */
871 SND_SOC_DAPM_MUX("ADC1 Left MUX", SND_SOC_NOPM, 0, 0, &adc1l_mux),
872 SND_SOC_DAPM_MUX("ADC1 Right MUX", SND_SOC_NOPM, 0, 0, &adc1r_mux),
873 SND_SOC_DAPM_MUX("ADC2 Left MUX", SND_SOC_NOPM, 0, 0, &adc2l_mux),
874 SND_SOC_DAPM_MUX("ADC2 Right MUX", SND_SOC_NOPM, 0, 0, &adc2r_mux),
875
876 SND_SOC_DAPM_MUX("HP Left MUX", SND_SOC_NOPM, 0, 0, &hpl_mux),
877 SND_SOC_DAPM_MUX("HP Right MUX", SND_SOC_NOPM, 0, 0, &hpr_mux),
878 SND_SOC_DAPM_MUX("Speaker MUX", SND_SOC_NOPM, 0, 0, &spk_mux),
879 SND_SOC_DAPM_MUX("LOUT2 MUX", SND_SOC_NOPM, 0, 0, &lout2_mux),
880 SND_SOC_DAPM_MUX("LOUT4 MUX", SND_SOC_NOPM, 0, 0, &lout4_mux),
881
882 /* AIF interfaces */
883 SND_SOC_DAPM_AIF_OUT("AIFA Output", "AIFA Capture", 0, DA732X_REG_AIFA3,
884 DA732X_AIF_EN_SHIFT, 0),
885 SND_SOC_DAPM_AIF_IN("AIFA Input", "AIFA Playback", 0, DA732X_REG_AIFA3,
886 DA732X_AIF_EN_SHIFT, 0),
887
888 SND_SOC_DAPM_AIF_OUT("AIFB Output", "AIFB Capture", 0, DA732X_REG_AIFB3,
889 DA732X_AIF_EN_SHIFT, 0),
890 SND_SOC_DAPM_AIF_IN("AIFB Input", "AIFB Playback", 0, DA732X_REG_AIFB3,
891 DA732X_AIF_EN_SHIFT, 0),
892};
893
894static const struct snd_soc_dapm_route da732x_dapm_routes[] = {
895 /* Inputs */
896 {"AUX1L PGA", "NULL", "AUX1L"},
897 {"AUX1R PGA", "NULL", "AUX1R"},
898 {"MIC1 PGA", NULL, "MIC1"},
899 {"MIC2 PGA", "NULL", "MIC2"},
900 {"MIC3 PGA", "NULL", "MIC3"},
901
902 /* Capture Path */
903 {"ADC1 Left MUX", "MIC1", "MIC1 PGA"},
904 {"ADC1 Left MUX", "AUX1L", "AUX1L PGA"},
905
906 {"ADC1 Right MUX", "AUX1R", "AUX1R PGA"},
907 {"ADC1 Right MUX", "MIC2", "MIC2 PGA"},
908 {"ADC1 Right MUX", "MIC3", "MIC3 PGA"},
909
910 {"ADC2 Left MUX", "AUX1L", "AUX1L PGA"},
911 {"ADC2 Left MUX", "MIC1", "MIC1 PGA"},
912
913 {"ADC2 Right MUX", "AUX1R", "AUX1R PGA"},
914 {"ADC2 Right MUX", "MIC2", "MIC2 PGA"},
915 {"ADC2 Right MUX", "MIC3", "MIC3 PGA"},
916
917 {"ADC1L", NULL, "ADC1 Supply"},
918 {"ADC1R", NULL, "ADC1 Supply"},
919 {"ADC2L", NULL, "ADC2 Supply"},
920 {"ADC2R", NULL, "ADC2 Supply"},
921
922 {"ADC1L", NULL, "ADC1 Left MUX"},
923 {"ADC1R", NULL, "ADC1 Right MUX"},
924 {"ADC2L", NULL, "ADC2 Left MUX"},
925 {"ADC2R", NULL, "ADC2 Right MUX"},
926
927 {"AIFA Output", NULL, "ADC1L"},
928 {"AIFA Output", NULL, "ADC1R"},
929 {"AIFB Output", NULL, "ADC2L"},
930 {"AIFB Output", NULL, "ADC2R"},
931
932 {"HP Left MUX", "Enabled", "AIFA Input"},
933 {"HP Right MUX", "Enabled", "AIFA Input"},
934 {"Speaker MUX", "Enabled", "AIFB Input"},
935 {"LOUT2 MUX", "Enabled", "AIFB Input"},
936 {"LOUT4 MUX", "Enabled", "AIFB Input"},
937
938 {"DAC1L", NULL, "DAC1 CLK"},
939 {"DAC1R", NULL, "DAC1 CLK"},
940 {"DAC2L", NULL, "DAC2 CLK"},
941 {"DAC2R", NULL, "DAC2 CLK"},
942 {"DAC3", NULL, "DAC3 CLK"},
943
944 {"DAC1L", NULL, "HP Left MUX"},
945 {"DAC1R", NULL, "HP Right MUX"},
946 {"DAC2L", NULL, "Speaker MUX"},
947 {"DAC2R", NULL, "LOUT4 MUX"},
948 {"DAC3", NULL, "LOUT2 MUX"},
949
950 /* Output Pgas */
951 {"HP Left", NULL, "DAC1L"},
952 {"HP Right", NULL, "DAC1R"},
953 {"LIN3", NULL, "DAC2L"},
954 {"LIN4", NULL, "DAC2R"},
955 {"LIN2", NULL, "DAC3"},
956
957 /* Outputs */
958 {"ClassD", NULL, "LIN3"},
959 {"LOUTL", NULL, "LIN2"},
960 {"LOUTR", NULL, "LIN4"},
961 {"HPL", NULL, "HP Left"},
962 {"HPR", NULL, "HP Right"},
963};
964
965static int da732x_hw_params(struct snd_pcm_substream *substream,
966 struct snd_pcm_hw_params *params,
967 struct snd_soc_dai *dai)
968{
969 struct snd_soc_codec *codec = dai->codec;
970 u32 aif = 0;
971 u32 reg_aif;
972 u32 fs;
973
974 reg_aif = dai->driver->base;
975
976 switch (params_format(params)) {
977 case SNDRV_PCM_FORMAT_S16_LE:
978 aif |= DA732X_AIF_WORD_16;
979 break;
980 case SNDRV_PCM_FORMAT_S20_3LE:
981 aif |= DA732X_AIF_WORD_20;
982 break;
983 case SNDRV_PCM_FORMAT_S24_LE:
984 aif |= DA732X_AIF_WORD_24;
985 break;
986 case SNDRV_PCM_FORMAT_S32_LE:
987 aif |= DA732X_AIF_WORD_32;
988 break;
989 default:
990 return -EINVAL;
991 }
992
993 switch (params_rate(params)) {
994 case 8000:
995 fs = DA732X_SR_8KHZ;
996 break;
997 case 11025:
998 fs = DA732X_SR_11_025KHZ;
999 break;
1000 case 12000:
1001 fs = DA732X_SR_12KHZ;
1002 break;
1003 case 16000:
1004 fs = DA732X_SR_16KHZ;
1005 break;
1006 case 22050:
1007 fs = DA732X_SR_22_05KHZ;
1008 break;
1009 case 24000:
1010 fs = DA732X_SR_24KHZ;
1011 break;
1012 case 32000:
1013 fs = DA732X_SR_32KHZ;
1014 break;
1015 case 44100:
1016 fs = DA732X_SR_44_1KHZ;
1017 break;
1018 case 48000:
1019 fs = DA732X_SR_48KHZ;
1020 break;
1021 case 88100:
1022 fs = DA732X_SR_88_1KHZ;
1023 break;
1024 case 96000:
1025 fs = DA732X_SR_96KHZ;
1026 break;
1027 default:
1028 return -EINVAL;
1029 }
1030
1031 snd_soc_update_bits(codec, reg_aif, DA732X_AIF_WORD_MASK, aif);
1032 snd_soc_update_bits(codec, DA732X_REG_CLK_CTRL, DA732X_SR1_MASK, fs);
1033
1034 return 0;
1035}
1036
1037static int da732x_set_dai_fmt(struct snd_soc_dai *dai, u32 fmt)
1038{
1039 struct snd_soc_codec *codec = dai->codec;
1040 u32 aif_mclk, pc_count;
1041 u32 reg_aif1, aif1;
1042 u32 reg_aif3, aif3;
1043
1044 switch (dai->id) {
1045 case DA732X_DAI_ID1:
1046 reg_aif1 = DA732X_REG_AIFA1;
1047 reg_aif3 = DA732X_REG_AIFA3;
1048 pc_count = DA732X_PC_PULSE_AIFA | DA732X_PC_RESYNC_NOT_AUT |
1049 DA732X_PC_SAME;
1050 break;
1051 case DA732X_DAI_ID2:
1052 reg_aif1 = DA732X_REG_AIFB1;
1053 reg_aif3 = DA732X_REG_AIFB3;
1054 pc_count = DA732X_PC_PULSE_AIFB | DA732X_PC_RESYNC_NOT_AUT |
1055 DA732X_PC_SAME;
1056 break;
1057 default:
1058 return -EINVAL;
1059 }
1060
1061 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1062 case SND_SOC_DAIFMT_CBS_CFS:
1063 aif1 = DA732X_AIF_SLAVE;
1064 aif_mclk = DA732X_AIFM_FRAME_64 | DA732X_AIFM_SRC_SEL_AIFA;
1065 break;
1066 case SND_SOC_DAIFMT_CBM_CFM:
1067 aif1 = DA732X_AIF_CLK_FROM_SRC;
1068 aif_mclk = DA732X_CLK_GENERATION_AIF_A;
1069 break;
1070 default:
1071 return -EINVAL;
1072 }
1073
1074 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1075 case SND_SOC_DAIFMT_I2S:
1076 aif3 = DA732X_AIF_I2S_MODE;
1077 break;
1078 case SND_SOC_DAIFMT_RIGHT_J:
1079 aif3 = DA732X_AIF_RIGHT_J_MODE;
1080 break;
1081 case SND_SOC_DAIFMT_LEFT_J:
1082 aif3 = DA732X_AIF_LEFT_J_MODE;
1083 break;
1084 case SND_SOC_DAIFMT_DSP_B:
1085 aif3 = DA732X_AIF_DSP_MODE;
1086 break;
1087 default:
1088 return -EINVAL;
1089 }
1090
1091 /* Clock inversion */
1092 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1093 case SND_SOC_DAIFMT_DSP_B:
1094 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1095 case SND_SOC_DAIFMT_NB_NF:
1096 break;
1097 case SND_SOC_DAIFMT_IB_NF:
1098 aif3 |= DA732X_AIF_BCLK_INV;
1099 break;
1100 default:
1101 return -EINVAL;
1102 }
1103 break;
1104 case SND_SOC_DAIFMT_I2S:
1105 case SND_SOC_DAIFMT_RIGHT_J:
1106 case SND_SOC_DAIFMT_LEFT_J:
1107 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1108 case SND_SOC_DAIFMT_NB_NF:
1109 break;
1110 case SND_SOC_DAIFMT_IB_IF:
1111 aif3 |= DA732X_AIF_BCLK_INV | DA732X_AIF_WCLK_INV;
1112 break;
1113 case SND_SOC_DAIFMT_IB_NF:
1114 aif3 |= DA732X_AIF_BCLK_INV;
1115 break;
1116 case SND_SOC_DAIFMT_NB_IF:
1117 aif3 |= DA732X_AIF_WCLK_INV;
1118 break;
1119 default:
1120 return -EINVAL;
1121 }
1122 break;
1123 default:
1124 return -EINVAL;
1125 }
1126
1127 snd_soc_write(codec, DA732X_REG_AIF_MCLK, aif_mclk);
1128 snd_soc_update_bits(codec, reg_aif1, DA732X_AIF1_CLK_MASK, aif1);
1129 snd_soc_update_bits(codec, reg_aif3, DA732X_AIF_BCLK_INV |
1130 DA732X_AIF_WCLK_INV | DA732X_AIF_MODE_MASK, aif3);
1131 snd_soc_write(codec, DA732X_REG_PC_CTRL, pc_count);
1132
1133 return 0;
1134}
1135
1136
1137
1138static int da732x_set_dai_pll(struct snd_soc_codec *codec, int pll_id,
1139 int source, unsigned int freq_in,
1140 unsigned int freq_out)
1141{
1142 struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec);
1143 int fref, indiv;
1144 u8 div_lo, div_mid, div_hi;
1145 u64 frac_div;
1146
1147 /* Disable PLL */
1148 if (freq_out == 0) {
1149 snd_soc_update_bits(codec, DA732X_REG_PLL_CTRL,
1150 DA732X_PLL_EN, 0);
1151 da732x->pll_en = false;
1152 return 0;
1153 }
1154
1155 if (da732x->pll_en)
1156 return -EBUSY;
1157
1158 if (source == DA732X_SRCCLK_MCLK) {
1159 /* Validate Sysclk rate */
1160 switch (da732x->sysclk) {
1161 case 11290000:
1162 case 12288000:
1163 case 22580000:
1164 case 24576000:
1165 case 45160000:
1166 case 49152000:
1167 snd_soc_write(codec, DA732X_REG_PLL_CTRL,
1168 DA732X_PLL_BYPASS);
1169 return 0;
1170 default:
1171 dev_err(codec->dev,
1172 "Cannot use PLL Bypass, invalid SYSCLK rate\n");
1173 return -EINVAL;
1174 }
1175 }
1176
1177 indiv = da732x_get_input_div(codec, da732x->sysclk);
1178 if (indiv < 0)
1179 return indiv;
1180
1181 fref = (da732x->sysclk / indiv);
1182 div_hi = freq_out / fref;
1183 frac_div = (u64)(freq_out % fref) * 8192ULL;
1184 do_div(frac_div, fref);
1185 div_mid = (frac_div >> DA732X_1BYTE_SHIFT) & DA732X_U8_MASK;
1186 div_lo = (frac_div) & DA732X_U8_MASK;
1187
1188 snd_soc_write(codec, DA732X_REG_PLL_DIV_LO, div_lo);
1189 snd_soc_write(codec, DA732X_REG_PLL_DIV_MID, div_mid);
1190 snd_soc_write(codec, DA732X_REG_PLL_DIV_HI, div_hi);
1191
1192 snd_soc_update_bits(codec, DA732X_REG_PLL_CTRL, DA732X_PLL_EN,
1193 DA732X_PLL_EN);
1194
1195 da732x->pll_en = true;
1196
1197 return 0;
1198}
1199
1200static int da732x_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
1201 unsigned int freq, int dir)
1202{
1203 struct snd_soc_codec *codec = dai->codec;
1204 struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec);
1205
1206 da732x->sysclk = freq;
1207
1208 return 0;
1209}
1210
1211#define DA732X_RATES SNDRV_PCM_RATE_8000_96000
1212
1213#define DA732X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
1214 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
1215
1216static struct snd_soc_dai_ops da732x_dai1_ops = {
1217 .hw_params = da732x_hw_params,
1218 .set_fmt = da732x_set_dai_fmt,
1219 .set_sysclk = da732x_set_dai_sysclk,
1220};
1221
1222static struct snd_soc_dai_ops da732x_dai2_ops = {
1223 .hw_params = da732x_hw_params,
1224 .set_fmt = da732x_set_dai_fmt,
1225 .set_sysclk = da732x_set_dai_sysclk,
1226};
1227
1228static struct snd_soc_dai_driver da732x_dai[] = {
1229 {
1230 .name = "DA732X_AIFA",
1231 .id = DA732X_DAI_ID1,
1232 .base = DA732X_REG_AIFA1,
1233 .playback = {
1234 .stream_name = "AIFA Playback",
1235 .channels_min = 1,
1236 .channels_max = 2,
1237 .rates = DA732X_RATES,
1238 .formats = DA732X_FORMATS,
1239 },
1240 .capture = {
1241 .stream_name = "AIFA Capture",
1242 .channels_min = 1,
1243 .channels_max = 2,
1244 .rates = DA732X_RATES,
1245 .formats = DA732X_FORMATS,
1246 },
1247 .ops = &da732x_dai1_ops,
1248 },
1249 {
1250 .name = "DA732X_AIFB",
1251 .id = DA732X_DAI_ID2,
1252 .base = DA732X_REG_AIFB1,
1253 .playback = {
1254 .stream_name = "AIFB Playback",
1255 .channels_min = 1,
1256 .channels_max = 2,
1257 .rates = DA732X_RATES,
1258 .formats = DA732X_FORMATS,
1259 },
1260 .capture = {
1261 .stream_name = "AIFB Capture",
1262 .channels_min = 1,
1263 .channels_max = 2,
1264 .rates = DA732X_RATES,
1265 .formats = DA732X_FORMATS,
1266 },
1267 .ops = &da732x_dai2_ops,
1268 },
1269};
1270
1271static const struct regmap_config da732x_regmap = {
1272 .reg_bits = 8,
1273 .val_bits = 8,
1274
1275 .max_register = DA732X_MAX_REG,
1276 .reg_defaults = da732x_reg_cache,
1277 .num_reg_defaults = ARRAY_SIZE(da732x_reg_cache),
1278 .cache_type = REGCACHE_RBTREE,
1279};
1280
1281
1282static void da732x_dac_offset_adjust(struct snd_soc_codec *codec)
1283{
1284 u8 offset[DA732X_HP_DACS];
1285 u8 sign[DA732X_HP_DACS];
1286 u8 step = DA732X_DAC_OFFSET_STEP;
1287
1288 /* Initialize DAC offset calibration circuits and registers */
1289 snd_soc_write(codec, DA732X_REG_HPL_DAC_OFFSET,
1290 DA732X_HP_DAC_OFFSET_TRIM_VAL);
1291 snd_soc_write(codec, DA732X_REG_HPR_DAC_OFFSET,
1292 DA732X_HP_DAC_OFFSET_TRIM_VAL);
1293 snd_soc_write(codec, DA732X_REG_HPL_DAC_OFF_CNTL,
1294 DA732X_HP_DAC_OFF_CALIBRATION |
1295 DA732X_HP_DAC_OFF_SCALE_STEPS);
1296 snd_soc_write(codec, DA732X_REG_HPR_DAC_OFF_CNTL,
1297 DA732X_HP_DAC_OFF_CALIBRATION |
1298 DA732X_HP_DAC_OFF_SCALE_STEPS);
1299
1300 /* Wait for voltage stabilization */
1301 msleep(DA732X_WAIT_FOR_STABILIZATION);
1302
1303 /* Check DAC offset sign */
1304 sign[DA732X_HPL_DAC] = (codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) &
1305 DA732X_HP_DAC_OFF_CNTL_COMPO);
1306 sign[DA732X_HPR_DAC] = (codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) &
1307 DA732X_HP_DAC_OFF_CNTL_COMPO);
1308
1309 /* Binary search DAC offset values (both channels at once) */
1310 offset[DA732X_HPL_DAC] = sign[DA732X_HPL_DAC] << DA732X_HP_DAC_COMPO_SHIFT;
1311 offset[DA732X_HPR_DAC] = sign[DA732X_HPR_DAC] << DA732X_HP_DAC_COMPO_SHIFT;
1312
1313 do {
1314 offset[DA732X_HPL_DAC] |= step;
1315 offset[DA732X_HPR_DAC] |= step;
1316 snd_soc_write(codec, DA732X_REG_HPL_DAC_OFFSET,
1317 ~offset[DA732X_HPL_DAC] & DA732X_HP_DAC_OFF_MASK);
1318 snd_soc_write(codec, DA732X_REG_HPR_DAC_OFFSET,
1319 ~offset[DA732X_HPR_DAC] & DA732X_HP_DAC_OFF_MASK);
1320
1321 msleep(DA732X_WAIT_FOR_STABILIZATION);
1322
1323 if ((codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) &
1324 DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPL_DAC])
1325 offset[DA732X_HPL_DAC] &= ~step;
1326 if ((codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) &
1327 DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPR_DAC])
1328 offset[DA732X_HPR_DAC] &= ~step;
1329
1330 step >>= 1;
1331 } while (step);
1332
1333 /* Write final DAC offsets to registers */
1334 snd_soc_write(codec, DA732X_REG_HPL_DAC_OFFSET,
1335 ~offset[DA732X_HPL_DAC] & DA732X_HP_DAC_OFF_MASK);
1336 snd_soc_write(codec, DA732X_REG_HPR_DAC_OFFSET,
1337 ~offset[DA732X_HPR_DAC] & DA732X_HP_DAC_OFF_MASK);
1338
1339 /* End DAC calibration mode */
1340 snd_soc_write(codec, DA732X_REG_HPL_DAC_OFF_CNTL,
1341 DA732X_HP_DAC_OFF_SCALE_STEPS);
1342 snd_soc_write(codec, DA732X_REG_HPR_DAC_OFF_CNTL,
1343 DA732X_HP_DAC_OFF_SCALE_STEPS);
1344}
1345
1346static void da732x_output_offset_adjust(struct snd_soc_codec *codec)
1347{
1348 u8 offset[DA732X_HP_AMPS];
1349 u8 sign[DA732X_HP_AMPS];
1350 u8 step = DA732X_OUTPUT_OFFSET_STEP;
1351
1352 offset[DA732X_HPL_AMP] = DA732X_HP_OUT_TRIM_VAL;
1353 offset[DA732X_HPR_AMP] = DA732X_HP_OUT_TRIM_VAL;
1354
1355 /* Initialize output offset calibration circuits and registers */
1356 snd_soc_write(codec, DA732X_REG_HPL_OUT_OFFSET, DA732X_HP_OUT_TRIM_VAL);
1357 snd_soc_write(codec, DA732X_REG_HPR_OUT_OFFSET, DA732X_HP_OUT_TRIM_VAL);
1358 snd_soc_write(codec, DA732X_REG_HPL,
1359 DA732X_HP_OUT_COMP | DA732X_HP_OUT_EN);
1360 snd_soc_write(codec, DA732X_REG_HPR,
1361 DA732X_HP_OUT_COMP | DA732X_HP_OUT_EN);
1362
1363 /* Wait for voltage stabilization */
1364 msleep(DA732X_WAIT_FOR_STABILIZATION);
1365
1366 /* Check output offset sign */
1367 sign[DA732X_HPL_AMP] = codec->hw_read(codec, DA732X_REG_HPL) &
1368 DA732X_HP_OUT_COMPO;
1369 sign[DA732X_HPR_AMP] = codec->hw_read(codec, DA732X_REG_HPR) &
1370 DA732X_HP_OUT_COMPO;
1371
1372 snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_OUT_COMP |
1373 (sign[DA732X_HPL_AMP] >> DA732X_HP_OUT_COMPO_SHIFT) |
1374 DA732X_HP_OUT_EN);
1375 snd_soc_write(codec, DA732X_REG_HPR, DA732X_HP_OUT_COMP |
1376 (sign[DA732X_HPR_AMP] >> DA732X_HP_OUT_COMPO_SHIFT) |
1377 DA732X_HP_OUT_EN);
1378
1379 /* Binary search output offset values (both channels at once) */
1380 do {
1381 offset[DA732X_HPL_AMP] |= step;
1382 offset[DA732X_HPR_AMP] |= step;
1383 snd_soc_write(codec, DA732X_REG_HPL_OUT_OFFSET,
1384 offset[DA732X_HPL_AMP]);
1385 snd_soc_write(codec, DA732X_REG_HPR_OUT_OFFSET,
1386 offset[DA732X_HPR_AMP]);
1387
1388 msleep(DA732X_WAIT_FOR_STABILIZATION);
1389
1390 if ((codec->hw_read(codec, DA732X_REG_HPL) &
1391 DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPL_AMP])
1392 offset[DA732X_HPL_AMP] &= ~step;
1393 if ((codec->hw_read(codec, DA732X_REG_HPR) &
1394 DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPR_AMP])
1395 offset[DA732X_HPR_AMP] &= ~step;
1396
1397 step >>= 1;
1398 } while (step);
1399
1400 /* Write final DAC offsets to registers */
1401 snd_soc_write(codec, DA732X_REG_HPL_OUT_OFFSET, offset[DA732X_HPL_AMP]);
1402 snd_soc_write(codec, DA732X_REG_HPR_OUT_OFFSET, offset[DA732X_HPR_AMP]);
1403}
1404
1405static void da732x_hp_dc_offset_cancellation(struct snd_soc_codec *codec)
1406{
1407 /* Make sure that we have Soft Mute enabled */
1408 snd_soc_write(codec, DA732X_REG_DAC1_SOFTMUTE, DA732X_SOFTMUTE_EN |
1409 DA732X_GAIN_RAMPED | DA732X_16_SAMPLES);
1410 snd_soc_write(codec, DA732X_REG_DAC1_SEL, DA732X_DACL_EN |
1411 DA732X_DACR_EN | DA732X_DACL_SDM | DA732X_DACR_SDM |
1412 DA732X_DACL_MUTE | DA732X_DACR_MUTE);
1413 snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN |
1414 DA732X_HP_OUT_MUTE | DA732X_HP_OUT_EN);
1415 snd_soc_write(codec, DA732X_REG_HPR, DA732X_HP_OUT_EN |
1416 DA732X_HP_OUT_MUTE | DA732X_HP_OUT_DAC_EN);
1417
1418 da732x_dac_offset_adjust(codec);
1419 da732x_output_offset_adjust(codec);
1420
1421 snd_soc_write(codec, DA732X_REG_DAC1_SEL, DA732X_DACS_DIS);
1422 snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_DIS);
1423 snd_soc_write(codec, DA732X_REG_HPR, DA732X_HP_DIS);
1424}
1425
1426static int da732x_set_bias_level(struct snd_soc_codec *codec,
1427 enum snd_soc_bias_level level)
1428{
1429 struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec);
1430
1431 switch (level) {
1432 case SND_SOC_BIAS_ON:
1433 snd_soc_update_bits(codec, DA732X_REG_BIAS_EN,
1434 DA732X_BIAS_BOOST_MASK,
1435 DA732X_BIAS_BOOST_100PC);
1436 break;
1437 case SND_SOC_BIAS_PREPARE:
1438 break;
1439 case SND_SOC_BIAS_STANDBY:
1440 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
1441 /* Init Codec */
1442 snd_soc_write(codec, DA732X_REG_REF1,
1443 DA732X_VMID_FASTCHG);
1444 snd_soc_write(codec, DA732X_REG_BIAS_EN,
1445 DA732X_BIAS_EN);
1446
1447 mdelay(DA732X_STARTUP_DELAY);
1448
1449 /* Disable Fast Charge and enable DAC ref voltage */
1450 snd_soc_write(codec, DA732X_REG_REF1,
1451 DA732X_REFBUFX2_EN);
1452
1453 /* Enable bypass DSP routing */
1454 snd_soc_write(codec, DA732X_REG_DATA_ROUTE,
1455 DA732X_BYPASS_DSP);
1456
1457 /* Enable Digital subsystem */
1458 snd_soc_write(codec, DA732X_REG_DSP_CTRL,
1459 DA732X_DIGITAL_EN);
1460
1461 snd_soc_write(codec, DA732X_REG_SPARE1_OUT,
1462 DA732X_HP_DRIVER_EN |
1463 DA732X_HP_GATE_LOW |
1464 DA732X_HP_LOOP_GAIN_CTRL);
1465 snd_soc_write(codec, DA732X_REG_HP_LIN1_GNDSEL,
1466 DA732X_HP_OUT_GNDSEL);
1467
1468 da732x_set_charge_pump(codec, DA732X_ENABLE_CP);
1469
1470 snd_soc_write(codec, DA732X_REG_CLK_EN1,
1471 DA732X_SYS3_CLK_EN | DA732X_PC_CLK_EN);
1472
1473 /* Enable Zero Crossing */
1474 snd_soc_write(codec, DA732X_REG_INP_ZC_EN,
1475 DA732X_MIC1_PRE_ZC_EN |
1476 DA732X_MIC1_ZC_EN |
1477 DA732X_MIC2_PRE_ZC_EN |
1478 DA732X_MIC2_ZC_EN |
1479 DA732X_AUXL_ZC_EN |
1480 DA732X_AUXR_ZC_EN |
1481 DA732X_MIC3_PRE_ZC_EN |
1482 DA732X_MIC3_ZC_EN);
1483 snd_soc_write(codec, DA732X_REG_OUT_ZC_EN,
1484 DA732X_HPL_ZC_EN | DA732X_HPR_ZC_EN |
1485 DA732X_LIN2_ZC_EN | DA732X_LIN3_ZC_EN |
1486 DA732X_LIN4_ZC_EN);
1487
1488 da732x_hp_dc_offset_cancellation(codec);
1489
1490 regcache_cache_only(codec->control_data, false);
1491 regcache_sync(codec->control_data);
1492 } else {
1493 snd_soc_update_bits(codec, DA732X_REG_BIAS_EN,
1494 DA732X_BIAS_BOOST_MASK,
1495 DA732X_BIAS_BOOST_50PC);
1496 snd_soc_update_bits(codec, DA732X_REG_PLL_CTRL,
1497 DA732X_PLL_EN, 0);
1498 da732x->pll_en = false;
1499 }
1500 break;
1501 case SND_SOC_BIAS_OFF:
1502 regcache_cache_only(codec->control_data, true);
1503 da732x_set_charge_pump(codec, DA732X_DISABLE_CP);
1504 snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, DA732X_BIAS_EN,
1505 DA732X_BIAS_DIS);
1506 da732x->pll_en = false;
1507 break;
1508 }
1509
1510 codec->dapm.bias_level = level;
1511
1512 return 0;
1513}
1514
1515static int da732x_probe(struct snd_soc_codec *codec)
1516{
1517 struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec);
1518 struct snd_soc_dapm_context *dapm = &codec->dapm;
1519 int ret = 0;
1520
1521 da732x->codec = codec;
1522
1523 dapm->idle_bias_off = false;
1524
1525 codec->control_data = da732x->regmap;
1526
1527 ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
1528 if (ret != 0) {
1529 dev_err(codec->dev, "Failed to register codec.\n");
1530 goto err;
1531 }
1532
1533 da732x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1534err:
1535 return ret;
1536}
1537
1538static int da732x_remove(struct snd_soc_codec *codec)
1539{
1540
1541 da732x_set_bias_level(codec, SND_SOC_BIAS_OFF);
1542
1543 return 0;
1544}
1545
1546static struct snd_soc_codec_driver soc_codec_dev_da732x = {
1547 .probe = da732x_probe,
1548 .remove = da732x_remove,
1549 .set_bias_level = da732x_set_bias_level,
1550 .controls = da732x_snd_controls,
1551 .num_controls = ARRAY_SIZE(da732x_snd_controls),
1552 .dapm_widgets = da732x_dapm_widgets,
1553 .num_dapm_widgets = ARRAY_SIZE(da732x_dapm_widgets),
1554 .dapm_routes = da732x_dapm_routes,
1555 .num_dapm_routes = ARRAY_SIZE(da732x_dapm_routes),
1556 .set_pll = da732x_set_dai_pll,
1557 .reg_cache_size = ARRAY_SIZE(da732x_reg_cache),
1558};
1559
1560static __devinit int da732x_i2c_probe(struct i2c_client *i2c,
1561 const struct i2c_device_id *id)
1562{
1563 struct da732x_priv *da732x;
1564 unsigned int reg;
1565 int ret;
1566
1567 da732x = devm_kzalloc(&i2c->dev, sizeof(struct da732x_priv),
1568 GFP_KERNEL);
1569 if (!da732x)
1570 return -ENOMEM;
1571
1572 i2c_set_clientdata(i2c, da732x);
1573
1574 da732x->regmap = devm_regmap_init_i2c(i2c, &da732x_regmap);
1575 if (IS_ERR(da732x->regmap)) {
1576 ret = PTR_ERR(da732x->regmap);
1577 dev_err(&i2c->dev, "Failed to initialize regmap\n");
1578 goto err;
1579 }
1580
1581 ret = regmap_read(da732x->regmap, DA732X_REG_ID, &reg);
1582 if (ret < 0) {
1583 dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
1584 goto err;
1585 }
1586
1587 dev_info(&i2c->dev, "Revision: %d.%d\n",
1588 (reg & DA732X_ID_MAJOR_MASK), (reg & DA732X_ID_MINOR_MASK));
1589
1590 ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_da732x,
1591 da732x_dai, ARRAY_SIZE(da732x_dai));
1592 if (ret != 0)
1593 dev_err(&i2c->dev, "Failed to register codec.\n");
1594
1595err:
1596 return ret;
1597}
1598
1599static __devexit int da732x_i2c_remove(struct i2c_client *client)
1600{
1601 snd_soc_unregister_codec(&client->dev);
1602
1603 return 0;
1604}
1605
1606static const struct i2c_device_id da732x_i2c_id[] = {
1607 { "da7320", 0},
1608 { }
1609};
1610MODULE_DEVICE_TABLE(i2c, da732x_i2c_id);
1611
1612static struct i2c_driver da732x_i2c_driver = {
1613 .driver = {
1614 .name = "da7320",
1615 .owner = THIS_MODULE,
1616 },
1617 .probe = da732x_i2c_probe,
1618 .remove = __devexit_p(da732x_i2c_remove),
1619 .id_table = da732x_i2c_id,
1620};
1621
1622module_i2c_driver(da732x_i2c_driver);
1623
1624
1625MODULE_DESCRIPTION("ASoC DA732X driver");
1626MODULE_AUTHOR("Michal Hajduk <michal.hajduk@diasemi.com>");
1627MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/da732x.h b/sound/soc/codecs/da732x.h
new file mode 100644
index 00000000000..c8ce5475de2
--- /dev/null
+++ b/sound/soc/codecs/da732x.h
@@ -0,0 +1,133 @@
1/*
2 * da732x.h -- Dialog DA732X ALSA SoC Audio Driver Header File
3 *
4 * Copyright (C) 2012 Dialog Semiconductor GmbH
5 *
6 * Author: Michal Hajduk <Michal.Hajduk@diasemi.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __DA732X_H_
14#define __DA732X_H
15
16#include <sound/soc.h>
17
18/* General */
19#define DA732X_U8_MASK 0xFF
20#define DA732X_4BYTES 4
21#define DA732X_3BYTES 3
22#define DA732X_2BYTES 2
23#define DA732X_1BYTE 1
24#define DA732X_1BYTE_SHIFT 8
25#define DA732X_2BYTES_SHIFT 16
26#define DA732X_3BYTES_SHIFT 24
27#define DA732X_4BYTES_SHIFT 32
28
29#define DA732X_DACS_DIS 0x0
30#define DA732X_HP_DIS 0x0
31#define DA732X_CLEAR_REG 0x0
32
33/* Calibration */
34#define DA732X_DAC_OFFSET_STEP 0x20
35#define DA732X_OUTPUT_OFFSET_STEP 0x80
36#define DA732X_HP_OUT_TRIM_VAL 0x0
37#define DA732X_WAIT_FOR_STABILIZATION 1
38#define DA732X_HPL_DAC 0
39#define DA732X_HPR_DAC 1
40#define DA732X_HP_DACS 2
41#define DA732X_HPL_AMP 0
42#define DA732X_HPR_AMP 1
43#define DA732X_HP_AMPS 2
44
45/* Clock settings */
46#define DA732X_STARTUP_DELAY 100
47#define DA732X_PLL_OUT_196608 196608000
48#define DA732X_PLL_OUT_180634 180633600
49#define DA732X_PLL_OUT_SRM 188620800
50#define DA732X_MCLK_10MHZ 10000000
51#define DA732X_MCLK_20MHZ 20000000
52#define DA732X_MCLK_40MHZ 40000000
53#define DA732X_MCLK_54MHZ 54000000
54#define DA732X_MCLK_RET_0_10MHZ 0
55#define DA732X_MCLK_VAL_0_10MHZ 1
56#define DA732X_MCLK_RET_10_20MHZ 1
57#define DA732X_MCLK_VAL_10_20MHZ 2
58#define DA732X_MCLK_RET_20_40MHZ 2
59#define DA732X_MCLK_VAL_20_40MHZ 4
60#define DA732X_MCLK_RET_40_54MHZ 3
61#define DA732X_MCLK_VAL_40_54MHZ 8
62#define DA732X_DAI_ID1 0
63#define DA732X_DAI_ID2 1
64#define DA732X_SRCCLK_PLL 0
65#define DA732X_SRCCLK_MCLK 1
66
67#define DA732X_LIN_LP_VOL 0x4F
68#define DA732X_LP_VOL 0x40
69
70/* Kcontrols */
71#define DA732X_DAC_EN_MAX 2
72#define DA732X_ADCL_MUX_MAX 2
73#define DA732X_ADCR_MUX_MAX 3
74#define DA732X_HPF_MODE_MAX 3
75#define DA732X_HPF_MODE_SHIFT 4
76#define DA732X_HPF_MUSIC_SHIFT 0
77#define DA732X_HPF_MUSIC_MAX 4
78#define DA732X_HPF_VOICE_SHIFT 4
79#define DA732X_HPF_VOICE_MAX 8
80#define DA732X_EQ_EN_MAX 1
81#define DA732X_HPF_VOICE 1
82#define DA732X_HPF_MUSIC 2
83#define DA732X_HPF_DISABLED 0
84#define DA732X_NO_INVERT 0
85#define DA732X_INVERT 1
86#define DA732X_SWITCH_MAX 1
87#define DA732X_ENABLE_CP 1
88#define DA732X_DISABLE_CP 0
89#define DA732X_DISABLE_ALL_CLKS 0
90#define DA732X_RESET_ADCS 0
91
92/* dB values */
93#define DA732X_MIC_VOL_DB_MIN 0
94#define DA732X_MIC_VOL_DB_INC 50
95#define DA732X_MIC_PRE_VOL_DB_MIN 0
96#define DA732X_MIC_PRE_VOL_DB_INC 600
97#define DA732X_AUX_VOL_DB_MIN -6000
98#define DA732X_AUX_VOL_DB_INC 150
99#define DA732X_HP_VOL_DB_MIN -2250
100#define DA732X_HP_VOL_DB_INC 150
101#define DA732X_LIN2_VOL_DB_MIN -1650
102#define DA732X_LIN2_VOL_DB_INC 150
103#define DA732X_LIN3_VOL_DB_MIN -1650
104#define DA732X_LIN3_VOL_DB_INC 150
105#define DA732X_LIN4_VOL_DB_MIN -2250
106#define DA732X_LIN4_VOL_DB_INC 150
107#define DA732X_EQ_BAND_VOL_DB_MIN -1050
108#define DA732X_EQ_BAND_VOL_DB_INC 150
109#define DA732X_DAC_VOL_DB_MIN -7725
110#define DA732X_DAC_VOL_DB_INC 75
111#define DA732X_ADC_VOL_DB_MIN 0
112#define DA732X_ADC_VOL_DB_INC -1
113#define DA732X_EQ_OVERALL_VOL_DB_MIN -1800
114#define DA732X_EQ_OVERALL_VOL_DB_INC 600
115
116#define DA732X_SOC_ENUM_DOUBLE_R(xreg, xrreg, xmax, xtext) \
117 {.reg = xreg, .reg2 = xrreg, .max = xmax, .texts = xtext}
118
119enum da732x_sysctl {
120 DA732X_SR_8KHZ = 0x1,
121 DA732X_SR_11_025KHZ = 0x2,
122 DA732X_SR_12KHZ = 0x3,
123 DA732X_SR_16KHZ = 0x5,
124 DA732X_SR_22_05KHZ = 0x6,
125 DA732X_SR_24KHZ = 0x7,
126 DA732X_SR_32KHZ = 0x9,
127 DA732X_SR_44_1KHZ = 0xA,
128 DA732X_SR_48KHZ = 0xB,
129 DA732X_SR_88_1KHZ = 0xE,
130 DA732X_SR_96KHZ = 0xF,
131};
132
133#endif /* __DA732X_H_ */
diff --git a/sound/soc/codecs/da732x_reg.h b/sound/soc/codecs/da732x_reg.h
new file mode 100644
index 00000000000..bdd03ca4b2d
--- /dev/null
+++ b/sound/soc/codecs/da732x_reg.h
@@ -0,0 +1,654 @@
1/*
2 * da732x_reg.h --- Dialog DA732X ALSA SoC Audio Registers Header File
3 *
4 * Copyright (C) 2012 Dialog Semiconductor GmbH
5 *
6 * Author: Michal Hajduk <Michal.Hajduk@diasemi.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __DA732X_REG_H_
14#define __DA732X_REG_H_
15
16/* DA732X registers */
17#define DA732X_REG_STATUS_EXT 0x00
18#define DA732X_REG_STATUS 0x01
19#define DA732X_REG_REF1 0x02
20#define DA732X_REG_BIAS_EN 0x03
21#define DA732X_REG_BIAS1 0x04
22#define DA732X_REG_BIAS2 0x05
23#define DA732X_REG_BIAS3 0x06
24#define DA732X_REG_BIAS4 0x07
25#define DA732X_REG_MICBIAS2 0x0F
26#define DA732X_REG_MICBIAS1 0x10
27#define DA732X_REG_MICDET 0x11
28#define DA732X_REG_MIC1_PRE 0x12
29#define DA732X_REG_MIC1 0x13
30#define DA732X_REG_MIC2_PRE 0x14
31#define DA732X_REG_MIC2 0x15
32#define DA732X_REG_AUX1L 0x16
33#define DA732X_REG_AUX1R 0x17
34#define DA732X_REG_MIC3_PRE 0x18
35#define DA732X_REG_MIC3 0x19
36#define DA732X_REG_INP_PINBIAS 0x1A
37#define DA732X_REG_INP_ZC_EN 0x1B
38#define DA732X_REG_INP_MUX 0x1D
39#define DA732X_REG_HP_DET 0x20
40#define DA732X_REG_HPL_DAC_OFFSET 0x21
41#define DA732X_REG_HPL_DAC_OFF_CNTL 0x22
42#define DA732X_REG_HPL_OUT_OFFSET 0x23
43#define DA732X_REG_HPL 0x24
44#define DA732X_REG_HPL_VOL 0x25
45#define DA732X_REG_HPR_DAC_OFFSET 0x26
46#define DA732X_REG_HPR_DAC_OFF_CNTL 0x27
47#define DA732X_REG_HPR_OUT_OFFSET 0x28
48#define DA732X_REG_HPR 0x29
49#define DA732X_REG_HPR_VOL 0x2A
50#define DA732X_REG_LIN2 0x2B
51#define DA732X_REG_LIN3 0x2C
52#define DA732X_REG_LIN4 0x2D
53#define DA732X_REG_OUT_ZC_EN 0x2E
54#define DA732X_REG_HP_LIN1_GNDSEL 0x37
55#define DA732X_REG_CP_HP1 0x3A
56#define DA732X_REG_CP_HP2 0x3B
57#define DA732X_REG_CP_CTRL1 0x40
58#define DA732X_REG_CP_CTRL2 0x41
59#define DA732X_REG_CP_CTRL3 0x42
60#define DA732X_REG_CP_LEVEL_MASK 0x43
61#define DA732X_REG_CP_DET 0x44
62#define DA732X_REG_CP_STATUS 0x45
63#define DA732X_REG_CP_THRESH1 0x46
64#define DA732X_REG_CP_THRESH2 0x47
65#define DA732X_REG_CP_THRESH3 0x48
66#define DA732X_REG_CP_THRESH4 0x49
67#define DA732X_REG_CP_THRESH5 0x4A
68#define DA732X_REG_CP_THRESH6 0x4B
69#define DA732X_REG_CP_THRESH7 0x4C
70#define DA732X_REG_CP_THRESH8 0x4D
71#define DA732X_REG_PLL_DIV_LO 0x50
72#define DA732X_REG_PLL_DIV_MID 0x51
73#define DA732X_REG_PLL_DIV_HI 0x52
74#define DA732X_REG_PLL_CTRL 0x53
75#define DA732X_REG_CLK_CTRL 0x54
76#define DA732X_REG_CLK_DSP 0x5A
77#define DA732X_REG_CLK_EN1 0x5B
78#define DA732X_REG_CLK_EN2 0x5C
79#define DA732X_REG_CLK_EN3 0x5D
80#define DA732X_REG_CLK_EN4 0x5E
81#define DA732X_REG_CLK_EN5 0x5F
82#define DA732X_REG_AIF_MCLK 0x60
83#define DA732X_REG_AIFA1 0x61
84#define DA732X_REG_AIFA2 0x62
85#define DA732X_REG_AIFA3 0x63
86#define DA732X_REG_AIFB1 0x64
87#define DA732X_REG_AIFB2 0x65
88#define DA732X_REG_AIFB3 0x66
89#define DA732X_REG_PC_CTRL 0x6A
90#define DA732X_REG_DATA_ROUTE 0x70
91#define DA732X_REG_DSP_CTRL 0x71
92#define DA732X_REG_CIF_CTRL2 0x74
93#define DA732X_REG_HANDSHAKE 0x75
94#define DA732X_REG_MBOX0 0x76
95#define DA732X_REG_MBOX1 0x77
96#define DA732X_REG_MBOX2 0x78
97#define DA732X_REG_MBOX_STATUS 0x79
98#define DA732X_REG_SPARE1_OUT 0x7D
99#define DA732X_REG_SPARE2_OUT 0x7E
100#define DA732X_REG_SPARE1_IN 0x7F
101#define DA732X_REG_ID 0x81
102#define DA732X_REG_ADC1_PD 0x90
103#define DA732X_REG_ADC1_HPF 0x93
104#define DA732X_REG_ADC1_SEL 0x94
105#define DA732X_REG_ADC1_EQ12 0x95
106#define DA732X_REG_ADC1_EQ34 0x96
107#define DA732X_REG_ADC1_EQ5 0x97
108#define DA732X_REG_ADC2_PD 0x98
109#define DA732X_REG_ADC2_HPF 0x9B
110#define DA732X_REG_ADC2_SEL 0x9C
111#define DA732X_REG_ADC2_EQ12 0x9D
112#define DA732X_REG_ADC2_EQ34 0x9E
113#define DA732X_REG_ADC2_EQ5 0x9F
114#define DA732X_REG_DAC1_HPF 0xA0
115#define DA732X_REG_DAC1_L_VOL 0xA1
116#define DA732X_REG_DAC1_R_VOL 0xA2
117#define DA732X_REG_DAC1_SEL 0xA3
118#define DA732X_REG_DAC1_SOFTMUTE 0xA4
119#define DA732X_REG_DAC1_EQ12 0xA5
120#define DA732X_REG_DAC1_EQ34 0xA6
121#define DA732X_REG_DAC1_EQ5 0xA7
122#define DA732X_REG_DAC2_HPF 0xB0
123#define DA732X_REG_DAC2_L_VOL 0xB1
124#define DA732X_REG_DAC2_R_VOL 0xB2
125#define DA732X_REG_DAC2_SEL 0xB3
126#define DA732X_REG_DAC2_SOFTMUTE 0xB4
127#define DA732X_REG_DAC2_EQ12 0xB5
128#define DA732X_REG_DAC2_EQ34 0xB6
129#define DA732X_REG_DAC2_EQ5 0xB7
130#define DA732X_REG_DAC3_HPF 0xC0
131#define DA732X_REG_DAC3_VOL 0xC1
132#define DA732X_REG_DAC3_SEL 0xC3
133#define DA732X_REG_DAC3_SOFTMUTE 0xC4
134#define DA732X_REG_DAC3_EQ12 0xC5
135#define DA732X_REG_DAC3_EQ34 0xC6
136#define DA732X_REG_DAC3_EQ5 0xC7
137#define DA732X_REG_BIQ_BYP 0xD2
138#define DA732X_REG_DMA_CMD 0xD3
139#define DA732X_REG_DMA_ADDR0 0xD4
140#define DA732X_REG_DMA_ADDR1 0xD5
141#define DA732X_REG_DMA_DATA0 0xD6
142#define DA732X_REG_DMA_DATA1 0xD7
143#define DA732X_REG_DMA_DATA2 0xD8
144#define DA732X_REG_DMA_DATA3 0xD9
145#define DA732X_REG_DMA_STATUS 0xDA
146#define DA732X_REG_BROWNOUT 0xDF
147#define DA732X_REG_UNLOCK 0xE0
148
149#define DA732X_MAX_REG DA732X_REG_UNLOCK
150/*
151 * Bits
152 */
153
154/* DA732X_REG_STATUS_EXT (addr=0x00) */
155#define DA732X_STATUS_EXT_DSP (1 << 4)
156#define DA732X_STATUS_EXT_CLEAR (0 << 0)
157
158/* DA732X_REG_STATUS (addr=0x01) */
159#define DA732X_STATUS_PLL_LOCK (1 << 0)
160#define DA732X_STATUS_PLL_MCLK_DET (1 << 1)
161#define DA732X_STATUS_HPDET_OUT (1 << 2)
162#define DA732X_STATUS_INP_MIXDET_1 (1 << 3)
163#define DA732X_STATUS_INP_MIXDET_2 (1 << 4)
164#define DA732X_STATUS_BO_STATUS (1 << 5)
165
166/* DA732X_REG_REF1 (addr=0x02) */
167#define DA732X_VMID_FASTCHG (1 << 1)
168#define DA732X_VMID_FASTDISCHG (1 << 2)
169#define DA732X_REFBUFX2_EN (1 << 6)
170#define DA732X_REFBUFX2_DIS (0 << 6)
171
172/* DA732X_REG_BIAS_EN (addr=0x03) */
173#define DA732X_BIAS_BOOST_MASK (3 << 0)
174#define DA732X_BIAS_BOOST_100PC (0 << 0)
175#define DA732X_BIAS_BOOST_133PC (1 << 0)
176#define DA732X_BIAS_BOOST_88PC (2 << 0)
177#define DA732X_BIAS_BOOST_50PC (3 << 0)
178#define DA732X_BIAS_EN (1 << 7)
179#define DA732X_BIAS_DIS (0 << 7)
180
181/* DA732X_REG_BIAS1 (addr=0x04) */
182#define DA732X_BIAS1_HP_DAC_BIAS_MASK (3 << 0)
183#define DA732X_BIAS1_HP_DAC_BIAS_100PC (0 << 0)
184#define DA732X_BIAS1_HP_DAC_BIAS_150PC (1 << 0)
185#define DA732X_BIAS1_HP_DAC_BIAS_50PC (2 << 0)
186#define DA732X_BIAS1_HP_DAC_BIAS_75PC (3 << 0)
187#define DA732X_BIAS1_HP_OUT_BIAS_MASK (7 << 4)
188#define DA732X_BIAS1_HP_OUT_BIAS_100PC (0 << 4)
189#define DA732X_BIAS1_HP_OUT_BIAS_125PC (1 << 4)
190#define DA732X_BIAS1_HP_OUT_BIAS_150PC (2 << 4)
191#define DA732X_BIAS1_HP_OUT_BIAS_175PC (3 << 4)
192#define DA732X_BIAS1_HP_OUT_BIAS_200PC (4 << 4)
193#define DA732X_BIAS1_HP_OUT_BIAS_250PC (5 << 4)
194#define DA732X_BIAS1_HP_OUT_BIAS_300PC (6 << 4)
195#define DA732X_BIAS1_HP_OUT_BIAS_350PC (7 << 4)
196
197/* DA732X_REG_BIAS2 (addr=0x05) */
198#define DA732X_BIAS2_LINE2_DAC_BIAS_MASK (3 << 0)
199#define DA732X_BIAS2_LINE2_DAC_BIAS_100PC (0 << 0)
200#define DA732X_BIAS2_LINE2_DAC_BIAS_150PC (1 << 0)
201#define DA732X_BIAS2_LINE2_DAC_BIAS_50PC (2 << 0)
202#define DA732X_BIAS2_LINE2_DAC_BIAS_75PC (3 << 0)
203#define DA732X_BIAS2_LINE2_OUT_BIAS_MASK (7 << 4)
204#define DA732X_BIAS2_LINE2_OUT_BIAS_100PC (0 << 4)
205#define DA732X_BIAS2_LINE2_OUT_BIAS_125PC (1 << 4)
206#define DA732X_BIAS2_LINE2_OUT_BIAS_150PC (2 << 4)
207#define DA732X_BIAS2_LINE2_OUT_BIAS_175PC (3 << 4)
208#define DA732X_BIAS2_LINE2_OUT_BIAS_200PC (4 << 4)
209#define DA732X_BIAS2_LINE2_OUT_BIAS_250PC (5 << 4)
210#define DA732X_BIAS2_LINE2_OUT_BIAS_300PC (6 << 4)
211#define DA732X_BIAS2_LINE2_OUT_BIAS_350PC (7 << 4)
212
213/* DA732X_REG_BIAS3 (addr=0x06) */
214#define DA732X_BIAS3_LINE3_DAC_BIAS_MASK (3 << 0)
215#define DA732X_BIAS3_LINE3_DAC_BIAS_100PC (0 << 0)
216#define DA732X_BIAS3_LINE3_DAC_BIAS_150PC (1 << 0)
217#define DA732X_BIAS3_LINE3_DAC_BIAS_50PC (2 << 0)
218#define DA732X_BIAS3_LINE3_DAC_BIAS_75PC (3 << 0)
219#define DA732X_BIAS3_LINE3_OUT_BIAS_MASK (7 << 4)
220#define DA732X_BIAS3_LINE3_OUT_BIAS_100PC (0 << 4)
221#define DA732X_BIAS3_LINE3_OUT_BIAS_125PC (1 << 4)
222#define DA732X_BIAS3_LINE3_OUT_BIAS_150PC (2 << 4)
223#define DA732X_BIAS3_LINE3_OUT_BIAS_175PC (3 << 4)
224#define DA732X_BIAS3_LINE3_OUT_BIAS_200PC (4 << 4)
225#define DA732X_BIAS3_LINE3_OUT_BIAS_250PC (5 << 4)
226#define DA732X_BIAS3_LINE3_OUT_BIAS_300PC (6 << 4)
227#define DA732X_BIAS3_LINE3_OUT_BIAS_350PC (7 << 4)
228
229/* DA732X_REG_BIAS4 (addr=0x07) */
230#define DA732X_BIAS4_LINE4_DAC_BIAS_MASK (3 << 0)
231#define DA732X_BIAS4_LINE4_DAC_BIAS_100PC (0 << 0)
232#define DA732X_BIAS4_LINE4_DAC_BIAS_150PC (1 << 0)
233#define DA732X_BIAS4_LINE4_DAC_BIAS_50PC (2 << 0)
234#define DA732X_BIAS4_LINE4_DAC_BIAS_75PC (3 << 0)
235#define DA732X_BIAS4_LINE4_OUT_BIAS_MASK (7 << 4)
236#define DA732X_BIAS4_LINE4_OUT_BIAS_100PC (0 << 4)
237#define DA732X_BIAS4_LINE4_OUT_BIAS_125PC (1 << 4)
238#define DA732X_BIAS4_LINE4_OUT_BIAS_150PC (2 << 4)
239#define DA732X_BIAS4_LINE4_OUT_BIAS_175PC (3 << 4)
240#define DA732X_BIAS4_LINE4_OUT_BIAS_200PC (4 << 4)
241#define DA732X_BIAS4_LINE4_OUT_BIAS_250PC (5 << 4)
242#define DA732X_BIAS4_LINE4_OUT_BIAS_300PC (6 << 4)
243#define DA732X_BIAS4_LINE4_OUT_BIAS_350PC (7 << 4)
244
245/* DA732X_REG_SIF_VDD_SEL (addr=0x08) */
246#define DA732X_SIF_VDD_SEL_AIFA_VDD2 (1 << 0)
247#define DA732X_SIF_VDD_SEL_AIFB_VDD2 (1 << 1)
248#define DA732X_SIF_VDD_SEL_CIFA_VDD2 (1 << 4)
249
250/* DA732X_REG_MICBIAS2/1 (addr=0x0F/0x10) */
251#define DA732X_MICBIAS_VOLTAGE_MASK (0x0F << 0)
252#define DA732X_MICBIAS_VOLTAGE_2V (0x00 << 0)
253#define DA732X_MICBIAS_VOLTAGE_2V05 (0x01 << 0)
254#define DA732X_MICBIAS_VOLTAGE_2V1 (0x02 << 0)
255#define DA732X_MICBIAS_VOLTAGE_2V15 (0x03 << 0)
256#define DA732X_MICBIAS_VOLTAGE_2V2 (0x04 << 0)
257#define DA732X_MICBIAS_VOLTAGE_2V25 (0x05 << 0)
258#define DA732X_MICBIAS_VOLTAGE_2V3 (0x06 << 0)
259#define DA732X_MICBIAS_VOLTAGE_2V35 (0x07 << 0)
260#define DA732X_MICBIAS_VOLTAGE_2V4 (0x08 << 0)
261#define DA732X_MICBIAS_VOLTAGE_2V45 (0x09 << 0)
262#define DA732X_MICBIAS_VOLTAGE_2V5 (0x0A << 0)
263#define DA732X_MICBIAS_EN (1 << 7)
264#define DA732X_MICBIAS_EN_SHIFT 7
265#define DA732X_MICBIAS_VOLTAGE_SHIFT 0
266#define DA732X_MICBIAS_VOLTAGE_MAX 0x0B
267
268/* DA732X_REG_MICDET (addr=0x11) */
269#define DA732X_MICDET_INP_MICRES (1 << 0)
270#define DA732X_MICDET_INP_MICHOOK (1 << 1)
271#define DA732X_MICDET_INP_DEBOUNCE_PRD_8MS (0 << 0)
272#define DA732X_MICDET_INP_DEBOUNCE_PRD_16MS (1 << 0)
273#define DA732X_MICDET_INP_DEBOUNCE_PRD_32MS (2 << 0)
274#define DA732X_MICDET_INP_DEBOUNCE_PRD_64MS (3 << 0)
275#define DA732X_MICDET_INP_MICDET_EN (1 << 7)
276
277/* DA732X_REG_MIC1/2/3_PRE (addr=0x11/0x14/0x18) */
278#define DA732X_MICBOOST_MASK 0x7
279#define DA732X_MICBOOST_SHIFT 0
280#define DA732X_MICBOOST_MIN 0x1
281#define DA732X_MICBOOST_MAX DA732X_MICBOOST_MASK
282
283/* DA732X_REG_MIC1/2/3 (addr=0x13/0x15/0x19) */
284#define DA732X_MIC_VOL_SHIFT 0
285#define DA732X_MIC_VOL_VAL_MASK 0x1F
286#define DA732X_MIC_MUTE_SHIFT 6
287#define DA732X_MIC_EN_SHIFT 7
288#define DA732X_MIC_VOL_VAL_MIN 0x7
289#define DA732X_MIC_VOL_VAL_MAX DA732X_MIC_VOL_VAL_MASK
290
291/* DA732X_REG_AUX1L/R (addr=0x16/0x17) */
292#define DA732X_AUX_VOL_SHIFT 0
293#define DA732X_AUX_VOL_MASK 0x7
294#define DA732X_AUX_MUTE_SHIFT 6
295#define DA732X_AUX_EN_SHIFT 7
296#define DA732X_AUX_VOL_VAL_MAX DA732X_AUX_VOL_MASK
297
298/* DA732X_REG_INP_PINBIAS (addr=0x1A) */
299#define DA732X_INP_MICL_PINBIAS_EN (1 << 0)
300#define DA732X_INP_MICR_PINBIAS_EN (1 << 1)
301#define DA732X_INP_AUX1L_PINBIAS_EN (1 << 2)
302#define DA732X_INP_AUX1R_PINBIAS_EN (1 << 3)
303#define DA732X_INP_AUX2_PINBIAS_EN (1 << 4)
304
305/* DA732X_REG_INP_ZC_EN (addr=0x1B) */
306#define DA732X_MIC1_PRE_ZC_EN (1 << 0)
307#define DA732X_MIC1_ZC_EN (1 << 1)
308#define DA732X_MIC2_PRE_ZC_EN (1 << 2)
309#define DA732X_MIC2_ZC_EN (1 << 3)
310#define DA732X_AUXL_ZC_EN (1 << 4)
311#define DA732X_AUXR_ZC_EN (1 << 5)
312#define DA732X_MIC3_PRE_ZC_EN (1 << 6)
313#define DA732X_MIC3_ZC_EN (1 << 7)
314
315/* DA732X_REG_INP_MUX (addr=0x1D) */
316#define DA732X_INP_ADC1L_MUX_SEL_AUX1L (0 << 0)
317#define DA732X_INP_ADC1L_MUX_SEL_MIC1 (1 << 0)
318#define DA732X_INP_ADC1R_MUX_SEL_MASK (3 << 2)
319#define DA732X_INP_ADC1R_MUX_SEL_AUX1R (0 << 2)
320#define DA732X_INP_ADC1R_MUX_SEL_MIC2 (1 << 2)
321#define DA732X_INP_ADC1R_MUX_SEL_MIC3 (2 << 2)
322#define DA732X_INP_ADC2L_MUX_SEL_AUX1L (0 << 4)
323#define DA732X_INP_ADC2L_MUX_SEL_MICL (1 << 4)
324#define DA732X_INP_ADC2R_MUX_SEL_MASK (3 << 6)
325#define DA732X_INP_ADC2R_MUX_SEL_AUX1R (0 << 6)
326#define DA732X_INP_ADC2R_MUX_SEL_MICR (1 << 6)
327#define DA732X_INP_ADC2R_MUX_SEL_AUX2 (2 << 6)
328#define DA732X_ADC1L_MUX_SEL_SHIFT 0
329#define DA732X_ADC1R_MUX_SEL_SHIFT 2
330#define DA732X_ADC2L_MUX_SEL_SHIFT 4
331#define DA732X_ADC2R_MUX_SEL_SHIFT 6
332
333/* DA732X_REG_HP_DET (addr=0x20) */
334#define DA732X_HP_DET_AZ (1 << 0)
335#define DA732X_HP_DET_SEL1 (1 << 1)
336#define DA732X_HP_DET_IS_MASK (3 << 2)
337#define DA732X_HP_DET_IS_0_5UA (0 << 2)
338#define DA732X_HP_DET_IS_1UA (1 << 2)
339#define DA732X_HP_DET_IS_2UA (2 << 2)
340#define DA732X_HP_DET_IS_4UA (3 << 2)
341#define DA732X_HP_DET_RS_MASK (3 << 4)
342#define DA732X_HP_DET_RS_INFINITE (0 << 4)
343#define DA732X_HP_DET_RS_100KOHM (1 << 4)
344#define DA732X_HP_DET_RS_10KOHM (2 << 4)
345#define DA732X_HP_DET_RS_1KOHM (3 << 4)
346#define DA732X_HP_DET_EN (1 << 7)
347
348/* DA732X_REG_HPL_DAC_OFFSET (addr=0x21/0x26) */
349#define DA732X_HP_DAC_OFFSET_TRIM_MASK (0x3F << 0)
350#define DA732X_HP_DAC_OFFSET_DAC_SIGN (1 << 6)
351
352/* DA732X_REG_HPL_DAC_OFF_CNTL (addr=0x22/0x27) */
353#define DA732X_HP_DAC_OFF_CNTL_CONT_MASK (7 << 0)
354#define DA732X_HP_DAC_OFF_CNTL_COMPO (1 << 3)
355#define DA732X_HP_DAC_OFF_CALIBRATION (1 << 0)
356#define DA732X_HP_DAC_OFF_SCALE_STEPS (1 << 1)
357#define DA732X_HP_DAC_OFF_MASK 0x7F
358#define DA732X_HP_DAC_COMPO_SHIFT 3
359
360/* DA732X_REG_HPL_OUT_OFFSET (addr=0x23/0x28) */
361#define DA732X_HP_OUT_OFFSET_MASK (0xFF << 0)
362#define DA732X_HP_DAC_OFFSET_TRIM_VAL 0x7F
363
364/* DA732X_REG_HPL/R (addr=0x24/0x29) */
365#define DA732X_HP_OUT_SIGN (1 << 0)
366#define DA732X_HP_OUT_COMP (1 << 1)
367#define DA732X_HP_OUT_RESERVED (1 << 2)
368#define DA732X_HP_OUT_COMPO (1 << 3)
369#define DA732X_HP_OUT_DAC_EN (1 << 4)
370#define DA732X_HP_OUT_HIZ_EN (1 << 5)
371#define DA732X_HP_OUT_HIZ_DIS (0 << 5)
372#define DA732X_HP_OUT_MUTE (1 << 6)
373#define DA732X_HP_OUT_EN (1 << 7)
374#define DA732X_HP_OUT_COMPO_SHIFT 3
375#define DA732X_HP_OUT_DAC_EN_SHIFT 4
376#define DA732X_HP_HIZ_SHIFT 5
377#define DA732X_HP_MUTE_SHIFT 6
378#define DA732X_HP_OUT_EN_SHIFT 7
379
380#define DA732X_OUT_HIZ_EN (1 << 5)
381#define DA732X_OUT_HIZ_DIS (0 << 5)
382
383/* DA732X_REG_HPL/R_VOL (addr=0x25/0x2A) */
384#define DA732X_HP_VOL_VAL_MASK 0xF
385#define DA732X_HP_VOL_SHIFT 0
386#define DA732X_HP_VOL_VAL_MAX DA732X_HP_VOL_VAL_MASK
387
388/* DA732X_REG_LIN2/3/4 (addr=0x2B/0x2C/0x2D) */
389#define DA732X_LOUT_VOL_SHIFT 0
390#define DA732X_LOUT_VOL_MASK 0x0F
391#define DA732X_LOUT_DAC_OFF (0 << 4)
392#define DA732X_LOUT_DAC_EN (1 << 4)
393#define DA732X_LOUT_HIZ_N_DIS (0 << 5)
394#define DA732X_LOUT_HIZ_N_EN (1 << 5)
395#define DA732X_LOUT_UNMUTED (0 << 6)
396#define DA732X_LOUT_MUTED (1 << 6)
397#define DA732X_LOUT_EN (0 << 7)
398#define DA732X_LOUT_DIS (1 << 7)
399#define DA732X_LOUT_DAC_EN_SHIFT 4
400#define DA732X_LOUT_MUTE_SHIFT 6
401#define DA732X_LIN_OUT_EN_SHIFT 7
402#define DA732X_LOUT_VOL_VAL_MAX DA732X_LOUT_VOL_MASK
403
404/* DA732X_REG_OUT_ZC_EN (addr=0x2E) */
405#define DA732X_HPL_ZC_EN_SHIFT 0
406#define DA732X_HPR_ZC_EN_SHIFT 1
407#define DA732X_HPL_ZC_EN (1 << 0)
408#define DA732X_HPL_ZC_DIS (0 << 0)
409#define DA732X_HPR_ZC_EN (1 << 1)
410#define DA732X_HPR_ZC_DIS (0 << 1)
411#define DA732X_LIN2_ZC_EN (1 << 2)
412#define DA732X_LIN2_ZC_DIS (0 << 2)
413#define DA732X_LIN3_ZC_EN (1 << 3)
414#define DA732X_LIN3_ZC_DIS (0 << 3)
415#define DA732X_LIN4_ZC_EN (1 << 4)
416#define DA732X_LIN4_ZC_DIS (0 << 4)
417
418/* DA732X_REG_HP_LIN1_GNDSEL (addr=0x37) */
419#define DA732X_HP_OUT_GNDSEL (1 << 0)
420
421/* DA732X_REG_CP_HP2 (addr=0x3a) */
422#define DA732X_HP_CP_PULSESKIP (1 << 0)
423#define DA732X_HP_CP_REG (1 << 1)
424#define DA732X_HP_CP_EN (1 << 3)
425#define DA732X_HP_CP_DIS (0 << 3)
426
427/* DA732X_REG_CP_CTRL1 (addr=0x40) */
428#define DA732X_CP_MODE_MASK (7 << 1)
429#define DA732X_CP_CTRL_STANDBY (0 << 1)
430#define DA732X_CP_CTRL_CPVDD6 (2 << 1)
431#define DA732X_CP_CTRL_CPVDD5 (3 << 1)
432#define DA732X_CP_CTRL_CPVDD4 (4 << 1)
433#define DA732X_CP_CTRL_CPVDD3 (5 << 1)
434#define DA732X_CP_CTRL_CPVDD2 (6 << 1)
435#define DA732X_CP_CTRL_CPVDD1 (7 << 1)
436#define DA723X_CP_DIS (0 << 7)
437#define DA732X_CP_EN (1 << 7)
438
439/* DA732X_REG_CP_CTRL2 (addr=0x41) */
440#define DA732X_CP_BOOST (1 << 0)
441#define DA732X_CP_MANAGE_MAGNITUDE (2 << 2)
442
443/* DA732X_REG_CP_CTRL3 (addr=0x42) */
444#define DA732X_CP_1MHZ (0 << 0)
445#define DA732X_CP_500KHZ (1 << 0)
446#define DA732X_CP_250KHZ (2 << 0)
447#define DA732X_CP_125KHZ (3 << 0)
448#define DA732X_CP_63KHZ (4 << 0)
449#define DA732X_CP_0KHZ (5 << 0)
450
451/* DA732X_REG_PLL_CTRL (addr=0x53) */
452#define DA732X_PLL_INDIV_MASK (3 << 0)
453#define DA732X_PLL_SRM_EN (1 << 2)
454#define DA732X_PLL_EN (1 << 7)
455#define DA732X_PLL_BYPASS (0 << 0)
456
457/* DA732X_REG_CLK_CTRL (addr=0x54) */
458#define DA732X_SR1_MASK (0xF)
459#define DA732X_SR2_MASK (0xF0)
460
461/* DA732X_REG_CLK_DSP (addr=0x5A) */
462#define DA732X_DSP_FREQ_MASK (7 << 0)
463#define DA732X_DSP_FREQ_12MHZ (0 << 0)
464#define DA732X_DSP_FREQ_24MHZ (1 << 0)
465#define DA732X_DSP_FREQ_36MHZ (2 << 0)
466#define DA732X_DSP_FREQ_48MHZ (3 << 0)
467#define DA732X_DSP_FREQ_60MHZ (4 << 0)
468#define DA732X_DSP_FREQ_72MHZ (5 << 0)
469#define DA732X_DSP_FREQ_84MHZ (6 << 0)
470#define DA732X_DSP_FREQ_96MHZ (7 << 0)
471
472/* DA732X_REG_CLK_EN1 (addr=0x5B) */
473#define DA732X_DSP_CLK_EN (1 << 0)
474#define DA732X_SYS3_CLK_EN (1 << 1)
475#define DA732X_DSP12_CLK_EN (1 << 2)
476#define DA732X_PC_CLK_EN (1 << 3)
477#define DA732X_MCLK_SQR_EN (1 << 7)
478
479/* DA732X_REG_CLK_EN2 (addr=0x5C) */
480#define DA732X_UART_CLK_EN (1 << 1)
481#define DA732X_CP_CLK_EN (1 << 2)
482#define DA732X_CP_CLK_DIS (0 << 2)
483
484/* DA732X_REG_CLK_EN3 (addr=0x5D) */
485#define DA732X_ADCA_BB_CLK_EN (1 << 0)
486#define DA732X_ADCC_BB_CLK_EN (1 << 4)
487
488/* DA732X_REG_CLK_EN4 (addr=0x5E) */
489#define DA732X_DACA_BB_CLK_EN (1 << 0)
490#define DA732X_DACC_BB_CLK_EN (1 << 4)
491#define DA732X_DACA_BB_CLK_SHIFT 0
492#define DA732X_DACC_BB_CLK_SHIFT 4
493
494/* DA732X_REG_CLK_EN5 (addr=0x5F) */
495#define DA732X_DACE_BB_CLK_EN (1 << 0)
496#define DA732X_DACE_BB_CLK_SHIFT 0
497
498/* DA732X_REG_AIF_MCLK (addr=0x60) */
499#define DA732X_AIFM_FRAME_64 (1 << 2)
500#define DA732X_AIFM_SRC_SEL_AIFA (1 << 6)
501#define DA732X_CLK_GENERATION_AIF_A (1 << 4)
502#define DA732X_NO_CLK_GENERATION 0x0
503
504/* DA732X_REG_AIFA1 (addr=0x61) */
505#define DA732X_AIF_WORD_MASK (0x3 << 0)
506#define DA732X_AIF_WORD_16 (0 << 0)
507#define DA732X_AIF_WORD_20 (1 << 0)
508#define DA732X_AIF_WORD_24 (2 << 0)
509#define DA732X_AIF_WORD_32 (3 << 0)
510#define DA732X_AIF_TDM_MONO_SHIFT (1 << 6)
511#define DA732X_AIF1_CLK_MASK (1 << 7)
512#define DA732X_AIF_SLAVE (0 << 7)
513#define DA732X_AIF_CLK_FROM_SRC (1 << 7)
514
515/* DA732X_REG_AIFA3 (addr=0x63) */
516#define DA732X_AIF_MODE_SHIFT 0
517#define DA732X_AIF_MODE_MASK 0x3
518#define DA732X_AIF_I2S_MODE (0 << 0)
519#define DA732X_AIF_LEFT_J_MODE (1 << 0)
520#define DA732X_AIF_RIGHT_J_MODE (2 << 0)
521#define DA732X_AIF_DSP_MODE (3 << 0)
522#define DA732X_AIF_WCLK_INV (1 << 4)
523#define DA732X_AIF_BCLK_INV (1 << 5)
524#define DA732X_AIF_EN (1 << 7)
525#define DA732X_AIF_EN_SHIFT 7
526
527/* DA732X_REG_PC_CTRL (addr=0x6a) */
528#define DA732X_PC_PULSE_AIFA (0 << 0)
529#define DA732X_PC_PULSE_AIFB (1 << 0)
530#define DA732X_PC_RESYNC_AUT (1 << 6)
531#define DA732X_PC_RESYNC_NOT_AUT (0 << 6)
532#define DA732X_PC_SAME (1 << 7)
533
534/* DA732X_REG_DATA_ROUTE (addr=0x70) */
535#define DA732X_ADC1_TO_AIFA (0 << 0)
536#define DA732X_DSP_TO_AIFA (1 << 0)
537#define DA732X_ADC2_TO_AIFB (0 << 1)
538#define DA732X_DSP_TO_AIFB (1 << 1)
539#define DA732X_AIFA_TO_DAC1L (0 << 2)
540#define DA732X_DSP_TO_DAC1L (1 << 2)
541#define DA732X_AIFA_TO_DAC1R (0 << 3)
542#define DA732X_DSP_TO_DAC1R (1 << 3)
543#define DA732X_AIFB_TO_DAC2L (0 << 4)
544#define DA732X_DSP_TO_DAC2L (1 << 4)
545#define DA732X_AIFB_TO_DAC2R (0 << 5)
546#define DA732X_DSP_TO_DAC2R (1 << 5)
547#define DA732X_AIFB_TO_DAC3 (0 << 6)
548#define DA732X_DSP_TO_DAC3 (1 << 6)
549#define DA732X_BYPASS_DSP (0 << 0)
550#define DA732X_ALL_TO_DSP (0x7F << 0)
551
552/* DA732X_REG_DSP_CTRL (addr=0x71) */
553#define DA732X_DIGITAL_EN (1 << 0)
554#define DA732X_DIGITAL_RESET (0 << 0)
555#define DA732X_DSP_CORE_EN (1 << 1)
556#define DA732X_DSP_CORE_RESET (0 << 1)
557
558/* DA732X_REG_SPARE1_OUT (addr=0x7D)*/
559#define DA732X_HP_DRIVER_EN (1 << 0)
560#define DA732X_HP_GATE_LOW (1 << 2)
561#define DA732X_HP_LOOP_GAIN_CTRL (1 << 3)
562
563/* DA732X_REG_ID (addr=0x81)*/
564#define DA732X_ID_MINOR_MASK (0xF << 0)
565#define DA732X_ID_MAJOR_MASK (0xF << 4)
566
567/* DA732X_REG_ADC1/2_PD (addr=0x90/0x98) */
568#define DA732X_ADC_RST_MASK (0x3 << 0)
569#define DA732X_ADC_PD_MASK (0x3 << 2)
570#define DA732X_ADC_SET_ACT (0x3 << 0)
571#define DA732X_ADC_SET_RST (0x0 << 0)
572#define DA732X_ADC_ON (0x3 << 2)
573#define DA732X_ADC_OFF (0x0 << 2)
574
575/* DA732X_REG_ADC1/2_SEL (addr=0x94/0x9C) */
576#define DA732X_ADC_VOL_VAL_MASK 0x7
577#define DA732X_ADCL_VOL_SHIFT 0
578#define DA732X_ADCR_VOL_SHIFT 4
579#define DA732X_ADCL_EN_SHIFT 2
580#define DA732X_ADCR_EN_SHIFT 3
581#define DA732X_ADCL_EN (1 << 2)
582#define DA732X_ADCR_EN (1 << 3)
583#define DA732X_ADC_VOL_VAL_MAX DA732X_ADC_VOL_VAL_MASK
584
585/*
586 * DA732X_REG_ADC1/2_HPF (addr=0x93/0x9b)
587 * DA732x_REG_DAC1/2/3_HPG (addr=0xA5/0xB5/0xC5)
588 */
589#define DA732X_HPF_MUSIC_EN (1 << 3)
590#define DA732X_HPF_VOICE_EN ((1 << 3) | (1 << 7))
591#define DA732X_HPF_MASK ((1 << 3) | (1 << 7))
592#define DA732X_HPF_DIS ((0 << 3) | (0 << 7))
593
594/* DA732X_REG_DAC1/2/3_VOL */
595#define DA732X_DAC_VOL_VAL_MASK 0x7F
596#define DA732X_DAC_VOL_SHIFT 0
597#define DA732X_DAC_VOL_VAL_MAX DA732X_DAC_VOL_VAL_MASK
598
599/* DA732X_REG_DAC1/2/3_SEL (addr=0xA3/0xB3/0xC3) */
600#define DA732X_DACL_EN_SHIFT 3
601#define DA732X_DACR_EN_SHIFT 7
602#define DA732X_DACL_MUTE_SHIFT 2
603#define DA732X_DACR_MUTE_SHIFT 6
604#define DA732X_DACL_EN (1 << 3)
605#define DA732X_DACR_EN (1 << 7)
606#define DA732X_DACL_SDM (1 << 0)
607#define DA732X_DACR_SDM (1 << 4)
608#define DA732X_DACL_MUTE (1 << 2)
609#define DA732X_DACR_MUTE (1 << 6)
610
611/* DA732X_REG_DAC_SOFTMUTE (addr=0xA4/0xB4/0xC4) */
612#define DA732X_SOFTMUTE_EN (1 << 7)
613#define DA732X_GAIN_RAMPED (1 << 6)
614#define DA732X_16_SAMPLES (4 << 0)
615#define DA732X_SOFTMUTE_MASK (1 << 7)
616#define DA732X_SOFTMUTE_SHIFT 7
617
618/*
619 * DA732x_REG_ADC1/2_EQ12 (addr=0x95/0x9D)
620 * DA732x_REG_ADC1/2_EQ34 (addr=0x96/0x9E)
621 * DA732x_REG_ADC1/2_EQ5 (addr=0x97/0x9F)
622 * DA732x_REG_DAC1/2/3_EQ12 (addr=0xA5/0xB5/0xC5)
623 * DA732x_REG_DAC1/2/3_EQ34 (addr=0xA6/0xB6/0xC6)
624 * DA732x_REG_DAC1/2/3_EQ5 (addr=0xA7/0xB7/0xB7)
625 */
626#define DA732X_EQ_VOL_VAL_MASK 0xF
627#define DA732X_EQ_BAND1_SHIFT 0
628#define DA732X_EQ_BAND2_SHIFT 4
629#define DA732X_EQ_BAND3_SHIFT 0
630#define DA732X_EQ_BAND4_SHIFT 4
631#define DA732X_EQ_BAND5_SHIFT 0
632#define DA732X_EQ_OVERALL_SHIFT 4
633#define DA732X_EQ_OVERALL_VOL_VAL_MASK 0x3
634#define DA732X_EQ_DIS (0 << 7)
635#define DA732X_EQ_EN (1 << 7)
636#define DA732X_EQ_EN_SHIFT 7
637#define DA732X_EQ_VOL_VAL_MAX DA732X_EQ_VOL_VAL_MASK
638#define DA732X_EQ_OVERALL_VOL_VAL_MAX DA732X_EQ_OVERALL_VOL_VAL_MASK
639
640/* DA732X_REG_DMA_CMD (addr=0xD3) */
641#define DA732X_SEL_DSP_DMA_MASK (3 << 0)
642#define DA732X_SEL_DSP_DMA_DIS (0 << 0)
643#define DA732X_SEL_DSP_DMA_PMEM (1 << 0)
644#define DA732X_SEL_DSP_DMA_XMEM (2 << 0)
645#define DA732X_SEL_DSP_DMA_YMEM (3 << 0)
646#define DA732X_DSP_RW_MASK (1 << 4)
647#define DA732X_DSP_DMA_WRITE (0 << 4)
648#define DA732X_DSP_DMA_READ (1 << 4)
649
650/* DA732X_REG_DMA_STATUS (addr=0xDA) */
651#define DA732X_DSP_DMA_FREE (0 << 0)
652#define DA732X_DSP_DMA_BUSY (1 << 0)
653
654#endif /* __DA732X_REG_H_ */
diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c
new file mode 100644
index 00000000000..5d8f39e3297
--- /dev/null
+++ b/sound/soc/codecs/isabelle.c
@@ -0,0 +1,1176 @@
1/*
2 * isabelle.c - Low power high fidelity audio codec driver
3 *
4 * Copyright (c) 2012 Texas Instruments, Inc
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 *
11 * Initially based on sound/soc/codecs/twl6040.c
12 *
13 */
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/version.h>
17#include <linux/kernel.h>
18#include <linux/init.h>
19#include <linux/delay.h>
20#include <linux/pm.h>
21#include <linux/regmap.h>
22#include <linux/i2c.h>
23#include <linux/slab.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/pcm_params.h>
27#include <sound/soc.h>
28#include <sound/soc-dapm.h>
29#include <sound/tlv.h>
30#include <sound/jack.h>
31#include <sound/initval.h>
32#include <asm/div64.h>
33#include "isabelle.h"
34
35
36/* Register default values for ISABELLE driver. */
37static struct reg_default isabelle_reg_defs[] = {
38 { 0, 0x00 },
39 { 1, 0x00 },
40 { 2, 0x00 },
41 { 3, 0x00 },
42 { 4, 0x00 },
43 { 5, 0x00 },
44 { 6, 0x00 },
45 { 7, 0x00 },
46 { 8, 0x00 },
47 { 9, 0x00 },
48 { 10, 0x00 },
49 { 11, 0x00 },
50 { 12, 0x00 },
51 { 13, 0x00 },
52 { 14, 0x00 },
53 { 15, 0x00 },
54 { 16, 0x00 },
55 { 17, 0x00 },
56 { 18, 0x00 },
57 { 19, 0x00 },
58 { 20, 0x00 },
59 { 21, 0x02 },
60 { 22, 0x02 },
61 { 23, 0x02 },
62 { 24, 0x02 },
63 { 25, 0x0F },
64 { 26, 0x8F },
65 { 27, 0x0F },
66 { 28, 0x8F },
67 { 29, 0x00 },
68 { 30, 0x00 },
69 { 31, 0x00 },
70 { 32, 0x00 },
71 { 33, 0x00 },
72 { 34, 0x00 },
73 { 35, 0x00 },
74 { 36, 0x00 },
75 { 37, 0x00 },
76 { 38, 0x00 },
77 { 39, 0x00 },
78 { 40, 0x00 },
79 { 41, 0x00 },
80 { 42, 0x00 },
81 { 43, 0x00 },
82 { 44, 0x00 },
83 { 45, 0x00 },
84 { 46, 0x00 },
85 { 47, 0x00 },
86 { 48, 0x00 },
87 { 49, 0x00 },
88 { 50, 0x00 },
89 { 51, 0x00 },
90 { 52, 0x00 },
91 { 53, 0x00 },
92 { 54, 0x00 },
93 { 55, 0x00 },
94 { 56, 0x00 },
95 { 57, 0x00 },
96 { 58, 0x00 },
97 { 59, 0x00 },
98 { 60, 0x00 },
99 { 61, 0x00 },
100 { 62, 0x00 },
101 { 63, 0x00 },
102 { 64, 0x00 },
103 { 65, 0x00 },
104 { 66, 0x00 },
105 { 67, 0x00 },
106 { 68, 0x00 },
107 { 69, 0x90 },
108 { 70, 0x90 },
109 { 71, 0x90 },
110 { 72, 0x00 },
111 { 73, 0x00 },
112 { 74, 0x00 },
113 { 75, 0x00 },
114 { 76, 0x00 },
115 { 77, 0x00 },
116 { 78, 0x00 },
117 { 79, 0x00 },
118 { 80, 0x00 },
119 { 81, 0x00 },
120 { 82, 0x00 },
121 { 83, 0x00 },
122 { 84, 0x00 },
123 { 85, 0x07 },
124 { 86, 0x00 },
125 { 87, 0x00 },
126 { 88, 0x00 },
127 { 89, 0x07 },
128 { 90, 0x80 },
129 { 91, 0x07 },
130 { 92, 0x07 },
131 { 93, 0x00 },
132 { 94, 0x00 },
133 { 95, 0x00 },
134 { 96, 0x00 },
135 { 97, 0x00 },
136 { 98, 0x00 },
137 { 99, 0x00 },
138};
139
140static const char *isabelle_rx1_texts[] = {"VRX1", "ARX1"};
141static const char *isabelle_rx2_texts[] = {"VRX2", "ARX2"};
142
143static const struct soc_enum isabelle_rx1_enum[] = {
144 SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 3, 1, isabelle_rx1_texts),
145 SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 5, 1, isabelle_rx1_texts),
146};
147
148static const struct soc_enum isabelle_rx2_enum[] = {
149 SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 2, 1, isabelle_rx2_texts),
150 SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 4, 1, isabelle_rx2_texts),
151};
152
153/* Headset DAC playback switches */
154static const struct snd_kcontrol_new rx1_mux_controls =
155 SOC_DAPM_ENUM("Route", isabelle_rx1_enum);
156
157static const struct snd_kcontrol_new rx2_mux_controls =
158 SOC_DAPM_ENUM("Route", isabelle_rx2_enum);
159
160/* TX input selection */
161static const char *isabelle_atx_texts[] = {"AMIC1", "DMIC"};
162static const char *isabelle_vtx_texts[] = {"AMIC2", "DMIC"};
163
164static const struct soc_enum isabelle_atx_enum[] = {
165 SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 7, 1, isabelle_atx_texts),
166 SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_atx_texts),
167};
168
169static const struct soc_enum isabelle_vtx_enum[] = {
170 SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 6, 1, isabelle_vtx_texts),
171 SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_vtx_texts),
172};
173
174static const struct snd_kcontrol_new atx_mux_controls =
175 SOC_DAPM_ENUM("Route", isabelle_atx_enum);
176
177static const struct snd_kcontrol_new vtx_mux_controls =
178 SOC_DAPM_ENUM("Route", isabelle_vtx_enum);
179
180/* Left analog microphone selection */
181static const char *isabelle_amic1_texts[] = {
182 "Main Mic", "Headset Mic", "Aux/FM Left"};
183
184/* Left analog microphone selection */
185static const char *isabelle_amic2_texts[] = {"Sub Mic", "Aux/FM Right"};
186
187static const struct soc_enum isabelle_amic1_enum[] = {
188 SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 5,
189 ARRAY_SIZE(isabelle_amic1_texts),
190 isabelle_amic1_texts),
191};
192
193static const struct soc_enum isabelle_amic2_enum[] = {
194 SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 4,
195 ARRAY_SIZE(isabelle_amic2_texts),
196 isabelle_amic2_texts),
197};
198
199static const struct snd_kcontrol_new amic1_control =
200 SOC_DAPM_ENUM("Route", isabelle_amic1_enum);
201
202static const struct snd_kcontrol_new amic2_control =
203 SOC_DAPM_ENUM("Route", isabelle_amic2_enum);
204
205static const char *isabelle_st_audio_texts[] = {"ATX1", "ATX2"};
206
207static const char *isabelle_st_voice_texts[] = {"VTX1", "VTX2"};
208
209static const struct soc_enum isabelle_st_audio_enum[] = {
210 SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA1_CFG_REG, 7, 1,
211 isabelle_st_audio_texts),
212 SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA2_CFG_REG, 7, 1,
213 isabelle_st_audio_texts),
214};
215
216static const struct soc_enum isabelle_st_voice_enum[] = {
217 SOC_ENUM_SINGLE(ISABELLE_VTX_STPGA1_CFG_REG, 7, 1,
218 isabelle_st_voice_texts),
219 SOC_ENUM_SINGLE(ISABELLE_VTX2_STPGA2_CFG_REG, 7, 1,
220 isabelle_st_voice_texts),
221};
222
223static const struct snd_kcontrol_new st_audio_control =
224 SOC_DAPM_ENUM("Route", isabelle_st_audio_enum);
225
226static const struct snd_kcontrol_new st_voice_control =
227 SOC_DAPM_ENUM("Route", isabelle_st_voice_enum);
228
229/* Mixer controls */
230static const struct snd_kcontrol_new isabelle_hs_left_mixer_controls[] = {
231SOC_DAPM_SINGLE("DAC1L Playback Switch", ISABELLE_HSDRV_CFG1_REG, 7, 1, 0),
232SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_HSDRV_CFG1_REG, 6, 1, 0),
233};
234
235static const struct snd_kcontrol_new isabelle_hs_right_mixer_controls[] = {
236SOC_DAPM_SINGLE("DAC1R Playback Switch", ISABELLE_HSDRV_CFG1_REG, 5, 1, 0),
237SOC_DAPM_SINGLE("APGA2 Playback Switch", ISABELLE_HSDRV_CFG1_REG, 4, 1, 0),
238};
239
240static const struct snd_kcontrol_new isabelle_hf_left_mixer_controls[] = {
241SOC_DAPM_SINGLE("DAC2L Playback Switch", ISABELLE_HFLPGA_CFG_REG, 7, 1, 0),
242SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_HFLPGA_CFG_REG, 6, 1, 0),
243};
244
245static const struct snd_kcontrol_new isabelle_hf_right_mixer_controls[] = {
246SOC_DAPM_SINGLE("DAC2R Playback Switch", ISABELLE_HFRPGA_CFG_REG, 7, 1, 0),
247SOC_DAPM_SINGLE("APGA2 Playback Switch", ISABELLE_HFRPGA_CFG_REG, 6, 1, 0),
248};
249
250static const struct snd_kcontrol_new isabelle_ep_mixer_controls[] = {
251SOC_DAPM_SINGLE("DAC2L Playback Switch", ISABELLE_EARDRV_CFG1_REG, 7, 1, 0),
252SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_EARDRV_CFG1_REG, 6, 1, 0),
253};
254
255static const struct snd_kcontrol_new isabelle_aux_left_mixer_controls[] = {
256SOC_DAPM_SINGLE("DAC3L Playback Switch", ISABELLE_LINEAMP_CFG_REG, 7, 1, 0),
257SOC_DAPM_SINGLE("APGA1 Playback Switch", ISABELLE_LINEAMP_CFG_REG, 6, 1, 0),
258};
259
260static const struct snd_kcontrol_new isabelle_aux_right_mixer_controls[] = {
261SOC_DAPM_SINGLE("DAC3R Playback Switch", ISABELLE_LINEAMP_CFG_REG, 5, 1, 0),
262SOC_DAPM_SINGLE("APGA2 Playback Switch", ISABELLE_LINEAMP_CFG_REG, 4, 1, 0),
263};
264
265static const struct snd_kcontrol_new isabelle_dpga1_left_mixer_controls[] = {
266SOC_DAPM_SINGLE("RX1 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 7, 1, 0),
267SOC_DAPM_SINGLE("RX3 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 6, 1, 0),
268SOC_DAPM_SINGLE("RX5 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 5, 1, 0),
269};
270
271static const struct snd_kcontrol_new isabelle_dpga1_right_mixer_controls[] = {
272SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 3, 1, 0),
273SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 2, 1, 0),
274SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA1LR_IN_SEL_REG, 1, 1, 0),
275};
276
277static const struct snd_kcontrol_new isabelle_dpga2_left_mixer_controls[] = {
278SOC_DAPM_SINGLE("RX1 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 7, 1, 0),
279SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 6, 1, 0),
280SOC_DAPM_SINGLE("RX3 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 5, 1, 0),
281SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 4, 1, 0),
282SOC_DAPM_SINGLE("RX5 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 3, 1, 0),
283SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA2L_IN_SEL_REG, 2, 1, 0),
284};
285
286static const struct snd_kcontrol_new isabelle_dpga2_right_mixer_controls[] = {
287SOC_DAPM_SINGLE("USNC Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 7, 1, 0),
288SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 3, 1, 0),
289SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 2, 1, 0),
290SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA2R_IN_SEL_REG, 1, 1, 0),
291};
292
293static const struct snd_kcontrol_new isabelle_dpga3_left_mixer_controls[] = {
294SOC_DAPM_SINGLE("RX1 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 7, 1, 0),
295SOC_DAPM_SINGLE("RX3 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 6, 1, 0),
296SOC_DAPM_SINGLE("RX5 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 5, 1, 0),
297};
298
299static const struct snd_kcontrol_new isabelle_dpga3_right_mixer_controls[] = {
300SOC_DAPM_SINGLE("RX2 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 3, 1, 0),
301SOC_DAPM_SINGLE("RX4 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 2, 1, 0),
302SOC_DAPM_SINGLE("RX6 Playback Switch", ISABELLE_DPGA3LR_IN_SEL_REG, 1, 1, 0),
303};
304
305static const struct snd_kcontrol_new isabelle_rx1_mixer_controls[] = {
306SOC_DAPM_SINGLE("ST1 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 7, 1, 0),
307SOC_DAPM_SINGLE("DL1 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 6, 1, 0),
308};
309
310static const struct snd_kcontrol_new isabelle_rx2_mixer_controls[] = {
311SOC_DAPM_SINGLE("ST2 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 5, 1, 0),
312SOC_DAPM_SINGLE("DL2 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 4, 1, 0),
313};
314
315static const struct snd_kcontrol_new isabelle_rx3_mixer_controls[] = {
316SOC_DAPM_SINGLE("ST1 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 3, 1, 0),
317SOC_DAPM_SINGLE("DL3 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 2, 1, 0),
318};
319
320static const struct snd_kcontrol_new isabelle_rx4_mixer_controls[] = {
321SOC_DAPM_SINGLE("ST2 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 1, 1, 0),
322SOC_DAPM_SINGLE("DL4 Playback Switch", ISABELLE_RX_INPUT_CFG_REG, 0, 1, 0),
323};
324
325static const struct snd_kcontrol_new isabelle_rx5_mixer_controls[] = {
326SOC_DAPM_SINGLE("ST1 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 7, 1, 0),
327SOC_DAPM_SINGLE("DL5 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 6, 1, 0),
328};
329
330static const struct snd_kcontrol_new isabelle_rx6_mixer_controls[] = {
331SOC_DAPM_SINGLE("ST2 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 5, 1, 0),
332SOC_DAPM_SINGLE("DL6 Playback Switch", ISABELLE_RX_INPUT_CFG2_REG, 4, 1, 0),
333};
334
335static const struct snd_kcontrol_new ep_path_enable_control =
336 SOC_DAPM_SINGLE("Switch", ISABELLE_EARDRV_CFG2_REG, 0, 1, 0);
337
338/* TLV Declarations */
339static const DECLARE_TLV_DB_SCALE(mic_amp_tlv, 0, 100, 0);
340static const DECLARE_TLV_DB_SCALE(afm_amp_tlv, -3300, 300, 0);
341static const DECLARE_TLV_DB_SCALE(dac_tlv, -1200, 200, 0);
342static const DECLARE_TLV_DB_SCALE(hf_tlv, -5000, 200, 0);
343
344/* from -63 to 0 dB in 1 dB steps */
345static const DECLARE_TLV_DB_SCALE(dpga_tlv, -6300, 100, 1);
346
347/* from -63 to 9 dB in 1 dB steps */
348static const DECLARE_TLV_DB_SCALE(rx_tlv, -6300, 100, 1);
349
350static const DECLARE_TLV_DB_SCALE(st_tlv, -2700, 300, 1);
351static const DECLARE_TLV_DB_SCALE(tx_tlv, -600, 100, 0);
352
353static const struct snd_kcontrol_new isabelle_snd_controls[] = {
354 SOC_DOUBLE_TLV("Headset Playback Volume", ISABELLE_HSDRV_GAIN_REG,
355 4, 0, 0xF, 0, dac_tlv),
356 SOC_DOUBLE_R_TLV("Handsfree Playback Volume",
357 ISABELLE_HFLPGA_CFG_REG, ISABELLE_HFRPGA_CFG_REG,
358 0, 0x1F, 0, hf_tlv),
359 SOC_DOUBLE_TLV("Aux Playback Volume", ISABELLE_LINEAMP_GAIN_REG,
360 4, 0, 0xF, 0, dac_tlv),
361 SOC_SINGLE_TLV("Earpiece Playback Volume", ISABELLE_EARDRV_CFG1_REG,
362 0, 0xF, 0, dac_tlv),
363
364 SOC_DOUBLE_TLV("Aux FM Volume", ISABELLE_APGA_GAIN_REG, 4, 0, 0xF, 0,
365 afm_amp_tlv),
366 SOC_SINGLE_TLV("Mic1 Capture Volume", ISABELLE_MIC1_GAIN_REG, 3, 0x1F,
367 0, mic_amp_tlv),
368 SOC_SINGLE_TLV("Mic2 Capture Volume", ISABELLE_MIC2_GAIN_REG, 3, 0x1F,
369 0, mic_amp_tlv),
370
371 SOC_DOUBLE_R_TLV("DPGA1 Volume", ISABELLE_DPGA1L_GAIN_REG,
372 ISABELLE_DPGA1R_GAIN_REG, 0, 0x3F, 0, dpga_tlv),
373 SOC_DOUBLE_R_TLV("DPGA2 Volume", ISABELLE_DPGA2L_GAIN_REG,
374 ISABELLE_DPGA2R_GAIN_REG, 0, 0x3F, 0, dpga_tlv),
375 SOC_DOUBLE_R_TLV("DPGA3 Volume", ISABELLE_DPGA3L_GAIN_REG,
376 ISABELLE_DPGA3R_GAIN_REG, 0, 0x3F, 0, dpga_tlv),
377
378 SOC_SINGLE_TLV("Sidetone Audio TX1 Volume",
379 ISABELLE_ATX_STPGA1_CFG_REG, 0, 0xF, 0, st_tlv),
380 SOC_SINGLE_TLV("Sidetone Audio TX2 Volume",
381 ISABELLE_ATX_STPGA2_CFG_REG, 0, 0xF, 0, st_tlv),
382 SOC_SINGLE_TLV("Sidetone Voice TX1 Volume",
383 ISABELLE_VTX_STPGA1_CFG_REG, 0, 0xF, 0, st_tlv),
384 SOC_SINGLE_TLV("Sidetone Voice TX2 Volume",
385 ISABELLE_VTX2_STPGA2_CFG_REG, 0, 0xF, 0, st_tlv),
386
387 SOC_SINGLE_TLV("Audio TX1 Volume", ISABELLE_ATX1_DPGA_REG, 4, 0xF, 0,
388 tx_tlv),
389 SOC_SINGLE_TLV("Audio TX2 Volume", ISABELLE_ATX2_DPGA_REG, 4, 0xF, 0,
390 tx_tlv),
391 SOC_SINGLE_TLV("Voice TX1 Volume", ISABELLE_VTX1_DPGA_REG, 4, 0xF, 0,
392 tx_tlv),
393 SOC_SINGLE_TLV("Voice TX2 Volume", ISABELLE_VTX2_DPGA_REG, 4, 0xF, 0,
394 tx_tlv),
395
396 SOC_SINGLE_TLV("RX1 DPGA Volume", ISABELLE_RX1_DPGA_REG, 0, 0x3F, 0,
397 rx_tlv),
398 SOC_SINGLE_TLV("RX2 DPGA Volume", ISABELLE_RX2_DPGA_REG, 0, 0x3F, 0,
399 rx_tlv),
400 SOC_SINGLE_TLV("RX3 DPGA Volume", ISABELLE_RX3_DPGA_REG, 0, 0x3F, 0,
401 rx_tlv),
402 SOC_SINGLE_TLV("RX4 DPGA Volume", ISABELLE_RX4_DPGA_REG, 0, 0x3F, 0,
403 rx_tlv),
404 SOC_SINGLE_TLV("RX5 DPGA Volume", ISABELLE_RX5_DPGA_REG, 0, 0x3F, 0,
405 rx_tlv),
406 SOC_SINGLE_TLV("RX6 DPGA Volume", ISABELLE_RX6_DPGA_REG, 0, 0x3F, 0,
407 rx_tlv),
408
409 SOC_SINGLE("Headset Noise Gate", ISABELLE_HS_NG_CFG1_REG, 7, 1, 0),
410 SOC_SINGLE("Handsfree Noise Gate", ISABELLE_HF_NG_CFG1_REG, 7, 1, 0),
411
412 SOC_SINGLE("ATX1 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
413 7, 1, 0),
414 SOC_SINGLE("ATX2 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
415 6, 1, 0),
416 SOC_SINGLE("ARX1 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
417 5, 1, 0),
418 SOC_SINGLE("ARX2 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
419 4, 1, 0),
420 SOC_SINGLE("ARX3 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
421 3, 1, 0),
422 SOC_SINGLE("ARX4 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
423 2, 1, 0),
424 SOC_SINGLE("ARX5 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
425 1, 1, 0),
426 SOC_SINGLE("ARX6 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
427 0, 1, 0),
428 SOC_SINGLE("VRX1 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
429 3, 1, 0),
430 SOC_SINGLE("VRX2 Filter Bypass Switch", ISABELLE_AUDIO_HPF_CFG_REG,
431 2, 1, 0),
432
433 SOC_SINGLE("ATX1 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG,
434 7, 1, 0),
435 SOC_SINGLE("ATX2 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG,
436 6, 1, 0),
437 SOC_SINGLE("VTX1 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG,
438 5, 1, 0),
439 SOC_SINGLE("VTX2 Filter Enable Switch", ISABELLE_ALU_TX_EN_REG,
440 4, 1, 0),
441 SOC_SINGLE("RX1 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG,
442 5, 1, 0),
443 SOC_SINGLE("RX2 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG,
444 4, 1, 0),
445 SOC_SINGLE("RX3 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG,
446 3, 1, 0),
447 SOC_SINGLE("RX4 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG,
448 2, 1, 0),
449 SOC_SINGLE("RX5 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG,
450 1, 1, 0),
451 SOC_SINGLE("RX6 Filter Enable Switch", ISABELLE_ALU_RX_EN_REG,
452 0, 1, 0),
453
454 SOC_SINGLE("ULATX12 Capture Switch", ISABELLE_ULATX12_INTF_CFG_REG,
455 7, 1, 0),
456
457 SOC_SINGLE("DL12 Playback Switch", ISABELLE_DL12_INTF_CFG_REG,
458 7, 1, 0),
459 SOC_SINGLE("DL34 Playback Switch", ISABELLE_DL34_INTF_CFG_REG,
460 7, 1, 0),
461 SOC_SINGLE("DL56 Playback Switch", ISABELLE_DL56_INTF_CFG_REG,
462 7, 1, 0),
463
464 /* DMIC Switch */
465 SOC_SINGLE("DMIC Switch", ISABELLE_DMIC_CFG_REG, 0, 1, 0),
466};
467
468static const struct snd_soc_dapm_widget isabelle_dapm_widgets[] = {
469 /* Inputs */
470 SND_SOC_DAPM_INPUT("MAINMIC"),
471 SND_SOC_DAPM_INPUT("HSMIC"),
472 SND_SOC_DAPM_INPUT("SUBMIC"),
473 SND_SOC_DAPM_INPUT("LINEIN1"),
474 SND_SOC_DAPM_INPUT("LINEIN2"),
475 SND_SOC_DAPM_INPUT("DMICDAT"),
476
477 /* Outputs */
478 SND_SOC_DAPM_OUTPUT("HSOL"),
479 SND_SOC_DAPM_OUTPUT("HSOR"),
480 SND_SOC_DAPM_OUTPUT("HFL"),
481 SND_SOC_DAPM_OUTPUT("HFR"),
482 SND_SOC_DAPM_OUTPUT("EP"),
483 SND_SOC_DAPM_OUTPUT("LINEOUT1"),
484 SND_SOC_DAPM_OUTPUT("LINEOUT2"),
485
486 SND_SOC_DAPM_PGA("DL1", SND_SOC_NOPM, 0, 0, NULL, 0),
487 SND_SOC_DAPM_PGA("DL2", SND_SOC_NOPM, 0, 0, NULL, 0),
488 SND_SOC_DAPM_PGA("DL3", SND_SOC_NOPM, 0, 0, NULL, 0),
489 SND_SOC_DAPM_PGA("DL4", SND_SOC_NOPM, 0, 0, NULL, 0),
490 SND_SOC_DAPM_PGA("DL5", SND_SOC_NOPM, 0, 0, NULL, 0),
491 SND_SOC_DAPM_PGA("DL6", SND_SOC_NOPM, 0, 0, NULL, 0),
492
493 /* Analog input muxes for the capture amplifiers */
494 SND_SOC_DAPM_MUX("Analog Left Capture Route",
495 SND_SOC_NOPM, 0, 0, &amic1_control),
496 SND_SOC_DAPM_MUX("Analog Right Capture Route",
497 SND_SOC_NOPM, 0, 0, &amic2_control),
498
499 SND_SOC_DAPM_MUX("Sidetone Audio Playback", SND_SOC_NOPM, 0, 0,
500 &st_audio_control),
501 SND_SOC_DAPM_MUX("Sidetone Voice Playback", SND_SOC_NOPM, 0, 0,
502 &st_voice_control),
503
504 /* AIF */
505 SND_SOC_DAPM_AIF_IN("INTF1_SDI", NULL, 0, ISABELLE_INTF_EN_REG, 7, 0),
506 SND_SOC_DAPM_AIF_IN("INTF2_SDI", NULL, 0, ISABELLE_INTF_EN_REG, 6, 0),
507
508 SND_SOC_DAPM_AIF_OUT("INTF1_SDO", NULL, 0, ISABELLE_INTF_EN_REG, 5, 0),
509 SND_SOC_DAPM_AIF_OUT("INTF2_SDO", NULL, 0, ISABELLE_INTF_EN_REG, 4, 0),
510
511 SND_SOC_DAPM_OUT_DRV("ULATX1", SND_SOC_NOPM, 0, 0, NULL, 0),
512 SND_SOC_DAPM_OUT_DRV("ULATX2", SND_SOC_NOPM, 0, 0, NULL, 0),
513 SND_SOC_DAPM_OUT_DRV("ULVTX1", SND_SOC_NOPM, 0, 0, NULL, 0),
514 SND_SOC_DAPM_OUT_DRV("ULVTX2", SND_SOC_NOPM, 0, 0, NULL, 0),
515
516 /* Analog Capture PGAs */
517 SND_SOC_DAPM_PGA("MicAmp1", ISABELLE_AMIC_CFG_REG, 5, 0, NULL, 0),
518 SND_SOC_DAPM_PGA("MicAmp2", ISABELLE_AMIC_CFG_REG, 4, 0, NULL, 0),
519
520 /* Auxiliary FM PGAs */
521 SND_SOC_DAPM_PGA("APGA1", ISABELLE_APGA_CFG_REG, 7, 0, NULL, 0),
522 SND_SOC_DAPM_PGA("APGA2", ISABELLE_APGA_CFG_REG, 6, 0, NULL, 0),
523
524 /* ADCs */
525 SND_SOC_DAPM_ADC("ADC1", "Left Front Capture",
526 ISABELLE_AMIC_CFG_REG, 7, 0),
527 SND_SOC_DAPM_ADC("ADC2", "Right Front Capture",
528 ISABELLE_AMIC_CFG_REG, 6, 0),
529
530 /* Microphone Bias */
531 SND_SOC_DAPM_SUPPLY("Headset Mic Bias", ISABELLE_ABIAS_CFG_REG,
532 3, 0, NULL, 0),
533 SND_SOC_DAPM_SUPPLY("Main Mic Bias", ISABELLE_ABIAS_CFG_REG,
534 2, 0, NULL, 0),
535 SND_SOC_DAPM_SUPPLY("Digital Mic1 Bias",
536 ISABELLE_DBIAS_CFG_REG, 3, 0, NULL, 0),
537 SND_SOC_DAPM_SUPPLY("Digital Mic2 Bias",
538 ISABELLE_DBIAS_CFG_REG, 2, 0, NULL, 0),
539
540 /* Mixers */
541 SND_SOC_DAPM_MIXER("Headset Left Mixer", SND_SOC_NOPM, 0, 0,
542 isabelle_hs_left_mixer_controls,
543 ARRAY_SIZE(isabelle_hs_left_mixer_controls)),
544 SND_SOC_DAPM_MIXER("Headset Right Mixer", SND_SOC_NOPM, 0, 0,
545 isabelle_hs_right_mixer_controls,
546 ARRAY_SIZE(isabelle_hs_right_mixer_controls)),
547 SND_SOC_DAPM_MIXER("Handsfree Left Mixer", SND_SOC_NOPM, 0, 0,
548 isabelle_hf_left_mixer_controls,
549 ARRAY_SIZE(isabelle_hf_left_mixer_controls)),
550 SND_SOC_DAPM_MIXER("Handsfree Right Mixer", SND_SOC_NOPM, 0, 0,
551 isabelle_hf_right_mixer_controls,
552 ARRAY_SIZE(isabelle_hf_right_mixer_controls)),
553 SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0,
554 isabelle_aux_left_mixer_controls,
555 ARRAY_SIZE(isabelle_aux_left_mixer_controls)),
556 SND_SOC_DAPM_MIXER("LINEOUT2 Mixer", SND_SOC_NOPM, 0, 0,
557 isabelle_aux_right_mixer_controls,
558 ARRAY_SIZE(isabelle_aux_right_mixer_controls)),
559 SND_SOC_DAPM_MIXER("Earphone Mixer", SND_SOC_NOPM, 0, 0,
560 isabelle_ep_mixer_controls,
561 ARRAY_SIZE(isabelle_ep_mixer_controls)),
562
563 SND_SOC_DAPM_MIXER("DPGA1L Mixer", SND_SOC_NOPM, 0, 0,
564 isabelle_dpga1_left_mixer_controls,
565 ARRAY_SIZE(isabelle_dpga1_left_mixer_controls)),
566 SND_SOC_DAPM_MIXER("DPGA1R Mixer", SND_SOC_NOPM, 0, 0,
567 isabelle_dpga1_right_mixer_controls,
568 ARRAY_SIZE(isabelle_dpga1_right_mixer_controls)),
569 SND_SOC_DAPM_MIXER("DPGA2L Mixer", SND_SOC_NOPM, 0, 0,
570 isabelle_dpga2_left_mixer_controls,
571 ARRAY_SIZE(isabelle_dpga2_left_mixer_controls)),
572 SND_SOC_DAPM_MIXER("DPGA2R Mixer", SND_SOC_NOPM, 0, 0,
573 isabelle_dpga2_right_mixer_controls,
574 ARRAY_SIZE(isabelle_dpga2_right_mixer_controls)),
575 SND_SOC_DAPM_MIXER("DPGA3L Mixer", SND_SOC_NOPM, 0, 0,
576 isabelle_dpga3_left_mixer_controls,
577 ARRAY_SIZE(isabelle_dpga3_left_mixer_controls)),
578 SND_SOC_DAPM_MIXER("DPGA3R Mixer", SND_SOC_NOPM, 0, 0,
579 isabelle_dpga3_right_mixer_controls,
580 ARRAY_SIZE(isabelle_dpga3_right_mixer_controls)),
581
582 SND_SOC_DAPM_MIXER("RX1 Mixer", SND_SOC_NOPM, 0, 0,
583 isabelle_rx1_mixer_controls,
584 ARRAY_SIZE(isabelle_rx1_mixer_controls)),
585 SND_SOC_DAPM_MIXER("RX2 Mixer", SND_SOC_NOPM, 0, 0,
586 isabelle_rx2_mixer_controls,
587 ARRAY_SIZE(isabelle_rx2_mixer_controls)),
588 SND_SOC_DAPM_MIXER("RX3 Mixer", SND_SOC_NOPM, 0, 0,
589 isabelle_rx3_mixer_controls,
590 ARRAY_SIZE(isabelle_rx3_mixer_controls)),
591 SND_SOC_DAPM_MIXER("RX4 Mixer", SND_SOC_NOPM, 0, 0,
592 isabelle_rx4_mixer_controls,
593 ARRAY_SIZE(isabelle_rx4_mixer_controls)),
594 SND_SOC_DAPM_MIXER("RX5 Mixer", SND_SOC_NOPM, 0, 0,
595 isabelle_rx5_mixer_controls,
596 ARRAY_SIZE(isabelle_rx5_mixer_controls)),
597 SND_SOC_DAPM_MIXER("RX6 Mixer", SND_SOC_NOPM, 0, 0,
598 isabelle_rx6_mixer_controls,
599 ARRAY_SIZE(isabelle_rx6_mixer_controls)),
600
601 /* DACs */
602 SND_SOC_DAPM_DAC("DAC1L", "Headset Playback", ISABELLE_DAC_CFG_REG,
603 5, 0),
604 SND_SOC_DAPM_DAC("DAC1R", "Headset Playback", ISABELLE_DAC_CFG_REG,
605 4, 0),
606 SND_SOC_DAPM_DAC("DAC2L", "Handsfree Playback", ISABELLE_DAC_CFG_REG,
607 3, 0),
608 SND_SOC_DAPM_DAC("DAC2R", "Handsfree Playback", ISABELLE_DAC_CFG_REG,
609 2, 0),
610 SND_SOC_DAPM_DAC("DAC3L", "Lineout Playback", ISABELLE_DAC_CFG_REG,
611 1, 0),
612 SND_SOC_DAPM_DAC("DAC3R", "Lineout Playback", ISABELLE_DAC_CFG_REG,
613 0, 0),
614
615 /* Analog Playback PGAs */
616 SND_SOC_DAPM_PGA("Sidetone Audio PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
617 SND_SOC_DAPM_PGA("Sidetone Voice PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
618 SND_SOC_DAPM_PGA("HF Left PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
619 SND_SOC_DAPM_PGA("HF Right PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
620 SND_SOC_DAPM_PGA("DPGA1L", SND_SOC_NOPM, 0, 0, NULL, 0),
621 SND_SOC_DAPM_PGA("DPGA1R", SND_SOC_NOPM, 0, 0, NULL, 0),
622 SND_SOC_DAPM_PGA("DPGA2L", SND_SOC_NOPM, 0, 0, NULL, 0),
623 SND_SOC_DAPM_PGA("DPGA2R", SND_SOC_NOPM, 0, 0, NULL, 0),
624 SND_SOC_DAPM_PGA("DPGA3L", SND_SOC_NOPM, 0, 0, NULL, 0),
625 SND_SOC_DAPM_PGA("DPGA3R", SND_SOC_NOPM, 0, 0, NULL, 0),
626
627 /* Analog Playback Mux */
628 SND_SOC_DAPM_MUX("RX1 Playback", ISABELLE_ALU_RX_EN_REG, 5, 0,
629 &rx1_mux_controls),
630 SND_SOC_DAPM_MUX("RX2 Playback", ISABELLE_ALU_RX_EN_REG, 4, 0,
631 &rx2_mux_controls),
632
633 /* TX Select */
634 SND_SOC_DAPM_MUX("ATX Select", ISABELLE_TX_INPUT_CFG_REG,
635 7, 0, &atx_mux_controls),
636 SND_SOC_DAPM_MUX("VTX Select", ISABELLE_TX_INPUT_CFG_REG,
637 6, 0, &vtx_mux_controls),
638
639 SND_SOC_DAPM_SWITCH("Earphone Playback", SND_SOC_NOPM, 0, 0,
640 &ep_path_enable_control),
641
642 /* Output Drivers */
643 SND_SOC_DAPM_OUT_DRV("HS Left Driver", ISABELLE_HSDRV_CFG2_REG,
644 1, 0, NULL, 0),
645 SND_SOC_DAPM_OUT_DRV("HS Right Driver", ISABELLE_HSDRV_CFG2_REG,
646 0, 0, NULL, 0),
647 SND_SOC_DAPM_OUT_DRV("LINEOUT1 Left Driver", ISABELLE_LINEAMP_CFG_REG,
648 1, 0, NULL, 0),
649 SND_SOC_DAPM_OUT_DRV("LINEOUT2 Right Driver", ISABELLE_LINEAMP_CFG_REG,
650 0, 0, NULL, 0),
651 SND_SOC_DAPM_OUT_DRV("Earphone Driver", ISABELLE_EARDRV_CFG2_REG,
652 1, 0, NULL, 0),
653
654 SND_SOC_DAPM_OUT_DRV("HF Left Driver", ISABELLE_HFDRV_CFG_REG,
655 1, 0, NULL, 0),
656 SND_SOC_DAPM_OUT_DRV("HF Right Driver", ISABELLE_HFDRV_CFG_REG,
657 0, 0, NULL, 0),
658};
659
660static const struct snd_soc_dapm_route isabelle_intercon[] = {
661 /* Interface mapping */
662 { "DL1", "DL12 Playback Switch", "INTF1_SDI" },
663 { "DL2", "DL12 Playback Switch", "INTF1_SDI" },
664 { "DL3", "DL34 Playback Switch", "INTF1_SDI" },
665 { "DL4", "DL34 Playback Switch", "INTF1_SDI" },
666 { "DL5", "DL56 Playback Switch", "INTF1_SDI" },
667 { "DL6", "DL56 Playback Switch", "INTF1_SDI" },
668
669 { "DL1", "DL12 Playback Switch", "INTF2_SDI" },
670 { "DL2", "DL12 Playback Switch", "INTF2_SDI" },
671 { "DL3", "DL34 Playback Switch", "INTF2_SDI" },
672 { "DL4", "DL34 Playback Switch", "INTF2_SDI" },
673 { "DL5", "DL56 Playback Switch", "INTF2_SDI" },
674 { "DL6", "DL56 Playback Switch", "INTF2_SDI" },
675
676 /* Input side mapping */
677 { "Sidetone Audio PGA", NULL, "Sidetone Audio Playback" },
678 { "Sidetone Voice PGA", NULL, "Sidetone Voice Playback" },
679
680 { "RX1 Mixer", "ST1 Playback Switch", "Sidetone Audio PGA" },
681
682 { "RX1 Mixer", "ST1 Playback Switch", "Sidetone Voice PGA" },
683 { "RX1 Mixer", "DL1 Playback Switch", "DL1" },
684
685 { "RX2 Mixer", "ST2 Playback Switch", "Sidetone Audio PGA" },
686
687 { "RX2 Mixer", "ST2 Playback Switch", "Sidetone Voice PGA" },
688 { "RX2 Mixer", "DL2 Playback Switch", "DL2" },
689
690 { "RX3 Mixer", "ST1 Playback Switch", "Sidetone Voice PGA" },
691 { "RX3 Mixer", "DL3 Playback Switch", "DL3" },
692
693 { "RX4 Mixer", "ST2 Playback Switch", "Sidetone Voice PGA" },
694 { "RX4 Mixer", "DL4 Playback Switch", "DL4" },
695
696 { "RX5 Mixer", "ST1 Playback Switch", "Sidetone Voice PGA" },
697 { "RX5 Mixer", "DL5 Playback Switch", "DL5" },
698
699 { "RX6 Mixer", "ST2 Playback Switch", "Sidetone Voice PGA" },
700 { "RX6 Mixer", "DL6 Playback Switch", "DL6" },
701
702 /* Capture path */
703 { "Analog Left Capture Route", "Headset Mic", "HSMIC" },
704 { "Analog Left Capture Route", "Main Mic", "MAINMIC" },
705 { "Analog Left Capture Route", "Aux/FM Left", "LINEIN1" },
706
707 { "Analog Right Capture Route", "Sub Mic", "SUBMIC" },
708 { "Analog Right Capture Route", "Aux/FM Right", "LINEIN2" },
709
710 { "MicAmp1", NULL, "Analog Left Capture Route" },
711 { "MicAmp2", NULL, "Analog Right Capture Route" },
712
713 { "ADC1", NULL, "MicAmp1" },
714 { "ADC2", NULL, "MicAmp2" },
715
716 { "ATX Select", "AMIC1", "ADC1" },
717 { "ATX Select", "DMIC", "DMICDAT" },
718 { "ATX Select", "AMIC2", "ADC2" },
719
720 { "VTX Select", "AMIC1", "ADC1" },
721 { "VTX Select", "DMIC", "DMICDAT" },
722 { "VTX Select", "AMIC2", "ADC2" },
723
724 { "ULATX1", "ATX1 Filter Enable Switch", "ATX Select" },
725 { "ULATX1", "ATX1 Filter Bypass Switch", "ATX Select" },
726 { "ULATX2", "ATX2 Filter Enable Switch", "ATX Select" },
727 { "ULATX2", "ATX2 Filter Bypass Switch", "ATX Select" },
728
729 { "ULVTX1", "VTX1 Filter Enable Switch", "VTX Select" },
730 { "ULVTX1", "VTX1 Filter Bypass Switch", "VTX Select" },
731 { "ULVTX2", "VTX2 Filter Enable Switch", "VTX Select" },
732 { "ULVTX2", "VTX2 Filter Bypass Switch", "VTX Select" },
733
734 { "INTF1_SDO", "ULATX12 Capture Switch", "ULATX1" },
735 { "INTF1_SDO", "ULATX12 Capture Switch", "ULATX2" },
736 { "INTF2_SDO", "ULATX12 Capture Switch", "ULATX1" },
737 { "INTF2_SDO", "ULATX12 Capture Switch", "ULATX2" },
738
739 { "INTF1_SDO", NULL, "ULVTX1" },
740 { "INTF1_SDO", NULL, "ULVTX2" },
741 { "INTF2_SDO", NULL, "ULVTX1" },
742 { "INTF2_SDO", NULL, "ULVTX2" },
743
744 /* AFM Path */
745 { "APGA1", NULL, "LINEIN1" },
746 { "APGA2", NULL, "LINEIN2" },
747
748 { "RX1 Playback", "VRX1 Filter Bypass Switch", "RX1 Mixer" },
749 { "RX1 Playback", "ARX1 Filter Bypass Switch", "RX1 Mixer" },
750 { "RX1 Playback", "RX1 Filter Enable Switch", "RX1 Mixer" },
751
752 { "RX2 Playback", "VRX2 Filter Bypass Switch", "RX2 Mixer" },
753 { "RX2 Playback", "ARX2 Filter Bypass Switch", "RX2 Mixer" },
754 { "RX2 Playback", "RX2 Filter Enable Switch", "RX2 Mixer" },
755
756 { "RX3 Playback", "ARX3 Filter Bypass Switch", "RX3 Mixer" },
757 { "RX3 Playback", "RX3 Filter Enable Switch", "RX3 Mixer" },
758
759 { "RX4 Playback", "ARX4 Filter Bypass Switch", "RX4 Mixer" },
760 { "RX4 Playback", "RX4 Filter Enable Switch", "RX4 Mixer" },
761
762 { "RX5 Playback", "ARX5 Filter Bypass Switch", "RX5 Mixer" },
763 { "RX5 Playback", "RX5 Filter Enable Switch", "RX5 Mixer" },
764
765 { "RX6 Playback", "ARX6 Filter Bypass Switch", "RX6 Mixer" },
766 { "RX6 Playback", "RX6 Filter Enable Switch", "RX6 Mixer" },
767
768 { "DPGA1L Mixer", "RX1 Playback Switch", "RX1 Playback" },
769 { "DPGA1L Mixer", "RX3 Playback Switch", "RX3 Playback" },
770 { "DPGA1L Mixer", "RX5 Playback Switch", "RX5 Playback" },
771
772 { "DPGA1R Mixer", "RX2 Playback Switch", "RX2 Playback" },
773 { "DPGA1R Mixer", "RX4 Playback Switch", "RX4 Playback" },
774 { "DPGA1R Mixer", "RX6 Playback Switch", "RX6 Playback" },
775
776 { "DPGA1L", NULL, "DPGA1L Mixer" },
777 { "DPGA1R", NULL, "DPGA1R Mixer" },
778
779 { "DAC1L", NULL, "DPGA1L" },
780 { "DAC1R", NULL, "DPGA1R" },
781
782 { "DPGA2L Mixer", "RX1 Playback Switch", "RX1 Playback" },
783 { "DPGA2L Mixer", "RX2 Playback Switch", "RX2 Playback" },
784 { "DPGA2L Mixer", "RX3 Playback Switch", "RX3 Playback" },
785 { "DPGA2L Mixer", "RX4 Playback Switch", "RX4 Playback" },
786 { "DPGA2L Mixer", "RX5 Playback Switch", "RX5 Playback" },
787 { "DPGA2L Mixer", "RX6 Playback Switch", "RX6 Playback" },
788
789 { "DPGA2R Mixer", "RX2 Playback Switch", "RX2 Playback" },
790 { "DPGA2R Mixer", "RX4 Playback Switch", "RX4 Playback" },
791 { "DPGA2R Mixer", "RX6 Playback Switch", "RX6 Playback" },
792
793 { "DPGA2L", NULL, "DPGA2L Mixer" },
794 { "DPGA2R", NULL, "DPGA2R Mixer" },
795
796 { "DAC2L", NULL, "DPGA2L" },
797 { "DAC2R", NULL, "DPGA2R" },
798
799 { "DPGA3L Mixer", "RX1 Playback Switch", "RX1 Playback" },
800 { "DPGA3L Mixer", "RX3 Playback Switch", "RX3 Playback" },
801 { "DPGA3L Mixer", "RX5 Playback Switch", "RX5 Playback" },
802
803 { "DPGA3R Mixer", "RX2 Playback Switch", "RX2 Playback" },
804 { "DPGA3R Mixer", "RX4 Playback Switch", "RX4 Playback" },
805 { "DPGA3R Mixer", "RX6 Playback Switch", "RX6 Playback" },
806
807 { "DPGA3L", NULL, "DPGA3L Mixer" },
808 { "DPGA3R", NULL, "DPGA3R Mixer" },
809
810 { "DAC3L", NULL, "DPGA3L" },
811 { "DAC3R", NULL, "DPGA3R" },
812
813 { "Headset Left Mixer", "DAC1L Playback Switch", "DAC1L" },
814 { "Headset Left Mixer", "APGA1 Playback Switch", "APGA1" },
815
816 { "Headset Right Mixer", "DAC1R Playback Switch", "DAC1R" },
817 { "Headset Right Mixer", "APGA2 Playback Switch", "APGA2" },
818
819 { "HS Left Driver", NULL, "Headset Left Mixer" },
820 { "HS Right Driver", NULL, "Headset Right Mixer" },
821
822 { "HSOL", NULL, "HS Left Driver" },
823 { "HSOR", NULL, "HS Right Driver" },
824
825 /* Earphone playback path */
826 { "Earphone Mixer", "DAC2L Playback Switch", "DAC2L" },
827 { "Earphone Mixer", "APGA1 Playback Switch", "APGA1" },
828
829 { "Earphone Playback", "Switch", "Earphone Mixer" },
830 { "Earphone Driver", NULL, "Earphone Playback" },
831 { "EP", NULL, "Earphone Driver" },
832
833 { "Handsfree Left Mixer", "DAC2L Playback Switch", "DAC2L" },
834 { "Handsfree Left Mixer", "APGA1 Playback Switch", "APGA1" },
835
836 { "Handsfree Right Mixer", "DAC2R Playback Switch", "DAC2R" },
837 { "Handsfree Right Mixer", "APGA2 Playback Switch", "APGA2" },
838
839 { "HF Left PGA", NULL, "Handsfree Left Mixer" },
840 { "HF Right PGA", NULL, "Handsfree Right Mixer" },
841
842 { "HF Left Driver", NULL, "HF Left PGA" },
843 { "HF Right Driver", NULL, "HF Right PGA" },
844
845 { "HFL", NULL, "HF Left Driver" },
846 { "HFR", NULL, "HF Right Driver" },
847
848 { "LINEOUT1 Mixer", "DAC3L Playback Switch", "DAC3L" },
849 { "LINEOUT1 Mixer", "APGA1 Playback Switch", "APGA1" },
850
851 { "LINEOUT2 Mixer", "DAC3R Playback Switch", "DAC3R" },
852 { "LINEOUT2 Mixer", "APGA2 Playback Switch", "APGA2" },
853
854 { "LINEOUT1 Driver", NULL, "LINEOUT1 Mixer" },
855 { "LINEOUT2 Driver", NULL, "LINEOUT2 Mixer" },
856
857 { "LINEOUT1", NULL, "LINEOUT1 Driver" },
858 { "LINEOUT2", NULL, "LINEOUT2 Driver" },
859};
860
861static int isabelle_hs_mute(struct snd_soc_dai *dai, int mute)
862{
863 snd_soc_update_bits(dai->codec, ISABELLE_DAC1_SOFTRAMP_REG,
864 BIT(4), (mute ? BIT(4) : 0));
865
866 return 0;
867}
868
869static int isabelle_hf_mute(struct snd_soc_dai *dai, int mute)
870{
871 snd_soc_update_bits(dai->codec, ISABELLE_DAC2_SOFTRAMP_REG,
872 BIT(4), (mute ? BIT(4) : 0));
873
874 return 0;
875}
876
877static int isabelle_line_mute(struct snd_soc_dai *dai, int mute)
878{
879 snd_soc_update_bits(dai->codec, ISABELLE_DAC3_SOFTRAMP_REG,
880 BIT(4), (mute ? BIT(4) : 0));
881
882 return 0;
883}
884
885static int isabelle_set_bias_level(struct snd_soc_codec *codec,
886 enum snd_soc_bias_level level)
887{
888 switch (level) {
889 case SND_SOC_BIAS_ON:
890 break;
891 case SND_SOC_BIAS_PREPARE:
892 break;
893
894 case SND_SOC_BIAS_STANDBY:
895 snd_soc_update_bits(codec, ISABELLE_PWR_EN_REG,
896 ISABELLE_CHIP_EN, BIT(0));
897 break;
898
899 case SND_SOC_BIAS_OFF:
900 snd_soc_update_bits(codec, ISABELLE_PWR_EN_REG,
901 ISABELLE_CHIP_EN, 0);
902 break;
903 }
904
905 codec->dapm.bias_level = level;
906
907 return 0;
908}
909
910static int isabelle_hw_params(struct snd_pcm_substream *substream,
911 struct snd_pcm_hw_params *params,
912 struct snd_soc_dai *dai)
913{
914 struct snd_soc_pcm_runtime *rtd = substream->private_data;
915 struct snd_soc_codec *codec = rtd->codec;
916 u16 aif = 0;
917 unsigned int fs_val = 0;
918
919 switch (params_rate(params)) {
920 case 8000:
921 fs_val = ISABELLE_FS_RATE_8;
922 break;
923 case 11025:
924 fs_val = ISABELLE_FS_RATE_11;
925 break;
926 case 12000:
927 fs_val = ISABELLE_FS_RATE_12;
928 break;
929 case 16000:
930 fs_val = ISABELLE_FS_RATE_16;
931 break;
932 case 22050:
933 fs_val = ISABELLE_FS_RATE_22;
934 break;
935 case 24000:
936 fs_val = ISABELLE_FS_RATE_24;
937 break;
938 case 32000:
939 fs_val = ISABELLE_FS_RATE_32;
940 break;
941 case 44100:
942 fs_val = ISABELLE_FS_RATE_44;
943 break;
944 case 48000:
945 fs_val = ISABELLE_FS_RATE_48;
946 break;
947 default:
948 return -EINVAL;
949 }
950
951 snd_soc_update_bits(codec, ISABELLE_FS_RATE_CFG_REG,
952 ISABELLE_FS_RATE_MASK, fs_val);
953
954 /* bit size */
955 switch (params_format(params)) {
956 case SNDRV_PCM_FORMAT_S20_3LE:
957 aif |= ISABELLE_AIF_LENGTH_20;
958 break;
959 case SNDRV_PCM_FORMAT_S32_LE:
960 aif |= ISABELLE_AIF_LENGTH_32;
961 break;
962 default:
963 return -EINVAL;
964 }
965
966 snd_soc_update_bits(codec, ISABELLE_INTF_CFG_REG,
967 ISABELLE_AIF_LENGTH_MASK, aif);
968
969 return 0;
970}
971
972static int isabelle_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
973{
974 struct snd_soc_codec *codec = codec_dai->codec;
975 unsigned int aif_val = 0;
976
977 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
978 case SND_SOC_DAIFMT_CBS_CFS:
979 aif_val &= ~ISABELLE_AIF_MS;
980 break;
981 case SND_SOC_DAIFMT_CBM_CFM:
982 aif_val |= ISABELLE_AIF_MS;
983 break;
984 default:
985 return -EINVAL;
986 }
987
988 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
989 case SND_SOC_DAIFMT_I2S:
990 aif_val |= ISABELLE_I2S_MODE;
991 break;
992 case SND_SOC_DAIFMT_LEFT_J:
993 aif_val |= ISABELLE_LEFT_J_MODE;
994 break;
995 case SND_SOC_DAIFMT_PDM:
996 aif_val |= ISABELLE_PDM_MODE;
997 break;
998 default:
999 return -EINVAL;
1000 }
1001
1002 snd_soc_update_bits(codec, ISABELLE_INTF_CFG_REG,
1003 (ISABELLE_AIF_MS | ISABELLE_AIF_FMT_MASK), aif_val);
1004
1005 return 0;
1006}
1007
1008/* Rates supported by Isabelle driver */
1009#define ISABELLE_RATES SNDRV_PCM_RATE_8000_48000
1010
1011/* Formates supported by Isabelle driver. */
1012#define ISABELLE_FORMATS (SNDRV_PCM_FMTBIT_S20_3LE |\
1013 SNDRV_PCM_FMTBIT_S32_LE)
1014
1015static struct snd_soc_dai_ops isabelle_hs_dai_ops = {
1016 .hw_params = isabelle_hw_params,
1017 .set_fmt = isabelle_set_dai_fmt,
1018 .digital_mute = isabelle_hs_mute,
1019};
1020
1021static struct snd_soc_dai_ops isabelle_hf_dai_ops = {
1022 .hw_params = isabelle_hw_params,
1023 .set_fmt = isabelle_set_dai_fmt,
1024 .digital_mute = isabelle_hf_mute,
1025};
1026
1027static struct snd_soc_dai_ops isabelle_line_dai_ops = {
1028 .hw_params = isabelle_hw_params,
1029 .set_fmt = isabelle_set_dai_fmt,
1030 .digital_mute = isabelle_line_mute,
1031};
1032
1033static struct snd_soc_dai_ops isabelle_ul_dai_ops = {
1034 .hw_params = isabelle_hw_params,
1035 .set_fmt = isabelle_set_dai_fmt,
1036};
1037
1038/* ISABELLE dai structure */
1039static struct snd_soc_dai_driver isabelle_dai[] = {
1040 {
1041 .name = "isabelle-dl1",
1042 .playback = {
1043 .stream_name = "Headset Playback",
1044 .channels_min = 1,
1045 .channels_max = 2,
1046 .rates = ISABELLE_RATES,
1047 .formats = ISABELLE_FORMATS,
1048 },
1049 .ops = &isabelle_hs_dai_ops,
1050 },
1051 {
1052 .name = "isabelle-dl2",
1053 .playback = {
1054 .stream_name = "Handsfree Playback",
1055 .channels_min = 1,
1056 .channels_max = 2,
1057 .rates = ISABELLE_RATES,
1058 .formats = ISABELLE_FORMATS,
1059 },
1060 .ops = &isabelle_hf_dai_ops,
1061 },
1062 {
1063 .name = "isabelle-lineout",
1064 .playback = {
1065 .stream_name = "Lineout Playback",
1066 .channels_min = 1,
1067 .channels_max = 2,
1068 .rates = ISABELLE_RATES,
1069 .formats = ISABELLE_FORMATS,
1070 },
1071 .ops = &isabelle_line_dai_ops,
1072 },
1073 {
1074 .name = "isabelle-ul",
1075 .capture = {
1076 .stream_name = "Capture",
1077 .channels_min = 1,
1078 .channels_max = 2,
1079 .rates = ISABELLE_RATES,
1080 .formats = ISABELLE_FORMATS,
1081 },
1082 .ops = &isabelle_ul_dai_ops,
1083 },
1084};
1085
1086static int isabelle_probe(struct snd_soc_codec *codec)
1087{
1088 int ret = 0;
1089
1090 codec->control_data = dev_get_regmap(codec->dev, NULL);
1091
1092 ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
1093 if (ret < 0) {
1094 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1095 return ret;
1096 }
1097
1098 return 0;
1099}
1100
1101static struct snd_soc_codec_driver soc_codec_dev_isabelle = {
1102 .probe = isabelle_probe,
1103 .set_bias_level = isabelle_set_bias_level,
1104 .controls = isabelle_snd_controls,
1105 .num_controls = ARRAY_SIZE(isabelle_snd_controls),
1106 .dapm_widgets = isabelle_dapm_widgets,
1107 .num_dapm_widgets = ARRAY_SIZE(isabelle_dapm_widgets),
1108 .dapm_routes = isabelle_intercon,
1109 .num_dapm_routes = ARRAY_SIZE(isabelle_intercon),
1110 .idle_bias_off = true,
1111};
1112
1113static const struct regmap_config isabelle_regmap_config = {
1114 .reg_bits = 8,
1115 .val_bits = 8,
1116
1117 .max_register = ISABELLE_MAX_REGISTER,
1118 .reg_defaults = isabelle_reg_defs,
1119 .num_reg_defaults = ARRAY_SIZE(isabelle_reg_defs),
1120 .cache_type = REGCACHE_RBTREE,
1121};
1122
1123static int __devinit isabelle_i2c_probe(struct i2c_client *i2c,
1124 const struct i2c_device_id *id)
1125{
1126 struct regmap *isabelle_regmap;
1127 int ret = 0;
1128
1129 isabelle_regmap = devm_regmap_init_i2c(i2c, &isabelle_regmap_config);
1130 if (IS_ERR(isabelle_regmap)) {
1131 ret = PTR_ERR(isabelle_regmap);
1132 dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
1133 ret);
1134 return ret;
1135 }
1136 i2c_set_clientdata(i2c, isabelle_regmap);
1137
1138 ret = snd_soc_register_codec(&i2c->dev,
1139 &soc_codec_dev_isabelle, isabelle_dai,
1140 ARRAY_SIZE(isabelle_dai));
1141 if (ret < 0) {
1142 dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
1143 return ret;
1144 }
1145
1146 return ret;
1147}
1148
1149static int __devexit isabelle_i2c_remove(struct i2c_client *client)
1150{
1151 snd_soc_unregister_codec(&client->dev);
1152 return 0;
1153}
1154
1155static const struct i2c_device_id isabelle_i2c_id[] = {
1156 { "isabelle", 0 },
1157 { }
1158};
1159MODULE_DEVICE_TABLE(i2c, isabelle_i2c_id);
1160
1161static struct i2c_driver isabelle_i2c_driver = {
1162 .driver = {
1163 .name = "isabelle",
1164 .owner = THIS_MODULE,
1165 },
1166 .probe = isabelle_i2c_probe,
1167 .remove = __devexit_p(isabelle_i2c_remove),
1168 .id_table = isabelle_i2c_id,
1169};
1170
1171module_i2c_driver(isabelle_i2c_driver);
1172
1173MODULE_DESCRIPTION("ASoC ISABELLE driver");
1174MODULE_AUTHOR("Vishwas A Deshpande <vishwas.a.deshpande@ti.com>");
1175MODULE_AUTHOR("M R Swami Reddy <MR.Swami.Reddy@ti.com>");
1176MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/isabelle.h b/sound/soc/codecs/isabelle.h
new file mode 100644
index 00000000000..96d839a8c95
--- /dev/null
+++ b/sound/soc/codecs/isabelle.h
@@ -0,0 +1,143 @@
1/*
2 * isabelle.h - Low power high fidelity audio codec driver header file
3 *
4 * Copyright (c) 2012 Texas Instruments, Inc
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 */
11
12#ifndef _ISABELLE_H
13#define _ISABELLE_H
14
15#include <linux/bitops.h>
16
17/* ISABELLE REGISTERS */
18
19#define ISABELLE_PWR_CFG_REG 0x01
20#define ISABELLE_PWR_EN_REG 0x02
21#define ISABELLE_PS_EN1_REG 0x03
22#define ISABELLE_INT1_STATUS_REG 0x04
23#define ISABELLE_INT1_MASK_REG 0x05
24#define ISABELLE_INT2_STATUS_REG 0x06
25#define ISABELLE_INT2_MASK_REG 0x07
26#define ISABELLE_HKCTL1_REG 0x08
27#define ISABELLE_HKCTL2_REG 0x09
28#define ISABELLE_HKCTL3_REG 0x0A
29#define ISABELLE_ACCDET_STATUS_REG 0x0B
30#define ISABELLE_BUTTON_ID_REG 0x0C
31#define ISABELLE_PLL_CFG_REG 0x10
32#define ISABELLE_PLL_EN_REG 0x11
33#define ISABELLE_FS_RATE_CFG_REG 0x12
34#define ISABELLE_INTF_CFG_REG 0x13
35#define ISABELLE_INTF_EN_REG 0x14
36#define ISABELLE_ULATX12_INTF_CFG_REG 0x15
37#define ISABELLE_DL12_INTF_CFG_REG 0x16
38#define ISABELLE_DL34_INTF_CFG_REG 0x17
39#define ISABELLE_DL56_INTF_CFG_REG 0x18
40#define ISABELLE_ATX_STPGA1_CFG_REG 0x19
41#define ISABELLE_ATX_STPGA2_CFG_REG 0x1A
42#define ISABELLE_VTX_STPGA1_CFG_REG 0x1B
43#define ISABELLE_VTX2_STPGA2_CFG_REG 0x1C
44#define ISABELLE_ATX1_DPGA_REG 0x1D
45#define ISABELLE_ATX2_DPGA_REG 0x1E
46#define ISABELLE_VTX1_DPGA_REG 0x1F
47#define ISABELLE_VTX2_DPGA_REG 0x20
48#define ISABELLE_TX_INPUT_CFG_REG 0x21
49#define ISABELLE_RX_INPUT_CFG_REG 0x22
50#define ISABELLE_RX_INPUT_CFG2_REG 0x23
51#define ISABELLE_VOICE_HPF_CFG_REG 0x24
52#define ISABELLE_AUDIO_HPF_CFG_REG 0x25
53#define ISABELLE_RX1_DPGA_REG 0x26
54#define ISABELLE_RX2_DPGA_REG 0x27
55#define ISABELLE_RX3_DPGA_REG 0x28
56#define ISABELLE_RX4_DPGA_REG 0x29
57#define ISABELLE_RX5_DPGA_REG 0x2A
58#define ISABELLE_RX6_DPGA_REG 0x2B
59#define ISABELLE_ALU_TX_EN_REG 0x2C
60#define ISABELLE_ALU_RX_EN_REG 0x2D
61#define ISABELLE_IIR_RESYNC_REG 0x2E
62#define ISABELLE_ABIAS_CFG_REG 0x30
63#define ISABELLE_DBIAS_CFG_REG 0x31
64#define ISABELLE_MIC1_GAIN_REG 0x32
65#define ISABELLE_MIC2_GAIN_REG 0x33
66#define ISABELLE_AMIC_CFG_REG 0x34
67#define ISABELLE_DMIC_CFG_REG 0x35
68#define ISABELLE_APGA_GAIN_REG 0x36
69#define ISABELLE_APGA_CFG_REG 0x37
70#define ISABELLE_TX_GAIN_DLY_REG 0x38
71#define ISABELLE_RX_GAIN_DLY_REG 0x39
72#define ISABELLE_RX_PWR_CTRL_REG 0x3A
73#define ISABELLE_DPGA1LR_IN_SEL_REG 0x3B
74#define ISABELLE_DPGA1L_GAIN_REG 0x3C
75#define ISABELLE_DPGA1R_GAIN_REG 0x3D
76#define ISABELLE_DPGA2L_IN_SEL_REG 0x3E
77#define ISABELLE_DPGA2R_IN_SEL_REG 0x3F
78#define ISABELLE_DPGA2L_GAIN_REG 0x40
79#define ISABELLE_DPGA2R_GAIN_REG 0x41
80#define ISABELLE_DPGA3LR_IN_SEL_REG 0x42
81#define ISABELLE_DPGA3L_GAIN_REG 0x43
82#define ISABELLE_DPGA3R_GAIN_REG 0x44
83#define ISABELLE_DAC1_SOFTRAMP_REG 0x45
84#define ISABELLE_DAC2_SOFTRAMP_REG 0x46
85#define ISABELLE_DAC3_SOFTRAMP_REG 0x47
86#define ISABELLE_DAC_CFG_REG 0x48
87#define ISABELLE_EARDRV_CFG1_REG 0x49
88#define ISABELLE_EARDRV_CFG2_REG 0x4A
89#define ISABELLE_HSDRV_GAIN_REG 0x4B
90#define ISABELLE_HSDRV_CFG1_REG 0x4C
91#define ISABELLE_HSDRV_CFG2_REG 0x4D
92#define ISABELLE_HS_NG_CFG1_REG 0x4E
93#define ISABELLE_HS_NG_CFG2_REG 0x4F
94#define ISABELLE_LINEAMP_GAIN_REG 0x50
95#define ISABELLE_LINEAMP_CFG_REG 0x51
96#define ISABELLE_HFL_VOL_CTRL_REG 0x52
97#define ISABELLE_HFL_SFTVOL_CTRL_REG 0x53
98#define ISABELLE_HFL_LIM_CTRL_1_REG 0x54
99#define ISABELLE_HFL_LIM_CTRL_2_REG 0x55
100#define ISABELLE_HFR_VOL_CTRL_REG 0x56
101#define ISABELLE_HFR_SFTVOL_CTRL_REG 0x57
102#define ISABELLE_HFR_LIM_CTRL_1_REG 0x58
103#define ISABELLE_HFR_LIM_CTRL_2_REG 0x59
104#define ISABELLE_HF_MODE_REG 0x5A
105#define ISABELLE_HFLPGA_CFG_REG 0x5B
106#define ISABELLE_HFRPGA_CFG_REG 0x5C
107#define ISABELLE_HFDRV_CFG_REG 0x5D
108#define ISABELLE_PDMOUT_CFG1_REG 0x5E
109#define ISABELLE_PDMOUT_CFG2_REG 0x5F
110#define ISABELLE_PDMOUT_L_WM_REG 0x60
111#define ISABELLE_PDMOUT_R_WM_REG 0x61
112#define ISABELLE_HF_NG_CFG1_REG 0x62
113#define ISABELLE_HF_NG_CFG2_REG 0x63
114
115/* ISABELLE_PWR_EN_REG (0x02h) */
116#define ISABELLE_CHIP_EN BIT(0)
117
118/* ISABELLE DAI FORMATS */
119#define ISABELLE_AIF_FMT_MASK 0x70
120#define ISABELLE_I2S_MODE 0x0
121#define ISABELLE_LEFT_J_MODE 0x1
122#define ISABELLE_PDM_MODE 0x2
123
124#define ISABELLE_AIF_LENGTH_MASK 0x30
125#define ISABELLE_AIF_LENGTH_20 0x00
126#define ISABELLE_AIF_LENGTH_32 0x10
127
128#define ISABELLE_AIF_MS 0x80
129
130#define ISABELLE_FS_RATE_MASK 0xF
131#define ISABELLE_FS_RATE_8 0x0
132#define ISABELLE_FS_RATE_11 0x1
133#define ISABELLE_FS_RATE_12 0x2
134#define ISABELLE_FS_RATE_16 0x4
135#define ISABELLE_FS_RATE_22 0x5
136#define ISABELLE_FS_RATE_24 0x6
137#define ISABELLE_FS_RATE_32 0x8
138#define ISABELLE_FS_RATE_44 0x9
139#define ISABELLE_FS_RATE_48 0xA
140
141#define ISABELLE_MAX_REGISTER 0xFF
142
143#endif
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c
index 802b9f176b1..99b0a9dcff3 100644
--- a/sound/soc/codecs/lm49453.c
+++ b/sound/soc/codecs/lm49453.c
@@ -12,7 +12,6 @@
12 12
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/moduleparam.h> 14#include <linux/moduleparam.h>
15#include <linux/version.h>
16#include <linux/kernel.h> 15#include <linux/kernel.h>
17#include <linux/init.h> 16#include <linux/init.h>
18#include <linux/delay.h> 17#include <linux/delay.h>
@@ -1358,7 +1357,7 @@ static struct snd_soc_dai_ops lm49453_lineout_dai_ops = {
1358}; 1357};
1359 1358
1360/* LM49453 dai structure. */ 1359/* LM49453 dai structure. */
1361static const struct snd_soc_dai_driver lm49453_dai[] = { 1360static struct snd_soc_dai_driver lm49453_dai[] = {
1362 { 1361 {
1363 .name = "LM49453 Headset", 1362 .name = "LM49453 Headset",
1364 .playback = { 1363 .playback = {
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index 35179e2c23c..7cd508e16a5 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -2216,7 +2216,7 @@ static irqreturn_t max98095_report_jack(int irq, void *data)
2216 return IRQ_HANDLED; 2216 return IRQ_HANDLED;
2217} 2217}
2218 2218
2219int max98095_jack_detect_enable(struct snd_soc_codec *codec) 2219static int max98095_jack_detect_enable(struct snd_soc_codec *codec)
2220{ 2220{
2221 struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); 2221 struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
2222 int ret = 0; 2222 int ret = 0;
@@ -2245,7 +2245,7 @@ int max98095_jack_detect_enable(struct snd_soc_codec *codec)
2245 return ret; 2245 return ret;
2246} 2246}
2247 2247
2248int max98095_jack_detect_disable(struct snd_soc_codec *codec) 2248static int max98095_jack_detect_disable(struct snd_soc_codec *codec)
2249{ 2249{
2250 int ret = 0; 2250 int ret = 0;
2251 2251
@@ -2286,6 +2286,7 @@ int max98095_jack_detect(struct snd_soc_codec *codec,
2286 max98095_report_jack(client->irq, codec); 2286 max98095_report_jack(client->irq, codec);
2287 return 0; 2287 return 0;
2288} 2288}
2289EXPORT_SYMBOL_GPL(max98095_jack_detect);
2289 2290
2290#ifdef CONFIG_PM 2291#ifdef CONFIG_PM
2291static int max98095_suspend(struct snd_soc_codec *codec) 2292static int max98095_suspend(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c
index 22cb5bf5927..96aa5fa0516 100644
--- a/sound/soc/codecs/ml26124.c
+++ b/sound/soc/codecs/ml26124.c
@@ -638,7 +638,7 @@ static __devinit int ml26124_i2c_probe(struct i2c_client *i2c,
638 638
639 i2c_set_clientdata(i2c, priv); 639 i2c_set_clientdata(i2c, priv);
640 640
641 priv->regmap = regmap_init_i2c(i2c, &ml26124_i2c_regmap); 641 priv->regmap = devm_regmap_init_i2c(i2c, &ml26124_i2c_regmap);
642 if (IS_ERR(priv->regmap)) { 642 if (IS_ERR(priv->regmap)) {
643 ret = PTR_ERR(priv->regmap); 643 ret = PTR_ERR(priv->regmap);
644 dev_err(&i2c->dev, "regmap_init_i2c() failed: %d\n", ret); 644 dev_err(&i2c->dev, "regmap_init_i2c() failed: %d\n", ret);
@@ -651,10 +651,7 @@ static __devinit int ml26124_i2c_probe(struct i2c_client *i2c,
651 651
652static __devexit int ml26124_i2c_remove(struct i2c_client *client) 652static __devexit int ml26124_i2c_remove(struct i2c_client *client)
653{ 653{
654 struct ml26124_priv *priv = i2c_get_clientdata(client);
655
656 snd_soc_unregister_codec(&client->dev); 654 snd_soc_unregister_codec(&client->dev);
657 regmap_exit(priv->regmap);
658 return 0; 655 return 0;
659} 656}
660 657
diff --git a/sound/soc/codecs/spdif_receiver.c b/sound/soc/codecs/spdif_receiver.c
new file mode 100644
index 00000000000..dd8d856053f
--- /dev/null
+++ b/sound/soc/codecs/spdif_receiver.c
@@ -0,0 +1,67 @@
1/*
2 * ALSA SoC SPDIF DIR (Digital Interface Reciever) driver
3 *
4 * Based on ALSA SoC SPDIF DIT driver
5 *
6 * This driver is used by controllers which can operate in DIR (SPDI/F) where
7 * no codec is needed. This file provides stub codec that can be used
8 * in these configurations. SPEAr SPDIF IN Audio controller uses this driver.
9 *
10 * Author: Vipin Kumar, <vipin.kumar@st.com>
11 * Copyright: (C) 2012 ST Microelectronics
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 */
17
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/slab.h>
21#include <sound/soc.h>
22#include <sound/pcm.h>
23#include <sound/initval.h>
24
25#define STUB_RATES SNDRV_PCM_RATE_8000_192000
26#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
27 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
28
29static struct snd_soc_codec_driver soc_codec_spdif_dir;
30
31static struct snd_soc_dai_driver dir_stub_dai = {
32 .name = "dir-hifi",
33 .capture = {
34 .stream_name = "Capture",
35 .channels_min = 1,
36 .channels_max = 384,
37 .rates = STUB_RATES,
38 .formats = STUB_FORMATS,
39 },
40};
41
42static int spdif_dir_probe(struct platform_device *pdev)
43{
44 return snd_soc_register_codec(&pdev->dev, &soc_codec_spdif_dir,
45 &dir_stub_dai, 1);
46}
47
48static int spdif_dir_remove(struct platform_device *pdev)
49{
50 snd_soc_unregister_codec(&pdev->dev);
51 return 0;
52}
53
54static struct platform_driver spdif_dir_driver = {
55 .probe = spdif_dir_probe,
56 .remove = spdif_dir_remove,
57 .driver = {
58 .name = "spdif-dir",
59 .owner = THIS_MODULE,
60 },
61};
62
63module_platform_driver(spdif_dir_driver);
64
65MODULE_DESCRIPTION("ASoC SPDIF DIR driver");
66MODULE_AUTHOR("Vipin Kumar <vipin.kumar@st.com>");
67MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c
new file mode 100644
index 00000000000..0c225cd569d
--- /dev/null
+++ b/sound/soc/codecs/sta529.c
@@ -0,0 +1,442 @@
1/*
2 * ASoC codec driver for spear platform
3 *
4 * sound/soc/codecs/sta529.c -- spear ALSA Soc codec driver
5 *
6 * Copyright (C) 2012 ST Microelectronics
7 * Rajeev Kumar <rajeev-dlh.kumar@st.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#include <linux/clk.h>
15#include <linux/init.h>
16#include <linux/i2c.h>
17#include <linux/io.h>
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/pm.h>
21#include <linux/regmap.h>
22#include <linux/slab.h>
23
24#include <sound/core.h>
25#include <sound/initval.h>
26#include <sound/pcm.h>
27#include <sound/pcm_params.h>
28#include <sound/soc.h>
29#include <sound/soc-dapm.h>
30#include <sound/tlv.h>
31
32/* STA529 Register offsets */
33#define STA529_FFXCFG0 0x00
34#define STA529_FFXCFG1 0x01
35#define STA529_MVOL 0x02
36#define STA529_LVOL 0x03
37#define STA529_RVOL 0x04
38#define STA529_TTF0 0x05
39#define STA529_TTF1 0x06
40#define STA529_TTP0 0x07
41#define STA529_TTP1 0x08
42#define STA529_S2PCFG0 0x0A
43#define STA529_S2PCFG1 0x0B
44#define STA529_P2SCFG0 0x0C
45#define STA529_P2SCFG1 0x0D
46#define STA529_PLLCFG0 0x14
47#define STA529_PLLCFG1 0x15
48#define STA529_PLLCFG2 0x16
49#define STA529_PLLCFG3 0x17
50#define STA529_PLLPFE 0x18
51#define STA529_PLLST 0x19
52#define STA529_ADCCFG 0x1E /*mic_select*/
53#define STA529_CKOCFG 0x1F
54#define STA529_MISC 0x20
55#define STA529_PADST0 0x21
56#define STA529_PADST1 0x22
57#define STA529_FFXST 0x23
58#define STA529_PWMIN1 0x2D
59#define STA529_PWMIN2 0x2E
60#define STA529_POWST 0x32
61
62#define STA529_MAX_REGISTER 0x32
63
64#define STA529_RATES (SNDRV_PCM_RATE_8000 | \
65 SNDRV_PCM_RATE_11025 | \
66 SNDRV_PCM_RATE_16000 | \
67 SNDRV_PCM_RATE_22050 | \
68 SNDRV_PCM_RATE_32000 | \
69 SNDRV_PCM_RATE_44100 | \
70 SNDRV_PCM_RATE_48000)
71
72#define STA529_FORMAT (SNDRV_PCM_FMTBIT_S16_LE | \
73 SNDRV_PCM_FMTBIT_S24_LE | \
74 SNDRV_PCM_FMTBIT_S32_LE)
75#define S2PC_VALUE 0x98
76#define CLOCK_OUT 0x60
77#define LEFT_J_DATA_FORMAT 0x10
78#define I2S_DATA_FORMAT 0x12
79#define RIGHT_J_DATA_FORMAT 0x14
80#define CODEC_MUTE_VAL 0x80
81
82#define POWER_CNTLMSAK 0x40
83#define POWER_STDBY 0x40
84#define FFX_MASK 0x80
85#define FFX_OFF 0x80
86#define POWER_UP 0x00
87#define FFX_CLK_ENB 0x01
88#define FFX_CLK_DIS 0x00
89#define FFX_CLK_MSK 0x01
90#define PLAY_FREQ_RANGE_MSK 0x70
91#define CAP_FREQ_RANGE_MSK 0x0C
92#define PDATA_LEN_MSK 0xC0
93#define BCLK_TO_FS_MSK 0x30
94#define AUDIO_MUTE_MSK 0x80
95
96static const struct reg_default sta529_reg_defaults[] = {
97 { 0, 0x35 }, /* R0 - FFX Configuration reg 0 */
98 { 1, 0xc8 }, /* R1 - FFX Configuration reg 1 */
99 { 2, 0x50 }, /* R2 - Master Volume */
100 { 3, 0x00 }, /* R3 - Left Volume */
101 { 4, 0x00 }, /* R4 - Right Volume */
102 { 10, 0xb2 }, /* R10 - S2P Config Reg 0 */
103 { 11, 0x41 }, /* R11 - S2P Config Reg 1 */
104 { 12, 0x92 }, /* R12 - P2S Config Reg 0 */
105 { 13, 0x41 }, /* R13 - P2S Config Reg 1 */
106 { 30, 0xd2 }, /* R30 - ADC Config Reg */
107 { 31, 0x40 }, /* R31 - clock Out Reg */
108 { 32, 0x21 }, /* R32 - Misc Register */
109};
110
111struct sta529 {
112 struct regmap *regmap;
113};
114
115static bool sta529_readable(struct device *dev, unsigned int reg)
116{
117 switch (reg) {
118
119 case STA529_FFXCFG0:
120 case STA529_FFXCFG1:
121 case STA529_MVOL:
122 case STA529_LVOL:
123 case STA529_RVOL:
124 case STA529_S2PCFG0:
125 case STA529_S2PCFG1:
126 case STA529_P2SCFG0:
127 case STA529_P2SCFG1:
128 case STA529_ADCCFG:
129 case STA529_CKOCFG:
130 case STA529_MISC:
131 return true;
132 default:
133 return false;
134 }
135}
136
137
138static const char *pwm_mode_text[] = { "Binary", "Headphone", "Ternary",
139 "Phase-shift"};
140
141static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -9150, 50, 0);
142static const DECLARE_TLV_DB_SCALE(master_vol_tlv, -12750, 50, 0);
143static const SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text);
144
145static const struct snd_kcontrol_new sta529_snd_controls[] = {
146 SOC_DOUBLE_R_TLV("Digital Playback Volume", STA529_LVOL, STA529_RVOL, 0,
147 127, 0, out_gain_tlv),
148 SOC_SINGLE_TLV("Master Playback Volume", STA529_MVOL, 0, 127, 1,
149 master_vol_tlv),
150 SOC_ENUM("PWM Select", pwm_src),
151};
152
153static int sta529_set_bias_level(struct snd_soc_codec *codec, enum
154 snd_soc_bias_level level)
155{
156 struct sta529 *sta529 = snd_soc_codec_get_drvdata(codec);
157
158 switch (level) {
159 case SND_SOC_BIAS_ON:
160 case SND_SOC_BIAS_PREPARE:
161 snd_soc_update_bits(codec, STA529_FFXCFG0, POWER_CNTLMSAK,
162 POWER_UP);
163 snd_soc_update_bits(codec, STA529_MISC, FFX_CLK_MSK,
164 FFX_CLK_ENB);
165 break;
166 case SND_SOC_BIAS_STANDBY:
167 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
168 regcache_sync(sta529->regmap);
169 snd_soc_update_bits(codec, STA529_FFXCFG0,
170 POWER_CNTLMSAK, POWER_STDBY);
171 /* Making FFX output to zero */
172 snd_soc_update_bits(codec, STA529_FFXCFG0, FFX_MASK,
173 FFX_OFF);
174 snd_soc_update_bits(codec, STA529_MISC, FFX_CLK_MSK,
175 FFX_CLK_DIS);
176 break;
177 case SND_SOC_BIAS_OFF:
178 break;
179 }
180
181 /*
182 * store the label for powers down audio subsystem for suspend.This is
183 * used by soc core layer
184 */
185 codec->dapm.bias_level = level;
186
187 return 0;
188
189}
190
191static int sta529_hw_params(struct snd_pcm_substream *substream,
192 struct snd_pcm_hw_params *params,
193 struct snd_soc_dai *dai)
194{
195 struct snd_soc_pcm_runtime *rtd = substream->private_data;
196 struct snd_soc_codec *codec = rtd->codec;
197 int pdata, play_freq_val, record_freq_val;
198 int bclk_to_fs_ratio;
199
200 switch (params_format(params)) {
201 case SNDRV_PCM_FORMAT_S16_LE:
202 pdata = 1;
203 bclk_to_fs_ratio = 0;
204 break;
205 case SNDRV_PCM_FORMAT_S24_LE:
206 pdata = 2;
207 bclk_to_fs_ratio = 1;
208 break;
209 case SNDRV_PCM_FORMAT_S32_LE:
210 pdata = 3;
211 bclk_to_fs_ratio = 2;
212 break;
213 default:
214 dev_err(codec->dev, "Unsupported format\n");
215 return -EINVAL;
216 }
217
218 switch (params_rate(params)) {
219 case 8000:
220 case 11025:
221 play_freq_val = 0;
222 record_freq_val = 2;
223 break;
224 case 16000:
225 case 22050:
226 play_freq_val = 1;
227 record_freq_val = 0;
228 break;
229
230 case 32000:
231 case 44100:
232 case 48000:
233 play_freq_val = 2;
234 record_freq_val = 0;
235 break;
236 default:
237 dev_err(codec->dev, "Unsupported rate\n");
238 return -EINVAL;
239 }
240
241 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
242 snd_soc_update_bits(codec, STA529_S2PCFG1, PDATA_LEN_MSK,
243 pdata << 6);
244 snd_soc_update_bits(codec, STA529_S2PCFG1, BCLK_TO_FS_MSK,
245 bclk_to_fs_ratio << 4);
246 snd_soc_update_bits(codec, STA529_MISC, PLAY_FREQ_RANGE_MSK,
247 play_freq_val << 4);
248 } else {
249 snd_soc_update_bits(codec, STA529_P2SCFG1, PDATA_LEN_MSK,
250 pdata << 6);
251 snd_soc_update_bits(codec, STA529_P2SCFG1, BCLK_TO_FS_MSK,
252 bclk_to_fs_ratio << 4);
253 snd_soc_update_bits(codec, STA529_MISC, CAP_FREQ_RANGE_MSK,
254 record_freq_val << 2);
255 }
256
257 return 0;
258}
259
260static int sta529_mute(struct snd_soc_dai *dai, int mute)
261{
262 u8 val = 0;
263
264 if (mute)
265 val |= CODEC_MUTE_VAL;
266
267 snd_soc_update_bits(dai->codec, STA529_FFXCFG0, AUDIO_MUTE_MSK, val);
268
269 return 0;
270}
271
272static int sta529_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
273{
274 struct snd_soc_codec *codec = codec_dai->codec;
275 u8 mode = 0;
276
277 /* interface format */
278 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
279 case SND_SOC_DAIFMT_LEFT_J:
280 mode = LEFT_J_DATA_FORMAT;
281 break;
282 case SND_SOC_DAIFMT_I2S:
283 mode = I2S_DATA_FORMAT;
284 break;
285 case SND_SOC_DAIFMT_RIGHT_J:
286 mode = RIGHT_J_DATA_FORMAT;
287 break;
288 default:
289 return -EINVAL;
290 }
291
292 snd_soc_update_bits(codec, STA529_S2PCFG0, 0x0D, mode);
293
294 return 0;
295}
296
297static const struct snd_soc_dai_ops sta529_dai_ops = {
298 .hw_params = sta529_hw_params,
299 .set_fmt = sta529_set_dai_fmt,
300 .digital_mute = sta529_mute,
301};
302
303static struct snd_soc_dai_driver sta529_dai = {
304 .name = "sta529-audio",
305 .playback = {
306 .stream_name = "Playback",
307 .channels_min = 2,
308 .channels_max = 2,
309 .rates = STA529_RATES,
310 .formats = STA529_FORMAT,
311 },
312 .capture = {
313 .stream_name = "Capture",
314 .channels_min = 2,
315 .channels_max = 2,
316 .rates = STA529_RATES,
317 .formats = STA529_FORMAT,
318 },
319 .ops = &sta529_dai_ops,
320};
321
322static int sta529_probe(struct snd_soc_codec *codec)
323{
324 struct sta529 *sta529 = snd_soc_codec_get_drvdata(codec);
325 int ret;
326
327 codec->control_data = sta529->regmap;
328 ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
329
330 if (ret < 0) {
331 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
332 return ret;
333 }
334 sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
335
336 return 0;
337}
338
339/* power down chip */
340static int sta529_remove(struct snd_soc_codec *codec)
341{
342 sta529_set_bias_level(codec, SND_SOC_BIAS_OFF);
343
344 return 0;
345}
346
347static int sta529_suspend(struct snd_soc_codec *codec)
348{
349 sta529_set_bias_level(codec, SND_SOC_BIAS_OFF);
350
351 return 0;
352}
353
354static int sta529_resume(struct snd_soc_codec *codec)
355{
356 sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
357
358 return 0;
359}
360
361struct snd_soc_codec_driver sta529_codec_driver = {
362 .probe = sta529_probe,
363 .remove = sta529_remove,
364 .set_bias_level = sta529_set_bias_level,
365 .suspend = sta529_suspend,
366 .resume = sta529_resume,
367 .controls = sta529_snd_controls,
368 .num_controls = ARRAY_SIZE(sta529_snd_controls),
369};
370
371static const struct regmap_config sta529_regmap = {
372 .reg_bits = 8,
373 .val_bits = 8,
374
375 .max_register = STA529_MAX_REGISTER,
376 .readable_reg = sta529_readable,
377
378 .cache_type = REGCACHE_RBTREE,
379 .reg_defaults = sta529_reg_defaults,
380 .num_reg_defaults = ARRAY_SIZE(sta529_reg_defaults),
381};
382
383static __devinit int sta529_i2c_probe(struct i2c_client *i2c,
384 const struct i2c_device_id *id)
385{
386 struct sta529 *sta529;
387 int ret;
388
389 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
390 return -EINVAL;
391
392 sta529 = devm_kzalloc(&i2c->dev, sizeof(struct sta529), GFP_KERNEL);
393 if (sta529 == NULL) {
394 dev_err(&i2c->dev, "Can not allocate memory\n");
395 return -ENOMEM;
396 }
397
398 sta529->regmap = devm_regmap_init_i2c(i2c, &sta529_regmap);
399 if (IS_ERR(sta529->regmap)) {
400 ret = PTR_ERR(sta529->regmap);
401 dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
402 return ret;
403 }
404
405 i2c_set_clientdata(i2c, sta529);
406
407 ret = snd_soc_register_codec(&i2c->dev,
408 &sta529_codec_driver, &sta529_dai, 1);
409 if (ret != 0)
410 dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
411
412 return ret;
413}
414
415static int __devexit sta529_i2c_remove(struct i2c_client *client)
416{
417 snd_soc_unregister_codec(&client->dev);
418
419 return 0;
420}
421
422static const struct i2c_device_id sta529_i2c_id[] = {
423 { "sta529", 0 },
424 { }
425};
426MODULE_DEVICE_TABLE(i2c, sta529_i2c_id);
427
428static struct i2c_driver sta529_i2c_driver = {
429 .driver = {
430 .name = "sta529",
431 .owner = THIS_MODULE,
432 },
433 .probe = sta529_i2c_probe,
434 .remove = __devexit_p(sta529_i2c_remove),
435 .id_table = sta529_i2c_id,
436};
437
438module_i2c_driver(sta529_i2c_driver);
439
440MODULE_DESCRIPTION("ASoC STA529 codec driver");
441MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>");
442MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index e9b62b5ea63..dc78f5a4bcb 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -118,7 +118,9 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = {
118 0x00, 0x00, 0x00, 0x00, /* 88 */ 118 0x00, 0x00, 0x00, 0x00, /* 88 */
119 0x00, 0x00, 0x00, 0x00, /* 92 */ 119 0x00, 0x00, 0x00, 0x00, /* 92 */
120 0x00, 0x00, 0x00, 0x00, /* 96 */ 120 0x00, 0x00, 0x00, 0x00, /* 96 */
121 0x00, 0x00, 0x02, /* 100 */ 121 0x00, 0x00, 0x02, 0x00, /* 100 */
122 0x00, 0x00, 0x00, 0x00, /* 104 */
123 0x00, 0x00, /* 108 */
122}; 124};
123 125
124#define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \ 126#define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
@@ -229,6 +231,25 @@ static const struct soc_enum aic3x_enum[] = {
229 SOC_ENUM_DOUBLE(AIC3X_CODEC_DFILT_CTRL, 6, 4, 4, aic3x_adc_hpf), 231 SOC_ENUM_DOUBLE(AIC3X_CODEC_DFILT_CTRL, 6, 4, 4, aic3x_adc_hpf),
230}; 232};
231 233
234static const char *aic3x_agc_level[] =
235 { "-5.5dB", "-8dB", "-10dB", "-12dB", "-14dB", "-17dB", "-20dB", "-24dB" };
236static const struct soc_enum aic3x_agc_level_enum[] = {
237 SOC_ENUM_SINGLE(LAGC_CTRL_A, 4, 8, aic3x_agc_level),
238 SOC_ENUM_SINGLE(RAGC_CTRL_A, 4, 8, aic3x_agc_level),
239};
240
241static const char *aic3x_agc_attack[] = { "8ms", "11ms", "16ms", "20ms" };
242static const struct soc_enum aic3x_agc_attack_enum[] = {
243 SOC_ENUM_SINGLE(LAGC_CTRL_A, 2, 4, aic3x_agc_attack),
244 SOC_ENUM_SINGLE(RAGC_CTRL_A, 2, 4, aic3x_agc_attack),
245};
246
247static const char *aic3x_agc_decay[] = { "100ms", "200ms", "400ms", "500ms" };
248static const struct soc_enum aic3x_agc_decay_enum[] = {
249 SOC_ENUM_SINGLE(LAGC_CTRL_A, 0, 4, aic3x_agc_decay),
250 SOC_ENUM_SINGLE(RAGC_CTRL_A, 0, 4, aic3x_agc_decay),
251};
252
232/* 253/*
233 * DAC digital volumes. From -63.5 to 0 dB in 0.5 dB steps 254 * DAC digital volumes. From -63.5 to 0 dB in 0.5 dB steps
234 */ 255 */
@@ -353,6 +374,15 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
353 * adjust PGA to max value when ADC is on and will never go back. 374 * adjust PGA to max value when ADC is on and will never go back.
354 */ 375 */
355 SOC_DOUBLE_R("AGC Switch", LAGC_CTRL_A, RAGC_CTRL_A, 7, 0x01, 0), 376 SOC_DOUBLE_R("AGC Switch", LAGC_CTRL_A, RAGC_CTRL_A, 7, 0x01, 0),
377 SOC_ENUM("Left AGC Target level", aic3x_agc_level_enum[0]),
378 SOC_ENUM("Right AGC Target level", aic3x_agc_level_enum[1]),
379 SOC_ENUM("Left AGC Attack time", aic3x_agc_attack_enum[0]),
380 SOC_ENUM("Right AGC Attack time", aic3x_agc_attack_enum[1]),
381 SOC_ENUM("Left AGC Decay time", aic3x_agc_decay_enum[0]),
382 SOC_ENUM("Right AGC Decay time", aic3x_agc_decay_enum[1]),
383
384 /* De-emphasis */
385 SOC_DOUBLE("De-emphasis Switch", AIC3X_CODEC_DFILT_CTRL, 2, 0, 0x01, 0),
356 386
357 /* Input */ 387 /* Input */
358 SOC_DOUBLE_R_TLV("PGA Capture Volume", LADC_VOL, RADC_VOL, 388 SOC_DOUBLE_R_TLV("PGA Capture Volume", LADC_VOL, RADC_VOL,
@@ -368,7 +398,7 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
368static DECLARE_TLV_DB_SCALE(classd_amp_tlv, 0, 600, 0); 398static DECLARE_TLV_DB_SCALE(classd_amp_tlv, 0, 600, 0);
369 399
370static const struct snd_kcontrol_new aic3x_classd_amp_gain_ctrl = 400static const struct snd_kcontrol_new aic3x_classd_amp_gain_ctrl =
371 SOC_DOUBLE_TLV("Class-D Amplifier Gain", CLASSD_CTRL, 6, 4, 3, 0, classd_amp_tlv); 401 SOC_DOUBLE_TLV("Class-D Playback Volume", CLASSD_CTRL, 6, 4, 3, 0, classd_amp_tlv);
372 402
373/* Left DAC Mux */ 403/* Left DAC Mux */
374static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = 404static const struct snd_kcontrol_new aic3x_left_dac_mux_controls =
@@ -970,6 +1000,12 @@ static int aic3x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
970 struct snd_soc_codec *codec = codec_dai->codec; 1000 struct snd_soc_codec *codec = codec_dai->codec;
971 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); 1001 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
972 1002
1003 /* set clock on MCLK or GPIO2 or BCLK */
1004 snd_soc_update_bits(codec, AIC3X_CLKGEN_CTRL_REG, PLLCLK_IN_MASK,
1005 clk_id << PLLCLK_IN_SHIFT);
1006 snd_soc_update_bits(codec, AIC3X_CLKGEN_CTRL_REG, CLKDIV_IN_MASK,
1007 clk_id << CLKDIV_IN_SHIFT);
1008
973 aic3x->sysclk = freq; 1009 aic3x->sysclk = freq;
974 return 0; 1010 return 0;
975} 1011}
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h
index 08c7f6685ff..6db3c41b016 100644
--- a/sound/soc/codecs/tlv320aic3x.h
+++ b/sound/soc/codecs/tlv320aic3x.h
@@ -13,7 +13,7 @@
13#define _AIC3X_H 13#define _AIC3X_H
14 14
15/* AIC3X register space */ 15/* AIC3X register space */
16#define AIC3X_CACHEREGNUM 103 16#define AIC3X_CACHEREGNUM 110
17 17
18/* Page select register */ 18/* Page select register */
19#define AIC3X_PAGE_SELECT 0 19#define AIC3X_PAGE_SELECT 0
@@ -74,6 +74,8 @@
74#define HPLCOM_CFG 37 74#define HPLCOM_CFG 37
75/* Right High Power Output control registers */ 75/* Right High Power Output control registers */
76#define HPRCOM_CFG 38 76#define HPRCOM_CFG 38
77/* High Power Output Stage Control Register */
78#define HPOUT_SC 40
77/* DAC Output Switching control registers */ 79/* DAC Output Switching control registers */
78#define DAC_LINE_MUX 41 80#define DAC_LINE_MUX 41
79/* High Power Output Driver Pop Reduction registers */ 81/* High Power Output Driver Pop Reduction registers */
@@ -148,6 +150,17 @@
148#define AIC3X_GPIOB_REG 101 150#define AIC3X_GPIOB_REG 101
149/* Clock generation control register */ 151/* Clock generation control register */
150#define AIC3X_CLKGEN_CTRL_REG 102 152#define AIC3X_CLKGEN_CTRL_REG 102
153/* New AGC registers */
154#define LAGCN_ATTACK 103
155#define LAGCN_DECAY 104
156#define RAGCN_ATTACK 105
157#define RAGCN_DECAY 106
158/* New Programmable ADC Digital Path and I2C Bus Condition Register */
159#define NEW_ADC_DIGITALPATH 107
160/* Passive Analog Signal Bypass Selection During Powerdown Register */
161#define PASSIVE_BYPASS 108
162/* DAC Quiescent Current Adjustment Register */
163#define DAC_ICC_ADJ 109
151 164
152/* Page select register bits */ 165/* Page select register bits */
153#define PAGE0_SELECT 0 166#define PAGE0_SELECT 0
@@ -163,6 +176,10 @@
163#define DUAL_RATE_MODE ((1 << 5) | (1 << 6)) 176#define DUAL_RATE_MODE ((1 << 5) | (1 << 6))
164#define LDAC2LCH (0x1 << 3) 177#define LDAC2LCH (0x1 << 3)
165#define RDAC2RCH (0x1 << 1) 178#define RDAC2RCH (0x1 << 1)
179#define LDAC2RCH (0x2 << 3)
180#define RDAC2LCH (0x2 << 1)
181#define LDAC2MONOMIX (0x3 << 3)
182#define RDAC2MONOMIX (0x3 << 1)
166 183
167/* PLL registers bitfields */ 184/* PLL registers bitfields */
168#define PLLP_SHIFT 0 185#define PLLP_SHIFT 0
@@ -179,6 +196,14 @@
179#define PLL_CLKIN_SHIFT 4 196#define PLL_CLKIN_SHIFT 4
180#define MCLK_SOURCE 0x0 197#define MCLK_SOURCE 0x0
181#define PLL_CLKDIV_SHIFT 0 198#define PLL_CLKDIV_SHIFT 0
199#define PLLCLK_IN_MASK 0x30
200#define PLLCLK_IN_SHIFT 4
201#define CLKDIV_IN_MASK 0xc0
202#define CLKDIV_IN_SHIFT 6
203/* clock in source */
204#define CLKIN_MCLK 0
205#define CLKIN_GPIO2 1
206#define CLKIN_BCLK 2
182 207
183/* Software reset register bits */ 208/* Software reset register bits */
184#define SOFT_RESET 0x80 209#define SOFT_RESET 0x80
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index a36e9fcdf18..0ff1e70b777 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -553,7 +553,7 @@ static const struct snd_kcontrol_new vibrar_mux_controls =
553 553
554/* Headset power mode */ 554/* Headset power mode */
555static const char *twl6040_power_mode_texts[] = { 555static const char *twl6040_power_mode_texts[] = {
556 "Low-Power", "High-Perfomance", 556 "Low-Power", "High-Performance",
557}; 557};
558 558
559static const struct soc_enum twl6040_power_mode_enum = 559static const struct soc_enum twl6040_power_mode_enum =
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c
index e0b51e9f8b1..951d7b49476 100644
--- a/sound/soc/codecs/wm1250-ev1.c
+++ b/sound/soc/codecs/wm1250-ev1.c
@@ -121,20 +121,23 @@ static const struct snd_soc_dai_ops wm1250_ev1_ops = {
121 .hw_params = wm1250_ev1_hw_params, 121 .hw_params = wm1250_ev1_hw_params,
122}; 122};
123 123
124#define WM1250_EV1_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
125 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_64000)
126
124static struct snd_soc_dai_driver wm1250_ev1_dai = { 127static struct snd_soc_dai_driver wm1250_ev1_dai = {
125 .name = "wm1250-ev1", 128 .name = "wm1250-ev1",
126 .playback = { 129 .playback = {
127 .stream_name = "Playback", 130 .stream_name = "Playback",
128 .channels_min = 1, 131 .channels_min = 1,
129 .channels_max = 2, 132 .channels_max = 2,
130 .rates = SNDRV_PCM_RATE_8000, 133 .rates = WM1250_EV1_RATES,
131 .formats = SNDRV_PCM_FMTBIT_S16_LE, 134 .formats = SNDRV_PCM_FMTBIT_S16_LE,
132 }, 135 },
133 .capture = { 136 .capture = {
134 .stream_name = "Capture", 137 .stream_name = "Capture",
135 .channels_min = 1, 138 .channels_min = 1,
136 .channels_max = 2, 139 .channels_max = 2,
137 .rates = SNDRV_PCM_RATE_8000, 140 .rates = WM1250_EV1_RATES,
138 .formats = SNDRV_PCM_FMTBIT_S16_LE, 141 .formats = SNDRV_PCM_FMTBIT_S16_LE,
139 }, 142 },
140 .ops = &wm1250_ev1_ops, 143 .ops = &wm1250_ev1_ops,
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index 0418fa11e6b..3fd5b29dc93 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * wm2000.c -- WM2000 ALSA Soc Audio driver 2 * wm2000.c -- WM2000 ALSA Soc Audio driver
3 * 3 *
4 * Copyright 2008-2010 Wolfson Microelectronics PLC. 4 * Copyright 2008-2011 Wolfson Microelectronics PLC.
5 * 5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 * 7 *
@@ -674,9 +674,39 @@ static int wm2000_resume(struct snd_soc_codec *codec)
674#define wm2000_resume NULL 674#define wm2000_resume NULL
675#endif 675#endif
676 676
677static bool wm2000_readable_reg(struct device *dev, unsigned int reg)
678{
679 switch (reg) {
680 case WM2000_REG_SYS_START:
681 case WM2000_REG_SPEECH_CLARITY:
682 case WM2000_REG_SYS_WATCHDOG:
683 case WM2000_REG_ANA_VMID_PD_TIME:
684 case WM2000_REG_ANA_VMID_PU_TIME:
685 case WM2000_REG_CAT_FLTR_INDX:
686 case WM2000_REG_CAT_GAIN_0:
687 case WM2000_REG_SYS_STATUS:
688 case WM2000_REG_SYS_MODE_CNTRL:
689 case WM2000_REG_SYS_START0:
690 case WM2000_REG_SYS_START1:
691 case WM2000_REG_ID1:
692 case WM2000_REG_ID2:
693 case WM2000_REG_REVISON:
694 case WM2000_REG_SYS_CTL1:
695 case WM2000_REG_SYS_CTL2:
696 case WM2000_REG_ANC_STAT:
697 case WM2000_REG_IF_CTL:
698 return true;
699 default:
700 return false;
701 }
702}
703
677static const struct regmap_config wm2000_regmap = { 704static const struct regmap_config wm2000_regmap = {
678 .reg_bits = 8, 705 .reg_bits = 8,
679 .val_bits = 8, 706 .val_bits = 8,
707
708 .max_register = WM2000_REG_IF_CTL,
709 .readable_reg = wm2000_readable_reg,
680}; 710};
681 711
682static int wm2000_probe(struct snd_soc_codec *codec) 712static int wm2000_probe(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/wm5100-tables.c b/sound/soc/codecs/wm5100-tables.c
index e167207a19c..e239f4bf246 100644
--- a/sound/soc/codecs/wm5100-tables.c
+++ b/sound/soc/codecs/wm5100-tables.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * wm5100-tables.c -- WM5100 ALSA SoC Audio driver data 2 * wm5100-tables.c -- WM5100 ALSA SoC Audio driver data
3 * 3 *
4 * Copyright 2011 Wolfson Microelectronics plc 4 * Copyright 2011-2 Wolfson Microelectronics plc
5 * 5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 * 7 *
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index cb6d5372103..f4817292ef4 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * wm5100.c -- WM5100 ALSA SoC Audio driver 2 * wm5100.c -- WM5100 ALSA SoC Audio driver
3 * 3 *
4 * Copyright 2011 Wolfson Microelectronics plc 4 * Copyright 2011-2 Wolfson Microelectronics plc
5 * 5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 * 7 *
@@ -2378,13 +2378,6 @@ static int wm5100_remove(struct snd_soc_codec *codec)
2378 return 0; 2378 return 0;
2379} 2379}
2380 2380
2381static int wm5100_soc_volatile(struct snd_soc_codec *codec,
2382 unsigned int reg)
2383{
2384 return true;
2385}
2386
2387
2388static struct snd_soc_codec_driver soc_codec_dev_wm5100 = { 2381static struct snd_soc_codec_driver soc_codec_dev_wm5100 = {
2389 .probe = wm5100_probe, 2382 .probe = wm5100_probe,
2390 .remove = wm5100_remove, 2383 .remove = wm5100_remove,
@@ -2392,8 +2385,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5100 = {
2392 .set_sysclk = wm5100_set_sysclk, 2385 .set_sysclk = wm5100_set_sysclk,
2393 .set_pll = wm5100_set_fll, 2386 .set_pll = wm5100_set_fll,
2394 .idle_bias_off = 1, 2387 .idle_bias_off = 1,
2395 .reg_cache_size = WM5100_MAX_REGISTER,
2396 .volatile_register = wm5100_soc_volatile,
2397 2388
2398 .seq_notifier = wm5100_seq_notifier, 2389 .seq_notifier = wm5100_seq_notifier,
2399 .controls = wm5100_snd_controls, 2390 .controls = wm5100_snd_controls,
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
new file mode 100644
index 00000000000..6537f16d383
--- /dev/null
+++ b/sound/soc/codecs/wm5102.c
@@ -0,0 +1,903 @@
1/*
2 * wm5102.c -- WM5102 ALSA SoC Audio driver
3 *
4 * Copyright 2012 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/init.h>
16#include <linux/delay.h>
17#include <linux/pm.h>
18#include <linux/pm_runtime.h>
19#include <linux/regmap.h>
20#include <linux/slab.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/pcm_params.h>
24#include <sound/soc.h>
25#include <sound/jack.h>
26#include <sound/initval.h>
27#include <sound/tlv.h>
28
29#include <linux/mfd/arizona/core.h>
30#include <linux/mfd/arizona/registers.h>
31
32#include "arizona.h"
33#include "wm5102.h"
34
35struct wm5102_priv {
36 struct arizona_priv core;
37 struct arizona_fll fll[2];
38};
39
40static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0);
41static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
42static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
43static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0);
44
45static const struct snd_kcontrol_new wm5102_snd_controls[] = {
46SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL,
47 ARIZONA_IN1_OSR_SHIFT, 1, 0),
48SOC_SINGLE("IN2 High Performance Switch", ARIZONA_IN2L_CONTROL,
49 ARIZONA_IN2_OSR_SHIFT, 1, 0),
50SOC_SINGLE("IN3 High Performance Switch", ARIZONA_IN3L_CONTROL,
51 ARIZONA_IN3_OSR_SHIFT, 1, 0),
52
53SOC_DOUBLE_R_RANGE_TLV("IN1 Volume", ARIZONA_IN1L_CONTROL,
54 ARIZONA_IN1R_CONTROL,
55 ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
56SOC_DOUBLE_R_RANGE_TLV("IN2 Volume", ARIZONA_IN2L_CONTROL,
57 ARIZONA_IN2R_CONTROL,
58 ARIZONA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
59SOC_DOUBLE_R_RANGE_TLV("IN3 Volume", ARIZONA_IN3L_CONTROL,
60 ARIZONA_IN3R_CONTROL,
61 ARIZONA_IN3L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
62
63SOC_DOUBLE_R("IN1 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_1L,
64 ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_MUTE_SHIFT, 1, 1),
65SOC_DOUBLE_R("IN2 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_2L,
66 ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_MUTE_SHIFT, 1, 1),
67SOC_DOUBLE_R("IN3 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_3L,
68 ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_MUTE_SHIFT, 1, 1),
69
70SOC_DOUBLE_R_TLV("IN1 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L,
71 ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_DIG_VOL_SHIFT,
72 0xbf, 0, digital_tlv),
73SOC_DOUBLE_R_TLV("IN2 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_2L,
74 ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_DIG_VOL_SHIFT,
75 0xbf, 0, digital_tlv),
76SOC_DOUBLE_R_TLV("IN3 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_3L,
77 ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_DIG_VOL_SHIFT,
78 0xbf, 0, digital_tlv),
79
80ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
81ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
82ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
83ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
84
85SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
86 24, 0, eq_tlv),
87SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
88 24, 0, eq_tlv),
89SOC_SINGLE_TLV("EQ1 B3 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B3_GAIN_SHIFT,
90 24, 0, eq_tlv),
91SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
92 24, 0, eq_tlv),
93SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT,
94 24, 0, eq_tlv),
95
96SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT,
97 24, 0, eq_tlv),
98SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT,
99 24, 0, eq_tlv),
100SOC_SINGLE_TLV("EQ2 B3 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B3_GAIN_SHIFT,
101 24, 0, eq_tlv),
102SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
103 24, 0, eq_tlv),
104SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT,
105 24, 0, eq_tlv),
106
107SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT,
108 24, 0, eq_tlv),
109SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT,
110 24, 0, eq_tlv),
111SOC_SINGLE_TLV("EQ3 B3 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B3_GAIN_SHIFT,
112 24, 0, eq_tlv),
113SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT,
114 24, 0, eq_tlv),
115SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT,
116 24, 0, eq_tlv),
117
118SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT,
119 24, 0, eq_tlv),
120SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT,
121 24, 0, eq_tlv),
122SOC_SINGLE_TLV("EQ4 B3 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B3_GAIN_SHIFT,
123 24, 0, eq_tlv),
124SOC_SINGLE_TLV("EQ4 B4 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B4_GAIN_SHIFT,
125 24, 0, eq_tlv),
126SOC_SINGLE_TLV("EQ4 B5 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B5_GAIN_SHIFT,
127 24, 0, eq_tlv),
128
129ARIZONA_MIXER_CONTROLS("DRC1L", ARIZONA_DRC1LMIX_INPUT_1_SOURCE),
130ARIZONA_MIXER_CONTROLS("DRC1R", ARIZONA_DRC1RMIX_INPUT_1_SOURCE),
131ARIZONA_MIXER_CONTROLS("DRC2L", ARIZONA_DRC2LMIX_INPUT_1_SOURCE),
132ARIZONA_MIXER_CONTROLS("DRC2R", ARIZONA_DRC2RMIX_INPUT_1_SOURCE),
133
134SND_SOC_BYTES_MASK("DRC1", ARIZONA_DRC1_CTRL1, 5,
135 ARIZONA_DRC1R_ENA | ARIZONA_DRC1L_ENA),
136SND_SOC_BYTES_MASK("DRC2", ARIZONA_DRC2_CTRL1, 5,
137 ARIZONA_DRC2R_ENA | ARIZONA_DRC2L_ENA),
138
139ARIZONA_MIXER_CONTROLS("LHPF1", ARIZONA_HPLP1MIX_INPUT_1_SOURCE),
140ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
141ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
142ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
143
144SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
145SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
146SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
147SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
148
149ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE),
150ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE),
151
152SOC_SINGLE_TLV("Noise Generator Volume", ARIZONA_COMFORT_NOISE_GENERATOR,
153 ARIZONA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, noise_tlv),
154
155ARIZONA_MIXER_CONTROLS("HPOUT1L", ARIZONA_OUT1LMIX_INPUT_1_SOURCE),
156ARIZONA_MIXER_CONTROLS("HPOUT1R", ARIZONA_OUT1RMIX_INPUT_1_SOURCE),
157ARIZONA_MIXER_CONTROLS("HPOUT2L", ARIZONA_OUT2LMIX_INPUT_1_SOURCE),
158ARIZONA_MIXER_CONTROLS("HPOUT2R", ARIZONA_OUT2RMIX_INPUT_1_SOURCE),
159ARIZONA_MIXER_CONTROLS("EPOUT", ARIZONA_OUT3LMIX_INPUT_1_SOURCE),
160ARIZONA_MIXER_CONTROLS("SPKOUTL", ARIZONA_OUT4LMIX_INPUT_1_SOURCE),
161ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE),
162ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE),
163ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE),
164
165SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L,
166 ARIZONA_OUT1_OSR_SHIFT, 1, 0),
167SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L,
168 ARIZONA_OUT2_OSR_SHIFT, 1, 0),
169SOC_SINGLE("EPOUT High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L,
170 ARIZONA_OUT3_OSR_SHIFT, 1, 0),
171SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
172 ARIZONA_OUT4_OSR_SHIFT, 1, 0),
173SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
174 ARIZONA_OUT5_OSR_SHIFT, 1, 0),
175
176SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L,
177 ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1),
178SOC_DOUBLE_R("OUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L,
179 ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_MUTE_SHIFT, 1, 1),
180SOC_SINGLE("EPOUT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L,
181 ARIZONA_OUT3L_MUTE_SHIFT, 1, 1),
182SOC_DOUBLE_R("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L,
183 ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_MUTE_SHIFT, 1, 1),
184SOC_DOUBLE_R("SPKDAT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_5L,
185 ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_MUTE_SHIFT, 1, 1),
186
187SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_1L,
188 ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_VOL_SHIFT,
189 0xbf, 0, digital_tlv),
190SOC_DOUBLE_R_TLV("OUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L,
191 ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_VOL_SHIFT,
192 0xbf, 0, digital_tlv),
193SOC_SINGLE_TLV("EPOUT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L,
194 ARIZONA_OUT3L_VOL_SHIFT, 0xbf, 0, digital_tlv),
195SOC_DOUBLE_R_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L,
196 ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_VOL_SHIFT,
197 0xbf, 0, digital_tlv),
198SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
199 ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT,
200 0xbf, 0, digital_tlv),
201
202SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L,
203 ARIZONA_OUTPUT_PATH_CONFIG_1R,
204 ARIZONA_OUT1L_PGA_VOL_SHIFT,
205 0x34, 0x40, 0, ana_tlv),
206SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L,
207 ARIZONA_OUTPUT_PATH_CONFIG_2R,
208 ARIZONA_OUT2L_PGA_VOL_SHIFT,
209 0x34, 0x40, 0, ana_tlv),
210SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L,
211 ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv),
212
213SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
214 ARIZONA_SPK1R_MUTE_SHIFT, 1, 1),
215
216ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE),
217ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE),
218ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE),
219ARIZONA_MIXER_CONTROLS("AIF1TX4", ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE),
220ARIZONA_MIXER_CONTROLS("AIF1TX5", ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE),
221ARIZONA_MIXER_CONTROLS("AIF1TX6", ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE),
222ARIZONA_MIXER_CONTROLS("AIF1TX7", ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE),
223ARIZONA_MIXER_CONTROLS("AIF1TX8", ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE),
224
225ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE),
226ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE),
227
228ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE),
229ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE),
230};
231
232ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE);
233ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE);
234ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE);
235ARIZONA_MIXER_ENUMS(EQ4, ARIZONA_EQ4MIX_INPUT_1_SOURCE);
236
237ARIZONA_MIXER_ENUMS(DRC1L, ARIZONA_DRC1LMIX_INPUT_1_SOURCE);
238ARIZONA_MIXER_ENUMS(DRC1R, ARIZONA_DRC1RMIX_INPUT_1_SOURCE);
239ARIZONA_MIXER_ENUMS(DRC2L, ARIZONA_DRC2LMIX_INPUT_1_SOURCE);
240ARIZONA_MIXER_ENUMS(DRC2R, ARIZONA_DRC2RMIX_INPUT_1_SOURCE);
241
242ARIZONA_MIXER_ENUMS(LHPF1, ARIZONA_HPLP1MIX_INPUT_1_SOURCE);
243ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE);
244ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE);
245ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE);
246
247ARIZONA_MIXER_ENUMS(Mic, ARIZONA_MICMIX_INPUT_1_SOURCE);
248ARIZONA_MIXER_ENUMS(Noise, ARIZONA_NOISEMIX_INPUT_1_SOURCE);
249
250ARIZONA_MIXER_ENUMS(PWM1, ARIZONA_PWM1MIX_INPUT_1_SOURCE);
251ARIZONA_MIXER_ENUMS(PWM2, ARIZONA_PWM2MIX_INPUT_1_SOURCE);
252
253ARIZONA_MIXER_ENUMS(OUT1L, ARIZONA_OUT1LMIX_INPUT_1_SOURCE);
254ARIZONA_MIXER_ENUMS(OUT1R, ARIZONA_OUT1RMIX_INPUT_1_SOURCE);
255ARIZONA_MIXER_ENUMS(OUT2L, ARIZONA_OUT2LMIX_INPUT_1_SOURCE);
256ARIZONA_MIXER_ENUMS(OUT2R, ARIZONA_OUT2RMIX_INPUT_1_SOURCE);
257ARIZONA_MIXER_ENUMS(OUT3, ARIZONA_OUT3LMIX_INPUT_1_SOURCE);
258ARIZONA_MIXER_ENUMS(SPKOUTL, ARIZONA_OUT4LMIX_INPUT_1_SOURCE);
259ARIZONA_MIXER_ENUMS(SPKOUTR, ARIZONA_OUT4RMIX_INPUT_1_SOURCE);
260ARIZONA_MIXER_ENUMS(SPKDAT1L, ARIZONA_OUT5LMIX_INPUT_1_SOURCE);
261ARIZONA_MIXER_ENUMS(SPKDAT1R, ARIZONA_OUT5RMIX_INPUT_1_SOURCE);
262
263ARIZONA_MIXER_ENUMS(AIF1TX1, ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE);
264ARIZONA_MIXER_ENUMS(AIF1TX2, ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE);
265ARIZONA_MIXER_ENUMS(AIF1TX3, ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE);
266ARIZONA_MIXER_ENUMS(AIF1TX4, ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE);
267ARIZONA_MIXER_ENUMS(AIF1TX5, ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE);
268ARIZONA_MIXER_ENUMS(AIF1TX6, ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE);
269ARIZONA_MIXER_ENUMS(AIF1TX7, ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE);
270ARIZONA_MIXER_ENUMS(AIF1TX8, ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE);
271
272ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE);
273ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
274
275ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
276ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
277
278ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
279ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
280ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
281ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
282
283static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = {
284SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
285 0, NULL, 0),
286SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1,
287 ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0),
288
289SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0),
290SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0),
291SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
292SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0),
293SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0),
294SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0),
295
296SND_SOC_DAPM_SIGGEN("TONE"),
297SND_SOC_DAPM_SIGGEN("NOISE"),
298
299SND_SOC_DAPM_INPUT("IN1L"),
300SND_SOC_DAPM_INPUT("IN1R"),
301SND_SOC_DAPM_INPUT("IN2L"),
302SND_SOC_DAPM_INPUT("IN2R"),
303SND_SOC_DAPM_INPUT("IN3L"),
304SND_SOC_DAPM_INPUT("IN3R"),
305
306SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT,
307 0, NULL, 0, arizona_in_ev,
308 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
309SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT,
310 0, NULL, 0, arizona_in_ev,
311 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
312SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT,
313 0, NULL, 0, arizona_in_ev,
314 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
315SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT,
316 0, NULL, 0, arizona_in_ev,
317 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
318SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT,
319 0, NULL, 0, arizona_in_ev,
320 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
321SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
322 0, NULL, 0, arizona_in_ev,
323 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
324
325SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
326 ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
327SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2,
328 ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
329SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3,
330 ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
331
332SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR,
333 ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0),
334
335SND_SOC_DAPM_PGA("Tone Generator 1", ARIZONA_TONE_GENERATOR_1,
336 ARIZONA_TONE1_ENA_SHIFT, 0, NULL, 0),
337SND_SOC_DAPM_PGA("Tone Generator 2", ARIZONA_TONE_GENERATOR_1,
338 ARIZONA_TONE2_ENA_SHIFT, 0, NULL, 0),
339
340SND_SOC_DAPM_PGA("Mic Mute Mixer", ARIZONA_MIC_NOISE_MIX_CONTROL_1,
341 ARIZONA_MICMUTE_MIX_ENA_SHIFT, 0, NULL, 0),
342
343SND_SOC_DAPM_PGA("EQ1", ARIZONA_EQ1_1, ARIZONA_EQ1_ENA_SHIFT, 0, NULL, 0),
344SND_SOC_DAPM_PGA("EQ2", ARIZONA_EQ2_1, ARIZONA_EQ2_ENA_SHIFT, 0, NULL, 0),
345SND_SOC_DAPM_PGA("EQ3", ARIZONA_EQ3_1, ARIZONA_EQ3_ENA_SHIFT, 0, NULL, 0),
346SND_SOC_DAPM_PGA("EQ4", ARIZONA_EQ4_1, ARIZONA_EQ4_ENA_SHIFT, 0, NULL, 0),
347
348SND_SOC_DAPM_PGA("DRC1L", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1L_ENA_SHIFT, 0,
349 NULL, 0),
350SND_SOC_DAPM_PGA("DRC1R", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1R_ENA_SHIFT, 0,
351 NULL, 0),
352SND_SOC_DAPM_PGA("DRC2L", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2L_ENA_SHIFT, 0,
353 NULL, 0),
354SND_SOC_DAPM_PGA("DRC2R", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2R_ENA_SHIFT, 0,
355 NULL, 0),
356
357SND_SOC_DAPM_PGA("LHPF1", ARIZONA_HPLPF1_1, ARIZONA_LHPF1_ENA_SHIFT, 0,
358 NULL, 0),
359SND_SOC_DAPM_PGA("LHPF2", ARIZONA_HPLPF2_1, ARIZONA_LHPF2_ENA_SHIFT, 0,
360 NULL, 0),
361SND_SOC_DAPM_PGA("LHPF3", ARIZONA_HPLPF3_1, ARIZONA_LHPF3_ENA_SHIFT, 0,
362 NULL, 0),
363SND_SOC_DAPM_PGA("LHPF4", ARIZONA_HPLPF4_1, ARIZONA_LHPF4_ENA_SHIFT, 0,
364 NULL, 0),
365
366SND_SOC_DAPM_PGA("PWM1 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM1_ENA_SHIFT,
367 0, NULL, 0),
368SND_SOC_DAPM_PGA("PWM2 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM2_ENA_SHIFT,
369 0, NULL, 0),
370
371SND_SOC_DAPM_PGA("ASRC1L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1L_ENA_SHIFT, 0,
372 NULL, 0),
373SND_SOC_DAPM_PGA("ASRC1R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1R_ENA_SHIFT, 0,
374 NULL, 0),
375SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0,
376 NULL, 0),
377SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0,
378 NULL, 0),
379
380SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0,
381 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0),
382SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0,
383 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX2_ENA_SHIFT, 0),
384SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0,
385 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX3_ENA_SHIFT, 0),
386SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0,
387 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX4_ENA_SHIFT, 0),
388SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0,
389 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX5_ENA_SHIFT, 0),
390SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0,
391 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX6_ENA_SHIFT, 0),
392SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0,
393 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX7_ENA_SHIFT, 0),
394SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0,
395 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX8_ENA_SHIFT, 0),
396
397SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0,
398 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX1_ENA_SHIFT, 0),
399SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0,
400 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX2_ENA_SHIFT, 0),
401SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0,
402 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX3_ENA_SHIFT, 0),
403SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0,
404 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX4_ENA_SHIFT, 0),
405SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0,
406 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX5_ENA_SHIFT, 0),
407SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0,
408 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX6_ENA_SHIFT, 0),
409SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0,
410 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX7_ENA_SHIFT, 0),
411SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0,
412 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX8_ENA_SHIFT, 0),
413
414SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0,
415 ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0),
416SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0,
417 ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0),
418
419SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0,
420 ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0),
421SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0,
422 ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0),
423
424SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0,
425 ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0),
426SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0,
427 ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX2_ENA_SHIFT, 0),
428
429SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
430 ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX1_ENA_SHIFT, 0),
431SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
432 ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
433
434SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1,
435 ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
436 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
437SND_SOC_DAPM_PGA_E("OUT1R", ARIZONA_OUTPUT_ENABLES_1,
438 ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
439 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
440SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1,
441 ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
442 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
443SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1,
444 ARIZONA_OUT2R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
445 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
446SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1,
447 ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
448 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
449SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1,
450 ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
451 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
452SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1,
453 ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
454 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
455SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1,
456 ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
457 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
458SND_SOC_DAPM_PGA_E("OUT5R", ARIZONA_OUTPUT_ENABLES_1,
459 ARIZONA_OUT5R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
460 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
461
462ARIZONA_MIXER_WIDGETS(EQ1, "EQ1"),
463ARIZONA_MIXER_WIDGETS(EQ2, "EQ2"),
464ARIZONA_MIXER_WIDGETS(EQ3, "EQ3"),
465ARIZONA_MIXER_WIDGETS(EQ4, "EQ4"),
466
467ARIZONA_MIXER_WIDGETS(DRC1L, "DRC1L"),
468ARIZONA_MIXER_WIDGETS(DRC1R, "DRC1R"),
469ARIZONA_MIXER_WIDGETS(DRC2L, "DRC2L"),
470ARIZONA_MIXER_WIDGETS(DRC2R, "DRC2R"),
471
472ARIZONA_MIXER_WIDGETS(LHPF1, "LHPF1"),
473ARIZONA_MIXER_WIDGETS(LHPF2, "LHPF2"),
474ARIZONA_MIXER_WIDGETS(LHPF3, "LHPF3"),
475ARIZONA_MIXER_WIDGETS(LHPF4, "LHPF4"),
476
477ARIZONA_MIXER_WIDGETS(Mic, "Mic"),
478ARIZONA_MIXER_WIDGETS(Noise, "Noise"),
479
480ARIZONA_MIXER_WIDGETS(PWM1, "PWM1"),
481ARIZONA_MIXER_WIDGETS(PWM2, "PWM2"),
482
483ARIZONA_MIXER_WIDGETS(OUT1L, "HPOUT1L"),
484ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUT1R"),
485ARIZONA_MIXER_WIDGETS(OUT2L, "HPOUT2L"),
486ARIZONA_MIXER_WIDGETS(OUT2R, "HPOUT2R"),
487ARIZONA_MIXER_WIDGETS(OUT3, "EPOUT"),
488ARIZONA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"),
489ARIZONA_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"),
490ARIZONA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"),
491ARIZONA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"),
492
493ARIZONA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
494ARIZONA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
495ARIZONA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
496ARIZONA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
497ARIZONA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
498ARIZONA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
499ARIZONA_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"),
500ARIZONA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"),
501
502ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"),
503ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
504
505ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
506ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
507
508ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"),
509ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"),
510ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"),
511ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"),
512
513SND_SOC_DAPM_OUTPUT("HPOUT1L"),
514SND_SOC_DAPM_OUTPUT("HPOUT1R"),
515SND_SOC_DAPM_OUTPUT("HPOUT2L"),
516SND_SOC_DAPM_OUTPUT("HPOUT2R"),
517SND_SOC_DAPM_OUTPUT("EPOUTN"),
518SND_SOC_DAPM_OUTPUT("EPOUTP"),
519SND_SOC_DAPM_OUTPUT("SPKOUTLN"),
520SND_SOC_DAPM_OUTPUT("SPKOUTLP"),
521SND_SOC_DAPM_OUTPUT("SPKOUTRN"),
522SND_SOC_DAPM_OUTPUT("SPKOUTRP"),
523SND_SOC_DAPM_OUTPUT("SPKDAT1L"),
524SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
525};
526
527#define ARIZONA_MIXER_INPUT_ROUTES(name) \
528 { name, "Noise Generator", "Noise Generator" }, \
529 { name, "Tone Generator 1", "Tone Generator 1" }, \
530 { name, "Tone Generator 2", "Tone Generator 2" }, \
531 { name, "IN1L", "IN1L PGA" }, \
532 { name, "IN1R", "IN1R PGA" }, \
533 { name, "IN2L", "IN2L PGA" }, \
534 { name, "IN2R", "IN2R PGA" }, \
535 { name, "IN3L", "IN3L PGA" }, \
536 { name, "IN3R", "IN3R PGA" }, \
537 { name, "Mic Mute Mixer", "Mic Mute Mixer" }, \
538 { name, "AIF1RX1", "AIF1RX1" }, \
539 { name, "AIF1RX2", "AIF1RX2" }, \
540 { name, "AIF1RX3", "AIF1RX3" }, \
541 { name, "AIF1RX4", "AIF1RX4" }, \
542 { name, "AIF1RX5", "AIF1RX5" }, \
543 { name, "AIF1RX6", "AIF1RX6" }, \
544 { name, "AIF1RX7", "AIF1RX7" }, \
545 { name, "AIF1RX8", "AIF1RX8" }, \
546 { name, "AIF2RX1", "AIF2RX1" }, \
547 { name, "AIF2RX2", "AIF2RX2" }, \
548 { name, "AIF3RX1", "AIF3RX1" }, \
549 { name, "AIF3RX2", "AIF3RX2" }, \
550 { name, "EQ1", "EQ1" }, \
551 { name, "EQ2", "EQ2" }, \
552 { name, "EQ3", "EQ3" }, \
553 { name, "EQ4", "EQ4" }, \
554 { name, "DRC1L", "DRC1L" }, \
555 { name, "DRC1R", "DRC1R" }, \
556 { name, "DRC2L", "DRC2L" }, \
557 { name, "DRC2R", "DRC2R" }, \
558 { name, "LHPF1", "LHPF1" }, \
559 { name, "LHPF2", "LHPF2" }, \
560 { name, "LHPF3", "LHPF3" }, \
561 { name, "LHPF4", "LHPF4" }, \
562 { name, "ASRC1L", "ASRC1L" }, \
563 { name, "ASRC1R", "ASRC1R" }, \
564 { name, "ASRC2L", "ASRC2L" }, \
565 { name, "ASRC2R", "ASRC2R" }
566
567static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
568 { "AIF2 Capture", NULL, "DBVDD2" },
569 { "AIF2 Playback", NULL, "DBVDD2" },
570
571 { "AIF3 Capture", NULL, "DBVDD3" },
572 { "AIF3 Playback", NULL, "DBVDD3" },
573
574 { "OUT1L", NULL, "CPVDD" },
575 { "OUT1R", NULL, "CPVDD" },
576 { "OUT2L", NULL, "CPVDD" },
577 { "OUT2R", NULL, "CPVDD" },
578 { "OUT3L", NULL, "CPVDD" },
579
580 { "OUT4L", NULL, "SPKVDDL" },
581 { "OUT4R", NULL, "SPKVDDR" },
582
583 { "OUT1L", NULL, "SYSCLK" },
584 { "OUT1R", NULL, "SYSCLK" },
585 { "OUT2L", NULL, "SYSCLK" },
586 { "OUT2R", NULL, "SYSCLK" },
587 { "OUT3L", NULL, "SYSCLK" },
588 { "OUT4L", NULL, "SYSCLK" },
589 { "OUT4R", NULL, "SYSCLK" },
590 { "OUT5L", NULL, "SYSCLK" },
591 { "OUT5R", NULL, "SYSCLK" },
592
593 { "MICBIAS1", NULL, "MICVDD" },
594 { "MICBIAS2", NULL, "MICVDD" },
595 { "MICBIAS3", NULL, "MICVDD" },
596
597 { "Noise Generator", NULL, "NOISE" },
598 { "Tone Generator 1", NULL, "TONE" },
599 { "Tone Generator 2", NULL, "TONE" },
600
601 { "Mic Mute Mixer", NULL, "Noise Mixer" },
602 { "Mic Mute Mixer", NULL, "Mic Mixer" },
603
604 { "AIF1 Capture", NULL, "AIF1TX1" },
605 { "AIF1 Capture", NULL, "AIF1TX2" },
606 { "AIF1 Capture", NULL, "AIF1TX3" },
607 { "AIF1 Capture", NULL, "AIF1TX4" },
608 { "AIF1 Capture", NULL, "AIF1TX5" },
609 { "AIF1 Capture", NULL, "AIF1TX6" },
610 { "AIF1 Capture", NULL, "AIF1TX7" },
611 { "AIF1 Capture", NULL, "AIF1TX8" },
612
613 { "AIF1RX1", NULL, "AIF1 Playback" },
614 { "AIF1RX2", NULL, "AIF1 Playback" },
615 { "AIF1RX3", NULL, "AIF1 Playback" },
616 { "AIF1RX4", NULL, "AIF1 Playback" },
617 { "AIF1RX5", NULL, "AIF1 Playback" },
618 { "AIF1RX6", NULL, "AIF1 Playback" },
619 { "AIF1RX7", NULL, "AIF1 Playback" },
620 { "AIF1RX8", NULL, "AIF1 Playback" },
621
622 { "AIF2 Capture", NULL, "AIF2TX1" },
623 { "AIF2 Capture", NULL, "AIF2TX2" },
624
625 { "AIF2RX1", NULL, "AIF2 Playback" },
626 { "AIF2RX2", NULL, "AIF2 Playback" },
627
628 { "AIF3 Capture", NULL, "AIF3TX1" },
629 { "AIF3 Capture", NULL, "AIF3TX2" },
630
631 { "AIF3RX1", NULL, "AIF3 Playback" },
632 { "AIF3RX2", NULL, "AIF3 Playback" },
633
634 { "AIF1 Playback", NULL, "SYSCLK" },
635 { "AIF2 Playback", NULL, "SYSCLK" },
636 { "AIF3 Playback", NULL, "SYSCLK" },
637
638 { "AIF1 Capture", NULL, "SYSCLK" },
639 { "AIF2 Capture", NULL, "SYSCLK" },
640 { "AIF3 Capture", NULL, "SYSCLK" },
641
642 ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
643 ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),
644 ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"),
645 ARIZONA_MIXER_ROUTES("OUT2R", "HPOUT2R"),
646 ARIZONA_MIXER_ROUTES("OUT3L", "EPOUT"),
647
648 ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUTL"),
649 ARIZONA_MIXER_ROUTES("OUT4R", "SPKOUTR"),
650 ARIZONA_MIXER_ROUTES("OUT5L", "SPKDAT1L"),
651 ARIZONA_MIXER_ROUTES("OUT5R", "SPKDAT1R"),
652
653 ARIZONA_MIXER_ROUTES("PWM1 Driver", "PWM1"),
654 ARIZONA_MIXER_ROUTES("PWM2 Driver", "PWM2"),
655
656 ARIZONA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
657 ARIZONA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
658 ARIZONA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
659 ARIZONA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
660 ARIZONA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
661 ARIZONA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
662 ARIZONA_MIXER_ROUTES("AIF1TX7", "AIF1TX7"),
663 ARIZONA_MIXER_ROUTES("AIF1TX8", "AIF1TX8"),
664
665 ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"),
666 ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"),
667
668 ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"),
669 ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"),
670
671 ARIZONA_MIXER_ROUTES("EQ1", "EQ1"),
672 ARIZONA_MIXER_ROUTES("EQ2", "EQ2"),
673 ARIZONA_MIXER_ROUTES("EQ3", "EQ3"),
674 ARIZONA_MIXER_ROUTES("EQ4", "EQ4"),
675
676 ARIZONA_MIXER_ROUTES("DRC1L", "DRC1L"),
677 ARIZONA_MIXER_ROUTES("DRC1R", "DRC1R"),
678 ARIZONA_MIXER_ROUTES("DRC2L", "DRC2L"),
679 ARIZONA_MIXER_ROUTES("DRC2R", "DRC2R"),
680
681 ARIZONA_MIXER_ROUTES("LHPF1", "LHPF1"),
682 ARIZONA_MIXER_ROUTES("LHPF2", "LHPF2"),
683 ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
684 ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
685
686 ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"),
687 ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"),
688 ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"),
689 ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"),
690
691 { "HPOUT1L", NULL, "OUT1L" },
692 { "HPOUT1R", NULL, "OUT1R" },
693
694 { "HPOUT2L", NULL, "OUT2L" },
695 { "HPOUT2R", NULL, "OUT2R" },
696
697 { "EPOUTN", NULL, "OUT3L" },
698 { "EPOUTP", NULL, "OUT3L" },
699
700 { "SPKOUTLN", NULL, "OUT4L" },
701 { "SPKOUTLP", NULL, "OUT4L" },
702
703 { "SPKOUTRN", NULL, "OUT4R" },
704 { "SPKOUTRP", NULL, "OUT4R" },
705
706 { "SPKDAT1L", NULL, "OUT5L" },
707 { "SPKDAT1R", NULL, "OUT5R" },
708};
709
710static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
711 unsigned int Fref, unsigned int Fout)
712{
713 struct wm5102_priv *wm5102 = snd_soc_codec_get_drvdata(codec);
714
715 switch (fll_id) {
716 case WM5102_FLL1:
717 return arizona_set_fll(&wm5102->fll[0], source, Fref, Fout);
718 case WM5102_FLL2:
719 return arizona_set_fll(&wm5102->fll[1], source, Fref, Fout);
720 default:
721 return -EINVAL;
722 }
723}
724
725#define WM5102_RATES SNDRV_PCM_RATE_8000_192000
726
727#define WM5102_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
728 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
729
730static struct snd_soc_dai_driver wm5102_dai[] = {
731 {
732 .name = "wm5102-aif1",
733 .id = 1,
734 .base = ARIZONA_AIF1_BCLK_CTRL,
735 .playback = {
736 .stream_name = "AIF1 Playback",
737 .channels_min = 1,
738 .channels_max = 8,
739 .rates = WM5102_RATES,
740 .formats = WM5102_FORMATS,
741 },
742 .capture = {
743 .stream_name = "AIF1 Capture",
744 .channels_min = 1,
745 .channels_max = 8,
746 .rates = WM5102_RATES,
747 .formats = WM5102_FORMATS,
748 },
749 .ops = &arizona_dai_ops,
750 .symmetric_rates = 1,
751 },
752 {
753 .name = "wm5102-aif2",
754 .id = 2,
755 .base = ARIZONA_AIF2_BCLK_CTRL,
756 .playback = {
757 .stream_name = "AIF2 Playback",
758 .channels_min = 1,
759 .channels_max = 2,
760 .rates = WM5102_RATES,
761 .formats = WM5102_FORMATS,
762 },
763 .capture = {
764 .stream_name = "AIF2 Capture",
765 .channels_min = 1,
766 .channels_max = 2,
767 .rates = WM5102_RATES,
768 .formats = WM5102_FORMATS,
769 },
770 .ops = &arizona_dai_ops,
771 .symmetric_rates = 1,
772 },
773 {
774 .name = "wm5102-aif3",
775 .id = 3,
776 .base = ARIZONA_AIF3_BCLK_CTRL,
777 .playback = {
778 .stream_name = "AIF3 Playback",
779 .channels_min = 1,
780 .channels_max = 2,
781 .rates = WM5102_RATES,
782 .formats = WM5102_FORMATS,
783 },
784 .capture = {
785 .stream_name = "AIF3 Capture",
786 .channels_min = 1,
787 .channels_max = 2,
788 .rates = WM5102_RATES,
789 .formats = WM5102_FORMATS,
790 },
791 .ops = &arizona_dai_ops,
792 .symmetric_rates = 1,
793 },
794};
795
796static int wm5102_codec_probe(struct snd_soc_codec *codec)
797{
798 struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
799
800 codec->control_data = priv->core.arizona->regmap;
801 return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
802}
803
804#define WM5102_DIG_VU 0x0200
805
806static unsigned int wm5102_digital_vu[] = {
807 ARIZONA_ADC_DIGITAL_VOLUME_1L,
808 ARIZONA_ADC_DIGITAL_VOLUME_1R,
809 ARIZONA_ADC_DIGITAL_VOLUME_2L,
810 ARIZONA_ADC_DIGITAL_VOLUME_2R,
811 ARIZONA_ADC_DIGITAL_VOLUME_3L,
812 ARIZONA_ADC_DIGITAL_VOLUME_3R,
813
814 ARIZONA_DAC_DIGITAL_VOLUME_1L,
815 ARIZONA_DAC_DIGITAL_VOLUME_1R,
816 ARIZONA_DAC_DIGITAL_VOLUME_2L,
817 ARIZONA_DAC_DIGITAL_VOLUME_2R,
818 ARIZONA_DAC_DIGITAL_VOLUME_3L,
819 ARIZONA_DAC_DIGITAL_VOLUME_3R,
820 ARIZONA_DAC_DIGITAL_VOLUME_4L,
821 ARIZONA_DAC_DIGITAL_VOLUME_4R,
822 ARIZONA_DAC_DIGITAL_VOLUME_5L,
823 ARIZONA_DAC_DIGITAL_VOLUME_5R,
824};
825
826static struct snd_soc_codec_driver soc_codec_dev_wm5102 = {
827 .probe = wm5102_codec_probe,
828
829 .idle_bias_off = true,
830
831 .set_sysclk = arizona_set_sysclk,
832 .set_pll = wm5102_set_fll,
833
834 .controls = wm5102_snd_controls,
835 .num_controls = ARRAY_SIZE(wm5102_snd_controls),
836 .dapm_widgets = wm5102_dapm_widgets,
837 .num_dapm_widgets = ARRAY_SIZE(wm5102_dapm_widgets),
838 .dapm_routes = wm5102_dapm_routes,
839 .num_dapm_routes = ARRAY_SIZE(wm5102_dapm_routes),
840};
841
842static int __devinit wm5102_probe(struct platform_device *pdev)
843{
844 struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
845 struct wm5102_priv *wm5102;
846 int i;
847
848 wm5102 = devm_kzalloc(&pdev->dev, sizeof(struct wm5102_priv),
849 GFP_KERNEL);
850 if (wm5102 == NULL)
851 return -ENOMEM;
852 platform_set_drvdata(pdev, wm5102);
853
854 wm5102->core.arizona = arizona;
855
856 for (i = 0; i < ARRAY_SIZE(wm5102->fll); i++)
857 wm5102->fll[i].vco_mult = 1;
858
859 arizona_init_fll(arizona, 1, ARIZONA_FLL1_CONTROL_1 - 1,
860 ARIZONA_IRQ_FLL1_LOCK, ARIZONA_IRQ_FLL1_CLOCK_OK,
861 &wm5102->fll[0]);
862 arizona_init_fll(arizona, 2, ARIZONA_FLL2_CONTROL_1 - 1,
863 ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK,
864 &wm5102->fll[1]);
865
866 for (i = 0; i < ARRAY_SIZE(wm5102_dai); i++)
867 arizona_init_dai(&wm5102->core, i);
868
869 /* Latch volume update bits */
870 for (i = 0; i < ARRAY_SIZE(wm5102_digital_vu); i++)
871 regmap_update_bits(arizona->regmap, wm5102_digital_vu[i],
872 WM5102_DIG_VU, WM5102_DIG_VU);
873
874 pm_runtime_enable(&pdev->dev);
875 pm_runtime_idle(&pdev->dev);
876
877 return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5102,
878 wm5102_dai, ARRAY_SIZE(wm5102_dai));
879}
880
881static int __devexit wm5102_remove(struct platform_device *pdev)
882{
883 snd_soc_unregister_codec(&pdev->dev);
884 pm_runtime_disable(&pdev->dev);
885
886 return 0;
887}
888
889static struct platform_driver wm5102_codec_driver = {
890 .driver = {
891 .name = "wm5102-codec",
892 .owner = THIS_MODULE,
893 },
894 .probe = wm5102_probe,
895 .remove = __devexit_p(wm5102_remove),
896};
897
898module_platform_driver(wm5102_codec_driver);
899
900MODULE_DESCRIPTION("ASoC WM5102 driver");
901MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
902MODULE_LICENSE("GPL");
903MODULE_ALIAS("platform:wm5102-codec");
diff --git a/sound/soc/codecs/wm5102.h b/sound/soc/codecs/wm5102.h
new file mode 100644
index 00000000000..d30477f3070
--- /dev/null
+++ b/sound/soc/codecs/wm5102.h
@@ -0,0 +1,21 @@
1/*
2 * wm5102.h -- WM5102 ALSA SoC Audio driver
3 *
4 * Copyright 2012 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef _WM5102_H
14#define _WM5102_H
15
16#include "arizona.h"
17
18#define WM5102_FLL1 1
19#define WM5102_FLL2 2
20
21#endif
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
new file mode 100644
index 00000000000..8033f706518
--- /dev/null
+++ b/sound/soc/codecs/wm5110.c
@@ -0,0 +1,950 @@
1/*
2 * wm5110.c -- WM5110 ALSA SoC Audio driver
3 *
4 * Copyright 2012 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/init.h>
16#include <linux/delay.h>
17#include <linux/pm.h>
18#include <linux/pm_runtime.h>
19#include <linux/regmap.h>
20#include <linux/slab.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/pcm_params.h>
24#include <sound/soc.h>
25#include <sound/jack.h>
26#include <sound/initval.h>
27#include <sound/tlv.h>
28
29#include <linux/mfd/arizona/core.h>
30#include <linux/mfd/arizona/registers.h>
31
32#include "arizona.h"
33#include "wm5110.h"
34
35struct wm5110_priv {
36 struct arizona_priv core;
37 struct arizona_fll fll[2];
38};
39
40static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0);
41static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
42static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
43static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0);
44
45static const struct snd_kcontrol_new wm5110_snd_controls[] = {
46SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL,
47 ARIZONA_IN1_OSR_SHIFT, 1, 0),
48SOC_SINGLE("IN2 High Performance Switch", ARIZONA_IN2L_CONTROL,
49 ARIZONA_IN2_OSR_SHIFT, 1, 0),
50SOC_SINGLE("IN3 High Performance Switch", ARIZONA_IN3L_CONTROL,
51 ARIZONA_IN3_OSR_SHIFT, 1, 0),
52SOC_SINGLE("IN4 High Performance Switch", ARIZONA_IN4L_CONTROL,
53 ARIZONA_IN4_OSR_SHIFT, 1, 0),
54
55SOC_DOUBLE_R_RANGE_TLV("IN1 Volume", ARIZONA_IN1L_CONTROL,
56 ARIZONA_IN1R_CONTROL,
57 ARIZONA_IN1L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
58SOC_DOUBLE_R_RANGE_TLV("IN2 Volume", ARIZONA_IN2L_CONTROL,
59 ARIZONA_IN2R_CONTROL,
60 ARIZONA_IN2L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
61SOC_DOUBLE_R_RANGE_TLV("IN3 Volume", ARIZONA_IN3L_CONTROL,
62 ARIZONA_IN3R_CONTROL,
63 ARIZONA_IN3L_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
64
65SOC_DOUBLE_R("IN1 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_1L,
66 ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_MUTE_SHIFT, 1, 1),
67SOC_DOUBLE_R("IN2 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_2L,
68 ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_MUTE_SHIFT, 1, 1),
69SOC_DOUBLE_R("IN3 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_3L,
70 ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_MUTE_SHIFT, 1, 1),
71SOC_DOUBLE_R("IN4 Digital Switch", ARIZONA_ADC_DIGITAL_VOLUME_4L,
72 ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_IN4L_MUTE_SHIFT, 1, 1),
73
74SOC_DOUBLE_R_TLV("IN1 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L,
75 ARIZONA_ADC_DIGITAL_VOLUME_1R, ARIZONA_IN1L_DIG_VOL_SHIFT,
76 0xbf, 0, digital_tlv),
77SOC_DOUBLE_R_TLV("IN2 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_2L,
78 ARIZONA_ADC_DIGITAL_VOLUME_2R, ARIZONA_IN2L_DIG_VOL_SHIFT,
79 0xbf, 0, digital_tlv),
80SOC_DOUBLE_R_TLV("IN3 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_3L,
81 ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_DIG_VOL_SHIFT,
82 0xbf, 0, digital_tlv),
83SOC_DOUBLE_R_TLV("IN4 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_4L,
84 ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_IN4L_DIG_VOL_SHIFT,
85 0xbf, 0, digital_tlv),
86
87ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE),
88ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
89ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
90ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
91
92SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
93 24, 0, eq_tlv),
94SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
95 24, 0, eq_tlv),
96SOC_SINGLE_TLV("EQ1 B3 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B3_GAIN_SHIFT,
97 24, 0, eq_tlv),
98SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
99 24, 0, eq_tlv),
100SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT,
101 24, 0, eq_tlv),
102
103SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT,
104 24, 0, eq_tlv),
105SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT,
106 24, 0, eq_tlv),
107SOC_SINGLE_TLV("EQ2 B3 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B3_GAIN_SHIFT,
108 24, 0, eq_tlv),
109SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
110 24, 0, eq_tlv),
111SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT,
112 24, 0, eq_tlv),
113
114SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT,
115 24, 0, eq_tlv),
116SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT,
117 24, 0, eq_tlv),
118SOC_SINGLE_TLV("EQ3 B3 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B3_GAIN_SHIFT,
119 24, 0, eq_tlv),
120SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT,
121 24, 0, eq_tlv),
122SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT,
123 24, 0, eq_tlv),
124
125SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT,
126 24, 0, eq_tlv),
127SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT,
128 24, 0, eq_tlv),
129SOC_SINGLE_TLV("EQ4 B3 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B3_GAIN_SHIFT,
130 24, 0, eq_tlv),
131SOC_SINGLE_TLV("EQ4 B4 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B4_GAIN_SHIFT,
132 24, 0, eq_tlv),
133SOC_SINGLE_TLV("EQ4 B5 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B5_GAIN_SHIFT,
134 24, 0, eq_tlv),
135
136ARIZONA_MIXER_CONTROLS("DRC1L", ARIZONA_DRC1LMIX_INPUT_1_SOURCE),
137ARIZONA_MIXER_CONTROLS("DRC1R", ARIZONA_DRC1RMIX_INPUT_1_SOURCE),
138ARIZONA_MIXER_CONTROLS("DRC2L", ARIZONA_DRC2LMIX_INPUT_1_SOURCE),
139ARIZONA_MIXER_CONTROLS("DRC2R", ARIZONA_DRC2RMIX_INPUT_1_SOURCE),
140
141SND_SOC_BYTES_MASK("DRC1", ARIZONA_DRC1_CTRL1, 5,
142 ARIZONA_DRC1R_ENA | ARIZONA_DRC1L_ENA),
143SND_SOC_BYTES_MASK("DRC2", ARIZONA_DRC2_CTRL1, 5,
144 ARIZONA_DRC2R_ENA | ARIZONA_DRC2L_ENA),
145
146ARIZONA_MIXER_CONTROLS("LHPF1", ARIZONA_HPLP1MIX_INPUT_1_SOURCE),
147ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
148ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
149ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
150
151SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
152SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
153SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
154SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
155
156ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE),
157ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE),
158
159SOC_SINGLE_TLV("Noise Generator Volume", ARIZONA_COMFORT_NOISE_GENERATOR,
160 ARIZONA_NOISE_GEN_GAIN_SHIFT, 0x16, 0, noise_tlv),
161
162ARIZONA_MIXER_CONTROLS("HPOUT1L", ARIZONA_OUT1LMIX_INPUT_1_SOURCE),
163ARIZONA_MIXER_CONTROLS("HPOUT1R", ARIZONA_OUT1RMIX_INPUT_1_SOURCE),
164ARIZONA_MIXER_CONTROLS("HPOUT2L", ARIZONA_OUT2LMIX_INPUT_1_SOURCE),
165ARIZONA_MIXER_CONTROLS("HPOUT2R", ARIZONA_OUT2RMIX_INPUT_1_SOURCE),
166ARIZONA_MIXER_CONTROLS("EPOUT", ARIZONA_OUT3LMIX_INPUT_1_SOURCE),
167ARIZONA_MIXER_CONTROLS("SPKOUTL", ARIZONA_OUT4LMIX_INPUT_1_SOURCE),
168ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE),
169ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE),
170ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE),
171ARIZONA_MIXER_CONTROLS("SPKDAT2L", ARIZONA_OUT6LMIX_INPUT_1_SOURCE),
172ARIZONA_MIXER_CONTROLS("SPKDAT2R", ARIZONA_OUT6RMIX_INPUT_1_SOURCE),
173
174SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L,
175 ARIZONA_OUT1_OSR_SHIFT, 1, 0),
176SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L,
177 ARIZONA_OUT2_OSR_SHIFT, 1, 0),
178SOC_SINGLE("EPOUT High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L,
179 ARIZONA_OUT3_OSR_SHIFT, 1, 0),
180SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
181 ARIZONA_OUT4_OSR_SHIFT, 1, 0),
182SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
183 ARIZONA_OUT5_OSR_SHIFT, 1, 0),
184SOC_SINGLE("SPKDAT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_6L,
185 ARIZONA_OUT6_OSR_SHIFT, 1, 0),
186
187SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L,
188 ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1),
189SOC_DOUBLE_R("OUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L,
190 ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_MUTE_SHIFT, 1, 1),
191SOC_SINGLE("EPOUT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L,
192 ARIZONA_OUT3L_MUTE_SHIFT, 1, 1),
193SOC_DOUBLE_R("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L,
194 ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_MUTE_SHIFT, 1, 1),
195SOC_DOUBLE_R("SPKDAT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_5L,
196 ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_MUTE_SHIFT, 1, 1),
197SOC_DOUBLE_R("SPKDAT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_6L,
198 ARIZONA_DAC_DIGITAL_VOLUME_6R, ARIZONA_OUT6L_MUTE_SHIFT, 1, 1),
199
200SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_1L,
201 ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_VOL_SHIFT,
202 0xbf, 0, digital_tlv),
203SOC_DOUBLE_R_TLV("OUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L,
204 ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_VOL_SHIFT,
205 0xbf, 0, digital_tlv),
206SOC_SINGLE_TLV("EPOUT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L,
207 ARIZONA_OUT3L_VOL_SHIFT, 0xbf, 0, digital_tlv),
208SOC_DOUBLE_R_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L,
209 ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_VOL_SHIFT,
210 0xbf, 0, digital_tlv),
211SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
212 ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT,
213 0xbf, 0, digital_tlv),
214SOC_DOUBLE_R_TLV("SPKDAT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_6L,
215 ARIZONA_DAC_DIGITAL_VOLUME_6R, ARIZONA_OUT6L_VOL_SHIFT,
216 0xbf, 0, digital_tlv),
217
218SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L,
219 ARIZONA_OUTPUT_PATH_CONFIG_1R,
220 ARIZONA_OUT1L_PGA_VOL_SHIFT,
221 0x34, 0x40, 0, ana_tlv),
222SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L,
223 ARIZONA_OUTPUT_PATH_CONFIG_2R,
224 ARIZONA_OUT2L_PGA_VOL_SHIFT,
225 0x34, 0x40, 0, ana_tlv),
226SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L,
227 ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv),
228
229SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
230 ARIZONA_SPK1R_MUTE_SHIFT, 1, 1),
231SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT,
232 ARIZONA_SPK2R_MUTE_SHIFT, 1, 1),
233
234ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE),
235ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE),
236ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE),
237ARIZONA_MIXER_CONTROLS("AIF1TX4", ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE),
238ARIZONA_MIXER_CONTROLS("AIF1TX5", ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE),
239ARIZONA_MIXER_CONTROLS("AIF1TX6", ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE),
240ARIZONA_MIXER_CONTROLS("AIF1TX7", ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE),
241ARIZONA_MIXER_CONTROLS("AIF1TX8", ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE),
242
243ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE),
244ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE),
245
246ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE),
247ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE),
248};
249
250ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE);
251ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE);
252ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE);
253ARIZONA_MIXER_ENUMS(EQ4, ARIZONA_EQ4MIX_INPUT_1_SOURCE);
254
255ARIZONA_MIXER_ENUMS(DRC1L, ARIZONA_DRC1LMIX_INPUT_1_SOURCE);
256ARIZONA_MIXER_ENUMS(DRC1R, ARIZONA_DRC1RMIX_INPUT_1_SOURCE);
257ARIZONA_MIXER_ENUMS(DRC2L, ARIZONA_DRC2LMIX_INPUT_1_SOURCE);
258ARIZONA_MIXER_ENUMS(DRC2R, ARIZONA_DRC2RMIX_INPUT_1_SOURCE);
259
260ARIZONA_MIXER_ENUMS(LHPF1, ARIZONA_HPLP1MIX_INPUT_1_SOURCE);
261ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE);
262ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE);
263ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE);
264
265ARIZONA_MIXER_ENUMS(Mic, ARIZONA_MICMIX_INPUT_1_SOURCE);
266ARIZONA_MIXER_ENUMS(Noise, ARIZONA_NOISEMIX_INPUT_1_SOURCE);
267
268ARIZONA_MIXER_ENUMS(PWM1, ARIZONA_PWM1MIX_INPUT_1_SOURCE);
269ARIZONA_MIXER_ENUMS(PWM2, ARIZONA_PWM2MIX_INPUT_1_SOURCE);
270
271ARIZONA_MIXER_ENUMS(OUT1L, ARIZONA_OUT1LMIX_INPUT_1_SOURCE);
272ARIZONA_MIXER_ENUMS(OUT1R, ARIZONA_OUT1RMIX_INPUT_1_SOURCE);
273ARIZONA_MIXER_ENUMS(OUT2L, ARIZONA_OUT2LMIX_INPUT_1_SOURCE);
274ARIZONA_MIXER_ENUMS(OUT2R, ARIZONA_OUT2RMIX_INPUT_1_SOURCE);
275ARIZONA_MIXER_ENUMS(OUT3, ARIZONA_OUT3LMIX_INPUT_1_SOURCE);
276ARIZONA_MIXER_ENUMS(SPKOUTL, ARIZONA_OUT4LMIX_INPUT_1_SOURCE);
277ARIZONA_MIXER_ENUMS(SPKOUTR, ARIZONA_OUT4RMIX_INPUT_1_SOURCE);
278ARIZONA_MIXER_ENUMS(SPKDAT1L, ARIZONA_OUT5LMIX_INPUT_1_SOURCE);
279ARIZONA_MIXER_ENUMS(SPKDAT1R, ARIZONA_OUT5RMIX_INPUT_1_SOURCE);
280ARIZONA_MIXER_ENUMS(SPKDAT2L, ARIZONA_OUT6LMIX_INPUT_1_SOURCE);
281ARIZONA_MIXER_ENUMS(SPKDAT2R, ARIZONA_OUT6RMIX_INPUT_1_SOURCE);
282
283ARIZONA_MIXER_ENUMS(AIF1TX1, ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE);
284ARIZONA_MIXER_ENUMS(AIF1TX2, ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE);
285ARIZONA_MIXER_ENUMS(AIF1TX3, ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE);
286ARIZONA_MIXER_ENUMS(AIF1TX4, ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE);
287ARIZONA_MIXER_ENUMS(AIF1TX5, ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE);
288ARIZONA_MIXER_ENUMS(AIF1TX6, ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE);
289ARIZONA_MIXER_ENUMS(AIF1TX7, ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE);
290ARIZONA_MIXER_ENUMS(AIF1TX8, ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE);
291
292ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE);
293ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
294
295ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
296ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
297
298ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
299ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
300ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
301ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
302
303static const struct snd_soc_dapm_widget wm5110_dapm_widgets[] = {
304SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
305 0, NULL, 0),
306SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1,
307 ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0),
308
309SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0),
310SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0),
311SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
312SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0),
313SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0),
314SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0),
315
316SND_SOC_DAPM_SIGGEN("TONE"),
317SND_SOC_DAPM_SIGGEN("NOISE"),
318
319SND_SOC_DAPM_INPUT("IN1L"),
320SND_SOC_DAPM_INPUT("IN1R"),
321SND_SOC_DAPM_INPUT("IN2L"),
322SND_SOC_DAPM_INPUT("IN2R"),
323SND_SOC_DAPM_INPUT("IN3L"),
324SND_SOC_DAPM_INPUT("IN3R"),
325SND_SOC_DAPM_INPUT("IN4L"),
326SND_SOC_DAPM_INPUT("IN4R"),
327
328SND_SOC_DAPM_PGA_E("IN1L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1L_ENA_SHIFT,
329 0, NULL, 0, arizona_in_ev,
330 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
331SND_SOC_DAPM_PGA_E("IN1R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN1R_ENA_SHIFT,
332 0, NULL, 0, arizona_in_ev,
333 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
334SND_SOC_DAPM_PGA_E("IN2L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2L_ENA_SHIFT,
335 0, NULL, 0, arizona_in_ev,
336 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
337SND_SOC_DAPM_PGA_E("IN2R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN2R_ENA_SHIFT,
338 0, NULL, 0, arizona_in_ev,
339 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
340SND_SOC_DAPM_PGA_E("IN3L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3L_ENA_SHIFT,
341 0, NULL, 0, arizona_in_ev,
342 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
343SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
344 0, NULL, 0, arizona_in_ev,
345 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
346SND_SOC_DAPM_PGA_E("IN4L PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4L_ENA_SHIFT,
347 0, NULL, 0, arizona_in_ev,
348 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
349SND_SOC_DAPM_PGA_E("IN4R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN4R_ENA_SHIFT,
350 0, NULL, 0, arizona_in_ev,
351 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
352
353SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
354 ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
355SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2,
356 ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
357SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3,
358 ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
359
360SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR,
361 ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0),
362
363SND_SOC_DAPM_PGA("Tone Generator 1", ARIZONA_TONE_GENERATOR_1,
364 ARIZONA_TONE1_ENA_SHIFT, 0, NULL, 0),
365SND_SOC_DAPM_PGA("Tone Generator 2", ARIZONA_TONE_GENERATOR_1,
366 ARIZONA_TONE2_ENA_SHIFT, 0, NULL, 0),
367
368SND_SOC_DAPM_PGA("Mic Mute Mixer", ARIZONA_MIC_NOISE_MIX_CONTROL_1,
369 ARIZONA_MICMUTE_MIX_ENA_SHIFT, 0, NULL, 0),
370
371SND_SOC_DAPM_PGA("EQ1", ARIZONA_EQ1_1, ARIZONA_EQ1_ENA_SHIFT, 0, NULL, 0),
372SND_SOC_DAPM_PGA("EQ2", ARIZONA_EQ2_1, ARIZONA_EQ2_ENA_SHIFT, 0, NULL, 0),
373SND_SOC_DAPM_PGA("EQ3", ARIZONA_EQ3_1, ARIZONA_EQ3_ENA_SHIFT, 0, NULL, 0),
374SND_SOC_DAPM_PGA("EQ4", ARIZONA_EQ4_1, ARIZONA_EQ4_ENA_SHIFT, 0, NULL, 0),
375
376SND_SOC_DAPM_PGA("DRC1L", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1L_ENA_SHIFT, 0,
377 NULL, 0),
378SND_SOC_DAPM_PGA("DRC1R", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1R_ENA_SHIFT, 0,
379 NULL, 0),
380SND_SOC_DAPM_PGA("DRC2L", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2L_ENA_SHIFT, 0,
381 NULL, 0),
382SND_SOC_DAPM_PGA("DRC2R", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2R_ENA_SHIFT, 0,
383 NULL, 0),
384
385SND_SOC_DAPM_PGA("LHPF1", ARIZONA_HPLPF1_1, ARIZONA_LHPF1_ENA_SHIFT, 0,
386 NULL, 0),
387SND_SOC_DAPM_PGA("LHPF2", ARIZONA_HPLPF2_1, ARIZONA_LHPF2_ENA_SHIFT, 0,
388 NULL, 0),
389SND_SOC_DAPM_PGA("LHPF3", ARIZONA_HPLPF3_1, ARIZONA_LHPF3_ENA_SHIFT, 0,
390 NULL, 0),
391SND_SOC_DAPM_PGA("LHPF4", ARIZONA_HPLPF4_1, ARIZONA_LHPF4_ENA_SHIFT, 0,
392 NULL, 0),
393
394SND_SOC_DAPM_PGA("PWM1 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM1_ENA_SHIFT,
395 0, NULL, 0),
396SND_SOC_DAPM_PGA("PWM2 Driver", ARIZONA_PWM_DRIVE_1, ARIZONA_PWM2_ENA_SHIFT,
397 0, NULL, 0),
398
399SND_SOC_DAPM_PGA("ASRC1L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1L_ENA_SHIFT, 0,
400 NULL, 0),
401SND_SOC_DAPM_PGA("ASRC1R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC1R_ENA_SHIFT, 0,
402 NULL, 0),
403SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0,
404 NULL, 0),
405SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0,
406 NULL, 0),
407
408SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0,
409 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0),
410SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0,
411 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX2_ENA_SHIFT, 0),
412SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0,
413 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX3_ENA_SHIFT, 0),
414SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0,
415 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX4_ENA_SHIFT, 0),
416SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0,
417 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX5_ENA_SHIFT, 0),
418SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0,
419 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX6_ENA_SHIFT, 0),
420SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0,
421 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX7_ENA_SHIFT, 0),
422SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0,
423 ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX8_ENA_SHIFT, 0),
424
425SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0,
426 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX1_ENA_SHIFT, 0),
427SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0,
428 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX2_ENA_SHIFT, 0),
429SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0,
430 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX3_ENA_SHIFT, 0),
431SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0,
432 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX4_ENA_SHIFT, 0),
433SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0,
434 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX5_ENA_SHIFT, 0),
435SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0,
436 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX6_ENA_SHIFT, 0),
437SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0,
438 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX7_ENA_SHIFT, 0),
439SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0,
440 ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX8_ENA_SHIFT, 0),
441
442SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0,
443 ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0),
444SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0,
445 ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0),
446
447SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0,
448 ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0),
449SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0,
450 ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0),
451
452SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0,
453 ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0),
454SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0,
455 ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX2_ENA_SHIFT, 0),
456
457SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
458 ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX1_ENA_SHIFT, 0),
459SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
460 ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
461
462SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1,
463 ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
464 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
465SND_SOC_DAPM_PGA_E("OUT1R", ARIZONA_OUTPUT_ENABLES_1,
466 ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
467 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
468SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1,
469 ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
470 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
471SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1,
472 ARIZONA_OUT2R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
473 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
474SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1,
475 ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
476 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
477SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1,
478 ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
479 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
480SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1,
481 ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
482 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
483SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1,
484 ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
485 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
486SND_SOC_DAPM_PGA_E("OUT5R", ARIZONA_OUTPUT_ENABLES_1,
487 ARIZONA_OUT5R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
488 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
489SND_SOC_DAPM_PGA_E("OUT6L", ARIZONA_OUTPUT_ENABLES_1,
490 ARIZONA_OUT6L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
491 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
492SND_SOC_DAPM_PGA_E("OUT6R", ARIZONA_OUTPUT_ENABLES_1,
493 ARIZONA_OUT6R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
494 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
495
496ARIZONA_MIXER_WIDGETS(EQ1, "EQ1"),
497ARIZONA_MIXER_WIDGETS(EQ2, "EQ2"),
498ARIZONA_MIXER_WIDGETS(EQ3, "EQ3"),
499ARIZONA_MIXER_WIDGETS(EQ4, "EQ4"),
500
501ARIZONA_MIXER_WIDGETS(DRC1L, "DRC1L"),
502ARIZONA_MIXER_WIDGETS(DRC1R, "DRC1R"),
503ARIZONA_MIXER_WIDGETS(DRC2L, "DRC2L"),
504ARIZONA_MIXER_WIDGETS(DRC2R, "DRC2R"),
505
506ARIZONA_MIXER_WIDGETS(LHPF1, "LHPF1"),
507ARIZONA_MIXER_WIDGETS(LHPF2, "LHPF2"),
508ARIZONA_MIXER_WIDGETS(LHPF3, "LHPF3"),
509ARIZONA_MIXER_WIDGETS(LHPF4, "LHPF4"),
510
511ARIZONA_MIXER_WIDGETS(Mic, "Mic"),
512ARIZONA_MIXER_WIDGETS(Noise, "Noise"),
513
514ARIZONA_MIXER_WIDGETS(PWM1, "PWM1"),
515ARIZONA_MIXER_WIDGETS(PWM2, "PWM2"),
516
517ARIZONA_MIXER_WIDGETS(OUT1L, "HPOUT1L"),
518ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUT1R"),
519ARIZONA_MIXER_WIDGETS(OUT2L, "HPOUT2L"),
520ARIZONA_MIXER_WIDGETS(OUT2R, "HPOUT2R"),
521ARIZONA_MIXER_WIDGETS(OUT3, "EPOUT"),
522ARIZONA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"),
523ARIZONA_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"),
524ARIZONA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"),
525ARIZONA_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"),
526ARIZONA_MIXER_WIDGETS(SPKDAT2L, "SPKDAT2L"),
527ARIZONA_MIXER_WIDGETS(SPKDAT2R, "SPKDAT2R"),
528
529ARIZONA_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
530ARIZONA_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
531ARIZONA_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
532ARIZONA_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
533ARIZONA_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
534ARIZONA_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
535ARIZONA_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"),
536ARIZONA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"),
537
538ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"),
539ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
540
541ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
542ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
543
544ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"),
545ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"),
546ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"),
547ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"),
548
549SND_SOC_DAPM_OUTPUT("HPOUT1L"),
550SND_SOC_DAPM_OUTPUT("HPOUT1R"),
551SND_SOC_DAPM_OUTPUT("HPOUT2L"),
552SND_SOC_DAPM_OUTPUT("HPOUT2R"),
553SND_SOC_DAPM_OUTPUT("EPOUTN"),
554SND_SOC_DAPM_OUTPUT("EPOUTP"),
555SND_SOC_DAPM_OUTPUT("SPKOUTLN"),
556SND_SOC_DAPM_OUTPUT("SPKOUTLP"),
557SND_SOC_DAPM_OUTPUT("SPKOUTRN"),
558SND_SOC_DAPM_OUTPUT("SPKOUTRP"),
559SND_SOC_DAPM_OUTPUT("SPKDAT1L"),
560SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
561SND_SOC_DAPM_OUTPUT("SPKDAT2L"),
562SND_SOC_DAPM_OUTPUT("SPKDAT2R"),
563};
564
565#define ARIZONA_MIXER_INPUT_ROUTES(name) \
566 { name, "Noise Generator", "Noise Generator" }, \
567 { name, "Tone Generator 1", "Tone Generator 1" }, \
568 { name, "Tone Generator 2", "Tone Generator 2" }, \
569 { name, "IN1L", "IN1L PGA" }, \
570 { name, "IN1R", "IN1R PGA" }, \
571 { name, "IN2L", "IN2L PGA" }, \
572 { name, "IN2R", "IN2R PGA" }, \
573 { name, "IN3L", "IN3L PGA" }, \
574 { name, "IN3R", "IN3R PGA" }, \
575 { name, "IN4L", "IN4L PGA" }, \
576 { name, "IN4R", "IN4R PGA" }, \
577 { name, "Mic Mute Mixer", "Mic Mute Mixer" }, \
578 { name, "AIF1RX1", "AIF1RX1" }, \
579 { name, "AIF1RX2", "AIF1RX2" }, \
580 { name, "AIF1RX3", "AIF1RX3" }, \
581 { name, "AIF1RX4", "AIF1RX4" }, \
582 { name, "AIF1RX5", "AIF1RX5" }, \
583 { name, "AIF1RX6", "AIF1RX6" }, \
584 { name, "AIF1RX7", "AIF1RX7" }, \
585 { name, "AIF1RX8", "AIF1RX8" }, \
586 { name, "AIF2RX1", "AIF2RX1" }, \
587 { name, "AIF2RX2", "AIF2RX2" }, \
588 { name, "AIF3RX1", "AIF3RX1" }, \
589 { name, "AIF3RX2", "AIF3RX2" }, \
590 { name, "EQ1", "EQ1" }, \
591 { name, "EQ2", "EQ2" }, \
592 { name, "EQ3", "EQ3" }, \
593 { name, "EQ4", "EQ4" }, \
594 { name, "DRC1L", "DRC1L" }, \
595 { name, "DRC1R", "DRC1R" }, \
596 { name, "DRC2L", "DRC2L" }, \
597 { name, "DRC2R", "DRC2R" }, \
598 { name, "LHPF1", "LHPF1" }, \
599 { name, "LHPF2", "LHPF2" }, \
600 { name, "LHPF3", "LHPF3" }, \
601 { name, "LHPF4", "LHPF4" }, \
602 { name, "ASRC1L", "ASRC1L" }, \
603 { name, "ASRC1R", "ASRC1R" }, \
604 { name, "ASRC2L", "ASRC2L" }, \
605 { name, "ASRC2R", "ASRC2R" }
606
607static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
608 { "AIF2 Capture", NULL, "DBVDD2" },
609 { "AIF2 Playback", NULL, "DBVDD2" },
610
611 { "AIF3 Capture", NULL, "DBVDD3" },
612 { "AIF3 Playback", NULL, "DBVDD3" },
613
614 { "OUT1L", NULL, "CPVDD" },
615 { "OUT1R", NULL, "CPVDD" },
616 { "OUT2L", NULL, "CPVDD" },
617 { "OUT2R", NULL, "CPVDD" },
618 { "OUT3L", NULL, "CPVDD" },
619
620 { "OUT4L", NULL, "SPKVDDL" },
621 { "OUT4R", NULL, "SPKVDDR" },
622
623 { "OUT1L", NULL, "SYSCLK" },
624 { "OUT1R", NULL, "SYSCLK" },
625 { "OUT2L", NULL, "SYSCLK" },
626 { "OUT2R", NULL, "SYSCLK" },
627 { "OUT3L", NULL, "SYSCLK" },
628 { "OUT4L", NULL, "SYSCLK" },
629 { "OUT4R", NULL, "SYSCLK" },
630 { "OUT5L", NULL, "SYSCLK" },
631 { "OUT5R", NULL, "SYSCLK" },
632 { "OUT6L", NULL, "SYSCLK" },
633 { "OUT6R", NULL, "SYSCLK" },
634
635 { "MICBIAS1", NULL, "MICVDD" },
636 { "MICBIAS2", NULL, "MICVDD" },
637 { "MICBIAS3", NULL, "MICVDD" },
638
639 { "Noise Generator", NULL, "NOISE" },
640 { "Tone Generator 1", NULL, "TONE" },
641 { "Tone Generator 2", NULL, "TONE" },
642
643 { "Mic Mute Mixer", NULL, "Noise Mixer" },
644 { "Mic Mute Mixer", NULL, "Mic Mixer" },
645
646 { "AIF1 Capture", NULL, "AIF1TX1" },
647 { "AIF1 Capture", NULL, "AIF1TX2" },
648 { "AIF1 Capture", NULL, "AIF1TX3" },
649 { "AIF1 Capture", NULL, "AIF1TX4" },
650 { "AIF1 Capture", NULL, "AIF1TX5" },
651 { "AIF1 Capture", NULL, "AIF1TX6" },
652 { "AIF1 Capture", NULL, "AIF1TX7" },
653 { "AIF1 Capture", NULL, "AIF1TX8" },
654
655 { "AIF1RX1", NULL, "AIF1 Playback" },
656 { "AIF1RX2", NULL, "AIF1 Playback" },
657 { "AIF1RX3", NULL, "AIF1 Playback" },
658 { "AIF1RX4", NULL, "AIF1 Playback" },
659 { "AIF1RX5", NULL, "AIF1 Playback" },
660 { "AIF1RX6", NULL, "AIF1 Playback" },
661 { "AIF1RX7", NULL, "AIF1 Playback" },
662 { "AIF1RX8", NULL, "AIF1 Playback" },
663
664 { "AIF2 Capture", NULL, "AIF2TX1" },
665 { "AIF2 Capture", NULL, "AIF2TX2" },
666
667 { "AIF2RX1", NULL, "AIF2 Playback" },
668 { "AIF2RX2", NULL, "AIF2 Playback" },
669
670 { "AIF3 Capture", NULL, "AIF3TX1" },
671 { "AIF3 Capture", NULL, "AIF3TX2" },
672
673 { "AIF3RX1", NULL, "AIF3 Playback" },
674 { "AIF3RX2", NULL, "AIF3 Playback" },
675
676 { "AIF1 Playback", NULL, "SYSCLK" },
677 { "AIF2 Playback", NULL, "SYSCLK" },
678 { "AIF3 Playback", NULL, "SYSCLK" },
679
680 { "AIF1 Capture", NULL, "SYSCLK" },
681 { "AIF2 Capture", NULL, "SYSCLK" },
682 { "AIF3 Capture", NULL, "SYSCLK" },
683
684 ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
685 ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),
686 ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"),
687 ARIZONA_MIXER_ROUTES("OUT2R", "HPOUT2R"),
688 ARIZONA_MIXER_ROUTES("OUT3L", "EPOUT"),
689
690 ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUTL"),
691 ARIZONA_MIXER_ROUTES("OUT4R", "SPKOUTR"),
692 ARIZONA_MIXER_ROUTES("OUT5L", "SPKDAT1L"),
693 ARIZONA_MIXER_ROUTES("OUT5R", "SPKDAT1R"),
694 ARIZONA_MIXER_ROUTES("OUT6L", "SPKDAT2L"),
695 ARIZONA_MIXER_ROUTES("OUT6R", "SPKDAT2R"),
696
697 ARIZONA_MIXER_ROUTES("PWM1 Driver", "PWM1"),
698 ARIZONA_MIXER_ROUTES("PWM2 Driver", "PWM2"),
699
700 ARIZONA_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
701 ARIZONA_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
702 ARIZONA_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
703 ARIZONA_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
704 ARIZONA_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
705 ARIZONA_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
706 ARIZONA_MIXER_ROUTES("AIF1TX7", "AIF1TX7"),
707 ARIZONA_MIXER_ROUTES("AIF1TX8", "AIF1TX8"),
708
709 ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"),
710 ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"),
711
712 ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"),
713 ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"),
714
715 ARIZONA_MIXER_ROUTES("EQ1", "EQ1"),
716 ARIZONA_MIXER_ROUTES("EQ2", "EQ2"),
717 ARIZONA_MIXER_ROUTES("EQ3", "EQ3"),
718 ARIZONA_MIXER_ROUTES("EQ4", "EQ4"),
719
720 ARIZONA_MIXER_ROUTES("DRC1L", "DRC1L"),
721 ARIZONA_MIXER_ROUTES("DRC1R", "DRC1R"),
722 ARIZONA_MIXER_ROUTES("DRC2L", "DRC2L"),
723 ARIZONA_MIXER_ROUTES("DRC2R", "DRC2R"),
724
725 ARIZONA_MIXER_ROUTES("LHPF1", "LHPF1"),
726 ARIZONA_MIXER_ROUTES("LHPF2", "LHPF2"),
727 ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"),
728 ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"),
729
730 ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"),
731 ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"),
732 ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"),
733 ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"),
734
735 { "HPOUT1L", NULL, "OUT1L" },
736 { "HPOUT1R", NULL, "OUT1R" },
737
738 { "HPOUT2L", NULL, "OUT2L" },
739 { "HPOUT2R", NULL, "OUT2R" },
740
741 { "EPOUTN", NULL, "OUT3L" },
742 { "EPOUTP", NULL, "OUT3L" },
743
744 { "SPKOUTLN", NULL, "OUT4L" },
745 { "SPKOUTLP", NULL, "OUT4L" },
746
747 { "SPKOUTRN", NULL, "OUT4R" },
748 { "SPKOUTRP", NULL, "OUT4R" },
749
750 { "SPKDAT1L", NULL, "OUT5L" },
751 { "SPKDAT1R", NULL, "OUT5R" },
752
753 { "SPKDAT2L", NULL, "OUT6L" },
754 { "SPKDAT2R", NULL, "OUT6R" },
755};
756
757static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
758 unsigned int Fref, unsigned int Fout)
759{
760 struct wm5110_priv *wm5110 = snd_soc_codec_get_drvdata(codec);
761
762 switch (fll_id) {
763 case WM5110_FLL1:
764 return arizona_set_fll(&wm5110->fll[0], source, Fref, Fout);
765 case WM5110_FLL2:
766 return arizona_set_fll(&wm5110->fll[1], source, Fref, Fout);
767 default:
768 return -EINVAL;
769 }
770}
771
772#define WM5110_RATES SNDRV_PCM_RATE_8000_192000
773
774#define WM5110_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
775 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
776
777static struct snd_soc_dai_driver wm5110_dai[] = {
778 {
779 .name = "wm5110-aif1",
780 .id = 1,
781 .base = ARIZONA_AIF1_BCLK_CTRL,
782 .playback = {
783 .stream_name = "AIF1 Playback",
784 .channels_min = 1,
785 .channels_max = 8,
786 .rates = WM5110_RATES,
787 .formats = WM5110_FORMATS,
788 },
789 .capture = {
790 .stream_name = "AIF1 Capture",
791 .channels_min = 1,
792 .channels_max = 8,
793 .rates = WM5110_RATES,
794 .formats = WM5110_FORMATS,
795 },
796 .ops = &arizona_dai_ops,
797 .symmetric_rates = 1,
798 },
799 {
800 .name = "wm5110-aif2",
801 .id = 2,
802 .base = ARIZONA_AIF2_BCLK_CTRL,
803 .playback = {
804 .stream_name = "AIF2 Playback",
805 .channels_min = 1,
806 .channels_max = 2,
807 .rates = WM5110_RATES,
808 .formats = WM5110_FORMATS,
809 },
810 .capture = {
811 .stream_name = "AIF2 Capture",
812 .channels_min = 1,
813 .channels_max = 2,
814 .rates = WM5110_RATES,
815 .formats = WM5110_FORMATS,
816 },
817 .ops = &arizona_dai_ops,
818 .symmetric_rates = 1,
819 },
820 {
821 .name = "wm5110-aif3",
822 .id = 3,
823 .base = ARIZONA_AIF3_BCLK_CTRL,
824 .playback = {
825 .stream_name = "AIF3 Playback",
826 .channels_min = 1,
827 .channels_max = 2,
828 .rates = WM5110_RATES,
829 .formats = WM5110_FORMATS,
830 },
831 .capture = {
832 .stream_name = "AIF3 Capture",
833 .channels_min = 1,
834 .channels_max = 2,
835 .rates = WM5110_RATES,
836 .formats = WM5110_FORMATS,
837 },
838 .ops = &arizona_dai_ops,
839 .symmetric_rates = 1,
840 },
841};
842
843static int wm5110_codec_probe(struct snd_soc_codec *codec)
844{
845 struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec);
846
847 codec->control_data = priv->core.arizona->regmap;
848 return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP);
849}
850
851#define WM5110_DIG_VU 0x0200
852
853static unsigned int wm5110_digital_vu[] = {
854 ARIZONA_ADC_DIGITAL_VOLUME_1L,
855 ARIZONA_ADC_DIGITAL_VOLUME_1R,
856 ARIZONA_ADC_DIGITAL_VOLUME_2L,
857 ARIZONA_ADC_DIGITAL_VOLUME_2R,
858 ARIZONA_ADC_DIGITAL_VOLUME_3L,
859 ARIZONA_ADC_DIGITAL_VOLUME_3R,
860
861 ARIZONA_DAC_DIGITAL_VOLUME_1L,
862 ARIZONA_DAC_DIGITAL_VOLUME_1R,
863 ARIZONA_DAC_DIGITAL_VOLUME_2L,
864 ARIZONA_DAC_DIGITAL_VOLUME_2R,
865 ARIZONA_DAC_DIGITAL_VOLUME_3L,
866 ARIZONA_DAC_DIGITAL_VOLUME_3R,
867 ARIZONA_DAC_DIGITAL_VOLUME_4L,
868 ARIZONA_DAC_DIGITAL_VOLUME_4R,
869 ARIZONA_DAC_DIGITAL_VOLUME_5L,
870 ARIZONA_DAC_DIGITAL_VOLUME_5R,
871};
872
873static struct snd_soc_codec_driver soc_codec_dev_wm5110 = {
874 .probe = wm5110_codec_probe,
875
876 .idle_bias_off = true,
877
878 .set_sysclk = arizona_set_sysclk,
879 .set_pll = wm5110_set_fll,
880
881 .controls = wm5110_snd_controls,
882 .num_controls = ARRAY_SIZE(wm5110_snd_controls),
883 .dapm_widgets = wm5110_dapm_widgets,
884 .num_dapm_widgets = ARRAY_SIZE(wm5110_dapm_widgets),
885 .dapm_routes = wm5110_dapm_routes,
886 .num_dapm_routes = ARRAY_SIZE(wm5110_dapm_routes),
887};
888
889static int __devinit wm5110_probe(struct platform_device *pdev)
890{
891 struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
892 struct wm5110_priv *wm5110;
893 int i;
894
895 wm5110 = devm_kzalloc(&pdev->dev, sizeof(struct wm5110_priv),
896 GFP_KERNEL);
897 if (wm5110 == NULL)
898 return -ENOMEM;
899 platform_set_drvdata(pdev, wm5110);
900
901 wm5110->core.arizona = arizona;
902
903 for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++)
904 wm5110->fll[i].vco_mult = 3;
905
906 arizona_init_fll(arizona, 1, ARIZONA_FLL1_CONTROL_1 - 1,
907 ARIZONA_IRQ_FLL1_LOCK, ARIZONA_IRQ_FLL1_CLOCK_OK,
908 &wm5110->fll[0]);
909 arizona_init_fll(arizona, 2, ARIZONA_FLL2_CONTROL_1 - 1,
910 ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK,
911 &wm5110->fll[1]);
912
913 for (i = 0; i < ARRAY_SIZE(wm5110_dai); i++)
914 arizona_init_dai(&wm5110->core, i);
915
916 /* Latch volume update bits */
917 for (i = 0; i < ARRAY_SIZE(wm5110_digital_vu); i++)
918 regmap_update_bits(arizona->regmap, wm5110_digital_vu[i],
919 WM5110_DIG_VU, WM5110_DIG_VU);
920
921 pm_runtime_enable(&pdev->dev);
922 pm_runtime_idle(&pdev->dev);
923
924 return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5110,
925 wm5110_dai, ARRAY_SIZE(wm5110_dai));
926}
927
928static int __devexit wm5110_remove(struct platform_device *pdev)
929{
930 snd_soc_unregister_codec(&pdev->dev);
931 pm_runtime_disable(&pdev->dev);
932
933 return 0;
934}
935
936static struct platform_driver wm5110_codec_driver = {
937 .driver = {
938 .name = "wm5110-codec",
939 .owner = THIS_MODULE,
940 },
941 .probe = wm5110_probe,
942 .remove = __devexit_p(wm5110_remove),
943};
944
945module_platform_driver(wm5110_codec_driver);
946
947MODULE_DESCRIPTION("ASoC WM5110 driver");
948MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
949MODULE_LICENSE("GPL");
950MODULE_ALIAS("platform:wm5110-codec");
diff --git a/sound/soc/codecs/wm5110.h b/sound/soc/codecs/wm5110.h
new file mode 100644
index 00000000000..75e9351ccab
--- /dev/null
+++ b/sound/soc/codecs/wm5110.h
@@ -0,0 +1,21 @@
1/*
2 * wm5110.h -- WM5110 ALSA SoC Audio driver
3 *
4 * Copyright 2012 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef _WM5110_H
14#define _WM5110_H
15
16#include "arizona.h"
17
18#define WM5110_FLL1 1
19#define WM5110_FLL2 2
20
21#endif
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 555ee146ae0..d26c8ae4e6d 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * wm8350.c -- WM8350 ALSA SoC audio driver 2 * wm8350.c -- WM8350 ALSA SoC audio driver
3 * 3 *
4 * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC. 4 * Copyright (C) 2007-12 Wolfson Microelectronics PLC.
5 * 5 *
6 * Author: Liam Girdwood <lrg@slimlogic.co.uk> 6 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
7 * 7 *
@@ -71,20 +71,6 @@ struct wm8350_data {
71 int fll_freq_in; 71 int fll_freq_in;
72}; 72};
73 73
74static unsigned int wm8350_codec_read(struct snd_soc_codec *codec,
75 unsigned int reg)
76{
77 struct wm8350 *wm8350 = codec->control_data;
78 return wm8350_reg_read(wm8350, reg);
79}
80
81static int wm8350_codec_write(struct snd_soc_codec *codec, unsigned int reg,
82 unsigned int value)
83{
84 struct wm8350 *wm8350 = codec->control_data;
85 return wm8350_reg_write(wm8350, reg, value);
86}
87
88/* 74/*
89 * Ramp OUT1 PGA volume to minimise pops at stream startup and shutdown. 75 * Ramp OUT1 PGA volume to minimise pops at stream startup and shutdown.
90 */ 76 */
@@ -1519,7 +1505,9 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec)
1519 if (ret != 0) 1505 if (ret != 0)
1520 return ret; 1506 return ret;
1521 1507
1522 codec->control_data = wm8350; 1508 codec->control_data = wm8350->regmap;
1509
1510 snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
1523 1511
1524 /* Put the codec into reset if it wasn't already */ 1512 /* Put the codec into reset if it wasn't already */
1525 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); 1513 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
@@ -1629,8 +1617,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8350 = {
1629 .remove = wm8350_codec_remove, 1617 .remove = wm8350_codec_remove,
1630 .suspend = wm8350_suspend, 1618 .suspend = wm8350_suspend,
1631 .resume = wm8350_resume, 1619 .resume = wm8350_resume,
1632 .read = wm8350_codec_read,
1633 .write = wm8350_codec_write,
1634 .set_bias_level = wm8350_set_bias_level, 1620 .set_bias_level = wm8350_set_bias_level,
1635 1621
1636 .controls = wm8350_snd_controls, 1622 .controls = wm8350_snd_controls,
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index 5dc31ebcd0e..5d277a915f8 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * wm8400.c -- WM8400 ALSA Soc Audio driver 2 * wm8400.c -- WM8400 ALSA Soc Audio driver
3 * 3 *
4 * Copyright 2008, 2009 Wolfson Microelectronics PLC. 4 * Copyright 2008-11 Wolfson Microelectronics PLC.
5 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 5 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 211285164d7..7c68226376e 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * wm8580.c -- WM8580 ALSA Soc Audio driver 2 * wm8580.c -- WM8580 ALSA Soc Audio driver
3 * 3 *
4 * Copyright 2008, 2009 Wolfson Microelectronics PLC. 4 * Copyright 2008-11 Wolfson Microelectronics PLC.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the 7 * under the terms of the GNU General Public License as published by the
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 9d1b9b0271f..bb1d26919b1 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -2,6 +2,7 @@
2 * wm8731.c -- WM8731 ALSA SoC Audio driver 2 * wm8731.c -- WM8731 ALSA SoC Audio driver
3 * 3 *
4 * Copyright 2005 Openedhand Ltd. 4 * Copyright 2005 Openedhand Ltd.
5 * Copyright 2006-12 Wolfson Microelectronics, plc
5 * 6 *
6 * Author: Richard Purdie <richard@openedhand.com> 7 * Author: Richard Purdie <richard@openedhand.com>
7 * 8 *
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index 6e849cb0424..35f3d23200e 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * wm8741.c -- WM8741 ALSA SoC Audio driver 2 * wm8741.c -- WM8741 ALSA SoC Audio driver
3 * 3 *
4 * Copyright 2010 Wolfson Microelectronics plc 4 * Copyright 2010-1 Wolfson Microelectronics plc
5 * 5 *
6 * Author: Ian Lartey <ian@opensource.wolfsonmicro.com> 6 * Author: Ian Lartey <ian@opensource.wolfsonmicro.com>
7 * 7 *
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index a26482cd765..13bff87ddcf 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * wm8753.c -- WM8753 ALSA Soc Audio driver 2 * wm8753.c -- WM8753 ALSA Soc Audio driver
3 * 3 *
4 * Copyright 2003 Wolfson Microelectronics PLC. 4 * Copyright 2003-11 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood <lrg@slimlogic.co.uk> 5 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index a19db5a0a17..879c356a904 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * wm8776.c -- WM8776 ALSA SoC Audio driver 2 * wm8776.c -- WM8776 ALSA SoC Audio driver
3 * 3 *
4 * Copyright 2009 Wolfson Microelectronics plc 4 * Copyright 2009-12 Wolfson Microelectronics plc
5 * 5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 * 7 *
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index 6bd1b767b13..c088020172a 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * wm8804.c -- WM8804 S/PDIF transceiver driver 2 * wm8804.c -- WM8804 S/PDIF transceiver driver
3 * 3 *
4 * Copyright 2010 Wolfson Microelectronics plc 4 * Copyright 2010-11 Wolfson Microelectronics plc
5 * 5 *
6 * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> 6 * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
7 * 7 *
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 86b8a292659..73f1c8d7baf 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -1,8 +1,8 @@
1/* 1/*
2 * wm8903.c -- WM8903 ALSA SoC Audio driver 2 * wm8903.c -- WM8903 ALSA SoC Audio driver
3 * 3 *
4 * Copyright 2008 Wolfson Microelectronics 4 * Copyright 2008-12 Wolfson Microelectronics
5 * Copyright 2011 NVIDIA, Inc. 5 * Copyright 2011-2012 NVIDIA, Inc.
6 * 6 *
7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
8 * 8 *
@@ -116,6 +116,7 @@ static const struct reg_default wm8903_reg_defaults[] = {
116 116
117struct wm8903_priv { 117struct wm8903_priv {
118 struct wm8903_platform_data *pdata; 118 struct wm8903_platform_data *pdata;
119 struct device *dev;
119 struct snd_soc_codec *codec; 120 struct snd_soc_codec *codec;
120 struct regmap *regmap; 121 struct regmap *regmap;
121 122
@@ -1635,17 +1636,27 @@ EXPORT_SYMBOL_GPL(wm8903_mic_detect);
1635 1636
1636static irqreturn_t wm8903_irq(int irq, void *data) 1637static irqreturn_t wm8903_irq(int irq, void *data)
1637{ 1638{
1638 struct snd_soc_codec *codec = data; 1639 struct wm8903_priv *wm8903 = data;
1639 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); 1640 int mic_report, ret;
1640 int mic_report; 1641 unsigned int int_val, mask, int_pol;
1641 int int_pol;
1642 int int_val = 0;
1643 int mask = ~snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1_MASK);
1644 1642
1645 int_val = snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1) & mask; 1643 ret = regmap_read(wm8903->regmap, WM8903_INTERRUPT_STATUS_1_MASK,
1644 &mask);
1645 if (ret != 0) {
1646 dev_err(wm8903->dev, "Failed to read IRQ mask: %d\n", ret);
1647 return IRQ_NONE;
1648 }
1649
1650 ret = regmap_read(wm8903->regmap, WM8903_INTERRUPT_STATUS_1, &int_val);
1651 if (ret != 0) {
1652 dev_err(wm8903->dev, "Failed to read IRQ status: %d\n", ret);
1653 return IRQ_NONE;
1654 }
1655
1656 int_val &= ~mask;
1646 1657
1647 if (int_val & WM8903_WSEQ_BUSY_EINT) { 1658 if (int_val & WM8903_WSEQ_BUSY_EINT) {
1648 dev_warn(codec->dev, "Write sequencer done\n"); 1659 dev_warn(wm8903->dev, "Write sequencer done\n");
1649 } 1660 }
1650 1661
1651 /* 1662 /*
@@ -1656,22 +1667,28 @@ static irqreturn_t wm8903_irq(int irq, void *data)
1656 * the polarity register. 1667 * the polarity register.
1657 */ 1668 */
1658 mic_report = wm8903->mic_last_report; 1669 mic_report = wm8903->mic_last_report;
1659 int_pol = snd_soc_read(codec, WM8903_INTERRUPT_POLARITY_1); 1670 ret = regmap_read(wm8903->regmap, WM8903_INTERRUPT_POLARITY_1,
1671 &int_pol);
1672 if (ret != 0) {
1673 dev_err(wm8903->dev, "Failed to read interrupt polarity: %d\n",
1674 ret);
1675 return IRQ_HANDLED;
1676 }
1660 1677
1661#ifndef CONFIG_SND_SOC_WM8903_MODULE 1678#ifndef CONFIG_SND_SOC_WM8903_MODULE
1662 if (int_val & (WM8903_MICSHRT_EINT | WM8903_MICDET_EINT)) 1679 if (int_val & (WM8903_MICSHRT_EINT | WM8903_MICDET_EINT))
1663 trace_snd_soc_jack_irq(dev_name(codec->dev)); 1680 trace_snd_soc_jack_irq(dev_name(wm8903->dev));
1664#endif 1681#endif
1665 1682
1666 if (int_val & WM8903_MICSHRT_EINT) { 1683 if (int_val & WM8903_MICSHRT_EINT) {
1667 dev_dbg(codec->dev, "Microphone short (pol=%x)\n", int_pol); 1684 dev_dbg(wm8903->dev, "Microphone short (pol=%x)\n", int_pol);
1668 1685
1669 mic_report ^= wm8903->mic_short; 1686 mic_report ^= wm8903->mic_short;
1670 int_pol ^= WM8903_MICSHRT_INV; 1687 int_pol ^= WM8903_MICSHRT_INV;
1671 } 1688 }
1672 1689
1673 if (int_val & WM8903_MICDET_EINT) { 1690 if (int_val & WM8903_MICDET_EINT) {
1674 dev_dbg(codec->dev, "Microphone detect (pol=%x)\n", int_pol); 1691 dev_dbg(wm8903->dev, "Microphone detect (pol=%x)\n", int_pol);
1675 1692
1676 mic_report ^= wm8903->mic_det; 1693 mic_report ^= wm8903->mic_det;
1677 int_pol ^= WM8903_MICDET_INV; 1694 int_pol ^= WM8903_MICDET_INV;
@@ -1679,8 +1696,8 @@ static irqreturn_t wm8903_irq(int irq, void *data)
1679 msleep(wm8903->mic_delay); 1696 msleep(wm8903->mic_delay);
1680 } 1697 }
1681 1698
1682 snd_soc_update_bits(codec, WM8903_INTERRUPT_POLARITY_1, 1699 regmap_update_bits(wm8903->regmap, WM8903_INTERRUPT_POLARITY_1,
1683 WM8903_MICSHRT_INV | WM8903_MICDET_INV, int_pol); 1700 WM8903_MICSHRT_INV | WM8903_MICDET_INV, int_pol);
1684 1701
1685 snd_soc_jack_report(wm8903->mic_jack, mic_report, 1702 snd_soc_jack_report(wm8903->mic_jack, mic_report,
1686 wm8903->mic_short | wm8903->mic_det); 1703 wm8903->mic_short | wm8903->mic_det);
@@ -1774,7 +1791,6 @@ static int wm8903_gpio_request(struct gpio_chip *chip, unsigned offset)
1774static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) 1791static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
1775{ 1792{
1776 struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); 1793 struct wm8903_priv *wm8903 = gpio_to_wm8903(chip);
1777 struct snd_soc_codec *codec = wm8903->codec;
1778 unsigned int mask, val; 1794 unsigned int mask, val;
1779 int ret; 1795 int ret;
1780 1796
@@ -1782,8 +1798,8 @@ static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
1782 val = (WM8903_GPn_FN_GPIO_INPUT << WM8903_GP1_FN_SHIFT) | 1798 val = (WM8903_GPn_FN_GPIO_INPUT << WM8903_GP1_FN_SHIFT) |
1783 WM8903_GP1_DIR; 1799 WM8903_GP1_DIR;
1784 1800
1785 ret = snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, 1801 ret = regmap_update_bits(wm8903->regmap,
1786 mask, val); 1802 WM8903_GPIO_CONTROL_1 + offset, mask, val);
1787 if (ret < 0) 1803 if (ret < 0)
1788 return ret; 1804 return ret;
1789 1805
@@ -1793,10 +1809,9 @@ static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
1793static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset) 1809static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset)
1794{ 1810{
1795 struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); 1811 struct wm8903_priv *wm8903 = gpio_to_wm8903(chip);
1796 struct snd_soc_codec *codec = wm8903->codec; 1812 unsigned int reg;
1797 int reg;
1798 1813
1799 reg = snd_soc_read(codec, WM8903_GPIO_CONTROL_1 + offset); 1814 regmap_read(wm8903->regmap, WM8903_GPIO_CONTROL_1 + offset, &reg);
1800 1815
1801 return (reg & WM8903_GP1_LVL_MASK) >> WM8903_GP1_LVL_SHIFT; 1816 return (reg & WM8903_GP1_LVL_MASK) >> WM8903_GP1_LVL_SHIFT;
1802} 1817}
@@ -1805,7 +1820,6 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip,
1805 unsigned offset, int value) 1820 unsigned offset, int value)
1806{ 1821{
1807 struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); 1822 struct wm8903_priv *wm8903 = gpio_to_wm8903(chip);
1808 struct snd_soc_codec *codec = wm8903->codec;
1809 unsigned int mask, val; 1823 unsigned int mask, val;
1810 int ret; 1824 int ret;
1811 1825
@@ -1813,8 +1827,8 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip,
1813 val = (WM8903_GPn_FN_GPIO_OUTPUT << WM8903_GP1_FN_SHIFT) | 1827 val = (WM8903_GPn_FN_GPIO_OUTPUT << WM8903_GP1_FN_SHIFT) |
1814 (value << WM8903_GP2_LVL_SHIFT); 1828 (value << WM8903_GP2_LVL_SHIFT);
1815 1829
1816 ret = snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, 1830 ret = regmap_update_bits(wm8903->regmap,
1817 mask, val); 1831 WM8903_GPIO_CONTROL_1 + offset, mask, val);
1818 if (ret < 0) 1832 if (ret < 0)
1819 return ret; 1833 return ret;
1820 1834
@@ -1824,11 +1838,10 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip,
1824static void wm8903_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 1838static void wm8903_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
1825{ 1839{
1826 struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); 1840 struct wm8903_priv *wm8903 = gpio_to_wm8903(chip);
1827 struct snd_soc_codec *codec = wm8903->codec;
1828 1841
1829 snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, 1842 regmap_update_bits(wm8903->regmap, WM8903_GPIO_CONTROL_1 + offset,
1830 WM8903_GP1_LVL_MASK, 1843 WM8903_GP1_LVL_MASK,
1831 !!value << WM8903_GP1_LVL_SHIFT); 1844 !!value << WM8903_GP1_LVL_SHIFT);
1832} 1845}
1833 1846
1834static struct gpio_chip wm8903_template_chip = { 1847static struct gpio_chip wm8903_template_chip = {
@@ -1842,15 +1855,14 @@ static struct gpio_chip wm8903_template_chip = {
1842 .can_sleep = 1, 1855 .can_sleep = 1,
1843}; 1856};
1844 1857
1845static void wm8903_init_gpio(struct snd_soc_codec *codec) 1858static void wm8903_init_gpio(struct wm8903_priv *wm8903)
1846{ 1859{
1847 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
1848 struct wm8903_platform_data *pdata = wm8903->pdata; 1860 struct wm8903_platform_data *pdata = wm8903->pdata;
1849 int ret; 1861 int ret;
1850 1862
1851 wm8903->gpio_chip = wm8903_template_chip; 1863 wm8903->gpio_chip = wm8903_template_chip;
1852 wm8903->gpio_chip.ngpio = WM8903_NUM_GPIO; 1864 wm8903->gpio_chip.ngpio = WM8903_NUM_GPIO;
1853 wm8903->gpio_chip.dev = codec->dev; 1865 wm8903->gpio_chip.dev = wm8903->dev;
1854 1866
1855 if (pdata->gpio_base) 1867 if (pdata->gpio_base)
1856 wm8903->gpio_chip.base = pdata->gpio_base; 1868 wm8903->gpio_chip.base = pdata->gpio_base;
@@ -1859,24 +1871,23 @@ static void wm8903_init_gpio(struct snd_soc_codec *codec)
1859 1871
1860 ret = gpiochip_add(&wm8903->gpio_chip); 1872 ret = gpiochip_add(&wm8903->gpio_chip);
1861 if (ret != 0) 1873 if (ret != 0)
1862 dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret); 1874 dev_err(wm8903->dev, "Failed to add GPIOs: %d\n", ret);
1863} 1875}
1864 1876
1865static void wm8903_free_gpio(struct snd_soc_codec *codec) 1877static void wm8903_free_gpio(struct wm8903_priv *wm8903)
1866{ 1878{
1867 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
1868 int ret; 1879 int ret;
1869 1880
1870 ret = gpiochip_remove(&wm8903->gpio_chip); 1881 ret = gpiochip_remove(&wm8903->gpio_chip);
1871 if (ret != 0) 1882 if (ret != 0)
1872 dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret); 1883 dev_err(wm8903->dev, "Failed to remove GPIOs: %d\n", ret);
1873} 1884}
1874#else 1885#else
1875static void wm8903_init_gpio(struct snd_soc_codec *codec) 1886static void wm8903_init_gpio(struct wm8903_priv *wm8903)
1876{ 1887{
1877} 1888}
1878 1889
1879static void wm8903_free_gpio(struct snd_soc_codec *codec) 1890static void wm8903_free_gpio(struct wm8903_priv *wm8903)
1880{ 1891{
1881} 1892}
1882#endif 1893#endif
@@ -1884,11 +1895,7 @@ static void wm8903_free_gpio(struct snd_soc_codec *codec)
1884static int wm8903_probe(struct snd_soc_codec *codec) 1895static int wm8903_probe(struct snd_soc_codec *codec)
1885{ 1896{
1886 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); 1897 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
1887 struct wm8903_platform_data *pdata = wm8903->pdata; 1898 int ret;
1888 int ret, i;
1889 int trigger, irq_pol;
1890 u16 val;
1891 bool mic_gpio = false;
1892 1899
1893 wm8903->codec = codec; 1900 wm8903->codec = codec;
1894 codec->control_data = wm8903->regmap; 1901 codec->control_data = wm8903->regmap;
@@ -1899,121 +1906,16 @@ static int wm8903_probe(struct snd_soc_codec *codec)
1899 return ret; 1906 return ret;
1900 } 1907 }
1901 1908
1902 /* Set up GPIOs, detect if any are MIC detect outputs */
1903 for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) {
1904 if ((!pdata->gpio_cfg[i]) ||
1905 (pdata->gpio_cfg[i] > WM8903_GPIO_CONFIG_ZERO))
1906 continue;
1907
1908 snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i,
1909 pdata->gpio_cfg[i] & 0x7fff);
1910
1911 val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK)
1912 >> WM8903_GP1_FN_SHIFT;
1913
1914 switch (val) {
1915 case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT:
1916 case WM8903_GPn_FN_MICBIAS_SHORT_DETECT:
1917 mic_gpio = true;
1918 break;
1919 default:
1920 break;
1921 }
1922 }
1923
1924 /* Set up microphone detection */
1925 snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0,
1926 pdata->micdet_cfg);
1927
1928 /* Microphone detection needs the WSEQ clock */
1929 if (pdata->micdet_cfg)
1930 snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0,
1931 WM8903_WSEQ_ENA, WM8903_WSEQ_ENA);
1932
1933 /* If microphone detection is enabled by pdata but
1934 * detected via IRQ then interrupts can be lost before
1935 * the machine driver has set up microphone detection
1936 * IRQs as the IRQs are clear on read. The detection
1937 * will be enabled when the machine driver configures.
1938 */
1939 WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA));
1940
1941 wm8903->mic_delay = pdata->micdet_delay;
1942
1943 if (wm8903->irq) {
1944 if (pdata->irq_active_low) {
1945 trigger = IRQF_TRIGGER_LOW;
1946 irq_pol = WM8903_IRQ_POL;
1947 } else {
1948 trigger = IRQF_TRIGGER_HIGH;
1949 irq_pol = 0;
1950 }
1951
1952 snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL,
1953 WM8903_IRQ_POL, irq_pol);
1954
1955 ret = request_threaded_irq(wm8903->irq, NULL, wm8903_irq,
1956 trigger | IRQF_ONESHOT,
1957 "wm8903", codec);
1958 if (ret != 0) {
1959 dev_err(codec->dev, "Failed to request IRQ: %d\n",
1960 ret);
1961 return ret;
1962 }
1963
1964 /* Enable write sequencer interrupts */
1965 snd_soc_update_bits(codec, WM8903_INTERRUPT_STATUS_1_MASK,
1966 WM8903_IM_WSEQ_BUSY_EINT, 0);
1967 }
1968
1969 /* power on device */ 1909 /* power on device */
1970 wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1910 wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1971 1911
1972 /* Latch volume update bits */
1973 val = snd_soc_read(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT);
1974 val |= WM8903_ADCVU;
1975 snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, val);
1976 snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, val);
1977
1978 val = snd_soc_read(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT);
1979 val |= WM8903_DACVU;
1980 snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT, val);
1981 snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_RIGHT, val);
1982
1983 val = snd_soc_read(codec, WM8903_ANALOGUE_OUT1_LEFT);
1984 val |= WM8903_HPOUTVU;
1985 snd_soc_write(codec, WM8903_ANALOGUE_OUT1_LEFT, val);
1986 snd_soc_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, val);
1987
1988 val = snd_soc_read(codec, WM8903_ANALOGUE_OUT2_LEFT);
1989 val |= WM8903_LINEOUTVU;
1990 snd_soc_write(codec, WM8903_ANALOGUE_OUT2_LEFT, val);
1991 snd_soc_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, val);
1992
1993 val = snd_soc_read(codec, WM8903_ANALOGUE_OUT3_LEFT);
1994 val |= WM8903_SPKVU;
1995 snd_soc_write(codec, WM8903_ANALOGUE_OUT3_LEFT, val);
1996 snd_soc_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val);
1997
1998 /* Enable DAC soft mute by default */
1999 snd_soc_update_bits(codec, WM8903_DAC_DIGITAL_1,
2000 WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE,
2001 WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE);
2002
2003 wm8903_init_gpio(codec);
2004
2005 return ret; 1912 return ret;
2006} 1913}
2007 1914
2008/* power down chip */ 1915/* power down chip */
2009static int wm8903_remove(struct snd_soc_codec *codec) 1916static int wm8903_remove(struct snd_soc_codec *codec)
2010{ 1917{
2011 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
2012
2013 wm8903_free_gpio(codec);
2014 wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); 1918 wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
2015 if (wm8903->irq)
2016 free_irq(wm8903->irq, codec);
2017 1919
2018 return 0; 1920 return 0;
2019} 1921}
@@ -2123,15 +2025,18 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
2123{ 2025{
2124 struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev); 2026 struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev);
2125 struct wm8903_priv *wm8903; 2027 struct wm8903_priv *wm8903;
2126 unsigned int val; 2028 int trigger;
2127 int ret; 2029 bool mic_gpio = false;
2030 unsigned int val, irq_pol;
2031 int ret, i;
2128 2032
2129 wm8903 = devm_kzalloc(&i2c->dev, sizeof(struct wm8903_priv), 2033 wm8903 = devm_kzalloc(&i2c->dev, sizeof(struct wm8903_priv),
2130 GFP_KERNEL); 2034 GFP_KERNEL);
2131 if (wm8903 == NULL) 2035 if (wm8903 == NULL)
2132 return -ENOMEM; 2036 return -ENOMEM;
2037 wm8903->dev = &i2c->dev;
2133 2038
2134 wm8903->regmap = regmap_init_i2c(i2c, &wm8903_regmap); 2039 wm8903->regmap = devm_regmap_init_i2c(i2c, &wm8903_regmap);
2135 if (IS_ERR(wm8903->regmap)) { 2040 if (IS_ERR(wm8903->regmap)) {
2136 ret = PTR_ERR(wm8903->regmap); 2041 ret = PTR_ERR(wm8903->regmap);
2137 dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 2042 dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
@@ -2140,7 +2045,6 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
2140 } 2045 }
2141 2046
2142 i2c_set_clientdata(i2c, wm8903); 2047 i2c_set_clientdata(i2c, wm8903);
2143 wm8903->irq = i2c->irq;
2144 2048
2145 /* If no platform data was supplied, create storage for defaults */ 2049 /* If no platform data was supplied, create storage for defaults */
2146 if (pdata) { 2050 if (pdata) {
@@ -2167,6 +2071,8 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
2167 } 2071 }
2168 } 2072 }
2169 2073
2074 pdata = wm8903->pdata;
2075
2170 ret = regmap_read(wm8903->regmap, WM8903_SW_RESET_AND_ID, &val); 2076 ret = regmap_read(wm8903->regmap, WM8903_SW_RESET_AND_ID, &val);
2171 if (ret != 0) { 2077 if (ret != 0) {
2172 dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret); 2078 dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
@@ -2189,6 +2095,107 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
2189 /* Reset the device */ 2095 /* Reset the device */
2190 regmap_write(wm8903->regmap, WM8903_SW_RESET_AND_ID, 0x8903); 2096 regmap_write(wm8903->regmap, WM8903_SW_RESET_AND_ID, 0x8903);
2191 2097
2098 wm8903_init_gpio(wm8903);
2099
2100 /* Set up GPIO pin state, detect if any are MIC detect outputs */
2101 for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) {
2102 if ((!pdata->gpio_cfg[i]) ||
2103 (pdata->gpio_cfg[i] > WM8903_GPIO_CONFIG_ZERO))
2104 continue;
2105
2106 regmap_write(wm8903->regmap, WM8903_GPIO_CONTROL_1 + i,
2107 pdata->gpio_cfg[i] & 0x7fff);
2108
2109 val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK)
2110 >> WM8903_GP1_FN_SHIFT;
2111
2112 switch (val) {
2113 case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT:
2114 case WM8903_GPn_FN_MICBIAS_SHORT_DETECT:
2115 mic_gpio = true;
2116 break;
2117 default:
2118 break;
2119 }
2120 }
2121
2122 /* Set up microphone detection */
2123 regmap_write(wm8903->regmap, WM8903_MIC_BIAS_CONTROL_0,
2124 pdata->micdet_cfg);
2125
2126 /* Microphone detection needs the WSEQ clock */
2127 if (pdata->micdet_cfg)
2128 regmap_update_bits(wm8903->regmap, WM8903_WRITE_SEQUENCER_0,
2129 WM8903_WSEQ_ENA, WM8903_WSEQ_ENA);
2130
2131 /* If microphone detection is enabled by pdata but
2132 * detected via IRQ then interrupts can be lost before
2133 * the machine driver has set up microphone detection
2134 * IRQs as the IRQs are clear on read. The detection
2135 * will be enabled when the machine driver configures.
2136 */
2137 WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA));
2138
2139 wm8903->mic_delay = pdata->micdet_delay;
2140
2141 if (i2c->irq) {
2142 if (pdata->irq_active_low) {
2143 trigger = IRQF_TRIGGER_LOW;
2144 irq_pol = WM8903_IRQ_POL;
2145 } else {
2146 trigger = IRQF_TRIGGER_HIGH;
2147 irq_pol = 0;
2148 }
2149
2150 regmap_update_bits(wm8903->regmap, WM8903_INTERRUPT_CONTROL,
2151 WM8903_IRQ_POL, irq_pol);
2152
2153 ret = request_threaded_irq(i2c->irq, NULL, wm8903_irq,
2154 trigger | IRQF_ONESHOT,
2155 "wm8903", wm8903);
2156 if (ret != 0) {
2157 dev_err(wm8903->dev, "Failed to request IRQ: %d\n",
2158 ret);
2159 return ret;
2160 }
2161
2162 /* Enable write sequencer interrupts */
2163 regmap_update_bits(wm8903->regmap,
2164 WM8903_INTERRUPT_STATUS_1_MASK,
2165 WM8903_IM_WSEQ_BUSY_EINT, 0);
2166 }
2167
2168 /* Latch volume update bits */
2169 regmap_update_bits(wm8903->regmap, WM8903_ADC_DIGITAL_VOLUME_LEFT,
2170 WM8903_ADCVU, WM8903_ADCVU);
2171 regmap_update_bits(wm8903->regmap, WM8903_ADC_DIGITAL_VOLUME_RIGHT,
2172 WM8903_ADCVU, WM8903_ADCVU);
2173
2174 regmap_update_bits(wm8903->regmap, WM8903_DAC_DIGITAL_VOLUME_LEFT,
2175 WM8903_DACVU, WM8903_DACVU);
2176 regmap_update_bits(wm8903->regmap, WM8903_DAC_DIGITAL_VOLUME_RIGHT,
2177 WM8903_DACVU, WM8903_DACVU);
2178
2179 regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT1_LEFT,
2180 WM8903_HPOUTVU, WM8903_HPOUTVU);
2181 regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT1_RIGHT,
2182 WM8903_HPOUTVU, WM8903_HPOUTVU);
2183
2184 regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT2_LEFT,
2185 WM8903_LINEOUTVU, WM8903_LINEOUTVU);
2186 regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT2_RIGHT,
2187 WM8903_LINEOUTVU, WM8903_LINEOUTVU);
2188
2189 regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT3_LEFT,
2190 WM8903_SPKVU, WM8903_SPKVU);
2191 regmap_update_bits(wm8903->regmap, WM8903_ANALOGUE_OUT3_RIGHT,
2192 WM8903_SPKVU, WM8903_SPKVU);
2193
2194 /* Enable DAC soft mute by default */
2195 regmap_update_bits(wm8903->regmap, WM8903_DAC_DIGITAL_1,
2196 WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE,
2197 WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE);
2198
2192 ret = snd_soc_register_codec(&i2c->dev, 2199 ret = snd_soc_register_codec(&i2c->dev,
2193 &soc_codec_dev_wm8903, &wm8903_dai, 1); 2200 &soc_codec_dev_wm8903, &wm8903_dai, 1);
2194 if (ret != 0) 2201 if (ret != 0)
@@ -2196,7 +2203,6 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
2196 2203
2197 return 0; 2204 return 0;
2198err: 2205err:
2199 regmap_exit(wm8903->regmap);
2200 return ret; 2206 return ret;
2201} 2207}
2202 2208
@@ -2204,7 +2210,9 @@ static __devexit int wm8903_i2c_remove(struct i2c_client *client)
2204{ 2210{
2205 struct wm8903_priv *wm8903 = i2c_get_clientdata(client); 2211 struct wm8903_priv *wm8903 = i2c_get_clientdata(client);
2206 2212
2207 regmap_exit(wm8903->regmap); 2213 if (client->irq)
2214 free_irq(client->irq, wm8903);
2215 wm8903_free_gpio(wm8903);
2208 snd_soc_unregister_codec(&client->dev); 2216 snd_soc_unregister_codec(&client->dev);
2209 2217
2210 return 0; 2218 return 0;
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 812acd83fb4..0013afe48e6 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * wm8904.c -- WM8904 ALSA SoC Audio driver 2 * wm8904.c -- WM8904 ALSA SoC Audio driver
3 * 3 *
4 * Copyright 2009 Wolfson Microelectronics plc 4 * Copyright 2009-12 Wolfson Microelectronics plc
5 * 5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 * 7 *
@@ -314,11 +314,6 @@ static bool wm8904_readable_register(struct device *dev, unsigned int reg)
314 } 314 }
315} 315}
316 316
317static int wm8904_reset(struct snd_soc_codec *codec)
318{
319 return snd_soc_write(codec, WM8904_SW_RESET_AND_ID, 0);
320}
321
322static int wm8904_configure_clocking(struct snd_soc_codec *codec) 317static int wm8904_configure_clocking(struct snd_soc_codec *codec)
323{ 318{
324 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); 319 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
@@ -1945,25 +1940,6 @@ static struct snd_soc_dai_driver wm8904_dai = {
1945 .symmetric_rates = 1, 1940 .symmetric_rates = 1,
1946}; 1941};
1947 1942
1948#ifdef CONFIG_PM
1949static int wm8904_suspend(struct snd_soc_codec *codec)
1950{
1951 wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF);
1952
1953 return 0;
1954}
1955
1956static int wm8904_resume(struct snd_soc_codec *codec)
1957{
1958 wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1959
1960 return 0;
1961}
1962#else
1963#define wm8904_suspend NULL
1964#define wm8904_resume NULL
1965#endif
1966
1967static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec) 1943static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec)
1968{ 1944{
1969 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); 1945 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
@@ -2078,8 +2054,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
2078static int wm8904_probe(struct snd_soc_codec *codec) 2054static int wm8904_probe(struct snd_soc_codec *codec)
2079{ 2055{
2080 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); 2056 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
2081 struct wm8904_pdata *pdata = wm8904->pdata; 2057 int ret;
2082 int ret, i;
2083 2058
2084 codec->control_data = wm8904->regmap; 2059 codec->control_data = wm8904->regmap;
2085 2060
@@ -2101,127 +2076,17 @@ static int wm8904_probe(struct snd_soc_codec *codec)
2101 return ret; 2076 return ret;
2102 } 2077 }
2103 2078
2104 for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++)
2105 wm8904->supplies[i].supply = wm8904_supply_names[i];
2106
2107 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8904->supplies),
2108 wm8904->supplies);
2109 if (ret != 0) {
2110 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
2111 return ret;
2112 }
2113
2114 ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies),
2115 wm8904->supplies);
2116 if (ret != 0) {
2117 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
2118 goto err_get;
2119 }
2120
2121 ret = snd_soc_read(codec, WM8904_SW_RESET_AND_ID);
2122 if (ret < 0) {
2123 dev_err(codec->dev, "Failed to read ID register\n");
2124 goto err_enable;
2125 }
2126 if (ret != 0x8904) {
2127 dev_err(codec->dev, "Device is not a WM8904, ID is %x\n", ret);
2128 ret = -EINVAL;
2129 goto err_enable;
2130 }
2131
2132 ret = snd_soc_read(codec, WM8904_REVISION);
2133 if (ret < 0) {
2134 dev_err(codec->dev, "Failed to read device revision: %d\n",
2135 ret);
2136 goto err_enable;
2137 }
2138 dev_info(codec->dev, "revision %c\n", ret + 'A');
2139
2140 ret = wm8904_reset(codec);
2141 if (ret < 0) {
2142 dev_err(codec->dev, "Failed to issue reset\n");
2143 goto err_enable;
2144 }
2145
2146 regcache_cache_only(wm8904->regmap, true);
2147 /* Change some default settings - latch VU and enable ZC */
2148 snd_soc_update_bits(codec, WM8904_ADC_DIGITAL_VOLUME_LEFT,
2149 WM8904_ADC_VU, WM8904_ADC_VU);
2150 snd_soc_update_bits(codec, WM8904_ADC_DIGITAL_VOLUME_RIGHT,
2151 WM8904_ADC_VU, WM8904_ADC_VU);
2152 snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_VOLUME_LEFT,
2153 WM8904_DAC_VU, WM8904_DAC_VU);
2154 snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_VOLUME_RIGHT,
2155 WM8904_DAC_VU, WM8904_DAC_VU);
2156 snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT1_LEFT,
2157 WM8904_HPOUT_VU | WM8904_HPOUTLZC,
2158 WM8904_HPOUT_VU | WM8904_HPOUTLZC);
2159 snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT1_RIGHT,
2160 WM8904_HPOUT_VU | WM8904_HPOUTRZC,
2161 WM8904_HPOUT_VU | WM8904_HPOUTRZC);
2162 snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT2_LEFT,
2163 WM8904_LINEOUT_VU | WM8904_LINEOUTLZC,
2164 WM8904_LINEOUT_VU | WM8904_LINEOUTLZC);
2165 snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT2_RIGHT,
2166 WM8904_LINEOUT_VU | WM8904_LINEOUTRZC,
2167 WM8904_LINEOUT_VU | WM8904_LINEOUTRZC);
2168 snd_soc_update_bits(codec, WM8904_CLOCK_RATES_0,
2169 WM8904_SR_MODE, 0);
2170
2171 /* Apply configuration from the platform data. */
2172 if (wm8904->pdata) {
2173 for (i = 0; i < WM8904_GPIO_REGS; i++) {
2174 if (!pdata->gpio_cfg[i])
2175 continue;
2176
2177 regmap_update_bits(wm8904->regmap,
2178 WM8904_GPIO_CONTROL_1 + i,
2179 0xffff,
2180 pdata->gpio_cfg[i]);
2181 }
2182
2183 /* Zero is the default value for these anyway */
2184 for (i = 0; i < WM8904_MIC_REGS; i++)
2185 regmap_update_bits(wm8904->regmap,
2186 WM8904_MIC_BIAS_CONTROL_0 + i,
2187 0xffff,
2188 pdata->mic_cfg[i]);
2189 }
2190
2191 /* Set Class W by default - this will be managed by the Class
2192 * G widget at runtime where bypass paths are available.
2193 */
2194 snd_soc_update_bits(codec, WM8904_CLASS_W_0,
2195 WM8904_CP_DYN_PWR, WM8904_CP_DYN_PWR);
2196
2197 /* Use normal bias source */
2198 snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0,
2199 WM8904_POBCTRL, 0);
2200
2201 wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
2202
2203 /* Bias level configuration will have done an extra enable */
2204 regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
2205
2206 wm8904_handle_pdata(codec); 2079 wm8904_handle_pdata(codec);
2207 2080
2208 wm8904_add_widgets(codec); 2081 wm8904_add_widgets(codec);
2209 2082
2210 return 0; 2083 return 0;
2211
2212err_enable:
2213 regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
2214err_get:
2215 regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
2216 return ret;
2217} 2084}
2218 2085
2219static int wm8904_remove(struct snd_soc_codec *codec) 2086static int wm8904_remove(struct snd_soc_codec *codec)
2220{ 2087{
2221 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); 2088 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
2222 2089
2223 wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF);
2224 regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
2225 kfree(wm8904->retune_mobile_texts); 2090 kfree(wm8904->retune_mobile_texts);
2226 kfree(wm8904->drc_texts); 2091 kfree(wm8904->drc_texts);
2227 2092
@@ -2231,8 +2096,6 @@ static int wm8904_remove(struct snd_soc_codec *codec)
2231static struct snd_soc_codec_driver soc_codec_dev_wm8904 = { 2096static struct snd_soc_codec_driver soc_codec_dev_wm8904 = {
2232 .probe = wm8904_probe, 2097 .probe = wm8904_probe,
2233 .remove = wm8904_remove, 2098 .remove = wm8904_remove,
2234 .suspend = wm8904_suspend,
2235 .resume = wm8904_resume,
2236 .set_bias_level = wm8904_set_bias_level, 2099 .set_bias_level = wm8904_set_bias_level,
2237 .idle_bias_off = true, 2100 .idle_bias_off = true,
2238}; 2101};
@@ -2254,14 +2117,15 @@ static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
2254 const struct i2c_device_id *id) 2117 const struct i2c_device_id *id)
2255{ 2118{
2256 struct wm8904_priv *wm8904; 2119 struct wm8904_priv *wm8904;
2257 int ret; 2120 unsigned int val;
2121 int ret, i;
2258 2122
2259 wm8904 = devm_kzalloc(&i2c->dev, sizeof(struct wm8904_priv), 2123 wm8904 = devm_kzalloc(&i2c->dev, sizeof(struct wm8904_priv),
2260 GFP_KERNEL); 2124 GFP_KERNEL);
2261 if (wm8904 == NULL) 2125 if (wm8904 == NULL)
2262 return -ENOMEM; 2126 return -ENOMEM;
2263 2127
2264 wm8904->regmap = regmap_init_i2c(i2c, &wm8904_regmap); 2128 wm8904->regmap = devm_regmap_init_i2c(i2c, &wm8904_regmap);
2265 if (IS_ERR(wm8904->regmap)) { 2129 if (IS_ERR(wm8904->regmap)) {
2266 ret = PTR_ERR(wm8904->regmap); 2130 ret = PTR_ERR(wm8904->regmap);
2267 dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 2131 dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
@@ -2273,23 +2137,121 @@ static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
2273 i2c_set_clientdata(i2c, wm8904); 2137 i2c_set_clientdata(i2c, wm8904);
2274 wm8904->pdata = i2c->dev.platform_data; 2138 wm8904->pdata = i2c->dev.platform_data;
2275 2139
2140 for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++)
2141 wm8904->supplies[i].supply = wm8904_supply_names[i];
2142
2143 ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8904->supplies),
2144 wm8904->supplies);
2145 if (ret != 0) {
2146 dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
2147 return ret;
2148 }
2149
2150 ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies),
2151 wm8904->supplies);
2152 if (ret != 0) {
2153 dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
2154 return ret;
2155 }
2156
2157 ret = regmap_read(wm8904->regmap, WM8904_SW_RESET_AND_ID, &val);
2158 if (ret < 0) {
2159 dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
2160 goto err_enable;
2161 }
2162 if (val != 0x8904) {
2163 dev_err(&i2c->dev, "Device is not a WM8904, ID is %x\n", val);
2164 ret = -EINVAL;
2165 goto err_enable;
2166 }
2167
2168 ret = regmap_read(wm8904->regmap, WM8904_REVISION, &val);
2169 if (ret < 0) {
2170 dev_err(&i2c->dev, "Failed to read device revision: %d\n",
2171 ret);
2172 goto err_enable;
2173 }
2174 dev_info(&i2c->dev, "revision %c\n", val + 'A');
2175
2176 ret = regmap_write(wm8904->regmap, WM8904_SW_RESET_AND_ID, 0);
2177 if (ret < 0) {
2178 dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret);
2179 goto err_enable;
2180 }
2181
2182 /* Change some default settings - latch VU and enable ZC */
2183 regmap_update_bits(wm8904->regmap, WM8904_ADC_DIGITAL_VOLUME_LEFT,
2184 WM8904_ADC_VU, WM8904_ADC_VU);
2185 regmap_update_bits(wm8904->regmap, WM8904_ADC_DIGITAL_VOLUME_RIGHT,
2186 WM8904_ADC_VU, WM8904_ADC_VU);
2187 regmap_update_bits(wm8904->regmap, WM8904_DAC_DIGITAL_VOLUME_LEFT,
2188 WM8904_DAC_VU, WM8904_DAC_VU);
2189 regmap_update_bits(wm8904->regmap, WM8904_DAC_DIGITAL_VOLUME_RIGHT,
2190 WM8904_DAC_VU, WM8904_DAC_VU);
2191 regmap_update_bits(wm8904->regmap, WM8904_ANALOGUE_OUT1_LEFT,
2192 WM8904_HPOUT_VU | WM8904_HPOUTLZC,
2193 WM8904_HPOUT_VU | WM8904_HPOUTLZC);
2194 regmap_update_bits(wm8904->regmap, WM8904_ANALOGUE_OUT1_RIGHT,
2195 WM8904_HPOUT_VU | WM8904_HPOUTRZC,
2196 WM8904_HPOUT_VU | WM8904_HPOUTRZC);
2197 regmap_update_bits(wm8904->regmap, WM8904_ANALOGUE_OUT2_LEFT,
2198 WM8904_LINEOUT_VU | WM8904_LINEOUTLZC,
2199 WM8904_LINEOUT_VU | WM8904_LINEOUTLZC);
2200 regmap_update_bits(wm8904->regmap, WM8904_ANALOGUE_OUT2_RIGHT,
2201 WM8904_LINEOUT_VU | WM8904_LINEOUTRZC,
2202 WM8904_LINEOUT_VU | WM8904_LINEOUTRZC);
2203 regmap_update_bits(wm8904->regmap, WM8904_CLOCK_RATES_0,
2204 WM8904_SR_MODE, 0);
2205
2206 /* Apply configuration from the platform data. */
2207 if (wm8904->pdata) {
2208 for (i = 0; i < WM8904_GPIO_REGS; i++) {
2209 if (!wm8904->pdata->gpio_cfg[i])
2210 continue;
2211
2212 regmap_update_bits(wm8904->regmap,
2213 WM8904_GPIO_CONTROL_1 + i,
2214 0xffff,
2215 wm8904->pdata->gpio_cfg[i]);
2216 }
2217
2218 /* Zero is the default value for these anyway */
2219 for (i = 0; i < WM8904_MIC_REGS; i++)
2220 regmap_update_bits(wm8904->regmap,
2221 WM8904_MIC_BIAS_CONTROL_0 + i,
2222 0xffff,
2223 wm8904->pdata->mic_cfg[i]);
2224 }
2225
2226 /* Set Class W by default - this will be managed by the Class
2227 * G widget at runtime where bypass paths are available.
2228 */
2229 regmap_update_bits(wm8904->regmap, WM8904_CLASS_W_0,
2230 WM8904_CP_DYN_PWR, WM8904_CP_DYN_PWR);
2231
2232 /* Use normal bias source */
2233 regmap_update_bits(wm8904->regmap, WM8904_BIAS_CONTROL_0,
2234 WM8904_POBCTRL, 0);
2235
2236 /* Can leave the device powered off until we need it */
2237 regcache_cache_only(wm8904->regmap, true);
2238 regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
2239
2276 ret = snd_soc_register_codec(&i2c->dev, 2240 ret = snd_soc_register_codec(&i2c->dev,
2277 &soc_codec_dev_wm8904, &wm8904_dai, 1); 2241 &soc_codec_dev_wm8904, &wm8904_dai, 1);
2278 if (ret != 0) 2242 if (ret != 0)
2279 goto err; 2243 return ret;
2280 2244
2281 return 0; 2245 return 0;
2282 2246
2283err: 2247err_enable:
2284 regmap_exit(wm8904->regmap); 2248 regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
2285 return ret; 2249 return ret;
2286} 2250}
2287 2251
2288static __devexit int wm8904_i2c_remove(struct i2c_client *client) 2252static __devexit int wm8904_i2c_remove(struct i2c_client *client)
2289{ 2253{
2290 struct wm8904_priv *wm8904 = i2c_get_clientdata(client);
2291 snd_soc_unregister_codec(&client->dev); 2254 snd_soc_unregister_codec(&client->dev);
2292 regmap_exit(wm8904->regmap);
2293 return 0; 2255 return 0;
2294} 2256}
2295 2257
@@ -2311,23 +2273,7 @@ static struct i2c_driver wm8904_i2c_driver = {
2311 .id_table = wm8904_i2c_id, 2273 .id_table = wm8904_i2c_id,
2312}; 2274};
2313 2275
2314static int __init wm8904_modinit(void) 2276module_i2c_driver(wm8904_i2c_driver);
2315{
2316 int ret = 0;
2317 ret = i2c_add_driver(&wm8904_i2c_driver);
2318 if (ret != 0) {
2319 printk(KERN_ERR "Failed to register wm8904 I2C driver: %d\n",
2320 ret);
2321 }
2322 return ret;
2323}
2324module_init(wm8904_modinit);
2325
2326static void __exit wm8904_exit(void)
2327{
2328 i2c_del_driver(&wm8904_i2c_driver);
2329}
2330module_exit(wm8904_exit);
2331 2277
2332MODULE_DESCRIPTION("ASoC WM8904 driver"); 2278MODULE_DESCRIPTION("ASoC WM8904 driver");
2333MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 2279MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 8bc659d8dd2..96518ac8e24 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -1,6 +1,8 @@
1/* 1/*
2 * wm8960.c -- WM8960 ALSA SoC Audio driver 2 * wm8960.c -- WM8960 ALSA SoC Audio driver
3 * 3 *
4 * Copyright 2007-11 Wolfson Microelectronics, plc
5 *
4 * Author: Liam Girdwood 6 * Author: Liam Girdwood
5 * 7 *
6 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index 05ea7c27409..01edbcc754d 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -1,6 +1,8 @@
1/* 1/*
2 * wm8961.c -- WM8961 ALSA SoC Audio driver 2 * wm8961.c -- WM8961 ALSA SoC Audio driver
3 * 3 *
4 * Copyright 2009-10 Wolfson Microelectronics, plc
5 *
4 * Author: Mark Brown 6 * Author: Mark Brown
5 * 7 *
6 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 0cfce9999c8..eaf65863ec2 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * wm8962.c -- WM8962 ALSA SoC Audio driver 2 * wm8962.c -- WM8962 ALSA SoC Audio driver
3 * 3 *
4 * Copyright 2010 Wolfson Microelectronics plc 4 * Copyright 2010-2 Wolfson Microelectronics plc
5 * 5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 * 7 *
@@ -2580,6 +2580,9 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
2580 WM8962_SAMPLE_RATE_INT_MODE | 2580 WM8962_SAMPLE_RATE_INT_MODE |
2581 WM8962_SAMPLE_RATE_MASK, adctl3); 2581 WM8962_SAMPLE_RATE_MASK, adctl3);
2582 2582
2583 dev_dbg(codec->dev, "hw_params set BCLK %dHz LRCLK %dHz\n",
2584 wm8962->bclk, wm8962->lrclk);
2585
2583 if (codec->dapm.bias_level == SND_SOC_BIAS_ON) 2586 if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
2584 wm8962_configure_bclk(codec); 2587 wm8962_configure_bclk(codec);
2585 2588
@@ -3722,6 +3725,9 @@ static int wm8962_runtime_resume(struct device *dev)
3722 } 3725 }
3723 3726
3724 regcache_cache_only(wm8962->regmap, false); 3727 regcache_cache_only(wm8962->regmap, false);
3728
3729 wm8962_reset(wm8962);
3730
3725 regcache_sync(wm8962->regmap); 3731 regcache_sync(wm8962->regmap);
3726 3732
3727 regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP, 3733 regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP,
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index 36acfccab99..9fd80d68897 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * wm8993.c -- WM8993 ALSA SoC audio driver 2 * wm8993.c -- WM8993 ALSA SoC audio driver
3 * 3 *
4 * Copyright 2009, 2010 Wolfson Microelectronics plc 4 * Copyright 2009-12 Wolfson Microelectronics plc
5 * 5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 * 7 *
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 1436b6ce74d..bb62f4b3d56 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * wm8994.c -- WM8994 ALSA SoC Audio driver 2 * wm8994.c -- WM8994 ALSA SoC Audio driver
3 * 3 *
4 * Copyright 2009 Wolfson Microelectronics plc 4 * Copyright 2009-12 Wolfson Microelectronics plc
5 * 5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 * 7 *
@@ -2967,23 +2967,8 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
2967static int wm8994_codec_suspend(struct snd_soc_codec *codec) 2967static int wm8994_codec_suspend(struct snd_soc_codec *codec)
2968{ 2968{
2969 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 2969 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
2970 struct wm8994 *control = wm8994->wm8994;
2971 int i, ret; 2970 int i, ret;
2972 2971
2973 switch (control->type) {
2974 case WM8994:
2975 snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0);
2976 break;
2977 case WM1811:
2978 snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
2979 WM1811_JACKDET_MODE_MASK, 0);
2980 /* Fall through */
2981 case WM8958:
2982 snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
2983 WM8958_MICD_ENA, 0);
2984 break;
2985 }
2986
2987 for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { 2972 for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
2988 memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i], 2973 memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i],
2989 sizeof(struct wm8994_fll_config)); 2974 sizeof(struct wm8994_fll_config));
@@ -3033,28 +3018,6 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec)
3033 i + 1, ret); 3018 i + 1, ret);
3034 } 3019 }
3035 3020
3036 switch (control->type) {
3037 case WM8994:
3038 if (wm8994->micdet[0].jack || wm8994->micdet[1].jack)
3039 snd_soc_update_bits(codec, WM8994_MICBIAS,
3040 WM8994_MICD_ENA, WM8994_MICD_ENA);
3041 break;
3042 case WM1811:
3043 if (wm8994->jackdet && wm8994->jack_cb) {
3044 /* Restart from idle */
3045 snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
3046 WM1811_JACKDET_MODE_MASK,
3047 WM1811_JACKDET_MODE_JACK);
3048 break;
3049 }
3050 break;
3051 case WM8958:
3052 if (wm8994->jack_cb)
3053 snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
3054 WM8958_MICD_ENA, WM8958_MICD_ENA);
3055 break;
3056 }
3057
3058 return 0; 3021 return 0;
3059} 3022}
3060#else 3023#else
@@ -3729,9 +3692,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
3729 3692
3730 if (wm8994->pdata && wm8994->pdata->micdet_irq) 3693 if (wm8994->pdata && wm8994->pdata->micdet_irq)
3731 wm8994->micdet_irq = wm8994->pdata->micdet_irq; 3694 wm8994->micdet_irq = wm8994->pdata->micdet_irq;
3732 else if (wm8994->pdata && wm8994->pdata->irq_base)
3733 wm8994->micdet_irq = wm8994->pdata->irq_base +
3734 WM8994_IRQ_MIC1_DET;
3735 3695
3736 pm_runtime_enable(codec->dev); 3696 pm_runtime_enable(codec->dev);
3737 pm_runtime_idle(codec->dev); 3697 pm_runtime_idle(codec->dev);
@@ -3870,6 +3830,10 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
3870 dev_warn(codec->dev, 3830 dev_warn(codec->dev,
3871 "Failed to request Mic detect IRQ: %d\n", 3831 "Failed to request Mic detect IRQ: %d\n",
3872 ret); 3832 ret);
3833 } else {
3834 wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_MIC1_DET,
3835 wm8958_mic_irq, "Mic detect",
3836 wm8994);
3873 } 3837 }
3874 } 3838 }
3875 3839
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index dc9b42b7fc4..00f183dfa45 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * wm8996.c - WM8996 audio codec interface 2 * wm8996.c - WM8996 audio codec interface
3 * 3 *
4 * Copyright 2011 Wolfson Microelectronics PLC. 4 * Copyright 2011-2 Wolfson Microelectronics PLC.
5 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 5 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
@@ -296,184 +296,6 @@ static struct reg_default wm8996_reg[] = {
296 { WM8996_RIGHT_PDM_SPEAKER, 0x1 }, 296 { WM8996_RIGHT_PDM_SPEAKER, 0x1 },
297 { WM8996_PDM_SPEAKER_MUTE_SEQUENCE, 0x69 }, 297 { WM8996_PDM_SPEAKER_MUTE_SEQUENCE, 0x69 },
298 { WM8996_PDM_SPEAKER_VOLUME, 0x66 }, 298 { WM8996_PDM_SPEAKER_VOLUME, 0x66 },
299 { WM8996_WRITE_SEQUENCER_0, 0x1 },
300 { WM8996_WRITE_SEQUENCER_1, 0x1 },
301 { WM8996_WRITE_SEQUENCER_3, 0x6 },
302 { WM8996_WRITE_SEQUENCER_4, 0x40 },
303 { WM8996_WRITE_SEQUENCER_5, 0x1 },
304 { WM8996_WRITE_SEQUENCER_6, 0xf },
305 { WM8996_WRITE_SEQUENCER_7, 0x6 },
306 { WM8996_WRITE_SEQUENCER_8, 0x1 },
307 { WM8996_WRITE_SEQUENCER_9, 0x3 },
308 { WM8996_WRITE_SEQUENCER_10, 0x104 },
309 { WM8996_WRITE_SEQUENCER_12, 0x60 },
310 { WM8996_WRITE_SEQUENCER_13, 0x11 },
311 { WM8996_WRITE_SEQUENCER_14, 0x401 },
312 { WM8996_WRITE_SEQUENCER_16, 0x50 },
313 { WM8996_WRITE_SEQUENCER_17, 0x3 },
314 { WM8996_WRITE_SEQUENCER_18, 0x100 },
315 { WM8996_WRITE_SEQUENCER_20, 0x51 },
316 { WM8996_WRITE_SEQUENCER_21, 0x3 },
317 { WM8996_WRITE_SEQUENCER_22, 0x104 },
318 { WM8996_WRITE_SEQUENCER_23, 0xa },
319 { WM8996_WRITE_SEQUENCER_24, 0x60 },
320 { WM8996_WRITE_SEQUENCER_25, 0x3b },
321 { WM8996_WRITE_SEQUENCER_26, 0x502 },
322 { WM8996_WRITE_SEQUENCER_27, 0x100 },
323 { WM8996_WRITE_SEQUENCER_28, 0x2fff },
324 { WM8996_WRITE_SEQUENCER_32, 0x2fff },
325 { WM8996_WRITE_SEQUENCER_36, 0x2fff },
326 { WM8996_WRITE_SEQUENCER_40, 0x2fff },
327 { WM8996_WRITE_SEQUENCER_44, 0x2fff },
328 { WM8996_WRITE_SEQUENCER_48, 0x2fff },
329 { WM8996_WRITE_SEQUENCER_52, 0x2fff },
330 { WM8996_WRITE_SEQUENCER_56, 0x2fff },
331 { WM8996_WRITE_SEQUENCER_60, 0x2fff },
332 { WM8996_WRITE_SEQUENCER_64, 0x1 },
333 { WM8996_WRITE_SEQUENCER_65, 0x1 },
334 { WM8996_WRITE_SEQUENCER_67, 0x6 },
335 { WM8996_WRITE_SEQUENCER_68, 0x40 },
336 { WM8996_WRITE_SEQUENCER_69, 0x1 },
337 { WM8996_WRITE_SEQUENCER_70, 0xf },
338 { WM8996_WRITE_SEQUENCER_71, 0x6 },
339 { WM8996_WRITE_SEQUENCER_72, 0x1 },
340 { WM8996_WRITE_SEQUENCER_73, 0x3 },
341 { WM8996_WRITE_SEQUENCER_74, 0x104 },
342 { WM8996_WRITE_SEQUENCER_76, 0x60 },
343 { WM8996_WRITE_SEQUENCER_77, 0x11 },
344 { WM8996_WRITE_SEQUENCER_78, 0x401 },
345 { WM8996_WRITE_SEQUENCER_80, 0x50 },
346 { WM8996_WRITE_SEQUENCER_81, 0x3 },
347 { WM8996_WRITE_SEQUENCER_82, 0x100 },
348 { WM8996_WRITE_SEQUENCER_84, 0x60 },
349 { WM8996_WRITE_SEQUENCER_85, 0x3b },
350 { WM8996_WRITE_SEQUENCER_86, 0x502 },
351 { WM8996_WRITE_SEQUENCER_87, 0x100 },
352 { WM8996_WRITE_SEQUENCER_88, 0x2fff },
353 { WM8996_WRITE_SEQUENCER_92, 0x2fff },
354 { WM8996_WRITE_SEQUENCER_96, 0x2fff },
355 { WM8996_WRITE_SEQUENCER_100, 0x2fff },
356 { WM8996_WRITE_SEQUENCER_104, 0x2fff },
357 { WM8996_WRITE_SEQUENCER_108, 0x2fff },
358 { WM8996_WRITE_SEQUENCER_112, 0x2fff },
359 { WM8996_WRITE_SEQUENCER_116, 0x2fff },
360 { WM8996_WRITE_SEQUENCER_120, 0x2fff },
361 { WM8996_WRITE_SEQUENCER_124, 0x2fff },
362 { WM8996_WRITE_SEQUENCER_128, 0x1 },
363 { WM8996_WRITE_SEQUENCER_129, 0x1 },
364 { WM8996_WRITE_SEQUENCER_131, 0x6 },
365 { WM8996_WRITE_SEQUENCER_132, 0x40 },
366 { WM8996_WRITE_SEQUENCER_133, 0x1 },
367 { WM8996_WRITE_SEQUENCER_134, 0xf },
368 { WM8996_WRITE_SEQUENCER_135, 0x6 },
369 { WM8996_WRITE_SEQUENCER_136, 0x1 },
370 { WM8996_WRITE_SEQUENCER_137, 0x3 },
371 { WM8996_WRITE_SEQUENCER_138, 0x106 },
372 { WM8996_WRITE_SEQUENCER_140, 0x61 },
373 { WM8996_WRITE_SEQUENCER_141, 0x11 },
374 { WM8996_WRITE_SEQUENCER_142, 0x401 },
375 { WM8996_WRITE_SEQUENCER_144, 0x50 },
376 { WM8996_WRITE_SEQUENCER_145, 0x3 },
377 { WM8996_WRITE_SEQUENCER_146, 0x102 },
378 { WM8996_WRITE_SEQUENCER_148, 0x51 },
379 { WM8996_WRITE_SEQUENCER_149, 0x3 },
380 { WM8996_WRITE_SEQUENCER_150, 0x106 },
381 { WM8996_WRITE_SEQUENCER_151, 0xa },
382 { WM8996_WRITE_SEQUENCER_152, 0x61 },
383 { WM8996_WRITE_SEQUENCER_153, 0x3b },
384 { WM8996_WRITE_SEQUENCER_154, 0x502 },
385 { WM8996_WRITE_SEQUENCER_155, 0x100 },
386 { WM8996_WRITE_SEQUENCER_156, 0x2fff },
387 { WM8996_WRITE_SEQUENCER_160, 0x2fff },
388 { WM8996_WRITE_SEQUENCER_164, 0x2fff },
389 { WM8996_WRITE_SEQUENCER_168, 0x2fff },
390 { WM8996_WRITE_SEQUENCER_172, 0x2fff },
391 { WM8996_WRITE_SEQUENCER_176, 0x2fff },
392 { WM8996_WRITE_SEQUENCER_180, 0x2fff },
393 { WM8996_WRITE_SEQUENCER_184, 0x2fff },
394 { WM8996_WRITE_SEQUENCER_188, 0x2fff },
395 { WM8996_WRITE_SEQUENCER_192, 0x1 },
396 { WM8996_WRITE_SEQUENCER_193, 0x1 },
397 { WM8996_WRITE_SEQUENCER_195, 0x6 },
398 { WM8996_WRITE_SEQUENCER_196, 0x40 },
399 { WM8996_WRITE_SEQUENCER_197, 0x1 },
400 { WM8996_WRITE_SEQUENCER_198, 0xf },
401 { WM8996_WRITE_SEQUENCER_199, 0x6 },
402 { WM8996_WRITE_SEQUENCER_200, 0x1 },
403 { WM8996_WRITE_SEQUENCER_201, 0x3 },
404 { WM8996_WRITE_SEQUENCER_202, 0x106 },
405 { WM8996_WRITE_SEQUENCER_204, 0x61 },
406 { WM8996_WRITE_SEQUENCER_205, 0x11 },
407 { WM8996_WRITE_SEQUENCER_206, 0x401 },
408 { WM8996_WRITE_SEQUENCER_208, 0x50 },
409 { WM8996_WRITE_SEQUENCER_209, 0x3 },
410 { WM8996_WRITE_SEQUENCER_210, 0x102 },
411 { WM8996_WRITE_SEQUENCER_212, 0x61 },
412 { WM8996_WRITE_SEQUENCER_213, 0x3b },
413 { WM8996_WRITE_SEQUENCER_214, 0x502 },
414 { WM8996_WRITE_SEQUENCER_215, 0x100 },
415 { WM8996_WRITE_SEQUENCER_216, 0x2fff },
416 { WM8996_WRITE_SEQUENCER_220, 0x2fff },
417 { WM8996_WRITE_SEQUENCER_224, 0x2fff },
418 { WM8996_WRITE_SEQUENCER_228, 0x2fff },
419 { WM8996_WRITE_SEQUENCER_232, 0x2fff },
420 { WM8996_WRITE_SEQUENCER_236, 0x2fff },
421 { WM8996_WRITE_SEQUENCER_240, 0x2fff },
422 { WM8996_WRITE_SEQUENCER_244, 0x2fff },
423 { WM8996_WRITE_SEQUENCER_248, 0x2fff },
424 { WM8996_WRITE_SEQUENCER_252, 0x2fff },
425 { WM8996_WRITE_SEQUENCER_256, 0x60 },
426 { WM8996_WRITE_SEQUENCER_258, 0x601 },
427 { WM8996_WRITE_SEQUENCER_260, 0x50 },
428 { WM8996_WRITE_SEQUENCER_262, 0x100 },
429 { WM8996_WRITE_SEQUENCER_264, 0x1 },
430 { WM8996_WRITE_SEQUENCER_266, 0x104 },
431 { WM8996_WRITE_SEQUENCER_267, 0x100 },
432 { WM8996_WRITE_SEQUENCER_268, 0x2fff },
433 { WM8996_WRITE_SEQUENCER_272, 0x2fff },
434 { WM8996_WRITE_SEQUENCER_276, 0x2fff },
435 { WM8996_WRITE_SEQUENCER_280, 0x2fff },
436 { WM8996_WRITE_SEQUENCER_284, 0x2fff },
437 { WM8996_WRITE_SEQUENCER_288, 0x2fff },
438 { WM8996_WRITE_SEQUENCER_292, 0x2fff },
439 { WM8996_WRITE_SEQUENCER_296, 0x2fff },
440 { WM8996_WRITE_SEQUENCER_300, 0x2fff },
441 { WM8996_WRITE_SEQUENCER_304, 0x2fff },
442 { WM8996_WRITE_SEQUENCER_308, 0x2fff },
443 { WM8996_WRITE_SEQUENCER_312, 0x2fff },
444 { WM8996_WRITE_SEQUENCER_316, 0x2fff },
445 { WM8996_WRITE_SEQUENCER_320, 0x61 },
446 { WM8996_WRITE_SEQUENCER_322, 0x601 },
447 { WM8996_WRITE_SEQUENCER_324, 0x50 },
448 { WM8996_WRITE_SEQUENCER_326, 0x102 },
449 { WM8996_WRITE_SEQUENCER_328, 0x1 },
450 { WM8996_WRITE_SEQUENCER_330, 0x106 },
451 { WM8996_WRITE_SEQUENCER_331, 0x100 },
452 { WM8996_WRITE_SEQUENCER_332, 0x2fff },
453 { WM8996_WRITE_SEQUENCER_336, 0x2fff },
454 { WM8996_WRITE_SEQUENCER_340, 0x2fff },
455 { WM8996_WRITE_SEQUENCER_344, 0x2fff },
456 { WM8996_WRITE_SEQUENCER_348, 0x2fff },
457 { WM8996_WRITE_SEQUENCER_352, 0x2fff },
458 { WM8996_WRITE_SEQUENCER_356, 0x2fff },
459 { WM8996_WRITE_SEQUENCER_360, 0x2fff },
460 { WM8996_WRITE_SEQUENCER_364, 0x2fff },
461 { WM8996_WRITE_SEQUENCER_368, 0x2fff },
462 { WM8996_WRITE_SEQUENCER_372, 0x2fff },
463 { WM8996_WRITE_SEQUENCER_376, 0x2fff },
464 { WM8996_WRITE_SEQUENCER_380, 0x2fff },
465 { WM8996_WRITE_SEQUENCER_384, 0x60 },
466 { WM8996_WRITE_SEQUENCER_386, 0x601 },
467 { WM8996_WRITE_SEQUENCER_388, 0x61 },
468 { WM8996_WRITE_SEQUENCER_390, 0x601 },
469 { WM8996_WRITE_SEQUENCER_392, 0x50 },
470 { WM8996_WRITE_SEQUENCER_394, 0x300 },
471 { WM8996_WRITE_SEQUENCER_396, 0x1 },
472 { WM8996_WRITE_SEQUENCER_398, 0x304 },
473 { WM8996_WRITE_SEQUENCER_400, 0x40 },
474 { WM8996_WRITE_SEQUENCER_402, 0xf },
475 { WM8996_WRITE_SEQUENCER_404, 0x1 },
476 { WM8996_WRITE_SEQUENCER_407, 0x100 },
477}; 299};
478 300
479static const DECLARE_TLV_DB_SCALE(inpga_tlv, 0, 100, 0); 301static const DECLARE_TLV_DB_SCALE(inpga_tlv, 0, 100, 0);
@@ -1706,18 +1528,6 @@ static bool wm8996_volatile_register(struct device *dev, unsigned int reg)
1706 } 1528 }
1707} 1529}
1708 1530
1709static int wm8996_reset(struct wm8996_priv *wm8996)
1710{
1711 if (wm8996->pdata.ldo_ena > 0) {
1712 gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
1713 gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1);
1714 return 0;
1715 } else {
1716 return regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET,
1717 0x8915);
1718 }
1719}
1720
1721static const int bclk_divs[] = { 1531static const int bclk_divs[] = {
1722 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96 1532 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96
1723}; 1533};
@@ -1809,8 +1619,10 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec,
1809 1619
1810 case SND_SOC_BIAS_OFF: 1620 case SND_SOC_BIAS_OFF:
1811 regcache_cache_only(codec->control_data, true); 1621 regcache_cache_only(codec->control_data, true);
1812 if (wm8996->pdata.ldo_ena >= 0) 1622 if (wm8996->pdata.ldo_ena >= 0) {
1813 gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); 1623 gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
1624 regcache_cache_only(codec->control_data, true);
1625 }
1814 regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), 1626 regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies),
1815 wm8996->supplies); 1627 wm8996->supplies);
1816 break; 1628 break;
@@ -2807,7 +2619,7 @@ static int wm8996_probe(struct snd_soc_codec *codec)
2807 int ret; 2619 int ret;
2808 struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); 2620 struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
2809 struct i2c_client *i2c = to_i2c_client(codec->dev); 2621 struct i2c_client *i2c = to_i2c_client(codec->dev);
2810 int i, irq_flags; 2622 int irq_flags;
2811 2623
2812 wm8996->codec = codec; 2624 wm8996->codec = codec;
2813 2625
@@ -2822,177 +2634,12 @@ static int wm8996_probe(struct snd_soc_codec *codec)
2822 goto err; 2634 goto err;
2823 } 2635 }
2824 2636
2825 wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0;
2826 wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1;
2827 wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2;
2828
2829 /* This should really be moved into the regulator core */
2830 for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) {
2831 ret = regulator_register_notifier(wm8996->supplies[i].consumer,
2832 &wm8996->disable_nb[i]);
2833 if (ret != 0) {
2834 dev_err(codec->dev,
2835 "Failed to register regulator notifier: %d\n",
2836 ret);
2837 }
2838 }
2839
2840 /* Apply platform data settings */
2841 snd_soc_update_bits(codec, WM8996_LINE_INPUT_CONTROL,
2842 WM8996_INL_MODE_MASK | WM8996_INR_MODE_MASK,
2843 wm8996->pdata.inl_mode << WM8996_INL_MODE_SHIFT |
2844 wm8996->pdata.inr_mode);
2845
2846 for (i = 0; i < ARRAY_SIZE(wm8996->pdata.gpio_default); i++) {
2847 if (!wm8996->pdata.gpio_default[i])
2848 continue;
2849
2850 snd_soc_write(codec, WM8996_GPIO_1 + i,
2851 wm8996->pdata.gpio_default[i] & 0xffff);
2852 }
2853
2854 if (wm8996->pdata.spkmute_seq)
2855 snd_soc_update_bits(codec, WM8996_PDM_SPEAKER_MUTE_SEQUENCE,
2856 WM8996_SPK_MUTE_ENDIAN |
2857 WM8996_SPK_MUTE_SEQ1_MASK,
2858 wm8996->pdata.spkmute_seq);
2859
2860 snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_2,
2861 WM8996_MICD_BIAS_SRC | WM8996_HPOUT1FB_SRC |
2862 WM8996_MICD_SRC, wm8996->pdata.micdet_def);
2863
2864 /* Latch volume update bits */
2865 snd_soc_update_bits(codec, WM8996_LEFT_LINE_INPUT_VOLUME,
2866 WM8996_IN1_VU, WM8996_IN1_VU);
2867 snd_soc_update_bits(codec, WM8996_RIGHT_LINE_INPUT_VOLUME,
2868 WM8996_IN1_VU, WM8996_IN1_VU);
2869
2870 snd_soc_update_bits(codec, WM8996_DAC1_LEFT_VOLUME,
2871 WM8996_DAC1_VU, WM8996_DAC1_VU);
2872 snd_soc_update_bits(codec, WM8996_DAC1_RIGHT_VOLUME,
2873 WM8996_DAC1_VU, WM8996_DAC1_VU);
2874 snd_soc_update_bits(codec, WM8996_DAC2_LEFT_VOLUME,
2875 WM8996_DAC2_VU, WM8996_DAC2_VU);
2876 snd_soc_update_bits(codec, WM8996_DAC2_RIGHT_VOLUME,
2877 WM8996_DAC2_VU, WM8996_DAC2_VU);
2878
2879 snd_soc_update_bits(codec, WM8996_OUTPUT1_LEFT_VOLUME,
2880 WM8996_DAC1_VU, WM8996_DAC1_VU);
2881 snd_soc_update_bits(codec, WM8996_OUTPUT1_RIGHT_VOLUME,
2882 WM8996_DAC1_VU, WM8996_DAC1_VU);
2883 snd_soc_update_bits(codec, WM8996_OUTPUT2_LEFT_VOLUME,
2884 WM8996_DAC2_VU, WM8996_DAC2_VU);
2885 snd_soc_update_bits(codec, WM8996_OUTPUT2_RIGHT_VOLUME,
2886 WM8996_DAC2_VU, WM8996_DAC2_VU);
2887
2888 snd_soc_update_bits(codec, WM8996_DSP1_TX_LEFT_VOLUME,
2889 WM8996_DSP1TX_VU, WM8996_DSP1TX_VU);
2890 snd_soc_update_bits(codec, WM8996_DSP1_TX_RIGHT_VOLUME,
2891 WM8996_DSP1TX_VU, WM8996_DSP1TX_VU);
2892 snd_soc_update_bits(codec, WM8996_DSP2_TX_LEFT_VOLUME,
2893 WM8996_DSP2TX_VU, WM8996_DSP2TX_VU);
2894 snd_soc_update_bits(codec, WM8996_DSP2_TX_RIGHT_VOLUME,
2895 WM8996_DSP2TX_VU, WM8996_DSP2TX_VU);
2896
2897 snd_soc_update_bits(codec, WM8996_DSP1_RX_LEFT_VOLUME,
2898 WM8996_DSP1RX_VU, WM8996_DSP1RX_VU);
2899 snd_soc_update_bits(codec, WM8996_DSP1_RX_RIGHT_VOLUME,
2900 WM8996_DSP1RX_VU, WM8996_DSP1RX_VU);
2901 snd_soc_update_bits(codec, WM8996_DSP2_RX_LEFT_VOLUME,
2902 WM8996_DSP2RX_VU, WM8996_DSP2RX_VU);
2903 snd_soc_update_bits(codec, WM8996_DSP2_RX_RIGHT_VOLUME,
2904 WM8996_DSP2RX_VU, WM8996_DSP2RX_VU);
2905
2906 /* No support currently for the underclocked TDM modes and
2907 * pick a default TDM layout with each channel pair working with
2908 * slots 0 and 1. */
2909 snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_0_CONFIGURATION,
2910 WM8996_AIF1RX_CHAN0_SLOTS_MASK |
2911 WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
2912 1 << WM8996_AIF1RX_CHAN0_SLOTS_SHIFT | 0);
2913 snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_1_CONFIGURATION,
2914 WM8996_AIF1RX_CHAN1_SLOTS_MASK |
2915 WM8996_AIF1RX_CHAN1_START_SLOT_MASK,
2916 1 << WM8996_AIF1RX_CHAN1_SLOTS_SHIFT | 1);
2917 snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_2_CONFIGURATION,
2918 WM8996_AIF1RX_CHAN2_SLOTS_MASK |
2919 WM8996_AIF1RX_CHAN2_START_SLOT_MASK,
2920 1 << WM8996_AIF1RX_CHAN2_SLOTS_SHIFT | 0);
2921 snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_3_CONFIGURATION,
2922 WM8996_AIF1RX_CHAN3_SLOTS_MASK |
2923 WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
2924 1 << WM8996_AIF1RX_CHAN3_SLOTS_SHIFT | 1);
2925 snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_4_CONFIGURATION,
2926 WM8996_AIF1RX_CHAN4_SLOTS_MASK |
2927 WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
2928 1 << WM8996_AIF1RX_CHAN4_SLOTS_SHIFT | 0);
2929 snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_5_CONFIGURATION,
2930 WM8996_AIF1RX_CHAN5_SLOTS_MASK |
2931 WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
2932 1 << WM8996_AIF1RX_CHAN5_SLOTS_SHIFT | 1);
2933
2934 snd_soc_update_bits(codec, WM8996_AIF2RX_CHANNEL_0_CONFIGURATION,
2935 WM8996_AIF2RX_CHAN0_SLOTS_MASK |
2936 WM8996_AIF2RX_CHAN0_START_SLOT_MASK,
2937 1 << WM8996_AIF2RX_CHAN0_SLOTS_SHIFT | 0);
2938 snd_soc_update_bits(codec, WM8996_AIF2RX_CHANNEL_1_CONFIGURATION,
2939 WM8996_AIF2RX_CHAN1_SLOTS_MASK |
2940 WM8996_AIF2RX_CHAN1_START_SLOT_MASK,
2941 1 << WM8996_AIF2RX_CHAN1_SLOTS_SHIFT | 1);
2942
2943 snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_0_CONFIGURATION,
2944 WM8996_AIF1TX_CHAN0_SLOTS_MASK |
2945 WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
2946 1 << WM8996_AIF1TX_CHAN0_SLOTS_SHIFT | 0);
2947 snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_1_CONFIGURATION,
2948 WM8996_AIF1TX_CHAN1_SLOTS_MASK |
2949 WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
2950 1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1);
2951 snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_2_CONFIGURATION,
2952 WM8996_AIF1TX_CHAN2_SLOTS_MASK |
2953 WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
2954 1 << WM8996_AIF1TX_CHAN2_SLOTS_SHIFT | 0);
2955 snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_3_CONFIGURATION,
2956 WM8996_AIF1TX_CHAN3_SLOTS_MASK |
2957 WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
2958 1 << WM8996_AIF1TX_CHAN3_SLOTS_SHIFT | 1);
2959 snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_4_CONFIGURATION,
2960 WM8996_AIF1TX_CHAN4_SLOTS_MASK |
2961 WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
2962 1 << WM8996_AIF1TX_CHAN4_SLOTS_SHIFT | 0);
2963 snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_5_CONFIGURATION,
2964 WM8996_AIF1TX_CHAN5_SLOTS_MASK |
2965 WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
2966 1 << WM8996_AIF1TX_CHAN5_SLOTS_SHIFT | 1);
2967
2968 snd_soc_update_bits(codec, WM8996_AIF2TX_CHANNEL_0_CONFIGURATION,
2969 WM8996_AIF2TX_CHAN0_SLOTS_MASK |
2970 WM8996_AIF2TX_CHAN0_START_SLOT_MASK,
2971 1 << WM8996_AIF2TX_CHAN0_SLOTS_SHIFT | 0);
2972 snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_1_CONFIGURATION,
2973 WM8996_AIF2TX_CHAN1_SLOTS_MASK |
2974 WM8996_AIF2TX_CHAN1_START_SLOT_MASK,
2975 1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1);
2976
2977 if (wm8996->pdata.num_retune_mobile_cfgs) 2637 if (wm8996->pdata.num_retune_mobile_cfgs)
2978 wm8996_retune_mobile_pdata(codec); 2638 wm8996_retune_mobile_pdata(codec);
2979 else 2639 else
2980 snd_soc_add_codec_controls(codec, wm8996_eq_controls, 2640 snd_soc_add_codec_controls(codec, wm8996_eq_controls,
2981 ARRAY_SIZE(wm8996_eq_controls)); 2641 ARRAY_SIZE(wm8996_eq_controls));
2982 2642
2983 /* If the TX LRCLK pins are not in LRCLK mode configure the
2984 * AIFs to source their clocks from the RX LRCLKs.
2985 */
2986 if ((snd_soc_read(codec, WM8996_GPIO_1)))
2987 snd_soc_update_bits(codec, WM8996_AIF1_TX_LRCLK_2,
2988 WM8996_AIF1TX_LRCLK_MODE,
2989 WM8996_AIF1TX_LRCLK_MODE);
2990
2991 if ((snd_soc_read(codec, WM8996_GPIO_2)))
2992 snd_soc_update_bits(codec, WM8996_AIF2_TX_LRCLK_2,
2993 WM8996_AIF2TX_LRCLK_MODE,
2994 WM8996_AIF2TX_LRCLK_MODE);
2995
2996 if (i2c->irq) { 2643 if (i2c->irq) {
2997 if (wm8996->pdata.irq_flags) 2644 if (wm8996->pdata.irq_flags)
2998 irq_flags = wm8996->pdata.irq_flags; 2645 irq_flags = wm8996->pdata.irq_flags;
@@ -3036,9 +2683,7 @@ err:
3036 2683
3037static int wm8996_remove(struct snd_soc_codec *codec) 2684static int wm8996_remove(struct snd_soc_codec *codec)
3038{ 2685{
3039 struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
3040 struct i2c_client *i2c = to_i2c_client(codec->dev); 2686 struct i2c_client *i2c = to_i2c_client(codec->dev);
3041 int i;
3042 2687
3043 snd_soc_update_bits(codec, WM8996_INTERRUPT_CONTROL, 2688 snd_soc_update_bits(codec, WM8996_INTERRUPT_CONTROL,
3044 WM8996_IM_IRQ, WM8996_IM_IRQ); 2689 WM8996_IM_IRQ, WM8996_IM_IRQ);
@@ -3046,10 +2691,6 @@ static int wm8996_remove(struct snd_soc_codec *codec)
3046 if (i2c->irq) 2691 if (i2c->irq)
3047 free_irq(i2c->irq, codec); 2692 free_irq(i2c->irq, codec);
3048 2693
3049 for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
3050 regulator_unregister_notifier(wm8996->supplies[i].consumer,
3051 &wm8996->disable_nb[i]);
3052
3053 return 0; 2694 return 0;
3054} 2695}
3055 2696
@@ -3163,6 +2804,21 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
3163 goto err_gpio; 2804 goto err_gpio;
3164 } 2805 }
3165 2806
2807 wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0;
2808 wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1;
2809 wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2;
2810
2811 /* This should really be moved into the regulator core */
2812 for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) {
2813 ret = regulator_register_notifier(wm8996->supplies[i].consumer,
2814 &wm8996->disable_nb[i]);
2815 if (ret != 0) {
2816 dev_err(&i2c->dev,
2817 "Failed to register regulator notifier: %d\n",
2818 ret);
2819 }
2820 }
2821
3166 ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies), 2822 ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies),
3167 wm8996->supplies); 2823 wm8996->supplies);
3168 if (ret != 0) { 2824 if (ret != 0) {
@@ -3175,7 +2831,7 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
3175 msleep(5); 2831 msleep(5);
3176 } 2832 }
3177 2833
3178 wm8996->regmap = regmap_init_i2c(i2c, &wm8996_regmap); 2834 wm8996->regmap = devm_regmap_init_i2c(i2c, &wm8996_regmap);
3179 if (IS_ERR(wm8996->regmap)) { 2835 if (IS_ERR(wm8996->regmap)) {
3180 ret = PTR_ERR(wm8996->regmap); 2836 ret = PTR_ERR(wm8996->regmap);
3181 dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); 2837 dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
@@ -3203,15 +2859,199 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
3203 dev_info(&i2c->dev, "revision %c\n", 2859 dev_info(&i2c->dev, "revision %c\n",
3204 (reg & WM8996_CHIP_REV_MASK) + 'A'); 2860 (reg & WM8996_CHIP_REV_MASK) + 'A');
3205 2861
3206 ret = wm8996_reset(wm8996); 2862 if (wm8996->pdata.ldo_ena > 0) {
3207 if (ret < 0) { 2863 gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
3208 dev_err(&i2c->dev, "Failed to issue reset\n"); 2864 regcache_cache_only(wm8996->regmap, true);
3209 goto err_regmap; 2865 } else {
2866 ret = regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET,
2867 0x8915);
2868 if (ret != 0) {
2869 dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret);
2870 goto err_regmap;
2871 }
3210 } 2872 }
3211 2873
3212 regcache_cache_only(wm8996->regmap, true);
3213 regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); 2874 regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
3214 2875
2876 /* Apply platform data settings */
2877 regmap_update_bits(wm8996->regmap, WM8996_LINE_INPUT_CONTROL,
2878 WM8996_INL_MODE_MASK | WM8996_INR_MODE_MASK,
2879 wm8996->pdata.inl_mode << WM8996_INL_MODE_SHIFT |
2880 wm8996->pdata.inr_mode);
2881
2882 for (i = 0; i < ARRAY_SIZE(wm8996->pdata.gpio_default); i++) {
2883 if (!wm8996->pdata.gpio_default[i])
2884 continue;
2885
2886 regmap_write(wm8996->regmap, WM8996_GPIO_1 + i,
2887 wm8996->pdata.gpio_default[i] & 0xffff);
2888 }
2889
2890 if (wm8996->pdata.spkmute_seq)
2891 regmap_update_bits(wm8996->regmap,
2892 WM8996_PDM_SPEAKER_MUTE_SEQUENCE,
2893 WM8996_SPK_MUTE_ENDIAN |
2894 WM8996_SPK_MUTE_SEQ1_MASK,
2895 wm8996->pdata.spkmute_seq);
2896
2897 regmap_update_bits(wm8996->regmap, WM8996_ACCESSORY_DETECT_MODE_2,
2898 WM8996_MICD_BIAS_SRC | WM8996_HPOUT1FB_SRC |
2899 WM8996_MICD_SRC, wm8996->pdata.micdet_def);
2900
2901 /* Latch volume update bits */
2902 regmap_update_bits(wm8996->regmap, WM8996_LEFT_LINE_INPUT_VOLUME,
2903 WM8996_IN1_VU, WM8996_IN1_VU);
2904 regmap_update_bits(wm8996->regmap, WM8996_RIGHT_LINE_INPUT_VOLUME,
2905 WM8996_IN1_VU, WM8996_IN1_VU);
2906
2907 regmap_update_bits(wm8996->regmap, WM8996_DAC1_LEFT_VOLUME,
2908 WM8996_DAC1_VU, WM8996_DAC1_VU);
2909 regmap_update_bits(wm8996->regmap, WM8996_DAC1_RIGHT_VOLUME,
2910 WM8996_DAC1_VU, WM8996_DAC1_VU);
2911 regmap_update_bits(wm8996->regmap, WM8996_DAC2_LEFT_VOLUME,
2912 WM8996_DAC2_VU, WM8996_DAC2_VU);
2913 regmap_update_bits(wm8996->regmap, WM8996_DAC2_RIGHT_VOLUME,
2914 WM8996_DAC2_VU, WM8996_DAC2_VU);
2915
2916 regmap_update_bits(wm8996->regmap, WM8996_OUTPUT1_LEFT_VOLUME,
2917 WM8996_DAC1_VU, WM8996_DAC1_VU);
2918 regmap_update_bits(wm8996->regmap, WM8996_OUTPUT1_RIGHT_VOLUME,
2919 WM8996_DAC1_VU, WM8996_DAC1_VU);
2920 regmap_update_bits(wm8996->regmap, WM8996_OUTPUT2_LEFT_VOLUME,
2921 WM8996_DAC2_VU, WM8996_DAC2_VU);
2922 regmap_update_bits(wm8996->regmap, WM8996_OUTPUT2_RIGHT_VOLUME,
2923 WM8996_DAC2_VU, WM8996_DAC2_VU);
2924
2925 regmap_update_bits(wm8996->regmap, WM8996_DSP1_TX_LEFT_VOLUME,
2926 WM8996_DSP1TX_VU, WM8996_DSP1TX_VU);
2927 regmap_update_bits(wm8996->regmap, WM8996_DSP1_TX_RIGHT_VOLUME,
2928 WM8996_DSP1TX_VU, WM8996_DSP1TX_VU);
2929 regmap_update_bits(wm8996->regmap, WM8996_DSP2_TX_LEFT_VOLUME,
2930 WM8996_DSP2TX_VU, WM8996_DSP2TX_VU);
2931 regmap_update_bits(wm8996->regmap, WM8996_DSP2_TX_RIGHT_VOLUME,
2932 WM8996_DSP2TX_VU, WM8996_DSP2TX_VU);
2933
2934 regmap_update_bits(wm8996->regmap, WM8996_DSP1_RX_LEFT_VOLUME,
2935 WM8996_DSP1RX_VU, WM8996_DSP1RX_VU);
2936 regmap_update_bits(wm8996->regmap, WM8996_DSP1_RX_RIGHT_VOLUME,
2937 WM8996_DSP1RX_VU, WM8996_DSP1RX_VU);
2938 regmap_update_bits(wm8996->regmap, WM8996_DSP2_RX_LEFT_VOLUME,
2939 WM8996_DSP2RX_VU, WM8996_DSP2RX_VU);
2940 regmap_update_bits(wm8996->regmap, WM8996_DSP2_RX_RIGHT_VOLUME,
2941 WM8996_DSP2RX_VU, WM8996_DSP2RX_VU);
2942
2943 /* No support currently for the underclocked TDM modes and
2944 * pick a default TDM layout with each channel pair working with
2945 * slots 0 and 1. */
2946 regmap_update_bits(wm8996->regmap,
2947 WM8996_AIF1RX_CHANNEL_0_CONFIGURATION,
2948 WM8996_AIF1RX_CHAN0_SLOTS_MASK |
2949 WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
2950 1 << WM8996_AIF1RX_CHAN0_SLOTS_SHIFT | 0);
2951 regmap_update_bits(wm8996->regmap,
2952 WM8996_AIF1RX_CHANNEL_1_CONFIGURATION,
2953 WM8996_AIF1RX_CHAN1_SLOTS_MASK |
2954 WM8996_AIF1RX_CHAN1_START_SLOT_MASK,
2955 1 << WM8996_AIF1RX_CHAN1_SLOTS_SHIFT | 1);
2956 regmap_update_bits(wm8996->regmap,
2957 WM8996_AIF1RX_CHANNEL_2_CONFIGURATION,
2958 WM8996_AIF1RX_CHAN2_SLOTS_MASK |
2959 WM8996_AIF1RX_CHAN2_START_SLOT_MASK,
2960 1 << WM8996_AIF1RX_CHAN2_SLOTS_SHIFT | 0);
2961 regmap_update_bits(wm8996->regmap,
2962 WM8996_AIF1RX_CHANNEL_3_CONFIGURATION,
2963 WM8996_AIF1RX_CHAN3_SLOTS_MASK |
2964 WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
2965 1 << WM8996_AIF1RX_CHAN3_SLOTS_SHIFT | 1);
2966 regmap_update_bits(wm8996->regmap,
2967 WM8996_AIF1RX_CHANNEL_4_CONFIGURATION,
2968 WM8996_AIF1RX_CHAN4_SLOTS_MASK |
2969 WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
2970 1 << WM8996_AIF1RX_CHAN4_SLOTS_SHIFT | 0);
2971 regmap_update_bits(wm8996->regmap,
2972 WM8996_AIF1RX_CHANNEL_5_CONFIGURATION,
2973 WM8996_AIF1RX_CHAN5_SLOTS_MASK |
2974 WM8996_AIF1RX_CHAN0_START_SLOT_MASK,
2975 1 << WM8996_AIF1RX_CHAN5_SLOTS_SHIFT | 1);
2976
2977 regmap_update_bits(wm8996->regmap,
2978 WM8996_AIF2RX_CHANNEL_0_CONFIGURATION,
2979 WM8996_AIF2RX_CHAN0_SLOTS_MASK |
2980 WM8996_AIF2RX_CHAN0_START_SLOT_MASK,
2981 1 << WM8996_AIF2RX_CHAN0_SLOTS_SHIFT | 0);
2982 regmap_update_bits(wm8996->regmap,
2983 WM8996_AIF2RX_CHANNEL_1_CONFIGURATION,
2984 WM8996_AIF2RX_CHAN1_SLOTS_MASK |
2985 WM8996_AIF2RX_CHAN1_START_SLOT_MASK,
2986 1 << WM8996_AIF2RX_CHAN1_SLOTS_SHIFT | 1);
2987
2988 regmap_update_bits(wm8996->regmap,
2989 WM8996_AIF1TX_CHANNEL_0_CONFIGURATION,
2990 WM8996_AIF1TX_CHAN0_SLOTS_MASK |
2991 WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
2992 1 << WM8996_AIF1TX_CHAN0_SLOTS_SHIFT | 0);
2993 regmap_update_bits(wm8996->regmap,
2994 WM8996_AIF1TX_CHANNEL_1_CONFIGURATION,
2995 WM8996_AIF1TX_CHAN1_SLOTS_MASK |
2996 WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
2997 1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1);
2998 regmap_update_bits(wm8996->regmap,
2999 WM8996_AIF1TX_CHANNEL_2_CONFIGURATION,
3000 WM8996_AIF1TX_CHAN2_SLOTS_MASK |
3001 WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
3002 1 << WM8996_AIF1TX_CHAN2_SLOTS_SHIFT | 0);
3003 regmap_update_bits(wm8996->regmap,
3004 WM8996_AIF1TX_CHANNEL_3_CONFIGURATION,
3005 WM8996_AIF1TX_CHAN3_SLOTS_MASK |
3006 WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
3007 1 << WM8996_AIF1TX_CHAN3_SLOTS_SHIFT | 1);
3008 regmap_update_bits(wm8996->regmap,
3009 WM8996_AIF1TX_CHANNEL_4_CONFIGURATION,
3010 WM8996_AIF1TX_CHAN4_SLOTS_MASK |
3011 WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
3012 1 << WM8996_AIF1TX_CHAN4_SLOTS_SHIFT | 0);
3013 regmap_update_bits(wm8996->regmap,
3014 WM8996_AIF1TX_CHANNEL_5_CONFIGURATION,
3015 WM8996_AIF1TX_CHAN5_SLOTS_MASK |
3016 WM8996_AIF1TX_CHAN0_START_SLOT_MASK,
3017 1 << WM8996_AIF1TX_CHAN5_SLOTS_SHIFT | 1);
3018
3019 regmap_update_bits(wm8996->regmap,
3020 WM8996_AIF2TX_CHANNEL_0_CONFIGURATION,
3021 WM8996_AIF2TX_CHAN0_SLOTS_MASK |
3022 WM8996_AIF2TX_CHAN0_START_SLOT_MASK,
3023 1 << WM8996_AIF2TX_CHAN0_SLOTS_SHIFT | 0);
3024 regmap_update_bits(wm8996->regmap,
3025 WM8996_AIF1TX_CHANNEL_1_CONFIGURATION,
3026 WM8996_AIF2TX_CHAN1_SLOTS_MASK |
3027 WM8996_AIF2TX_CHAN1_START_SLOT_MASK,
3028 1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1);
3029
3030 /* If the TX LRCLK pins are not in LRCLK mode configure the
3031 * AIFs to source their clocks from the RX LRCLKs.
3032 */
3033 ret = regmap_read(wm8996->regmap, WM8996_GPIO_1, &reg);
3034 if (ret != 0) {
3035 dev_err(&i2c->dev, "Failed to read GPIO1: %d\n", ret);
3036 goto err_regmap;
3037 }
3038
3039 if (reg & WM8996_GP1_FN_MASK)
3040 regmap_update_bits(wm8996->regmap, WM8996_AIF1_TX_LRCLK_2,
3041 WM8996_AIF1TX_LRCLK_MODE,
3042 WM8996_AIF1TX_LRCLK_MODE);
3043
3044 ret = regmap_read(wm8996->regmap, WM8996_GPIO_2, &reg);
3045 if (ret != 0) {
3046 dev_err(&i2c->dev, "Failed to read GPIO2: %d\n", ret);
3047 goto err_regmap;
3048 }
3049
3050 if (reg & WM8996_GP2_FN_MASK)
3051 regmap_update_bits(wm8996->regmap, WM8996_AIF2_TX_LRCLK_2,
3052 WM8996_AIF2TX_LRCLK_MODE,
3053 WM8996_AIF2TX_LRCLK_MODE);
3054
3215 wm8996_init_gpio(wm8996); 3055 wm8996_init_gpio(wm8996);
3216 3056
3217 ret = snd_soc_register_codec(&i2c->dev, 3057 ret = snd_soc_register_codec(&i2c->dev,
@@ -3225,7 +3065,6 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
3225err_gpiolib: 3065err_gpiolib:
3226 wm8996_free_gpio(wm8996); 3066 wm8996_free_gpio(wm8996);
3227err_regmap: 3067err_regmap:
3228 regmap_exit(wm8996->regmap);
3229err_enable: 3068err_enable:
3230 if (wm8996->pdata.ldo_ena > 0) 3069 if (wm8996->pdata.ldo_ena > 0)
3231 gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); 3070 gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
@@ -3241,14 +3080,18 @@ err:
3241static __devexit int wm8996_i2c_remove(struct i2c_client *client) 3080static __devexit int wm8996_i2c_remove(struct i2c_client *client)
3242{ 3081{
3243 struct wm8996_priv *wm8996 = i2c_get_clientdata(client); 3082 struct wm8996_priv *wm8996 = i2c_get_clientdata(client);
3083 int i;
3244 3084
3245 snd_soc_unregister_codec(&client->dev); 3085 snd_soc_unregister_codec(&client->dev);
3246 wm8996_free_gpio(wm8996); 3086 wm8996_free_gpio(wm8996);
3247 regmap_exit(wm8996->regmap);
3248 if (wm8996->pdata.ldo_ena > 0) { 3087 if (wm8996->pdata.ldo_ena > 0) {
3249 gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); 3088 gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
3250 gpio_free(wm8996->pdata.ldo_ena); 3089 gpio_free(wm8996->pdata.ldo_ena);
3251 } 3090 }
3091 for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
3092 regulator_unregister_notifier(wm8996->supplies[i].consumer,
3093 &wm8996->disable_nb[i]);
3094
3252 return 0; 3095 return 0;
3253} 3096}
3254 3097
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 9328270df16..2de74e1ea22 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Author: Mark Brown 4 * Author: Mark Brown
5 * 5 *
6 * Copyright 2009 Wolfson Microelectronics plc 6 * Copyright 2009-12 Wolfson Microelectronics plc
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index 4b263b6edf1..2c2346fdd63 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * ALSA SoC WM9090 driver 2 * ALSA SoC WM9090 driver
3 * 3 *
4 * Copyright 2009, 2010 Wolfson Microelectronics 4 * Copyright 2009-12 Wolfson Microelectronics
5 * 5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 * 7 *
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index a1541414d90..099e6ec3212 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * wm9712.c -- ALSA Soc WM9712 codec support 2 * wm9712.c -- ALSA Soc WM9712 codec support
3 * 3 *
4 * Copyright 2006 Wolfson Microelectronics PLC. 4 * Copyright 2006-12 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood <lrg@slimlogic.co.uk> 5 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 2d22cc70d53..3eb19fb71d1 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * wm9713.c -- ALSA Soc WM9713 codec support 2 * wm9713.c -- ALSA Soc WM9713 codec support
3 * 3 *
4 * Copyright 2006 Wolfson Microelectronics PLC. 4 * Copyright 2006-10 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood <lrg@slimlogic.co.uk> 5 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index dfe957a47f2..61baa48823c 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * wm_hubs.c -- WM8993/4 common code 2 * wm_hubs.c -- WM8993/4 common code
3 * 3 *
4 * Copyright 2009 Wolfson Microelectronics plc 4 * Copyright 2009-12 Wolfson Microelectronics plc
5 * 5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 * 7 *
diff --git a/sound/soc/dwc/Kconfig b/sound/soc/dwc/Kconfig
new file mode 100644
index 00000000000..e334900cf0b
--- /dev/null
+++ b/sound/soc/dwc/Kconfig
@@ -0,0 +1,9 @@
1config SND_DESIGNWARE_I2S
2 tristate "Synopsys I2S Device Driver"
3 depends on CLKDEV_LOOKUP
4 help
5 Say Y or M if you want to add support for I2S driver for
6 Synopsys desigwnware I2S device. The device supports upto
7 maximum of 8 channels each for play and record.
8
9
diff --git a/sound/soc/dwc/Makefile b/sound/soc/dwc/Makefile
new file mode 100644
index 00000000000..319371f690f
--- /dev/null
+++ b/sound/soc/dwc/Makefile
@@ -0,0 +1,3 @@
1# SYNOPSYS Platform Support
2obj-$(CONFIG_SND_DESIGNWARE_I2S) += designware_i2s.o
3
diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c
new file mode 100644
index 00000000000..1aa51300c56
--- /dev/null
+++ b/sound/soc/dwc/designware_i2s.c
@@ -0,0 +1,455 @@
1/*
2 * ALSA SoC Synopsys I2S Audio Layer
3 *
4 * sound/soc/spear/designware_i2s.c
5 *
6 * Copyright (C) 2010 ST Microelectronics
7 * Rajeev Kumar <rajeev-dlh.kumar@st.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#include <linux/clk.h>
15#include <linux/device.h>
16#include <linux/init.h>
17#include <linux/io.h>
18#include <linux/interrupt.h>
19#include <linux/module.h>
20#include <linux/slab.h>
21#include <sound/designware_i2s.h>
22#include <sound/pcm.h>
23#include <sound/pcm_params.h>
24#include <sound/soc.h>
25
26/* common register for all channel */
27#define IER 0x000
28#define IRER 0x004
29#define ITER 0x008
30#define CER 0x00C
31#define CCR 0x010
32#define RXFFR 0x014
33#define TXFFR 0x018
34
35/* I2STxRxRegisters for all channels */
36#define LRBR_LTHR(x) (0x40 * x + 0x020)
37#define RRBR_RTHR(x) (0x40 * x + 0x024)
38#define RER(x) (0x40 * x + 0x028)
39#define TER(x) (0x40 * x + 0x02C)
40#define RCR(x) (0x40 * x + 0x030)
41#define TCR(x) (0x40 * x + 0x034)
42#define ISR(x) (0x40 * x + 0x038)
43#define IMR(x) (0x40 * x + 0x03C)
44#define ROR(x) (0x40 * x + 0x040)
45#define TOR(x) (0x40 * x + 0x044)
46#define RFCR(x) (0x40 * x + 0x048)
47#define TFCR(x) (0x40 * x + 0x04C)
48#define RFF(x) (0x40 * x + 0x050)
49#define TFF(x) (0x40 * x + 0x054)
50
51/* I2SCOMPRegisters */
52#define I2S_COMP_PARAM_2 0x01F0
53#define I2S_COMP_PARAM_1 0x01F4
54#define I2S_COMP_VERSION 0x01F8
55#define I2S_COMP_TYPE 0x01FC
56
57#define MAX_CHANNEL_NUM 8
58#define MIN_CHANNEL_NUM 2
59
60struct dw_i2s_dev {
61 void __iomem *i2s_base;
62 struct clk *clk;
63 int active;
64 unsigned int capability;
65 struct device *dev;
66
67 /* data related to DMA transfers b/w i2s and DMAC */
68 struct i2s_dma_data play_dma_data;
69 struct i2s_dma_data capture_dma_data;
70 struct i2s_clk_config_data config;
71 int (*i2s_clk_cfg)(struct i2s_clk_config_data *config);
72};
73
74static inline void i2s_write_reg(void __iomem *io_base, int reg, u32 val)
75{
76 writel(val, io_base + reg);
77}
78
79static inline u32 i2s_read_reg(void __iomem *io_base, int reg)
80{
81 return readl(io_base + reg);
82}
83
84static inline void i2s_disable_channels(struct dw_i2s_dev *dev, u32 stream)
85{
86 u32 i = 0;
87
88 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
89 for (i = 0; i < 4; i++)
90 i2s_write_reg(dev->i2s_base, TER(i), 0);
91 } else {
92 for (i = 0; i < 4; i++)
93 i2s_write_reg(dev->i2s_base, RER(i), 0);
94 }
95}
96
97static inline void i2s_clear_irqs(struct dw_i2s_dev *dev, u32 stream)
98{
99 u32 i = 0;
100
101 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
102 for (i = 0; i < 4; i++)
103 i2s_write_reg(dev->i2s_base, TOR(i), 0);
104 } else {
105 for (i = 0; i < 4; i++)
106 i2s_write_reg(dev->i2s_base, ROR(i), 0);
107 }
108}
109
110static void i2s_start(struct dw_i2s_dev *dev,
111 struct snd_pcm_substream *substream)
112{
113
114 i2s_write_reg(dev->i2s_base, IER, 1);
115
116 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
117 i2s_write_reg(dev->i2s_base, ITER, 1);
118 else
119 i2s_write_reg(dev->i2s_base, IRER, 1);
120
121 i2s_write_reg(dev->i2s_base, CER, 1);
122}
123
124static void i2s_stop(struct dw_i2s_dev *dev,
125 struct snd_pcm_substream *substream)
126{
127 u32 i = 0, irq;
128
129 i2s_clear_irqs(dev, substream->stream);
130 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
131 i2s_write_reg(dev->i2s_base, ITER, 0);
132
133 for (i = 0; i < 4; i++) {
134 irq = i2s_read_reg(dev->i2s_base, IMR(i));
135 i2s_write_reg(dev->i2s_base, IMR(i), irq | 0x30);
136 }
137 } else {
138 i2s_write_reg(dev->i2s_base, IRER, 0);
139
140 for (i = 0; i < 4; i++) {
141 irq = i2s_read_reg(dev->i2s_base, IMR(i));
142 i2s_write_reg(dev->i2s_base, IMR(i), irq | 0x03);
143 }
144 }
145
146 if (!dev->active) {
147 i2s_write_reg(dev->i2s_base, CER, 0);
148 i2s_write_reg(dev->i2s_base, IER, 0);
149 }
150}
151
152static int dw_i2s_startup(struct snd_pcm_substream *substream,
153 struct snd_soc_dai *cpu_dai)
154{
155 struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
156 struct i2s_dma_data *dma_data = NULL;
157
158 if (!(dev->capability & DWC_I2S_RECORD) &&
159 (substream->stream == SNDRV_PCM_STREAM_CAPTURE))
160 return -EINVAL;
161
162 if (!(dev->capability & DWC_I2S_PLAY) &&
163 (substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
164 return -EINVAL;
165
166 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
167 dma_data = &dev->play_dma_data;
168 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
169 dma_data = &dev->capture_dma_data;
170
171 snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)dma_data);
172
173 return 0;
174}
175
176static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
177 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
178{
179 struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
180 struct i2s_clk_config_data *config = &dev->config;
181 u32 ccr, xfer_resolution, ch_reg, irq;
182 int ret;
183
184 switch (params_format(params)) {
185 case SNDRV_PCM_FORMAT_S16_LE:
186 config->data_width = 16;
187 ccr = 0x00;
188 xfer_resolution = 0x02;
189 break;
190
191 case SNDRV_PCM_FORMAT_S24_LE:
192 config->data_width = 24;
193 ccr = 0x08;
194 xfer_resolution = 0x04;
195 break;
196
197 case SNDRV_PCM_FORMAT_S32_LE:
198 config->data_width = 32;
199 ccr = 0x10;
200 xfer_resolution = 0x05;
201 break;
202
203 default:
204 dev_err(dev->dev, "designware-i2s: unsuppted PCM fmt");
205 return -EINVAL;
206 }
207
208 config->chan_nr = params_channels(params);
209
210 switch (config->chan_nr) {
211 case EIGHT_CHANNEL_SUPPORT:
212 ch_reg = 3;
213 case SIX_CHANNEL_SUPPORT:
214 ch_reg = 2;
215 case FOUR_CHANNEL_SUPPORT:
216 ch_reg = 1;
217 case TWO_CHANNEL_SUPPORT:
218 ch_reg = 0;
219 break;
220 default:
221 dev_err(dev->dev, "channel not supported\n");
222 }
223
224 i2s_disable_channels(dev, substream->stream);
225
226 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
227 i2s_write_reg(dev->i2s_base, TCR(ch_reg), xfer_resolution);
228 i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02);
229 irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
230 i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30);
231 i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
232 } else {
233 i2s_write_reg(dev->i2s_base, RCR(ch_reg), xfer_resolution);
234 i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07);
235 irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
236 i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03);
237 i2s_write_reg(dev->i2s_base, RER(ch_reg), 1);
238 }
239
240 i2s_write_reg(dev->i2s_base, CCR, ccr);
241
242 config->sample_rate = params_rate(params);
243
244 if (!dev->i2s_clk_cfg)
245 return -EINVAL;
246
247 ret = dev->i2s_clk_cfg(config);
248 if (ret < 0) {
249 dev_err(dev->dev, "runtime audio clk config fail\n");
250 return ret;
251 }
252
253 return 0;
254}
255
256static void dw_i2s_shutdown(struct snd_pcm_substream *substream,
257 struct snd_soc_dai *dai)
258{
259 snd_soc_dai_set_dma_data(dai, substream, NULL);
260}
261
262static int dw_i2s_trigger(struct snd_pcm_substream *substream,
263 int cmd, struct snd_soc_dai *dai)
264{
265 struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
266 int ret = 0;
267
268 switch (cmd) {
269 case SNDRV_PCM_TRIGGER_START:
270 case SNDRV_PCM_TRIGGER_RESUME:
271 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
272 dev->active++;
273 i2s_start(dev, substream);
274 break;
275
276 case SNDRV_PCM_TRIGGER_STOP:
277 case SNDRV_PCM_TRIGGER_SUSPEND:
278 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
279 dev->active--;
280 i2s_stop(dev, substream);
281 break;
282 default:
283 ret = -EINVAL;
284 break;
285 }
286 return ret;
287}
288
289static struct snd_soc_dai_ops dw_i2s_dai_ops = {
290 .startup = dw_i2s_startup,
291 .shutdown = dw_i2s_shutdown,
292 .hw_params = dw_i2s_hw_params,
293 .trigger = dw_i2s_trigger,
294};
295
296#ifdef CONFIG_PM
297
298static int dw_i2s_suspend(struct snd_soc_dai *dai)
299{
300 struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
301
302 clk_disable(dev->clk);
303 return 0;
304}
305
306static int dw_i2s_resume(struct snd_soc_dai *dai)
307{
308 struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
309
310 clk_enable(dev->clk);
311 return 0;
312}
313
314#else
315#define dw_i2s_suspend NULL
316#define dw_i2s_resume NULL
317#endif
318
319static int dw_i2s_probe(struct platform_device *pdev)
320{
321 const struct i2s_platform_data *pdata = pdev->dev.platform_data;
322 struct dw_i2s_dev *dev;
323 struct resource *res;
324 int ret;
325 unsigned int cap;
326 struct snd_soc_dai_driver *dw_i2s_dai;
327
328 if (!pdata) {
329 dev_err(&pdev->dev, "Invalid platform data\n");
330 return -EINVAL;
331 }
332
333 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
334 if (!res) {
335 dev_err(&pdev->dev, "no i2s resource defined\n");
336 return -ENODEV;
337 }
338
339 if (!devm_request_mem_region(&pdev->dev, res->start,
340 resource_size(res), pdev->name)) {
341 dev_err(&pdev->dev, "i2s region already claimed\n");
342 return -EBUSY;
343 }
344
345 dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
346 if (!dev) {
347 dev_warn(&pdev->dev, "kzalloc fail\n");
348 return -ENOMEM;
349 }
350
351 dev->i2s_base = devm_ioremap(&pdev->dev, res->start,
352 resource_size(res));
353 if (!dev->i2s_base) {
354 dev_err(&pdev->dev, "ioremap fail for i2s_region\n");
355 return -ENOMEM;
356 }
357
358 cap = pdata->cap;
359 dev->capability = cap;
360 dev->i2s_clk_cfg = pdata->i2s_clk_cfg;
361
362 /* Set DMA slaves info */
363
364 dev->play_dma_data.data = pdata->play_dma_data;
365 dev->capture_dma_data.data = pdata->capture_dma_data;
366 dev->play_dma_data.addr = res->start + I2S_TXDMA;
367 dev->capture_dma_data.addr = res->start + I2S_RXDMA;
368 dev->play_dma_data.max_burst = 16;
369 dev->capture_dma_data.max_burst = 16;
370 dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
371 dev->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
372 dev->play_dma_data.filter = pdata->filter;
373 dev->capture_dma_data.filter = pdata->filter;
374
375 dev->clk = clk_get(&pdev->dev, NULL);
376 if (IS_ERR(dev->clk))
377 return PTR_ERR(dev->clk);
378
379 ret = clk_enable(dev->clk);
380 if (ret < 0)
381 goto err_clk_put;
382
383 dw_i2s_dai = devm_kzalloc(&pdev->dev, sizeof(*dw_i2s_dai), GFP_KERNEL);
384 if (!dw_i2s_dai) {
385 dev_err(&pdev->dev, "mem allocation failed for dai driver\n");
386 ret = -ENOMEM;
387 goto err_clk_disable;
388 }
389
390 if (cap & DWC_I2S_PLAY) {
391 dev_dbg(&pdev->dev, " SPEAr: play supported\n");
392 dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM;
393 dw_i2s_dai->playback.channels_max = pdata->channel;
394 dw_i2s_dai->playback.formats = pdata->snd_fmts;
395 dw_i2s_dai->playback.rates = pdata->snd_rates;
396 }
397
398 if (cap & DWC_I2S_RECORD) {
399 dev_dbg(&pdev->dev, "SPEAr: record supported\n");
400 dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM;
401 dw_i2s_dai->capture.channels_max = pdata->channel;
402 dw_i2s_dai->capture.formats = pdata->snd_fmts;
403 dw_i2s_dai->capture.rates = pdata->snd_rates;
404 }
405
406 dw_i2s_dai->ops = &dw_i2s_dai_ops;
407 dw_i2s_dai->suspend = dw_i2s_suspend;
408 dw_i2s_dai->resume = dw_i2s_resume;
409
410 dev->dev = &pdev->dev;
411 dev_set_drvdata(&pdev->dev, dev);
412 ret = snd_soc_register_dai(&pdev->dev, dw_i2s_dai);
413 if (ret != 0) {
414 dev_err(&pdev->dev, "not able to register dai\n");
415 goto err_set_drvdata;
416 }
417
418 return 0;
419
420err_set_drvdata:
421 dev_set_drvdata(&pdev->dev, NULL);
422err_clk_disable:
423 clk_disable(dev->clk);
424err_clk_put:
425 clk_put(dev->clk);
426 return ret;
427}
428
429static int dw_i2s_remove(struct platform_device *pdev)
430{
431 struct dw_i2s_dev *dev = dev_get_drvdata(&pdev->dev);
432
433 snd_soc_unregister_dai(&pdev->dev);
434 dev_set_drvdata(&pdev->dev, NULL);
435
436 clk_put(dev->clk);
437
438 return 0;
439}
440
441static struct platform_driver dw_i2s_driver = {
442 .probe = dw_i2s_probe,
443 .remove = dw_i2s_remove,
444 .driver = {
445 .name = "designware-i2s",
446 .owner = THIS_MODULE,
447 },
448};
449
450module_platform_driver(dw_i2s_driver);
451
452MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>");
453MODULE_DESCRIPTION("DESIGNWARE I2S SoC Interface");
454MODULE_LICENSE("GPL");
455MODULE_ALIAS("platform:designware_i2s");
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c
index 162dbb74f4c..4eea98b42bc 100644
--- a/sound/soc/ep93xx/ep93xx-pcm.c
+++ b/sound/soc/ep93xx/ep93xx-pcm.c
@@ -136,7 +136,7 @@ static struct snd_pcm_ops ep93xx_pcm_ops = {
136 .hw_params = ep93xx_pcm_hw_params, 136 .hw_params = ep93xx_pcm_hw_params,
137 .hw_free = ep93xx_pcm_hw_free, 137 .hw_free = ep93xx_pcm_hw_free,
138 .trigger = snd_dmaengine_pcm_trigger, 138 .trigger = snd_dmaengine_pcm_trigger,
139 .pointer = snd_dmaengine_pcm_pointer, 139 .pointer = snd_dmaengine_pcm_pointer_no_residue,
140 .mmap = ep93xx_pcm_mmap, 140 .mmap = ep93xx_pcm_mmap,
141}; 141};
142 142
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c
index 080327414c6..e7c800ebbd7 100644
--- a/sound/soc/fsl/imx-audmux.c
+++ b/sound/soc/fsl/imx-audmux.c
@@ -156,7 +156,7 @@ static void __init audmux_debugfs_init(void)
156 return; 156 return;
157 } 157 }
158 158
159 for (i = 0; i < MX31_AUDMUX_PORT6_SSI_PINS_6 + 1; i++) { 159 for (i = 0; i < MX31_AUDMUX_PORT7_SSI_PINS_7 + 1; i++) {
160 snprintf(buf, sizeof(buf), "ssi%d", i); 160 snprintf(buf, sizeof(buf), "ssi%d", i);
161 if (!debugfs_create_file(buf, 0444, audmux_debugfs_root, 161 if (!debugfs_create_file(buf, 0444, audmux_debugfs_root,
162 (void *)i, &audmux_debugfs_fops)) 162 (void *)i, &audmux_debugfs_fops))
diff --git a/sound/soc/fsl/imx-audmux.h b/sound/soc/fsl/imx-audmux.h
index 04ebbab8d7b..b8ff44b9daf 100644
--- a/sound/soc/fsl/imx-audmux.h
+++ b/sound/soc/fsl/imx-audmux.h
@@ -14,6 +14,7 @@
14#define MX31_AUDMUX_PORT4_SSI_PINS_4 3 14#define MX31_AUDMUX_PORT4_SSI_PINS_4 3
15#define MX31_AUDMUX_PORT5_SSI_PINS_5 4 15#define MX31_AUDMUX_PORT5_SSI_PINS_5 4
16#define MX31_AUDMUX_PORT6_SSI_PINS_6 5 16#define MX31_AUDMUX_PORT6_SSI_PINS_6 5
17#define MX31_AUDMUX_PORT7_SSI_PINS_7 6
17 18
18#define MX51_AUDMUX_PORT1_SSI0 0 19#define MX51_AUDMUX_PORT1_SSI0 0
19#define MX51_AUDMUX_PORT2_SSI1 1 20#define MX51_AUDMUX_PORT2_SSI1 1
diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c
index f59c3494366..549b31fdc9d 100644
--- a/sound/soc/fsl/imx-mc13783.c
+++ b/sound/soc/fsl/imx-mc13783.c
@@ -111,22 +111,39 @@ static int __devinit imx_mc13783_probe(struct platform_device *pdev)
111 return ret; 111 return ret;
112 } 112 }
113 113
114 imx_audmux_v2_configure_port(MX31_AUDMUX_PORT4_SSI_PINS_4, 114 if (machine_is_mx31_3ds()) {
115 IMX_AUDMUX_V2_PTCR_SYN, 115 imx_audmux_v2_configure_port(MX31_AUDMUX_PORT4_SSI_PINS_4,
116 IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0) | 116 IMX_AUDMUX_V2_PTCR_SYN,
117 IMX_AUDMUX_V2_PDCR_MODE(1) | 117 IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0) |
118 IMX_AUDMUX_V2_PDCR_INMMASK(0xfc)); 118 IMX_AUDMUX_V2_PDCR_MODE(1) |
119 imx_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, 119 IMX_AUDMUX_V2_PDCR_INMMASK(0xfc));
120 IMX_AUDMUX_V2_PTCR_SYN | 120 imx_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0,
121 IMX_AUDMUX_V2_PTCR_TFSDIR | 121 IMX_AUDMUX_V2_PTCR_SYN |
122 IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT4_SSI_PINS_4) | 122 IMX_AUDMUX_V2_PTCR_TFSDIR |
123 IMX_AUDMUX_V2_PTCR_TCLKDIR | 123 IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT4_SSI_PINS_4) |
124 IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT4_SSI_PINS_4) | 124 IMX_AUDMUX_V2_PTCR_TCLKDIR |
125 IMX_AUDMUX_V2_PTCR_RFSDIR | 125 IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT4_SSI_PINS_4) |
126 IMX_AUDMUX_V2_PTCR_RFSEL(MX31_AUDMUX_PORT4_SSI_PINS_4) | 126 IMX_AUDMUX_V2_PTCR_RFSDIR |
127 IMX_AUDMUX_V2_PTCR_RCLKDIR | 127 IMX_AUDMUX_V2_PTCR_RFSEL(MX31_AUDMUX_PORT4_SSI_PINS_4) |
128 IMX_AUDMUX_V2_PTCR_RCSEL(MX31_AUDMUX_PORT4_SSI_PINS_4), 128 IMX_AUDMUX_V2_PTCR_RCLKDIR |
129 IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT4_SSI_PINS_4)); 129 IMX_AUDMUX_V2_PTCR_RCSEL(MX31_AUDMUX_PORT4_SSI_PINS_4),
130 IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT4_SSI_PINS_4));
131 } else if (machine_is_mx27_3ds()) {
132 imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
133 IMX_AUDMUX_V1_PCR_SYN |
134 IMX_AUDMUX_V1_PCR_TFSDIR |
135 IMX_AUDMUX_V1_PCR_TCLKDIR |
136 IMX_AUDMUX_V1_PCR_RFSDIR |
137 IMX_AUDMUX_V1_PCR_RCLKDIR |
138 IMX_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) |
139 IMX_AUDMUX_V1_PCR_RFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) |
140 IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4)
141 );
142 imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR3_SSI_PINS_4,
143 IMX_AUDMUX_V1_PCR_SYN |
144 IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0)
145 );
146 }
130 147
131 return ret; 148 return ret;
132} 149}
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
index f3c0a5ef35c..48f9d886f02 100644
--- a/sound/soc/fsl/imx-pcm-dma.c
+++ b/sound/soc/fsl/imx-pcm-dma.c
@@ -141,7 +141,7 @@ static struct snd_pcm_ops imx_pcm_ops = {
141 .ioctl = snd_pcm_lib_ioctl, 141 .ioctl = snd_pcm_lib_ioctl,
142 .hw_params = snd_imx_pcm_hw_params, 142 .hw_params = snd_imx_pcm_hw_params,
143 .trigger = snd_dmaengine_pcm_trigger, 143 .trigger = snd_dmaengine_pcm_trigger,
144 .pointer = snd_dmaengine_pcm_pointer, 144 .pointer = snd_dmaengine_pcm_pointer_no_residue,
145 .mmap = snd_imx_pcm_mmap, 145 .mmap = snd_imx_pcm_mmap,
146}; 146};
147 147
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c
index 3a729caeb8c..fb21b17f17f 100644
--- a/sound/soc/fsl/imx-sgtl5000.c
+++ b/sound/soc/fsl/imx-sgtl5000.c
@@ -95,8 +95,7 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev)
95 return ret; 95 return ret;
96 } 96 }
97 imx_audmux_v2_configure_port(ext_port, 97 imx_audmux_v2_configure_port(ext_port,
98 IMX_AUDMUX_V2_PTCR_SYN | 98 IMX_AUDMUX_V2_PTCR_SYN,
99 IMX_AUDMUX_V2_PTCR_TCSEL(int_port),
100 IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)); 99 IMX_AUDMUX_V2_PDCR_RXDSEL(int_port));
101 if (ret) { 100 if (ret) {
102 dev_err(&pdev->dev, "audmux external port setup failed\n"); 101 dev_err(&pdev->dev, "audmux external port setup failed\n");
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c
index 373dec90579..f82d766cbf9 100644
--- a/sound/soc/mxs/mxs-pcm.c
+++ b/sound/soc/mxs/mxs-pcm.c
@@ -141,7 +141,7 @@ static struct snd_pcm_ops mxs_pcm_ops = {
141 .ioctl = snd_pcm_lib_ioctl, 141 .ioctl = snd_pcm_lib_ioctl,
142 .hw_params = snd_mxs_pcm_hw_params, 142 .hw_params = snd_mxs_pcm_hw_params,
143 .trigger = snd_dmaengine_pcm_trigger, 143 .trigger = snd_dmaengine_pcm_trigger,
144 .pointer = snd_dmaengine_pcm_pointer, 144 .pointer = snd_dmaengine_pcm_pointer_no_residue,
145 .mmap = snd_mxs_pcm_mmap, 145 .mmap = snd_mxs_pcm_mmap,
146}; 146};
147 147
diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c
index 3e6e8764b2e..215113b05f7 100644
--- a/sound/soc/mxs/mxs-sgtl5000.c
+++ b/sound/soc/mxs/mxs-sgtl5000.c
@@ -133,7 +133,7 @@ static int __devinit mxs_sgtl5000_probe_dt(struct platform_device *pdev)
133 mxs_sgtl5000_dai[i].codec_name = NULL; 133 mxs_sgtl5000_dai[i].codec_name = NULL;
134 mxs_sgtl5000_dai[i].codec_of_node = codec_np; 134 mxs_sgtl5000_dai[i].codec_of_node = codec_np;
135 mxs_sgtl5000_dai[i].cpu_dai_name = NULL; 135 mxs_sgtl5000_dai[i].cpu_dai_name = NULL;
136 mxs_sgtl5000_dai[i].cpu_dai_of_node = saif_np[i]; 136 mxs_sgtl5000_dai[i].cpu_of_node = saif_np[i];
137 mxs_sgtl5000_dai[i].platform_name = NULL; 137 mxs_sgtl5000_dai[i].platform_name = NULL;
138 mxs_sgtl5000_dai[i].platform_of_node = saif_np[i]; 138 mxs_sgtl5000_dai[i].platform_of_node = saif_np[i];
139 } 139 }
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index a0f7d3cfa47..4d2e46fae77 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -8,6 +8,15 @@ config SND_PXA2XX_SOC
8 the PXA2xx AC97, I2S or SSP interface. You will also need 8 the PXA2xx AC97, I2S or SSP interface. You will also need
9 to select the audio interfaces to support below. 9 to select the audio interfaces to support below.
10 10
11config SND_MMP_SOC
12 bool "Soc Audio for Marvell MMP chips"
13 depends on ARCH_MMP
14 select SND_SOC_DMAENGINE_PCM
15 select SND_ARM
16 help
17 Say Y if you want to add support for codecs attached to
18 the MMP SSPA interface.
19
11config SND_PXA2XX_AC97 20config SND_PXA2XX_AC97
12 tristate 21 tristate
13 select SND_AC97_CODEC 22 select SND_AC97_CODEC
@@ -26,6 +35,9 @@ config SND_PXA_SOC_SSP
26 tristate 35 tristate
27 select PXA_SSP 36 select PXA_SSP
28 37
38config SND_MMP_SOC_SSPA
39 tristate
40
29config SND_PXA2XX_SOC_CORGI 41config SND_PXA2XX_SOC_CORGI
30 tristate "SoC Audio support for Sharp Zaurus SL-C7x0" 42 tristate "SoC Audio support for Sharp Zaurus SL-C7x0"
31 depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx 43 depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx
@@ -138,6 +150,26 @@ config SND_SOC_TAVOREVB3
138 Say Y if you want to add support for SoC audio on the 150 Say Y if you want to add support for SoC audio on the
139 Marvell Saarb reference platform. 151 Marvell Saarb reference platform.
140 152
153config SND_PXA910_SOC
154 tristate "SoC Audio for Marvell PXA910 chip"
155 depends on ARCH_MMP && SND
156 select SND_PCM
157 help
158 Say Y if you want to add support for SoC audio on the
159 Marvell PXA910 reference platform.
160
161config SND_SOC_TTC_DKB
162 bool "SoC Audio support for TTC DKB"
163 depends on SND_PXA910_SOC && MACH_TTC_DKB
164 select PXA_SSP
165 select SND_PXA_SOC_SSP
166 select SND_MMP_SOC
167 select MFD_88PM860X
168 select SND_SOC_88PM860X
169 help
170 Say Y if you want to add support for SoC audio on TTC DKB
171
172
141config SND_SOC_ZYLONITE 173config SND_SOC_ZYLONITE
142 tristate "SoC Audio support for Marvell Zylonite" 174 tristate "SoC Audio support for Marvell Zylonite"
143 depends on SND_PXA2XX_SOC && MACH_ZYLONITE 175 depends on SND_PXA2XX_SOC && MACH_ZYLONITE
@@ -194,3 +226,13 @@ config SND_PXA2XX_SOC_IMOTE2
194 help 226 help
195 Say Y if you want to add support for SoC audio on the 227 Say Y if you want to add support for SoC audio on the
196 IMote 2. 228 IMote 2.
229
230config SND_MMP_SOC_BROWNSTONE
231 tristate "SoC Audio support for Marvell Brownstone"
232 depends on SND_MMP_SOC && MACH_BROWNSTONE
233 select SND_MMP_SOC_SSPA
234 select MFD_WM8994
235 select SND_SOC_WM8994
236 help
237 Say Y if you want to add support for SoC audio on the
238 Marvell Brownstone reference platform.
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index af357623be9..d8a265d2d5d 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -3,11 +3,15 @@ snd-soc-pxa2xx-objs := pxa2xx-pcm.o
3snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o 3snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o
4snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o 4snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o
5snd-soc-pxa-ssp-objs := pxa-ssp.o 5snd-soc-pxa-ssp-objs := pxa-ssp.o
6snd-soc-mmp-objs := mmp-pcm.o
7snd-soc-mmp-sspa-objs := mmp-sspa.o
6 8
7obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o 9obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o
8obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o 10obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o
9obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o 11obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o
10obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o 12obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o
13obj-$(CONFIG_SND_MMP_SOC) += snd-soc-mmp.o
14obj-$(CONFIG_SND_MMP_SOC_SSPA) += snd-soc-mmp-sspa.o
11 15
12# PXA Machine Support 16# PXA Machine Support
13snd-soc-corgi-objs := corgi.o 17snd-soc-corgi-objs := corgi.o
@@ -28,6 +32,8 @@ snd-soc-mioa701-objs := mioa701_wm9713.o
28snd-soc-z2-objs := z2.o 32snd-soc-z2-objs := z2.o
29snd-soc-imote2-objs := imote2.o 33snd-soc-imote2-objs := imote2.o
30snd-soc-raumfeld-objs := raumfeld.o 34snd-soc-raumfeld-objs := raumfeld.o
35snd-soc-brownstone-objs := brownstone.o
36snd-soc-ttc-dkb-objs := ttc-dkb.o
31 37
32obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o 38obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
33obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o 39obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
@@ -47,3 +53,5 @@ obj-$(CONFIG_SND_SOC_TAVOREVB3) += snd-soc-tavorevb3.o
47obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o 53obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
48obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o 54obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o
49obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o 55obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o
56obj-$(CONFIG_SND_MMP_SOC_BROWNSTONE) += snd-soc-brownstone.o
57obj-$(CONFIG_SND_SOC_TTC_DKB) += snd-soc-ttc-dkb.o
diff --git a/sound/soc/pxa/brownstone.c b/sound/soc/pxa/brownstone.c
new file mode 100644
index 00000000000..5e666e03d33
--- /dev/null
+++ b/sound/soc/pxa/brownstone.c
@@ -0,0 +1,174 @@
1/*
2 * linux/sound/soc/pxa/brownstone.c
3 *
4 * Copyright (C) 2011 Marvell International Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 */
12
13#include <linux/module.h>
14#include <sound/core.h>
15#include <sound/pcm.h>
16#include <sound/soc.h>
17#include <sound/jack.h>
18
19#include "../codecs/wm8994.h"
20#include "mmp-sspa.h"
21
22static const struct snd_kcontrol_new brownstone_dapm_control[] = {
23 SOC_DAPM_PIN_SWITCH("Ext Spk"),
24};
25
26static const struct snd_soc_dapm_widget brownstone_dapm_widgets[] = {
27 SND_SOC_DAPM_SPK("Ext Spk", NULL),
28 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
29 SND_SOC_DAPM_MIC("Headset Mic", NULL),
30 SND_SOC_DAPM_MIC("Main Mic", NULL),
31};
32
33static const struct snd_soc_dapm_route brownstone_audio_map[] = {
34 {"Ext Spk", NULL, "SPKOUTLP"},
35 {"Ext Spk", NULL, "SPKOUTLN"},
36 {"Ext Spk", NULL, "SPKOUTRP"},
37 {"Ext Spk", NULL, "SPKOUTRN"},
38
39 {"Headset Stereophone", NULL, "HPOUT1L"},
40 {"Headset Stereophone", NULL, "HPOUT1R"},
41
42 {"IN1RN", NULL, "Headset Mic"},
43
44 {"DMIC1DAT", NULL, "MICBIAS1"},
45 {"MICBIAS1", NULL, "Main Mic"},
46};
47
48static int brownstone_wm8994_init(struct snd_soc_pcm_runtime *rtd)
49{
50 struct snd_soc_codec *codec = rtd->codec;
51 struct snd_soc_dapm_context *dapm = &codec->dapm;
52
53 snd_soc_dapm_enable_pin(dapm, "Ext Spk");
54 snd_soc_dapm_enable_pin(dapm, "Headset Stereophone");
55 snd_soc_dapm_enable_pin(dapm, "Headset Mic");
56 snd_soc_dapm_enable_pin(dapm, "Main Mic");
57
58 /* set endpoints to not connected */
59 snd_soc_dapm_nc_pin(dapm, "HPOUT2P");
60 snd_soc_dapm_nc_pin(dapm, "HPOUT2N");
61 snd_soc_dapm_nc_pin(dapm, "LINEOUT1N");
62 snd_soc_dapm_nc_pin(dapm, "LINEOUT1P");
63 snd_soc_dapm_nc_pin(dapm, "LINEOUT2N");
64 snd_soc_dapm_nc_pin(dapm, "LINEOUT2P");
65 snd_soc_dapm_nc_pin(dapm, "IN1LN");
66 snd_soc_dapm_nc_pin(dapm, "IN1LP");
67 snd_soc_dapm_nc_pin(dapm, "IN1RP");
68 snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN");
69 snd_soc_dapm_nc_pin(dapm, "IN2RN");
70 snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP");
71 snd_soc_dapm_nc_pin(dapm, "IN2LN");
72
73 snd_soc_dapm_sync(dapm);
74
75 return 0;
76}
77
78static int brownstone_wm8994_hw_params(struct snd_pcm_substream *substream,
79 struct snd_pcm_hw_params *params)
80{
81 struct snd_soc_pcm_runtime *rtd = substream->private_data;
82 struct snd_soc_dai *codec_dai = rtd->codec_dai;
83 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
84 int freq_out, sspa_mclk, sysclk;
85 int sspa_div;
86
87 if (params_rate(params) > 11025) {
88 freq_out = params_rate(params) * 512;
89 sysclk = params_rate(params) * 256;
90 sspa_mclk = params_rate(params) * 64;
91 } else {
92 freq_out = params_rate(params) * 1024;
93 sysclk = params_rate(params) * 512;
94 sspa_mclk = params_rate(params) * 64;
95 }
96 sspa_div = freq_out;
97 do_div(sspa_div, sspa_mclk);
98
99 snd_soc_dai_set_sysclk(cpu_dai, MMP_SSPA_CLK_AUDIO, freq_out, 0);
100 snd_soc_dai_set_pll(cpu_dai, MMP_SYSCLK, 0, freq_out, sysclk);
101 snd_soc_dai_set_pll(cpu_dai, MMP_SSPA_CLK, 0, freq_out, sspa_mclk);
102
103 /* set wm8994 sysclk */
104 snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK1, sysclk, 0);
105
106 return 0;
107}
108
109/* machine stream operations */
110static struct snd_soc_ops brownstone_ops = {
111 .hw_params = brownstone_wm8994_hw_params,
112};
113
114static struct snd_soc_dai_link brownstone_wm8994_dai[] = {
115{
116 .name = "WM8994",
117 .stream_name = "WM8994 HiFi",
118 .cpu_dai_name = "mmp-sspa-dai.0",
119 .codec_dai_name = "wm8994-aif1",
120 .platform_name = "mmp-pcm-audio",
121 .codec_name = "wm8994-codec",
122 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
123 SND_SOC_DAIFMT_CBS_CFS,
124 .ops = &brownstone_ops,
125 .init = brownstone_wm8994_init,
126},
127};
128
129/* audio machine driver */
130static struct snd_soc_card brownstone = {
131 .name = "brownstone",
132 .dai_link = brownstone_wm8994_dai,
133 .num_links = ARRAY_SIZE(brownstone_wm8994_dai),
134
135 .controls = brownstone_dapm_control,
136 .num_controls = ARRAY_SIZE(brownstone_dapm_control),
137 .dapm_widgets = brownstone_dapm_widgets,
138 .num_dapm_widgets = ARRAY_SIZE(brownstone_dapm_widgets),
139 .dapm_routes = brownstone_audio_map,
140 .num_dapm_routes = ARRAY_SIZE(brownstone_audio_map),
141};
142
143static int __devinit brownstone_probe(struct platform_device *pdev)
144{
145 int ret;
146
147 brownstone.dev = &pdev->dev;
148 ret = snd_soc_register_card(&brownstone);
149 if (ret)
150 dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
151 ret);
152 return ret;
153}
154
155static int __devexit brownstone_remove(struct platform_device *pdev)
156{
157 snd_soc_unregister_card(&brownstone);
158 return 0;
159}
160
161static struct platform_driver mmp_driver = {
162 .driver = {
163 .name = "brownstone-audio",
164 .owner = THIS_MODULE,
165 },
166 .probe = brownstone_probe,
167 .remove = __devexit_p(brownstone_remove),
168};
169
170module_platform_driver(mmp_driver);
171
172MODULE_AUTHOR("Leo Yan <leoy@marvell.com>");
173MODULE_DESCRIPTION("ALSA SoC Brownstone");
174MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c
new file mode 100644
index 00000000000..73ac5463c9e
--- /dev/null
+++ b/sound/soc/pxa/mmp-pcm.c
@@ -0,0 +1,297 @@
1/*
2 * linux/sound/soc/pxa/mmp-pcm.c
3 *
4 * Copyright (C) 2011 Marvell International Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 */
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/platform_device.h>
15#include <linux/slab.h>
16#include <linux/dma-mapping.h>
17#include <linux/dmaengine.h>
18#include <linux/platform_data/mmp_audio.h>
19#include <sound/pxa2xx-lib.h>
20#include <sound/core.h>
21#include <sound/pcm.h>
22#include <sound/pcm_params.h>
23#include <sound/soc.h>
24#include <mach/sram.h>
25#include <sound/dmaengine_pcm.h>
26
27struct mmp_dma_data {
28 int ssp_id;
29 struct resource *dma_res;
30};
31
32#define MMP_PCM_INFO (SNDRV_PCM_INFO_MMAP | \
33 SNDRV_PCM_INFO_MMAP_VALID | \
34 SNDRV_PCM_INFO_INTERLEAVED | \
35 SNDRV_PCM_INFO_PAUSE | \
36 SNDRV_PCM_INFO_RESUME)
37
38#define MMP_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
39 SNDRV_PCM_FMTBIT_S24_LE | \
40 SNDRV_PCM_FMTBIT_S32_LE)
41
42static struct snd_pcm_hardware mmp_pcm_hardware[] = {
43 {
44 .info = MMP_PCM_INFO,
45 .formats = MMP_PCM_FORMATS,
46 .period_bytes_min = 1024,
47 .period_bytes_max = 2048,
48 .periods_min = 2,
49 .periods_max = 32,
50 .buffer_bytes_max = 4096,
51 .fifo_size = 32,
52 },
53 {
54 .info = MMP_PCM_INFO,
55 .formats = MMP_PCM_FORMATS,
56 .period_bytes_min = 1024,
57 .period_bytes_max = 2048,
58 .periods_min = 2,
59 .periods_max = 32,
60 .buffer_bytes_max = 4096,
61 .fifo_size = 32,
62 },
63};
64
65static int mmp_pcm_hw_params(struct snd_pcm_substream *substream,
66 struct snd_pcm_hw_params *params)
67{
68 struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
69 struct snd_soc_pcm_runtime *rtd = substream->private_data;
70 struct pxa2xx_pcm_dma_params *dma_params;
71 struct dma_slave_config slave_config;
72 int ret;
73
74 dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
75 if (!dma_params)
76 return 0;
77
78 ret = snd_hwparams_to_dma_slave_config(substream, params, &slave_config);
79 if (ret)
80 return ret;
81
82 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
83 slave_config.dst_addr = dma_params->dev_addr;
84 slave_config.dst_maxburst = 4;
85 } else {
86 slave_config.src_addr = dma_params->dev_addr;
87 slave_config.src_maxburst = 4;
88 }
89
90 ret = dmaengine_slave_config(chan, &slave_config);
91 if (ret)
92 return ret;
93
94 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
95
96 return 0;
97}
98
99static bool filter(struct dma_chan *chan, void *param)
100{
101 struct mmp_dma_data *dma_data = param;
102 bool found = false;
103 char *devname;
104
105 devname = kasprintf(GFP_KERNEL, "%s.%d", dma_data->dma_res->name,
106 dma_data->ssp_id);
107 if ((strcmp(dev_name(chan->device->dev), devname) == 0) &&
108 (chan->chan_id == dma_data->dma_res->start)) {
109 found = true;
110 }
111
112 kfree(devname);
113 return found;
114}
115
116static int mmp_pcm_open(struct snd_pcm_substream *substream)
117{
118 struct snd_soc_pcm_runtime *rtd = substream->private_data;
119 struct platform_device *pdev = to_platform_device(rtd->platform->dev);
120 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
121 struct mmp_dma_data *dma_data;
122 struct resource *r;
123 int ret;
124
125 r = platform_get_resource(pdev, IORESOURCE_DMA, substream->stream);
126 if (!r)
127 return -EBUSY;
128
129 snd_soc_set_runtime_hwparams(substream,
130 &mmp_pcm_hardware[substream->stream]);
131 dma_data = devm_kzalloc(&pdev->dev,
132 sizeof(struct mmp_dma_data), GFP_KERNEL);
133 if (dma_data == NULL)
134 return -ENOMEM;
135
136 dma_data->dma_res = r;
137 dma_data->ssp_id = cpu_dai->id;
138
139 ret = snd_dmaengine_pcm_open(substream, filter, dma_data);
140 if (ret) {
141 devm_kfree(&pdev->dev, dma_data);
142 return ret;
143 }
144
145 snd_dmaengine_pcm_set_data(substream, dma_data);
146 return 0;
147}
148
149static int mmp_pcm_close(struct snd_pcm_substream *substream)
150{
151 struct mmp_dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
152 struct snd_soc_pcm_runtime *rtd = substream->private_data;
153 struct platform_device *pdev = to_platform_device(rtd->platform->dev);
154
155 snd_dmaengine_pcm_close(substream);
156 devm_kfree(&pdev->dev, dma_data);
157 return 0;
158}
159
160static int mmp_pcm_mmap(struct snd_pcm_substream *substream,
161 struct vm_area_struct *vma)
162{
163 struct snd_pcm_runtime *runtime = substream->runtime;
164 unsigned long off = vma->vm_pgoff;
165
166 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
167 return remap_pfn_range(vma, vma->vm_start,
168 __phys_to_pfn(runtime->dma_addr) + off,
169 vma->vm_end - vma->vm_start, vma->vm_page_prot);
170}
171
172struct snd_pcm_ops mmp_pcm_ops = {
173 .open = mmp_pcm_open,
174 .close = mmp_pcm_close,
175 .ioctl = snd_pcm_lib_ioctl,
176 .hw_params = mmp_pcm_hw_params,
177 .trigger = snd_dmaengine_pcm_trigger,
178 .pointer = snd_dmaengine_pcm_pointer,
179 .mmap = mmp_pcm_mmap,
180};
181
182static void mmp_pcm_free_dma_buffers(struct snd_pcm *pcm)
183{
184 struct snd_pcm_substream *substream;
185 struct snd_dma_buffer *buf;
186 int stream;
187 struct gen_pool *gpool;
188
189 gpool = sram_get_gpool("asram");
190 if (!gpool)
191 return;
192
193 for (stream = 0; stream < 2; stream++) {
194 size_t size = mmp_pcm_hardware[stream].buffer_bytes_max;
195
196 substream = pcm->streams[stream].substream;
197 if (!substream)
198 continue;
199
200 buf = &substream->dma_buffer;
201 if (!buf->area)
202 continue;
203 gen_pool_free(gpool, (unsigned long)buf->area, size);
204 buf->area = NULL;
205 }
206
207 return;
208}
209
210static int mmp_pcm_preallocate_dma_buffer(struct snd_pcm_substream *substream,
211 int stream)
212{
213 struct snd_dma_buffer *buf = &substream->dma_buffer;
214 size_t size = mmp_pcm_hardware[stream].buffer_bytes_max;
215 struct gen_pool *gpool;
216
217 buf->dev.type = SNDRV_DMA_TYPE_DEV;
218 buf->dev.dev = substream->pcm->card->dev;
219 buf->private_data = NULL;
220
221 gpool = sram_get_gpool("asram");
222 if (!gpool)
223 return -ENOMEM;
224
225 buf->area = (unsigned char *)gen_pool_alloc(gpool, size);
226 if (!buf->area)
227 return -ENOMEM;
228 buf->addr = gen_pool_virt_to_phys(gpool, (unsigned long)buf->area);
229 buf->bytes = size;
230 return 0;
231}
232
233int mmp_pcm_new(struct snd_soc_pcm_runtime *rtd)
234{
235 struct snd_pcm_substream *substream;
236 struct snd_pcm *pcm = rtd->pcm;
237 int ret = 0, stream;
238
239 for (stream = 0; stream < 2; stream++) {
240 substream = pcm->streams[stream].substream;
241
242 ret = mmp_pcm_preallocate_dma_buffer(substream, stream);
243 if (ret)
244 goto err;
245 }
246
247 return 0;
248
249err:
250 mmp_pcm_free_dma_buffers(pcm);
251 return ret;
252}
253
254struct snd_soc_platform_driver mmp_soc_platform = {
255 .ops = &mmp_pcm_ops,
256 .pcm_new = mmp_pcm_new,
257 .pcm_free = mmp_pcm_free_dma_buffers,
258};
259
260static __devinit int mmp_pcm_probe(struct platform_device *pdev)
261{
262 struct mmp_audio_platdata *pdata = pdev->dev.platform_data;
263
264 if (pdata) {
265 mmp_pcm_hardware[SNDRV_PCM_STREAM_PLAYBACK].buffer_bytes_max =
266 pdata->buffer_max_playback;
267 mmp_pcm_hardware[SNDRV_PCM_STREAM_PLAYBACK].period_bytes_max =
268 pdata->period_max_playback;
269 mmp_pcm_hardware[SNDRV_PCM_STREAM_CAPTURE].buffer_bytes_max =
270 pdata->buffer_max_capture;
271 mmp_pcm_hardware[SNDRV_PCM_STREAM_CAPTURE].period_bytes_max =
272 pdata->period_max_capture;
273 }
274 return snd_soc_register_platform(&pdev->dev, &mmp_soc_platform);
275}
276
277static int __devexit mmp_pcm_remove(struct platform_device *pdev)
278{
279 snd_soc_unregister_platform(&pdev->dev);
280 return 0;
281}
282
283static struct platform_driver mmp_pcm_driver = {
284 .driver = {
285 .name = "mmp-pcm-audio",
286 .owner = THIS_MODULE,
287 },
288
289 .probe = mmp_pcm_probe,
290 .remove = __devexit_p(mmp_pcm_remove),
291};
292
293module_platform_driver(mmp_pcm_driver);
294
295MODULE_AUTHOR("Leo Yan <leoy@marvell.com>");
296MODULE_DESCRIPTION("MMP Soc Audio DMA module");
297MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c
new file mode 100644
index 00000000000..4d6cb8a30fc
--- /dev/null
+++ b/sound/soc/pxa/mmp-sspa.c
@@ -0,0 +1,480 @@
1/*
2 * linux/sound/soc/pxa/mmp-sspa.c
3 * Base on pxa2xx-ssp.c
4 *
5 * Copyright (C) 2011 Marvell International Ltd.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22#include <linux/init.h>
23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/delay.h>
26#include <linux/clk.h>
27#include <linux/slab.h>
28#include <linux/pxa2xx_ssp.h>
29#include <linux/io.h>
30#include <sound/core.h>
31#include <sound/pcm.h>
32#include <sound/initval.h>
33#include <sound/pcm_params.h>
34#include <sound/soc.h>
35#include <sound/pxa2xx-lib.h>
36#include "mmp-sspa.h"
37
38/*
39 * SSPA audio private data
40 */
41struct sspa_priv {
42 struct ssp_device *sspa;
43 struct pxa2xx_pcm_dma_params *dma_params;
44 struct clk *audio_clk;
45 struct clk *sysclk;
46 int dai_fmt;
47 int running_cnt;
48};
49
50static void mmp_sspa_write_reg(struct ssp_device *sspa, u32 reg, u32 val)
51{
52 __raw_writel(val, sspa->mmio_base + reg);
53}
54
55static u32 mmp_sspa_read_reg(struct ssp_device *sspa, u32 reg)
56{
57 return __raw_readl(sspa->mmio_base + reg);
58}
59
60static void mmp_sspa_tx_enable(struct ssp_device *sspa)
61{
62 unsigned int sspa_sp;
63
64 sspa_sp = mmp_sspa_read_reg(sspa, SSPA_TXSP);
65 sspa_sp |= SSPA_SP_S_EN;
66 sspa_sp |= SSPA_SP_WEN;
67 mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp);
68}
69
70static void mmp_sspa_tx_disable(struct ssp_device *sspa)
71{
72 unsigned int sspa_sp;
73
74 sspa_sp = mmp_sspa_read_reg(sspa, SSPA_TXSP);
75 sspa_sp &= ~SSPA_SP_S_EN;
76 sspa_sp |= SSPA_SP_WEN;
77 mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp);
78}
79
80static void mmp_sspa_rx_enable(struct ssp_device *sspa)
81{
82 unsigned int sspa_sp;
83
84 sspa_sp = mmp_sspa_read_reg(sspa, SSPA_RXSP);
85 sspa_sp |= SSPA_SP_S_EN;
86 sspa_sp |= SSPA_SP_WEN;
87 mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp);
88}
89
90static void mmp_sspa_rx_disable(struct ssp_device *sspa)
91{
92 unsigned int sspa_sp;
93
94 sspa_sp = mmp_sspa_read_reg(sspa, SSPA_RXSP);
95 sspa_sp &= ~SSPA_SP_S_EN;
96 sspa_sp |= SSPA_SP_WEN;
97 mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp);
98}
99
100static int mmp_sspa_startup(struct snd_pcm_substream *substream,
101 struct snd_soc_dai *dai)
102{
103 struct sspa_priv *priv = snd_soc_dai_get_drvdata(dai);
104
105 clk_enable(priv->sysclk);
106 clk_enable(priv->sspa->clk);
107
108 return 0;
109}
110
111static void mmp_sspa_shutdown(struct snd_pcm_substream *substream,
112 struct snd_soc_dai *dai)
113{
114 struct sspa_priv *priv = snd_soc_dai_get_drvdata(dai);
115
116 clk_disable(priv->sspa->clk);
117 clk_disable(priv->sysclk);
118
119 return;
120}
121
122/*
123 * Set the SSP ports SYSCLK.
124 */
125static int mmp_sspa_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
126 int clk_id, unsigned int freq, int dir)
127{
128 struct sspa_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
129 int ret = 0;
130
131 switch (clk_id) {
132 case MMP_SSPA_CLK_AUDIO:
133 ret = clk_set_rate(priv->audio_clk, freq);
134 if (ret)
135 return ret;
136 break;
137 case MMP_SSPA_CLK_PLL:
138 case MMP_SSPA_CLK_VCXO:
139 /* not support yet */
140 return -EINVAL;
141 default:
142 return -EINVAL;
143 }
144
145 return 0;
146}
147
148static int mmp_sspa_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id,
149 int source, unsigned int freq_in,
150 unsigned int freq_out)
151{
152 struct sspa_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
153 int ret = 0;
154
155 switch (pll_id) {
156 case MMP_SYSCLK:
157 ret = clk_set_rate(priv->sysclk, freq_out);
158 if (ret)
159 return ret;
160 break;
161 case MMP_SSPA_CLK:
162 ret = clk_set_rate(priv->sspa->clk, freq_out);
163 if (ret)
164 return ret;
165 break;
166 default:
167 return -ENODEV;
168 }
169
170 return 0;
171}
172
173/*
174 * Set up the sspa dai format. The sspa port must be inactive
175 * before calling this function as the physical
176 * interface format is changed.
177 */
178static int mmp_sspa_set_dai_fmt(struct snd_soc_dai *cpu_dai,
179 unsigned int fmt)
180{
181 struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(cpu_dai);
182 struct ssp_device *sspa = sspa_priv->sspa;
183 u32 sspa_sp, sspa_ctrl;
184
185 /* check if we need to change anything at all */
186 if (sspa_priv->dai_fmt == fmt)
187 return 0;
188
189 /* we can only change the settings if the port is not in use */
190 if ((mmp_sspa_read_reg(sspa, SSPA_TXSP) & SSPA_SP_S_EN) ||
191 (mmp_sspa_read_reg(sspa, SSPA_RXSP) & SSPA_SP_S_EN)) {
192 dev_err(&sspa->pdev->dev,
193 "can't change hardware dai format: stream is in use\n");
194 return -EINVAL;
195 }
196
197 /* reset port settings */
198 sspa_sp = SSPA_SP_WEN | SSPA_SP_S_RST | SSPA_SP_FFLUSH;
199 sspa_ctrl = 0;
200
201 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
202 case SND_SOC_DAIFMT_CBS_CFS:
203 sspa_sp |= SSPA_SP_MSL;
204 break;
205 case SND_SOC_DAIFMT_CBM_CFM:
206 break;
207 default:
208 return -EINVAL;
209 }
210
211 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
212 case SND_SOC_DAIFMT_NB_NF:
213 sspa_sp |= SSPA_SP_FSP;
214 break;
215 default:
216 return -EINVAL;
217 }
218
219 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
220 case SND_SOC_DAIFMT_I2S:
221 sspa_sp |= SSPA_TXSP_FPER(63);
222 sspa_sp |= SSPA_SP_FWID(31);
223 sspa_ctrl |= SSPA_CTL_XDATDLY(1);
224 break;
225 default:
226 return -EINVAL;
227 }
228
229 mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp);
230 mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp);
231
232 sspa_sp &= ~(SSPA_SP_S_RST | SSPA_SP_FFLUSH);
233 mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp);
234 mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp);
235
236 /*
237 * FIXME: hw issue, for the tx serial port,
238 * can not config the master/slave mode;
239 * so must clean this bit.
240 * The master/slave mode has been set in the
241 * rx port.
242 */
243 sspa_sp &= ~SSPA_SP_MSL;
244 mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp);
245
246 mmp_sspa_write_reg(sspa, SSPA_TXCTL, sspa_ctrl);
247 mmp_sspa_write_reg(sspa, SSPA_RXCTL, sspa_ctrl);
248
249 /* Since we are configuring the timings for the format by hand
250 * we have to defer some things until hw_params() where we
251 * know parameters like the sample size.
252 */
253 sspa_priv->dai_fmt = fmt;
254 return 0;
255}
256
257/*
258 * Set the SSPA audio DMA parameters and sample size.
259 * Can be called multiple times by oss emulation.
260 */
261static int mmp_sspa_hw_params(struct snd_pcm_substream *substream,
262 struct snd_pcm_hw_params *params,
263 struct snd_soc_dai *dai)
264{
265 struct snd_soc_pcm_runtime *rtd = substream->private_data;
266 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
267 struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai);
268 struct ssp_device *sspa = sspa_priv->sspa;
269 struct pxa2xx_pcm_dma_params *dma_params;
270 u32 sspa_ctrl;
271
272 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
273 sspa_ctrl = mmp_sspa_read_reg(sspa, SSPA_TXCTL);
274 else
275 sspa_ctrl = mmp_sspa_read_reg(sspa, SSPA_RXCTL);
276
277 sspa_ctrl &= ~SSPA_CTL_XFRLEN1_MASK;
278 sspa_ctrl |= SSPA_CTL_XFRLEN1(params_channels(params) - 1);
279 sspa_ctrl &= ~SSPA_CTL_XWDLEN1_MASK;
280 sspa_ctrl |= SSPA_CTL_XWDLEN1(SSPA_CTL_32_BITS);
281 sspa_ctrl &= ~SSPA_CTL_XSSZ1_MASK;
282
283 switch (params_format(params)) {
284 case SNDRV_PCM_FORMAT_S8:
285 sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_8_BITS);
286 break;
287 case SNDRV_PCM_FORMAT_S16_LE:
288 sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_16_BITS);
289 break;
290 case SNDRV_PCM_FORMAT_S20_3LE:
291 sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_20_BITS);
292 break;
293 case SNDRV_PCM_FORMAT_S24_3LE:
294 sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_24_BITS);
295 break;
296 case SNDRV_PCM_FORMAT_S32_LE:
297 sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_32_BITS);
298 break;
299 default:
300 return -EINVAL;
301 }
302
303 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
304 mmp_sspa_write_reg(sspa, SSPA_TXCTL, sspa_ctrl);
305 mmp_sspa_write_reg(sspa, SSPA_TXFIFO_LL, 0x1);
306 } else {
307 mmp_sspa_write_reg(sspa, SSPA_RXCTL, sspa_ctrl);
308 mmp_sspa_write_reg(sspa, SSPA_RXFIFO_UL, 0x0);
309 }
310
311 dma_params = &sspa_priv->dma_params[substream->stream];
312 dma_params->dev_addr = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
313 (sspa->phys_base + SSPA_TXD) :
314 (sspa->phys_base + SSPA_RXD);
315 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_params);
316 return 0;
317}
318
319static int mmp_sspa_trigger(struct snd_pcm_substream *substream, int cmd,
320 struct snd_soc_dai *dai)
321{
322 struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai);
323 struct ssp_device *sspa = sspa_priv->sspa;
324 int ret = 0;
325
326 switch (cmd) {
327 case SNDRV_PCM_TRIGGER_START:
328 case SNDRV_PCM_TRIGGER_RESUME:
329 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
330 /*
331 * whatever playback or capture, must enable rx.
332 * this is a hw issue, so need check if rx has been
333 * enabled or not; if has been enabled by another
334 * stream, do not enable again.
335 */
336 if (!sspa_priv->running_cnt)
337 mmp_sspa_rx_enable(sspa);
338
339 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
340 mmp_sspa_tx_enable(sspa);
341
342 sspa_priv->running_cnt++;
343 break;
344
345 case SNDRV_PCM_TRIGGER_STOP:
346 case SNDRV_PCM_TRIGGER_SUSPEND:
347 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
348 sspa_priv->running_cnt--;
349
350 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
351 mmp_sspa_tx_disable(sspa);
352
353 /* have no capture stream, disable rx port */
354 if (!sspa_priv->running_cnt)
355 mmp_sspa_rx_disable(sspa);
356 break;
357
358 default:
359 ret = -EINVAL;
360 }
361
362 return ret;
363}
364
365static int mmp_sspa_probe(struct snd_soc_dai *dai)
366{
367 struct sspa_priv *priv = dev_get_drvdata(dai->dev);
368
369 snd_soc_dai_set_drvdata(dai, priv);
370 return 0;
371
372}
373
374#define MMP_SSPA_RATES SNDRV_PCM_RATE_8000_192000
375#define MMP_SSPA_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
376 SNDRV_PCM_FMTBIT_S16_LE | \
377 SNDRV_PCM_FMTBIT_S24_LE | \
378 SNDRV_PCM_FMTBIT_S24_LE | \
379 SNDRV_PCM_FMTBIT_S32_LE)
380
381static struct snd_soc_dai_ops mmp_sspa_dai_ops = {
382 .startup = mmp_sspa_startup,
383 .shutdown = mmp_sspa_shutdown,
384 .trigger = mmp_sspa_trigger,
385 .hw_params = mmp_sspa_hw_params,
386 .set_sysclk = mmp_sspa_set_dai_sysclk,
387 .set_pll = mmp_sspa_set_dai_pll,
388 .set_fmt = mmp_sspa_set_dai_fmt,
389};
390
391struct snd_soc_dai_driver mmp_sspa_dai = {
392 .probe = mmp_sspa_probe,
393 .playback = {
394 .channels_min = 1,
395 .channels_max = 128,
396 .rates = MMP_SSPA_RATES,
397 .formats = MMP_SSPA_FORMATS,
398 },
399 .capture = {
400 .channels_min = 1,
401 .channels_max = 2,
402 .rates = MMP_SSPA_RATES,
403 .formats = MMP_SSPA_FORMATS,
404 },
405 .ops = &mmp_sspa_dai_ops,
406};
407
408static __devinit int asoc_mmp_sspa_probe(struct platform_device *pdev)
409{
410 struct sspa_priv *priv;
411 struct resource *res;
412
413 priv = devm_kzalloc(&pdev->dev,
414 sizeof(struct sspa_priv), GFP_KERNEL);
415 if (!priv)
416 return -ENOMEM;
417
418 priv->sspa = devm_kzalloc(&pdev->dev,
419 sizeof(struct ssp_device), GFP_KERNEL);
420 if (priv->sspa == NULL)
421 return -ENOMEM;
422
423 priv->dma_params = devm_kzalloc(&pdev->dev,
424 2 * sizeof(struct pxa2xx_pcm_dma_params), GFP_KERNEL);
425 if (priv->dma_params == NULL)
426 return -ENOMEM;
427
428 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
429 if (res == NULL)
430 return -ENOMEM;
431
432 priv->sspa->mmio_base = devm_request_and_ioremap(&pdev->dev, res);
433 if (priv->sspa->mmio_base == NULL)
434 return -ENODEV;
435
436 priv->sspa->clk = devm_clk_get(&pdev->dev, NULL);
437 if (IS_ERR(priv->sspa->clk))
438 return PTR_ERR(priv->sspa->clk);
439
440 priv->audio_clk = clk_get(NULL, "mmp-audio");
441 if (IS_ERR(priv->audio_clk))
442 return PTR_ERR(priv->audio_clk);
443
444 priv->sysclk = clk_get(NULL, "mmp-sysclk");
445 if (IS_ERR(priv->sysclk)) {
446 clk_put(priv->audio_clk);
447 return PTR_ERR(priv->sysclk);
448 }
449 clk_enable(priv->audio_clk);
450 priv->dai_fmt = (unsigned int) -1;
451 platform_set_drvdata(pdev, priv);
452
453 return snd_soc_register_dai(&pdev->dev, &mmp_sspa_dai);
454}
455
456static int __devexit asoc_mmp_sspa_remove(struct platform_device *pdev)
457{
458 struct sspa_priv *priv = platform_get_drvdata(pdev);
459
460 clk_disable(priv->audio_clk);
461 clk_put(priv->audio_clk);
462 clk_put(priv->sysclk);
463 snd_soc_unregister_dai(&pdev->dev);
464 return 0;
465}
466
467static struct platform_driver asoc_mmp_sspa_driver = {
468 .driver = {
469 .name = "mmp-sspa-dai",
470 .owner = THIS_MODULE,
471 },
472 .probe = asoc_mmp_sspa_probe,
473 .remove = __devexit_p(asoc_mmp_sspa_remove),
474};
475
476module_platform_driver(asoc_mmp_sspa_driver);
477
478MODULE_AUTHOR("Leo Yan <leoy@marvell.com>");
479MODULE_DESCRIPTION("MMP SSPA SoC Interface");
480MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/mmp-sspa.h b/sound/soc/pxa/mmp-sspa.h
new file mode 100644
index 00000000000..ea365cb9e78
--- /dev/null
+++ b/sound/soc/pxa/mmp-sspa.h
@@ -0,0 +1,92 @@
1/*
2 * linux/sound/soc/pxa/mmp-sspa.h
3 *
4 * Copyright (C) 2011 Marvell International Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21#ifndef _MMP_SSPA_H
22#define _MMP_SSPA_H
23
24/*
25 * SSPA Registers
26 */
27#define SSPA_RXD (0x00)
28#define SSPA_RXID (0x04)
29#define SSPA_RXCTL (0x08)
30#define SSPA_RXSP (0x0c)
31#define SSPA_RXFIFO_UL (0x10)
32#define SSPA_RXINT_MASK (0x14)
33#define SSPA_RXC (0x18)
34#define SSPA_RXFIFO_NOFS (0x1c)
35#define SSPA_RXFIFO_SIZE (0x20)
36
37#define SSPA_TXD (0x80)
38#define SSPA_TXID (0x84)
39#define SSPA_TXCTL (0x88)
40#define SSPA_TXSP (0x8c)
41#define SSPA_TXFIFO_LL (0x90)
42#define SSPA_TXINT_MASK (0x94)
43#define SSPA_TXC (0x98)
44#define SSPA_TXFIFO_NOFS (0x9c)
45#define SSPA_TXFIFO_SIZE (0xa0)
46
47/* SSPA Control Register */
48#define SSPA_CTL_XPH (1 << 31) /* Read Phase */
49#define SSPA_CTL_XFIG (1 << 15) /* Transmit Zeros when FIFO Empty */
50#define SSPA_CTL_JST (1 << 3) /* Audio Sample Justification */
51#define SSPA_CTL_XFRLEN2_MASK (7 << 24)
52#define SSPA_CTL_XFRLEN2(x) ((x) << 24) /* Transmit Frame Length in Phase 2 */
53#define SSPA_CTL_XWDLEN2_MASK (7 << 21)
54#define SSPA_CTL_XWDLEN2(x) ((x) << 21) /* Transmit Word Length in Phase 2 */
55#define SSPA_CTL_XDATDLY(x) ((x) << 19) /* Tansmit Data Delay */
56#define SSPA_CTL_XSSZ2_MASK (7 << 16)
57#define SSPA_CTL_XSSZ2(x) ((x) << 16) /* Transmit Sample Audio Size */
58#define SSPA_CTL_XFRLEN1_MASK (7 << 8)
59#define SSPA_CTL_XFRLEN1(x) ((x) << 8) /* Transmit Frame Length in Phase 1 */
60#define SSPA_CTL_XWDLEN1_MASK (7 << 5)
61#define SSPA_CTL_XWDLEN1(x) ((x) << 5) /* Transmit Word Length in Phase 1 */
62#define SSPA_CTL_XSSZ1_MASK (7 << 0)
63#define SSPA_CTL_XSSZ1(x) ((x) << 0) /* XSSZ1 */
64
65#define SSPA_CTL_8_BITS (0x0) /* Sample Size */
66#define SSPA_CTL_12_BITS (0x1)
67#define SSPA_CTL_16_BITS (0x2)
68#define SSPA_CTL_20_BITS (0x3)
69#define SSPA_CTL_24_BITS (0x4)
70#define SSPA_CTL_32_BITS (0x5)
71
72/* SSPA Serial Port Register */
73#define SSPA_SP_WEN (1 << 31) /* Write Configuration Enable */
74#define SSPA_SP_MSL (1 << 18) /* Master Slave Configuration */
75#define SSPA_SP_CLKP (1 << 17) /* CLKP Polarity Clock Edge Select */
76#define SSPA_SP_FSP (1 << 16) /* FSP Polarity Clock Edge Select */
77#define SSPA_SP_FFLUSH (1 << 2) /* FIFO Flush */
78#define SSPA_SP_S_RST (1 << 1) /* Active High Reset Signal */
79#define SSPA_SP_S_EN (1 << 0) /* Serial Clock Domain Enable */
80#define SSPA_SP_FWID(x) ((x) << 20) /* Frame-Sync Width */
81#define SSPA_TXSP_FPER(x) ((x) << 4) /* Frame-Sync Active */
82
83/* sspa clock sources */
84#define MMP_SSPA_CLK_PLL 0
85#define MMP_SSPA_CLK_VCXO 1
86#define MMP_SSPA_CLK_AUDIO 3
87
88/* sspa pll id */
89#define MMP_SYSCLK 0
90#define MMP_SSPA_CLK 1
91
92#endif /* _MMP_SSPA_H */
diff --git a/sound/soc/pxa/ttc-dkb.c b/sound/soc/pxa/ttc-dkb.c
new file mode 100644
index 00000000000..935491a8a77
--- /dev/null
+++ b/sound/soc/pxa/ttc-dkb.c
@@ -0,0 +1,173 @@
1/*
2 * linux/sound/soc/pxa/ttc_dkb.c
3 *
4 * Copyright (C) 2012 Marvell International Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21#include <linux/module.h>
22#include <linux/moduleparam.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/soc.h>
26#include <sound/jack.h>
27#include <asm/mach-types.h>
28#include <sound/pcm_params.h>
29#include "../codecs/88pm860x-codec.h"
30
31static struct snd_soc_jack hs_jack, mic_jack;
32
33static struct snd_soc_jack_pin hs_jack_pins[] = {
34 { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, },
35};
36
37static struct snd_soc_jack_pin mic_jack_pins[] = {
38 { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, },
39};
40
41/* ttc machine dapm widgets */
42static const struct snd_soc_dapm_widget ttc_dapm_widgets[] = {
43 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
44 SND_SOC_DAPM_LINE("Lineout Out 1", NULL),
45 SND_SOC_DAPM_LINE("Lineout Out 2", NULL),
46 SND_SOC_DAPM_SPK("Ext Speaker", NULL),
47 SND_SOC_DAPM_MIC("Ext Mic 1", NULL),
48 SND_SOC_DAPM_MIC("Headset Mic 2", NULL),
49 SND_SOC_DAPM_MIC("Ext Mic 3", NULL),
50};
51
52/* ttc machine audio map */
53static const struct snd_soc_dapm_route ttc_audio_map[] = {
54 {"Headset Stereophone", NULL, "HS1"},
55 {"Headset Stereophone", NULL, "HS2"},
56
57 {"Ext Speaker", NULL, "LSP"},
58 {"Ext Speaker", NULL, "LSN"},
59
60 {"Lineout Out 1", NULL, "LINEOUT1"},
61 {"Lineout Out 2", NULL, "LINEOUT2"},
62
63 {"MIC1P", NULL, "Mic1 Bias"},
64 {"MIC1N", NULL, "Mic1 Bias"},
65 {"Mic1 Bias", NULL, "Ext Mic 1"},
66
67 {"MIC2P", NULL, "Mic1 Bias"},
68 {"MIC2N", NULL, "Mic1 Bias"},
69 {"Mic1 Bias", NULL, "Headset Mic 2"},
70
71 {"MIC3P", NULL, "Mic3 Bias"},
72 {"MIC3N", NULL, "Mic3 Bias"},
73 {"Mic3 Bias", NULL, "Ext Mic 3"},
74};
75
76static int ttc_pm860x_init(struct snd_soc_pcm_runtime *rtd)
77{
78 struct snd_soc_codec *codec = rtd->codec;
79 struct snd_soc_dapm_context *dapm = &codec->dapm;
80
81 /* connected pins */
82 snd_soc_dapm_enable_pin(dapm, "Ext Speaker");
83 snd_soc_dapm_enable_pin(dapm, "Ext Mic 1");
84 snd_soc_dapm_enable_pin(dapm, "Ext Mic 3");
85 snd_soc_dapm_disable_pin(dapm, "Headset Mic 2");
86 snd_soc_dapm_disable_pin(dapm, "Headset Stereophone");
87
88 /* Headset jack detection */
89 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE
90 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
91 &hs_jack);
92 snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
93 hs_jack_pins);
94 snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE,
95 &mic_jack);
96 snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins),
97 mic_jack_pins);
98
99 /* headphone, microphone detection & headset short detection */
100 pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE,
101 SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2);
102 pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE);
103
104 return 0;
105}
106
107/* ttc/td-dkb digital audio interface glue - connects codec <--> CPU */
108static struct snd_soc_dai_link ttc_pm860x_hifi_dai[] = {
109{
110 .name = "88pm860x i2s",
111 .stream_name = "audio playback",
112 .codec_name = "88pm860x-codec",
113 .platform_name = "mmp-pcm-audio",
114 .cpu_dai_name = "pxa-ssp-dai.1",
115 .codec_dai_name = "88pm860x-i2s",
116 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
117 SND_SOC_DAIFMT_CBM_CFM,
118 .init = ttc_pm860x_init,
119},
120};
121
122/* ttc/td audio machine driver */
123static struct snd_soc_card ttc_dkb_card = {
124 .name = "ttc-dkb-hifi",
125 .dai_link = ttc_pm860x_hifi_dai,
126 .num_links = ARRAY_SIZE(ttc_pm860x_hifi_dai),
127
128 .dapm_widgets = ttc_dapm_widgets,
129 .num_dapm_widgets = ARRAY_SIZE(ttc_dapm_widgets),
130 .dapm_routes = ttc_audio_map,
131 .num_dapm_routes = ARRAY_SIZE(ttc_audio_map),
132};
133
134static int __devinit ttc_dkb_probe(struct platform_device *pdev)
135{
136 struct snd_soc_card *card = &ttc_dkb_card;
137 int ret;
138
139 card->dev = &pdev->dev;
140
141 ret = snd_soc_register_card(card);
142 if (ret)
143 dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
144 ret);
145
146 return ret;
147}
148
149static int __devexit ttc_dkb_remove(struct platform_device *pdev)
150{
151 struct snd_soc_card *card = platform_get_drvdata(pdev);
152
153 snd_soc_unregister_card(card);
154
155 return 0;
156}
157
158static struct platform_driver ttc_dkb_driver = {
159 .driver = {
160 .name = "ttc-dkb-audio",
161 .owner = THIS_MODULE,
162 },
163 .probe = ttc_dkb_probe,
164 .remove = __devexit_p(ttc_dkb_remove),
165};
166
167module_platform_driver(ttc_dkb_driver);
168
169/* Module information */
170MODULE_AUTHOR("Qiao Zhou, <zhouqiao@marvell.com>");
171MODULE_DESCRIPTION("ALSA SoC TTC DKB");
172MODULE_LICENSE("GPL");
173MODULE_ALIAS("platform:ttc-dkb-audio");
diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c
index c82c646b8a0..ee52c8a0077 100644
--- a/sound/soc/samsung/littlemill.c
+++ b/sound/soc/samsung/littlemill.c
@@ -211,6 +211,11 @@ static int bbclk_ev(struct snd_soc_dapm_widget *w,
211 return 0; 211 return 0;
212} 212}
213 213
214static const struct snd_kcontrol_new controls[] = {
215 SOC_DAPM_PIN_SWITCH("WM1250 Input"),
216 SOC_DAPM_PIN_SWITCH("WM1250 Output"),
217};
218
214static struct snd_soc_dapm_widget widgets[] = { 219static struct snd_soc_dapm_widget widgets[] = {
215 SND_SOC_DAPM_HP("Headphone", NULL), 220 SND_SOC_DAPM_HP("Headphone", NULL),
216 221
@@ -282,6 +287,8 @@ static struct snd_soc_card littlemill = {
282 .set_bias_level = littlemill_set_bias_level, 287 .set_bias_level = littlemill_set_bias_level,
283 .set_bias_level_post = littlemill_set_bias_level_post, 288 .set_bias_level_post = littlemill_set_bias_level_post,
284 289
290 .controls = controls,
291 .num_controls = ARRAY_SIZE(controls),
285 .dapm_widgets = widgets, 292 .dapm_widgets = widgets,
286 .num_dapm_widgets = ARRAY_SIZE(widgets), 293 .num_dapm_widgets = ARRAY_SIZE(widgets),
287 .dapm_routes = audio_paths, 294 .dapm_routes = audio_paths,
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c
index 79fbeea99d4..ac7701b3c5d 100644
--- a/sound/soc/samsung/s3c2412-i2s.c
+++ b/sound/soc/samsung/s3c2412-i2s.c
@@ -25,7 +25,6 @@
25#include <sound/soc.h> 25#include <sound/soc.h>
26#include <sound/pcm_params.h> 26#include <sound/pcm_params.h>
27 27
28#include <mach/regs-gpio.h>
29#include <mach/dma.h> 28#include <mach/dma.h>
30 29
31#include "dma.h" 30#include "dma.h"
@@ -83,12 +82,9 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai)
83 82
84 s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk; 83 s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk;
85 84
86 /* Configure the I2S pins in correct mode */ 85 /* Configure the I2S pins (GPE0...GPE4) in correct mode */
87 s3c2410_gpio_cfgpin(S3C2410_GPE0, S3C2410_GPE0_I2SLRCK); 86 s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2),
88 s3c2410_gpio_cfgpin(S3C2410_GPE1, S3C2410_GPE1_I2SSCLK); 87 S3C_GPIO_PULL_NONE);
89 s3c2410_gpio_cfgpin(S3C2410_GPE2, S3C2410_GPE2_CDCLK);
90 s3c2410_gpio_cfgpin(S3C2410_GPE3, S3C2410_GPE3_I2SSDI);
91 s3c2410_gpio_cfgpin(S3C2410_GPE4, S3C2410_GPE4_I2SSDO);
92 88
93 return 0; 89 return 0;
94} 90}
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c
index c4aa4d412fb..0aae3a3883d 100644
--- a/sound/soc/samsung/s3c24xx-i2s.c
+++ b/sound/soc/samsung/s3c24xx-i2s.c
@@ -23,7 +23,6 @@
23#include <sound/soc.h> 23#include <sound/soc.h>
24#include <sound/pcm_params.h> 24#include <sound/pcm_params.h>
25 25
26#include <mach/regs-gpio.h>
27#include <mach/dma.h> 26#include <mach/dma.h>
28#include <plat/regs-iis.h> 27#include <plat/regs-iis.h>
29 28
@@ -391,12 +390,9 @@ static int s3c24xx_i2s_probe(struct snd_soc_dai *dai)
391 } 390 }
392 clk_enable(s3c24xx_i2s.iis_clk); 391 clk_enable(s3c24xx_i2s.iis_clk);
393 392
394 /* Configure the I2S pins in correct mode */ 393 /* Configure the I2S pins (GPE0...GPE4) in correct mode */
395 s3c2410_gpio_cfgpin(S3C2410_GPE0, S3C2410_GPE0_I2SLRCK); 394 s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2),
396 s3c2410_gpio_cfgpin(S3C2410_GPE1, S3C2410_GPE1_I2SSCLK); 395 S3C_GPIO_PULL_NONE);
397 s3c2410_gpio_cfgpin(S3C2410_GPE2, S3C2410_GPE2_CDCLK);
398 s3c2410_gpio_cfgpin(S3C2410_GPE3, S3C2410_GPE3_I2SSDI);
399 s3c2410_gpio_cfgpin(S3C2410_GPE4, S3C2410_GPE4_I2SSDO);
400 396
401 writel(S3C2410_IISCON_IISEN, s3c24xx_i2s.regs + S3C2410_IISCON); 397 writel(S3C2410_IISCON_IISEN, s3c24xx_i2s.regs + S3C2410_IISCON);
402 398
diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c
index 8eb309f23d1..48dd4dd9ee0 100644
--- a/sound/soc/samsung/smdk_wm8994.c
+++ b/sound/soc/samsung/smdk_wm8994.c
@@ -149,31 +149,41 @@ static struct snd_soc_card smdk = {
149 .num_links = ARRAY_SIZE(smdk_dai), 149 .num_links = ARRAY_SIZE(smdk_dai),
150}; 150};
151 151
152static struct platform_device *smdk_snd_device;
153 152
154static int __init smdk_audio_init(void) 153static int __devinit smdk_audio_probe(struct platform_device *pdev)
155{ 154{
156 int ret; 155 int ret;
156 struct snd_soc_card *card = &smdk;
157 157
158 smdk_snd_device = platform_device_alloc("soc-audio", -1); 158 card->dev = &pdev->dev;
159 if (!smdk_snd_device) 159 ret = snd_soc_register_card(card);
160 return -ENOMEM;
161 160
162 platform_set_drvdata(smdk_snd_device, &smdk);
163
164 ret = platform_device_add(smdk_snd_device);
165 if (ret) 161 if (ret)
166 platform_device_put(smdk_snd_device); 162 dev_err(&pdev->dev, "snd_soc_register_card() failed:%d\n", ret);
167 163
168 return ret; 164 return ret;
169} 165}
170module_init(smdk_audio_init);
171 166
172static void __exit smdk_audio_exit(void) 167static int __devexit smdk_audio_remove(struct platform_device *pdev)
173{ 168{
174 platform_device_unregister(smdk_snd_device); 169 struct snd_soc_card *card = platform_get_drvdata(pdev);
170
171 snd_soc_unregister_card(card);
172
173 return 0;
175} 174}
176module_exit(smdk_audio_exit); 175
176static struct platform_driver smdk_audio_driver = {
177 .driver = {
178 .name = "smdk-audio",
179 .owner = THIS_MODULE,
180 },
181 .probe = smdk_audio_probe,
182 .remove = __devexit_p(smdk_audio_remove),
183};
184
185module_platform_driver(smdk_audio_driver);
177 186
178MODULE_DESCRIPTION("ALSA SoC SMDK WM8994"); 187MODULE_DESCRIPTION("ALSA SoC SMDK WM8994");
179MODULE_LICENSE("GPL"); 188MODULE_LICENSE("GPL");
189MODULE_ALIAS("platform:smdk-audio");
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 2ef98536f1d..53486ff9c2a 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -247,7 +247,7 @@ struct fsi_priv {
247struct fsi_stream_handler { 247struct fsi_stream_handler {
248 int (*init)(struct fsi_priv *fsi, struct fsi_stream *io); 248 int (*init)(struct fsi_priv *fsi, struct fsi_stream *io);
249 int (*quit)(struct fsi_priv *fsi, struct fsi_stream *io); 249 int (*quit)(struct fsi_priv *fsi, struct fsi_stream *io);
250 int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io); 250 int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev);
251 int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io); 251 int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io);
252 int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io); 252 int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io);
253 void (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io, 253 void (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io,
@@ -571,16 +571,16 @@ static int fsi_stream_transfer(struct fsi_stream *io)
571#define fsi_stream_stop(fsi, io)\ 571#define fsi_stream_stop(fsi, io)\
572 fsi_stream_handler_call(io, start_stop, fsi, io, 0) 572 fsi_stream_handler_call(io, start_stop, fsi, io, 0)
573 573
574static int fsi_stream_probe(struct fsi_priv *fsi) 574static int fsi_stream_probe(struct fsi_priv *fsi, struct device *dev)
575{ 575{
576 struct fsi_stream *io; 576 struct fsi_stream *io;
577 int ret1, ret2; 577 int ret1, ret2;
578 578
579 io = &fsi->playback; 579 io = &fsi->playback;
580 ret1 = fsi_stream_handler_call(io, probe, fsi, io); 580 ret1 = fsi_stream_handler_call(io, probe, fsi, io, dev);
581 581
582 io = &fsi->capture; 582 io = &fsi->capture;
583 ret2 = fsi_stream_handler_call(io, probe, fsi, io); 583 ret2 = fsi_stream_handler_call(io, probe, fsi, io, dev);
584 584
585 if (ret1 < 0) 585 if (ret1 < 0)
586 return ret1; 586 return ret1;
@@ -1089,13 +1089,10 @@ static void fsi_dma_do_tasklet(unsigned long data)
1089{ 1089{
1090 struct fsi_stream *io = (struct fsi_stream *)data; 1090 struct fsi_stream *io = (struct fsi_stream *)data;
1091 struct fsi_priv *fsi = fsi_stream_to_priv(io); 1091 struct fsi_priv *fsi = fsi_stream_to_priv(io);
1092 struct dma_chan *chan;
1093 struct snd_soc_dai *dai; 1092 struct snd_soc_dai *dai;
1094 struct dma_async_tx_descriptor *desc; 1093 struct dma_async_tx_descriptor *desc;
1095 struct scatterlist sg;
1096 struct snd_pcm_runtime *runtime; 1094 struct snd_pcm_runtime *runtime;
1097 enum dma_data_direction dir; 1095 enum dma_data_direction dir;
1098 dma_cookie_t cookie;
1099 int is_play = fsi_stream_is_play(fsi, io); 1096 int is_play = fsi_stream_is_play(fsi, io);
1100 int len; 1097 int len;
1101 dma_addr_t buf; 1098 dma_addr_t buf;
@@ -1104,7 +1101,6 @@ static void fsi_dma_do_tasklet(unsigned long data)
1104 return; 1101 return;
1105 1102
1106 dai = fsi_get_dai(io->substream); 1103 dai = fsi_get_dai(io->substream);
1107 chan = io->chan;
1108 runtime = io->substream->runtime; 1104 runtime = io->substream->runtime;
1109 dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; 1105 dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
1110 len = samples_to_bytes(runtime, io->period_samples); 1106 len = samples_to_bytes(runtime, io->period_samples);
@@ -1112,14 +1108,8 @@ static void fsi_dma_do_tasklet(unsigned long data)
1112 1108
1113 dma_sync_single_for_device(dai->dev, buf, len, dir); 1109 dma_sync_single_for_device(dai->dev, buf, len, dir);
1114 1110
1115 sg_init_table(&sg, 1); 1111 desc = dmaengine_prep_slave_single(io->chan, buf, len, dir,
1116 sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf)), 1112 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
1117 len , offset_in_page(buf));
1118 sg_dma_address(&sg) = buf;
1119 sg_dma_len(&sg) = len;
1120
1121 desc = dmaengine_prep_slave_sg(chan, &sg, 1, dir,
1122 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
1123 if (!desc) { 1113 if (!desc) {
1124 dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n"); 1114 dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n");
1125 return; 1115 return;
@@ -1128,13 +1118,12 @@ static void fsi_dma_do_tasklet(unsigned long data)
1128 desc->callback = fsi_dma_complete; 1118 desc->callback = fsi_dma_complete;
1129 desc->callback_param = io; 1119 desc->callback_param = io;
1130 1120
1131 cookie = desc->tx_submit(desc); 1121 if (dmaengine_submit(desc) < 0) {
1132 if (cookie < 0) {
1133 dev_err(dai->dev, "tx_submit() fail\n"); 1122 dev_err(dai->dev, "tx_submit() fail\n");
1134 return; 1123 return;
1135 } 1124 }
1136 1125
1137 dma_async_issue_pending(chan); 1126 dma_async_issue_pending(io->chan);
1138 1127
1139 /* 1128 /*
1140 * FIXME 1129 * FIXME
@@ -1184,7 +1173,7 @@ static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
1184 fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); 1173 fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
1185} 1174}
1186 1175
1187static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io) 1176static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev)
1188{ 1177{
1189 dma_cap_mask_t mask; 1178 dma_cap_mask_t mask;
1190 1179
@@ -1192,8 +1181,19 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io)
1192 dma_cap_set(DMA_SLAVE, mask); 1181 dma_cap_set(DMA_SLAVE, mask);
1193 1182
1194 io->chan = dma_request_channel(mask, fsi_dma_filter, &io->slave); 1183 io->chan = dma_request_channel(mask, fsi_dma_filter, &io->slave);
1195 if (!io->chan) 1184 if (!io->chan) {
1196 return -EIO; 1185
1186 /* switch to PIO handler */
1187 if (fsi_stream_is_play(fsi, io))
1188 fsi->playback.handler = &fsi_pio_push_handler;
1189 else
1190 fsi->capture.handler = &fsi_pio_pop_handler;
1191
1192 dev_info(dev, "switch handler (dma => pio)\n");
1193
1194 /* probe again */
1195 return fsi_stream_probe(fsi, dev);
1196 }
1197 1197
1198 tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io); 1198 tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io);
1199 1199
@@ -1683,7 +1683,7 @@ static int fsi_probe(struct platform_device *pdev)
1683 master->fsia.master = master; 1683 master->fsia.master = master;
1684 master->fsia.info = &info->port_a; 1684 master->fsia.info = &info->port_a;
1685 fsi_handler_init(&master->fsia); 1685 fsi_handler_init(&master->fsia);
1686 ret = fsi_stream_probe(&master->fsia); 1686 ret = fsi_stream_probe(&master->fsia, &pdev->dev);
1687 if (ret < 0) { 1687 if (ret < 0) {
1688 dev_err(&pdev->dev, "FSIA stream probe failed\n"); 1688 dev_err(&pdev->dev, "FSIA stream probe failed\n");
1689 goto exit_iounmap; 1689 goto exit_iounmap;
@@ -1694,7 +1694,7 @@ static int fsi_probe(struct platform_device *pdev)
1694 master->fsib.master = master; 1694 master->fsib.master = master;
1695 master->fsib.info = &info->port_b; 1695 master->fsib.info = &info->port_b;
1696 fsi_handler_init(&master->fsib); 1696 fsi_handler_init(&master->fsib);
1697 ret = fsi_stream_probe(&master->fsib); 1697 ret = fsi_stream_probe(&master->fsib, &pdev->dev);
1698 if (ret < 0) { 1698 if (ret < 0) {
1699 dev_err(&pdev->dev, "FSIB stream probe failed\n"); 1699 dev_err(&pdev->dev, "FSIB stream probe failed\n");
1700 goto exit_fsia; 1700 goto exit_fsia;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index b37ee8077ed..f219b2f7ee6 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -812,13 +812,15 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
812 812
813 /* Find CPU DAI from registered DAIs*/ 813 /* Find CPU DAI from registered DAIs*/
814 list_for_each_entry(cpu_dai, &dai_list, list) { 814 list_for_each_entry(cpu_dai, &dai_list, list) {
815 if (dai_link->cpu_dai_of_node) { 815 if (dai_link->cpu_of_node &&
816 if (cpu_dai->dev->of_node != dai_link->cpu_dai_of_node) 816 (cpu_dai->dev->of_node != dai_link->cpu_of_node))
817 continue; 817 continue;
818 } else { 818 if (dai_link->cpu_name &&
819 if (strcmp(cpu_dai->name, dai_link->cpu_dai_name)) 819 strcmp(dev_name(cpu_dai->dev), dai_link->cpu_name))
820 continue; 820 continue;
821 } 821 if (dai_link->cpu_dai_name &&
822 strcmp(cpu_dai->name, dai_link->cpu_dai_name))
823 continue;
822 824
823 rtd->cpu_dai = cpu_dai; 825 rtd->cpu_dai = cpu_dai;
824 } 826 }
@@ -896,6 +898,28 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
896 return 0; 898 return 0;
897} 899}
898 900
901static int soc_remove_platform(struct snd_soc_platform *platform)
902{
903 int ret;
904
905 if (platform->driver->remove) {
906 ret = platform->driver->remove(platform);
907 if (ret < 0)
908 pr_err("asoc: failed to remove %s: %d\n",
909 platform->name, ret);
910 }
911
912 /* Make sure all DAPM widgets are freed */
913 snd_soc_dapm_free(&platform->dapm);
914
915 soc_cleanup_platform_debugfs(platform);
916 platform->probed = 0;
917 list_del(&platform->card_list);
918 module_put(platform->dev->driver->owner);
919
920 return 0;
921}
922
899static void soc_remove_codec(struct snd_soc_codec *codec) 923static void soc_remove_codec(struct snd_soc_codec *codec)
900{ 924{
901 int err; 925 int err;
@@ -917,11 +941,9 @@ static void soc_remove_codec(struct snd_soc_codec *codec)
917 module_put(codec->dev->driver->owner); 941 module_put(codec->dev->driver->owner);
918} 942}
919 943
920static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order) 944static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order)
921{ 945{
922 struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; 946 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
923 struct snd_soc_codec *codec = rtd->codec;
924 struct snd_soc_platform *platform = rtd->platform;
925 struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; 947 struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
926 int err; 948 int err;
927 949
@@ -946,30 +968,6 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
946 list_del(&codec_dai->card_list); 968 list_del(&codec_dai->card_list);
947 } 969 }
948 970
949 /* remove the platform */
950 if (platform && platform->probed &&
951 platform->driver->remove_order == order) {
952 if (platform->driver->remove) {
953 err = platform->driver->remove(platform);
954 if (err < 0)
955 pr_err("asoc: failed to remove %s: %d\n",
956 platform->name, err);
957 }
958
959 /* Make sure all DAPM widgets are freed */
960 snd_soc_dapm_free(&platform->dapm);
961
962 soc_cleanup_platform_debugfs(platform);
963 platform->probed = 0;
964 list_del(&platform->card_list);
965 module_put(platform->dev->driver->owner);
966 }
967
968 /* remove the CODEC */
969 if (codec && codec->probed &&
970 codec->driver->remove_order == order)
971 soc_remove_codec(codec);
972
973 /* remove the cpu_dai */ 971 /* remove the cpu_dai */
974 if (cpu_dai && cpu_dai->probed && 972 if (cpu_dai && cpu_dai->probed &&
975 cpu_dai->driver->remove_order == order) { 973 cpu_dai->driver->remove_order == order) {
@@ -981,7 +979,43 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
981 } 979 }
982 cpu_dai->probed = 0; 980 cpu_dai->probed = 0;
983 list_del(&cpu_dai->card_list); 981 list_del(&cpu_dai->card_list);
984 module_put(cpu_dai->dev->driver->owner); 982
983 if (!cpu_dai->codec) {
984 snd_soc_dapm_free(&cpu_dai->dapm);
985 module_put(cpu_dai->dev->driver->owner);
986 }
987 }
988}
989
990static void soc_remove_link_components(struct snd_soc_card *card, int num,
991 int order)
992{
993 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
994 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
995 struct snd_soc_dai *codec_dai = rtd->codec_dai;
996 struct snd_soc_platform *platform = rtd->platform;
997 struct snd_soc_codec *codec;
998
999 /* remove the platform */
1000 if (platform && platform->probed &&
1001 platform->driver->remove_order == order) {
1002 soc_remove_platform(platform);
1003 }
1004
1005 /* remove the CODEC-side CODEC */
1006 if (codec_dai) {
1007 codec = codec_dai->codec;
1008 if (codec && codec->probed &&
1009 codec->driver->remove_order == order)
1010 soc_remove_codec(codec);
1011 }
1012
1013 /* remove any CPU-side CODEC */
1014 if (cpu_dai) {
1015 codec = cpu_dai->codec;
1016 if (codec && codec->probed &&
1017 codec->driver->remove_order == order)
1018 soc_remove_codec(codec);
985 } 1019 }
986} 1020}
987 1021
@@ -992,8 +1026,15 @@ static void soc_remove_dai_links(struct snd_soc_card *card)
992 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; 1026 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
993 order++) { 1027 order++) {
994 for (dai = 0; dai < card->num_rtd; dai++) 1028 for (dai = 0; dai < card->num_rtd; dai++)
995 soc_remove_dai_link(card, dai, order); 1029 soc_remove_link_dais(card, dai, order);
996 } 1030 }
1031
1032 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
1033 order++) {
1034 for (dai = 0; dai < card->num_rtd; dai++)
1035 soc_remove_link_components(card, dai, order);
1036 }
1037
997 card->num_rtd = 0; 1038 card->num_rtd = 0;
998} 1039}
999 1040
@@ -1054,6 +1095,10 @@ static int soc_probe_codec(struct snd_soc_card *card,
1054 } 1095 }
1055 } 1096 }
1056 1097
1098 /* If the driver didn't set I/O up try regmap */
1099 if (!codec->control_data)
1100 snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
1101
1057 if (driver->controls) 1102 if (driver->controls)
1058 snd_soc_add_codec_controls(codec, driver->controls, 1103 snd_soc_add_codec_controls(codec, driver->controls,
1059 driver->num_controls); 1104 driver->num_controls);
@@ -1230,7 +1275,44 @@ out:
1230 return 0; 1275 return 0;
1231} 1276}
1232 1277
1233static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order) 1278static int soc_probe_link_components(struct snd_soc_card *card, int num,
1279 int order)
1280{
1281 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
1282 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1283 struct snd_soc_dai *codec_dai = rtd->codec_dai;
1284 struct snd_soc_platform *platform = rtd->platform;
1285 int ret;
1286
1287 /* probe the CPU-side component, if it is a CODEC */
1288 if (cpu_dai->codec &&
1289 !cpu_dai->codec->probed &&
1290 cpu_dai->codec->driver->probe_order == order) {
1291 ret = soc_probe_codec(card, cpu_dai->codec);
1292 if (ret < 0)
1293 return ret;
1294 }
1295
1296 /* probe the CODEC-side component */
1297 if (!codec_dai->codec->probed &&
1298 codec_dai->codec->driver->probe_order == order) {
1299 ret = soc_probe_codec(card, codec_dai->codec);
1300 if (ret < 0)
1301 return ret;
1302 }
1303
1304 /* probe the platform */
1305 if (!platform->probed &&
1306 platform->driver->probe_order == order) {
1307 ret = soc_probe_platform(card, platform);
1308 if (ret < 0)
1309 return ret;
1310 }
1311
1312 return 0;
1313}
1314
1315static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
1234{ 1316{
1235 struct snd_soc_dai_link *dai_link = &card->dai_link[num]; 1317 struct snd_soc_dai_link *dai_link = &card->dai_link[num];
1236 struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; 1318 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
@@ -1255,11 +1337,14 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
1255 /* probe the cpu_dai */ 1337 /* probe the cpu_dai */
1256 if (!cpu_dai->probed && 1338 if (!cpu_dai->probed &&
1257 cpu_dai->driver->probe_order == order) { 1339 cpu_dai->driver->probe_order == order) {
1258 cpu_dai->dapm.card = card; 1340 if (!cpu_dai->codec) {
1259 if (!try_module_get(cpu_dai->dev->driver->owner)) 1341 cpu_dai->dapm.card = card;
1260 return -ENODEV; 1342 if (!try_module_get(cpu_dai->dev->driver->owner))
1343 return -ENODEV;
1261 1344
1262 snd_soc_dapm_new_dai_widgets(&cpu_dai->dapm, cpu_dai); 1345 list_add(&cpu_dai->dapm.list, &card->dapm_list);
1346 snd_soc_dapm_new_dai_widgets(&cpu_dai->dapm, cpu_dai);
1347 }
1263 1348
1264 if (cpu_dai->driver->probe) { 1349 if (cpu_dai->driver->probe) {
1265 ret = cpu_dai->driver->probe(cpu_dai); 1350 ret = cpu_dai->driver->probe(cpu_dai);
@@ -1275,22 +1360,6 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
1275 list_add(&cpu_dai->card_list, &card->dai_dev_list); 1360 list_add(&cpu_dai->card_list, &card->dai_dev_list);
1276 } 1361 }
1277 1362
1278 /* probe the CODEC */
1279 if (!codec->probed &&
1280 codec->driver->probe_order == order) {
1281 ret = soc_probe_codec(card, codec);
1282 if (ret < 0)
1283 return ret;
1284 }
1285
1286 /* probe the platform */
1287 if (!platform->probed &&
1288 platform->driver->probe_order == order) {
1289 ret = soc_probe_platform(card, platform);
1290 if (ret < 0)
1291 return ret;
1292 }
1293
1294 /* probe the CODEC DAI */ 1363 /* probe the CODEC DAI */
1295 if (!codec_dai->probed && codec_dai->driver->probe_order == order) { 1364 if (!codec_dai->probed && codec_dai->driver->probe_order == order) {
1296 if (codec_dai->driver->probe) { 1365 if (codec_dai->driver->probe) {
@@ -1565,14 +1634,27 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
1565 goto card_probe_error; 1634 goto card_probe_error;
1566 } 1635 }
1567 1636
1568 /* early DAI link probe */ 1637 /* probe all components used by DAI links on this card */
1569 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; 1638 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
1570 order++) { 1639 order++) {
1571 for (i = 0; i < card->num_links; i++) { 1640 for (i = 0; i < card->num_links; i++) {
1572 ret = soc_probe_dai_link(card, i, order); 1641 ret = soc_probe_link_components(card, i, order);
1573 if (ret < 0) { 1642 if (ret < 0) {
1574 pr_err("asoc: failed to instantiate card %s: %d\n", 1643 pr_err("asoc: failed to instantiate card %s: %d\n",
1575 card->name, ret); 1644 card->name, ret);
1645 goto probe_dai_err;
1646 }
1647 }
1648 }
1649
1650 /* probe all DAI links on this card */
1651 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
1652 order++) {
1653 for (i = 0; i < card->num_links; i++) {
1654 ret = soc_probe_link_dais(card, i, order);
1655 if (ret < 0) {
1656 pr_err("asoc: failed to instantiate card %s: %d\n",
1657 card->name, ret);
1576 goto probe_dai_err; 1658 goto probe_dai_err;
1577 } 1659 }
1578 } 1660 }
@@ -2790,6 +2872,104 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
2790EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); 2872EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
2791 2873
2792/** 2874/**
2875 * snd_soc_info_volsw_range - single mixer info callback with range.
2876 * @kcontrol: mixer control
2877 * @uinfo: control element information
2878 *
2879 * Callback to provide information, within a range, about a single
2880 * mixer control.
2881 *
2882 * returns 0 for success.
2883 */
2884int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol,
2885 struct snd_ctl_elem_info *uinfo)
2886{
2887 struct soc_mixer_control *mc =
2888 (struct soc_mixer_control *)kcontrol->private_value;
2889 int platform_max;
2890 int min = mc->min;
2891
2892 if (!mc->platform_max)
2893 mc->platform_max = mc->max;
2894 platform_max = mc->platform_max;
2895
2896 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2897 uinfo->count = 1;
2898 uinfo->value.integer.min = 0;
2899 uinfo->value.integer.max = platform_max - min;
2900
2901 return 0;
2902}
2903EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range);
2904
2905/**
2906 * snd_soc_put_volsw_range - single mixer put value callback with range.
2907 * @kcontrol: mixer control
2908 * @ucontrol: control element information
2909 *
2910 * Callback to set the value, within a range, for a single mixer control.
2911 *
2912 * Returns 0 for success.
2913 */
2914int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
2915 struct snd_ctl_elem_value *ucontrol)
2916{
2917 struct soc_mixer_control *mc =
2918 (struct soc_mixer_control *)kcontrol->private_value;
2919 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2920 unsigned int reg = mc->reg;
2921 unsigned int shift = mc->shift;
2922 int min = mc->min;
2923 int max = mc->max;
2924 unsigned int mask = (1 << fls(max)) - 1;
2925 unsigned int invert = mc->invert;
2926 unsigned int val, val_mask;
2927
2928 val = ((ucontrol->value.integer.value[0] + min) & mask);
2929 if (invert)
2930 val = max - val;
2931 val_mask = mask << shift;
2932 val = val << shift;
2933
2934 return snd_soc_update_bits_locked(codec, reg, val_mask, val);
2935}
2936EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range);
2937
2938/**
2939 * snd_soc_get_volsw_range - single mixer get callback with range
2940 * @kcontrol: mixer control
2941 * @ucontrol: control element information
2942 *
2943 * Callback to get the value, within a range, of a single mixer control.
2944 *
2945 * Returns 0 for success.
2946 */
2947int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
2948 struct snd_ctl_elem_value *ucontrol)
2949{
2950 struct soc_mixer_control *mc =
2951 (struct soc_mixer_control *)kcontrol->private_value;
2952 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2953 unsigned int reg = mc->reg;
2954 unsigned int shift = mc->shift;
2955 int min = mc->min;
2956 int max = mc->max;
2957 unsigned int mask = (1 << fls(max)) - 1;
2958 unsigned int invert = mc->invert;
2959
2960 ucontrol->value.integer.value[0] =
2961 (snd_soc_read(codec, reg) >> shift) & mask;
2962 if (invert)
2963 ucontrol->value.integer.value[0] =
2964 max - ucontrol->value.integer.value[0];
2965 ucontrol->value.integer.value[0] =
2966 ucontrol->value.integer.value[0] - min;
2967
2968 return 0;
2969}
2970EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
2971
2972/**
2793 * snd_soc_limit_volume - Set new limit to an existing volume control. 2973 * snd_soc_limit_volume - Set new limit to an existing volume control.
2794 * 2974 *
2795 * @codec: where to look for the control 2975 * @codec: where to look for the control
@@ -3346,6 +3526,12 @@ int snd_soc_register_card(struct snd_soc_card *card)
3346 link->name); 3526 link->name);
3347 return -EINVAL; 3527 return -EINVAL;
3348 } 3528 }
3529 /* Codec DAI name must be specified */
3530 if (!link->codec_dai_name) {
3531 dev_err(card->dev, "codec_dai_name not set for %s\n",
3532 link->name);
3533 return -EINVAL;
3534 }
3349 3535
3350 /* 3536 /*
3351 * Platform may be specified by either name or OF node, but 3537 * Platform may be specified by either name or OF node, but
@@ -3358,12 +3544,24 @@ int snd_soc_register_card(struct snd_soc_card *card)
3358 } 3544 }
3359 3545
3360 /* 3546 /*
3361 * CPU DAI must be specified by 1 of name or OF node, 3547 * CPU device may be specified by either name or OF node, but
3362 * not both or neither. 3548 * can be left unspecified, and will be matched based on DAI
3549 * name alone..
3550 */
3551 if (link->cpu_name && link->cpu_of_node) {
3552 dev_err(card->dev,
3553 "Neither/both cpu name/of_node are set for %s\n",
3554 link->name);
3555 return -EINVAL;
3556 }
3557 /*
3558 * At least one of CPU DAI name or CPU device name/node must be
3559 * specified
3363 */ 3560 */
3364 if (!!link->cpu_dai_name == !!link->cpu_dai_of_node) { 3561 if (!link->cpu_dai_name &&
3562 !(link->cpu_name || link->cpu_of_node)) {
3365 dev_err(card->dev, 3563 dev_err(card->dev,
3366 "Neither/both cpu_dai name/of_node are set for %s\n", 3564 "Neither cpu_dai_name nor cpu_name/of_node are set for %s\n",
3367 link->name); 3565 link->name);
3368 return -EINVAL; 3566 return -EINVAL;
3369 } 3567 }
@@ -3938,6 +4136,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
3938 dev_err(card->dev, 4136 dev_err(card->dev,
3939 "Property '%s' index %d could not be read: %d\n", 4137 "Property '%s' index %d could not be read: %d\n",
3940 propname, 2 * i, ret); 4138 propname, 2 * i, ret);
4139 kfree(routes);
3941 return -EINVAL; 4140 return -EINVAL;
3942 } 4141 }
3943 ret = of_property_read_string_index(np, propname, 4142 ret = of_property_read_string_index(np, propname,
@@ -3946,6 +4145,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
3946 dev_err(card->dev, 4145 dev_err(card->dev,
3947 "Property '%s' index %d could not be read: %d\n", 4146 "Property '%s' index %d could not be read: %d\n",
3948 propname, (2 * i) + 1, ret); 4147 propname, (2 * i) + 1, ret);
4148 kfree(routes);
3949 return -EINVAL; 4149 return -EINVAL;
3950 } 4150 }
3951 } 4151 }
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 89eae93445c..f7a13f72052 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -35,6 +35,7 @@
35#include <linux/debugfs.h> 35#include <linux/debugfs.h>
36#include <linux/pm_runtime.h> 36#include <linux/pm_runtime.h>
37#include <linux/regulator/consumer.h> 37#include <linux/regulator/consumer.h>
38#include <linux/clk.h>
38#include <linux/slab.h> 39#include <linux/slab.h>
39#include <sound/core.h> 40#include <sound/core.h>
40#include <sound/pcm.h> 41#include <sound/pcm.h>
@@ -51,6 +52,7 @@ static int dapm_up_seq[] = {
51 [snd_soc_dapm_pre] = 0, 52 [snd_soc_dapm_pre] = 0,
52 [snd_soc_dapm_supply] = 1, 53 [snd_soc_dapm_supply] = 1,
53 [snd_soc_dapm_regulator_supply] = 1, 54 [snd_soc_dapm_regulator_supply] = 1,
55 [snd_soc_dapm_clock_supply] = 1,
54 [snd_soc_dapm_micbias] = 2, 56 [snd_soc_dapm_micbias] = 2,
55 [snd_soc_dapm_dai_link] = 2, 57 [snd_soc_dapm_dai_link] = 2,
56 [snd_soc_dapm_dai] = 3, 58 [snd_soc_dapm_dai] = 3,
@@ -92,6 +94,7 @@ static int dapm_down_seq[] = {
92 [snd_soc_dapm_aif_out] = 10, 94 [snd_soc_dapm_aif_out] = 10,
93 [snd_soc_dapm_dai] = 10, 95 [snd_soc_dapm_dai] = 10,
94 [snd_soc_dapm_dai_link] = 11, 96 [snd_soc_dapm_dai_link] = 11,
97 [snd_soc_dapm_clock_supply] = 12,
95 [snd_soc_dapm_regulator_supply] = 12, 98 [snd_soc_dapm_regulator_supply] = 12,
96 [snd_soc_dapm_supply] = 12, 99 [snd_soc_dapm_supply] = 12,
97 [snd_soc_dapm_post] = 13, 100 [snd_soc_dapm_post] = 13,
@@ -391,6 +394,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
391 case snd_soc_dapm_vmid: 394 case snd_soc_dapm_vmid:
392 case snd_soc_dapm_supply: 395 case snd_soc_dapm_supply:
393 case snd_soc_dapm_regulator_supply: 396 case snd_soc_dapm_regulator_supply:
397 case snd_soc_dapm_clock_supply:
394 case snd_soc_dapm_aif_in: 398 case snd_soc_dapm_aif_in:
395 case snd_soc_dapm_aif_out: 399 case snd_soc_dapm_aif_out:
396 case snd_soc_dapm_dai: 400 case snd_soc_dapm_dai:
@@ -764,6 +768,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
764 switch (widget->id) { 768 switch (widget->id) {
765 case snd_soc_dapm_supply: 769 case snd_soc_dapm_supply:
766 case snd_soc_dapm_regulator_supply: 770 case snd_soc_dapm_regulator_supply:
771 case snd_soc_dapm_clock_supply:
767 return 0; 772 return 0;
768 default: 773 default:
769 break; 774 break;
@@ -850,6 +855,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
850 switch (widget->id) { 855 switch (widget->id) {
851 case snd_soc_dapm_supply: 856 case snd_soc_dapm_supply:
852 case snd_soc_dapm_regulator_supply: 857 case snd_soc_dapm_regulator_supply:
858 case snd_soc_dapm_clock_supply:
853 return 0; 859 return 0;
854 default: 860 default:
855 break; 861 break;
@@ -996,6 +1002,27 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
996} 1002}
997EXPORT_SYMBOL_GPL(dapm_regulator_event); 1003EXPORT_SYMBOL_GPL(dapm_regulator_event);
998 1004
1005/*
1006 * Handler for clock supply widget.
1007 */
1008int dapm_clock_event(struct snd_soc_dapm_widget *w,
1009 struct snd_kcontrol *kcontrol, int event)
1010{
1011 if (!w->clk)
1012 return -EIO;
1013
1014#ifdef CONFIG_HAVE_CLK
1015 if (SND_SOC_DAPM_EVENT_ON(event)) {
1016 return clk_enable(w->clk);
1017 } else {
1018 clk_disable(w->clk);
1019 return 0;
1020 }
1021#endif
1022 return 0;
1023}
1024EXPORT_SYMBOL_GPL(dapm_clock_event);
1025
999static int dapm_widget_power_check(struct snd_soc_dapm_widget *w) 1026static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)
1000{ 1027{
1001 if (w->power_checked) 1028 if (w->power_checked)
@@ -1487,6 +1514,7 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
1487 switch (w->id) { 1514 switch (w->id) {
1488 case snd_soc_dapm_supply: 1515 case snd_soc_dapm_supply:
1489 case snd_soc_dapm_regulator_supply: 1516 case snd_soc_dapm_regulator_supply:
1517 case snd_soc_dapm_clock_supply:
1490 /* Supplies can't affect their outputs, only their inputs */ 1518 /* Supplies can't affect their outputs, only their inputs */
1491 break; 1519 break;
1492 default: 1520 default:
@@ -1587,6 +1615,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1587 break; 1615 break;
1588 case snd_soc_dapm_supply: 1616 case snd_soc_dapm_supply:
1589 case snd_soc_dapm_regulator_supply: 1617 case snd_soc_dapm_regulator_supply:
1618 case snd_soc_dapm_clock_supply:
1590 case snd_soc_dapm_micbias: 1619 case snd_soc_dapm_micbias:
1591 if (d->target_bias_level < SND_SOC_BIAS_STANDBY) 1620 if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
1592 d->target_bias_level = SND_SOC_BIAS_STANDBY; 1621 d->target_bias_level = SND_SOC_BIAS_STANDBY;
@@ -1941,6 +1970,7 @@ static ssize_t dapm_widget_show(struct device *dev,
1941 case snd_soc_dapm_mixer_named_ctl: 1970 case snd_soc_dapm_mixer_named_ctl:
1942 case snd_soc_dapm_supply: 1971 case snd_soc_dapm_supply:
1943 case snd_soc_dapm_regulator_supply: 1972 case snd_soc_dapm_regulator_supply:
1973 case snd_soc_dapm_clock_supply:
1944 if (w->name) 1974 if (w->name)
1945 count += sprintf(buf + count, "%s: %s\n", 1975 count += sprintf(buf + count, "%s: %s\n",
1946 w->name, w->power ? "On":"Off"); 1976 w->name, w->power ? "On":"Off");
@@ -2187,6 +2217,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2187 case snd_soc_dapm_post: 2217 case snd_soc_dapm_post:
2188 case snd_soc_dapm_supply: 2218 case snd_soc_dapm_supply:
2189 case snd_soc_dapm_regulator_supply: 2219 case snd_soc_dapm_regulator_supply:
2220 case snd_soc_dapm_clock_supply:
2190 case snd_soc_dapm_aif_in: 2221 case snd_soc_dapm_aif_in:
2191 case snd_soc_dapm_aif_out: 2222 case snd_soc_dapm_aif_out:
2192 case snd_soc_dapm_dai: 2223 case snd_soc_dapm_dai:
@@ -2221,6 +2252,10 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
2221 path->connect = 0; 2252 path->connect = 0;
2222 return 0; 2253 return 0;
2223 } 2254 }
2255
2256 dapm_mark_dirty(wsource, "Route added");
2257 dapm_mark_dirty(wsink, "Route added");
2258
2224 return 0; 2259 return 0;
2225 2260
2226err: 2261err:
@@ -2230,6 +2265,59 @@ err:
2230 return ret; 2265 return ret;
2231} 2266}
2232 2267
2268static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
2269 const struct snd_soc_dapm_route *route)
2270{
2271 struct snd_soc_dapm_path *path, *p;
2272 const char *sink;
2273 const char *source;
2274 char prefixed_sink[80];
2275 char prefixed_source[80];
2276
2277 if (route->control) {
2278 dev_err(dapm->dev,
2279 "Removal of routes with controls not supported\n");
2280 return -EINVAL;
2281 }
2282
2283 if (dapm->codec && dapm->codec->name_prefix) {
2284 snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
2285 dapm->codec->name_prefix, route->sink);
2286 sink = prefixed_sink;
2287 snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
2288 dapm->codec->name_prefix, route->source);
2289 source = prefixed_source;
2290 } else {
2291 sink = route->sink;
2292 source = route->source;
2293 }
2294
2295 path = NULL;
2296 list_for_each_entry(p, &dapm->card->paths, list) {
2297 if (strcmp(p->source->name, source) != 0)
2298 continue;
2299 if (strcmp(p->sink->name, sink) != 0)
2300 continue;
2301 path = p;
2302 break;
2303 }
2304
2305 if (path) {
2306 dapm_mark_dirty(path->source, "Route removed");
2307 dapm_mark_dirty(path->sink, "Route removed");
2308
2309 list_del(&path->list);
2310 list_del(&path->list_sink);
2311 list_del(&path->list_source);
2312 kfree(path);
2313 } else {
2314 dev_warn(dapm->dev, "Route %s->%s does not exist\n",
2315 source, sink);
2316 }
2317
2318 return 0;
2319}
2320
2233/** 2321/**
2234 * snd_soc_dapm_add_routes - Add routes between DAPM widgets 2322 * snd_soc_dapm_add_routes - Add routes between DAPM widgets
2235 * @dapm: DAPM context 2323 * @dapm: DAPM context
@@ -2246,15 +2334,15 @@ err:
2246int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, 2334int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
2247 const struct snd_soc_dapm_route *route, int num) 2335 const struct snd_soc_dapm_route *route, int num)
2248{ 2336{
2249 int i, ret = 0; 2337 int i, r, ret = 0;
2250 2338
2251 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); 2339 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
2252 for (i = 0; i < num; i++) { 2340 for (i = 0; i < num; i++) {
2253 ret = snd_soc_dapm_add_route(dapm, route); 2341 r = snd_soc_dapm_add_route(dapm, route);
2254 if (ret < 0) { 2342 if (r < 0) {
2255 dev_err(dapm->dev, "Failed to add route %s->%s\n", 2343 dev_err(dapm->dev, "Failed to add route %s->%s\n",
2256 route->source, route->sink); 2344 route->source, route->sink);
2257 break; 2345 ret = r;
2258 } 2346 }
2259 route++; 2347 route++;
2260 } 2348 }
@@ -2264,6 +2352,30 @@ int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
2264} 2352}
2265EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes); 2353EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);
2266 2354
2355/**
2356 * snd_soc_dapm_del_routes - Remove routes between DAPM widgets
2357 * @dapm: DAPM context
2358 * @route: audio routes
2359 * @num: number of routes
2360 *
2361 * Removes routes from the DAPM context.
2362 */
2363int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm,
2364 const struct snd_soc_dapm_route *route, int num)
2365{
2366 int i, ret = 0;
2367
2368 mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
2369 for (i = 0; i < num; i++) {
2370 snd_soc_dapm_del_route(dapm, route);
2371 route++;
2372 }
2373 mutex_unlock(&dapm->card->dapm_mutex);
2374
2375 return ret;
2376}
2377EXPORT_SYMBOL_GPL(snd_soc_dapm_del_routes);
2378
2267static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm, 2379static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm,
2268 const struct snd_soc_dapm_route *route) 2380 const struct snd_soc_dapm_route *route)
2269{ 2381{
@@ -2434,23 +2546,20 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
2434 (struct soc_mixer_control *)kcontrol->private_value; 2546 (struct soc_mixer_control *)kcontrol->private_value;
2435 unsigned int reg = mc->reg; 2547 unsigned int reg = mc->reg;
2436 unsigned int shift = mc->shift; 2548 unsigned int shift = mc->shift;
2437 unsigned int rshift = mc->rshift;
2438 int max = mc->max; 2549 int max = mc->max;
2439 unsigned int invert = mc->invert;
2440 unsigned int mask = (1 << fls(max)) - 1; 2550 unsigned int mask = (1 << fls(max)) - 1;
2551 unsigned int invert = mc->invert;
2552
2553 if (snd_soc_volsw_is_stereo(mc))
2554 dev_warn(widget->dapm->dev,
2555 "Control '%s' is stereo, which is not supported\n",
2556 kcontrol->id.name);
2441 2557
2442 ucontrol->value.integer.value[0] = 2558 ucontrol->value.integer.value[0] =
2443 (snd_soc_read(widget->codec, reg) >> shift) & mask; 2559 (snd_soc_read(widget->codec, reg) >> shift) & mask;
2444 if (shift != rshift) 2560 if (invert)
2445 ucontrol->value.integer.value[1] =
2446 (snd_soc_read(widget->codec, reg) >> rshift) & mask;
2447 if (invert) {
2448 ucontrol->value.integer.value[0] = 2561 ucontrol->value.integer.value[0] =
2449 max - ucontrol->value.integer.value[0]; 2562 max - ucontrol->value.integer.value[0];
2450 if (shift != rshift)
2451 ucontrol->value.integer.value[1] =
2452 max - ucontrol->value.integer.value[1];
2453 }
2454 2563
2455 return 0; 2564 return 0;
2456} 2565}
@@ -2484,20 +2593,19 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
2484 struct snd_soc_dapm_update update; 2593 struct snd_soc_dapm_update update;
2485 int wi; 2594 int wi;
2486 2595
2596 if (snd_soc_volsw_is_stereo(mc))
2597 dev_warn(widget->dapm->dev,
2598 "Control '%s' is stereo, which is not supported\n",
2599 kcontrol->id.name);
2600
2487 val = (ucontrol->value.integer.value[0] & mask); 2601 val = (ucontrol->value.integer.value[0] & mask);
2602 connect = !!val;
2488 2603
2489 if (invert) 2604 if (invert)
2490 val = max - val; 2605 val = max - val;
2491 mask = mask << shift; 2606 mask = mask << shift;
2492 val = val << shift; 2607 val = val << shift;
2493 2608
2494 if (val)
2495 /* new connection */
2496 connect = invert ? 0 : 1;
2497 else
2498 /* old connection must be powered down */
2499 connect = invert ? 1 : 0;
2500
2501 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2609 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2502 2610
2503 change = snd_soc_test_bits(widget->codec, reg, mask, val); 2611 change = snd_soc_test_bits(widget->codec, reg, mask, val);
@@ -2873,6 +2981,19 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2873 return NULL; 2981 return NULL;
2874 } 2982 }
2875 break; 2983 break;
2984 case snd_soc_dapm_clock_supply:
2985#ifdef CONFIG_CLKDEV_LOOKUP
2986 w->clk = devm_clk_get(dapm->dev, w->name);
2987 if (IS_ERR(w->clk)) {
2988 ret = PTR_ERR(w->clk);
2989 dev_err(dapm->dev, "Failed to request %s: %d\n",
2990 w->name, ret);
2991 return NULL;
2992 }
2993#else
2994 return NULL;
2995#endif
2996 break;
2876 default: 2997 default:
2877 break; 2998 break;
2878 } 2999 }
@@ -2924,6 +3045,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
2924 break; 3045 break;
2925 case snd_soc_dapm_supply: 3046 case snd_soc_dapm_supply:
2926 case snd_soc_dapm_regulator_supply: 3047 case snd_soc_dapm_regulator_supply:
3048 case snd_soc_dapm_clock_supply:
2927 w->power_check = dapm_supply_check_power; 3049 w->power_check = dapm_supply_check_power;
2928 break; 3050 break;
2929 case snd_soc_dapm_dai: 3051 case snd_soc_dapm_dai:
diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c
index 475695234b3..5df529eda25 100644
--- a/sound/soc/soc-dmaengine-pcm.c
+++ b/sound/soc/soc-dmaengine-pcm.c
@@ -30,6 +30,7 @@
30 30
31struct dmaengine_pcm_runtime_data { 31struct dmaengine_pcm_runtime_data {
32 struct dma_chan *dma_chan; 32 struct dma_chan *dma_chan;
33 dma_cookie_t cookie;
33 34
34 unsigned int pos; 35 unsigned int pos;
35 36
@@ -153,7 +154,7 @@ static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
153 154
154 desc->callback = dmaengine_pcm_dma_complete; 155 desc->callback = dmaengine_pcm_dma_complete;
155 desc->callback_param = substream; 156 desc->callback_param = substream;
156 dmaengine_submit(desc); 157 prtd->cookie = dmaengine_submit(desc);
157 158
158 return 0; 159 return 0;
159} 160}
@@ -200,6 +201,20 @@ int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
200EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger); 201EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger);
201 202
202/** 203/**
204 * snd_dmaengine_pcm_pointer_no_residue - dmaengine based PCM pointer implementation
205 * @substream: PCM substream
206 *
207 * This function is deprecated and should not be used by new drivers, as its
208 * results may be unreliable.
209 */
210snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream)
211{
212 struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
213 return bytes_to_frames(substream->runtime, prtd->pos);
214}
215EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer_no_residue);
216
217/**
203 * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation 218 * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation
204 * @substream: PCM substream 219 * @substream: PCM substream
205 * 220 *
@@ -209,7 +224,19 @@ EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger);
209snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) 224snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
210{ 225{
211 struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); 226 struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
212 return bytes_to_frames(substream->runtime, prtd->pos); 227 struct dma_tx_state state;
228 enum dma_status status;
229 unsigned int buf_size;
230 unsigned int pos = 0;
231
232 status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state);
233 if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) {
234 buf_size = snd_pcm_lib_buffer_bytes(substream);
235 if (state.residue > 0 && state.residue <= buf_size)
236 pos = buf_size - state.residue;
237 }
238
239 return bytes_to_frames(substream->runtime, pos);
213} 240}
214EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); 241EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer);
215 242
@@ -243,7 +270,7 @@ static int dmaengine_pcm_request_channel(struct dmaengine_pcm_runtime_data *prtd
243 * Note that this function will use private_data field of the substream's 270 * Note that this function will use private_data field of the substream's
244 * runtime. So it is not availabe to your pcm driver implementation. If you need 271 * runtime. So it is not availabe to your pcm driver implementation. If you need
245 * to keep additional data attached to a substream use 272 * to keep additional data attached to a substream use
246 * snd_dmaeinge_pcm_{set,get}_data. 273 * snd_dmaengine_pcm_{set,get}_data.
247 */ 274 */
248int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, 275int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
249 dma_filter_fn filter_fn, void *filter_data) 276 dma_filter_fn filter_fn, void *filter_data)
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
index 4d8dc6a27d4..29183ef2b93 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -142,11 +142,16 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
142 case SND_SOC_REGMAP: 142 case SND_SOC_REGMAP:
143 /* Device has made its own regmap arrangements */ 143 /* Device has made its own regmap arrangements */
144 codec->using_regmap = true; 144 codec->using_regmap = true;
145 145 if (!codec->control_data)
146 ret = regmap_get_val_bytes(codec->control_data); 146 codec->control_data = dev_get_regmap(codec->dev, NULL);
147 /* Errors are legitimate for non-integer byte multiples */ 147
148 if (ret > 0) 148 if (codec->control_data) {
149 codec->val_bytes = ret; 149 ret = regmap_get_val_bytes(codec->control_data);
150 /* Errors are legitimate for non-integer byte
151 * multiples */
152 if (ret > 0)
153 codec->val_bytes = ret;
154 }
150 break; 155 break;
151 156
152 default: 157 default:
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 48fd15b312c..ef22d0bd9e9 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1955,10 +1955,8 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream)
1955 fe->dpcm[stream].runtime = fe_substream->runtime; 1955 fe->dpcm[stream].runtime = fe_substream->runtime;
1956 1956
1957 if (dpcm_path_get(fe, stream, &list) <= 0) { 1957 if (dpcm_path_get(fe, stream, &list) <= 0) {
1958 dev_warn(fe->dev, "asoc: %s no valid %s route\n", 1958 dev_dbg(fe->dev, "asoc: %s no valid %s route\n",
1959 fe->dai_link->name, stream ? "capture" : "playback"); 1959 fe->dai_link->name, stream ? "capture" : "playback");
1960 mutex_unlock(&fe->card->mutex);
1961 return -EINVAL;
1962 } 1960 }
1963 1961
1964 /* calculate valid and active FE <-> BE dpcms */ 1962 /* calculate valid and active FE <-> BE dpcms */
@@ -2003,7 +2001,6 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream)
2003/* create a new pcm */ 2001/* create a new pcm */
2004int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) 2002int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
2005{ 2003{
2006 struct snd_soc_codec *codec = rtd->codec;
2007 struct snd_soc_platform *platform = rtd->platform; 2004 struct snd_soc_platform *platform = rtd->platform;
2008 struct snd_soc_dai *codec_dai = rtd->codec_dai; 2005 struct snd_soc_dai *codec_dai = rtd->codec_dai;
2009 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 2006 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
@@ -2042,7 +2039,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
2042 capture, &pcm); 2039 capture, &pcm);
2043 } 2040 }
2044 if (ret < 0) { 2041 if (ret < 0) {
2045 printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name); 2042 dev_err(rtd->card->dev, "can't create pcm for %s\n",
2043 rtd->dai_link->name);
2046 return ret; 2044 return ret;
2047 } 2045 }
2048 dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num, new_name); 2046 dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num, new_name);
@@ -2099,14 +2097,14 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
2099 if (platform->driver->pcm_new) { 2097 if (platform->driver->pcm_new) {
2100 ret = platform->driver->pcm_new(rtd); 2098 ret = platform->driver->pcm_new(rtd);
2101 if (ret < 0) { 2099 if (ret < 0) {
2102 pr_err("asoc: platform pcm constructor failed\n"); 2100 dev_err(platform->dev, "pcm constructor failed\n");
2103 return ret; 2101 return ret;
2104 } 2102 }
2105 } 2103 }
2106 2104
2107 pcm->private_free = platform->driver->pcm_free; 2105 pcm->private_free = platform->driver->pcm_free;
2108out: 2106out:
2109 printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name, 2107 dev_info(rtd->card->dev, " %s <-> %s mapping ok\n", codec_dai->name,
2110 cpu_dai->name); 2108 cpu_dai->name);
2111 return ret; 2109 return ret;
2112} 2110}
diff --git a/sound/soc/spear/spdif_in.c b/sound/soc/spear/spdif_in.c
new file mode 100644
index 00000000000..c7c4b20395b
--- /dev/null
+++ b/sound/soc/spear/spdif_in.c
@@ -0,0 +1,297 @@
1/*
2 * ALSA SoC SPDIF In Audio Layer for spear processors
3 *
4 * Copyright (C) 2012 ST Microelectronics
5 * Vipin Kumar <vipin.kumar@st.com>
6 *
7 * This file is licensed under the terms of the GNU General Public
8 * License version 2. This program is licensed "as is" without any
9 * warranty of any kind, whether express or implied.
10 */
11
12#include <linux/clk.h>
13#include <linux/delay.h>
14#include <linux/device.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/io.h>
18#include <linux/ioport.h>
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <sound/pcm.h>
22#include <sound/pcm_params.h>
23#include <sound/soc.h>
24#include <sound/spear_dma.h>
25#include <sound/spear_spdif.h>
26#include "spdif_in_regs.h"
27
28struct spdif_in_params {
29 u32 format;
30};
31
32struct spdif_in_dev {
33 struct clk *clk;
34 struct spear_dma_data dma_params;
35 struct spdif_in_params saved_params;
36 void *io_base;
37 struct device *dev;
38 void (*reset_perip)(void);
39 int irq;
40};
41
42static void spdif_in_configure(struct spdif_in_dev *host)
43{
44 u32 ctrl = SPDIF_IN_PRTYEN | SPDIF_IN_STATEN | SPDIF_IN_USREN |
45 SPDIF_IN_VALEN | SPDIF_IN_BLKEN;
46 ctrl |= SPDIF_MODE_16BIT | SPDIF_FIFO_THRES_16;
47
48 writel(ctrl, host->io_base + SPDIF_IN_CTRL);
49 writel(0xF, host->io_base + SPDIF_IN_IRQ_MASK);
50}
51
52static int spdif_in_startup(struct snd_pcm_substream *substream,
53 struct snd_soc_dai *cpu_dai)
54{
55 struct spdif_in_dev *host = snd_soc_dai_get_drvdata(cpu_dai);
56
57 if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
58 return -EINVAL;
59
60 snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)&host->dma_params);
61 return 0;
62}
63
64static void spdif_in_shutdown(struct snd_pcm_substream *substream,
65 struct snd_soc_dai *dai)
66{
67 struct spdif_in_dev *host = snd_soc_dai_get_drvdata(dai);
68
69 if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
70 return;
71
72 writel(0x0, host->io_base + SPDIF_IN_IRQ_MASK);
73 snd_soc_dai_set_dma_data(dai, substream, NULL);
74}
75
76static void spdif_in_format(struct spdif_in_dev *host, u32 format)
77{
78 u32 ctrl = readl(host->io_base + SPDIF_IN_CTRL);
79
80 switch (format) {
81 case SNDRV_PCM_FORMAT_S16_LE:
82 ctrl |= SPDIF_XTRACT_16BIT;
83 break;
84
85 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
86 ctrl &= ~SPDIF_XTRACT_16BIT;
87 break;
88 }
89
90 writel(ctrl, host->io_base + SPDIF_IN_CTRL);
91}
92
93static int spdif_in_hw_params(struct snd_pcm_substream *substream,
94 struct snd_pcm_hw_params *params,
95 struct snd_soc_dai *dai)
96{
97 struct spdif_in_dev *host = snd_soc_dai_get_drvdata(dai);
98 u32 format;
99
100 if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
101 return -EINVAL;
102
103 format = params_format(params);
104 host->saved_params.format = format;
105
106 return 0;
107}
108
109static int spdif_in_trigger(struct snd_pcm_substream *substream, int cmd,
110 struct snd_soc_dai *dai)
111{
112 struct spdif_in_dev *host = snd_soc_dai_get_drvdata(dai);
113 u32 ctrl;
114 int ret = 0;
115
116 if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
117 return -EINVAL;
118
119 switch (cmd) {
120 case SNDRV_PCM_TRIGGER_START:
121 case SNDRV_PCM_TRIGGER_RESUME:
122 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
123 clk_enable(host->clk);
124 spdif_in_configure(host);
125 spdif_in_format(host, host->saved_params.format);
126
127 ctrl = readl(host->io_base + SPDIF_IN_CTRL);
128 ctrl |= SPDIF_IN_SAMPLE | SPDIF_IN_ENB;
129 writel(ctrl, host->io_base + SPDIF_IN_CTRL);
130 writel(0xF, host->io_base + SPDIF_IN_IRQ_MASK);
131 break;
132
133 case SNDRV_PCM_TRIGGER_STOP:
134 case SNDRV_PCM_TRIGGER_SUSPEND:
135 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
136 ctrl = readl(host->io_base + SPDIF_IN_CTRL);
137 ctrl &= ~(SPDIF_IN_SAMPLE | SPDIF_IN_ENB);
138 writel(ctrl, host->io_base + SPDIF_IN_CTRL);
139 writel(0x0, host->io_base + SPDIF_IN_IRQ_MASK);
140
141 if (host->reset_perip)
142 host->reset_perip();
143 clk_disable(host->clk);
144 break;
145
146 default:
147 ret = -EINVAL;
148 break;
149 }
150 return ret;
151}
152
153static struct snd_soc_dai_ops spdif_in_dai_ops = {
154 .startup = spdif_in_startup,
155 .shutdown = spdif_in_shutdown,
156 .trigger = spdif_in_trigger,
157 .hw_params = spdif_in_hw_params,
158};
159
160struct snd_soc_dai_driver spdif_in_dai = {
161 .capture = {
162 .channels_min = 2,
163 .channels_max = 2,
164 .rates = (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
165 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | \
166 SNDRV_PCM_RATE_192000),
167 .formats = SNDRV_PCM_FMTBIT_S16_LE | \
168 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE,
169 },
170 .ops = &spdif_in_dai_ops,
171};
172
173static irqreturn_t spdif_in_irq(int irq, void *arg)
174{
175 struct spdif_in_dev *host = (struct spdif_in_dev *)arg;
176
177 u32 irq_status = readl(host->io_base + SPDIF_IN_IRQ);
178
179 if (!irq_status)
180 return IRQ_NONE;
181
182 if (irq_status & SPDIF_IRQ_FIFOWRITE)
183 dev_err(host->dev, "spdif in: fifo write error");
184 if (irq_status & SPDIF_IRQ_EMPTYFIFOREAD)
185 dev_err(host->dev, "spdif in: empty fifo read error");
186 if (irq_status & SPDIF_IRQ_FIFOFULL)
187 dev_err(host->dev, "spdif in: fifo full error");
188 if (irq_status & SPDIF_IRQ_OUTOFRANGE)
189 dev_err(host->dev, "spdif in: out of range error");
190
191 writel(0, host->io_base + SPDIF_IN_IRQ);
192
193 return IRQ_HANDLED;
194}
195
196static int spdif_in_probe(struct platform_device *pdev)
197{
198 struct spdif_in_dev *host;
199 struct spear_spdif_platform_data *pdata;
200 struct resource *res, *res_fifo;
201 int ret;
202
203 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
204 if (!res)
205 return -EINVAL;
206
207 res_fifo = platform_get_resource(pdev, IORESOURCE_IO, 0);
208 if (!res_fifo)
209 return -EINVAL;
210
211 if (!devm_request_mem_region(&pdev->dev, res->start,
212 resource_size(res), pdev->name)) {
213 dev_warn(&pdev->dev, "Failed to get memory resourse\n");
214 return -ENOENT;
215 }
216
217 host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
218 if (!host) {
219 dev_warn(&pdev->dev, "kzalloc fail\n");
220 return -ENOMEM;
221 }
222
223 host->io_base = devm_ioremap(&pdev->dev, res->start,
224 resource_size(res));
225 if (!host->io_base) {
226 dev_warn(&pdev->dev, "ioremap failed\n");
227 return -ENOMEM;
228 }
229
230 host->irq = platform_get_irq(pdev, 0);
231 if (host->irq < 0)
232 return -EINVAL;
233
234 host->clk = clk_get(&pdev->dev, NULL);
235 if (IS_ERR(host->clk))
236 return PTR_ERR(host->clk);
237
238 pdata = dev_get_platdata(&pdev->dev);
239
240 if (!pdata)
241 return -EINVAL;
242
243 host->dma_params.data = pdata->dma_params;
244 host->dma_params.addr = res_fifo->start;
245 host->dma_params.max_burst = 16;
246 host->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
247 host->dma_params.filter = pdata->filter;
248 host->reset_perip = pdata->reset_perip;
249
250 host->dev = &pdev->dev;
251 dev_set_drvdata(&pdev->dev, host);
252
253 ret = devm_request_irq(&pdev->dev, host->irq, spdif_in_irq, 0,
254 "spdif-in", host);
255 if (ret) {
256 clk_put(host->clk);
257 dev_warn(&pdev->dev, "request_irq failed\n");
258 return ret;
259 }
260
261 ret = snd_soc_register_dai(&pdev->dev, &spdif_in_dai);
262 if (ret != 0) {
263 clk_put(host->clk);
264 return ret;
265 }
266
267 return 0;
268}
269
270static int spdif_in_remove(struct platform_device *pdev)
271{
272 struct spdif_in_dev *host = dev_get_drvdata(&pdev->dev);
273
274 snd_soc_unregister_dai(&pdev->dev);
275 dev_set_drvdata(&pdev->dev, NULL);
276
277 clk_put(host->clk);
278
279 return 0;
280}
281
282
283static struct platform_driver spdif_in_driver = {
284 .probe = spdif_in_probe,
285 .remove = spdif_in_remove,
286 .driver = {
287 .name = "spdif-in",
288 .owner = THIS_MODULE,
289 },
290};
291
292module_platform_driver(spdif_in_driver);
293
294MODULE_AUTHOR("Vipin Kumar <vipin.kumar@st.com>");
295MODULE_DESCRIPTION("SPEAr SPDIF IN SoC Interface");
296MODULE_LICENSE("GPL");
297MODULE_ALIAS("platform:spdif_in");
diff --git a/sound/soc/spear/spdif_in_regs.h b/sound/soc/spear/spdif_in_regs.h
new file mode 100644
index 00000000000..37af7bc66b7
--- /dev/null
+++ b/sound/soc/spear/spdif_in_regs.h
@@ -0,0 +1,60 @@
1/*
2 * SPEAr SPDIF IN controller header file
3 *
4 * Copyright (ST) 2011 Vipin Kumar (vipin.kumar@st.com)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#ifndef SPDIF_IN_REGS_H
22#define SPDIF_IN_REGS_H
23
24#define SPDIF_IN_CTRL 0x00
25 #define SPDIF_IN_PRTYEN (1 << 20)
26 #define SPDIF_IN_STATEN (1 << 19)
27 #define SPDIF_IN_USREN (1 << 18)
28 #define SPDIF_IN_VALEN (1 << 17)
29 #define SPDIF_IN_BLKEN (1 << 16)
30
31 #define SPDIF_MODE_24BIT (8 << 12)
32 #define SPDIF_MODE_23BIT (7 << 12)
33 #define SPDIF_MODE_22BIT (6 << 12)
34 #define SPDIF_MODE_21BIT (5 << 12)
35 #define SPDIF_MODE_20BIT (4 << 12)
36 #define SPDIF_MODE_19BIT (3 << 12)
37 #define SPDIF_MODE_18BIT (2 << 12)
38 #define SPDIF_MODE_17BIT (1 << 12)
39 #define SPDIF_MODE_16BIT (0 << 12)
40 #define SPDIF_MODE_MASK (0x0F << 12)
41
42 #define SPDIF_IN_VALID (1 << 11)
43 #define SPDIF_IN_SAMPLE (1 << 10)
44 #define SPDIF_DATA_SWAP (1 << 9)
45 #define SPDIF_IN_ENB (1 << 8)
46 #define SPDIF_DATA_REVERT (1 << 7)
47 #define SPDIF_XTRACT_16BIT (1 << 6)
48 #define SPDIF_FIFO_THRES_16 (16 << 0)
49
50#define SPDIF_IN_IRQ_MASK 0x04
51#define SPDIF_IN_IRQ 0x08
52 #define SPDIF_IRQ_FIFOWRITE (1 << 0)
53 #define SPDIF_IRQ_EMPTYFIFOREAD (1 << 1)
54 #define SPDIF_IRQ_FIFOFULL (1 << 2)
55 #define SPDIF_IRQ_OUTOFRANGE (1 << 3)
56
57#define SPDIF_IN_STA 0x0C
58 #define SPDIF_IN_LOCK (0x1 << 0)
59
60#endif /* SPDIF_IN_REGS_H */
diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c
new file mode 100644
index 00000000000..5eac4cda2fd
--- /dev/null
+++ b/sound/soc/spear/spdif_out.c
@@ -0,0 +1,389 @@
1/*
2 * ALSA SoC SPDIF Out Audio Layer for spear processors
3 *
4 * Copyright (C) 2012 ST Microelectronics
5 * Vipin Kumar <vipin.kumar@st.com>
6 *
7 * This file is licensed under the terms of the GNU General Public
8 * License version 2. This program is licensed "as is" without any
9 * warranty of any kind, whether express or implied.
10 */
11
12#include <linux/clk.h>
13#include <linux/delay.h>
14#include <linux/device.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/io.h>
18#include <linux/ioport.h>
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <sound/soc.h>
22#include <sound/spear_dma.h>
23#include <sound/spear_spdif.h>
24#include "spdif_out_regs.h"
25
26struct spdif_out_params {
27 u32 rate;
28 u32 core_freq;
29 u32 mute;
30};
31
32struct spdif_out_dev {
33 struct clk *clk;
34 struct spear_dma_data dma_params;
35 struct spdif_out_params saved_params;
36 u32 running;
37 void __iomem *io_base;
38};
39
40static void spdif_out_configure(struct spdif_out_dev *host)
41{
42 writel(SPDIF_OUT_RESET, host->io_base + SPDIF_OUT_SOFT_RST);
43 mdelay(1);
44 writel(readl(host->io_base + SPDIF_OUT_SOFT_RST) & ~SPDIF_OUT_RESET,
45 host->io_base + SPDIF_OUT_SOFT_RST);
46
47 writel(SPDIF_OUT_FDMA_TRIG_16 | SPDIF_OUT_MEMFMT_16_16 |
48 SPDIF_OUT_VALID_HW | SPDIF_OUT_USER_HW |
49 SPDIF_OUT_CHNLSTA_HW | SPDIF_OUT_PARITY_HW,
50 host->io_base + SPDIF_OUT_CFG);
51
52 writel(0x7F, host->io_base + SPDIF_OUT_INT_STA_CLR);
53 writel(0x7F, host->io_base + SPDIF_OUT_INT_EN_CLR);
54}
55
56static int spdif_out_startup(struct snd_pcm_substream *substream,
57 struct snd_soc_dai *cpu_dai)
58{
59 struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai);
60 int ret;
61
62 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
63 return -EINVAL;
64
65 snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)&host->dma_params);
66
67 ret = clk_enable(host->clk);
68 if (ret)
69 return ret;
70
71 host->running = true;
72 spdif_out_configure(host);
73
74 return 0;
75}
76
77static void spdif_out_shutdown(struct snd_pcm_substream *substream,
78 struct snd_soc_dai *dai)
79{
80 struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai);
81
82 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
83 return;
84
85 clk_disable(host->clk);
86 host->running = false;
87 snd_soc_dai_set_dma_data(dai, substream, NULL);
88}
89
90static void spdif_out_clock(struct spdif_out_dev *host, u32 core_freq,
91 u32 rate)
92{
93 u32 divider, ctrl;
94
95 clk_set_rate(host->clk, core_freq);
96 divider = DIV_ROUND_CLOSEST(clk_get_rate(host->clk), (rate * 128));
97
98 ctrl = readl(host->io_base + SPDIF_OUT_CTRL);
99 ctrl &= ~SPDIF_DIVIDER_MASK;
100 ctrl |= (divider << SPDIF_DIVIDER_SHIFT) & SPDIF_DIVIDER_MASK;
101 writel(ctrl, host->io_base + SPDIF_OUT_CTRL);
102}
103
104static int spdif_out_hw_params(struct snd_pcm_substream *substream,
105 struct snd_pcm_hw_params *params,
106 struct snd_soc_dai *dai)
107{
108 struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai);
109 u32 rate, core_freq;
110
111 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
112 return -EINVAL;
113
114 rate = params_rate(params);
115
116 switch (rate) {
117 case 8000:
118 case 16000:
119 case 32000:
120 case 64000:
121 /*
122 * The clock is multiplied by 10 to bring it to feasible range
123 * of frequencies for sscg
124 */
125 core_freq = 64000 * 128 * 10; /* 81.92 MHz */
126 break;
127 case 5512:
128 case 11025:
129 case 22050:
130 case 44100:
131 case 88200:
132 case 176400:
133 core_freq = 176400 * 128; /* 22.5792 MHz */
134 break;
135 case 48000:
136 case 96000:
137 case 192000:
138 default:
139 core_freq = 192000 * 128; /* 24.576 MHz */
140 break;
141 }
142
143 spdif_out_clock(host, core_freq, rate);
144 host->saved_params.core_freq = core_freq;
145 host->saved_params.rate = rate;
146
147 return 0;
148}
149
150static int spdif_out_trigger(struct snd_pcm_substream *substream, int cmd,
151 struct snd_soc_dai *dai)
152{
153 struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai);
154 u32 ctrl;
155 int ret = 0;
156
157 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
158 return -EINVAL;
159
160 switch (cmd) {
161 case SNDRV_PCM_TRIGGER_START:
162 case SNDRV_PCM_TRIGGER_RESUME:
163 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
164 ctrl = readl(host->io_base + SPDIF_OUT_CTRL);
165 ctrl &= ~SPDIF_OPMODE_MASK;
166 if (!host->saved_params.mute)
167 ctrl |= SPDIF_OPMODE_AUD_DATA |
168 SPDIF_STATE_NORMAL;
169 else
170 ctrl |= SPDIF_OPMODE_MUTE_PCM;
171 writel(ctrl, host->io_base + SPDIF_OUT_CTRL);
172 break;
173
174 case SNDRV_PCM_TRIGGER_STOP:
175 case SNDRV_PCM_TRIGGER_SUSPEND:
176 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
177 ctrl = readl(host->io_base + SPDIF_OUT_CTRL);
178 ctrl &= ~SPDIF_OPMODE_MASK;
179 ctrl |= SPDIF_OPMODE_OFF;
180 writel(ctrl, host->io_base + SPDIF_OUT_CTRL);
181 break;
182
183 default:
184 ret = -EINVAL;
185 break;
186 }
187 return ret;
188}
189
190static int spdif_digital_mute(struct snd_soc_dai *dai, int mute)
191{
192 struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai);
193 u32 val;
194
195 host->saved_params.mute = mute;
196 val = readl(host->io_base + SPDIF_OUT_CTRL);
197 val &= ~SPDIF_OPMODE_MASK;
198
199 if (mute)
200 val |= SPDIF_OPMODE_MUTE_PCM;
201 else {
202 if (host->running)
203 val |= SPDIF_OPMODE_AUD_DATA | SPDIF_STATE_NORMAL;
204 else
205 val |= SPDIF_OPMODE_OFF;
206 }
207
208 writel(val, host->io_base + SPDIF_OUT_CTRL);
209 return 0;
210}
211
212static int spdif_mute_get(struct snd_kcontrol *kcontrol,
213 struct snd_ctl_elem_value *ucontrol)
214{
215 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
216 struct snd_soc_card *card = codec->card;
217 struct snd_soc_pcm_runtime *rtd = card->rtd;
218 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
219 struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai);
220
221 ucontrol->value.integer.value[0] = host->saved_params.mute;
222 return 0;
223}
224
225static int spdif_mute_put(struct snd_kcontrol *kcontrol,
226 struct snd_ctl_elem_value *ucontrol)
227{
228 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
229 struct snd_soc_card *card = codec->card;
230 struct snd_soc_pcm_runtime *rtd = card->rtd;
231 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
232 struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai);
233
234 if (host->saved_params.mute == ucontrol->value.integer.value[0])
235 return 0;
236
237 spdif_digital_mute(cpu_dai, ucontrol->value.integer.value[0]);
238
239 return 1;
240}
241static const struct snd_kcontrol_new spdif_out_controls[] = {
242 SOC_SINGLE_BOOL_EXT("IEC958 Playback Switch", 0,
243 spdif_mute_get, spdif_mute_put),
244};
245
246int spdif_soc_dai_probe(struct snd_soc_dai *dai)
247{
248 return snd_soc_add_dai_controls(dai, spdif_out_controls,
249 ARRAY_SIZE(spdif_out_controls));
250}
251
252static const struct snd_soc_dai_ops spdif_out_dai_ops = {
253 .digital_mute = spdif_digital_mute,
254 .startup = spdif_out_startup,
255 .shutdown = spdif_out_shutdown,
256 .trigger = spdif_out_trigger,
257 .hw_params = spdif_out_hw_params,
258};
259
260static struct snd_soc_dai_driver spdif_out_dai = {
261 .playback = {
262 .channels_min = 2,
263 .channels_max = 2,
264 .rates = (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
265 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | \
266 SNDRV_PCM_RATE_192000),
267 .formats = SNDRV_PCM_FMTBIT_S16_LE,
268 },
269 .probe = spdif_soc_dai_probe,
270 .ops = &spdif_out_dai_ops,
271};
272
273static int spdif_out_probe(struct platform_device *pdev)
274{
275 struct spdif_out_dev *host;
276 struct spear_spdif_platform_data *pdata;
277 struct resource *res;
278 int ret;
279
280 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
281 if (!res)
282 return -EINVAL;
283
284 if (!devm_request_mem_region(&pdev->dev, res->start,
285 resource_size(res), pdev->name)) {
286 dev_warn(&pdev->dev, "Failed to get memory resourse\n");
287 return -ENOENT;
288 }
289
290 host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
291 if (!host) {
292 dev_warn(&pdev->dev, "kzalloc fail\n");
293 return -ENOMEM;
294 }
295
296 host->io_base = devm_ioremap(&pdev->dev, res->start,
297 resource_size(res));
298 if (!host->io_base) {
299 dev_warn(&pdev->dev, "ioremap failed\n");
300 return -ENOMEM;
301 }
302
303 host->clk = clk_get(&pdev->dev, NULL);
304 if (IS_ERR(host->clk))
305 return PTR_ERR(host->clk);
306
307 pdata = dev_get_platdata(&pdev->dev);
308
309 host->dma_params.data = pdata->dma_params;
310 host->dma_params.addr = res->start + SPDIF_OUT_FIFO_DATA;
311 host->dma_params.max_burst = 16;
312 host->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
313 host->dma_params.filter = pdata->filter;
314
315 dev_set_drvdata(&pdev->dev, host);
316
317 ret = snd_soc_register_dai(&pdev->dev, &spdif_out_dai);
318 if (ret != 0) {
319 clk_put(host->clk);
320 return ret;
321 }
322
323 return 0;
324}
325
326static int spdif_out_remove(struct platform_device *pdev)
327{
328 struct spdif_out_dev *host = dev_get_drvdata(&pdev->dev);
329
330 snd_soc_unregister_dai(&pdev->dev);
331 dev_set_drvdata(&pdev->dev, NULL);
332
333 clk_put(host->clk);
334
335 return 0;
336}
337
338#ifdef CONFIG_PM
339static int spdif_out_suspend(struct device *dev)
340{
341 struct platform_device *pdev = to_platform_device(dev);
342 struct spdif_out_dev *host = dev_get_drvdata(&pdev->dev);
343
344 if (host->running)
345 clk_disable(host->clk);
346
347 return 0;
348}
349
350static int spdif_out_resume(struct device *dev)
351{
352 struct platform_device *pdev = to_platform_device(dev);
353 struct spdif_out_dev *host = dev_get_drvdata(&pdev->dev);
354
355 if (host->running) {
356 clk_enable(host->clk);
357 spdif_out_configure(host);
358 spdif_out_clock(host, host->saved_params.core_freq,
359 host->saved_params.rate);
360 }
361 return 0;
362}
363
364static SIMPLE_DEV_PM_OPS(spdif_out_dev_pm_ops, spdif_out_suspend, \
365 spdif_out_resume);
366
367#define SPDIF_OUT_DEV_PM_OPS (&spdif_out_dev_pm_ops)
368
369#else
370#define SPDIF_OUT_DEV_PM_OPS NULL
371
372#endif
373
374static struct platform_driver spdif_out_driver = {
375 .probe = spdif_out_probe,
376 .remove = spdif_out_remove,
377 .driver = {
378 .name = "spdif-out",
379 .owner = THIS_MODULE,
380 .pm = SPDIF_OUT_DEV_PM_OPS,
381 },
382};
383
384module_platform_driver(spdif_out_driver);
385
386MODULE_AUTHOR("Vipin Kumar <vipin.kumar@st.com>");
387MODULE_DESCRIPTION("SPEAr SPDIF OUT SoC Interface");
388MODULE_LICENSE("GPL");
389MODULE_ALIAS("platform:spdif_out");
diff --git a/sound/soc/spear/spdif_out_regs.h b/sound/soc/spear/spdif_out_regs.h
new file mode 100644
index 00000000000..a5e53324b45
--- /dev/null
+++ b/sound/soc/spear/spdif_out_regs.h
@@ -0,0 +1,79 @@
1/*
2 * SPEAr SPDIF OUT controller header file
3 *
4 * Copyright (ST) 2011 Vipin Kumar (vipin.kumar@st.com)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#ifndef SPDIF_OUT_REGS_H
22#define SPDIF_OUT_REGS_H
23
24#define SPDIF_OUT_SOFT_RST 0x00
25 #define SPDIF_OUT_RESET (1 << 0)
26#define SPDIF_OUT_FIFO_DATA 0x04
27#define SPDIF_OUT_INT_STA 0x08
28#define SPDIF_OUT_INT_STA_CLR 0x0C
29 #define SPDIF_INT_UNDERFLOW (1 << 0)
30 #define SPDIF_INT_EODATA (1 << 1)
31 #define SPDIF_INT_EOBLOCK (1 << 2)
32 #define SPDIF_INT_EOLATENCY (1 << 3)
33 #define SPDIF_INT_EOPD_DATA (1 << 4)
34 #define SPDIF_INT_MEMFULLREAD (1 << 5)
35 #define SPDIF_INT_EOPD_PAUSE (1 << 6)
36
37#define SPDIF_OUT_INT_EN 0x10
38#define SPDIF_OUT_INT_EN_SET 0x14
39#define SPDIF_OUT_INT_EN_CLR 0x18
40#define SPDIF_OUT_CTRL 0x1C
41 #define SPDIF_OPMODE_MASK (7 << 0)
42 #define SPDIF_OPMODE_OFF (0 << 0)
43 #define SPDIF_OPMODE_MUTE_PCM (1 << 0)
44 #define SPDIF_OPMODE_MUTE_PAUSE (2 << 0)
45 #define SPDIF_OPMODE_AUD_DATA (3 << 0)
46 #define SPDIF_OPMODE_ENCODE (4 << 0)
47 #define SPDIF_STATE_NORMAL (1 << 3)
48 #define SPDIF_DIVIDER_MASK (0xff << 5)
49 #define SPDIF_DIVIDER_SHIFT (5)
50 #define SPDIF_SAMPLEREAD_MASK (0x1ffff << 15)
51 #define SPDIF_SAMPLEREAD_SHIFT (15)
52#define SPDIF_OUT_STA 0x20
53#define SPDIF_OUT_PA_PB 0x24
54#define SPDIF_OUT_PC_PD 0x28
55#define SPDIF_OUT_CL1 0x2C
56#define SPDIF_OUT_CR1 0x30
57#define SPDIF_OUT_CL2_CR2_UV 0x34
58#define SPDIF_OUT_PAUSE_LAT 0x38
59#define SPDIF_OUT_FRMLEN_BRST 0x3C
60#define SPDIF_OUT_CFG 0x40
61 #define SPDIF_OUT_MEMFMT_16_0 (0 << 5)
62 #define SPDIF_OUT_MEMFMT_16_16 (1 << 5)
63 #define SPDIF_OUT_VALID_DMA (0 << 3)
64 #define SPDIF_OUT_VALID_HW (1 << 3)
65 #define SPDIF_OUT_USER_DMA (0 << 2)
66 #define SPDIF_OUT_USER_HW (1 << 2)
67 #define SPDIF_OUT_CHNLSTA_DMA (0 << 1)
68 #define SPDIF_OUT_CHNLSTA_HW (1 << 1)
69 #define SPDIF_OUT_PARITY_HW (0 << 0)
70 #define SPDIF_OUT_PARITY_DMA (1 << 0)
71 #define SPDIF_OUT_FDMA_TRIG_2 (2 << 8)
72 #define SPDIF_OUT_FDMA_TRIG_6 (6 << 8)
73 #define SPDIF_OUT_FDMA_TRIG_8 (8 << 8)
74 #define SPDIF_OUT_FDMA_TRIG_10 (10 << 8)
75 #define SPDIF_OUT_FDMA_TRIG_12 (12 << 8)
76 #define SPDIF_OUT_FDMA_TRIG_16 (16 << 8)
77 #define SPDIF_OUT_FDMA_TRIG_18 (18 << 8)
78
79#endif /* SPDIF_OUT_REGS_H */
diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c
new file mode 100644
index 00000000000..97c2cac8e92
--- /dev/null
+++ b/sound/soc/spear/spear_pcm.c
@@ -0,0 +1,214 @@
1/*
2 * ALSA PCM interface for ST SPEAr Processors
3 *
4 * sound/soc/spear/spear_pcm.c
5 *
6 * Copyright (C) 2012 ST Microelectronics
7 * Rajeev Kumar<rajeev-dlh.kumar@st.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#include <linux/module.h>
15#include <linux/dmaengine.h>
16#include <linux/dma-mapping.h>
17#include <linux/init.h>
18#include <linux/platform_device.h>
19#include <linux/scatterlist.h>
20#include <linux/slab.h>
21#include <sound/core.h>
22#include <sound/dmaengine_pcm.h>
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h>
26#include <sound/spear_dma.h>
27
28struct snd_pcm_hardware spear_pcm_hardware = {
29 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
30 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
31 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
32 .buffer_bytes_max = 16 * 1024, /* max buffer size */
33 .period_bytes_min = 2 * 1024, /* 1 msec data minimum period size */
34 .period_bytes_max = 2 * 1024, /* maximum period size */
35 .periods_min = 1, /* min # periods */
36 .periods_max = 8, /* max # of periods */
37 .fifo_size = 0, /* fifo size in bytes */
38};
39
40static int spear_pcm_hw_params(struct snd_pcm_substream *substream,
41 struct snd_pcm_hw_params *params)
42{
43 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
44
45 return 0;
46}
47
48static int spear_pcm_hw_free(struct snd_pcm_substream *substream)
49{
50 snd_pcm_set_runtime_buffer(substream, NULL);
51
52 return 0;
53}
54
55static int spear_pcm_open(struct snd_pcm_substream *substream)
56{
57 struct snd_soc_pcm_runtime *rtd = substream->private_data;
58
59 struct spear_dma_data *dma_data = (struct spear_dma_data *)
60 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
61 int ret;
62
63 ret = snd_soc_set_runtime_hwparams(substream, &spear_pcm_hardware);
64 if (ret)
65 return ret;
66
67 ret = snd_dmaengine_pcm_open(substream, dma_data->filter, dma_data);
68 if (ret)
69 return ret;
70
71 snd_dmaengine_pcm_set_data(substream, dma_data);
72
73 return 0;
74}
75
76static int spear_pcm_close(struct snd_pcm_substream *substream)
77{
78
79 snd_dmaengine_pcm_close(substream);
80
81 return 0;
82}
83
84static int spear_pcm_mmap(struct snd_pcm_substream *substream,
85 struct vm_area_struct *vma)
86{
87 struct snd_pcm_runtime *runtime = substream->runtime;
88
89 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
90 runtime->dma_area, runtime->dma_addr,
91 runtime->dma_bytes);
92}
93
94static struct snd_pcm_ops spear_pcm_ops = {
95 .open = spear_pcm_open,
96 .close = spear_pcm_close,
97 .ioctl = snd_pcm_lib_ioctl,
98 .hw_params = spear_pcm_hw_params,
99 .hw_free = spear_pcm_hw_free,
100 .trigger = snd_dmaengine_pcm_trigger,
101 .pointer = snd_dmaengine_pcm_pointer,
102 .mmap = spear_pcm_mmap,
103};
104
105static int
106spear_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream,
107 size_t size)
108{
109 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
110 struct snd_dma_buffer *buf = &substream->dma_buffer;
111
112 buf->dev.type = SNDRV_DMA_TYPE_DEV;
113 buf->dev.dev = pcm->card->dev;
114 buf->private_data = NULL;
115
116 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
117 &buf->addr, GFP_KERNEL);
118 if (!buf->area)
119 return -ENOMEM;
120
121 dev_info(buf->dev.dev,
122 " preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
123 (void *)buf->area, (void *)buf->addr, size);
124
125 buf->bytes = size;
126 return 0;
127}
128
129static void spear_pcm_free(struct snd_pcm *pcm)
130{
131 struct snd_pcm_substream *substream;
132 struct snd_dma_buffer *buf;
133 int stream;
134
135 for (stream = 0; stream < 2; stream++) {
136 substream = pcm->streams[stream].substream;
137 if (!substream)
138 continue;
139
140 buf = &substream->dma_buffer;
141 if (!buf && !buf->area)
142 continue;
143
144 dma_free_writecombine(pcm->card->dev, buf->bytes,
145 buf->area, buf->addr);
146 buf->area = NULL;
147 }
148}
149
150static u64 spear_pcm_dmamask = DMA_BIT_MASK(32);
151
152static int spear_pcm_new(struct snd_card *card,
153 struct snd_soc_dai *dai, struct snd_pcm *pcm)
154{
155 int ret;
156
157 if (!card->dev->dma_mask)
158 card->dev->dma_mask = &spear_pcm_dmamask;
159 if (!card->dev->coherent_dma_mask)
160 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
161
162 if (dai->driver->playback.channels_min) {
163 ret = spear_pcm_preallocate_dma_buffer(pcm,
164 SNDRV_PCM_STREAM_PLAYBACK,
165 spear_pcm_hardware.buffer_bytes_max);
166 if (ret)
167 return ret;
168 }
169
170 if (dai->driver->capture.channels_min) {
171 ret = spear_pcm_preallocate_dma_buffer(pcm,
172 SNDRV_PCM_STREAM_CAPTURE,
173 spear_pcm_hardware.buffer_bytes_max);
174 if (ret)
175 return ret;
176 }
177
178 return 0;
179}
180
181struct snd_soc_platform_driver spear_soc_platform = {
182 .ops = &spear_pcm_ops,
183 .pcm_new = spear_pcm_new,
184 .pcm_free = spear_pcm_free,
185};
186
187static int __devinit spear_soc_platform_probe(struct platform_device *pdev)
188{
189 return snd_soc_register_platform(&pdev->dev, &spear_soc_platform);
190}
191
192static int __devexit spear_soc_platform_remove(struct platform_device *pdev)
193{
194 snd_soc_unregister_platform(&pdev->dev);
195
196 return 0;
197}
198
199static struct platform_driver spear_pcm_driver = {
200 .driver = {
201 .name = "spear-pcm-audio",
202 .owner = THIS_MODULE,
203 },
204
205 .probe = spear_soc_platform_probe,
206 .remove = __devexit_p(spear_soc_platform_remove),
207};
208
209module_platform_driver(spear_pcm_driver);
210
211MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>");
212MODULE_DESCRIPTION("SPEAr PCM DMA module");
213MODULE_LICENSE("GPL");
214MODULE_ALIAS("platform:spear-pcm-audio");
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index c1c8e955f4d..7b6a1ebd197 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -1,7 +1,8 @@
1config SND_SOC_TEGRA 1config SND_SOC_TEGRA
2 tristate "SoC Audio for the Tegra System-on-Chip" 2 tristate "SoC Audio for the Tegra System-on-Chip"
3 depends on ARCH_TEGRA && TEGRA_SYSTEM_DMA 3 depends on ARCH_TEGRA && (TEGRA_SYSTEM_DMA || TEGRA20_APB_DMA)
4 select REGMAP_MMIO 4 select REGMAP_MMIO
5 select SND_SOC_DMAENGINE_PCM if TEGRA20_APB_DMA
5 help 6 help
6 Say Y or M here if you want support for SoC audio on Tegra. 7 Say Y or M here if you want support for SoC audio on Tegra.
7 8
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c
index 0c7af63d444..c5fc6b1404f 100644
--- a/sound/soc/tegra/tegra20_i2s.c
+++ b/sound/soc/tegra/tegra20_i2s.c
@@ -46,18 +46,6 @@
46 46
47#define DRV_NAME "tegra20-i2s" 47#define DRV_NAME "tegra20-i2s"
48 48
49static inline void tegra20_i2s_write(struct tegra20_i2s *i2s, u32 reg, u32 val)
50{
51 regmap_write(i2s->regmap, reg, val);
52}
53
54static inline u32 tegra20_i2s_read(struct tegra20_i2s *i2s, u32 reg)
55{
56 u32 val;
57 regmap_read(i2s->regmap, reg, &val);
58 return val;
59}
60
61static int tegra20_i2s_runtime_suspend(struct device *dev) 49static int tegra20_i2s_runtime_suspend(struct device *dev)
62{ 50{
63 struct tegra20_i2s *i2s = dev_get_drvdata(dev); 51 struct tegra20_i2s *i2s = dev_get_drvdata(dev);
@@ -85,6 +73,7 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
85 unsigned int fmt) 73 unsigned int fmt)
86{ 74{
87 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); 75 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
76 unsigned int mask, val;
88 77
89 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 78 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
90 case SND_SOC_DAIFMT_NB_NF: 79 case SND_SOC_DAIFMT_NB_NF:
@@ -93,10 +82,10 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
93 return -EINVAL; 82 return -EINVAL;
94 } 83 }
95 84
96 i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_MASTER_ENABLE; 85 mask = TEGRA20_I2S_CTRL_MASTER_ENABLE;
97 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 86 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
98 case SND_SOC_DAIFMT_CBS_CFS: 87 case SND_SOC_DAIFMT_CBS_CFS:
99 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_MASTER_ENABLE; 88 val = TEGRA20_I2S_CTRL_MASTER_ENABLE;
100 break; 89 break;
101 case SND_SOC_DAIFMT_CBM_CFM: 90 case SND_SOC_DAIFMT_CBM_CFM:
102 break; 91 break;
@@ -104,33 +93,35 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
104 return -EINVAL; 93 return -EINVAL;
105 } 94 }
106 95
107 i2s->reg_ctrl &= ~(TEGRA20_I2S_CTRL_BIT_FORMAT_MASK | 96 mask |= TEGRA20_I2S_CTRL_BIT_FORMAT_MASK |
108 TEGRA20_I2S_CTRL_LRCK_MASK); 97 TEGRA20_I2S_CTRL_LRCK_MASK;
109 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 98 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
110 case SND_SOC_DAIFMT_DSP_A: 99 case SND_SOC_DAIFMT_DSP_A:
111 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; 100 val |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP;
112 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; 101 val |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
113 break; 102 break;
114 case SND_SOC_DAIFMT_DSP_B: 103 case SND_SOC_DAIFMT_DSP_B:
115 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP; 104 val |= TEGRA20_I2S_CTRL_BIT_FORMAT_DSP;
116 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_R_LOW; 105 val |= TEGRA20_I2S_CTRL_LRCK_R_LOW;
117 break; 106 break;
118 case SND_SOC_DAIFMT_I2S: 107 case SND_SOC_DAIFMT_I2S:
119 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_I2S; 108 val |= TEGRA20_I2S_CTRL_BIT_FORMAT_I2S;
120 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; 109 val |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
121 break; 110 break;
122 case SND_SOC_DAIFMT_RIGHT_J: 111 case SND_SOC_DAIFMT_RIGHT_J:
123 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_RJM; 112 val |= TEGRA20_I2S_CTRL_BIT_FORMAT_RJM;
124 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; 113 val |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
125 break; 114 break;
126 case SND_SOC_DAIFMT_LEFT_J: 115 case SND_SOC_DAIFMT_LEFT_J:
127 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_FORMAT_LJM; 116 val |= TEGRA20_I2S_CTRL_BIT_FORMAT_LJM;
128 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_LRCK_L_LOW; 117 val |= TEGRA20_I2S_CTRL_LRCK_L_LOW;
129 break; 118 break;
130 default: 119 default:
131 return -EINVAL; 120 return -EINVAL;
132 } 121 }
133 122
123 regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, mask, val);
124
134 return 0; 125 return 0;
135} 126}
136 127
@@ -138,29 +129,34 @@ static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream,
138 struct snd_pcm_hw_params *params, 129 struct snd_pcm_hw_params *params,
139 struct snd_soc_dai *dai) 130 struct snd_soc_dai *dai)
140{ 131{
141 struct device *dev = substream->pcm->card->dev; 132 struct device *dev = dai->dev;
142 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai); 133 struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
143 u32 reg; 134 unsigned int mask, val;
144 int ret, sample_size, srate, i2sclock, bitcnt; 135 int ret, sample_size, srate, i2sclock, bitcnt;
145 136
146 i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_BIT_SIZE_MASK; 137 mask = TEGRA20_I2S_CTRL_BIT_SIZE_MASK;
147 switch (params_format(params)) { 138 switch (params_format(params)) {
148 case SNDRV_PCM_FORMAT_S16_LE: 139 case SNDRV_PCM_FORMAT_S16_LE:
149 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_16; 140 val = TEGRA20_I2S_CTRL_BIT_SIZE_16;
150 sample_size = 16; 141 sample_size = 16;
151 break; 142 break;
152 case SNDRV_PCM_FORMAT_S24_LE: 143 case SNDRV_PCM_FORMAT_S24_LE:
153 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_24; 144 val = TEGRA20_I2S_CTRL_BIT_SIZE_24;
154 sample_size = 24; 145 sample_size = 24;
155 break; 146 break;
156 case SNDRV_PCM_FORMAT_S32_LE: 147 case SNDRV_PCM_FORMAT_S32_LE:
157 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_BIT_SIZE_32; 148 val = TEGRA20_I2S_CTRL_BIT_SIZE_32;
158 sample_size = 32; 149 sample_size = 32;
159 break; 150 break;
160 default: 151 default:
161 return -EINVAL; 152 return -EINVAL;
162 } 153 }
163 154
155 mask |= TEGRA20_I2S_CTRL_FIFO_FORMAT_MASK;
156 val |= TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED;
157
158 regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL, mask, val);
159
164 srate = params_rate(params); 160 srate = params_rate(params);
165 161
166 /* Final "* 2" required by Tegra hardware */ 162 /* Final "* 2" required by Tegra hardware */
@@ -175,42 +171,44 @@ static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream,
175 bitcnt = (i2sclock / (2 * srate)) - 1; 171 bitcnt = (i2sclock / (2 * srate)) - 1;
176 if (bitcnt < 0 || bitcnt > TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US) 172 if (bitcnt < 0 || bitcnt > TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US)
177 return -EINVAL; 173 return -EINVAL;
178 reg = bitcnt << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT; 174 val = bitcnt << TEGRA20_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
179 175
180 if (i2sclock % (2 * srate)) 176 if (i2sclock % (2 * srate))
181 reg |= TEGRA20_I2S_TIMING_NON_SYM_ENABLE; 177 val |= TEGRA20_I2S_TIMING_NON_SYM_ENABLE;
182 178
183 tegra20_i2s_write(i2s, TEGRA20_I2S_TIMING, reg); 179 regmap_write(i2s->regmap, TEGRA20_I2S_TIMING, val);
184 180
185 tegra20_i2s_write(i2s, TEGRA20_I2S_FIFO_SCR, 181 regmap_write(i2s->regmap, TEGRA20_I2S_FIFO_SCR,
186 TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS | 182 TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS |
187 TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS); 183 TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS);
188 184
189 return 0; 185 return 0;
190} 186}
191 187
192static void tegra20_i2s_start_playback(struct tegra20_i2s *i2s) 188static void tegra20_i2s_start_playback(struct tegra20_i2s *i2s)
193{ 189{
194 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO1_ENABLE; 190 regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL,
195 tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); 191 TEGRA20_I2S_CTRL_FIFO1_ENABLE,
192 TEGRA20_I2S_CTRL_FIFO1_ENABLE);
196} 193}
197 194
198static void tegra20_i2s_stop_playback(struct tegra20_i2s *i2s) 195static void tegra20_i2s_stop_playback(struct tegra20_i2s *i2s)
199{ 196{
200 i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO1_ENABLE; 197 regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL,
201 tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); 198 TEGRA20_I2S_CTRL_FIFO1_ENABLE, 0);
202} 199}
203 200
204static void tegra20_i2s_start_capture(struct tegra20_i2s *i2s) 201static void tegra20_i2s_start_capture(struct tegra20_i2s *i2s)
205{ 202{
206 i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO2_ENABLE; 203 regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL,
207 tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); 204 TEGRA20_I2S_CTRL_FIFO2_ENABLE,
205 TEGRA20_I2S_CTRL_FIFO2_ENABLE);
208} 206}
209 207
210static void tegra20_i2s_stop_capture(struct tegra20_i2s *i2s) 208static void tegra20_i2s_stop_capture(struct tegra20_i2s *i2s)
211{ 209{
212 i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO2_ENABLE; 210 regmap_update_bits(i2s->regmap, TEGRA20_I2S_CTRL,
213 tegra20_i2s_write(i2s, TEGRA20_I2S_CTRL, i2s->reg_ctrl); 211 TEGRA20_I2S_CTRL_FIFO2_ENABLE, 0);
214} 212}
215 213
216static int tegra20_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 214static int tegra20_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
@@ -261,12 +259,14 @@ static const struct snd_soc_dai_ops tegra20_i2s_dai_ops = {
261static const struct snd_soc_dai_driver tegra20_i2s_dai_template = { 259static const struct snd_soc_dai_driver tegra20_i2s_dai_template = {
262 .probe = tegra20_i2s_probe, 260 .probe = tegra20_i2s_probe,
263 .playback = { 261 .playback = {
262 .stream_name = "Playback",
264 .channels_min = 2, 263 .channels_min = 2,
265 .channels_max = 2, 264 .channels_max = 2,
266 .rates = SNDRV_PCM_RATE_8000_96000, 265 .rates = SNDRV_PCM_RATE_8000_96000,
267 .formats = SNDRV_PCM_FMTBIT_S16_LE, 266 .formats = SNDRV_PCM_FMTBIT_S16_LE,
268 }, 267 },
269 .capture = { 268 .capture = {
269 .stream_name = "Capture",
270 .channels_min = 2, 270 .channels_min = 2,
271 .channels_max = 2, 271 .channels_max = 2,
272 .rates = SNDRV_PCM_RATE_8000_96000, 272 .rates = SNDRV_PCM_RATE_8000_96000,
@@ -412,8 +412,6 @@ static __devinit int tegra20_i2s_platform_probe(struct platform_device *pdev)
412 i2s->playback_dma_data.width = 32; 412 i2s->playback_dma_data.width = 32;
413 i2s->playback_dma_data.req_sel = dma_ch; 413 i2s->playback_dma_data.req_sel = dma_ch;
414 414
415 i2s->reg_ctrl = TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED;
416
417 pm_runtime_enable(&pdev->dev); 415 pm_runtime_enable(&pdev->dev);
418 if (!pm_runtime_enabled(&pdev->dev)) { 416 if (!pm_runtime_enabled(&pdev->dev)) {
419 ret = tegra20_i2s_runtime_resume(&pdev->dev); 417 ret = tegra20_i2s_runtime_resume(&pdev->dev);
diff --git a/sound/soc/tegra/tegra20_i2s.h b/sound/soc/tegra/tegra20_i2s.h
index a57efc6a597..c27069d24d7 100644
--- a/sound/soc/tegra/tegra20_i2s.h
+++ b/sound/soc/tegra/tegra20_i2s.h
@@ -158,7 +158,6 @@ struct tegra20_i2s {
158 struct tegra_pcm_dma_params capture_dma_data; 158 struct tegra_pcm_dma_params capture_dma_data;
159 struct tegra_pcm_dma_params playback_dma_data; 159 struct tegra_pcm_dma_params playback_dma_data;
160 struct regmap *regmap; 160 struct regmap *regmap;
161 u32 reg_ctrl;
162}; 161};
163 162
164#endif 163#endif
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c
index f9b57418bd0..5c33c618929 100644
--- a/sound/soc/tegra/tegra20_spdif.c
+++ b/sound/soc/tegra/tegra20_spdif.c
@@ -37,19 +37,6 @@
37 37
38#define DRV_NAME "tegra20-spdif" 38#define DRV_NAME "tegra20-spdif"
39 39
40static inline void tegra20_spdif_write(struct tegra20_spdif *spdif, u32 reg,
41 u32 val)
42{
43 regmap_write(spdif->regmap, reg, val);
44}
45
46static inline u32 tegra20_spdif_read(struct tegra20_spdif *spdif, u32 reg)
47{
48 u32 val;
49 regmap_read(spdif->regmap, reg, &val);
50 return val;
51}
52
53static int tegra20_spdif_runtime_suspend(struct device *dev) 40static int tegra20_spdif_runtime_suspend(struct device *dev)
54{ 41{
55 struct tegra20_spdif *spdif = dev_get_drvdata(dev); 42 struct tegra20_spdif *spdif = dev_get_drvdata(dev);
@@ -77,21 +64,24 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
77 struct snd_pcm_hw_params *params, 64 struct snd_pcm_hw_params *params,
78 struct snd_soc_dai *dai) 65 struct snd_soc_dai *dai)
79{ 66{
80 struct device *dev = substream->pcm->card->dev; 67 struct device *dev = dai->dev;
81 struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai); 68 struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
69 unsigned int mask, val;
82 int ret, spdifclock; 70 int ret, spdifclock;
83 71
84 spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_PACK; 72 mask = TEGRA20_SPDIF_CTRL_PACK |
85 spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_BIT_MODE_MASK; 73 TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
86 switch (params_format(params)) { 74 switch (params_format(params)) {
87 case SNDRV_PCM_FORMAT_S16_LE: 75 case SNDRV_PCM_FORMAT_S16_LE:
88 spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_PACK; 76 val = TEGRA20_SPDIF_CTRL_PACK |
89 spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT; 77 TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
90 break; 78 break;
91 default: 79 default:
92 return -EINVAL; 80 return -EINVAL;
93 } 81 }
94 82
83 regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL, mask, val);
84
95 switch (params_rate(params)) { 85 switch (params_rate(params)) {
96 case 32000: 86 case 32000:
97 spdifclock = 4096000; 87 spdifclock = 4096000;
@@ -129,14 +119,15 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
129 119
130static void tegra20_spdif_start_playback(struct tegra20_spdif *spdif) 120static void tegra20_spdif_start_playback(struct tegra20_spdif *spdif)
131{ 121{
132 spdif->reg_ctrl |= TEGRA20_SPDIF_CTRL_TX_EN; 122 regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL,
133 tegra20_spdif_write(spdif, TEGRA20_SPDIF_CTRL, spdif->reg_ctrl); 123 TEGRA20_SPDIF_CTRL_TX_EN,
124 TEGRA20_SPDIF_CTRL_TX_EN);
134} 125}
135 126
136static void tegra20_spdif_stop_playback(struct tegra20_spdif *spdif) 127static void tegra20_spdif_stop_playback(struct tegra20_spdif *spdif)
137{ 128{
138 spdif->reg_ctrl &= ~TEGRA20_SPDIF_CTRL_TX_EN; 129 regmap_update_bits(spdif->regmap, TEGRA20_SPDIF_CTRL,
139 tegra20_spdif_write(spdif, TEGRA20_SPDIF_CTRL, spdif->reg_ctrl); 130 TEGRA20_SPDIF_CTRL_TX_EN, 0);
140} 131}
141 132
142static int tegra20_spdif_trigger(struct snd_pcm_substream *substream, int cmd, 133static int tegra20_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
@@ -181,6 +172,7 @@ static struct snd_soc_dai_driver tegra20_spdif_dai = {
181 .name = DRV_NAME, 172 .name = DRV_NAME,
182 .probe = tegra20_spdif_probe, 173 .probe = tegra20_spdif_probe,
183 .playback = { 174 .playback = {
175 .stream_name = "Playback",
184 .channels_min = 2, 176 .channels_min = 2,
185 .channels_max = 2, 177 .channels_max = 2,
186 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | 178 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
diff --git a/sound/soc/tegra/tegra20_spdif.h b/sound/soc/tegra/tegra20_spdif.h
index ed756527efe..b48d699fd58 100644
--- a/sound/soc/tegra/tegra20_spdif.h
+++ b/sound/soc/tegra/tegra20_spdif.h
@@ -465,7 +465,6 @@ struct tegra20_spdif {
465 struct tegra_pcm_dma_params capture_dma_data; 465 struct tegra_pcm_dma_params capture_dma_data;
466 struct tegra_pcm_dma_params playback_dma_data; 466 struct tegra_pcm_dma_params playback_dma_data;
467 struct regmap *regmap; 467 struct regmap *regmap;
468 u32 reg_ctrl;
469}; 468};
470 469
471#endif 470#endif
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index 8596032985d..b68e27a1460 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -44,18 +44,6 @@
44 44
45#define DRV_NAME "tegra30-i2s" 45#define DRV_NAME "tegra30-i2s"
46 46
47static inline void tegra30_i2s_write(struct tegra30_i2s *i2s, u32 reg, u32 val)
48{
49 regmap_write(i2s->regmap, reg, val);
50}
51
52static inline u32 tegra30_i2s_read(struct tegra30_i2s *i2s, u32 reg)
53{
54 u32 val;
55 regmap_read(i2s->regmap, reg, &val);
56 return val;
57}
58
59static int tegra30_i2s_runtime_suspend(struct device *dev) 47static int tegra30_i2s_runtime_suspend(struct device *dev)
60{ 48{
61 struct tegra30_i2s *i2s = dev_get_drvdata(dev); 49 struct tegra30_i2s *i2s = dev_get_drvdata(dev);
@@ -128,6 +116,7 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
128 unsigned int fmt) 116 unsigned int fmt)
129{ 117{
130 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); 118 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
119 unsigned int mask, val;
131 120
132 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 121 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
133 case SND_SOC_DAIFMT_NB_NF: 122 case SND_SOC_DAIFMT_NB_NF:
@@ -136,10 +125,10 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
136 return -EINVAL; 125 return -EINVAL;
137 } 126 }
138 127
139 i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_MASTER_ENABLE; 128 mask = TEGRA30_I2S_CTRL_MASTER_ENABLE;
140 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 129 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
141 case SND_SOC_DAIFMT_CBS_CFS: 130 case SND_SOC_DAIFMT_CBS_CFS:
142 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_MASTER_ENABLE; 131 val = TEGRA30_I2S_CTRL_MASTER_ENABLE;
143 break; 132 break;
144 case SND_SOC_DAIFMT_CBM_CFM: 133 case SND_SOC_DAIFMT_CBM_CFM:
145 break; 134 break;
@@ -147,33 +136,37 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
147 return -EINVAL; 136 return -EINVAL;
148 } 137 }
149 138
150 i2s->reg_ctrl &= ~(TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK | 139 mask |= TEGRA30_I2S_CTRL_FRAME_FORMAT_MASK |
151 TEGRA30_I2S_CTRL_LRCK_MASK); 140 TEGRA30_I2S_CTRL_LRCK_MASK;
152 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 141 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
153 case SND_SOC_DAIFMT_DSP_A: 142 case SND_SOC_DAIFMT_DSP_A:
154 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC; 143 val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
155 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; 144 val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
156 break; 145 break;
157 case SND_SOC_DAIFMT_DSP_B: 146 case SND_SOC_DAIFMT_DSP_B:
158 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC; 147 val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC;
159 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_R_LOW; 148 val |= TEGRA30_I2S_CTRL_LRCK_R_LOW;
160 break; 149 break;
161 case SND_SOC_DAIFMT_I2S: 150 case SND_SOC_DAIFMT_I2S:
162 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; 151 val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
163 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; 152 val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
164 break; 153 break;
165 case SND_SOC_DAIFMT_RIGHT_J: 154 case SND_SOC_DAIFMT_RIGHT_J:
166 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; 155 val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
167 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; 156 val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
168 break; 157 break;
169 case SND_SOC_DAIFMT_LEFT_J: 158 case SND_SOC_DAIFMT_LEFT_J:
170 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK; 159 val |= TEGRA30_I2S_CTRL_FRAME_FORMAT_LRCK;
171 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_LRCK_L_LOW; 160 val |= TEGRA30_I2S_CTRL_LRCK_L_LOW;
172 break; 161 break;
173 default: 162 default:
174 return -EINVAL; 163 return -EINVAL;
175 } 164 }
176 165
166 pm_runtime_get_sync(dai->dev);
167 regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val);
168 pm_runtime_put(dai->dev);
169
177 return 0; 170 return 0;
178} 171}
179 172
@@ -181,24 +174,26 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
181 struct snd_pcm_hw_params *params, 174 struct snd_pcm_hw_params *params,
182 struct snd_soc_dai *dai) 175 struct snd_soc_dai *dai)
183{ 176{
184 struct device *dev = substream->pcm->card->dev; 177 struct device *dev = dai->dev;
185 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai); 178 struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
186 u32 val; 179 unsigned int mask, val, reg;
187 int ret, sample_size, srate, i2sclock, bitcnt; 180 int ret, sample_size, srate, i2sclock, bitcnt;
188 181
189 if (params_channels(params) != 2) 182 if (params_channels(params) != 2)
190 return -EINVAL; 183 return -EINVAL;
191 184
192 i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_BIT_SIZE_MASK; 185 mask = TEGRA30_I2S_CTRL_BIT_SIZE_MASK;
193 switch (params_format(params)) { 186 switch (params_format(params)) {
194 case SNDRV_PCM_FORMAT_S16_LE: 187 case SNDRV_PCM_FORMAT_S16_LE:
195 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_16; 188 val = TEGRA30_I2S_CTRL_BIT_SIZE_16;
196 sample_size = 16; 189 sample_size = 16;
197 break; 190 break;
198 default: 191 default:
199 return -EINVAL; 192 return -EINVAL;
200 } 193 }
201 194
195 regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL, mask, val);
196
202 srate = params_rate(params); 197 srate = params_rate(params);
203 198
204 /* Final "* 2" required by Tegra hardware */ 199 /* Final "* 2" required by Tegra hardware */
@@ -219,7 +214,7 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
219 if (i2sclock % (2 * srate)) 214 if (i2sclock % (2 * srate))
220 val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE; 215 val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE;
221 216
222 tegra30_i2s_write(i2s, TEGRA30_I2S_TIMING, val); 217 regmap_write(i2s->regmap, TEGRA30_I2S_TIMING, val);
223 218
224 val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) | 219 val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
225 (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) | 220 (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
@@ -229,15 +224,17 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
229 224
230 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 225 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
231 val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX; 226 val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
232 tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_RX_CTRL, val); 227 reg = TEGRA30_I2S_CIF_RX_CTRL;
233 } else { 228 } else {
234 val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX; 229 val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
235 tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_TX_CTRL, val); 230 reg = TEGRA30_I2S_CIF_RX_CTRL;
236 } 231 }
237 232
233 regmap_write(i2s->regmap, reg, val);
234
238 val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) | 235 val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) |
239 (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT); 236 (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
240 tegra30_i2s_write(i2s, TEGRA30_I2S_OFFSET, val); 237 regmap_write(i2s->regmap, TEGRA30_I2S_OFFSET, val);
241 238
242 return 0; 239 return 0;
243} 240}
@@ -245,29 +242,31 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
245static void tegra30_i2s_start_playback(struct tegra30_i2s *i2s) 242static void tegra30_i2s_start_playback(struct tegra30_i2s *i2s)
246{ 243{
247 tegra30_ahub_enable_tx_fifo(i2s->playback_fifo_cif); 244 tegra30_ahub_enable_tx_fifo(i2s->playback_fifo_cif);
248 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX; 245 regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
249 tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); 246 TEGRA30_I2S_CTRL_XFER_EN_TX,
247 TEGRA30_I2S_CTRL_XFER_EN_TX);
250} 248}
251 249
252static void tegra30_i2s_stop_playback(struct tegra30_i2s *i2s) 250static void tegra30_i2s_stop_playback(struct tegra30_i2s *i2s)
253{ 251{
254 tegra30_ahub_disable_tx_fifo(i2s->playback_fifo_cif); 252 tegra30_ahub_disable_tx_fifo(i2s->playback_fifo_cif);
255 i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX; 253 regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
256 tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); 254 TEGRA30_I2S_CTRL_XFER_EN_TX, 0);
257} 255}
258 256
259static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s) 257static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s)
260{ 258{
261 tegra30_ahub_enable_rx_fifo(i2s->capture_fifo_cif); 259 tegra30_ahub_enable_rx_fifo(i2s->capture_fifo_cif);
262 i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_RX; 260 regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
263 tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); 261 TEGRA30_I2S_CTRL_XFER_EN_RX,
262 TEGRA30_I2S_CTRL_XFER_EN_RX);
264} 263}
265 264
266static void tegra30_i2s_stop_capture(struct tegra30_i2s *i2s) 265static void tegra30_i2s_stop_capture(struct tegra30_i2s *i2s)
267{ 266{
268 tegra30_ahub_disable_rx_fifo(i2s->capture_fifo_cif); 267 tegra30_ahub_disable_rx_fifo(i2s->capture_fifo_cif);
269 i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX; 268 regmap_update_bits(i2s->regmap, TEGRA30_I2S_CTRL,
270 tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl); 269 TEGRA30_I2S_CTRL_XFER_EN_RX, 0);
271} 270}
272 271
273static int tegra30_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 272static int tegra30_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
@@ -320,12 +319,14 @@ static struct snd_soc_dai_ops tegra30_i2s_dai_ops = {
320static const struct snd_soc_dai_driver tegra30_i2s_dai_template = { 319static const struct snd_soc_dai_driver tegra30_i2s_dai_template = {
321 .probe = tegra30_i2s_probe, 320 .probe = tegra30_i2s_probe,
322 .playback = { 321 .playback = {
322 .stream_name = "Playback",
323 .channels_min = 2, 323 .channels_min = 2,
324 .channels_max = 2, 324 .channels_max = 2,
325 .rates = SNDRV_PCM_RATE_8000_96000, 325 .rates = SNDRV_PCM_RATE_8000_96000,
326 .formats = SNDRV_PCM_FMTBIT_S16_LE, 326 .formats = SNDRV_PCM_FMTBIT_S16_LE,
327 }, 327 },
328 .capture = { 328 .capture = {
329 .stream_name = "Capture",
329 .channels_min = 2, 330 .channels_min = 2,
330 .channels_max = 2, 331 .channels_max = 2,
331 .rates = SNDRV_PCM_RATE_8000_96000, 332 .rates = SNDRV_PCM_RATE_8000_96000,
diff --git a/sound/soc/tegra/tegra30_i2s.h b/sound/soc/tegra/tegra30_i2s.h
index 91adf29c7a8..34dc47b9581 100644
--- a/sound/soc/tegra/tegra30_i2s.h
+++ b/sound/soc/tegra/tegra30_i2s.h
@@ -236,7 +236,6 @@ struct tegra30_i2s {
236 enum tegra30_ahub_txcif playback_fifo_cif; 236 enum tegra30_ahub_txcif playback_fifo_cif;
237 struct tegra_pcm_dma_params playback_dma_data; 237 struct tegra_pcm_dma_params playback_dma_data;
238 struct regmap *regmap; 238 struct regmap *regmap;
239 u32 reg_ctrl;
240}; 239};
241 240
242#endif 241#endif
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
index 32de7006daf..d684df294c0 100644
--- a/sound/soc/tegra/tegra_alc5632.c
+++ b/sound/soc/tegra/tegra_alc5632.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * tegra_alc5632.c -- Toshiba AC100(PAZ00) machine ASoC driver 2* tegra_alc5632.c -- Toshiba AC100(PAZ00) machine ASoC driver
3 * 3 *
4 * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net> 4 * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
5 * Copyright (C) 2012 - NVIDIA, Inc. 5 * Copyright (C) 2012 - NVIDIA, Inc.
@@ -33,11 +33,8 @@
33 33
34#define DRV_NAME "tegra-alc5632" 34#define DRV_NAME "tegra-alc5632"
35 35
36#define GPIO_HP_DET BIT(0)
37
38struct tegra_alc5632 { 36struct tegra_alc5632 {
39 struct tegra_asoc_utils_data util_data; 37 struct tegra_asoc_utils_data util_data;
40 int gpio_requested;
41 int gpio_hp_det; 38 int gpio_hp_det;
42}; 39};
43 40
@@ -46,7 +43,7 @@ static int tegra_alc5632_asoc_hw_params(struct snd_pcm_substream *substream,
46{ 43{
47 struct snd_soc_pcm_runtime *rtd = substream->private_data; 44 struct snd_soc_pcm_runtime *rtd = substream->private_data;
48 struct snd_soc_dai *codec_dai = rtd->codec_dai; 45 struct snd_soc_dai *codec_dai = rtd->codec_dai;
49 struct snd_soc_codec *codec = rtd->codec; 46 struct snd_soc_codec *codec = codec_dai->codec;
50 struct snd_soc_card *card = codec->card; 47 struct snd_soc_card *card = codec->card;
51 struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card); 48 struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card);
52 int srate, mclk; 49 int srate, mclk;
@@ -108,9 +105,9 @@ static const struct snd_kcontrol_new tegra_alc5632_controls[] = {
108 105
109static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd) 106static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
110{ 107{
111 struct snd_soc_codec *codec = rtd->codec; 108 struct snd_soc_dai *codec_dai = rtd->codec_dai;
109 struct snd_soc_codec *codec = codec_dai->codec;
112 struct snd_soc_dapm_context *dapm = &codec->dapm; 110 struct snd_soc_dapm_context *dapm = &codec->dapm;
113 struct device_node *np = codec->card->dev->of_node;
114 struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card); 111 struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card);
115 112
116 snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET, 113 snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
@@ -119,14 +116,11 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
119 ARRAY_SIZE(tegra_alc5632_hs_jack_pins), 116 ARRAY_SIZE(tegra_alc5632_hs_jack_pins),
120 tegra_alc5632_hs_jack_pins); 117 tegra_alc5632_hs_jack_pins);
121 118
122 machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
123
124 if (gpio_is_valid(machine->gpio_hp_det)) { 119 if (gpio_is_valid(machine->gpio_hp_det)) {
125 tegra_alc5632_hp_jack_gpio.gpio = machine->gpio_hp_det; 120 tegra_alc5632_hp_jack_gpio.gpio = machine->gpio_hp_det;
126 snd_soc_jack_add_gpios(&tegra_alc5632_hs_jack, 121 snd_soc_jack_add_gpios(&tegra_alc5632_hs_jack,
127 1, 122 1,
128 &tegra_alc5632_hp_jack_gpio); 123 &tegra_alc5632_hp_jack_gpio);
129 machine->gpio_requested |= GPIO_HP_DET;
130 } 124 }
131 125
132 snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1"); 126 snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1");
@@ -159,6 +153,7 @@ static struct snd_soc_card snd_soc_tegra_alc5632 = {
159 153
160static __devinit int tegra_alc5632_probe(struct platform_device *pdev) 154static __devinit int tegra_alc5632_probe(struct platform_device *pdev)
161{ 155{
156 struct device_node *np = pdev->dev.of_node;
162 struct snd_soc_card *card = &snd_soc_tegra_alc5632; 157 struct snd_soc_card *card = &snd_soc_tegra_alc5632;
163 struct tegra_alc5632 *alc5632; 158 struct tegra_alc5632 *alc5632;
164 int ret; 159 int ret;
@@ -181,6 +176,10 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev)
181 goto err; 176 goto err;
182 } 177 }
183 178
179 alc5632->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
180 if (alc5632->gpio_hp_det == -ENODEV)
181 return -EPROBE_DEFER;
182
184 ret = snd_soc_of_parse_card_name(card, "nvidia,model"); 183 ret = snd_soc_of_parse_card_name(card, "nvidia,model");
185 if (ret) 184 if (ret)
186 goto err; 185 goto err;
@@ -199,16 +198,16 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev)
199 goto err; 198 goto err;
200 } 199 }
201 200
202 tegra_alc5632_dai.cpu_dai_of_node = of_parse_phandle( 201 tegra_alc5632_dai.cpu_of_node = of_parse_phandle(
203 pdev->dev.of_node, "nvidia,i2s-controller", 0); 202 pdev->dev.of_node, "nvidia,i2s-controller", 0);
204 if (!tegra_alc5632_dai.cpu_dai_of_node) { 203 if (!tegra_alc5632_dai.cpu_of_node) {
205 dev_err(&pdev->dev, 204 dev_err(&pdev->dev,
206 "Property 'nvidia,i2s-controller' missing or invalid\n"); 205 "Property 'nvidia,i2s-controller' missing or invalid\n");
207 ret = -EINVAL; 206 ret = -EINVAL;
208 goto err; 207 goto err;
209 } 208 }
210 209
211 tegra_alc5632_dai.platform_of_node = tegra_alc5632_dai.cpu_dai_of_node; 210 tegra_alc5632_dai.platform_of_node = tegra_alc5632_dai.cpu_of_node;
212 211
213 ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev); 212 ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev);
214 if (ret) 213 if (ret)
@@ -234,11 +233,8 @@ static int __devexit tegra_alc5632_remove(struct platform_device *pdev)
234 struct snd_soc_card *card = platform_get_drvdata(pdev); 233 struct snd_soc_card *card = platform_get_drvdata(pdev);
235 struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(card); 234 struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(card);
236 235
237 if (machine->gpio_requested & GPIO_HP_DET) 236 snd_soc_jack_free_gpios(&tegra_alc5632_hs_jack, 1,
238 snd_soc_jack_free_gpios(&tegra_alc5632_hs_jack, 237 &tegra_alc5632_hp_jack_gpio);
239 1,
240 &tegra_alc5632_hp_jack_gpio);
241 machine->gpio_requested = 0;
242 238
243 snd_soc_unregister_card(card); 239 snd_soc_unregister_card(card);
244 240
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index 127348dc09b..5658bcec193 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -36,6 +36,7 @@
36#include <sound/pcm.h> 36#include <sound/pcm.h>
37#include <sound/pcm_params.h> 37#include <sound/pcm_params.h>
38#include <sound/soc.h> 38#include <sound/soc.h>
39#include <sound/dmaengine_pcm.h>
39 40
40#include "tegra_pcm.h" 41#include "tegra_pcm.h"
41 42
@@ -56,6 +57,7 @@ static const struct snd_pcm_hardware tegra_pcm_hardware = {
56 .fifo_size = 4, 57 .fifo_size = 4,
57}; 58};
58 59
60#if defined(CONFIG_TEGRA_SYSTEM_DMA)
59static void tegra_pcm_queue_dma(struct tegra_runtime_data *prtd) 61static void tegra_pcm_queue_dma(struct tegra_runtime_data *prtd)
60{ 62{
61 struct snd_pcm_substream *substream = prtd->substream; 63 struct snd_pcm_substream *substream = prtd->substream;
@@ -285,6 +287,119 @@ static struct snd_pcm_ops tegra_pcm_ops = {
285 .pointer = tegra_pcm_pointer, 287 .pointer = tegra_pcm_pointer,
286 .mmap = tegra_pcm_mmap, 288 .mmap = tegra_pcm_mmap,
287}; 289};
290#else
291static int tegra_pcm_open(struct snd_pcm_substream *substream)
292{
293 struct snd_soc_pcm_runtime *rtd = substream->private_data;
294 struct device *dev = rtd->platform->dev;
295 int ret;
296
297 /* Set HW params now that initialization is complete */
298 snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware);
299
300 ret = snd_dmaengine_pcm_open(substream, NULL, NULL);
301 if (ret) {
302 dev_err(dev, "dmaengine pcm open failed with err %d\n", ret);
303 return ret;
304 }
305
306 return 0;
307}
308
309static int tegra_pcm_close(struct snd_pcm_substream *substream)
310{
311 snd_dmaengine_pcm_close(substream);
312 return 0;
313}
314
315static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
316 struct snd_pcm_hw_params *params)
317{
318 struct snd_soc_pcm_runtime *rtd = substream->private_data;
319 struct device *dev = rtd->platform->dev;
320 struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
321 struct tegra_pcm_dma_params *dmap;
322 struct dma_slave_config slave_config;
323 int ret;
324
325 dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
326
327 ret = snd_hwparams_to_dma_slave_config(substream, params,
328 &slave_config);
329 if (ret) {
330 dev_err(dev, "hw params config failed with err %d\n", ret);
331 return ret;
332 }
333
334 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
335 slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
336 slave_config.dst_addr = dmap->addr;
337 slave_config.src_maxburst = 0;
338 } else {
339 slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
340 slave_config.src_addr = dmap->addr;
341 slave_config.dst_maxburst = 0;
342 }
343 slave_config.slave_id = dmap->req_sel;
344
345 ret = dmaengine_slave_config(chan, &slave_config);
346 if (ret < 0) {
347 dev_err(dev, "dma slave config failed with err %d\n", ret);
348 return ret;
349 }
350
351 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
352 return 0;
353}
354
355static int tegra_pcm_hw_free(struct snd_pcm_substream *substream)
356{
357 snd_pcm_set_runtime_buffer(substream, NULL);
358 return 0;
359}
360
361static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
362{
363 switch (cmd) {
364 case SNDRV_PCM_TRIGGER_START:
365 case SNDRV_PCM_TRIGGER_RESUME:
366 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
367 return snd_dmaengine_pcm_trigger(substream,
368 SNDRV_PCM_TRIGGER_START);
369
370 case SNDRV_PCM_TRIGGER_STOP:
371 case SNDRV_PCM_TRIGGER_SUSPEND:
372 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
373 return snd_dmaengine_pcm_trigger(substream,
374 SNDRV_PCM_TRIGGER_STOP);
375 default:
376 return -EINVAL;
377 }
378 return 0;
379}
380
381static int tegra_pcm_mmap(struct snd_pcm_substream *substream,
382 struct vm_area_struct *vma)
383{
384 struct snd_pcm_runtime *runtime = substream->runtime;
385
386 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
387 runtime->dma_area,
388 runtime->dma_addr,
389 runtime->dma_bytes);
390}
391
392static struct snd_pcm_ops tegra_pcm_ops = {
393 .open = tegra_pcm_open,
394 .close = tegra_pcm_close,
395 .ioctl = snd_pcm_lib_ioctl,
396 .hw_params = tegra_pcm_hw_params,
397 .hw_free = tegra_pcm_hw_free,
398 .trigger = tegra_pcm_trigger,
399 .pointer = snd_dmaengine_pcm_pointer,
400 .mmap = tegra_pcm_mmap,
401};
402#endif
288 403
289static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) 404static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
290{ 405{
diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h
index 985d418a35e..a3a450352dc 100644
--- a/sound/soc/tegra/tegra_pcm.h
+++ b/sound/soc/tegra/tegra_pcm.h
@@ -40,6 +40,7 @@ struct tegra_pcm_dma_params {
40 unsigned long req_sel; 40 unsigned long req_sel;
41}; 41};
42 42
43#if defined(CONFIG_TEGRA_SYSTEM_DMA)
43struct tegra_runtime_data { 44struct tegra_runtime_data {
44 struct snd_pcm_substream *substream; 45 struct snd_pcm_substream *substream;
45 spinlock_t lock; 46 spinlock_t lock;
@@ -51,6 +52,7 @@ struct tegra_runtime_data {
51 struct tegra_dma_req dma_req[2]; 52 struct tegra_dma_req dma_req[2];
52 struct tegra_dma_channel *dma_chan; 53 struct tegra_dma_channel *dma_chan;
53}; 54};
55#endif
54 56
55int tegra_pcm_platform_register(struct device *dev); 57int tegra_pcm_platform_register(struct device *dev);
56void tegra_pcm_platform_unregister(struct device *dev); 58void tegra_pcm_platform_unregister(struct device *dev);
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
index 4e77026807a..ea9166d5c4e 100644
--- a/sound/soc/tegra/tegra_wm8753.c
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -57,7 +57,7 @@ static int tegra_wm8753_hw_params(struct snd_pcm_substream *substream,
57{ 57{
58 struct snd_soc_pcm_runtime *rtd = substream->private_data; 58 struct snd_soc_pcm_runtime *rtd = substream->private_data;
59 struct snd_soc_dai *codec_dai = rtd->codec_dai; 59 struct snd_soc_dai *codec_dai = rtd->codec_dai;
60 struct snd_soc_codec *codec = rtd->codec; 60 struct snd_soc_codec *codec = codec_dai->codec;
61 struct snd_soc_card *card = codec->card; 61 struct snd_soc_card *card = codec->card;
62 struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card); 62 struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
63 int srate, mclk; 63 int srate, mclk;
@@ -157,9 +157,9 @@ static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev)
157 goto err; 157 goto err;
158 } 158 }
159 159
160 tegra_wm8753_dai.cpu_dai_of_node = of_parse_phandle( 160 tegra_wm8753_dai.cpu_of_node = of_parse_phandle(
161 pdev->dev.of_node, "nvidia,i2s-controller", 0); 161 pdev->dev.of_node, "nvidia,i2s-controller", 0);
162 if (!tegra_wm8753_dai.cpu_dai_of_node) { 162 if (!tegra_wm8753_dai.cpu_of_node) {
163 dev_err(&pdev->dev, 163 dev_err(&pdev->dev,
164 "Property 'nvidia,i2s-controller' missing or invalid\n"); 164 "Property 'nvidia,i2s-controller' missing or invalid\n");
165 ret = -EINVAL; 165 ret = -EINVAL;
@@ -167,7 +167,7 @@ static __devinit int tegra_wm8753_driver_probe(struct platform_device *pdev)
167 } 167 }
168 168
169 tegra_wm8753_dai.platform_of_node = 169 tegra_wm8753_dai.platform_of_node =
170 tegra_wm8753_dai.cpu_dai_of_node; 170 tegra_wm8753_dai.cpu_of_node;
171 171
172 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); 172 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
173 if (ret) 173 if (ret)
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index 3b6da91188a..0c5bb33d258 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -28,8 +28,6 @@
28 * 28 *
29 */ 29 */
30 30
31#include <asm/mach-types.h>
32
33#include <linux/module.h> 31#include <linux/module.h>
34#include <linux/platform_device.h> 32#include <linux/platform_device.h>
35#include <linux/slab.h> 33#include <linux/slab.h>
@@ -50,16 +48,9 @@
50 48
51#define DRV_NAME "tegra-snd-wm8903" 49#define DRV_NAME "tegra-snd-wm8903"
52 50
53#define GPIO_SPKR_EN BIT(0)
54#define GPIO_HP_MUTE BIT(1)
55#define GPIO_INT_MIC_EN BIT(2)
56#define GPIO_EXT_MIC_EN BIT(3)
57#define GPIO_HP_DET BIT(4)
58
59struct tegra_wm8903 { 51struct tegra_wm8903 {
60 struct tegra_wm8903_platform_data pdata; 52 struct tegra_wm8903_platform_data pdata;
61 struct tegra_asoc_utils_data util_data; 53 struct tegra_asoc_utils_data util_data;
62 int gpio_requested;
63}; 54};
64 55
65static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, 56static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
@@ -67,8 +58,7 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
67{ 58{
68 struct snd_soc_pcm_runtime *rtd = substream->private_data; 59 struct snd_soc_pcm_runtime *rtd = substream->private_data;
69 struct snd_soc_dai *codec_dai = rtd->codec_dai; 60 struct snd_soc_dai *codec_dai = rtd->codec_dai;
70 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 61 struct snd_soc_codec *codec = codec_dai->codec;
71 struct snd_soc_codec *codec = rtd->codec;
72 struct snd_soc_card *card = codec->card; 62 struct snd_soc_card *card = codec->card;
73 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); 63 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
74 int srate, mclk; 64 int srate, mclk;
@@ -95,24 +85,6 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
95 return err; 85 return err;
96 } 86 }
97 87
98 err = snd_soc_dai_set_fmt(codec_dai,
99 SND_SOC_DAIFMT_I2S |
100 SND_SOC_DAIFMT_NB_NF |
101 SND_SOC_DAIFMT_CBS_CFS);
102 if (err < 0) {
103 dev_err(card->dev, "codec_dai fmt not set\n");
104 return err;
105 }
106
107 err = snd_soc_dai_set_fmt(cpu_dai,
108 SND_SOC_DAIFMT_I2S |
109 SND_SOC_DAIFMT_NB_NF |
110 SND_SOC_DAIFMT_CBS_CFS);
111 if (err < 0) {
112 dev_err(card->dev, "cpu_dai fmt not set\n");
113 return err;
114 }
115
116 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, 88 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
117 SND_SOC_CLOCK_IN); 89 SND_SOC_CLOCK_IN);
118 if (err < 0) { 90 if (err < 0) {
@@ -160,7 +132,7 @@ static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w,
160 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); 132 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
161 struct tegra_wm8903_platform_data *pdata = &machine->pdata; 133 struct tegra_wm8903_platform_data *pdata = &machine->pdata;
162 134
163 if (!(machine->gpio_requested & GPIO_SPKR_EN)) 135 if (!gpio_is_valid(pdata->gpio_spkr_en))
164 return 0; 136 return 0;
165 137
166 gpio_set_value_cansleep(pdata->gpio_spkr_en, 138 gpio_set_value_cansleep(pdata->gpio_spkr_en,
@@ -177,7 +149,7 @@ static int tegra_wm8903_event_hp(struct snd_soc_dapm_widget *w,
177 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); 149 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
178 struct tegra_wm8903_platform_data *pdata = &machine->pdata; 150 struct tegra_wm8903_platform_data *pdata = &machine->pdata;
179 151
180 if (!(machine->gpio_requested & GPIO_HP_MUTE)) 152 if (!gpio_is_valid(pdata->gpio_hp_mute))
181 return 0; 153 return 0;
182 154
183 gpio_set_value_cansleep(pdata->gpio_hp_mute, 155 gpio_set_value_cansleep(pdata->gpio_hp_mute,
@@ -203,122 +175,18 @@ static const struct snd_soc_dapm_route harmony_audio_map[] = {
203 {"IN1L", NULL, "Mic Jack"}, 175 {"IN1L", NULL, "Mic Jack"},
204}; 176};
205 177
206static const struct snd_soc_dapm_route seaboard_audio_map[] = {
207 {"Headphone Jack", NULL, "HPOUTR"},
208 {"Headphone Jack", NULL, "HPOUTL"},
209 {"Int Spk", NULL, "ROP"},
210 {"Int Spk", NULL, "RON"},
211 {"Int Spk", NULL, "LOP"},
212 {"Int Spk", NULL, "LON"},
213 {"Mic Jack", NULL, "MICBIAS"},
214 {"IN1R", NULL, "Mic Jack"},
215};
216
217static const struct snd_soc_dapm_route kaen_audio_map[] = {
218 {"Headphone Jack", NULL, "HPOUTR"},
219 {"Headphone Jack", NULL, "HPOUTL"},
220 {"Int Spk", NULL, "ROP"},
221 {"Int Spk", NULL, "RON"},
222 {"Int Spk", NULL, "LOP"},
223 {"Int Spk", NULL, "LON"},
224 {"Mic Jack", NULL, "MICBIAS"},
225 {"IN2R", NULL, "Mic Jack"},
226};
227
228static const struct snd_soc_dapm_route aebl_audio_map[] = {
229 {"Headphone Jack", NULL, "HPOUTR"},
230 {"Headphone Jack", NULL, "HPOUTL"},
231 {"Int Spk", NULL, "LINEOUTR"},
232 {"Int Spk", NULL, "LINEOUTL"},
233 {"Mic Jack", NULL, "MICBIAS"},
234 {"IN1R", NULL, "Mic Jack"},
235};
236
237static const struct snd_kcontrol_new tegra_wm8903_controls[] = { 178static const struct snd_kcontrol_new tegra_wm8903_controls[] = {
238 SOC_DAPM_PIN_SWITCH("Int Spk"), 179 SOC_DAPM_PIN_SWITCH("Int Spk"),
239}; 180};
240 181
241static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) 182static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
242{ 183{
243 struct snd_soc_codec *codec = rtd->codec; 184 struct snd_soc_dai *codec_dai = rtd->codec_dai;
185 struct snd_soc_codec *codec = codec_dai->codec;
244 struct snd_soc_dapm_context *dapm = &codec->dapm; 186 struct snd_soc_dapm_context *dapm = &codec->dapm;
245 struct snd_soc_card *card = codec->card; 187 struct snd_soc_card *card = codec->card;
246 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); 188 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
247 struct tegra_wm8903_platform_data *pdata = &machine->pdata; 189 struct tegra_wm8903_platform_data *pdata = &machine->pdata;
248 struct device_node *np = card->dev->of_node;
249 int ret;
250
251 if (card->dev->platform_data) {
252 memcpy(pdata, card->dev->platform_data, sizeof(*pdata));
253 } else if (np) {
254 /*
255 * This part must be in init() rather than probe() in order to
256 * guarantee that the WM8903 has been probed, and hence its
257 * GPIO controller registered, which is a pre-condition for
258 * of_get_named_gpio() to be able to map the phandles in the
259 * properties to the controller node. Given this, all
260 * pdata handling is in init() for consistency.
261 */
262 pdata->gpio_spkr_en = of_get_named_gpio(np,
263 "nvidia,spkr-en-gpios", 0);
264 pdata->gpio_hp_mute = of_get_named_gpio(np,
265 "nvidia,hp-mute-gpios", 0);
266 pdata->gpio_hp_det = of_get_named_gpio(np,
267 "nvidia,hp-det-gpios", 0);
268 pdata->gpio_int_mic_en = of_get_named_gpio(np,
269 "nvidia,int-mic-en-gpios", 0);
270 pdata->gpio_ext_mic_en = of_get_named_gpio(np,
271 "nvidia,ext-mic-en-gpios", 0);
272 } else {
273 dev_err(card->dev, "No platform data supplied\n");
274 return -EINVAL;
275 }
276
277 if (gpio_is_valid(pdata->gpio_spkr_en)) {
278 ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
279 if (ret) {
280 dev_err(card->dev, "cannot get spkr_en gpio\n");
281 return ret;
282 }
283 machine->gpio_requested |= GPIO_SPKR_EN;
284
285 gpio_direction_output(pdata->gpio_spkr_en, 0);
286 }
287
288 if (gpio_is_valid(pdata->gpio_hp_mute)) {
289 ret = gpio_request(pdata->gpio_hp_mute, "hp_mute");
290 if (ret) {
291 dev_err(card->dev, "cannot get hp_mute gpio\n");
292 return ret;
293 }
294 machine->gpio_requested |= GPIO_HP_MUTE;
295
296 gpio_direction_output(pdata->gpio_hp_mute, 1);
297 }
298
299 if (gpio_is_valid(pdata->gpio_int_mic_en)) {
300 ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
301 if (ret) {
302 dev_err(card->dev, "cannot get int_mic_en gpio\n");
303 return ret;
304 }
305 machine->gpio_requested |= GPIO_INT_MIC_EN;
306
307 /* Disable int mic; enable signal is active-high */
308 gpio_direction_output(pdata->gpio_int_mic_en, 0);
309 }
310
311 if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
312 ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
313 if (ret) {
314 dev_err(card->dev, "cannot get ext_mic_en gpio\n");
315 return ret;
316 }
317 machine->gpio_requested |= GPIO_EXT_MIC_EN;
318
319 /* Enable ext mic; enable signal is active-low */
320 gpio_direction_output(pdata->gpio_ext_mic_en, 0);
321 }
322 190
323 if (gpio_is_valid(pdata->gpio_hp_det)) { 191 if (gpio_is_valid(pdata->gpio_hp_det)) {
324 tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det; 192 tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det;
@@ -330,7 +198,6 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
330 snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack, 198 snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack,
331 1, 199 1,
332 &tegra_wm8903_hp_jack_gpio); 200 &tegra_wm8903_hp_jack_gpio);
333 machine->gpio_requested |= GPIO_HP_DET;
334 } 201 }
335 202
336 snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, 203 snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE,
@@ -366,6 +233,9 @@ static struct snd_soc_dai_link tegra_wm8903_dai = {
366 .codec_dai_name = "wm8903-hifi", 233 .codec_dai_name = "wm8903-hifi",
367 .init = tegra_wm8903_init, 234 .init = tegra_wm8903_init,
368 .ops = &tegra_wm8903_ops, 235 .ops = &tegra_wm8903_ops,
236 .dai_fmt = SND_SOC_DAIFMT_I2S |
237 SND_SOC_DAIFMT_NB_NF |
238 SND_SOC_DAIFMT_CBS_CFS,
369}; 239};
370 240
371static struct snd_soc_card snd_soc_tegra_wm8903 = { 241static struct snd_soc_card snd_soc_tegra_wm8903 = {
@@ -385,8 +255,10 @@ static struct snd_soc_card snd_soc_tegra_wm8903 = {
385 255
386static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) 256static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
387{ 257{
258 struct device_node *np = pdev->dev.of_node;
388 struct snd_soc_card *card = &snd_soc_tegra_wm8903; 259 struct snd_soc_card *card = &snd_soc_tegra_wm8903;
389 struct tegra_wm8903 *machine; 260 struct tegra_wm8903 *machine;
261 struct tegra_wm8903_platform_data *pdata;
390 int ret; 262 int ret;
391 263
392 if (!pdev->dev.platform_data && !pdev->dev.of_node) { 264 if (!pdev->dev.platform_data && !pdev->dev.of_node) {
@@ -401,12 +273,42 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
401 ret = -ENOMEM; 273 ret = -ENOMEM;
402 goto err; 274 goto err;
403 } 275 }
276 pdata = &machine->pdata;
404 277
405 card->dev = &pdev->dev; 278 card->dev = &pdev->dev;
406 platform_set_drvdata(pdev, card); 279 platform_set_drvdata(pdev, card);
407 snd_soc_card_set_drvdata(card, machine); 280 snd_soc_card_set_drvdata(card, machine);
408 281
409 if (pdev->dev.of_node) { 282 if (pdev->dev.platform_data) {
283 memcpy(pdata, card->dev->platform_data, sizeof(*pdata));
284 } else if (np) {
285 pdata->gpio_spkr_en = of_get_named_gpio(np,
286 "nvidia,spkr-en-gpios", 0);
287 if (pdata->gpio_spkr_en == -ENODEV)
288 return -EPROBE_DEFER;
289
290 pdata->gpio_hp_mute = of_get_named_gpio(np,
291 "nvidia,hp-mute-gpios", 0);
292 if (pdata->gpio_hp_mute == -ENODEV)
293 return -EPROBE_DEFER;
294
295 pdata->gpio_hp_det = of_get_named_gpio(np,
296 "nvidia,hp-det-gpios", 0);
297 if (pdata->gpio_hp_det == -ENODEV)
298 return -EPROBE_DEFER;
299
300 pdata->gpio_int_mic_en = of_get_named_gpio(np,
301 "nvidia,int-mic-en-gpios", 0);
302 if (pdata->gpio_int_mic_en == -ENODEV)
303 return -EPROBE_DEFER;
304
305 pdata->gpio_ext_mic_en = of_get_named_gpio(np,
306 "nvidia,ext-mic-en-gpios", 0);
307 if (pdata->gpio_ext_mic_en == -ENODEV)
308 return -EPROBE_DEFER;
309 }
310
311 if (np) {
410 ret = snd_soc_of_parse_card_name(card, "nvidia,model"); 312 ret = snd_soc_of_parse_card_name(card, "nvidia,model");
411 if (ret) 313 if (ret)
412 goto err; 314 goto err;
@@ -417,8 +319,8 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
417 goto err; 319 goto err;
418 320
419 tegra_wm8903_dai.codec_name = NULL; 321 tegra_wm8903_dai.codec_name = NULL;
420 tegra_wm8903_dai.codec_of_node = of_parse_phandle( 322 tegra_wm8903_dai.codec_of_node = of_parse_phandle(np,
421 pdev->dev.of_node, "nvidia,audio-codec", 0); 323 "nvidia,audio-codec", 0);
422 if (!tegra_wm8903_dai.codec_of_node) { 324 if (!tegra_wm8903_dai.codec_of_node) {
423 dev_err(&pdev->dev, 325 dev_err(&pdev->dev,
424 "Property 'nvidia,audio-codec' missing or invalid\n"); 326 "Property 'nvidia,audio-codec' missing or invalid\n");
@@ -427,9 +329,9 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
427 } 329 }
428 330
429 tegra_wm8903_dai.cpu_dai_name = NULL; 331 tegra_wm8903_dai.cpu_dai_name = NULL;
430 tegra_wm8903_dai.cpu_dai_of_node = of_parse_phandle( 332 tegra_wm8903_dai.cpu_of_node = of_parse_phandle(np,
431 pdev->dev.of_node, "nvidia,i2s-controller", 0); 333 "nvidia,i2s-controller", 0);
432 if (!tegra_wm8903_dai.cpu_dai_of_node) { 334 if (!tegra_wm8903_dai.cpu_of_node) {
433 dev_err(&pdev->dev, 335 dev_err(&pdev->dev,
434 "Property 'nvidia,i2s-controller' missing or invalid\n"); 336 "Property 'nvidia,i2s-controller' missing or invalid\n");
435 ret = -EINVAL; 337 ret = -EINVAL;
@@ -438,20 +340,47 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
438 340
439 tegra_wm8903_dai.platform_name = NULL; 341 tegra_wm8903_dai.platform_name = NULL;
440 tegra_wm8903_dai.platform_of_node = 342 tegra_wm8903_dai.platform_of_node =
441 tegra_wm8903_dai.cpu_dai_of_node; 343 tegra_wm8903_dai.cpu_of_node;
442 } else { 344 } else {
443 if (machine_is_harmony()) { 345 card->dapm_routes = harmony_audio_map;
444 card->dapm_routes = harmony_audio_map; 346 card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map);
445 card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map); 347 }
446 } else if (machine_is_seaboard()) { 348
447 card->dapm_routes = seaboard_audio_map; 349 if (gpio_is_valid(pdata->gpio_spkr_en)) {
448 card->num_dapm_routes = ARRAY_SIZE(seaboard_audio_map); 350 ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_spkr_en,
449 } else if (machine_is_kaen()) { 351 GPIOF_OUT_INIT_LOW, "spkr_en");
450 card->dapm_routes = kaen_audio_map; 352 if (ret) {
451 card->num_dapm_routes = ARRAY_SIZE(kaen_audio_map); 353 dev_err(card->dev, "cannot get spkr_en gpio\n");
452 } else { 354 return ret;
453 card->dapm_routes = aebl_audio_map; 355 }
454 card->num_dapm_routes = ARRAY_SIZE(aebl_audio_map); 356 }
357
358 if (gpio_is_valid(pdata->gpio_hp_mute)) {
359 ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_hp_mute,
360 GPIOF_OUT_INIT_HIGH, "hp_mute");
361 if (ret) {
362 dev_err(card->dev, "cannot get hp_mute gpio\n");
363 return ret;
364 }
365 }
366
367 if (gpio_is_valid(pdata->gpio_int_mic_en)) {
368 /* Disable int mic; enable signal is active-high */
369 ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_int_mic_en,
370 GPIOF_OUT_INIT_LOW, "int_mic_en");
371 if (ret) {
372 dev_err(card->dev, "cannot get int_mic_en gpio\n");
373 return ret;
374 }
375 }
376
377 if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
378 /* Enable ext mic; enable signal is active-low */
379 ret = devm_gpio_request_one(&pdev->dev, pdata->gpio_ext_mic_en,
380 GPIOF_OUT_INIT_LOW, "ext_mic_en");
381 if (ret) {
382 dev_err(card->dev, "cannot get ext_mic_en gpio\n");
383 return ret;
455 } 384 }
456 } 385 }
457 386
@@ -478,21 +407,9 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
478{ 407{
479 struct snd_soc_card *card = platform_get_drvdata(pdev); 408 struct snd_soc_card *card = platform_get_drvdata(pdev);
480 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); 409 struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
481 struct tegra_wm8903_platform_data *pdata = &machine->pdata;
482 410
483 if (machine->gpio_requested & GPIO_HP_DET) 411 snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack, 1,
484 snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack, 412 &tegra_wm8903_hp_jack_gpio);
485 1,
486 &tegra_wm8903_hp_jack_gpio);
487 if (machine->gpio_requested & GPIO_EXT_MIC_EN)
488 gpio_free(pdata->gpio_ext_mic_en);
489 if (machine->gpio_requested & GPIO_INT_MIC_EN)
490 gpio_free(pdata->gpio_int_mic_en);
491 if (machine->gpio_requested & GPIO_HP_MUTE)
492 gpio_free(pdata->gpio_hp_mute);
493 if (machine->gpio_requested & GPIO_SPKR_EN)
494 gpio_free(pdata->gpio_spkr_en);
495 machine->gpio_requested = 0;
496 413
497 snd_soc_unregister_card(card); 414 snd_soc_unregister_card(card);
498 415
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c
index 4a8d5b672c9..e69a4f7000d 100644
--- a/sound/soc/tegra/trimslice.c
+++ b/sound/soc/tegra/trimslice.c
@@ -52,8 +52,7 @@ static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream,
52{ 52{
53 struct snd_soc_pcm_runtime *rtd = substream->private_data; 53 struct snd_soc_pcm_runtime *rtd = substream->private_data;
54 struct snd_soc_dai *codec_dai = rtd->codec_dai; 54 struct snd_soc_dai *codec_dai = rtd->codec_dai;
55 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 55 struct snd_soc_codec *codec = codec_dai->codec;
56 struct snd_soc_codec *codec = rtd->codec;
57 struct snd_soc_card *card = codec->card; 56 struct snd_soc_card *card = codec->card;
58 struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card); 57 struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card);
59 int srate, mclk; 58 int srate, mclk;
@@ -68,24 +67,6 @@ static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream,
68 return err; 67 return err;
69 } 68 }
70 69
71 err = snd_soc_dai_set_fmt(codec_dai,
72 SND_SOC_DAIFMT_I2S |
73 SND_SOC_DAIFMT_NB_NF |
74 SND_SOC_DAIFMT_CBS_CFS);
75 if (err < 0) {
76 dev_err(card->dev, "codec_dai fmt not set\n");
77 return err;
78 }
79
80 err = snd_soc_dai_set_fmt(cpu_dai,
81 SND_SOC_DAIFMT_I2S |
82 SND_SOC_DAIFMT_NB_NF |
83 SND_SOC_DAIFMT_CBS_CFS);
84 if (err < 0) {
85 dev_err(card->dev, "cpu_dai fmt not set\n");
86 return err;
87 }
88
89 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, 70 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
90 SND_SOC_CLOCK_IN); 71 SND_SOC_CLOCK_IN);
91 if (err < 0) { 72 if (err < 0) {
@@ -121,6 +102,9 @@ static struct snd_soc_dai_link trimslice_tlv320aic23_dai = {
121 .cpu_dai_name = "tegra20-i2s.0", 102 .cpu_dai_name = "tegra20-i2s.0",
122 .codec_dai_name = "tlv320aic23-hifi", 103 .codec_dai_name = "tlv320aic23-hifi",
123 .ops = &trimslice_asoc_ops, 104 .ops = &trimslice_asoc_ops,
105 .dai_fmt = SND_SOC_DAIFMT_I2S |
106 SND_SOC_DAIFMT_NB_NF |
107 SND_SOC_DAIFMT_CBS_CFS,
124}; 108};
125 109
126static struct snd_soc_card snd_soc_trimslice = { 110static struct snd_soc_card snd_soc_trimslice = {
@@ -162,9 +146,9 @@ static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
162 } 146 }
163 147
164 trimslice_tlv320aic23_dai.cpu_dai_name = NULL; 148 trimslice_tlv320aic23_dai.cpu_dai_name = NULL;
165 trimslice_tlv320aic23_dai.cpu_dai_of_node = of_parse_phandle( 149 trimslice_tlv320aic23_dai.cpu_of_node = of_parse_phandle(
166 pdev->dev.of_node, "nvidia,i2s-controller", 0); 150 pdev->dev.of_node, "nvidia,i2s-controller", 0);
167 if (!trimslice_tlv320aic23_dai.cpu_dai_of_node) { 151 if (!trimslice_tlv320aic23_dai.cpu_of_node) {
168 dev_err(&pdev->dev, 152 dev_err(&pdev->dev,
169 "Property 'nvidia,i2s-controller' missing or invalid\n"); 153 "Property 'nvidia,i2s-controller' missing or invalid\n");
170 ret = -EINVAL; 154 ret = -EINVAL;
@@ -173,7 +157,7 @@ static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
173 157
174 trimslice_tlv320aic23_dai.platform_name = NULL; 158 trimslice_tlv320aic23_dai.platform_name = NULL;
175 trimslice_tlv320aic23_dai.platform_of_node = 159 trimslice_tlv320aic23_dai.platform_of_node =
176 trimslice_tlv320aic23_dai.cpu_dai_of_node; 160 trimslice_tlv320aic23_dai.cpu_of_node;
177 } 161 }
178 162
179 ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev); 163 ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev);
diff --git a/sound/soc/ux500/Kconfig b/sound/soc/ux500/Kconfig
index 44cf43404cd..069330d82be 100644
--- a/sound/soc/ux500/Kconfig
+++ b/sound/soc/ux500/Kconfig
@@ -12,3 +12,21 @@ menuconfig SND_SOC_UX500
12config SND_SOC_UX500_PLAT_MSP_I2S 12config SND_SOC_UX500_PLAT_MSP_I2S
13 tristate 13 tristate
14 depends on SND_SOC_UX500 14 depends on SND_SOC_UX500
15
16config SND_SOC_UX500_PLAT_DMA
17 tristate "Platform - DB8500 (DMA)"
18 depends on SND_SOC_UX500
19 select SND_SOC_DMAENGINE_PCM
20 help
21 Say Y if you want to enable the Ux500 platform-driver.
22
23+config SND_SOC_UX500_MACH_MOP500
24+ tristate "Machine - MOP500 (Ux500 + AB8500)"
25 depends on AB8500_CORE && AB8500_GPADC && SND_SOC_UX500
26 select SND_SOC_AB8500_CODEC
27 select SND_SOC_UX500_PLAT_MSP_I2S
28 select SND_SOC_UX500_PLAT_DMA
29 help
30 Select this to enable the MOP500 machine-driver.
31 This will enable platform-drivers for: Ux500
32 This will enable codec-drivers for: AB8500
diff --git a/sound/soc/ux500/Makefile b/sound/soc/ux500/Makefile
index 19974c5a2ea..cce0c11a4d8 100644
--- a/sound/soc/ux500/Makefile
+++ b/sound/soc/ux500/Makefile
@@ -2,3 +2,9 @@
2 2
3snd-soc-ux500-plat-msp-i2s-objs := ux500_msp_dai.o ux500_msp_i2s.o 3snd-soc-ux500-plat-msp-i2s-objs := ux500_msp_dai.o ux500_msp_i2s.o
4obj-$(CONFIG_SND_SOC_UX500_PLAT_MSP_I2S) += snd-soc-ux500-plat-msp-i2s.o 4obj-$(CONFIG_SND_SOC_UX500_PLAT_MSP_I2S) += snd-soc-ux500-plat-msp-i2s.o
5
6snd-soc-ux500-plat-dma-objs := ux500_pcm.o
7obj-$(CONFIG_SND_SOC_UX500_PLAT_DMA) += snd-soc-ux500-plat-dma.o
8
9snd-soc-ux500-mach-mop500-objs := mop500.o mop500_ab8500.o
10obj-$(CONFIG_SND_SOC_UX500_MACH_MOP500) += snd-soc-ux500-mach-mop500.o
diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c
new file mode 100644
index 00000000000..31c4d26d035
--- /dev/null
+++ b/sound/soc/ux500/mop500.c
@@ -0,0 +1,113 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2012
3 *
4 * Author: Ola Lilja (ola.o.lilja@stericsson.com)
5 * for ST-Ericsson.
6 *
7 * License terms:
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as published
11 * by the Free Software Foundation.
12 */
13
14#include <asm/mach-types.h>
15
16#include <linux/module.h>
17#include <linux/io.h>
18#include <linux/spi/spi.h>
19
20#include <sound/soc.h>
21#include <sound/initval.h>
22
23#include "ux500_pcm.h"
24#include "ux500_msp_dai.h"
25
26#include <mop500_ab8500.h>
27
28/* Define the whole MOP500 soundcard, linking platform to the codec-drivers */
29struct snd_soc_dai_link mop500_dai_links[] = {
30 {
31 .name = "ab8500_0",
32 .stream_name = "ab8500_0",
33 .cpu_dai_name = "ux500-msp-i2s.1",
34 .codec_dai_name = "ab8500-codec-dai.0",
35 .platform_name = "ux500-pcm.0",
36 .codec_name = "ab8500-codec.0",
37 .init = mop500_ab8500_machine_init,
38 .ops = mop500_ab8500_ops,
39 },
40 {
41 .name = "ab8500_1",
42 .stream_name = "ab8500_1",
43 .cpu_dai_name = "ux500-msp-i2s.3",
44 .codec_dai_name = "ab8500-codec-dai.1",
45 .platform_name = "ux500-pcm.0",
46 .codec_name = "ab8500-codec.0",
47 .init = NULL,
48 .ops = mop500_ab8500_ops,
49 },
50};
51
52static struct snd_soc_card mop500_card = {
53 .name = "MOP500-card",
54 .probe = NULL,
55 .dai_link = mop500_dai_links,
56 .num_links = ARRAY_SIZE(mop500_dai_links),
57};
58
59static int __devinit mop500_probe(struct platform_device *pdev)
60{
61 int ret;
62
63 pr_debug("%s: Enter.\n", __func__);
64
65 dev_dbg(&pdev->dev, "%s: Enter.\n", __func__);
66
67 mop500_card.dev = &pdev->dev;
68
69 dev_dbg(&pdev->dev, "%s: Card %s: Set platform drvdata.\n",
70 __func__, mop500_card.name);
71 platform_set_drvdata(pdev, &mop500_card);
72
73 snd_soc_card_set_drvdata(&mop500_card, NULL);
74
75 dev_dbg(&pdev->dev, "%s: Card %s: num_links = %d\n",
76 __func__, mop500_card.name, mop500_card.num_links);
77 dev_dbg(&pdev->dev, "%s: Card %s: DAI-link 0: name = %s\n",
78 __func__, mop500_card.name, mop500_card.dai_link[0].name);
79 dev_dbg(&pdev->dev, "%s: Card %s: DAI-link 0: stream_name = %s\n",
80 __func__, mop500_card.name,
81 mop500_card.dai_link[0].stream_name);
82
83 ret = snd_soc_register_card(&mop500_card);
84 if (ret)
85 dev_err(&pdev->dev,
86 "Error: snd_soc_register_card failed (%d)!\n",
87 ret);
88
89 return ret;
90}
91
92static int __devexit mop500_remove(struct platform_device *pdev)
93{
94 struct snd_soc_card *mop500_card = platform_get_drvdata(pdev);
95
96 pr_debug("%s: Enter.\n", __func__);
97
98 snd_soc_unregister_card(mop500_card);
99 mop500_ab8500_remove(mop500_card);
100
101 return 0;
102}
103
104static struct platform_driver snd_soc_mop500_driver = {
105 .driver = {
106 .owner = THIS_MODULE,
107 .name = "snd-soc-mop500",
108 },
109 .probe = mop500_probe,
110 .remove = __devexit_p(mop500_remove),
111};
112
113module_platform_driver(snd_soc_mop500_driver);
diff --git a/sound/soc/ux500/mop500_ab8500.c b/sound/soc/ux500/mop500_ab8500.c
new file mode 100644
index 00000000000..78cce236693
--- /dev/null
+++ b/sound/soc/ux500/mop500_ab8500.c
@@ -0,0 +1,431 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2012
3 *
4 * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
5 * Kristoffer Karlsson <kristoffer.karlsson@stericsson.com>
6 * for ST-Ericsson.
7 *
8 * License terms:
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as published
12 * by the Free Software Foundation.
13 */
14
15#include <linux/module.h>
16#include <linux/device.h>
17#include <linux/io.h>
18#include <linux/clk.h>
19
20#include <mach/hardware.h>
21
22#include <sound/soc.h>
23#include <sound/soc-dapm.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26
27#include "ux500_pcm.h"
28#include "ux500_msp_dai.h"
29#include "../codecs/ab8500-codec.h"
30
31#define TX_SLOT_MONO 0x0008
32#define TX_SLOT_STEREO 0x000a
33#define RX_SLOT_MONO 0x0001
34#define RX_SLOT_STEREO 0x0003
35#define TX_SLOT_8CH 0x00FF
36#define RX_SLOT_8CH 0x00FF
37
38#define DEF_TX_SLOTS TX_SLOT_STEREO
39#define DEF_RX_SLOTS RX_SLOT_MONO
40
41#define DRIVERMODE_NORMAL 0
42#define DRIVERMODE_CODEC_ONLY 1
43
44/* Slot configuration */
45static unsigned int tx_slots = DEF_TX_SLOTS;
46static unsigned int rx_slots = DEF_RX_SLOTS;
47
48/* Clocks */
49static const char * const enum_mclk[] = {
50 "SYSCLK",
51 "ULPCLK"
52};
53enum mclk {
54 MCLK_SYSCLK,
55 MCLK_ULPCLK,
56};
57
58static SOC_ENUM_SINGLE_EXT_DECL(soc_enum_mclk, enum_mclk);
59
60/* Private data for machine-part MOP500<->AB8500 */
61struct mop500_ab8500_drvdata {
62 /* Clocks */
63 enum mclk mclk_sel;
64 struct clk *clk_ptr_intclk;
65 struct clk *clk_ptr_sysclk;
66 struct clk *clk_ptr_ulpclk;
67};
68
69static inline const char *get_mclk_str(enum mclk mclk_sel)
70{
71 switch (mclk_sel) {
72 case MCLK_SYSCLK:
73 return "SYSCLK";
74 case MCLK_ULPCLK:
75 return "ULPCLK";
76 default:
77 return "Unknown";
78 }
79}
80
81static int mop500_ab8500_set_mclk(struct device *dev,
82 struct mop500_ab8500_drvdata *drvdata)
83{
84 int status;
85 struct clk *clk_ptr;
86
87 if (IS_ERR(drvdata->clk_ptr_intclk)) {
88 dev_err(dev,
89 "%s: ERROR: intclk not initialized!\n", __func__);
90 return -EIO;
91 }
92
93 switch (drvdata->mclk_sel) {
94 case MCLK_SYSCLK:
95 clk_ptr = drvdata->clk_ptr_sysclk;
96 break;
97 case MCLK_ULPCLK:
98 clk_ptr = drvdata->clk_ptr_ulpclk;
99 break;
100 default:
101 return -EINVAL;
102 }
103
104 if (IS_ERR(clk_ptr)) {
105 dev_err(dev, "%s: ERROR: %s not initialized!\n", __func__,
106 get_mclk_str(drvdata->mclk_sel));
107 return -EIO;
108 }
109
110 status = clk_set_parent(drvdata->clk_ptr_intclk, clk_ptr);
111 if (status)
112 dev_err(dev,
113 "%s: ERROR: Setting intclk parent to %s failed (ret = %d)!",
114 __func__, get_mclk_str(drvdata->mclk_sel), status);
115 else
116 dev_dbg(dev,
117 "%s: intclk parent changed to %s.\n",
118 __func__, get_mclk_str(drvdata->mclk_sel));
119
120 return status;
121}
122
123/*
124 * Control-events
125 */
126
127static int mclk_input_control_get(struct snd_kcontrol *kcontrol,
128 struct snd_ctl_elem_value *ucontrol)
129{
130 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
131 struct mop500_ab8500_drvdata *drvdata =
132 snd_soc_card_get_drvdata(codec->card);
133
134 ucontrol->value.enumerated.item[0] = drvdata->mclk_sel;
135
136 return 0;
137}
138
139static int mclk_input_control_put(struct snd_kcontrol *kcontrol,
140 struct snd_ctl_elem_value *ucontrol)
141{
142 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
143 struct mop500_ab8500_drvdata *drvdata =
144 snd_soc_card_get_drvdata(codec->card);
145 unsigned int val = ucontrol->value.enumerated.item[0];
146
147 if (val > (unsigned int)MCLK_ULPCLK)
148 return -EINVAL;
149 if (drvdata->mclk_sel == val)
150 return 0;
151
152 drvdata->mclk_sel = val;
153
154 return 1;
155}
156
157/*
158 * Controls
159 */
160
161static struct snd_kcontrol_new mop500_ab8500_ctrls[] = {
162 SOC_ENUM_EXT("Master Clock Select",
163 soc_enum_mclk,
164 mclk_input_control_get, mclk_input_control_put),
165 /* Digital interface - Clocks */
166 SOC_SINGLE("Digital Interface Master Generator Switch",
167 AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENMASTGEN,
168 1, 0),
169 SOC_SINGLE("Digital Interface 0 Bit-clock Switch",
170 AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENFSBITCLK0,
171 1, 0),
172 SOC_SINGLE("Digital Interface 1 Bit-clock Switch",
173 AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENFSBITCLK1,
174 1, 0),
175 SOC_DAPM_PIN_SWITCH("Headset Left"),
176 SOC_DAPM_PIN_SWITCH("Headset Right"),
177 SOC_DAPM_PIN_SWITCH("Earpiece"),
178 SOC_DAPM_PIN_SWITCH("Speaker Left"),
179 SOC_DAPM_PIN_SWITCH("Speaker Right"),
180 SOC_DAPM_PIN_SWITCH("LineOut Left"),
181 SOC_DAPM_PIN_SWITCH("LineOut Right"),
182 SOC_DAPM_PIN_SWITCH("Vibra 1"),
183 SOC_DAPM_PIN_SWITCH("Vibra 2"),
184 SOC_DAPM_PIN_SWITCH("Mic 1"),
185 SOC_DAPM_PIN_SWITCH("Mic 2"),
186 SOC_DAPM_PIN_SWITCH("LineIn Left"),
187 SOC_DAPM_PIN_SWITCH("LineIn Right"),
188 SOC_DAPM_PIN_SWITCH("DMic 1"),
189 SOC_DAPM_PIN_SWITCH("DMic 2"),
190 SOC_DAPM_PIN_SWITCH("DMic 3"),
191 SOC_DAPM_PIN_SWITCH("DMic 4"),
192 SOC_DAPM_PIN_SWITCH("DMic 5"),
193 SOC_DAPM_PIN_SWITCH("DMic 6"),
194};
195
196/* ASoC */
197
198int mop500_ab8500_startup(struct snd_pcm_substream *substream)
199{
200 struct snd_soc_pcm_runtime *rtd = substream->private_data;
201
202 /* Set audio-clock source */
203 return mop500_ab8500_set_mclk(rtd->card->dev,
204 snd_soc_card_get_drvdata(rtd->card));
205}
206
207void mop500_ab8500_shutdown(struct snd_pcm_substream *substream)
208{
209 struct snd_soc_pcm_runtime *rtd = substream->private_data;
210 struct device *dev = rtd->card->dev;
211
212 dev_dbg(dev, "%s: Enter\n", __func__);
213
214 /* Reset slots configuration to default(s) */
215 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
216 tx_slots = DEF_TX_SLOTS;
217 else
218 rx_slots = DEF_RX_SLOTS;
219}
220
221int mop500_ab8500_hw_params(struct snd_pcm_substream *substream,
222 struct snd_pcm_hw_params *params)
223{
224 struct snd_soc_pcm_runtime *rtd = substream->private_data;
225 struct snd_soc_dai *codec_dai = rtd->codec_dai;
226 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
227 struct device *dev = rtd->card->dev;
228 unsigned int fmt;
229 int channels, ret = 0, driver_mode, slots;
230 unsigned int sw_codec, sw_cpu;
231 bool is_playback;
232
233 dev_dbg(dev, "%s: Enter\n", __func__);
234
235 dev_dbg(dev, "%s: substream->pcm->name = %s\n"
236 "substream->pcm->id = %s.\n"
237 "substream->name = %s.\n"
238 "substream->number = %d.\n",
239 __func__,
240 substream->pcm->name,
241 substream->pcm->id,
242 substream->name,
243 substream->number);
244
245 channels = params_channels(params);
246
247 switch (params_format(params)) {
248 case SNDRV_PCM_FORMAT_S32_LE:
249 sw_cpu = 32;
250 break;
251
252 case SNDRV_PCM_FORMAT_S16_LE:
253 sw_cpu = 16;
254 break;
255
256 default:
257 return -EINVAL;
258 }
259
260 /* Setup codec depending on driver-mode */
261 if (channels == 8)
262 driver_mode = DRIVERMODE_CODEC_ONLY;
263 else
264 driver_mode = DRIVERMODE_NORMAL;
265 dev_dbg(dev, "%s: Driver-mode: %s.\n", __func__,
266 (driver_mode == DRIVERMODE_NORMAL) ? "NORMAL" : "CODEC_ONLY");
267
268 /* Setup format */
269
270 if (driver_mode == DRIVERMODE_NORMAL) {
271 fmt = SND_SOC_DAIFMT_DSP_A |
272 SND_SOC_DAIFMT_CBM_CFM |
273 SND_SOC_DAIFMT_NB_NF |
274 SND_SOC_DAIFMT_CONT;
275 } else {
276 fmt = SND_SOC_DAIFMT_DSP_A |
277 SND_SOC_DAIFMT_CBM_CFM |
278 SND_SOC_DAIFMT_NB_NF |
279 SND_SOC_DAIFMT_GATED;
280 }
281
282 ret = snd_soc_dai_set_fmt(codec_dai, fmt);
283 if (ret < 0) {
284 dev_err(dev,
285 "%s: ERROR: snd_soc_dai_set_fmt failed for codec_dai (ret = %d)!\n",
286 __func__, ret);
287 return ret;
288 }
289
290 ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
291 if (ret < 0) {
292 dev_err(dev,
293 "%s: ERROR: snd_soc_dai_set_fmt failed for cpu_dai (ret = %d)!\n",
294 __func__, ret);
295 return ret;
296 }
297
298 /* Setup TDM-slots */
299
300 is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
301 switch (channels) {
302 case 1:
303 slots = 16;
304 tx_slots = (is_playback) ? TX_SLOT_MONO : 0;
305 rx_slots = (is_playback) ? 0 : RX_SLOT_MONO;
306 break;
307 case 2:
308 slots = 16;
309 tx_slots = (is_playback) ? TX_SLOT_STEREO : 0;
310 rx_slots = (is_playback) ? 0 : RX_SLOT_STEREO;
311 break;
312 case 8:
313 slots = 16;
314 tx_slots = (is_playback) ? TX_SLOT_8CH : 0;
315 rx_slots = (is_playback) ? 0 : RX_SLOT_8CH;
316 break;
317 default:
318 return -EINVAL;
319 }
320
321 if (driver_mode == DRIVERMODE_NORMAL)
322 sw_codec = sw_cpu;
323 else
324 sw_codec = 20;
325
326 dev_dbg(dev, "%s: CPU-DAI TDM: TX=0x%04X RX=0x%04x\n", __func__,
327 tx_slots, rx_slots);
328 ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_slots, rx_slots, slots,
329 sw_cpu);
330 if (ret)
331 return ret;
332
333 dev_dbg(dev, "%s: CODEC-DAI TDM: TX=0x%04X RX=0x%04x\n", __func__,
334 tx_slots, rx_slots);
335 ret = snd_soc_dai_set_tdm_slot(codec_dai, tx_slots, rx_slots, slots,
336 sw_codec);
337 if (ret)
338 return ret;
339
340 return 0;
341}
342
343struct snd_soc_ops mop500_ab8500_ops[] = {
344 {
345 .hw_params = mop500_ab8500_hw_params,
346 .startup = mop500_ab8500_startup,
347 .shutdown = mop500_ab8500_shutdown,
348 }
349};
350
351int mop500_ab8500_machine_init(struct snd_soc_pcm_runtime *rtd)
352{
353 struct snd_soc_codec *codec = rtd->codec;
354 struct device *dev = rtd->card->dev;
355 struct mop500_ab8500_drvdata *drvdata;
356 int ret;
357
358 dev_dbg(dev, "%s Enter.\n", __func__);
359
360 /* Create driver private-data struct */
361 drvdata = devm_kzalloc(dev, sizeof(struct mop500_ab8500_drvdata),
362 GFP_KERNEL);
363 snd_soc_card_set_drvdata(rtd->card, drvdata);
364
365 /* Setup clocks */
366
367 drvdata->clk_ptr_sysclk = clk_get(dev, "sysclk");
368 if (IS_ERR(drvdata->clk_ptr_sysclk))
369 dev_warn(dev, "%s: WARNING: clk_get failed for 'sysclk'!\n",
370 __func__);
371 drvdata->clk_ptr_ulpclk = clk_get(dev, "ulpclk");
372 if (IS_ERR(drvdata->clk_ptr_ulpclk))
373 dev_warn(dev, "%s: WARNING: clk_get failed for 'ulpclk'!\n",
374 __func__);
375 drvdata->clk_ptr_intclk = clk_get(dev, "intclk");
376 if (IS_ERR(drvdata->clk_ptr_intclk))
377 dev_warn(dev, "%s: WARNING: clk_get failed for 'intclk'!\n",
378 __func__);
379
380 /* Set intclk default parent to ulpclk */
381 drvdata->mclk_sel = MCLK_ULPCLK;
382 ret = mop500_ab8500_set_mclk(dev, drvdata);
383 if (ret < 0)
384 dev_warn(dev, "%s: WARNING: mop500_ab8500_set_mclk!\n",
385 __func__);
386
387 drvdata->mclk_sel = MCLK_ULPCLK;
388
389 /* Add controls */
390 ret = snd_soc_add_codec_controls(codec, mop500_ab8500_ctrls,
391 ARRAY_SIZE(mop500_ab8500_ctrls));
392 if (ret < 0) {
393 pr_err("%s: Failed to add machine-controls (%d)!\n",
394 __func__, ret);
395 return ret;
396 }
397
398 ret = snd_soc_dapm_disable_pin(&codec->dapm, "Earpiece");
399 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Speaker Left");
400 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Speaker Right");
401 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineOut Left");
402 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineOut Right");
403 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Vibra 1");
404 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Vibra 2");
405 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Mic 1");
406 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "Mic 2");
407 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineIn Left");
408 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "LineIn Right");
409 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 1");
410 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 2");
411 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 3");
412 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 4");
413 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 5");
414 ret |= snd_soc_dapm_disable_pin(&codec->dapm, "DMic 6");
415
416 return ret;
417}
418
419void mop500_ab8500_remove(struct snd_soc_card *card)
420{
421 struct mop500_ab8500_drvdata *drvdata = snd_soc_card_get_drvdata(card);
422
423 if (drvdata->clk_ptr_sysclk != NULL)
424 clk_put(drvdata->clk_ptr_sysclk);
425 if (drvdata->clk_ptr_ulpclk != NULL)
426 clk_put(drvdata->clk_ptr_ulpclk);
427 if (drvdata->clk_ptr_intclk != NULL)
428 clk_put(drvdata->clk_ptr_intclk);
429
430 snd_soc_card_set_drvdata(card, drvdata);
431}
diff --git a/sound/soc/ux500/mop500_ab8500.h b/sound/soc/ux500/mop500_ab8500.h
new file mode 100644
index 00000000000..cca5b33964b
--- /dev/null
+++ b/sound/soc/ux500/mop500_ab8500.h
@@ -0,0 +1,22 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2012
3 *
4 * Author: Ola Lilja <ola.o.lilja@stericsson.com>
5 * for ST-Ericsson.
6 *
7 * License terms:
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as published
11 * by the Free Software Foundation.
12 */
13
14#ifndef MOP500_AB8500_H
15#define MOP500_AB8500_H
16
17extern struct snd_soc_ops mop500_ab8500_ops[];
18
19int mop500_ab8500_machine_init(struct snd_soc_pcm_runtime *runtime);
20void mop500_ab8500_remove(struct snd_soc_card *card);
21
22#endif
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c
index 93c6c40e724..62ac0285bfa 100644
--- a/sound/soc/ux500/ux500_msp_dai.c
+++ b/sound/soc/ux500/ux500_msp_dai.c
@@ -840,4 +840,4 @@ static struct platform_driver msp_i2s_driver = {
840}; 840};
841module_platform_driver(msp_i2s_driver); 841module_platform_driver(msp_i2s_driver);
842 842
843MODULE_LICENSE("GPLv2"); 843MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c
index 496dec10c96..ee14d2dac2f 100644
--- a/sound/soc/ux500/ux500_msp_i2s.c
+++ b/sound/soc/ux500/ux500_msp_i2s.c
@@ -739,4 +739,4 @@ void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev,
739 devm_kfree(&pdev->dev, msp); 739 devm_kfree(&pdev->dev, msp);
740} 740}
741 741
742MODULE_LICENSE("GPLv2"); 742MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c
new file mode 100644
index 00000000000..1a04e248453
--- /dev/null
+++ b/sound/soc/ux500/ux500_pcm.c
@@ -0,0 +1,318 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2012
3 *
4 * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
5 * Roger Nilsson <roger.xr.nilsson@stericsson.com>
6 * for ST-Ericsson.
7 *
8 * License terms:
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as published
12 * by the Free Software Foundation.
13 */
14
15#include <asm/page.h>
16
17#include <linux/module.h>
18#include <linux/dma-mapping.h>
19#include <linux/dmaengine.h>
20#include <linux/slab.h>
21
22#include <plat/ste_dma40.h>
23
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include <sound/soc.h>
27#include <sound/dmaengine_pcm.h>
28
29#include "ux500_msp_i2s.h"
30#include "ux500_pcm.h"
31
32static struct snd_pcm_hardware ux500_pcm_hw_playback = {
33 .info = SNDRV_PCM_INFO_INTERLEAVED |
34 SNDRV_PCM_INFO_MMAP |
35 SNDRV_PCM_INFO_RESUME |
36 SNDRV_PCM_INFO_PAUSE,
37 .formats = SNDRV_PCM_FMTBIT_S16_LE |
38 SNDRV_PCM_FMTBIT_U16_LE |
39 SNDRV_PCM_FMTBIT_S16_BE |
40 SNDRV_PCM_FMTBIT_U16_BE,
41 .rates = SNDRV_PCM_RATE_KNOT,
42 .rate_min = UX500_PLATFORM_MIN_RATE_PLAYBACK,
43 .rate_max = UX500_PLATFORM_MAX_RATE_PLAYBACK,
44 .channels_min = UX500_PLATFORM_MIN_CHANNELS,
45 .channels_max = UX500_PLATFORM_MAX_CHANNELS,
46 .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX,
47 .period_bytes_min = UX500_PLATFORM_PERIODS_BYTES_MIN,
48 .period_bytes_max = UX500_PLATFORM_PERIODS_BYTES_MAX,
49 .periods_min = UX500_PLATFORM_PERIODS_MIN,
50 .periods_max = UX500_PLATFORM_PERIODS_MAX,
51};
52
53static struct snd_pcm_hardware ux500_pcm_hw_capture = {
54 .info = SNDRV_PCM_INFO_INTERLEAVED |
55 SNDRV_PCM_INFO_MMAP |
56 SNDRV_PCM_INFO_RESUME |
57 SNDRV_PCM_INFO_PAUSE,
58 .formats = SNDRV_PCM_FMTBIT_S16_LE |
59 SNDRV_PCM_FMTBIT_U16_LE |
60 SNDRV_PCM_FMTBIT_S16_BE |
61 SNDRV_PCM_FMTBIT_U16_BE,
62 .rates = SNDRV_PCM_RATE_KNOT,
63 .rate_min = UX500_PLATFORM_MIN_RATE_CAPTURE,
64 .rate_max = UX500_PLATFORM_MAX_RATE_CAPTURE,
65 .channels_min = UX500_PLATFORM_MIN_CHANNELS,
66 .channels_max = UX500_PLATFORM_MAX_CHANNELS,
67 .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX,
68 .period_bytes_min = UX500_PLATFORM_PERIODS_BYTES_MIN,
69 .period_bytes_max = UX500_PLATFORM_PERIODS_BYTES_MAX,
70 .periods_min = UX500_PLATFORM_PERIODS_MIN,
71 .periods_max = UX500_PLATFORM_PERIODS_MAX,
72};
73
74static void ux500_pcm_dma_hw_free(struct device *dev,
75 struct snd_pcm_substream *substream)
76{
77 struct snd_pcm_runtime *runtime = substream->runtime;
78 struct snd_dma_buffer *buf = runtime->dma_buffer_p;
79
80 if (runtime->dma_area == NULL)
81 return;
82
83 if (buf != &substream->dma_buffer) {
84 dma_free_coherent(buf->dev.dev, buf->bytes, buf->area,
85 buf->addr);
86 kfree(runtime->dma_buffer_p);
87 }
88
89 snd_pcm_set_runtime_buffer(substream, NULL);
90}
91
92static int ux500_pcm_open(struct snd_pcm_substream *substream)
93{
94 int stream_id = substream->pstr->stream;
95 struct snd_pcm_runtime *runtime = substream->runtime;
96 struct snd_soc_pcm_runtime *rtd = substream->private_data;
97 struct snd_soc_dai *dai = rtd->cpu_dai;
98 struct device *dev = dai->dev;
99 int ret;
100 struct ux500_msp_dma_params *dma_params;
101 u16 per_data_width, mem_data_width;
102 struct stedma40_chan_cfg *dma_cfg;
103
104 dev_dbg(dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id,
105 snd_pcm_stream_str(substream));
106
107 dev_dbg(dev, "%s: Set runtime hwparams.\n", __func__);
108 if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
109 snd_soc_set_runtime_hwparams(substream,
110 &ux500_pcm_hw_playback);
111 else
112 snd_soc_set_runtime_hwparams(substream,
113 &ux500_pcm_hw_capture);
114
115 /* ensure that buffer size is a multiple of period size */
116 ret = snd_pcm_hw_constraint_integer(runtime,
117 SNDRV_PCM_HW_PARAM_PERIODS);
118 if (ret < 0) {
119 dev_err(dev, "%s: Error: snd_pcm_hw_constraints failed (%d)\n",
120 __func__, ret);
121 return ret;
122 }
123
124 dev_dbg(dev, "%s: Set hw-struct for %s.\n", __func__,
125 snd_pcm_stream_str(substream));
126 runtime->hw = (stream_id == SNDRV_PCM_STREAM_PLAYBACK) ?
127 ux500_pcm_hw_playback : ux500_pcm_hw_capture;
128
129 mem_data_width = STEDMA40_HALFWORD_WIDTH;
130
131 dma_params = snd_soc_dai_get_dma_data(dai, substream);
132 switch (dma_params->data_size) {
133 case 32:
134 per_data_width = STEDMA40_WORD_WIDTH;
135 break;
136 case 16:
137 per_data_width = STEDMA40_HALFWORD_WIDTH;
138 break;
139 case 8:
140 per_data_width = STEDMA40_BYTE_WIDTH;
141 break;
142 default:
143 per_data_width = STEDMA40_WORD_WIDTH;
144 dev_warn(rtd->platform->dev,
145 "%s: Unknown data-size (%d)! Assuming 32 bits.\n",
146 __func__, dma_params->data_size);
147 }
148
149 dma_cfg = dma_params->dma_cfg;
150
151 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
152 dma_cfg->src_info.data_width = mem_data_width;
153 dma_cfg->dst_info.data_width = per_data_width;
154 } else {
155 dma_cfg->src_info.data_width = per_data_width;
156 dma_cfg->dst_info.data_width = mem_data_width;
157 }
158
159
160 ret = snd_dmaengine_pcm_open(substream, stedma40_filter, dma_cfg);
161 if (ret) {
162 dev_dbg(dai->dev,
163 "%s: ERROR: snd_dmaengine_pcm_open failed (%d)!\n",
164 __func__, ret);
165 return ret;
166 }
167
168 snd_dmaengine_pcm_set_data(substream, dma_cfg);
169
170 return 0;
171}
172
173static int ux500_pcm_close(struct snd_pcm_substream *substream)
174{
175 struct snd_soc_pcm_runtime *rtd = substream->private_data;
176 struct snd_soc_dai *dai = rtd->cpu_dai;
177
178 dev_dbg(dai->dev, "%s: Enter\n", __func__);
179
180 snd_dmaengine_pcm_close(substream);
181
182 return 0;
183}
184
185static int ux500_pcm_hw_params(struct snd_pcm_substream *substream,
186 struct snd_pcm_hw_params *hw_params)
187{
188 struct snd_pcm_runtime *runtime = substream->runtime;
189 struct snd_dma_buffer *buf = runtime->dma_buffer_p;
190 struct snd_soc_pcm_runtime *rtd = substream->private_data;
191 int ret = 0;
192 int size;
193
194 dev_dbg(rtd->platform->dev, "%s: Enter\n", __func__);
195
196 size = params_buffer_bytes(hw_params);
197
198 if (buf) {
199 if (buf->bytes >= size)
200 goto out;
201 ux500_pcm_dma_hw_free(NULL, substream);
202 }
203
204 if (substream->dma_buffer.area != NULL &&
205 substream->dma_buffer.bytes >= size) {
206 buf = &substream->dma_buffer;
207 } else {
208 buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL);
209 if (!buf)
210 goto nomem;
211
212 buf->dev.type = SNDRV_DMA_TYPE_DEV;
213 buf->dev.dev = NULL;
214 buf->area = dma_alloc_coherent(NULL, size, &buf->addr,
215 GFP_KERNEL);
216 buf->bytes = size;
217 buf->private_data = NULL;
218
219 if (!buf->area)
220 goto free;
221 }
222 snd_pcm_set_runtime_buffer(substream, buf);
223 ret = 1;
224 out:
225 runtime->dma_bytes = size;
226 return ret;
227
228 free:
229 kfree(buf);
230 nomem:
231 return -ENOMEM;
232}
233
234static int ux500_pcm_hw_free(struct snd_pcm_substream *substream)
235{
236 struct snd_soc_pcm_runtime *rtd = substream->private_data;
237
238 dev_dbg(rtd->platform->dev, "%s: Enter\n", __func__);
239
240 ux500_pcm_dma_hw_free(NULL, substream);
241
242 return 0;
243}
244
245static int ux500_pcm_mmap(struct snd_pcm_substream *substream,
246 struct vm_area_struct *vma)
247{
248 struct snd_pcm_runtime *runtime = substream->runtime;
249 struct snd_soc_pcm_runtime *rtd = substream->private_data;
250
251 dev_dbg(rtd->platform->dev, "%s: Enter.\n", __func__);
252
253 return dma_mmap_coherent(NULL, vma, runtime->dma_area,
254 runtime->dma_addr, runtime->dma_bytes);
255}
256
257static struct snd_pcm_ops ux500_pcm_ops = {
258 .open = ux500_pcm_open,
259 .close = ux500_pcm_close,
260 .ioctl = snd_pcm_lib_ioctl,
261 .hw_params = ux500_pcm_hw_params,
262 .hw_free = ux500_pcm_hw_free,
263 .trigger = snd_dmaengine_pcm_trigger,
264 .pointer = snd_dmaengine_pcm_pointer_no_residue,
265 .mmap = ux500_pcm_mmap
266};
267
268int ux500_pcm_new(struct snd_soc_pcm_runtime *rtd)
269{
270 struct snd_pcm *pcm = rtd->pcm;
271
272 dev_dbg(rtd->platform->dev, "%s: Enter (id = '%s').\n", __func__,
273 pcm->id);
274
275 pcm->info_flags = 0;
276
277 return 0;
278}
279
280static struct snd_soc_platform_driver ux500_pcm_soc_drv = {
281 .ops = &ux500_pcm_ops,
282 .pcm_new = ux500_pcm_new,
283};
284
285static int __devexit ux500_pcm_drv_probe(struct platform_device *pdev)
286{
287 int ret;
288
289 ret = snd_soc_register_platform(&pdev->dev, &ux500_pcm_soc_drv);
290 if (ret < 0) {
291 dev_err(&pdev->dev,
292 "%s: ERROR: Failed to register platform '%s' (%d)!\n",
293 __func__, pdev->name, ret);
294 return ret;
295 }
296
297 return 0;
298}
299
300static int __devinit ux500_pcm_drv_remove(struct platform_device *pdev)
301{
302 snd_soc_unregister_platform(&pdev->dev);
303
304 return 0;
305}
306
307static struct platform_driver ux500_pcm_driver = {
308 .driver = {
309 .name = "ux500-pcm",
310 .owner = THIS_MODULE,
311 },
312
313 .probe = ux500_pcm_drv_probe,
314 .remove = __devexit_p(ux500_pcm_drv_remove),
315};
316module_platform_driver(ux500_pcm_driver);
317
318MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/ux500/ux500_pcm.h b/sound/soc/ux500/ux500_pcm.h
new file mode 100644
index 00000000000..77ed44d371e
--- /dev/null
+++ b/sound/soc/ux500/ux500_pcm.h
@@ -0,0 +1,35 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2012
3 *
4 * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
5 * Roger Nilsson <roger.xr.nilsson@stericsson.com>
6 * for ST-Ericsson.
7 *
8 * License terms:
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as published
12 * by the Free Software Foundation.
13 */
14#ifndef UX500_PCM_H
15#define UX500_PCM_H
16
17#include <asm/page.h>
18
19#include <linux/workqueue.h>
20
21#define UX500_PLATFORM_MIN_RATE_PLAYBACK 8000
22#define UX500_PLATFORM_MAX_RATE_PLAYBACK 48000
23#define UX500_PLATFORM_MIN_RATE_CAPTURE 8000
24#define UX500_PLATFORM_MAX_RATE_CAPTURE 48000
25
26#define UX500_PLATFORM_MIN_CHANNELS 1
27#define UX500_PLATFORM_MAX_CHANNELS 8
28
29#define UX500_PLATFORM_PERIODS_BYTES_MIN 128
30#define UX500_PLATFORM_PERIODS_BYTES_MAX (64 * PAGE_SIZE)
31#define UX500_PLATFORM_PERIODS_MIN 2
32#define UX500_PLATFORM_PERIODS_MAX 48
33#define UX500_PLATFORM_BUFFER_BYTES_MAX (2048 * PAGE_SIZE)
34
35#endif