aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-12-25 05:40:25 -0500
committerTakashi Iwai <tiwai@suse.de>2008-12-25 05:40:25 -0500
commit5c8261e44eaebbc91f9fc1bbd3f3167e91a50a57 (patch)
tree6b932687edc73c07e544ccba3f0130fdb257d902
parentfacef8685b3ff95c01c33d9d836401d0dd26211d (diff)
parent472346da9cc4231bec03ff2032e0d5fd4037232c (diff)
Merge branch 'topic/asoc' into to-push
-rw-r--r--Documentation/sound/alsa/soc/machine.txt8
-rw-r--r--MAINTAINERS2
-rw-r--r--arch/arm/mach-pxa/include/mach/palmasoc.h13
-rw-r--r--include/linux/mfd/wm8350/audio.h38
-rw-r--r--include/sound/l3.h18
-rw-r--r--include/sound/s3c24xx_uda134x.h14
-rw-r--r--include/sound/soc-dai.h231
-rw-r--r--include/sound/soc-dapm.h2
-rw-r--r--include/sound/soc.h206
-rw-r--r--include/sound/uda134x.h26
-rw-r--r--sound/soc/Kconfig13
-rw-r--r--sound/soc/Makefile12
-rw-r--r--sound/soc/at32/Kconfig34
-rw-r--r--sound/soc/at32/Makefile11
-rw-r--r--sound/soc/at32/at32-pcm.c492
-rw-r--r--sound/soc/at32/at32-pcm.h79
-rw-r--r--sound/soc/at32/at32-ssc.c849
-rw-r--r--sound/soc/at32/at32-ssc.h59
-rw-r--r--sound/soc/at91/Kconfig10
-rw-r--r--sound/soc/at91/Makefile6
-rw-r--r--sound/soc/at91/at91-pcm.c434
-rw-r--r--sound/soc/at91/at91-pcm.h72
-rw-r--r--sound/soc/at91/at91-ssc.c791
-rw-r--r--sound/soc/at91/at91-ssc.h27
-rw-r--r--sound/soc/atmel/Kconfig43
-rw-r--r--sound/soc/atmel/Makefile15
-rw-r--r--sound/soc/atmel/atmel-pcm.c494
-rw-r--r--sound/soc/atmel/atmel-pcm.h86
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c790
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.h121
-rw-r--r--sound/soc/atmel/playpaq_wm8510.c (renamed from sound/soc/at32/playpaq_wm8510.c)11
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c328
-rw-r--r--sound/soc/au1x/dbdma2.c3
-rw-r--r--sound/soc/au1x/psc-ac97.c16
-rw-r--r--sound/soc/au1x/psc-i2s.c18
-rw-r--r--sound/soc/au1x/sample-ac97.c4
-rw-r--r--sound/soc/blackfin/Kconfig22
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.c113
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.c178
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.h35
-rw-r--r--sound/soc/blackfin/bf5xx-ad1980.c8
-rw-r--r--sound/soc/blackfin/bf5xx-ad73311.c10
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c12
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c31
-rw-r--r--sound/soc/blackfin/bf5xx-sport.h2
-rw-r--r--sound/soc/blackfin/bf5xx-ssm2602.c14
-rw-r--r--sound/soc/codecs/Kconfig69
-rw-r--r--sound/soc/codecs/Makefile12
-rw-r--r--sound/soc/codecs/ac97.c7
-rw-r--r--sound/soc/codecs/ad1980.c24
-rw-r--r--sound/soc/codecs/ad73311.c18
-rw-r--r--sound/soc/codecs/ak4535.c19
-rw-r--r--sound/soc/codecs/cs4270.c38
-rw-r--r--sound/soc/codecs/l3.c91
-rw-r--r--sound/soc/codecs/pcm3008.c212
-rw-r--r--sound/soc/codecs/pcm3008.h25
-rw-r--r--sound/soc/codecs/ssm2602.c57
-rw-r--r--sound/soc/codecs/tlv320aic23.c262
-rw-r--r--sound/soc/codecs/tlv320aic26.c22
-rw-r--r--sound/soc/codecs/tlv320aic3x.c166
-rw-r--r--sound/soc/codecs/tlv320aic3x.h60
-rw-r--r--sound/soc/codecs/twl4030.c1317
-rw-r--r--sound/soc/codecs/twl4030.h219
-rw-r--r--sound/soc/codecs/uda134x.c668
-rw-r--r--sound/soc/codecs/uda134x.h36
-rw-r--r--sound/soc/codecs/uda1380.c29
-rw-r--r--sound/soc/codecs/wm8350.c1583
-rw-r--r--sound/soc/codecs/wm8350.h20
-rw-r--r--sound/soc/codecs/wm8510.c19
-rw-r--r--sound/soc/codecs/wm8580.c134
-rw-r--r--sound/soc/codecs/wm8580.h1
-rw-r--r--sound/soc/codecs/wm8728.c585
-rw-r--r--sound/soc/codecs/wm8728.h30
-rw-r--r--sound/soc/codecs/wm8731.c25
-rw-r--r--sound/soc/codecs/wm8750.c19
-rw-r--r--sound/soc/codecs/wm8753.c39
-rw-r--r--sound/soc/codecs/wm8900.c262
-rw-r--r--sound/soc/codecs/wm8900.h6
-rw-r--r--sound/soc/codecs/wm8903.c268
-rw-r--r--sound/soc/codecs/wm8903.h5
-rw-r--r--sound/soc/codecs/wm8971.c19
-rw-r--r--sound/soc/codecs/wm8990.c43
-rw-r--r--sound/soc/codecs/wm8990.h4
-rw-r--r--sound/soc/codecs/wm9712.c12
-rw-r--r--sound/soc/codecs/wm9713.c46
-rw-r--r--sound/soc/davinci/Kconfig10
-rw-r--r--sound/soc/davinci/Makefile2
-rw-r--r--sound/soc/davinci/davinci-evm.c14
-rw-r--r--sound/soc/davinci/davinci-i2s.c257
-rw-r--r--sound/soc/davinci/davinci-pcm.c30
-rw-r--r--sound/soc/davinci/davinci-sffsdr.c157
-rw-r--r--sound/soc/fsl/Kconfig2
-rw-r--r--sound/soc/fsl/fsl_dma.c14
-rw-r--r--sound/soc/fsl/fsl_ssi.c24
-rw-r--r--sound/soc/fsl/mpc5200_psc_i2s.c22
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c8
-rw-r--r--sound/soc/fsl/soc-of-simple.c12
-rw-r--r--sound/soc/omap/Kconfig35
-rw-r--r--sound/soc/omap/Makefile8
-rw-r--r--sound/soc/omap/n810.c10
-rw-r--r--sound/soc/omap/omap-mcbsp.c61
-rw-r--r--sound/soc/omap/omap-pcm.c14
-rw-r--r--sound/soc/omap/omap2evm.c151
-rw-r--r--sound/soc/omap/omap3beagle.c149
-rw-r--r--sound/soc/omap/omap3pandora.c311
-rw-r--r--sound/soc/omap/osk5912.c10
-rw-r--r--sound/soc/omap/overo.c148
-rw-r--r--sound/soc/omap/sdp3430.c152
-rw-r--r--sound/soc/pxa/Kconfig22
-rw-r--r--sound/soc/pxa/Makefile6
-rw-r--r--sound/soc/pxa/corgi.c12
-rw-r--r--sound/soc/pxa/e800_wm9712.c8
-rw-r--r--sound/soc/pxa/em-x270.c7
-rw-r--r--sound/soc/pxa/palm27x.c269
-rw-r--r--sound/soc/pxa/poodle.c6
-rw-r--r--sound/soc/pxa/pxa-ssp.c931
-rw-r--r--sound/soc/pxa/pxa-ssp.h47
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c33
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c35
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c14
-rw-r--r--sound/soc/pxa/spitz.c6
-rw-r--r--sound/soc/pxa/tosa.c38
-rw-r--r--sound/soc/pxa/zylonite.c219
-rw-r--r--sound/soc/s3c24xx/Kconfig5
-rw-r--r--sound/soc/s3c24xx/Makefile2
-rw-r--r--sound/soc/s3c24xx/ln2440sbc_alc650.c8
-rw-r--r--sound/soc/s3c24xx/neo1973_wm8753.c9
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.c38
-rw-r--r--sound/soc/s3c24xx/s3c2443-ac97.c30
-rw-r--r--sound/soc/s3c24xx/s3c24xx-i2s.c35
-rw-r--r--sound/soc/s3c24xx/s3c24xx-pcm.c12
-rw-r--r--sound/soc/s3c24xx/s3c24xx_uda134x.c373
-rw-r--r--sound/soc/s3c24xx/smdk2443_wm9710.c8
-rw-r--r--sound/soc/sh/dma-sh7760.c12
-rw-r--r--sound/soc/sh/hac.c19
-rw-r--r--sound/soc/sh/sh7760-ac97.c6
-rw-r--r--sound/soc/sh/ssi.c30
-rw-r--r--sound/soc/soc-core.c840
-rw-r--r--sound/soc/soc-dapm.c82
139 files changed, 12650 insertions, 4385 deletions
diff --git a/Documentation/sound/alsa/soc/machine.txt b/Documentation/sound/alsa/soc/machine.txt
index f370e7db86af..bab7711ce963 100644
--- a/Documentation/sound/alsa/soc/machine.txt
+++ b/Documentation/sound/alsa/soc/machine.txt
@@ -9,7 +9,7 @@ the audio subsystem with the kernel as a platform device and is represented by
9the following struct:- 9the following struct:-
10 10
11/* SoC machine */ 11/* SoC machine */
12struct snd_soc_machine { 12struct snd_soc_card {
13 char *name; 13 char *name;
14 14
15 int (*probe)(struct platform_device *pdev); 15 int (*probe)(struct platform_device *pdev);
@@ -67,10 +67,10 @@ static struct snd_soc_dai_link corgi_dai = {
67 .ops = &corgi_ops, 67 .ops = &corgi_ops,
68}; 68};
69 69
70struct snd_soc_machine then sets up the machine with it's DAIs. e.g. 70struct snd_soc_card then sets up the machine with it's DAIs. e.g.
71 71
72/* corgi audio machine driver */ 72/* corgi audio machine driver */
73static struct snd_soc_machine snd_soc_machine_corgi = { 73static struct snd_soc_card snd_soc_corgi = {
74 .name = "Corgi", 74 .name = "Corgi",
75 .dai_link = &corgi_dai, 75 .dai_link = &corgi_dai,
76 .num_links = 1, 76 .num_links = 1,
@@ -90,7 +90,7 @@ static struct wm8731_setup_data corgi_wm8731_setup = {
90 90
91/* corgi audio subsystem */ 91/* corgi audio subsystem */
92static struct snd_soc_device corgi_snd_devdata = { 92static struct snd_soc_device corgi_snd_devdata = {
93 .machine = &snd_soc_machine_corgi, 93 .machine = &snd_soc_corgi,
94 .platform = &pxa2xx_soc_platform, 94 .platform = &pxa2xx_soc_platform,
95 .codec_dev = &soc_codec_dev_wm8731, 95 .codec_dev = &soc_codec_dev_wm8731,
96 .codec_data = &corgi_wm8731_setup, 96 .codec_data = &corgi_wm8731_setup,
diff --git a/MAINTAINERS b/MAINTAINERS
index fbc8fa58d56d..701025701514 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3977,7 +3977,7 @@ M: tiwai@suse.de
3977L: alsa-devel@alsa-project.org (subscribers-only) 3977L: alsa-devel@alsa-project.org (subscribers-only)
3978S: Maintained 3978S: Maintained
3979 3979
3980SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT 3980SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
3981P: Liam Girdwood 3981P: Liam Girdwood
3982M: lrg@slimlogic.co.uk 3982M: lrg@slimlogic.co.uk
3983P: Mark Brown 3983P: Mark Brown
diff --git a/arch/arm/mach-pxa/include/mach/palmasoc.h b/arch/arm/mach-pxa/include/mach/palmasoc.h
new file mode 100644
index 000000000000..6c4b1f7de20a
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/palmasoc.h
@@ -0,0 +1,13 @@
1#ifndef _INCLUDE_PALMASOC_H_
2#define _INCLUDE_PALMASOC_H_
3struct palm27x_asoc_info {
4 int jack_gpio;
5};
6
7#ifdef CONFIG_SND_PXA2XX_SOC_PALM27X
8void __init palm27x_asoc_set_pdata(struct palm27x_asoc_info *data);
9#else
10static inline void palm27x_asoc_set_pdata(struct palm27x_asoc_info *data) {}
11#endif
12
13#endif
diff --git a/include/linux/mfd/wm8350/audio.h b/include/linux/mfd/wm8350/audio.h
index 217bb22ebb8e..af95a1d2f3a1 100644
--- a/include/linux/mfd/wm8350/audio.h
+++ b/include/linux/mfd/wm8350/audio.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * audio.h -- Audio Driver for Wolfson WM8350 PMIC 2 * audio.h -- Audio Driver for Wolfson WM8350 PMIC
3 * 3 *
4 * Copyright 2007 Wolfson Microelectronics PLC 4 * Copyright 2007, 2008 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
@@ -70,9 +70,9 @@
70#define WM8350_CODEC_ISEL_0_5 3 /* x0.5 */ 70#define WM8350_CODEC_ISEL_0_5 3 /* x0.5 */
71 71
72#define WM8350_VMID_OFF 0 72#define WM8350_VMID_OFF 0
73#define WM8350_VMID_500K 1 73#define WM8350_VMID_300K 1
74#define WM8350_VMID_100K 2 74#define WM8350_VMID_50K 2
75#define WM8350_VMID_10K 3 75#define WM8350_VMID_5K 3
76 76
77/* 77/*
78 * R40 (0x28) - Clock Control 1 78 * R40 (0x28) - Clock Control 1
@@ -591,8 +591,38 @@
591#define WM8350_IRQ_CODEC_MICSCD 41 591#define WM8350_IRQ_CODEC_MICSCD 41
592#define WM8350_IRQ_CODEC_MICD 42 592#define WM8350_IRQ_CODEC_MICD 42
593 593
594/*
595 * WM8350 Platform data.
596 *
597 * This must be initialised per platform for best audio performance.
598 * Please see WM8350 datasheet for information.
599 */
600struct wm8350_audio_platform_data {
601 int vmid_discharge_msecs; /* VMID --> OFF discharge time */
602 int drain_msecs; /* OFF drain time */
603 int cap_discharge_msecs; /* Cap ON (from OFF) discharge time */
604 int vmid_charge_msecs; /* vmid power up time */
605 u32 vmid_s_curve:2; /* vmid enable s curve speed */
606 u32 dis_out4:2; /* out4 discharge speed */
607 u32 dis_out3:2; /* out3 discharge speed */
608 u32 dis_out2:2; /* out2 discharge speed */
609 u32 dis_out1:2; /* out1 discharge speed */
610 u32 vroi_out4:1; /* out4 tie off */
611 u32 vroi_out3:1; /* out3 tie off */
612 u32 vroi_out2:1; /* out2 tie off */
613 u32 vroi_out1:1; /* out1 tie off */
614 u32 vroi_enable:1; /* enable tie off */
615 u32 codec_current_on:2; /* current level ON */
616 u32 codec_current_standby:2; /* current level STANDBY */
617 u32 codec_current_charge:2; /* codec current @ vmid charge */
618};
619
620struct snd_soc_codec;
621
594struct wm8350_codec { 622struct wm8350_codec {
595 struct platform_device *pdev; 623 struct platform_device *pdev;
624 struct snd_soc_codec *codec;
625 struct wm8350_audio_platform_data *platform_data;
596}; 626};
597 627
598#endif 628#endif
diff --git a/include/sound/l3.h b/include/sound/l3.h
new file mode 100644
index 000000000000..423a08f0f1b0
--- /dev/null
+++ b/include/sound/l3.h
@@ -0,0 +1,18 @@
1#ifndef _L3_H_
2#define _L3_H_ 1
3
4struct l3_pins {
5 void (*setdat)(int);
6 void (*setclk)(int);
7 void (*setmode)(int);
8 int data_hold;
9 int data_setup;
10 int clock_high;
11 int mode_hold;
12 int mode;
13 int mode_setup;
14};
15
16int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len);
17
18#endif
diff --git a/include/sound/s3c24xx_uda134x.h b/include/sound/s3c24xx_uda134x.h
new file mode 100644
index 000000000000..33df4cb909d3
--- /dev/null
+++ b/include/sound/s3c24xx_uda134x.h
@@ -0,0 +1,14 @@
1#ifndef _S3C24XX_UDA134X_H_
2#define _S3C24XX_UDA134X_H_ 1
3
4#include <sound/uda134x.h>
5
6struct s3c24xx_uda134x_platform_data {
7 int l3_clk;
8 int l3_mode;
9 int l3_data;
10 void (*power) (int);
11 int model;
12};
13
14#endif
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
new file mode 100644
index 000000000000..24247f763608
--- /dev/null
+++ b/include/sound/soc-dai.h
@@ -0,0 +1,231 @@
1/*
2 * linux/sound/soc-dai.h -- ALSA SoC Layer
3 *
4 * Copyright: 2005-2008 Wolfson Microelectronics. PLC.
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 * Digital Audio Interface (DAI) API.
11 */
12
13#ifndef __LINUX_SND_SOC_DAI_H
14#define __LINUX_SND_SOC_DAI_H
15
16
17#include <linux/list.h>
18
19struct snd_pcm_substream;
20
21/*
22 * DAI hardware audio formats.
23 *
24 * Describes the physical PCM data formating and clocking. Add new formats
25 * to the end.
26 */
27#define SND_SOC_DAIFMT_I2S 0 /* I2S mode */
28#define SND_SOC_DAIFMT_RIGHT_J 1 /* Right Justified mode */
29#define SND_SOC_DAIFMT_LEFT_J 2 /* Left Justified mode */
30#define SND_SOC_DAIFMT_DSP_A 3 /* L data msb after FRM LRC */
31#define SND_SOC_DAIFMT_DSP_B 4 /* L data msb during FRM LRC */
32#define SND_SOC_DAIFMT_AC97 5 /* AC97 */
33
34/* left and right justified also known as MSB and LSB respectively */
35#define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J
36#define SND_SOC_DAIFMT_LSB SND_SOC_DAIFMT_RIGHT_J
37
38/*
39 * DAI Clock gating.
40 *
41 * DAI bit clocks can be be gated (disabled) when not the DAI is not
42 * sending or receiving PCM data in a frame. This can be used to save power.
43 */
44#define SND_SOC_DAIFMT_CONT (0 << 4) /* continuous clock */
45#define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated */
46
47/*
48 * DAI Left/Right Clocks.
49 *
50 * Specifies whether the DAI can support different samples for similtanious
51 * playback and capture. This usually requires a seperate physical frame
52 * clock for playback and capture.
53 */
54#define SND_SOC_DAIFMT_SYNC (0 << 5) /* Tx FRM = Rx FRM */
55#define SND_SOC_DAIFMT_ASYNC (1 << 5) /* Tx FRM ~ Rx FRM */
56
57/*
58 * TDM
59 *
60 * Time Division Multiplexing. Allows PCM data to be multplexed with other
61 * data on the DAI.
62 */
63#define SND_SOC_DAIFMT_TDM (1 << 6)
64
65/*
66 * DAI hardware signal inversions.
67 *
68 * Specifies whether the DAI can also support inverted clocks for the specified
69 * format.
70 */
71#define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bit clock + frame */
72#define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal bclk + inv frm */
73#define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert bclk + nor frm */
74#define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert bclk + frm */
75
76/*
77 * DAI hardware clock masters.
78 *
79 * This is wrt the codec, the inverse is true for the interface
80 * i.e. if the codec is clk and frm master then the interface is
81 * clk and frame slave.
82 */
83#define SND_SOC_DAIFMT_CBM_CFM (0 << 12) /* codec clk & frm master */
84#define SND_SOC_DAIFMT_CBS_CFM (1 << 12) /* codec clk slave & frm master */
85#define SND_SOC_DAIFMT_CBM_CFS (2 << 12) /* codec clk master & frame slave */
86#define SND_SOC_DAIFMT_CBS_CFS (3 << 12) /* codec clk & frm slave */
87
88#define SND_SOC_DAIFMT_FORMAT_MASK 0x000f
89#define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0
90#define SND_SOC_DAIFMT_INV_MASK 0x0f00
91#define SND_SOC_DAIFMT_MASTER_MASK 0xf000
92
93/*
94 * Master Clock Directions
95 */
96#define SND_SOC_CLOCK_IN 0
97#define SND_SOC_CLOCK_OUT 1
98
99struct snd_soc_dai_ops;
100struct snd_soc_dai;
101struct snd_ac97_bus_ops;
102
103/* Digital Audio Interface registration */
104int snd_soc_register_dai(struct snd_soc_dai *dai);
105void snd_soc_unregister_dai(struct snd_soc_dai *dai);
106int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count);
107void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count);
108
109/* Digital Audio Interface clocking API.*/
110int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
111 unsigned int freq, int dir);
112
113int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
114 int div_id, int div);
115
116int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
117 int pll_id, unsigned int freq_in, unsigned int freq_out);
118
119/* Digital Audio interface formatting */
120int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
121
122int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
123 unsigned int mask, int slots);
124
125int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
126
127/* Digital Audio Interface mute */
128int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute);
129
130/*
131 * Digital Audio Interface.
132 *
133 * Describes the Digital Audio Interface in terms of it's ALSA, DAI and AC97
134 * operations an capabilities. Codec and platfom drivers will register a this
135 * structure for every DAI they have.
136 *
137 * This structure covers the clocking, formating and ALSA operations for each
138 * interface a
139 */
140struct snd_soc_dai_ops {
141 /*
142 * DAI clocking configuration, all optional.
143 * Called by soc_card drivers, normally in their hw_params.
144 */
145 int (*set_sysclk)(struct snd_soc_dai *dai,
146 int clk_id, unsigned int freq, int dir);
147 int (*set_pll)(struct snd_soc_dai *dai,
148 int pll_id, unsigned int freq_in, unsigned int freq_out);
149 int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);
150
151 /*
152 * DAI format configuration
153 * Called by soc_card drivers, normally in their hw_params.
154 */
155 int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);
156 int (*set_tdm_slot)(struct snd_soc_dai *dai,
157 unsigned int mask, int slots);
158 int (*set_tristate)(struct snd_soc_dai *dai, int tristate);
159
160 /*
161 * DAI digital mute - optional.
162 * Called by soc-core to minimise any pops.
163 */
164 int (*digital_mute)(struct snd_soc_dai *dai, int mute);
165
166 /*
167 * ALSA PCM audio operations - all optional.
168 * Called by soc-core during audio PCM operations.
169 */
170 int (*startup)(struct snd_pcm_substream *,
171 struct snd_soc_dai *);
172 void (*shutdown)(struct snd_pcm_substream *,
173 struct snd_soc_dai *);
174 int (*hw_params)(struct snd_pcm_substream *,
175 struct snd_pcm_hw_params *, struct snd_soc_dai *);
176 int (*hw_free)(struct snd_pcm_substream *,
177 struct snd_soc_dai *);
178 int (*prepare)(struct snd_pcm_substream *,
179 struct snd_soc_dai *);
180 int (*trigger)(struct snd_pcm_substream *, int,
181 struct snd_soc_dai *);
182};
183
184/*
185 * Digital Audio Interface runtime data.
186 *
187 * Holds runtime data for a DAI.
188 */
189struct snd_soc_dai {
190 /* DAI description */
191 char *name;
192 unsigned int id;
193 int ac97_control;
194
195 struct device *dev;
196
197 /* DAI callbacks */
198 int (*probe)(struct platform_device *pdev,
199 struct snd_soc_dai *dai);
200 void (*remove)(struct platform_device *pdev,
201 struct snd_soc_dai *dai);
202 int (*suspend)(struct snd_soc_dai *dai);
203 int (*resume)(struct snd_soc_dai *dai);
204
205 /* ops */
206 struct snd_soc_dai_ops ops;
207
208 /* DAI capabilities */
209 struct snd_soc_pcm_stream capture;
210 struct snd_soc_pcm_stream playback;
211
212 /* DAI runtime info */
213 struct snd_pcm_runtime *runtime;
214 struct snd_soc_codec *codec;
215 unsigned int active;
216 unsigned char pop_wait:1;
217 void *dma_data;
218
219 /* DAI private data */
220 void *private_data;
221
222 /* parent codec/platform */
223 union {
224 struct snd_soc_codec *codec;
225 struct snd_soc_platform *platform;
226 };
227
228 struct list_head list;
229};
230
231#endif
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index ca699a3017f3..7ee2f70ca42e 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -221,8 +221,6 @@ int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
221 int num); 221 int num);
222 222
223/* dapm path setup */ 223/* dapm path setup */
224int __deprecated snd_soc_dapm_connect_input(struct snd_soc_codec *codec,
225 const char *sink_name, const char *control_name, const char *src_name);
226int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec); 224int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec);
227void snd_soc_dapm_free(struct snd_soc_device *socdev); 225void snd_soc_dapm_free(struct snd_soc_device *socdev);
228int snd_soc_dapm_add_routes(struct snd_soc_codec *codec, 226int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 5e0189876afd..f86e455d3828 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -21,8 +21,6 @@
21#include <sound/control.h> 21#include <sound/control.h>
22#include <sound/ac97_codec.h> 22#include <sound/ac97_codec.h>
23 23
24#define SND_SOC_VERSION "0.13.2"
25
26/* 24/*
27 * Convenience kcontrol builders 25 * Convenience kcontrol builders
28 */ 26 */
@@ -145,105 +143,31 @@ enum snd_soc_bias_level {
145 SND_SOC_BIAS_OFF, 143 SND_SOC_BIAS_OFF,
146}; 144};
147 145
148/*
149 * Digital Audio Interface (DAI) types
150 */
151#define SND_SOC_DAI_AC97 0x1
152#define SND_SOC_DAI_I2S 0x2
153#define SND_SOC_DAI_PCM 0x4
154#define SND_SOC_DAI_AC97_BUS 0x8 /* for custom i.e. non ac97_codec.c */
155
156/*
157 * DAI hardware audio formats
158 */
159#define SND_SOC_DAIFMT_I2S 0 /* I2S mode */
160#define SND_SOC_DAIFMT_RIGHT_J 1 /* Right justified mode */
161#define SND_SOC_DAIFMT_LEFT_J 2 /* Left Justified mode */
162#define SND_SOC_DAIFMT_DSP_A 3 /* L data msb after FRM or LRC */
163#define SND_SOC_DAIFMT_DSP_B 4 /* L data msb during FRM or LRC */
164#define SND_SOC_DAIFMT_AC97 5 /* AC97 */
165
166#define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J
167#define SND_SOC_DAIFMT_LSB SND_SOC_DAIFMT_RIGHT_J
168
169/*
170 * DAI Gating
171 */
172#define SND_SOC_DAIFMT_CONT (0 << 4) /* continuous clock */
173#define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated when not Tx/Rx */
174
175/*
176 * DAI Sync
177 * Synchronous LR (Left Right) clocks and Frame signals.
178 */
179#define SND_SOC_DAIFMT_SYNC (0 << 5) /* Tx FRM = Rx FRM */
180#define SND_SOC_DAIFMT_ASYNC (1 << 5) /* Tx FRM ~ Rx FRM */
181
182/*
183 * TDM
184 */
185#define SND_SOC_DAIFMT_TDM (1 << 6)
186
187/*
188 * DAI hardware signal inversions
189 */
190#define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bclk + frm */
191#define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal bclk + inv frm */
192#define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert bclk + nor frm */
193#define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert bclk + frm */
194
195/*
196 * DAI hardware clock masters
197 * This is wrt the codec, the inverse is true for the interface
198 * i.e. if the codec is clk and frm master then the interface is
199 * clk and frame slave.
200 */
201#define SND_SOC_DAIFMT_CBM_CFM (0 << 12) /* codec clk & frm master */
202#define SND_SOC_DAIFMT_CBS_CFM (1 << 12) /* codec clk slave & frm master */
203#define SND_SOC_DAIFMT_CBM_CFS (2 << 12) /* codec clk master & frame slave */
204#define SND_SOC_DAIFMT_CBS_CFS (3 << 12) /* codec clk & frm slave */
205
206#define SND_SOC_DAIFMT_FORMAT_MASK 0x000f
207#define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0
208#define SND_SOC_DAIFMT_INV_MASK 0x0f00
209#define SND_SOC_DAIFMT_MASTER_MASK 0xf000
210
211
212/*
213 * Master Clock Directions
214 */
215#define SND_SOC_CLOCK_IN 0
216#define SND_SOC_CLOCK_OUT 1
217
218/*
219 * AC97 codec ID's bitmask
220 */
221#define SND_SOC_DAI_AC97_ID0 (1 << 0)
222#define SND_SOC_DAI_AC97_ID1 (1 << 1)
223#define SND_SOC_DAI_AC97_ID2 (1 << 2)
224#define SND_SOC_DAI_AC97_ID3 (1 << 3)
225
226struct snd_soc_device; 146struct snd_soc_device;
227struct snd_soc_pcm_stream; 147struct snd_soc_pcm_stream;
228struct snd_soc_ops; 148struct snd_soc_ops;
229struct snd_soc_dai_mode; 149struct snd_soc_dai_mode;
230struct snd_soc_pcm_runtime; 150struct snd_soc_pcm_runtime;
231struct snd_soc_dai; 151struct snd_soc_dai;
152struct snd_soc_platform;
232struct snd_soc_codec; 153struct snd_soc_codec;
233struct snd_soc_machine_config;
234struct soc_enum; 154struct soc_enum;
235struct snd_soc_ac97_ops; 155struct snd_soc_ac97_ops;
236struct snd_soc_clock_info;
237 156
238typedef int (*hw_write_t)(void *,const char* ,int); 157typedef int (*hw_write_t)(void *,const char* ,int);
239typedef int (*hw_read_t)(void *,char* ,int); 158typedef int (*hw_read_t)(void *,char* ,int);
240 159
241extern struct snd_ac97_bus_ops soc_ac97_ops; 160extern struct snd_ac97_bus_ops soc_ac97_ops;
242 161
162int snd_soc_register_platform(struct snd_soc_platform *platform);
163void snd_soc_unregister_platform(struct snd_soc_platform *platform);
164int snd_soc_register_codec(struct snd_soc_codec *codec);
165void snd_soc_unregister_codec(struct snd_soc_codec *codec);
166
243/* pcm <-> DAI connect */ 167/* pcm <-> DAI connect */
244void snd_soc_free_pcms(struct snd_soc_device *socdev); 168void snd_soc_free_pcms(struct snd_soc_device *socdev);
245int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid); 169int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid);
246int snd_soc_register_card(struct snd_soc_device *socdev); 170int snd_soc_init_card(struct snd_soc_device *socdev);
247 171
248/* set runtime hw params */ 172/* set runtime hw params */
249int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, 173int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
@@ -263,27 +187,6 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
263 struct snd_ac97_bus_ops *ops, int num); 187 struct snd_ac97_bus_ops *ops, int num);
264void snd_soc_free_ac97_codec(struct snd_soc_codec *codec); 188void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
265 189
266/* Digital Audio Interface clocking API.*/
267int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
268 unsigned int freq, int dir);
269
270int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
271 int div_id, int div);
272
273int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
274 int pll_id, unsigned int freq_in, unsigned int freq_out);
275
276/* Digital Audio interface formatting */
277int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
278
279int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
280 unsigned int mask, int slots);
281
282int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
283
284/* Digital Audio Interface mute */
285int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute);
286
287/* 190/*
288 *Controls 191 *Controls
289 */ 192 */
@@ -341,66 +244,14 @@ struct snd_soc_ops {
341 int (*trigger)(struct snd_pcm_substream *, int); 244 int (*trigger)(struct snd_pcm_substream *, int);
342}; 245};
343 246
344/* ASoC DAI ops */
345struct snd_soc_dai_ops {
346 /* DAI clocking configuration */
347 int (*set_sysclk)(struct snd_soc_dai *dai,
348 int clk_id, unsigned int freq, int dir);
349 int (*set_pll)(struct snd_soc_dai *dai,
350 int pll_id, unsigned int freq_in, unsigned int freq_out);
351 int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);
352
353 /* DAI format configuration */
354 int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);
355 int (*set_tdm_slot)(struct snd_soc_dai *dai,
356 unsigned int mask, int slots);
357 int (*set_tristate)(struct snd_soc_dai *dai, int tristate);
358
359 /* digital mute */
360 int (*digital_mute)(struct snd_soc_dai *dai, int mute);
361};
362
363/* SoC DAI (Digital Audio Interface) */
364struct snd_soc_dai {
365 /* DAI description */
366 char *name;
367 unsigned int id;
368 unsigned char type;
369
370 /* DAI callbacks */
371 int (*probe)(struct platform_device *pdev,
372 struct snd_soc_dai *dai);
373 void (*remove)(struct platform_device *pdev,
374 struct snd_soc_dai *dai);
375 int (*suspend)(struct platform_device *pdev,
376 struct snd_soc_dai *dai);
377 int (*resume)(struct platform_device *pdev,
378 struct snd_soc_dai *dai);
379
380 /* ops */
381 struct snd_soc_ops ops;
382 struct snd_soc_dai_ops dai_ops;
383
384 /* DAI capabilities */
385 struct snd_soc_pcm_stream capture;
386 struct snd_soc_pcm_stream playback;
387
388 /* DAI runtime info */
389 struct snd_pcm_runtime *runtime;
390 struct snd_soc_codec *codec;
391 unsigned int active;
392 unsigned char pop_wait:1;
393 void *dma_data;
394
395 /* DAI private data */
396 void *private_data;
397};
398
399/* SoC Audio Codec */ 247/* SoC Audio Codec */
400struct snd_soc_codec { 248struct snd_soc_codec {
401 char *name; 249 char *name;
402 struct module *owner; 250 struct module *owner;
403 struct mutex mutex; 251 struct mutex mutex;
252 struct device *dev;
253
254 struct list_head list;
404 255
405 /* callbacks */ 256 /* callbacks */
406 int (*set_bias_level)(struct snd_soc_codec *, 257 int (*set_bias_level)(struct snd_soc_codec *,
@@ -426,6 +277,7 @@ struct snd_soc_codec {
426 short reg_cache_step; 277 short reg_cache_step;
427 278
428 /* dapm */ 279 /* dapm */
280 u32 pop_time;
429 struct list_head dapm_widgets; 281 struct list_head dapm_widgets;
430 struct list_head dapm_paths; 282 struct list_head dapm_paths;
431 enum snd_soc_bias_level bias_level; 283 enum snd_soc_bias_level bias_level;
@@ -435,6 +287,11 @@ struct snd_soc_codec {
435 /* codec DAI's */ 287 /* codec DAI's */
436 struct snd_soc_dai *dai; 288 struct snd_soc_dai *dai;
437 unsigned int num_dai; 289 unsigned int num_dai;
290
291#ifdef CONFIG_DEBUG_FS
292 struct dentry *debugfs_reg;
293 struct dentry *debugfs_pop_time;
294#endif
438}; 295};
439 296
440/* codec device */ 297/* codec device */
@@ -448,13 +305,12 @@ struct snd_soc_codec_device {
448/* SoC platform interface */ 305/* SoC platform interface */
449struct snd_soc_platform { 306struct snd_soc_platform {
450 char *name; 307 char *name;
308 struct list_head list;
451 309
452 int (*probe)(struct platform_device *pdev); 310 int (*probe)(struct platform_device *pdev);
453 int (*remove)(struct platform_device *pdev); 311 int (*remove)(struct platform_device *pdev);
454 int (*suspend)(struct platform_device *pdev, 312 int (*suspend)(struct snd_soc_dai *dai);
455 struct snd_soc_dai *dai); 313 int (*resume)(struct snd_soc_dai *dai);
456 int (*resume)(struct platform_device *pdev,
457 struct snd_soc_dai *dai);
458 314
459 /* pcm creation and destruction */ 315 /* pcm creation and destruction */
460 int (*pcm_new)(struct snd_card *, struct snd_soc_dai *, 316 int (*pcm_new)(struct snd_card *, struct snd_soc_dai *,
@@ -484,9 +340,14 @@ struct snd_soc_dai_link {
484 struct snd_pcm *pcm; 340 struct snd_pcm *pcm;
485}; 341};
486 342
487/* SoC machine */ 343/* SoC card */
488struct snd_soc_machine { 344struct snd_soc_card {
489 char *name; 345 char *name;
346 struct device *dev;
347
348 struct list_head list;
349
350 int instantiated;
490 351
491 int (*probe)(struct platform_device *pdev); 352 int (*probe)(struct platform_device *pdev);
492 int (*remove)(struct platform_device *pdev); 353 int (*remove)(struct platform_device *pdev);
@@ -499,23 +360,26 @@ struct snd_soc_machine {
499 int (*resume_post)(struct platform_device *pdev); 360 int (*resume_post)(struct platform_device *pdev);
500 361
501 /* callbacks */ 362 /* callbacks */
502 int (*set_bias_level)(struct snd_soc_machine *, 363 int (*set_bias_level)(struct snd_soc_card *,
503 enum snd_soc_bias_level level); 364 enum snd_soc_bias_level level);
504 365
505 /* CPU <--> Codec DAI links */ 366 /* CPU <--> Codec DAI links */
506 struct snd_soc_dai_link *dai_link; 367 struct snd_soc_dai_link *dai_link;
507 int num_links; 368 int num_links;
369
370 struct snd_soc_device *socdev;
371
372 struct snd_soc_platform *platform;
373 struct delayed_work delayed_work;
374 struct work_struct deferred_resume_work;
508}; 375};
509 376
510/* SoC Device - the audio subsystem */ 377/* SoC Device - the audio subsystem */
511struct snd_soc_device { 378struct snd_soc_device {
512 struct device *dev; 379 struct device *dev;
513 struct snd_soc_machine *machine; 380 struct snd_soc_card *card;
514 struct snd_soc_platform *platform;
515 struct snd_soc_codec *codec; 381 struct snd_soc_codec *codec;
516 struct snd_soc_codec_device *codec_dev; 382 struct snd_soc_codec_device *codec_dev;
517 struct delayed_work delayed_work;
518 struct work_struct deferred_resume_work;
519 void *codec_data; 383 void *codec_data;
520}; 384};
521 385
@@ -542,4 +406,6 @@ struct soc_enum {
542 void *dapm; 406 void *dapm;
543}; 407};
544 408
409#include <sound/soc-dai.h>
410
545#endif 411#endif
diff --git a/include/sound/uda134x.h b/include/sound/uda134x.h
new file mode 100644
index 000000000000..475ef8bb7dcd
--- /dev/null
+++ b/include/sound/uda134x.h
@@ -0,0 +1,26 @@
1/*
2 * uda134x.h -- UDA134x ALSA SoC Codec driver
3 *
4 * Copyright 2007 Dension Audio Systems Ltd.
5 * Author: Zoltan Devai
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 version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _UDA134X_H
13#define _UDA134X_H
14
15#include <sound/l3.h>
16
17struct uda134x_platform_data {
18 struct l3_pins l3;
19 void (*power) (int);
20 int model;
21#define UDA134X_UDA1340 1
22#define UDA134X_UDA1341 2
23#define UDA134X_UDA1344 3
24};
25
26#endif /* _UDA134X_H */
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 4dfda6674bec..ef025c66cc66 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -22,17 +22,16 @@ if SND_SOC
22config SND_SOC_AC97_BUS 22config SND_SOC_AC97_BUS
23 bool 23 bool
24 24
25# All the supported Soc's 25# All the supported SoCs
26source "sound/soc/at32/Kconfig" 26source "sound/soc/atmel/Kconfig"
27source "sound/soc/at91/Kconfig"
28source "sound/soc/au1x/Kconfig" 27source "sound/soc/au1x/Kconfig"
28source "sound/soc/blackfin/Kconfig"
29source "sound/soc/davinci/Kconfig"
30source "sound/soc/fsl/Kconfig"
31source "sound/soc/omap/Kconfig"
29source "sound/soc/pxa/Kconfig" 32source "sound/soc/pxa/Kconfig"
30source "sound/soc/s3c24xx/Kconfig" 33source "sound/soc/s3c24xx/Kconfig"
31source "sound/soc/sh/Kconfig" 34source "sound/soc/sh/Kconfig"
32source "sound/soc/fsl/Kconfig"
33source "sound/soc/davinci/Kconfig"
34source "sound/soc/omap/Kconfig"
35source "sound/soc/blackfin/Kconfig"
36 35
37# Supported codecs 36# Supported codecs
38source "sound/soc/codecs/Kconfig" 37source "sound/soc/codecs/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index d849349f2c66..86a9b1f5b0f3 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,5 +1,13 @@
1snd-soc-core-objs := soc-core.o soc-dapm.o 1snd-soc-core-objs := soc-core.o soc-dapm.o
2 2
3obj-$(CONFIG_SND_SOC) += snd-soc-core.o 3obj-$(CONFIG_SND_SOC) += snd-soc-core.o
4obj-$(CONFIG_SND_SOC) += codecs/ at32/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/ 4obj-$(CONFIG_SND_SOC) += codecs/
5obj-$(CONFIG_SND_SOC) += omap/ au1x/ blackfin/ 5obj-$(CONFIG_SND_SOC) += atmel/
6obj-$(CONFIG_SND_SOC) += au1x/
7obj-$(CONFIG_SND_SOC) += blackfin/
8obj-$(CONFIG_SND_SOC) += davinci/
9obj-$(CONFIG_SND_SOC) += fsl/
10obj-$(CONFIG_SND_SOC) += omap/
11obj-$(CONFIG_SND_SOC) += pxa/
12obj-$(CONFIG_SND_SOC) += s3c24xx/
13obj-$(CONFIG_SND_SOC) += sh/
diff --git a/sound/soc/at32/Kconfig b/sound/soc/at32/Kconfig
deleted file mode 100644
index b0765e86c085..000000000000
--- a/sound/soc/at32/Kconfig
+++ /dev/null
@@ -1,34 +0,0 @@
1config SND_AT32_SOC
2 tristate "SoC Audio for the Atmel AT32 System-on-a-Chip"
3 depends on AVR32 && SND_SOC
4 help
5 Say Y or M if you want to add support for codecs attached to
6 the AT32 SSC interface. You will also need to
7 to select the audio interfaces to support below.
8
9
10config SND_AT32_SOC_SSC
11 tristate
12
13
14
15config SND_AT32_SOC_PLAYPAQ
16 tristate "SoC Audio support for PlayPaq with WM8510"
17 depends on SND_AT32_SOC && BOARD_PLAYPAQ
18 select SND_AT32_SOC_SSC
19 select SND_SOC_WM8510
20 help
21 Say Y or M here if you want to add support for SoC audio
22 on the LRS PlayPaq.
23
24
25
26config SND_AT32_SOC_PLAYPAQ_SLAVE
27 bool "Run CODEC on PlayPaq in slave mode"
28 depends on SND_AT32_SOC_PLAYPAQ
29 default n
30 help
31 Say Y if you want to run with the AT32 SSC generating the BCLK
32 and FRAME signals on the PlayPaq. Unless you want to play
33 with the AT32 as the SSC master, you probably want to say N here,
34 as this will give you better sound quality.
diff --git a/sound/soc/at32/Makefile b/sound/soc/at32/Makefile
deleted file mode 100644
index c03e55ececeb..000000000000
--- a/sound/soc/at32/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
1# AT32 Platform Support
2snd-soc-at32-objs := at32-pcm.o
3snd-soc-at32-ssc-objs := at32-ssc.o
4
5obj-$(CONFIG_SND_AT32_SOC) += snd-soc-at32.o
6obj-$(CONFIG_SND_AT32_SOC_SSC) += snd-soc-at32-ssc.o
7
8# AT32 Machine Support
9snd-soc-playpaq-objs := playpaq_wm8510.o
10
11obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o
diff --git a/sound/soc/at32/at32-pcm.c b/sound/soc/at32/at32-pcm.c
deleted file mode 100644
index c83584f989a9..000000000000
--- a/sound/soc/at32/at32-pcm.c
+++ /dev/null
@@ -1,492 +0,0 @@
1/* sound/soc/at32/at32-pcm.c
2 * ASoC PCM interface for Atmel AT32 SoC
3 *
4 * Copyright (C) 2008 Long Range Systems
5 * Geoffrey Wossum <gwossum@acm.org>
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 version 2 as
9 * published by the Free Software Foundation.
10 *
11 * Note that this is basically a port of the sound/soc/at91-pcm.c to
12 * the AVR32 kernel. Thanks to Frank Mandarino for that code.
13 */
14
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/platform_device.h>
18#include <linux/slab.h>
19#include <linux/dma-mapping.h>
20#include <linux/atmel_pdc.h>
21
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h>
26
27#include "at32-pcm.h"
28
29
30
31/*--------------------------------------------------------------------------*\
32 * Hardware definition
33\*--------------------------------------------------------------------------*/
34/* TODO: These values were taken from the AT91 platform driver, check
35 * them against real values for AT32
36 */
37static const struct snd_pcm_hardware at32_pcm_hardware = {
38 .info = (SNDRV_PCM_INFO_MMAP |
39 SNDRV_PCM_INFO_MMAP_VALID |
40 SNDRV_PCM_INFO_INTERLEAVED |
41 SNDRV_PCM_INFO_BLOCK_TRANSFER |
42 SNDRV_PCM_INFO_PAUSE),
43
44 .formats = SNDRV_PCM_FMTBIT_S16,
45 .period_bytes_min = 32,
46 .period_bytes_max = 8192, /* 512 frames * 16 bytes / frame */
47 .periods_min = 2,
48 .periods_max = 1024,
49 .buffer_bytes_max = 32 * 1024,
50};
51
52
53
54/*--------------------------------------------------------------------------*\
55 * Data types
56\*--------------------------------------------------------------------------*/
57struct at32_runtime_data {
58 struct at32_pcm_dma_params *params;
59 dma_addr_t dma_buffer; /* physical address of DMA buffer */
60 dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
61 size_t period_size;
62
63 dma_addr_t period_ptr; /* physical address of next period */
64 int periods; /* period index of period_ptr */
65
66 /* Save PDC registers (for power management) */
67 u32 pdc_xpr_save;
68 u32 pdc_xcr_save;
69 u32 pdc_xnpr_save;
70 u32 pdc_xncr_save;
71};
72
73
74
75/*--------------------------------------------------------------------------*\
76 * Helper functions
77\*--------------------------------------------------------------------------*/
78static int at32_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
79{
80 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
81 struct snd_dma_buffer *dmabuf = &substream->dma_buffer;
82 size_t size = at32_pcm_hardware.buffer_bytes_max;
83
84 dmabuf->dev.type = SNDRV_DMA_TYPE_DEV;
85 dmabuf->dev.dev = pcm->card->dev;
86 dmabuf->private_data = NULL;
87 dmabuf->area = dma_alloc_coherent(pcm->card->dev, size,
88 &dmabuf->addr, GFP_KERNEL);
89 pr_debug("at32_pcm: preallocate_dma_buffer: "
90 "area=%p, addr=%p, size=%ld\n",
91 (void *)dmabuf->area, (void *)dmabuf->addr, size);
92
93 if (!dmabuf->area)
94 return -ENOMEM;
95
96 dmabuf->bytes = size;
97 return 0;
98}
99
100
101
102/*--------------------------------------------------------------------------*\
103 * ISR
104\*--------------------------------------------------------------------------*/
105static void at32_pcm_dma_irq(u32 ssc_sr, struct snd_pcm_substream *substream)
106{
107 struct snd_pcm_runtime *rtd = substream->runtime;
108 struct at32_runtime_data *prtd = rtd->private_data;
109 struct at32_pcm_dma_params *params = prtd->params;
110 static int count;
111
112 count++;
113 if (ssc_sr & params->mask->ssc_endbuf) {
114 pr_warning("at32-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
115 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
116 "underrun" : "overrun", params->name, ssc_sr, count);
117
118 /* re-start the PDC */
119 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
120 params->mask->pdc_disable);
121 prtd->period_ptr += prtd->period_size;
122 if (prtd->period_ptr >= prtd->dma_buffer_end)
123 prtd->period_ptr = prtd->dma_buffer;
124
125
126 ssc_writex(params->ssc->regs, params->pdc->xpr,
127 prtd->period_ptr);
128 ssc_writex(params->ssc->regs, params->pdc->xcr,
129 prtd->period_size / params->pdc_xfer_size);
130 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
131 params->mask->pdc_enable);
132 }
133
134
135 if (ssc_sr & params->mask->ssc_endx) {
136 /* Load the PDC next pointer and counter registers */
137 prtd->period_ptr += prtd->period_size;
138 if (prtd->period_ptr >= prtd->dma_buffer_end)
139 prtd->period_ptr = prtd->dma_buffer;
140 ssc_writex(params->ssc->regs, params->pdc->xnpr,
141 prtd->period_ptr);
142 ssc_writex(params->ssc->regs, params->pdc->xncr,
143 prtd->period_size / params->pdc_xfer_size);
144 }
145
146
147 snd_pcm_period_elapsed(substream);
148}
149
150
151
152/*--------------------------------------------------------------------------*\
153 * PCM operations
154\*--------------------------------------------------------------------------*/
155static int at32_pcm_hw_params(struct snd_pcm_substream *substream,
156 struct snd_pcm_hw_params *params)
157{
158 struct snd_pcm_runtime *runtime = substream->runtime;
159 struct at32_runtime_data *prtd = runtime->private_data;
160 struct snd_soc_pcm_runtime *rtd = substream->private_data;
161
162 /* this may get called several times by oss emulation
163 * with different params
164 */
165 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
166 runtime->dma_bytes = params_buffer_bytes(params);
167
168 prtd->params = rtd->dai->cpu_dai->dma_data;
169 prtd->params->dma_intr_handler = at32_pcm_dma_irq;
170
171 prtd->dma_buffer = runtime->dma_addr;
172 prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
173 prtd->period_size = params_period_bytes(params);
174
175 pr_debug("hw_params: DMA for %s initialized "
176 "(dma_bytes=%ld, period_size=%ld)\n",
177 prtd->params->name, runtime->dma_bytes, prtd->period_size);
178
179 return 0;
180}
181
182
183
184static int at32_pcm_hw_free(struct snd_pcm_substream *substream)
185{
186 struct at32_runtime_data *prtd = substream->runtime->private_data;
187 struct at32_pcm_dma_params *params = prtd->params;
188
189 if (params != NULL) {
190 ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
191 params->mask->pdc_disable);
192 prtd->params->dma_intr_handler = NULL;
193 }
194
195 return 0;
196}
197
198
199
200static int at32_pcm_prepare(struct snd_pcm_substream *substream)
201{
202 struct at32_runtime_data *prtd = substream->runtime->private_data;
203 struct at32_pcm_dma_params *params = prtd->params;
204
205 ssc_writex(params->ssc->regs, SSC_IDR,
206 params->mask->ssc_endx | params->mask->ssc_endbuf);
207 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
208 params->mask->pdc_disable);
209
210 return 0;
211}
212
213
214static int at32_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
215{
216 struct snd_pcm_runtime *rtd = substream->runtime;
217 struct at32_runtime_data *prtd = rtd->private_data;
218 struct at32_pcm_dma_params *params = prtd->params;
219 int ret = 0;
220
221 pr_debug("at32_pcm_trigger: buffer_size = %ld, "
222 "dma_area = %p, dma_bytes = %ld\n",
223 rtd->buffer_size, rtd->dma_area, rtd->dma_bytes);
224
225 switch (cmd) {
226 case SNDRV_PCM_TRIGGER_START:
227 prtd->period_ptr = prtd->dma_buffer;
228
229 ssc_writex(params->ssc->regs, params->pdc->xpr,
230 prtd->period_ptr);
231 ssc_writex(params->ssc->regs, params->pdc->xcr,
232 prtd->period_size / params->pdc_xfer_size);
233
234 prtd->period_ptr += prtd->period_size;
235 ssc_writex(params->ssc->regs, params->pdc->xnpr,
236 prtd->period_ptr);
237 ssc_writex(params->ssc->regs, params->pdc->xncr,
238 prtd->period_size / params->pdc_xfer_size);
239
240 pr_debug("trigger: period_ptr=%lx, xpr=%x, "
241 "xcr=%d, xnpr=%x, xncr=%d\n",
242 (unsigned long)prtd->period_ptr,
243 ssc_readx(params->ssc->regs, params->pdc->xpr),
244 ssc_readx(params->ssc->regs, params->pdc->xcr),
245 ssc_readx(params->ssc->regs, params->pdc->xnpr),
246 ssc_readx(params->ssc->regs, params->pdc->xncr));
247
248 ssc_writex(params->ssc->regs, SSC_IER,
249 params->mask->ssc_endx | params->mask->ssc_endbuf);
250 ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
251 params->mask->pdc_enable);
252
253 pr_debug("sr=%x, imr=%x\n",
254 ssc_readx(params->ssc->regs, SSC_SR),
255 ssc_readx(params->ssc->regs, SSC_IER));
256 break; /* SNDRV_PCM_TRIGGER_START */
257
258
259
260 case SNDRV_PCM_TRIGGER_STOP:
261 case SNDRV_PCM_TRIGGER_SUSPEND:
262 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
263 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
264 params->mask->pdc_disable);
265 break;
266
267
268 case SNDRV_PCM_TRIGGER_RESUME:
269 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
270 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
271 params->mask->pdc_enable);
272 break;
273
274 default:
275 ret = -EINVAL;
276 }
277
278 return ret;
279}
280
281
282
283static snd_pcm_uframes_t at32_pcm_pointer(struct snd_pcm_substream *substream)
284{
285 struct snd_pcm_runtime *runtime = substream->runtime;
286 struct at32_runtime_data *prtd = runtime->private_data;
287 struct at32_pcm_dma_params *params = prtd->params;
288 dma_addr_t ptr;
289 snd_pcm_uframes_t x;
290
291 ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr);
292 x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
293
294 if (x == runtime->buffer_size)
295 x = 0;
296
297 return x;
298}
299
300
301
302static int at32_pcm_open(struct snd_pcm_substream *substream)
303{
304 struct snd_pcm_runtime *runtime = substream->runtime;
305 struct at32_runtime_data *prtd;
306 int ret = 0;
307
308 snd_soc_set_runtime_hwparams(substream, &at32_pcm_hardware);
309
310 /* ensure that buffer size is a multiple of period size */
311 ret = snd_pcm_hw_constraint_integer(runtime,
312 SNDRV_PCM_HW_PARAM_PERIODS);
313 if (ret < 0)
314 goto out;
315
316 prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
317 if (prtd == NULL) {
318 ret = -ENOMEM;
319 goto out;
320 }
321 runtime->private_data = prtd;
322
323
324out:
325 return ret;
326}
327
328
329
330static int at32_pcm_close(struct snd_pcm_substream *substream)
331{
332 struct at32_runtime_data *prtd = substream->runtime->private_data;
333
334 kfree(prtd);
335 return 0;
336}
337
338
339static int at32_pcm_mmap(struct snd_pcm_substream *substream,
340 struct vm_area_struct *vma)
341{
342 return remap_pfn_range(vma, vma->vm_start,
343 substream->dma_buffer.addr >> PAGE_SHIFT,
344 vma->vm_end - vma->vm_start, vma->vm_page_prot);
345}
346
347
348
349static struct snd_pcm_ops at32_pcm_ops = {
350 .open = at32_pcm_open,
351 .close = at32_pcm_close,
352 .ioctl = snd_pcm_lib_ioctl,
353 .hw_params = at32_pcm_hw_params,
354 .hw_free = at32_pcm_hw_free,
355 .prepare = at32_pcm_prepare,
356 .trigger = at32_pcm_trigger,
357 .pointer = at32_pcm_pointer,
358 .mmap = at32_pcm_mmap,
359};
360
361
362
363/*--------------------------------------------------------------------------*\
364 * ASoC platform driver
365\*--------------------------------------------------------------------------*/
366static u64 at32_pcm_dmamask = 0xffffffff;
367
368static int at32_pcm_new(struct snd_card *card,
369 struct snd_soc_dai *dai,
370 struct snd_pcm *pcm)
371{
372 int ret = 0;
373
374 if (!card->dev->dma_mask)
375 card->dev->dma_mask = &at32_pcm_dmamask;
376 if (!card->dev->coherent_dma_mask)
377 card->dev->coherent_dma_mask = 0xffffffff;
378
379 if (dai->playback.channels_min) {
380 ret = at32_pcm_preallocate_dma_buffer(
381 pcm, SNDRV_PCM_STREAM_PLAYBACK);
382 if (ret)
383 goto out;
384 }
385
386 if (dai->capture.channels_min) {
387 pr_debug("at32-pcm: Allocating PCM capture DMA buffer\n");
388 ret = at32_pcm_preallocate_dma_buffer(
389 pcm, SNDRV_PCM_STREAM_CAPTURE);
390 if (ret)
391 goto out;
392 }
393
394
395out:
396 return ret;
397}
398
399
400
401static void at32_pcm_free_dma_buffers(struct snd_pcm *pcm)
402{
403 struct snd_pcm_substream *substream;
404 struct snd_dma_buffer *buf;
405 int stream;
406
407 for (stream = 0; stream < 2; stream++) {
408 substream = pcm->streams[stream].substream;
409 if (substream == NULL)
410 continue;
411
412 buf = &substream->dma_buffer;
413 if (!buf->area)
414 continue;
415 dma_free_coherent(pcm->card->dev, buf->bytes,
416 buf->area, buf->addr);
417 buf->area = NULL;
418 }
419}
420
421
422
423#ifdef CONFIG_PM
424static int at32_pcm_suspend(struct platform_device *pdev,
425 struct snd_soc_dai *dai)
426{
427 struct snd_pcm_runtime *runtime = dai->runtime;
428 struct at32_runtime_data *prtd;
429 struct at32_pcm_dma_params *params;
430
431 if (runtime == NULL)
432 return 0;
433 prtd = runtime->private_data;
434 params = prtd->params;
435
436 /* Disable the PDC and save the PDC registers */
437 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
438 params->mask->pdc_disable);
439
440 prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr);
441 prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr);
442 prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr);
443 prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr);
444
445 return 0;
446}
447
448
449
450static int at32_pcm_resume(struct platform_device *pdev,
451 struct snd_soc_dai *dai)
452{
453 struct snd_pcm_runtime *runtime = dai->runtime;
454 struct at32_runtime_data *prtd;
455 struct at32_pcm_dma_params *params;
456
457 if (runtime == NULL)
458 return 0;
459 prtd = runtime->private_data;
460 params = prtd->params;
461
462 /* Restore the PDC registers and enable the PDC */
463 ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save);
464 ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save);
465 ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save);
466 ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save);
467
468 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, params->mask->pdc_enable);
469 return 0;
470}
471#else /* CONFIG_PM */
472# define at32_pcm_suspend NULL
473# define at32_pcm_resume NULL
474#endif /* CONFIG_PM */
475
476
477
478struct snd_soc_platform at32_soc_platform = {
479 .name = "at32-audio",
480 .pcm_ops = &at32_pcm_ops,
481 .pcm_new = at32_pcm_new,
482 .pcm_free = at32_pcm_free_dma_buffers,
483 .suspend = at32_pcm_suspend,
484 .resume = at32_pcm_resume,
485};
486EXPORT_SYMBOL_GPL(at32_soc_platform);
487
488
489
490MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
491MODULE_DESCRIPTION("Atmel AT32 PCM module");
492MODULE_LICENSE("GPL");
diff --git a/sound/soc/at32/at32-pcm.h b/sound/soc/at32/at32-pcm.h
deleted file mode 100644
index 2a52430417da..000000000000
--- a/sound/soc/at32/at32-pcm.h
+++ /dev/null
@@ -1,79 +0,0 @@
1/* sound/soc/at32/at32-pcm.h
2 * ASoC PCM interface for Atmel AT32 SoC
3 *
4 * Copyright (C) 2008 Long Range Systems
5 * Geoffrey Wossum <gwossum@acm.org>
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 version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef __SOUND_SOC_AT32_AT32_PCM_H
13#define __SOUND_SOC_AT32_AT32_PCM_H __FILE__
14
15#include <linux/atmel-ssc.h>
16
17
18/*
19 * Registers and status bits that are required by the PCM driver
20 * TODO: Is ptcr really used?
21 */
22struct at32_pdc_regs {
23 u32 xpr; /* PDC RX/TX pointer */
24 u32 xcr; /* PDC RX/TX counter */
25 u32 xnpr; /* PDC next RX/TX pointer */
26 u32 xncr; /* PDC next RX/TX counter */
27 u32 ptcr; /* PDC transfer control */
28};
29
30
31
32/*
33 * SSC mask info
34 */
35struct at32_ssc_mask {
36 u32 ssc_enable; /* SSC RX/TX enable */
37 u32 ssc_disable; /* SSC RX/TX disable */
38 u32 ssc_endx; /* SSC ENDTX or ENDRX */
39 u32 ssc_endbuf; /* SSC TXBUFF or RXBUFF */
40 u32 pdc_enable; /* PDC RX/TX enable */
41 u32 pdc_disable; /* PDC RX/TX disable */
42};
43
44
45
46/*
47 * This structure, shared between the PCM driver and the interface,
48 * contains all information required by the PCM driver to perform the
49 * PDC DMA operation. All fields except dma_intr_handler() are initialized
50 * by the interface. The dms_intr_handler() pointer is set by the PCM
51 * driver and called by the interface SSC interrupt handler if it is
52 * non-NULL.
53 */
54struct at32_pcm_dma_params {
55 char *name; /* stream identifier */
56 int pdc_xfer_size; /* PDC counter increment in bytes */
57 struct ssc_device *ssc; /* SSC device for stream */
58 struct at32_pdc_regs *pdc; /* PDC register info */
59 struct at32_ssc_mask *mask; /* SSC mask info */
60 struct snd_pcm_substream *substream;
61 void (*dma_intr_handler) (u32, struct snd_pcm_substream *);
62};
63
64
65
66/*
67 * The AT32 ASoC platform driver
68 */
69extern struct snd_soc_platform at32_soc_platform;
70
71
72
73/*
74 * SSC register access (since ssc_writel() / ssc_readl() require literal name)
75 */
76#define ssc_readx(base, reg) (__raw_readl((base) + (reg)))
77#define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg))
78
79#endif /* __SOUND_SOC_AT32_AT32_PCM_H */
diff --git a/sound/soc/at32/at32-ssc.c b/sound/soc/at32/at32-ssc.c
deleted file mode 100644
index 4ef6492c902e..000000000000
--- a/sound/soc/at32/at32-ssc.c
+++ /dev/null
@@ -1,849 +0,0 @@
1/* sound/soc/at32/at32-ssc.c
2 * ASoC platform driver for AT32 using SSC as DAI
3 *
4 * Copyright (C) 2008 Long Range Systems
5 * Geoffrey Wossum <gwossum@acm.org>
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 version 2 as
9 * published by the Free Software Foundation.
10 *
11 * Note that this is basically a port of the sound/soc/at91-ssc.c to
12 * the AVR32 kernel. Thanks to Frank Mandarino for that code.
13 */
14
15/* #define DEBUG */
16
17#include <linux/init.h>
18#include <linux/module.h>
19#include <linux/interrupt.h>
20#include <linux/device.h>
21#include <linux/delay.h>
22#include <linux/clk.h>
23#include <linux/io.h>
24#include <linux/atmel_pdc.h>
25#include <linux/atmel-ssc.h>
26
27#include <sound/core.h>
28#include <sound/pcm.h>
29#include <sound/pcm_params.h>
30#include <sound/initval.h>
31#include <sound/soc.h>
32
33#include "at32-pcm.h"
34#include "at32-ssc.h"
35
36
37
38/*-------------------------------------------------------------------------*\
39 * Constants
40\*-------------------------------------------------------------------------*/
41#define NUM_SSC_DEVICES 3
42
43/*
44 * SSC direction masks
45 */
46#define SSC_DIR_MASK_UNUSED 0
47#define SSC_DIR_MASK_PLAYBACK 1
48#define SSC_DIR_MASK_CAPTURE 2
49
50/*
51 * SSC register values that Atmel left out of <linux/atmel-ssc.h>. These
52 * are expected to be used with SSC_BF
53 */
54/* START bit field values */
55#define SSC_START_CONTINUOUS 0
56#define SSC_START_TX_RX 1
57#define SSC_START_LOW_RF 2
58#define SSC_START_HIGH_RF 3
59#define SSC_START_FALLING_RF 4
60#define SSC_START_RISING_RF 5
61#define SSC_START_LEVEL_RF 6
62#define SSC_START_EDGE_RF 7
63#define SSS_START_COMPARE_0 8
64
65/* CKI bit field values */
66#define SSC_CKI_FALLING 0
67#define SSC_CKI_RISING 1
68
69/* CKO bit field values */
70#define SSC_CKO_NONE 0
71#define SSC_CKO_CONTINUOUS 1
72#define SSC_CKO_TRANSFER 2
73
74/* CKS bit field values */
75#define SSC_CKS_DIV 0
76#define SSC_CKS_CLOCK 1
77#define SSC_CKS_PIN 2
78
79/* FSEDGE bit field values */
80#define SSC_FSEDGE_POSITIVE 0
81#define SSC_FSEDGE_NEGATIVE 1
82
83/* FSOS bit field values */
84#define SSC_FSOS_NONE 0
85#define SSC_FSOS_NEGATIVE 1
86#define SSC_FSOS_POSITIVE 2
87#define SSC_FSOS_LOW 3
88#define SSC_FSOS_HIGH 4
89#define SSC_FSOS_TOGGLE 5
90
91#define START_DELAY 1
92
93
94
95/*-------------------------------------------------------------------------*\
96 * Module data
97\*-------------------------------------------------------------------------*/
98/*
99 * SSC PDC registered required by the PCM DMA engine
100 */
101static struct at32_pdc_regs pdc_tx_reg = {
102 .xpr = SSC_PDC_TPR,
103 .xcr = SSC_PDC_TCR,
104 .xnpr = SSC_PDC_TNPR,
105 .xncr = SSC_PDC_TNCR,
106};
107
108
109
110static struct at32_pdc_regs pdc_rx_reg = {
111 .xpr = SSC_PDC_RPR,
112 .xcr = SSC_PDC_RCR,
113 .xnpr = SSC_PDC_RNPR,
114 .xncr = SSC_PDC_RNCR,
115};
116
117
118
119/*
120 * SSC and PDC status bits for transmit and receive
121 */
122static struct at32_ssc_mask ssc_tx_mask = {
123 .ssc_enable = SSC_BIT(CR_TXEN),
124 .ssc_disable = SSC_BIT(CR_TXDIS),
125 .ssc_endx = SSC_BIT(SR_ENDTX),
126 .ssc_endbuf = SSC_BIT(SR_TXBUFE),
127 .pdc_enable = SSC_BIT(PDC_PTCR_TXTEN),
128 .pdc_disable = SSC_BIT(PDC_PTCR_TXTDIS),
129};
130
131
132
133static struct at32_ssc_mask ssc_rx_mask = {
134 .ssc_enable = SSC_BIT(CR_RXEN),
135 .ssc_disable = SSC_BIT(CR_RXDIS),
136 .ssc_endx = SSC_BIT(SR_ENDRX),
137 .ssc_endbuf = SSC_BIT(SR_RXBUFF),
138 .pdc_enable = SSC_BIT(PDC_PTCR_RXTEN),
139 .pdc_disable = SSC_BIT(PDC_PTCR_RXTDIS),
140};
141
142
143
144/*
145 * DMA parameters for each SSC
146 */
147static struct at32_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
148 {
149 {
150 .name = "SSC0 PCM out",
151 .pdc = &pdc_tx_reg,
152 .mask = &ssc_tx_mask,
153 },
154 {
155 .name = "SSC0 PCM in",
156 .pdc = &pdc_rx_reg,
157 .mask = &ssc_rx_mask,
158 },
159 },
160 {
161 {
162 .name = "SSC1 PCM out",
163 .pdc = &pdc_tx_reg,
164 .mask = &ssc_tx_mask,
165 },
166 {
167 .name = "SSC1 PCM in",
168 .pdc = &pdc_rx_reg,
169 .mask = &ssc_rx_mask,
170 },
171 },
172 {
173 {
174 .name = "SSC2 PCM out",
175 .pdc = &pdc_tx_reg,
176 .mask = &ssc_tx_mask,
177 },
178 {
179 .name = "SSC2 PCM in",
180 .pdc = &pdc_rx_reg,
181 .mask = &ssc_rx_mask,
182 },
183 },
184};
185
186
187
188static struct at32_ssc_info ssc_info[NUM_SSC_DEVICES] = {
189 {
190 .name = "ssc0",
191 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
192 .dir_mask = SSC_DIR_MASK_UNUSED,
193 .initialized = 0,
194 },
195 {
196 .name = "ssc1",
197 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
198 .dir_mask = SSC_DIR_MASK_UNUSED,
199 .initialized = 0,
200 },
201 {
202 .name = "ssc2",
203 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
204 .dir_mask = SSC_DIR_MASK_UNUSED,
205 .initialized = 0,
206 },
207};
208
209
210
211
212/*-------------------------------------------------------------------------*\
213 * ISR
214\*-------------------------------------------------------------------------*/
215/*
216 * SSC interrupt handler. Passes PDC interrupts to the DMA interrupt
217 * handler in the PCM driver.
218 */
219static irqreturn_t at32_ssc_interrupt(int irq, void *dev_id)
220{
221 struct at32_ssc_info *ssc_p = dev_id;
222 struct at32_pcm_dma_params *dma_params;
223 u32 ssc_sr;
224 u32 ssc_substream_mask;
225 int i;
226
227 ssc_sr = (ssc_readl(ssc_p->ssc->regs, SR) &
228 ssc_readl(ssc_p->ssc->regs, IMR));
229
230 /*
231 * Loop through substreams attached to this SSC. If a DMA-related
232 * interrupt occured on that substream, call the DMA interrupt
233 * handler function, if one has been registered in the dma_param
234 * structure by the PCM driver.
235 */
236 for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
237 dma_params = ssc_p->dma_params[i];
238
239 if ((dma_params != NULL) &&
240 (dma_params->dma_intr_handler != NULL)) {
241 ssc_substream_mask = (dma_params->mask->ssc_endx |
242 dma_params->mask->ssc_endbuf);
243 if (ssc_sr & ssc_substream_mask) {
244 dma_params->dma_intr_handler(ssc_sr,
245 dma_params->
246 substream);
247 }
248 }
249 }
250
251
252 return IRQ_HANDLED;
253}
254
255/*-------------------------------------------------------------------------*\
256 * DAI functions
257\*-------------------------------------------------------------------------*/
258/*
259 * Startup. Only that one substream allowed in each direction.
260 */
261static int at32_ssc_startup(struct snd_pcm_substream *substream)
262{
263 struct snd_soc_pcm_runtime *rtd = substream->private_data;
264 struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
265 int dir_mask;
266
267 dir_mask = ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
268 SSC_DIR_MASK_PLAYBACK : SSC_DIR_MASK_CAPTURE);
269
270 spin_lock_irq(&ssc_p->lock);
271 if (ssc_p->dir_mask & dir_mask) {
272 spin_unlock_irq(&ssc_p->lock);
273 return -EBUSY;
274 }
275 ssc_p->dir_mask |= dir_mask;
276 spin_unlock_irq(&ssc_p->lock);
277
278 return 0;
279}
280
281
282
283/*
284 * Shutdown. Clear DMA parameters and shutdown the SSC if there
285 * are no other substreams open.
286 */
287static void at32_ssc_shutdown(struct snd_pcm_substream *substream)
288{
289 struct snd_soc_pcm_runtime *rtd = substream->private_data;
290 struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
291 struct at32_pcm_dma_params *dma_params;
292 int dir_mask;
293
294 dma_params = ssc_p->dma_params[substream->stream];
295
296 if (dma_params != NULL) {
297 ssc_writel(dma_params->ssc->regs, CR,
298 dma_params->mask->ssc_disable);
299 pr_debug("%s disabled SSC_SR=0x%08x\n",
300 (substream->stream ? "receiver" : "transmit"),
301 ssc_readl(ssc_p->ssc->regs, SR));
302
303 dma_params->ssc = NULL;
304 dma_params->substream = NULL;
305 ssc_p->dma_params[substream->stream] = NULL;
306 }
307
308
309 dir_mask = 1 << substream->stream;
310 spin_lock_irq(&ssc_p->lock);
311 ssc_p->dir_mask &= ~dir_mask;
312 if (!ssc_p->dir_mask) {
313 /* Shutdown the SSC clock */
314 pr_debug("at32-ssc: Stopping user %d clock\n",
315 ssc_p->ssc->user);
316 clk_disable(ssc_p->ssc->clk);
317
318 if (ssc_p->initialized) {
319 free_irq(ssc_p->ssc->irq, ssc_p);
320 ssc_p->initialized = 0;
321 }
322
323 /* Reset the SSC */
324 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
325
326 /* clear the SSC dividers */
327 ssc_p->cmr_div = 0;
328 ssc_p->tcmr_period = 0;
329 ssc_p->rcmr_period = 0;
330 }
331 spin_unlock_irq(&ssc_p->lock);
332}
333
334
335
336/*
337 * Set the SSC system clock rate
338 */
339static int at32_ssc_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
340 int clk_id, unsigned int freq, int dir)
341{
342 /* TODO: What the heck do I do here? */
343 return 0;
344}
345
346
347
348/*
349 * Record DAI format for use by hw_params()
350 */
351static int at32_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
352 unsigned int fmt)
353{
354 struct at32_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
355
356 ssc_p->daifmt = fmt;
357 return 0;
358}
359
360
361
362/*
363 * Record SSC clock dividers for use in hw_params()
364 */
365static int at32_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
366 int div_id, int div)
367{
368 struct at32_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
369
370 switch (div_id) {
371 case AT32_SSC_CMR_DIV:
372 /*
373 * The same master clock divider is used for both
374 * transmit and receive, so if a value has already
375 * been set, it must match this value
376 */
377 if (ssc_p->cmr_div == 0)
378 ssc_p->cmr_div = div;
379 else if (div != ssc_p->cmr_div)
380 return -EBUSY;
381 break;
382
383 case AT32_SSC_TCMR_PERIOD:
384 ssc_p->tcmr_period = div;
385 break;
386
387 case AT32_SSC_RCMR_PERIOD:
388 ssc_p->rcmr_period = div;
389 break;
390
391 default:
392 return -EINVAL;
393 }
394
395 return 0;
396}
397
398
399
400/*
401 * Configure the SSC
402 */
403static int at32_ssc_hw_params(struct snd_pcm_substream *substream,
404 struct snd_pcm_hw_params *params)
405{
406 struct snd_soc_pcm_runtime *rtd = substream->private_data;
407 int id = rtd->dai->cpu_dai->id;
408 struct at32_ssc_info *ssc_p = &ssc_info[id];
409 struct at32_pcm_dma_params *dma_params;
410 int channels, bits;
411 u32 tfmr, rfmr, tcmr, rcmr;
412 int start_event;
413 int ret;
414
415
416 /*
417 * Currently, there is only one set of dma_params for each direction.
418 * If more are added, this code will have to be changed to select
419 * the proper set
420 */
421 dma_params = &ssc_dma_params[id][substream->stream];
422 dma_params->ssc = ssc_p->ssc;
423 dma_params->substream = substream;
424
425 ssc_p->dma_params[substream->stream] = dma_params;
426
427
428 /*
429 * The cpu_dai->dma_data field is only used to communicate the
430 * appropriate DMA parameters to the PCM driver's hw_params()
431 * function. It should not be used for other purposes as it
432 * is common to all substreams.
433 */
434 rtd->dai->cpu_dai->dma_data = dma_params;
435
436 channels = params_channels(params);
437
438
439 /*
440 * Determine sample size in bits and the PDC increment
441 */
442 switch (params_format(params)) {
443 case SNDRV_PCM_FORMAT_S8:
444 bits = 8;
445 dma_params->pdc_xfer_size = 1;
446 break;
447
448 case SNDRV_PCM_FORMAT_S16:
449 bits = 16;
450 dma_params->pdc_xfer_size = 2;
451 break;
452
453 case SNDRV_PCM_FORMAT_S24:
454 bits = 24;
455 dma_params->pdc_xfer_size = 4;
456 break;
457
458 case SNDRV_PCM_FORMAT_S32:
459 bits = 32;
460 dma_params->pdc_xfer_size = 4;
461 break;
462
463 default:
464 pr_warning("at32-ssc: Unsupported PCM format %d",
465 params_format(params));
466 return -EINVAL;
467 }
468 pr_debug("at32-ssc: bits = %d, pdc_xfer_size = %d, channels = %d\n",
469 bits, dma_params->pdc_xfer_size, channels);
470
471
472 /*
473 * The SSC only supports up to 16-bit samples in I2S format, due
474 * to the size of the Frame Mode Register FSLEN field.
475 */
476 if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S)
477 if (bits > 16) {
478 pr_warning("at32-ssc: "
479 "sample size %d is too large for I2S\n",
480 bits);
481 return -EINVAL;
482 }
483
484
485 /*
486 * Compute the SSC register settings
487 */
488 switch (ssc_p->daifmt & (SND_SOC_DAIFMT_FORMAT_MASK |
489 SND_SOC_DAIFMT_MASTER_MASK)) {
490 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
491 /*
492 * I2S format, SSC provides BCLK and LRS clocks.
493 *
494 * The SSC transmit and receive clocks are generated from the
495 * MCK divider, and the BCLK signal is output on the SSC TK line
496 */
497 pr_debug("at32-ssc: SSC mode is I2S BCLK / FRAME master\n");
498 rcmr = (SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) |
499 SSC_BF(RCMR_STTDLY, START_DELAY) |
500 SSC_BF(RCMR_START, SSC_START_FALLING_RF) |
501 SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
502 SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
503 SSC_BF(RCMR_CKS, SSC_CKS_DIV));
504
505 rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
506 SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) |
507 SSC_BF(RFMR_FSLEN, bits - 1) |
508 SSC_BF(RFMR_DATNB, channels - 1) |
509 SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
510
511 tcmr = (SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) |
512 SSC_BF(TCMR_STTDLY, START_DELAY) |
513 SSC_BF(TCMR_START, SSC_START_FALLING_RF) |
514 SSC_BF(TCMR_CKI, SSC_CKI_FALLING) |
515 SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) |
516 SSC_BF(TCMR_CKS, SSC_CKS_DIV));
517
518 tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
519 SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) |
520 SSC_BF(TFMR_FSLEN, bits - 1) |
521 SSC_BF(TFMR_DATNB, channels - 1) | SSC_BIT(TFMR_MSBF) |
522 SSC_BF(TFMR_DATLEN, bits - 1));
523 break;
524
525
526 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
527 /*
528 * I2S format, CODEC supplies BCLK and LRC clock.
529 *
530 * The SSC transmit clock is obtained from the BCLK signal
531 * on the TK line, and the SSC receive clock is generated from
532 * the transmit clock.
533 *
534 * For single channel data, one sample is transferred on the
535 * falling edge of the LRC clock. For two channel data, one
536 * sample is transferred on both edges of the LRC clock.
537 */
538 pr_debug("at32-ssc: SSC mode is I2S BCLK / FRAME slave\n");
539 start_event = ((channels == 1) ?
540 SSC_START_FALLING_RF : SSC_START_EDGE_RF);
541
542 rcmr = (SSC_BF(RCMR_STTDLY, START_DELAY) |
543 SSC_BF(RCMR_START, start_event) |
544 SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
545 SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
546 SSC_BF(RCMR_CKS, SSC_CKS_CLOCK));
547
548 rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
549 SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) |
550 SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
551
552 tcmr = (SSC_BF(TCMR_STTDLY, START_DELAY) |
553 SSC_BF(TCMR_START, start_event) |
554 SSC_BF(TCMR_CKI, SSC_CKI_FALLING) |
555 SSC_BF(TCMR_CKO, SSC_CKO_NONE) |
556 SSC_BF(TCMR_CKS, SSC_CKS_PIN));
557
558 tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
559 SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) |
560 SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1));
561 break;
562
563
564 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
565 /*
566 * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
567 *
568 * The SSC transmit and receive clocks are generated from the
569 * MCK divider, and the BCLK signal is output on the SSC TK line
570 */
571 pr_debug("at32-ssc: SSC mode is DSP A BCLK / FRAME master\n");
572 rcmr = (SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) |
573 SSC_BF(RCMR_STTDLY, 1) |
574 SSC_BF(RCMR_START, SSC_START_RISING_RF) |
575 SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
576 SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
577 SSC_BF(RCMR_CKS, SSC_CKS_DIV));
578
579 rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
580 SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE) |
581 SSC_BF(RFMR_DATNB, channels - 1) |
582 SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
583
584 tcmr = (SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) |
585 SSC_BF(TCMR_STTDLY, 1) |
586 SSC_BF(TCMR_START, SSC_START_RISING_RF) |
587 SSC_BF(TCMR_CKI, SSC_CKI_RISING) |
588 SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) |
589 SSC_BF(TCMR_CKS, SSC_CKS_DIV));
590
591 tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
592 SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE) |
593 SSC_BF(TFMR_DATNB, channels - 1) |
594 SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1));
595 break;
596
597
598 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
599 default:
600 pr_warning("at32-ssc: unsupported DAI format 0x%x\n",
601 ssc_p->daifmt);
602 return -EINVAL;
603 break;
604 }
605 pr_debug("at32-ssc: RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
606 rcmr, rfmr, tcmr, tfmr);
607
608
609 if (!ssc_p->initialized) {
610 /* enable peripheral clock */
611 pr_debug("at32-ssc: Starting clock\n");
612 clk_enable(ssc_p->ssc->clk);
613
614 /* Reset the SSC and its PDC registers */
615 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
616
617 ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0);
618 ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0);
619 ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0);
620 ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0);
621
622 ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0);
623 ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0);
624 ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0);
625 ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0);
626
627 ret = request_irq(ssc_p->ssc->irq, at32_ssc_interrupt, 0,
628 ssc_p->name, ssc_p);
629 if (ret < 0) {
630 pr_warning("at32-ssc: request irq failed (%d)\n", ret);
631 pr_debug("at32-ssc: Stopping clock\n");
632 clk_disable(ssc_p->ssc->clk);
633 return ret;
634 }
635
636 ssc_p->initialized = 1;
637 }
638
639 /* Set SSC clock mode register */
640 ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div);
641
642 /* set receive clock mode and format */
643 ssc_writel(ssc_p->ssc->regs, RCMR, rcmr);
644 ssc_writel(ssc_p->ssc->regs, RFMR, rfmr);
645
646 /* set transmit clock mode and format */
647 ssc_writel(ssc_p->ssc->regs, TCMR, tcmr);
648 ssc_writel(ssc_p->ssc->regs, TFMR, tfmr);
649
650 pr_debug("at32-ssc: SSC initialized\n");
651 return 0;
652}
653
654
655
656static int at32_ssc_prepare(struct snd_pcm_substream *substream)
657{
658 struct snd_soc_pcm_runtime *rtd = substream->private_data;
659 struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
660 struct at32_pcm_dma_params *dma_params;
661
662 dma_params = ssc_p->dma_params[substream->stream];
663
664 ssc_writel(dma_params->ssc->regs, CR, dma_params->mask->ssc_enable);
665
666 return 0;
667}
668
669
670
671#ifdef CONFIG_PM
672static int at32_ssc_suspend(struct platform_device *pdev,
673 struct snd_soc_dai *cpu_dai)
674{
675 struct at32_ssc_info *ssc_p;
676
677 if (!cpu_dai->active)
678 return 0;
679
680 ssc_p = &ssc_info[cpu_dai->id];
681
682 /* Save the status register before disabling transmit and receive */
683 ssc_p->ssc_state.ssc_sr = ssc_readl(ssc_p->ssc->regs, SR);
684 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_TXDIS) | SSC_BIT(CR_RXDIS));
685
686 /* Save the current interrupt mask, then disable unmasked interrupts */
687 ssc_p->ssc_state.ssc_imr = ssc_readl(ssc_p->ssc->regs, IMR);
688 ssc_writel(ssc_p->ssc->regs, IDR, ssc_p->ssc_state.ssc_imr);
689
690 ssc_p->ssc_state.ssc_cmr = ssc_readl(ssc_p->ssc->regs, CMR);
691 ssc_p->ssc_state.ssc_rcmr = ssc_readl(ssc_p->ssc->regs, RCMR);
692 ssc_p->ssc_state.ssc_rfmr = ssc_readl(ssc_p->ssc->regs, RFMR);
693 ssc_p->ssc_state.ssc_tcmr = ssc_readl(ssc_p->ssc->regs, TCMR);
694 ssc_p->ssc_state.ssc_tfmr = ssc_readl(ssc_p->ssc->regs, TFMR);
695
696 return 0;
697}
698
699
700
701static int at32_ssc_resume(struct platform_device *pdev,
702 struct snd_soc_dai *cpu_dai)
703{
704 struct at32_ssc_info *ssc_p;
705 u32 cr;
706
707 if (!cpu_dai->active)
708 return 0;
709
710 ssc_p = &ssc_info[cpu_dai->id];
711
712 /* restore SSC register settings */
713 ssc_writel(ssc_p->ssc->regs, TFMR, ssc_p->ssc_state.ssc_tfmr);
714 ssc_writel(ssc_p->ssc->regs, TCMR, ssc_p->ssc_state.ssc_tcmr);
715 ssc_writel(ssc_p->ssc->regs, RFMR, ssc_p->ssc_state.ssc_rfmr);
716 ssc_writel(ssc_p->ssc->regs, RCMR, ssc_p->ssc_state.ssc_rcmr);
717 ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->ssc_state.ssc_cmr);
718
719 /* re-enable interrupts */
720 ssc_writel(ssc_p->ssc->regs, IER, ssc_p->ssc_state.ssc_imr);
721
722 /* Re-enable recieve and transmit as appropriate */
723 cr = 0;
724 cr |=
725 (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_RXEN)) ? SSC_BIT(CR_RXEN) : 0;
726 cr |=
727 (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_TXEN)) ? SSC_BIT(CR_TXEN) : 0;
728 ssc_writel(ssc_p->ssc->regs, CR, cr);
729
730 return 0;
731}
732#else /* CONFIG_PM */
733# define at32_ssc_suspend NULL
734# define at32_ssc_resume NULL
735#endif /* CONFIG_PM */
736
737
738#define AT32_SSC_RATES \
739 (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
740 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
741 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
742
743
744#define AT32_SSC_FORMATS \
745 (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16 | \
746 SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_S32)
747
748
749struct snd_soc_dai at32_ssc_dai[NUM_SSC_DEVICES] = {
750 {
751 .name = "at32-ssc0",
752 .id = 0,
753 .type = SND_SOC_DAI_PCM,
754 .suspend = at32_ssc_suspend,
755 .resume = at32_ssc_resume,
756 .playback = {
757 .channels_min = 1,
758 .channels_max = 2,
759 .rates = AT32_SSC_RATES,
760 .formats = AT32_SSC_FORMATS,
761 },
762 .capture = {
763 .channels_min = 1,
764 .channels_max = 2,
765 .rates = AT32_SSC_RATES,
766 .formats = AT32_SSC_FORMATS,
767 },
768 .ops = {
769 .startup = at32_ssc_startup,
770 .shutdown = at32_ssc_shutdown,
771 .prepare = at32_ssc_prepare,
772 .hw_params = at32_ssc_hw_params,
773 },
774 .dai_ops = {
775 .set_sysclk = at32_ssc_set_dai_sysclk,
776 .set_fmt = at32_ssc_set_dai_fmt,
777 .set_clkdiv = at32_ssc_set_dai_clkdiv,
778 },
779 .private_data = &ssc_info[0],
780 },
781 {
782 .name = "at32-ssc1",
783 .id = 1,
784 .type = SND_SOC_DAI_PCM,
785 .suspend = at32_ssc_suspend,
786 .resume = at32_ssc_resume,
787 .playback = {
788 .channels_min = 1,
789 .channels_max = 2,
790 .rates = AT32_SSC_RATES,
791 .formats = AT32_SSC_FORMATS,
792 },
793 .capture = {
794 .channels_min = 1,
795 .channels_max = 2,
796 .rates = AT32_SSC_RATES,
797 .formats = AT32_SSC_FORMATS,
798 },
799 .ops = {
800 .startup = at32_ssc_startup,
801 .shutdown = at32_ssc_shutdown,
802 .prepare = at32_ssc_prepare,
803 .hw_params = at32_ssc_hw_params,
804 },
805 .dai_ops = {
806 .set_sysclk = at32_ssc_set_dai_sysclk,
807 .set_fmt = at32_ssc_set_dai_fmt,
808 .set_clkdiv = at32_ssc_set_dai_clkdiv,
809 },
810 .private_data = &ssc_info[1],
811 },
812 {
813 .name = "at32-ssc2",
814 .id = 2,
815 .type = SND_SOC_DAI_PCM,
816 .suspend = at32_ssc_suspend,
817 .resume = at32_ssc_resume,
818 .playback = {
819 .channels_min = 1,
820 .channels_max = 2,
821 .rates = AT32_SSC_RATES,
822 .formats = AT32_SSC_FORMATS,
823 },
824 .capture = {
825 .channels_min = 1,
826 .channels_max = 2,
827 .rates = AT32_SSC_RATES,
828 .formats = AT32_SSC_FORMATS,
829 },
830 .ops = {
831 .startup = at32_ssc_startup,
832 .shutdown = at32_ssc_shutdown,
833 .prepare = at32_ssc_prepare,
834 .hw_params = at32_ssc_hw_params,
835 },
836 .dai_ops = {
837 .set_sysclk = at32_ssc_set_dai_sysclk,
838 .set_fmt = at32_ssc_set_dai_fmt,
839 .set_clkdiv = at32_ssc_set_dai_clkdiv,
840 },
841 .private_data = &ssc_info[2],
842 },
843};
844EXPORT_SYMBOL_GPL(at32_ssc_dai);
845
846
847MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
848MODULE_DESCRIPTION("AT32 SSC ASoC Interface");
849MODULE_LICENSE("GPL");
diff --git a/sound/soc/at32/at32-ssc.h b/sound/soc/at32/at32-ssc.h
deleted file mode 100644
index 3c052dbbe460..000000000000
--- a/sound/soc/at32/at32-ssc.h
+++ /dev/null
@@ -1,59 +0,0 @@
1/* sound/soc/at32/at32-ssc.h
2 * ASoC SSC interface for Atmel AT32 SoC
3 *
4 * Copyright (C) 2008 Long Range Systems
5 * Geoffrey Wossum <gwossum@acm.org>
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 version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef __SOUND_SOC_AT32_AT32_SSC_H
13#define __SOUND_SOC_AT32_AT32_SSC_H __FILE__
14
15#include <linux/types.h>
16#include <linux/atmel-ssc.h>
17
18#include "at32-pcm.h"
19
20
21
22struct at32_ssc_state {
23 u32 ssc_cmr;
24 u32 ssc_rcmr;
25 u32 ssc_rfmr;
26 u32 ssc_tcmr;
27 u32 ssc_tfmr;
28 u32 ssc_sr;
29 u32 ssc_imr;
30};
31
32
33
34struct at32_ssc_info {
35 char *name;
36 struct ssc_device *ssc;
37 spinlock_t lock; /* lock for dir_mask */
38 unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
39 unsigned short initialized; /* true if SSC has been initialized */
40 unsigned short daifmt;
41 unsigned short cmr_div;
42 unsigned short tcmr_period;
43 unsigned short rcmr_period;
44 struct at32_pcm_dma_params *dma_params[2];
45 struct at32_ssc_state ssc_state;
46};
47
48
49/* SSC divider ids */
50#define AT32_SSC_CMR_DIV 0 /* MCK divider for BCLK */
51#define AT32_SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
52#define AT32_SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
53
54
55extern struct snd_soc_dai at32_ssc_dai[];
56
57
58
59#endif /* __SOUND_SOC_AT32_AT32_SSC_H */
diff --git a/sound/soc/at91/Kconfig b/sound/soc/at91/Kconfig
deleted file mode 100644
index 85a883299c2e..000000000000
--- a/sound/soc/at91/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
1config SND_AT91_SOC
2 tristate "SoC Audio for the Atmel AT91 System-on-Chip"
3 depends on ARCH_AT91
4 help
5 Say Y or M if you want to add support for codecs attached to
6 the AT91 SSC interface. You will also need
7 to select the audio interfaces to support below.
8
9config SND_AT91_SOC_SSC
10 tristate
diff --git a/sound/soc/at91/Makefile b/sound/soc/at91/Makefile
deleted file mode 100644
index b817f11df286..000000000000
--- a/sound/soc/at91/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
1# AT91 Platform Support
2snd-soc-at91-objs := at91-pcm.o
3snd-soc-at91-ssc-objs := at91-ssc.o
4
5obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o
6obj-$(CONFIG_SND_AT91_SOC_SSC) += snd-soc-at91-ssc.o
diff --git a/sound/soc/at91/at91-pcm.c b/sound/soc/at91/at91-pcm.c
deleted file mode 100644
index 7ab48bd25e4c..000000000000
--- a/sound/soc/at91/at91-pcm.c
+++ /dev/null
@@ -1,434 +0,0 @@
1/*
2 * at91-pcm.c -- ALSA PCM interface for the Atmel AT91 SoC
3 *
4 * Author: Frank Mandarino <fmandarino@endrelia.com>
5 * Endrelia Technologies Inc.
6 * Created: Mar 3, 2006
7 *
8 * Based on pxa2xx-pcm.c by:
9 *
10 * Author: Nicolas Pitre
11 * Created: Nov 30, 2004
12 * Copyright: (C) 2004 MontaVista Software, Inc.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/platform_device.h>
22#include <linux/slab.h>
23#include <linux/dma-mapping.h>
24#include <linux/atmel_pdc.h>
25
26#include <sound/core.h>
27#include <sound/pcm.h>
28#include <sound/pcm_params.h>
29#include <sound/soc.h>
30
31#include <mach/hardware.h>
32#include <mach/at91_ssc.h>
33
34#include "at91-pcm.h"
35
36#if 0
37#define DBG(x...) printk(KERN_INFO "at91-pcm: " x)
38#else
39#define DBG(x...)
40#endif
41
42static const struct snd_pcm_hardware at91_pcm_hardware = {
43 .info = SNDRV_PCM_INFO_MMAP |
44 SNDRV_PCM_INFO_MMAP_VALID |
45 SNDRV_PCM_INFO_INTERLEAVED |
46 SNDRV_PCM_INFO_PAUSE,
47 .formats = SNDRV_PCM_FMTBIT_S16_LE,
48 .period_bytes_min = 32,
49 .period_bytes_max = 8192,
50 .periods_min = 2,
51 .periods_max = 1024,
52 .buffer_bytes_max = 32 * 1024,
53};
54
55struct at91_runtime_data {
56 struct at91_pcm_dma_params *params;
57 dma_addr_t dma_buffer; /* physical address of dma buffer */
58 dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
59 size_t period_size;
60 dma_addr_t period_ptr; /* physical address of next period */
61 u32 pdc_xpr_save; /* PDC register save */
62 u32 pdc_xcr_save;
63 u32 pdc_xnpr_save;
64 u32 pdc_xncr_save;
65};
66
67static void at91_pcm_dma_irq(u32 ssc_sr,
68 struct snd_pcm_substream *substream)
69{
70 struct at91_runtime_data *prtd = substream->runtime->private_data;
71 struct at91_pcm_dma_params *params = prtd->params;
72 static int count = 0;
73
74 count++;
75
76 if (ssc_sr & params->mask->ssc_endbuf) {
77
78 printk(KERN_WARNING
79 "at91-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
80 substream->stream == SNDRV_PCM_STREAM_PLAYBACK
81 ? "underrun" : "overrun",
82 params->name, ssc_sr, count);
83
84 /* re-start the PDC */
85 at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
86
87 prtd->period_ptr += prtd->period_size;
88 if (prtd->period_ptr >= prtd->dma_buffer_end) {
89 prtd->period_ptr = prtd->dma_buffer;
90 }
91
92 at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr);
93 at91_ssc_write(params->ssc_base + params->pdc->xcr,
94 prtd->period_size / params->pdc_xfer_size);
95
96 at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
97 }
98
99 if (ssc_sr & params->mask->ssc_endx) {
100
101 /* Load the PDC next pointer and counter registers */
102 prtd->period_ptr += prtd->period_size;
103 if (prtd->period_ptr >= prtd->dma_buffer_end) {
104 prtd->period_ptr = prtd->dma_buffer;
105 }
106 at91_ssc_write(params->ssc_base + params->pdc->xnpr,
107 prtd->period_ptr);
108 at91_ssc_write(params->ssc_base + params->pdc->xncr,
109 prtd->period_size / params->pdc_xfer_size);
110 }
111
112 snd_pcm_period_elapsed(substream);
113}
114
115static int at91_pcm_hw_params(struct snd_pcm_substream *substream,
116 struct snd_pcm_hw_params *params)
117{
118 struct snd_pcm_runtime *runtime = substream->runtime;
119 struct at91_runtime_data *prtd = runtime->private_data;
120 struct snd_soc_pcm_runtime *rtd = substream->private_data;
121
122 /* this may get called several times by oss emulation
123 * with different params */
124
125 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
126 runtime->dma_bytes = params_buffer_bytes(params);
127
128 prtd->params = rtd->dai->cpu_dai->dma_data;
129 prtd->params->dma_intr_handler = at91_pcm_dma_irq;
130
131 prtd->dma_buffer = runtime->dma_addr;
132 prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
133 prtd->period_size = params_period_bytes(params);
134
135 DBG("hw_params: DMA for %s initialized (dma_bytes=%d, period_size=%d)\n",
136 prtd->params->name, runtime->dma_bytes, prtd->period_size);
137 return 0;
138}
139
140static int at91_pcm_hw_free(struct snd_pcm_substream *substream)
141{
142 struct at91_runtime_data *prtd = substream->runtime->private_data;
143 struct at91_pcm_dma_params *params = prtd->params;
144
145 if (params != NULL) {
146 at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
147 prtd->params->dma_intr_handler = NULL;
148 }
149
150 return 0;
151}
152
153static int at91_pcm_prepare(struct snd_pcm_substream *substream)
154{
155 struct at91_runtime_data *prtd = substream->runtime->private_data;
156 struct at91_pcm_dma_params *params = prtd->params;
157
158 at91_ssc_write(params->ssc_base + AT91_SSC_IDR,
159 params->mask->ssc_endx | params->mask->ssc_endbuf);
160
161 at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
162 return 0;
163}
164
165static int at91_pcm_trigger(struct snd_pcm_substream *substream,
166 int cmd)
167{
168 struct at91_runtime_data *prtd = substream->runtime->private_data;
169 struct at91_pcm_dma_params *params = prtd->params;
170 int ret = 0;
171
172 switch (cmd) {
173 case SNDRV_PCM_TRIGGER_START:
174 prtd->period_ptr = prtd->dma_buffer;
175
176 at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr);
177 at91_ssc_write(params->ssc_base + params->pdc->xcr,
178 prtd->period_size / params->pdc_xfer_size);
179
180 prtd->period_ptr += prtd->period_size;
181 at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->period_ptr);
182 at91_ssc_write(params->ssc_base + params->pdc->xncr,
183 prtd->period_size / params->pdc_xfer_size);
184
185 DBG("trigger: period_ptr=%lx, xpr=%lx, xcr=%ld, xnpr=%lx, xncr=%ld\n",
186 (unsigned long) prtd->period_ptr,
187 at91_ssc_read(params->ssc_base + params->pdc->xpr),
188 at91_ssc_read(params->ssc_base + params->pdc->xcr),
189 at91_ssc_read(params->ssc_base + params->pdc->xnpr),
190 at91_ssc_read(params->ssc_base + params->pdc->xncr));
191
192 at91_ssc_write(params->ssc_base + AT91_SSC_IER,
193 params->mask->ssc_endx | params->mask->ssc_endbuf);
194
195 at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR,
196 params->mask->pdc_enable);
197
198 DBG("sr=%lx imr=%lx\n",
199 at91_ssc_read(params->ssc_base + AT91_SSC_SR),
200 at91_ssc_read(params->ssc_base + AT91_SSC_IMR));
201 break;
202
203 case SNDRV_PCM_TRIGGER_STOP:
204 case SNDRV_PCM_TRIGGER_SUSPEND:
205 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
206 at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
207 break;
208
209 case SNDRV_PCM_TRIGGER_RESUME:
210 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
211 at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
212 break;
213
214 default:
215 ret = -EINVAL;
216 }
217
218 return ret;
219}
220
221static snd_pcm_uframes_t at91_pcm_pointer(
222 struct snd_pcm_substream *substream)
223{
224 struct snd_pcm_runtime *runtime = substream->runtime;
225 struct at91_runtime_data *prtd = runtime->private_data;
226 struct at91_pcm_dma_params *params = prtd->params;
227 dma_addr_t ptr;
228 snd_pcm_uframes_t x;
229
230 ptr = (dma_addr_t) at91_ssc_read(params->ssc_base + params->pdc->xpr);
231 x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
232
233 if (x == runtime->buffer_size)
234 x = 0;
235 return x;
236}
237
238static int at91_pcm_open(struct snd_pcm_substream *substream)
239{
240 struct snd_pcm_runtime *runtime = substream->runtime;
241 struct at91_runtime_data *prtd;
242 int ret = 0;
243
244 snd_soc_set_runtime_hwparams(substream, &at91_pcm_hardware);
245
246 /* ensure that buffer size is a multiple of period size */
247 ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
248 if (ret < 0)
249 goto out;
250
251 prtd = kzalloc(sizeof(struct at91_runtime_data), GFP_KERNEL);
252 if (prtd == NULL) {
253 ret = -ENOMEM;
254 goto out;
255 }
256 runtime->private_data = prtd;
257
258 out:
259 return ret;
260}
261
262static int at91_pcm_close(struct snd_pcm_substream *substream)
263{
264 struct at91_runtime_data *prtd = substream->runtime->private_data;
265
266 kfree(prtd);
267 return 0;
268}
269
270static int at91_pcm_mmap(struct snd_pcm_substream *substream,
271 struct vm_area_struct *vma)
272{
273 struct snd_pcm_runtime *runtime = substream->runtime;
274
275 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
276 runtime->dma_area,
277 runtime->dma_addr,
278 runtime->dma_bytes);
279}
280
281struct snd_pcm_ops at91_pcm_ops = {
282 .open = at91_pcm_open,
283 .close = at91_pcm_close,
284 .ioctl = snd_pcm_lib_ioctl,
285 .hw_params = at91_pcm_hw_params,
286 .hw_free = at91_pcm_hw_free,
287 .prepare = at91_pcm_prepare,
288 .trigger = at91_pcm_trigger,
289 .pointer = at91_pcm_pointer,
290 .mmap = at91_pcm_mmap,
291};
292
293static int at91_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
294 int stream)
295{
296 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
297 struct snd_dma_buffer *buf = &substream->dma_buffer;
298 size_t size = at91_pcm_hardware.buffer_bytes_max;
299
300 buf->dev.type = SNDRV_DMA_TYPE_DEV;
301 buf->dev.dev = pcm->card->dev;
302 buf->private_data = NULL;
303 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
304 &buf->addr, GFP_KERNEL);
305
306 DBG("preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
307 (void *) buf->area,
308 (void *) buf->addr,
309 size);
310
311 if (!buf->area)
312 return -ENOMEM;
313
314 buf->bytes = size;
315 return 0;
316}
317
318static u64 at91_pcm_dmamask = 0xffffffff;
319
320static int at91_pcm_new(struct snd_card *card,
321 struct snd_soc_dai *dai, struct snd_pcm *pcm)
322{
323 int ret = 0;
324
325 if (!card->dev->dma_mask)
326 card->dev->dma_mask = &at91_pcm_dmamask;
327 if (!card->dev->coherent_dma_mask)
328 card->dev->coherent_dma_mask = 0xffffffff;
329
330 if (dai->playback.channels_min) {
331 ret = at91_pcm_preallocate_dma_buffer(pcm,
332 SNDRV_PCM_STREAM_PLAYBACK);
333 if (ret)
334 goto out;
335 }
336
337 if (dai->capture.channels_min) {
338 ret = at91_pcm_preallocate_dma_buffer(pcm,
339 SNDRV_PCM_STREAM_CAPTURE);
340 if (ret)
341 goto out;
342 }
343 out:
344 return ret;
345}
346
347static void at91_pcm_free_dma_buffers(struct snd_pcm *pcm)
348{
349 struct snd_pcm_substream *substream;
350 struct snd_dma_buffer *buf;
351 int stream;
352
353 for (stream = 0; stream < 2; stream++) {
354 substream = pcm->streams[stream].substream;
355 if (!substream)
356 continue;
357
358 buf = &substream->dma_buffer;
359 if (!buf->area)
360 continue;
361
362 dma_free_writecombine(pcm->card->dev, buf->bytes,
363 buf->area, buf->addr);
364 buf->area = NULL;
365 }
366}
367
368#ifdef CONFIG_PM
369static int at91_pcm_suspend(struct platform_device *pdev,
370 struct snd_soc_dai *dai)
371{
372 struct snd_pcm_runtime *runtime = dai->runtime;
373 struct at91_runtime_data *prtd;
374 struct at91_pcm_dma_params *params;
375
376 if (!runtime)
377 return 0;
378
379 prtd = runtime->private_data;
380 params = prtd->params;
381
382 /* disable the PDC and save the PDC registers */
383
384 at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
385
386 prtd->pdc_xpr_save = at91_ssc_read(params->ssc_base + params->pdc->xpr);
387 prtd->pdc_xcr_save = at91_ssc_read(params->ssc_base + params->pdc->xcr);
388 prtd->pdc_xnpr_save = at91_ssc_read(params->ssc_base + params->pdc->xnpr);
389 prtd->pdc_xncr_save = at91_ssc_read(params->ssc_base + params->pdc->xncr);
390
391 return 0;
392}
393
394static int at91_pcm_resume(struct platform_device *pdev,
395 struct snd_soc_dai *dai)
396{
397 struct snd_pcm_runtime *runtime = dai->runtime;
398 struct at91_runtime_data *prtd;
399 struct at91_pcm_dma_params *params;
400
401 if (!runtime)
402 return 0;
403
404 prtd = runtime->private_data;
405 params = prtd->params;
406
407 /* restore the PDC registers and enable the PDC */
408 at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->pdc_xpr_save);
409 at91_ssc_write(params->ssc_base + params->pdc->xcr, prtd->pdc_xcr_save);
410 at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->pdc_xnpr_save);
411 at91_ssc_write(params->ssc_base + params->pdc->xncr, prtd->pdc_xncr_save);
412
413 at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
414 return 0;
415}
416#else
417#define at91_pcm_suspend NULL
418#define at91_pcm_resume NULL
419#endif
420
421struct snd_soc_platform at91_soc_platform = {
422 .name = "at91-audio",
423 .pcm_ops = &at91_pcm_ops,
424 .pcm_new = at91_pcm_new,
425 .pcm_free = at91_pcm_free_dma_buffers,
426 .suspend = at91_pcm_suspend,
427 .resume = at91_pcm_resume,
428};
429
430EXPORT_SYMBOL_GPL(at91_soc_platform);
431
432MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>");
433MODULE_DESCRIPTION("Atmel AT91 PCM module");
434MODULE_LICENSE("GPL");
diff --git a/sound/soc/at91/at91-pcm.h b/sound/soc/at91/at91-pcm.h
deleted file mode 100644
index e5aada2cb102..000000000000
--- a/sound/soc/at91/at91-pcm.h
+++ /dev/null
@@ -1,72 +0,0 @@
1/*
2 * at91-pcm.h - ALSA PCM interface for the Atmel AT91 SoC
3 *
4 * Author: Frank Mandarino <fmandarino@endrelia.com>
5 * Endrelia Technologies Inc.
6 * Created: Mar 3, 2006
7 *
8 * Based on pxa2xx-pcm.h by:
9 *
10 * Author: Nicolas Pitre
11 * Created: Nov 30, 2004
12 * Copyright: MontaVista Software, Inc.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18
19#ifndef _AT91_PCM_H
20#define _AT91_PCM_H
21
22#include <mach/hardware.h>
23
24struct at91_ssc_periph {
25 void __iomem *base;
26 u32 pid;
27};
28
29/*
30 * Registers and status bits that are required by the PCM driver.
31 */
32struct at91_pdc_regs {
33 unsigned int xpr; /* PDC recv/trans pointer */
34 unsigned int xcr; /* PDC recv/trans counter */
35 unsigned int xnpr; /* PDC next recv/trans pointer */
36 unsigned int xncr; /* PDC next recv/trans counter */
37 unsigned int ptcr; /* PDC transfer control */
38};
39
40struct at91_ssc_mask {
41 u32 ssc_enable; /* SSC recv/trans enable */
42 u32 ssc_disable; /* SSC recv/trans disable */
43 u32 ssc_endx; /* SSC ENDTX or ENDRX */
44 u32 ssc_endbuf; /* SSC TXBUFE or RXBUFF */
45 u32 pdc_enable; /* PDC recv/trans enable */
46 u32 pdc_disable; /* PDC recv/trans disable */
47};
48
49/*
50 * This structure, shared between the PCM driver and the interface,
51 * contains all information required by the PCM driver to perform the
52 * PDC DMA operation. All fields except dma_intr_handler() are initialized
53 * by the interface. The dms_intr_handler() pointer is set by the PCM
54 * driver and called by the interface SSC interrupt handler if it is
55 * non-NULL.
56 */
57struct at91_pcm_dma_params {
58 char *name; /* stream identifier */
59 int pdc_xfer_size; /* PDC counter increment in bytes */
60 void __iomem *ssc_base; /* SSC base address */
61 struct at91_pdc_regs *pdc; /* PDC receive or transmit registers */
62 struct at91_ssc_mask *mask;/* SSC & PDC status bits */
63 struct snd_pcm_substream *substream;
64 void (*dma_intr_handler)(u32, struct snd_pcm_substream *);
65};
66
67extern struct snd_soc_platform at91_soc_platform;
68
69#define at91_ssc_read(a) ((unsigned long) __raw_readl(a))
70#define at91_ssc_write(a,v) __raw_writel((v),(a))
71
72#endif /* _AT91_PCM_H */
diff --git a/sound/soc/at91/at91-ssc.c b/sound/soc/at91/at91-ssc.c
deleted file mode 100644
index 1b61cc461261..000000000000
--- a/sound/soc/at91/at91-ssc.c
+++ /dev/null
@@ -1,791 +0,0 @@
1/*
2 * at91-ssc.c -- ALSA SoC AT91 SSC Audio Layer Platform driver
3 *
4 * Author: Frank Mandarino <fmandarino@endrelia.com>
5 * Endrelia Technologies Inc.
6 *
7 * Based on pxa2xx Platform drivers by
8 * Liam Girdwood <lrg@slimlogic.co.uk>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 */
16
17#include <linux/init.h>
18#include <linux/module.h>
19#include <linux/interrupt.h>
20#include <linux/device.h>
21#include <linux/delay.h>
22#include <linux/clk.h>
23#include <linux/atmel_pdc.h>
24
25#include <sound/core.h>
26#include <sound/pcm.h>
27#include <sound/pcm_params.h>
28#include <sound/initval.h>
29#include <sound/soc.h>
30
31#include <mach/hardware.h>
32#include <mach/at91_pmc.h>
33#include <mach/at91_ssc.h>
34
35#include "at91-pcm.h"
36#include "at91-ssc.h"
37
38#if 0
39#define DBG(x...) printk(KERN_DEBUG "at91-ssc:" x)
40#else
41#define DBG(x...)
42#endif
43
44#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
45#define NUM_SSC_DEVICES 1
46#else
47#define NUM_SSC_DEVICES 3
48#endif
49
50
51/*
52 * SSC PDC registers required by the PCM DMA engine.
53 */
54static struct at91_pdc_regs pdc_tx_reg = {
55 .xpr = ATMEL_PDC_TPR,
56 .xcr = ATMEL_PDC_TCR,
57 .xnpr = ATMEL_PDC_TNPR,
58 .xncr = ATMEL_PDC_TNCR,
59};
60
61static struct at91_pdc_regs pdc_rx_reg = {
62 .xpr = ATMEL_PDC_RPR,
63 .xcr = ATMEL_PDC_RCR,
64 .xnpr = ATMEL_PDC_RNPR,
65 .xncr = ATMEL_PDC_RNCR,
66};
67
68/*
69 * SSC & PDC status bits for transmit and receive.
70 */
71static struct at91_ssc_mask ssc_tx_mask = {
72 .ssc_enable = AT91_SSC_TXEN,
73 .ssc_disable = AT91_SSC_TXDIS,
74 .ssc_endx = AT91_SSC_ENDTX,
75 .ssc_endbuf = AT91_SSC_TXBUFE,
76 .pdc_enable = ATMEL_PDC_TXTEN,
77 .pdc_disable = ATMEL_PDC_TXTDIS,
78};
79
80static struct at91_ssc_mask ssc_rx_mask = {
81 .ssc_enable = AT91_SSC_RXEN,
82 .ssc_disable = AT91_SSC_RXDIS,
83 .ssc_endx = AT91_SSC_ENDRX,
84 .ssc_endbuf = AT91_SSC_RXBUFF,
85 .pdc_enable = ATMEL_PDC_RXTEN,
86 .pdc_disable = ATMEL_PDC_RXTDIS,
87};
88
89
90/*
91 * DMA parameters.
92 */
93static struct at91_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
94 {{
95 .name = "SSC0 PCM out",
96 .pdc = &pdc_tx_reg,
97 .mask = &ssc_tx_mask,
98 },
99 {
100 .name = "SSC0 PCM in",
101 .pdc = &pdc_rx_reg,
102 .mask = &ssc_rx_mask,
103 }},
104#if NUM_SSC_DEVICES == 3
105 {{
106 .name = "SSC1 PCM out",
107 .pdc = &pdc_tx_reg,
108 .mask = &ssc_tx_mask,
109 },
110 {
111 .name = "SSC1 PCM in",
112 .pdc = &pdc_rx_reg,
113 .mask = &ssc_rx_mask,
114 }},
115 {{
116 .name = "SSC2 PCM out",
117 .pdc = &pdc_tx_reg,
118 .mask = &ssc_tx_mask,
119 },
120 {
121 .name = "SSC2 PCM in",
122 .pdc = &pdc_rx_reg,
123 .mask = &ssc_rx_mask,
124 }},
125#endif
126};
127
128struct at91_ssc_state {
129 u32 ssc_cmr;
130 u32 ssc_rcmr;
131 u32 ssc_rfmr;
132 u32 ssc_tcmr;
133 u32 ssc_tfmr;
134 u32 ssc_sr;
135 u32 ssc_imr;
136};
137
138static struct at91_ssc_info {
139 char *name;
140 struct at91_ssc_periph ssc;
141 spinlock_t lock; /* lock for dir_mask */
142 unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
143 unsigned short initialized; /* 1=SSC has been initialized */
144 unsigned short daifmt;
145 unsigned short cmr_div;
146 unsigned short tcmr_period;
147 unsigned short rcmr_period;
148 struct at91_pcm_dma_params *dma_params[2];
149 struct at91_ssc_state ssc_state;
150
151} ssc_info[NUM_SSC_DEVICES] = {
152 {
153 .name = "ssc0",
154 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
155 .dir_mask = 0,
156 .initialized = 0,
157 },
158#if NUM_SSC_DEVICES == 3
159 {
160 .name = "ssc1",
161 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
162 .dir_mask = 0,
163 .initialized = 0,
164 },
165 {
166 .name = "ssc2",
167 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
168 .dir_mask = 0,
169 .initialized = 0,
170 },
171#endif
172};
173
174static unsigned int at91_ssc_sysclk;
175
176/*
177 * SSC interrupt handler. Passes PDC interrupts to the DMA
178 * interrupt handler in the PCM driver.
179 */
180static irqreturn_t at91_ssc_interrupt(int irq, void *dev_id)
181{
182 struct at91_ssc_info *ssc_p = dev_id;
183 struct at91_pcm_dma_params *dma_params;
184 u32 ssc_sr;
185 int i;
186
187 ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR)
188 & at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR);
189
190 /*
191 * Loop through the substreams attached to this SSC. If
192 * a DMA-related interrupt occurred on that substream, call
193 * the DMA interrupt handler function, if one has been
194 * registered in the dma_params structure by the PCM driver.
195 */
196 for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
197 dma_params = ssc_p->dma_params[i];
198
199 if (dma_params != NULL && dma_params->dma_intr_handler != NULL &&
200 (ssc_sr &
201 (dma_params->mask->ssc_endx | dma_params->mask->ssc_endbuf)))
202
203 dma_params->dma_intr_handler(ssc_sr, dma_params->substream);
204 }
205
206 return IRQ_HANDLED;
207}
208
209/*
210 * Startup. Only that one substream allowed in each direction.
211 */
212static int at91_ssc_startup(struct snd_pcm_substream *substream)
213{
214 struct snd_soc_pcm_runtime *rtd = substream->private_data;
215 struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
216 int dir_mask;
217
218 DBG("ssc_startup: SSC_SR=0x%08lx\n",
219 at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
220 dir_mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0x1 : 0x2;
221
222 spin_lock_irq(&ssc_p->lock);
223 if (ssc_p->dir_mask & dir_mask) {
224 spin_unlock_irq(&ssc_p->lock);
225 return -EBUSY;
226 }
227 ssc_p->dir_mask |= dir_mask;
228 spin_unlock_irq(&ssc_p->lock);
229
230 return 0;
231}
232
233/*
234 * Shutdown. Clear DMA parameters and shutdown the SSC if there
235 * are no other substreams open.
236 */
237static void at91_ssc_shutdown(struct snd_pcm_substream *substream)
238{
239 struct snd_soc_pcm_runtime *rtd = substream->private_data;
240 struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
241 struct at91_pcm_dma_params *dma_params;
242 int dir, dir_mask;
243
244 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
245 dma_params = ssc_p->dma_params[dir];
246
247 if (dma_params != NULL) {
248 at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
249 dma_params->mask->ssc_disable);
250 DBG("%s disabled SSC_SR=0x%08lx\n", (dir ? "receive" : "transmit"),
251 at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
252
253 dma_params->ssc_base = NULL;
254 dma_params->substream = NULL;
255 ssc_p->dma_params[dir] = NULL;
256 }
257
258 dir_mask = 1 << dir;
259
260 spin_lock_irq(&ssc_p->lock);
261 ssc_p->dir_mask &= ~dir_mask;
262 if (!ssc_p->dir_mask) {
263 /* Shutdown the SSC clock. */
264 DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
265 at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid);
266
267 if (ssc_p->initialized) {
268 free_irq(ssc_p->ssc.pid, ssc_p);
269 ssc_p->initialized = 0;
270 }
271
272 /* Reset the SSC */
273 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
274
275 /* Clear the SSC dividers */
276 ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0;
277 }
278 spin_unlock_irq(&ssc_p->lock);
279}
280
281/*
282 * Record the SSC system clock rate.
283 */
284static int at91_ssc_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
285 int clk_id, unsigned int freq, int dir)
286{
287 /*
288 * The only clock supplied to the SSC is the AT91 master clock,
289 * which is only used if the SSC is generating BCLK and/or
290 * LRC clocks.
291 */
292 switch (clk_id) {
293 case AT91_SYSCLK_MCK:
294 at91_ssc_sysclk = freq;
295 break;
296 default:
297 return -EINVAL;
298 }
299
300 return 0;
301}
302
303/*
304 * Record the DAI format for use in hw_params().
305 */
306static int at91_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
307 unsigned int fmt)
308{
309 struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
310
311 ssc_p->daifmt = fmt;
312 return 0;
313}
314
315/*
316 * Record SSC clock dividers for use in hw_params().
317 */
318static int at91_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
319 int div_id, int div)
320{
321 struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
322
323 switch (div_id) {
324 case AT91SSC_CMR_DIV:
325 /*
326 * The same master clock divider is used for both
327 * transmit and receive, so if a value has already
328 * been set, it must match this value.
329 */
330 if (ssc_p->cmr_div == 0)
331 ssc_p->cmr_div = div;
332 else
333 if (div != ssc_p->cmr_div)
334 return -EBUSY;
335 break;
336
337 case AT91SSC_TCMR_PERIOD:
338 ssc_p->tcmr_period = div;
339 break;
340
341 case AT91SSC_RCMR_PERIOD:
342 ssc_p->rcmr_period = div;
343 break;
344
345 default:
346 return -EINVAL;
347 }
348
349 return 0;
350}
351
352/*
353 * Configure the SSC.
354 */
355static int at91_ssc_hw_params(struct snd_pcm_substream *substream,
356 struct snd_pcm_hw_params *params)
357{
358 struct snd_soc_pcm_runtime *rtd = substream->private_data;
359 int id = rtd->dai->cpu_dai->id;
360 struct at91_ssc_info *ssc_p = &ssc_info[id];
361 struct at91_pcm_dma_params *dma_params;
362 int dir, channels, bits;
363 u32 tfmr, rfmr, tcmr, rcmr;
364 int start_event;
365 int ret;
366
367 /*
368 * Currently, there is only one set of dma params for
369 * each direction. If more are added, this code will
370 * have to be changed to select the proper set.
371 */
372 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
373
374 dma_params = &ssc_dma_params[id][dir];
375 dma_params->ssc_base = ssc_p->ssc.base;
376 dma_params->substream = substream;
377
378 ssc_p->dma_params[dir] = dma_params;
379
380 /*
381 * The cpu_dai->dma_data field is only used to communicate the
382 * appropriate DMA parameters to the pcm driver hw_params()
383 * function. It should not be used for other purposes
384 * as it is common to all substreams.
385 */
386 rtd->dai->cpu_dai->dma_data = dma_params;
387
388 channels = params_channels(params);
389
390 /*
391 * Determine sample size in bits and the PDC increment.
392 */
393 switch(params_format(params)) {
394 case SNDRV_PCM_FORMAT_S8:
395 bits = 8;
396 dma_params->pdc_xfer_size = 1;
397 break;
398 case SNDRV_PCM_FORMAT_S16_LE:
399 bits = 16;
400 dma_params->pdc_xfer_size = 2;
401 break;
402 case SNDRV_PCM_FORMAT_S24_LE:
403 bits = 24;
404 dma_params->pdc_xfer_size = 4;
405 break;
406 case SNDRV_PCM_FORMAT_S32_LE:
407 bits = 32;
408 dma_params->pdc_xfer_size = 4;
409 break;
410 default:
411 printk(KERN_WARNING "at91-ssc: unsupported PCM format\n");
412 return -EINVAL;
413 }
414
415 /*
416 * The SSC only supports up to 16-bit samples in I2S format, due
417 * to the size of the Frame Mode Register FSLEN field.
418 */
419 if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
420 && bits > 16) {
421 printk(KERN_WARNING
422 "at91-ssc: sample size %d is too large for I2S\n", bits);
423 return -EINVAL;
424 }
425
426 /*
427 * Compute SSC register settings.
428 */
429 switch (ssc_p->daifmt
430 & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
431
432 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
433 /*
434 * I2S format, SSC provides BCLK and LRC clocks.
435 *
436 * The SSC transmit and receive clocks are generated from the
437 * MCK divider, and the BCLK signal is output on the SSC TK line.
438 */
439 rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD)
440 | (( 1 << 16) & AT91_SSC_STTDLY)
441 | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START)
442 | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
443 | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
444 | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
445
446 rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
447 | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS)
448 | (((bits - 1) << 16) & AT91_SSC_FSLEN)
449 | (((channels - 1) << 8) & AT91_SSC_DATNB)
450 | (( 1 << 7) & AT91_SSC_MSBF)
451 | (( 0 << 5) & AT91_SSC_LOOP)
452 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
453
454 tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD)
455 | (( 1 << 16) & AT91_SSC_STTDLY)
456 | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START)
457 | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI)
458 | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO)
459 | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
460
461 tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
462 | (( 0 << 23) & AT91_SSC_FSDEN)
463 | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS)
464 | (((bits - 1) << 16) & AT91_SSC_FSLEN)
465 | (((channels - 1) << 8) & AT91_SSC_DATNB)
466 | (( 1 << 7) & AT91_SSC_MSBF)
467 | (( 0 << 5) & AT91_SSC_DATDEF)
468 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
469 break;
470
471 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
472 /*
473 * I2S format, CODEC supplies BCLK and LRC clocks.
474 *
475 * The SSC transmit clock is obtained from the BCLK signal on
476 * on the TK line, and the SSC receive clock is generated from the
477 * transmit clock.
478 *
479 * For single channel data, one sample is transferred on the falling
480 * edge of the LRC clock. For two channel data, one sample is
481 * transferred on both edges of the LRC clock.
482 */
483 start_event = channels == 1
484 ? AT91_SSC_START_FALLING_RF
485 : AT91_SSC_START_EDGE_RF;
486
487 rcmr = (( 0 << 24) & AT91_SSC_PERIOD)
488 | (( 1 << 16) & AT91_SSC_STTDLY)
489 | (( start_event ) & AT91_SSC_START)
490 | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
491 | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
492 | (( AT91_SSC_CKS_CLOCK ) & AT91_SSC_CKS);
493
494 rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
495 | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS)
496 | (( 0 << 16) & AT91_SSC_FSLEN)
497 | (( 0 << 8) & AT91_SSC_DATNB)
498 | (( 1 << 7) & AT91_SSC_MSBF)
499 | (( 0 << 5) & AT91_SSC_LOOP)
500 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
501
502 tcmr = (( 0 << 24) & AT91_SSC_PERIOD)
503 | (( 1 << 16) & AT91_SSC_STTDLY)
504 | (( start_event ) & AT91_SSC_START)
505 | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI)
506 | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
507 | (( AT91_SSC_CKS_PIN ) & AT91_SSC_CKS);
508
509 tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
510 | (( 0 << 23) & AT91_SSC_FSDEN)
511 | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS)
512 | (( 0 << 16) & AT91_SSC_FSLEN)
513 | (( 0 << 8) & AT91_SSC_DATNB)
514 | (( 1 << 7) & AT91_SSC_MSBF)
515 | (( 0 << 5) & AT91_SSC_DATDEF)
516 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
517 break;
518
519 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
520 /*
521 * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
522 *
523 * The SSC transmit and receive clocks are generated from the
524 * MCK divider, and the BCLK signal is output on the SSC TK line.
525 */
526 rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD)
527 | (( 1 << 16) & AT91_SSC_STTDLY)
528 | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START)
529 | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
530 | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
531 | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
532
533 rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
534 | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS)
535 | (( 0 << 16) & AT91_SSC_FSLEN)
536 | (((channels - 1) << 8) & AT91_SSC_DATNB)
537 | (( 1 << 7) & AT91_SSC_MSBF)
538 | (( 0 << 5) & AT91_SSC_LOOP)
539 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
540
541 tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD)
542 | (( 1 << 16) & AT91_SSC_STTDLY)
543 | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START)
544 | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
545 | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO)
546 | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
547
548 tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
549 | (( 0 << 23) & AT91_SSC_FSDEN)
550 | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS)
551 | (( 0 << 16) & AT91_SSC_FSLEN)
552 | (((channels - 1) << 8) & AT91_SSC_DATNB)
553 | (( 1 << 7) & AT91_SSC_MSBF)
554 | (( 0 << 5) & AT91_SSC_DATDEF)
555 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
556
557
558
559 break;
560
561 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
562 default:
563 printk(KERN_WARNING "at91-ssc: unsupported DAI format 0x%x.\n",
564 ssc_p->daifmt);
565 return -EINVAL;
566 break;
567 }
568 DBG("RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", rcmr, rfmr, tcmr, tfmr);
569
570 if (!ssc_p->initialized) {
571
572 /* Enable PMC peripheral clock for this SSC */
573 DBG("Starting pid %d clock\n", ssc_p->ssc.pid);
574 at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid);
575
576 /* Reset the SSC and its PDC registers */
577 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
578
579 at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RPR, 0);
580 at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RCR, 0);
581 at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RNPR, 0);
582 at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RNCR, 0);
583 at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TPR, 0);
584 at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TCR, 0);
585 at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNPR, 0);
586 at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNCR, 0);
587
588 if ((ret = request_irq(ssc_p->ssc.pid, at91_ssc_interrupt,
589 0, ssc_p->name, ssc_p)) < 0) {
590 printk(KERN_WARNING "at91-ssc: request_irq failure\n");
591
592 DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
593 at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid);
594 return ret;
595 }
596
597 ssc_p->initialized = 1;
598 }
599
600 /* set SSC clock mode register */
601 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->cmr_div);
602
603 /* set receive clock mode and format */
604 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, rcmr);
605 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, rfmr);
606
607 /* set transmit clock mode and format */
608 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, tcmr);
609 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, tfmr);
610
611 DBG("hw_params: SSC initialized\n");
612 return 0;
613}
614
615
616static int at91_ssc_prepare(struct snd_pcm_substream *substream)
617{
618 struct snd_soc_pcm_runtime *rtd = substream->private_data;
619 struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
620 struct at91_pcm_dma_params *dma_params;
621 int dir;
622
623 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
624 dma_params = ssc_p->dma_params[dir];
625
626 at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
627 dma_params->mask->ssc_enable);
628
629 DBG("%s enabled SSC_SR=0x%08lx\n", dir ? "receive" : "transmit",
630 at91_ssc_read(dma_params->ssc_base + AT91_SSC_SR));
631 return 0;
632}
633
634
635#ifdef CONFIG_PM
636static int at91_ssc_suspend(struct platform_device *pdev,
637 struct snd_soc_dai *cpu_dai)
638{
639 struct at91_ssc_info *ssc_p;
640
641 if(!cpu_dai->active)
642 return 0;
643
644 ssc_p = &ssc_info[cpu_dai->id];
645
646 /* Save the status register before disabling transmit and receive. */
647 ssc_p->ssc_state.ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR);
648 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
649 AT91_SSC_TXDIS | AT91_SSC_RXDIS);
650
651 /* Save the current interrupt mask, then disable unmasked interrupts. */
652 ssc_p->ssc_state.ssc_imr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR);
653 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IDR, ssc_p->ssc_state.ssc_imr);
654
655 ssc_p->ssc_state.ssc_cmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_CMR);
656 ssc_p->ssc_state.ssc_rcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR);
657 ssc_p->ssc_state.ssc_rfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RFMR);
658 ssc_p->ssc_state.ssc_tcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TCMR);
659 ssc_p->ssc_state.ssc_tfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TFMR);
660
661 return 0;
662}
663
664static int at91_ssc_resume(struct platform_device *pdev,
665 struct snd_soc_dai *cpu_dai)
666{
667 struct at91_ssc_info *ssc_p;
668
669 if(!cpu_dai->active)
670 return 0;
671
672 ssc_p = &ssc_info[cpu_dai->id];
673
674 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, ssc_p->ssc_state.ssc_tfmr);
675 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, ssc_p->ssc_state.ssc_tcmr);
676 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, ssc_p->ssc_state.ssc_rfmr);
677 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->ssc_state.ssc_rcmr);
678 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->ssc_state.ssc_cmr);
679
680 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IER, ssc_p->ssc_state.ssc_imr);
681
682 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
683 ((ssc_p->ssc_state.ssc_sr & AT91_SSC_RXENA) ? AT91_SSC_RXEN : 0) |
684 ((ssc_p->ssc_state.ssc_sr & AT91_SSC_TXENA) ? AT91_SSC_TXEN : 0));
685
686 return 0;
687}
688
689#else
690#define at91_ssc_suspend NULL
691#define at91_ssc_resume NULL
692#endif
693
694#define AT91_SSC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
695 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
696 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
697 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
698 SNDRV_PCM_RATE_96000)
699
700#define AT91_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
701 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
702
703struct snd_soc_dai at91_ssc_dai[NUM_SSC_DEVICES] = {
704 { .name = "at91-ssc0",
705 .id = 0,
706 .type = SND_SOC_DAI_PCM,
707 .suspend = at91_ssc_suspend,
708 .resume = at91_ssc_resume,
709 .playback = {
710 .channels_min = 1,
711 .channels_max = 2,
712 .rates = AT91_SSC_RATES,
713 .formats = AT91_SSC_FORMATS,},
714 .capture = {
715 .channels_min = 1,
716 .channels_max = 2,
717 .rates = AT91_SSC_RATES,
718 .formats = AT91_SSC_FORMATS,},
719 .ops = {
720 .startup = at91_ssc_startup,
721 .shutdown = at91_ssc_shutdown,
722 .prepare = at91_ssc_prepare,
723 .hw_params = at91_ssc_hw_params,},
724 .dai_ops = {
725 .set_sysclk = at91_ssc_set_dai_sysclk,
726 .set_fmt = at91_ssc_set_dai_fmt,
727 .set_clkdiv = at91_ssc_set_dai_clkdiv,},
728 .private_data = &ssc_info[0].ssc,
729 },
730#if NUM_SSC_DEVICES == 3
731 { .name = "at91-ssc1",
732 .id = 1,
733 .type = SND_SOC_DAI_PCM,
734 .suspend = at91_ssc_suspend,
735 .resume = at91_ssc_resume,
736 .playback = {
737 .channels_min = 1,
738 .channels_max = 2,
739 .rates = AT91_SSC_RATES,
740 .formats = AT91_SSC_FORMATS,},
741 .capture = {
742 .channels_min = 1,
743 .channels_max = 2,
744 .rates = AT91_SSC_RATES,
745 .formats = AT91_SSC_FORMATS,},
746 .ops = {
747 .startup = at91_ssc_startup,
748 .shutdown = at91_ssc_shutdown,
749 .prepare = at91_ssc_prepare,
750 .hw_params = at91_ssc_hw_params,},
751 .dai_ops = {
752 .set_sysclk = at91_ssc_set_dai_sysclk,
753 .set_fmt = at91_ssc_set_dai_fmt,
754 .set_clkdiv = at91_ssc_set_dai_clkdiv,},
755 .private_data = &ssc_info[1].ssc,
756 },
757 { .name = "at91-ssc2",
758 .id = 2,
759 .type = SND_SOC_DAI_PCM,
760 .suspend = at91_ssc_suspend,
761 .resume = at91_ssc_resume,
762 .playback = {
763 .channels_min = 1,
764 .channels_max = 2,
765 .rates = AT91_SSC_RATES,
766 .formats = AT91_SSC_FORMATS,},
767 .capture = {
768 .channels_min = 1,
769 .channels_max = 2,
770 .rates = AT91_SSC_RATES,
771 .formats = AT91_SSC_FORMATS,},
772 .ops = {
773 .startup = at91_ssc_startup,
774 .shutdown = at91_ssc_shutdown,
775 .prepare = at91_ssc_prepare,
776 .hw_params = at91_ssc_hw_params,},
777 .dai_ops = {
778 .set_sysclk = at91_ssc_set_dai_sysclk,
779 .set_fmt = at91_ssc_set_dai_fmt,
780 .set_clkdiv = at91_ssc_set_dai_clkdiv,},
781 .private_data = &ssc_info[2].ssc,
782 },
783#endif
784};
785
786EXPORT_SYMBOL_GPL(at91_ssc_dai);
787
788/* Module information */
789MODULE_AUTHOR("Frank Mandarino, fmandarino@endrelia.com, www.endrelia.com");
790MODULE_DESCRIPTION("AT91 SSC ASoC Interface");
791MODULE_LICENSE("GPL");
diff --git a/sound/soc/at91/at91-ssc.h b/sound/soc/at91/at91-ssc.h
deleted file mode 100644
index 6b7bf382d06f..000000000000
--- a/sound/soc/at91/at91-ssc.h
+++ /dev/null
@@ -1,27 +0,0 @@
1/*
2 * at91-ssc.h - ALSA SSC interface for the Atmel AT91 SoC
3 *
4 * Author: Frank Mandarino <fmandarino@endrelia.com>
5 * Endrelia Technologies Inc.
6 * Created: Jan 9, 2007
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 _AT91_SSC_H
14#define _AT91_SSC_H
15
16/* SSC system clock ids */
17#define AT91_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */
18
19/* SSC divider ids */
20#define AT91SSC_CMR_DIV 0 /* MCK divider for BCLK */
21#define AT91SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
22#define AT91SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
23
24extern struct snd_soc_dai at91_ssc_dai[];
25
26#endif /* _AT91_SSC_H */
27
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
new file mode 100644
index 000000000000..a608d7009dbd
--- /dev/null
+++ b/sound/soc/atmel/Kconfig
@@ -0,0 +1,43 @@
1config SND_ATMEL_SOC
2 tristate "SoC Audio for the Atmel System-on-Chip"
3 depends on ARCH_AT91 || AVR32
4 help
5 Say Y or M if you want to add support for codecs attached to
6 the ATMEL SSC interface. You will also need
7 to select the audio interfaces to support below.
8
9config SND_ATMEL_SOC_SSC
10 tristate
11 depends on SND_ATMEL_SOC
12 help
13 Say Y or M if you want to add support for codecs the
14 ATMEL SSC interface. You will also needs to select the individual
15 machine drivers to support below.
16
17config SND_AT91_SOC_SAM9G20_WM8731
18 tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board"
19 depends on ATMEL_SSC && ARCH_AT91SAM9G20 && SND_ATMEL_SOC
20 select SND_ATMEL_SOC_SSC
21 select SND_SOC_WM8731
22 help
23 Say Y if you want to add support for SoC audio on WM8731-based
24 AT91sam9g20 evaluation board.
25
26config SND_AT32_SOC_PLAYPAQ
27 tristate "SoC Audio support for PlayPaq with WM8510"
28 depends on SND_ATMEL_SOC && BOARD_PLAYPAQ
29 select SND_ATMEL_SOC_SSC
30 select SND_SOC_WM8510
31 help
32 Say Y or M here if you want to add support for SoC audio
33 on the LRS PlayPaq.
34
35config SND_AT32_SOC_PLAYPAQ_SLAVE
36 bool "Run CODEC on PlayPaq in slave mode"
37 depends on SND_AT32_SOC_PLAYPAQ
38 default n
39 help
40 Say Y if you want to run with the AT32 SSC generating the BCLK
41 and FRAME signals on the PlayPaq. Unless you want to play
42 with the AT32 as the SSC master, you probably want to say N here,
43 as this will give you better sound quality.
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
new file mode 100644
index 000000000000..f54a7cc68e66
--- /dev/null
+++ b/sound/soc/atmel/Makefile
@@ -0,0 +1,15 @@
1# AT91 Platform Support
2snd-soc-atmel-pcm-objs := atmel-pcm.o
3snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
4
5obj-$(CONFIG_SND_ATMEL_SOC) += snd-soc-atmel-pcm.o
6obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
7
8# AT91 Machine Support
9snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
10
11# AT32 Machine Support
12snd-soc-playpaq-objs := playpaq_wm8510.o
13
14obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o
15obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
new file mode 100644
index 000000000000..1fac5efd285b
--- /dev/null
+++ b/sound/soc/atmel/atmel-pcm.c
@@ -0,0 +1,494 @@
1/*
2 * atmel-pcm.c -- ALSA PCM interface for the Atmel atmel SoC.
3 *
4 * Copyright (C) 2005 SAN People
5 * Copyright (C) 2008 Atmel
6 *
7 * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
8 *
9 * Based on at91-pcm. by:
10 * Frank Mandarino <fmandarino@endrelia.com>
11 * Copyright 2006 Endrelia Technologies Inc.
12 *
13 * Based on pxa2xx-pcm.c by:
14 *
15 * Author: Nicolas Pitre
16 * Created: Nov 30, 2004
17 * Copyright: (C) 2004 MontaVista Software, Inc.
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 */
33
34#include <linux/module.h>
35#include <linux/init.h>
36#include <linux/platform_device.h>
37#include <linux/slab.h>
38#include <linux/dma-mapping.h>
39#include <linux/atmel_pdc.h>
40#include <linux/atmel-ssc.h>
41
42#include <sound/core.h>
43#include <sound/pcm.h>
44#include <sound/pcm_params.h>
45#include <sound/soc.h>
46
47#include <mach/hardware.h>
48
49#include "atmel-pcm.h"
50
51
52/*--------------------------------------------------------------------------*\
53 * Hardware definition
54\*--------------------------------------------------------------------------*/
55/* TODO: These values were taken from the AT91 platform driver, check
56 * them against real values for AT32
57 */
58static const struct snd_pcm_hardware atmel_pcm_hardware = {
59 .info = SNDRV_PCM_INFO_MMAP |
60 SNDRV_PCM_INFO_MMAP_VALID |
61 SNDRV_PCM_INFO_INTERLEAVED |
62 SNDRV_PCM_INFO_PAUSE,
63 .formats = SNDRV_PCM_FMTBIT_S16_LE,
64 .period_bytes_min = 32,
65 .period_bytes_max = 8192,
66 .periods_min = 2,
67 .periods_max = 1024,
68 .buffer_bytes_max = 32 * 1024,
69};
70
71
72/*--------------------------------------------------------------------------*\
73 * Data types
74\*--------------------------------------------------------------------------*/
75struct atmel_runtime_data {
76 struct atmel_pcm_dma_params *params;
77 dma_addr_t dma_buffer; /* physical address of dma buffer */
78 dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
79 size_t period_size;
80
81 dma_addr_t period_ptr; /* physical address of next period */
82 int periods; /* period index of period_ptr */
83
84 /* PDC register save */
85 u32 pdc_xpr_save;
86 u32 pdc_xcr_save;
87 u32 pdc_xnpr_save;
88 u32 pdc_xncr_save;
89};
90
91
92/*--------------------------------------------------------------------------*\
93 * Helper functions
94\*--------------------------------------------------------------------------*/
95static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
96 int stream)
97{
98 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
99 struct snd_dma_buffer *buf = &substream->dma_buffer;
100 size_t size = atmel_pcm_hardware.buffer_bytes_max;
101
102 buf->dev.type = SNDRV_DMA_TYPE_DEV;
103 buf->dev.dev = pcm->card->dev;
104 buf->private_data = NULL;
105 buf->area = dma_alloc_coherent(pcm->card->dev, size,
106 &buf->addr, GFP_KERNEL);
107 pr_debug("atmel-pcm:"
108 "preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
109 (void *) buf->area,
110 (void *) buf->addr,
111 size);
112
113 if (!buf->area)
114 return -ENOMEM;
115
116 buf->bytes = size;
117 return 0;
118}
119/*--------------------------------------------------------------------------*\
120 * ISR
121\*--------------------------------------------------------------------------*/
122static void atmel_pcm_dma_irq(u32 ssc_sr,
123 struct snd_pcm_substream *substream)
124{
125 struct atmel_runtime_data *prtd = substream->runtime->private_data;
126 struct atmel_pcm_dma_params *params = prtd->params;
127 static int count;
128
129 count++;
130
131 if (ssc_sr & params->mask->ssc_endbuf) {
132 pr_warning("atmel-pcm: buffer %s on %s"
133 " (SSC_SR=%#x, count=%d)\n",
134 substream->stream == SNDRV_PCM_STREAM_PLAYBACK
135 ? "underrun" : "overrun",
136 params->name, ssc_sr, count);
137
138 /* re-start the PDC */
139 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
140 params->mask->pdc_disable);
141 prtd->period_ptr += prtd->period_size;
142 if (prtd->period_ptr >= prtd->dma_buffer_end)
143 prtd->period_ptr = prtd->dma_buffer;
144
145 ssc_writex(params->ssc->regs, params->pdc->xpr,
146 prtd->period_ptr);
147 ssc_writex(params->ssc->regs, params->pdc->xcr,
148 prtd->period_size / params->pdc_xfer_size);
149 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
150 params->mask->pdc_enable);
151 }
152
153 if (ssc_sr & params->mask->ssc_endx) {
154 /* Load the PDC next pointer and counter registers */
155 prtd->period_ptr += prtd->period_size;
156 if (prtd->period_ptr >= prtd->dma_buffer_end)
157 prtd->period_ptr = prtd->dma_buffer;
158
159 ssc_writex(params->ssc->regs, params->pdc->xnpr,
160 prtd->period_ptr);
161 ssc_writex(params->ssc->regs, params->pdc->xncr,
162 prtd->period_size / params->pdc_xfer_size);
163 }
164
165 snd_pcm_period_elapsed(substream);
166}
167
168
169/*--------------------------------------------------------------------------*\
170 * PCM operations
171\*--------------------------------------------------------------------------*/
172static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
173 struct snd_pcm_hw_params *params)
174{
175 struct snd_pcm_runtime *runtime = substream->runtime;
176 struct atmel_runtime_data *prtd = runtime->private_data;
177 struct snd_soc_pcm_runtime *rtd = substream->private_data;
178
179 /* this may get called several times by oss emulation
180 * with different params */
181
182 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
183 runtime->dma_bytes = params_buffer_bytes(params);
184
185 prtd->params = rtd->dai->cpu_dai->dma_data;
186 prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
187
188 prtd->dma_buffer = runtime->dma_addr;
189 prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
190 prtd->period_size = params_period_bytes(params);
191
192 pr_debug("atmel-pcm: "
193 "hw_params: DMA for %s initialized "
194 "(dma_bytes=%u, period_size=%u)\n",
195 prtd->params->name,
196 runtime->dma_bytes,
197 prtd->period_size);
198 return 0;
199}
200
201static int atmel_pcm_hw_free(struct snd_pcm_substream *substream)
202{
203 struct atmel_runtime_data *prtd = substream->runtime->private_data;
204 struct atmel_pcm_dma_params *params = prtd->params;
205
206 if (params != NULL) {
207 ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
208 params->mask->pdc_disable);
209 prtd->params->dma_intr_handler = NULL;
210 }
211
212 return 0;
213}
214
215static int atmel_pcm_prepare(struct snd_pcm_substream *substream)
216{
217 struct atmel_runtime_data *prtd = substream->runtime->private_data;
218 struct atmel_pcm_dma_params *params = prtd->params;
219
220 ssc_writex(params->ssc->regs, SSC_IDR,
221 params->mask->ssc_endx | params->mask->ssc_endbuf);
222 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
223 params->mask->pdc_disable);
224 return 0;
225}
226
227static int atmel_pcm_trigger(struct snd_pcm_substream *substream,
228 int cmd)
229{
230 struct snd_pcm_runtime *rtd = substream->runtime;
231 struct atmel_runtime_data *prtd = rtd->private_data;
232 struct atmel_pcm_dma_params *params = prtd->params;
233 int ret = 0;
234
235 pr_debug("atmel-pcm:buffer_size = %ld,"
236 "dma_area = %p, dma_bytes = %u\n",
237 rtd->buffer_size, rtd->dma_area, rtd->dma_bytes);
238
239 switch (cmd) {
240 case SNDRV_PCM_TRIGGER_START:
241 prtd->period_ptr = prtd->dma_buffer;
242
243 ssc_writex(params->ssc->regs, params->pdc->xpr,
244 prtd->period_ptr);
245 ssc_writex(params->ssc->regs, params->pdc->xcr,
246 prtd->period_size / params->pdc_xfer_size);
247
248 prtd->period_ptr += prtd->period_size;
249 ssc_writex(params->ssc->regs, params->pdc->xnpr,
250 prtd->period_ptr);
251 ssc_writex(params->ssc->regs, params->pdc->xncr,
252 prtd->period_size / params->pdc_xfer_size);
253
254 pr_debug("atmel-pcm: trigger: "
255 "period_ptr=%lx, xpr=%u, "
256 "xcr=%u, xnpr=%u, xncr=%u\n",
257 (unsigned long)prtd->period_ptr,
258 ssc_readx(params->ssc->regs, params->pdc->xpr),
259 ssc_readx(params->ssc->regs, params->pdc->xcr),
260 ssc_readx(params->ssc->regs, params->pdc->xnpr),
261 ssc_readx(params->ssc->regs, params->pdc->xncr));
262
263 ssc_writex(params->ssc->regs, SSC_IER,
264 params->mask->ssc_endx | params->mask->ssc_endbuf);
265 ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
266 params->mask->pdc_enable);
267
268 pr_debug("sr=%u imr=%u\n",
269 ssc_readx(params->ssc->regs, SSC_SR),
270 ssc_readx(params->ssc->regs, SSC_IER));
271 break; /* SNDRV_PCM_TRIGGER_START */
272
273 case SNDRV_PCM_TRIGGER_STOP:
274 case SNDRV_PCM_TRIGGER_SUSPEND:
275 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
276 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
277 params->mask->pdc_disable);
278 break;
279
280 case SNDRV_PCM_TRIGGER_RESUME:
281 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
282 ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
283 params->mask->pdc_enable);
284 break;
285
286 default:
287 ret = -EINVAL;
288 }
289
290 return ret;
291}
292
293static snd_pcm_uframes_t atmel_pcm_pointer(
294 struct snd_pcm_substream *substream)
295{
296 struct snd_pcm_runtime *runtime = substream->runtime;
297 struct atmel_runtime_data *prtd = runtime->private_data;
298 struct atmel_pcm_dma_params *params = prtd->params;
299 dma_addr_t ptr;
300 snd_pcm_uframes_t x;
301
302 ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr);
303 x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
304
305 if (x == runtime->buffer_size)
306 x = 0;
307
308 return x;
309}
310
311static int atmel_pcm_open(struct snd_pcm_substream *substream)
312{
313 struct snd_pcm_runtime *runtime = substream->runtime;
314 struct atmel_runtime_data *prtd;
315 int ret = 0;
316
317 snd_soc_set_runtime_hwparams(substream, &atmel_pcm_hardware);
318
319 /* ensure that buffer size is a multiple of period size */
320 ret = snd_pcm_hw_constraint_integer(runtime,
321 SNDRV_PCM_HW_PARAM_PERIODS);
322 if (ret < 0)
323 goto out;
324
325 prtd = kzalloc(sizeof(struct atmel_runtime_data), GFP_KERNEL);
326 if (prtd == NULL) {
327 ret = -ENOMEM;
328 goto out;
329 }
330 runtime->private_data = prtd;
331
332 out:
333 return ret;
334}
335
336static int atmel_pcm_close(struct snd_pcm_substream *substream)
337{
338 struct atmel_runtime_data *prtd = substream->runtime->private_data;
339
340 kfree(prtd);
341 return 0;
342}
343
344static int atmel_pcm_mmap(struct snd_pcm_substream *substream,
345 struct vm_area_struct *vma)
346{
347 return remap_pfn_range(vma, vma->vm_start,
348 substream->dma_buffer.addr >> PAGE_SHIFT,
349 vma->vm_end - vma->vm_start, vma->vm_page_prot);
350}
351
352struct snd_pcm_ops atmel_pcm_ops = {
353 .open = atmel_pcm_open,
354 .close = atmel_pcm_close,
355 .ioctl = snd_pcm_lib_ioctl,
356 .hw_params = atmel_pcm_hw_params,
357 .hw_free = atmel_pcm_hw_free,
358 .prepare = atmel_pcm_prepare,
359 .trigger = atmel_pcm_trigger,
360 .pointer = atmel_pcm_pointer,
361 .mmap = atmel_pcm_mmap,
362};
363
364
365/*--------------------------------------------------------------------------*\
366 * ASoC platform driver
367\*--------------------------------------------------------------------------*/
368static u64 atmel_pcm_dmamask = 0xffffffff;
369
370static int atmel_pcm_new(struct snd_card *card,
371 struct snd_soc_dai *dai, struct snd_pcm *pcm)
372{
373 int ret = 0;
374
375 if (!card->dev->dma_mask)
376 card->dev->dma_mask = &atmel_pcm_dmamask;
377 if (!card->dev->coherent_dma_mask)
378 card->dev->coherent_dma_mask = 0xffffffff;
379
380 if (dai->playback.channels_min) {
381 ret = atmel_pcm_preallocate_dma_buffer(pcm,
382 SNDRV_PCM_STREAM_PLAYBACK);
383 if (ret)
384 goto out;
385 }
386
387 if (dai->capture.channels_min) {
388 pr_debug("at32-pcm:"
389 "Allocating PCM capture DMA buffer\n");
390 ret = atmel_pcm_preallocate_dma_buffer(pcm,
391 SNDRV_PCM_STREAM_CAPTURE);
392 if (ret)
393 goto out;
394 }
395 out:
396 return ret;
397}
398
399static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm)
400{
401 struct snd_pcm_substream *substream;
402 struct snd_dma_buffer *buf;
403 int stream;
404
405 for (stream = 0; stream < 2; stream++) {
406 substream = pcm->streams[stream].substream;
407 if (!substream)
408 continue;
409
410 buf = &substream->dma_buffer;
411 if (!buf->area)
412 continue;
413 dma_free_coherent(pcm->card->dev, buf->bytes,
414 buf->area, buf->addr);
415 buf->area = NULL;
416 }
417}
418
419#ifdef CONFIG_PM
420static int atmel_pcm_suspend(struct snd_soc_dai *dai)
421{
422 struct snd_pcm_runtime *runtime = dai->runtime;
423 struct atmel_runtime_data *prtd;
424 struct atmel_pcm_dma_params *params;
425
426 if (!runtime)
427 return 0;
428
429 prtd = runtime->private_data;
430 params = prtd->params;
431
432 /* disable the PDC and save the PDC registers */
433
434 ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_disable);
435
436 prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr);
437 prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr);
438 prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr);
439 prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr);
440
441 return 0;
442}
443
444static int atmel_pcm_resume(struct snd_soc_dai *dai)
445{
446 struct snd_pcm_runtime *runtime = dai->runtime;
447 struct atmel_runtime_data *prtd;
448 struct atmel_pcm_dma_params *params;
449
450 if (!runtime)
451 return 0;
452
453 prtd = runtime->private_data;
454 params = prtd->params;
455
456 /* restore the PDC registers and enable the PDC */
457 ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save);
458 ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save);
459 ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save);
460 ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save);
461
462 ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_enable);
463 return 0;
464}
465#else
466#define atmel_pcm_suspend NULL
467#define atmel_pcm_resume NULL
468#endif
469
470struct snd_soc_platform atmel_soc_platform = {
471 .name = "atmel-audio",
472 .pcm_ops = &atmel_pcm_ops,
473 .pcm_new = atmel_pcm_new,
474 .pcm_free = atmel_pcm_free_dma_buffers,
475 .suspend = atmel_pcm_suspend,
476 .resume = atmel_pcm_resume,
477};
478EXPORT_SYMBOL_GPL(atmel_soc_platform);
479
480static int __init atmel_pcm_modinit(void)
481{
482 return snd_soc_register_platform(&atmel_soc_platform);
483}
484module_init(atmel_pcm_modinit);
485
486static void __exit atmel_pcm_modexit(void)
487{
488 snd_soc_unregister_platform(&atmel_soc_platform);
489}
490module_exit(atmel_pcm_modexit);
491
492MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
493MODULE_DESCRIPTION("Atmel PCM module");
494MODULE_LICENSE("GPL");
diff --git a/sound/soc/atmel/atmel-pcm.h b/sound/soc/atmel/atmel-pcm.h
new file mode 100644
index 000000000000..ec9b2824b663
--- /dev/null
+++ b/sound/soc/atmel/atmel-pcm.h
@@ -0,0 +1,86 @@
1/*
2 * at91-pcm.h - ALSA PCM interface for the Atmel AT91 SoC.
3 *
4 * Copyright (C) 2005 SAN People
5 * Copyright (C) 2008 Atmel
6 *
7 * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
8 *
9 * Based on at91-pcm. by:
10 * Frank Mandarino <fmandarino@endrelia.com>
11 * Copyright 2006 Endrelia Technologies Inc.
12 *
13 * Based on pxa2xx-pcm.c by:
14 *
15 * Author: Nicolas Pitre
16 * Created: Nov 30, 2004
17 * Copyright: (C) 2004 MontaVista Software, Inc.
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 */
33
34#ifndef _ATMEL_PCM_H
35#define _ATMEL_PCM_H
36
37#include <linux/atmel-ssc.h>
38
39/*
40 * Registers and status bits that are required by the PCM driver.
41 */
42struct atmel_pdc_regs {
43 unsigned int xpr; /* PDC recv/trans pointer */
44 unsigned int xcr; /* PDC recv/trans counter */
45 unsigned int xnpr; /* PDC next recv/trans pointer */
46 unsigned int xncr; /* PDC next recv/trans counter */
47 unsigned int ptcr; /* PDC transfer control */
48};
49
50struct atmel_ssc_mask {
51 u32 ssc_enable; /* SSC recv/trans enable */
52 u32 ssc_disable; /* SSC recv/trans disable */
53 u32 ssc_endx; /* SSC ENDTX or ENDRX */
54 u32 ssc_endbuf; /* SSC TXBUFE or RXBUFF */
55 u32 pdc_enable; /* PDC recv/trans enable */
56 u32 pdc_disable; /* PDC recv/trans disable */
57};
58
59/*
60 * This structure, shared between the PCM driver and the interface,
61 * contains all information required by the PCM driver to perform the
62 * PDC DMA operation. All fields except dma_intr_handler() are initialized
63 * by the interface. The dms_intr_handler() pointer is set by the PCM
64 * driver and called by the interface SSC interrupt handler if it is
65 * non-NULL.
66 */
67struct atmel_pcm_dma_params {
68 char *name; /* stream identifier */
69 int pdc_xfer_size; /* PDC counter increment in bytes */
70 struct ssc_device *ssc; /* SSC device for stream */
71 struct atmel_pdc_regs *pdc; /* PDC receive or transmit registers */
72 struct atmel_ssc_mask *mask; /* SSC & PDC status bits */
73 struct snd_pcm_substream *substream;
74 void (*dma_intr_handler)(u32, struct snd_pcm_substream *);
75};
76
77extern struct snd_soc_platform atmel_soc_platform;
78
79
80/*
81 * SSC register access (since ssc_writel() / ssc_readl() require literal name)
82 */
83#define ssc_readx(base, reg) (__raw_readl((base) + (reg)))
84#define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg))
85
86#endif /* _ATMEL_PCM_H */
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
new file mode 100644
index 000000000000..c5d67900d666
--- /dev/null
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -0,0 +1,790 @@
1/*
2 * atmel_ssc_dai.c -- ALSA SoC ATMEL SSC Audio Layer Platform driver
3 *
4 * Copyright (C) 2005 SAN People
5 * Copyright (C) 2008 Atmel
6 *
7 * Author: Sedji Gaouaou <sedji.gaouaou@atmel.com>
8 * ATMEL CORP.
9 *
10 * Based on at91-ssc.c by
11 * Frank Mandarino <fmandarino@endrelia.com>
12 * Based on pxa2xx Platform drivers by
13 * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30#include <linux/init.h>
31#include <linux/module.h>
32#include <linux/interrupt.h>
33#include <linux/device.h>
34#include <linux/delay.h>
35#include <linux/clk.h>
36#include <linux/atmel_pdc.h>
37
38#include <linux/atmel-ssc.h>
39#include <sound/core.h>
40#include <sound/pcm.h>
41#include <sound/pcm_params.h>
42#include <sound/initval.h>
43#include <sound/soc.h>
44
45#include <mach/hardware.h>
46
47#include "atmel-pcm.h"
48#include "atmel_ssc_dai.h"
49
50
51#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
52#define NUM_SSC_DEVICES 1
53#else
54#define NUM_SSC_DEVICES 3
55#endif
56
57/*
58 * SSC PDC registers required by the PCM DMA engine.
59 */
60static struct atmel_pdc_regs pdc_tx_reg = {
61 .xpr = ATMEL_PDC_TPR,
62 .xcr = ATMEL_PDC_TCR,
63 .xnpr = ATMEL_PDC_TNPR,
64 .xncr = ATMEL_PDC_TNCR,
65};
66
67static struct atmel_pdc_regs pdc_rx_reg = {
68 .xpr = ATMEL_PDC_RPR,
69 .xcr = ATMEL_PDC_RCR,
70 .xnpr = ATMEL_PDC_RNPR,
71 .xncr = ATMEL_PDC_RNCR,
72};
73
74/*
75 * SSC & PDC status bits for transmit and receive.
76 */
77static struct atmel_ssc_mask ssc_tx_mask = {
78 .ssc_enable = SSC_BIT(CR_TXEN),
79 .ssc_disable = SSC_BIT(CR_TXDIS),
80 .ssc_endx = SSC_BIT(SR_ENDTX),
81 .ssc_endbuf = SSC_BIT(SR_TXBUFE),
82 .pdc_enable = ATMEL_PDC_TXTEN,
83 .pdc_disable = ATMEL_PDC_TXTDIS,
84};
85
86static struct atmel_ssc_mask ssc_rx_mask = {
87 .ssc_enable = SSC_BIT(CR_RXEN),
88 .ssc_disable = SSC_BIT(CR_RXDIS),
89 .ssc_endx = SSC_BIT(SR_ENDRX),
90 .ssc_endbuf = SSC_BIT(SR_RXBUFF),
91 .pdc_enable = ATMEL_PDC_RXTEN,
92 .pdc_disable = ATMEL_PDC_RXTDIS,
93};
94
95
96/*
97 * DMA parameters.
98 */
99static struct atmel_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
100 {{
101 .name = "SSC0 PCM out",
102 .pdc = &pdc_tx_reg,
103 .mask = &ssc_tx_mask,
104 },
105 {
106 .name = "SSC0 PCM in",
107 .pdc = &pdc_rx_reg,
108 .mask = &ssc_rx_mask,
109 } },
110#if NUM_SSC_DEVICES == 3
111 {{
112 .name = "SSC1 PCM out",
113 .pdc = &pdc_tx_reg,
114 .mask = &ssc_tx_mask,
115 },
116 {
117 .name = "SSC1 PCM in",
118 .pdc = &pdc_rx_reg,
119 .mask = &ssc_rx_mask,
120 } },
121 {{
122 .name = "SSC2 PCM out",
123 .pdc = &pdc_tx_reg,
124 .mask = &ssc_tx_mask,
125 },
126 {
127 .name = "SSC2 PCM in",
128 .pdc = &pdc_rx_reg,
129 .mask = &ssc_rx_mask,
130 } },
131#endif
132};
133
134
135static struct atmel_ssc_info ssc_info[NUM_SSC_DEVICES] = {
136 {
137 .name = "ssc0",
138 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
139 .dir_mask = SSC_DIR_MASK_UNUSED,
140 .initialized = 0,
141 },
142#if NUM_SSC_DEVICES == 3
143 {
144 .name = "ssc1",
145 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
146 .dir_mask = SSC_DIR_MASK_UNUSED,
147 .initialized = 0,
148 },
149 {
150 .name = "ssc2",
151 .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
152 .dir_mask = SSC_DIR_MASK_UNUSED,
153 .initialized = 0,
154 },
155#endif
156};
157
158
159/*
160 * SSC interrupt handler. Passes PDC interrupts to the DMA
161 * interrupt handler in the PCM driver.
162 */
163static irqreturn_t atmel_ssc_interrupt(int irq, void *dev_id)
164{
165 struct atmel_ssc_info *ssc_p = dev_id;
166 struct atmel_pcm_dma_params *dma_params;
167 u32 ssc_sr;
168 u32 ssc_substream_mask;
169 int i;
170
171 ssc_sr = (unsigned long)ssc_readl(ssc_p->ssc->regs, SR)
172 & (unsigned long)ssc_readl(ssc_p->ssc->regs, IMR);
173
174 /*
175 * Loop through the substreams attached to this SSC. If
176 * a DMA-related interrupt occurred on that substream, call
177 * the DMA interrupt handler function, if one has been
178 * registered in the dma_params structure by the PCM driver.
179 */
180 for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
181 dma_params = ssc_p->dma_params[i];
182
183 if ((dma_params != NULL) &&
184 (dma_params->dma_intr_handler != NULL)) {
185 ssc_substream_mask = (dma_params->mask->ssc_endx |
186 dma_params->mask->ssc_endbuf);
187 if (ssc_sr & ssc_substream_mask) {
188 dma_params->dma_intr_handler(ssc_sr,
189 dma_params->
190 substream);
191 }
192 }
193 }
194
195 return IRQ_HANDLED;
196}
197
198
199/*-------------------------------------------------------------------------*\
200 * DAI functions
201\*-------------------------------------------------------------------------*/
202/*
203 * Startup. Only that one substream allowed in each direction.
204 */
205static int atmel_ssc_startup(struct snd_pcm_substream *substream,
206 struct snd_soc_dai *dai)
207{
208 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
209 struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
210 int dir_mask;
211
212 pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
213 ssc_readl(ssc_p->ssc->regs, SR));
214
215 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
216 dir_mask = SSC_DIR_MASK_PLAYBACK;
217 else
218 dir_mask = SSC_DIR_MASK_CAPTURE;
219
220 spin_lock_irq(&ssc_p->lock);
221 if (ssc_p->dir_mask & dir_mask) {
222 spin_unlock_irq(&ssc_p->lock);
223 return -EBUSY;
224 }
225 ssc_p->dir_mask |= dir_mask;
226 spin_unlock_irq(&ssc_p->lock);
227
228 return 0;
229}
230
231/*
232 * Shutdown. Clear DMA parameters and shutdown the SSC if there
233 * are no other substreams open.
234 */
235static void atmel_ssc_shutdown(struct snd_pcm_substream *substream,
236 struct snd_soc_dai *dai)
237{
238 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
239 struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
240 struct atmel_pcm_dma_params *dma_params;
241 int dir, dir_mask;
242
243 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
244 dir = 0;
245 else
246 dir = 1;
247
248 dma_params = ssc_p->dma_params[dir];
249
250 if (dma_params != NULL) {
251 ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
252 pr_debug("atmel_ssc_shutdown: %s disabled SSC_SR=0x%08x\n",
253 (dir ? "receive" : "transmit"),
254 ssc_readl(ssc_p->ssc->regs, SR));
255
256 dma_params->ssc = NULL;
257 dma_params->substream = NULL;
258 ssc_p->dma_params[dir] = NULL;
259 }
260
261 dir_mask = 1 << dir;
262
263 spin_lock_irq(&ssc_p->lock);
264 ssc_p->dir_mask &= ~dir_mask;
265 if (!ssc_p->dir_mask) {
266 if (ssc_p->initialized) {
267 /* Shutdown the SSC clock. */
268 pr_debug("atmel_ssc_dau: Stopping clock\n");
269 clk_disable(ssc_p->ssc->clk);
270
271 free_irq(ssc_p->ssc->irq, ssc_p);
272 ssc_p->initialized = 0;
273 }
274
275 /* Reset the SSC */
276 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
277 /* Clear the SSC dividers */
278 ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0;
279 }
280 spin_unlock_irq(&ssc_p->lock);
281}
282
283
284/*
285 * Record the DAI format for use in hw_params().
286 */
287static int atmel_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
288 unsigned int fmt)
289{
290 struct atmel_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
291
292 ssc_p->daifmt = fmt;
293 return 0;
294}
295
296/*
297 * Record SSC clock dividers for use in hw_params().
298 */
299static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
300 int div_id, int div)
301{
302 struct atmel_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
303
304 switch (div_id) {
305 case ATMEL_SSC_CMR_DIV:
306 /*
307 * The same master clock divider is used for both
308 * transmit and receive, so if a value has already
309 * been set, it must match this value.
310 */
311 if (ssc_p->cmr_div == 0)
312 ssc_p->cmr_div = div;
313 else
314 if (div != ssc_p->cmr_div)
315 return -EBUSY;
316 break;
317
318 case ATMEL_SSC_TCMR_PERIOD:
319 ssc_p->tcmr_period = div;
320 break;
321
322 case ATMEL_SSC_RCMR_PERIOD:
323 ssc_p->rcmr_period = div;
324 break;
325
326 default:
327 return -EINVAL;
328 }
329
330 return 0;
331}
332
333/*
334 * Configure the SSC.
335 */
336static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
337 struct snd_pcm_hw_params *params,
338 struct snd_soc_dai *dai)
339{
340 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
341 int id = rtd->dai->cpu_dai->id;
342 struct atmel_ssc_info *ssc_p = &ssc_info[id];
343 struct atmel_pcm_dma_params *dma_params;
344 int dir, channels, bits;
345 u32 tfmr, rfmr, tcmr, rcmr;
346 int start_event;
347 int ret;
348
349 /*
350 * Currently, there is only one set of dma params for
351 * each direction. If more are added, this code will
352 * have to be changed to select the proper set.
353 */
354 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
355 dir = 0;
356 else
357 dir = 1;
358
359 dma_params = &ssc_dma_params[id][dir];
360 dma_params->ssc = ssc_p->ssc;
361 dma_params->substream = substream;
362
363 ssc_p->dma_params[dir] = dma_params;
364
365 /*
366 * The cpu_dai->dma_data field is only used to communicate the
367 * appropriate DMA parameters to the pcm driver hw_params()
368 * function. It should not be used for other purposes
369 * as it is common to all substreams.
370 */
371 rtd->dai->cpu_dai->dma_data = dma_params;
372
373 channels = params_channels(params);
374
375 /*
376 * Determine sample size in bits and the PDC increment.
377 */
378 switch (params_format(params)) {
379 case SNDRV_PCM_FORMAT_S8:
380 bits = 8;
381 dma_params->pdc_xfer_size = 1;
382 break;
383 case SNDRV_PCM_FORMAT_S16_LE:
384 bits = 16;
385 dma_params->pdc_xfer_size = 2;
386 break;
387 case SNDRV_PCM_FORMAT_S24_LE:
388 bits = 24;
389 dma_params->pdc_xfer_size = 4;
390 break;
391 case SNDRV_PCM_FORMAT_S32_LE:
392 bits = 32;
393 dma_params->pdc_xfer_size = 4;
394 break;
395 default:
396 printk(KERN_WARNING "atmel_ssc_dai: unsupported PCM format");
397 return -EINVAL;
398 }
399
400 /*
401 * The SSC only supports up to 16-bit samples in I2S format, due
402 * to the size of the Frame Mode Register FSLEN field.
403 */
404 if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
405 && bits > 16) {
406 printk(KERN_WARNING
407 "atmel_ssc_dai: sample size %d"
408 "is too large for I2S\n", bits);
409 return -EINVAL;
410 }
411
412 /*
413 * Compute SSC register settings.
414 */
415 switch (ssc_p->daifmt
416 & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
417
418 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
419 /*
420 * I2S format, SSC provides BCLK and LRC clocks.
421 *
422 * The SSC transmit and receive clocks are generated
423 * from the MCK divider, and the BCLK signal
424 * is output on the SSC TK line.
425 */
426 rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
427 | SSC_BF(RCMR_STTDLY, START_DELAY)
428 | SSC_BF(RCMR_START, SSC_START_FALLING_RF)
429 | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
430 | SSC_BF(RCMR_CKO, SSC_CKO_NONE)
431 | SSC_BF(RCMR_CKS, SSC_CKS_DIV);
432
433 rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
434 | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
435 | SSC_BF(RFMR_FSLEN, (bits - 1))
436 | SSC_BF(RFMR_DATNB, (channels - 1))
437 | SSC_BIT(RFMR_MSBF)
438 | SSC_BF(RFMR_LOOP, 0)
439 | SSC_BF(RFMR_DATLEN, (bits - 1));
440
441 tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period)
442 | SSC_BF(TCMR_STTDLY, START_DELAY)
443 | SSC_BF(TCMR_START, SSC_START_FALLING_RF)
444 | SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
445 | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
446 | SSC_BF(TCMR_CKS, SSC_CKS_DIV);
447
448 tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
449 | SSC_BF(TFMR_FSDEN, 0)
450 | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
451 | SSC_BF(TFMR_FSLEN, (bits - 1))
452 | SSC_BF(TFMR_DATNB, (channels - 1))
453 | SSC_BIT(TFMR_MSBF)
454 | SSC_BF(TFMR_DATDEF, 0)
455 | SSC_BF(TFMR_DATLEN, (bits - 1));
456 break;
457
458 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
459 /*
460 * I2S format, CODEC supplies BCLK and LRC clocks.
461 *
462 * The SSC transmit clock is obtained from the BCLK signal on
463 * on the TK line, and the SSC receive clock is
464 * generated from the transmit clock.
465 *
466 * For single channel data, one sample is transferred
467 * on the falling edge of the LRC clock.
468 * For two channel data, one sample is
469 * transferred on both edges of the LRC clock.
470 */
471 start_event = ((channels == 1)
472 ? SSC_START_FALLING_RF
473 : SSC_START_EDGE_RF);
474
475 rcmr = SSC_BF(RCMR_PERIOD, 0)
476 | SSC_BF(RCMR_STTDLY, START_DELAY)
477 | SSC_BF(RCMR_START, start_event)
478 | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
479 | SSC_BF(RCMR_CKO, SSC_CKO_NONE)
480 | SSC_BF(RCMR_CKS, SSC_CKS_CLOCK);
481
482 rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
483 | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE)
484 | SSC_BF(RFMR_FSLEN, 0)
485 | SSC_BF(RFMR_DATNB, 0)
486 | SSC_BIT(RFMR_MSBF)
487 | SSC_BF(RFMR_LOOP, 0)
488 | SSC_BF(RFMR_DATLEN, (bits - 1));
489
490 tcmr = SSC_BF(TCMR_PERIOD, 0)
491 | SSC_BF(TCMR_STTDLY, START_DELAY)
492 | SSC_BF(TCMR_START, start_event)
493 | SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
494 | SSC_BF(TCMR_CKO, SSC_CKO_NONE)
495 | SSC_BF(TCMR_CKS, SSC_CKS_PIN);
496
497 tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
498 | SSC_BF(TFMR_FSDEN, 0)
499 | SSC_BF(TFMR_FSOS, SSC_FSOS_NONE)
500 | SSC_BF(TFMR_FSLEN, 0)
501 | SSC_BF(TFMR_DATNB, 0)
502 | SSC_BIT(TFMR_MSBF)
503 | SSC_BF(TFMR_DATDEF, 0)
504 | SSC_BF(TFMR_DATLEN, (bits - 1));
505 break;
506
507 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
508 /*
509 * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
510 *
511 * The SSC transmit and receive clocks are generated from the
512 * MCK divider, and the BCLK signal is output
513 * on the SSC TK line.
514 */
515 rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
516 | SSC_BF(RCMR_STTDLY, 1)
517 | SSC_BF(RCMR_START, SSC_START_RISING_RF)
518 | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
519 | SSC_BF(RCMR_CKO, SSC_CKO_NONE)
520 | SSC_BF(RCMR_CKS, SSC_CKS_DIV);
521
522 rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
523 | SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE)
524 | SSC_BF(RFMR_FSLEN, 0)
525 | SSC_BF(RFMR_DATNB, (channels - 1))
526 | SSC_BIT(RFMR_MSBF)
527 | SSC_BF(RFMR_LOOP, 0)
528 | SSC_BF(RFMR_DATLEN, (bits - 1));
529
530 tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period)
531 | SSC_BF(TCMR_STTDLY, 1)
532 | SSC_BF(TCMR_START, SSC_START_RISING_RF)
533 | SSC_BF(TCMR_CKI, SSC_CKI_RISING)
534 | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
535 | SSC_BF(TCMR_CKS, SSC_CKS_DIV);
536
537 tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
538 | SSC_BF(TFMR_FSDEN, 0)
539 | SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE)
540 | SSC_BF(TFMR_FSLEN, 0)
541 | SSC_BF(TFMR_DATNB, (channels - 1))
542 | SSC_BIT(TFMR_MSBF)
543 | SSC_BF(TFMR_DATDEF, 0)
544 | SSC_BF(TFMR_DATLEN, (bits - 1));
545 break;
546
547 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
548 default:
549 printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n",
550 ssc_p->daifmt);
551 return -EINVAL;
552 break;
553 }
554 pr_debug("atmel_ssc_hw_params: "
555 "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
556 rcmr, rfmr, tcmr, tfmr);
557
558 if (!ssc_p->initialized) {
559
560 /* Enable PMC peripheral clock for this SSC */
561 pr_debug("atmel_ssc_dai: Starting clock\n");
562 clk_enable(ssc_p->ssc->clk);
563
564 /* Reset the SSC and its PDC registers */
565 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
566
567 ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0);
568 ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0);
569 ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0);
570 ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0);
571
572 ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0);
573 ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0);
574 ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0);
575 ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0);
576
577 ret = request_irq(ssc_p->ssc->irq, atmel_ssc_interrupt, 0,
578 ssc_p->name, ssc_p);
579 if (ret < 0) {
580 printk(KERN_WARNING
581 "atmel_ssc_dai: request_irq failure\n");
582 pr_debug("Atmel_ssc_dai: Stoping clock\n");
583 clk_disable(ssc_p->ssc->clk);
584 return ret;
585 }
586
587 ssc_p->initialized = 1;
588 }
589
590 /* set SSC clock mode register */
591 ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div);
592
593 /* set receive clock mode and format */
594 ssc_writel(ssc_p->ssc->regs, RCMR, rcmr);
595 ssc_writel(ssc_p->ssc->regs, RFMR, rfmr);
596
597 /* set transmit clock mode and format */
598 ssc_writel(ssc_p->ssc->regs, TCMR, tcmr);
599 ssc_writel(ssc_p->ssc->regs, TFMR, tfmr);
600
601 pr_debug("atmel_ssc_dai,hw_params: SSC initialized\n");
602 return 0;
603}
604
605
606static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
607 struct snd_soc_dai *dai)
608{
609 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
610 struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
611 struct atmel_pcm_dma_params *dma_params;
612 int dir;
613
614 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
615 dir = 0;
616 else
617 dir = 1;
618
619 dma_params = ssc_p->dma_params[dir];
620
621 ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
622
623 pr_debug("%s enabled SSC_SR=0x%08x\n",
624 dir ? "receive" : "transmit",
625 ssc_readl(ssc_p->ssc->regs, SR));
626 return 0;
627}
628
629
630#ifdef CONFIG_PM
631static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai)
632{
633 struct atmel_ssc_info *ssc_p;
634
635 if (!cpu_dai->active)
636 return 0;
637
638 ssc_p = &ssc_info[cpu_dai->id];
639
640 /* Save the status register before disabling transmit and receive */
641 ssc_p->ssc_state.ssc_sr = ssc_readl(ssc_p->ssc->regs, SR);
642 ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_TXDIS) | SSC_BIT(CR_RXDIS));
643
644 /* Save the current interrupt mask, then disable unmasked interrupts */
645 ssc_p->ssc_state.ssc_imr = ssc_readl(ssc_p->ssc->regs, IMR);
646 ssc_writel(ssc_p->ssc->regs, IDR, ssc_p->ssc_state.ssc_imr);
647
648 ssc_p->ssc_state.ssc_cmr = ssc_readl(ssc_p->ssc->regs, CMR);
649 ssc_p->ssc_state.ssc_rcmr = ssc_readl(ssc_p->ssc->regs, RCMR);
650 ssc_p->ssc_state.ssc_rfmr = ssc_readl(ssc_p->ssc->regs, RFMR);
651 ssc_p->ssc_state.ssc_tcmr = ssc_readl(ssc_p->ssc->regs, TCMR);
652 ssc_p->ssc_state.ssc_tfmr = ssc_readl(ssc_p->ssc->regs, TFMR);
653
654 return 0;
655}
656
657
658
659static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)
660{
661 struct atmel_ssc_info *ssc_p;
662 u32 cr;
663
664 if (!cpu_dai->active)
665 return 0;
666
667 ssc_p = &ssc_info[cpu_dai->id];
668
669 /* restore SSC register settings */
670 ssc_writel(ssc_p->ssc->regs, TFMR, ssc_p->ssc_state.ssc_tfmr);
671 ssc_writel(ssc_p->ssc->regs, TCMR, ssc_p->ssc_state.ssc_tcmr);
672 ssc_writel(ssc_p->ssc->regs, RFMR, ssc_p->ssc_state.ssc_rfmr);
673 ssc_writel(ssc_p->ssc->regs, RCMR, ssc_p->ssc_state.ssc_rcmr);
674 ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->ssc_state.ssc_cmr);
675
676 /* re-enable interrupts */
677 ssc_writel(ssc_p->ssc->regs, IER, ssc_p->ssc_state.ssc_imr);
678
679 /* Re-enable recieve and transmit as appropriate */
680 cr = 0;
681 cr |=
682 (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_RXEN)) ? SSC_BIT(CR_RXEN) : 0;
683 cr |=
684 (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_TXEN)) ? SSC_BIT(CR_TXEN) : 0;
685 ssc_writel(ssc_p->ssc->regs, CR, cr);
686
687 return 0;
688}
689#else /* CONFIG_PM */
690# define atmel_ssc_suspend NULL
691# define atmel_ssc_resume NULL
692#endif /* CONFIG_PM */
693
694
695#define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000)
696
697#define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
698 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
699
700struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
701 { .name = "atmel-ssc0",
702 .id = 0,
703 .suspend = atmel_ssc_suspend,
704 .resume = atmel_ssc_resume,
705 .playback = {
706 .channels_min = 1,
707 .channels_max = 2,
708 .rates = ATMEL_SSC_RATES,
709 .formats = ATMEL_SSC_FORMATS,},
710 .capture = {
711 .channels_min = 1,
712 .channels_max = 2,
713 .rates = ATMEL_SSC_RATES,
714 .formats = ATMEL_SSC_FORMATS,},
715 .ops = {
716 .startup = atmel_ssc_startup,
717 .shutdown = atmel_ssc_shutdown,
718 .prepare = atmel_ssc_prepare,
719 .hw_params = atmel_ssc_hw_params,
720 .set_fmt = atmel_ssc_set_dai_fmt,
721 .set_clkdiv = atmel_ssc_set_dai_clkdiv,},
722 .private_data = &ssc_info[0],
723 },
724#if NUM_SSC_DEVICES == 3
725 { .name = "atmel-ssc1",
726 .id = 1,
727 .suspend = atmel_ssc_suspend,
728 .resume = atmel_ssc_resume,
729 .playback = {
730 .channels_min = 1,
731 .channels_max = 2,
732 .rates = ATMEL_SSC_RATES,
733 .formats = ATMEL_SSC_FORMATS,},
734 .capture = {
735 .channels_min = 1,
736 .channels_max = 2,
737 .rates = ATMEL_SSC_RATES,
738 .formats = ATMEL_SSC_FORMATS,},
739 .ops = {
740 .startup = atmel_ssc_startup,
741 .shutdown = atmel_ssc_shutdown,
742 .prepare = atmel_ssc_prepare,
743 .hw_params = atmel_ssc_hw_params,
744 .set_fmt = atmel_ssc_set_dai_fmt,
745 .set_clkdiv = atmel_ssc_set_dai_clkdiv,},
746 .private_data = &ssc_info[1],
747 },
748 { .name = "atmel-ssc2",
749 .id = 2,
750 .suspend = atmel_ssc_suspend,
751 .resume = atmel_ssc_resume,
752 .playback = {
753 .channels_min = 1,
754 .channels_max = 2,
755 .rates = ATMEL_SSC_RATES,
756 .formats = ATMEL_SSC_FORMATS,},
757 .capture = {
758 .channels_min = 1,
759 .channels_max = 2,
760 .rates = ATMEL_SSC_RATES,
761 .formats = ATMEL_SSC_FORMATS,},
762 .ops = {
763 .startup = atmel_ssc_startup,
764 .shutdown = atmel_ssc_shutdown,
765 .prepare = atmel_ssc_prepare,
766 .hw_params = atmel_ssc_hw_params,
767 .set_fmt = atmel_ssc_set_dai_fmt,
768 .set_clkdiv = atmel_ssc_set_dai_clkdiv,},
769 .private_data = &ssc_info[2],
770 },
771#endif
772};
773EXPORT_SYMBOL_GPL(atmel_ssc_dai);
774
775static int __init atmel_ssc_modinit(void)
776{
777 return snd_soc_register_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai));
778}
779module_init(atmel_ssc_modinit);
780
781static void __exit atmel_ssc_modexit(void)
782{
783 snd_soc_unregister_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai));
784}
785module_exit(atmel_ssc_modexit);
786
787/* Module information */
788MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com");
789MODULE_DESCRIPTION("ATMEL SSC ASoC Interface");
790MODULE_LICENSE("GPL");
diff --git a/sound/soc/atmel/atmel_ssc_dai.h b/sound/soc/atmel/atmel_ssc_dai.h
new file mode 100644
index 000000000000..a828746e8a2f
--- /dev/null
+++ b/sound/soc/atmel/atmel_ssc_dai.h
@@ -0,0 +1,121 @@
1/*
2 * atmel_ssc_dai.h - ALSA SSC interface for the Atmel SoC
3 *
4 * Copyright (C) 2005 SAN People
5 * Copyright (C) 2008 Atmel
6 *
7 * Author: Sedji Gaouaou <sedji.gaouaou@atmel.com>
8 * ATMEL CORP.
9 *
10 * Based on at91-ssc.c by
11 * Frank Mandarino <fmandarino@endrelia.com>
12 * Based on pxa2xx Platform drivers by
13 * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30#ifndef _ATMEL_SSC_DAI_H
31#define _ATMEL_SSC_DAI_H
32
33#include <linux/types.h>
34#include <linux/atmel-ssc.h>
35
36#include "atmel-pcm.h"
37
38/* SSC system clock ids */
39#define ATMEL_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */
40
41/* SSC divider ids */
42#define ATMEL_SSC_CMR_DIV 0 /* MCK divider for BCLK */
43#define ATMEL_SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
44#define ATMEL_SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
45/*
46 * SSC direction masks
47 */
48#define SSC_DIR_MASK_UNUSED 0
49#define SSC_DIR_MASK_PLAYBACK 1
50#define SSC_DIR_MASK_CAPTURE 2
51
52/*
53 * SSC register values that Atmel left out of <linux/atmel-ssc.h>. These
54 * are expected to be used with SSC_BF
55 */
56/* START bit field values */
57#define SSC_START_CONTINUOUS 0
58#define SSC_START_TX_RX 1
59#define SSC_START_LOW_RF 2
60#define SSC_START_HIGH_RF 3
61#define SSC_START_FALLING_RF 4
62#define SSC_START_RISING_RF 5
63#define SSC_START_LEVEL_RF 6
64#define SSC_START_EDGE_RF 7
65#define SSS_START_COMPARE_0 8
66
67/* CKI bit field values */
68#define SSC_CKI_FALLING 0
69#define SSC_CKI_RISING 1
70
71/* CKO bit field values */
72#define SSC_CKO_NONE 0
73#define SSC_CKO_CONTINUOUS 1
74#define SSC_CKO_TRANSFER 2
75
76/* CKS bit field values */
77#define SSC_CKS_DIV 0
78#define SSC_CKS_CLOCK 1
79#define SSC_CKS_PIN 2
80
81/* FSEDGE bit field values */
82#define SSC_FSEDGE_POSITIVE 0
83#define SSC_FSEDGE_NEGATIVE 1
84
85/* FSOS bit field values */
86#define SSC_FSOS_NONE 0
87#define SSC_FSOS_NEGATIVE 1
88#define SSC_FSOS_POSITIVE 2
89#define SSC_FSOS_LOW 3
90#define SSC_FSOS_HIGH 4
91#define SSC_FSOS_TOGGLE 5
92
93#define START_DELAY 1
94
95struct atmel_ssc_state {
96 u32 ssc_cmr;
97 u32 ssc_rcmr;
98 u32 ssc_rfmr;
99 u32 ssc_tcmr;
100 u32 ssc_tfmr;
101 u32 ssc_sr;
102 u32 ssc_imr;
103};
104
105
106struct atmel_ssc_info {
107 char *name;
108 struct ssc_device *ssc;
109 spinlock_t lock; /* lock for dir_mask */
110 unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
111 unsigned short initialized; /* true if SSC has been initialized */
112 unsigned short daifmt;
113 unsigned short cmr_div;
114 unsigned short tcmr_period;
115 unsigned short rcmr_period;
116 struct atmel_pcm_dma_params *dma_params[2];
117 struct atmel_ssc_state ssc_state;
118};
119extern struct snd_soc_dai atmel_ssc_dai[];
120
121#endif /* _AT91_SSC_DAI_H */
diff --git a/sound/soc/at32/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c
index b1966e4dfcd3..43dd8cee83c6 100644
--- a/sound/soc/at32/playpaq_wm8510.c
+++ b/sound/soc/atmel/playpaq_wm8510.c
@@ -22,7 +22,6 @@
22 22
23#include <linux/module.h> 23#include <linux/module.h>
24#include <linux/moduleparam.h> 24#include <linux/moduleparam.h>
25#include <linux/version.h>
26#include <linux/kernel.h> 25#include <linux/kernel.h>
27#include <linux/errno.h> 26#include <linux/errno.h>
28#include <linux/clk.h> 27#include <linux/clk.h>
@@ -40,8 +39,8 @@
40#include <mach/portmux.h> 39#include <mach/portmux.h>
41 40
42#include "../codecs/wm8510.h" 41#include "../codecs/wm8510.h"
43#include "at32-pcm.h" 42#include "atmel-pcm.h"
44#include "at32-ssc.h" 43#include "atmel_ssc_dai.h"
45 44
46 45
47/*-------------------------------------------------------------------------*\ 46/*-------------------------------------------------------------------------*\
@@ -362,8 +361,9 @@ static struct snd_soc_dai_link playpaq_wm8510_dai = {
362 361
363 362
364 363
365static struct snd_soc_machine snd_soc_machine_playpaq = { 364static struct snd_soc_card snd_soc_playpaq = {
366 .name = "LRS_PlayPaq_WM8510", 365 .name = "LRS_PlayPaq_WM8510",
366 .platform = &at32_soc_platform,
367 .dai_link = &playpaq_wm8510_dai, 367 .dai_link = &playpaq_wm8510_dai,
368 .num_links = 1, 368 .num_links = 1,
369}; 369};
@@ -378,8 +378,7 @@ static struct wm8510_setup_data playpaq_wm8510_setup = {
378 378
379 379
380static struct snd_soc_device playpaq_wm8510_snd_devdata = { 380static struct snd_soc_device playpaq_wm8510_snd_devdata = {
381 .machine = &snd_soc_machine_playpaq, 381 .card = &snd_soc_playpaq,
382 .platform = &at32_soc_platform,
383 .codec_dev = &soc_codec_dev_wm8510, 382 .codec_dev = &soc_codec_dev_wm8510,
384 .codec_data = &playpaq_wm8510_setup, 383 .codec_data = &playpaq_wm8510_setup,
385}; 384};
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
new file mode 100644
index 000000000000..1fb59a9d3719
--- /dev/null
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -0,0 +1,328 @@
1/*
2 * sam9g20_wm8731 -- SoC audio for AT91SAM9G20-based
3 * ATMEL AT91SAM9G20ek board.
4 *
5 * Copyright (C) 2005 SAN People
6 * Copyright (C) 2008 Atmel
7 *
8 * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
9 *
10 * Based on ati_b1_wm8731.c by:
11 * Frank Mandarino <fmandarino@endrelia.com>
12 * Copyright 2006 Endrelia Technologies Inc.
13 * Based on corgi.c by:
14 * Copyright 2005 Wolfson Microelectronics PLC.
15 * Copyright 2005 Openedhand Ltd.
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 */
31
32#include <linux/module.h>
33#include <linux/moduleparam.h>
34#include <linux/kernel.h>
35#include <linux/clk.h>
36#include <linux/timer.h>
37#include <linux/interrupt.h>
38#include <linux/platform_device.h>
39
40#include <linux/atmel-ssc.h>
41
42#include <sound/core.h>
43#include <sound/pcm.h>
44#include <sound/pcm_params.h>
45#include <sound/soc.h>
46#include <sound/soc-dapm.h>
47
48#include <mach/hardware.h>
49#include <mach/gpio.h>
50
51#include "../codecs/wm8731.h"
52#include "atmel-pcm.h"
53#include "atmel_ssc_dai.h"
54
55
56static int at91sam9g20ek_startup(struct snd_pcm_substream *substream)
57{
58 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
59 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
60 int ret;
61
62 /* codec system clock is supplied by PCK0, set to 12MHz */
63 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
64 12000000, SND_SOC_CLOCK_IN);
65 if (ret < 0)
66 return ret;
67
68 return 0;
69}
70
71static void at91sam9g20ek_shutdown(struct snd_pcm_substream *substream)
72{
73 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
74
75 dev_dbg(rtd->socdev->dev, "shutdown");
76}
77
78static int at91sam9g20ek_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->dai->codec_dai;
83 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
84 struct atmel_ssc_info *ssc_p = cpu_dai->private_data;
85 struct ssc_device *ssc = ssc_p->ssc;
86 int ret;
87
88 unsigned int rate;
89 int cmr_div, period;
90
91 if (ssc == NULL) {
92 printk(KERN_INFO "at91sam9g20ek_hw_params: ssc is NULL!\n");
93 return -EINVAL;
94 }
95
96 /* set codec DAI configuration */
97 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
98 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
99 if (ret < 0)
100 return ret;
101
102 /* set cpu DAI configuration */
103 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
104 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
105 if (ret < 0)
106 return ret;
107
108 /*
109 * The SSC clock dividers depend on the sample rate. The CMR.DIV
110 * field divides the system master clock MCK to drive the SSC TK
111 * signal which provides the codec BCLK. The TCMR.PERIOD and
112 * RCMR.PERIOD fields further divide the BCLK signal to drive
113 * the SSC TF and RF signals which provide the codec DACLRC and
114 * ADCLRC clocks.
115 *
116 * The dividers were determined through trial and error, where a
117 * CMR.DIV value is chosen such that the resulting BCLK value is
118 * divisible, or almost divisible, by (2 * sample rate), and then
119 * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1.
120 */
121 rate = params_rate(params);
122
123 switch (rate) {
124 case 8000:
125 cmr_div = 55; /* BCLK = 133MHz/(2*55) = 1.209MHz */
126 period = 74; /* LRC = BCLK/(2*(74+1)) ~= 8060,6Hz */
127 break;
128 case 11025:
129 cmr_div = 67; /* BCLK = 133MHz/(2*60) = 1.108MHz */
130 period = 45; /* LRC = BCLK/(2*(49+1)) = 11083,3Hz */
131 break;
132 case 16000:
133 cmr_div = 63; /* BCLK = 133MHz/(2*63) = 1.055MHz */
134 period = 32; /* LRC = BCLK/(2*(32+1)) = 15993,2Hz */
135 break;
136 case 22050:
137 cmr_div = 52; /* BCLK = 133MHz/(2*52) = 1.278MHz */
138 period = 28; /* LRC = BCLK/(2*(28+1)) = 22049Hz */
139 break;
140 case 32000:
141 cmr_div = 66; /* BCLK = 133MHz/(2*66) = 1.007MHz */
142 period = 15; /* LRC = BCLK/(2*(15+1)) = 31486,742Hz */
143 break;
144 case 44100:
145 cmr_div = 29; /* BCLK = 133MHz/(2*29) = 2.293MHz */
146 period = 25; /* LRC = BCLK/(2*(25+1)) = 44098Hz */
147 break;
148 case 48000:
149 cmr_div = 33; /* BCLK = 133MHz/(2*33) = 2.015MHz */
150 period = 20; /* LRC = BCLK/(2*(20+1)) = 47979,79Hz */
151 break;
152 case 88200:
153 cmr_div = 29; /* BCLK = 133MHz/(2*29) = 2.293MHz */
154 period = 12; /* LRC = BCLK/(2*(12+1)) = 88196Hz */
155 break;
156 case 96000:
157 cmr_div = 23; /* BCLK = 133MHz/(2*23) = 2.891MHz */
158 period = 14; /* LRC = BCLK/(2*(14+1)) = 96376Hz */
159 break;
160 default:
161 printk(KERN_WARNING "unsupported rate %d"
162 " on at91sam9g20ek board\n", rate);
163 return -EINVAL;
164 }
165
166 /* set the MCK divider for BCLK */
167 ret = snd_soc_dai_set_clkdiv(cpu_dai, ATMEL_SSC_CMR_DIV, cmr_div);
168 if (ret < 0)
169 return ret;
170
171 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
172 /* set the BCLK divider for DACLRC */
173 ret = snd_soc_dai_set_clkdiv(cpu_dai,
174 ATMEL_SSC_TCMR_PERIOD, period);
175 } else {
176 /* set the BCLK divider for ADCLRC */
177 ret = snd_soc_dai_set_clkdiv(cpu_dai,
178 ATMEL_SSC_RCMR_PERIOD, period);
179 }
180 if (ret < 0)
181 return ret;
182
183 return 0;
184}
185
186static struct snd_soc_ops at91sam9g20ek_ops = {
187 .startup = at91sam9g20ek_startup,
188 .hw_params = at91sam9g20ek_hw_params,
189 .shutdown = at91sam9g20ek_shutdown,
190};
191
192
193static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = {
194 SND_SOC_DAPM_MIC("Int Mic", NULL),
195 SND_SOC_DAPM_SPK("Ext Spk", NULL),
196};
197
198static const struct snd_soc_dapm_route intercon[] = {
199
200 /* speaker connected to LHPOUT */
201 {"Ext Spk", NULL, "LHPOUT"},
202
203 /* mic is connected to Mic Jack, with WM8731 Mic Bias */
204 {"MICIN", NULL, "Mic Bias"},
205 {"Mic Bias", NULL, "Int Mic"},
206};
207
208/*
209 * Logic for a wm8731 as connected on a at91sam9g20ek board.
210 */
211static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec)
212{
213 printk(KERN_DEBUG
214 "at91sam9g20ek_wm8731 "
215 ": at91sam9g20ek_wm8731_init() called\n");
216
217 /* Add specific widgets */
218 snd_soc_dapm_new_controls(codec, at91sam9g20ek_dapm_widgets,
219 ARRAY_SIZE(at91sam9g20ek_dapm_widgets));
220 /* Set up specific audio path interconnects */
221 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
222
223 /* not connected */
224 snd_soc_dapm_disable_pin(codec, "RLINEIN");
225 snd_soc_dapm_disable_pin(codec, "LLINEIN");
226
227 /* always connected */
228 snd_soc_dapm_enable_pin(codec, "Int Mic");
229 snd_soc_dapm_enable_pin(codec, "Ext Spk");
230
231 snd_soc_dapm_sync(codec);
232
233 return 0;
234}
235
236static struct snd_soc_dai_link at91sam9g20ek_dai = {
237 .name = "WM8731",
238 .stream_name = "WM8731 PCM",
239 .cpu_dai = &atmel_ssc_dai[0],
240 .codec_dai = &wm8731_dai,
241 .init = at91sam9g20ek_wm8731_init,
242 .ops = &at91sam9g20ek_ops,
243};
244
245static struct snd_soc_card snd_soc_at91sam9g20ek = {
246 .name = "WM8731",
247 .platform = &atmel_soc_platform,
248 .dai_link = &at91sam9g20ek_dai,
249 .num_links = 1,
250};
251
252static struct wm8731_setup_data at91sam9g20ek_wm8731_setup = {
253 .i2c_bus = 0,
254 .i2c_address = 0x1b,
255};
256
257static struct snd_soc_device at91sam9g20ek_snd_devdata = {
258 .card = &snd_soc_at91sam9g20ek,
259 .codec_dev = &soc_codec_dev_wm8731,
260 .codec_data = &at91sam9g20ek_wm8731_setup,
261};
262
263static struct platform_device *at91sam9g20ek_snd_device;
264
265static int __init at91sam9g20ek_init(void)
266{
267 struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data;
268 struct ssc_device *ssc = NULL;
269 int ret;
270
271 /*
272 * Request SSC device
273 */
274 ssc = ssc_request(0);
275 if (IS_ERR(ssc)) {
276 ret = PTR_ERR(ssc);
277 ssc = NULL;
278 goto err_ssc;
279 }
280 ssc_p->ssc = ssc;
281
282 at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1);
283 if (!at91sam9g20ek_snd_device) {
284 printk(KERN_DEBUG
285 "platform device allocation failed\n");
286 ret = -ENOMEM;
287 }
288
289 platform_set_drvdata(at91sam9g20ek_snd_device,
290 &at91sam9g20ek_snd_devdata);
291 at91sam9g20ek_snd_devdata.dev = &at91sam9g20ek_snd_device->dev;
292
293 ret = platform_device_add(at91sam9g20ek_snd_device);
294 if (ret) {
295 printk(KERN_DEBUG
296 "platform device allocation failed\n");
297 platform_device_put(at91sam9g20ek_snd_device);
298 }
299
300 return ret;
301
302err_ssc:
303 return ret;
304}
305
306static void __exit at91sam9g20ek_exit(void)
307{
308 struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data;
309 struct ssc_device *ssc;
310
311 if (ssc_p != NULL) {
312 ssc = ssc_p->ssc;
313 if (ssc != NULL)
314 ssc_free(ssc);
315 ssc_p->ssc = NULL;
316 }
317
318 platform_device_unregister(at91sam9g20ek_snd_device);
319 at91sam9g20ek_snd_device = NULL;
320}
321
322module_init(at91sam9g20ek_init);
323module_exit(at91sam9g20ek_exit);
324
325/* Module information */
326MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
327MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK_WM8731");
328MODULE_LICENSE("GPL");
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
index 1466d9328800..74c823d60f91 100644
--- a/sound/soc/au1x/dbdma2.c
+++ b/sound/soc/au1x/dbdma2.c
@@ -406,11 +406,12 @@ static int __init au1xpsc_audio_dbdma_init(void)
406{ 406{
407 au1xpsc_audio_pcmdma[PCM_TX] = NULL; 407 au1xpsc_audio_pcmdma[PCM_TX] = NULL;
408 au1xpsc_audio_pcmdma[PCM_RX] = NULL; 408 au1xpsc_audio_pcmdma[PCM_RX] = NULL;
409 return 0; 409 return snd_soc_register_platform(&au1xpsc_soc_platform);
410} 410}
411 411
412static void __exit au1xpsc_audio_dbdma_exit(void) 412static void __exit au1xpsc_audio_dbdma_exit(void)
413{ 413{
414 snd_soc_unregister_platform(&au1xpsc_soc_platform);
414} 415}
415 416
416module_init(au1xpsc_audio_dbdma_init); 417module_init(au1xpsc_audio_dbdma_init);
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index 57facbad6825..f0e30aec7f23 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -160,7 +160,8 @@ struct snd_ac97_bus_ops soc_ac97_ops = {
160EXPORT_SYMBOL_GPL(soc_ac97_ops); 160EXPORT_SYMBOL_GPL(soc_ac97_ops);
161 161
162static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, 162static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
163 struct snd_pcm_hw_params *params) 163 struct snd_pcm_hw_params *params,
164 struct snd_soc_dai *dai)
164{ 165{
165 /* FIXME */ 166 /* FIXME */
166 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; 167 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
@@ -210,7 +211,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
210} 211}
211 212
212static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream, 213static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
213 int cmd) 214 int cmd, struct snd_soc_dai *dai)
214{ 215{
215 /* FIXME */ 216 /* FIXME */
216 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; 217 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
@@ -313,8 +314,7 @@ static void au1xpsc_ac97_remove(struct platform_device *pdev,
313 au1xpsc_ac97_workdata = NULL; 314 au1xpsc_ac97_workdata = NULL;
314} 315}
315 316
316static int au1xpsc_ac97_suspend(struct platform_device *pdev, 317static int au1xpsc_ac97_suspend(struct snd_soc_dai *dai)
317 struct snd_soc_dai *dai)
318{ 318{
319 /* save interesting registers and disable PSC */ 319 /* save interesting registers and disable PSC */
320 au1xpsc_ac97_workdata->pm[0] = 320 au1xpsc_ac97_workdata->pm[0] =
@@ -328,8 +328,7 @@ static int au1xpsc_ac97_suspend(struct platform_device *pdev,
328 return 0; 328 return 0;
329} 329}
330 330
331static int au1xpsc_ac97_resume(struct platform_device *pdev, 331static int au1xpsc_ac97_resume(struct snd_soc_dai *dai)
332 struct snd_soc_dai *dai)
333{ 332{
334 /* restore PSC clock config */ 333 /* restore PSC clock config */
335 au_writel(au1xpsc_ac97_workdata->pm[0] | PSC_SEL_PS_AC97MODE, 334 au_writel(au1xpsc_ac97_workdata->pm[0] | PSC_SEL_PS_AC97MODE,
@@ -345,7 +344,7 @@ static int au1xpsc_ac97_resume(struct platform_device *pdev,
345 344
346struct snd_soc_dai au1xpsc_ac97_dai = { 345struct snd_soc_dai au1xpsc_ac97_dai = {
347 .name = "au1xpsc_ac97", 346 .name = "au1xpsc_ac97",
348 .type = SND_SOC_DAI_AC97, 347 .ac97_control = 1,
349 .probe = au1xpsc_ac97_probe, 348 .probe = au1xpsc_ac97_probe,
350 .remove = au1xpsc_ac97_remove, 349 .remove = au1xpsc_ac97_remove,
351 .suspend = au1xpsc_ac97_suspend, 350 .suspend = au1xpsc_ac97_suspend,
@@ -372,11 +371,12 @@ EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai);
372static int __init au1xpsc_ac97_init(void) 371static int __init au1xpsc_ac97_init(void)
373{ 372{
374 au1xpsc_ac97_workdata = NULL; 373 au1xpsc_ac97_workdata = NULL;
375 return 0; 374 return snd_soc_register_dai(&au1xpsc_ac97_dai);
376} 375}
377 376
378static void __exit au1xpsc_ac97_exit(void) 377static void __exit au1xpsc_ac97_exit(void)
379{ 378{
379 snd_soc_unregister_dai(&au1xpsc_ac97_dai);
380} 380}
381 381
382module_init(au1xpsc_ac97_init); 382module_init(au1xpsc_ac97_init);
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
index 9384702c7ebd..f916de4400ed 100644
--- a/sound/soc/au1x/psc-i2s.c
+++ b/sound/soc/au1x/psc-i2s.c
@@ -116,7 +116,8 @@ out:
116} 116}
117 117
118static int au1xpsc_i2s_hw_params(struct snd_pcm_substream *substream, 118static int au1xpsc_i2s_hw_params(struct snd_pcm_substream *substream,
119 struct snd_pcm_hw_params *params) 119 struct snd_pcm_hw_params *params,
120 struct snd_soc_dai *dai)
120{ 121{
121 struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata; 122 struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata;
122 123
@@ -240,7 +241,8 @@ static int au1xpsc_i2s_stop(struct au1xpsc_audio_data *pscdata, int stype)
240 return 0; 241 return 0;
241} 242}
242 243
243static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd) 244static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
245 struct snd_soc_dai *dai)
244{ 246{
245 struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata; 247 struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata;
246 int ret, stype = SUBSTREAM_TYPE(substream); 248 int ret, stype = SUBSTREAM_TYPE(substream);
@@ -337,8 +339,7 @@ static void au1xpsc_i2s_remove(struct platform_device *pdev,
337 au1xpsc_i2s_workdata = NULL; 339 au1xpsc_i2s_workdata = NULL;
338} 340}
339 341
340static int au1xpsc_i2s_suspend(struct platform_device *pdev, 342static int au1xpsc_i2s_suspend(struct snd_soc_dai *cpu_dai)
341 struct snd_soc_dai *cpu_dai)
342{ 343{
343 /* save interesting register and disable PSC */ 344 /* save interesting register and disable PSC */
344 au1xpsc_i2s_workdata->pm[0] = 345 au1xpsc_i2s_workdata->pm[0] =
@@ -352,8 +353,7 @@ static int au1xpsc_i2s_suspend(struct platform_device *pdev,
352 return 0; 353 return 0;
353} 354}
354 355
355static int au1xpsc_i2s_resume(struct platform_device *pdev, 356static int au1xpsc_i2s_resume(struct snd_soc_dai *cpu_dai)
356 struct snd_soc_dai *cpu_dai)
357{ 357{
358 /* select I2S mode and PSC clock */ 358 /* select I2S mode and PSC clock */
359 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata)); 359 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata));
@@ -369,7 +369,6 @@ static int au1xpsc_i2s_resume(struct platform_device *pdev,
369 369
370struct snd_soc_dai au1xpsc_i2s_dai = { 370struct snd_soc_dai au1xpsc_i2s_dai = {
371 .name = "au1xpsc_i2s", 371 .name = "au1xpsc_i2s",
372 .type = SND_SOC_DAI_I2S,
373 .probe = au1xpsc_i2s_probe, 372 .probe = au1xpsc_i2s_probe,
374 .remove = au1xpsc_i2s_remove, 373 .remove = au1xpsc_i2s_remove,
375 .suspend = au1xpsc_i2s_suspend, 374 .suspend = au1xpsc_i2s_suspend,
@@ -389,8 +388,6 @@ struct snd_soc_dai au1xpsc_i2s_dai = {
389 .ops = { 388 .ops = {
390 .trigger = au1xpsc_i2s_trigger, 389 .trigger = au1xpsc_i2s_trigger,
391 .hw_params = au1xpsc_i2s_hw_params, 390 .hw_params = au1xpsc_i2s_hw_params,
392 },
393 .dai_ops = {
394 .set_fmt = au1xpsc_i2s_set_fmt, 391 .set_fmt = au1xpsc_i2s_set_fmt,
395 }, 392 },
396}; 393};
@@ -399,11 +396,12 @@ EXPORT_SYMBOL(au1xpsc_i2s_dai);
399static int __init au1xpsc_i2s_init(void) 396static int __init au1xpsc_i2s_init(void)
400{ 397{
401 au1xpsc_i2s_workdata = NULL; 398 au1xpsc_i2s_workdata = NULL;
402 return 0; 399 return snd_soc_register_dai(&au1xpsc_i2s_dai);
403} 400}
404 401
405static void __exit au1xpsc_i2s_exit(void) 402static void __exit au1xpsc_i2s_exit(void)
406{ 403{
404 snd_soc_unregister_dai(&au1xpsc_i2s_dai);
407} 405}
408 406
409module_init(au1xpsc_i2s_init); 407module_init(au1xpsc_i2s_init);
diff --git a/sound/soc/au1x/sample-ac97.c b/sound/soc/au1x/sample-ac97.c
index f75ae7f62c3d..27683eb7905e 100644
--- a/sound/soc/au1x/sample-ac97.c
+++ b/sound/soc/au1x/sample-ac97.c
@@ -42,14 +42,14 @@ static struct snd_soc_dai_link au1xpsc_sample_ac97_dai = {
42 .ops = NULL, 42 .ops = NULL,
43}; 43};
44 44
45static struct snd_soc_machine au1xpsc_sample_ac97_machine = { 45static struct snd_soc_card au1xpsc_sample_ac97_machine = {
46 .name = "Au1xxx PSC AC97 Audio", 46 .name = "Au1xxx PSC AC97 Audio",
47 .dai_link = &au1xpsc_sample_ac97_dai, 47 .dai_link = &au1xpsc_sample_ac97_dai,
48 .num_links = 1, 48 .num_links = 1,
49}; 49};
50 50
51static struct snd_soc_device au1xpsc_sample_ac97_devdata = { 51static struct snd_soc_device au1xpsc_sample_ac97_devdata = {
52 .machine = &au1xpsc_sample_ac97_machine, 52 .card = &au1xpsc_sample_ac97_machine,
53 .platform = &au1xpsc_soc_platform, /* see dbdma2.c */ 53 .platform = &au1xpsc_soc_platform, /* see dbdma2.c */
54 .codec_dev = &soc_codec_dev_ac97, 54 .codec_dev = &soc_codec_dev_ac97,
55}; 55};
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
index dc006206f622..0a2f8f9eff53 100644
--- a/sound/soc/blackfin/Kconfig
+++ b/sound/soc/blackfin/Kconfig
@@ -1,6 +1,6 @@
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 BF5xx chip"
3 depends on BLACKFIN && SND_SOC 3 depends on BLACKFIN
4 help 4 help
5 Say Y or M if you want to add support for codecs attached to 5 Say Y or M if you want to add support for codecs attached to
6 the Blackfin SPORT (synchronous serial ports) interface in I2S 6 the Blackfin SPORT (synchronous serial ports) interface in I2S
@@ -13,7 +13,6 @@ config SND_BF5XX_SOC_SSM2602
13 select SND_BF5XX_SOC_I2S 13 select SND_BF5XX_SOC_I2S
14 select SND_SOC_SSM2602 14 select SND_SOC_SSM2602
15 select I2C 15 select I2C
16 select I2C_BLACKFIN_TWI
17 help 16 help
18 Say Y if you want to add support for SoC audio on BF527-EZKIT. 17 Say Y if you want to add support for SoC audio on BF527-EZKIT.
19 18
@@ -35,7 +34,7 @@ config SND_BFIN_AD73311_SE
35 34
36config SND_BF5XX_AC97 35config SND_BF5XX_AC97
37 tristate "SoC AC97 Audio for the ADI BF5xx chip" 36 tristate "SoC AC97 Audio for the ADI BF5xx chip"
38 depends on BLACKFIN && SND_SOC 37 depends on BLACKFIN
39 help 38 help
40 Say Y or M if you want to add support for codecs attached to 39 Say Y or M if you want to add support for codecs attached to
41 the Blackfin SPORT (synchronous serial ports) interface in slot 16 40 the Blackfin SPORT (synchronous serial ports) interface in slot 16
@@ -47,7 +46,7 @@ config SND_BF5XX_AC97
47 properly with this driver. This driver is known to work with the 46 properly with this driver. This driver is known to work with the
48 Analog Devices line of AC97 codecs. 47 Analog Devices line of AC97 codecs.
49 48
50config SND_MMAP_SUPPORT 49config SND_BF5XX_MMAP_SUPPORT
51 bool "Enable MMAP Support" 50 bool "Enable MMAP Support"
52 depends on SND_BF5XX_AC97 51 depends on SND_BF5XX_AC97
53 default y 52 default y
@@ -55,9 +54,17 @@ config SND_MMAP_SUPPORT
55 Say y if you want AC97 driver to support mmap mode. 54 Say y if you want AC97 driver to support mmap mode.
56 We introduce an intermediate buffer to simulate mmap. 55 We introduce an intermediate buffer to simulate mmap.
57 56
57config SND_BF5XX_MULTICHAN_SUPPORT
58 bool "Enable Multichannel Support"
59 depends on SND_BF5XX_AC97
60 default n
61 help
62 Say y if you want AC97 driver to support up to 5.1 channel audio.
63 this mode will consume much more memory for DMA.
64
58config SND_BF5XX_SOC_SPORT 65config SND_BF5XX_SOC_SPORT
59 tristate 66 tristate
60 67
61config SND_BF5XX_SOC_I2S 68config SND_BF5XX_SOC_I2S
62 tristate 69 tristate
63 select SND_BF5XX_SOC_SPORT 70 select SND_BF5XX_SOC_SPORT
@@ -80,7 +87,7 @@ config SND_BF5XX_SPORT_NUM
80 int "Set a SPORT for Sound chip" 87 int "Set a SPORT for Sound chip"
81 depends on (SND_BF5XX_I2S || SND_BF5XX_AC97) 88 depends on (SND_BF5XX_I2S || SND_BF5XX_AC97)
82 range 0 3 if BF54x 89 range 0 3 if BF54x
83 range 0 1 if (BF53x || BF561) 90 range 0 1 if !BF54x
84 default 0 91 default 0
85 help 92 help
86 Set the correct SPORT for sound chip. 93 Set the correct SPORT for sound chip.
@@ -90,12 +97,13 @@ config SND_BF5XX_HAVE_COLD_RESET
90 depends on SND_BF5XX_AC97 97 depends on SND_BF5XX_AC97
91 default y if BFIN548_EZKIT 98 default y if BFIN548_EZKIT
92 default n if !BFIN548_EZKIT 99 default n if !BFIN548_EZKIT
93 100
94config SND_BF5XX_RESET_GPIO_NUM 101config SND_BF5XX_RESET_GPIO_NUM
95 int "Set a GPIO for cold reset" 102 int "Set a GPIO for cold reset"
96 depends on SND_BF5XX_HAVE_COLD_RESET 103 depends on SND_BF5XX_HAVE_COLD_RESET
97 range 0 159 104 range 0 159
98 default 19 if BFIN548_EZKIT 105 default 19 if BFIN548_EZKIT
99 default 5 if BFIN537_STAMP 106 default 5 if BFIN537_STAMP
107 default 0
100 help 108 help
101 Set the correct GPIO for RESET the sound chip. 109 Set the correct GPIO for RESET the sound chip.
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 25e50d2ea1ec..8067cfafa3a7 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -43,24 +43,34 @@
43#include "bf5xx-ac97.h" 43#include "bf5xx-ac97.h"
44#include "bf5xx-sport.h" 44#include "bf5xx-sport.h"
45 45
46#if defined(CONFIG_SND_MMAP_SUPPORT) 46static unsigned int ac97_chan_mask[] = {
47 SP_FL, /* Mono */
48 SP_STEREO, /* Stereo */
49 SP_2DOT1, /* 2.1*/
50 SP_QUAD,/*Quadraquic*/
51 SP_FL | SP_FR | SP_FC | SP_SL | SP_SR,/*5 channels */
52 SP_5DOT1, /* 5.1 */
53};
54
55#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
47static void bf5xx_mmap_copy(struct snd_pcm_substream *substream, 56static void bf5xx_mmap_copy(struct snd_pcm_substream *substream,
48 snd_pcm_uframes_t count) 57 snd_pcm_uframes_t count)
49{ 58{
50 struct snd_pcm_runtime *runtime = substream->runtime; 59 struct snd_pcm_runtime *runtime = substream->runtime;
51 struct sport_device *sport = runtime->private_data; 60 struct sport_device *sport = runtime->private_data;
61 unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1];
52 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 62 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
53 bf5xx_pcm_to_ac97( 63 bf5xx_pcm_to_ac97((struct ac97_frame *)sport->tx_dma_buf +
54 (struct ac97_frame *)sport->tx_dma_buf + sport->tx_pos, 64 sport->tx_pos, (__u16 *)runtime->dma_area + sport->tx_pos *
55 (__u32 *)runtime->dma_area + sport->tx_pos, count); 65 runtime->channels, count, chan_mask);
56 sport->tx_pos += runtime->period_size; 66 sport->tx_pos += runtime->period_size;
57 if (sport->tx_pos >= runtime->buffer_size) 67 if (sport->tx_pos >= runtime->buffer_size)
58 sport->tx_pos %= runtime->buffer_size; 68 sport->tx_pos %= runtime->buffer_size;
59 sport->tx_delay_pos = sport->tx_pos; 69 sport->tx_delay_pos = sport->tx_pos;
60 } else { 70 } else {
61 bf5xx_ac97_to_pcm( 71 bf5xx_ac97_to_pcm((struct ac97_frame *)sport->rx_dma_buf +
62 (struct ac97_frame *)sport->rx_dma_buf + sport->rx_pos, 72 sport->rx_pos, (__u16 *)runtime->dma_area + sport->rx_pos *
63 (__u32 *)runtime->dma_area + sport->rx_pos, count); 73 runtime->channels, count);
64 sport->rx_pos += runtime->period_size; 74 sport->rx_pos += runtime->period_size;
65 if (sport->rx_pos >= runtime->buffer_size) 75 if (sport->rx_pos >= runtime->buffer_size)
66 sport->rx_pos %= runtime->buffer_size; 76 sport->rx_pos %= runtime->buffer_size;
@@ -71,7 +81,7 @@ static void bf5xx_mmap_copy(struct snd_pcm_substream *substream,
71static void bf5xx_dma_irq(void *data) 81static void bf5xx_dma_irq(void *data)
72{ 82{
73 struct snd_pcm_substream *pcm = data; 83 struct snd_pcm_substream *pcm = data;
74#if defined(CONFIG_SND_MMAP_SUPPORT) 84#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
75 struct snd_pcm_runtime *runtime = pcm->runtime; 85 struct snd_pcm_runtime *runtime = pcm->runtime;
76 struct sport_device *sport = runtime->private_data; 86 struct sport_device *sport = runtime->private_data;
77 bf5xx_mmap_copy(pcm, runtime->period_size); 87 bf5xx_mmap_copy(pcm, runtime->period_size);
@@ -90,17 +100,14 @@ static void bf5xx_dma_irq(void *data)
90 * The total rx/tx buffer is for ac97 frame to hold all pcm data 100 * The total rx/tx buffer is for ac97 frame to hold all pcm data
91 * is 0x20000 * sizeof(struct ac97_frame) / 4. 101 * is 0x20000 * sizeof(struct ac97_frame) / 4.
92 */ 102 */
93#ifdef CONFIG_SND_MMAP_SUPPORT
94static const struct snd_pcm_hardware bf5xx_pcm_hardware = { 103static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
95 .info = SNDRV_PCM_INFO_INTERLEAVED | 104 .info = SNDRV_PCM_INFO_INTERLEAVED |
105#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
96 SNDRV_PCM_INFO_MMAP | 106 SNDRV_PCM_INFO_MMAP |
97 SNDRV_PCM_INFO_MMAP_VALID | 107 SNDRV_PCM_INFO_MMAP_VALID |
98 SNDRV_PCM_INFO_BLOCK_TRANSFER,
99#else
100static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
101 .info = SNDRV_PCM_INFO_INTERLEAVED |
102 SNDRV_PCM_INFO_BLOCK_TRANSFER,
103#endif 108#endif
109 SNDRV_PCM_INFO_BLOCK_TRANSFER,
110
104 .formats = SNDRV_PCM_FMTBIT_S16_LE, 111 .formats = SNDRV_PCM_FMTBIT_S16_LE,
105 .period_bytes_min = 32, 112 .period_bytes_min = 32,
106 .period_bytes_max = 0x10000, 113 .period_bytes_max = 0x10000,
@@ -123,10 +130,20 @@ static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream,
123 130
124static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) 131static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
125{ 132{
133#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
126 struct snd_pcm_runtime *runtime = substream->runtime; 134 struct snd_pcm_runtime *runtime = substream->runtime;
135 struct sport_device *sport = runtime->private_data;
127 136
128 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 137 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
129 memset(runtime->dma_area, 0, runtime->buffer_size); 138 sport->once = 0;
139 if (runtime->dma_area)
140 memset(runtime->dma_area, 0, runtime->buffer_size);
141 memset(sport->tx_dma_buf, 0, runtime->buffer_size *
142 sizeof(struct ac97_frame));
143 } else
144 memset(sport->rx_dma_buf, 0, runtime->buffer_size *
145 sizeof(struct ac97_frame));
146#endif
130 snd_pcm_lib_free_pages(substream); 147 snd_pcm_lib_free_pages(substream);
131 return 0; 148 return 0;
132} 149}
@@ -139,7 +156,7 @@ static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream)
139 /* An intermediate buffer is introduced for implementing mmap for 156 /* An intermediate buffer is introduced for implementing mmap for
140 * SPORT working in TMD mode(include AC97). 157 * SPORT working in TMD mode(include AC97).
141 */ 158 */
142#if defined(CONFIG_SND_MMAP_SUPPORT) 159#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
143 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 160 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
144 sport_set_tx_callback(sport, bf5xx_dma_irq, substream); 161 sport_set_tx_callback(sport, bf5xx_dma_irq, substream);
145 sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods, 162 sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods,
@@ -173,24 +190,24 @@ static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
173 switch (cmd) { 190 switch (cmd) {
174 case SNDRV_PCM_TRIGGER_START: 191 case SNDRV_PCM_TRIGGER_START:
175 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 192 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
193#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
176 bf5xx_mmap_copy(substream, runtime->period_size); 194 bf5xx_mmap_copy(substream, runtime->period_size);
177 snd_pcm_period_elapsed(substream);
178 sport->tx_delay_pos = 0; 195 sport->tx_delay_pos = 0;
196#endif
179 sport_tx_start(sport); 197 sport_tx_start(sport);
180 } 198 } else
181 else
182 sport_rx_start(sport); 199 sport_rx_start(sport);
183 break; 200 break;
184 case SNDRV_PCM_TRIGGER_STOP: 201 case SNDRV_PCM_TRIGGER_STOP:
185 case SNDRV_PCM_TRIGGER_SUSPEND: 202 case SNDRV_PCM_TRIGGER_SUSPEND:
186 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 203 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
187 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 204 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
188#if defined(CONFIG_SND_MMAP_SUPPORT) 205#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
189 sport->tx_pos = 0; 206 sport->tx_pos = 0;
190#endif 207#endif
191 sport_tx_stop(sport); 208 sport_tx_stop(sport);
192 } else { 209 } else {
193#if defined(CONFIG_SND_MMAP_SUPPORT) 210#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
194 sport->rx_pos = 0; 211 sport->rx_pos = 0;
195#endif 212#endif
196 sport_rx_stop(sport); 213 sport_rx_stop(sport);
@@ -208,7 +225,7 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
208 struct sport_device *sport = runtime->private_data; 225 struct sport_device *sport = runtime->private_data;
209 unsigned int curr; 226 unsigned int curr;
210 227
211#if defined(CONFIG_SND_MMAP_SUPPORT) 228#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
212 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 229 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
213 curr = sport->tx_delay_pos; 230 curr = sport->tx_delay_pos;
214 else 231 else
@@ -249,22 +266,7 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
249 return ret; 266 return ret;
250} 267}
251 268
252static int bf5xx_pcm_close(struct snd_pcm_substream *substream) 269#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
253{
254 struct snd_pcm_runtime *runtime = substream->runtime;
255 struct sport_device *sport = runtime->private_data;
256
257 pr_debug("%s enter\n", __func__);
258 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
259 sport->once = 0;
260 memset(sport->tx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
261 } else
262 memset(sport->rx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
263
264 return 0;
265}
266
267#ifdef CONFIG_SND_MMAP_SUPPORT
268static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, 270static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream,
269 struct vm_area_struct *vma) 271 struct vm_area_struct *vma)
270{ 272{
@@ -281,32 +283,29 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
281 void __user *buf, snd_pcm_uframes_t count) 283 void __user *buf, snd_pcm_uframes_t count)
282{ 284{
283 struct snd_pcm_runtime *runtime = substream->runtime; 285 struct snd_pcm_runtime *runtime = substream->runtime;
284 286 unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1];
285 pr_debug("%s copy pos:0x%lx count:0x%lx\n", 287 pr_debug("%s copy pos:0x%lx count:0x%lx\n",
286 substream->stream ? "Capture" : "Playback", pos, count); 288 substream->stream ? "Capture" : "Playback", pos, count);
287 289
288 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 290 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
289 bf5xx_pcm_to_ac97( 291 bf5xx_pcm_to_ac97((struct ac97_frame *)runtime->dma_area + pos,
290 (struct ac97_frame *)runtime->dma_area + pos, 292 (__u16 *)buf, count, chan_mask);
291 buf, count);
292 else 293 else
293 bf5xx_ac97_to_pcm( 294 bf5xx_ac97_to_pcm((struct ac97_frame *)runtime->dma_area + pos,
294 (struct ac97_frame *)runtime->dma_area + pos, 295 (__u16 *)buf, count);
295 buf, count);
296 return 0; 296 return 0;
297} 297}
298#endif 298#endif
299 299
300struct snd_pcm_ops bf5xx_pcm_ac97_ops = { 300struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
301 .open = bf5xx_pcm_open, 301 .open = bf5xx_pcm_open,
302 .close = bf5xx_pcm_close,
303 .ioctl = snd_pcm_lib_ioctl, 302 .ioctl = snd_pcm_lib_ioctl,
304 .hw_params = bf5xx_pcm_hw_params, 303 .hw_params = bf5xx_pcm_hw_params,
305 .hw_free = bf5xx_pcm_hw_free, 304 .hw_free = bf5xx_pcm_hw_free,
306 .prepare = bf5xx_pcm_prepare, 305 .prepare = bf5xx_pcm_prepare,
307 .trigger = bf5xx_pcm_trigger, 306 .trigger = bf5xx_pcm_trigger,
308 .pointer = bf5xx_pcm_pointer, 307 .pointer = bf5xx_pcm_pointer,
309#ifdef CONFIG_SND_MMAP_SUPPORT 308#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
310 .mmap = bf5xx_pcm_mmap, 309 .mmap = bf5xx_pcm_mmap,
311#else 310#else
312 .copy = bf5xx_pcm_copy, 311 .copy = bf5xx_pcm_copy,
@@ -344,7 +343,7 @@ static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
344 * Need to allocate local buffer when enable 343 * Need to allocate local buffer when enable
345 * MMAP for SPORT working in TMD mode (include AC97). 344 * MMAP for SPORT working in TMD mode (include AC97).
346 */ 345 */
347#if defined(CONFIG_SND_MMAP_SUPPORT) 346#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
348 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 347 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
349 if (!sport_handle->tx_dma_buf) { 348 if (!sport_handle->tx_dma_buf) {
350 sport_handle->tx_dma_buf = dma_alloc_coherent(NULL, \ 349 sport_handle->tx_dma_buf = dma_alloc_coherent(NULL, \
@@ -381,7 +380,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
381 struct snd_pcm_substream *substream; 380 struct snd_pcm_substream *substream;
382 struct snd_dma_buffer *buf; 381 struct snd_dma_buffer *buf;
383 int stream; 382 int stream;
384#if defined(CONFIG_SND_MMAP_SUPPORT) 383#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
385 size_t size = bf5xx_pcm_hardware.buffer_bytes_max * 384 size_t size = bf5xx_pcm_hardware.buffer_bytes_max *
386 sizeof(struct ac97_frame) / 4; 385 sizeof(struct ac97_frame) / 4;
387#endif 386#endif
@@ -395,7 +394,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
395 continue; 394 continue;
396 dma_free_coherent(NULL, buf->bytes, buf->area, 0); 395 dma_free_coherent(NULL, buf->bytes, buf->area, 0);
397 buf->area = NULL; 396 buf->area = NULL;
398#if defined(CONFIG_SND_MMAP_SUPPORT) 397#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
399 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 398 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
400 if (sport_handle->tx_dma_buf) 399 if (sport_handle->tx_dma_buf)
401 dma_free_coherent(NULL, size, \ 400 dma_free_coherent(NULL, size, \
@@ -452,6 +451,18 @@ struct snd_soc_platform bf5xx_ac97_soc_platform = {
452}; 451};
453EXPORT_SYMBOL_GPL(bf5xx_ac97_soc_platform); 452EXPORT_SYMBOL_GPL(bf5xx_ac97_soc_platform);
454 453
454static int __init bfin_ac97_init(void)
455{
456 return snd_soc_register_platform(&bf5xx_ac97_soc_platform);
457}
458module_init(bfin_ac97_init);
459
460static void __exit bfin_ac97_exit(void)
461{
462 snd_soc_unregister_platform(&bf5xx_ac97_soc_platform);
463}
464module_exit(bfin_ac97_exit);
465
455MODULE_AUTHOR("Cliff Cai"); 466MODULE_AUTHOR("Cliff Cai");
456MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module"); 467MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module");
457MODULE_LICENSE("GPL"); 468MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index 5e5aafb6485f..3be2be60576d 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -54,71 +54,103 @@
54static int *cmd_count; 54static int *cmd_count;
55static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; 55static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM;
56 56
57#if defined(CONFIG_BF54x) 57static u16 sport_req[][7] = {
58 PIN_REQ_SPORT_0,
59#ifdef PIN_REQ_SPORT_1
60 PIN_REQ_SPORT_1,
61#endif
62#ifdef PIN_REQ_SPORT_2
63 PIN_REQ_SPORT_2,
64#endif
65#ifdef PIN_REQ_SPORT_3
66 PIN_REQ_SPORT_3,
67#endif
68 };
69
58static struct sport_param sport_params[4] = { 70static struct sport_param sport_params[4] = {
59 { 71 {
60 .dma_rx_chan = CH_SPORT0_RX, 72 .dma_rx_chan = CH_SPORT0_RX,
61 .dma_tx_chan = CH_SPORT0_TX, 73 .dma_tx_chan = CH_SPORT0_TX,
62 .err_irq = IRQ_SPORT0_ERR, 74 .err_irq = IRQ_SPORT0_ERROR,
63 .regs = (struct sport_register *)SPORT0_TCR1, 75 .regs = (struct sport_register *)SPORT0_TCR1,
64 }, 76 },
77#ifdef PIN_REQ_SPORT_1
65 { 78 {
66 .dma_rx_chan = CH_SPORT1_RX, 79 .dma_rx_chan = CH_SPORT1_RX,
67 .dma_tx_chan = CH_SPORT1_TX, 80 .dma_tx_chan = CH_SPORT1_TX,
68 .err_irq = IRQ_SPORT1_ERR, 81 .err_irq = IRQ_SPORT1_ERROR,
69 .regs = (struct sport_register *)SPORT1_TCR1, 82 .regs = (struct sport_register *)SPORT1_TCR1,
70 }, 83 },
84#endif
85#ifdef PIN_REQ_SPORT_2
71 { 86 {
72 .dma_rx_chan = CH_SPORT2_RX, 87 .dma_rx_chan = CH_SPORT2_RX,
73 .dma_tx_chan = CH_SPORT2_TX, 88 .dma_tx_chan = CH_SPORT2_TX,
74 .err_irq = IRQ_SPORT2_ERR, 89 .err_irq = IRQ_SPORT2_ERROR,
75 .regs = (struct sport_register *)SPORT2_TCR1, 90 .regs = (struct sport_register *)SPORT2_TCR1,
76 }, 91 },
92#endif
93#ifdef PIN_REQ_SPORT_3
77 { 94 {
78 .dma_rx_chan = CH_SPORT3_RX, 95 .dma_rx_chan = CH_SPORT3_RX,
79 .dma_tx_chan = CH_SPORT3_TX, 96 .dma_tx_chan = CH_SPORT3_TX,
80 .err_irq = IRQ_SPORT3_ERR, 97 .err_irq = IRQ_SPORT3_ERROR,
81 .regs = (struct sport_register *)SPORT3_TCR1, 98 .regs = (struct sport_register *)SPORT3_TCR1,
82 } 99 }
83};
84#else
85static struct sport_param sport_params[2] = {
86 {
87 .dma_rx_chan = CH_SPORT0_RX,
88 .dma_tx_chan = CH_SPORT0_TX,
89 .err_irq = IRQ_SPORT0_ERROR,
90 .regs = (struct sport_register *)SPORT0_TCR1,
91 },
92 {
93 .dma_rx_chan = CH_SPORT1_RX,
94 .dma_tx_chan = CH_SPORT1_TX,
95 .err_irq = IRQ_SPORT1_ERROR,
96 .regs = (struct sport_register *)SPORT1_TCR1,
97 }
98};
99#endif 100#endif
101};
100 102
101void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u32 *src, \ 103void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src,
102 size_t count) 104 size_t count, unsigned int chan_mask)
103{ 105{
104 while (count--) { 106 while (count--) {
105 dst->ac97_tag = TAG_VALID | TAG_PCM; 107 dst->ac97_tag = TAG_VALID;
106 (dst++)->ac97_pcm = *src++; 108 if (chan_mask & SP_FL) {
109 dst->ac97_pcm_r = *src++;
110 dst->ac97_tag |= TAG_PCM_RIGHT;
111 }
112 if (chan_mask & SP_FR) {
113 dst->ac97_pcm_l = *src++;
114 dst->ac97_tag |= TAG_PCM_LEFT;
115
116 }
117#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
118 if (chan_mask & SP_SR) {
119 dst->ac97_sl = *src++;
120 dst->ac97_tag |= TAG_PCM_SL;
121 }
122 if (chan_mask & SP_SL) {
123 dst->ac97_sr = *src++;
124 dst->ac97_tag |= TAG_PCM_SR;
125 }
126 if (chan_mask & SP_LFE) {
127 dst->ac97_lfe = *src++;
128 dst->ac97_tag |= TAG_PCM_LFE;
129 }
130 if (chan_mask & SP_FC) {
131 dst->ac97_center = *src++;
132 dst->ac97_tag |= TAG_PCM_CENTER;
133 }
134#endif
135 dst++;
107 } 136 }
108} 137}
109EXPORT_SYMBOL(bf5xx_pcm_to_ac97); 138EXPORT_SYMBOL(bf5xx_pcm_to_ac97);
110 139
111void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u32 *dst, \ 140void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u16 *dst,
112 size_t count) 141 size_t count)
113{ 142{
114 while (count--) 143 while (count--) {
115 *(dst++) = (src++)->ac97_pcm; 144 *(dst++) = src->ac97_pcm_l;
145 *(dst++) = src->ac97_pcm_r;
146 src++;
147 }
116} 148}
117EXPORT_SYMBOL(bf5xx_ac97_to_pcm); 149EXPORT_SYMBOL(bf5xx_ac97_to_pcm);
118 150
119static unsigned int sport_tx_curr_frag(struct sport_device *sport) 151static unsigned int sport_tx_curr_frag(struct sport_device *sport)
120{ 152{
121 return sport->tx_curr_frag = sport_curr_offset_tx(sport) / \ 153 return sport->tx_curr_frag = sport_curr_offset_tx(sport) /
122 sport->tx_fragsize; 154 sport->tx_fragsize;
123} 155}
124 156
@@ -130,7 +162,7 @@ static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data)
130 162
131 sport_incfrag(sport, &nextfrag, 1); 163 sport_incfrag(sport, &nextfrag, 1);
132 164
133 nextwrite = (struct ac97_frame *)(sport->tx_buf + \ 165 nextwrite = (struct ac97_frame *)(sport->tx_buf +
134 nextfrag * sport->tx_fragsize); 166 nextfrag * sport->tx_fragsize);
135 pr_debug("sport->tx_buf:%p, nextfrag:0x%x nextwrite:%p, cmd_count:%d\n", 167 pr_debug("sport->tx_buf:%p, nextfrag:0x%x nextwrite:%p, cmd_count:%d\n",
136 sport->tx_buf, nextfrag, nextwrite, cmd_count[nextfrag]); 168 sport->tx_buf, nextfrag, nextwrite, cmd_count[nextfrag]);
@@ -237,8 +269,7 @@ struct snd_ac97_bus_ops soc_ac97_ops = {
237EXPORT_SYMBOL_GPL(soc_ac97_ops); 269EXPORT_SYMBOL_GPL(soc_ac97_ops);
238 270
239#ifdef CONFIG_PM 271#ifdef CONFIG_PM
240static int bf5xx_ac97_suspend(struct platform_device *pdev, 272static int bf5xx_ac97_suspend(struct snd_soc_dai *dai)
241 struct snd_soc_dai *dai)
242{ 273{
243 struct sport_device *sport = 274 struct sport_device *sport =
244 (struct sport_device *)dai->private_data; 275 (struct sport_device *)dai->private_data;
@@ -253,8 +284,7 @@ static int bf5xx_ac97_suspend(struct platform_device *pdev,
253 return 0; 284 return 0;
254} 285}
255 286
256static int bf5xx_ac97_resume(struct platform_device *pdev, 287static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
257 struct snd_soc_dai *dai)
258{ 288{
259 int ret; 289 int ret;
260 struct sport_device *sport = 290 struct sport_device *sport =
@@ -297,20 +327,15 @@ static int bf5xx_ac97_resume(struct platform_device *pdev,
297static int bf5xx_ac97_probe(struct platform_device *pdev, 327static int bf5xx_ac97_probe(struct platform_device *pdev,
298 struct snd_soc_dai *dai) 328 struct snd_soc_dai *dai)
299{ 329{
300 int ret; 330 int ret = 0;
301#if defined(CONFIG_BF54x)
302 u16 sport_req[][7] = {PIN_REQ_SPORT_0, PIN_REQ_SPORT_1,
303 PIN_REQ_SPORT_2, PIN_REQ_SPORT_3};
304#else
305 u16 sport_req[][7] = {PIN_REQ_SPORT_0, PIN_REQ_SPORT_1};
306#endif
307 cmd_count = (int *)get_zeroed_page(GFP_KERNEL); 331 cmd_count = (int *)get_zeroed_page(GFP_KERNEL);
308 if (cmd_count == NULL) 332 if (cmd_count == NULL)
309 return -ENOMEM; 333 return -ENOMEM;
310 334
311 if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { 335 if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
312 pr_err("Requesting Peripherals failed\n"); 336 pr_err("Requesting Peripherals failed\n");
313 return -EFAULT; 337 ret = -EFAULT;
338 goto peripheral_err;
314 } 339 }
315 340
316#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET 341#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
@@ -318,54 +343,54 @@ static int bf5xx_ac97_probe(struct platform_device *pdev,
318 if (gpio_request(CONFIG_SND_BF5XX_RESET_GPIO_NUM, "SND_AD198x RESET")) { 343 if (gpio_request(CONFIG_SND_BF5XX_RESET_GPIO_NUM, "SND_AD198x RESET")) {
319 pr_err("Failed to request GPIO_%d for reset\n", 344 pr_err("Failed to request GPIO_%d for reset\n",
320 CONFIG_SND_BF5XX_RESET_GPIO_NUM); 345 CONFIG_SND_BF5XX_RESET_GPIO_NUM);
321 peripheral_free_list(&sport_req[sport_num][0]); 346 ret = -1;
322 return -1; 347 goto gpio_err;
323 } 348 }
324 gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1); 349 gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1);
325#endif 350#endif
326 sport_handle = sport_init(&sport_params[sport_num], 2, \ 351 sport_handle = sport_init(&sport_params[sport_num], 2, \
327 sizeof(struct ac97_frame), NULL); 352 sizeof(struct ac97_frame), NULL);
328 if (!sport_handle) { 353 if (!sport_handle) {
329 peripheral_free_list(&sport_req[sport_num][0]); 354 ret = -ENODEV;
330#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET 355 goto sport_err;
331 gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
332#endif
333 return -ENODEV;
334 } 356 }
335 /*SPORT works in TDM mode to simulate AC97 transfers*/ 357 /*SPORT works in TDM mode to simulate AC97 transfers*/
336 ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1); 358 ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1);
337 if (ret) { 359 if (ret) {
338 pr_err("SPORT is busy!\n"); 360 pr_err("SPORT is busy!\n");
339 kfree(sport_handle); 361 ret = -EBUSY;
340 peripheral_free_list(&sport_req[sport_num][0]); 362 goto sport_config_err;
341#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
342 gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
343#endif
344 return -EBUSY;
345 } 363 }
346 364
347 ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1)); 365 ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1));
348 if (ret) { 366 if (ret) {
349 pr_err("SPORT is busy!\n"); 367 pr_err("SPORT is busy!\n");
350 kfree(sport_handle); 368 ret = -EBUSY;
351 peripheral_free_list(&sport_req[sport_num][0]); 369 goto sport_config_err;
352#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
353 gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
354#endif
355 return -EBUSY;
356 } 370 }
357 371
358 ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1)); 372 ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1));
359 if (ret) { 373 if (ret) {
360 pr_err("SPORT is busy!\n"); 374 pr_err("SPORT is busy!\n");
361 kfree(sport_handle); 375 ret = -EBUSY;
362 peripheral_free_list(&sport_req[sport_num][0]); 376 goto sport_config_err;
363#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
364 gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
365#endif
366 return -EBUSY;
367 } 377 }
378
368 return 0; 379 return 0;
380
381sport_config_err:
382 kfree(sport_handle);
383sport_err:
384#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
385 gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
386#endif
387gpio_err:
388 peripheral_free_list(&sport_req[sport_num][0]);
389peripheral_err:
390 free_page((unsigned long)cmd_count);
391 cmd_count = NULL;
392
393 return ret;
369} 394}
370 395
371static void bf5xx_ac97_remove(struct platform_device *pdev, 396static void bf5xx_ac97_remove(struct platform_device *pdev,
@@ -373,6 +398,7 @@ static void bf5xx_ac97_remove(struct platform_device *pdev,
373{ 398{
374 free_page((unsigned long)cmd_count); 399 free_page((unsigned long)cmd_count);
375 cmd_count = NULL; 400 cmd_count = NULL;
401 peripheral_free_list(&sport_req[sport_num][0]);
376#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET 402#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
377 gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); 403 gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
378#endif 404#endif
@@ -381,7 +407,7 @@ static void bf5xx_ac97_remove(struct platform_device *pdev,
381struct snd_soc_dai bfin_ac97_dai = { 407struct snd_soc_dai bfin_ac97_dai = {
382 .name = "bf5xx-ac97", 408 .name = "bf5xx-ac97",
383 .id = 0, 409 .id = 0,
384 .type = SND_SOC_DAI_AC97, 410 .ac97_control = 1,
385 .probe = bf5xx_ac97_probe, 411 .probe = bf5xx_ac97_probe,
386 .remove = bf5xx_ac97_remove, 412 .remove = bf5xx_ac97_remove,
387 .suspend = bf5xx_ac97_suspend, 413 .suspend = bf5xx_ac97_suspend,
@@ -389,7 +415,11 @@ struct snd_soc_dai bfin_ac97_dai = {
389 .playback = { 415 .playback = {
390 .stream_name = "AC97 Playback", 416 .stream_name = "AC97 Playback",
391 .channels_min = 2, 417 .channels_min = 2,
418#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
419 .channels_max = 6,
420#else
392 .channels_max = 2, 421 .channels_max = 2,
422#endif
393 .rates = SNDRV_PCM_RATE_48000, 423 .rates = SNDRV_PCM_RATE_48000,
394 .formats = SNDRV_PCM_FMTBIT_S16_LE, }, 424 .formats = SNDRV_PCM_FMTBIT_S16_LE, },
395 .capture = { 425 .capture = {
@@ -401,6 +431,18 @@ struct snd_soc_dai bfin_ac97_dai = {
401}; 431};
402EXPORT_SYMBOL_GPL(bfin_ac97_dai); 432EXPORT_SYMBOL_GPL(bfin_ac97_dai);
403 433
434static int __init bfin_ac97_init(void)
435{
436 return snd_soc_register_dai(&bfin_ac97_dai);
437}
438module_init(bfin_ac97_init);
439
440static void __exit bfin_ac97_exit(void)
441{
442 snd_soc_unregister_dai(&bfin_ac97_dai);
443}
444module_exit(bfin_ac97_exit);
445
404MODULE_AUTHOR("Roy Huang"); 446MODULE_AUTHOR("Roy Huang");
405MODULE_DESCRIPTION("AC97 driver for ADI Blackfin"); 447MODULE_DESCRIPTION("AC97 driver for ADI Blackfin");
406MODULE_LICENSE("GPL"); 448MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/bf5xx-ac97.h b/sound/soc/blackfin/bf5xx-ac97.h
index 3f77cc558dc0..3f2a911fe0cb 100644
--- a/sound/soc/blackfin/bf5xx-ac97.h
+++ b/sound/soc/blackfin/bf5xx-ac97.h
@@ -16,21 +16,46 @@ struct ac97_frame {
16 u16 ac97_tag; /* slot 0 */ 16 u16 ac97_tag; /* slot 0 */
17 u16 ac97_addr; /* slot 1 */ 17 u16 ac97_addr; /* slot 1 */
18 u16 ac97_data; /* slot 2 */ 18 u16 ac97_data; /* slot 2 */
19 u32 ac97_pcm; /* slot 3 and 4: left and right pcm data */ 19 u16 ac97_pcm_l; /*slot 3:front left*/
20 u16 ac97_pcm_r; /*slot 4:front left*/
21#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
22 u16 ac97_mdm_l1;
23 u16 ac97_center; /*slot 6:center*/
24 u16 ac97_sl; /*slot 7:surround left*/
25 u16 ac97_sr; /*slot 8:surround right*/
26 u16 ac97_lfe; /*slot 9:lfe*/
27#endif
20} __attribute__ ((packed)); 28} __attribute__ ((packed));
21 29
30/* Speaker location */
31#define SP_FL 0x0001
32#define SP_FR 0x0010
33#define SP_FC 0x0002
34#define SP_LFE 0x0020
35#define SP_SL 0x0004
36#define SP_SR 0x0040
37
38#define SP_STEREO (SP_FL | SP_FR)
39#define SP_2DOT1 (SP_FL | SP_FR | SP_LFE)
40#define SP_QUAD (SP_FL | SP_FR | SP_SL | SP_SR)
41#define SP_5DOT1 (SP_FL | SP_FR | SP_FC | SP_LFE | SP_SL | SP_SR)
42
22#define TAG_VALID 0x8000 43#define TAG_VALID 0x8000
23#define TAG_CMD 0x6000 44#define TAG_CMD 0x6000
24#define TAG_PCM_LEFT 0x1000 45#define TAG_PCM_LEFT 0x1000
25#define TAG_PCM_RIGHT 0x0800 46#define TAG_PCM_RIGHT 0x0800
26#define TAG_PCM (TAG_PCM_LEFT | TAG_PCM_RIGHT) 47#define TAG_PCM_MDM_L1 0x0400
48#define TAG_PCM_CENTER 0x0200
49#define TAG_PCM_SL 0x0100
50#define TAG_PCM_SR 0x0080
51#define TAG_PCM_LFE 0x0040
27 52
28extern struct snd_soc_dai bfin_ac97_dai; 53extern struct snd_soc_dai bfin_ac97_dai;
29 54
30void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u32 *src, \ 55void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, \
31 size_t count); 56 size_t count, unsigned int chan_mask);
32 57
33void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u32 *dst, \ 58void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u16 *dst, \
34 size_t count); 59 size_t count);
35 60
36#endif 61#endif
diff --git a/sound/soc/blackfin/bf5xx-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c
index 124425d22320..d8f591273778 100644
--- a/sound/soc/blackfin/bf5xx-ad1980.c
+++ b/sound/soc/blackfin/bf5xx-ad1980.c
@@ -43,7 +43,7 @@
43#include "bf5xx-ac97-pcm.h" 43#include "bf5xx-ac97-pcm.h"
44#include "bf5xx-ac97.h" 44#include "bf5xx-ac97.h"
45 45
46static struct snd_soc_machine bf5xx_board; 46static struct snd_soc_card bf5xx_board;
47 47
48static int bf5xx_board_startup(struct snd_pcm_substream *substream) 48static int bf5xx_board_startup(struct snd_pcm_substream *substream)
49{ 49{
@@ -67,15 +67,15 @@ static struct snd_soc_dai_link bf5xx_board_dai = {
67 .ops = &bf5xx_board_ops, 67 .ops = &bf5xx_board_ops,
68}; 68};
69 69
70static struct snd_soc_machine bf5xx_board = { 70static struct snd_soc_card bf5xx_board = {
71 .name = "bf5xx-board", 71 .name = "bf5xx-board",
72 .platform = &bf5xx_ac97_soc_platform,
72 .dai_link = &bf5xx_board_dai, 73 .dai_link = &bf5xx_board_dai,
73 .num_links = 1, 74 .num_links = 1,
74}; 75};
75 76
76static struct snd_soc_device bf5xx_board_snd_devdata = { 77static struct snd_soc_device bf5xx_board_snd_devdata = {
77 .machine = &bf5xx_board, 78 .card = &bf5xx_board,
78 .platform = &bf5xx_ac97_soc_platform,
79 .codec_dev = &soc_codec_dev_ad1980, 79 .codec_dev = &soc_codec_dev_ad1980,
80}; 80};
81 81
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
index 622c9b909532..7f2a5e199075 100644
--- a/sound/soc/blackfin/bf5xx-ad73311.c
+++ b/sound/soc/blackfin/bf5xx-ad73311.c
@@ -65,7 +65,7 @@
65 65
66#define GPIO_SE CONFIG_SND_BFIN_AD73311_SE 66#define GPIO_SE CONFIG_SND_BFIN_AD73311_SE
67 67
68static struct snd_soc_machine bf5xx_ad73311; 68static struct snd_soc_card bf5xx_ad73311;
69 69
70static int snd_ad73311_startup(void) 70static int snd_ad73311_startup(void)
71{ 71{
@@ -168,7 +168,7 @@ static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream,
168 params_format(params)); 168 params_format(params));
169 169
170 /* set cpu DAI configuration */ 170 /* set cpu DAI configuration */
171 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | 171 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
172 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 172 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
173 if (ret < 0) 173 if (ret < 0)
174 return ret; 174 return ret;
@@ -190,16 +190,16 @@ static struct snd_soc_dai_link bf5xx_ad73311_dai = {
190 .ops = &bf5xx_ad73311_ops, 190 .ops = &bf5xx_ad73311_ops,
191}; 191};
192 192
193static struct snd_soc_machine bf5xx_ad73311 = { 193static struct snd_soc_card bf5xx_ad73311 = {
194 .name = "bf5xx_ad73311", 194 .name = "bf5xx_ad73311",
195 .platform = &bf5xx_i2s_soc_platform,
195 .probe = bf5xx_probe, 196 .probe = bf5xx_probe,
196 .dai_link = &bf5xx_ad73311_dai, 197 .dai_link = &bf5xx_ad73311_dai,
197 .num_links = 1, 198 .num_links = 1,
198}; 199};
199 200
200static struct snd_soc_device bf5xx_ad73311_snd_devdata = { 201static struct snd_soc_device bf5xx_ad73311_snd_devdata = {
201 .machine = &bf5xx_ad73311, 202 .card = &bf5xx_ad73311,
202 .platform = &bf5xx_i2s_soc_platform,
203 .codec_dev = &soc_codec_dev_ad73311, 203 .codec_dev = &soc_codec_dev_ad73311,
204}; 204};
205 205
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index 61fccf925192..53d290b3ea47 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -283,6 +283,18 @@ struct snd_soc_platform bf5xx_i2s_soc_platform = {
283}; 283};
284EXPORT_SYMBOL_GPL(bf5xx_i2s_soc_platform); 284EXPORT_SYMBOL_GPL(bf5xx_i2s_soc_platform);
285 285
286static int __init bfin_i2s_init(void)
287{
288 return snd_soc_register_platform(&bf5xx_i2s_soc_platform);
289}
290module_init(bfin_i2s_init);
291
292static void __exit bfin_i2s_exit(void)
293{
294 snd_soc_unregister_platform(&bf5xx_i2s_soc_platform);
295}
296module_exit(bfin_i2s_exit);
297
286MODULE_AUTHOR("Cliff Cai"); 298MODULE_AUTHOR("Cliff Cai");
287MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module"); 299MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module");
288MODULE_LICENSE("GPL"); 300MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index e020c160ee44..d1d95d2393fe 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -132,7 +132,8 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
132 return ret; 132 return ret;
133} 133}
134 134
135static int bf5xx_i2s_startup(struct snd_pcm_substream *substream) 135static int bf5xx_i2s_startup(struct snd_pcm_substream *substream,
136 struct snd_soc_dai *dai)
136{ 137{
137 pr_debug("%s enter\n", __func__); 138 pr_debug("%s enter\n", __func__);
138 139
@@ -142,7 +143,8 @@ static int bf5xx_i2s_startup(struct snd_pcm_substream *substream)
142} 143}
143 144
144static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, 145static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
145 struct snd_pcm_hw_params *params) 146 struct snd_pcm_hw_params *params,
147 struct snd_soc_dai *dai)
146{ 148{
147 int ret = 0; 149 int ret = 0;
148 150
@@ -193,7 +195,8 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
193 return 0; 195 return 0;
194} 196}
195 197
196static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream) 198static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream,
199 struct snd_soc_dai *dai)
197{ 200{
198 pr_debug("%s enter\n", __func__); 201 pr_debug("%s enter\n", __func__);
199 bf5xx_i2s.counter--; 202 bf5xx_i2s.counter--;
@@ -219,16 +222,14 @@ static int bf5xx_i2s_probe(struct platform_device *pdev,
219 return 0; 222 return 0;
220} 223}
221 224
222static void bf5xx_i2s_remove(struct platform_device *pdev, 225static void bf5xx_i2s_remove(struct snd_soc_dai *dai)
223 struct snd_soc_dai *dai)
224{ 226{
225 pr_debug("%s enter\n", __func__); 227 pr_debug("%s enter\n", __func__);
226 peripheral_free_list(&sport_req[sport_num][0]); 228 peripheral_free_list(&sport_req[sport_num][0]);
227} 229}
228 230
229#ifdef CONFIG_PM 231#ifdef CONFIG_PM
230static int bf5xx_i2s_suspend(struct platform_device *dev, 232static int bf5xx_i2s_suspend(struct snd_soc_dai *dai)
231 struct snd_soc_dai *dai)
232{ 233{
233 struct sport_device *sport = 234 struct sport_device *sport =
234 (struct sport_device *)dai->private_data; 235 (struct sport_device *)dai->private_data;
@@ -289,7 +290,6 @@ static int bf5xx_i2s_resume(struct platform_device *pdev,
289struct snd_soc_dai bf5xx_i2s_dai = { 290struct snd_soc_dai bf5xx_i2s_dai = {
290 .name = "bf5xx-i2s", 291 .name = "bf5xx-i2s",
291 .id = 0, 292 .id = 0,
292 .type = SND_SOC_DAI_I2S,
293 .probe = bf5xx_i2s_probe, 293 .probe = bf5xx_i2s_probe,
294 .remove = bf5xx_i2s_remove, 294 .remove = bf5xx_i2s_remove,
295 .suspend = bf5xx_i2s_suspend, 295 .suspend = bf5xx_i2s_suspend,
@@ -307,13 +307,24 @@ struct snd_soc_dai bf5xx_i2s_dai = {
307 .ops = { 307 .ops = {
308 .startup = bf5xx_i2s_startup, 308 .startup = bf5xx_i2s_startup,
309 .shutdown = bf5xx_i2s_shutdown, 309 .shutdown = bf5xx_i2s_shutdown,
310 .hw_params = bf5xx_i2s_hw_params,}, 310 .hw_params = bf5xx_i2s_hw_params,
311 .dai_ops = {
312 .set_fmt = bf5xx_i2s_set_dai_fmt, 311 .set_fmt = bf5xx_i2s_set_dai_fmt,
313 }, 312 },
314}; 313};
315EXPORT_SYMBOL_GPL(bf5xx_i2s_dai); 314EXPORT_SYMBOL_GPL(bf5xx_i2s_dai);
316 315
316static int __init bfin_i2s_init(void)
317{
318 return snd_soc_register_dai(&bf5xx_i2s_dai);
319}
320module_init(bfin_i2s_init);
321
322static void __exit bfin_i2s_exit(void)
323{
324 snd_soc_unregister_dai(&bf5xx_i2s_dai);
325}
326module_exit(bfin_i2s_exit);
327
317/* Module information */ 328/* Module information */
318MODULE_AUTHOR("Cliff Cai"); 329MODULE_AUTHOR("Cliff Cai");
319MODULE_DESCRIPTION("I2S driver for ADI Blackfin"); 330MODULE_DESCRIPTION("I2S driver for ADI Blackfin");
diff --git a/sound/soc/blackfin/bf5xx-sport.h b/sound/soc/blackfin/bf5xx-sport.h
index fcadcc081f7f..2e63dea73e9c 100644
--- a/sound/soc/blackfin/bf5xx-sport.h
+++ b/sound/soc/blackfin/bf5xx-sport.h
@@ -116,7 +116,7 @@ struct sport_device {
116 void *err_data; 116 void *err_data;
117 unsigned char *tx_dma_buf; 117 unsigned char *tx_dma_buf;
118 unsigned char *rx_dma_buf; 118 unsigned char *rx_dma_buf;
119#ifdef CONFIG_SND_MMAP_SUPPORT 119#ifdef CONFIG_SND_BF5XX_MMAP_SUPPORT
120 dma_addr_t tx_dma_phy; 120 dma_addr_t tx_dma_phy;
121 dma_addr_t rx_dma_phy; 121 dma_addr_t rx_dma_phy;
122 int tx_pos;/*pcm sample count*/ 122 int tx_pos;/*pcm sample count*/
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c
index e15f67fd7769..bc0cdded7116 100644
--- a/sound/soc/blackfin/bf5xx-ssm2602.c
+++ b/sound/soc/blackfin/bf5xx-ssm2602.c
@@ -44,7 +44,7 @@
44#include "bf5xx-i2s-pcm.h" 44#include "bf5xx-i2s-pcm.h"
45#include "bf5xx-i2s.h" 45#include "bf5xx-i2s.h"
46 46
47static struct snd_soc_machine bf5xx_ssm2602; 47static struct snd_soc_card bf5xx_ssm2602;
48 48
49static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream) 49static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream)
50{ 50{
@@ -92,17 +92,17 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream,
92 */ 92 */
93 93
94 /* set codec DAI configuration */ 94 /* set codec DAI configuration */
95 ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 95 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
96 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 96 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
97 if (ret < 0) 97 if (ret < 0)
98 return ret; 98 return ret;
99 /* set cpu DAI configuration */ 99 /* set cpu DAI configuration */
100 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | 100 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
101 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); 101 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
102 if (ret < 0) 102 if (ret < 0)
103 return ret; 103 return ret;
104 104
105 ret = codec_dai->dai_ops.set_sysclk(codec_dai, SSM2602_SYSCLK, clk, 105 ret = snd_soc_dai_set_sysclk(codec_dai, SSM2602_SYSCLK, clk,
106 SND_SOC_CLOCK_IN); 106 SND_SOC_CLOCK_IN);
107 if (ret < 0) 107 if (ret < 0)
108 return ret; 108 return ret;
@@ -135,15 +135,15 @@ static struct ssm2602_setup_data bf5xx_ssm2602_setup = {
135 .i2c_address = 0x1b, 135 .i2c_address = 0x1b,
136}; 136};
137 137
138static struct snd_soc_machine bf5xx_ssm2602 = { 138static struct snd_soc_card bf5xx_ssm2602 = {
139 .name = "bf5xx_ssm2602", 139 .name = "bf5xx_ssm2602",
140 .platform = &bf5xx_i2s_soc_platform,
140 .dai_link = &bf5xx_ssm2602_dai, 141 .dai_link = &bf5xx_ssm2602_dai,
141 .num_links = 1, 142 .num_links = 1,
142}; 143};
143 144
144static struct snd_soc_device bf5xx_ssm2602_snd_devdata = { 145static struct snd_soc_device bf5xx_ssm2602_snd_devdata = {
145 .machine = &bf5xx_ssm2602, 146 .card = &bf5xx_ssm2602,
146 .platform = &bf5xx_i2s_soc_platform,
147 .codec_dev = &soc_codec_dev_ssm2602, 147 .codec_dev = &soc_codec_dev_ssm2602,
148 .codec_data = &bf5xx_ssm2602_setup, 148 .codec_data = &bf5xx_ssm2602_setup,
149}; 149};
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 38a0e3b620a7..c41289b5f586 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -1,31 +1,40 @@
1config SND_SOC_ALL_CODECS 1config SND_SOC_ALL_CODECS
2 tristate "Build all ASoC CODEC drivers" 2 tristate "Build all ASoC CODEC drivers"
3 depends on I2C 3 select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
4 select SPI 4 select SND_SOC_AD1980 if SND_SOC_AC97_BUS
5 select SPI_MASTER 5 select SND_SOC_AD73311 if I2C
6 select SND_SOC_AD73311 6 select SND_SOC_AK4535 if I2C
7 select SND_SOC_AK4535 7 select SND_SOC_CS4270 if I2C
8 select SND_SOC_CS4270 8 select SND_SOC_PCM3008
9 select SND_SOC_SSM2602 9 select SND_SOC_SSM2602 if I2C
10 select SND_SOC_TLV320AIC23 10 select SND_SOC_TLV320AIC23 if I2C
11 select SND_SOC_TLV320AIC26 11 select SND_SOC_TLV320AIC26 if SPI_MASTER
12 select SND_SOC_TLV320AIC3X 12 select SND_SOC_TLV320AIC3X if I2C
13 select SND_SOC_UDA1380 13 select SND_SOC_TWL4030 if TWL4030_CORE
14 select SND_SOC_WM8510 14 select SND_SOC_UDA134X
15 select SND_SOC_WM8580 15 select SND_SOC_UDA1380 if I2C
16 select SND_SOC_WM8731 16 select SND_SOC_WM8350 if MFD_WM8350
17 select SND_SOC_WM8750 17 select SND_SOC_WM8510 if (I2C || SPI_MASTER)
18 select SND_SOC_WM8753 18 select SND_SOC_WM8580 if I2C
19 select SND_SOC_WM8900 19 select SND_SOC_WM8728 if (I2C || SPI_MASTER)
20 select SND_SOC_WM8903 20 select SND_SOC_WM8731 if (I2C || SPI_MASTER)
21 select SND_SOC_WM8971 21 select SND_SOC_WM8750 if (I2C || SPI_MASTER)
22 select SND_SOC_WM8990 22 select SND_SOC_WM8753 if (I2C || SPI_MASTER)
23 select SND_SOC_WM8900 if I2C
24 select SND_SOC_WM8903 if I2C
25 select SND_SOC_WM8971 if I2C
26 select SND_SOC_WM8990 if I2C
27 select SND_SOC_WM9712 if SND_SOC_AC97_BUS
28 select SND_SOC_WM9713 if SND_SOC_AC97_BUS
23 help 29 help
24 Normally ASoC codec drivers are only built if a machine driver which 30 Normally ASoC codec drivers are only built if a machine driver which
25 uses them is also built since they are only usable with a machine 31 uses them is also built since they are only usable with a machine
26 driver. Selecting this option will allow these drivers to be built 32 driver. Selecting this option will allow these drivers to be built
27 without an explicit machine driver for test and development purposes. 33 without an explicit machine driver for test and development purposes.
28 34
35 Support for the bus types used to access the codecs to be built must
36 be selected separately.
37
29 If unsure select "N". 38 If unsure select "N".
30 39
31 40
@@ -60,6 +69,12 @@ config SND_SOC_CS4270_VD33_ERRATA
60 bool 69 bool
61 depends on SND_SOC_CS4270 70 depends on SND_SOC_CS4270
62 71
72config SND_SOC_L3
73 tristate
74
75config SND_SOC_PCM3008
76 tristate
77
63config SND_SOC_SSM2602 78config SND_SOC_SSM2602
64 tristate 79 tristate
65 80
@@ -75,15 +90,29 @@ config SND_SOC_TLV320AIC3X
75 tristate 90 tristate
76 depends on I2C 91 depends on I2C
77 92
93config SND_SOC_TWL4030
94 tristate
95 depends on TWL4030_CORE
96
97config SND_SOC_UDA134X
98 tristate
99 select SND_SOC_L3
100
78config SND_SOC_UDA1380 101config SND_SOC_UDA1380
79 tristate 102 tristate
80 103
104config SND_SOC_WM8350
105 tristate
106
81config SND_SOC_WM8510 107config SND_SOC_WM8510
82 tristate 108 tristate
83 109
84config SND_SOC_WM8580 110config SND_SOC_WM8580
85 tristate 111 tristate
86 112
113config SND_SOC_WM8728
114 tristate
115
87config SND_SOC_WM8731 116config SND_SOC_WM8731
88 tristate 117 tristate
89 118
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 90f0a585fc70..c4ddc9aa2bbd 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -3,13 +3,19 @@ snd-soc-ad1980-objs := ad1980.o
3snd-soc-ad73311-objs := ad73311.o 3snd-soc-ad73311-objs := ad73311.o
4snd-soc-ak4535-objs := ak4535.o 4snd-soc-ak4535-objs := ak4535.o
5snd-soc-cs4270-objs := cs4270.o 5snd-soc-cs4270-objs := cs4270.o
6snd-soc-l3-objs := l3.o
7snd-soc-pcm3008-objs := pcm3008.o
6snd-soc-ssm2602-objs := ssm2602.o 8snd-soc-ssm2602-objs := ssm2602.o
7snd-soc-tlv320aic23-objs := tlv320aic23.o 9snd-soc-tlv320aic23-objs := tlv320aic23.o
8snd-soc-tlv320aic26-objs := tlv320aic26.o 10snd-soc-tlv320aic26-objs := tlv320aic26.o
9snd-soc-tlv320aic3x-objs := tlv320aic3x.o 11snd-soc-tlv320aic3x-objs := tlv320aic3x.o
12snd-soc-twl4030-objs := twl4030.o
13snd-soc-uda134x-objs := uda134x.o
10snd-soc-uda1380-objs := uda1380.o 14snd-soc-uda1380-objs := uda1380.o
15snd-soc-wm8350-objs := wm8350.o
11snd-soc-wm8510-objs := wm8510.o 16snd-soc-wm8510-objs := wm8510.o
12snd-soc-wm8580-objs := wm8580.o 17snd-soc-wm8580-objs := wm8580.o
18snd-soc-wm8728-objs := wm8728.o
13snd-soc-wm8731-objs := wm8731.o 19snd-soc-wm8731-objs := wm8731.o
14snd-soc-wm8750-objs := wm8750.o 20snd-soc-wm8750-objs := wm8750.o
15snd-soc-wm8753-objs := wm8753.o 21snd-soc-wm8753-objs := wm8753.o
@@ -25,13 +31,19 @@ obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
25obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o 31obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
26obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o 32obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
27obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o 33obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
34obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
35obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
28obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o 36obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
29obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o 37obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
30obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o 38obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
31obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o 39obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
40obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
41obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
32obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o 42obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
43obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o
33obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o 44obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o
34obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o 45obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o
46obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o
35obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o 47obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
36obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o 48obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
37obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o 49obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index bd1ebdc6c86c..fb53e6511af2 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -24,7 +24,8 @@
24 24
25#define AC97_VERSION "0.6" 25#define AC97_VERSION "0.6"
26 26
27static int ac97_prepare(struct snd_pcm_substream *substream) 27static int ac97_prepare(struct snd_pcm_substream *substream,
28 struct snd_soc_dai *dai)
28{ 29{
29 struct snd_pcm_runtime *runtime = substream->runtime; 30 struct snd_pcm_runtime *runtime = substream->runtime;
30 struct snd_soc_pcm_runtime *rtd = substream->private_data; 31 struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -42,7 +43,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream)
42 43
43struct snd_soc_dai ac97_dai = { 44struct snd_soc_dai ac97_dai = {
44 .name = "AC97 HiFi", 45 .name = "AC97 HiFi",
45 .type = SND_SOC_DAI_AC97, 46 .ac97_control = 1,
46 .playback = { 47 .playback = {
47 .stream_name = "AC97 Playback", 48 .stream_name = "AC97 Playback",
48 .channels_min = 1, 49 .channels_min = 1,
@@ -113,7 +114,7 @@ static int ac97_soc_probe(struct platform_device *pdev)
113 if (ret < 0) 114 if (ret < 0)
114 goto bus_err; 115 goto bus_err;
115 116
116 ret = snd_soc_register_card(socdev); 117 ret = snd_soc_init_card(socdev);
117 if (ret < 0) 118 if (ret < 0)
118 goto bus_err; 119 goto bus_err;
119 return 0; 120 return 0;
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 1397b8e06c0b..73fdbb4d4a3d 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -85,6 +85,9 @@ SOC_DOUBLE("Line HP Swap Switch", AC97_AD_MISC, 10, 5, 1, 0),
85SOC_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1), 85SOC_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1),
86SOC_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1), 86SOC_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1),
87 87
88SOC_DOUBLE("Center/LFE Playback Volume", AC97_CENTER_LFE_MASTER, 8, 0, 31, 1),
89SOC_DOUBLE("Center/LFE Playback Switch", AC97_CENTER_LFE_MASTER, 15, 7, 1, 1),
90
88SOC_ENUM("Capture Source", ad1980_cap_src), 91SOC_ENUM("Capture Source", ad1980_cap_src),
89 92
90SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0), 93SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0),
@@ -142,10 +145,11 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
142 145
143struct snd_soc_dai ad1980_dai = { 146struct snd_soc_dai ad1980_dai = {
144 .name = "AC97", 147 .name = "AC97",
148 .ac97_control = 1,
145 .playback = { 149 .playback = {
146 .stream_name = "Playback", 150 .stream_name = "Playback",
147 .channels_min = 2, 151 .channels_min = 2,
148 .channels_max = 2, 152 .channels_max = 6,
149 .rates = SNDRV_PCM_RATE_48000, 153 .rates = SNDRV_PCM_RATE_48000,
150 .formats = SNDRV_PCM_FMTBIT_S16_LE, }, 154 .formats = SNDRV_PCM_FMTBIT_S16_LE, },
151 .capture = { 155 .capture = {
@@ -192,6 +196,7 @@ static int ad1980_soc_probe(struct platform_device *pdev)
192 struct snd_soc_codec *codec; 196 struct snd_soc_codec *codec;
193 int ret = 0; 197 int ret = 0;
194 u16 vendor_id2; 198 u16 vendor_id2;
199 u16 ext_status;
195 200
196 printk(KERN_INFO "AD1980 SoC Audio Codec\n"); 201 printk(KERN_INFO "AD1980 SoC Audio Codec\n");
197 202
@@ -234,7 +239,7 @@ static int ad1980_soc_probe(struct platform_device *pdev)
234 239
235 ret = ad1980_reset(codec, 0); 240 ret = ad1980_reset(codec, 0);
236 if (ret < 0) { 241 if (ret < 0) {
237 printk(KERN_ERR "AC97 link error\n"); 242 printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n");
238 goto reset_err; 243 goto reset_err;
239 } 244 }
240 245
@@ -253,12 +258,19 @@ static int ad1980_soc_probe(struct platform_device *pdev)
253 "supported\n"); 258 "supported\n");
254 } 259 }
255 260
256 ac97_write(codec, AC97_MASTER, 0x0000); /* unmute line out volume */ 261 /* unmute captures and playbacks volume */
257 ac97_write(codec, AC97_PCM, 0x0000); /* unmute PCM out volume */ 262 ac97_write(codec, AC97_MASTER, 0x0000);
258 ac97_write(codec, AC97_REC_GAIN, 0x0000);/* unmute record volume */ 263 ac97_write(codec, AC97_PCM, 0x0000);
264 ac97_write(codec, AC97_REC_GAIN, 0x0000);
265 ac97_write(codec, AC97_CENTER_LFE_MASTER, 0x0000);
266 ac97_write(codec, AC97_SURROUND_MASTER, 0x0000);
267
268 /*power on LFE/CENTER/Surround DACs*/
269 ext_status = ac97_read(codec, AC97_EXTENDED_STATUS);
270 ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800);
259 271
260 ad1980_add_controls(codec); 272 ad1980_add_controls(codec);
261 ret = snd_soc_register_card(socdev); 273 ret = snd_soc_init_card(socdev);
262 if (ret < 0) { 274 if (ret < 0) {
263 printk(KERN_ERR "ad1980: failed to register card\n"); 275 printk(KERN_ERR "ad1980: failed to register card\n");
264 goto reset_err; 276 goto reset_err;
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
index 37af8607b00a..b09289a1e55a 100644
--- a/sound/soc/codecs/ad73311.c
+++ b/sound/soc/codecs/ad73311.c
@@ -8,14 +8,10 @@
8 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your 9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. 10 * option) any later version.
11 *
12 * Revision history
13 * 25th Sep 2008 Initial version.
14 */ 11 */
15 12
16#include <linux/init.h> 13#include <linux/init.h>
17#include <linux/module.h> 14#include <linux/module.h>
18#include <linux/version.h>
19#include <linux/kernel.h> 15#include <linux/kernel.h>
20#include <linux/device.h> 16#include <linux/device.h>
21#include <sound/core.h> 17#include <sound/core.h>
@@ -68,7 +64,7 @@ static int ad73311_soc_probe(struct platform_device *pdev)
68 goto pcm_err; 64 goto pcm_err;
69 } 65 }
70 66
71 ret = snd_soc_register_card(socdev); 67 ret = snd_soc_init_card(socdev);
72 if (ret < 0) { 68 if (ret < 0) {
73 printk(KERN_ERR "ad73311: failed to register card\n"); 69 printk(KERN_ERR "ad73311: failed to register card\n");
74 goto register_err; 70 goto register_err;
@@ -102,6 +98,18 @@ struct snd_soc_codec_device soc_codec_dev_ad73311 = {
102}; 98};
103EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311); 99EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311);
104 100
101static int __init ad73311_init(void)
102{
103 return snd_soc_register_dai(&ad73311_dai);
104}
105module_init(ad73311_init);
106
107static void __exit ad73311_exit(void)
108{
109 snd_soc_unregister_dai(&ad73311_dai);
110}
111module_exit(ad73311_exit);
112
105MODULE_DESCRIPTION("ASoC ad73311 driver"); 113MODULE_DESCRIPTION("ASoC ad73311 driver");
106MODULE_AUTHOR("Cliff Cai "); 114MODULE_AUTHOR("Cliff Cai ");
107MODULE_LICENSE("GPL"); 115MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 2a89b5888e11..81300d8d42ca 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -339,7 +339,8 @@ static int ak4535_set_dai_sysclk(struct snd_soc_dai *codec_dai,
339} 339}
340 340
341static int ak4535_hw_params(struct snd_pcm_substream *substream, 341static int ak4535_hw_params(struct snd_pcm_substream *substream,
342 struct snd_pcm_hw_params *params) 342 struct snd_pcm_hw_params *params,
343 struct snd_soc_dai *dai)
343{ 344{
344 struct snd_soc_pcm_runtime *rtd = substream->private_data; 345 struct snd_soc_pcm_runtime *rtd = substream->private_data;
345 struct snd_soc_device *socdev = rtd->socdev; 346 struct snd_soc_device *socdev = rtd->socdev;
@@ -451,8 +452,6 @@ struct snd_soc_dai ak4535_dai = {
451 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 452 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
452 .ops = { 453 .ops = {
453 .hw_params = ak4535_hw_params, 454 .hw_params = ak4535_hw_params,
454 },
455 .dai_ops = {
456 .set_fmt = ak4535_set_dai_fmt, 455 .set_fmt = ak4535_set_dai_fmt,
457 .digital_mute = ak4535_mute, 456 .digital_mute = ak4535_mute,
458 .set_sysclk = ak4535_set_dai_sysclk, 457 .set_sysclk = ak4535_set_dai_sysclk,
@@ -513,7 +512,7 @@ static int ak4535_init(struct snd_soc_device *socdev)
513 512
514 ak4535_add_controls(codec); 513 ak4535_add_controls(codec);
515 ak4535_add_widgets(codec); 514 ak4535_add_widgets(codec);
516 ret = snd_soc_register_card(socdev); 515 ret = snd_soc_init_card(socdev);
517 if (ret < 0) { 516 if (ret < 0) {
518 printk(KERN_ERR "ak4535: failed to register card\n"); 517 printk(KERN_ERR "ak4535: failed to register card\n");
519 goto card_err; 518 goto card_err;
@@ -689,6 +688,18 @@ struct snd_soc_codec_device soc_codec_dev_ak4535 = {
689}; 688};
690EXPORT_SYMBOL_GPL(soc_codec_dev_ak4535); 689EXPORT_SYMBOL_GPL(soc_codec_dev_ak4535);
691 690
691static int __init ak4535_modinit(void)
692{
693 return snd_soc_register_dai(&ak4535_dai);
694}
695module_init(ak4535_modinit);
696
697static void __exit ak4535_exit(void)
698{
699 snd_soc_unregister_dai(&ak4535_dai);
700}
701module_exit(ak4535_exit);
702
692MODULE_DESCRIPTION("Soc AK4535 driver"); 703MODULE_DESCRIPTION("Soc AK4535 driver");
693MODULE_AUTHOR("Richard Purdie"); 704MODULE_AUTHOR("Richard Purdie");
694MODULE_LICENSE("GPL"); 705MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 0bbd94501d7e..f1aa0c34421c 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -360,13 +360,14 @@ static int cs4270_i2c_write(struct snd_soc_codec *codec, unsigned int reg,
360/* 360/*
361 * Program the CS4270 with the given hardware parameters. 361 * Program the CS4270 with the given hardware parameters.
362 * 362 *
363 * The .dai_ops functions are used to provide board-specific data, like 363 * The .ops functions are used to provide board-specific data, like
364 * input frequencies, to this driver. This function takes that information, 364 * input frequencies, to this driver. This function takes that information,
365 * combines it with the hardware parameters provided, and programs the 365 * combines it with the hardware parameters provided, and programs the
366 * hardware accordingly. 366 * hardware accordingly.
367 */ 367 */
368static int cs4270_hw_params(struct snd_pcm_substream *substream, 368static int cs4270_hw_params(struct snd_pcm_substream *substream,
369 struct snd_pcm_hw_params *params) 369 struct snd_pcm_hw_params *params,
370 struct snd_soc_dai *dai)
370{ 371{
371 struct snd_soc_pcm_runtime *rtd = substream->private_data; 372 struct snd_soc_pcm_runtime *rtd = substream->private_data;
372 struct snd_soc_device *socdev = rtd->socdev; 373 struct snd_soc_device *socdev = rtd->socdev;
@@ -450,6 +451,19 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
450 return ret; 451 return ret;
451 } 452 }
452 453
454 /* Disable automatic volume control. It's enabled by default, and
455 * it causes volume change commands to be delayed, sometimes until
456 * after playback has started.
457 */
458
459 reg = cs4270_read_reg_cache(codec, CS4270_TRANS);
460 reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO);
461 ret = cs4270_i2c_write(codec, CS4270_TRANS, reg);
462 if (ret < 0) {
463 printk(KERN_ERR "I2C write failed\n");
464 return ret;
465 }
466
453 /* Thaw and power-up the codec */ 467 /* Thaw and power-up the codec */
454 468
455 ret = snd_soc_write(codec, CS4270_PWRCTL, 0); 469 ret = snd_soc_write(codec, CS4270_PWRCTL, 0);
@@ -697,10 +711,10 @@ static int cs4270_probe(struct platform_device *pdev)
697 if (codec->control_data) { 711 if (codec->control_data) {
698 /* Initialize codec ops */ 712 /* Initialize codec ops */
699 cs4270_dai.ops.hw_params = cs4270_hw_params; 713 cs4270_dai.ops.hw_params = cs4270_hw_params;
700 cs4270_dai.dai_ops.set_sysclk = cs4270_set_dai_sysclk; 714 cs4270_dai.ops.set_sysclk = cs4270_set_dai_sysclk;
701 cs4270_dai.dai_ops.set_fmt = cs4270_set_dai_fmt; 715 cs4270_dai.ops.set_fmt = cs4270_set_dai_fmt;
702#ifdef CONFIG_SND_SOC_CS4270_HWMUTE 716#ifdef CONFIG_SND_SOC_CS4270_HWMUTE
703 cs4270_dai.dai_ops.digital_mute = cs4270_mute; 717 cs4270_dai.ops.digital_mute = cs4270_mute;
704#endif 718#endif
705 } else 719 } else
706 printk(KERN_INFO "cs4270: no I2C device found, " 720 printk(KERN_INFO "cs4270: no I2C device found, "
@@ -709,7 +723,7 @@ static int cs4270_probe(struct platform_device *pdev)
709 printk(KERN_INFO "cs4270: I2C disabled, using stand-alone mode\n"); 723 printk(KERN_INFO "cs4270: I2C disabled, using stand-alone mode\n");
710#endif 724#endif
711 725
712 ret = snd_soc_register_card(socdev); 726 ret = snd_soc_init_card(socdev);
713 if (ret < 0) { 727 if (ret < 0) {
714 printk(KERN_ERR "cs4270: failed to register card\n"); 728 printk(KERN_ERR "cs4270: failed to register card\n");
715 goto error_del_driver; 729 goto error_del_driver;
@@ -760,6 +774,18 @@ struct snd_soc_codec_device soc_codec_device_cs4270 = {
760}; 774};
761EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); 775EXPORT_SYMBOL_GPL(soc_codec_device_cs4270);
762 776
777static int __init cs4270_init(void)
778{
779 return snd_soc_register_dai(&cs4270_dai);
780}
781module_init(cs4270_init);
782
783static void __exit cs4270_exit(void)
784{
785 snd_soc_unregister_dai(&cs4270_dai);
786}
787module_exit(cs4270_exit);
788
763MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); 789MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
764MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver"); 790MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver");
765MODULE_LICENSE("GPL"); 791MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/l3.c b/sound/soc/codecs/l3.c
new file mode 100644
index 000000000000..5353af58862c
--- /dev/null
+++ b/sound/soc/codecs/l3.c
@@ -0,0 +1,91 @@
1/*
2 * L3 code
3 *
4 * Copyright (C) 2008, Christian Pellegrin <chripell@evolware.org>
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 * based on:
12 *
13 * L3 bus algorithm module.
14 *
15 * Copyright (C) 2001 Russell King, All Rights Reserved.
16 *
17 *
18 */
19
20#include <linux/module.h>
21#include <linux/kernel.h>
22#include <linux/delay.h>
23
24#include <sound/l3.h>
25
26/*
27 * Send one byte of data to the chip. Data is latched into the chip on
28 * the rising edge of the clock.
29 */
30static void sendbyte(struct l3_pins *adap, unsigned int byte)
31{
32 int i;
33
34 for (i = 0; i < 8; i++) {
35 adap->setclk(0);
36 udelay(adap->data_hold);
37 adap->setdat(byte & 1);
38 udelay(adap->data_setup);
39 adap->setclk(1);
40 udelay(adap->clock_high);
41 byte >>= 1;
42 }
43}
44
45/*
46 * Send a set of bytes to the chip. We need to pulse the MODE line
47 * between each byte, but never at the start nor at the end of the
48 * transfer.
49 */
50static void sendbytes(struct l3_pins *adap, const u8 *buf,
51 int len)
52{
53 int i;
54
55 for (i = 0; i < len; i++) {
56 if (i) {
57 udelay(adap->mode_hold);
58 adap->setmode(0);
59 udelay(adap->mode);
60 }
61 adap->setmode(1);
62 udelay(adap->mode_setup);
63 sendbyte(adap, buf[i]);
64 }
65}
66
67int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len)
68{
69 adap->setclk(1);
70 adap->setdat(1);
71 adap->setmode(1);
72 udelay(adap->mode);
73
74 adap->setmode(0);
75 udelay(adap->mode_setup);
76 sendbyte(adap, addr);
77 udelay(adap->mode_hold);
78
79 sendbytes(adap, data, len);
80
81 adap->setclk(1);
82 adap->setdat(1);
83 adap->setmode(0);
84
85 return len;
86}
87EXPORT_SYMBOL_GPL(l3_write);
88
89MODULE_DESCRIPTION("L3 bit-banging driver");
90MODULE_AUTHOR("Christian Pellegrin <chripell@evolware.org>");
91MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c
new file mode 100644
index 000000000000..9a3e67e5319c
--- /dev/null
+++ b/sound/soc/codecs/pcm3008.c
@@ -0,0 +1,212 @@
1/*
2 * ALSA Soc PCM3008 codec support
3 *
4 * Author: Hugo Villeneuve
5 * Copyright (C) 2008 Lyrtech inc
6 *
7 * Based on AC97 Soc codec, original copyright follow:
8 * Copyright 2005 Wolfson Microelectronics PLC.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 * Generic PCM3008 support.
16 */
17
18#include <linux/init.h>
19#include <linux/kernel.h>
20#include <linux/device.h>
21#include <linux/gpio.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/initval.h>
25#include <sound/soc.h>
26
27#include "pcm3008.h"
28
29#define PCM3008_VERSION "0.2"
30
31#define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
32 SNDRV_PCM_RATE_48000)
33
34struct snd_soc_dai pcm3008_dai = {
35 .name = "PCM3008 HiFi",
36 .playback = {
37 .stream_name = "PCM3008 Playback",
38 .channels_min = 1,
39 .channels_max = 2,
40 .rates = PCM3008_RATES,
41 .formats = SNDRV_PCM_FMTBIT_S16_LE,
42 },
43 .capture = {
44 .stream_name = "PCM3008 Capture",
45 .channels_min = 1,
46 .channels_max = 2,
47 .rates = PCM3008_RATES,
48 .formats = SNDRV_PCM_FMTBIT_S16_LE,
49 },
50};
51EXPORT_SYMBOL_GPL(pcm3008_dai);
52
53static void pcm3008_gpio_free(struct pcm3008_setup_data *setup)
54{
55 gpio_free(setup->dem0_pin);
56 gpio_free(setup->dem1_pin);
57 gpio_free(setup->pdad_pin);
58 gpio_free(setup->pdda_pin);
59}
60
61static int pcm3008_soc_probe(struct platform_device *pdev)
62{
63 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
64 struct snd_soc_codec *codec;
65 struct pcm3008_setup_data *setup = socdev->codec_data;
66 int ret = 0;
67
68 printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION);
69
70 socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
71 if (!socdev->codec)
72 return -ENOMEM;
73
74 codec = socdev->codec;
75 mutex_init(&codec->mutex);
76
77 codec->name = "PCM3008";
78 codec->owner = THIS_MODULE;
79 codec->dai = &pcm3008_dai;
80 codec->num_dai = 1;
81 codec->write = NULL;
82 codec->read = NULL;
83 INIT_LIST_HEAD(&codec->dapm_widgets);
84 INIT_LIST_HEAD(&codec->dapm_paths);
85
86 /* Register PCMs. */
87 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
88 if (ret < 0) {
89 printk(KERN_ERR "pcm3008: failed to create pcms\n");
90 goto pcm_err;
91 }
92
93 /* Register Card. */
94 ret = snd_soc_init_card(socdev);
95 if (ret < 0) {
96 printk(KERN_ERR "pcm3008: failed to register card\n");
97 goto card_err;
98 }
99
100 /* DEM1 DEM0 DE-EMPHASIS_MODE
101 * Low Low De-emphasis 44.1 kHz ON
102 * Low High De-emphasis OFF
103 * High Low De-emphasis 48 kHz ON
104 * High High De-emphasis 32 kHz ON
105 */
106
107 /* Configure DEM0 GPIO (turning OFF DAC De-emphasis). */
108 ret = gpio_request(setup->dem0_pin, "codec_dem0");
109 if (ret == 0)
110 ret = gpio_direction_output(setup->dem0_pin, 1);
111 if (ret != 0)
112 goto gpio_err;
113
114 /* Configure DEM1 GPIO (turning OFF DAC De-emphasis). */
115 ret = gpio_request(setup->dem1_pin, "codec_dem1");
116 if (ret == 0)
117 ret = gpio_direction_output(setup->dem1_pin, 0);
118 if (ret != 0)
119 goto gpio_err;
120
121 /* Configure PDAD GPIO. */
122 ret = gpio_request(setup->pdad_pin, "codec_pdad");
123 if (ret == 0)
124 ret = gpio_direction_output(setup->pdad_pin, 1);
125 if (ret != 0)
126 goto gpio_err;
127
128 /* Configure PDDA GPIO. */
129 ret = gpio_request(setup->pdda_pin, "codec_pdda");
130 if (ret == 0)
131 ret = gpio_direction_output(setup->pdda_pin, 1);
132 if (ret != 0)
133 goto gpio_err;
134
135 return ret;
136
137gpio_err:
138 pcm3008_gpio_free(setup);
139card_err:
140 snd_soc_free_pcms(socdev);
141pcm_err:
142 kfree(socdev->codec);
143
144 return ret;
145}
146
147static int pcm3008_soc_remove(struct platform_device *pdev)
148{
149 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
150 struct snd_soc_codec *codec = socdev->codec;
151 struct pcm3008_setup_data *setup = socdev->codec_data;
152
153 if (!codec)
154 return 0;
155
156 pcm3008_gpio_free(setup);
157 snd_soc_free_pcms(socdev);
158 kfree(socdev->codec);
159
160 return 0;
161}
162
163#ifdef CONFIG_PM
164static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg)
165{
166 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
167 struct pcm3008_setup_data *setup = socdev->codec_data;
168
169 gpio_set_value(setup->pdad_pin, 0);
170 gpio_set_value(setup->pdda_pin, 0);
171
172 return 0;
173}
174
175static int pcm3008_soc_resume(struct platform_device *pdev)
176{
177 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
178 struct pcm3008_setup_data *setup = socdev->codec_data;
179
180 gpio_set_value(setup->pdad_pin, 1);
181 gpio_set_value(setup->pdda_pin, 1);
182
183 return 0;
184}
185#else
186#define pcm3008_soc_suspend NULL
187#define pcm3008_soc_resume NULL
188#endif
189
190struct snd_soc_codec_device soc_codec_dev_pcm3008 = {
191 .probe = pcm3008_soc_probe,
192 .remove = pcm3008_soc_remove,
193 .suspend = pcm3008_soc_suspend,
194 .resume = pcm3008_soc_resume,
195};
196EXPORT_SYMBOL_GPL(soc_codec_dev_pcm3008);
197
198static int __init pcm3008_init(void)
199{
200 return snd_soc_register_dai(&pcm3008_dai);
201}
202module_init(pcm3008_init);
203
204static void __exit pcm3008_exit(void)
205{
206 snd_soc_unregister_dai(&pcm3008_dai);
207}
208module_exit(pcm3008_exit);
209
210MODULE_DESCRIPTION("Soc PCM3008 driver");
211MODULE_AUTHOR("Hugo Villeneuve");
212MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/pcm3008.h b/sound/soc/codecs/pcm3008.h
new file mode 100644
index 000000000000..d04e87d3c060
--- /dev/null
+++ b/sound/soc/codecs/pcm3008.h
@@ -0,0 +1,25 @@
1/*
2 * PCM3008 ALSA SoC Layer
3 *
4 * Author: Hugo Villeneuve
5 * Copyright (C) 2008 Lyrtech inc
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 version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef __LINUX_SND_SOC_PCM3008_H
13#define __LINUX_SND_SOC_PCM3008_H
14
15struct pcm3008_setup_data {
16 unsigned dem0_pin;
17 unsigned dem1_pin;
18 unsigned pdad_pin;
19 unsigned pdda_pin;
20};
21
22extern struct snd_soc_codec_device soc_codec_dev_pcm3008;
23extern struct snd_soc_dai pcm3008_dai;
24
25#endif
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 44ef0dacd564..cac373616768 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -285,16 +285,23 @@ static inline int get_coeff(int mclk, int rate)
285} 285}
286 286
287static int ssm2602_hw_params(struct snd_pcm_substream *substream, 287static int ssm2602_hw_params(struct snd_pcm_substream *substream,
288 struct snd_pcm_hw_params *params) 288 struct snd_pcm_hw_params *params,
289 struct snd_soc_dai *dai)
289{ 290{
290 u16 srate; 291 u16 srate;
291 struct snd_soc_pcm_runtime *rtd = substream->private_data; 292 struct snd_soc_pcm_runtime *rtd = substream->private_data;
292 struct snd_soc_device *socdev = rtd->socdev; 293 struct snd_soc_device *socdev = rtd->socdev;
293 struct snd_soc_codec *codec = socdev->codec; 294 struct snd_soc_codec *codec = socdev->codec;
294 struct ssm2602_priv *ssm2602 = codec->private_data; 295 struct ssm2602_priv *ssm2602 = codec->private_data;
296 struct i2c_client *i2c = codec->control_data;
295 u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; 297 u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3;
296 int i = get_coeff(ssm2602->sysclk, params_rate(params)); 298 int i = get_coeff(ssm2602->sysclk, params_rate(params));
297 299
300 if (substream == ssm2602->slave_substream) {
301 dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n");
302 return 0;
303 }
304
298 /*no match is found*/ 305 /*no match is found*/
299 if (i == ARRAY_SIZE(coeff_div)) 306 if (i == ARRAY_SIZE(coeff_div))
300 return -EINVAL; 307 return -EINVAL;
@@ -324,19 +331,26 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
324 return 0; 331 return 0;
325} 332}
326 333
327static int ssm2602_startup(struct snd_pcm_substream *substream) 334static int ssm2602_startup(struct snd_pcm_substream *substream,
335 struct snd_soc_dai *dai)
328{ 336{
329 struct snd_soc_pcm_runtime *rtd = substream->private_data; 337 struct snd_soc_pcm_runtime *rtd = substream->private_data;
330 struct snd_soc_device *socdev = rtd->socdev; 338 struct snd_soc_device *socdev = rtd->socdev;
331 struct snd_soc_codec *codec = socdev->codec; 339 struct snd_soc_codec *codec = socdev->codec;
332 struct ssm2602_priv *ssm2602 = codec->private_data; 340 struct ssm2602_priv *ssm2602 = codec->private_data;
341 struct i2c_client *i2c = codec->control_data;
333 struct snd_pcm_runtime *master_runtime; 342 struct snd_pcm_runtime *master_runtime;
334 343
335 /* The DAI has shared clocks so if we already have a playback or 344 /* The DAI has shared clocks so if we already have a playback or
336 * capture going then constrain this substream to match it. 345 * capture going then constrain this substream to match it.
346 * TODO: the ssm2602 allows pairs of non-matching PB/REC rates
337 */ 347 */
338 if (ssm2602->master_substream) { 348 if (ssm2602->master_substream) {
339 master_runtime = ssm2602->master_substream->runtime; 349 master_runtime = ssm2602->master_substream->runtime;
350 dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n",
351 master_runtime->sample_bits,
352 master_runtime->rate);
353
340 snd_pcm_hw_constraint_minmax(substream->runtime, 354 snd_pcm_hw_constraint_minmax(substream->runtime,
341 SNDRV_PCM_HW_PARAM_RATE, 355 SNDRV_PCM_HW_PARAM_RATE,
342 master_runtime->rate, 356 master_runtime->rate,
@@ -354,7 +368,8 @@ static int ssm2602_startup(struct snd_pcm_substream *substream)
354 return 0; 368 return 0;
355} 369}
356 370
357static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream) 371static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream,
372 struct snd_soc_dai *dai)
358{ 373{
359 struct snd_soc_pcm_runtime *rtd = substream->private_data; 374 struct snd_soc_pcm_runtime *rtd = substream->private_data;
360 struct snd_soc_device *socdev = rtd->socdev; 375 struct snd_soc_device *socdev = rtd->socdev;
@@ -365,14 +380,21 @@ static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream)
365 return 0; 380 return 0;
366} 381}
367 382
368static void ssm2602_shutdown(struct snd_pcm_substream *substream) 383static void ssm2602_shutdown(struct snd_pcm_substream *substream,
384 struct snd_soc_dai *dai)
369{ 385{
370 struct snd_soc_pcm_runtime *rtd = substream->private_data; 386 struct snd_soc_pcm_runtime *rtd = substream->private_data;
371 struct snd_soc_device *socdev = rtd->socdev; 387 struct snd_soc_device *socdev = rtd->socdev;
372 struct snd_soc_codec *codec = socdev->codec; 388 struct snd_soc_codec *codec = socdev->codec;
389 struct ssm2602_priv *ssm2602 = codec->private_data;
373 /* deactivate */ 390 /* deactivate */
374 if (!codec->active) 391 if (!codec->active)
375 ssm2602_write(codec, SSM2602_ACTIVE, 0); 392 ssm2602_write(codec, SSM2602_ACTIVE, 0);
393
394 if (ssm2602->master_substream == substream)
395 ssm2602->master_substream = ssm2602->slave_substream;
396
397 ssm2602->slave_substream = NULL;
376} 398}
377 399
378static int ssm2602_mute(struct snd_soc_dai *dai, int mute) 400static int ssm2602_mute(struct snd_soc_dai *dai, int mute)
@@ -432,10 +454,10 @@ static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
432 iface |= 0x0001; 454 iface |= 0x0001;
433 break; 455 break;
434 case SND_SOC_DAIFMT_DSP_A: 456 case SND_SOC_DAIFMT_DSP_A:
435 iface |= 0x0003; 457 iface |= 0x0013;
436 break; 458 break;
437 case SND_SOC_DAIFMT_DSP_B: 459 case SND_SOC_DAIFMT_DSP_B:
438 iface |= 0x0013; 460 iface |= 0x0003;
439 break; 461 break;
440 default: 462 default:
441 return -EINVAL; 463 return -EINVAL;
@@ -496,6 +518,9 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
496 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ 518 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
497 SNDRV_PCM_RATE_96000) 519 SNDRV_PCM_RATE_96000)
498 520
521#define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
522 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
523
499struct snd_soc_dai ssm2602_dai = { 524struct snd_soc_dai ssm2602_dai = {
500 .name = "SSM2602", 525 .name = "SSM2602",
501 .playback = { 526 .playback = {
@@ -503,20 +528,18 @@ struct snd_soc_dai ssm2602_dai = {
503 .channels_min = 2, 528 .channels_min = 2,
504 .channels_max = 2, 529 .channels_max = 2,
505 .rates = SSM2602_RATES, 530 .rates = SSM2602_RATES,
506 .formats = SNDRV_PCM_FMTBIT_S32_LE,}, 531 .formats = SSM2602_FORMATS,},
507 .capture = { 532 .capture = {
508 .stream_name = "Capture", 533 .stream_name = "Capture",
509 .channels_min = 2, 534 .channels_min = 2,
510 .channels_max = 2, 535 .channels_max = 2,
511 .rates = SSM2602_RATES, 536 .rates = SSM2602_RATES,
512 .formats = SNDRV_PCM_FMTBIT_S32_LE,}, 537 .formats = SSM2602_FORMATS,},
513 .ops = { 538 .ops = {
514 .startup = ssm2602_startup, 539 .startup = ssm2602_startup,
515 .prepare = ssm2602_pcm_prepare, 540 .prepare = ssm2602_pcm_prepare,
516 .hw_params = ssm2602_hw_params, 541 .hw_params = ssm2602_hw_params,
517 .shutdown = ssm2602_shutdown, 542 .shutdown = ssm2602_shutdown,
518 },
519 .dai_ops = {
520 .digital_mute = ssm2602_mute, 543 .digital_mute = ssm2602_mute,
521 .set_sysclk = ssm2602_set_dai_sysclk, 544 .set_sysclk = ssm2602_set_dai_sysclk,
522 .set_fmt = ssm2602_set_dai_fmt, 545 .set_fmt = ssm2602_set_dai_fmt,
@@ -601,7 +624,7 @@ static int ssm2602_init(struct snd_soc_device *socdev)
601 624
602 ssm2602_add_controls(codec); 625 ssm2602_add_controls(codec);
603 ssm2602_add_widgets(codec); 626 ssm2602_add_widgets(codec);
604 ret = snd_soc_register_card(socdev); 627 ret = snd_soc_init_card(socdev);
605 if (ret < 0) { 628 if (ret < 0) {
606 pr_err("ssm2602: failed to register card\n"); 629 pr_err("ssm2602: failed to register card\n");
607 goto card_err; 630 goto card_err;
@@ -770,6 +793,18 @@ struct snd_soc_codec_device soc_codec_dev_ssm2602 = {
770}; 793};
771EXPORT_SYMBOL_GPL(soc_codec_dev_ssm2602); 794EXPORT_SYMBOL_GPL(soc_codec_dev_ssm2602);
772 795
796static int __init ssm2602_modinit(void)
797{
798 return snd_soc_register_dai(&ssm2602_dai);
799}
800module_init(ssm2602_modinit);
801
802static void __exit ssm2602_exit(void)
803{
804 snd_soc_unregister_dai(&ssm2602_dai);
805}
806module_exit(ssm2602_exit);
807
773MODULE_DESCRIPTION("ASoC ssm2602 driver"); 808MODULE_DESCRIPTION("ASoC ssm2602 driver");
774MODULE_AUTHOR("Cliff Cai"); 809MODULE_AUTHOR("Cliff Cai");
775MODULE_LICENSE("GPL"); 810MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 44308dac9e18..cfdea007c4cb 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -37,12 +37,6 @@
37 37
38#define AIC23_VERSION "0.1" 38#define AIC23_VERSION "0.1"
39 39
40struct tlv320aic23_srate_reg_info {
41 u32 sample_rate;
42 u8 control; /* SR3, SR2, SR1, SR0 and BOSR */
43 u8 divider; /* if 0 CLKIN = MCLK, if 1 CLKIN = MCLK/2 */
44};
45
46/* 40/*
47 * AIC23 register cache 41 * AIC23 register cache
48 */ 42 */
@@ -261,20 +255,156 @@ static const struct snd_soc_dapm_route intercon[] = {
261 255
262}; 256};
263 257
264/* tlv320aic23 related */ 258/* AIC23 driver data */
265static const struct tlv320aic23_srate_reg_info srate_reg_info[] = { 259struct aic23 {
266 {4000, 0x06, 1}, /* 4000 */ 260 struct snd_soc_codec codec;
267 {8000, 0x06, 0}, /* 8000 */ 261 int mclk;
268 {16000, 0x0C, 1}, /* 16000 */ 262 int requested_adc;
269 {22050, 0x11, 1}, /* 22050 */ 263 int requested_dac;
270 {24000, 0x00, 1}, /* 24000 */ 264};
271 {32000, 0x0C, 0}, /* 32000 */ 265
272 {44100, 0x11, 0}, /* 44100 */ 266/*
273 {48000, 0x00, 0}, /* 48000 */ 267 * Common Crystals used
274 {88200, 0x1F, 0}, /* 88200 */ 268 * 11.2896 Mhz /128 = *88.2k /192 = 58.8k
275 {96000, 0x0E, 0}, /* 96000 */ 269 * 12.0000 Mhz /125 = *96k /136 = 88.235K
270 * 12.2880 Mhz /128 = *96k /192 = 64k
271 * 16.9344 Mhz /128 = 132.3k /192 = *88.2k
272 * 18.4320 Mhz /128 = 144k /192 = *96k
273 */
274
275/*
276 * Normal BOSR 0-256/2 = 128, 1-384/2 = 192
277 * USB BOSR 0-250/2 = 125, 1-272/2 = 136
278 */
279static const int bosr_usb_divisor_table[] = {
280 128, 125, 192, 136
281};
282#define LOWER_GROUP ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<6) | (1<<7))
283#define UPPER_GROUP ((1<<8) | (1<<9) | (1<<10) | (1<<11) | (1<<15))
284static const unsigned short sr_valid_mask[] = {
285 LOWER_GROUP|UPPER_GROUP, /* Normal, bosr - 0*/
286 LOWER_GROUP|UPPER_GROUP, /* Normal, bosr - 1*/
287 LOWER_GROUP, /* Usb, bosr - 0*/
288 UPPER_GROUP, /* Usb, bosr - 1*/
289};
290/*
291 * Every divisor is a factor of 11*12
292 */
293#define SR_MULT (11*12)
294#define A(x) (x) ? (SR_MULT/x) : 0
295static const unsigned char sr_adc_mult_table[] = {
296 A(2), A(2), A(12), A(12), A(0), A(0), A(3), A(1),
297 A(2), A(2), A(11), A(11), A(0), A(0), A(0), A(1)
298};
299static const unsigned char sr_dac_mult_table[] = {
300 A(2), A(12), A(2), A(12), A(0), A(0), A(3), A(1),
301 A(2), A(11), A(2), A(11), A(0), A(0), A(0), A(1)
276}; 302};
277 303
304static unsigned get_score(int adc, int adc_l, int adc_h, int need_adc,
305 int dac, int dac_l, int dac_h, int need_dac)
306{
307 if ((adc >= adc_l) && (adc <= adc_h) &&
308 (dac >= dac_l) && (dac <= dac_h)) {
309 int diff_adc = need_adc - adc;
310 int diff_dac = need_dac - dac;
311 return abs(diff_adc) + abs(diff_dac);
312 }
313 return UINT_MAX;
314}
315
316static int find_rate(int mclk, u32 need_adc, u32 need_dac)
317{
318 int i, j;
319 int best_i = -1;
320 int best_j = -1;
321 int best_div = 0;
322 unsigned best_score = UINT_MAX;
323 int adc_l, adc_h, dac_l, dac_h;
324
325 need_adc *= SR_MULT;
326 need_dac *= SR_MULT;
327 /*
328 * rates given are +/- 1/32
329 */
330 adc_l = need_adc - (need_adc >> 5);
331 adc_h = need_adc + (need_adc >> 5);
332 dac_l = need_dac - (need_dac >> 5);
333 dac_h = need_dac + (need_dac >> 5);
334 for (i = 0; i < ARRAY_SIZE(bosr_usb_divisor_table); i++) {
335 int base = mclk / bosr_usb_divisor_table[i];
336 int mask = sr_valid_mask[i];
337 for (j = 0; j < ARRAY_SIZE(sr_adc_mult_table);
338 j++, mask >>= 1) {
339 int adc;
340 int dac;
341 int score;
342 if ((mask & 1) == 0)
343 continue;
344 adc = base * sr_adc_mult_table[j];
345 dac = base * sr_dac_mult_table[j];
346 score = get_score(adc, adc_l, adc_h, need_adc,
347 dac, dac_l, dac_h, need_dac);
348 if (best_score > score) {
349 best_score = score;
350 best_i = i;
351 best_j = j;
352 best_div = 0;
353 }
354 score = get_score((adc >> 1), adc_l, adc_h, need_adc,
355 (dac >> 1), dac_l, dac_h, need_dac);
356 /* prefer to have a /2 */
357 if ((score != UINT_MAX) && (best_score >= score)) {
358 best_score = score;
359 best_i = i;
360 best_j = j;
361 best_div = 1;
362 }
363 }
364 }
365 return (best_j << 2) | best_i | (best_div << TLV320AIC23_CLKIN_SHIFT);
366}
367
368#ifdef DEBUG
369static void get_current_sample_rates(struct snd_soc_codec *codec, int mclk,
370 u32 *sample_rate_adc, u32 *sample_rate_dac)
371{
372 int src = tlv320aic23_read_reg_cache(codec, TLV320AIC23_SRATE);
373 int sr = (src >> 2) & 0x0f;
374 int val = (mclk / bosr_usb_divisor_table[src & 3]);
375 int adc = (val * sr_adc_mult_table[sr]) / SR_MULT;
376 int dac = (val * sr_dac_mult_table[sr]) / SR_MULT;
377 if (src & TLV320AIC23_CLKIN_HALF) {
378 adc >>= 1;
379 dac >>= 1;
380 }
381 *sample_rate_adc = adc;
382 *sample_rate_dac = dac;
383}
384#endif
385
386static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk,
387 u32 sample_rate_adc, u32 sample_rate_dac)
388{
389 /* Search for the right sample rate */
390 int data = find_rate(mclk, sample_rate_adc, sample_rate_dac);
391 if (data < 0) {
392 printk(KERN_ERR "%s:Invalid rate %u,%u requested\n",
393 __func__, sample_rate_adc, sample_rate_dac);
394 return -EINVAL;
395 }
396 tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
397#ifdef DEBUG
398 {
399 u32 adc, dac;
400 get_current_sample_rates(codec, mclk, &adc, &dac);
401 printk(KERN_DEBUG "actual samplerate = %u,%u reg=%x\n",
402 adc, dac, data);
403 }
404#endif
405 return 0;
406}
407
278static int tlv320aic23_add_widgets(struct snd_soc_codec *codec) 408static int tlv320aic23_add_widgets(struct snd_soc_codec *codec)
279{ 409{
280 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, 410 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
@@ -288,32 +418,36 @@ static int tlv320aic23_add_widgets(struct snd_soc_codec *codec)
288} 418}
289 419
290static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, 420static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
291 struct snd_pcm_hw_params *params) 421 struct snd_pcm_hw_params *params,
422 struct snd_soc_dai *dai)
292{ 423{
293 struct snd_soc_pcm_runtime *rtd = substream->private_data; 424 struct snd_soc_pcm_runtime *rtd = substream->private_data;
294 struct snd_soc_device *socdev = rtd->socdev; 425 struct snd_soc_device *socdev = rtd->socdev;
295 struct snd_soc_codec *codec = socdev->codec; 426 struct snd_soc_codec *codec = socdev->codec;
296 u16 iface_reg, data; 427 u16 iface_reg;
297 u8 count = 0; 428 int ret;
429 struct aic23 *aic23 = container_of(codec, struct aic23, codec);
430 u32 sample_rate_adc = aic23->requested_adc;
431 u32 sample_rate_dac = aic23->requested_dac;
432 u32 sample_rate = params_rate(params);
433
434 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
435 aic23->requested_dac = sample_rate_dac = sample_rate;
436 if (!sample_rate_adc)
437 sample_rate_adc = sample_rate;
438 } else {
439 aic23->requested_adc = sample_rate_adc = sample_rate;
440 if (!sample_rate_dac)
441 sample_rate_dac = sample_rate;
442 }
443 ret = set_sample_rate_control(codec, aic23->mclk, sample_rate_adc,
444 sample_rate_dac);
445 if (ret < 0)
446 return ret;
298 447
299 iface_reg = 448 iface_reg =
300 tlv320aic23_read_reg_cache(codec, 449 tlv320aic23_read_reg_cache(codec,
301 TLV320AIC23_DIGT_FMT) & ~(0x03 << 2); 450 TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
302
303 /* Search for the right sample rate */
304 /* Verify what happens if the rate is not supported
305 * now it goes to 96Khz */
306 while ((srate_reg_info[count].sample_rate != params_rate(params)) &&
307 (count < ARRAY_SIZE(srate_reg_info))) {
308 count++;
309 }
310
311 data = (srate_reg_info[count].divider << TLV320AIC23_CLKIN_SHIFT) |
312 (srate_reg_info[count]. control << TLV320AIC23_BOSR_SHIFT) |
313 TLV320AIC23_USB_CLK_ON;
314
315 tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
316
317 switch (params_format(params)) { 451 switch (params_format(params)) {
318 case SNDRV_PCM_FORMAT_S16_LE: 452 case SNDRV_PCM_FORMAT_S16_LE:
319 break; 453 break;
@@ -332,7 +466,8 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
332 return 0; 466 return 0;
333} 467}
334 468
335static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream) 469static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
470 struct snd_soc_dai *dai)
336{ 471{
337 struct snd_soc_pcm_runtime *rtd = substream->private_data; 472 struct snd_soc_pcm_runtime *rtd = substream->private_data;
338 struct snd_soc_device *socdev = rtd->socdev; 473 struct snd_soc_device *socdev = rtd->socdev;
@@ -344,17 +479,23 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream)
344 return 0; 479 return 0;
345} 480}
346 481
347static void tlv320aic23_shutdown(struct snd_pcm_substream *substream) 482static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
483 struct snd_soc_dai *dai)
348{ 484{
349 struct snd_soc_pcm_runtime *rtd = substream->private_data; 485 struct snd_soc_pcm_runtime *rtd = substream->private_data;
350 struct snd_soc_device *socdev = rtd->socdev; 486 struct snd_soc_device *socdev = rtd->socdev;
351 struct snd_soc_codec *codec = socdev->codec; 487 struct snd_soc_codec *codec = socdev->codec;
488 struct aic23 *aic23 = container_of(codec, struct aic23, codec);
352 489
353 /* deactivate */ 490 /* deactivate */
354 if (!codec->active) { 491 if (!codec->active) {
355 udelay(50); 492 udelay(50);
356 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0); 493 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
357 } 494 }
495 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
496 aic23->requested_dac = 0;
497 else
498 aic23->requested_adc = 0;
358} 499}
359 500
360static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute) 501static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute)
@@ -400,7 +541,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
400 case SND_SOC_DAIFMT_I2S: 541 case SND_SOC_DAIFMT_I2S:
401 iface_reg |= TLV320AIC23_FOR_I2S; 542 iface_reg |= TLV320AIC23_FOR_I2S;
402 break; 543 break;
403 case SND_SOC_DAIFMT_DSP_A: 544 case SND_SOC_DAIFMT_DSP_B:
404 iface_reg |= TLV320AIC23_FOR_DSP; 545 iface_reg |= TLV320AIC23_FOR_DSP;
405 break; 546 break;
406 case SND_SOC_DAIFMT_RIGHT_J: 547 case SND_SOC_DAIFMT_RIGHT_J:
@@ -422,12 +563,9 @@ static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai,
422 int clk_id, unsigned int freq, int dir) 563 int clk_id, unsigned int freq, int dir)
423{ 564{
424 struct snd_soc_codec *codec = codec_dai->codec; 565 struct snd_soc_codec *codec = codec_dai->codec;
425 566 struct aic23 *aic23 = container_of(codec, struct aic23, codec);
426 switch (freq) { 567 aic23->mclk = freq;
427 case 12000000: 568 return 0;
428 return 0;
429 }
430 return -EINVAL;
431} 569}
432 570
433static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec, 571static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
@@ -478,12 +616,10 @@ struct snd_soc_dai tlv320aic23_dai = {
478 .prepare = tlv320aic23_pcm_prepare, 616 .prepare = tlv320aic23_pcm_prepare,
479 .hw_params = tlv320aic23_hw_params, 617 .hw_params = tlv320aic23_hw_params,
480 .shutdown = tlv320aic23_shutdown, 618 .shutdown = tlv320aic23_shutdown,
481 }, 619 .digital_mute = tlv320aic23_mute,
482 .dai_ops = { 620 .set_fmt = tlv320aic23_set_dai_fmt,
483 .digital_mute = tlv320aic23_mute, 621 .set_sysclk = tlv320aic23_set_dai_sysclk,
484 .set_fmt = tlv320aic23_set_dai_fmt, 622 }
485 .set_sysclk = tlv320aic23_set_dai_sysclk,
486 }
487}; 623};
488EXPORT_SYMBOL_GPL(tlv320aic23_dai); 624EXPORT_SYMBOL_GPL(tlv320aic23_dai);
489 625
@@ -584,7 +720,7 @@ static int tlv320aic23_init(struct snd_soc_device *socdev)
584 720
585 tlv320aic23_add_controls(codec); 721 tlv320aic23_add_controls(codec);
586 tlv320aic23_add_widgets(codec); 722 tlv320aic23_add_widgets(codec);
587 ret = snd_soc_register_card(socdev); 723 ret = snd_soc_init_card(socdev);
588 if (ret < 0) { 724 if (ret < 0) {
589 printk(KERN_ERR "tlv320aic23: failed to register card\n"); 725 printk(KERN_ERR "tlv320aic23: failed to register card\n");
590 goto card_err; 726 goto card_err;
@@ -659,14 +795,15 @@ static int tlv320aic23_probe(struct platform_device *pdev)
659{ 795{
660 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 796 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
661 struct snd_soc_codec *codec; 797 struct snd_soc_codec *codec;
798 struct aic23 *aic23;
662 int ret = 0; 799 int ret = 0;
663 800
664 printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION); 801 printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
665 802
666 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 803 aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL);
667 if (codec == NULL) 804 if (aic23 == NULL)
668 return -ENOMEM; 805 return -ENOMEM;
669 806 codec = &aic23->codec;
670 socdev->codec = codec; 807 socdev->codec = codec;
671 mutex_init(&codec->mutex); 808 mutex_init(&codec->mutex);
672 INIT_LIST_HEAD(&codec->dapm_widgets); 809 INIT_LIST_HEAD(&codec->dapm_widgets);
@@ -687,6 +824,7 @@ static int tlv320aic23_remove(struct platform_device *pdev)
687{ 824{
688 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 825 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
689 struct snd_soc_codec *codec = socdev->codec; 826 struct snd_soc_codec *codec = socdev->codec;
827 struct aic23 *aic23 = container_of(codec, struct aic23, codec);
690 828
691 if (codec->control_data) 829 if (codec->control_data)
692 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); 830 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -697,7 +835,7 @@ static int tlv320aic23_remove(struct platform_device *pdev)
697 i2c_del_driver(&tlv320aic23_i2c_driver); 835 i2c_del_driver(&tlv320aic23_i2c_driver);
698#endif 836#endif
699 kfree(codec->reg_cache); 837 kfree(codec->reg_cache);
700 kfree(codec); 838 kfree(aic23);
701 839
702 return 0; 840 return 0;
703} 841}
@@ -709,6 +847,18 @@ struct snd_soc_codec_device soc_codec_dev_tlv320aic23 = {
709}; 847};
710EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23); 848EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23);
711 849
850static int __init tlv320aic23_modinit(void)
851{
852 return snd_soc_register_dai(&tlv320aic23_dai);
853}
854module_init(tlv320aic23_modinit);
855
856static void __exit tlv320aic23_exit(void)
857{
858 snd_soc_unregister_dai(&tlv320aic23_dai);
859}
860module_exit(tlv320aic23_exit);
861
712MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); 862MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver");
713MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); 863MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
714MODULE_LICENSE("GPL"); 864MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index bed8a9e63ddc..29f2f1a017fd 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -125,7 +125,8 @@ static int aic26_reg_write(struct snd_soc_codec *codec, unsigned int reg,
125 * Digital Audio Interface Operations 125 * Digital Audio Interface Operations
126 */ 126 */
127static int aic26_hw_params(struct snd_pcm_substream *substream, 127static int aic26_hw_params(struct snd_pcm_substream *substream,
128 struct snd_pcm_hw_params *params) 128 struct snd_pcm_hw_params *params,
129 struct snd_soc_dai *dai)
129{ 130{
130 struct snd_soc_pcm_runtime *rtd = substream->private_data; 131 struct snd_soc_pcm_runtime *rtd = substream->private_data;
131 struct snd_soc_device *socdev = rtd->socdev; 132 struct snd_soc_device *socdev = rtd->socdev;
@@ -287,8 +288,6 @@ struct snd_soc_dai aic26_dai = {
287 }, 288 },
288 .ops = { 289 .ops = {
289 .hw_params = aic26_hw_params, 290 .hw_params = aic26_hw_params,
290 },
291 .dai_ops = {
292 .digital_mute = aic26_mute, 291 .digital_mute = aic26_mute,
293 .set_sysclk = aic26_set_sysclk, 292 .set_sysclk = aic26_set_sysclk,
294 .set_fmt = aic26_set_fmt, 293 .set_fmt = aic26_set_fmt,
@@ -360,7 +359,7 @@ static int aic26_probe(struct platform_device *pdev)
360 359
361 /* CODEC is setup, we can register the card now */ 360 /* CODEC is setup, we can register the card now */
362 dev_dbg(&pdev->dev, "Registering card\n"); 361 dev_dbg(&pdev->dev, "Registering card\n");
363 ret = snd_soc_register_card(socdev); 362 ret = snd_soc_init_card(socdev);
364 if (ret < 0) { 363 if (ret < 0) {
365 dev_err(&pdev->dev, "aic26: failed to register card\n"); 364 dev_err(&pdev->dev, "aic26: failed to register card\n");
366 goto card_err; 365 goto card_err;
@@ -427,7 +426,7 @@ static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set);
427static int aic26_spi_probe(struct spi_device *spi) 426static int aic26_spi_probe(struct spi_device *spi)
428{ 427{
429 struct aic26 *aic26; 428 struct aic26 *aic26;
430 int rc, i, reg; 429 int ret, i, reg;
431 430
432 dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n"); 431 dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n");
433 432
@@ -457,6 +456,14 @@ static int aic26_spi_probe(struct spi_device *spi)
457 aic26->codec.reg_cache_size = AIC26_NUM_REGS; 456 aic26->codec.reg_cache_size = AIC26_NUM_REGS;
458 aic26->codec.reg_cache = aic26->reg_cache; 457 aic26->codec.reg_cache = aic26->reg_cache;
459 458
459 aic26_dai.dev = &spi->dev;
460 ret = snd_soc_register_dai(&aic26_dai);
461 if (ret != 0) {
462 dev_err(&spi->dev, "Failed to register DAI: %d\n", ret);
463 kfree(aic26);
464 return ret;
465 }
466
460 /* Reset the codec to power on defaults */ 467 /* Reset the codec to power on defaults */
461 aic26_reg_write(&aic26->codec, AIC26_REG_RESET, 0xBB00); 468 aic26_reg_write(&aic26->codec, AIC26_REG_RESET, 0xBB00);
462 469
@@ -475,8 +482,8 @@ static int aic26_spi_probe(struct spi_device *spi)
475 482
476 /* Register the sysfs files for debugging */ 483 /* Register the sysfs files for debugging */
477 /* Create SysFS files */ 484 /* Create SysFS files */
478 rc = device_create_file(&spi->dev, &dev_attr_keyclick); 485 ret = device_create_file(&spi->dev, &dev_attr_keyclick);
479 if (rc) 486 if (ret)
480 dev_info(&spi->dev, "error creating sysfs files\n"); 487 dev_info(&spi->dev, "error creating sysfs files\n");
481 488
482#if defined(CONFIG_SND_SOC_OF_SIMPLE) 489#if defined(CONFIG_SND_SOC_OF_SIMPLE)
@@ -493,6 +500,7 @@ static int aic26_spi_remove(struct spi_device *spi)
493{ 500{
494 struct aic26 *aic26 = dev_get_drvdata(&spi->dev); 501 struct aic26 *aic26 = dev_get_drvdata(&spi->dev);
495 502
503 snd_soc_unregister_dai(&aic26_dai);
496 kfree(aic26); 504 kfree(aic26);
497 505
498 return 0; 506 return 0;
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index cff276ee261e..b47a749c5ea2 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -253,11 +253,17 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
253 253
254 SOC_DOUBLE_R("Line DAC Playback Volume", DACL1_2_LLOPM_VOL, 254 SOC_DOUBLE_R("Line DAC Playback Volume", DACL1_2_LLOPM_VOL,
255 DACR1_2_RLOPM_VOL, 0, 0x7f, 1), 255 DACR1_2_RLOPM_VOL, 0, 0x7f, 1),
256 SOC_DOUBLE_R("Line DAC Playback Switch", LLOPM_CTRL, RLOPM_CTRL, 3, 256 SOC_SINGLE("LineL Playback Switch", LLOPM_CTRL, 3, 0x01, 0),
257 0x01, 0), 257 SOC_SINGLE("LineR Playback Switch", RLOPM_CTRL, 3, 0x01, 0),
258 SOC_DOUBLE_R("Line PGA Bypass Playback Volume", PGAL_2_LLOPM_VOL, 258 SOC_DOUBLE_R("LineL DAC Playback Volume", DACL1_2_LLOPM_VOL,
259 PGAR_2_RLOPM_VOL, 0, 0x7f, 1), 259 DACR1_2_LLOPM_VOL, 0, 0x7f, 1),
260 SOC_DOUBLE_R("Line Line2 Bypass Playback Volume", LINE2L_2_LLOPM_VOL, 260 SOC_SINGLE("LineL Left PGA Bypass Playback Volume", PGAL_2_LLOPM_VOL,
261 0, 0x7f, 1),
262 SOC_SINGLE("LineR Right PGA Bypass Playback Volume", PGAR_2_RLOPM_VOL,
263 0, 0x7f, 1),
264 SOC_DOUBLE_R("LineL Line2 Bypass Playback Volume", LINE2L_2_LLOPM_VOL,
265 LINE2R_2_LLOPM_VOL, 0, 0x7f, 1),
266 SOC_DOUBLE_R("LineR Line2 Bypass Playback Volume", LINE2L_2_RLOPM_VOL,
261 LINE2R_2_RLOPM_VOL, 0, 0x7f, 1), 267 LINE2R_2_RLOPM_VOL, 0, 0x7f, 1),
262 268
263 SOC_DOUBLE_R("Mono DAC Playback Volume", DACL1_2_MONOLOPM_VOL, 269 SOC_DOUBLE_R("Mono DAC Playback Volume", DACL1_2_MONOLOPM_VOL,
@@ -272,8 +278,12 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
272 DACR1_2_HPROUT_VOL, 0, 0x7f, 1), 278 DACR1_2_HPROUT_VOL, 0, 0x7f, 1),
273 SOC_DOUBLE_R("HP DAC Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3, 279 SOC_DOUBLE_R("HP DAC Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3,
274 0x01, 0), 280 0x01, 0),
275 SOC_DOUBLE_R("HP PGA Bypass Playback Volume", PGAL_2_HPLOUT_VOL, 281 SOC_DOUBLE_R("HP Right PGA Bypass Playback Volume", PGAR_2_HPLOUT_VOL,
276 PGAR_2_HPROUT_VOL, 0, 0x7f, 1), 282 PGAR_2_HPROUT_VOL, 0, 0x7f, 1),
283 SOC_SINGLE("HPL PGA Bypass Playback Volume", PGAL_2_HPLOUT_VOL,
284 0, 0x7f, 1),
285 SOC_SINGLE("HPR PGA Bypass Playback Volume", PGAL_2_HPROUT_VOL,
286 0, 0x7f, 1),
277 SOC_DOUBLE_R("HP Line2 Bypass Playback Volume", LINE2L_2_HPLOUT_VOL, 287 SOC_DOUBLE_R("HP Line2 Bypass Playback Volume", LINE2L_2_HPLOUT_VOL,
278 LINE2R_2_HPROUT_VOL, 0, 0x7f, 1), 288 LINE2R_2_HPROUT_VOL, 0, 0x7f, 1),
279 289
@@ -281,8 +291,10 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
281 DACR1_2_HPRCOM_VOL, 0, 0x7f, 1), 291 DACR1_2_HPRCOM_VOL, 0, 0x7f, 1),
282 SOC_DOUBLE_R("HPCOM DAC Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3, 292 SOC_DOUBLE_R("HPCOM DAC Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3,
283 0x01, 0), 293 0x01, 0),
284 SOC_DOUBLE_R("HPCOM PGA Bypass Playback Volume", PGAL_2_HPLCOM_VOL, 294 SOC_SINGLE("HPLCOM PGA Bypass Playback Volume", PGAL_2_HPLCOM_VOL,
285 PGAR_2_HPRCOM_VOL, 0, 0x7f, 1), 295 0, 0x7f, 1),
296 SOC_SINGLE("HPRCOM PGA Bypass Playback Volume", PGAL_2_HPRCOM_VOL,
297 0, 0x7f, 1),
286 SOC_DOUBLE_R("HPCOM Line2 Bypass Playback Volume", LINE2L_2_HPLCOM_VOL, 298 SOC_DOUBLE_R("HPCOM Line2 Bypass Playback Volume", LINE2L_2_HPLCOM_VOL,
287 LINE2R_2_HPRCOM_VOL, 0, 0x7f, 1), 299 LINE2R_2_HPRCOM_VOL, 0, 0x7f, 1),
288 300
@@ -333,7 +345,8 @@ SOC_DAPM_ENUM("Route", aic3x_enum[RHPCOM_ENUM]);
333 345
334/* Left DAC_L1 Mixer */ 346/* Left DAC_L1 Mixer */
335static const struct snd_kcontrol_new aic3x_left_dac_mixer_controls[] = { 347static const struct snd_kcontrol_new aic3x_left_dac_mixer_controls[] = {
336 SOC_DAPM_SINGLE("Line Switch", DACL1_2_LLOPM_VOL, 7, 1, 0), 348 SOC_DAPM_SINGLE("LineL Switch", DACL1_2_LLOPM_VOL, 7, 1, 0),
349 SOC_DAPM_SINGLE("LineR Switch", DACL1_2_RLOPM_VOL, 7, 1, 0),
337 SOC_DAPM_SINGLE("Mono Switch", DACL1_2_MONOLOPM_VOL, 7, 1, 0), 350 SOC_DAPM_SINGLE("Mono Switch", DACL1_2_MONOLOPM_VOL, 7, 1, 0),
338 SOC_DAPM_SINGLE("HP Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0), 351 SOC_DAPM_SINGLE("HP Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0),
339 SOC_DAPM_SINGLE("HPCOM Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0), 352 SOC_DAPM_SINGLE("HPCOM Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0),
@@ -341,7 +354,8 @@ static const struct snd_kcontrol_new aic3x_left_dac_mixer_controls[] = {
341 354
342/* Right DAC_R1 Mixer */ 355/* Right DAC_R1 Mixer */
343static const struct snd_kcontrol_new aic3x_right_dac_mixer_controls[] = { 356static const struct snd_kcontrol_new aic3x_right_dac_mixer_controls[] = {
344 SOC_DAPM_SINGLE("Line Switch", DACR1_2_RLOPM_VOL, 7, 1, 0), 357 SOC_DAPM_SINGLE("LineL Switch", DACR1_2_LLOPM_VOL, 7, 1, 0),
358 SOC_DAPM_SINGLE("LineR Switch", DACR1_2_RLOPM_VOL, 7, 1, 0),
345 SOC_DAPM_SINGLE("Mono Switch", DACR1_2_MONOLOPM_VOL, 7, 1, 0), 359 SOC_DAPM_SINGLE("Mono Switch", DACR1_2_MONOLOPM_VOL, 7, 1, 0),
346 SOC_DAPM_SINGLE("HP Switch", DACR1_2_HPROUT_VOL, 7, 1, 0), 360 SOC_DAPM_SINGLE("HP Switch", DACR1_2_HPROUT_VOL, 7, 1, 0),
347 SOC_DAPM_SINGLE("HPCOM Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0), 361 SOC_DAPM_SINGLE("HPCOM Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0),
@@ -350,14 +364,18 @@ static const struct snd_kcontrol_new aic3x_right_dac_mixer_controls[] = {
350/* Left PGA Mixer */ 364/* Left PGA Mixer */
351static const struct snd_kcontrol_new aic3x_left_pga_mixer_controls[] = { 365static const struct snd_kcontrol_new aic3x_left_pga_mixer_controls[] = {
352 SOC_DAPM_SINGLE_AIC3X("Line1L Switch", LINE1L_2_LADC_CTRL, 3, 1, 1), 366 SOC_DAPM_SINGLE_AIC3X("Line1L Switch", LINE1L_2_LADC_CTRL, 3, 1, 1),
367 SOC_DAPM_SINGLE_AIC3X("Line1R Switch", LINE1R_2_LADC_CTRL, 3, 1, 1),
353 SOC_DAPM_SINGLE_AIC3X("Line2L Switch", LINE2L_2_LADC_CTRL, 3, 1, 1), 368 SOC_DAPM_SINGLE_AIC3X("Line2L Switch", LINE2L_2_LADC_CTRL, 3, 1, 1),
354 SOC_DAPM_SINGLE_AIC3X("Mic3L Switch", MIC3LR_2_LADC_CTRL, 4, 1, 1), 369 SOC_DAPM_SINGLE_AIC3X("Mic3L Switch", MIC3LR_2_LADC_CTRL, 4, 1, 1),
370 SOC_DAPM_SINGLE_AIC3X("Mic3R Switch", MIC3LR_2_LADC_CTRL, 0, 1, 1),
355}; 371};
356 372
357/* Right PGA Mixer */ 373/* Right PGA Mixer */
358static const struct snd_kcontrol_new aic3x_right_pga_mixer_controls[] = { 374static const struct snd_kcontrol_new aic3x_right_pga_mixer_controls[] = {
359 SOC_DAPM_SINGLE_AIC3X("Line1R Switch", LINE1R_2_RADC_CTRL, 3, 1, 1), 375 SOC_DAPM_SINGLE_AIC3X("Line1R Switch", LINE1R_2_RADC_CTRL, 3, 1, 1),
376 SOC_DAPM_SINGLE_AIC3X("Line1L Switch", LINE1L_2_RADC_CTRL, 3, 1, 1),
360 SOC_DAPM_SINGLE_AIC3X("Line2R Switch", LINE2R_2_RADC_CTRL, 3, 1, 1), 377 SOC_DAPM_SINGLE_AIC3X("Line2R Switch", LINE2R_2_RADC_CTRL, 3, 1, 1),
378 SOC_DAPM_SINGLE_AIC3X("Mic3L Switch", MIC3LR_2_RADC_CTRL, 4, 1, 1),
361 SOC_DAPM_SINGLE_AIC3X("Mic3R Switch", MIC3LR_2_RADC_CTRL, 0, 1, 1), 379 SOC_DAPM_SINGLE_AIC3X("Mic3R Switch", MIC3LR_2_RADC_CTRL, 0, 1, 1),
362}; 380};
363 381
@@ -379,34 +397,42 @@ SOC_DAPM_ENUM("Route", aic3x_enum[LINE2R_ENUM]);
379 397
380/* Left PGA Bypass Mixer */ 398/* Left PGA Bypass Mixer */
381static const struct snd_kcontrol_new aic3x_left_pga_bp_mixer_controls[] = { 399static const struct snd_kcontrol_new aic3x_left_pga_bp_mixer_controls[] = {
382 SOC_DAPM_SINGLE("Line Switch", PGAL_2_LLOPM_VOL, 7, 1, 0), 400 SOC_DAPM_SINGLE("LineL Switch", PGAL_2_LLOPM_VOL, 7, 1, 0),
401 SOC_DAPM_SINGLE("LineR Switch", PGAL_2_RLOPM_VOL, 7, 1, 0),
383 SOC_DAPM_SINGLE("Mono Switch", PGAL_2_MONOLOPM_VOL, 7, 1, 0), 402 SOC_DAPM_SINGLE("Mono Switch", PGAL_2_MONOLOPM_VOL, 7, 1, 0),
384 SOC_DAPM_SINGLE("HP Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0), 403 SOC_DAPM_SINGLE("HPL Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0),
385 SOC_DAPM_SINGLE("HPCOM Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0), 404 SOC_DAPM_SINGLE("HPR Switch", PGAL_2_HPROUT_VOL, 7, 1, 0),
405 SOC_DAPM_SINGLE("HPLCOM Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0),
406 SOC_DAPM_SINGLE("HPRCOM Switch", PGAL_2_HPRCOM_VOL, 7, 1, 0),
386}; 407};
387 408
388/* Right PGA Bypass Mixer */ 409/* Right PGA Bypass Mixer */
389static const struct snd_kcontrol_new aic3x_right_pga_bp_mixer_controls[] = { 410static const struct snd_kcontrol_new aic3x_right_pga_bp_mixer_controls[] = {
390 SOC_DAPM_SINGLE("Line Switch", PGAR_2_RLOPM_VOL, 7, 1, 0), 411 SOC_DAPM_SINGLE("LineL Switch", PGAR_2_LLOPM_VOL, 7, 1, 0),
412 SOC_DAPM_SINGLE("LineR Switch", PGAR_2_RLOPM_VOL, 7, 1, 0),
391 SOC_DAPM_SINGLE("Mono Switch", PGAR_2_MONOLOPM_VOL, 7, 1, 0), 413 SOC_DAPM_SINGLE("Mono Switch", PGAR_2_MONOLOPM_VOL, 7, 1, 0),
392 SOC_DAPM_SINGLE("HP Switch", PGAR_2_HPROUT_VOL, 7, 1, 0), 414 SOC_DAPM_SINGLE("HPL Switch", PGAR_2_HPLOUT_VOL, 7, 1, 0),
393 SOC_DAPM_SINGLE("HPCOM Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0), 415 SOC_DAPM_SINGLE("HPR Switch", PGAR_2_HPROUT_VOL, 7, 1, 0),
416 SOC_DAPM_SINGLE("HPLCOM Switch", PGAR_2_HPLCOM_VOL, 7, 1, 0),
417 SOC_DAPM_SINGLE("HPRCOM Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0),
394}; 418};
395 419
396/* Left Line2 Bypass Mixer */ 420/* Left Line2 Bypass Mixer */
397static const struct snd_kcontrol_new aic3x_left_line2_bp_mixer_controls[] = { 421static const struct snd_kcontrol_new aic3x_left_line2_bp_mixer_controls[] = {
398 SOC_DAPM_SINGLE("Line Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0), 422 SOC_DAPM_SINGLE("LineL Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0),
423 SOC_DAPM_SINGLE("LineR Switch", LINE2L_2_RLOPM_VOL, 7, 1, 0),
399 SOC_DAPM_SINGLE("Mono Switch", LINE2L_2_MONOLOPM_VOL, 7, 1, 0), 424 SOC_DAPM_SINGLE("Mono Switch", LINE2L_2_MONOLOPM_VOL, 7, 1, 0),
400 SOC_DAPM_SINGLE("HP Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0), 425 SOC_DAPM_SINGLE("HP Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0),
401 SOC_DAPM_SINGLE("HPCOM Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0), 426 SOC_DAPM_SINGLE("HPLCOM Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0),
402}; 427};
403 428
404/* Right Line2 Bypass Mixer */ 429/* Right Line2 Bypass Mixer */
405static const struct snd_kcontrol_new aic3x_right_line2_bp_mixer_controls[] = { 430static const struct snd_kcontrol_new aic3x_right_line2_bp_mixer_controls[] = {
406 SOC_DAPM_SINGLE("Line Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0), 431 SOC_DAPM_SINGLE("LineL Switch", LINE2R_2_LLOPM_VOL, 7, 1, 0),
432 SOC_DAPM_SINGLE("LineR Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0),
407 SOC_DAPM_SINGLE("Mono Switch", LINE2R_2_MONOLOPM_VOL, 7, 1, 0), 433 SOC_DAPM_SINGLE("Mono Switch", LINE2R_2_MONOLOPM_VOL, 7, 1, 0),
408 SOC_DAPM_SINGLE("HP Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0), 434 SOC_DAPM_SINGLE("HP Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0),
409 SOC_DAPM_SINGLE("HPCOM Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0), 435 SOC_DAPM_SINGLE("HPRCOM Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0),
410}; 436};
411 437
412static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { 438static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
@@ -439,22 +465,26 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
439 /* Mono Output */ 465 /* Mono Output */
440 SND_SOC_DAPM_PGA("Mono Out", MONOLOPM_CTRL, 0, 0, NULL, 0), 466 SND_SOC_DAPM_PGA("Mono Out", MONOLOPM_CTRL, 0, 0, NULL, 0),
441 467
442 /* Left Inputs to Left ADC */ 468 /* Inputs to Left ADC */
443 SND_SOC_DAPM_ADC("Left ADC", "Left Capture", LINE1L_2_LADC_CTRL, 2, 0), 469 SND_SOC_DAPM_ADC("Left ADC", "Left Capture", LINE1L_2_LADC_CTRL, 2, 0),
444 SND_SOC_DAPM_MIXER("Left PGA Mixer", SND_SOC_NOPM, 0, 0, 470 SND_SOC_DAPM_MIXER("Left PGA Mixer", SND_SOC_NOPM, 0, 0,
445 &aic3x_left_pga_mixer_controls[0], 471 &aic3x_left_pga_mixer_controls[0],
446 ARRAY_SIZE(aic3x_left_pga_mixer_controls)), 472 ARRAY_SIZE(aic3x_left_pga_mixer_controls)),
447 SND_SOC_DAPM_MUX("Left Line1L Mux", SND_SOC_NOPM, 0, 0, 473 SND_SOC_DAPM_MUX("Left Line1L Mux", SND_SOC_NOPM, 0, 0,
448 &aic3x_left_line1_mux_controls), 474 &aic3x_left_line1_mux_controls),
475 SND_SOC_DAPM_MUX("Left Line1R Mux", SND_SOC_NOPM, 0, 0,
476 &aic3x_left_line1_mux_controls),
449 SND_SOC_DAPM_MUX("Left Line2L Mux", SND_SOC_NOPM, 0, 0, 477 SND_SOC_DAPM_MUX("Left Line2L Mux", SND_SOC_NOPM, 0, 0,
450 &aic3x_left_line2_mux_controls), 478 &aic3x_left_line2_mux_controls),
451 479
452 /* Right Inputs to Right ADC */ 480 /* Inputs to Right ADC */
453 SND_SOC_DAPM_ADC("Right ADC", "Right Capture", 481 SND_SOC_DAPM_ADC("Right ADC", "Right Capture",
454 LINE1R_2_RADC_CTRL, 2, 0), 482 LINE1R_2_RADC_CTRL, 2, 0),
455 SND_SOC_DAPM_MIXER("Right PGA Mixer", SND_SOC_NOPM, 0, 0, 483 SND_SOC_DAPM_MIXER("Right PGA Mixer", SND_SOC_NOPM, 0, 0,
456 &aic3x_right_pga_mixer_controls[0], 484 &aic3x_right_pga_mixer_controls[0],
457 ARRAY_SIZE(aic3x_right_pga_mixer_controls)), 485 ARRAY_SIZE(aic3x_right_pga_mixer_controls)),
486 SND_SOC_DAPM_MUX("Right Line1L Mux", SND_SOC_NOPM, 0, 0,
487 &aic3x_right_line1_mux_controls),
458 SND_SOC_DAPM_MUX("Right Line1R Mux", SND_SOC_NOPM, 0, 0, 488 SND_SOC_DAPM_MUX("Right Line1R Mux", SND_SOC_NOPM, 0, 0,
459 &aic3x_right_line1_mux_controls), 489 &aic3x_right_line1_mux_controls),
460 SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0, 490 SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0,
@@ -531,7 +561,8 @@ static const struct snd_soc_dapm_route intercon[] = {
531 {"Left DAC Mux", "DAC_L2", "Left DAC"}, 561 {"Left DAC Mux", "DAC_L2", "Left DAC"},
532 {"Left DAC Mux", "DAC_L3", "Left DAC"}, 562 {"Left DAC Mux", "DAC_L3", "Left DAC"},
533 563
534 {"Left DAC_L1 Mixer", "Line Switch", "Left DAC Mux"}, 564 {"Left DAC_L1 Mixer", "LineL Switch", "Left DAC Mux"},
565 {"Left DAC_L1 Mixer", "LineR Switch", "Left DAC Mux"},
535 {"Left DAC_L1 Mixer", "Mono Switch", "Left DAC Mux"}, 566 {"Left DAC_L1 Mixer", "Mono Switch", "Left DAC Mux"},
536 {"Left DAC_L1 Mixer", "HP Switch", "Left DAC Mux"}, 567 {"Left DAC_L1 Mixer", "HP Switch", "Left DAC Mux"},
537 {"Left DAC_L1 Mixer", "HPCOM Switch", "Left DAC Mux"}, 568 {"Left DAC_L1 Mixer", "HPCOM Switch", "Left DAC Mux"},
@@ -557,7 +588,8 @@ static const struct snd_soc_dapm_route intercon[] = {
557 {"Right DAC Mux", "DAC_R2", "Right DAC"}, 588 {"Right DAC Mux", "DAC_R2", "Right DAC"},
558 {"Right DAC Mux", "DAC_R3", "Right DAC"}, 589 {"Right DAC Mux", "DAC_R3", "Right DAC"},
559 590
560 {"Right DAC_R1 Mixer", "Line Switch", "Right DAC Mux"}, 591 {"Right DAC_R1 Mixer", "LineL Switch", "Right DAC Mux"},
592 {"Right DAC_R1 Mixer", "LineR Switch", "Right DAC Mux"},
561 {"Right DAC_R1 Mixer", "Mono Switch", "Right DAC Mux"}, 593 {"Right DAC_R1 Mixer", "Mono Switch", "Right DAC Mux"},
562 {"Right DAC_R1 Mixer", "HP Switch", "Right DAC Mux"}, 594 {"Right DAC_R1 Mixer", "HP Switch", "Right DAC Mux"},
563 {"Right DAC_R1 Mixer", "HPCOM Switch", "Right DAC Mux"}, 595 {"Right DAC_R1 Mixer", "HPCOM Switch", "Right DAC Mux"},
@@ -592,8 +624,10 @@ static const struct snd_soc_dapm_route intercon[] = {
592 {"Left Line2L Mux", "differential", "LINE2L"}, 624 {"Left Line2L Mux", "differential", "LINE2L"},
593 625
594 {"Left PGA Mixer", "Line1L Switch", "Left Line1L Mux"}, 626 {"Left PGA Mixer", "Line1L Switch", "Left Line1L Mux"},
627 {"Left PGA Mixer", "Line1R Switch", "Left Line1R Mux"},
595 {"Left PGA Mixer", "Line2L Switch", "Left Line2L Mux"}, 628 {"Left PGA Mixer", "Line2L Switch", "Left Line2L Mux"},
596 {"Left PGA Mixer", "Mic3L Switch", "MIC3L"}, 629 {"Left PGA Mixer", "Mic3L Switch", "MIC3L"},
630 {"Left PGA Mixer", "Mic3R Switch", "MIC3R"},
597 631
598 {"Left ADC", NULL, "Left PGA Mixer"}, 632 {"Left ADC", NULL, "Left PGA Mixer"},
599 {"Left ADC", NULL, "GPIO1 dmic modclk"}, 633 {"Left ADC", NULL, "GPIO1 dmic modclk"},
@@ -605,18 +639,23 @@ static const struct snd_soc_dapm_route intercon[] = {
605 {"Right Line2R Mux", "single-ended", "LINE2R"}, 639 {"Right Line2R Mux", "single-ended", "LINE2R"},
606 {"Right Line2R Mux", "differential", "LINE2R"}, 640 {"Right Line2R Mux", "differential", "LINE2R"},
607 641
642 {"Right PGA Mixer", "Line1L Switch", "Right Line1L Mux"},
608 {"Right PGA Mixer", "Line1R Switch", "Right Line1R Mux"}, 643 {"Right PGA Mixer", "Line1R Switch", "Right Line1R Mux"},
609 {"Right PGA Mixer", "Line2R Switch", "Right Line2R Mux"}, 644 {"Right PGA Mixer", "Line2R Switch", "Right Line2R Mux"},
645 {"Right PGA Mixer", "Mic3L Switch", "MIC3L"},
610 {"Right PGA Mixer", "Mic3R Switch", "MIC3R"}, 646 {"Right PGA Mixer", "Mic3R Switch", "MIC3R"},
611 647
612 {"Right ADC", NULL, "Right PGA Mixer"}, 648 {"Right ADC", NULL, "Right PGA Mixer"},
613 {"Right ADC", NULL, "GPIO1 dmic modclk"}, 649 {"Right ADC", NULL, "GPIO1 dmic modclk"},
614 650
615 /* Left PGA Bypass */ 651 /* Left PGA Bypass */
616 {"Left PGA Bypass Mixer", "Line Switch", "Left PGA Mixer"}, 652 {"Left PGA Bypass Mixer", "LineL Switch", "Left PGA Mixer"},
653 {"Left PGA Bypass Mixer", "LineR Switch", "Left PGA Mixer"},
617 {"Left PGA Bypass Mixer", "Mono Switch", "Left PGA Mixer"}, 654 {"Left PGA Bypass Mixer", "Mono Switch", "Left PGA Mixer"},
618 {"Left PGA Bypass Mixer", "HP Switch", "Left PGA Mixer"}, 655 {"Left PGA Bypass Mixer", "HPL Switch", "Left PGA Mixer"},
619 {"Left PGA Bypass Mixer", "HPCOM Switch", "Left PGA Mixer"}, 656 {"Left PGA Bypass Mixer", "HPR Switch", "Left PGA Mixer"},
657 {"Left PGA Bypass Mixer", "HPLCOM Switch", "Left PGA Mixer"},
658 {"Left PGA Bypass Mixer", "HPRCOM Switch", "Left PGA Mixer"},
620 659
621 {"Left HPCOM Mux", "differential of HPLOUT", "Left PGA Bypass Mixer"}, 660 {"Left HPCOM Mux", "differential of HPLOUT", "Left PGA Bypass Mixer"},
622 {"Left HPCOM Mux", "constant VCM", "Left PGA Bypass Mixer"}, 661 {"Left HPCOM Mux", "constant VCM", "Left PGA Bypass Mixer"},
@@ -627,10 +666,13 @@ static const struct snd_soc_dapm_route intercon[] = {
627 {"Left HP Out", NULL, "Left PGA Bypass Mixer"}, 666 {"Left HP Out", NULL, "Left PGA Bypass Mixer"},
628 667
629 /* Right PGA Bypass */ 668 /* Right PGA Bypass */
630 {"Right PGA Bypass Mixer", "Line Switch", "Right PGA Mixer"}, 669 {"Right PGA Bypass Mixer", "LineL Switch", "Right PGA Mixer"},
670 {"Right PGA Bypass Mixer", "LineR Switch", "Right PGA Mixer"},
631 {"Right PGA Bypass Mixer", "Mono Switch", "Right PGA Mixer"}, 671 {"Right PGA Bypass Mixer", "Mono Switch", "Right PGA Mixer"},
632 {"Right PGA Bypass Mixer", "HP Switch", "Right PGA Mixer"}, 672 {"Right PGA Bypass Mixer", "HPL Switch", "Right PGA Mixer"},
633 {"Right PGA Bypass Mixer", "HPCOM Switch", "Right PGA Mixer"}, 673 {"Right PGA Bypass Mixer", "HPR Switch", "Right PGA Mixer"},
674 {"Right PGA Bypass Mixer", "HPLCOM Switch", "Right PGA Mixer"},
675 {"Right PGA Bypass Mixer", "HPRCOM Switch", "Right PGA Mixer"},
634 676
635 {"Right HPCOM Mux", "differential of HPROUT", "Right PGA Bypass Mixer"}, 677 {"Right HPCOM Mux", "differential of HPROUT", "Right PGA Bypass Mixer"},
636 {"Right HPCOM Mux", "constant VCM", "Right PGA Bypass Mixer"}, 678 {"Right HPCOM Mux", "constant VCM", "Right PGA Bypass Mixer"},
@@ -643,10 +685,11 @@ static const struct snd_soc_dapm_route intercon[] = {
643 {"Right HP Out", NULL, "Right PGA Bypass Mixer"}, 685 {"Right HP Out", NULL, "Right PGA Bypass Mixer"},
644 686
645 /* Left Line2 Bypass */ 687 /* Left Line2 Bypass */
646 {"Left Line2 Bypass Mixer", "Line Switch", "Left Line2L Mux"}, 688 {"Left Line2 Bypass Mixer", "LineL Switch", "Left Line2L Mux"},
689 {"Left Line2 Bypass Mixer", "LineR Switch", "Left Line2L Mux"},
647 {"Left Line2 Bypass Mixer", "Mono Switch", "Left Line2L Mux"}, 690 {"Left Line2 Bypass Mixer", "Mono Switch", "Left Line2L Mux"},
648 {"Left Line2 Bypass Mixer", "HP Switch", "Left Line2L Mux"}, 691 {"Left Line2 Bypass Mixer", "HP Switch", "Left Line2L Mux"},
649 {"Left Line2 Bypass Mixer", "HPCOM Switch", "Left Line2L Mux"}, 692 {"Left Line2 Bypass Mixer", "HPLCOM Switch", "Left Line2L Mux"},
650 693
651 {"Left HPCOM Mux", "differential of HPLOUT", "Left Line2 Bypass Mixer"}, 694 {"Left HPCOM Mux", "differential of HPLOUT", "Left Line2 Bypass Mixer"},
652 {"Left HPCOM Mux", "constant VCM", "Left Line2 Bypass Mixer"}, 695 {"Left HPCOM Mux", "constant VCM", "Left Line2 Bypass Mixer"},
@@ -657,10 +700,11 @@ static const struct snd_soc_dapm_route intercon[] = {
657 {"Left HP Out", NULL, "Left Line2 Bypass Mixer"}, 700 {"Left HP Out", NULL, "Left Line2 Bypass Mixer"},
658 701
659 /* Right Line2 Bypass */ 702 /* Right Line2 Bypass */
660 {"Right Line2 Bypass Mixer", "Line Switch", "Right Line2R Mux"}, 703 {"Right Line2 Bypass Mixer", "LineL Switch", "Right Line2R Mux"},
704 {"Right Line2 Bypass Mixer", "LineR Switch", "Right Line2R Mux"},
661 {"Right Line2 Bypass Mixer", "Mono Switch", "Right Line2R Mux"}, 705 {"Right Line2 Bypass Mixer", "Mono Switch", "Right Line2R Mux"},
662 {"Right Line2 Bypass Mixer", "HP Switch", "Right Line2R Mux"}, 706 {"Right Line2 Bypass Mixer", "HP Switch", "Right Line2R Mux"},
663 {"Right Line2 Bypass Mixer", "HPCOM Switch", "Right Line2R Mux"}, 707 {"Right Line2 Bypass Mixer", "HPRCOM Switch", "Right Line2R Mux"},
664 708
665 {"Right HPCOM Mux", "differential of HPROUT", "Right Line2 Bypass Mixer"}, 709 {"Right HPCOM Mux", "differential of HPROUT", "Right Line2 Bypass Mixer"},
666 {"Right HPCOM Mux", "constant VCM", "Right Line2 Bypass Mixer"}, 710 {"Right HPCOM Mux", "constant VCM", "Right Line2 Bypass Mixer"},
@@ -694,7 +738,8 @@ static int aic3x_add_widgets(struct snd_soc_codec *codec)
694} 738}
695 739
696static int aic3x_hw_params(struct snd_pcm_substream *substream, 740static int aic3x_hw_params(struct snd_pcm_substream *substream,
697 struct snd_pcm_hw_params *params) 741 struct snd_pcm_hw_params *params,
742 struct snd_soc_dai *dai)
698{ 743{
699 struct snd_soc_pcm_runtime *rtd = substream->private_data; 744 struct snd_soc_pcm_runtime *rtd = substream->private_data;
700 struct snd_soc_device *socdev = rtd->socdev; 745 struct snd_soc_device *socdev = rtd->socdev;
@@ -846,6 +891,7 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
846 struct snd_soc_codec *codec = codec_dai->codec; 891 struct snd_soc_codec *codec = codec_dai->codec;
847 struct aic3x_priv *aic3x = codec->private_data; 892 struct aic3x_priv *aic3x = codec->private_data;
848 u8 iface_areg, iface_breg; 893 u8 iface_areg, iface_breg;
894 int delay = 0;
849 895
850 iface_areg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLA) & 0x3f; 896 iface_areg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLA) & 0x3f;
851 iface_breg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & 0x3f; 897 iface_breg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & 0x3f;
@@ -871,6 +917,8 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
871 SND_SOC_DAIFMT_INV_MASK)) { 917 SND_SOC_DAIFMT_INV_MASK)) {
872 case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF): 918 case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF):
873 break; 919 break;
920 case (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF):
921 delay = 1;
874 case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF): 922 case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF):
875 iface_breg |= (0x01 << 6); 923 iface_breg |= (0x01 << 6);
876 break; 924 break;
@@ -887,6 +935,7 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
887 /* set iface */ 935 /* set iface */
888 aic3x_write(codec, AIC3X_ASD_INTF_CTRLA, iface_areg); 936 aic3x_write(codec, AIC3X_ASD_INTF_CTRLA, iface_areg);
889 aic3x_write(codec, AIC3X_ASD_INTF_CTRLB, iface_breg); 937 aic3x_write(codec, AIC3X_ASD_INTF_CTRLB, iface_breg);
938 aic3x_write(codec, AIC3X_ASD_INTF_CTRLC, delay);
890 939
891 return 0; 940 return 0;
892} 941}
@@ -981,14 +1030,41 @@ int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio)
981} 1030}
982EXPORT_SYMBOL_GPL(aic3x_get_gpio); 1031EXPORT_SYMBOL_GPL(aic3x_get_gpio);
983 1032
1033void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
1034 int headset_debounce, int button_debounce)
1035{
1036 u8 val;
1037
1038 val = ((detect & AIC3X_HEADSET_DETECT_MASK)
1039 << AIC3X_HEADSET_DETECT_SHIFT) |
1040 ((headset_debounce & AIC3X_HEADSET_DEBOUNCE_MASK)
1041 << AIC3X_HEADSET_DEBOUNCE_SHIFT) |
1042 ((button_debounce & AIC3X_BUTTON_DEBOUNCE_MASK)
1043 << AIC3X_BUTTON_DEBOUNCE_SHIFT);
1044
1045 if (detect & AIC3X_HEADSET_DETECT_MASK)
1046 val |= AIC3X_HEADSET_DETECT_ENABLED;
1047
1048 aic3x_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val);
1049}
1050EXPORT_SYMBOL_GPL(aic3x_set_headset_detection);
1051
984int aic3x_headset_detected(struct snd_soc_codec *codec) 1052int aic3x_headset_detected(struct snd_soc_codec *codec)
985{ 1053{
986 u8 val; 1054 u8 val;
987 aic3x_read(codec, AIC3X_RT_IRQ_FLAGS_REG, &val); 1055 aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
988 return (val >> 2) & 1; 1056 return (val >> 4) & 1;
989} 1057}
990EXPORT_SYMBOL_GPL(aic3x_headset_detected); 1058EXPORT_SYMBOL_GPL(aic3x_headset_detected);
991 1059
1060int aic3x_button_pressed(struct snd_soc_codec *codec)
1061{
1062 u8 val;
1063 aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
1064 return (val >> 5) & 1;
1065}
1066EXPORT_SYMBOL_GPL(aic3x_button_pressed);
1067
992#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000 1068#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000
993#define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 1069#define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
994 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) 1070 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
@@ -1009,8 +1085,6 @@ struct snd_soc_dai aic3x_dai = {
1009 .formats = AIC3X_FORMATS,}, 1085 .formats = AIC3X_FORMATS,},
1010 .ops = { 1086 .ops = {
1011 .hw_params = aic3x_hw_params, 1087 .hw_params = aic3x_hw_params,
1012 },
1013 .dai_ops = {
1014 .digital_mute = aic3x_mute, 1088 .digital_mute = aic3x_mute,
1015 .set_sysclk = aic3x_set_dai_sysclk, 1089 .set_sysclk = aic3x_set_dai_sysclk,
1016 .set_fmt = aic3x_set_dai_fmt, 1090 .set_fmt = aic3x_set_dai_fmt,
@@ -1152,7 +1226,7 @@ static int aic3x_init(struct snd_soc_device *socdev)
1152 1226
1153 aic3x_add_controls(codec); 1227 aic3x_add_controls(codec);
1154 aic3x_add_widgets(codec); 1228 aic3x_add_widgets(codec);
1155 ret = snd_soc_register_card(socdev); 1229 ret = snd_soc_init_card(socdev);
1156 if (ret < 0) { 1230 if (ret < 0) {
1157 printk(KERN_ERR "aic3x: failed to register card\n"); 1231 printk(KERN_ERR "aic3x: failed to register card\n");
1158 goto card_err; 1232 goto card_err;
@@ -1341,6 +1415,18 @@ struct snd_soc_codec_device soc_codec_dev_aic3x = {
1341}; 1415};
1342EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x); 1416EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x);
1343 1417
1418static int __init aic3x_modinit(void)
1419{
1420 return snd_soc_register_dai(&aic3x_dai);
1421}
1422module_init(aic3x_modinit);
1423
1424static void __exit aic3x_exit(void)
1425{
1426 snd_soc_unregister_dai(&aic3x_dai);
1427}
1428module_exit(aic3x_exit);
1429
1344MODULE_DESCRIPTION("ASoC TLV320AIC3X codec driver"); 1430MODULE_DESCRIPTION("ASoC TLV320AIC3X codec driver");
1345MODULE_AUTHOR("Vladimir Barinov"); 1431MODULE_AUTHOR("Vladimir Barinov");
1346MODULE_LICENSE("GPL"); 1432MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h
index 00a195aa02e4..ac827e578c4d 100644
--- a/sound/soc/codecs/tlv320aic3x.h
+++ b/sound/soc/codecs/tlv320aic3x.h
@@ -35,11 +35,15 @@
35#define AIC3X_ASD_INTF_CTRLA 8 35#define AIC3X_ASD_INTF_CTRLA 8
36/* Audio serial data interface control register B */ 36/* Audio serial data interface control register B */
37#define AIC3X_ASD_INTF_CTRLB 9 37#define AIC3X_ASD_INTF_CTRLB 9
38/* Audio serial data interface control register C */
39#define AIC3X_ASD_INTF_CTRLC 10
38/* Audio overflow status and PLL R value programming register */ 40/* Audio overflow status and PLL R value programming register */
39#define AIC3X_OVRF_STATUS_AND_PLLR_REG 11 41#define AIC3X_OVRF_STATUS_AND_PLLR_REG 11
40/* Audio codec digital filter control register */ 42/* Audio codec digital filter control register */
41#define AIC3X_CODEC_DFILT_CTRL 12 43#define AIC3X_CODEC_DFILT_CTRL 12
42 44/* Headset/button press detection register */
45#define AIC3X_HEADSET_DETECT_CTRL_A 13
46#define AIC3X_HEADSET_DETECT_CTRL_B 14
43/* ADC PGA Gain control registers */ 47/* ADC PGA Gain control registers */
44#define LADC_VOL 15 48#define LADC_VOL 15
45#define RADC_VOL 16 49#define RADC_VOL 16
@@ -48,7 +52,9 @@
48#define MIC3LR_2_RADC_CTRL 18 52#define MIC3LR_2_RADC_CTRL 18
49/* Line1 Input control registers */ 53/* Line1 Input control registers */
50#define LINE1L_2_LADC_CTRL 19 54#define LINE1L_2_LADC_CTRL 19
55#define LINE1R_2_LADC_CTRL 21
51#define LINE1R_2_RADC_CTRL 22 56#define LINE1R_2_RADC_CTRL 22
57#define LINE1L_2_RADC_CTRL 24
52/* Line2 Input control registers */ 58/* Line2 Input control registers */
53#define LINE2L_2_LADC_CTRL 20 59#define LINE2L_2_LADC_CTRL 20
54#define LINE2R_2_RADC_CTRL 23 60#define LINE2R_2_RADC_CTRL 23
@@ -79,6 +85,8 @@
79#define LINE2L_2_HPLOUT_VOL 45 85#define LINE2L_2_HPLOUT_VOL 45
80#define LINE2R_2_HPROUT_VOL 62 86#define LINE2R_2_HPROUT_VOL 62
81#define PGAL_2_HPLOUT_VOL 46 87#define PGAL_2_HPLOUT_VOL 46
88#define PGAL_2_HPROUT_VOL 60
89#define PGAR_2_HPLOUT_VOL 49
82#define PGAR_2_HPROUT_VOL 63 90#define PGAR_2_HPROUT_VOL 63
83#define DACL1_2_HPLOUT_VOL 47 91#define DACL1_2_HPLOUT_VOL 47
84#define DACR1_2_HPROUT_VOL 64 92#define DACR1_2_HPROUT_VOL 64
@@ -88,6 +96,8 @@
88#define LINE2L_2_HPLCOM_VOL 52 96#define LINE2L_2_HPLCOM_VOL 52
89#define LINE2R_2_HPRCOM_VOL 69 97#define LINE2R_2_HPRCOM_VOL 69
90#define PGAL_2_HPLCOM_VOL 53 98#define PGAL_2_HPLCOM_VOL 53
99#define PGAR_2_HPLCOM_VOL 56
100#define PGAL_2_HPRCOM_VOL 67
91#define PGAR_2_HPRCOM_VOL 70 101#define PGAR_2_HPRCOM_VOL 70
92#define DACL1_2_HPLCOM_VOL 54 102#define DACL1_2_HPLCOM_VOL 54
93#define DACR1_2_HPRCOM_VOL 71 103#define DACR1_2_HPRCOM_VOL 71
@@ -103,11 +113,17 @@
103#define MONOLOPM_CTRL 79 113#define MONOLOPM_CTRL 79
104/* Line Output Plus/Minus control registers */ 114/* Line Output Plus/Minus control registers */
105#define LINE2L_2_LLOPM_VOL 80 115#define LINE2L_2_LLOPM_VOL 80
116#define LINE2L_2_RLOPM_VOL 87
117#define LINE2R_2_LLOPM_VOL 83
106#define LINE2R_2_RLOPM_VOL 90 118#define LINE2R_2_RLOPM_VOL 90
107#define PGAL_2_LLOPM_VOL 81 119#define PGAL_2_LLOPM_VOL 81
120#define PGAL_2_RLOPM_VOL 88
121#define PGAR_2_LLOPM_VOL 84
108#define PGAR_2_RLOPM_VOL 91 122#define PGAR_2_RLOPM_VOL 91
109#define DACL1_2_LLOPM_VOL 82 123#define DACL1_2_LLOPM_VOL 82
124#define DACL1_2_RLOPM_VOL 89
110#define DACR1_2_RLOPM_VOL 92 125#define DACR1_2_RLOPM_VOL 92
126#define DACR1_2_LLOPM_VOL 85
111#define LLOPM_CTRL 86 127#define LLOPM_CTRL 86
112#define RLOPM_CTRL 93 128#define RLOPM_CTRL 93
113/* GPIO/IRQ registers */ 129/* GPIO/IRQ registers */
@@ -221,7 +237,49 @@ enum {
221 237
222void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state); 238void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state);
223int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio); 239int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio);
240
241/* headset detection / button API */
242
243/* The AIC3x supports detection of stereo headsets (GND + left + right signal)
244 * and cellular headsets (GND + speaker output + microphone input).
245 * It is recommended to enable MIC bias for this function to work properly.
246 * For more information, please refer to the datasheet. */
247enum {
248 AIC3X_HEADSET_DETECT_OFF = 0,
249 AIC3X_HEADSET_DETECT_STEREO = 1,
250 AIC3X_HEADSET_DETECT_CELLULAR = 2,
251 AIC3X_HEADSET_DETECT_BOTH = 3
252};
253
254enum {
255 AIC3X_HEADSET_DEBOUNCE_16MS = 0,
256 AIC3X_HEADSET_DEBOUNCE_32MS = 1,
257 AIC3X_HEADSET_DEBOUNCE_64MS = 2,
258 AIC3X_HEADSET_DEBOUNCE_128MS = 3,
259 AIC3X_HEADSET_DEBOUNCE_256MS = 4,
260 AIC3X_HEADSET_DEBOUNCE_512MS = 5
261};
262
263enum {
264 AIC3X_BUTTON_DEBOUNCE_0MS = 0,
265 AIC3X_BUTTON_DEBOUNCE_8MS = 1,
266 AIC3X_BUTTON_DEBOUNCE_16MS = 2,
267 AIC3X_BUTTON_DEBOUNCE_32MS = 3
268};
269
270#define AIC3X_HEADSET_DETECT_ENABLED 0x80
271#define AIC3X_HEADSET_DETECT_SHIFT 5
272#define AIC3X_HEADSET_DETECT_MASK 3
273#define AIC3X_HEADSET_DEBOUNCE_SHIFT 2
274#define AIC3X_HEADSET_DEBOUNCE_MASK 7
275#define AIC3X_BUTTON_DEBOUNCE_SHIFT 0
276#define AIC3X_BUTTON_DEBOUNCE_MASK 3
277
278/* see the enums above for valid parameters to this function */
279void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
280 int headset_debounce, int button_debounce);
224int aic3x_headset_detected(struct snd_soc_codec *codec); 281int aic3x_headset_detected(struct snd_soc_codec *codec);
282int aic3x_button_pressed(struct snd_soc_codec *codec);
225 283
226struct aic3x_setup_data { 284struct aic3x_setup_data {
227 int i2c_bus; 285 int i2c_bus;
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
new file mode 100644
index 000000000000..51848880504a
--- /dev/null
+++ b/sound/soc/codecs/twl4030.c
@@ -0,0 +1,1317 @@
1/*
2 * ALSA SoC TWL4030 codec driver
3 *
4 * Author: Steve Sakoman, <steve@sakoman.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * 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., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/module.h>
23#include <linux/moduleparam.h>
24#include <linux/init.h>
25#include <linux/delay.h>
26#include <linux/pm.h>
27#include <linux/i2c.h>
28#include <linux/platform_device.h>
29#include <linux/i2c/twl4030.h>
30#include <sound/core.h>
31#include <sound/pcm.h>
32#include <sound/pcm_params.h>
33#include <sound/soc.h>
34#include <sound/soc-dapm.h>
35#include <sound/initval.h>
36#include <sound/tlv.h>
37
38#include "twl4030.h"
39
40/*
41 * twl4030 register cache & default register settings
42 */
43static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
44 0x00, /* this register not used */
45 0x93, /* REG_CODEC_MODE (0x1) */
46 0xc3, /* REG_OPTION (0x2) */
47 0x00, /* REG_UNKNOWN (0x3) */
48 0x00, /* REG_MICBIAS_CTL (0x4) */
49 0x20, /* REG_ANAMICL (0x5) */
50 0x00, /* REG_ANAMICR (0x6) */
51 0x00, /* REG_AVADC_CTL (0x7) */
52 0x00, /* REG_ADCMICSEL (0x8) */
53 0x00, /* REG_DIGMIXING (0x9) */
54 0x0c, /* REG_ATXL1PGA (0xA) */
55 0x0c, /* REG_ATXR1PGA (0xB) */
56 0x00, /* REG_AVTXL2PGA (0xC) */
57 0x00, /* REG_AVTXR2PGA (0xD) */
58 0x01, /* REG_AUDIO_IF (0xE) */
59 0x00, /* REG_VOICE_IF (0xF) */
60 0x00, /* REG_ARXR1PGA (0x10) */
61 0x00, /* REG_ARXL1PGA (0x11) */
62 0x6c, /* REG_ARXR2PGA (0x12) */
63 0x6c, /* REG_ARXL2PGA (0x13) */
64 0x00, /* REG_VRXPGA (0x14) */
65 0x00, /* REG_VSTPGA (0x15) */
66 0x00, /* REG_VRX2ARXPGA (0x16) */
67 0x0c, /* REG_AVDAC_CTL (0x17) */
68 0x00, /* REG_ARX2VTXPGA (0x18) */
69 0x00, /* REG_ARXL1_APGA_CTL (0x19) */
70 0x00, /* REG_ARXR1_APGA_CTL (0x1A) */
71 0x4b, /* REG_ARXL2_APGA_CTL (0x1B) */
72 0x4b, /* REG_ARXR2_APGA_CTL (0x1C) */
73 0x00, /* REG_ATX2ARXPGA (0x1D) */
74 0x00, /* REG_BT_IF (0x1E) */
75 0x00, /* REG_BTPGA (0x1F) */
76 0x00, /* REG_BTSTPGA (0x20) */
77 0x00, /* REG_EAR_CTL (0x21) */
78 0x24, /* REG_HS_SEL (0x22) */
79 0x0a, /* REG_HS_GAIN_SET (0x23) */
80 0x00, /* REG_HS_POPN_SET (0x24) */
81 0x00, /* REG_PREDL_CTL (0x25) */
82 0x00, /* REG_PREDR_CTL (0x26) */
83 0x00, /* REG_PRECKL_CTL (0x27) */
84 0x00, /* REG_PRECKR_CTL (0x28) */
85 0x00, /* REG_HFL_CTL (0x29) */
86 0x00, /* REG_HFR_CTL (0x2A) */
87 0x00, /* REG_ALC_CTL (0x2B) */
88 0x00, /* REG_ALC_SET1 (0x2C) */
89 0x00, /* REG_ALC_SET2 (0x2D) */
90 0x00, /* REG_BOOST_CTL (0x2E) */
91 0x00, /* REG_SOFTVOL_CTL (0x2F) */
92 0x00, /* REG_DTMF_FREQSEL (0x30) */
93 0x00, /* REG_DTMF_TONEXT1H (0x31) */
94 0x00, /* REG_DTMF_TONEXT1L (0x32) */
95 0x00, /* REG_DTMF_TONEXT2H (0x33) */
96 0x00, /* REG_DTMF_TONEXT2L (0x34) */
97 0x00, /* REG_DTMF_TONOFF (0x35) */
98 0x00, /* REG_DTMF_WANONOFF (0x36) */
99 0x00, /* REG_I2S_RX_SCRAMBLE_H (0x37) */
100 0x00, /* REG_I2S_RX_SCRAMBLE_M (0x38) */
101 0x00, /* REG_I2S_RX_SCRAMBLE_L (0x39) */
102 0x16, /* REG_APLL_CTL (0x3A) */
103 0x00, /* REG_DTMF_CTL (0x3B) */
104 0x00, /* REG_DTMF_PGA_CTL2 (0x3C) */
105 0x00, /* REG_DTMF_PGA_CTL1 (0x3D) */
106 0x00, /* REG_MISC_SET_1 (0x3E) */
107 0x00, /* REG_PCMBTMUX (0x3F) */
108 0x00, /* not used (0x40) */
109 0x00, /* not used (0x41) */
110 0x00, /* not used (0x42) */
111 0x00, /* REG_RX_PATH_SEL (0x43) */
112 0x00, /* REG_VDL_APGA_CTL (0x44) */
113 0x00, /* REG_VIBRA_CTL (0x45) */
114 0x00, /* REG_VIBRA_SET (0x46) */
115 0x00, /* REG_VIBRA_PWM_SET (0x47) */
116 0x00, /* REG_ANAMIC_GAIN (0x48) */
117 0x00, /* REG_MISC_SET_2 (0x49) */
118};
119
120/*
121 * read twl4030 register cache
122 */
123static inline unsigned int twl4030_read_reg_cache(struct snd_soc_codec *codec,
124 unsigned int reg)
125{
126 u8 *cache = codec->reg_cache;
127
128 return cache[reg];
129}
130
131/*
132 * write twl4030 register cache
133 */
134static inline void twl4030_write_reg_cache(struct snd_soc_codec *codec,
135 u8 reg, u8 value)
136{
137 u8 *cache = codec->reg_cache;
138
139 if (reg >= TWL4030_CACHEREGNUM)
140 return;
141 cache[reg] = value;
142}
143
144/*
145 * write to the twl4030 register space
146 */
147static int twl4030_write(struct snd_soc_codec *codec,
148 unsigned int reg, unsigned int value)
149{
150 twl4030_write_reg_cache(codec, reg, value);
151 return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg);
152}
153
154static void twl4030_clear_codecpdz(struct snd_soc_codec *codec)
155{
156 u8 mode;
157
158 mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
159 twl4030_write(codec, TWL4030_REG_CODEC_MODE,
160 mode & ~TWL4030_CODECPDZ);
161
162 /* REVISIT: this delay is present in TI sample drivers */
163 /* but there seems to be no TRM requirement for it */
164 udelay(10);
165}
166
167static void twl4030_set_codecpdz(struct snd_soc_codec *codec)
168{
169 u8 mode;
170
171 mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
172 twl4030_write(codec, TWL4030_REG_CODEC_MODE,
173 mode | TWL4030_CODECPDZ);
174
175 /* REVISIT: this delay is present in TI sample drivers */
176 /* but there seems to be no TRM requirement for it */
177 udelay(10);
178}
179
180static void twl4030_init_chip(struct snd_soc_codec *codec)
181{
182 int i;
183
184 /* clear CODECPDZ prior to setting register defaults */
185 twl4030_clear_codecpdz(codec);
186
187 /* set all audio section registers to reasonable defaults */
188 for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++)
189 twl4030_write(codec, i, twl4030_reg[i]);
190
191}
192
193/* Earpiece */
194static const char *twl4030_earpiece_texts[] =
195 {"Off", "DACL1", "DACL2", "Invalid", "DACR1"};
196
197static const struct soc_enum twl4030_earpiece_enum =
198 SOC_ENUM_SINGLE(TWL4030_REG_EAR_CTL, 1,
199 ARRAY_SIZE(twl4030_earpiece_texts),
200 twl4030_earpiece_texts);
201
202static const struct snd_kcontrol_new twl4030_dapm_earpiece_control =
203SOC_DAPM_ENUM("Route", twl4030_earpiece_enum);
204
205/* PreDrive Left */
206static const char *twl4030_predrivel_texts[] =
207 {"Off", "DACL1", "DACL2", "Invalid", "DACR2"};
208
209static const struct soc_enum twl4030_predrivel_enum =
210 SOC_ENUM_SINGLE(TWL4030_REG_PREDL_CTL, 1,
211 ARRAY_SIZE(twl4030_predrivel_texts),
212 twl4030_predrivel_texts);
213
214static const struct snd_kcontrol_new twl4030_dapm_predrivel_control =
215SOC_DAPM_ENUM("Route", twl4030_predrivel_enum);
216
217/* PreDrive Right */
218static const char *twl4030_predriver_texts[] =
219 {"Off", "DACR1", "DACR2", "Invalid", "DACL2"};
220
221static const struct soc_enum twl4030_predriver_enum =
222 SOC_ENUM_SINGLE(TWL4030_REG_PREDR_CTL, 1,
223 ARRAY_SIZE(twl4030_predriver_texts),
224 twl4030_predriver_texts);
225
226static const struct snd_kcontrol_new twl4030_dapm_predriver_control =
227SOC_DAPM_ENUM("Route", twl4030_predriver_enum);
228
229/* Headset Left */
230static const char *twl4030_hsol_texts[] =
231 {"Off", "DACL1", "DACL2"};
232
233static const struct soc_enum twl4030_hsol_enum =
234 SOC_ENUM_SINGLE(TWL4030_REG_HS_SEL, 1,
235 ARRAY_SIZE(twl4030_hsol_texts),
236 twl4030_hsol_texts);
237
238static const struct snd_kcontrol_new twl4030_dapm_hsol_control =
239SOC_DAPM_ENUM("Route", twl4030_hsol_enum);
240
241/* Headset Right */
242static const char *twl4030_hsor_texts[] =
243 {"Off", "DACR1", "DACR2"};
244
245static const struct soc_enum twl4030_hsor_enum =
246 SOC_ENUM_SINGLE(TWL4030_REG_HS_SEL, 4,
247 ARRAY_SIZE(twl4030_hsor_texts),
248 twl4030_hsor_texts);
249
250static const struct snd_kcontrol_new twl4030_dapm_hsor_control =
251SOC_DAPM_ENUM("Route", twl4030_hsor_enum);
252
253/* Carkit Left */
254static const char *twl4030_carkitl_texts[] =
255 {"Off", "DACL1", "DACL2"};
256
257static const struct soc_enum twl4030_carkitl_enum =
258 SOC_ENUM_SINGLE(TWL4030_REG_PRECKL_CTL, 1,
259 ARRAY_SIZE(twl4030_carkitl_texts),
260 twl4030_carkitl_texts);
261
262static const struct snd_kcontrol_new twl4030_dapm_carkitl_control =
263SOC_DAPM_ENUM("Route", twl4030_carkitl_enum);
264
265/* Carkit Right */
266static const char *twl4030_carkitr_texts[] =
267 {"Off", "DACR1", "DACR2"};
268
269static const struct soc_enum twl4030_carkitr_enum =
270 SOC_ENUM_SINGLE(TWL4030_REG_PRECKR_CTL, 1,
271 ARRAY_SIZE(twl4030_carkitr_texts),
272 twl4030_carkitr_texts);
273
274static const struct snd_kcontrol_new twl4030_dapm_carkitr_control =
275SOC_DAPM_ENUM("Route", twl4030_carkitr_enum);
276
277/* Handsfree Left */
278static const char *twl4030_handsfreel_texts[] =
279 {"Voice", "DACL1", "DACL2", "DACR2"};
280
281static const struct soc_enum twl4030_handsfreel_enum =
282 SOC_ENUM_SINGLE(TWL4030_REG_HFL_CTL, 0,
283 ARRAY_SIZE(twl4030_handsfreel_texts),
284 twl4030_handsfreel_texts);
285
286static const struct snd_kcontrol_new twl4030_dapm_handsfreel_control =
287SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum);
288
289/* Handsfree Right */
290static const char *twl4030_handsfreer_texts[] =
291 {"Voice", "DACR1", "DACR2", "DACL2"};
292
293static const struct soc_enum twl4030_handsfreer_enum =
294 SOC_ENUM_SINGLE(TWL4030_REG_HFR_CTL, 0,
295 ARRAY_SIZE(twl4030_handsfreer_texts),
296 twl4030_handsfreer_texts);
297
298static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control =
299SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum);
300
301static int outmixer_event(struct snd_soc_dapm_widget *w,
302 struct snd_kcontrol *kcontrol, int event)
303{
304 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
305 int ret = 0;
306 int val;
307
308 switch (e->reg) {
309 case TWL4030_REG_PREDL_CTL:
310 case TWL4030_REG_PREDR_CTL:
311 case TWL4030_REG_EAR_CTL:
312 val = w->value >> e->shift_l;
313 if (val == 3) {
314 printk(KERN_WARNING
315 "Invalid MUX setting for register 0x%02x (%d)\n",
316 e->reg, val);
317 ret = -1;
318 }
319 break;
320 }
321
322 return ret;
323}
324
325static int handsfree_event(struct snd_soc_dapm_widget *w,
326 struct snd_kcontrol *kcontrol, int event)
327{
328 struct soc_enum *e = (struct soc_enum *)w->kcontrols->private_value;
329 unsigned char hs_ctl;
330
331 hs_ctl = twl4030_read_reg_cache(w->codec, e->reg);
332
333 if (hs_ctl & TWL4030_HF_CTL_REF_EN) {
334 hs_ctl |= TWL4030_HF_CTL_RAMP_EN;
335 twl4030_write(w->codec, e->reg, hs_ctl);
336 hs_ctl |= TWL4030_HF_CTL_LOOP_EN;
337 twl4030_write(w->codec, e->reg, hs_ctl);
338 hs_ctl |= TWL4030_HF_CTL_HB_EN;
339 twl4030_write(w->codec, e->reg, hs_ctl);
340 } else {
341 hs_ctl &= ~(TWL4030_HF_CTL_RAMP_EN | TWL4030_HF_CTL_LOOP_EN
342 | TWL4030_HF_CTL_HB_EN);
343 twl4030_write(w->codec, e->reg, hs_ctl);
344 }
345
346 return 0;
347}
348
349/*
350 * Some of the gain controls in TWL (mostly those which are associated with
351 * the outputs) are implemented in an interesting way:
352 * 0x0 : Power down (mute)
353 * 0x1 : 6dB
354 * 0x2 : 0 dB
355 * 0x3 : -6 dB
356 * Inverting not going to help with these.
357 * Custom volsw and volsw_2r get/put functions to handle these gain bits.
358 */
359#define SOC_DOUBLE_TLV_TWL4030(xname, xreg, shift_left, shift_right, xmax,\
360 xinvert, tlv_array) \
361{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
362 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
363 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
364 .tlv.p = (tlv_array), \
365 .info = snd_soc_info_volsw, \
366 .get = snd_soc_get_volsw_twl4030, \
367 .put = snd_soc_put_volsw_twl4030, \
368 .private_value = (unsigned long)&(struct soc_mixer_control) \
369 {.reg = xreg, .shift = shift_left, .rshift = shift_right,\
370 .max = xmax, .invert = xinvert} }
371#define SOC_DOUBLE_R_TLV_TWL4030(xname, reg_left, reg_right, xshift, xmax,\
372 xinvert, tlv_array) \
373{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
374 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
375 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
376 .tlv.p = (tlv_array), \
377 .info = snd_soc_info_volsw_2r, \
378 .get = snd_soc_get_volsw_r2_twl4030,\
379 .put = snd_soc_put_volsw_r2_twl4030, \
380 .private_value = (unsigned long)&(struct soc_mixer_control) \
381 {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
382 .rshift = xshift, .max = xmax, .invert = xinvert} }
383#define SOC_SINGLE_TLV_TWL4030(xname, xreg, xshift, xmax, xinvert, tlv_array) \
384 SOC_DOUBLE_TLV_TWL4030(xname, xreg, xshift, xshift, xmax, \
385 xinvert, tlv_array)
386
387static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol,
388 struct snd_ctl_elem_value *ucontrol)
389{
390 struct soc_mixer_control *mc =
391 (struct soc_mixer_control *)kcontrol->private_value;
392 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
393 unsigned int reg = mc->reg;
394 unsigned int shift = mc->shift;
395 unsigned int rshift = mc->rshift;
396 int max = mc->max;
397 int mask = (1 << fls(max)) - 1;
398
399 ucontrol->value.integer.value[0] =
400 (snd_soc_read(codec, reg) >> shift) & mask;
401 if (ucontrol->value.integer.value[0])
402 ucontrol->value.integer.value[0] =
403 max + 1 - ucontrol->value.integer.value[0];
404
405 if (shift != rshift) {
406 ucontrol->value.integer.value[1] =
407 (snd_soc_read(codec, reg) >> rshift) & mask;
408 if (ucontrol->value.integer.value[1])
409 ucontrol->value.integer.value[1] =
410 max + 1 - ucontrol->value.integer.value[1];
411 }
412
413 return 0;
414}
415
416static int snd_soc_put_volsw_twl4030(struct snd_kcontrol *kcontrol,
417 struct snd_ctl_elem_value *ucontrol)
418{
419 struct soc_mixer_control *mc =
420 (struct soc_mixer_control *)kcontrol->private_value;
421 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
422 unsigned int reg = mc->reg;
423 unsigned int shift = mc->shift;
424 unsigned int rshift = mc->rshift;
425 int max = mc->max;
426 int mask = (1 << fls(max)) - 1;
427 unsigned short val, val2, val_mask;
428
429 val = (ucontrol->value.integer.value[0] & mask);
430
431 val_mask = mask << shift;
432 if (val)
433 val = max + 1 - val;
434 val = val << shift;
435 if (shift != rshift) {
436 val2 = (ucontrol->value.integer.value[1] & mask);
437 val_mask |= mask << rshift;
438 if (val2)
439 val2 = max + 1 - val2;
440 val |= val2 << rshift;
441 }
442 return snd_soc_update_bits(codec, reg, val_mask, val);
443}
444
445static int snd_soc_get_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
446 struct snd_ctl_elem_value *ucontrol)
447{
448 struct soc_mixer_control *mc =
449 (struct soc_mixer_control *)kcontrol->private_value;
450 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
451 unsigned int reg = mc->reg;
452 unsigned int reg2 = mc->rreg;
453 unsigned int shift = mc->shift;
454 int max = mc->max;
455 int mask = (1<<fls(max))-1;
456
457 ucontrol->value.integer.value[0] =
458 (snd_soc_read(codec, reg) >> shift) & mask;
459 ucontrol->value.integer.value[1] =
460 (snd_soc_read(codec, reg2) >> shift) & mask;
461
462 if (ucontrol->value.integer.value[0])
463 ucontrol->value.integer.value[0] =
464 max + 1 - ucontrol->value.integer.value[0];
465 if (ucontrol->value.integer.value[1])
466 ucontrol->value.integer.value[1] =
467 max + 1 - ucontrol->value.integer.value[1];
468
469 return 0;
470}
471
472static int snd_soc_put_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
473 struct snd_ctl_elem_value *ucontrol)
474{
475 struct soc_mixer_control *mc =
476 (struct soc_mixer_control *)kcontrol->private_value;
477 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
478 unsigned int reg = mc->reg;
479 unsigned int reg2 = mc->rreg;
480 unsigned int shift = mc->shift;
481 int max = mc->max;
482 int mask = (1 << fls(max)) - 1;
483 int err;
484 unsigned short val, val2, val_mask;
485
486 val_mask = mask << shift;
487 val = (ucontrol->value.integer.value[0] & mask);
488 val2 = (ucontrol->value.integer.value[1] & mask);
489
490 if (val)
491 val = max + 1 - val;
492 if (val2)
493 val2 = max + 1 - val2;
494
495 val = val << shift;
496 val2 = val2 << shift;
497
498 err = snd_soc_update_bits(codec, reg, val_mask, val);
499 if (err < 0)
500 return err;
501
502 err = snd_soc_update_bits(codec, reg2, val_mask, val2);
503 return err;
504}
505
506static int twl4030_get_left_input(struct snd_kcontrol *kcontrol,
507 struct snd_ctl_elem_value *ucontrol)
508{
509 struct snd_soc_codec *codec = kcontrol->private_data;
510 u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
511 int result = 0;
512
513 /* one bit must be set a time */
514 reg &= TWL4030_CKMIC_EN | TWL4030_AUXL_EN | TWL4030_HSMIC_EN
515 | TWL4030_MAINMIC_EN;
516 if (reg != 0) {
517 result++;
518 while ((reg & 1) == 0) {
519 result++;
520 reg >>= 1;
521 }
522 }
523
524 ucontrol->value.integer.value[0] = result;
525 return 0;
526}
527
528static int twl4030_put_left_input(struct snd_kcontrol *kcontrol,
529 struct snd_ctl_elem_value *ucontrol)
530{
531 struct snd_soc_codec *codec = kcontrol->private_data;
532 int value = ucontrol->value.integer.value[0];
533 u8 anamicl, micbias, avadc_ctl;
534
535 anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
536 anamicl &= ~(TWL4030_CKMIC_EN | TWL4030_AUXL_EN | TWL4030_HSMIC_EN
537 | TWL4030_MAINMIC_EN);
538 micbias = twl4030_read_reg_cache(codec, TWL4030_REG_MICBIAS_CTL);
539 micbias &= ~(TWL4030_HSMICBIAS_EN | TWL4030_MICBIAS1_EN);
540 avadc_ctl = twl4030_read_reg_cache(codec, TWL4030_REG_AVADC_CTL);
541
542 switch (value) {
543 case 1:
544 anamicl |= TWL4030_MAINMIC_EN;
545 micbias |= TWL4030_MICBIAS1_EN;
546 break;
547 case 2:
548 anamicl |= TWL4030_HSMIC_EN;
549 micbias |= TWL4030_HSMICBIAS_EN;
550 break;
551 case 3:
552 anamicl |= TWL4030_AUXL_EN;
553 break;
554 case 4:
555 anamicl |= TWL4030_CKMIC_EN;
556 break;
557 default:
558 break;
559 }
560
561 /* If some input is selected, enable amp and ADC */
562 if (value != 0) {
563 anamicl |= TWL4030_MICAMPL_EN;
564 avadc_ctl |= TWL4030_ADCL_EN;
565 } else {
566 anamicl &= ~TWL4030_MICAMPL_EN;
567 avadc_ctl &= ~TWL4030_ADCL_EN;
568 }
569
570 twl4030_write(codec, TWL4030_REG_ANAMICL, anamicl);
571 twl4030_write(codec, TWL4030_REG_MICBIAS_CTL, micbias);
572 twl4030_write(codec, TWL4030_REG_AVADC_CTL, avadc_ctl);
573
574 return 1;
575}
576
577static int twl4030_get_right_input(struct snd_kcontrol *kcontrol,
578 struct snd_ctl_elem_value *ucontrol)
579{
580 struct snd_soc_codec *codec = kcontrol->private_data;
581 u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICR);
582 int value = 0;
583
584 reg &= TWL4030_SUBMIC_EN|TWL4030_AUXR_EN;
585 switch (reg) {
586 case TWL4030_SUBMIC_EN:
587 value = 1;
588 break;
589 case TWL4030_AUXR_EN:
590 value = 2;
591 break;
592 default:
593 break;
594 }
595
596 ucontrol->value.integer.value[0] = value;
597 return 0;
598}
599
600static int twl4030_put_right_input(struct snd_kcontrol *kcontrol,
601 struct snd_ctl_elem_value *ucontrol)
602{
603 struct snd_soc_codec *codec = kcontrol->private_data;
604 int value = ucontrol->value.integer.value[0];
605 u8 anamicr, micbias, avadc_ctl;
606
607 anamicr = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICR);
608 anamicr &= ~(TWL4030_SUBMIC_EN|TWL4030_AUXR_EN);
609 micbias = twl4030_read_reg_cache(codec, TWL4030_REG_MICBIAS_CTL);
610 micbias &= ~TWL4030_MICBIAS2_EN;
611 avadc_ctl = twl4030_read_reg_cache(codec, TWL4030_REG_AVADC_CTL);
612
613 switch (value) {
614 case 1:
615 anamicr |= TWL4030_SUBMIC_EN;
616 micbias |= TWL4030_MICBIAS2_EN;
617 break;
618 case 2:
619 anamicr |= TWL4030_AUXR_EN;
620 break;
621 default:
622 break;
623 }
624
625 if (value != 0) {
626 anamicr |= TWL4030_MICAMPR_EN;
627 avadc_ctl |= TWL4030_ADCR_EN;
628 } else {
629 anamicr &= ~TWL4030_MICAMPR_EN;
630 avadc_ctl &= ~TWL4030_ADCR_EN;
631 }
632
633 twl4030_write(codec, TWL4030_REG_ANAMICR, anamicr);
634 twl4030_write(codec, TWL4030_REG_MICBIAS_CTL, micbias);
635 twl4030_write(codec, TWL4030_REG_AVADC_CTL, avadc_ctl);
636
637 return 1;
638}
639
640static const char *twl4030_left_in_sel[] = {
641 "None",
642 "Main Mic",
643 "Headset Mic",
644 "Line In",
645 "Carkit Mic",
646};
647
648static const char *twl4030_right_in_sel[] = {
649 "None",
650 "Sub Mic",
651 "Line In",
652};
653
654static const struct soc_enum twl4030_left_input_mux =
655 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl4030_left_in_sel),
656 twl4030_left_in_sel);
657
658static const struct soc_enum twl4030_right_input_mux =
659 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl4030_right_in_sel),
660 twl4030_right_in_sel);
661
662/*
663 * FGAIN volume control:
664 * from -62 to 0 dB in 1 dB steps (mute instead of -63 dB)
665 */
666static DECLARE_TLV_DB_SCALE(digital_fine_tlv, -6300, 100, 1);
667
668/*
669 * CGAIN volume control:
670 * 0 dB to 12 dB in 6 dB steps
671 * value 2 and 3 means 12 dB
672 */
673static DECLARE_TLV_DB_SCALE(digital_coarse_tlv, 0, 600, 0);
674
675/*
676 * Analog playback gain
677 * -24 dB to 12 dB in 2 dB steps
678 */
679static DECLARE_TLV_DB_SCALE(analog_tlv, -2400, 200, 0);
680
681/*
682 * Gain controls tied to outputs
683 * -6 dB to 6 dB in 6 dB steps (mute instead of -12)
684 */
685static DECLARE_TLV_DB_SCALE(output_tvl, -1200, 600, 1);
686
687/*
688 * Capture gain after the ADCs
689 * from 0 dB to 31 dB in 1 dB steps
690 */
691static DECLARE_TLV_DB_SCALE(digital_capture_tlv, 0, 100, 0);
692
693/*
694 * Gain control for input amplifiers
695 * 0 dB to 30 dB in 6 dB steps
696 */
697static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0);
698
699static const struct snd_kcontrol_new twl4030_snd_controls[] = {
700 /* Common playback gain controls */
701 SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume",
702 TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA,
703 0, 0x3f, 0, digital_fine_tlv),
704 SOC_DOUBLE_R_TLV("DAC2 Digital Fine Playback Volume",
705 TWL4030_REG_ARXL2PGA, TWL4030_REG_ARXR2PGA,
706 0, 0x3f, 0, digital_fine_tlv),
707
708 SOC_DOUBLE_R_TLV("DAC1 Digital Coarse Playback Volume",
709 TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA,
710 6, 0x2, 0, digital_coarse_tlv),
711 SOC_DOUBLE_R_TLV("DAC2 Digital Coarse Playback Volume",
712 TWL4030_REG_ARXL2PGA, TWL4030_REG_ARXR2PGA,
713 6, 0x2, 0, digital_coarse_tlv),
714
715 SOC_DOUBLE_R_TLV("DAC1 Analog Playback Volume",
716 TWL4030_REG_ARXL1_APGA_CTL, TWL4030_REG_ARXR1_APGA_CTL,
717 3, 0x12, 1, analog_tlv),
718 SOC_DOUBLE_R_TLV("DAC2 Analog Playback Volume",
719 TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL,
720 3, 0x12, 1, analog_tlv),
721 SOC_DOUBLE_R("DAC1 Analog Playback Switch",
722 TWL4030_REG_ARXL1_APGA_CTL, TWL4030_REG_ARXR1_APGA_CTL,
723 1, 1, 0),
724 SOC_DOUBLE_R("DAC2 Analog Playback Switch",
725 TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL,
726 1, 1, 0),
727
728 /* Separate output gain controls */
729 SOC_DOUBLE_R_TLV_TWL4030("PreDriv Playback Volume",
730 TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL,
731 4, 3, 0, output_tvl),
732
733 SOC_DOUBLE_TLV_TWL4030("Headset Playback Volume",
734 TWL4030_REG_HS_GAIN_SET, 0, 2, 3, 0, output_tvl),
735
736 SOC_DOUBLE_R_TLV_TWL4030("Carkit Playback Volume",
737 TWL4030_REG_PRECKL_CTL, TWL4030_REG_PRECKR_CTL,
738 4, 3, 0, output_tvl),
739
740 SOC_SINGLE_TLV_TWL4030("Earpiece Playback Volume",
741 TWL4030_REG_EAR_CTL, 4, 3, 0, output_tvl),
742
743 /* Common capture gain controls */
744 SOC_DOUBLE_R_TLV("Capture Volume",
745 TWL4030_REG_ATXL1PGA, TWL4030_REG_ATXR1PGA,
746 0, 0x1f, 0, digital_capture_tlv),
747
748 SOC_DOUBLE_TLV("Input Boost Volume", TWL4030_REG_ANAMIC_GAIN,
749 0, 3, 5, 0, input_gain_tlv),
750
751 /* Input source controls */
752 SOC_ENUM_EXT("Left Input Source", twl4030_left_input_mux,
753 twl4030_get_left_input, twl4030_put_left_input),
754 SOC_ENUM_EXT("Right Input Source", twl4030_right_input_mux,
755 twl4030_get_right_input, twl4030_put_right_input),
756};
757
758/* add non dapm controls */
759static int twl4030_add_controls(struct snd_soc_codec *codec)
760{
761 int err, i;
762
763 for (i = 0; i < ARRAY_SIZE(twl4030_snd_controls); i++) {
764 err = snd_ctl_add(codec->card,
765 snd_soc_cnew(&twl4030_snd_controls[i],
766 codec, NULL));
767 if (err < 0)
768 return err;
769 }
770
771 return 0;
772}
773
774static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
775 SND_SOC_DAPM_INPUT("INL"),
776 SND_SOC_DAPM_INPUT("INR"),
777
778 SND_SOC_DAPM_OUTPUT("OUTL"),
779 SND_SOC_DAPM_OUTPUT("OUTR"),
780 SND_SOC_DAPM_OUTPUT("EARPIECE"),
781 SND_SOC_DAPM_OUTPUT("PREDRIVEL"),
782 SND_SOC_DAPM_OUTPUT("PREDRIVER"),
783 SND_SOC_DAPM_OUTPUT("HSOL"),
784 SND_SOC_DAPM_OUTPUT("HSOR"),
785 SND_SOC_DAPM_OUTPUT("CARKITL"),
786 SND_SOC_DAPM_OUTPUT("CARKITR"),
787 SND_SOC_DAPM_OUTPUT("HFL"),
788 SND_SOC_DAPM_OUTPUT("HFR"),
789
790 /* DACs */
791 SND_SOC_DAPM_DAC("DAC Right1", "Right Front Playback",
792 TWL4030_REG_AVDAC_CTL, 0, 0),
793 SND_SOC_DAPM_DAC("DAC Left1", "Left Front Playback",
794 TWL4030_REG_AVDAC_CTL, 1, 0),
795 SND_SOC_DAPM_DAC("DAC Right2", "Right Rear Playback",
796 TWL4030_REG_AVDAC_CTL, 2, 0),
797 SND_SOC_DAPM_DAC("DAC Left2", "Left Rear Playback",
798 TWL4030_REG_AVDAC_CTL, 3, 0),
799
800 /* Analog PGAs */
801 SND_SOC_DAPM_PGA("ARXR1_APGA", TWL4030_REG_ARXR1_APGA_CTL,
802 0, 0, NULL, 0),
803 SND_SOC_DAPM_PGA("ARXL1_APGA", TWL4030_REG_ARXL1_APGA_CTL,
804 0, 0, NULL, 0),
805 SND_SOC_DAPM_PGA("ARXR2_APGA", TWL4030_REG_ARXR2_APGA_CTL,
806 0, 0, NULL, 0),
807 SND_SOC_DAPM_PGA("ARXL2_APGA", TWL4030_REG_ARXL2_APGA_CTL,
808 0, 0, NULL, 0),
809
810 /* Output MUX controls */
811 /* Earpiece */
812 SND_SOC_DAPM_MUX_E("Earpiece Mux", SND_SOC_NOPM, 0, 0,
813 &twl4030_dapm_earpiece_control, outmixer_event,
814 SND_SOC_DAPM_PRE_REG),
815 /* PreDrivL/R */
816 SND_SOC_DAPM_MUX_E("PredriveL Mux", SND_SOC_NOPM, 0, 0,
817 &twl4030_dapm_predrivel_control, outmixer_event,
818 SND_SOC_DAPM_PRE_REG),
819 SND_SOC_DAPM_MUX_E("PredriveR Mux", SND_SOC_NOPM, 0, 0,
820 &twl4030_dapm_predriver_control, outmixer_event,
821 SND_SOC_DAPM_PRE_REG),
822 /* HeadsetL/R */
823 SND_SOC_DAPM_MUX("HeadsetL Mux", SND_SOC_NOPM, 0, 0,
824 &twl4030_dapm_hsol_control),
825 SND_SOC_DAPM_MUX("HeadsetR Mux", SND_SOC_NOPM, 0, 0,
826 &twl4030_dapm_hsor_control),
827 /* CarkitL/R */
828 SND_SOC_DAPM_MUX("CarkitL Mux", SND_SOC_NOPM, 0, 0,
829 &twl4030_dapm_carkitl_control),
830 SND_SOC_DAPM_MUX("CarkitR Mux", SND_SOC_NOPM, 0, 0,
831 &twl4030_dapm_carkitr_control),
832 /* HandsfreeL/R */
833 SND_SOC_DAPM_MUX_E("HandsfreeL Mux", TWL4030_REG_HFL_CTL, 5, 0,
834 &twl4030_dapm_handsfreel_control, handsfree_event,
835 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
836 SND_SOC_DAPM_MUX_E("HandsfreeR Mux", TWL4030_REG_HFR_CTL, 5, 0,
837 &twl4030_dapm_handsfreer_control, handsfree_event,
838 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
839
840 SND_SOC_DAPM_ADC("ADCL", "Left Capture", SND_SOC_NOPM, 0, 0),
841 SND_SOC_DAPM_ADC("ADCR", "Right Capture", SND_SOC_NOPM, 0, 0),
842};
843
844static const struct snd_soc_dapm_route intercon[] = {
845 {"ARXL1_APGA", NULL, "DAC Left1"},
846 {"ARXR1_APGA", NULL, "DAC Right1"},
847 {"ARXL2_APGA", NULL, "DAC Left2"},
848 {"ARXR2_APGA", NULL, "DAC Right2"},
849
850 /* Internal playback routings */
851 /* Earpiece */
852 {"Earpiece Mux", "DACL1", "ARXL1_APGA"},
853 {"Earpiece Mux", "DACL2", "ARXL2_APGA"},
854 {"Earpiece Mux", "DACR1", "ARXR1_APGA"},
855 /* PreDrivL */
856 {"PredriveL Mux", "DACL1", "ARXL1_APGA"},
857 {"PredriveL Mux", "DACL2", "ARXL2_APGA"},
858 {"PredriveL Mux", "DACR2", "ARXR2_APGA"},
859 /* PreDrivR */
860 {"PredriveR Mux", "DACR1", "ARXR1_APGA"},
861 {"PredriveR Mux", "DACR2", "ARXR2_APGA"},
862 {"PredriveR Mux", "DACL2", "ARXL2_APGA"},
863 /* HeadsetL */
864 {"HeadsetL Mux", "DACL1", "ARXL1_APGA"},
865 {"HeadsetL Mux", "DACL2", "ARXL2_APGA"},
866 /* HeadsetR */
867 {"HeadsetR Mux", "DACR1", "ARXR1_APGA"},
868 {"HeadsetR Mux", "DACR2", "ARXR2_APGA"},
869 /* CarkitL */
870 {"CarkitL Mux", "DACL1", "ARXL1_APGA"},
871 {"CarkitL Mux", "DACL2", "ARXL2_APGA"},
872 /* CarkitR */
873 {"CarkitR Mux", "DACR1", "ARXR1_APGA"},
874 {"CarkitR Mux", "DACR2", "ARXR2_APGA"},
875 /* HandsfreeL */
876 {"HandsfreeL Mux", "DACL1", "ARXL1_APGA"},
877 {"HandsfreeL Mux", "DACL2", "ARXL2_APGA"},
878 {"HandsfreeL Mux", "DACR2", "ARXR2_APGA"},
879 /* HandsfreeR */
880 {"HandsfreeR Mux", "DACR1", "ARXR1_APGA"},
881 {"HandsfreeR Mux", "DACR2", "ARXR2_APGA"},
882 {"HandsfreeR Mux", "DACL2", "ARXL2_APGA"},
883
884 /* outputs */
885 {"OUTL", NULL, "ARXL2_APGA"},
886 {"OUTR", NULL, "ARXR2_APGA"},
887 {"EARPIECE", NULL, "Earpiece Mux"},
888 {"PREDRIVEL", NULL, "PredriveL Mux"},
889 {"PREDRIVER", NULL, "PredriveR Mux"},
890 {"HSOL", NULL, "HeadsetL Mux"},
891 {"HSOR", NULL, "HeadsetR Mux"},
892 {"CARKITL", NULL, "CarkitL Mux"},
893 {"CARKITR", NULL, "CarkitR Mux"},
894 {"HFL", NULL, "HandsfreeL Mux"},
895 {"HFR", NULL, "HandsfreeR Mux"},
896
897 /* inputs */
898 {"ADCL", NULL, "INL"},
899 {"ADCR", NULL, "INR"},
900};
901
902static int twl4030_add_widgets(struct snd_soc_codec *codec)
903{
904 snd_soc_dapm_new_controls(codec, twl4030_dapm_widgets,
905 ARRAY_SIZE(twl4030_dapm_widgets));
906
907 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
908
909 snd_soc_dapm_new_widgets(codec);
910 return 0;
911}
912
913static void twl4030_power_up(struct snd_soc_codec *codec)
914{
915 u8 anamicl, regmisc1, byte, popn;
916 int i = 0;
917
918 /* set CODECPDZ to turn on codec */
919 twl4030_set_codecpdz(codec);
920
921 /* initiate offset cancellation */
922 anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
923 twl4030_write(codec, TWL4030_REG_ANAMICL,
924 anamicl | TWL4030_CNCL_OFFSET_START);
925
926 /* wait for offset cancellation to complete */
927 do {
928 /* this takes a little while, so don't slam i2c */
929 udelay(2000);
930 twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte,
931 TWL4030_REG_ANAMICL);
932 } while ((i++ < 100) &&
933 ((byte & TWL4030_CNCL_OFFSET_START) ==
934 TWL4030_CNCL_OFFSET_START));
935
936 /* anti-pop when changing analog gain */
937 regmisc1 = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1);
938 twl4030_write(codec, TWL4030_REG_MISC_SET_1,
939 regmisc1 | TWL4030_SMOOTH_ANAVOL_EN);
940
941 /* toggle CODECPDZ as per TRM */
942 twl4030_clear_codecpdz(codec);
943 twl4030_set_codecpdz(codec);
944
945 /* program anti-pop with bias ramp delay */
946 popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
947 popn &= TWL4030_RAMP_DELAY;
948 popn |= TWL4030_RAMP_DELAY_645MS;
949 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
950 popn |= TWL4030_VMID_EN;
951 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
952
953 /* enable anti-pop ramp */
954 popn |= TWL4030_RAMP_EN;
955 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
956}
957
958static void twl4030_power_down(struct snd_soc_codec *codec)
959{
960 u8 popn;
961
962 /* disable anti-pop ramp */
963 popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
964 popn &= ~TWL4030_RAMP_EN;
965 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
966
967 /* disable bias out */
968 popn &= ~TWL4030_VMID_EN;
969 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
970
971 /* power down */
972 twl4030_clear_codecpdz(codec);
973}
974
975static int twl4030_set_bias_level(struct snd_soc_codec *codec,
976 enum snd_soc_bias_level level)
977{
978 switch (level) {
979 case SND_SOC_BIAS_ON:
980 twl4030_power_up(codec);
981 break;
982 case SND_SOC_BIAS_PREPARE:
983 /* TODO: develop a twl4030_prepare function */
984 break;
985 case SND_SOC_BIAS_STANDBY:
986 /* TODO: develop a twl4030_standby function */
987 twl4030_power_down(codec);
988 break;
989 case SND_SOC_BIAS_OFF:
990 twl4030_power_down(codec);
991 break;
992 }
993 codec->bias_level = level;
994
995 return 0;
996}
997
998static int twl4030_hw_params(struct snd_pcm_substream *substream,
999 struct snd_pcm_hw_params *params,
1000 struct snd_soc_dai *dai)
1001{
1002 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1003 struct snd_soc_device *socdev = rtd->socdev;
1004 struct snd_soc_codec *codec = socdev->codec;
1005 u8 mode, old_mode, format, old_format;
1006
1007
1008 /* bit rate */
1009 old_mode = twl4030_read_reg_cache(codec,
1010 TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ;
1011 mode = old_mode & ~TWL4030_APLL_RATE;
1012
1013 switch (params_rate(params)) {
1014 case 8000:
1015 mode |= TWL4030_APLL_RATE_8000;
1016 break;
1017 case 11025:
1018 mode |= TWL4030_APLL_RATE_11025;
1019 break;
1020 case 12000:
1021 mode |= TWL4030_APLL_RATE_12000;
1022 break;
1023 case 16000:
1024 mode |= TWL4030_APLL_RATE_16000;
1025 break;
1026 case 22050:
1027 mode |= TWL4030_APLL_RATE_22050;
1028 break;
1029 case 24000:
1030 mode |= TWL4030_APLL_RATE_24000;
1031 break;
1032 case 32000:
1033 mode |= TWL4030_APLL_RATE_32000;
1034 break;
1035 case 44100:
1036 mode |= TWL4030_APLL_RATE_44100;
1037 break;
1038 case 48000:
1039 mode |= TWL4030_APLL_RATE_48000;
1040 break;
1041 default:
1042 printk(KERN_ERR "TWL4030 hw params: unknown rate %d\n",
1043 params_rate(params));
1044 return -EINVAL;
1045 }
1046
1047 if (mode != old_mode) {
1048 /* change rate and set CODECPDZ */
1049 twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
1050 twl4030_set_codecpdz(codec);
1051 }
1052
1053 /* sample size */
1054 old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
1055 format = old_format;
1056 format &= ~TWL4030_DATA_WIDTH;
1057 switch (params_format(params)) {
1058 case SNDRV_PCM_FORMAT_S16_LE:
1059 format |= TWL4030_DATA_WIDTH_16S_16W;
1060 break;
1061 case SNDRV_PCM_FORMAT_S24_LE:
1062 format |= TWL4030_DATA_WIDTH_32S_24W;
1063 break;
1064 default:
1065 printk(KERN_ERR "TWL4030 hw params: unknown format %d\n",
1066 params_format(params));
1067 return -EINVAL;
1068 }
1069
1070 if (format != old_format) {
1071
1072 /* clear CODECPDZ before changing format (codec requirement) */
1073 twl4030_clear_codecpdz(codec);
1074
1075 /* change format */
1076 twl4030_write(codec, TWL4030_REG_AUDIO_IF, format);
1077
1078 /* set CODECPDZ afterwards */
1079 twl4030_set_codecpdz(codec);
1080 }
1081 return 0;
1082}
1083
1084static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai,
1085 int clk_id, unsigned int freq, int dir)
1086{
1087 struct snd_soc_codec *codec = codec_dai->codec;
1088 u8 infreq;
1089
1090 switch (freq) {
1091 case 19200000:
1092 infreq = TWL4030_APLL_INFREQ_19200KHZ;
1093 break;
1094 case 26000000:
1095 infreq = TWL4030_APLL_INFREQ_26000KHZ;
1096 break;
1097 case 38400000:
1098 infreq = TWL4030_APLL_INFREQ_38400KHZ;
1099 break;
1100 default:
1101 printk(KERN_ERR "TWL4030 set sysclk: unknown rate %d\n",
1102 freq);
1103 return -EINVAL;
1104 }
1105
1106 infreq |= TWL4030_APLL_EN;
1107 twl4030_write(codec, TWL4030_REG_APLL_CTL, infreq);
1108
1109 return 0;
1110}
1111
1112static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
1113 unsigned int fmt)
1114{
1115 struct snd_soc_codec *codec = codec_dai->codec;
1116 u8 old_format, format;
1117
1118 /* get format */
1119 old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
1120 format = old_format;
1121
1122 /* set master/slave audio interface */
1123 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1124 case SND_SOC_DAIFMT_CBM_CFM:
1125 format &= ~(TWL4030_AIF_SLAVE_EN);
1126 format &= ~(TWL4030_CLK256FS_EN);
1127 break;
1128 case SND_SOC_DAIFMT_CBS_CFS:
1129 format |= TWL4030_AIF_SLAVE_EN;
1130 format |= TWL4030_CLK256FS_EN;
1131 break;
1132 default:
1133 return -EINVAL;
1134 }
1135
1136 /* interface format */
1137 format &= ~TWL4030_AIF_FORMAT;
1138 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1139 case SND_SOC_DAIFMT_I2S:
1140 format |= TWL4030_AIF_FORMAT_CODEC;
1141 break;
1142 default:
1143 return -EINVAL;
1144 }
1145
1146 if (format != old_format) {
1147
1148 /* clear CODECPDZ before changing format (codec requirement) */
1149 twl4030_clear_codecpdz(codec);
1150
1151 /* change format */
1152 twl4030_write(codec, TWL4030_REG_AUDIO_IF, format);
1153
1154 /* set CODECPDZ afterwards */
1155 twl4030_set_codecpdz(codec);
1156 }
1157
1158 return 0;
1159}
1160
1161#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000)
1162#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
1163
1164struct snd_soc_dai twl4030_dai = {
1165 .name = "twl4030",
1166 .playback = {
1167 .stream_name = "Playback",
1168 .channels_min = 2,
1169 .channels_max = 2,
1170 .rates = TWL4030_RATES,
1171 .formats = TWL4030_FORMATS,},
1172 .capture = {
1173 .stream_name = "Capture",
1174 .channels_min = 2,
1175 .channels_max = 2,
1176 .rates = TWL4030_RATES,
1177 .formats = TWL4030_FORMATS,},
1178 .ops = {
1179 .hw_params = twl4030_hw_params,
1180 .set_sysclk = twl4030_set_dai_sysclk,
1181 .set_fmt = twl4030_set_dai_fmt,
1182 }
1183};
1184EXPORT_SYMBOL_GPL(twl4030_dai);
1185
1186static int twl4030_suspend(struct platform_device *pdev, pm_message_t state)
1187{
1188 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1189 struct snd_soc_codec *codec = socdev->codec;
1190
1191 twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
1192
1193 return 0;
1194}
1195
1196static int twl4030_resume(struct platform_device *pdev)
1197{
1198 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1199 struct snd_soc_codec *codec = socdev->codec;
1200
1201 twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1202 twl4030_set_bias_level(codec, codec->suspend_bias_level);
1203 return 0;
1204}
1205
1206/*
1207 * initialize the driver
1208 * register the mixer and dsp interfaces with the kernel
1209 */
1210
1211static int twl4030_init(struct snd_soc_device *socdev)
1212{
1213 struct snd_soc_codec *codec = socdev->codec;
1214 int ret = 0;
1215
1216 printk(KERN_INFO "TWL4030 Audio Codec init \n");
1217
1218 codec->name = "twl4030";
1219 codec->owner = THIS_MODULE;
1220 codec->read = twl4030_read_reg_cache;
1221 codec->write = twl4030_write;
1222 codec->set_bias_level = twl4030_set_bias_level;
1223 codec->dai = &twl4030_dai;
1224 codec->num_dai = 1;
1225 codec->reg_cache_size = sizeof(twl4030_reg);
1226 codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg),
1227 GFP_KERNEL);
1228 if (codec->reg_cache == NULL)
1229 return -ENOMEM;
1230
1231 /* register pcms */
1232 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1233 if (ret < 0) {
1234 printk(KERN_ERR "twl4030: failed to create pcms\n");
1235 goto pcm_err;
1236 }
1237
1238 twl4030_init_chip(codec);
1239
1240 /* power on device */
1241 twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1242
1243 twl4030_add_controls(codec);
1244 twl4030_add_widgets(codec);
1245
1246 ret = snd_soc_init_card(socdev);
1247 if (ret < 0) {
1248 printk(KERN_ERR "twl4030: failed to register card\n");
1249 goto card_err;
1250 }
1251
1252 return ret;
1253
1254card_err:
1255 snd_soc_free_pcms(socdev);
1256 snd_soc_dapm_free(socdev);
1257pcm_err:
1258 kfree(codec->reg_cache);
1259 return ret;
1260}
1261
1262static struct snd_soc_device *twl4030_socdev;
1263
1264static int twl4030_probe(struct platform_device *pdev)
1265{
1266 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1267 struct snd_soc_codec *codec;
1268
1269 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
1270 if (codec == NULL)
1271 return -ENOMEM;
1272
1273 socdev->codec = codec;
1274 mutex_init(&codec->mutex);
1275 INIT_LIST_HEAD(&codec->dapm_widgets);
1276 INIT_LIST_HEAD(&codec->dapm_paths);
1277
1278 twl4030_socdev = socdev;
1279 twl4030_init(socdev);
1280
1281 return 0;
1282}
1283
1284static int twl4030_remove(struct platform_device *pdev)
1285{
1286 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1287 struct snd_soc_codec *codec = socdev->codec;
1288
1289 printk(KERN_INFO "TWL4030 Audio Codec remove\n");
1290 kfree(codec);
1291
1292 return 0;
1293}
1294
1295struct snd_soc_codec_device soc_codec_dev_twl4030 = {
1296 .probe = twl4030_probe,
1297 .remove = twl4030_remove,
1298 .suspend = twl4030_suspend,
1299 .resume = twl4030_resume,
1300};
1301EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030);
1302
1303static int __init twl4030_modinit(void)
1304{
1305 return snd_soc_register_dai(&twl4030_dai);
1306}
1307module_init(twl4030_modinit);
1308
1309static void __exit twl4030_exit(void)
1310{
1311 snd_soc_unregister_dai(&twl4030_dai);
1312}
1313module_exit(twl4030_exit);
1314
1315MODULE_DESCRIPTION("ASoC TWL4030 codec driver");
1316MODULE_AUTHOR("Steve Sakoman");
1317MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
new file mode 100644
index 000000000000..54615c76802b
--- /dev/null
+++ b/sound/soc/codecs/twl4030.h
@@ -0,0 +1,219 @@
1/*
2 * ALSA SoC TWL4030 codec driver
3 *
4 * Author: Steve Sakoman <steve@sakoman.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * 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., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#ifndef __TWL4030_AUDIO_H__
23#define __TWL4030_AUDIO_H__
24
25#define TWL4030_REG_CODEC_MODE 0x1
26#define TWL4030_REG_OPTION 0x2
27#define TWL4030_REG_UNKNOWN 0x3
28#define TWL4030_REG_MICBIAS_CTL 0x4
29#define TWL4030_REG_ANAMICL 0x5
30#define TWL4030_REG_ANAMICR 0x6
31#define TWL4030_REG_AVADC_CTL 0x7
32#define TWL4030_REG_ADCMICSEL 0x8
33#define TWL4030_REG_DIGMIXING 0x9
34#define TWL4030_REG_ATXL1PGA 0xA
35#define TWL4030_REG_ATXR1PGA 0xB
36#define TWL4030_REG_AVTXL2PGA 0xC
37#define TWL4030_REG_AVTXR2PGA 0xD
38#define TWL4030_REG_AUDIO_IF 0xE
39#define TWL4030_REG_VOICE_IF 0xF
40#define TWL4030_REG_ARXR1PGA 0x10
41#define TWL4030_REG_ARXL1PGA 0x11
42#define TWL4030_REG_ARXR2PGA 0x12
43#define TWL4030_REG_ARXL2PGA 0x13
44#define TWL4030_REG_VRXPGA 0x14
45#define TWL4030_REG_VSTPGA 0x15
46#define TWL4030_REG_VRX2ARXPGA 0x16
47#define TWL4030_REG_AVDAC_CTL 0x17
48#define TWL4030_REG_ARX2VTXPGA 0x18
49#define TWL4030_REG_ARXL1_APGA_CTL 0x19
50#define TWL4030_REG_ARXR1_APGA_CTL 0x1A
51#define TWL4030_REG_ARXL2_APGA_CTL 0x1B
52#define TWL4030_REG_ARXR2_APGA_CTL 0x1C
53#define TWL4030_REG_ATX2ARXPGA 0x1D
54#define TWL4030_REG_BT_IF 0x1E
55#define TWL4030_REG_BTPGA 0x1F
56#define TWL4030_REG_BTSTPGA 0x20
57#define TWL4030_REG_EAR_CTL 0x21
58#define TWL4030_REG_HS_SEL 0x22
59#define TWL4030_REG_HS_GAIN_SET 0x23
60#define TWL4030_REG_HS_POPN_SET 0x24
61#define TWL4030_REG_PREDL_CTL 0x25
62#define TWL4030_REG_PREDR_CTL 0x26
63#define TWL4030_REG_PRECKL_CTL 0x27
64#define TWL4030_REG_PRECKR_CTL 0x28
65#define TWL4030_REG_HFL_CTL 0x29
66#define TWL4030_REG_HFR_CTL 0x2A
67#define TWL4030_REG_ALC_CTL 0x2B
68#define TWL4030_REG_ALC_SET1 0x2C
69#define TWL4030_REG_ALC_SET2 0x2D
70#define TWL4030_REG_BOOST_CTL 0x2E
71#define TWL4030_REG_SOFTVOL_CTL 0x2F
72#define TWL4030_REG_DTMF_FREQSEL 0x30
73#define TWL4030_REG_DTMF_TONEXT1H 0x31
74#define TWL4030_REG_DTMF_TONEXT1L 0x32
75#define TWL4030_REG_DTMF_TONEXT2H 0x33
76#define TWL4030_REG_DTMF_TONEXT2L 0x34
77#define TWL4030_REG_DTMF_TONOFF 0x35
78#define TWL4030_REG_DTMF_WANONOFF 0x36
79#define TWL4030_REG_I2S_RX_SCRAMBLE_H 0x37
80#define TWL4030_REG_I2S_RX_SCRAMBLE_M 0x38
81#define TWL4030_REG_I2S_RX_SCRAMBLE_L 0x39
82#define TWL4030_REG_APLL_CTL 0x3A
83#define TWL4030_REG_DTMF_CTL 0x3B
84#define TWL4030_REG_DTMF_PGA_CTL2 0x3C
85#define TWL4030_REG_DTMF_PGA_CTL1 0x3D
86#define TWL4030_REG_MISC_SET_1 0x3E
87#define TWL4030_REG_PCMBTMUX 0x3F
88#define TWL4030_REG_RX_PATH_SEL 0x43
89#define TWL4030_REG_VDL_APGA_CTL 0x44
90#define TWL4030_REG_VIBRA_CTL 0x45
91#define TWL4030_REG_VIBRA_SET 0x46
92#define TWL4030_REG_VIBRA_PWM_SET 0x47
93#define TWL4030_REG_ANAMIC_GAIN 0x48
94#define TWL4030_REG_MISC_SET_2 0x49
95
96#define TWL4030_CACHEREGNUM (TWL4030_REG_MISC_SET_2 + 1)
97
98/* Bitfield Definitions */
99
100/* TWL4030_CODEC_MODE (0x01) Fields */
101
102#define TWL4030_APLL_RATE 0xF0
103#define TWL4030_APLL_RATE_8000 0x00
104#define TWL4030_APLL_RATE_11025 0x10
105#define TWL4030_APLL_RATE_12000 0x20
106#define TWL4030_APLL_RATE_16000 0x40
107#define TWL4030_APLL_RATE_22050 0x50
108#define TWL4030_APLL_RATE_24000 0x60
109#define TWL4030_APLL_RATE_32000 0x80
110#define TWL4030_APLL_RATE_44100 0x90
111#define TWL4030_APLL_RATE_48000 0xA0
112#define TWL4030_SEL_16K 0x04
113#define TWL4030_CODECPDZ 0x02
114#define TWL4030_OPT_MODE 0x01
115
116/* TWL4030_REG_MICBIAS_CTL (0x04) Fields */
117
118#define TWL4030_MICBIAS2_CTL 0x40
119#define TWL4030_MICBIAS1_CTL 0x20
120#define TWL4030_HSMICBIAS_EN 0x04
121#define TWL4030_MICBIAS2_EN 0x02
122#define TWL4030_MICBIAS1_EN 0x01
123
124/* ANAMICL (0x05) Fields */
125
126#define TWL4030_CNCL_OFFSET_START 0x80
127#define TWL4030_OFFSET_CNCL_SEL 0x60
128#define TWL4030_OFFSET_CNCL_SEL_ARX1 0x00
129#define TWL4030_OFFSET_CNCL_SEL_ARX2 0x20
130#define TWL4030_OFFSET_CNCL_SEL_VRX 0x40
131#define TWL4030_OFFSET_CNCL_SEL_ALL 0x60
132#define TWL4030_MICAMPL_EN 0x10
133#define TWL4030_CKMIC_EN 0x08
134#define TWL4030_AUXL_EN 0x04
135#define TWL4030_HSMIC_EN 0x02
136#define TWL4030_MAINMIC_EN 0x01
137
138/* ANAMICR (0x06) Fields */
139
140#define TWL4030_MICAMPR_EN 0x10
141#define TWL4030_AUXR_EN 0x04
142#define TWL4030_SUBMIC_EN 0x01
143
144/* AVADC_CTL (0x07) Fields */
145
146#define TWL4030_ADCL_EN 0x08
147#define TWL4030_AVADC_CLK_PRIORITY 0x04
148#define TWL4030_ADCR_EN 0x02
149
150/* AUDIO_IF (0x0E) Fields */
151
152#define TWL4030_AIF_SLAVE_EN 0x80
153#define TWL4030_DATA_WIDTH 0x60
154#define TWL4030_DATA_WIDTH_16S_16W 0x00
155#define TWL4030_DATA_WIDTH_32S_16W 0x40
156#define TWL4030_DATA_WIDTH_32S_24W 0x60
157#define TWL4030_AIF_FORMAT 0x18
158#define TWL4030_AIF_FORMAT_CODEC 0x00
159#define TWL4030_AIF_FORMAT_LEFT 0x08
160#define TWL4030_AIF_FORMAT_RIGHT 0x10
161#define TWL4030_AIF_FORMAT_TDM 0x18
162#define TWL4030_AIF_TRI_EN 0x04
163#define TWL4030_CLK256FS_EN 0x02
164#define TWL4030_AIF_EN 0x01
165
166/* HS_GAIN_SET (0x23) Fields */
167
168#define TWL4030_HSR_GAIN 0x0C
169#define TWL4030_HSR_GAIN_PWR_DOWN 0x00
170#define TWL4030_HSR_GAIN_PLUS_6DB 0x04
171#define TWL4030_HSR_GAIN_0DB 0x08
172#define TWL4030_HSR_GAIN_MINUS_6DB 0x0C
173#define TWL4030_HSL_GAIN 0x03
174#define TWL4030_HSL_GAIN_PWR_DOWN 0x00
175#define TWL4030_HSL_GAIN_PLUS_6DB 0x01
176#define TWL4030_HSL_GAIN_0DB 0x02
177#define TWL4030_HSL_GAIN_MINUS_6DB 0x03
178
179/* HS_POPN_SET (0x24) Fields */
180
181#define TWL4030_VMID_EN 0x40
182#define TWL4030_EXTMUTE 0x20
183#define TWL4030_RAMP_DELAY 0x1C
184#define TWL4030_RAMP_DELAY_20MS 0x00
185#define TWL4030_RAMP_DELAY_40MS 0x04
186#define TWL4030_RAMP_DELAY_81MS 0x08
187#define TWL4030_RAMP_DELAY_161MS 0x0C
188#define TWL4030_RAMP_DELAY_323MS 0x10
189#define TWL4030_RAMP_DELAY_645MS 0x14
190#define TWL4030_RAMP_DELAY_1291MS 0x18
191#define TWL4030_RAMP_DELAY_2581MS 0x1C
192#define TWL4030_RAMP_EN 0x02
193
194/* HFL_CTL (0x29, 0x2A) Fields */
195#define TWL4030_HF_CTL_HB_EN 0x04
196#define TWL4030_HF_CTL_LOOP_EN 0x08
197#define TWL4030_HF_CTL_RAMP_EN 0x10
198#define TWL4030_HF_CTL_REF_EN 0x20
199
200/* APLL_CTL (0x3A) Fields */
201
202#define TWL4030_APLL_EN 0x10
203#define TWL4030_APLL_INFREQ 0x0F
204#define TWL4030_APLL_INFREQ_19200KHZ 0x05
205#define TWL4030_APLL_INFREQ_26000KHZ 0x06
206#define TWL4030_APLL_INFREQ_38400KHZ 0x0F
207
208/* REG_MISC_SET_1 (0x3E) Fields */
209
210#define TWL4030_CLK64_EN 0x80
211#define TWL4030_SCRAMBLE_EN 0x40
212#define TWL4030_FMLOOP_EN 0x20
213#define TWL4030_SMOOTH_ANAVOL_EN 0x02
214#define TWL4030_DIGMIC_LR_SWAP_EN 0x01
215
216extern struct snd_soc_dai twl4030_dai;
217extern struct snd_soc_codec_device soc_codec_dev_twl4030;
218
219#endif /* End of __TWL4030_AUDIO_H__ */
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
new file mode 100644
index 000000000000..a2c5064a774b
--- /dev/null
+++ b/sound/soc/codecs/uda134x.c
@@ -0,0 +1,668 @@
1/*
2 * uda134x.c -- UDA134X ALSA SoC Codec driver
3 *
4 * Modifications by Christian Pellegrin <chripell@evolware.org>
5 *
6 * Copyright 2007 Dension Audio Systems Ltd.
7 * Author: Zoltan Devai
8 *
9 * Based on the WM87xx drivers by Liam Girdwood and Richard Purdie
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#include <linux/module.h>
17#include <linux/delay.h>
18#include <sound/pcm.h>
19#include <sound/pcm_params.h>
20#include <sound/soc.h>
21#include <sound/soc-dapm.h>
22#include <sound/initval.h>
23
24#include <sound/uda134x.h>
25#include <sound/l3.h>
26
27#include "uda134x.h"
28
29
30#define POWER_OFF_ON_STANDBY 1
31/*
32 ALSA SOC usually puts the device in standby mode when it's not used
33 for sometime. If you define POWER_OFF_ON_STANDBY the driver will
34 turn off the ADC/DAC when this callback is invoked and turn it back
35 on when needed. Unfortunately this will result in a very light bump
36 (it can be audible only with good earphones). If this bothers you
37 just comment this line, you will have slightly higher power
38 consumption . Please note that sending the L3 command for ADC is
39 enough to make the bump, so it doesn't make difference if you
40 completely take off power from the codec.
41 */
42
43#define UDA134X_RATES SNDRV_PCM_RATE_8000_48000
44#define UDA134X_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
45 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE)
46
47struct uda134x_priv {
48 int sysclk;
49 int dai_fmt;
50
51 struct snd_pcm_substream *master_substream;
52 struct snd_pcm_substream *slave_substream;
53};
54
55/* In-data addresses are hard-coded into the reg-cache values */
56static const char uda134x_reg[UDA134X_REGS_NUM] = {
57 /* Extended address registers */
58 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
59 /* Status, data regs */
60 0x00, 0x83, 0x00, 0x40, 0x80, 0x00,
61};
62
63/*
64 * The codec has no support for reading its registers except for peak level...
65 */
66static inline unsigned int uda134x_read_reg_cache(struct snd_soc_codec *codec,
67 unsigned int reg)
68{
69 u8 *cache = codec->reg_cache;
70
71 if (reg >= UDA134X_REGS_NUM)
72 return -1;
73 return cache[reg];
74}
75
76/*
77 * Write the register cache
78 */
79static inline void uda134x_write_reg_cache(struct snd_soc_codec *codec,
80 u8 reg, unsigned int value)
81{
82 u8 *cache = codec->reg_cache;
83
84 if (reg >= UDA134X_REGS_NUM)
85 return;
86 cache[reg] = value;
87}
88
89/*
90 * Write to the uda134x registers
91 *
92 */
93static int uda134x_write(struct snd_soc_codec *codec, unsigned int reg,
94 unsigned int value)
95{
96 int ret;
97 u8 addr;
98 u8 data = value;
99 struct uda134x_platform_data *pd = codec->control_data;
100
101 pr_debug("%s reg: %02X, value:%02X\n", __func__, reg, value);
102
103 if (reg >= UDA134X_REGS_NUM) {
104 printk(KERN_ERR "%s unkown register: reg: %d",
105 __func__, reg);
106 return -EINVAL;
107 }
108
109 uda134x_write_reg_cache(codec, reg, value);
110
111 switch (reg) {
112 case UDA134X_STATUS0:
113 case UDA134X_STATUS1:
114 addr = UDA134X_STATUS_ADDR;
115 break;
116 case UDA134X_DATA000:
117 case UDA134X_DATA001:
118 case UDA134X_DATA010:
119 addr = UDA134X_DATA0_ADDR;
120 break;
121 case UDA134X_DATA1:
122 addr = UDA134X_DATA1_ADDR;
123 break;
124 default:
125 /* It's an extended address register */
126 addr = (reg | UDA134X_EXTADDR_PREFIX);
127
128 ret = l3_write(&pd->l3,
129 UDA134X_DATA0_ADDR, &addr, 1);
130 if (ret != 1)
131 return -EIO;
132
133 addr = UDA134X_DATA0_ADDR;
134 data = (value | UDA134X_EXTDATA_PREFIX);
135 break;
136 }
137
138 ret = l3_write(&pd->l3,
139 addr, &data, 1);
140 if (ret != 1)
141 return -EIO;
142
143 return 0;
144}
145
146static inline void uda134x_reset(struct snd_soc_codec *codec)
147{
148 u8 reset_reg = uda134x_read_reg_cache(codec, UDA134X_STATUS0);
149 uda134x_write(codec, UDA134X_STATUS0, reset_reg | (1<<6));
150 msleep(1);
151 uda134x_write(codec, UDA134X_STATUS0, reset_reg & ~(1<<6));
152}
153
154static int uda134x_mute(struct snd_soc_dai *dai, int mute)
155{
156 struct snd_soc_codec *codec = dai->codec;
157 u8 mute_reg = uda134x_read_reg_cache(codec, UDA134X_DATA010);
158
159 pr_debug("%s mute: %d\n", __func__, mute);
160
161 if (mute)
162 mute_reg |= (1<<2);
163 else
164 mute_reg &= ~(1<<2);
165
166 uda134x_write(codec, UDA134X_DATA010, mute_reg & ~(1<<2));
167
168 return 0;
169}
170
171static int uda134x_startup(struct snd_pcm_substream *substream,
172 struct snd_soc_dai *dai)
173{
174 struct snd_soc_pcm_runtime *rtd = substream->private_data;
175 struct snd_soc_device *socdev = rtd->socdev;
176 struct snd_soc_codec *codec = socdev->codec;
177 struct uda134x_priv *uda134x = codec->private_data;
178 struct snd_pcm_runtime *master_runtime;
179
180 if (uda134x->master_substream) {
181 master_runtime = uda134x->master_substream->runtime;
182
183 pr_debug("%s constraining to %d bits at %d\n", __func__,
184 master_runtime->sample_bits,
185 master_runtime->rate);
186
187 snd_pcm_hw_constraint_minmax(substream->runtime,
188 SNDRV_PCM_HW_PARAM_RATE,
189 master_runtime->rate,
190 master_runtime->rate);
191
192 snd_pcm_hw_constraint_minmax(substream->runtime,
193 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
194 master_runtime->sample_bits,
195 master_runtime->sample_bits);
196
197 uda134x->slave_substream = substream;
198 } else
199 uda134x->master_substream = substream;
200
201 return 0;
202}
203
204static void uda134x_shutdown(struct snd_pcm_substream *substream,
205 struct snd_soc_dai *dai)
206{
207 struct snd_soc_pcm_runtime *rtd = substream->private_data;
208 struct snd_soc_device *socdev = rtd->socdev;
209 struct snd_soc_codec *codec = socdev->codec;
210 struct uda134x_priv *uda134x = codec->private_data;
211
212 if (uda134x->master_substream == substream)
213 uda134x->master_substream = uda134x->slave_substream;
214
215 uda134x->slave_substream = NULL;
216}
217
218static int uda134x_hw_params(struct snd_pcm_substream *substream,
219 struct snd_pcm_hw_params *params,
220 struct snd_soc_dai *dai)
221{
222 struct snd_soc_pcm_runtime *rtd = substream->private_data;
223 struct snd_soc_device *socdev = rtd->socdev;
224 struct snd_soc_codec *codec = socdev->codec;
225 struct uda134x_priv *uda134x = codec->private_data;
226 u8 hw_params;
227
228 if (substream == uda134x->slave_substream) {
229 pr_debug("%s ignoring hw_params for slave substream\n",
230 __func__);
231 return 0;
232 }
233
234 hw_params = uda134x_read_reg_cache(codec, UDA134X_STATUS0);
235 hw_params &= STATUS0_SYSCLK_MASK;
236 hw_params &= STATUS0_DAIFMT_MASK;
237
238 pr_debug("%s sysclk: %d, rate:%d\n", __func__,
239 uda134x->sysclk, params_rate(params));
240
241 /* set SYSCLK / fs ratio */
242 switch (uda134x->sysclk / params_rate(params)) {
243 case 512:
244 break;
245 case 384:
246 hw_params |= (1<<4);
247 break;
248 case 256:
249 hw_params |= (1<<5);
250 break;
251 default:
252 printk(KERN_ERR "%s unsupported fs\n", __func__);
253 return -EINVAL;
254 }
255
256 pr_debug("%s dai_fmt: %d, params_format:%d\n", __func__,
257 uda134x->dai_fmt, params_format(params));
258
259 /* set DAI format and word length */
260 switch (uda134x->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
261 case SND_SOC_DAIFMT_I2S:
262 break;
263 case SND_SOC_DAIFMT_RIGHT_J:
264 switch (params_format(params)) {
265 case SNDRV_PCM_FORMAT_S16_LE:
266 hw_params |= (1<<1);
267 break;
268 case SNDRV_PCM_FORMAT_S18_3LE:
269 hw_params |= (1<<2);
270 break;
271 case SNDRV_PCM_FORMAT_S20_3LE:
272 hw_params |= ((1<<2) | (1<<1));
273 break;
274 default:
275 printk(KERN_ERR "%s unsupported format (right)\n",
276 __func__);
277 return -EINVAL;
278 }
279 break;
280 case SND_SOC_DAIFMT_LEFT_J:
281 hw_params |= (1<<3);
282 break;
283 default:
284 printk(KERN_ERR "%s unsupported format\n", __func__);
285 return -EINVAL;
286 }
287
288 uda134x_write(codec, UDA134X_STATUS0, hw_params);
289
290 return 0;
291}
292
293static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
294 int clk_id, unsigned int freq, int dir)
295{
296 struct snd_soc_codec *codec = codec_dai->codec;
297 struct uda134x_priv *uda134x = codec->private_data;
298
299 pr_debug("%s clk_id: %d, freq: %d, dir: %d\n", __func__,
300 clk_id, freq, dir);
301
302 /* Anything between 256fs*8Khz and 512fs*48Khz should be acceptable
303 because the codec is slave. Of course limitations of the clock
304 master (the IIS controller) apply.
305 We'll error out on set_hw_params if it's not OK */
306 if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
307 uda134x->sysclk = freq;
308 return 0;
309 }
310
311 printk(KERN_ERR "%s unsupported sysclk\n", __func__);
312 return -EINVAL;
313}
314
315static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai,
316 unsigned int fmt)
317{
318 struct snd_soc_codec *codec = codec_dai->codec;
319 struct uda134x_priv *uda134x = codec->private_data;
320
321 pr_debug("%s fmt: %08X\n", __func__, fmt);
322
323 /* codec supports only full slave mode */
324 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
325 printk(KERN_ERR "%s unsupported slave mode\n", __func__);
326 return -EINVAL;
327 }
328
329 /* no support for clock inversion */
330 if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {
331 printk(KERN_ERR "%s unsupported clock inversion\n", __func__);
332 return -EINVAL;
333 }
334
335 /* We can't setup DAI format here as it depends on the word bit num */
336 /* so let's just store the value for later */
337 uda134x->dai_fmt = fmt;
338
339 return 0;
340}
341
342static int uda134x_set_bias_level(struct snd_soc_codec *codec,
343 enum snd_soc_bias_level level)
344{
345 u8 reg;
346 struct uda134x_platform_data *pd = codec->control_data;
347 int i;
348 u8 *cache = codec->reg_cache;
349
350 pr_debug("%s bias level %d\n", __func__, level);
351
352 switch (level) {
353 case SND_SOC_BIAS_ON:
354 /* ADC, DAC on */
355 reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
356 uda134x_write(codec, UDA134X_STATUS1, reg | 0x03);
357 break;
358 case SND_SOC_BIAS_PREPARE:
359 /* power on */
360 if (pd->power) {
361 pd->power(1);
362 /* Sync reg_cache with the hardware */
363 for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++)
364 codec->write(codec, i, *cache++);
365 }
366 break;
367 case SND_SOC_BIAS_STANDBY:
368 /* ADC, DAC power off */
369 reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
370 uda134x_write(codec, UDA134X_STATUS1, reg & ~(0x03));
371 break;
372 case SND_SOC_BIAS_OFF:
373 /* power off */
374 if (pd->power)
375 pd->power(0);
376 break;
377 }
378 codec->bias_level = level;
379 return 0;
380}
381
382static const char *uda134x_dsp_setting[] = {"Flat", "Minimum1",
383 "Minimum2", "Maximum"};
384static const char *uda134x_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
385static const char *uda134x_mixmode[] = {"Differential", "Analog1",
386 "Analog2", "Both"};
387
388static const struct soc_enum uda134x_mixer_enum[] = {
389SOC_ENUM_SINGLE(UDA134X_DATA010, 0, 0x04, uda134x_dsp_setting),
390SOC_ENUM_SINGLE(UDA134X_DATA010, 3, 0x04, uda134x_deemph),
391SOC_ENUM_SINGLE(UDA134X_EA010, 0, 0x04, uda134x_mixmode),
392};
393
394static const struct snd_kcontrol_new uda1341_snd_controls[] = {
395SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
396SOC_SINGLE("Capture Volume", UDA134X_EA010, 2, 0x07, 0),
397SOC_SINGLE("Analog1 Volume", UDA134X_EA000, 0, 0x1F, 1),
398SOC_SINGLE("Analog2 Volume", UDA134X_EA001, 0, 0x1F, 1),
399
400SOC_SINGLE("Mic Sensitivity", UDA134X_EA010, 2, 7, 0),
401SOC_SINGLE("Mic Volume", UDA134X_EA101, 0, 0x1F, 0),
402
403SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0),
404SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0),
405
406SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]),
407SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
408SOC_ENUM("Input Mux", uda134x_mixer_enum[2]),
409
410SOC_SINGLE("AGC Switch", UDA134X_EA100, 4, 1, 0),
411SOC_SINGLE("AGC Target Volume", UDA134X_EA110, 0, 0x03, 1),
412SOC_SINGLE("AGC Timing", UDA134X_EA110, 2, 0x07, 0),
413
414SOC_SINGLE("DAC +6dB Switch", UDA134X_STATUS1, 6, 1, 0),
415SOC_SINGLE("ADC +6dB Switch", UDA134X_STATUS1, 5, 1, 0),
416SOC_SINGLE("ADC Polarity Switch", UDA134X_STATUS1, 4, 1, 0),
417SOC_SINGLE("DAC Polarity Switch", UDA134X_STATUS1, 3, 1, 0),
418SOC_SINGLE("Double Speed Playback Switch", UDA134X_STATUS1, 2, 1, 0),
419SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
420};
421
422static const struct snd_kcontrol_new uda1340_snd_controls[] = {
423SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
424
425SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0),
426SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0),
427
428SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]),
429SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
430
431SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
432};
433
434static int uda134x_add_controls(struct snd_soc_codec *codec)
435{
436 int err, i, n;
437 const struct snd_kcontrol_new *ctrls;
438 struct uda134x_platform_data *pd = codec->control_data;
439
440 switch (pd->model) {
441 case UDA134X_UDA1340:
442 case UDA134X_UDA1344:
443 n = ARRAY_SIZE(uda1340_snd_controls);
444 ctrls = uda1340_snd_controls;
445 break;
446 case UDA134X_UDA1341:
447 n = ARRAY_SIZE(uda1341_snd_controls);
448 ctrls = uda1341_snd_controls;
449 break;
450 default:
451 printk(KERN_ERR "%s unkown codec type: %d",
452 __func__, pd->model);
453 return -EINVAL;
454 }
455
456 for (i = 0; i < n; i++) {
457 err = snd_ctl_add(codec->card,
458 snd_soc_cnew(&ctrls[i],
459 codec, NULL));
460 if (err < 0)
461 return err;
462 }
463
464 return 0;
465}
466
467struct snd_soc_dai uda134x_dai = {
468 .name = "UDA134X",
469 /* playback capabilities */
470 .playback = {
471 .stream_name = "Playback",
472 .channels_min = 1,
473 .channels_max = 2,
474 .rates = UDA134X_RATES,
475 .formats = UDA134X_FORMATS,
476 },
477 /* capture capabilities */
478 .capture = {
479 .stream_name = "Capture",
480 .channels_min = 1,
481 .channels_max = 2,
482 .rates = UDA134X_RATES,
483 .formats = UDA134X_FORMATS,
484 },
485 /* pcm operations */
486 .ops = {
487 .startup = uda134x_startup,
488 .shutdown = uda134x_shutdown,
489 .hw_params = uda134x_hw_params,
490 .digital_mute = uda134x_mute,
491 .set_sysclk = uda134x_set_dai_sysclk,
492 .set_fmt = uda134x_set_dai_fmt,
493 }
494};
495EXPORT_SYMBOL(uda134x_dai);
496
497
498static int uda134x_soc_probe(struct platform_device *pdev)
499{
500 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
501 struct snd_soc_codec *codec;
502 struct uda134x_priv *uda134x;
503 void *codec_setup_data = socdev->codec_data;
504 int ret = -ENOMEM;
505 struct uda134x_platform_data *pd;
506
507 printk(KERN_INFO "UDA134X SoC Audio Codec\n");
508
509 if (!codec_setup_data) {
510 printk(KERN_ERR "UDA134X SoC codec: "
511 "missing L3 bitbang function\n");
512 return -ENODEV;
513 }
514
515 pd = codec_setup_data;
516 switch (pd->model) {
517 case UDA134X_UDA1340:
518 case UDA134X_UDA1341:
519 case UDA134X_UDA1344:
520 break;
521 default:
522 printk(KERN_ERR "UDA134X SoC codec: "
523 "unsupported model %d\n",
524 pd->model);
525 return -EINVAL;
526 }
527
528 socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
529 if (socdev->codec == NULL)
530 return ret;
531
532 codec = socdev->codec;
533
534 uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL);
535 if (uda134x == NULL)
536 goto priv_err;
537 codec->private_data = uda134x;
538
539 codec->reg_cache = kmemdup(uda134x_reg, sizeof(uda134x_reg),
540 GFP_KERNEL);
541 if (codec->reg_cache == NULL)
542 goto reg_err;
543
544 mutex_init(&codec->mutex);
545
546 codec->reg_cache_size = sizeof(uda134x_reg);
547 codec->reg_cache_step = 1;
548
549 codec->name = "UDA134X";
550 codec->owner = THIS_MODULE;
551 codec->dai = &uda134x_dai;
552 codec->num_dai = 1;
553 codec->read = uda134x_read_reg_cache;
554 codec->write = uda134x_write;
555#ifdef POWER_OFF_ON_STANDBY
556 codec->set_bias_level = uda134x_set_bias_level;
557#endif
558 INIT_LIST_HEAD(&codec->dapm_widgets);
559 INIT_LIST_HEAD(&codec->dapm_paths);
560
561 codec->control_data = codec_setup_data;
562
563 if (pd->power)
564 pd->power(1);
565
566 uda134x_reset(codec);
567
568 /* register pcms */
569 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
570 if (ret < 0) {
571 printk(KERN_ERR "UDA134X: failed to register pcms\n");
572 goto pcm_err;
573 }
574
575 ret = uda134x_add_controls(codec);
576 if (ret < 0) {
577 printk(KERN_ERR "UDA134X: failed to register controls\n");
578 goto pcm_err;
579 }
580
581 ret = snd_soc_init_card(socdev);
582 if (ret < 0) {
583 printk(KERN_ERR "UDA134X: failed to register card\n");
584 goto card_err;
585 }
586
587 return 0;
588
589card_err:
590 snd_soc_free_pcms(socdev);
591 snd_soc_dapm_free(socdev);
592pcm_err:
593 kfree(codec->reg_cache);
594reg_err:
595 kfree(codec->private_data);
596priv_err:
597 kfree(codec);
598 return ret;
599}
600
601/* power down chip */
602static int uda134x_soc_remove(struct platform_device *pdev)
603{
604 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
605 struct snd_soc_codec *codec = socdev->codec;
606
607 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
608 uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
609
610 snd_soc_free_pcms(socdev);
611 snd_soc_dapm_free(socdev);
612
613 kfree(codec->private_data);
614 kfree(codec->reg_cache);
615 kfree(codec);
616
617 return 0;
618}
619
620#if defined(CONFIG_PM)
621static int uda134x_soc_suspend(struct platform_device *pdev,
622 pm_message_t state)
623{
624 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
625 struct snd_soc_codec *codec = socdev->codec;
626
627 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
628 uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
629 return 0;
630}
631
632static int uda134x_soc_resume(struct platform_device *pdev)
633{
634 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
635 struct snd_soc_codec *codec = socdev->codec;
636
637 uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
638 uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
639 return 0;
640}
641#else
642#define uda134x_soc_suspend NULL
643#define uda134x_soc_resume NULL
644#endif /* CONFIG_PM */
645
646struct snd_soc_codec_device soc_codec_dev_uda134x = {
647 .probe = uda134x_soc_probe,
648 .remove = uda134x_soc_remove,
649 .suspend = uda134x_soc_suspend,
650 .resume = uda134x_soc_resume,
651};
652EXPORT_SYMBOL_GPL(soc_codec_dev_uda134x);
653
654static int __init uda134x_init(void)
655{
656 return snd_soc_register_dai(&uda134x_dai);
657}
658module_init(uda134x_init);
659
660static void __exit uda134x_exit(void)
661{
662 snd_soc_unregister_dai(&uda134x_dai);
663}
664module_exit(uda134x_exit);
665
666MODULE_DESCRIPTION("UDA134X ALSA soc codec driver");
667MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
668MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/uda134x.h b/sound/soc/codecs/uda134x.h
new file mode 100644
index 000000000000..94f440490b31
--- /dev/null
+++ b/sound/soc/codecs/uda134x.h
@@ -0,0 +1,36 @@
1#ifndef _UDA134X_CODEC_H
2#define _UDA134X_CODEC_H
3
4#define UDA134X_L3ADDR 5
5#define UDA134X_DATA0_ADDR ((UDA134X_L3ADDR << 2) | 0)
6#define UDA134X_DATA1_ADDR ((UDA134X_L3ADDR << 2) | 1)
7#define UDA134X_STATUS_ADDR ((UDA134X_L3ADDR << 2) | 2)
8
9#define UDA134X_EXTADDR_PREFIX 0xC0
10#define UDA134X_EXTDATA_PREFIX 0xE0
11
12/* UDA134X registers */
13#define UDA134X_EA000 0
14#define UDA134X_EA001 1
15#define UDA134X_EA010 2
16#define UDA134X_EA011 3
17#define UDA134X_EA100 4
18#define UDA134X_EA101 5
19#define UDA134X_EA110 6
20#define UDA134X_EA111 7
21#define UDA134X_STATUS0 8
22#define UDA134X_STATUS1 9
23#define UDA134X_DATA000 10
24#define UDA134X_DATA001 11
25#define UDA134X_DATA010 12
26#define UDA134X_DATA1 13
27
28#define UDA134X_REGS_NUM 14
29
30#define STATUS0_DAIFMT_MASK (~(7<<1))
31#define STATUS0_SYSCLK_MASK (~(3<<4))
32
33extern struct snd_soc_dai uda134x_dai;
34extern struct snd_soc_codec_device soc_codec_dev_uda134x;
35
36#endif
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index a69ee72a7af5..e6bf0844fbf3 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -407,7 +407,8 @@ static int uda1380_set_dai_fmt(struct snd_soc_dai *codec_dai,
407 * when the DAI is being clocked by the CPU DAI. It's up to the 407 * when the DAI is being clocked by the CPU DAI. It's up to the
408 * machine and cpu DAI driver to do this before we are called. 408 * machine and cpu DAI driver to do this before we are called.
409 */ 409 */
410static int uda1380_pcm_prepare(struct snd_pcm_substream *substream) 410static int uda1380_pcm_prepare(struct snd_pcm_substream *substream,
411 struct snd_soc_dai *dai)
411{ 412{
412 struct snd_soc_pcm_runtime *rtd = substream->private_data; 413 struct snd_soc_pcm_runtime *rtd = substream->private_data;
413 struct snd_soc_device *socdev = rtd->socdev; 414 struct snd_soc_device *socdev = rtd->socdev;
@@ -439,7 +440,8 @@ static int uda1380_pcm_prepare(struct snd_pcm_substream *substream)
439} 440}
440 441
441static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream, 442static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream,
442 struct snd_pcm_hw_params *params) 443 struct snd_pcm_hw_params *params,
444 struct snd_soc_dai *dai)
443{ 445{
444 struct snd_soc_pcm_runtime *rtd = substream->private_data; 446 struct snd_soc_pcm_runtime *rtd = substream->private_data;
445 struct snd_soc_device *socdev = rtd->socdev; 447 struct snd_soc_device *socdev = rtd->socdev;
@@ -477,7 +479,8 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream,
477 return 0; 479 return 0;
478} 480}
479 481
480static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream) 482static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream,
483 struct snd_soc_dai *dai)
481{ 484{
482 struct snd_soc_pcm_runtime *rtd = substream->private_data; 485 struct snd_soc_pcm_runtime *rtd = substream->private_data;
483 struct snd_soc_device *socdev = rtd->socdev; 486 struct snd_soc_device *socdev = rtd->socdev;
@@ -560,8 +563,6 @@ struct snd_soc_dai uda1380_dai[] = {
560 .hw_params = uda1380_pcm_hw_params, 563 .hw_params = uda1380_pcm_hw_params,
561 .shutdown = uda1380_pcm_shutdown, 564 .shutdown = uda1380_pcm_shutdown,
562 .prepare = uda1380_pcm_prepare, 565 .prepare = uda1380_pcm_prepare,
563 },
564 .dai_ops = {
565 .digital_mute = uda1380_mute, 566 .digital_mute = uda1380_mute,
566 .set_fmt = uda1380_set_dai_fmt, 567 .set_fmt = uda1380_set_dai_fmt,
567 }, 568 },
@@ -579,8 +580,6 @@ struct snd_soc_dai uda1380_dai[] = {
579 .hw_params = uda1380_pcm_hw_params, 580 .hw_params = uda1380_pcm_hw_params,
580 .shutdown = uda1380_pcm_shutdown, 581 .shutdown = uda1380_pcm_shutdown,
581 .prepare = uda1380_pcm_prepare, 582 .prepare = uda1380_pcm_prepare,
582 },
583 .dai_ops = {
584 .digital_mute = uda1380_mute, 583 .digital_mute = uda1380_mute,
585 .set_fmt = uda1380_set_dai_fmt, 584 .set_fmt = uda1380_set_dai_fmt,
586 }, 585 },
@@ -598,8 +597,6 @@ struct snd_soc_dai uda1380_dai[] = {
598 .hw_params = uda1380_pcm_hw_params, 597 .hw_params = uda1380_pcm_hw_params,
599 .shutdown = uda1380_pcm_shutdown, 598 .shutdown = uda1380_pcm_shutdown,
600 .prepare = uda1380_pcm_prepare, 599 .prepare = uda1380_pcm_prepare,
601 },
602 .dai_ops = {
603 .set_fmt = uda1380_set_dai_fmt, 600 .set_fmt = uda1380_set_dai_fmt,
604 }, 601 },
605}, 602},
@@ -680,7 +677,7 @@ static int uda1380_init(struct snd_soc_device *socdev, int dac_clk)
680 /* uda1380 init */ 677 /* uda1380 init */
681 uda1380_add_controls(codec); 678 uda1380_add_controls(codec);
682 uda1380_add_widgets(codec); 679 uda1380_add_widgets(codec);
683 ret = snd_soc_register_card(socdev); 680 ret = snd_soc_init_card(socdev);
684 if (ret < 0) { 681 if (ret < 0) {
685 pr_err("uda1380: failed to register card\n"); 682 pr_err("uda1380: failed to register card\n");
686 goto card_err; 683 goto card_err;
@@ -844,6 +841,18 @@ struct snd_soc_codec_device soc_codec_dev_uda1380 = {
844}; 841};
845EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380); 842EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380);
846 843
844static int __init uda1380_modinit(void)
845{
846 return snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
847}
848module_init(uda1380_modinit);
849
850static void __exit uda1380_exit(void)
851{
852 snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
853}
854module_exit(uda1380_exit);
855
847MODULE_AUTHOR("Giorgio Padrin"); 856MODULE_AUTHOR("Giorgio Padrin");
848MODULE_DESCRIPTION("Audio support for codec Philips UDA1380"); 857MODULE_DESCRIPTION("Audio support for codec Philips UDA1380");
849MODULE_LICENSE("GPL"); 858MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
new file mode 100644
index 000000000000..e3989d406f54
--- /dev/null
+++ b/sound/soc/codecs/wm8350.c
@@ -0,0 +1,1583 @@
1/*
2 * wm8350.c -- WM8350 ALSA SoC audio driver
3 *
4 * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC.
5 *
6 * Author: Liam Girdwood <lg@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/platform_device.h>
19#include <linux/mfd/wm8350/audio.h>
20#include <linux/mfd/wm8350/core.h>
21#include <linux/regulator/consumer.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h>
26#include <sound/soc-dapm.h>
27#include <sound/initval.h>
28#include <sound/tlv.h>
29
30#include "wm8350.h"
31
32#define WM8350_OUTn_0dB 0x39
33
34#define WM8350_RAMP_NONE 0
35#define WM8350_RAMP_UP 1
36#define WM8350_RAMP_DOWN 2
37
38/* We only include the analogue supplies here; the digital supplies
39 * need to be available well before this driver can be probed.
40 */
41static const char *supply_names[] = {
42 "AVDD",
43 "HPVDD",
44};
45
46struct wm8350_output {
47 u16 active;
48 u16 left_vol;
49 u16 right_vol;
50 u16 ramp;
51 u16 mute;
52};
53
54struct wm8350_data {
55 struct snd_soc_codec codec;
56 struct wm8350_output out1;
57 struct wm8350_output out2;
58 struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
59};
60
61static unsigned int wm8350_codec_cache_read(struct snd_soc_codec *codec,
62 unsigned int reg)
63{
64 struct wm8350 *wm8350 = codec->control_data;
65 return wm8350->reg_cache[reg];
66}
67
68static unsigned int wm8350_codec_read(struct snd_soc_codec *codec,
69 unsigned int reg)
70{
71 struct wm8350 *wm8350 = codec->control_data;
72 return wm8350_reg_read(wm8350, reg);
73}
74
75static int wm8350_codec_write(struct snd_soc_codec *codec, unsigned int reg,
76 unsigned int value)
77{
78 struct wm8350 *wm8350 = codec->control_data;
79 return wm8350_reg_write(wm8350, reg, value);
80}
81
82/*
83 * Ramp OUT1 PGA volume to minimise pops at stream startup and shutdown.
84 */
85static inline int wm8350_out1_ramp_step(struct snd_soc_codec *codec)
86{
87 struct wm8350_data *wm8350_data = codec->private_data;
88 struct wm8350_output *out1 = &wm8350_data->out1;
89 struct wm8350 *wm8350 = codec->control_data;
90 int left_complete = 0, right_complete = 0;
91 u16 reg, val;
92
93 /* left channel */
94 reg = wm8350_reg_read(wm8350, WM8350_LOUT1_VOLUME);
95 val = (reg & WM8350_OUT1L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT;
96
97 if (out1->ramp == WM8350_RAMP_UP) {
98 /* ramp step up */
99 if (val < out1->left_vol) {
100 val++;
101 reg &= ~WM8350_OUT1L_VOL_MASK;
102 wm8350_reg_write(wm8350, WM8350_LOUT1_VOLUME,
103 reg | (val << WM8350_OUT1L_VOL_SHIFT));
104 } else
105 left_complete = 1;
106 } else if (out1->ramp == WM8350_RAMP_DOWN) {
107 /* ramp step down */
108 if (val > 0) {
109 val--;
110 reg &= ~WM8350_OUT1L_VOL_MASK;
111 wm8350_reg_write(wm8350, WM8350_LOUT1_VOLUME,
112 reg | (val << WM8350_OUT1L_VOL_SHIFT));
113 } else
114 left_complete = 1;
115 } else
116 return 1;
117
118 /* right channel */
119 reg = wm8350_reg_read(wm8350, WM8350_ROUT1_VOLUME);
120 val = (reg & WM8350_OUT1R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT;
121 if (out1->ramp == WM8350_RAMP_UP) {
122 /* ramp step up */
123 if (val < out1->right_vol) {
124 val++;
125 reg &= ~WM8350_OUT1R_VOL_MASK;
126 wm8350_reg_write(wm8350, WM8350_ROUT1_VOLUME,
127 reg | (val << WM8350_OUT1R_VOL_SHIFT));
128 } else
129 right_complete = 1;
130 } else if (out1->ramp == WM8350_RAMP_DOWN) {
131 /* ramp step down */
132 if (val > 0) {
133 val--;
134 reg &= ~WM8350_OUT1R_VOL_MASK;
135 wm8350_reg_write(wm8350, WM8350_ROUT1_VOLUME,
136 reg | (val << WM8350_OUT1R_VOL_SHIFT));
137 } else
138 right_complete = 1;
139 }
140
141 /* only hit the update bit if either volume has changed this step */
142 if (!left_complete || !right_complete)
143 wm8350_set_bits(wm8350, WM8350_LOUT1_VOLUME, WM8350_OUT1_VU);
144
145 return left_complete & right_complete;
146}
147
148/*
149 * Ramp OUT2 PGA volume to minimise pops at stream startup and shutdown.
150 */
151static inline int wm8350_out2_ramp_step(struct snd_soc_codec *codec)
152{
153 struct wm8350_data *wm8350_data = codec->private_data;
154 struct wm8350_output *out2 = &wm8350_data->out2;
155 struct wm8350 *wm8350 = codec->control_data;
156 int left_complete = 0, right_complete = 0;
157 u16 reg, val;
158
159 /* left channel */
160 reg = wm8350_reg_read(wm8350, WM8350_LOUT2_VOLUME);
161 val = (reg & WM8350_OUT2L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT;
162 if (out2->ramp == WM8350_RAMP_UP) {
163 /* ramp step up */
164 if (val < out2->left_vol) {
165 val++;
166 reg &= ~WM8350_OUT2L_VOL_MASK;
167 wm8350_reg_write(wm8350, WM8350_LOUT2_VOLUME,
168 reg | (val << WM8350_OUT1L_VOL_SHIFT));
169 } else
170 left_complete = 1;
171 } else if (out2->ramp == WM8350_RAMP_DOWN) {
172 /* ramp step down */
173 if (val > 0) {
174 val--;
175 reg &= ~WM8350_OUT2L_VOL_MASK;
176 wm8350_reg_write(wm8350, WM8350_LOUT2_VOLUME,
177 reg | (val << WM8350_OUT1L_VOL_SHIFT));
178 } else
179 left_complete = 1;
180 } else
181 return 1;
182
183 /* right channel */
184 reg = wm8350_reg_read(wm8350, WM8350_ROUT2_VOLUME);
185 val = (reg & WM8350_OUT2R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT;
186 if (out2->ramp == WM8350_RAMP_UP) {
187 /* ramp step up */
188 if (val < out2->right_vol) {
189 val++;
190 reg &= ~WM8350_OUT2R_VOL_MASK;
191 wm8350_reg_write(wm8350, WM8350_ROUT2_VOLUME,
192 reg | (val << WM8350_OUT1R_VOL_SHIFT));
193 } else
194 right_complete = 1;
195 } else if (out2->ramp == WM8350_RAMP_DOWN) {
196 /* ramp step down */
197 if (val > 0) {
198 val--;
199 reg &= ~WM8350_OUT2R_VOL_MASK;
200 wm8350_reg_write(wm8350, WM8350_ROUT2_VOLUME,
201 reg | (val << WM8350_OUT1R_VOL_SHIFT));
202 } else
203 right_complete = 1;
204 }
205
206 /* only hit the update bit if either volume has changed this step */
207 if (!left_complete || !right_complete)
208 wm8350_set_bits(wm8350, WM8350_LOUT2_VOLUME, WM8350_OUT2_VU);
209
210 return left_complete & right_complete;
211}
212
213/*
214 * This work ramps both output PGAs at stream start/stop time to
215 * minimise pop associated with DAPM power switching.
216 * It's best to enable Zero Cross when ramping occurs to minimise any
217 * zipper noises.
218 */
219static void wm8350_pga_work(struct work_struct *work)
220{
221 struct snd_soc_codec *codec =
222 container_of(work, struct snd_soc_codec, delayed_work.work);
223 struct wm8350_data *wm8350_data = codec->private_data;
224 struct wm8350_output *out1 = &wm8350_data->out1,
225 *out2 = &wm8350_data->out2;
226 int i, out1_complete, out2_complete;
227
228 /* do we need to ramp at all ? */
229 if (out1->ramp == WM8350_RAMP_NONE && out2->ramp == WM8350_RAMP_NONE)
230 return;
231
232 /* PGA volumes have 6 bits of resolution to ramp */
233 for (i = 0; i <= 63; i++) {
234 out1_complete = 1, out2_complete = 1;
235 if (out1->ramp != WM8350_RAMP_NONE)
236 out1_complete = wm8350_out1_ramp_step(codec);
237 if (out2->ramp != WM8350_RAMP_NONE)
238 out2_complete = wm8350_out2_ramp_step(codec);
239
240 /* ramp finished ? */
241 if (out1_complete && out2_complete)
242 break;
243
244 /* we need to delay longer on the up ramp */
245 if (out1->ramp == WM8350_RAMP_UP ||
246 out2->ramp == WM8350_RAMP_UP) {
247 /* delay is longer over 0dB as increases are larger */
248 if (i >= WM8350_OUTn_0dB)
249 schedule_timeout_interruptible(msecs_to_jiffies
250 (2));
251 else
252 schedule_timeout_interruptible(msecs_to_jiffies
253 (1));
254 } else
255 udelay(50); /* doesn't matter if we delay longer */
256 }
257
258 out1->ramp = WM8350_RAMP_NONE;
259 out2->ramp = WM8350_RAMP_NONE;
260}
261
262/*
263 * WM8350 Controls
264 */
265
266static int pga_event(struct snd_soc_dapm_widget *w,
267 struct snd_kcontrol *kcontrol, int event)
268{
269 struct snd_soc_codec *codec = w->codec;
270 struct wm8350_data *wm8350_data = codec->private_data;
271 struct wm8350_output *out;
272
273 switch (w->shift) {
274 case 0:
275 case 1:
276 out = &wm8350_data->out1;
277 break;
278 case 2:
279 case 3:
280 out = &wm8350_data->out2;
281 break;
282
283 default:
284 BUG();
285 return -1;
286 }
287
288 switch (event) {
289 case SND_SOC_DAPM_POST_PMU:
290 out->ramp = WM8350_RAMP_UP;
291 out->active = 1;
292
293 if (!delayed_work_pending(&codec->delayed_work))
294 schedule_delayed_work(&codec->delayed_work,
295 msecs_to_jiffies(1));
296 break;
297
298 case SND_SOC_DAPM_PRE_PMD:
299 out->ramp = WM8350_RAMP_DOWN;
300 out->active = 0;
301
302 if (!delayed_work_pending(&codec->delayed_work))
303 schedule_delayed_work(&codec->delayed_work,
304 msecs_to_jiffies(1));
305 break;
306 }
307
308 return 0;
309}
310
311static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
312 struct snd_ctl_elem_value *ucontrol)
313{
314 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
315 struct wm8350_data *wm8350_priv = codec->private_data;
316 struct wm8350_output *out = NULL;
317 struct soc_mixer_control *mc =
318 (struct soc_mixer_control *)kcontrol->private_value;
319 int ret;
320 unsigned int reg = mc->reg;
321 u16 val;
322
323 /* For OUT1 and OUT2 we shadow the values and only actually write
324 * them out when active in order to ensure the amplifier comes on
325 * as quietly as possible. */
326 switch (reg) {
327 case WM8350_LOUT1_VOLUME:
328 out = &wm8350_priv->out1;
329 break;
330 case WM8350_LOUT2_VOLUME:
331 out = &wm8350_priv->out2;
332 break;
333 default:
334 break;
335 }
336
337 if (out) {
338 out->left_vol = ucontrol->value.integer.value[0];
339 out->right_vol = ucontrol->value.integer.value[1];
340 if (!out->active)
341 return 1;
342 }
343
344 ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
345 if (ret < 0)
346 return ret;
347
348 /* now hit the volume update bits (always bit 8) */
349 val = wm8350_codec_read(codec, reg);
350 wm8350_codec_write(codec, reg, val | WM8350_OUT1_VU);
351 return 1;
352}
353
354static int wm8350_get_volsw_2r(struct snd_kcontrol *kcontrol,
355 struct snd_ctl_elem_value *ucontrol)
356{
357 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
358 struct wm8350_data *wm8350_priv = codec->private_data;
359 struct wm8350_output *out1 = &wm8350_priv->out1;
360 struct wm8350_output *out2 = &wm8350_priv->out2;
361 struct soc_mixer_control *mc =
362 (struct soc_mixer_control *)kcontrol->private_value;
363 unsigned int reg = mc->reg;
364
365 /* If these are cached registers use the cache */
366 switch (reg) {
367 case WM8350_LOUT1_VOLUME:
368 ucontrol->value.integer.value[0] = out1->left_vol;
369 ucontrol->value.integer.value[1] = out1->right_vol;
370 return 0;
371
372 case WM8350_LOUT2_VOLUME:
373 ucontrol->value.integer.value[0] = out2->left_vol;
374 ucontrol->value.integer.value[1] = out2->right_vol;
375 return 0;
376
377 default:
378 break;
379 }
380
381 return snd_soc_get_volsw_2r(kcontrol, ucontrol);
382}
383
384/* double control with volume update */
385#define SOC_WM8350_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \
386 xinvert, tlv_array) \
387{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
388 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
389 SNDRV_CTL_ELEM_ACCESS_READWRITE | \
390 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
391 .tlv.p = (tlv_array), \
392 .info = snd_soc_info_volsw_2r, \
393 .get = wm8350_get_volsw_2r, .put = wm8350_put_volsw_2r_vu, \
394 .private_value = (unsigned long)&(struct soc_mixer_control) \
395 {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
396 .rshift = xshift, .max = xmax, .invert = xinvert}, }
397
398static const char *wm8350_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
399static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" };
400static const char *wm8350_dacmutem[] = { "Normal", "Soft" };
401static const char *wm8350_dacmutes[] = { "Fast", "Slow" };
402static const char *wm8350_dacfilter[] = { "Normal", "Sloping" };
403static const char *wm8350_adcfilter[] = { "None", "High Pass" };
404static const char *wm8350_adchp[] = { "44.1kHz", "8kHz", "16kHz", "32kHz" };
405static const char *wm8350_lr[] = { "Left", "Right" };
406
407static const struct soc_enum wm8350_enum[] = {
408 SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 4, 4, wm8350_deemp),
409 SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 0, 4, wm8350_pol),
410 SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 14, 2, wm8350_dacmutem),
411 SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 13, 2, wm8350_dacmutes),
412 SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 12, 2, wm8350_dacfilter),
413 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 15, 2, wm8350_adcfilter),
414 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 8, 4, wm8350_adchp),
415 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 0, 4, wm8350_pol),
416 SOC_ENUM_SINGLE(WM8350_INPUT_MIXER_VOLUME, 15, 2, wm8350_lr),
417};
418
419static DECLARE_TLV_DB_LINEAR(pre_amp_tlv, -1200, 3525);
420static DECLARE_TLV_DB_LINEAR(out_pga_tlv, -5700, 600);
421static DECLARE_TLV_DB_SCALE(dac_pcm_tlv, -7163, 36, 1);
422static DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -12700, 50, 1);
423static DECLARE_TLV_DB_SCALE(out_mix_tlv, -1500, 300, 1);
424
425static const unsigned int capture_sd_tlv[] = {
426 TLV_DB_RANGE_HEAD(2),
427 0, 12, TLV_DB_SCALE_ITEM(-3600, 300, 1),
428 13, 15, TLV_DB_SCALE_ITEM(0, 0, 0),
429};
430
431static const struct snd_kcontrol_new wm8350_snd_controls[] = {
432 SOC_ENUM("Playback Deemphasis", wm8350_enum[0]),
433 SOC_ENUM("Playback DAC Inversion", wm8350_enum[1]),
434 SOC_WM8350_DOUBLE_R_TLV("Playback PCM Volume",
435 WM8350_DAC_DIGITAL_VOLUME_L,
436 WM8350_DAC_DIGITAL_VOLUME_R,
437 0, 255, 0, dac_pcm_tlv),
438 SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]),
439 SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]),
440 SOC_ENUM("Playback PCM Filter", wm8350_enum[4]),
441 SOC_ENUM("Capture PCM Filter", wm8350_enum[5]),
442 SOC_ENUM("Capture PCM HP Filter", wm8350_enum[6]),
443 SOC_ENUM("Capture ADC Inversion", wm8350_enum[7]),
444 SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume",
445 WM8350_ADC_DIGITAL_VOLUME_L,
446 WM8350_ADC_DIGITAL_VOLUME_R,
447 0, 255, 0, adc_pcm_tlv),
448 SOC_DOUBLE_TLV("Capture Sidetone Volume",
449 WM8350_ADC_DIVIDER,
450 8, 4, 15, 1, capture_sd_tlv),
451 SOC_WM8350_DOUBLE_R_TLV("Capture Volume",
452 WM8350_LEFT_INPUT_VOLUME,
453 WM8350_RIGHT_INPUT_VOLUME,
454 2, 63, 0, pre_amp_tlv),
455 SOC_DOUBLE_R("Capture ZC Switch",
456 WM8350_LEFT_INPUT_VOLUME,
457 WM8350_RIGHT_INPUT_VOLUME, 13, 1, 0),
458 SOC_SINGLE_TLV("Left Input Left Sidetone Volume",
459 WM8350_OUTPUT_LEFT_MIXER_VOLUME, 1, 7, 0, out_mix_tlv),
460 SOC_SINGLE_TLV("Left Input Right Sidetone Volume",
461 WM8350_OUTPUT_LEFT_MIXER_VOLUME,
462 5, 7, 0, out_mix_tlv),
463 SOC_SINGLE_TLV("Left Input Bypass Volume",
464 WM8350_OUTPUT_LEFT_MIXER_VOLUME,
465 9, 7, 0, out_mix_tlv),
466 SOC_SINGLE_TLV("Right Input Left Sidetone Volume",
467 WM8350_OUTPUT_RIGHT_MIXER_VOLUME,
468 1, 7, 0, out_mix_tlv),
469 SOC_SINGLE_TLV("Right Input Right Sidetone Volume",
470 WM8350_OUTPUT_RIGHT_MIXER_VOLUME,
471 5, 7, 0, out_mix_tlv),
472 SOC_SINGLE_TLV("Right Input Bypass Volume",
473 WM8350_OUTPUT_RIGHT_MIXER_VOLUME,
474 13, 7, 0, out_mix_tlv),
475 SOC_SINGLE("Left Input Mixer +20dB Switch",
476 WM8350_INPUT_MIXER_VOLUME_L, 0, 1, 0),
477 SOC_SINGLE("Right Input Mixer +20dB Switch",
478 WM8350_INPUT_MIXER_VOLUME_R, 0, 1, 0),
479 SOC_SINGLE_TLV("Out4 Capture Volume",
480 WM8350_INPUT_MIXER_VOLUME,
481 1, 7, 0, out_mix_tlv),
482 SOC_WM8350_DOUBLE_R_TLV("Out1 Playback Volume",
483 WM8350_LOUT1_VOLUME,
484 WM8350_ROUT1_VOLUME,
485 2, 63, 0, out_pga_tlv),
486 SOC_DOUBLE_R("Out1 Playback ZC Switch",
487 WM8350_LOUT1_VOLUME,
488 WM8350_ROUT1_VOLUME, 13, 1, 0),
489 SOC_WM8350_DOUBLE_R_TLV("Out2 Playback Volume",
490 WM8350_LOUT2_VOLUME,
491 WM8350_ROUT2_VOLUME,
492 2, 63, 0, out_pga_tlv),
493 SOC_DOUBLE_R("Out2 Playback ZC Switch", WM8350_LOUT2_VOLUME,
494 WM8350_ROUT2_VOLUME, 13, 1, 0),
495 SOC_SINGLE("Out2 Right Invert Switch", WM8350_ROUT2_VOLUME, 10, 1, 0),
496 SOC_SINGLE_TLV("Out2 Beep Volume", WM8350_BEEP_VOLUME,
497 5, 7, 0, out_mix_tlv),
498
499 SOC_DOUBLE_R("Out1 Playback Switch",
500 WM8350_LOUT1_VOLUME,
501 WM8350_ROUT1_VOLUME,
502 14, 1, 1),
503 SOC_DOUBLE_R("Out2 Playback Switch",
504 WM8350_LOUT2_VOLUME,
505 WM8350_ROUT2_VOLUME,
506 14, 1, 1),
507};
508
509/*
510 * DAPM Controls
511 */
512
513/* Left Playback Mixer */
514static const struct snd_kcontrol_new wm8350_left_play_mixer_controls[] = {
515 SOC_DAPM_SINGLE("Playback Switch",
516 WM8350_LEFT_MIXER_CONTROL, 11, 1, 0),
517 SOC_DAPM_SINGLE("Left Bypass Switch",
518 WM8350_LEFT_MIXER_CONTROL, 2, 1, 0),
519 SOC_DAPM_SINGLE("Right Playback Switch",
520 WM8350_LEFT_MIXER_CONTROL, 12, 1, 0),
521 SOC_DAPM_SINGLE("Left Sidetone Switch",
522 WM8350_LEFT_MIXER_CONTROL, 0, 1, 0),
523 SOC_DAPM_SINGLE("Right Sidetone Switch",
524 WM8350_LEFT_MIXER_CONTROL, 1, 1, 0),
525};
526
527/* Right Playback Mixer */
528static const struct snd_kcontrol_new wm8350_right_play_mixer_controls[] = {
529 SOC_DAPM_SINGLE("Playback Switch",
530 WM8350_RIGHT_MIXER_CONTROL, 12, 1, 0),
531 SOC_DAPM_SINGLE("Right Bypass Switch",
532 WM8350_RIGHT_MIXER_CONTROL, 3, 1, 0),
533 SOC_DAPM_SINGLE("Left Playback Switch",
534 WM8350_RIGHT_MIXER_CONTROL, 11, 1, 0),
535 SOC_DAPM_SINGLE("Left Sidetone Switch",
536 WM8350_RIGHT_MIXER_CONTROL, 0, 1, 0),
537 SOC_DAPM_SINGLE("Right Sidetone Switch",
538 WM8350_RIGHT_MIXER_CONTROL, 1, 1, 0),
539};
540
541/* Out4 Mixer */
542static const struct snd_kcontrol_new wm8350_out4_mixer_controls[] = {
543 SOC_DAPM_SINGLE("Right Playback Switch",
544 WM8350_OUT4_MIXER_CONTROL, 12, 1, 0),
545 SOC_DAPM_SINGLE("Left Playback Switch",
546 WM8350_OUT4_MIXER_CONTROL, 11, 1, 0),
547 SOC_DAPM_SINGLE("Right Capture Switch",
548 WM8350_OUT4_MIXER_CONTROL, 9, 1, 0),
549 SOC_DAPM_SINGLE("Out3 Playback Switch",
550 WM8350_OUT4_MIXER_CONTROL, 2, 1, 0),
551 SOC_DAPM_SINGLE("Right Mixer Switch",
552 WM8350_OUT4_MIXER_CONTROL, 1, 1, 0),
553 SOC_DAPM_SINGLE("Left Mixer Switch",
554 WM8350_OUT4_MIXER_CONTROL, 0, 1, 0),
555};
556
557/* Out3 Mixer */
558static const struct snd_kcontrol_new wm8350_out3_mixer_controls[] = {
559 SOC_DAPM_SINGLE("Left Playback Switch",
560 WM8350_OUT3_MIXER_CONTROL, 11, 1, 0),
561 SOC_DAPM_SINGLE("Left Capture Switch",
562 WM8350_OUT3_MIXER_CONTROL, 8, 1, 0),
563 SOC_DAPM_SINGLE("Out4 Playback Switch",
564 WM8350_OUT3_MIXER_CONTROL, 3, 1, 0),
565 SOC_DAPM_SINGLE("Left Mixer Switch",
566 WM8350_OUT3_MIXER_CONTROL, 0, 1, 0),
567};
568
569/* Left Input Mixer */
570static const struct snd_kcontrol_new wm8350_left_capt_mixer_controls[] = {
571 SOC_DAPM_SINGLE_TLV("L2 Capture Volume",
572 WM8350_INPUT_MIXER_VOLUME_L, 1, 7, 0, out_mix_tlv),
573 SOC_DAPM_SINGLE_TLV("L3 Capture Volume",
574 WM8350_INPUT_MIXER_VOLUME_L, 9, 7, 0, out_mix_tlv),
575 SOC_DAPM_SINGLE("PGA Capture Switch",
576 WM8350_LEFT_INPUT_VOLUME, 14, 1, 0),
577};
578
579/* Right Input Mixer */
580static const struct snd_kcontrol_new wm8350_right_capt_mixer_controls[] = {
581 SOC_DAPM_SINGLE_TLV("L2 Capture Volume",
582 WM8350_INPUT_MIXER_VOLUME_R, 5, 7, 0, out_mix_tlv),
583 SOC_DAPM_SINGLE_TLV("L3 Capture Volume",
584 WM8350_INPUT_MIXER_VOLUME_R, 13, 7, 0, out_mix_tlv),
585 SOC_DAPM_SINGLE("PGA Capture Switch",
586 WM8350_RIGHT_INPUT_VOLUME, 14, 1, 0),
587};
588
589/* Left Mic Mixer */
590static const struct snd_kcontrol_new wm8350_left_mic_mixer_controls[] = {
591 SOC_DAPM_SINGLE("INN Capture Switch", WM8350_INPUT_CONTROL, 1, 1, 0),
592 SOC_DAPM_SINGLE("INP Capture Switch", WM8350_INPUT_CONTROL, 0, 1, 0),
593 SOC_DAPM_SINGLE("IN2 Capture Switch", WM8350_INPUT_CONTROL, 2, 1, 0),
594};
595
596/* Right Mic Mixer */
597static const struct snd_kcontrol_new wm8350_right_mic_mixer_controls[] = {
598 SOC_DAPM_SINGLE("INN Capture Switch", WM8350_INPUT_CONTROL, 9, 1, 0),
599 SOC_DAPM_SINGLE("INP Capture Switch", WM8350_INPUT_CONTROL, 8, 1, 0),
600 SOC_DAPM_SINGLE("IN2 Capture Switch", WM8350_INPUT_CONTROL, 10, 1, 0),
601};
602
603/* Beep Switch */
604static const struct snd_kcontrol_new wm8350_beep_switch_controls =
605SOC_DAPM_SINGLE("Switch", WM8350_BEEP_VOLUME, 15, 1, 1);
606
607/* Out4 Capture Mux */
608static const struct snd_kcontrol_new wm8350_out4_capture_controls =
609SOC_DAPM_ENUM("Route", wm8350_enum[8]);
610
611static const struct snd_soc_dapm_widget wm8350_dapm_widgets[] = {
612
613 SND_SOC_DAPM_PGA("IN3R PGA", WM8350_POWER_MGMT_2, 11, 0, NULL, 0),
614 SND_SOC_DAPM_PGA("IN3L PGA", WM8350_POWER_MGMT_2, 10, 0, NULL, 0),
615 SND_SOC_DAPM_PGA_E("Right Out2 PGA", WM8350_POWER_MGMT_3, 3, 0, NULL,
616 0, pga_event,
617 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
618 SND_SOC_DAPM_PGA_E("Left Out2 PGA", WM8350_POWER_MGMT_3, 2, 0, NULL, 0,
619 pga_event,
620 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
621 SND_SOC_DAPM_PGA_E("Right Out1 PGA", WM8350_POWER_MGMT_3, 1, 0, NULL,
622 0, pga_event,
623 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
624 SND_SOC_DAPM_PGA_E("Left Out1 PGA", WM8350_POWER_MGMT_3, 0, 0, NULL, 0,
625 pga_event,
626 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
627
628 SND_SOC_DAPM_MIXER("Right Capture Mixer", WM8350_POWER_MGMT_2,
629 7, 0, &wm8350_right_capt_mixer_controls[0],
630 ARRAY_SIZE(wm8350_right_capt_mixer_controls)),
631
632 SND_SOC_DAPM_MIXER("Left Capture Mixer", WM8350_POWER_MGMT_2,
633 6, 0, &wm8350_left_capt_mixer_controls[0],
634 ARRAY_SIZE(wm8350_left_capt_mixer_controls)),
635
636 SND_SOC_DAPM_MIXER("Out4 Mixer", WM8350_POWER_MGMT_2, 5, 0,
637 &wm8350_out4_mixer_controls[0],
638 ARRAY_SIZE(wm8350_out4_mixer_controls)),
639
640 SND_SOC_DAPM_MIXER("Out3 Mixer", WM8350_POWER_MGMT_2, 4, 0,
641 &wm8350_out3_mixer_controls[0],
642 ARRAY_SIZE(wm8350_out3_mixer_controls)),
643
644 SND_SOC_DAPM_MIXER("Right Playback Mixer", WM8350_POWER_MGMT_2, 1, 0,
645 &wm8350_right_play_mixer_controls[0],
646 ARRAY_SIZE(wm8350_right_play_mixer_controls)),
647
648 SND_SOC_DAPM_MIXER("Left Playback Mixer", WM8350_POWER_MGMT_2, 0, 0,
649 &wm8350_left_play_mixer_controls[0],
650 ARRAY_SIZE(wm8350_left_play_mixer_controls)),
651
652 SND_SOC_DAPM_MIXER("Left Mic Mixer", WM8350_POWER_MGMT_2, 8, 0,
653 &wm8350_left_mic_mixer_controls[0],
654 ARRAY_SIZE(wm8350_left_mic_mixer_controls)),
655
656 SND_SOC_DAPM_MIXER("Right Mic Mixer", WM8350_POWER_MGMT_2, 9, 0,
657 &wm8350_right_mic_mixer_controls[0],
658 ARRAY_SIZE(wm8350_right_mic_mixer_controls)),
659
660 /* virtual mixer for Beep and Out2R */
661 SND_SOC_DAPM_MIXER("Out2 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
662
663 SND_SOC_DAPM_SWITCH("Beep", WM8350_POWER_MGMT_3, 7, 0,
664 &wm8350_beep_switch_controls),
665
666 SND_SOC_DAPM_ADC("Right ADC", "Right Capture",
667 WM8350_POWER_MGMT_4, 3, 0),
668 SND_SOC_DAPM_ADC("Left ADC", "Left Capture",
669 WM8350_POWER_MGMT_4, 2, 0),
670 SND_SOC_DAPM_DAC("Right DAC", "Right Playback",
671 WM8350_POWER_MGMT_4, 5, 0),
672 SND_SOC_DAPM_DAC("Left DAC", "Left Playback",
673 WM8350_POWER_MGMT_4, 4, 0),
674
675 SND_SOC_DAPM_MICBIAS("Mic Bias", WM8350_POWER_MGMT_1, 4, 0),
676
677 SND_SOC_DAPM_MUX("Out4 Capture Channel", SND_SOC_NOPM, 0, 0,
678 &wm8350_out4_capture_controls),
679
680 SND_SOC_DAPM_OUTPUT("OUT1R"),
681 SND_SOC_DAPM_OUTPUT("OUT1L"),
682 SND_SOC_DAPM_OUTPUT("OUT2R"),
683 SND_SOC_DAPM_OUTPUT("OUT2L"),
684 SND_SOC_DAPM_OUTPUT("OUT3"),
685 SND_SOC_DAPM_OUTPUT("OUT4"),
686
687 SND_SOC_DAPM_INPUT("IN1RN"),
688 SND_SOC_DAPM_INPUT("IN1RP"),
689 SND_SOC_DAPM_INPUT("IN2R"),
690 SND_SOC_DAPM_INPUT("IN1LP"),
691 SND_SOC_DAPM_INPUT("IN1LN"),
692 SND_SOC_DAPM_INPUT("IN2L"),
693 SND_SOC_DAPM_INPUT("IN3R"),
694 SND_SOC_DAPM_INPUT("IN3L"),
695};
696
697static const struct snd_soc_dapm_route audio_map[] = {
698
699 /* left playback mixer */
700 {"Left Playback Mixer", "Playback Switch", "Left DAC"},
701 {"Left Playback Mixer", "Left Bypass Switch", "IN3L PGA"},
702 {"Left Playback Mixer", "Right Playback Switch", "Right DAC"},
703 {"Left Playback Mixer", "Left Sidetone Switch", "Left Mic Mixer"},
704 {"Left Playback Mixer", "Right Sidetone Switch", "Right Mic Mixer"},
705
706 /* right playback mixer */
707 {"Right Playback Mixer", "Playback Switch", "Right DAC"},
708 {"Right Playback Mixer", "Right Bypass Switch", "IN3R PGA"},
709 {"Right Playback Mixer", "Left Playback Switch", "Left DAC"},
710 {"Right Playback Mixer", "Left Sidetone Switch", "Left Mic Mixer"},
711 {"Right Playback Mixer", "Right Sidetone Switch", "Right Mic Mixer"},
712
713 /* out4 playback mixer */
714 {"Out4 Mixer", "Right Playback Switch", "Right DAC"},
715 {"Out4 Mixer", "Left Playback Switch", "Left DAC"},
716 {"Out4 Mixer", "Right Capture Switch", "Right Capture Mixer"},
717 {"Out4 Mixer", "Out3 Playback Switch", "Out3 Mixer"},
718 {"Out4 Mixer", "Right Mixer Switch", "Right Playback Mixer"},
719 {"Out4 Mixer", "Left Mixer Switch", "Left Playback Mixer"},
720 {"OUT4", NULL, "Out4 Mixer"},
721
722 /* out3 playback mixer */
723 {"Out3 Mixer", "Left Playback Switch", "Left DAC"},
724 {"Out3 Mixer", "Left Capture Switch", "Left Capture Mixer"},
725 {"Out3 Mixer", "Left Mixer Switch", "Left Playback Mixer"},
726 {"Out3 Mixer", "Out4 Playback Switch", "Out4 Mixer"},
727 {"OUT3", NULL, "Out3 Mixer"},
728
729 /* out2 */
730 {"Right Out2 PGA", NULL, "Right Playback Mixer"},
731 {"Left Out2 PGA", NULL, "Left Playback Mixer"},
732 {"OUT2L", NULL, "Left Out2 PGA"},
733 {"OUT2R", NULL, "Right Out2 PGA"},
734
735 /* out1 */
736 {"Right Out1 PGA", NULL, "Right Playback Mixer"},
737 {"Left Out1 PGA", NULL, "Left Playback Mixer"},
738 {"OUT1L", NULL, "Left Out1 PGA"},
739 {"OUT1R", NULL, "Right Out1 PGA"},
740
741 /* ADCs */
742 {"Left ADC", NULL, "Left Capture Mixer"},
743 {"Right ADC", NULL, "Right Capture Mixer"},
744
745 /* Left capture mixer */
746 {"Left Capture Mixer", "L2 Capture Volume", "IN2L"},
747 {"Left Capture Mixer", "L3 Capture Volume", "IN3L PGA"},
748 {"Left Capture Mixer", "PGA Capture Switch", "Left Mic Mixer"},
749 {"Left Capture Mixer", NULL, "Out4 Capture Channel"},
750
751 /* Right capture mixer */
752 {"Right Capture Mixer", "L2 Capture Volume", "IN2R"},
753 {"Right Capture Mixer", "L3 Capture Volume", "IN3R PGA"},
754 {"Right Capture Mixer", "PGA Capture Switch", "Right Mic Mixer"},
755 {"Right Capture Mixer", NULL, "Out4 Capture Channel"},
756
757 /* L3 Inputs */
758 {"IN3L PGA", NULL, "IN3L"},
759 {"IN3R PGA", NULL, "IN3R"},
760
761 /* Left Mic mixer */
762 {"Left Mic Mixer", "INN Capture Switch", "IN1LN"},
763 {"Left Mic Mixer", "INP Capture Switch", "IN1LP"},
764 {"Left Mic Mixer", "IN2 Capture Switch", "IN2L"},
765
766 /* Right Mic mixer */
767 {"Right Mic Mixer", "INN Capture Switch", "IN1RN"},
768 {"Right Mic Mixer", "INP Capture Switch", "IN1RP"},
769 {"Right Mic Mixer", "IN2 Capture Switch", "IN2R"},
770
771 /* out 4 capture */
772 {"Out4 Capture Channel", NULL, "Out4 Mixer"},
773
774 /* Beep */
775 {"Beep", NULL, "IN3R PGA"},
776};
777
778static int wm8350_add_controls(struct snd_soc_codec *codec)
779{
780 int err, i;
781
782 for (i = 0; i < ARRAY_SIZE(wm8350_snd_controls); i++) {
783 err = snd_ctl_add(codec->card,
784 snd_soc_cnew(&wm8350_snd_controls[i],
785 codec, NULL));
786 if (err < 0)
787 return err;
788 }
789
790 return 0;
791}
792
793static int wm8350_add_widgets(struct snd_soc_codec *codec)
794{
795 int ret;
796
797 ret = snd_soc_dapm_new_controls(codec,
798 wm8350_dapm_widgets,
799 ARRAY_SIZE(wm8350_dapm_widgets));
800 if (ret != 0) {
801 dev_err(codec->dev, "dapm control register failed\n");
802 return ret;
803 }
804
805 /* set up audio paths */
806 ret = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
807 if (ret != 0) {
808 dev_err(codec->dev, "DAPM route register failed\n");
809 return ret;
810 }
811
812 return snd_soc_dapm_new_widgets(codec);
813}
814
815static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai,
816 int clk_id, unsigned int freq, int dir)
817{
818 struct snd_soc_codec *codec = codec_dai->codec;
819 struct wm8350 *wm8350 = codec->control_data;
820 u16 fll_4;
821
822 switch (clk_id) {
823 case WM8350_MCLK_SEL_MCLK:
824 wm8350_clear_bits(wm8350, WM8350_CLOCK_CONTROL_1,
825 WM8350_MCLK_SEL);
826 break;
827 case WM8350_MCLK_SEL_PLL_MCLK:
828 case WM8350_MCLK_SEL_PLL_DAC:
829 case WM8350_MCLK_SEL_PLL_ADC:
830 case WM8350_MCLK_SEL_PLL_32K:
831 wm8350_set_bits(wm8350, WM8350_CLOCK_CONTROL_1,
832 WM8350_MCLK_SEL);
833 fll_4 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_4) &
834 ~WM8350_FLL_CLK_SRC_MASK;
835 wm8350_codec_write(codec, WM8350_FLL_CONTROL_4, fll_4 | clk_id);
836 break;
837 }
838
839 /* MCLK direction */
840 if (dir == WM8350_MCLK_DIR_OUT)
841 wm8350_set_bits(wm8350, WM8350_CLOCK_CONTROL_2,
842 WM8350_MCLK_DIR);
843 else
844 wm8350_clear_bits(wm8350, WM8350_CLOCK_CONTROL_2,
845 WM8350_MCLK_DIR);
846
847 return 0;
848}
849
850static int wm8350_set_clkdiv(struct snd_soc_dai *codec_dai, int div_id, int div)
851{
852 struct snd_soc_codec *codec = codec_dai->codec;
853 u16 val;
854
855 switch (div_id) {
856 case WM8350_ADC_CLKDIV:
857 val = wm8350_codec_read(codec, WM8350_ADC_DIVIDER) &
858 ~WM8350_ADC_CLKDIV_MASK;
859 wm8350_codec_write(codec, WM8350_ADC_DIVIDER, val | div);
860 break;
861 case WM8350_DAC_CLKDIV:
862 val = wm8350_codec_read(codec, WM8350_DAC_CLOCK_CONTROL) &
863 ~WM8350_DAC_CLKDIV_MASK;
864 wm8350_codec_write(codec, WM8350_DAC_CLOCK_CONTROL, val | div);
865 break;
866 case WM8350_BCLK_CLKDIV:
867 val = wm8350_codec_read(codec, WM8350_CLOCK_CONTROL_1) &
868 ~WM8350_BCLK_DIV_MASK;
869 wm8350_codec_write(codec, WM8350_CLOCK_CONTROL_1, val | div);
870 break;
871 case WM8350_OPCLK_CLKDIV:
872 val = wm8350_codec_read(codec, WM8350_CLOCK_CONTROL_1) &
873 ~WM8350_OPCLK_DIV_MASK;
874 wm8350_codec_write(codec, WM8350_CLOCK_CONTROL_1, val | div);
875 break;
876 case WM8350_SYS_CLKDIV:
877 val = wm8350_codec_read(codec, WM8350_CLOCK_CONTROL_1) &
878 ~WM8350_MCLK_DIV_MASK;
879 wm8350_codec_write(codec, WM8350_CLOCK_CONTROL_1, val | div);
880 break;
881 case WM8350_DACLR_CLKDIV:
882 val = wm8350_codec_read(codec, WM8350_DAC_LR_RATE) &
883 ~WM8350_DACLRC_RATE_MASK;
884 wm8350_codec_write(codec, WM8350_DAC_LR_RATE, val | div);
885 break;
886 case WM8350_ADCLR_CLKDIV:
887 val = wm8350_codec_read(codec, WM8350_ADC_LR_RATE) &
888 ~WM8350_ADCLRC_RATE_MASK;
889 wm8350_codec_write(codec, WM8350_ADC_LR_RATE, val | div);
890 break;
891 default:
892 return -EINVAL;
893 }
894
895 return 0;
896}
897
898static int wm8350_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
899{
900 struct snd_soc_codec *codec = codec_dai->codec;
901 u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) &
902 ~(WM8350_AIF_BCLK_INV | WM8350_AIF_LRCLK_INV | WM8350_AIF_FMT_MASK);
903 u16 master = wm8350_codec_read(codec, WM8350_AI_DAC_CONTROL) &
904 ~WM8350_BCLK_MSTR;
905 u16 dac_lrc = wm8350_codec_read(codec, WM8350_DAC_LR_RATE) &
906 ~WM8350_DACLRC_ENA;
907 u16 adc_lrc = wm8350_codec_read(codec, WM8350_ADC_LR_RATE) &
908 ~WM8350_ADCLRC_ENA;
909
910 /* set master/slave audio interface */
911 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
912 case SND_SOC_DAIFMT_CBM_CFM:
913 master |= WM8350_BCLK_MSTR;
914 dac_lrc |= WM8350_DACLRC_ENA;
915 adc_lrc |= WM8350_ADCLRC_ENA;
916 break;
917 case SND_SOC_DAIFMT_CBS_CFS:
918 break;
919 default:
920 return -EINVAL;
921 }
922
923 /* interface format */
924 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
925 case SND_SOC_DAIFMT_I2S:
926 iface |= 0x2 << 8;
927 break;
928 case SND_SOC_DAIFMT_RIGHT_J:
929 break;
930 case SND_SOC_DAIFMT_LEFT_J:
931 iface |= 0x1 << 8;
932 break;
933 case SND_SOC_DAIFMT_DSP_A:
934 iface |= 0x3 << 8;
935 break;
936 case SND_SOC_DAIFMT_DSP_B:
937 iface |= 0x3 << 8; /* lg not sure which mode */
938 break;
939 default:
940 return -EINVAL;
941 }
942
943 /* clock inversion */
944 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
945 case SND_SOC_DAIFMT_NB_NF:
946 break;
947 case SND_SOC_DAIFMT_IB_IF:
948 iface |= WM8350_AIF_LRCLK_INV | WM8350_AIF_BCLK_INV;
949 break;
950 case SND_SOC_DAIFMT_IB_NF:
951 iface |= WM8350_AIF_BCLK_INV;
952 break;
953 case SND_SOC_DAIFMT_NB_IF:
954 iface |= WM8350_AIF_LRCLK_INV;
955 break;
956 default:
957 return -EINVAL;
958 }
959
960 wm8350_codec_write(codec, WM8350_AI_FORMATING, iface);
961 wm8350_codec_write(codec, WM8350_AI_DAC_CONTROL, master);
962 wm8350_codec_write(codec, WM8350_DAC_LR_RATE, dac_lrc);
963 wm8350_codec_write(codec, WM8350_ADC_LR_RATE, adc_lrc);
964 return 0;
965}
966
967static int wm8350_pcm_trigger(struct snd_pcm_substream *substream,
968 int cmd, struct snd_soc_dai *codec_dai)
969{
970 struct snd_soc_codec *codec = codec_dai->codec;
971 int master = wm8350_codec_cache_read(codec, WM8350_AI_DAC_CONTROL) &
972 WM8350_BCLK_MSTR;
973 int enabled = 0;
974
975 /* Check that the DACs or ADCs are enabled since they are
976 * required for LRC in master mode. The DACs or ADCs need a
977 * valid audio path i.e. pin -> ADC or DAC -> pin before
978 * the LRC will be enabled in master mode. */
979 if (!master && cmd != SNDRV_PCM_TRIGGER_START)
980 return 0;
981
982 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
983 enabled = wm8350_codec_cache_read(codec, WM8350_POWER_MGMT_4) &
984 (WM8350_ADCR_ENA | WM8350_ADCL_ENA);
985 } else {
986 enabled = wm8350_codec_cache_read(codec, WM8350_POWER_MGMT_4) &
987 (WM8350_DACR_ENA | WM8350_DACL_ENA);
988 }
989
990 if (!enabled) {
991 dev_err(codec->dev,
992 "%s: invalid audio path - no clocks available\n",
993 __func__);
994 return -EINVAL;
995 }
996 return 0;
997}
998
999static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream,
1000 struct snd_pcm_hw_params *params,
1001 struct snd_soc_dai *codec_dai)
1002{
1003 struct snd_soc_codec *codec = codec_dai->codec;
1004 u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) &
1005 ~WM8350_AIF_WL_MASK;
1006
1007 /* bit size */
1008 switch (params_format(params)) {
1009 case SNDRV_PCM_FORMAT_S16_LE:
1010 break;
1011 case SNDRV_PCM_FORMAT_S20_3LE:
1012 iface |= 0x1 << 10;
1013 break;
1014 case SNDRV_PCM_FORMAT_S24_LE:
1015 iface |= 0x2 << 10;
1016 break;
1017 case SNDRV_PCM_FORMAT_S32_LE:
1018 iface |= 0x3 << 10;
1019 break;
1020 }
1021
1022 wm8350_codec_write(codec, WM8350_AI_FORMATING, iface);
1023 return 0;
1024}
1025
1026static int wm8350_mute(struct snd_soc_dai *dai, int mute)
1027{
1028 struct snd_soc_codec *codec = dai->codec;
1029 struct wm8350 *wm8350 = codec->control_data;
1030
1031 if (mute)
1032 wm8350_set_bits(wm8350, WM8350_DAC_MUTE, WM8350_DAC_MUTE_ENA);
1033 else
1034 wm8350_clear_bits(wm8350, WM8350_DAC_MUTE, WM8350_DAC_MUTE_ENA);
1035 return 0;
1036}
1037
1038/* FLL divisors */
1039struct _fll_div {
1040 int div; /* FLL_OUTDIV */
1041 int n;
1042 int k;
1043 int ratio; /* FLL_FRATIO */
1044};
1045
1046/* The size in bits of the fll divide multiplied by 10
1047 * to allow rounding later */
1048#define FIXED_FLL_SIZE ((1 << 16) * 10)
1049
1050static inline int fll_factors(struct _fll_div *fll_div, unsigned int input,
1051 unsigned int output)
1052{
1053 u64 Kpart;
1054 unsigned int t1, t2, K, Nmod;
1055
1056 if (output >= 2815250 && output <= 3125000)
1057 fll_div->div = 0x4;
1058 else if (output >= 5625000 && output <= 6250000)
1059 fll_div->div = 0x3;
1060 else if (output >= 11250000 && output <= 12500000)
1061 fll_div->div = 0x2;
1062 else if (output >= 22500000 && output <= 25000000)
1063 fll_div->div = 0x1;
1064 else {
1065 printk(KERN_ERR "wm8350: fll freq %d out of range\n", output);
1066 return -EINVAL;
1067 }
1068
1069 if (input > 48000)
1070 fll_div->ratio = 1;
1071 else
1072 fll_div->ratio = 8;
1073
1074 t1 = output * (1 << (fll_div->div + 1));
1075 t2 = input * fll_div->ratio;
1076
1077 fll_div->n = t1 / t2;
1078 Nmod = t1 % t2;
1079
1080 if (Nmod) {
1081 Kpart = FIXED_FLL_SIZE * (long long)Nmod;
1082 do_div(Kpart, t2);
1083 K = Kpart & 0xFFFFFFFF;
1084
1085 /* Check if we need to round */
1086 if ((K % 10) >= 5)
1087 K += 5;
1088
1089 /* Move down to proper range now rounding is done */
1090 K /= 10;
1091 fll_div->k = K;
1092 } else
1093 fll_div->k = 0;
1094
1095 return 0;
1096}
1097
1098static int wm8350_set_fll(struct snd_soc_dai *codec_dai,
1099 int pll_id, unsigned int freq_in,
1100 unsigned int freq_out)
1101{
1102 struct snd_soc_codec *codec = codec_dai->codec;
1103 struct wm8350 *wm8350 = codec->control_data;
1104 struct _fll_div fll_div;
1105 int ret = 0;
1106 u16 fll_1, fll_4;
1107
1108 /* power down FLL - we need to do this for reconfiguration */
1109 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4,
1110 WM8350_FLL_ENA | WM8350_FLL_OSC_ENA);
1111
1112 if (freq_out == 0 || freq_in == 0)
1113 return ret;
1114
1115 ret = fll_factors(&fll_div, freq_in, freq_out);
1116 if (ret < 0)
1117 return ret;
1118 dev_dbg(wm8350->dev,
1119 "FLL in %d FLL out %d N 0x%x K 0x%x div %d ratio %d",
1120 freq_in, freq_out, fll_div.n, fll_div.k, fll_div.div,
1121 fll_div.ratio);
1122
1123 /* set up N.K & dividers */
1124 fll_1 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_1) &
1125 ~(WM8350_FLL_OUTDIV_MASK | WM8350_FLL_RSP_RATE_MASK | 0xc000);
1126 wm8350_codec_write(codec, WM8350_FLL_CONTROL_1,
1127 fll_1 | (fll_div.div << 8) | 0x50);
1128 wm8350_codec_write(codec, WM8350_FLL_CONTROL_2,
1129 (fll_div.ratio << 11) | (fll_div.
1130 n & WM8350_FLL_N_MASK));
1131 wm8350_codec_write(codec, WM8350_FLL_CONTROL_3, fll_div.k);
1132 fll_4 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_4) &
1133 ~(WM8350_FLL_FRAC | WM8350_FLL_SLOW_LOCK_REF);
1134 wm8350_codec_write(codec, WM8350_FLL_CONTROL_4,
1135 fll_4 | (fll_div.k ? WM8350_FLL_FRAC : 0) |
1136 (fll_div.ratio == 8 ? WM8350_FLL_SLOW_LOCK_REF : 0));
1137
1138 /* power FLL on */
1139 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_OSC_ENA);
1140 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_ENA);
1141
1142 return 0;
1143}
1144
1145static int wm8350_set_bias_level(struct snd_soc_codec *codec,
1146 enum snd_soc_bias_level level)
1147{
1148 struct wm8350 *wm8350 = codec->control_data;
1149 struct wm8350_data *priv = codec->private_data;
1150 struct wm8350_audio_platform_data *platform =
1151 wm8350->codec.platform_data;
1152 u16 pm1;
1153 int ret;
1154
1155 switch (level) {
1156 case SND_SOC_BIAS_ON:
1157 pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) &
1158 ~(WM8350_VMID_MASK | WM8350_CODEC_ISEL_MASK);
1159 wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1,
1160 pm1 | WM8350_VMID_50K |
1161 platform->codec_current_on << 14);
1162 break;
1163
1164 case SND_SOC_BIAS_PREPARE:
1165 pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1);
1166 pm1 &= ~WM8350_VMID_MASK;
1167 wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1,
1168 pm1 | WM8350_VMID_50K);
1169 break;
1170
1171 case SND_SOC_BIAS_STANDBY:
1172 if (codec->bias_level == SND_SOC_BIAS_OFF) {
1173 ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies),
1174 priv->supplies);
1175 if (ret != 0)
1176 return ret;
1177
1178 /* Enable the system clock */
1179 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4,
1180 WM8350_SYSCLK_ENA);
1181
1182 /* mute DAC & outputs */
1183 wm8350_set_bits(wm8350, WM8350_DAC_MUTE,
1184 WM8350_DAC_MUTE_ENA);
1185
1186 /* discharge cap memory */
1187 wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL,
1188 platform->dis_out1 |
1189 (platform->dis_out2 << 2) |
1190 (platform->dis_out3 << 4) |
1191 (platform->dis_out4 << 6));
1192
1193 /* wait for discharge */
1194 schedule_timeout_interruptible(msecs_to_jiffies
1195 (platform->
1196 cap_discharge_msecs));
1197
1198 /* enable antipop */
1199 wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL,
1200 (platform->vmid_s_curve << 8));
1201
1202 /* ramp up vmid */
1203 wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1,
1204 (platform->
1205 codec_current_charge << 14) |
1206 WM8350_VMID_5K | WM8350_VMIDEN |
1207 WM8350_VBUFEN);
1208
1209 /* wait for vmid */
1210 schedule_timeout_interruptible(msecs_to_jiffies
1211 (platform->
1212 vmid_charge_msecs));
1213
1214 /* turn on vmid 300k */
1215 pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) &
1216 ~(WM8350_VMID_MASK | WM8350_CODEC_ISEL_MASK);
1217 pm1 |= WM8350_VMID_300K |
1218 (platform->codec_current_standby << 14);
1219 wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1,
1220 pm1);
1221
1222
1223 /* enable analogue bias */
1224 pm1 |= WM8350_BIASEN;
1225 wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, pm1);
1226
1227 /* disable antipop */
1228 wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL, 0);
1229
1230 } else {
1231 /* turn on vmid 300k and reduce current */
1232 pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) &
1233 ~(WM8350_VMID_MASK | WM8350_CODEC_ISEL_MASK);
1234 wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1,
1235 pm1 | WM8350_VMID_300K |
1236 (platform->
1237 codec_current_standby << 14));
1238
1239 }
1240 break;
1241
1242 case SND_SOC_BIAS_OFF:
1243
1244 /* mute DAC & enable outputs */
1245 wm8350_set_bits(wm8350, WM8350_DAC_MUTE, WM8350_DAC_MUTE_ENA);
1246
1247 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_3,
1248 WM8350_OUT1L_ENA | WM8350_OUT1R_ENA |
1249 WM8350_OUT2L_ENA | WM8350_OUT2R_ENA);
1250
1251 /* enable anti pop S curve */
1252 wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL,
1253 (platform->vmid_s_curve << 8));
1254
1255 /* turn off vmid */
1256 pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) &
1257 ~WM8350_VMIDEN;
1258 wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, pm1);
1259
1260 /* wait */
1261 schedule_timeout_interruptible(msecs_to_jiffies
1262 (platform->
1263 vmid_discharge_msecs));
1264
1265 wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL,
1266 (platform->vmid_s_curve << 8) |
1267 platform->dis_out1 |
1268 (platform->dis_out2 << 2) |
1269 (platform->dis_out3 << 4) |
1270 (platform->dis_out4 << 6));
1271
1272 /* turn off VBuf and drain */
1273 pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) &
1274 ~(WM8350_VBUFEN | WM8350_VMID_MASK);
1275 wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1,
1276 pm1 | WM8350_OUTPUT_DRAIN_EN);
1277
1278 /* wait */
1279 schedule_timeout_interruptible(msecs_to_jiffies
1280 (platform->drain_msecs));
1281
1282 pm1 &= ~WM8350_BIASEN;
1283 wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, pm1);
1284
1285 /* disable anti-pop */
1286 wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL, 0);
1287
1288 wm8350_clear_bits(wm8350, WM8350_LOUT1_VOLUME,
1289 WM8350_OUT1L_ENA);
1290 wm8350_clear_bits(wm8350, WM8350_ROUT1_VOLUME,
1291 WM8350_OUT1R_ENA);
1292 wm8350_clear_bits(wm8350, WM8350_LOUT2_VOLUME,
1293 WM8350_OUT2L_ENA);
1294 wm8350_clear_bits(wm8350, WM8350_ROUT2_VOLUME,
1295 WM8350_OUT2R_ENA);
1296
1297 /* disable clock gen */
1298 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4,
1299 WM8350_SYSCLK_ENA);
1300
1301 regulator_bulk_disable(ARRAY_SIZE(priv->supplies),
1302 priv->supplies);
1303 break;
1304 }
1305 codec->bias_level = level;
1306 return 0;
1307}
1308
1309static int wm8350_suspend(struct platform_device *pdev, pm_message_t state)
1310{
1311 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1312 struct snd_soc_codec *codec = socdev->codec;
1313
1314 wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF);
1315 return 0;
1316}
1317
1318static int wm8350_resume(struct platform_device *pdev)
1319{
1320 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1321 struct snd_soc_codec *codec = socdev->codec;
1322
1323 wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1324
1325 if (codec->suspend_bias_level == SND_SOC_BIAS_ON)
1326 wm8350_set_bias_level(codec, SND_SOC_BIAS_ON);
1327
1328 return 0;
1329}
1330
1331static struct snd_soc_codec *wm8350_codec;
1332
1333static int wm8350_probe(struct platform_device *pdev)
1334{
1335 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1336 struct snd_soc_codec *codec;
1337 struct wm8350 *wm8350;
1338 struct wm8350_data *priv;
1339 int ret;
1340 struct wm8350_output *out1;
1341 struct wm8350_output *out2;
1342
1343 BUG_ON(!wm8350_codec);
1344
1345 socdev->codec = wm8350_codec;
1346 codec = socdev->codec;
1347 wm8350 = codec->control_data;
1348 priv = codec->private_data;
1349
1350 /* Enable the codec */
1351 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
1352
1353 /* Enable robust clocking mode in ADC */
1354 wm8350_codec_write(codec, WM8350_SECURITY, 0xa7);
1355 wm8350_codec_write(codec, 0xde, 0x13);
1356 wm8350_codec_write(codec, WM8350_SECURITY, 0);
1357
1358 /* read OUT1 & OUT2 volumes */
1359 out1 = &priv->out1;
1360 out2 = &priv->out2;
1361 out1->left_vol = (wm8350_reg_read(wm8350, WM8350_LOUT1_VOLUME) &
1362 WM8350_OUT1L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT;
1363 out1->right_vol = (wm8350_reg_read(wm8350, WM8350_ROUT1_VOLUME) &
1364 WM8350_OUT1R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT;
1365 out2->left_vol = (wm8350_reg_read(wm8350, WM8350_LOUT2_VOLUME) &
1366 WM8350_OUT2L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT;
1367 out2->right_vol = (wm8350_reg_read(wm8350, WM8350_ROUT2_VOLUME) &
1368 WM8350_OUT2R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT;
1369 wm8350_reg_write(wm8350, WM8350_LOUT1_VOLUME, 0);
1370 wm8350_reg_write(wm8350, WM8350_ROUT1_VOLUME, 0);
1371 wm8350_reg_write(wm8350, WM8350_LOUT2_VOLUME, 0);
1372 wm8350_reg_write(wm8350, WM8350_ROUT2_VOLUME, 0);
1373
1374 /* Latch VU bits & mute */
1375 wm8350_set_bits(wm8350, WM8350_LOUT1_VOLUME,
1376 WM8350_OUT1_VU | WM8350_OUT1L_MUTE);
1377 wm8350_set_bits(wm8350, WM8350_LOUT2_VOLUME,
1378 WM8350_OUT2_VU | WM8350_OUT2L_MUTE);
1379 wm8350_set_bits(wm8350, WM8350_ROUT1_VOLUME,
1380 WM8350_OUT1_VU | WM8350_OUT1R_MUTE);
1381 wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME,
1382 WM8350_OUT2_VU | WM8350_OUT2R_MUTE);
1383
1384 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1385 if (ret < 0) {
1386 dev_err(&pdev->dev, "failed to create pcms\n");
1387 return ret;
1388 }
1389
1390 wm8350_add_controls(codec);
1391 wm8350_add_widgets(codec);
1392
1393 wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1394
1395 ret = snd_soc_init_card(socdev);
1396 if (ret < 0) {
1397 dev_err(&pdev->dev, "failed to register card\n");
1398 goto card_err;
1399 }
1400
1401 return 0;
1402
1403card_err:
1404 snd_soc_free_pcms(socdev);
1405 snd_soc_dapm_free(socdev);
1406 return ret;
1407}
1408
1409static int wm8350_remove(struct platform_device *pdev)
1410{
1411 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1412 struct snd_soc_codec *codec = socdev->codec;
1413 struct wm8350 *wm8350 = codec->control_data;
1414 int ret;
1415
1416 /* cancel any work waiting to be queued. */
1417 ret = cancel_delayed_work(&codec->delayed_work);
1418
1419 /* if there was any work waiting then we run it now and
1420 * wait for its completion */
1421 if (ret) {
1422 schedule_delayed_work(&codec->delayed_work, 0);
1423 flush_scheduled_work();
1424 }
1425
1426 wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF);
1427
1428 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
1429
1430 return 0;
1431}
1432
1433#define WM8350_RATES (SNDRV_PCM_RATE_8000_96000)
1434
1435#define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
1436 SNDRV_PCM_FMTBIT_S20_3LE |\
1437 SNDRV_PCM_FMTBIT_S24_LE)
1438
1439struct snd_soc_dai wm8350_dai = {
1440 .name = "WM8350",
1441 .playback = {
1442 .stream_name = "Playback",
1443 .channels_min = 1,
1444 .channels_max = 2,
1445 .rates = WM8350_RATES,
1446 .formats = WM8350_FORMATS,
1447 },
1448 .capture = {
1449 .stream_name = "Capture",
1450 .channels_min = 1,
1451 .channels_max = 2,
1452 .rates = WM8350_RATES,
1453 .formats = WM8350_FORMATS,
1454 },
1455 .ops = {
1456 .hw_params = wm8350_pcm_hw_params,
1457 .digital_mute = wm8350_mute,
1458 .trigger = wm8350_pcm_trigger,
1459 .set_fmt = wm8350_set_dai_fmt,
1460 .set_sysclk = wm8350_set_dai_sysclk,
1461 .set_pll = wm8350_set_fll,
1462 .set_clkdiv = wm8350_set_clkdiv,
1463 },
1464};
1465EXPORT_SYMBOL_GPL(wm8350_dai);
1466
1467struct snd_soc_codec_device soc_codec_dev_wm8350 = {
1468 .probe = wm8350_probe,
1469 .remove = wm8350_remove,
1470 .suspend = wm8350_suspend,
1471 .resume = wm8350_resume,
1472};
1473EXPORT_SYMBOL_GPL(soc_codec_dev_wm8350);
1474
1475static int wm8350_codec_probe(struct platform_device *pdev)
1476{
1477 struct wm8350 *wm8350 = platform_get_drvdata(pdev);
1478 struct wm8350_data *priv;
1479 struct snd_soc_codec *codec;
1480 int ret, i;
1481
1482 if (wm8350->codec.platform_data == NULL) {
1483 dev_err(&pdev->dev, "No audio platform data supplied\n");
1484 return -EINVAL;
1485 }
1486
1487 priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL);
1488 if (priv == NULL)
1489 return -ENOMEM;
1490
1491 for (i = 0; i < ARRAY_SIZE(supply_names); i++)
1492 priv->supplies[i].supply = supply_names[i];
1493
1494 ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies),
1495 priv->supplies);
1496 if (ret != 0)
1497 goto err_priv;
1498
1499 codec = &priv->codec;
1500 wm8350->codec.codec = codec;
1501
1502 wm8350_dai.dev = &pdev->dev;
1503
1504 mutex_init(&codec->mutex);
1505 INIT_LIST_HEAD(&codec->dapm_widgets);
1506 INIT_LIST_HEAD(&codec->dapm_paths);
1507 codec->dev = &pdev->dev;
1508 codec->name = "WM8350";
1509 codec->owner = THIS_MODULE;
1510 codec->read = wm8350_codec_read;
1511 codec->write = wm8350_codec_write;
1512 codec->bias_level = SND_SOC_BIAS_OFF;
1513 codec->set_bias_level = wm8350_set_bias_level;
1514 codec->dai = &wm8350_dai;
1515 codec->num_dai = 1;
1516 codec->reg_cache_size = WM8350_MAX_REGISTER;
1517 codec->private_data = priv;
1518 codec->control_data = wm8350;
1519
1520 /* Put the codec into reset if it wasn't already */
1521 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
1522
1523 INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work);
1524 ret = snd_soc_register_codec(codec);
1525 if (ret != 0)
1526 goto err_supply;
1527
1528 wm8350_codec = codec;
1529
1530 ret = snd_soc_register_dai(&wm8350_dai);
1531 if (ret != 0)
1532 goto err_codec;
1533 return 0;
1534
1535err_codec:
1536 snd_soc_unregister_codec(codec);
1537err_supply:
1538 regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
1539err_priv:
1540 kfree(priv);
1541 wm8350_codec = NULL;
1542 return ret;
1543}
1544
1545static int __devexit wm8350_codec_remove(struct platform_device *pdev)
1546{
1547 struct wm8350 *wm8350 = platform_get_drvdata(pdev);
1548 struct snd_soc_codec *codec = wm8350->codec.codec;
1549 struct wm8350_data *priv = codec->private_data;
1550
1551 snd_soc_unregister_dai(&wm8350_dai);
1552 snd_soc_unregister_codec(codec);
1553 regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
1554 kfree(priv);
1555 wm8350_codec = NULL;
1556 return 0;
1557}
1558
1559static struct platform_driver wm8350_codec_driver = {
1560 .driver = {
1561 .name = "wm8350-codec",
1562 .owner = THIS_MODULE,
1563 },
1564 .probe = wm8350_codec_probe,
1565 .remove = __devexit_p(wm8350_codec_remove),
1566};
1567
1568static __init int wm8350_init(void)
1569{
1570 return platform_driver_register(&wm8350_codec_driver);
1571}
1572module_init(wm8350_init);
1573
1574static __exit void wm8350_exit(void)
1575{
1576 platform_driver_unregister(&wm8350_codec_driver);
1577}
1578module_exit(wm8350_exit);
1579
1580MODULE_DESCRIPTION("ASoC WM8350 driver");
1581MODULE_AUTHOR("Liam Girdwood");
1582MODULE_LICENSE("GPL");
1583MODULE_ALIAS("platform:wm8350-codec");
diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h
new file mode 100644
index 000000000000..cc2887aa6c38
--- /dev/null
+++ b/sound/soc/codecs/wm8350.h
@@ -0,0 +1,20 @@
1/*
2 * wm8350.h - WM8903 audio codec interface
3 *
4 * Copyright 2008 Wolfson Microelectronics PLC.
5 *
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
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#ifndef _WM8350_H
13#define _WM8350_H
14
15#include <sound/soc.h>
16
17extern struct snd_soc_dai wm8350_dai;
18extern struct snd_soc_codec_device soc_codec_dev_wm8350;
19
20#endif
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index d8ca2da8d634..40f8238df717 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -463,7 +463,8 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai,
463} 463}
464 464
465static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, 465static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
466 struct snd_pcm_hw_params *params) 466 struct snd_pcm_hw_params *params,
467 struct snd_soc_dai *dai)
467{ 468{
468 struct snd_soc_pcm_runtime *rtd = substream->private_data; 469 struct snd_soc_pcm_runtime *rtd = substream->private_data;
469 struct snd_soc_device *socdev = rtd->socdev; 470 struct snd_soc_device *socdev = rtd->socdev;
@@ -585,8 +586,6 @@ struct snd_soc_dai wm8510_dai = {
585 .formats = WM8510_FORMATS,}, 586 .formats = WM8510_FORMATS,},
586 .ops = { 587 .ops = {
587 .hw_params = wm8510_pcm_hw_params, 588 .hw_params = wm8510_pcm_hw_params,
588 },
589 .dai_ops = {
590 .digital_mute = wm8510_mute, 589 .digital_mute = wm8510_mute,
591 .set_fmt = wm8510_set_dai_fmt, 590 .set_fmt = wm8510_set_dai_fmt,
592 .set_clkdiv = wm8510_set_dai_clkdiv, 591 .set_clkdiv = wm8510_set_dai_clkdiv,
@@ -659,7 +658,7 @@ static int wm8510_init(struct snd_soc_device *socdev)
659 wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 658 wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
660 wm8510_add_controls(codec); 659 wm8510_add_controls(codec);
661 wm8510_add_widgets(codec); 660 wm8510_add_widgets(codec);
662 ret = snd_soc_register_card(socdev); 661 ret = snd_soc_init_card(socdev);
663 if (ret < 0) { 662 if (ret < 0) {
664 printk(KERN_ERR "wm8510: failed to register card\n"); 663 printk(KERN_ERR "wm8510: failed to register card\n");
665 goto card_err; 664 goto card_err;
@@ -890,6 +889,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8510 = {
890}; 889};
891EXPORT_SYMBOL_GPL(soc_codec_dev_wm8510); 890EXPORT_SYMBOL_GPL(soc_codec_dev_wm8510);
892 891
892static int __init wm8510_modinit(void)
893{
894 return snd_soc_register_dai(&wm8510_dai);
895}
896module_init(wm8510_modinit);
897
898static void __exit wm8510_exit(void)
899{
900 snd_soc_unregister_dai(&wm8510_dai);
901}
902module_exit(wm8510_exit);
903
893MODULE_DESCRIPTION("ASoC WM8510 driver"); 904MODULE_DESCRIPTION("ASoC WM8510 driver");
894MODULE_AUTHOR("Liam Girdwood"); 905MODULE_AUTHOR("Liam Girdwood");
895MODULE_LICENSE("GPL"); 906MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 627ebfb4209b..d004e5845298 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -548,13 +548,13 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai,
548 * Set PCM DAI bit size and sample rate. 548 * Set PCM DAI bit size and sample rate.
549 */ 549 */
550static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, 550static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
551 struct snd_pcm_hw_params *params) 551 struct snd_pcm_hw_params *params,
552 struct snd_soc_dai *dai)
552{ 553{
553 struct snd_soc_pcm_runtime *rtd = substream->private_data; 554 struct snd_soc_pcm_runtime *rtd = substream->private_data;
554 struct snd_soc_dai_link *dai = rtd->dai;
555 struct snd_soc_device *socdev = rtd->socdev; 555 struct snd_soc_device *socdev = rtd->socdev;
556 struct snd_soc_codec *codec = socdev->codec; 556 struct snd_soc_codec *codec = socdev->codec;
557 u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->codec_dai->id); 557 u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->id);
558 558
559 paifb &= ~WM8580_AIF_LENGTH_MASK; 559 paifb &= ~WM8580_AIF_LENGTH_MASK;
560 /* bit size */ 560 /* bit size */
@@ -574,7 +574,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
574 return -EINVAL; 574 return -EINVAL;
575 } 575 }
576 576
577 wm8580_write(codec, WM8580_PAIF3 + dai->codec_dai->id, paifb); 577 wm8580_write(codec, WM8580_PAIF3 + dai->id, paifb);
578 return 0; 578 return 0;
579} 579}
580 580
@@ -798,8 +798,6 @@ struct snd_soc_dai wm8580_dai[] = {
798 }, 798 },
799 .ops = { 799 .ops = {
800 .hw_params = wm8580_paif_hw_params, 800 .hw_params = wm8580_paif_hw_params,
801 },
802 .dai_ops = {
803 .set_fmt = wm8580_set_paif_dai_fmt, 801 .set_fmt = wm8580_set_paif_dai_fmt,
804 .set_clkdiv = wm8580_set_dai_clkdiv, 802 .set_clkdiv = wm8580_set_dai_clkdiv,
805 .set_pll = wm8580_set_dai_pll, 803 .set_pll = wm8580_set_dai_pll,
@@ -818,8 +816,6 @@ struct snd_soc_dai wm8580_dai[] = {
818 }, 816 },
819 .ops = { 817 .ops = {
820 .hw_params = wm8580_paif_hw_params, 818 .hw_params = wm8580_paif_hw_params,
821 },
822 .dai_ops = {
823 .set_fmt = wm8580_set_paif_dai_fmt, 819 .set_fmt = wm8580_set_paif_dai_fmt,
824 .set_clkdiv = wm8580_set_dai_clkdiv, 820 .set_clkdiv = wm8580_set_dai_clkdiv,
825 .set_pll = wm8580_set_dai_pll, 821 .set_pll = wm8580_set_dai_pll,
@@ -873,7 +869,7 @@ static int wm8580_init(struct snd_soc_device *socdev)
873 wm8580_add_controls(codec); 869 wm8580_add_controls(codec);
874 wm8580_add_widgets(codec); 870 wm8580_add_widgets(codec);
875 871
876 ret = snd_soc_register_card(socdev); 872 ret = snd_soc_init_card(socdev);
877 if (ret < 0) { 873 if (ret < 0) {
878 printk(KERN_ERR "wm8580: failed to register card\n"); 874 printk(KERN_ERR "wm8580: failed to register card\n");
879 goto card_err; 875 goto card_err;
@@ -900,85 +896,85 @@ static struct snd_soc_device *wm8580_socdev;
900 * low = 0x1a 896 * low = 0x1a
901 * high = 0x1b 897 * high = 0x1b
902 */ 898 */
903static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
904
905/* Magic definition of all other variables and things */
906I2C_CLIENT_INSMOD;
907 899
908static struct i2c_driver wm8580_i2c_driver; 900static int wm8580_i2c_probe(struct i2c_client *i2c,
909static struct i2c_client client_template; 901 const struct i2c_device_id *id)
910
911static int wm8580_codec_probe(struct i2c_adapter *adap, int addr, int kind)
912{ 902{
913 struct snd_soc_device *socdev = wm8580_socdev; 903 struct snd_soc_device *socdev = wm8580_socdev;
914 struct wm8580_setup_data *setup = socdev->codec_data;
915 struct snd_soc_codec *codec = socdev->codec; 904 struct snd_soc_codec *codec = socdev->codec;
916 struct i2c_client *i2c;
917 int ret; 905 int ret;
918 906
919 if (addr != setup->i2c_address)
920 return -ENODEV;
921
922 client_template.adapter = adap;
923 client_template.addr = addr;
924
925 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
926 if (i2c == NULL) {
927 kfree(codec);
928 return -ENOMEM;
929 }
930 i2c_set_clientdata(i2c, codec); 907 i2c_set_clientdata(i2c, codec);
931 codec->control_data = i2c; 908 codec->control_data = i2c;
932 909
933 ret = i2c_attach_client(i2c);
934 if (ret < 0) {
935 dev_err(&i2c->dev, "failed to attach codec at addr %x\n", addr);
936 goto err;
937 }
938
939 ret = wm8580_init(socdev); 910 ret = wm8580_init(socdev);
940 if (ret < 0) { 911 if (ret < 0)
941 dev_err(&i2c->dev, "failed to initialise WM8580\n"); 912 dev_err(&i2c->dev, "failed to initialise WM8580\n");
942 goto err;
943 }
944
945 return ret;
946
947err:
948 kfree(codec);
949 kfree(i2c);
950 return ret; 913 return ret;
951} 914}
952 915
953static int wm8580_i2c_detach(struct i2c_client *client) 916static int wm8580_i2c_remove(struct i2c_client *client)
954{ 917{
955 struct snd_soc_codec *codec = i2c_get_clientdata(client); 918 struct snd_soc_codec *codec = i2c_get_clientdata(client);
956 i2c_detach_client(client);
957 kfree(codec->reg_cache); 919 kfree(codec->reg_cache);
958 kfree(client);
959 return 0; 920 return 0;
960} 921}
961 922
962static int wm8580_i2c_attach(struct i2c_adapter *adap) 923static const struct i2c_device_id wm8580_i2c_id[] = {
963{ 924 { "wm8580", 0 },
964 return i2c_probe(adap, &addr_data, wm8580_codec_probe); 925 { }
965} 926};
927MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id);
966 928
967/* corgi i2c codec control layer */
968static struct i2c_driver wm8580_i2c_driver = { 929static struct i2c_driver wm8580_i2c_driver = {
969 .driver = { 930 .driver = {
970 .name = "WM8580 I2C Codec", 931 .name = "WM8580 I2C Codec",
971 .owner = THIS_MODULE, 932 .owner = THIS_MODULE,
972 }, 933 },
973 .attach_adapter = wm8580_i2c_attach, 934 .probe = wm8580_i2c_probe,
974 .detach_client = wm8580_i2c_detach, 935 .remove = wm8580_i2c_remove,
975 .command = NULL, 936 .id_table = wm8580_i2c_id,
976}; 937};
977 938
978static struct i2c_client client_template = { 939static int wm8580_add_i2c_device(struct platform_device *pdev,
979 .name = "WM8580", 940 const struct wm8580_setup_data *setup)
980 .driver = &wm8580_i2c_driver, 941{
981}; 942 struct i2c_board_info info;
943 struct i2c_adapter *adapter;
944 struct i2c_client *client;
945 int ret;
946
947 ret = i2c_add_driver(&wm8580_i2c_driver);
948 if (ret != 0) {
949 dev_err(&pdev->dev, "can't add i2c driver\n");
950 return ret;
951 }
952
953 memset(&info, 0, sizeof(struct i2c_board_info));
954 info.addr = setup->i2c_address;
955 strlcpy(info.type, "wm8580", I2C_NAME_SIZE);
956
957 adapter = i2c_get_adapter(setup->i2c_bus);
958 if (!adapter) {
959 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
960 setup->i2c_bus);
961 goto err_driver;
962 }
963
964 client = i2c_new_device(adapter, &info);
965 i2c_put_adapter(adapter);
966 if (!client) {
967 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
968 (unsigned int)info.addr);
969 goto err_driver;
970 }
971
972 return 0;
973
974err_driver:
975 i2c_del_driver(&wm8580_i2c_driver);
976 return -ENODEV;
977}
982#endif 978#endif
983 979
984static int wm8580_probe(struct platform_device *pdev) 980static int wm8580_probe(struct platform_device *pdev)
@@ -1011,11 +1007,8 @@ static int wm8580_probe(struct platform_device *pdev)
1011 1007
1012#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1008#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1013 if (setup->i2c_address) { 1009 if (setup->i2c_address) {
1014 normal_i2c[0] = setup->i2c_address;
1015 codec->hw_write = (hw_write_t)i2c_master_send; 1010 codec->hw_write = (hw_write_t)i2c_master_send;
1016 ret = i2c_add_driver(&wm8580_i2c_driver); 1011 ret = wm8580_add_i2c_device(pdev, setup);
1017 if (ret != 0)
1018 printk(KERN_ERR "can't add i2c driver");
1019 } 1012 }
1020#else 1013#else
1021 /* Add other interfaces here */ 1014 /* Add other interfaces here */
@@ -1034,6 +1027,7 @@ static int wm8580_remove(struct platform_device *pdev)
1034 snd_soc_free_pcms(socdev); 1027 snd_soc_free_pcms(socdev);
1035 snd_soc_dapm_free(socdev); 1028 snd_soc_dapm_free(socdev);
1036#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1029#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1030 i2c_unregister_device(codec->control_data);
1037 i2c_del_driver(&wm8580_i2c_driver); 1031 i2c_del_driver(&wm8580_i2c_driver);
1038#endif 1032#endif
1039 kfree(codec->private_data); 1033 kfree(codec->private_data);
@@ -1048,6 +1042,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8580 = {
1048}; 1042};
1049EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); 1043EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580);
1050 1044
1045static int __init wm8580_modinit(void)
1046{
1047 return snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
1048}
1049module_init(wm8580_modinit);
1050
1051static void __exit wm8580_exit(void)
1052{
1053 snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
1054}
1055module_exit(wm8580_exit);
1056
1051MODULE_DESCRIPTION("ASoC WM8580 driver"); 1057MODULE_DESCRIPTION("ASoC WM8580 driver");
1052MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 1058MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1053MODULE_LICENSE("GPL"); 1059MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8580.h b/sound/soc/codecs/wm8580.h
index 589ddaba21d7..09e4422f6f2f 100644
--- a/sound/soc/codecs/wm8580.h
+++ b/sound/soc/codecs/wm8580.h
@@ -29,6 +29,7 @@
29#define WM8580_CLKSRC_NONE 5 29#define WM8580_CLKSRC_NONE 5
30 30
31struct wm8580_setup_data { 31struct wm8580_setup_data {
32 int i2c_bus;
32 unsigned short i2c_address; 33 unsigned short i2c_address;
33}; 34};
34 35
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
new file mode 100644
index 000000000000..80b11983e137
--- /dev/null
+++ b/sound/soc/codecs/wm8728.c
@@ -0,0 +1,585 @@
1/*
2 * wm8728.c -- WM8728 ALSA SoC Audio driver
3 *
4 * Copyright 2008 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/i2c.h>
19#include <linux/platform_device.h>
20#include <linux/spi/spi.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/soc-dapm.h>
26#include <sound/initval.h>
27#include <sound/tlv.h>
28
29#include "wm8728.h"
30
31struct snd_soc_codec_device soc_codec_dev_wm8728;
32
33/*
34 * We can't read the WM8728 register space so we cache them instead.
35 * Note that the defaults here aren't the physical defaults, we latch
36 * the volume update bits, mute the output and enable infinite zero
37 * detect.
38 */
39static const u16 wm8728_reg_defaults[] = {
40 0x1ff,
41 0x1ff,
42 0x001,
43 0x100,
44};
45
46static inline unsigned int wm8728_read_reg_cache(struct snd_soc_codec *codec,
47 unsigned int reg)
48{
49 u16 *cache = codec->reg_cache;
50 BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults));
51 return cache[reg];
52}
53
54static inline void wm8728_write_reg_cache(struct snd_soc_codec *codec,
55 u16 reg, unsigned int value)
56{
57 u16 *cache = codec->reg_cache;
58 BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults));
59 cache[reg] = value;
60}
61
62/*
63 * write to the WM8728 register space
64 */
65static int wm8728_write(struct snd_soc_codec *codec, unsigned int reg,
66 unsigned int value)
67{
68 u8 data[2];
69
70 /* data is
71 * D15..D9 WM8728 register offset
72 * D8...D0 register data
73 */
74 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
75 data[1] = value & 0x00ff;
76
77 wm8728_write_reg_cache(codec, reg, value);
78
79 if (codec->hw_write(codec->control_data, data, 2) == 2)
80 return 0;
81 else
82 return -EIO;
83}
84
85static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1);
86
87static const struct snd_kcontrol_new wm8728_snd_controls[] = {
88
89SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8728_DACLVOL, WM8728_DACRVOL,
90 0, 255, 0, wm8728_tlv),
91
92SOC_SINGLE("Deemphasis", WM8728_DACCTL, 1, 1, 0),
93};
94
95static int wm8728_add_controls(struct snd_soc_codec *codec)
96{
97 int err, i;
98
99 for (i = 0; i < ARRAY_SIZE(wm8728_snd_controls); i++) {
100 err = snd_ctl_add(codec->card,
101 snd_soc_cnew(&wm8728_snd_controls[i],
102 codec, NULL));
103 if (err < 0)
104 return err;
105 }
106
107 return 0;
108}
109
110/*
111 * DAPM controls.
112 */
113static const struct snd_soc_dapm_widget wm8728_dapm_widgets[] = {
114SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SND_SOC_NOPM, 0, 0),
115SND_SOC_DAPM_OUTPUT("VOUTL"),
116SND_SOC_DAPM_OUTPUT("VOUTR"),
117};
118
119static const struct snd_soc_dapm_route intercon[] = {
120 {"VOUTL", NULL, "DAC"},
121 {"VOUTR", NULL, "DAC"},
122};
123
124static int wm8728_add_widgets(struct snd_soc_codec *codec)
125{
126 snd_soc_dapm_new_controls(codec, wm8728_dapm_widgets,
127 ARRAY_SIZE(wm8728_dapm_widgets));
128
129 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
130
131 snd_soc_dapm_new_widgets(codec);
132
133 return 0;
134}
135
136static int wm8728_mute(struct snd_soc_dai *dai, int mute)
137{
138 struct snd_soc_codec *codec = dai->codec;
139 u16 mute_reg = wm8728_read_reg_cache(codec, WM8728_DACCTL);
140
141 if (mute)
142 wm8728_write(codec, WM8728_DACCTL, mute_reg | 1);
143 else
144 wm8728_write(codec, WM8728_DACCTL, mute_reg & ~1);
145
146 return 0;
147}
148
149static int wm8728_hw_params(struct snd_pcm_substream *substream,
150 struct snd_pcm_hw_params *params,
151 struct snd_soc_dai *dai)
152{
153 struct snd_soc_pcm_runtime *rtd = substream->private_data;
154 struct snd_soc_device *socdev = rtd->socdev;
155 struct snd_soc_codec *codec = socdev->codec;
156 u16 dac = wm8728_read_reg_cache(codec, WM8728_DACCTL);
157
158 dac &= ~0x18;
159
160 switch (params_format(params)) {
161 case SNDRV_PCM_FORMAT_S16_LE:
162 break;
163 case SNDRV_PCM_FORMAT_S20_3LE:
164 dac |= 0x10;
165 break;
166 case SNDRV_PCM_FORMAT_S24_LE:
167 dac |= 0x08;
168 break;
169 default:
170 return -EINVAL;
171 }
172
173 wm8728_write(codec, WM8728_DACCTL, dac);
174
175 return 0;
176}
177
178static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai,
179 unsigned int fmt)
180{
181 struct snd_soc_codec *codec = codec_dai->codec;
182 u16 iface = wm8728_read_reg_cache(codec, WM8728_IFCTL);
183
184 /* Currently only I2S is supported by the driver, though the
185 * hardware is more flexible.
186 */
187 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
188 case SND_SOC_DAIFMT_I2S:
189 iface |= 1;
190 break;
191 default:
192 return -EINVAL;
193 }
194
195 /* The hardware only support full slave mode */
196 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
197 case SND_SOC_DAIFMT_CBS_CFS:
198 break;
199 default:
200 return -EINVAL;
201 }
202
203 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
204 case SND_SOC_DAIFMT_NB_NF:
205 iface &= ~0x22;
206 break;
207 case SND_SOC_DAIFMT_IB_NF:
208 iface |= 0x20;
209 iface &= ~0x02;
210 break;
211 case SND_SOC_DAIFMT_NB_IF:
212 iface |= 0x02;
213 iface &= ~0x20;
214 break;
215 case SND_SOC_DAIFMT_IB_IF:
216 iface |= 0x22;
217 break;
218 default:
219 return -EINVAL;
220 }
221
222 wm8728_write(codec, WM8728_IFCTL, iface);
223 return 0;
224}
225
226static int wm8728_set_bias_level(struct snd_soc_codec *codec,
227 enum snd_soc_bias_level level)
228{
229 u16 reg;
230 int i;
231
232 switch (level) {
233 case SND_SOC_BIAS_ON:
234 case SND_SOC_BIAS_PREPARE:
235 case SND_SOC_BIAS_STANDBY:
236 if (codec->bias_level == SND_SOC_BIAS_OFF) {
237 /* Power everything up... */
238 reg = wm8728_read_reg_cache(codec, WM8728_DACCTL);
239 wm8728_write(codec, WM8728_DACCTL, reg & ~0x4);
240
241 /* ..then sync in the register cache. */
242 for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++)
243 wm8728_write(codec, i,
244 wm8728_read_reg_cache(codec, i));
245 }
246 break;
247
248 case SND_SOC_BIAS_OFF:
249 reg = wm8728_read_reg_cache(codec, WM8728_DACCTL);
250 wm8728_write(codec, WM8728_DACCTL, reg | 0x4);
251 break;
252 }
253 codec->bias_level = level;
254 return 0;
255}
256
257#define WM8728_RATES (SNDRV_PCM_RATE_8000_192000)
258
259#define WM8728_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
260 SNDRV_PCM_FMTBIT_S24_LE)
261
262struct snd_soc_dai wm8728_dai = {
263 .name = "WM8728",
264 .playback = {
265 .stream_name = "Playback",
266 .channels_min = 2,
267 .channels_max = 2,
268 .rates = WM8728_RATES,
269 .formats = WM8728_FORMATS,
270 },
271 .ops = {
272 .hw_params = wm8728_hw_params,
273 .digital_mute = wm8728_mute,
274 .set_fmt = wm8728_set_dai_fmt,
275 }
276};
277EXPORT_SYMBOL_GPL(wm8728_dai);
278
279static int wm8728_suspend(struct platform_device *pdev, pm_message_t state)
280{
281 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
282 struct snd_soc_codec *codec = socdev->codec;
283
284 wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
285
286 return 0;
287}
288
289static int wm8728_resume(struct platform_device *pdev)
290{
291 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
292 struct snd_soc_codec *codec = socdev->codec;
293
294 wm8728_set_bias_level(codec, codec->suspend_bias_level);
295
296 return 0;
297}
298
299/*
300 * initialise the WM8728 driver
301 * register the mixer and dsp interfaces with the kernel
302 */
303static int wm8728_init(struct snd_soc_device *socdev)
304{
305 struct snd_soc_codec *codec = socdev->codec;
306 int ret = 0;
307
308 codec->name = "WM8728";
309 codec->owner = THIS_MODULE;
310 codec->read = wm8728_read_reg_cache;
311 codec->write = wm8728_write;
312 codec->set_bias_level = wm8728_set_bias_level;
313 codec->dai = &wm8728_dai;
314 codec->num_dai = 1;
315 codec->bias_level = SND_SOC_BIAS_OFF;
316 codec->reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults);
317 codec->reg_cache = kmemdup(wm8728_reg_defaults,
318 sizeof(wm8728_reg_defaults),
319 GFP_KERNEL);
320 if (codec->reg_cache == NULL)
321 return -ENOMEM;
322
323 /* register pcms */
324 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
325 if (ret < 0) {
326 printk(KERN_ERR "wm8728: failed to create pcms\n");
327 goto pcm_err;
328 }
329
330 /* power on device */
331 wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
332
333 wm8728_add_controls(codec);
334 wm8728_add_widgets(codec);
335 ret = snd_soc_init_card(socdev);
336 if (ret < 0) {
337 printk(KERN_ERR "wm8728: failed to register card\n");
338 goto card_err;
339 }
340
341 return ret;
342
343card_err:
344 snd_soc_free_pcms(socdev);
345 snd_soc_dapm_free(socdev);
346pcm_err:
347 kfree(codec->reg_cache);
348 return ret;
349}
350
351static struct snd_soc_device *wm8728_socdev;
352
353#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
354
355/*
356 * WM8728 2 wire address is determined by GPIO5
357 * state during powerup.
358 * low = 0x1a
359 * high = 0x1b
360 */
361
362static int wm8728_i2c_probe(struct i2c_client *i2c,
363 const struct i2c_device_id *id)
364{
365 struct snd_soc_device *socdev = wm8728_socdev;
366 struct snd_soc_codec *codec = socdev->codec;
367 int ret;
368
369 i2c_set_clientdata(i2c, codec);
370 codec->control_data = i2c;
371
372 ret = wm8728_init(socdev);
373 if (ret < 0)
374 pr_err("failed to initialise WM8728\n");
375
376 return ret;
377}
378
379static int wm8728_i2c_remove(struct i2c_client *client)
380{
381 struct snd_soc_codec *codec = i2c_get_clientdata(client);
382 kfree(codec->reg_cache);
383 return 0;
384}
385
386static const struct i2c_device_id wm8728_i2c_id[] = {
387 { "wm8728", 0 },
388 { }
389};
390MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id);
391
392static struct i2c_driver wm8728_i2c_driver = {
393 .driver = {
394 .name = "WM8728 I2C Codec",
395 .owner = THIS_MODULE,
396 },
397 .probe = wm8728_i2c_probe,
398 .remove = wm8728_i2c_remove,
399 .id_table = wm8728_i2c_id,
400};
401
402static int wm8728_add_i2c_device(struct platform_device *pdev,
403 const struct wm8728_setup_data *setup)
404{
405 struct i2c_board_info info;
406 struct i2c_adapter *adapter;
407 struct i2c_client *client;
408 int ret;
409
410 ret = i2c_add_driver(&wm8728_i2c_driver);
411 if (ret != 0) {
412 dev_err(&pdev->dev, "can't add i2c driver\n");
413 return ret;
414 }
415
416 memset(&info, 0, sizeof(struct i2c_board_info));
417 info.addr = setup->i2c_address;
418 strlcpy(info.type, "wm8728", I2C_NAME_SIZE);
419
420 adapter = i2c_get_adapter(setup->i2c_bus);
421 if (!adapter) {
422 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
423 setup->i2c_bus);
424 goto err_driver;
425 }
426
427 client = i2c_new_device(adapter, &info);
428 i2c_put_adapter(adapter);
429 if (!client) {
430 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
431 (unsigned int)info.addr);
432 goto err_driver;
433 }
434
435 return 0;
436
437err_driver:
438 i2c_del_driver(&wm8728_i2c_driver);
439 return -ENODEV;
440}
441#endif
442
443#if defined(CONFIG_SPI_MASTER)
444static int __devinit wm8728_spi_probe(struct spi_device *spi)
445{
446 struct snd_soc_device *socdev = wm8728_socdev;
447 struct snd_soc_codec *codec = socdev->codec;
448 int ret;
449
450 codec->control_data = spi;
451
452 ret = wm8728_init(socdev);
453 if (ret < 0)
454 dev_err(&spi->dev, "failed to initialise WM8728\n");
455
456 return ret;
457}
458
459static int __devexit wm8728_spi_remove(struct spi_device *spi)
460{
461 return 0;
462}
463
464static struct spi_driver wm8728_spi_driver = {
465 .driver = {
466 .name = "wm8728",
467 .bus = &spi_bus_type,
468 .owner = THIS_MODULE,
469 },
470 .probe = wm8728_spi_probe,
471 .remove = __devexit_p(wm8728_spi_remove),
472};
473
474static int wm8728_spi_write(struct spi_device *spi, const char *data, int len)
475{
476 struct spi_transfer t;
477 struct spi_message m;
478 u8 msg[2];
479
480 if (len <= 0)
481 return 0;
482
483 msg[0] = data[0];
484 msg[1] = data[1];
485
486 spi_message_init(&m);
487 memset(&t, 0, (sizeof t));
488
489 t.tx_buf = &msg[0];
490 t.len = len;
491
492 spi_message_add_tail(&t, &m);
493 spi_sync(spi, &m);
494
495 return len;
496}
497#endif /* CONFIG_SPI_MASTER */
498
499static int wm8728_probe(struct platform_device *pdev)
500{
501 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
502 struct wm8728_setup_data *setup;
503 struct snd_soc_codec *codec;
504 int ret = 0;
505
506 setup = socdev->codec_data;
507 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
508 if (codec == NULL)
509 return -ENOMEM;
510
511 socdev->codec = codec;
512 mutex_init(&codec->mutex);
513 INIT_LIST_HEAD(&codec->dapm_widgets);
514 INIT_LIST_HEAD(&codec->dapm_paths);
515
516 wm8728_socdev = socdev;
517 ret = -ENODEV;
518
519#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
520 if (setup->i2c_address) {
521 codec->hw_write = (hw_write_t)i2c_master_send;
522 ret = wm8728_add_i2c_device(pdev, setup);
523 }
524#endif
525#if defined(CONFIG_SPI_MASTER)
526 if (setup->spi) {
527 codec->hw_write = (hw_write_t)wm8728_spi_write;
528 ret = spi_register_driver(&wm8728_spi_driver);
529 if (ret != 0)
530 printk(KERN_ERR "can't add spi driver");
531 }
532#endif
533
534 if (ret != 0)
535 kfree(codec);
536
537 return ret;
538}
539
540/* power down chip */
541static int wm8728_remove(struct platform_device *pdev)
542{
543 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
544 struct snd_soc_codec *codec = socdev->codec;
545
546 if (codec->control_data)
547 wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
548
549 snd_soc_free_pcms(socdev);
550 snd_soc_dapm_free(socdev);
551#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
552 i2c_unregister_device(codec->control_data);
553 i2c_del_driver(&wm8728_i2c_driver);
554#endif
555#if defined(CONFIG_SPI_MASTER)
556 spi_unregister_driver(&wm8728_spi_driver);
557#endif
558 kfree(codec);
559
560 return 0;
561}
562
563struct snd_soc_codec_device soc_codec_dev_wm8728 = {
564 .probe = wm8728_probe,
565 .remove = wm8728_remove,
566 .suspend = wm8728_suspend,
567 .resume = wm8728_resume,
568};
569EXPORT_SYMBOL_GPL(soc_codec_dev_wm8728);
570
571static int __init wm8728_modinit(void)
572{
573 return snd_soc_register_dai(&wm8728_dai);
574}
575module_init(wm8728_modinit);
576
577static void __exit wm8728_exit(void)
578{
579 snd_soc_unregister_dai(&wm8728_dai);
580}
581module_exit(wm8728_exit);
582
583MODULE_DESCRIPTION("ASoC WM8728 driver");
584MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
585MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8728.h b/sound/soc/codecs/wm8728.h
new file mode 100644
index 000000000000..d269c132474b
--- /dev/null
+++ b/sound/soc/codecs/wm8728.h
@@ -0,0 +1,30 @@
1/*
2 * wm8728.h -- WM8728 ASoC codec driver
3 *
4 * Copyright 2008 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 _WM8728_H
14#define _WM8728_H
15
16#define WM8728_DACLVOL 0x00
17#define WM8728_DACRVOL 0x01
18#define WM8728_DACCTL 0x02
19#define WM8728_IFCTL 0x03
20
21struct wm8728_setup_data {
22 int spi;
23 int i2c_bus;
24 unsigned short i2c_address;
25};
26
27extern struct snd_soc_dai wm8728_dai;
28extern struct snd_soc_codec_device soc_codec_dev_wm8728;
29
30#endif
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 7f8a7e36b33e..c444b9f2701e 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -264,7 +264,8 @@ static inline int get_coeff(int mclk, int rate)
264} 264}
265 265
266static int wm8731_hw_params(struct snd_pcm_substream *substream, 266static int wm8731_hw_params(struct snd_pcm_substream *substream,
267 struct snd_pcm_hw_params *params) 267 struct snd_pcm_hw_params *params,
268 struct snd_soc_dai *dai)
268{ 269{
269 struct snd_soc_pcm_runtime *rtd = substream->private_data; 270 struct snd_soc_pcm_runtime *rtd = substream->private_data;
270 struct snd_soc_device *socdev = rtd->socdev; 271 struct snd_soc_device *socdev = rtd->socdev;
@@ -293,7 +294,8 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
293 return 0; 294 return 0;
294} 295}
295 296
296static int wm8731_pcm_prepare(struct snd_pcm_substream *substream) 297static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
298 struct snd_soc_dai *dai)
297{ 299{
298 struct snd_soc_pcm_runtime *rtd = substream->private_data; 300 struct snd_soc_pcm_runtime *rtd = substream->private_data;
299 struct snd_soc_device *socdev = rtd->socdev; 301 struct snd_soc_device *socdev = rtd->socdev;
@@ -305,7 +307,8 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream)
305 return 0; 307 return 0;
306} 308}
307 309
308static void wm8731_shutdown(struct snd_pcm_substream *substream) 310static void wm8731_shutdown(struct snd_pcm_substream *substream,
311 struct snd_soc_dai *dai)
309{ 312{
310 struct snd_soc_pcm_runtime *rtd = substream->private_data; 313 struct snd_soc_pcm_runtime *rtd = substream->private_data;
311 struct snd_soc_device *socdev = rtd->socdev; 314 struct snd_soc_device *socdev = rtd->socdev;
@@ -461,8 +464,6 @@ struct snd_soc_dai wm8731_dai = {
461 .prepare = wm8731_pcm_prepare, 464 .prepare = wm8731_pcm_prepare,
462 .hw_params = wm8731_hw_params, 465 .hw_params = wm8731_hw_params,
463 .shutdown = wm8731_shutdown, 466 .shutdown = wm8731_shutdown,
464 },
465 .dai_ops = {
466 .digital_mute = wm8731_mute, 467 .digital_mute = wm8731_mute,
467 .set_sysclk = wm8731_set_dai_sysclk, 468 .set_sysclk = wm8731_set_dai_sysclk,
468 .set_fmt = wm8731_set_dai_fmt, 469 .set_fmt = wm8731_set_dai_fmt,
@@ -544,7 +545,7 @@ static int wm8731_init(struct snd_soc_device *socdev)
544 545
545 wm8731_add_controls(codec); 546 wm8731_add_controls(codec);
546 wm8731_add_widgets(codec); 547 wm8731_add_widgets(codec);
547 ret = snd_soc_register_card(socdev); 548 ret = snd_soc_init_card(socdev);
548 if (ret < 0) { 549 if (ret < 0) {
549 printk(KERN_ERR "wm8731: failed to register card\n"); 550 printk(KERN_ERR "wm8731: failed to register card\n");
550 goto card_err; 551 goto card_err;
@@ -792,6 +793,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8731 = {
792}; 793};
793EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); 794EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
794 795
796static int __init wm8731_modinit(void)
797{
798 return snd_soc_register_dai(&wm8731_dai);
799}
800module_init(wm8731_modinit);
801
802static void __exit wm8731_exit(void)
803{
804 snd_soc_unregister_dai(&wm8731_dai);
805}
806module_exit(wm8731_exit);
807
795MODULE_DESCRIPTION("ASoC WM8731 driver"); 808MODULE_DESCRIPTION("ASoC WM8731 driver");
796MODULE_AUTHOR("Richard Purdie"); 809MODULE_AUTHOR("Richard Purdie");
797MODULE_LICENSE("GPL"); 810MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 9b7296ee5b08..5997fa68e0d5 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -614,7 +614,8 @@ static int wm8750_set_dai_fmt(struct snd_soc_dai *codec_dai,
614} 614}
615 615
616static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, 616static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
617 struct snd_pcm_hw_params *params) 617 struct snd_pcm_hw_params *params,
618 struct snd_soc_dai *dai)
618{ 619{
619 struct snd_soc_pcm_runtime *rtd = substream->private_data; 620 struct snd_soc_pcm_runtime *rtd = substream->private_data;
620 struct snd_soc_device *socdev = rtd->socdev; 621 struct snd_soc_device *socdev = rtd->socdev;
@@ -709,8 +710,6 @@ struct snd_soc_dai wm8750_dai = {
709 .formats = WM8750_FORMATS,}, 710 .formats = WM8750_FORMATS,},
710 .ops = { 711 .ops = {
711 .hw_params = wm8750_pcm_hw_params, 712 .hw_params = wm8750_pcm_hw_params,
712 },
713 .dai_ops = {
714 .digital_mute = wm8750_mute, 713 .digital_mute = wm8750_mute,
715 .set_fmt = wm8750_set_dai_fmt, 714 .set_fmt = wm8750_set_dai_fmt,
716 .set_sysclk = wm8750_set_dai_sysclk, 715 .set_sysclk = wm8750_set_dai_sysclk,
@@ -819,7 +818,7 @@ static int wm8750_init(struct snd_soc_device *socdev)
819 818
820 wm8750_add_controls(codec); 819 wm8750_add_controls(codec);
821 wm8750_add_widgets(codec); 820 wm8750_add_widgets(codec);
822 ret = snd_soc_register_card(socdev); 821 ret = snd_soc_init_card(socdev);
823 if (ret < 0) { 822 if (ret < 0) {
824 printk(KERN_ERR "wm8750: failed to register card\n"); 823 printk(KERN_ERR "wm8750: failed to register card\n");
825 goto card_err; 824 goto card_err;
@@ -1086,6 +1085,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8750 = {
1086}; 1085};
1087EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750); 1086EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750);
1088 1087
1088static int __init wm8750_modinit(void)
1089{
1090 return snd_soc_register_dai(&wm8750_dai);
1091}
1092module_init(wm8750_modinit);
1093
1094static void __exit wm8750_exit(void)
1095{
1096 snd_soc_unregister_dai(&wm8750_dai);
1097}
1098module_exit(wm8750_exit);
1099
1089MODULE_DESCRIPTION("ASoC WM8750 driver"); 1100MODULE_DESCRIPTION("ASoC WM8750 driver");
1090MODULE_AUTHOR("Liam Girdwood"); 1101MODULE_AUTHOR("Liam Girdwood");
1091MODULE_LICENSE("GPL"); 1102MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index d426eaa22185..6c21b50c9375 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -922,7 +922,8 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,
922 * Set PCM DAI bit size and sample rate. 922 * Set PCM DAI bit size and sample rate.
923 */ 923 */
924static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, 924static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
925 struct snd_pcm_hw_params *params) 925 struct snd_pcm_hw_params *params,
926 struct snd_soc_dai *dai)
926{ 927{
927 struct snd_soc_pcm_runtime *rtd = substream->private_data; 928 struct snd_soc_pcm_runtime *rtd = substream->private_data;
928 struct snd_soc_device *socdev = rtd->socdev; 929 struct snd_soc_device *socdev = rtd->socdev;
@@ -1155,7 +1156,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
1155 * Set PCM DAI bit size and sample rate. 1156 * Set PCM DAI bit size and sample rate.
1156 */ 1157 */
1157static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, 1158static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
1158 struct snd_pcm_hw_params *params) 1159 struct snd_pcm_hw_params *params,
1160 struct snd_soc_dai *dai)
1159{ 1161{
1160 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1162 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1161 struct snd_soc_device *socdev = rtd->socdev; 1163 struct snd_soc_device *socdev = rtd->socdev;
@@ -1323,16 +1325,15 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
1323 .channels_min = 1, 1325 .channels_min = 1,
1324 .channels_max = 2, 1326 .channels_max = 2,
1325 .rates = WM8753_RATES, 1327 .rates = WM8753_RATES,
1326 .formats = WM8753_FORMATS,}, 1328 .formats = WM8753_FORMATS},
1327 .capture = { /* dummy for fast DAI switching */ 1329 .capture = { /* dummy for fast DAI switching */
1328 .stream_name = "Capture", 1330 .stream_name = "Capture",
1329 .channels_min = 1, 1331 .channels_min = 1,
1330 .channels_max = 2, 1332 .channels_max = 2,
1331 .rates = WM8753_RATES, 1333 .rates = WM8753_RATES,
1332 .formats = WM8753_FORMATS,}, 1334 .formats = WM8753_FORMATS},
1333 .ops = { 1335 .ops = {
1334 .hw_params = wm8753_i2s_hw_params,}, 1336 .hw_params = wm8753_i2s_hw_params,
1335 .dai_ops = {
1336 .digital_mute = wm8753_mute, 1337 .digital_mute = wm8753_mute,
1337 .set_fmt = wm8753_mode1h_set_dai_fmt, 1338 .set_fmt = wm8753_mode1h_set_dai_fmt,
1338 .set_clkdiv = wm8753_set_dai_clkdiv, 1339 .set_clkdiv = wm8753_set_dai_clkdiv,
@@ -1356,8 +1357,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
1356 .rates = WM8753_RATES, 1357 .rates = WM8753_RATES,
1357 .formats = WM8753_FORMATS,}, 1358 .formats = WM8753_FORMATS,},
1358 .ops = { 1359 .ops = {
1359 .hw_params = wm8753_pcm_hw_params,}, 1360 .hw_params = wm8753_pcm_hw_params,
1360 .dai_ops = {
1361 .digital_mute = wm8753_mute, 1361 .digital_mute = wm8753_mute,
1362 .set_fmt = wm8753_mode1v_set_dai_fmt, 1362 .set_fmt = wm8753_mode1v_set_dai_fmt,
1363 .set_clkdiv = wm8753_set_dai_clkdiv, 1363 .set_clkdiv = wm8753_set_dai_clkdiv,
@@ -1385,8 +1385,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
1385 .rates = WM8753_RATES, 1385 .rates = WM8753_RATES,
1386 .formats = WM8753_FORMATS,}, 1386 .formats = WM8753_FORMATS,},
1387 .ops = { 1387 .ops = {
1388 .hw_params = wm8753_pcm_hw_params,}, 1388 .hw_params = wm8753_pcm_hw_params,
1389 .dai_ops = {
1390 .digital_mute = wm8753_mute, 1389 .digital_mute = wm8753_mute,
1391 .set_fmt = wm8753_mode2_set_dai_fmt, 1390 .set_fmt = wm8753_mode2_set_dai_fmt,
1392 .set_clkdiv = wm8753_set_dai_clkdiv, 1391 .set_clkdiv = wm8753_set_dai_clkdiv,
@@ -1410,8 +1409,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
1410 .rates = WM8753_RATES, 1409 .rates = WM8753_RATES,
1411 .formats = WM8753_FORMATS,}, 1410 .formats = WM8753_FORMATS,},
1412 .ops = { 1411 .ops = {
1413 .hw_params = wm8753_i2s_hw_params,}, 1412 .hw_params = wm8753_i2s_hw_params,
1414 .dai_ops = {
1415 .digital_mute = wm8753_mute, 1413 .digital_mute = wm8753_mute,
1416 .set_fmt = wm8753_mode3_4_set_dai_fmt, 1414 .set_fmt = wm8753_mode3_4_set_dai_fmt,
1417 .set_clkdiv = wm8753_set_dai_clkdiv, 1415 .set_clkdiv = wm8753_set_dai_clkdiv,
@@ -1439,8 +1437,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
1439 .rates = WM8753_RATES, 1437 .rates = WM8753_RATES,
1440 .formats = WM8753_FORMATS,}, 1438 .formats = WM8753_FORMATS,},
1441 .ops = { 1439 .ops = {
1442 .hw_params = wm8753_i2s_hw_params,}, 1440 .hw_params = wm8753_i2s_hw_params,
1443 .dai_ops = {
1444 .digital_mute = wm8753_mute, 1441 .digital_mute = wm8753_mute,
1445 .set_fmt = wm8753_mode3_4_set_dai_fmt, 1442 .set_fmt = wm8753_mode3_4_set_dai_fmt,
1446 .set_clkdiv = wm8753_set_dai_clkdiv, 1443 .set_clkdiv = wm8753_set_dai_clkdiv,
@@ -1608,7 +1605,7 @@ static int wm8753_init(struct snd_soc_device *socdev)
1608 1605
1609 wm8753_add_controls(codec); 1606 wm8753_add_controls(codec);
1610 wm8753_add_widgets(codec); 1607 wm8753_add_widgets(codec);
1611 ret = snd_soc_register_card(socdev); 1608 ret = snd_soc_init_card(socdev);
1612 if (ret < 0) { 1609 if (ret < 0) {
1613 printk(KERN_ERR "wm8753: failed to register card\n"); 1610 printk(KERN_ERR "wm8753: failed to register card\n");
1614 goto card_err; 1611 goto card_err;
@@ -1877,6 +1874,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8753 = {
1877}; 1874};
1878EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753); 1875EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753);
1879 1876
1877static int __init wm8753_modinit(void)
1878{
1879 return snd_soc_register_dais(wm8753_dai, ARRAY_SIZE(wm8753_dai));
1880}
1881module_init(wm8753_modinit);
1882
1883static void __exit wm8753_exit(void)
1884{
1885 snd_soc_unregister_dais(wm8753_dai, ARRAY_SIZE(wm8753_dai));
1886}
1887module_exit(wm8753_exit);
1888
1880MODULE_DESCRIPTION("ASoC WM8753 driver"); 1889MODULE_DESCRIPTION("ASoC WM8753 driver");
1881MODULE_AUTHOR("Liam Girdwood"); 1890MODULE_AUTHOR("Liam Girdwood");
1882MODULE_LICENSE("GPL"); 1891MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 3b326c9b5586..6767de10ded0 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -138,6 +138,10 @@
138struct snd_soc_codec_device soc_codec_dev_wm8900; 138struct snd_soc_codec_device soc_codec_dev_wm8900;
139 139
140struct wm8900_priv { 140struct wm8900_priv {
141 struct snd_soc_codec codec;
142
143 u16 reg_cache[WM8900_MAXREG];
144
141 u32 fll_in; /* FLL input frequency */ 145 u32 fll_in; /* FLL input frequency */
142 u32 fll_out; /* FLL output frequency */ 146 u32 fll_out; /* FLL output frequency */
143}; 147};
@@ -727,7 +731,8 @@ static int wm8900_add_widgets(struct snd_soc_codec *codec)
727} 731}
728 732
729static int wm8900_hw_params(struct snd_pcm_substream *substream, 733static int wm8900_hw_params(struct snd_pcm_substream *substream,
730 struct snd_pcm_hw_params *params) 734 struct snd_pcm_hw_params *params,
735 struct snd_soc_dai *dai)
731{ 736{
732 struct snd_soc_pcm_runtime *rtd = substream->private_data; 737 struct snd_soc_pcm_runtime *rtd = substream->private_data;
733 struct snd_soc_device *socdev = rtd->socdev; 738 struct snd_soc_device *socdev = rtd->socdev;
@@ -1117,8 +1122,6 @@ struct snd_soc_dai wm8900_dai = {
1117 }, 1122 },
1118 .ops = { 1123 .ops = {
1119 .hw_params = wm8900_hw_params, 1124 .hw_params = wm8900_hw_params,
1120 },
1121 .dai_ops = {
1122 .set_clkdiv = wm8900_set_dai_clkdiv, 1125 .set_clkdiv = wm8900_set_dai_clkdiv,
1123 .set_pll = wm8900_set_dai_pll, 1126 .set_pll = wm8900_set_dai_pll,
1124 .set_fmt = wm8900_set_dai_fmt, 1127 .set_fmt = wm8900_set_dai_fmt,
@@ -1283,16 +1286,28 @@ static int wm8900_resume(struct platform_device *pdev)
1283 return 0; 1286 return 0;
1284} 1287}
1285 1288
1286/* 1289static struct snd_soc_codec *wm8900_codec;
1287 * initialise the WM8900 driver 1290
1288 * register the mixer and dsp interfaces with the kernel 1291static int wm8900_i2c_probe(struct i2c_client *i2c,
1289 */ 1292 const struct i2c_device_id *id)
1290static int wm8900_init(struct snd_soc_device *socdev)
1291{ 1293{
1292 struct snd_soc_codec *codec = socdev->codec; 1294 struct wm8900_priv *wm8900;
1293 int ret = 0; 1295 struct snd_soc_codec *codec;
1294 unsigned int reg; 1296 unsigned int reg;
1295 struct i2c_client *i2c_client = socdev->codec->control_data; 1297 int ret;
1298
1299 wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL);
1300 if (wm8900 == NULL)
1301 return -ENOMEM;
1302
1303 codec = &wm8900->codec;
1304 codec->private_data = wm8900;
1305 codec->reg_cache = &wm8900->reg_cache[0];
1306 codec->reg_cache_size = WM8900_MAXREG;
1307
1308 mutex_init(&codec->mutex);
1309 INIT_LIST_HEAD(&codec->dapm_widgets);
1310 INIT_LIST_HEAD(&codec->dapm_paths);
1296 1311
1297 codec->name = "WM8900"; 1312 codec->name = "WM8900";
1298 codec->owner = THIS_MODULE; 1313 codec->owner = THIS_MODULE;
@@ -1300,33 +1315,28 @@ static int wm8900_init(struct snd_soc_device *socdev)
1300 codec->write = wm8900_write; 1315 codec->write = wm8900_write;
1301 codec->dai = &wm8900_dai; 1316 codec->dai = &wm8900_dai;
1302 codec->num_dai = 1; 1317 codec->num_dai = 1;
1303 codec->reg_cache_size = WM8900_MAXREG; 1318 codec->hw_write = (hw_write_t)i2c_master_send;
1304 codec->reg_cache = kmemdup(wm8900_reg_defaults, 1319 codec->control_data = i2c;
1305 sizeof(wm8900_reg_defaults), GFP_KERNEL); 1320 codec->set_bias_level = wm8900_set_bias_level;
1306 1321 codec->dev = &i2c->dev;
1307 if (codec->reg_cache == NULL)
1308 return -ENOMEM;
1309 1322
1310 reg = wm8900_read(codec, WM8900_REG_ID); 1323 reg = wm8900_read(codec, WM8900_REG_ID);
1311 if (reg != 0x8900) { 1324 if (reg != 0x8900) {
1312 dev_err(&i2c_client->dev, "Device is not a WM8900 - ID %x\n", 1325 dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg);
1313 reg); 1326 ret = -ENODEV;
1314 return -ENODEV; 1327 goto err;
1315 }
1316
1317 codec->private_data = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL);
1318 if (codec->private_data == NULL) {
1319 ret = -ENOMEM;
1320 goto priv_err;
1321 } 1328 }
1322 1329
1323 /* Read back from the chip */ 1330 /* Read back from the chip */
1324 reg = wm8900_chip_read(codec, WM8900_REG_POWER1); 1331 reg = wm8900_chip_read(codec, WM8900_REG_POWER1);
1325 reg = (reg >> 12) & 0xf; 1332 reg = (reg >> 12) & 0xf;
1326 dev_info(&i2c_client->dev, "WM8900 revision %d\n", reg); 1333 dev_info(&i2c->dev, "WM8900 revision %d\n", reg);
1327 1334
1328 wm8900_reset(codec); 1335 wm8900_reset(codec);
1329 1336
1337 /* Turn the chip on */
1338 wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1339
1330 /* Latch the volume update bits */ 1340 /* Latch the volume update bits */
1331 wm8900_write(codec, WM8900_REG_LINVOL, 1341 wm8900_write(codec, WM8900_REG_LINVOL,
1332 wm8900_read(codec, WM8900_REG_LINVOL) | 0x100); 1342 wm8900_read(codec, WM8900_REG_LINVOL) | 0x100);
@@ -1352,160 +1362,98 @@ static int wm8900_init(struct snd_soc_device *socdev)
1352 /* Set the DAC and mixer output bias */ 1362 /* Set the DAC and mixer output bias */
1353 wm8900_write(codec, WM8900_REG_OUTBIASCTL, 0x81); 1363 wm8900_write(codec, WM8900_REG_OUTBIASCTL, 0x81);
1354 1364
1355 /* Register pcms */ 1365 wm8900_dai.dev = &i2c->dev;
1356 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1357 if (ret < 0) {
1358 dev_err(&i2c_client->dev, "Failed to register new PCMs\n");
1359 goto pcm_err;
1360 }
1361
1362 /* Turn the chip on */
1363 codec->bias_level = SND_SOC_BIAS_OFF;
1364 wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1365
1366 wm8900_add_controls(codec);
1367 wm8900_add_widgets(codec);
1368
1369 ret = snd_soc_register_card(socdev);
1370 if (ret < 0) {
1371 dev_err(&i2c_client->dev, "Failed to register card\n");
1372 goto card_err;
1373 }
1374 return ret;
1375
1376card_err:
1377 snd_soc_free_pcms(socdev);
1378 snd_soc_dapm_free(socdev);
1379pcm_err:
1380 kfree(codec->reg_cache);
1381priv_err:
1382 kfree(codec->private_data);
1383 return ret;
1384}
1385 1366
1386static struct snd_soc_device *wm8900_socdev; 1367 wm8900_codec = codec;
1387 1368
1388#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1369 ret = snd_soc_register_codec(codec);
1389 1370 if (ret != 0) {
1390static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END }; 1371 dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
1391
1392/* Magic definition of all other variables and things */
1393I2C_CLIENT_INSMOD;
1394
1395static struct i2c_driver wm8900_i2c_driver;
1396static struct i2c_client client_template;
1397
1398/* If the i2c layer weren't so broken, we could pass this kind of data
1399 around */
1400static int wm8900_codec_probe(struct i2c_adapter *adap, int addr, int kind)
1401{
1402 struct snd_soc_device *socdev = wm8900_socdev;
1403 struct wm8900_setup_data *setup = socdev->codec_data;
1404 struct snd_soc_codec *codec = socdev->codec;
1405 struct i2c_client *i2c;
1406 int ret;
1407
1408 if (addr != setup->i2c_address)
1409 return -ENODEV;
1410
1411 dev_err(&adap->dev, "Probe on %x\n", addr);
1412
1413 client_template.adapter = adap;
1414 client_template.addr = addr;
1415
1416 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
1417 if (i2c == NULL) {
1418 kfree(codec);
1419 return -ENOMEM;
1420 }
1421 i2c_set_clientdata(i2c, codec);
1422 codec->control_data = i2c;
1423
1424 ret = i2c_attach_client(i2c);
1425 if (ret < 0) {
1426 dev_err(&adap->dev,
1427 "failed to attach codec at addr %x\n", addr);
1428 goto err; 1372 goto err;
1429 } 1373 }
1430 1374
1431 ret = wm8900_init(socdev); 1375 ret = snd_soc_register_dai(&wm8900_dai);
1432 if (ret < 0) { 1376 if (ret != 0) {
1433 dev_err(&adap->dev, "failed to initialise WM8900\n"); 1377 dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret);
1434 goto err; 1378 goto err_codec;
1435 } 1379 }
1380
1436 return ret; 1381 return ret;
1437 1382
1383err_codec:
1384 snd_soc_unregister_codec(codec);
1438err: 1385err:
1439 kfree(codec); 1386 kfree(wm8900);
1440 kfree(i2c); 1387 wm8900_codec = NULL;
1441 return ret; 1388 return ret;
1442} 1389}
1443 1390
1444static int wm8900_i2c_detach(struct i2c_client *client) 1391static int wm8900_i2c_remove(struct i2c_client *client)
1445{ 1392{
1446 struct snd_soc_codec *codec = i2c_get_clientdata(client); 1393 snd_soc_unregister_dai(&wm8900_dai);
1447 i2c_detach_client(client); 1394 snd_soc_unregister_codec(wm8900_codec);
1448 kfree(codec->reg_cache); 1395
1449 kfree(client); 1396 wm8900_set_bias_level(wm8900_codec, SND_SOC_BIAS_OFF);
1397
1398 wm8900_dai.dev = NULL;
1399 kfree(wm8900_codec->private_data);
1400 wm8900_codec = NULL;
1401
1450 return 0; 1402 return 0;
1451} 1403}
1452 1404
1453static int wm8900_i2c_attach(struct i2c_adapter *adap) 1405static const struct i2c_device_id wm8900_i2c_id[] = {
1454{ 1406 { "wm8900", 0 },
1455 return i2c_probe(adap, &addr_data, wm8900_codec_probe); 1407 { }
1456} 1408};
1409MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id);
1457 1410
1458/* corgi i2c codec control layer */
1459static struct i2c_driver wm8900_i2c_driver = { 1411static struct i2c_driver wm8900_i2c_driver = {
1460 .driver = { 1412 .driver = {
1461 .name = "WM8900 I2C codec", 1413 .name = "WM8900",
1462 .owner = THIS_MODULE, 1414 .owner = THIS_MODULE,
1463 }, 1415 },
1464 .attach_adapter = wm8900_i2c_attach, 1416 .probe = wm8900_i2c_probe,
1465 .detach_client = wm8900_i2c_detach, 1417 .remove = wm8900_i2c_remove,
1466 .command = NULL, 1418 .id_table = wm8900_i2c_id,
1467};
1468
1469static struct i2c_client client_template = {
1470 .name = "WM8900",
1471 .driver = &wm8900_i2c_driver,
1472}; 1419};
1473#endif
1474 1420
1475static int wm8900_probe(struct platform_device *pdev) 1421static int wm8900_probe(struct platform_device *pdev)
1476{ 1422{
1477 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1423 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1478 struct wm8900_setup_data *setup;
1479 struct snd_soc_codec *codec; 1424 struct snd_soc_codec *codec;
1480 int ret = 0; 1425 int ret = 0;
1481 1426
1482 dev_info(&pdev->dev, "WM8900 Audio Codec\n"); 1427 if (!wm8900_codec) {
1483 1428 dev_err(&pdev->dev, "I2C client not yet instantiated\n");
1484 setup = socdev->codec_data; 1429 return -ENODEV;
1485 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 1430 }
1486 if (codec == NULL)
1487 return -ENOMEM;
1488
1489 mutex_init(&codec->mutex);
1490 INIT_LIST_HEAD(&codec->dapm_widgets);
1491 INIT_LIST_HEAD(&codec->dapm_paths);
1492 1431
1432 codec = wm8900_codec;
1493 socdev->codec = codec; 1433 socdev->codec = codec;
1494 1434
1495 codec->set_bias_level = wm8900_set_bias_level; 1435 /* Register pcms */
1436 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1437 if (ret < 0) {
1438 dev_err(&pdev->dev, "Failed to register new PCMs\n");
1439 goto pcm_err;
1440 }
1496 1441
1497 wm8900_socdev = socdev; 1442 wm8900_add_controls(codec);
1498#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1443 wm8900_add_widgets(codec);
1499 if (setup->i2c_address) { 1444
1500 normal_i2c[0] = setup->i2c_address; 1445 ret = snd_soc_init_card(socdev);
1501 codec->hw_write = (hw_write_t)i2c_master_send; 1446 if (ret < 0) {
1502 ret = i2c_add_driver(&wm8900_i2c_driver); 1447 dev_err(&pdev->dev, "Failed to register card\n");
1503 if (ret != 0) 1448 goto card_err;
1504 printk(KERN_ERR "can't add i2c driver");
1505 } 1449 }
1506#else 1450
1507#error Non-I2C interfaces not yet supported 1451 return ret;
1508#endif 1452
1453card_err:
1454 snd_soc_free_pcms(socdev);
1455 snd_soc_dapm_free(socdev);
1456pcm_err:
1509 return ret; 1457 return ret;
1510} 1458}
1511 1459
@@ -1513,17 +1461,9 @@ static int wm8900_probe(struct platform_device *pdev)
1513static int wm8900_remove(struct platform_device *pdev) 1461static int wm8900_remove(struct platform_device *pdev)
1514{ 1462{
1515 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1463 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1516 struct snd_soc_codec *codec = socdev->codec;
1517
1518 if (codec->control_data)
1519 wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF);
1520 1464
1521 snd_soc_free_pcms(socdev); 1465 snd_soc_free_pcms(socdev);
1522 snd_soc_dapm_free(socdev); 1466 snd_soc_dapm_free(socdev);
1523#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1524 i2c_del_driver(&wm8900_i2c_driver);
1525#endif
1526 kfree(codec);
1527 1467
1528 return 0; 1468 return 0;
1529} 1469}
@@ -1536,6 +1476,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8900 = {
1536}; 1476};
1537EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900); 1477EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900);
1538 1478
1479static int __init wm8900_modinit(void)
1480{
1481 return i2c_add_driver(&wm8900_i2c_driver);
1482}
1483module_init(wm8900_modinit);
1484
1485static void __exit wm8900_exit(void)
1486{
1487 i2c_del_driver(&wm8900_i2c_driver);
1488}
1489module_exit(wm8900_exit);
1490
1539MODULE_DESCRIPTION("ASoC WM8900 driver"); 1491MODULE_DESCRIPTION("ASoC WM8900 driver");
1540MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>"); 1492MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>");
1541MODULE_LICENSE("GPL"); 1493MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8900.h b/sound/soc/codecs/wm8900.h
index ba450d99e902..fd15007d10c7 100644
--- a/sound/soc/codecs/wm8900.h
+++ b/sound/soc/codecs/wm8900.h
@@ -52,12 +52,6 @@
52#define WM8900_DAC_CLKDIV_5_5 0x14 52#define WM8900_DAC_CLKDIV_5_5 0x14
53#define WM8900_DAC_CLKDIV_6 0x18 53#define WM8900_DAC_CLKDIV_6 0x18
54 54
55#define WM8900_
56
57struct wm8900_setup_data {
58 unsigned short i2c_address;
59};
60
61extern struct snd_soc_dai wm8900_dai; 55extern struct snd_soc_dai wm8900_dai;
62extern struct snd_soc_codec_device soc_codec_dev_wm8900; 56extern struct snd_soc_codec_device soc_codec_dev_wm8900;
63 57
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index ce40d7877605..bde74546db4a 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -33,19 +33,6 @@
33 33
34#include "wm8903.h" 34#include "wm8903.h"
35 35
36struct wm8903_priv {
37 int sysclk;
38
39 /* Reference counts */
40 int charge_pump_users;
41 int class_w_users;
42 int playback_active;
43 int capture_active;
44
45 struct snd_pcm_substream *master_substream;
46 struct snd_pcm_substream *slave_substream;
47};
48
49/* Register defaults at reset */ 36/* Register defaults at reset */
50static u16 wm8903_reg_defaults[] = { 37static u16 wm8903_reg_defaults[] = {
51 0x8903, /* R0 - SW Reset and ID */ 38 0x8903, /* R0 - SW Reset and ID */
@@ -223,6 +210,23 @@ static u16 wm8903_reg_defaults[] = {
223 0x0000, /* R172 - Analogue Output Bias 0 */ 210 0x0000, /* R172 - Analogue Output Bias 0 */
224}; 211};
225 212
213struct wm8903_priv {
214 struct snd_soc_codec codec;
215 u16 reg_cache[ARRAY_SIZE(wm8903_reg_defaults)];
216
217 int sysclk;
218
219 /* Reference counts */
220 int charge_pump_users;
221 int class_w_users;
222 int playback_active;
223 int capture_active;
224
225 struct snd_pcm_substream *master_substream;
226 struct snd_pcm_substream *slave_substream;
227};
228
229
226static unsigned int wm8903_read_reg_cache(struct snd_soc_codec *codec, 230static unsigned int wm8903_read_reg_cache(struct snd_soc_codec *codec,
227 unsigned int reg) 231 unsigned int reg)
228{ 232{
@@ -360,6 +364,8 @@ static void wm8903_sync_reg_cache(struct snd_soc_codec *codec, u16 *cache)
360static void wm8903_reset(struct snd_soc_codec *codec) 364static void wm8903_reset(struct snd_soc_codec *codec)
361{ 365{
362 wm8903_write(codec, WM8903_SW_RESET_AND_ID, 0); 366 wm8903_write(codec, WM8903_SW_RESET_AND_ID, 0);
367 memcpy(codec->reg_cache, wm8903_reg_defaults,
368 sizeof(wm8903_reg_defaults));
363} 369}
364 370
365#define WM8903_OUTPUT_SHORT 0x8 371#define WM8903_OUTPUT_SHORT 0x8
@@ -392,6 +398,7 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
392 break; 398 break;
393 default: 399 default:
394 BUG(); 400 BUG();
401 return -EINVAL; /* Spurious warning from some compilers */
395 } 402 }
396 403
397 switch (w->shift) { 404 switch (w->shift) {
@@ -403,6 +410,7 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
403 break; 410 break;
404 default: 411 default:
405 BUG(); 412 BUG();
413 return -EINVAL; /* Spurious warning from some compilers */
406 } 414 }
407 415
408 if (event & SND_SOC_DAPM_PRE_PMU) { 416 if (event & SND_SOC_DAPM_PRE_PMU) {
@@ -773,14 +781,14 @@ static const struct snd_kcontrol_new left_output_mixer[] = {
773SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0), 781SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0),
774SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0), 782SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0),
775SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0), 783SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0),
776SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0), 784SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 0, 1, 0),
777}; 785};
778 786
779static const struct snd_kcontrol_new right_output_mixer[] = { 787static const struct snd_kcontrol_new right_output_mixer[] = {
780SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 3, 1, 0), 788SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 3, 1, 0),
781SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 2, 1, 0), 789SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 2, 1, 0),
782SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0), 790SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0),
783SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0), 791SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 0, 1, 0),
784}; 792};
785 793
786static const struct snd_kcontrol_new left_speaker_mixer[] = { 794static const struct snd_kcontrol_new left_speaker_mixer[] = {
@@ -788,7 +796,7 @@ SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 3, 1, 0),
788SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 2, 1, 0), 796SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 2, 1, 0),
789SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 1, 1, 0), 797SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 1, 1, 0),
790SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 798SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0,
791 1, 1, 0), 799 0, 1, 0),
792}; 800};
793 801
794static const struct snd_kcontrol_new right_speaker_mixer[] = { 802static const struct snd_kcontrol_new right_speaker_mixer[] = {
@@ -797,7 +805,7 @@ SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, 2, 1, 0),
797SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, 805SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0,
798 1, 1, 0), 806 1, 1, 0),
799SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, 807SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0,
800 1, 1, 0), 808 0, 1, 0),
801}; 809};
802 810
803static const struct snd_soc_dapm_widget wm8903_dapm_widgets[] = { 811static const struct snd_soc_dapm_widget wm8903_dapm_widgets[] = {
@@ -989,6 +997,9 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec,
989 997
990 case SND_SOC_BIAS_STANDBY: 998 case SND_SOC_BIAS_STANDBY:
991 if (codec->bias_level == SND_SOC_BIAS_OFF) { 999 if (codec->bias_level == SND_SOC_BIAS_OFF) {
1000 wm8903_write(codec, WM8903_CLOCK_RATES_2,
1001 WM8903_CLK_SYS_ENA);
1002
992 wm8903_run_sequence(codec, 0); 1003 wm8903_run_sequence(codec, 0);
993 wm8903_sync_reg_cache(codec, codec->reg_cache); 1004 wm8903_sync_reg_cache(codec, codec->reg_cache);
994 1005
@@ -1019,6 +1030,9 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec,
1019 1030
1020 case SND_SOC_BIAS_OFF: 1031 case SND_SOC_BIAS_OFF:
1021 wm8903_run_sequence(codec, 32); 1032 wm8903_run_sequence(codec, 32);
1033 reg = wm8903_read(codec, WM8903_CLOCK_RATES_2);
1034 reg &= ~WM8903_CLK_SYS_ENA;
1035 wm8903_write(codec, WM8903_CLOCK_RATES_2, reg);
1022 break; 1036 break;
1023 } 1037 }
1024 1038
@@ -1257,7 +1271,8 @@ static struct {
1257 { 0, 0 }, 1271 { 0, 0 },
1258}; 1272};
1259 1273
1260static int wm8903_startup(struct snd_pcm_substream *substream) 1274static int wm8903_startup(struct snd_pcm_substream *substream,
1275 struct snd_soc_dai *dai)
1261{ 1276{
1262 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1277 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1263 struct snd_soc_device *socdev = rtd->socdev; 1278 struct snd_soc_device *socdev = rtd->socdev;
@@ -1298,7 +1313,8 @@ static int wm8903_startup(struct snd_pcm_substream *substream)
1298 return 0; 1313 return 0;
1299} 1314}
1300 1315
1301static void wm8903_shutdown(struct snd_pcm_substream *substream) 1316static void wm8903_shutdown(struct snd_pcm_substream *substream,
1317 struct snd_soc_dai *dai)
1302{ 1318{
1303 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1319 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1304 struct snd_soc_device *socdev = rtd->socdev; 1320 struct snd_soc_device *socdev = rtd->socdev;
@@ -1317,7 +1333,8 @@ static void wm8903_shutdown(struct snd_pcm_substream *substream)
1317} 1333}
1318 1334
1319static int wm8903_hw_params(struct snd_pcm_substream *substream, 1335static int wm8903_hw_params(struct snd_pcm_substream *substream,
1320 struct snd_pcm_hw_params *params) 1336 struct snd_pcm_hw_params *params,
1337 struct snd_soc_dai *dai)
1321{ 1338{
1322 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1339 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1323 struct snd_soc_device *socdev = rtd->socdev; 1340 struct snd_soc_device *socdev = rtd->socdev;
@@ -1515,8 +1532,6 @@ struct snd_soc_dai wm8903_dai = {
1515 .startup = wm8903_startup, 1532 .startup = wm8903_startup,
1516 .shutdown = wm8903_shutdown, 1533 .shutdown = wm8903_shutdown,
1517 .hw_params = wm8903_hw_params, 1534 .hw_params = wm8903_hw_params,
1518 },
1519 .dai_ops = {
1520 .digital_mute = wm8903_digital_mute, 1535 .digital_mute = wm8903_digital_mute,
1521 .set_fmt = wm8903_set_dai_fmt, 1536 .set_fmt = wm8903_set_dai_fmt,
1522 .set_sysclk = wm8903_set_dai_sysclk 1537 .set_sysclk = wm8903_set_dai_sysclk
@@ -1560,39 +1575,48 @@ static int wm8903_resume(struct platform_device *pdev)
1560 return 0; 1575 return 0;
1561} 1576}
1562 1577
1563/* 1578static struct snd_soc_codec *wm8903_codec;
1564 * initialise the WM8903 driver 1579
1565 * register the mixer and dsp interfaces with the kernel 1580static int wm8903_i2c_probe(struct i2c_client *i2c,
1566 */ 1581 const struct i2c_device_id *id)
1567static int wm8903_init(struct snd_soc_device *socdev)
1568{ 1582{
1569 struct snd_soc_codec *codec = socdev->codec; 1583 struct wm8903_priv *wm8903;
1570 struct i2c_client *i2c = codec->control_data; 1584 struct snd_soc_codec *codec;
1571 int ret = 0; 1585 int ret;
1572 u16 val; 1586 u16 val;
1573 1587
1574 val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID); 1588 wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL);
1575 if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) { 1589 if (wm8903 == NULL)
1576 dev_err(&i2c->dev, 1590 return -ENOMEM;
1577 "Device with ID register %x is not a WM8903\n", val); 1591
1578 return -ENODEV; 1592 codec = &wm8903->codec;
1579 }
1580 1593
1594 mutex_init(&codec->mutex);
1595 INIT_LIST_HEAD(&codec->dapm_widgets);
1596 INIT_LIST_HEAD(&codec->dapm_paths);
1597
1598 codec->dev = &i2c->dev;
1581 codec->name = "WM8903"; 1599 codec->name = "WM8903";
1582 codec->owner = THIS_MODULE; 1600 codec->owner = THIS_MODULE;
1583 codec->read = wm8903_read; 1601 codec->read = wm8903_read;
1584 codec->write = wm8903_write; 1602 codec->write = wm8903_write;
1603 codec->hw_write = (hw_write_t)i2c_master_send;
1585 codec->bias_level = SND_SOC_BIAS_OFF; 1604 codec->bias_level = SND_SOC_BIAS_OFF;
1586 codec->set_bias_level = wm8903_set_bias_level; 1605 codec->set_bias_level = wm8903_set_bias_level;
1587 codec->dai = &wm8903_dai; 1606 codec->dai = &wm8903_dai;
1588 codec->num_dai = 1; 1607 codec->num_dai = 1;
1589 codec->reg_cache_size = ARRAY_SIZE(wm8903_reg_defaults); 1608 codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache);
1590 codec->reg_cache = kmemdup(wm8903_reg_defaults, 1609 codec->reg_cache = &wm8903->reg_cache[0];
1591 sizeof(wm8903_reg_defaults), 1610 codec->private_data = wm8903;
1592 GFP_KERNEL); 1611
1593 if (codec->reg_cache == NULL) { 1612 i2c_set_clientdata(i2c, codec);
1594 dev_err(&i2c->dev, "Failed to allocate register cache\n"); 1613 codec->control_data = i2c;
1595 return -ENOMEM; 1614
1615 val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID);
1616 if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) {
1617 dev_err(&i2c->dev,
1618 "Device with ID register %x is not a WM8903\n", val);
1619 return -ENODEV;
1596 } 1620 }
1597 1621
1598 val = wm8903_read(codec, WM8903_REVISION_NUMBER); 1622 val = wm8903_read(codec, WM8903_REVISION_NUMBER);
@@ -1601,16 +1625,6 @@ static int wm8903_init(struct snd_soc_device *socdev)
1601 1625
1602 wm8903_reset(codec); 1626 wm8903_reset(codec);
1603 1627
1604 /* register pcms */
1605 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1606 if (ret < 0) {
1607 dev_err(&i2c->dev, "failed to create pcms\n");
1608 goto pcm_err;
1609 }
1610
1611 /* SYSCLK is required for pretty much anything */
1612 wm8903_write(codec, WM8903_CLOCK_RATES_2, WM8903_CLK_SYS_ENA);
1613
1614 /* power on device */ 1628 /* power on device */
1615 wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1629 wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1616 1630
@@ -1645,47 +1659,45 @@ static int wm8903_init(struct snd_soc_device *socdev)
1645 val |= WM8903_DAC_MUTEMODE; 1659 val |= WM8903_DAC_MUTEMODE;
1646 wm8903_write(codec, WM8903_DAC_DIGITAL_1, val); 1660 wm8903_write(codec, WM8903_DAC_DIGITAL_1, val);
1647 1661
1648 wm8903_add_controls(codec); 1662 wm8903_dai.dev = &i2c->dev;
1649 wm8903_add_widgets(codec); 1663 wm8903_codec = codec;
1650 ret = snd_soc_register_card(socdev); 1664
1651 if (ret < 0) { 1665 ret = snd_soc_register_codec(codec);
1652 dev_err(&i2c->dev, "wm8903: failed to register card\n"); 1666 if (ret != 0) {
1653 goto card_err; 1667 dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
1668 goto err;
1669 }
1670
1671 ret = snd_soc_register_dai(&wm8903_dai);
1672 if (ret != 0) {
1673 dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret);
1674 goto err_codec;
1654 } 1675 }
1655 1676
1656 return ret; 1677 return ret;
1657 1678
1658card_err: 1679err_codec:
1659 snd_soc_free_pcms(socdev); 1680 snd_soc_unregister_codec(codec);
1660 snd_soc_dapm_free(socdev); 1681err:
1661pcm_err: 1682 wm8903_codec = NULL;
1662 kfree(codec->reg_cache); 1683 kfree(wm8903);
1663 return ret; 1684 return ret;
1664} 1685}
1665 1686
1666static struct snd_soc_device *wm8903_socdev; 1687static int wm8903_i2c_remove(struct i2c_client *client)
1667
1668static int wm8903_i2c_probe(struct i2c_client *i2c,
1669 const struct i2c_device_id *id)
1670{ 1688{
1671 struct snd_soc_device *socdev = wm8903_socdev; 1689 struct snd_soc_codec *codec = i2c_get_clientdata(client);
1672 struct snd_soc_codec *codec = socdev->codec;
1673 int ret;
1674 1690
1675 i2c_set_clientdata(i2c, codec); 1691 snd_soc_unregister_dai(&wm8903_dai);
1676 codec->control_data = i2c; 1692 snd_soc_unregister_codec(codec);
1677 1693
1678 ret = wm8903_init(socdev); 1694 wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
1679 if (ret < 0)
1680 dev_err(&i2c->dev, "Device initialisation failed\n");
1681 1695
1682 return ret; 1696 kfree(codec->private_data);
1683} 1697
1698 wm8903_codec = NULL;
1699 wm8903_dai.dev = NULL;
1684 1700
1685static int wm8903_i2c_remove(struct i2c_client *client)
1686{
1687 struct snd_soc_codec *codec = i2c_get_clientdata(client);
1688 kfree(codec->reg_cache);
1689 return 0; 1701 return 0;
1690} 1702}
1691 1703
@@ -1709,75 +1721,37 @@ static struct i2c_driver wm8903_i2c_driver = {
1709static int wm8903_probe(struct platform_device *pdev) 1721static int wm8903_probe(struct platform_device *pdev)
1710{ 1722{
1711 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1723 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1712 struct wm8903_setup_data *setup;
1713 struct snd_soc_codec *codec;
1714 struct wm8903_priv *wm8903;
1715 struct i2c_board_info board_info;
1716 struct i2c_adapter *adapter;
1717 struct i2c_client *i2c_client;
1718 int ret = 0; 1724 int ret = 0;
1719 1725
1720 setup = socdev->codec_data; 1726 if (!wm8903_codec) {
1721 1727 dev_err(&pdev->dev, "I2C device not yet probed\n");
1722 if (!setup->i2c_address) { 1728 goto err;
1723 dev_err(&pdev->dev, "No codec address provided\n");
1724 return -ENODEV;
1725 } 1729 }
1726 1730
1727 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 1731 socdev->codec = wm8903_codec;
1728 if (codec == NULL)
1729 return -ENOMEM;
1730 1732
1731 wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); 1733 /* register pcms */
1732 if (wm8903 == NULL) { 1734 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1733 ret = -ENOMEM; 1735 if (ret < 0) {
1734 goto err_codec; 1736 dev_err(&pdev->dev, "failed to create pcms\n");
1737 goto err;
1735 } 1738 }
1736 1739
1737 codec->private_data = wm8903; 1740 wm8903_add_controls(socdev->codec);
1738 socdev->codec = codec; 1741 wm8903_add_widgets(socdev->codec);
1739 mutex_init(&codec->mutex);
1740 INIT_LIST_HEAD(&codec->dapm_widgets);
1741 INIT_LIST_HEAD(&codec->dapm_paths);
1742
1743 wm8903_socdev = socdev;
1744 1742
1745 codec->hw_write = (hw_write_t)i2c_master_send; 1743 ret = snd_soc_init_card(socdev);
1746 ret = i2c_add_driver(&wm8903_i2c_driver); 1744 if (ret < 0) {
1747 if (ret != 0) { 1745 dev_err(&pdev->dev, "wm8903: failed to register card\n");
1748 dev_err(&pdev->dev, "can't add i2c driver\n"); 1746 goto card_err;
1749 goto err_priv;
1750 } else {
1751 memset(&board_info, 0, sizeof(board_info));
1752 strlcpy(board_info.type, "wm8903", I2C_NAME_SIZE);
1753 board_info.addr = setup->i2c_address;
1754
1755 adapter = i2c_get_adapter(setup->i2c_bus);
1756 if (!adapter) {
1757 dev_err(&pdev->dev, "Can't get I2C bus %d\n",
1758 setup->i2c_bus);
1759 ret = -ENODEV;
1760 goto err_adapter;
1761 }
1762
1763 i2c_client = i2c_new_device(adapter, &board_info);
1764 i2c_put_adapter(adapter);
1765 if (i2c_client == NULL) {
1766 dev_err(&pdev->dev,
1767 "I2C driver registration failed\n");
1768 ret = -ENODEV;
1769 goto err_adapter;
1770 }
1771 } 1747 }
1772 1748
1773 return ret; 1749 return ret;
1774 1750
1775err_adapter: 1751card_err:
1776 i2c_del_driver(&wm8903_i2c_driver); 1752 snd_soc_free_pcms(socdev);
1777err_priv: 1753 snd_soc_dapm_free(socdev);
1778 kfree(codec->private_data); 1754err:
1779err_codec:
1780 kfree(codec);
1781 return ret; 1755 return ret;
1782} 1756}
1783 1757
@@ -1792,10 +1766,6 @@ static int wm8903_remove(struct platform_device *pdev)
1792 1766
1793 snd_soc_free_pcms(socdev); 1767 snd_soc_free_pcms(socdev);
1794 snd_soc_dapm_free(socdev); 1768 snd_soc_dapm_free(socdev);
1795 i2c_unregister_device(socdev->codec->control_data);
1796 i2c_del_driver(&wm8903_i2c_driver);
1797 kfree(codec->private_data);
1798 kfree(codec);
1799 1769
1800 return 0; 1770 return 0;
1801} 1771}
@@ -1808,6 +1778,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8903 = {
1808}; 1778};
1809EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903); 1779EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903);
1810 1780
1781static int __init wm8903_modinit(void)
1782{
1783 return i2c_add_driver(&wm8903_i2c_driver);
1784}
1785module_init(wm8903_modinit);
1786
1787static void __exit wm8903_exit(void)
1788{
1789 i2c_del_driver(&wm8903_i2c_driver);
1790}
1791module_exit(wm8903_exit);
1792
1811MODULE_DESCRIPTION("ASoC WM8903 driver"); 1793MODULE_DESCRIPTION("ASoC WM8903 driver");
1812MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.cm>"); 1794MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.cm>");
1813MODULE_LICENSE("GPL"); 1795MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8903.h b/sound/soc/codecs/wm8903.h
index cec622f2f660..0ea27e2b9963 100644
--- a/sound/soc/codecs/wm8903.h
+++ b/sound/soc/codecs/wm8903.h
@@ -18,11 +18,6 @@
18extern struct snd_soc_dai wm8903_dai; 18extern struct snd_soc_dai wm8903_dai;
19extern struct snd_soc_codec_device soc_codec_dev_wm8903; 19extern struct snd_soc_codec_device soc_codec_dev_wm8903;
20 20
21struct wm8903_setup_data {
22 int i2c_bus;
23 int i2c_address;
24};
25
26#define WM8903_MCLK_DIV_2 1 21#define WM8903_MCLK_DIV_2 1
27#define WM8903_CLK_SYS 2 22#define WM8903_CLK_SYS 2
28#define WM8903_BCLK 3 23#define WM8903_BCLK 3
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index f41a578ddd4f..88ead7f8dd98 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -541,7 +541,8 @@ static int wm8971_set_dai_fmt(struct snd_soc_dai *codec_dai,
541} 541}
542 542
543static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, 543static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
544 struct snd_pcm_hw_params *params) 544 struct snd_pcm_hw_params *params,
545 struct snd_soc_dai *dai)
545{ 546{
546 struct snd_soc_pcm_runtime *rtd = substream->private_data; 547 struct snd_soc_pcm_runtime *rtd = substream->private_data;
547 struct snd_soc_device *socdev = rtd->socdev; 548 struct snd_soc_device *socdev = rtd->socdev;
@@ -634,8 +635,6 @@ struct snd_soc_dai wm8971_dai = {
634 .formats = WM8971_FORMATS,}, 635 .formats = WM8971_FORMATS,},
635 .ops = { 636 .ops = {
636 .hw_params = wm8971_pcm_hw_params, 637 .hw_params = wm8971_pcm_hw_params,
637 },
638 .dai_ops = {
639 .digital_mute = wm8971_mute, 638 .digital_mute = wm8971_mute,
640 .set_fmt = wm8971_set_dai_fmt, 639 .set_fmt = wm8971_set_dai_fmt,
641 .set_sysclk = wm8971_set_dai_sysclk, 640 .set_sysclk = wm8971_set_dai_sysclk,
@@ -748,7 +747,7 @@ static int wm8971_init(struct snd_soc_device *socdev)
748 747
749 wm8971_add_controls(codec); 748 wm8971_add_controls(codec);
750 wm8971_add_widgets(codec); 749 wm8971_add_widgets(codec);
751 ret = snd_soc_register_card(socdev); 750 ret = snd_soc_init_card(socdev);
752 if (ret < 0) { 751 if (ret < 0) {
753 printk(KERN_ERR "wm8971: failed to register card\n"); 752 printk(KERN_ERR "wm8971: failed to register card\n");
754 goto card_err; 753 goto card_err;
@@ -936,6 +935,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8971 = {
936 935
937EXPORT_SYMBOL_GPL(soc_codec_dev_wm8971); 936EXPORT_SYMBOL_GPL(soc_codec_dev_wm8971);
938 937
938static int __init wm8971_modinit(void)
939{
940 return snd_soc_register_dai(&wm8971_dai);
941}
942module_init(wm8971_modinit);
943
944static void __exit wm8971_exit(void)
945{
946 snd_soc_unregister_dai(&wm8971_dai);
947}
948module_exit(wm8971_exit);
949
939MODULE_DESCRIPTION("ASoC WM8971 driver"); 950MODULE_DESCRIPTION("ASoC WM8971 driver");
940MODULE_AUTHOR("Lab126"); 951MODULE_AUTHOR("Lab126");
941MODULE_LICENSE("GPL"); 952MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 572d22b0880b..5b5afc144478 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -106,6 +106,7 @@ static const u16 wm8990_reg[] = {
106 0x0008, /* R60 - PLL1 */ 106 0x0008, /* R60 - PLL1 */
107 0x0031, /* R61 - PLL2 */ 107 0x0031, /* R61 - PLL2 */
108 0x0026, /* R62 - PLL3 */ 108 0x0026, /* R62 - PLL3 */
109 0x0000, /* R63 - Driver internal */
109}; 110};
110 111
111/* 112/*
@@ -126,10 +127,9 @@ static inline void wm8990_write_reg_cache(struct snd_soc_codec *codec,
126 unsigned int reg, unsigned int value) 127 unsigned int reg, unsigned int value)
127{ 128{
128 u16 *cache = codec->reg_cache; 129 u16 *cache = codec->reg_cache;
129 BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1);
130 130
131 /* Reset register is uncached */ 131 /* Reset register and reserved registers are uncached */
132 if (reg == 0) 132 if (reg == 0 || reg > ARRAY_SIZE(wm8990_reg) - 1)
133 return; 133 return;
134 134
135 cache[reg] = value; 135 cache[reg] = value;
@@ -1172,7 +1172,8 @@ static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
1172 * Set PCM DAI bit size and sample rate. 1172 * Set PCM DAI bit size and sample rate.
1173 */ 1173 */
1174static int wm8990_hw_params(struct snd_pcm_substream *substream, 1174static int wm8990_hw_params(struct snd_pcm_substream *substream,
1175 struct snd_pcm_hw_params *params) 1175 struct snd_pcm_hw_params *params,
1176 struct snd_soc_dai *dai)
1176{ 1177{
1177 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1178 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1178 struct snd_soc_device *socdev = rtd->socdev; 1179 struct snd_soc_device *socdev = rtd->socdev;
@@ -1222,8 +1223,14 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
1222 switch (level) { 1223 switch (level) {
1223 case SND_SOC_BIAS_ON: 1224 case SND_SOC_BIAS_ON:
1224 break; 1225 break;
1226
1225 case SND_SOC_BIAS_PREPARE: 1227 case SND_SOC_BIAS_PREPARE:
1228 /* VMID=2*50k */
1229 val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) &
1230 ~WM8990_VMID_MODE_MASK;
1231 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2);
1226 break; 1232 break;
1233
1227 case SND_SOC_BIAS_STANDBY: 1234 case SND_SOC_BIAS_STANDBY:
1228 if (codec->bias_level == SND_SOC_BIAS_OFF) { 1235 if (codec->bias_level == SND_SOC_BIAS_OFF) {
1229 /* Enable all output discharge bits */ 1236 /* Enable all output discharge bits */
@@ -1272,10 +1279,17 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
1272 1279
1273 /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ 1280 /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
1274 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN); 1281 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN);
1275 } else {
1276 /* ON -> standby */
1277 1282
1283 /* Enable workaround for ADC clocking issue. */
1284 wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0x2);
1285 wm8990_write(codec, WM8990_EXT_CTL1, 0xa003);
1286 wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0);
1278 } 1287 }
1288
1289 /* VMID=2*250k */
1290 val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) &
1291 ~WM8990_VMID_MODE_MASK;
1292 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4);
1279 break; 1293 break;
1280 1294
1281 case SND_SOC_BIAS_OFF: 1295 case SND_SOC_BIAS_OFF:
@@ -1349,8 +1363,7 @@ struct snd_soc_dai wm8990_dai = {
1349 .rates = WM8990_RATES, 1363 .rates = WM8990_RATES,
1350 .formats = WM8990_FORMATS,}, 1364 .formats = WM8990_FORMATS,},
1351 .ops = { 1365 .ops = {
1352 .hw_params = wm8990_hw_params,}, 1366 .hw_params = wm8990_hw_params,
1353 .dai_ops = {
1354 .digital_mute = wm8990_mute, 1367 .digital_mute = wm8990_mute,
1355 .set_fmt = wm8990_set_dai_fmt, 1368 .set_fmt = wm8990_set_dai_fmt,
1356 .set_clkdiv = wm8990_set_dai_clkdiv, 1369 .set_clkdiv = wm8990_set_dai_clkdiv,
@@ -1449,7 +1462,7 @@ static int wm8990_init(struct snd_soc_device *socdev)
1449 1462
1450 wm8990_add_controls(codec); 1463 wm8990_add_controls(codec);
1451 wm8990_add_widgets(codec); 1464 wm8990_add_widgets(codec);
1452 ret = snd_soc_register_card(socdev); 1465 ret = snd_soc_init_card(socdev);
1453 if (ret < 0) { 1466 if (ret < 0) {
1454 printk(KERN_ERR "wm8990: failed to register card\n"); 1467 printk(KERN_ERR "wm8990: failed to register card\n");
1455 goto card_err; 1468 goto card_err;
@@ -1630,6 +1643,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8990 = {
1630}; 1643};
1631EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990); 1644EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990);
1632 1645
1646static int __init wm8990_modinit(void)
1647{
1648 return snd_soc_register_dai(&wm8990_dai);
1649}
1650module_init(wm8990_modinit);
1651
1652static void __exit wm8990_exit(void)
1653{
1654 snd_soc_unregister_dai(&wm8990_dai);
1655}
1656module_exit(wm8990_exit);
1657
1633MODULE_DESCRIPTION("ASoC WM8990 driver"); 1658MODULE_DESCRIPTION("ASoC WM8990 driver");
1634MODULE_AUTHOR("Liam Girdwood"); 1659MODULE_AUTHOR("Liam Girdwood");
1635MODULE_LICENSE("GPL"); 1660MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8990.h b/sound/soc/codecs/wm8990.h
index 0e192f3b0788..7114ddc88b4b 100644
--- a/sound/soc/codecs/wm8990.h
+++ b/sound/soc/codecs/wm8990.h
@@ -80,8 +80,8 @@
80#define WM8990_PLL3 0x3E 80#define WM8990_PLL3 0x3E
81#define WM8990_INTDRIVBITS 0x3F 81#define WM8990_INTDRIVBITS 0x3F
82 82
83#define WM8990_REGISTER_COUNT 60 83#define WM8990_EXT_ACCESS_ENA 0x75
84#define WM8990_MAX_REGISTER 0x3F 84#define WM8990_EXT_CTL1 0x7a
85 85
86/* 86/*
87 * Field Definitions. 87 * Field Definitions.
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index ffb471e420e2..af83d629078a 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -487,7 +487,8 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
487 return 0; 487 return 0;
488} 488}
489 489
490static int ac97_prepare(struct snd_pcm_substream *substream) 490static int ac97_prepare(struct snd_pcm_substream *substream,
491 struct snd_soc_dai *dai)
491{ 492{
492 struct snd_pcm_runtime *runtime = substream->runtime; 493 struct snd_pcm_runtime *runtime = substream->runtime;
493 struct snd_soc_pcm_runtime *rtd = substream->private_data; 494 struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -507,7 +508,8 @@ static int ac97_prepare(struct snd_pcm_substream *substream)
507 return ac97_write(codec, reg, runtime->rate); 508 return ac97_write(codec, reg, runtime->rate);
508} 509}
509 510
510static int ac97_aux_prepare(struct snd_pcm_substream *substream) 511static int ac97_aux_prepare(struct snd_pcm_substream *substream,
512 struct snd_soc_dai *dai)
511{ 513{
512 struct snd_pcm_runtime *runtime = substream->runtime; 514 struct snd_pcm_runtime *runtime = substream->runtime;
513 struct snd_soc_pcm_runtime *rtd = substream->private_data; 515 struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -533,7 +535,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream)
533struct snd_soc_dai wm9712_dai[] = { 535struct snd_soc_dai wm9712_dai[] = {
534{ 536{
535 .name = "AC97 HiFi", 537 .name = "AC97 HiFi",
536 .type = SND_SOC_DAI_AC97_BUS, 538 .ac97_control = 1,
537 .playback = { 539 .playback = {
538 .stream_name = "HiFi Playback", 540 .stream_name = "HiFi Playback",
539 .channels_min = 1, 541 .channels_min = 1,
@@ -688,7 +690,7 @@ static int wm9712_soc_probe(struct platform_device *pdev)
688 690
689 ret = wm9712_reset(codec, 0); 691 ret = wm9712_reset(codec, 0);
690 if (ret < 0) { 692 if (ret < 0) {
691 printk(KERN_ERR "AC97 link error\n"); 693 printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n");
692 goto reset_err; 694 goto reset_err;
693 } 695 }
694 696
@@ -698,7 +700,7 @@ static int wm9712_soc_probe(struct platform_device *pdev)
698 wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 700 wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
699 wm9712_add_controls(codec); 701 wm9712_add_controls(codec);
700 wm9712_add_widgets(codec); 702 wm9712_add_widgets(codec);
701 ret = snd_soc_register_card(socdev); 703 ret = snd_soc_init_card(socdev);
702 if (ret < 0) { 704 if (ret < 0) {
703 printk(KERN_ERR "wm9712: failed to register card\n"); 705 printk(KERN_ERR "wm9712: failed to register card\n");
704 goto reset_err; 706 goto reset_err;
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 945b32ed9884..f3ca8aaf0139 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -928,11 +928,10 @@ static int wm9713_set_dai_fmt(struct snd_soc_dai *codec_dai,
928} 928}
929 929
930static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream, 930static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
931 struct snd_pcm_hw_params *params) 931 struct snd_pcm_hw_params *params,
932 struct snd_soc_dai *dai)
932{ 933{
933 struct snd_soc_pcm_runtime *rtd = substream->private_data; 934 struct snd_soc_codec *codec = dai->codec;
934 struct snd_soc_device *socdev = rtd->socdev;
935 struct snd_soc_codec *codec = socdev->codec;
936 u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xfff3; 935 u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xfff3;
937 936
938 switch (params_format(params)) { 937 switch (params_format(params)) {
@@ -954,11 +953,10 @@ static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
954 return 0; 953 return 0;
955} 954}
956 955
957static void wm9713_voiceshutdown(struct snd_pcm_substream *substream) 956static void wm9713_voiceshutdown(struct snd_pcm_substream *substream,
957 struct snd_soc_dai *dai)
958{ 958{
959 struct snd_soc_pcm_runtime *rtd = substream->private_data; 959 struct snd_soc_codec *codec = dai->codec;
960 struct snd_soc_device *socdev = rtd->socdev;
961 struct snd_soc_codec *codec = socdev->codec;
962 u16 status; 960 u16 status;
963 961
964 /* Gracefully shut down the voice interface. */ 962 /* Gracefully shut down the voice interface. */
@@ -969,12 +967,11 @@ static void wm9713_voiceshutdown(struct snd_pcm_substream *substream)
969 ac97_write(codec, AC97_EXTENDED_MID, status); 967 ac97_write(codec, AC97_EXTENDED_MID, status);
970} 968}
971 969
972static int ac97_hifi_prepare(struct snd_pcm_substream *substream) 970static int ac97_hifi_prepare(struct snd_pcm_substream *substream,
971 struct snd_soc_dai *dai)
973{ 972{
973 struct snd_soc_codec *codec = dai->codec;
974 struct snd_pcm_runtime *runtime = substream->runtime; 974 struct snd_pcm_runtime *runtime = substream->runtime;
975 struct snd_soc_pcm_runtime *rtd = substream->private_data;
976 struct snd_soc_device *socdev = rtd->socdev;
977 struct snd_soc_codec *codec = socdev->codec;
978 int reg; 975 int reg;
979 u16 vra; 976 u16 vra;
980 977
@@ -989,12 +986,11 @@ static int ac97_hifi_prepare(struct snd_pcm_substream *substream)
989 return ac97_write(codec, reg, runtime->rate); 986 return ac97_write(codec, reg, runtime->rate);
990} 987}
991 988
992static int ac97_aux_prepare(struct snd_pcm_substream *substream) 989static int ac97_aux_prepare(struct snd_pcm_substream *substream,
990 struct snd_soc_dai *dai)
993{ 991{
992 struct snd_soc_codec *codec = dai->codec;
994 struct snd_pcm_runtime *runtime = substream->runtime; 993 struct snd_pcm_runtime *runtime = substream->runtime;
995 struct snd_soc_pcm_runtime *rtd = substream->private_data;
996 struct snd_soc_device *socdev = rtd->socdev;
997 struct snd_soc_codec *codec = socdev->codec;
998 u16 vra, xsle; 994 u16 vra, xsle;
999 995
1000 vra = ac97_read(codec, AC97_EXTENDED_STATUS); 996 vra = ac97_read(codec, AC97_EXTENDED_STATUS);
@@ -1028,7 +1024,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream)
1028struct snd_soc_dai wm9713_dai[] = { 1024struct snd_soc_dai wm9713_dai[] = {
1029{ 1025{
1030 .name = "AC97 HiFi", 1026 .name = "AC97 HiFi",
1031 .type = SND_SOC_DAI_AC97_BUS, 1027 .ac97_control = 1,
1032 .playback = { 1028 .playback = {
1033 .stream_name = "HiFi Playback", 1029 .stream_name = "HiFi Playback",
1034 .channels_min = 1, 1030 .channels_min = 1,
@@ -1042,8 +1038,7 @@ struct snd_soc_dai wm9713_dai[] = {
1042 .rates = WM9713_RATES, 1038 .rates = WM9713_RATES,
1043 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 1039 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
1044 .ops = { 1040 .ops = {
1045 .prepare = ac97_hifi_prepare,}, 1041 .prepare = ac97_hifi_prepare,
1046 .dai_ops = {
1047 .set_clkdiv = wm9713_set_dai_clkdiv, 1042 .set_clkdiv = wm9713_set_dai_clkdiv,
1048 .set_pll = wm9713_set_dai_pll,}, 1043 .set_pll = wm9713_set_dai_pll,},
1049 }, 1044 },
@@ -1056,8 +1051,7 @@ struct snd_soc_dai wm9713_dai[] = {
1056 .rates = WM9713_RATES, 1051 .rates = WM9713_RATES,
1057 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 1052 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
1058 .ops = { 1053 .ops = {
1059 .prepare = ac97_aux_prepare,}, 1054 .prepare = ac97_aux_prepare,
1060 .dai_ops = {
1061 .set_clkdiv = wm9713_set_dai_clkdiv, 1055 .set_clkdiv = wm9713_set_dai_clkdiv,
1062 .set_pll = wm9713_set_dai_pll,}, 1056 .set_pll = wm9713_set_dai_pll,},
1063 }, 1057 },
@@ -1077,8 +1071,7 @@ struct snd_soc_dai wm9713_dai[] = {
1077 .formats = WM9713_PCM_FORMATS,}, 1071 .formats = WM9713_PCM_FORMATS,},
1078 .ops = { 1072 .ops = {
1079 .hw_params = wm9713_pcm_hw_params, 1073 .hw_params = wm9713_pcm_hw_params,
1080 .shutdown = wm9713_voiceshutdown,}, 1074 .shutdown = wm9713_voiceshutdown,
1081 .dai_ops = {
1082 .set_clkdiv = wm9713_set_dai_clkdiv, 1075 .set_clkdiv = wm9713_set_dai_clkdiv,
1083 .set_pll = wm9713_set_dai_pll, 1076 .set_pll = wm9713_set_dai_pll,
1084 .set_fmt = wm9713_set_dai_fmt, 1077 .set_fmt = wm9713_set_dai_fmt,
@@ -1097,6 +1090,8 @@ int wm9713_reset(struct snd_soc_codec *codec, int try_warm)
1097 } 1090 }
1098 1091
1099 soc_ac97_ops.reset(codec->ac97); 1092 soc_ac97_ops.reset(codec->ac97);
1093 if (soc_ac97_ops.warm_reset)
1094 soc_ac97_ops.warm_reset(codec->ac97);
1100 if (ac97_read(codec, 0) != wm9713_reg[0]) 1095 if (ac97_read(codec, 0) != wm9713_reg[0])
1101 return -EIO; 1096 return -EIO;
1102 return 0; 1097 return 0;
@@ -1240,7 +1235,7 @@ static int wm9713_soc_probe(struct platform_device *pdev)
1240 wm9713_reset(codec, 0); 1235 wm9713_reset(codec, 0);
1241 ret = wm9713_reset(codec, 1); 1236 ret = wm9713_reset(codec, 1);
1242 if (ret < 0) { 1237 if (ret < 0) {
1243 printk(KERN_ERR "AC97 link error\n"); 1238 printk(KERN_ERR "Failed to reset WM9713: AC97 link error\n");
1244 goto reset_err; 1239 goto reset_err;
1245 } 1240 }
1246 1241
@@ -1252,7 +1247,7 @@ static int wm9713_soc_probe(struct platform_device *pdev)
1252 1247
1253 wm9713_add_controls(codec); 1248 wm9713_add_controls(codec);
1254 wm9713_add_widgets(codec); 1249 wm9713_add_widgets(codec);
1255 ret = snd_soc_register_card(socdev); 1250 ret = snd_soc_init_card(socdev);
1256 if (ret < 0) 1251 if (ret < 0)
1257 goto reset_err; 1252 goto reset_err;
1258 return 0; 1253 return 0;
@@ -1288,7 +1283,6 @@ static int wm9713_soc_remove(struct platform_device *pdev)
1288 snd_soc_free_ac97_codec(codec); 1283 snd_soc_free_ac97_codec(codec);
1289 kfree(codec->private_data); 1284 kfree(codec->private_data);
1290 kfree(codec->reg_cache); 1285 kfree(codec->reg_cache);
1291 kfree(codec->dai);
1292 kfree(codec); 1286 kfree(codec);
1293 return 0; 1287 return 0;
1294} 1288}
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index 8f7e33834902..b502741692d6 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -17,3 +17,13 @@ config SND_DAVINCI_SOC_EVM
17 help 17 help
18 Say Y if you want to add support for SoC audio on TI 18 Say Y if you want to add support for SoC audio on TI
19 DaVinci EVM platform. 19 DaVinci EVM platform.
20
21config SND_DAVINCI_SOC_SFFSDR
22 tristate "SoC Audio support for SFFSDR"
23 depends on SND_DAVINCI_SOC && MACH_DAVINCI_SFFSDR
24 select SND_DAVINCI_SOC_I2S
25 select SND_SOC_PCM3008
26 select SFFSDR_FPGA
27 help
28 Say Y if you want to add support for SoC audio on
29 Lyrtech SFFSDR board.
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile
index ca772e5b4637..ca8bae1fc3f6 100644
--- a/sound/soc/davinci/Makefile
+++ b/sound/soc/davinci/Makefile
@@ -7,5 +7,7 @@ obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
7 7
8# DAVINCI Machine Support 8# DAVINCI Machine Support
9snd-soc-evm-objs := davinci-evm.o 9snd-soc-evm-objs := davinci-evm.o
10snd-soc-sffsdr-objs := davinci-sffsdr.o
10 11
11obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o 12obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
13obj-$(CONFIG_SND_DAVINCI_SOC_SFFSDR) += snd-soc-sffsdr.o
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index 9e6062cd6b59..01b948bb55a1 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -28,6 +28,8 @@
28 28
29#define EVM_CODEC_CLOCK 22579200 29#define EVM_CODEC_CLOCK 22579200
30 30
31#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
32 SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
31static int evm_hw_params(struct snd_pcm_substream *substream, 33static int evm_hw_params(struct snd_pcm_substream *substream,
32 struct snd_pcm_hw_params *params) 34 struct snd_pcm_hw_params *params)
33{ 35{
@@ -37,14 +39,12 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
37 int ret = 0; 39 int ret = 0;
38 40
39 /* set codec DAI configuration */ 41 /* set codec DAI configuration */
40 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 42 ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT);
41 SND_SOC_DAIFMT_CBM_CFM);
42 if (ret < 0) 43 if (ret < 0)
43 return ret; 44 return ret;
44 45
45 /* set cpu DAI configuration */ 46 /* set cpu DAI configuration */
46 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM | 47 ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
47 SND_SOC_DAIFMT_IB_NF);
48 if (ret < 0) 48 if (ret < 0)
49 return ret; 49 return ret;
50 50
@@ -128,8 +128,9 @@ static struct snd_soc_dai_link evm_dai = {
128}; 128};
129 129
130/* davinci-evm audio machine driver */ 130/* davinci-evm audio machine driver */
131static struct snd_soc_machine snd_soc_machine_evm = { 131static struct snd_soc_card snd_soc_card_evm = {
132 .name = "DaVinci EVM", 132 .name = "DaVinci EVM",
133 .platform = &davinci_soc_platform,
133 .dai_link = &evm_dai, 134 .dai_link = &evm_dai,
134 .num_links = 1, 135 .num_links = 1,
135}; 136};
@@ -142,8 +143,7 @@ static struct aic3x_setup_data evm_aic3x_setup = {
142 143
143/* evm audio subsystem */ 144/* evm audio subsystem */
144static struct snd_soc_device evm_snd_devdata = { 145static struct snd_soc_device evm_snd_devdata = {
145 .machine = &snd_soc_machine_evm, 146 .card = &snd_soc_card_evm,
146 .platform = &davinci_soc_platform,
147 .codec_dev = &soc_codec_dev_aic3x, 147 .codec_dev = &soc_codec_dev_aic3x,
148 .codec_data = &evm_aic3x_setup, 148 .codec_data = &evm_aic3x_setup,
149}; 149};
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index abb5fedb0b1e..0fee779e3c76 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -59,6 +59,7 @@
59#define DAVINCI_MCBSP_PCR_CLKXP (1 << 1) 59#define DAVINCI_MCBSP_PCR_CLKXP (1 << 1)
60#define DAVINCI_MCBSP_PCR_FSRP (1 << 2) 60#define DAVINCI_MCBSP_PCR_FSRP (1 << 2)
61#define DAVINCI_MCBSP_PCR_FSXP (1 << 3) 61#define DAVINCI_MCBSP_PCR_FSXP (1 << 3)
62#define DAVINCI_MCBSP_PCR_SCLKME (1 << 7)
62#define DAVINCI_MCBSP_PCR_CLKRM (1 << 8) 63#define DAVINCI_MCBSP_PCR_CLKRM (1 << 8)
63#define DAVINCI_MCBSP_PCR_CLKXM (1 << 9) 64#define DAVINCI_MCBSP_PCR_CLKXM (1 << 9)
64#define DAVINCI_MCBSP_PCR_FSRM (1 << 10) 65#define DAVINCI_MCBSP_PCR_FSRM (1 << 10)
@@ -110,16 +111,59 @@ static void davinci_mcbsp_start(struct snd_pcm_substream *substream)
110{ 111{
111 struct snd_soc_pcm_runtime *rtd = substream->private_data; 112 struct snd_soc_pcm_runtime *rtd = substream->private_data;
112 struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; 113 struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
114 struct snd_soc_device *socdev = rtd->socdev;
115 struct snd_soc_platform *platform = socdev->card->platform;
113 u32 w; 116 u32 w;
117 int ret;
114 118
115 /* Start the sample generator and enable transmitter/receiver */ 119 /* Start the sample generator and enable transmitter/receiver */
116 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); 120 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
117 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1); 121 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1);
118 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 122 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
123
124 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
125 /* Stop the DMA to avoid data loss */
126 /* while the transmitter is out of reset to handle XSYNCERR */
127 if (platform->pcm_ops->trigger) {
128 ret = platform->pcm_ops->trigger(substream,
129 SNDRV_PCM_TRIGGER_STOP);
130 if (ret < 0)
131 printk(KERN_DEBUG "Playback DMA stop failed\n");
132 }
133
134 /* Enable the transmitter */
135 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
119 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1); 136 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
120 else 137 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
138
139 /* wait for any unexpected frame sync error to occur */
140 udelay(100);
141
142 /* Disable the transmitter to clear any outstanding XSYNCERR */
143 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
144 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0);
145 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
146
147 /* Restart the DMA */
148 if (platform->pcm_ops->trigger) {
149 ret = platform->pcm_ops->trigger(substream,
150 SNDRV_PCM_TRIGGER_START);
151 if (ret < 0)
152 printk(KERN_DEBUG "Playback DMA start failed\n");
153 }
154 /* Enable the transmitter */
155 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
156 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
157 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
158
159 } else {
160
161 /* Enable the reciever */
162 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
121 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1); 163 MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1);
122 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); 164 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
165 }
166
123 167
124 /* Start frame sync */ 168 /* Start frame sync */
125 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); 169 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
@@ -144,7 +188,8 @@ static void davinci_mcbsp_stop(struct snd_pcm_substream *substream)
144 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); 188 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
145} 189}
146 190
147static int davinci_i2s_startup(struct snd_pcm_substream *substream) 191static int davinci_i2s_startup(struct snd_pcm_substream *substream,
192 struct snd_soc_dai *dai)
148{ 193{
149 struct snd_soc_pcm_runtime *rtd = substream->private_data; 194 struct snd_soc_pcm_runtime *rtd = substream->private_data;
150 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 195 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -155,61 +200,138 @@ static int davinci_i2s_startup(struct snd_pcm_substream *substream)
155 return 0; 200 return 0;
156} 201}
157 202
203#define DEFAULT_BITPERSAMPLE 16
204
158static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, 205static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
159 unsigned int fmt) 206 unsigned int fmt)
160{ 207{
161 struct davinci_mcbsp_dev *dev = cpu_dai->private_data; 208 struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
162 u32 w; 209 unsigned int pcr;
210 unsigned int srgr;
211 unsigned int rcr;
212 unsigned int xcr;
213 srgr = DAVINCI_MCBSP_SRGR_FSGM |
214 DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) |
215 DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1);
163 216
164 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 217 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
165 case SND_SOC_DAIFMT_CBS_CFS: 218 case SND_SOC_DAIFMT_CBS_CFS:
166 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, 219 /* cpu is master */
167 DAVINCI_MCBSP_PCR_FSXM | 220 pcr = DAVINCI_MCBSP_PCR_FSXM |
168 DAVINCI_MCBSP_PCR_FSRM | 221 DAVINCI_MCBSP_PCR_FSRM |
169 DAVINCI_MCBSP_PCR_CLKXM | 222 DAVINCI_MCBSP_PCR_CLKXM |
170 DAVINCI_MCBSP_PCR_CLKRM); 223 DAVINCI_MCBSP_PCR_CLKRM;
171 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, 224 break;
172 DAVINCI_MCBSP_SRGR_FSGM); 225 case SND_SOC_DAIFMT_CBM_CFS:
226 /* McBSP CLKR pin is the input for the Sample Rate Generator.
227 * McBSP FSR and FSX are driven by the Sample Rate Generator. */
228 pcr = DAVINCI_MCBSP_PCR_SCLKME |
229 DAVINCI_MCBSP_PCR_FSXM |
230 DAVINCI_MCBSP_PCR_FSRM;
173 break; 231 break;
174 case SND_SOC_DAIFMT_CBM_CFM: 232 case SND_SOC_DAIFMT_CBM_CFM:
175 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, 0); 233 /* codec is master */
234 pcr = 0;
176 break; 235 break;
177 default: 236 default:
237 printk(KERN_ERR "%s:bad master\n", __func__);
178 return -EINVAL; 238 return -EINVAL;
179 } 239 }
180 240
181 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 241 rcr = DAVINCI_MCBSP_RCR_RFRLEN1(1);
182 case SND_SOC_DAIFMT_IB_NF: 242 xcr = DAVINCI_MCBSP_XCR_XFIG | DAVINCI_MCBSP_XCR_XFRLEN1(1);
183 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_PCR_REG); 243 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
184 MOD_REG_BIT(w, DAVINCI_MCBSP_PCR_CLKXP | 244 case SND_SOC_DAIFMT_DSP_B:
185 DAVINCI_MCBSP_PCR_CLKRP, 1);
186 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, w);
187 break; 245 break;
188 case SND_SOC_DAIFMT_NB_IF: 246 case SND_SOC_DAIFMT_I2S:
189 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_PCR_REG); 247 /* Davinci doesn't support TRUE I2S, but some codecs will have
190 MOD_REG_BIT(w, DAVINCI_MCBSP_PCR_FSXP | 248 * the left and right channels contiguous. This allows
191 DAVINCI_MCBSP_PCR_FSRP, 1); 249 * dsp_a mode to be used with an inverted normal frame clk.
192 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, w); 250 * If your codec is master and does not have contiguous
251 * channels, then you will have sound on only one channel.
252 * Try using a different mode, or codec as slave.
253 *
254 * The TLV320AIC33 is an example of a codec where this works.
255 * It has a variable bit clock frequency allowing it to have
256 * valid data on every bit clock.
257 *
258 * The TLV320AIC23 is an example of a codec where this does not
259 * work. It has a fixed bit clock frequency with progressively
260 * more empty bit clock slots between channels as the sample
261 * rate is lowered.
262 */
263 fmt ^= SND_SOC_DAIFMT_NB_IF;
264 case SND_SOC_DAIFMT_DSP_A:
265 rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1);
266 xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1);
267 break;
268 default:
269 printk(KERN_ERR "%s:bad format\n", __func__);
270 return -EINVAL;
271 }
272
273 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
274 case SND_SOC_DAIFMT_NB_NF:
275 /* CLKRP Receive clock polarity,
276 * 1 - sampled on rising edge of CLKR
277 * valid on rising edge
278 * CLKXP Transmit clock polarity,
279 * 1 - clocked on falling edge of CLKX
280 * valid on rising edge
281 * FSRP Receive frame sync pol, 0 - active high
282 * FSXP Transmit frame sync pol, 0 - active high
283 */
284 pcr |= (DAVINCI_MCBSP_PCR_CLKXP | DAVINCI_MCBSP_PCR_CLKRP);
193 break; 285 break;
194 case SND_SOC_DAIFMT_IB_IF: 286 case SND_SOC_DAIFMT_IB_IF:
195 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_PCR_REG); 287 /* CLKRP Receive clock polarity,
196 MOD_REG_BIT(w, DAVINCI_MCBSP_PCR_CLKXP | 288 * 0 - sampled on falling edge of CLKR
197 DAVINCI_MCBSP_PCR_CLKRP | 289 * valid on falling edge
198 DAVINCI_MCBSP_PCR_FSXP | 290 * CLKXP Transmit clock polarity,
199 DAVINCI_MCBSP_PCR_FSRP, 1); 291 * 0 - clocked on rising edge of CLKX
200 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, w); 292 * valid on falling edge
293 * FSRP Receive frame sync pol, 1 - active low
294 * FSXP Transmit frame sync pol, 1 - active low
295 */
296 pcr |= (DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP);
201 break; 297 break;
202 case SND_SOC_DAIFMT_NB_NF: 298 case SND_SOC_DAIFMT_NB_IF:
299 /* CLKRP Receive clock polarity,
300 * 1 - sampled on rising edge of CLKR
301 * valid on rising edge
302 * CLKXP Transmit clock polarity,
303 * 1 - clocked on falling edge of CLKX
304 * valid on rising edge
305 * FSRP Receive frame sync pol, 1 - active low
306 * FSXP Transmit frame sync pol, 1 - active low
307 */
308 pcr |= (DAVINCI_MCBSP_PCR_CLKXP | DAVINCI_MCBSP_PCR_CLKRP |
309 DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP);
310 break;
311 case SND_SOC_DAIFMT_IB_NF:
312 /* CLKRP Receive clock polarity,
313 * 0 - sampled on falling edge of CLKR
314 * valid on falling edge
315 * CLKXP Transmit clock polarity,
316 * 0 - clocked on rising edge of CLKX
317 * valid on falling edge
318 * FSRP Receive frame sync pol, 0 - active high
319 * FSXP Transmit frame sync pol, 0 - active high
320 */
203 break; 321 break;
204 default: 322 default:
205 return -EINVAL; 323 return -EINVAL;
206 } 324 }
207 325 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
326 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr);
327 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);
328 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
208 return 0; 329 return 0;
209} 330}
210 331
211static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, 332static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
212 struct snd_pcm_hw_params *params) 333 struct snd_pcm_hw_params *params,
334 struct snd_soc_dai *dai)
213{ 335{
214 struct snd_soc_pcm_runtime *rtd = substream->private_data; 336 struct snd_soc_pcm_runtime *rtd = substream->private_data;
215 struct davinci_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data; 337 struct davinci_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data;
@@ -219,25 +341,20 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
219 u32 w; 341 u32 w;
220 342
221 /* general line settings */ 343 /* general line settings */
222 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, 344 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
223 DAVINCI_MCBSP_SPCR_RINTM(3) | 345 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
224 DAVINCI_MCBSP_SPCR_XINTM(3) | 346 w |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
225 DAVINCI_MCBSP_SPCR_FREE); 347 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
226 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, 348 } else {
227 DAVINCI_MCBSP_RCR_RFRLEN1(1) | 349 w |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
228 DAVINCI_MCBSP_RCR_RDATDLY(1)); 350 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
229 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, 351 }
230 DAVINCI_MCBSP_XCR_XFRLEN1(1) |
231 DAVINCI_MCBSP_XCR_XDATDLY(1) |
232 DAVINCI_MCBSP_XCR_XFIG);
233 352
234 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); 353 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
235 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SRGR_REG); 354 w = DAVINCI_MCBSP_SRGR_FSGM;
236 MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1), 1); 355 MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1), 1);
237 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w);
238 356
239 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS); 357 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);
240 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SRGR_REG);
241 MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1), 1); 358 MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1), 1);
242 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w); 359 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w);
243 360
@@ -260,20 +377,24 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
260 return -EINVAL; 377 return -EINVAL;
261 } 378 }
262 379
263 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG); 380 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
264 MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) | 381 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG);
265 DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1); 382 MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
266 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w); 383 DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1);
384 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w);
267 385
268 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG); 386 } else {
269 MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) | 387 w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG);
270 DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1); 388 MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
271 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w); 389 DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1);
390 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w);
272 391
392 }
273 return 0; 393 return 0;
274} 394}
275 395
276static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd) 396static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
397 struct snd_soc_dai *dai)
277{ 398{
278 int ret = 0; 399 int ret = 0;
279 400
@@ -299,8 +420,8 @@ static int davinci_i2s_probe(struct platform_device *pdev,
299 struct snd_soc_dai *dai) 420 struct snd_soc_dai *dai)
300{ 421{
301 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 422 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
302 struct snd_soc_machine *machine = socdev->machine; 423 struct snd_soc_card *card = socdev->card;
303 struct snd_soc_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai; 424 struct snd_soc_dai *cpu_dai = card->dai_link[pdev->id].cpu_dai;
304 struct davinci_mcbsp_dev *dev; 425 struct davinci_mcbsp_dev *dev;
305 struct resource *mem, *ioarea; 426 struct resource *mem, *ioarea;
306 struct evm_snd_platform_data *pdata; 427 struct evm_snd_platform_data *pdata;
@@ -361,8 +482,8 @@ static void davinci_i2s_remove(struct platform_device *pdev,
361 struct snd_soc_dai *dai) 482 struct snd_soc_dai *dai)
362{ 483{
363 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 484 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
364 struct snd_soc_machine *machine = socdev->machine; 485 struct snd_soc_card *card = socdev->card;
365 struct snd_soc_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai; 486 struct snd_soc_dai *cpu_dai = card->dai_link[pdev->id].cpu_dai;
366 struct davinci_mcbsp_dev *dev = cpu_dai->private_data; 487 struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
367 struct resource *mem; 488 struct resource *mem;
368 489
@@ -381,7 +502,6 @@ static void davinci_i2s_remove(struct platform_device *pdev,
381struct snd_soc_dai davinci_i2s_dai = { 502struct snd_soc_dai davinci_i2s_dai = {
382 .name = "davinci-i2s", 503 .name = "davinci-i2s",
383 .id = 0, 504 .id = 0,
384 .type = SND_SOC_DAI_I2S,
385 .probe = davinci_i2s_probe, 505 .probe = davinci_i2s_probe,
386 .remove = davinci_i2s_remove, 506 .remove = davinci_i2s_remove,
387 .playback = { 507 .playback = {
@@ -397,13 +517,24 @@ struct snd_soc_dai davinci_i2s_dai = {
397 .ops = { 517 .ops = {
398 .startup = davinci_i2s_startup, 518 .startup = davinci_i2s_startup,
399 .trigger = davinci_i2s_trigger, 519 .trigger = davinci_i2s_trigger,
400 .hw_params = davinci_i2s_hw_params,}, 520 .hw_params = davinci_i2s_hw_params,
401 .dai_ops = {
402 .set_fmt = davinci_i2s_set_dai_fmt, 521 .set_fmt = davinci_i2s_set_dai_fmt,
403 }, 522 },
404}; 523};
405EXPORT_SYMBOL_GPL(davinci_i2s_dai); 524EXPORT_SYMBOL_GPL(davinci_i2s_dai);
406 525
526static int __init davinci_i2s_init(void)
527{
528 return snd_soc_register_dai(&davinci_i2s_dai);
529}
530module_init(davinci_i2s_init);
531
532static void __exit davinci_i2s_exit(void)
533{
534 snd_soc_unregister_dai(&davinci_i2s_dai);
535}
536module_exit(davinci_i2s_exit);
537
407MODULE_AUTHOR("Vladimir Barinov"); 538MODULE_AUTHOR("Vladimir Barinov");
408MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface"); 539MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface");
409MODULE_LICENSE("GPL"); 540MODULE_LICENSE("GPL");
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index 76feaa657375..74abc9b4f1cc 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -14,6 +14,7 @@
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/dma-mapping.h> 16#include <linux/dma-mapping.h>
17#include <linux/kernel.h>
17 18
18#include <sound/core.h> 19#include <sound/core.h>
19#include <sound/pcm.h> 20#include <sound/pcm.h>
@@ -24,13 +25,6 @@
24 25
25#include "davinci-pcm.h" 26#include "davinci-pcm.h"
26 27
27#define DAVINCI_PCM_DEBUG 0
28#if DAVINCI_PCM_DEBUG
29#define DPRINTK(x...) printk(KERN_DEBUG x)
30#else
31#define DPRINTK(x...)
32#endif
33
34static struct snd_pcm_hardware davinci_pcm_hardware = { 28static struct snd_pcm_hardware davinci_pcm_hardware = {
35 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | 29 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
36 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 30 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
@@ -78,8 +72,8 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
78 dma_offset = prtd->period * period_size; 72 dma_offset = prtd->period * period_size;
79 dma_pos = runtime->dma_addr + dma_offset; 73 dma_pos = runtime->dma_addr + dma_offset;
80 74
81 DPRINTK("audio_set_dma_params_play channel = %d dma_ptr = %x " 75 pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d "
82 "period_size=%x\n", lch, dma_pos, period_size); 76 "dma_ptr = %x period_size=%x\n", lch, dma_pos, period_size);
83 77
84 data_type = prtd->params->data_type; 78 data_type = prtd->params->data_type;
85 count = period_size / data_type; 79 count = period_size / data_type;
@@ -112,7 +106,7 @@ static void davinci_pcm_dma_irq(int lch, u16 ch_status, void *data)
112 struct snd_pcm_substream *substream = data; 106 struct snd_pcm_substream *substream = data;
113 struct davinci_runtime_data *prtd = substream->runtime->private_data; 107 struct davinci_runtime_data *prtd = substream->runtime->private_data;
114 108
115 DPRINTK("lch=%d, status=0x%x\n", lch, ch_status); 109 pr_debug("davinci_pcm: lch=%d, status=0x%x\n", lch, ch_status);
116 110
117 if (unlikely(ch_status != DMA_COMPLETE)) 111 if (unlikely(ch_status != DMA_COMPLETE))
118 return; 112 return;
@@ -316,8 +310,8 @@ static int davinci_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
316 buf->area = dma_alloc_writecombine(pcm->card->dev, size, 310 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
317 &buf->addr, GFP_KERNEL); 311 &buf->addr, GFP_KERNEL);
318 312
319 DPRINTK("preallocate_dma_buffer: area=%p, addr=%p, size=%d\n", 313 pr_debug("davinci_pcm: preallocate_dma_buffer: area=%p, addr=%p, "
320 (void *) buf->area, (void *) buf->addr, size); 314 "size=%d\n", (void *) buf->area, (void *) buf->addr, size);
321 315
322 if (!buf->area) 316 if (!buf->area)
323 return -ENOMEM; 317 return -ENOMEM;
@@ -384,6 +378,18 @@ struct snd_soc_platform davinci_soc_platform = {
384}; 378};
385EXPORT_SYMBOL_GPL(davinci_soc_platform); 379EXPORT_SYMBOL_GPL(davinci_soc_platform);
386 380
381static int __init davinci_soc_platform_init(void)
382{
383 return snd_soc_register_platform(&davinci_soc_platform);
384}
385module_init(davinci_soc_platform_init);
386
387static void __exit davinci_soc_platform_exit(void)
388{
389 snd_soc_unregister_platform(&davinci_soc_platform);
390}
391module_exit(davinci_soc_platform_exit);
392
387MODULE_AUTHOR("Vladimir Barinov"); 393MODULE_AUTHOR("Vladimir Barinov");
388MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); 394MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");
389MODULE_LICENSE("GPL"); 395MODULE_LICENSE("GPL");
diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c
new file mode 100644
index 000000000000..f67579d52765
--- /dev/null
+++ b/sound/soc/davinci/davinci-sffsdr.c
@@ -0,0 +1,157 @@
1/*
2 * ASoC driver for Lyrtech SFFSDR board.
3 *
4 * Author: Hugo Villeneuve
5 * Copyright (C) 2008 Lyrtech inc
6 *
7 * Based on ASoC driver for TI DAVINCI EVM platform, original copyright follow:
8 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
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
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/timer.h>
18#include <linux/interrupt.h>
19#include <linux/platform_device.h>
20#include <linux/gpio.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/soc.h>
24#include <sound/soc-dapm.h>
25
26#include <asm/dma.h>
27#include <asm/plat-sffsdr/sffsdr-fpga.h>
28
29#include <mach/mcbsp.h>
30#include <mach/edma.h>
31
32#include "../codecs/pcm3008.h"
33#include "davinci-pcm.h"
34#include "davinci-i2s.h"
35
36static int sffsdr_hw_params(struct snd_pcm_substream *substream,
37 struct snd_pcm_hw_params *params,
38 struct snd_soc_dai *dai)
39{
40 struct snd_soc_pcm_runtime *rtd = substream->private_data;
41 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
42 int fs;
43 int ret = 0;
44
45 /* Set cpu DAI configuration:
46 * CLKX and CLKR are the inputs for the Sample Rate Generator.
47 * FSX and FSR are outputs, driven by the sample Rate Generator. */
48 ret = snd_soc_dai_set_fmt(cpu_dai,
49 SND_SOC_DAIFMT_RIGHT_J |
50 SND_SOC_DAIFMT_CBM_CFS |
51 SND_SOC_DAIFMT_IB_NF);
52 if (ret < 0)
53 return ret;
54
55 /* Fsref can be 32000, 44100 or 48000. */
56 fs = params_rate(params);
57
58 pr_debug("sffsdr_hw_params: rate = %d Hz\n", fs);
59
60 return sffsdr_fpga_set_codec_fs(fs);
61}
62
63static struct snd_soc_ops sffsdr_ops = {
64 .hw_params = sffsdr_hw_params,
65};
66
67/* davinci-sffsdr digital audio interface glue - connects codec <--> CPU */
68static struct snd_soc_dai_link sffsdr_dai = {
69 .name = "PCM3008", /* Codec name */
70 .stream_name = "PCM3008 HiFi",
71 .cpu_dai = &davinci_i2s_dai,
72 .codec_dai = &pcm3008_dai,
73 .ops = &sffsdr_ops,
74};
75
76/* davinci-sffsdr audio machine driver */
77static struct snd_soc_card snd_soc_sffsdr = {
78 .name = "DaVinci SFFSDR",
79 .platform = &davinci_soc_platform,
80 .dai_link = &sffsdr_dai,
81 .num_links = 1,
82};
83
84/* sffsdr audio private data */
85static struct pcm3008_setup_data sffsdr_pcm3008_setup = {
86 .dem0_pin = GPIO(45),
87 .dem1_pin = GPIO(46),
88 .pdad_pin = GPIO(47),
89 .pdda_pin = GPIO(38),
90};
91
92/* sffsdr audio subsystem */
93static struct snd_soc_device sffsdr_snd_devdata = {
94 .card = &snd_soc_sffsdr,
95 .codec_dev = &soc_codec_dev_pcm3008,
96 .codec_data = &sffsdr_pcm3008_setup,
97};
98
99static struct resource sffsdr_snd_resources[] = {
100 {
101 .start = DAVINCI_MCBSP_BASE,
102 .end = DAVINCI_MCBSP_BASE + SZ_8K - 1,
103 .flags = IORESOURCE_MEM,
104 },
105};
106
107static struct evm_snd_platform_data sffsdr_snd_data = {
108 .tx_dma_ch = DAVINCI_DMA_MCBSP_TX,
109 .rx_dma_ch = DAVINCI_DMA_MCBSP_RX,
110};
111
112static struct platform_device *sffsdr_snd_device;
113
114static int __init sffsdr_init(void)
115{
116 int ret;
117
118 sffsdr_snd_device = platform_device_alloc("soc-audio", 0);
119 if (!sffsdr_snd_device) {
120 printk(KERN_ERR "platform device allocation failed\n");
121 return -ENOMEM;
122 }
123
124 platform_set_drvdata(sffsdr_snd_device, &sffsdr_snd_devdata);
125 sffsdr_snd_devdata.dev = &sffsdr_snd_device->dev;
126 sffsdr_snd_device->dev.platform_data = &sffsdr_snd_data;
127
128 ret = platform_device_add_resources(sffsdr_snd_device,
129 sffsdr_snd_resources,
130 ARRAY_SIZE(sffsdr_snd_resources));
131 if (ret) {
132 printk(KERN_ERR "platform device add ressources failed\n");
133 goto error;
134 }
135
136 ret = platform_device_add(sffsdr_snd_device);
137 if (ret)
138 goto error;
139
140 return ret;
141
142error:
143 platform_device_put(sffsdr_snd_device);
144 return ret;
145}
146
147static void __exit sffsdr_exit(void)
148{
149 platform_device_unregister(sffsdr_snd_device);
150}
151
152module_init(sffsdr_init);
153module_exit(sffsdr_exit);
154
155MODULE_AUTHOR("Hugo Villeneuve");
156MODULE_DESCRIPTION("Lyrtech SFFSDR ASoC driver");
157MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 8d73edc56102..95c12b26fe37 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -20,7 +20,7 @@ config SND_SOC_MPC8610_HPCD
20 20
21config SND_SOC_MPC5200_I2S 21config SND_SOC_MPC5200_I2S
22 tristate "Freescale MPC5200 PSC in I2S mode driver" 22 tristate "Freescale MPC5200 PSC in I2S mode driver"
23 depends on SND_SOC && PPC_MPC52xx && PPC_BESTCOMM 23 depends on PPC_MPC52xx && PPC_BESTCOMM
24 select SND_SOC_OF_SIMPLE 24 select SND_SOC_OF_SIMPLE
25 select PPC_BESTCOMM_GEN_BD 25 select PPC_BESTCOMM_GEN_BD
26 help 26 help
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index d2d3da9729f2..64993eda5679 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -284,7 +284,7 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
284 * fsl_dma_new: initialize this PCM driver. 284 * fsl_dma_new: initialize this PCM driver.
285 * 285 *
286 * This function is called when the codec driver calls snd_soc_new_pcms(), 286 * This function is called when the codec driver calls snd_soc_new_pcms(),
287 * once for each .dai_link in the machine driver's snd_soc_machine 287 * once for each .dai_link in the machine driver's snd_soc_card
288 * structure. 288 * structure.
289 */ 289 */
290static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, 290static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
@@ -853,6 +853,18 @@ int fsl_dma_configure(struct fsl_dma_info *dma_info)
853} 853}
854EXPORT_SYMBOL_GPL(fsl_dma_configure); 854EXPORT_SYMBOL_GPL(fsl_dma_configure);
855 855
856static int __init fsl_soc_platform_init(void)
857{
858 return snd_soc_register_platform(&fsl_soc_platform);
859}
860module_init(fsl_soc_platform_init);
861
862static void __exit fsl_soc_platform_exit(void)
863{
864 snd_soc_unregister_platform(&fsl_soc_platform);
865}
866module_exit(fsl_soc_platform_exit);
867
856MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); 868MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
857MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM module"); 869MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM module");
858MODULE_LICENSE("GPL"); 870MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 157a7895ffa1..c6d6eb71dc1d 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -266,7 +266,8 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
266 * If this is the first stream open, then grab the IRQ and program most of 266 * If this is the first stream open, then grab the IRQ and program most of
267 * the SSI registers. 267 * the SSI registers.
268 */ 268 */
269static int fsl_ssi_startup(struct snd_pcm_substream *substream) 269static int fsl_ssi_startup(struct snd_pcm_substream *substream,
270 struct snd_soc_dai *dai)
270{ 271{
271 struct snd_soc_pcm_runtime *rtd = substream->private_data; 272 struct snd_soc_pcm_runtime *rtd = substream->private_data;
272 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; 273 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
@@ -411,7 +412,8 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream)
411 * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the 412 * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the
412 * clock master. 413 * clock master.
413 */ 414 */
414static int fsl_ssi_prepare(struct snd_pcm_substream *substream) 415static int fsl_ssi_prepare(struct snd_pcm_substream *substream,
416 struct snd_soc_dai *dai)
415{ 417{
416 struct snd_pcm_runtime *runtime = substream->runtime; 418 struct snd_pcm_runtime *runtime = substream->runtime;
417 struct snd_soc_pcm_runtime *rtd = substream->private_data; 419 struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -441,7 +443,8 @@ static int fsl_ssi_prepare(struct snd_pcm_substream *substream)
441 * The DMA channel is in external master start and pause mode, which 443 * The DMA channel is in external master start and pause mode, which
442 * means the SSI completely controls the flow of data. 444 * means the SSI completely controls the flow of data.
443 */ 445 */
444static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd) 446static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
447 struct snd_soc_dai *dai)
445{ 448{
446 struct snd_soc_pcm_runtime *rtd = substream->private_data; 449 struct snd_soc_pcm_runtime *rtd = substream->private_data;
447 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; 450 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
@@ -490,7 +493,8 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd)
490 * 493 *
491 * Shutdown the SSI if there are no other substreams open. 494 * Shutdown the SSI if there are no other substreams open.
492 */ 495 */
493static void fsl_ssi_shutdown(struct snd_pcm_substream *substream) 496static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
497 struct snd_soc_dai *dai)
494{ 498{
495 struct snd_soc_pcm_runtime *rtd = substream->private_data; 499 struct snd_soc_pcm_runtime *rtd = substream->private_data;
496 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; 500 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
@@ -578,8 +582,6 @@ static struct snd_soc_dai fsl_ssi_dai_template = {
578 .prepare = fsl_ssi_prepare, 582 .prepare = fsl_ssi_prepare,
579 .shutdown = fsl_ssi_shutdown, 583 .shutdown = fsl_ssi_shutdown,
580 .trigger = fsl_ssi_trigger, 584 .trigger = fsl_ssi_trigger,
581 },
582 .dai_ops = {
583 .set_sysclk = fsl_ssi_set_sysclk, 585 .set_sysclk = fsl_ssi_set_sysclk,
584 .set_fmt = fsl_ssi_set_fmt, 586 .set_fmt = fsl_ssi_set_fmt,
585 }, 587 },
@@ -671,6 +673,14 @@ struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info)
671 fsl_ssi_dai->private_data = ssi_private; 673 fsl_ssi_dai->private_data = ssi_private;
672 fsl_ssi_dai->name = ssi_private->name; 674 fsl_ssi_dai->name = ssi_private->name;
673 fsl_ssi_dai->id = ssi_info->id; 675 fsl_ssi_dai->id = ssi_info->id;
676 fsl_ssi_dai->dev = ssi_info->dev;
677
678 ret = snd_soc_register_dai(fsl_ssi_dai);
679 if (ret != 0) {
680 dev_err(ssi_info->dev, "failed to register DAI: %d\n", ret);
681 kfree(fsl_ssi_dai);
682 return NULL;
683 }
674 684
675 return fsl_ssi_dai; 685 return fsl_ssi_dai;
676} 686}
@@ -688,6 +698,8 @@ void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai)
688 698
689 device_remove_file(ssi_private->dev, &ssi_private->dev_attr); 699 device_remove_file(ssi_private->dev, &ssi_private->dev_attr);
690 700
701 snd_soc_unregister_dai(&ssi_private->cpu_dai);
702
691 kfree(ssi_private); 703 kfree(ssi_private);
692} 704}
693EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai); 705EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai);
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
index 94a02eaa4825..9eb1ce185bd0 100644
--- a/sound/soc/fsl/mpc5200_psc_i2s.c
+++ b/sound/soc/fsl/mpc5200_psc_i2s.c
@@ -187,7 +187,8 @@ static irqreturn_t psc_i2s_bcom_irq(int irq, void *_psc_i2s_stream)
187 * If this is the first stream open, then grab the IRQ and program most of 187 * If this is the first stream open, then grab the IRQ and program most of
188 * the PSC registers. 188 * the PSC registers.
189 */ 189 */
190static int psc_i2s_startup(struct snd_pcm_substream *substream) 190static int psc_i2s_startup(struct snd_pcm_substream *substream,
191 struct snd_soc_dai *dai)
191{ 192{
192 struct snd_soc_pcm_runtime *rtd = substream->private_data; 193 struct snd_soc_pcm_runtime *rtd = substream->private_data;
193 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; 194 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
@@ -220,7 +221,8 @@ static int psc_i2s_startup(struct snd_pcm_substream *substream)
220} 221}
221 222
222static int psc_i2s_hw_params(struct snd_pcm_substream *substream, 223static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
223 struct snd_pcm_hw_params *params) 224 struct snd_pcm_hw_params *params,
225 struct snd_soc_dai *dai)
224{ 226{
225 struct snd_soc_pcm_runtime *rtd = substream->private_data; 227 struct snd_soc_pcm_runtime *rtd = substream->private_data;
226 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; 228 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
@@ -256,7 +258,8 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
256 return 0; 258 return 0;
257} 259}
258 260
259static int psc_i2s_hw_free(struct snd_pcm_substream *substream) 261static int psc_i2s_hw_free(struct snd_pcm_substream *substream,
262 struct snd_soc_dai *dai)
260{ 263{
261 snd_pcm_set_runtime_buffer(substream, NULL); 264 snd_pcm_set_runtime_buffer(substream, NULL);
262 return 0; 265 return 0;
@@ -268,7 +271,8 @@ static int psc_i2s_hw_free(struct snd_pcm_substream *substream)
268 * This function is called by ALSA to start, stop, pause, and resume the DMA 271 * This function is called by ALSA to start, stop, pause, and resume the DMA
269 * transfer of data. 272 * transfer of data.
270 */ 273 */
271static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd) 274static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
275 struct snd_soc_dai *dai)
272{ 276{
273 struct snd_soc_pcm_runtime *rtd = substream->private_data; 277 struct snd_soc_pcm_runtime *rtd = substream->private_data;
274 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; 278 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
@@ -383,7 +387,8 @@ static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
383 * 387 *
384 * Shutdown the PSC if there are no other substreams open. 388 * Shutdown the PSC if there are no other substreams open.
385 */ 389 */
386static void psc_i2s_shutdown(struct snd_pcm_substream *substream) 390static void psc_i2s_shutdown(struct snd_pcm_substream *substream,
391 struct snd_soc_dai *dai)
387{ 392{
388 struct snd_soc_pcm_runtime *rtd = substream->private_data; 393 struct snd_soc_pcm_runtime *rtd = substream->private_data;
389 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; 394 struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
@@ -464,7 +469,6 @@ static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
464 * psc_i2s_dai_template: template CPU Digital Audio Interface 469 * psc_i2s_dai_template: template CPU Digital Audio Interface
465 */ 470 */
466static struct snd_soc_dai psc_i2s_dai_template = { 471static struct snd_soc_dai psc_i2s_dai_template = {
467 .type = SND_SOC_DAI_I2S,
468 .playback = { 472 .playback = {
469 .channels_min = 2, 473 .channels_min = 2,
470 .channels_max = 2, 474 .channels_max = 2,
@@ -483,8 +487,6 @@ static struct snd_soc_dai psc_i2s_dai_template = {
483 .hw_free = psc_i2s_hw_free, 487 .hw_free = psc_i2s_hw_free,
484 .shutdown = psc_i2s_shutdown, 488 .shutdown = psc_i2s_shutdown,
485 .trigger = psc_i2s_trigger, 489 .trigger = psc_i2s_trigger,
486 },
487 .dai_ops = {
488 .set_sysclk = psc_i2s_set_sysclk, 490 .set_sysclk = psc_i2s_set_sysclk,
489 .set_fmt = psc_i2s_set_fmt, 491 .set_fmt = psc_i2s_set_fmt,
490 }, 492 },
@@ -826,6 +828,8 @@ static int __devinit psc_i2s_of_probe(struct of_device *op,
826 if (rc) 828 if (rc)
827 dev_info(psc_i2s->dev, "error creating sysfs files\n"); 829 dev_info(psc_i2s->dev, "error creating sysfs files\n");
828 830
831 snd_soc_register_platform(&psc_i2s_pcm_soc_platform);
832
829 /* Tell the ASoC OF helpers about it */ 833 /* Tell the ASoC OF helpers about it */
830 of_snd_soc_register_platform(&psc_i2s_pcm_soc_platform, op->node, 834 of_snd_soc_register_platform(&psc_i2s_pcm_soc_platform, op->node,
831 &psc_i2s->dai); 835 &psc_i2s->dai);
@@ -839,6 +843,8 @@ static int __devexit psc_i2s_of_remove(struct of_device *op)
839 843
840 dev_dbg(&op->dev, "psc_i2s_remove()\n"); 844 dev_dbg(&op->dev, "psc_i2s_remove()\n");
841 845
846 snd_soc_unregister_platform(&psc_i2s_pcm_soc_platform);
847
842 bcom_gen_bd_rx_release(psc_i2s->capture.bcom_task); 848 bcom_gen_bd_rx_release(psc_i2s->capture.bcom_task);
843 bcom_gen_bd_tx_release(psc_i2s->playback.bcom_task); 849 bcom_gen_bd_tx_release(psc_i2s->playback.bcom_task);
844 850
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index 94f89debde1f..bcec3f60bad9 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -29,7 +29,7 @@
29struct mpc8610_hpcd_data { 29struct mpc8610_hpcd_data {
30 struct snd_soc_device sound_devdata; 30 struct snd_soc_device sound_devdata;
31 struct snd_soc_dai_link dai; 31 struct snd_soc_dai_link dai;
32 struct snd_soc_machine machine; 32 struct snd_soc_card machine;
33 unsigned int dai_format; 33 unsigned int dai_format;
34 unsigned int codec_clk_direction; 34 unsigned int codec_clk_direction;
35 unsigned int cpu_clk_direction; 35 unsigned int cpu_clk_direction;
@@ -185,7 +185,7 @@ static struct snd_soc_ops mpc8610_hpcd_ops = {
185/** 185/**
186 * mpc8610_hpcd_machine: ASoC machine data 186 * mpc8610_hpcd_machine: ASoC machine data
187 */ 187 */
188static struct snd_soc_machine mpc8610_hpcd_machine = { 188static struct snd_soc_card mpc8610_hpcd_machine = {
189 .probe = mpc8610_hpcd_machine_probe, 189 .probe = mpc8610_hpcd_machine_probe,
190 .remove = mpc8610_hpcd_machine_remove, 190 .remove = mpc8610_hpcd_machine_remove,
191 .name = "MPC8610 HPCD", 191 .name = "MPC8610 HPCD",
@@ -465,9 +465,9 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev,
465 goto error; 465 goto error;
466 } 466 }
467 467
468 machine_data->sound_devdata.machine = &mpc8610_hpcd_machine; 468 machine_data->sound_devdata.card = &mpc8610_hpcd_machine;
469 machine_data->sound_devdata.codec_dev = &soc_codec_device_cs4270; 469 machine_data->sound_devdata.codec_dev = &soc_codec_device_cs4270;
470 machine_data->sound_devdata.platform = &fsl_soc_platform; 470 machine_data->machine.platform = &fsl_soc_platform;
471 471
472 sound_device->dev.platform_data = machine_data; 472 sound_device->dev.platform_data = machine_data;
473 473
diff --git a/sound/soc/fsl/soc-of-simple.c b/sound/soc/fsl/soc-of-simple.c
index 0382fdac51cd..8bc5cd9e972f 100644
--- a/sound/soc/fsl/soc-of-simple.c
+++ b/sound/soc/fsl/soc-of-simple.c
@@ -31,7 +31,7 @@ struct of_snd_soc_device {
31 int id; 31 int id;
32 struct list_head list; 32 struct list_head list;
33 struct snd_soc_device device; 33 struct snd_soc_device device;
34 struct snd_soc_machine machine; 34 struct snd_soc_card card;
35 struct snd_soc_dai_link dai_link; 35 struct snd_soc_dai_link dai_link;
36 struct platform_device *pdev; 36 struct platform_device *pdev;
37 struct device_node *platform_node; 37 struct device_node *platform_node;
@@ -58,9 +58,9 @@ of_snd_soc_get_device(struct device_node *codec_node)
58 /* Initialize the structure and add it to the global list */ 58 /* Initialize the structure and add it to the global list */
59 of_soc->codec_node = codec_node; 59 of_soc->codec_node = codec_node;
60 of_soc->id = of_snd_soc_next_index++; 60 of_soc->id = of_snd_soc_next_index++;
61 of_soc->machine.dai_link = &of_soc->dai_link; 61 of_soc->card.dai_link = &of_soc->dai_link;
62 of_soc->machine.num_links = 1; 62 of_soc->card.num_links = 1;
63 of_soc->device.machine = &of_soc->machine; 63 of_soc->device.card = &of_soc->card;
64 of_soc->dai_link.ops = &of_snd_soc_ops; 64 of_soc->dai_link.ops = &of_snd_soc_ops;
65 list_add(&of_soc->list, &of_snd_soc_device_list); 65 list_add(&of_soc->list, &of_snd_soc_device_list);
66 66
@@ -158,8 +158,8 @@ int of_snd_soc_register_platform(struct snd_soc_platform *platform,
158 158
159 of_soc->platform_node = node; 159 of_soc->platform_node = node;
160 of_soc->dai_link.cpu_dai = cpu_dai; 160 of_soc->dai_link.cpu_dai = cpu_dai;
161 of_soc->device.platform = platform; 161 of_soc->card.platform = platform;
162 of_soc->machine.name = of_soc->dai_link.cpu_dai->name; 162 of_soc->card.name = of_soc->dai_link.cpu_dai->name;
163 163
164 /* Now try to register the SoC device */ 164 /* Now try to register the SoC device */
165 of_snd_soc_register_device(of_soc); 165 of_snd_soc_register_device(of_soc);
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 8b7766b998d7..a7b1d77b2105 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -1,6 +1,6 @@
1config SND_OMAP_SOC 1config SND_OMAP_SOC
2 tristate "SoC Audio for the Texas Instruments OMAP chips" 2 tristate "SoC Audio for the Texas Instruments OMAP chips"
3 depends on ARCH_OMAP && SND_SOC 3 depends on ARCH_OMAP
4 4
5config SND_OMAP_SOC_MCBSP 5config SND_OMAP_SOC_MCBSP
6 tristate 6 tristate
@@ -21,3 +21,36 @@ config SND_OMAP_SOC_OSK5912
21 select SND_SOC_TLV320AIC23 21 select SND_SOC_TLV320AIC23
22 help 22 help
23 Say Y if you want to add support for SoC audio on osk5912. 23 Say Y if you want to add support for SoC audio on osk5912.
24
25config SND_OMAP_SOC_OVERO
26 tristate "SoC Audio support for Gumstix Overo"
27 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OVERO
28 select SND_OMAP_SOC_MCBSP
29 select SND_SOC_TWL4030
30 help
31 Say Y if you want to add support for SoC audio on the Gumstix Overo.
32
33config SND_OMAP_SOC_OMAP2EVM
34 tristate "SoC Audio support for OMAP2EVM board"
35 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP2EVM
36 select SND_OMAP_SOC_MCBSP
37 select SND_SOC_TWL4030
38 help
39 Say Y if you want to add support for SoC audio on the omap2evm board.
40
41config SND_OMAP_SOC_SDP3430
42 tristate "SoC Audio support for Texas Instruments SDP3430"
43 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP
44 select SND_OMAP_SOC_MCBSP
45 select SND_SOC_TWL4030
46 help
47 Say Y if you want to add support for SoC audio on Texas Instruments
48 SDP3430.
49
50config SND_OMAP_SOC_OMAP3_PANDORA
51 tristate "SoC Audio support for OMAP3 Pandora"
52 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA
53 select SND_OMAP_SOC_MCBSP
54 select SND_SOC_TWL4030
55 help
56 Say Y if you want to add support for SoC audio on the OMAP3 Pandora.
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index e09d1f297f64..76fedd96e365 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -8,6 +8,14 @@ obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
8# OMAP Machine Support 8# OMAP Machine Support
9snd-soc-n810-objs := n810.o 9snd-soc-n810-objs := n810.o
10snd-soc-osk5912-objs := osk5912.o 10snd-soc-osk5912-objs := osk5912.o
11snd-soc-overo-objs := overo.o
12snd-soc-omap2evm-objs := omap2evm.o
13snd-soc-sdp3430-objs := sdp3430.o
14snd-soc-omap3pandora-objs := omap3pandora.o
11 15
12obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o 16obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
13obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o 17obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
18obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
19obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o
20obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
21obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index fae3ad36e0bf..25593fee9121 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -70,9 +70,13 @@ static void n810_ext_control(struct snd_soc_codec *codec)
70 70
71static int n810_startup(struct snd_pcm_substream *substream) 71static int n810_startup(struct snd_pcm_substream *substream)
72{ 72{
73 struct snd_pcm_runtime *runtime = substream->runtime;
73 struct snd_soc_pcm_runtime *rtd = substream->private_data; 74 struct snd_soc_pcm_runtime *rtd = substream->private_data;
74 struct snd_soc_codec *codec = rtd->socdev->codec; 75 struct snd_soc_codec *codec = rtd->socdev->codec;
75 76
77 snd_pcm_hw_constraint_minmax(runtime,
78 SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
79
76 n810_ext_control(codec); 80 n810_ext_control(codec);
77 return clk_enable(sys_clkout2); 81 return clk_enable(sys_clkout2);
78} 82}
@@ -282,8 +286,9 @@ static struct snd_soc_dai_link n810_dai = {
282}; 286};
283 287
284/* Audio machine driver */ 288/* Audio machine driver */
285static struct snd_soc_machine snd_soc_machine_n810 = { 289static struct snd_soc_card snd_soc_n810 = {
286 .name = "N810", 290 .name = "N810",
291 .platform = &omap_soc_platform,
287 .dai_link = &n810_dai, 292 .dai_link = &n810_dai,
288 .num_links = 1, 293 .num_links = 1,
289}; 294};
@@ -298,8 +303,7 @@ static struct aic3x_setup_data n810_aic33_setup = {
298 303
299/* Audio subsystem */ 304/* Audio subsystem */
300static struct snd_soc_device n810_snd_devdata = { 305static struct snd_soc_device n810_snd_devdata = {
301 .machine = &snd_soc_machine_n810, 306 .card = &snd_soc_n810,
302 .platform = &omap_soc_platform,
303 .codec_dev = &soc_codec_dev_aic3x, 307 .codec_dev = &soc_codec_dev_aic3x,
304 .codec_data = &n810_aic33_setup, 308 .codec_data = &n810_aic33_setup,
305}; 309};
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 8485a8a9d0ff..ec5e18a78758 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -36,9 +36,7 @@
36#include "omap-mcbsp.h" 36#include "omap-mcbsp.h"
37#include "omap-pcm.h" 37#include "omap-pcm.h"
38 38
39#define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_44100 | \ 39#define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000)
40 SNDRV_PCM_RATE_48000 | \
41 SNDRV_PCM_RATE_KNOT)
42 40
43struct omap_mcbsp_data { 41struct omap_mcbsp_data {
44 unsigned int bus_id; 42 unsigned int bus_id;
@@ -140,7 +138,8 @@ static const unsigned long omap34xx_mcbsp_port[][2] = {
140static const unsigned long omap34xx_mcbsp_port[][2] = {}; 138static const unsigned long omap34xx_mcbsp_port[][2] = {};
141#endif 139#endif
142 140
143static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream) 141static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
142 struct snd_soc_dai *dai)
144{ 143{
145 struct snd_soc_pcm_runtime *rtd = substream->private_data; 144 struct snd_soc_pcm_runtime *rtd = substream->private_data;
146 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 145 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -153,7 +152,8 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream)
153 return err; 152 return err;
154} 153}
155 154
156static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream) 155static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
156 struct snd_soc_dai *dai)
157{ 157{
158 struct snd_soc_pcm_runtime *rtd = substream->private_data; 158 struct snd_soc_pcm_runtime *rtd = substream->private_data;
159 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 159 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -165,7 +165,8 @@ static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream)
165 } 165 }
166} 166}
167 167
168static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd) 168static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
169 struct snd_soc_dai *dai)
169{ 170{
170 struct snd_soc_pcm_runtime *rtd = substream->private_data; 171 struct snd_soc_pcm_runtime *rtd = substream->private_data;
171 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 172 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -194,14 +195,15 @@ static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd)
194} 195}
195 196
196static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, 197static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
197 struct snd_pcm_hw_params *params) 198 struct snd_pcm_hw_params *params,
199 struct snd_soc_dai *dai)
198{ 200{
199 struct snd_soc_pcm_runtime *rtd = substream->private_data; 201 struct snd_soc_pcm_runtime *rtd = substream->private_data;
200 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 202 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
201 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 203 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
202 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; 204 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
203 int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; 205 int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
204 int wlen; 206 int wlen, channels;
205 unsigned long port; 207 unsigned long port;
206 208
207 if (cpu_class_is_omap1()) { 209 if (cpu_class_is_omap1()) {
@@ -230,12 +232,17 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
230 return 0; 232 return 0;
231 } 233 }
232 234
233 switch (params_channels(params)) { 235 channels = params_channels(params);
236 switch (channels) {
234 case 2: 237 case 2:
235 /* Set 1 word per (McBPSP) frame and use dual-phase frames */ 238 /* Use dual-phase frames */
236 regs->rcr2 |= RFRLEN2(1 - 1) | RPHASE; 239 regs->rcr2 |= RPHASE;
240 regs->xcr2 |= XPHASE;
241 case 1:
242 /* Set 1 word per (McBSP) frame */
243 regs->rcr2 |= RFRLEN2(1 - 1);
237 regs->rcr1 |= RFRLEN1(1 - 1); 244 regs->rcr1 |= RFRLEN1(1 - 1);
238 regs->xcr2 |= XFRLEN2(1 - 1) | XPHASE; 245 regs->xcr2 |= XFRLEN2(1 - 1);
239 regs->xcr1 |= XFRLEN1(1 - 1); 246 regs->xcr1 |= XFRLEN1(1 - 1);
240 break; 247 break;
241 default: 248 default:
@@ -263,9 +270,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
263 regs->srgr2 |= FPER(wlen * 2 - 1); 270 regs->srgr2 |= FPER(wlen * 2 - 1);
264 regs->srgr1 |= FWID(wlen - 1); 271 regs->srgr1 |= FWID(wlen - 1);
265 break; 272 break;
266 case SND_SOC_DAIFMT_DSP_A: 273 case SND_SOC_DAIFMT_DSP_B:
267 regs->srgr2 |= FPER(wlen * 2 - 1); 274 regs->srgr2 |= FPER(wlen * channels - 1);
268 regs->srgr1 |= FWID(wlen * 2 - 2); 275 regs->srgr1 |= FWID(wlen * channels - 2);
269 break; 276 break;
270 } 277 }
271 278
@@ -302,7 +309,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
302 regs->rcr2 |= RDATDLY(1); 309 regs->rcr2 |= RDATDLY(1);
303 regs->xcr2 |= XDATDLY(1); 310 regs->xcr2 |= XDATDLY(1);
304 break; 311 break;
305 case SND_SOC_DAIFMT_DSP_A: 312 case SND_SOC_DAIFMT_DSP_B:
306 /* 0-bit data delay */ 313 /* 0-bit data delay */
307 regs->rcr2 |= RDATDLY(0); 314 regs->rcr2 |= RDATDLY(0);
308 regs->xcr2 |= XDATDLY(0); 315 regs->xcr2 |= XDATDLY(0);
@@ -452,17 +459,16 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
452 459
453#define OMAP_MCBSP_DAI_BUILDER(link_id) \ 460#define OMAP_MCBSP_DAI_BUILDER(link_id) \
454{ \ 461{ \
455 .name = "omap-mcbsp-dai-(link_id)", \ 462 .name = "omap-mcbsp-dai-"#link_id, \
456 .id = (link_id), \ 463 .id = (link_id), \
457 .type = SND_SOC_DAI_I2S, \
458 .playback = { \ 464 .playback = { \
459 .channels_min = 2, \ 465 .channels_min = 1, \
460 .channels_max = 2, \ 466 .channels_max = 2, \
461 .rates = OMAP_MCBSP_RATES, \ 467 .rates = OMAP_MCBSP_RATES, \
462 .formats = SNDRV_PCM_FMTBIT_S16_LE, \ 468 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
463 }, \ 469 }, \
464 .capture = { \ 470 .capture = { \
465 .channels_min = 2, \ 471 .channels_min = 1, \
466 .channels_max = 2, \ 472 .channels_max = 2, \
467 .rates = OMAP_MCBSP_RATES, \ 473 .rates = OMAP_MCBSP_RATES, \
468 .formats = SNDRV_PCM_FMTBIT_S16_LE, \ 474 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
@@ -472,8 +478,6 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
472 .shutdown = omap_mcbsp_dai_shutdown, \ 478 .shutdown = omap_mcbsp_dai_shutdown, \
473 .trigger = omap_mcbsp_dai_trigger, \ 479 .trigger = omap_mcbsp_dai_trigger, \
474 .hw_params = omap_mcbsp_dai_hw_params, \ 480 .hw_params = omap_mcbsp_dai_hw_params, \
475 }, \
476 .dai_ops = { \
477 .set_fmt = omap_mcbsp_dai_set_dai_fmt, \ 481 .set_fmt = omap_mcbsp_dai_set_dai_fmt, \
478 .set_clkdiv = omap_mcbsp_dai_set_clkdiv, \ 482 .set_clkdiv = omap_mcbsp_dai_set_clkdiv, \
479 .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, \ 483 .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, \
@@ -495,6 +499,19 @@ struct snd_soc_dai omap_mcbsp_dai[] = {
495 499
496EXPORT_SYMBOL_GPL(omap_mcbsp_dai); 500EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
497 501
502static int __init snd_omap_mcbsp_init(void)
503{
504 return snd_soc_register_dais(omap_mcbsp_dai,
505 ARRAY_SIZE(omap_mcbsp_dai));
506}
507module_init(snd_omap_mcbsp_init);
508
509static void __exit snd_omap_mcbsp_exit(void)
510{
511 snd_soc_unregister_dais(omap_mcbsp_dai, ARRAY_SIZE(omap_mcbsp_dai));
512}
513module_exit(snd_omap_mcbsp_exit);
514
498MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>"); 515MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
499MODULE_DESCRIPTION("OMAP I2S SoC Interface"); 516MODULE_DESCRIPTION("OMAP I2S SoC Interface");
500MODULE_LICENSE("GPL"); 517MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index acd68efb2b75..b0362dfd5b71 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -97,7 +97,7 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
97 prtd->dma_data = dma_data; 97 prtd->dma_data = dma_data;
98 err = omap_request_dma(dma_data->dma_req, dma_data->name, 98 err = omap_request_dma(dma_data->dma_req, dma_data->name,
99 omap_pcm_dma_irq, substream, &prtd->dma_ch); 99 omap_pcm_dma_irq, substream, &prtd->dma_ch);
100 if (!err & !cpu_is_omap1510()) { 100 if (!err && !cpu_is_omap1510()) {
101 /* 101 /*
102 * Link channel with itself so DMA doesn't need any 102 * Link channel with itself so DMA doesn't need any
103 * reprogramming while looping the buffer 103 * reprogramming while looping the buffer
@@ -354,6 +354,18 @@ struct snd_soc_platform omap_soc_platform = {
354}; 354};
355EXPORT_SYMBOL_GPL(omap_soc_platform); 355EXPORT_SYMBOL_GPL(omap_soc_platform);
356 356
357static int __init omap_soc_platform_init(void)
358{
359 return snd_soc_register_platform(&omap_soc_platform);
360}
361module_init(omap_soc_platform_init);
362
363static void __exit omap_soc_platform_exit(void)
364{
365 snd_soc_unregister_platform(&omap_soc_platform);
366}
367module_exit(omap_soc_platform_exit);
368
357MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>"); 369MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
358MODULE_DESCRIPTION("OMAP PCM DMA module"); 370MODULE_DESCRIPTION("OMAP PCM DMA module");
359MODULE_LICENSE("GPL"); 371MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap2evm.c b/sound/soc/omap/omap2evm.c
new file mode 100644
index 000000000000..0c2322dcf02a
--- /dev/null
+++ b/sound/soc/omap/omap2evm.c
@@ -0,0 +1,151 @@
1/*
2 * omap2evm.c -- SoC audio machine driver for omap2evm board
3 *
4 * Author: Arun KS <arunks@mistralsolutions.com>
5 *
6 * Based on sound/soc/omap/overo.c by Steve Sakoman
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * 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., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/clk.h>
25#include <linux/platform_device.h>
26#include <sound/core.h>
27#include <sound/pcm.h>
28#include <sound/soc.h>
29#include <sound/soc-dapm.h>
30
31#include <asm/mach-types.h>
32#include <mach/hardware.h>
33#include <mach/gpio.h>
34#include <mach/mcbsp.h>
35
36#include "omap-mcbsp.h"
37#include "omap-pcm.h"
38#include "../codecs/twl4030.h"
39
40static int omap2evm_hw_params(struct snd_pcm_substream *substream,
41 struct snd_pcm_hw_params *params,
42 struct snd_soc_dai *dai)
43{
44 struct snd_soc_pcm_runtime *rtd = substream->private_data;
45 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
46 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
47 int ret;
48
49 /* Set codec DAI configuration */
50 ret = snd_soc_dai_set_fmt(codec_dai,
51 SND_SOC_DAIFMT_I2S |
52 SND_SOC_DAIFMT_NB_NF |
53 SND_SOC_DAIFMT_CBM_CFM);
54 if (ret < 0) {
55 printk(KERN_ERR "can't set codec DAI configuration\n");
56 return ret;
57 }
58
59 /* Set cpu DAI configuration */
60 ret = snd_soc_dai_set_fmt(cpu_dai,
61 SND_SOC_DAIFMT_I2S |
62 SND_SOC_DAIFMT_NB_NF |
63 SND_SOC_DAIFMT_CBM_CFM);
64 if (ret < 0) {
65 printk(KERN_ERR "can't set cpu DAI configuration\n");
66 return ret;
67 }
68
69 /* Set the codec system clock for DAC and ADC */
70 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
71 SND_SOC_CLOCK_IN);
72 if (ret < 0) {
73 printk(KERN_ERR "can't set codec system clock\n");
74 return ret;
75 }
76
77 return 0;
78}
79
80static struct snd_soc_ops omap2evm_ops = {
81 .hw_params = omap2evm_hw_params,
82};
83
84/* Digital audio interface glue - connects codec <--> CPU */
85static struct snd_soc_dai_link omap2evm_dai = {
86 .name = "TWL4030",
87 .stream_name = "TWL4030",
88 .cpu_dai = &omap_mcbsp_dai[0],
89 .codec_dai = &twl4030_dai,
90 .ops = &omap2evm_ops,
91};
92
93/* Audio machine driver */
94static struct snd_soc_card snd_soc_omap2evm = {
95 .name = "omap2evm",
96 .platform = &omap_soc_platform,
97 .dai_link = &omap2evm_dai,
98 .num_links = 1,
99};
100
101/* Audio subsystem */
102static struct snd_soc_device omap2evm_snd_devdata = {
103 .card = &snd_soc_omap2evm,
104 .codec_dev = &soc_codec_dev_twl4030,
105};
106
107static struct platform_device *omap2evm_snd_device;
108
109static int __init omap2evm_soc_init(void)
110{
111 int ret;
112
113 if (!machine_is_omap2evm()) {
114 pr_debug("Not omap2evm!\n");
115 return -ENODEV;
116 }
117 printk(KERN_INFO "omap2evm SoC init\n");
118
119 omap2evm_snd_device = platform_device_alloc("soc-audio", -1);
120 if (!omap2evm_snd_device) {
121 printk(KERN_ERR "Platform device allocation failed\n");
122 return -ENOMEM;
123 }
124
125 platform_set_drvdata(omap2evm_snd_device, &omap2evm_snd_devdata);
126 omap2evm_snd_devdata.dev = &omap2evm_snd_device->dev;
127 *(unsigned int *)omap2evm_dai.cpu_dai->private_data = 1; /* McBSP2 */
128
129 ret = platform_device_add(omap2evm_snd_device);
130 if (ret)
131 goto err1;
132
133 return 0;
134
135err1:
136 printk(KERN_ERR "Unable to add platform device\n");
137 platform_device_put(omap2evm_snd_device);
138
139 return ret;
140}
141module_init(omap2evm_soc_init);
142
143static void __exit omap2evm_soc_exit(void)
144{
145 platform_device_unregister(omap2evm_snd_device);
146}
147module_exit(omap2evm_soc_exit);
148
149MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
150MODULE_DESCRIPTION("ALSA SoC omap2evm");
151MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c
new file mode 100644
index 000000000000..fd24a4acd2f5
--- /dev/null
+++ b/sound/soc/omap/omap3beagle.c
@@ -0,0 +1,149 @@
1/*
2 * omap3beagle.c -- SoC audio for OMAP3 Beagle
3 *
4 * Author: Steve Sakoman <steve@sakoman.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * 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., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/clk.h>
23#include <linux/platform_device.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28
29#include <asm/mach-types.h>
30#include <mach/hardware.h>
31#include <mach/gpio.h>
32#include <mach/mcbsp.h>
33
34#include "omap-mcbsp.h"
35#include "omap-pcm.h"
36#include "../codecs/twl4030.h"
37
38static int omap3beagle_hw_params(struct snd_pcm_substream *substream,
39 struct snd_pcm_hw_params *params)
40{
41 struct snd_soc_pcm_runtime *rtd = substream->private_data;
42 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
43 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
44 int ret;
45
46 /* Set codec DAI configuration */
47 ret = snd_soc_dai_set_fmt(codec_dai,
48 SND_SOC_DAIFMT_I2S |
49 SND_SOC_DAIFMT_NB_NF |
50 SND_SOC_DAIFMT_CBM_CFM);
51 if (ret < 0) {
52 printk(KERN_ERR "can't set codec DAI configuration\n");
53 return ret;
54 }
55
56 /* Set cpu DAI configuration */
57 ret = snd_soc_dai_set_fmt(cpu_dai,
58 SND_SOC_DAIFMT_I2S |
59 SND_SOC_DAIFMT_NB_NF |
60 SND_SOC_DAIFMT_CBM_CFM);
61 if (ret < 0) {
62 printk(KERN_ERR "can't set cpu DAI configuration\n");
63 return ret;
64 }
65
66 /* Set the codec system clock for DAC and ADC */
67 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
68 SND_SOC_CLOCK_IN);
69 if (ret < 0) {
70 printk(KERN_ERR "can't set codec system clock\n");
71 return ret;
72 }
73
74 return 0;
75}
76
77static struct snd_soc_ops omap3beagle_ops = {
78 .hw_params = omap3beagle_hw_params,
79};
80
81/* Digital audio interface glue - connects codec <--> CPU */
82static struct snd_soc_dai_link omap3beagle_dai = {
83 .name = "TWL4030",
84 .stream_name = "TWL4030",
85 .cpu_dai = &omap_mcbsp_dai[0],
86 .codec_dai = &twl4030_dai,
87 .ops = &omap3beagle_ops,
88};
89
90/* Audio machine driver */
91static struct snd_soc_card snd_soc_omap3beagle = {
92 .name = "omap3beagle",
93 .platform = &omap_soc_platform,
94 .dai_link = &omap3beagle_dai,
95 .num_links = 1,
96};
97
98/* Audio subsystem */
99static struct snd_soc_device omap3beagle_snd_devdata = {
100 .card = &snd_soc_omap3beagle,
101 .codec_dev = &soc_codec_dev_twl4030,
102};
103
104static struct platform_device *omap3beagle_snd_device;
105
106static int __init omap3beagle_soc_init(void)
107{
108 int ret;
109
110 if (!machine_is_omap3_beagle()) {
111 pr_debug("Not OMAP3 Beagle!\n");
112 return -ENODEV;
113 }
114 pr_info("OMAP3 Beagle SoC init\n");
115
116 omap3beagle_snd_device = platform_device_alloc("soc-audio", -1);
117 if (!omap3beagle_snd_device) {
118 printk(KERN_ERR "Platform device allocation failed\n");
119 return -ENOMEM;
120 }
121
122 platform_set_drvdata(omap3beagle_snd_device, &omap3beagle_snd_devdata);
123 omap3beagle_snd_devdata.dev = &omap3beagle_snd_device->dev;
124 *(unsigned int *)omap3beagle_dai.cpu_dai->private_data = 1; /* McBSP2 */
125
126 ret = platform_device_add(omap3beagle_snd_device);
127 if (ret)
128 goto err1;
129
130 return 0;
131
132err1:
133 printk(KERN_ERR "Unable to add platform device\n");
134 platform_device_put(omap3beagle_snd_device);
135
136 return ret;
137}
138
139static void __exit omap3beagle_soc_exit(void)
140{
141 platform_device_unregister(omap3beagle_snd_device);
142}
143
144module_init(omap3beagle_soc_init);
145module_exit(omap3beagle_soc_exit);
146
147MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>");
148MODULE_DESCRIPTION("ALSA SoC OMAP3 Beagle");
149MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
new file mode 100644
index 000000000000..bd91594496b1
--- /dev/null
+++ b/sound/soc/omap/omap3pandora.c
@@ -0,0 +1,311 @@
1/*
2 * omap3pandora.c -- SoC audio for Pandora Handheld Console
3 *
4 * Author: Gražvydas Ignotas <notasas@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * 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., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/clk.h>
23#include <linux/platform_device.h>
24#include <linux/gpio.h>
25#include <linux/delay.h>
26
27#include <sound/core.h>
28#include <sound/pcm.h>
29#include <sound/soc.h>
30#include <sound/soc-dapm.h>
31
32#include <asm/mach-types.h>
33
34#include "omap-mcbsp.h"
35#include "omap-pcm.h"
36#include "../codecs/twl4030.h"
37
38#define OMAP3_PANDORA_DAC_POWER_GPIO 118
39#define OMAP3_PANDORA_AMP_POWER_GPIO 14
40
41#define PREFIX "ASoC omap3pandora: "
42
43static int omap3pandora_cmn_hw_params(struct snd_soc_dai *codec_dai,
44 struct snd_soc_dai *cpu_dai, unsigned int fmt)
45{
46 int ret;
47
48 /* Set codec DAI configuration */
49 ret = snd_soc_dai_set_fmt(codec_dai, fmt);
50 if (ret < 0) {
51 pr_err(PREFIX "can't set codec DAI configuration\n");
52 return ret;
53 }
54
55 /* Set cpu DAI configuration */
56 ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
57 if (ret < 0) {
58 pr_err(PREFIX "can't set cpu DAI configuration\n");
59 return ret;
60 }
61
62 /* Set the codec system clock for DAC and ADC */
63 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
64 SND_SOC_CLOCK_IN);
65 if (ret < 0) {
66 pr_err(PREFIX "can't set codec system clock\n");
67 return ret;
68 }
69
70 /* Set McBSP clock to external */
71 ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_EXT, 0,
72 SND_SOC_CLOCK_IN);
73 if (ret < 0) {
74 pr_err(PREFIX "can't set cpu system clock\n");
75 return ret;
76 }
77
78 ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, 8);
79 if (ret < 0) {
80 pr_err(PREFIX "can't set SRG clock divider\n");
81 return ret;
82 }
83
84 return 0;
85}
86
87static int omap3pandora_out_hw_params(struct snd_pcm_substream *substream,
88 struct snd_pcm_hw_params *params)
89{
90 struct snd_soc_pcm_runtime *rtd = substream->private_data;
91 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
92 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
93
94 return omap3pandora_cmn_hw_params(codec_dai, cpu_dai,
95 SND_SOC_DAIFMT_I2S |
96 SND_SOC_DAIFMT_IB_NF |
97 SND_SOC_DAIFMT_CBS_CFS);
98}
99
100static int omap3pandora_in_hw_params(struct snd_pcm_substream *substream,
101 struct snd_pcm_hw_params *params)
102{
103 struct snd_soc_pcm_runtime *rtd = substream->private_data;
104 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
105 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
106
107 return omap3pandora_cmn_hw_params(codec_dai, cpu_dai,
108 SND_SOC_DAIFMT_I2S |
109 SND_SOC_DAIFMT_NB_NF |
110 SND_SOC_DAIFMT_CBS_CFS);
111}
112
113static int omap3pandora_hp_event(struct snd_soc_dapm_widget *w,
114 struct snd_kcontrol *k, int event)
115{
116 if (SND_SOC_DAPM_EVENT_ON(event)) {
117 gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1);
118 gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 1);
119 } else {
120 gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 0);
121 mdelay(1);
122 gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 0);
123 }
124
125 return 0;
126}
127
128/*
129 * Audio paths on Pandora board:
130 *
131 * |O| ---> PCM DAC +-> AMP -> Headphone Jack
132 * |M| A +--------> Line Out
133 * |A| <~~clk~~+
134 * |P| <--- TWL4030 <--------- Line In and MICs
135 */
136static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = {
137 SND_SOC_DAPM_DAC("PCM DAC", "Playback", SND_SOC_NOPM, 0, 0),
138 SND_SOC_DAPM_PGA_E("Headphone Amplifier", SND_SOC_NOPM,
139 0, 0, NULL, 0, omap3pandora_hp_event,
140 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
141 SND_SOC_DAPM_HP("Headphone Jack", NULL),
142 SND_SOC_DAPM_LINE("Line Out", NULL),
143};
144
145static const struct snd_soc_dapm_widget omap3pandora_in_dapm_widgets[] = {
146 SND_SOC_DAPM_MIC("Mic (Internal)", NULL),
147 SND_SOC_DAPM_MIC("Mic (external)", NULL),
148 SND_SOC_DAPM_LINE("Line In", NULL),
149};
150
151static const struct snd_soc_dapm_route omap3pandora_out_map[] = {
152 {"Headphone Amplifier", NULL, "PCM DAC"},
153 {"Line Out", NULL, "PCM DAC"},
154 {"Headphone Jack", NULL, "Headphone Amplifier"},
155};
156
157static const struct snd_soc_dapm_route omap3pandora_in_map[] = {
158 {"INL", NULL, "Line In"},
159 {"INR", NULL, "Line In"},
160 {"INL", NULL, "Mic (Internal)"},
161 {"INR", NULL, "Mic (external)"},
162};
163
164static int omap3pandora_out_init(struct snd_soc_codec *codec)
165{
166 int ret;
167
168 ret = snd_soc_dapm_new_controls(codec, omap3pandora_out_dapm_widgets,
169 ARRAY_SIZE(omap3pandora_out_dapm_widgets));
170 if (ret < 0)
171 return ret;
172
173 snd_soc_dapm_add_routes(codec, omap3pandora_out_map,
174 ARRAY_SIZE(omap3pandora_out_map));
175
176 return snd_soc_dapm_sync(codec);
177}
178
179static int omap3pandora_in_init(struct snd_soc_codec *codec)
180{
181 int ret;
182
183 ret = snd_soc_dapm_new_controls(codec, omap3pandora_in_dapm_widgets,
184 ARRAY_SIZE(omap3pandora_in_dapm_widgets));
185 if (ret < 0)
186 return ret;
187
188 snd_soc_dapm_add_routes(codec, omap3pandora_in_map,
189 ARRAY_SIZE(omap3pandora_in_map));
190
191 return snd_soc_dapm_sync(codec);
192}
193
194static struct snd_soc_ops omap3pandora_out_ops = {
195 .hw_params = omap3pandora_out_hw_params,
196};
197
198static struct snd_soc_ops omap3pandora_in_ops = {
199 .hw_params = omap3pandora_in_hw_params,
200};
201
202/* Digital audio interface glue - connects codec <--> CPU */
203static struct snd_soc_dai_link omap3pandora_dai[] = {
204 {
205 .name = "PCM1773",
206 .stream_name = "HiFi Out",
207 .cpu_dai = &omap_mcbsp_dai[0],
208 .codec_dai = &twl4030_dai,
209 .ops = &omap3pandora_out_ops,
210 .init = omap3pandora_out_init,
211 }, {
212 .name = "TWL4030",
213 .stream_name = "Line/Mic In",
214 .cpu_dai = &omap_mcbsp_dai[1],
215 .codec_dai = &twl4030_dai,
216 .ops = &omap3pandora_in_ops,
217 .init = omap3pandora_in_init,
218 }
219};
220
221/* SoC card */
222static struct snd_soc_card snd_soc_card_omap3pandora = {
223 .name = "omap3pandora",
224 .platform = &omap_soc_platform,
225 .dai_link = omap3pandora_dai,
226 .num_links = ARRAY_SIZE(omap3pandora_dai),
227};
228
229/* Audio subsystem */
230static struct snd_soc_device omap3pandora_snd_data = {
231 .card = &snd_soc_card_omap3pandora,
232 .codec_dev = &soc_codec_dev_twl4030,
233};
234
235static struct platform_device *omap3pandora_snd_device;
236
237static int __init omap3pandora_soc_init(void)
238{
239 int ret;
240
241 if (!machine_is_omap3_pandora()) {
242 pr_debug(PREFIX "Not OMAP3 Pandora\n");
243 return -ENODEV;
244 }
245 pr_info("OMAP3 Pandora SoC init\n");
246
247 ret = gpio_request(OMAP3_PANDORA_DAC_POWER_GPIO, "dac_power");
248 if (ret) {
249 pr_err(PREFIX "Failed to get DAC power GPIO\n");
250 return ret;
251 }
252
253 ret = gpio_direction_output(OMAP3_PANDORA_DAC_POWER_GPIO, 0);
254 if (ret) {
255 pr_err(PREFIX "Failed to set DAC power GPIO direction\n");
256 goto fail0;
257 }
258
259 ret = gpio_request(OMAP3_PANDORA_AMP_POWER_GPIO, "amp_power");
260 if (ret) {
261 pr_err(PREFIX "Failed to get amp power GPIO\n");
262 goto fail0;
263 }
264
265 ret = gpio_direction_output(OMAP3_PANDORA_AMP_POWER_GPIO, 0);
266 if (ret) {
267 pr_err(PREFIX "Failed to set amp power GPIO direction\n");
268 goto fail1;
269 }
270
271 omap3pandora_snd_device = platform_device_alloc("soc-audio", -1);
272 if (omap3pandora_snd_device == NULL) {
273 pr_err(PREFIX "Platform device allocation failed\n");
274 ret = -ENOMEM;
275 goto fail1;
276 }
277
278 platform_set_drvdata(omap3pandora_snd_device, &omap3pandora_snd_data);
279 omap3pandora_snd_data.dev = &omap3pandora_snd_device->dev;
280 *(unsigned int *)omap_mcbsp_dai[0].private_data = 1; /* McBSP2 */
281 *(unsigned int *)omap_mcbsp_dai[1].private_data = 3; /* McBSP4 */
282
283 ret = platform_device_add(omap3pandora_snd_device);
284 if (ret) {
285 pr_err(PREFIX "Unable to add platform device\n");
286 goto fail2;
287 }
288
289 return 0;
290
291fail2:
292 platform_device_put(omap3pandora_snd_device);
293fail1:
294 gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO);
295fail0:
296 gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO);
297 return ret;
298}
299module_init(omap3pandora_soc_init);
300
301static void __exit omap3pandora_soc_exit(void)
302{
303 platform_device_unregister(omap3pandora_snd_device);
304 gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO);
305 gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO);
306}
307module_exit(omap3pandora_soc_exit);
308
309MODULE_AUTHOR("Grazvydas Ignotas <notasas@gmail.com>");
310MODULE_DESCRIPTION("ALSA SoC OMAP3 Pandora");
311MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c
index 0fe733796898..cd41a948df7b 100644
--- a/sound/soc/omap/osk5912.c
+++ b/sound/soc/omap/osk5912.c
@@ -61,7 +61,7 @@ static int osk_hw_params(struct snd_pcm_substream *substream,
61 61
62 /* Set codec DAI configuration */ 62 /* Set codec DAI configuration */
63 err = snd_soc_dai_set_fmt(codec_dai, 63 err = snd_soc_dai_set_fmt(codec_dai,
64 SND_SOC_DAIFMT_DSP_A | 64 SND_SOC_DAIFMT_DSP_B |
65 SND_SOC_DAIFMT_NB_IF | 65 SND_SOC_DAIFMT_NB_IF |
66 SND_SOC_DAIFMT_CBM_CFM); 66 SND_SOC_DAIFMT_CBM_CFM);
67 if (err < 0) { 67 if (err < 0) {
@@ -71,7 +71,7 @@ static int osk_hw_params(struct snd_pcm_substream *substream,
71 71
72 /* Set cpu DAI configuration */ 72 /* Set cpu DAI configuration */
73 err = snd_soc_dai_set_fmt(cpu_dai, 73 err = snd_soc_dai_set_fmt(cpu_dai,
74 SND_SOC_DAIFMT_DSP_A | 74 SND_SOC_DAIFMT_DSP_B |
75 SND_SOC_DAIFMT_NB_IF | 75 SND_SOC_DAIFMT_NB_IF |
76 SND_SOC_DAIFMT_CBM_CFM); 76 SND_SOC_DAIFMT_CBM_CFM);
77 if (err < 0) { 77 if (err < 0) {
@@ -143,16 +143,16 @@ static struct snd_soc_dai_link osk_dai = {
143}; 143};
144 144
145/* Audio machine driver */ 145/* Audio machine driver */
146static struct snd_soc_machine snd_soc_machine_osk = { 146static struct snd_soc_card snd_soc_card_osk = {
147 .name = "OSK5912", 147 .name = "OSK5912",
148 .platform = &omap_soc_platform,
148 .dai_link = &osk_dai, 149 .dai_link = &osk_dai,
149 .num_links = 1, 150 .num_links = 1,
150}; 151};
151 152
152/* Audio subsystem */ 153/* Audio subsystem */
153static struct snd_soc_device osk_snd_devdata = { 154static struct snd_soc_device osk_snd_devdata = {
154 .machine = &snd_soc_machine_osk, 155 .card = &snd_soc_card_osk,
155 .platform = &omap_soc_platform,
156 .codec_dev = &soc_codec_dev_tlv320aic23, 156 .codec_dev = &soc_codec_dev_tlv320aic23,
157}; 157};
158 158
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c
new file mode 100644
index 000000000000..a72dc4e159e5
--- /dev/null
+++ b/sound/soc/omap/overo.c
@@ -0,0 +1,148 @@
1/*
2 * overo.c -- SoC audio for Gumstix Overo
3 *
4 * Author: Steve Sakoman <steve@sakoman.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * 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., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/clk.h>
23#include <linux/platform_device.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28
29#include <asm/mach-types.h>
30#include <mach/hardware.h>
31#include <mach/gpio.h>
32#include <mach/mcbsp.h>
33
34#include "omap-mcbsp.h"
35#include "omap-pcm.h"
36#include "../codecs/twl4030.h"
37
38static int overo_hw_params(struct snd_pcm_substream *substream,
39 struct snd_pcm_hw_params *params)
40{
41 struct snd_soc_pcm_runtime *rtd = substream->private_data;
42 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
43 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
44 int ret;
45
46 /* Set codec DAI configuration */
47 ret = snd_soc_dai_set_fmt(codec_dai,
48 SND_SOC_DAIFMT_I2S |
49 SND_SOC_DAIFMT_NB_NF |
50 SND_SOC_DAIFMT_CBM_CFM);
51 if (ret < 0) {
52 printk(KERN_ERR "can't set codec DAI configuration\n");
53 return ret;
54 }
55
56 /* Set cpu DAI configuration */
57 ret = snd_soc_dai_set_fmt(cpu_dai,
58 SND_SOC_DAIFMT_I2S |
59 SND_SOC_DAIFMT_NB_NF |
60 SND_SOC_DAIFMT_CBM_CFM);
61 if (ret < 0) {
62 printk(KERN_ERR "can't set cpu DAI configuration\n");
63 return ret;
64 }
65
66 /* Set the codec system clock for DAC and ADC */
67 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
68 SND_SOC_CLOCK_IN);
69 if (ret < 0) {
70 printk(KERN_ERR "can't set codec system clock\n");
71 return ret;
72 }
73
74 return 0;
75}
76
77static struct snd_soc_ops overo_ops = {
78 .hw_params = overo_hw_params,
79};
80
81/* Digital audio interface glue - connects codec <--> CPU */
82static struct snd_soc_dai_link overo_dai = {
83 .name = "TWL4030",
84 .stream_name = "TWL4030",
85 .cpu_dai = &omap_mcbsp_dai[0],
86 .codec_dai = &twl4030_dai,
87 .ops = &overo_ops,
88};
89
90/* Audio machine driver */
91static struct snd_soc_card snd_soc_card_overo = {
92 .name = "overo",
93 .platform = &omap_soc_platform,
94 .dai_link = &overo_dai,
95 .num_links = 1,
96};
97
98/* Audio subsystem */
99static struct snd_soc_device overo_snd_devdata = {
100 .card = &snd_soc_card_overo,
101 .codec_dev = &soc_codec_dev_twl4030,
102};
103
104static struct platform_device *overo_snd_device;
105
106static int __init overo_soc_init(void)
107{
108 int ret;
109
110 if (!machine_is_overo()) {
111 pr_debug("Not Overo!\n");
112 return -ENODEV;
113 }
114 printk(KERN_INFO "overo SoC init\n");
115
116 overo_snd_device = platform_device_alloc("soc-audio", -1);
117 if (!overo_snd_device) {
118 printk(KERN_ERR "Platform device allocation failed\n");
119 return -ENOMEM;
120 }
121
122 platform_set_drvdata(overo_snd_device, &overo_snd_devdata);
123 overo_snd_devdata.dev = &overo_snd_device->dev;
124 *(unsigned int *)overo_dai.cpu_dai->private_data = 1; /* McBSP2 */
125
126 ret = platform_device_add(overo_snd_device);
127 if (ret)
128 goto err1;
129
130 return 0;
131
132err1:
133 printk(KERN_ERR "Unable to add platform device\n");
134 platform_device_put(overo_snd_device);
135
136 return ret;
137}
138module_init(overo_soc_init);
139
140static void __exit overo_soc_exit(void)
141{
142 platform_device_unregister(overo_snd_device);
143}
144module_exit(overo_soc_exit);
145
146MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>");
147MODULE_DESCRIPTION("ALSA SoC overo");
148MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c
new file mode 100644
index 000000000000..ad97836818b1
--- /dev/null
+++ b/sound/soc/omap/sdp3430.c
@@ -0,0 +1,152 @@
1/*
2 * sdp3430.c -- SoC audio for TI OMAP3430 SDP
3 *
4 * Author: Misael Lopez Cruz <x0052729@ti.com>
5 *
6 * Based on:
7 * Author: Steve Sakoman <steve@sakoman.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#include <linux/clk.h>
26#include <linux/platform_device.h>
27#include <sound/core.h>
28#include <sound/pcm.h>
29#include <sound/soc.h>
30#include <sound/soc-dapm.h>
31
32#include <asm/mach-types.h>
33#include <mach/hardware.h>
34#include <mach/gpio.h>
35#include <mach/mcbsp.h>
36
37#include "omap-mcbsp.h"
38#include "omap-pcm.h"
39#include "../codecs/twl4030.h"
40
41static int sdp3430_hw_params(struct snd_pcm_substream *substream,
42 struct snd_pcm_hw_params *params)
43{
44 struct snd_soc_pcm_runtime *rtd = substream->private_data;
45 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
46 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
47 int ret;
48
49 /* Set codec DAI configuration */
50 ret = snd_soc_dai_set_fmt(codec_dai,
51 SND_SOC_DAIFMT_I2S |
52 SND_SOC_DAIFMT_NB_NF |
53 SND_SOC_DAIFMT_CBM_CFM);
54 if (ret < 0) {
55 printk(KERN_ERR "can't set codec DAI configuration\n");
56 return ret;
57 }
58
59 /* Set cpu DAI configuration */
60 ret = snd_soc_dai_set_fmt(cpu_dai,
61 SND_SOC_DAIFMT_I2S |
62 SND_SOC_DAIFMT_NB_NF |
63 SND_SOC_DAIFMT_CBM_CFM);
64 if (ret < 0) {
65 printk(KERN_ERR "can't set cpu DAI configuration\n");
66 return ret;
67 }
68
69 /* Set the codec system clock for DAC and ADC */
70 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
71 SND_SOC_CLOCK_IN);
72 if (ret < 0) {
73 printk(KERN_ERR "can't set codec system clock\n");
74 return ret;
75 }
76
77 return 0;
78}
79
80static struct snd_soc_ops sdp3430_ops = {
81 .hw_params = sdp3430_hw_params,
82};
83
84/* Digital audio interface glue - connects codec <--> CPU */
85static struct snd_soc_dai_link sdp3430_dai = {
86 .name = "TWL4030",
87 .stream_name = "TWL4030",
88 .cpu_dai = &omap_mcbsp_dai[0],
89 .codec_dai = &twl4030_dai,
90 .ops = &sdp3430_ops,
91};
92
93/* Audio machine driver */
94static struct snd_soc_machine snd_soc_machine_sdp3430 = {
95 .name = "SDP3430",
96 .platform = &omap_soc_platform,
97 .dai_link = &sdp3430_dai,
98 .num_links = 1,
99};
100
101/* Audio subsystem */
102static struct snd_soc_device sdp3430_snd_devdata = {
103 .machine = &snd_soc_machine_sdp3430,
104 .codec_dev = &soc_codec_dev_twl4030,
105};
106
107static struct platform_device *sdp3430_snd_device;
108
109static int __init sdp3430_soc_init(void)
110{
111 int ret;
112
113 if (!machine_is_omap_3430sdp()) {
114 pr_debug("Not SDP3430!\n");
115 return -ENODEV;
116 }
117 printk(KERN_INFO "SDP3430 SoC init\n");
118
119 sdp3430_snd_device = platform_device_alloc("soc-audio", -1);
120 if (!sdp3430_snd_device) {
121 printk(KERN_ERR "Platform device allocation failed\n");
122 return -ENOMEM;
123 }
124
125 platform_set_drvdata(sdp3430_snd_device, &sdp3430_snd_devdata);
126 sdp3430_snd_devdata.dev = &sdp3430_snd_device->dev;
127 *(unsigned int *)sdp3430_dai.cpu_dai->private_data = 1; /* McBSP2 */
128
129 ret = platform_device_add(sdp3430_snd_device);
130 if (ret)
131 goto err1;
132
133 return 0;
134
135err1:
136 printk(KERN_ERR "Unable to add platform device\n");
137 platform_device_put(sdp3430_snd_device);
138
139 return ret;
140}
141module_init(sdp3430_soc_init);
142
143static void __exit sdp3430_soc_exit(void)
144{
145 platform_device_unregister(sdp3430_snd_device);
146}
147module_exit(sdp3430_soc_exit);
148
149MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
150MODULE_DESCRIPTION("ALSA SoC SDP3430");
151MODULE_LICENSE("GPL");
152
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index f8c1cdd940ac..f82e10699471 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -21,6 +21,9 @@ config SND_PXA2XX_SOC_AC97
21config SND_PXA2XX_SOC_I2S 21config SND_PXA2XX_SOC_I2S
22 tristate 22 tristate
23 23
24config SND_PXA_SOC_SSP
25 tristate
26
24config SND_PXA2XX_SOC_CORGI 27config SND_PXA2XX_SOC_CORGI
25 tristate "SoC Audio support for Sharp Zaurus SL-C7x0" 28 tristate "SoC Audio support for Sharp Zaurus SL-C7x0"
26 depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx 29 depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx
@@ -75,3 +78,22 @@ config SND_PXA2XX_SOC_EM_X270
75 help 78 help
76 Say Y if you want to add support for SoC audio on 79 Say Y if you want to add support for SoC audio on
77 CompuLab EM-x270. 80 CompuLab EM-x270.
81
82config SND_PXA2XX_SOC_PALM27X
83 bool "SoC Audio support for Palm T|X, T5 and LifeDrive"
84 depends on SND_PXA2XX_SOC && (MACH_PALMLD || MACH_PALMTX || MACH_PALMT5)
85 select SND_PXA2XX_SOC_AC97
86 select SND_SOC_WM9712
87 help
88 Say Y if you want to add support for SoC audio on
89 Palm T|X, T5 or LifeDrive handheld computer.
90
91config SND_SOC_ZYLONITE
92 tristate "SoC Audio support for Marvell Zylonite"
93 depends on SND_PXA2XX_SOC && MACH_ZYLONITE
94 select SND_PXA2XX_SOC_AC97
95 select SND_PXA_SOC_SSP
96 select SND_SOC_WM9713
97 help
98 Say Y if you want to add support for SoC audio on the
99 Marvell Zylonite reference platform.
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index 5bc8edf9dca9..08a9f2797729 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -2,10 +2,12 @@
2snd-soc-pxa2xx-objs := pxa2xx-pcm.o 2snd-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
5 6
6obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o 7obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o
7obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o 8obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o
8obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o 9obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o
10obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o
9 11
10# PXA Machine Support 12# PXA Machine Support
11snd-soc-corgi-objs := corgi.o 13snd-soc-corgi-objs := corgi.o
@@ -14,6 +16,8 @@ snd-soc-tosa-objs := tosa.o
14snd-soc-e800-objs := e800_wm9712.o 16snd-soc-e800-objs := e800_wm9712.o
15snd-soc-spitz-objs := spitz.o 17snd-soc-spitz-objs := spitz.o
16snd-soc-em-x270-objs := em-x270.o 18snd-soc-em-x270-objs := em-x270.o
19snd-soc-palm27x-objs := palm27x.o
20snd-soc-zylonite-objs := zylonite.o
17 21
18obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o 22obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
19obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o 23obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
@@ -21,3 +25,5 @@ obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o
21obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o 25obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o
22obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o 26obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o
23obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o 27obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o
28obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o
29obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index 2718eaf7895f..1ba25a559524 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -108,15 +108,11 @@ static int corgi_startup(struct snd_pcm_substream *substream)
108} 108}
109 109
110/* we need to unmute the HP at shutdown as the mute burns power on corgi */ 110/* we need to unmute the HP at shutdown as the mute burns power on corgi */
111static int corgi_shutdown(struct snd_pcm_substream *substream) 111static void corgi_shutdown(struct snd_pcm_substream *substream)
112{ 112{
113 struct snd_soc_pcm_runtime *rtd = substream->private_data;
114 struct snd_soc_codec *codec = rtd->socdev->codec;
115
116 /* set = unmute headphone */ 113 /* set = unmute headphone */
117 gpio_set_value(CORGI_GPIO_MUTE_L, 1); 114 gpio_set_value(CORGI_GPIO_MUTE_L, 1);
118 gpio_set_value(CORGI_GPIO_MUTE_R, 1); 115 gpio_set_value(CORGI_GPIO_MUTE_R, 1);
119 return 0;
120} 116}
121 117
122static int corgi_hw_params(struct snd_pcm_substream *substream, 118static int corgi_hw_params(struct snd_pcm_substream *substream,
@@ -314,8 +310,9 @@ static struct snd_soc_dai_link corgi_dai = {
314}; 310};
315 311
316/* corgi audio machine driver */ 312/* corgi audio machine driver */
317static struct snd_soc_machine snd_soc_machine_corgi = { 313static struct snd_soc_card snd_soc_corgi = {
318 .name = "Corgi", 314 .name = "Corgi",
315 .platform = &pxa2xx_soc_platform,
319 .dai_link = &corgi_dai, 316 .dai_link = &corgi_dai,
320 .num_links = 1, 317 .num_links = 1,
321}; 318};
@@ -328,8 +325,7 @@ static struct wm8731_setup_data corgi_wm8731_setup = {
328 325
329/* corgi audio subsystem */ 326/* corgi audio subsystem */
330static struct snd_soc_device corgi_snd_devdata = { 327static struct snd_soc_device corgi_snd_devdata = {
331 .machine = &snd_soc_machine_corgi, 328 .card = &snd_soc_corgi,
332 .platform = &pxa2xx_soc_platform,
333 .codec_dev = &soc_codec_dev_wm8731, 329 .codec_dev = &soc_codec_dev_wm8731,
334 .codec_data = &corgi_wm8731_setup, 330 .codec_data = &corgi_wm8731_setup,
335}; 331};
diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c
index 6781c5be242f..2e3386dfa0f0 100644
--- a/sound/soc/pxa/e800_wm9712.c
+++ b/sound/soc/pxa/e800_wm9712.c
@@ -29,7 +29,7 @@
29#include "pxa2xx-pcm.h" 29#include "pxa2xx-pcm.h"
30#include "pxa2xx-ac97.h" 30#include "pxa2xx-ac97.h"
31 31
32static struct snd_soc_machine e800; 32static struct snd_soc_card e800;
33 33
34static struct snd_soc_dai_link e800_dai[] = { 34static struct snd_soc_dai_link e800_dai[] = {
35{ 35{
@@ -40,15 +40,15 @@ static struct snd_soc_dai_link e800_dai[] = {
40}, 40},
41}; 41};
42 42
43static struct snd_soc_machine e800 = { 43static struct snd_soc_card e800 = {
44 .name = "Toshiba e800", 44 .name = "Toshiba e800",
45 .platform = &pxa2xx_soc_platform,
45 .dai_link = e800_dai, 46 .dai_link = e800_dai,
46 .num_links = ARRAY_SIZE(e800_dai), 47 .num_links = ARRAY_SIZE(e800_dai),
47}; 48};
48 49
49static struct snd_soc_device e800_snd_devdata = { 50static struct snd_soc_device e800_snd_devdata = {
50 .machine = &e800, 51 .card = &e800,
51 .platform = &pxa2xx_soc_platform,
52 .codec_dev = &soc_codec_dev_wm9712, 52 .codec_dev = &soc_codec_dev_wm9712,
53}; 53};
54 54
diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c
index e6ff6929ab4b..fe4a729ea648 100644
--- a/sound/soc/pxa/em-x270.c
+++ b/sound/soc/pxa/em-x270.c
@@ -23,7 +23,6 @@
23#include <linux/moduleparam.h> 23#include <linux/moduleparam.h>
24#include <linux/device.h> 24#include <linux/device.h>
25 25
26#include <sound/driver.h>
27#include <sound/core.h> 26#include <sound/core.h>
28#include <sound/pcm.h> 27#include <sound/pcm.h>
29#include <sound/soc.h> 28#include <sound/soc.h>
@@ -53,15 +52,15 @@ static struct snd_soc_dai_link em_x270_dai[] = {
53 }, 52 },
54}; 53};
55 54
56static struct snd_soc_machine em_x270 = { 55static struct snd_soc_card em_x270 = {
57 .name = "EM-X270", 56 .name = "EM-X270",
57 .platform = &pxa2xx_soc_platform,
58 .dai_link = em_x270_dai, 58 .dai_link = em_x270_dai,
59 .num_links = ARRAY_SIZE(em_x270_dai), 59 .num_links = ARRAY_SIZE(em_x270_dai),
60}; 60};
61 61
62static struct snd_soc_device em_x270_snd_devdata = { 62static struct snd_soc_device em_x270_snd_devdata = {
63 .machine = &em_x270, 63 .card = &em_x270,
64 .platform = &pxa2xx_soc_platform,
65 .codec_dev = &soc_codec_dev_wm9712, 64 .codec_dev = &soc_codec_dev_wm9712,
66}; 65};
67 66
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
new file mode 100644
index 000000000000..4a9cf3083af0
--- /dev/null
+++ b/sound/soc/pxa/palm27x.c
@@ -0,0 +1,269 @@
1/*
2 * linux/sound/soc/pxa/palm27x.c
3 *
4 * SoC Audio driver for Palm T|X, T5 and LifeDrive
5 *
6 * based on tosa.c
7 *
8 * Copyright (C) 2008 Marek Vasut <marek.vasut@gmail.com>
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
12 * published by the Free Software Foundation.
13 *
14 */
15
16#include <linux/module.h>
17#include <linux/moduleparam.h>
18#include <linux/device.h>
19#include <linux/gpio.h>
20#include <linux/interrupt.h>
21#include <linux/irq.h>
22
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/soc.h>
26#include <sound/soc-dapm.h>
27
28#include <asm/mach-types.h>
29#include <mach/audio.h>
30#include <mach/palmasoc.h>
31
32#include "../codecs/wm9712.h"
33#include "pxa2xx-pcm.h"
34#include "pxa2xx-ac97.h"
35
36static int palm27x_jack_func = 1;
37static int palm27x_spk_func = 1;
38static int palm27x_ep_gpio = -1;
39
40static void palm27x_ext_control(struct snd_soc_codec *codec)
41{
42 if (!palm27x_spk_func)
43 snd_soc_dapm_enable_pin(codec, "Speaker");
44 else
45 snd_soc_dapm_disable_pin(codec, "Speaker");
46
47 if (!palm27x_jack_func)
48 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
49 else
50 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
51
52 snd_soc_dapm_sync(codec);
53}
54
55static int palm27x_startup(struct snd_pcm_substream *substream)
56{
57 struct snd_soc_pcm_runtime *rtd = substream->private_data;
58 struct snd_soc_codec *codec = rtd->socdev->codec;
59
60 /* check the jack status at stream startup */
61 palm27x_ext_control(codec);
62 return 0;
63}
64
65static struct snd_soc_ops palm27x_ops = {
66 .startup = palm27x_startup,
67};
68
69static irqreturn_t palm27x_interrupt(int irq, void *v)
70{
71 palm27x_spk_func = gpio_get_value(palm27x_ep_gpio);
72 palm27x_jack_func = !palm27x_spk_func;
73 return IRQ_HANDLED;
74}
75
76static int palm27x_get_jack(struct snd_kcontrol *kcontrol,
77 struct snd_ctl_elem_value *ucontrol)
78{
79 ucontrol->value.integer.value[0] = palm27x_jack_func;
80 return 0;
81}
82
83static int palm27x_set_jack(struct snd_kcontrol *kcontrol,
84 struct snd_ctl_elem_value *ucontrol)
85{
86 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
87
88 if (palm27x_jack_func == ucontrol->value.integer.value[0])
89 return 0;
90
91 palm27x_jack_func = ucontrol->value.integer.value[0];
92 palm27x_ext_control(codec);
93 return 1;
94}
95
96static int palm27x_get_spk(struct snd_kcontrol *kcontrol,
97 struct snd_ctl_elem_value *ucontrol)
98{
99 ucontrol->value.integer.value[0] = palm27x_spk_func;
100 return 0;
101}
102
103static int palm27x_set_spk(struct snd_kcontrol *kcontrol,
104 struct snd_ctl_elem_value *ucontrol)
105{
106 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
107
108 if (palm27x_spk_func == ucontrol->value.integer.value[0])
109 return 0;
110
111 palm27x_spk_func = ucontrol->value.integer.value[0];
112 palm27x_ext_control(codec);
113 return 1;
114}
115
116/* PalmTX machine dapm widgets */
117static const struct snd_soc_dapm_widget palm27x_dapm_widgets[] = {
118 SND_SOC_DAPM_HP("Headphone Jack", NULL),
119 SND_SOC_DAPM_SPK("Speaker", NULL),
120};
121
122/* PalmTX audio map */
123static const struct snd_soc_dapm_route audio_map[] = {
124 /* headphone connected to HPOUTL, HPOUTR */
125 {"Headphone Jack", NULL, "HPOUTL"},
126 {"Headphone Jack", NULL, "HPOUTR"},
127
128 /* ext speaker connected to ROUT2, LOUT2 */
129 {"Speaker", NULL, "LOUT2"},
130 {"Speaker", NULL, "ROUT2"},
131};
132
133static const char *jack_function[] = {"Headphone", "Off"};
134static const char *spk_function[] = {"On", "Off"};
135static const struct soc_enum palm27x_enum[] = {
136 SOC_ENUM_SINGLE_EXT(2, jack_function),
137 SOC_ENUM_SINGLE_EXT(2, spk_function),
138};
139
140static const struct snd_kcontrol_new palm27x_controls[] = {
141 SOC_ENUM_EXT("Jack Function", palm27x_enum[0], palm27x_get_jack,
142 palm27x_set_jack),
143 SOC_ENUM_EXT("Speaker Function", palm27x_enum[1], palm27x_get_spk,
144 palm27x_set_spk),
145};
146
147static int palm27x_ac97_init(struct snd_soc_codec *codec)
148{
149 int i, err;
150
151 snd_soc_dapm_nc_pin(codec, "OUT3");
152 snd_soc_dapm_nc_pin(codec, "MONOOUT");
153
154 /* add palm27x specific controls */
155 for (i = 0; i < ARRAY_SIZE(palm27x_controls); i++) {
156 err = snd_ctl_add(codec->card,
157 snd_soc_cnew(&palm27x_controls[i],
158 codec, NULL));
159 if (err < 0)
160 return err;
161 }
162
163 /* add palm27x specific widgets */
164 snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets,
165 ARRAY_SIZE(palm27x_dapm_widgets));
166
167 /* set up palm27x specific audio path audio_map */
168 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
169
170 snd_soc_dapm_sync(codec);
171 return 0;
172}
173
174static struct snd_soc_dai_link palm27x_dai[] = {
175{
176 .name = "AC97 HiFi",
177 .stream_name = "AC97 HiFi",
178 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
179 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
180 .init = palm27x_ac97_init,
181 .ops = &palm27x_ops,
182},
183{
184 .name = "AC97 Aux",
185 .stream_name = "AC97 Aux",
186 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
187 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
188 .ops = &palm27x_ops,
189},
190};
191
192static struct snd_soc_card palm27x_asoc = {
193 .name = "Palm/PXA27x",
194 .platform = &pxa2xx_soc_platform,
195 .dai_link = palm27x_dai,
196 .num_links = ARRAY_SIZE(palm27x_dai),
197};
198
199static struct snd_soc_device palm27x_snd_devdata = {
200 .card = &palm27x_asoc,
201 .codec_dev = &soc_codec_dev_wm9712,
202};
203
204static struct platform_device *palm27x_snd_device;
205
206static int __init palm27x_asoc_init(void)
207{
208 int ret;
209
210 if (!(machine_is_palmtx() || machine_is_palmt5() ||
211 machine_is_palmld()))
212 return -ENODEV;
213
214 ret = gpio_request(palm27x_ep_gpio, "Headphone Jack");
215 if (ret)
216 return ret;
217 ret = gpio_direction_input(palm27x_ep_gpio);
218 if (ret)
219 goto err_alloc;
220
221 if (request_irq(gpio_to_irq(palm27x_ep_gpio), palm27x_interrupt,
222 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
223 "Headphone jack", NULL))
224 goto err_alloc;
225
226 palm27x_snd_device = platform_device_alloc("soc-audio", -1);
227 if (!palm27x_snd_device) {
228 ret = -ENOMEM;
229 goto err_dev;
230 }
231
232 platform_set_drvdata(palm27x_snd_device, &palm27x_snd_devdata);
233 palm27x_snd_devdata.dev = &palm27x_snd_device->dev;
234 ret = platform_device_add(palm27x_snd_device);
235
236 if (ret != 0)
237 goto put_device;
238
239 return 0;
240
241put_device:
242 platform_device_put(palm27x_snd_device);
243err_dev:
244 free_irq(gpio_to_irq(palm27x_ep_gpio), NULL);
245err_alloc:
246 gpio_free(palm27x_ep_gpio);
247
248 return ret;
249}
250
251static void __exit palm27x_asoc_exit(void)
252{
253 free_irq(gpio_to_irq(palm27x_ep_gpio), NULL);
254 gpio_free(palm27x_ep_gpio);
255 platform_device_unregister(palm27x_snd_device);
256}
257
258void __init palm27x_asoc_set_pdata(struct palm27x_asoc_info *data)
259{
260 palm27x_ep_gpio = data->jack_gpio;
261}
262
263module_init(palm27x_asoc_init);
264module_exit(palm27x_asoc_exit);
265
266/* Module information */
267MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
268MODULE_DESCRIPTION("ALSA SoC Palm T|X, T5 and LifeDrive");
269MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index 4d9930c52789..6e9827189fff 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -276,8 +276,9 @@ static struct snd_soc_dai_link poodle_dai = {
276}; 276};
277 277
278/* poodle audio machine driver */ 278/* poodle audio machine driver */
279static struct snd_soc_machine snd_soc_machine_poodle = { 279static struct snd_soc_card snd_soc_poodle = {
280 .name = "Poodle", 280 .name = "Poodle",
281 .platform = &pxa2xx_soc_platform,
281 .dai_link = &poodle_dai, 282 .dai_link = &poodle_dai,
282 .num_links = 1, 283 .num_links = 1,
283}; 284};
@@ -290,8 +291,7 @@ static struct wm8731_setup_data poodle_wm8731_setup = {
290 291
291/* poodle audio subsystem */ 292/* poodle audio subsystem */
292static struct snd_soc_device poodle_snd_devdata = { 293static struct snd_soc_device poodle_snd_devdata = {
293 .machine = &snd_soc_machine_poodle, 294 .card = &snd_soc_poodle,
294 .platform = &pxa2xx_soc_platform,
295 .codec_dev = &soc_codec_dev_wm8731, 295 .codec_dev = &soc_codec_dev_wm8731,
296 .codec_data = &poodle_wm8731_setup, 296 .codec_data = &poodle_wm8731_setup,
297}; 297};
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
new file mode 100644
index 000000000000..73cb6b4c2f2d
--- /dev/null
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -0,0 +1,931 @@
1#define DEBUG
2/*
3 * pxa-ssp.c -- ALSA Soc Audio Layer
4 *
5 * Copyright 2005,2008 Wolfson Microelectronics PLC.
6 * Author: Liam Girdwood
7 * Mark Brown <broonie@opensource.wolfsonmicro.com>
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 as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * TODO:
15 * o Test network mode for > 16bit sample size
16 */
17
18#include <linux/init.h>
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <linux/clk.h>
22#include <linux/io.h>
23
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/initval.h>
27#include <sound/pcm_params.h>
28#include <sound/soc.h>
29#include <sound/pxa2xx-lib.h>
30
31#include <mach/hardware.h>
32#include <mach/pxa-regs.h>
33#include <mach/regs-ssp.h>
34#include <mach/audio.h>
35#include <mach/ssp.h>
36
37#include "pxa2xx-pcm.h"
38#include "pxa-ssp.h"
39
40/*
41 * SSP audio private data
42 */
43struct ssp_priv {
44 struct ssp_dev dev;
45 unsigned int sysclk;
46 int dai_fmt;
47#ifdef CONFIG_PM
48 struct ssp_state state;
49#endif
50};
51
52#define PXA2xx_SSP1_BASE 0x41000000
53#define PXA27x_SSP2_BASE 0x41700000
54#define PXA27x_SSP3_BASE 0x41900000
55#define PXA3xx_SSP4_BASE 0x41a00000
56
57static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_mono_out = {
58 .name = "SSP1 PCM Mono out",
59 .dev_addr = PXA2xx_SSP1_BASE + SSDR,
60 .drcmr = &DRCMR(14),
61 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
62 DCMD_BURST16 | DCMD_WIDTH2,
63};
64
65static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_mono_in = {
66 .name = "SSP1 PCM Mono in",
67 .dev_addr = PXA2xx_SSP1_BASE + SSDR,
68 .drcmr = &DRCMR(13),
69 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
70 DCMD_BURST16 | DCMD_WIDTH2,
71};
72
73static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_stereo_out = {
74 .name = "SSP1 PCM Stereo out",
75 .dev_addr = PXA2xx_SSP1_BASE + SSDR,
76 .drcmr = &DRCMR(14),
77 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
78 DCMD_BURST16 | DCMD_WIDTH4,
79};
80
81static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_stereo_in = {
82 .name = "SSP1 PCM Stereo in",
83 .dev_addr = PXA2xx_SSP1_BASE + SSDR,
84 .drcmr = &DRCMR(13),
85 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
86 DCMD_BURST16 | DCMD_WIDTH4,
87};
88
89static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_mono_out = {
90 .name = "SSP2 PCM Mono out",
91 .dev_addr = PXA27x_SSP2_BASE + SSDR,
92 .drcmr = &DRCMR(16),
93 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
94 DCMD_BURST16 | DCMD_WIDTH2,
95};
96
97static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_mono_in = {
98 .name = "SSP2 PCM Mono in",
99 .dev_addr = PXA27x_SSP2_BASE + SSDR,
100 .drcmr = &DRCMR(15),
101 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
102 DCMD_BURST16 | DCMD_WIDTH2,
103};
104
105static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_stereo_out = {
106 .name = "SSP2 PCM Stereo out",
107 .dev_addr = PXA27x_SSP2_BASE + SSDR,
108 .drcmr = &DRCMR(16),
109 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
110 DCMD_BURST16 | DCMD_WIDTH4,
111};
112
113static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_stereo_in = {
114 .name = "SSP2 PCM Stereo in",
115 .dev_addr = PXA27x_SSP2_BASE + SSDR,
116 .drcmr = &DRCMR(15),
117 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
118 DCMD_BURST16 | DCMD_WIDTH4,
119};
120
121static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_mono_out = {
122 .name = "SSP3 PCM Mono out",
123 .dev_addr = PXA27x_SSP3_BASE + SSDR,
124 .drcmr = &DRCMR(67),
125 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
126 DCMD_BURST16 | DCMD_WIDTH2,
127};
128
129static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_mono_in = {
130 .name = "SSP3 PCM Mono in",
131 .dev_addr = PXA27x_SSP3_BASE + SSDR,
132 .drcmr = &DRCMR(66),
133 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
134 DCMD_BURST16 | DCMD_WIDTH2,
135};
136
137static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_stereo_out = {
138 .name = "SSP3 PCM Stereo out",
139 .dev_addr = PXA27x_SSP3_BASE + SSDR,
140 .drcmr = &DRCMR(67),
141 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
142 DCMD_BURST16 | DCMD_WIDTH4,
143};
144
145static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_stereo_in = {
146 .name = "SSP3 PCM Stereo in",
147 .dev_addr = PXA27x_SSP3_BASE + SSDR,
148 .drcmr = &DRCMR(66),
149 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
150 DCMD_BURST16 | DCMD_WIDTH4,
151};
152
153static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_mono_out = {
154 .name = "SSP4 PCM Mono out",
155 .dev_addr = PXA3xx_SSP4_BASE + SSDR,
156 .drcmr = &DRCMR(67),
157 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
158 DCMD_BURST16 | DCMD_WIDTH2,
159};
160
161static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_mono_in = {
162 .name = "SSP4 PCM Mono in",
163 .dev_addr = PXA3xx_SSP4_BASE + SSDR,
164 .drcmr = &DRCMR(66),
165 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
166 DCMD_BURST16 | DCMD_WIDTH2,
167};
168
169static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_stereo_out = {
170 .name = "SSP4 PCM Stereo out",
171 .dev_addr = PXA3xx_SSP4_BASE + SSDR,
172 .drcmr = &DRCMR(67),
173 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
174 DCMD_BURST16 | DCMD_WIDTH4,
175};
176
177static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_stereo_in = {
178 .name = "SSP4 PCM Stereo in",
179 .dev_addr = PXA3xx_SSP4_BASE + SSDR,
180 .drcmr = &DRCMR(66),
181 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
182 DCMD_BURST16 | DCMD_WIDTH4,
183};
184
185static void dump_registers(struct ssp_device *ssp)
186{
187 dev_dbg(&ssp->pdev->dev, "SSCR0 0x%08x SSCR1 0x%08x SSTO 0x%08x\n",
188 ssp_read_reg(ssp, SSCR0), ssp_read_reg(ssp, SSCR1),
189 ssp_read_reg(ssp, SSTO));
190
191 dev_dbg(&ssp->pdev->dev, "SSPSP 0x%08x SSSR 0x%08x SSACD 0x%08x\n",
192 ssp_read_reg(ssp, SSPSP), ssp_read_reg(ssp, SSSR),
193 ssp_read_reg(ssp, SSACD));
194}
195
196static struct pxa2xx_pcm_dma_params *ssp_dma_params[4][4] = {
197 {
198 &pxa_ssp1_pcm_mono_out, &pxa_ssp1_pcm_mono_in,
199 &pxa_ssp1_pcm_stereo_out, &pxa_ssp1_pcm_stereo_in,
200 },
201 {
202 &pxa_ssp2_pcm_mono_out, &pxa_ssp2_pcm_mono_in,
203 &pxa_ssp2_pcm_stereo_out, &pxa_ssp2_pcm_stereo_in,
204 },
205 {
206 &pxa_ssp3_pcm_mono_out, &pxa_ssp3_pcm_mono_in,
207 &pxa_ssp3_pcm_stereo_out, &pxa_ssp3_pcm_stereo_in,
208 },
209 {
210 &pxa_ssp4_pcm_mono_out, &pxa_ssp4_pcm_mono_in,
211 &pxa_ssp4_pcm_stereo_out, &pxa_ssp4_pcm_stereo_in,
212 },
213};
214
215static int pxa_ssp_startup(struct snd_pcm_substream *substream,
216 struct snd_soc_dai *dai)
217{
218 struct snd_soc_pcm_runtime *rtd = substream->private_data;
219 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
220 struct ssp_priv *priv = cpu_dai->private_data;
221 int ret = 0;
222
223 if (!cpu_dai->active) {
224 ret = ssp_init(&priv->dev, cpu_dai->id + 1, SSP_NO_IRQ);
225 if (ret < 0)
226 return ret;
227 ssp_disable(&priv->dev);
228 }
229 return ret;
230}
231
232static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
233 struct snd_soc_dai *dai)
234{
235 struct snd_soc_pcm_runtime *rtd = substream->private_data;
236 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
237 struct ssp_priv *priv = cpu_dai->private_data;
238
239 if (!cpu_dai->active) {
240 ssp_disable(&priv->dev);
241 ssp_exit(&priv->dev);
242 }
243}
244
245#ifdef CONFIG_PM
246
247static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai)
248{
249 struct ssp_priv *priv = cpu_dai->private_data;
250
251 if (!cpu_dai->active)
252 return 0;
253
254 ssp_save_state(&priv->dev, &priv->state);
255 clk_disable(priv->dev.ssp->clk);
256 return 0;
257}
258
259static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai)
260{
261 struct ssp_priv *priv = cpu_dai->private_data;
262
263 if (!cpu_dai->active)
264 return 0;
265
266 clk_enable(priv->dev.ssp->clk);
267 ssp_restore_state(&priv->dev, &priv->state);
268 ssp_enable(&priv->dev);
269
270 return 0;
271}
272
273#else
274#define pxa_ssp_suspend NULL
275#define pxa_ssp_resume NULL
276#endif
277
278/**
279 * ssp_set_clkdiv - set SSP clock divider
280 * @div: serial clock rate divider
281 */
282static void ssp_set_scr(struct ssp_dev *dev, u32 div)
283{
284 struct ssp_device *ssp = dev->ssp;
285 u32 sscr0 = ssp_read_reg(dev->ssp, SSCR0) & ~SSCR0_SCR;
286
287 ssp_write_reg(ssp, SSCR0, (sscr0 | SSCR0_SerClkDiv(div)));
288}
289
290/*
291 * Set the SSP ports SYSCLK.
292 */
293static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
294 int clk_id, unsigned int freq, int dir)
295{
296 struct ssp_priv *priv = cpu_dai->private_data;
297 struct ssp_device *ssp = priv->dev.ssp;
298 int val;
299
300 u32 sscr0 = ssp_read_reg(ssp, SSCR0) &
301 ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ADC);
302
303 dev_dbg(&ssp->pdev->dev,
304 "pxa_ssp_set_dai_sysclk id: %d, clk_id %d, freq %d\n",
305 cpu_dai->id, clk_id, freq);
306
307 switch (clk_id) {
308 case PXA_SSP_CLK_NET_PLL:
309 sscr0 |= SSCR0_MOD;
310 break;
311 case PXA_SSP_CLK_PLL:
312 /* Internal PLL is fixed */
313 if (cpu_is_pxa25x())
314 priv->sysclk = 1843200;
315 else
316 priv->sysclk = 13000000;
317 break;
318 case PXA_SSP_CLK_EXT:
319 priv->sysclk = freq;
320 sscr0 |= SSCR0_ECS;
321 break;
322 case PXA_SSP_CLK_NET:
323 priv->sysclk = freq;
324 sscr0 |= SSCR0_NCS | SSCR0_MOD;
325 break;
326 case PXA_SSP_CLK_AUDIO:
327 priv->sysclk = 0;
328 ssp_set_scr(&priv->dev, 1);
329 sscr0 |= SSCR0_ADC;
330 break;
331 default:
332 return -ENODEV;
333 }
334
335 /* The SSP clock must be disabled when changing SSP clock mode
336 * on PXA2xx. On PXA3xx it must be enabled when doing so. */
337 if (!cpu_is_pxa3xx())
338 clk_disable(priv->dev.ssp->clk);
339 val = ssp_read_reg(ssp, SSCR0) | sscr0;
340 ssp_write_reg(ssp, SSCR0, val);
341 if (!cpu_is_pxa3xx())
342 clk_enable(priv->dev.ssp->clk);
343
344 return 0;
345}
346
347/*
348 * Set the SSP clock dividers.
349 */
350static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
351 int div_id, int div)
352{
353 struct ssp_priv *priv = cpu_dai->private_data;
354 struct ssp_device *ssp = priv->dev.ssp;
355 int val;
356
357 switch (div_id) {
358 case PXA_SSP_AUDIO_DIV_ACDS:
359 val = (ssp_read_reg(ssp, SSACD) & ~0x7) | SSACD_ACDS(div);
360 ssp_write_reg(ssp, SSACD, val);
361 break;
362 case PXA_SSP_AUDIO_DIV_SCDB:
363 val = ssp_read_reg(ssp, SSACD);
364 val &= ~SSACD_SCDB;
365#if defined(CONFIG_PXA3xx)
366 if (cpu_is_pxa3xx())
367 val &= ~SSACD_SCDX8;
368#endif
369 switch (div) {
370 case PXA_SSP_CLK_SCDB_1:
371 val |= SSACD_SCDB;
372 break;
373 case PXA_SSP_CLK_SCDB_4:
374 break;
375#if defined(CONFIG_PXA3xx)
376 case PXA_SSP_CLK_SCDB_8:
377 if (cpu_is_pxa3xx())
378 val |= SSACD_SCDX8;
379 else
380 return -EINVAL;
381 break;
382#endif
383 default:
384 return -EINVAL;
385 }
386 ssp_write_reg(ssp, SSACD, val);
387 break;
388 case PXA_SSP_DIV_SCR:
389 ssp_set_scr(&priv->dev, div);
390 break;
391 default:
392 return -ENODEV;
393 }
394
395 return 0;
396}
397
398/*
399 * Configure the PLL frequency pxa27x and (afaik - pxa320 only)
400 */
401static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai,
402 int pll_id, unsigned int freq_in, unsigned int freq_out)
403{
404 struct ssp_priv *priv = cpu_dai->private_data;
405 struct ssp_device *ssp = priv->dev.ssp;
406 u32 ssacd = ssp_read_reg(ssp, SSACD) & ~0x70;
407
408#if defined(CONFIG_PXA3xx)
409 if (cpu_is_pxa3xx())
410 ssp_write_reg(ssp, SSACDD, 0);
411#endif
412
413 switch (freq_out) {
414 case 5622000:
415 break;
416 case 11345000:
417 ssacd |= (0x1 << 4);
418 break;
419 case 12235000:
420 ssacd |= (0x2 << 4);
421 break;
422 case 14857000:
423 ssacd |= (0x3 << 4);
424 break;
425 case 32842000:
426 ssacd |= (0x4 << 4);
427 break;
428 case 48000000:
429 ssacd |= (0x5 << 4);
430 break;
431 case 0:
432 /* Disable */
433 break;
434
435 default:
436#ifdef CONFIG_PXA3xx
437 /* PXA3xx has a clock ditherer which can be used to generate
438 * a wider range of frequencies - calculate a value for it.
439 */
440 if (cpu_is_pxa3xx()) {
441 u32 val;
442 u64 tmp = 19968;
443 tmp *= 1000000;
444 do_div(tmp, freq_out);
445 val = tmp;
446
447 val = (val << 16) | 64;;
448 ssp_write_reg(ssp, SSACDD, val);
449
450 ssacd |= (0x6 << 4);
451
452 dev_dbg(&ssp->pdev->dev,
453 "Using SSACDD %x to supply %dHz\n",
454 val, freq_out);
455 break;
456 }
457#endif
458
459 return -EINVAL;
460 }
461
462 ssp_write_reg(ssp, SSACD, ssacd);
463
464 return 0;
465}
466
467/*
468 * Set the active slots in TDM/Network mode
469 */
470static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
471 unsigned int mask, int slots)
472{
473 struct ssp_priv *priv = cpu_dai->private_data;
474 struct ssp_device *ssp = priv->dev.ssp;
475 u32 sscr0;
476
477 sscr0 = ssp_read_reg(ssp, SSCR0) & ~SSCR0_SlotsPerFrm(7);
478
479 /* set number of active slots */
480 sscr0 |= SSCR0_SlotsPerFrm(slots);
481 ssp_write_reg(ssp, SSCR0, sscr0);
482
483 /* set active slot mask */
484 ssp_write_reg(ssp, SSTSA, mask);
485 ssp_write_reg(ssp, SSRSA, mask);
486 return 0;
487}
488
489/*
490 * Tristate the SSP DAI lines
491 */
492static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai,
493 int tristate)
494{
495 struct ssp_priv *priv = cpu_dai->private_data;
496 struct ssp_device *ssp = priv->dev.ssp;
497 u32 sscr1;
498
499 sscr1 = ssp_read_reg(ssp, SSCR1);
500 if (tristate)
501 sscr1 &= ~SSCR1_TTE;
502 else
503 sscr1 |= SSCR1_TTE;
504 ssp_write_reg(ssp, SSCR1, sscr1);
505
506 return 0;
507}
508
509/*
510 * Set up the SSP DAI format.
511 * The SSP Port must be inactive before calling this function as the
512 * physical interface format is changed.
513 */
514static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
515 unsigned int fmt)
516{
517 struct ssp_priv *priv = cpu_dai->private_data;
518 struct ssp_device *ssp = priv->dev.ssp;
519 u32 sscr0;
520 u32 sscr1;
521 u32 sspsp;
522
523 /* reset port settings */
524 sscr0 = ssp_read_reg(ssp, SSCR0) &
525 (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ADC);
526 sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7);
527 sspsp = 0;
528
529 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
530 case SND_SOC_DAIFMT_CBM_CFM:
531 sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR;
532 break;
533 case SND_SOC_DAIFMT_CBM_CFS:
534 sscr1 |= SSCR1_SCLKDIR;
535 break;
536 case SND_SOC_DAIFMT_CBS_CFS:
537 break;
538 default:
539 return -EINVAL;
540 }
541
542 ssp_write_reg(ssp, SSCR0, sscr0);
543 ssp_write_reg(ssp, SSCR1, sscr1);
544 ssp_write_reg(ssp, SSPSP, sspsp);
545
546 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
547 case SND_SOC_DAIFMT_I2S:
548 sscr0 |= SSCR0_MOD | SSCR0_PSP;
549 sscr1 |= SSCR1_RWOT | SSCR1_TRAIL;
550
551 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
552 case SND_SOC_DAIFMT_NB_NF:
553 sspsp |= SSPSP_FSRT;
554 break;
555 case SND_SOC_DAIFMT_NB_IF:
556 sspsp |= SSPSP_SFRMP | SSPSP_FSRT;
557 break;
558 case SND_SOC_DAIFMT_IB_IF:
559 sspsp |= SSPSP_SFRMP;
560 break;
561 default:
562 return -EINVAL;
563 }
564 break;
565
566 case SND_SOC_DAIFMT_DSP_A:
567 sspsp |= SSPSP_FSRT;
568 case SND_SOC_DAIFMT_DSP_B:
569 sscr0 |= SSCR0_MOD | SSCR0_PSP;
570 sscr1 |= SSCR1_TRAIL | SSCR1_RWOT;
571
572 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
573 case SND_SOC_DAIFMT_NB_NF:
574 sspsp |= SSPSP_SFRMP;
575 break;
576 case SND_SOC_DAIFMT_IB_IF:
577 break;
578 default:
579 return -EINVAL;
580 }
581 break;
582
583 default:
584 return -EINVAL;
585 }
586
587 ssp_write_reg(ssp, SSCR0, sscr0);
588 ssp_write_reg(ssp, SSCR1, sscr1);
589 ssp_write_reg(ssp, SSPSP, sspsp);
590
591 dump_registers(ssp);
592
593 /* Since we are configuring the timings for the format by hand
594 * we have to defer some things until hw_params() where we
595 * know parameters like the sample size.
596 */
597 priv->dai_fmt = fmt;
598
599 return 0;
600}
601
602/*
603 * Set the SSP audio DMA parameters and sample size.
604 * Can be called multiple times by oss emulation.
605 */
606static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
607 struct snd_pcm_hw_params *params,
608 struct snd_soc_dai *dai)
609{
610 struct snd_soc_pcm_runtime *rtd = substream->private_data;
611 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
612 struct ssp_priv *priv = cpu_dai->private_data;
613 struct ssp_device *ssp = priv->dev.ssp;
614 int dma = 0, chn = params_channels(params);
615 u32 sscr0;
616 u32 sspsp;
617 int width = snd_pcm_format_physical_width(params_format(params));
618
619 /* select correct DMA params */
620 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
621 dma = 1; /* capture DMA offset is 1,3 */
622 if (chn == 2)
623 dma += 2; /* stereo DMA offset is 2, mono is 0 */
624 cpu_dai->dma_data = ssp_dma_params[cpu_dai->id][dma];
625
626 dev_dbg(&ssp->pdev->dev, "pxa_ssp_hw_params: dma %d\n", dma);
627
628 /* we can only change the settings if the port is not in use */
629 if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)
630 return 0;
631
632 /* clear selected SSP bits */
633 sscr0 = ssp_read_reg(ssp, SSCR0) & ~(SSCR0_DSS | SSCR0_EDSS);
634 ssp_write_reg(ssp, SSCR0, sscr0);
635
636 /* bit size */
637 sscr0 = ssp_read_reg(ssp, SSCR0);
638 switch (params_format(params)) {
639 case SNDRV_PCM_FORMAT_S16_LE:
640#ifdef CONFIG_PXA3xx
641 if (cpu_is_pxa3xx())
642 sscr0 |= SSCR0_FPCKE;
643#endif
644 sscr0 |= SSCR0_DataSize(16);
645 if (params_channels(params) > 1)
646 sscr0 |= SSCR0_EDSS;
647 break;
648 case SNDRV_PCM_FORMAT_S24_LE:
649 sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8));
650 /* we must be in network mode (2 slots) for 24 bit stereo */
651 break;
652 case SNDRV_PCM_FORMAT_S32_LE:
653 sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16));
654 /* we must be in network mode (2 slots) for 32 bit stereo */
655 break;
656 }
657 ssp_write_reg(ssp, SSCR0, sscr0);
658
659 switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
660 case SND_SOC_DAIFMT_I2S:
661 /* Cleared when the DAI format is set */
662 sspsp = ssp_read_reg(ssp, SSPSP) | SSPSP_SFRMWDTH(width);
663 ssp_write_reg(ssp, SSPSP, sspsp);
664 break;
665 default:
666 break;
667 }
668
669 /* We always use a network mode so we always require TDM slots
670 * - complain loudly and fail if they've not been set up yet.
671 */
672 if (!(ssp_read_reg(ssp, SSTSA) & 0xf)) {
673 dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n");
674 return -EINVAL;
675 }
676
677 dump_registers(ssp);
678
679 return 0;
680}
681
682static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
683 struct snd_soc_dai *dai)
684{
685 struct snd_soc_pcm_runtime *rtd = substream->private_data;
686 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
687 int ret = 0;
688 struct ssp_priv *priv = cpu_dai->private_data;
689 struct ssp_device *ssp = priv->dev.ssp;
690 int val;
691
692 switch (cmd) {
693 case SNDRV_PCM_TRIGGER_RESUME:
694 ssp_enable(&priv->dev);
695 break;
696 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
697 val = ssp_read_reg(ssp, SSCR1);
698 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
699 val |= SSCR1_TSRE;
700 else
701 val |= SSCR1_RSRE;
702 ssp_write_reg(ssp, SSCR1, val);
703 val = ssp_read_reg(ssp, SSSR);
704 ssp_write_reg(ssp, SSSR, val);
705 break;
706 case SNDRV_PCM_TRIGGER_START:
707 val = ssp_read_reg(ssp, SSCR1);
708 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
709 val |= SSCR1_TSRE;
710 else
711 val |= SSCR1_RSRE;
712 ssp_write_reg(ssp, SSCR1, val);
713 ssp_enable(&priv->dev);
714 break;
715 case SNDRV_PCM_TRIGGER_STOP:
716 val = ssp_read_reg(ssp, SSCR1);
717 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
718 val &= ~SSCR1_TSRE;
719 else
720 val &= ~SSCR1_RSRE;
721 ssp_write_reg(ssp, SSCR1, val);
722 break;
723 case SNDRV_PCM_TRIGGER_SUSPEND:
724 ssp_disable(&priv->dev);
725 break;
726 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
727 val = ssp_read_reg(ssp, SSCR1);
728 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
729 val &= ~SSCR1_TSRE;
730 else
731 val &= ~SSCR1_RSRE;
732 ssp_write_reg(ssp, SSCR1, val);
733 break;
734
735 default:
736 ret = -EINVAL;
737 }
738
739 dump_registers(ssp);
740
741 return ret;
742}
743
744static int pxa_ssp_probe(struct platform_device *pdev,
745 struct snd_soc_dai *dai)
746{
747 struct ssp_priv *priv;
748 int ret;
749
750 priv = kzalloc(sizeof(struct ssp_priv), GFP_KERNEL);
751 if (!priv)
752 return -ENOMEM;
753
754 priv->dev.ssp = ssp_request(dai->id, "SoC audio");
755 if (priv->dev.ssp == NULL) {
756 ret = -ENODEV;
757 goto err_priv;
758 }
759
760 dai->private_data = priv;
761
762 return 0;
763
764err_priv:
765 kfree(priv);
766 return ret;
767}
768
769static void pxa_ssp_remove(struct platform_device *pdev,
770 struct snd_soc_dai *dai)
771{
772 struct ssp_priv *priv = dai->private_data;
773 ssp_free(priv->dev.ssp);
774}
775
776#define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
777 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
778 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
779 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
780
781#define PXA_SSP_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
782 SNDRV_PCM_FMTBIT_S24_LE | \
783 SNDRV_PCM_FMTBIT_S32_LE)
784
785struct snd_soc_dai pxa_ssp_dai[] = {
786 {
787 .name = "pxa2xx-ssp1",
788 .id = 0,
789 .probe = pxa_ssp_probe,
790 .remove = pxa_ssp_remove,
791 .suspend = pxa_ssp_suspend,
792 .resume = pxa_ssp_resume,
793 .playback = {
794 .channels_min = 1,
795 .channels_max = 2,
796 .rates = PXA_SSP_RATES,
797 .formats = PXA_SSP_FORMATS,
798 },
799 .capture = {
800 .channels_min = 1,
801 .channels_max = 2,
802 .rates = PXA_SSP_RATES,
803 .formats = PXA_SSP_FORMATS,
804 },
805 .ops = {
806 .startup = pxa_ssp_startup,
807 .shutdown = pxa_ssp_shutdown,
808 .trigger = pxa_ssp_trigger,
809 .hw_params = pxa_ssp_hw_params,
810 .set_sysclk = pxa_ssp_set_dai_sysclk,
811 .set_clkdiv = pxa_ssp_set_dai_clkdiv,
812 .set_pll = pxa_ssp_set_dai_pll,
813 .set_fmt = pxa_ssp_set_dai_fmt,
814 .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
815 .set_tristate = pxa_ssp_set_dai_tristate,
816 },
817 },
818 { .name = "pxa2xx-ssp2",
819 .id = 1,
820 .probe = pxa_ssp_probe,
821 .remove = pxa_ssp_remove,
822 .suspend = pxa_ssp_suspend,
823 .resume = pxa_ssp_resume,
824 .playback = {
825 .channels_min = 1,
826 .channels_max = 2,
827 .rates = PXA_SSP_RATES,
828 .formats = PXA_SSP_FORMATS,
829 },
830 .capture = {
831 .channels_min = 1,
832 .channels_max = 2,
833 .rates = PXA_SSP_RATES,
834 .formats = PXA_SSP_FORMATS,
835 },
836 .ops = {
837 .startup = pxa_ssp_startup,
838 .shutdown = pxa_ssp_shutdown,
839 .trigger = pxa_ssp_trigger,
840 .hw_params = pxa_ssp_hw_params,
841 .set_sysclk = pxa_ssp_set_dai_sysclk,
842 .set_clkdiv = pxa_ssp_set_dai_clkdiv,
843 .set_pll = pxa_ssp_set_dai_pll,
844 .set_fmt = pxa_ssp_set_dai_fmt,
845 .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
846 .set_tristate = pxa_ssp_set_dai_tristate,
847 },
848 },
849 {
850 .name = "pxa2xx-ssp3",
851 .id = 2,
852 .probe = pxa_ssp_probe,
853 .remove = pxa_ssp_remove,
854 .suspend = pxa_ssp_suspend,
855 .resume = pxa_ssp_resume,
856 .playback = {
857 .channels_min = 1,
858 .channels_max = 2,
859 .rates = PXA_SSP_RATES,
860 .formats = PXA_SSP_FORMATS,
861 },
862 .capture = {
863 .channels_min = 1,
864 .channels_max = 2,
865 .rates = PXA_SSP_RATES,
866 .formats = PXA_SSP_FORMATS,
867 },
868 .ops = {
869 .startup = pxa_ssp_startup,
870 .shutdown = pxa_ssp_shutdown,
871 .trigger = pxa_ssp_trigger,
872 .hw_params = pxa_ssp_hw_params,
873 .set_sysclk = pxa_ssp_set_dai_sysclk,
874 .set_clkdiv = pxa_ssp_set_dai_clkdiv,
875 .set_pll = pxa_ssp_set_dai_pll,
876 .set_fmt = pxa_ssp_set_dai_fmt,
877 .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
878 .set_tristate = pxa_ssp_set_dai_tristate,
879 },
880 },
881 {
882 .name = "pxa2xx-ssp4",
883 .id = 3,
884 .probe = pxa_ssp_probe,
885 .remove = pxa_ssp_remove,
886 .suspend = pxa_ssp_suspend,
887 .resume = pxa_ssp_resume,
888 .playback = {
889 .channels_min = 1,
890 .channels_max = 2,
891 .rates = PXA_SSP_RATES,
892 .formats = PXA_SSP_FORMATS,
893 },
894 .capture = {
895 .channels_min = 1,
896 .channels_max = 2,
897 .rates = PXA_SSP_RATES,
898 .formats = PXA_SSP_FORMATS,
899 },
900 .ops = {
901 .startup = pxa_ssp_startup,
902 .shutdown = pxa_ssp_shutdown,
903 .trigger = pxa_ssp_trigger,
904 .hw_params = pxa_ssp_hw_params,
905 .set_sysclk = pxa_ssp_set_dai_sysclk,
906 .set_clkdiv = pxa_ssp_set_dai_clkdiv,
907 .set_pll = pxa_ssp_set_dai_pll,
908 .set_fmt = pxa_ssp_set_dai_fmt,
909 .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
910 .set_tristate = pxa_ssp_set_dai_tristate,
911 },
912 },
913};
914EXPORT_SYMBOL_GPL(pxa_ssp_dai);
915
916static int __init pxa_ssp_init(void)
917{
918 return snd_soc_register_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai));
919}
920module_init(pxa_ssp_init);
921
922static void __exit pxa_ssp_exit(void)
923{
924 snd_soc_unregister_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai));
925}
926module_exit(pxa_ssp_exit);
927
928/* Module information */
929MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
930MODULE_DESCRIPTION("PXA SSP/PCM SoC Interface");
931MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/pxa-ssp.h b/sound/soc/pxa/pxa-ssp.h
new file mode 100644
index 000000000000..91deadd55675
--- /dev/null
+++ b/sound/soc/pxa/pxa-ssp.h
@@ -0,0 +1,47 @@
1/*
2 * ASoC PXA SSP port support
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 version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _PXA_SSP_H
10#define _PXA_SSP_H
11
12/* pxa DAI SSP IDs */
13#define PXA_DAI_SSP1 0
14#define PXA_DAI_SSP2 1
15#define PXA_DAI_SSP3 2
16#define PXA_DAI_SSP4 3
17
18/* SSP clock sources */
19#define PXA_SSP_CLK_PLL 0
20#define PXA_SSP_CLK_EXT 1
21#define PXA_SSP_CLK_NET 2
22#define PXA_SSP_CLK_AUDIO 3
23#define PXA_SSP_CLK_NET_PLL 4
24
25/* SSP audio dividers */
26#define PXA_SSP_AUDIO_DIV_ACDS 0
27#define PXA_SSP_AUDIO_DIV_SCDB 1
28#define PXA_SSP_DIV_SCR 2
29
30/* SSP ACDS audio dividers values */
31#define PXA_SSP_CLK_AUDIO_DIV_1 0
32#define PXA_SSP_CLK_AUDIO_DIV_2 1
33#define PXA_SSP_CLK_AUDIO_DIV_4 2
34#define PXA_SSP_CLK_AUDIO_DIV_8 3
35#define PXA_SSP_CLK_AUDIO_DIV_16 4
36#define PXA_SSP_CLK_AUDIO_DIV_32 5
37
38/* SSP divider bypass */
39#define PXA_SSP_CLK_SCDB_4 0
40#define PXA_SSP_CLK_SCDB_1 1
41#define PXA_SSP_CLK_SCDB_8 2
42
43#define PXA_SSP_PLL_OUT 0
44
45extern struct snd_soc_dai pxa_ssp_dai[4];
46
47#endif
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index a7a3a9c5c6ff..780db6757ad2 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -87,14 +87,12 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = {
87}; 87};
88 88
89#ifdef CONFIG_PM 89#ifdef CONFIG_PM
90static int pxa2xx_ac97_suspend(struct platform_device *pdev, 90static int pxa2xx_ac97_suspend(struct snd_soc_dai *dai)
91 struct snd_soc_dai *dai)
92{ 91{
93 return pxa2xx_ac97_hw_suspend(); 92 return pxa2xx_ac97_hw_suspend();
94} 93}
95 94
96static int pxa2xx_ac97_resume(struct platform_device *pdev, 95static int pxa2xx_ac97_resume(struct snd_soc_dai *dai)
97 struct snd_soc_dai *dai)
98{ 96{
99 return pxa2xx_ac97_hw_resume(); 97 return pxa2xx_ac97_hw_resume();
100} 98}
@@ -117,7 +115,8 @@ static void pxa2xx_ac97_remove(struct platform_device *pdev,
117} 115}
118 116
119static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, 117static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
120 struct snd_pcm_hw_params *params) 118 struct snd_pcm_hw_params *params,
119 struct snd_soc_dai *dai)
121{ 120{
122 struct snd_soc_pcm_runtime *rtd = substream->private_data; 121 struct snd_soc_pcm_runtime *rtd = substream->private_data;
123 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 122 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -131,7 +130,8 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
131} 130}
132 131
133static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream, 132static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
134 struct snd_pcm_hw_params *params) 133 struct snd_pcm_hw_params *params,
134 struct snd_soc_dai *dai)
135{ 135{
136 struct snd_soc_pcm_runtime *rtd = substream->private_data; 136 struct snd_soc_pcm_runtime *rtd = substream->private_data;
137 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 137 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -145,7 +145,8 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
145} 145}
146 146
147static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream, 147static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
148 struct snd_pcm_hw_params *params) 148 struct snd_pcm_hw_params *params,
149 struct snd_soc_dai *dai)
149{ 150{
150 struct snd_soc_pcm_runtime *rtd = substream->private_data; 151 struct snd_soc_pcm_runtime *rtd = substream->private_data;
151 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 152 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -170,7 +171,7 @@ struct snd_soc_dai pxa_ac97_dai[] = {
170{ 171{
171 .name = "pxa2xx-ac97", 172 .name = "pxa2xx-ac97",
172 .id = 0, 173 .id = 0,
173 .type = SND_SOC_DAI_AC97, 174 .ac97_control = 1,
174 .probe = pxa2xx_ac97_probe, 175 .probe = pxa2xx_ac97_probe,
175 .remove = pxa2xx_ac97_remove, 176 .remove = pxa2xx_ac97_remove,
176 .suspend = pxa2xx_ac97_suspend, 177 .suspend = pxa2xx_ac97_suspend,
@@ -193,7 +194,7 @@ struct snd_soc_dai pxa_ac97_dai[] = {
193{ 194{
194 .name = "pxa2xx-ac97-aux", 195 .name = "pxa2xx-ac97-aux",
195 .id = 1, 196 .id = 1,
196 .type = SND_SOC_DAI_AC97, 197 .ac97_control = 1,
197 .playback = { 198 .playback = {
198 .stream_name = "AC97 Aux Playback", 199 .stream_name = "AC97 Aux Playback",
199 .channels_min = 1, 200 .channels_min = 1,
@@ -212,7 +213,7 @@ struct snd_soc_dai pxa_ac97_dai[] = {
212{ 213{
213 .name = "pxa2xx-ac97-mic", 214 .name = "pxa2xx-ac97-mic",
214 .id = 2, 215 .id = 2,
215 .type = SND_SOC_DAI_AC97, 216 .ac97_control = 1,
216 .capture = { 217 .capture = {
217 .stream_name = "AC97 Mic Capture", 218 .stream_name = "AC97 Mic Capture",
218 .channels_min = 1, 219 .channels_min = 1,
@@ -227,6 +228,18 @@ struct snd_soc_dai pxa_ac97_dai[] = {
227EXPORT_SYMBOL_GPL(pxa_ac97_dai); 228EXPORT_SYMBOL_GPL(pxa_ac97_dai);
228EXPORT_SYMBOL_GPL(soc_ac97_ops); 229EXPORT_SYMBOL_GPL(soc_ac97_ops);
229 230
231static int __init pxa_ac97_init(void)
232{
233 return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai));
234}
235module_init(pxa_ac97_init);
236
237static void __exit pxa_ac97_exit(void)
238{
239 snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai));
240}
241module_exit(pxa_ac97_exit);
242
230MODULE_AUTHOR("Nicolas Pitre"); 243MODULE_AUTHOR("Nicolas Pitre");
231MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip"); 244MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
232MODULE_LICENSE("GPL"); 245MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index e758034db5c3..517991fb1099 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -121,7 +121,8 @@ static struct pxa2xx_gpio gpio_bus[] = {
121 }, 121 },
122}; 122};
123 123
124static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream) 124static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream,
125 struct snd_soc_dai *dai)
125{ 126{
126 struct snd_soc_pcm_runtime *rtd = substream->private_data; 127 struct snd_soc_pcm_runtime *rtd = substream->private_data;
127 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 128 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -187,7 +188,8 @@ static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
187} 188}
188 189
189static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, 190static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
190 struct snd_pcm_hw_params *params) 191 struct snd_pcm_hw_params *params,
192 struct snd_soc_dai *dai)
191{ 193{
192 struct snd_soc_pcm_runtime *rtd = substream->private_data; 194 struct snd_soc_pcm_runtime *rtd = substream->private_data;
193 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 195 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -248,7 +250,8 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
248 return 0; 250 return 0;
249} 251}
250 252
251static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd) 253static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
254 struct snd_soc_dai *dai)
252{ 255{
253 int ret = 0; 256 int ret = 0;
254 257
@@ -269,7 +272,8 @@ static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
269 return ret; 272 return ret;
270} 273}
271 274
272static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream) 275static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream,
276 struct snd_soc_dai *dai)
273{ 277{
274 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 278 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
275 SACR1 |= SACR1_DRPL; 279 SACR1 |= SACR1_DRPL;
@@ -289,8 +293,7 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream)
289} 293}
290 294
291#ifdef CONFIG_PM 295#ifdef CONFIG_PM
292static int pxa2xx_i2s_suspend(struct platform_device *dev, 296static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai)
293 struct snd_soc_dai *dai)
294{ 297{
295 if (!dai->active) 298 if (!dai->active)
296 return 0; 299 return 0;
@@ -307,8 +310,7 @@ static int pxa2xx_i2s_suspend(struct platform_device *dev,
307 return 0; 310 return 0;
308} 311}
309 312
310static int pxa2xx_i2s_resume(struct platform_device *pdev, 313static int pxa2xx_i2s_resume(struct snd_soc_dai *dai)
311 struct snd_soc_dai *dai)
312{ 314{
313 if (!dai->active) 315 if (!dai->active)
314 return 0; 316 return 0;
@@ -336,7 +338,6 @@ static int pxa2xx_i2s_resume(struct platform_device *pdev,
336struct snd_soc_dai pxa_i2s_dai = { 338struct snd_soc_dai pxa_i2s_dai = {
337 .name = "pxa2xx-i2s", 339 .name = "pxa2xx-i2s",
338 .id = 0, 340 .id = 0,
339 .type = SND_SOC_DAI_I2S,
340 .suspend = pxa2xx_i2s_suspend, 341 .suspend = pxa2xx_i2s_suspend,
341 .resume = pxa2xx_i2s_resume, 342 .resume = pxa2xx_i2s_resume,
342 .playback = { 343 .playback = {
@@ -353,8 +354,7 @@ struct snd_soc_dai pxa_i2s_dai = {
353 .startup = pxa2xx_i2s_startup, 354 .startup = pxa2xx_i2s_startup,
354 .shutdown = pxa2xx_i2s_shutdown, 355 .shutdown = pxa2xx_i2s_shutdown,
355 .trigger = pxa2xx_i2s_trigger, 356 .trigger = pxa2xx_i2s_trigger,
356 .hw_params = pxa2xx_i2s_hw_params,}, 357 .hw_params = pxa2xx_i2s_hw_params,
357 .dai_ops = {
358 .set_fmt = pxa2xx_i2s_set_dai_fmt, 358 .set_fmt = pxa2xx_i2s_set_dai_fmt,
359 .set_sysclk = pxa2xx_i2s_set_dai_sysclk, 359 .set_sysclk = pxa2xx_i2s_set_dai_sysclk,
360 }, 360 },
@@ -364,12 +364,23 @@ EXPORT_SYMBOL_GPL(pxa_i2s_dai);
364 364
365static int pxa2xx_i2s_probe(struct platform_device *dev) 365static int pxa2xx_i2s_probe(struct platform_device *dev)
366{ 366{
367 int ret;
368
367 clk_i2s = clk_get(&dev->dev, "I2SCLK"); 369 clk_i2s = clk_get(&dev->dev, "I2SCLK");
368 return IS_ERR(clk_i2s) ? PTR_ERR(clk_i2s) : 0; 370 if (IS_ERR(clk_i2s))
371 return PTR_ERR(clk_i2s);
372
373 pxa_i2s_dai.dev = &dev->dev;
374 ret = snd_soc_register_dai(&pxa_i2s_dai);
375 if (ret != 0)
376 clk_put(clk_i2s);
377
378 return ret;
369} 379}
370 380
371static int __devexit pxa2xx_i2s_remove(struct platform_device *dev) 381static int __devexit pxa2xx_i2s_remove(struct platform_device *dev)
372{ 382{
383 snd_soc_unregister_dai(&pxa_i2s_dai);
373 clk_put(clk_i2s); 384 clk_put(clk_i2s);
374 clk_i2s = ERR_PTR(-ENOENT); 385 clk_i2s = ERR_PTR(-ENOENT);
375 return 0; 386 return 0;
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index afcd892cd2fa..c670d08e7c9e 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -69,7 +69,7 @@ static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
69 return 0; 69 return 0;
70} 70}
71 71
72struct snd_pcm_ops pxa2xx_pcm_ops = { 72static struct snd_pcm_ops pxa2xx_pcm_ops = {
73 .open = __pxa2xx_pcm_open, 73 .open = __pxa2xx_pcm_open,
74 .close = __pxa2xx_pcm_close, 74 .close = __pxa2xx_pcm_close,
75 .ioctl = snd_pcm_lib_ioctl, 75 .ioctl = snd_pcm_lib_ioctl,
@@ -118,6 +118,18 @@ struct snd_soc_platform pxa2xx_soc_platform = {
118}; 118};
119EXPORT_SYMBOL_GPL(pxa2xx_soc_platform); 119EXPORT_SYMBOL_GPL(pxa2xx_soc_platform);
120 120
121static int __init pxa2xx_soc_platform_init(void)
122{
123 return snd_soc_register_platform(&pxa2xx_soc_platform);
124}
125module_init(pxa2xx_soc_platform_init);
126
127static void __exit pxa2xx_soc_platform_exit(void)
128{
129 snd_soc_unregister_platform(&pxa2xx_soc_platform);
130}
131module_exit(pxa2xx_soc_platform_exit);
132
121MODULE_AUTHOR("Nicolas Pitre"); 133MODULE_AUTHOR("Nicolas Pitre");
122MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module"); 134MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
123MODULE_LICENSE("GPL"); 135MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index d307b6757e95..a3b9e6bdf979 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -319,8 +319,9 @@ static struct snd_soc_dai_link spitz_dai = {
319}; 319};
320 320
321/* spitz audio machine driver */ 321/* spitz audio machine driver */
322static struct snd_soc_machine snd_soc_machine_spitz = { 322static struct snd_soc_card snd_soc_spitz = {
323 .name = "Spitz", 323 .name = "Spitz",
324 .platform = &pxa2xx_soc_platform,
324 .dai_link = &spitz_dai, 325 .dai_link = &spitz_dai,
325 .num_links = 1, 326 .num_links = 1,
326}; 327};
@@ -333,8 +334,7 @@ static struct wm8750_setup_data spitz_wm8750_setup = {
333 334
334/* spitz audio subsystem */ 335/* spitz audio subsystem */
335static struct snd_soc_device spitz_snd_devdata = { 336static struct snd_soc_device spitz_snd_devdata = {
336 .machine = &snd_soc_machine_spitz, 337 .card = &snd_soc_spitz,
337 .platform = &pxa2xx_soc_platform,
338 .codec_dev = &soc_codec_dev_wm8750, 338 .codec_dev = &soc_codec_dev_wm8750,
339 .codec_data = &spitz_wm8750_setup, 339 .codec_data = &spitz_wm8750_setup,
340}; 340};
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index afefe41b8c46..c77194f74c9b 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -38,7 +38,7 @@
38#include "pxa2xx-pcm.h" 38#include "pxa2xx-pcm.h"
39#include "pxa2xx-ac97.h" 39#include "pxa2xx-ac97.h"
40 40
41static struct snd_soc_machine tosa; 41static struct snd_soc_card tosa;
42 42
43#define TOSA_HP 0 43#define TOSA_HP 0
44#define TOSA_MIC_INT 1 44#define TOSA_MIC_INT 1
@@ -230,15 +230,37 @@ static struct snd_soc_dai_link tosa_dai[] = {
230}, 230},
231}; 231};
232 232
233static struct snd_soc_machine tosa = { 233static int tosa_probe(struct platform_device *dev)
234{
235 int ret;
236
237 ret = gpio_request(TOSA_GPIO_L_MUTE, "Headphone Jack");
238 if (ret)
239 return ret;
240 ret = gpio_direction_output(TOSA_GPIO_L_MUTE, 0);
241 if (ret)
242 gpio_free(TOSA_GPIO_L_MUTE);
243
244 return ret;
245}
246
247static int tosa_remove(struct platform_device *dev)
248{
249 gpio_free(TOSA_GPIO_L_MUTE);
250 return 0;
251}
252
253static struct snd_soc_card tosa = {
234 .name = "Tosa", 254 .name = "Tosa",
255 .platform = &pxa2xx_soc_platform,
235 .dai_link = tosa_dai, 256 .dai_link = tosa_dai,
236 .num_links = ARRAY_SIZE(tosa_dai), 257 .num_links = ARRAY_SIZE(tosa_dai),
258 .probe = tosa_probe,
259 .remove = tosa_remove,
237}; 260};
238 261
239static struct snd_soc_device tosa_snd_devdata = { 262static struct snd_soc_device tosa_snd_devdata = {
240 .machine = &tosa, 263 .card = &tosa,
241 .platform = &pxa2xx_soc_platform,
242 .codec_dev = &soc_codec_dev_wm9712, 264 .codec_dev = &soc_codec_dev_wm9712,
243}; 265};
244 266
@@ -251,11 +273,6 @@ static int __init tosa_init(void)
251 if (!machine_is_tosa()) 273 if (!machine_is_tosa())
252 return -ENODEV; 274 return -ENODEV;
253 275
254 ret = gpio_request(TOSA_GPIO_L_MUTE, "Headphone Jack");
255 if (ret)
256 return ret;
257 gpio_direction_output(TOSA_GPIO_L_MUTE, 0);
258
259 tosa_snd_device = platform_device_alloc("soc-audio", -1); 276 tosa_snd_device = platform_device_alloc("soc-audio", -1);
260 if (!tosa_snd_device) { 277 if (!tosa_snd_device) {
261 ret = -ENOMEM; 278 ret = -ENOMEM;
@@ -272,15 +289,12 @@ static int __init tosa_init(void)
272 platform_device_put(tosa_snd_device); 289 platform_device_put(tosa_snd_device);
273 290
274err_alloc: 291err_alloc:
275 gpio_free(TOSA_GPIO_L_MUTE);
276
277 return ret; 292 return ret;
278} 293}
279 294
280static void __exit tosa_exit(void) 295static void __exit tosa_exit(void)
281{ 296{
282 platform_device_unregister(tosa_snd_device); 297 platform_device_unregister(tosa_snd_device);
283 gpio_free(TOSA_GPIO_L_MUTE);
284} 298}
285 299
286module_init(tosa_init); 300module_init(tosa_init);
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c
new file mode 100644
index 000000000000..f8e9ecd589d3
--- /dev/null
+++ b/sound/soc/pxa/zylonite.c
@@ -0,0 +1,219 @@
1/*
2 * zylonite.c -- SoC audio for Zylonite
3 *
4 * Copyright 2008 Wolfson Microelectronics PLC.
5 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/device.h>
17#include <linux/i2c.h>
18#include <sound/core.h>
19#include <sound/pcm.h>
20#include <sound/pcm_params.h>
21#include <sound/soc.h>
22#include <sound/soc-dapm.h>
23
24#include "../codecs/wm9713.h"
25#include "pxa2xx-pcm.h"
26#include "pxa2xx-ac97.h"
27#include "pxa-ssp.h"
28
29static struct snd_soc_card zylonite;
30
31static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = {
32 SND_SOC_DAPM_HP("Headphone", NULL),
33 SND_SOC_DAPM_MIC("Headset Microphone", NULL),
34 SND_SOC_DAPM_MIC("Handset Microphone", NULL),
35 SND_SOC_DAPM_SPK("Multiactor", NULL),
36 SND_SOC_DAPM_SPK("Headset Earpiece", NULL),
37};
38
39/* Currently supported audio map */
40static const struct snd_soc_dapm_route audio_map[] = {
41
42 /* Headphone output connected to HPL/HPR */
43 { "Headphone", NULL, "HPL" },
44 { "Headphone", NULL, "HPR" },
45
46 /* On-board earpiece */
47 { "Headset Earpiece", NULL, "OUT3" },
48
49 /* Headphone mic */
50 { "MIC2A", NULL, "Mic Bias" },
51 { "Mic Bias", NULL, "Headset Microphone" },
52
53 /* On-board mic */
54 { "MIC1", NULL, "Mic Bias" },
55 { "Mic Bias", NULL, "Handset Microphone" },
56
57 /* Multiactor differentially connected over SPKL/SPKR */
58 { "Multiactor", NULL, "SPKL" },
59 { "Multiactor", NULL, "SPKR" },
60};
61
62static int zylonite_wm9713_init(struct snd_soc_codec *codec)
63{
64 /* Currently we only support use of the AC97 clock here. If
65 * CLK_POUT is selected by SW15 then the clock API will need
66 * to be used to request and enable it here.
67 */
68
69 snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets,
70 ARRAY_SIZE(zylonite_dapm_widgets));
71
72 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
73
74 /* Static setup for now */
75 snd_soc_dapm_enable_pin(codec, "Headphone");
76 snd_soc_dapm_enable_pin(codec, "Headset Earpiece");
77
78 snd_soc_dapm_sync(codec);
79 return 0;
80}
81
82static int zylonite_voice_hw_params(struct snd_pcm_substream *substream,
83 struct snd_pcm_hw_params *params)
84{
85 struct snd_soc_pcm_runtime *rtd = substream->private_data;
86 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
87 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
88 unsigned int pll_out = 0;
89 unsigned int acds = 0;
90 unsigned int wm9713_div = 0;
91 int ret = 0;
92
93 switch (params_rate(params)) {
94 case 8000:
95 wm9713_div = 12;
96 pll_out = 2048000;
97 break;
98 case 16000:
99 wm9713_div = 6;
100 pll_out = 4096000;
101 break;
102 case 48000:
103 default:
104 wm9713_div = 2;
105 pll_out = 12288000;
106 acds = 1;
107 break;
108 }
109
110 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
111 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
112 if (ret < 0)
113 return ret;
114
115 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
116 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
117 if (ret < 0)
118 return ret;
119
120 ret = snd_soc_dai_set_tdm_slot(cpu_dai,
121 params_channels(params),
122 params_channels(params));
123 if (ret < 0)
124 return ret;
125
126 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, pll_out);
127 if (ret < 0)
128 return ret;
129
130 ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds);
131 if (ret < 0)
132 return ret;
133
134 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1);
135 if (ret < 0)
136 return ret;
137
138 /* Note that if the PLL is in use the WM9713_PCMCLK_PLL_DIV needs
139 * to be set instead.
140 */
141 ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV,
142 WM9713_PCMDIV(wm9713_div));
143 if (ret < 0)
144 return ret;
145
146 return 0;
147}
148
149static struct snd_soc_ops zylonite_voice_ops = {
150 .hw_params = zylonite_voice_hw_params,
151};
152
153static struct snd_soc_dai_link zylonite_dai[] = {
154{
155 .name = "AC97",
156 .stream_name = "AC97 HiFi",
157 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
158 .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI],
159 .init = zylonite_wm9713_init,
160},
161{
162 .name = "AC97 Aux",
163 .stream_name = "AC97 Aux",
164 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
165 .codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX],
166},
167{
168 .name = "WM9713 Voice",
169 .stream_name = "WM9713 Voice",
170 .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP3],
171 .codec_dai = &wm9713_dai[WM9713_DAI_PCM_VOICE],
172 .ops = &zylonite_voice_ops,
173},
174};
175
176static struct snd_soc_card zylonite = {
177 .name = "Zylonite",
178 .platform = &pxa2xx_soc_platform,
179 .dai_link = zylonite_dai,
180 .num_links = ARRAY_SIZE(zylonite_dai),
181};
182
183static struct snd_soc_device zylonite_snd_ac97_devdata = {
184 .card = &zylonite,
185 .codec_dev = &soc_codec_dev_wm9713,
186};
187
188static struct platform_device *zylonite_snd_ac97_device;
189
190static int __init zylonite_init(void)
191{
192 int ret;
193
194 zylonite_snd_ac97_device = platform_device_alloc("soc-audio", -1);
195 if (!zylonite_snd_ac97_device)
196 return -ENOMEM;
197
198 platform_set_drvdata(zylonite_snd_ac97_device,
199 &zylonite_snd_ac97_devdata);
200 zylonite_snd_ac97_devdata.dev = &zylonite_snd_ac97_device->dev;
201
202 ret = platform_device_add(zylonite_snd_ac97_device);
203 if (ret != 0)
204 platform_device_put(zylonite_snd_ac97_device);
205
206 return ret;
207}
208
209static void __exit zylonite_exit(void)
210{
211 platform_device_unregister(zylonite_snd_ac97_device);
212}
213
214module_init(zylonite_init);
215module_exit(zylonite_exit);
216
217MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
218MODULE_DESCRIPTION("ALSA SoC WM9713 Zylonite");
219MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
index b9f2353effeb..fcd03acf10f6 100644
--- a/sound/soc/s3c24xx/Kconfig
+++ b/sound/soc/s3c24xx/Kconfig
@@ -44,3 +44,8 @@ config SND_S3C24XX_SOC_LN2440SBC_ALC650
44 Say Y if you want to add support for SoC audio on ln2440sbc 44 Say Y if you want to add support for SoC audio on ln2440sbc
45 with the ALC650. 45 with the ALC650.
46 46
47config SND_S3C24XX_SOC_S3C24XX_UDA134X
48 tristate "SoC I2S Audio support UDA134X wired to a S3C24XX"
49 depends on SND_S3C24XX_SOC
50 select SND_S3C24XX_SOC_I2S
51 select SND_SOC_UDA134X
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile
index 0aa5fb0b9700..96b3f3f617d4 100644
--- a/sound/soc/s3c24xx/Makefile
+++ b/sound/soc/s3c24xx/Makefile
@@ -13,7 +13,9 @@ obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o
13snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o 13snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o
14snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o 14snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o
15snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o 15snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o
16snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o
16 17
17obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o 18obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
18obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o 19obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o
19obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o 20obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o
21obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o
diff --git a/sound/soc/s3c24xx/ln2440sbc_alc650.c b/sound/soc/s3c24xx/ln2440sbc_alc650.c
index 4eab2c19c454..12c71482d258 100644
--- a/sound/soc/s3c24xx/ln2440sbc_alc650.c
+++ b/sound/soc/s3c24xx/ln2440sbc_alc650.c
@@ -27,7 +27,7 @@
27#include "s3c24xx-pcm.h" 27#include "s3c24xx-pcm.h"
28#include "s3c24xx-ac97.h" 28#include "s3c24xx-ac97.h"
29 29
30static struct snd_soc_machine ln2440sbc; 30static struct snd_soc_card ln2440sbc;
31 31
32static struct snd_soc_dai_link ln2440sbc_dai[] = { 32static struct snd_soc_dai_link ln2440sbc_dai[] = {
33{ 33{
@@ -38,15 +38,15 @@ static struct snd_soc_dai_link ln2440sbc_dai[] = {
38}, 38},
39}; 39};
40 40
41static struct snd_soc_machine ln2440sbc = { 41static struct snd_soc_card ln2440sbc = {
42 .name = "LN2440SBC", 42 .name = "LN2440SBC",
43 .platform = &s3c24xx_soc_platform,
43 .dai_link = ln2440sbc_dai, 44 .dai_link = ln2440sbc_dai,
44 .num_links = ARRAY_SIZE(ln2440sbc_dai), 45 .num_links = ARRAY_SIZE(ln2440sbc_dai),
45}; 46};
46 47
47static struct snd_soc_device ln2440sbc_snd_ac97_devdata = { 48static struct snd_soc_device ln2440sbc_snd_ac97_devdata = {
48 .machine = &ln2440sbc, 49 .card = &ln2440sbc,
49 .platform = &s3c24xx_soc_platform,
50 .codec_dev = &soc_codec_dev_ac97, 50 .codec_dev = &soc_codec_dev_ac97,
51}; 51};
52 52
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
index 87ddfefcc2fb..45bb12e8ea44 100644
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c
@@ -59,7 +59,7 @@
59#define NEO_CAPTURE_HEADSET 7 59#define NEO_CAPTURE_HEADSET 7
60#define NEO_CAPTURE_BLUETOOTH 8 60#define NEO_CAPTURE_BLUETOOTH 8
61 61
62static struct snd_soc_machine neo1973; 62static struct snd_soc_card neo1973;
63static struct i2c_client *i2c; 63static struct i2c_client *i2c;
64 64
65static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, 65static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
@@ -548,7 +548,6 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec)
548static struct snd_soc_dai bt_dai = { 548static struct snd_soc_dai bt_dai = {
549 .name = "Bluetooth", 549 .name = "Bluetooth",
550 .id = 0, 550 .id = 0,
551 .type = SND_SOC_DAI_PCM,
552 .playback = { 551 .playback = {
553 .channels_min = 1, 552 .channels_min = 1,
554 .channels_max = 1, 553 .channels_max = 1,
@@ -579,8 +578,9 @@ static struct snd_soc_dai_link neo1973_dai[] = {
579}, 578},
580}; 579};
581 580
582static struct snd_soc_machine neo1973 = { 581static struct snd_soc_card neo1973 = {
583 .name = "neo1973", 582 .name = "neo1973",
583 .platform = &s3c24xx_soc_platform,
584 .dai_link = neo1973_dai, 584 .dai_link = neo1973_dai,
585 .num_links = ARRAY_SIZE(neo1973_dai), 585 .num_links = ARRAY_SIZE(neo1973_dai),
586}; 586};
@@ -591,8 +591,7 @@ static struct wm8753_setup_data neo1973_wm8753_setup = {
591}; 591};
592 592
593static struct snd_soc_device neo1973_snd_devdata = { 593static struct snd_soc_device neo1973_snd_devdata = {
594 .machine = &neo1973, 594 .card = &neo1973,
595 .platform = &s3c24xx_soc_platform,
596 .codec_dev = &soc_codec_dev_wm8753, 595 .codec_dev = &soc_codec_dev_wm8753,
597 .codec_data = &neo1973_wm8753_setup, 596 .codec_data = &neo1973_wm8753_setup,
598}; 597};
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c
index ded7d995a922..f3fc0aba0aaf 100644
--- a/sound/soc/s3c24xx/s3c2412-i2s.c
+++ b/sound/soc/s3c24xx/s3c2412-i2s.c
@@ -343,7 +343,8 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
343} 343}
344 344
345static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, 345static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
346 struct snd_pcm_hw_params *params) 346 struct snd_pcm_hw_params *params,
347 struct snd_soc_dai *dai)
347{ 348{
348 struct snd_soc_pcm_runtime *rtd = substream->private_data; 349 struct snd_soc_pcm_runtime *rtd = substream->private_data;
349 u32 iismod; 350 u32 iismod;
@@ -373,7 +374,8 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
373 return 0; 374 return 0;
374} 375}
375 376
376static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd) 377static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
378 struct snd_soc_dai *dai)
377{ 379{
378 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); 380 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
379 unsigned long irqs; 381 unsigned long irqs;
@@ -647,8 +649,7 @@ static int s3c2412_i2s_probe(struct platform_device *pdev,
647} 649}
648 650
649#ifdef CONFIG_PM 651#ifdef CONFIG_PM
650static int s3c2412_i2s_suspend(struct platform_device *dev, 652static int s3c2412_i2s_suspend(struct snd_soc_dai *dai)
651 struct snd_soc_dai *dai)
652{ 653{
653 struct s3c2412_i2s_info *i2s = &s3c2412_i2s; 654 struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
654 u32 iismod; 655 u32 iismod;
@@ -663,25 +664,24 @@ static int s3c2412_i2s_suspend(struct platform_device *dev,
663 iismod = readl(i2s->regs + S3C2412_IISMOD); 664 iismod = readl(i2s->regs + S3C2412_IISMOD);
664 665
665 if (iismod & S3C2412_IISCON_RXDMA_ACTIVE) 666 if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
666 dev_warn(&dev->dev, "%s: RXDMA active?\n", __func__); 667 pr_warning("%s: RXDMA active?\n", __func__);
667 668
668 if (iismod & S3C2412_IISCON_TXDMA_ACTIVE) 669 if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
669 dev_warn(&dev->dev, "%s: TXDMA active?\n", __func__); 670 pr_warning("%s: TXDMA active?\n", __func__);
670 671
671 if (iismod & S3C2412_IISCON_IIS_ACTIVE) 672 if (iismod & S3C2412_IISCON_IIS_ACTIVE)
672 dev_warn(&dev->dev, "%s: IIS active\n", __func__); 673 pr_warning("%s: IIS active\n", __func__);
673 } 674 }
674 675
675 return 0; 676 return 0;
676} 677}
677 678
678static int s3c2412_i2s_resume(struct platform_device *pdev, 679static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
679 struct snd_soc_dai *dai)
680{ 680{
681 struct s3c2412_i2s_info *i2s = &s3c2412_i2s; 681 struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
682 682
683 dev_info(&pdev->dev, "dai_active %d, IISMOD %08x, IISCON %08x\n", 683 pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n",
684 dai->active, i2s->suspend_iismod, i2s->suspend_iiscon); 684 dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
685 685
686 if (dai->active) { 686 if (dai->active) {
687 writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON); 687 writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
@@ -711,7 +711,6 @@ static int s3c2412_i2s_resume(struct platform_device *pdev,
711struct snd_soc_dai s3c2412_i2s_dai = { 711struct snd_soc_dai s3c2412_i2s_dai = {
712 .name = "s3c2412-i2s", 712 .name = "s3c2412-i2s",
713 .id = 0, 713 .id = 0,
714 .type = SND_SOC_DAI_I2S,
715 .probe = s3c2412_i2s_probe, 714 .probe = s3c2412_i2s_probe,
716 .suspend = s3c2412_i2s_suspend, 715 .suspend = s3c2412_i2s_suspend,
717 .resume = s3c2412_i2s_resume, 716 .resume = s3c2412_i2s_resume,
@@ -730,8 +729,6 @@ struct snd_soc_dai s3c2412_i2s_dai = {
730 .ops = { 729 .ops = {
731 .trigger = s3c2412_i2s_trigger, 730 .trigger = s3c2412_i2s_trigger,
732 .hw_params = s3c2412_i2s_hw_params, 731 .hw_params = s3c2412_i2s_hw_params,
733 },
734 .dai_ops = {
735 .set_fmt = s3c2412_i2s_set_fmt, 732 .set_fmt = s3c2412_i2s_set_fmt,
736 .set_clkdiv = s3c2412_i2s_set_clkdiv, 733 .set_clkdiv = s3c2412_i2s_set_clkdiv,
737 .set_sysclk = s3c2412_i2s_set_sysclk, 734 .set_sysclk = s3c2412_i2s_set_sysclk,
@@ -739,6 +736,19 @@ struct snd_soc_dai s3c2412_i2s_dai = {
739}; 736};
740EXPORT_SYMBOL_GPL(s3c2412_i2s_dai); 737EXPORT_SYMBOL_GPL(s3c2412_i2s_dai);
741 738
739static int __init s3c2412_i2s_init(void)
740{
741 return snd_soc_register_dai(&s3c2412_i2s_dai);
742}
743module_init(s3c2412_i2s_init);
744
745static void __exit s3c2412_i2s_exit(void)
746{
747 snd_soc_unregister_dai(&s3c2412_i2s_dai);
748}
749module_exit(s3c2412_i2s_exit);
750
751
742/* Module information */ 752/* Module information */
743MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); 753MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
744MODULE_DESCRIPTION("S3C2412 I2S SoC Interface"); 754MODULE_DESCRIPTION("S3C2412 I2S SoC Interface");
diff --git a/sound/soc/s3c24xx/s3c2443-ac97.c b/sound/soc/s3c24xx/s3c2443-ac97.c
index 19c5c3cf5d8c..1bfce40bb2e4 100644
--- a/sound/soc/s3c24xx/s3c2443-ac97.c
+++ b/sound/soc/s3c24xx/s3c2443-ac97.c
@@ -271,7 +271,8 @@ static void s3c2443_ac97_remove(struct platform_device *pdev,
271} 271}
272 272
273static int s3c2443_ac97_hw_params(struct snd_pcm_substream *substream, 273static int s3c2443_ac97_hw_params(struct snd_pcm_substream *substream,
274 struct snd_pcm_hw_params *params) 274 struct snd_pcm_hw_params *params,
275 struct snd_soc_dai *dai)
275{ 276{
276 struct snd_soc_pcm_runtime *rtd = substream->private_data; 277 struct snd_soc_pcm_runtime *rtd = substream->private_data;
277 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 278 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -284,7 +285,8 @@ static int s3c2443_ac97_hw_params(struct snd_pcm_substream *substream,
284 return 0; 285 return 0;
285} 286}
286 287
287static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd) 288static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
289 struct snd_soc_dai *dai)
288{ 290{
289 u32 ac_glbctrl; 291 u32 ac_glbctrl;
290 292
@@ -313,7 +315,8 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd)
313} 315}
314 316
315static int s3c2443_ac97_hw_mic_params(struct snd_pcm_substream *substream, 317static int s3c2443_ac97_hw_mic_params(struct snd_pcm_substream *substream,
316 struct snd_pcm_hw_params *params) 318 struct snd_pcm_hw_params *params,
319 struct snd_soc_dai *dai)
317{ 320{
318 struct snd_soc_pcm_runtime *rtd = substream->private_data; 321 struct snd_soc_pcm_runtime *rtd = substream->private_data;
319 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 322 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -327,7 +330,7 @@ static int s3c2443_ac97_hw_mic_params(struct snd_pcm_substream *substream,
327} 330}
328 331
329static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream, 332static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
330 int cmd) 333 int cmd, struct snd_soc_dai *dai)
331{ 334{
332 u32 ac_glbctrl; 335 u32 ac_glbctrl;
333 336
@@ -356,7 +359,7 @@ struct snd_soc_dai s3c2443_ac97_dai[] = {
356{ 359{
357 .name = "s3c2443-ac97", 360 .name = "s3c2443-ac97",
358 .id = 0, 361 .id = 0,
359 .type = SND_SOC_DAI_AC97, 362 .ac97_control = 1,
360 .probe = s3c2443_ac97_probe, 363 .probe = s3c2443_ac97_probe,
361 .remove = s3c2443_ac97_remove, 364 .remove = s3c2443_ac97_remove,
362 .playback = { 365 .playback = {
@@ -378,7 +381,7 @@ struct snd_soc_dai s3c2443_ac97_dai[] = {
378{ 381{
379 .name = "pxa2xx-ac97-mic", 382 .name = "pxa2xx-ac97-mic",
380 .id = 1, 383 .id = 1,
381 .type = SND_SOC_DAI_AC97, 384 .ac97_control = 1,
382 .capture = { 385 .capture = {
383 .stream_name = "AC97 Mic Capture", 386 .stream_name = "AC97 Mic Capture",
384 .channels_min = 1, 387 .channels_min = 1,
@@ -393,6 +396,21 @@ struct snd_soc_dai s3c2443_ac97_dai[] = {
393EXPORT_SYMBOL_GPL(s3c2443_ac97_dai); 396EXPORT_SYMBOL_GPL(s3c2443_ac97_dai);
394EXPORT_SYMBOL_GPL(soc_ac97_ops); 397EXPORT_SYMBOL_GPL(soc_ac97_ops);
395 398
399static int __init s3c2443_ac97_init(void)
400{
401 return snd_soc_register_dais(s3c2443_ac97_dai,
402 ARRAY_SIZE(s3c2443_ac97_dai));
403}
404module_init(s3c2443_ac97_init);
405
406static void __exit s3c2443_ac97_exit(void)
407{
408 snd_soc_unregister_dais(s3c2443_ac97_dai,
409 ARRAY_SIZE(s3c2443_ac97_dai));
410}
411module_exit(s3c2443_ac97_exit);
412
413
396MODULE_AUTHOR("Graeme Gregory"); 414MODULE_AUTHOR("Graeme Gregory");
397MODULE_DESCRIPTION("AC97 driver for the Samsung s3c2443 chip"); 415MODULE_DESCRIPTION("AC97 driver for the Samsung s3c2443 chip");
398MODULE_LICENSE("GPL"); 416MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index ba4476b55fbc..6f4d439b57aa 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -243,7 +243,8 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
243} 243}
244 244
245static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, 245static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
246 struct snd_pcm_hw_params *params) 246 struct snd_pcm_hw_params *params,
247 struct snd_soc_dai *dai)
247{ 248{
248 struct snd_soc_pcm_runtime *rtd = substream->private_data; 249 struct snd_soc_pcm_runtime *rtd = substream->private_data;
249 u32 iismod; 250 u32 iismod;
@@ -261,10 +262,17 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
261 262
262 switch (params_format(params)) { 263 switch (params_format(params)) {
263 case SNDRV_PCM_FORMAT_S8: 264 case SNDRV_PCM_FORMAT_S8:
265 iismod &= ~S3C2410_IISMOD_16BIT;
266 ((struct s3c24xx_pcm_dma_params *)
267 rtd->dai->cpu_dai->dma_data)->dma_size = 1;
264 break; 268 break;
265 case SNDRV_PCM_FORMAT_S16_LE: 269 case SNDRV_PCM_FORMAT_S16_LE:
266 iismod |= S3C2410_IISMOD_16BIT; 270 iismod |= S3C2410_IISMOD_16BIT;
271 ((struct s3c24xx_pcm_dma_params *)
272 rtd->dai->cpu_dai->dma_data)->dma_size = 2;
267 break; 273 break;
274 default:
275 return -EINVAL;
268 } 276 }
269 277
270 writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); 278 writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
@@ -272,7 +280,8 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
272 return 0; 280 return 0;
273} 281}
274 282
275static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd) 283static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
284 struct snd_soc_dai *dai)
276{ 285{
277 int ret = 0; 286 int ret = 0;
278 287
@@ -410,8 +419,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev,
410} 419}
411 420
412#ifdef CONFIG_PM 421#ifdef CONFIG_PM
413static int s3c24xx_i2s_suspend(struct platform_device *pdev, 422static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai)
414 struct snd_soc_dai *cpu_dai)
415{ 423{
416 DBG("Entered %s\n", __func__); 424 DBG("Entered %s\n", __func__);
417 425
@@ -425,8 +433,7 @@ static int s3c24xx_i2s_suspend(struct platform_device *pdev,
425 return 0; 433 return 0;
426} 434}
427 435
428static int s3c24xx_i2s_resume(struct platform_device *pdev, 436static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai)
429 struct snd_soc_dai *cpu_dai)
430{ 437{
431 DBG("Entered %s\n", __func__); 438 DBG("Entered %s\n", __func__);
432 clk_enable(s3c24xx_i2s.iis_clk); 439 clk_enable(s3c24xx_i2s.iis_clk);
@@ -452,7 +459,6 @@ static int s3c24xx_i2s_resume(struct platform_device *pdev,
452struct snd_soc_dai s3c24xx_i2s_dai = { 459struct snd_soc_dai s3c24xx_i2s_dai = {
453 .name = "s3c24xx-i2s", 460 .name = "s3c24xx-i2s",
454 .id = 0, 461 .id = 0,
455 .type = SND_SOC_DAI_I2S,
456 .probe = s3c24xx_i2s_probe, 462 .probe = s3c24xx_i2s_probe,
457 .suspend = s3c24xx_i2s_suspend, 463 .suspend = s3c24xx_i2s_suspend,
458 .resume = s3c24xx_i2s_resume, 464 .resume = s3c24xx_i2s_resume,
@@ -468,8 +474,7 @@ struct snd_soc_dai s3c24xx_i2s_dai = {
468 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, 474 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
469 .ops = { 475 .ops = {
470 .trigger = s3c24xx_i2s_trigger, 476 .trigger = s3c24xx_i2s_trigger,
471 .hw_params = s3c24xx_i2s_hw_params,}, 477 .hw_params = s3c24xx_i2s_hw_params,
472 .dai_ops = {
473 .set_fmt = s3c24xx_i2s_set_fmt, 478 .set_fmt = s3c24xx_i2s_set_fmt,
474 .set_clkdiv = s3c24xx_i2s_set_clkdiv, 479 .set_clkdiv = s3c24xx_i2s_set_clkdiv,
475 .set_sysclk = s3c24xx_i2s_set_sysclk, 480 .set_sysclk = s3c24xx_i2s_set_sysclk,
@@ -477,6 +482,18 @@ struct snd_soc_dai s3c24xx_i2s_dai = {
477}; 482};
478EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai); 483EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai);
479 484
485static int __init s3c24xx_i2s_init(void)
486{
487 return snd_soc_register_dai(&s3c24xx_i2s_dai);
488}
489module_init(s3c24xx_i2s_init);
490
491static void __exit s3c24xx_i2s_exit(void)
492{
493 snd_soc_unregister_dai(&s3c24xx_i2s_dai);
494}
495module_exit(s3c24xx_i2s_exit);
496
480/* Module information */ 497/* Module information */
481MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); 498MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
482MODULE_DESCRIPTION("s3c24xx I2S SoC Interface"); 499MODULE_DESCRIPTION("s3c24xx I2S SoC Interface");
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c
index e13e614bada9..7c64d31d067e 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
@@ -465,6 +465,18 @@ struct snd_soc_platform s3c24xx_soc_platform = {
465}; 465};
466EXPORT_SYMBOL_GPL(s3c24xx_soc_platform); 466EXPORT_SYMBOL_GPL(s3c24xx_soc_platform);
467 467
468static int __init s3c24xx_soc_platform_init(void)
469{
470 return snd_soc_register_platform(&s3c24xx_soc_platform);
471}
472module_init(s3c24xx_soc_platform_init);
473
474static void __exit s3c24xx_soc_platform_exit(void)
475{
476 snd_soc_unregister_platform(&s3c24xx_soc_platform);
477}
478module_exit(s3c24xx_soc_platform_exit);
479
468MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); 480MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
469MODULE_DESCRIPTION("Samsung S3C24XX PCM DMA module"); 481MODULE_DESCRIPTION("Samsung S3C24XX PCM DMA module");
470MODULE_LICENSE("GPL"); 482MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c24xx_uda134x.c b/sound/soc/s3c24xx/s3c24xx_uda134x.c
new file mode 100644
index 000000000000..a0a4d1832a14
--- /dev/null
+++ b/sound/soc/s3c24xx/s3c24xx_uda134x.c
@@ -0,0 +1,373 @@
1/*
2 * Modifications by Christian Pellegrin <chripell@evolware.org>
3 *
4 * s3c24xx_uda134x.c -- S3C24XX_UDA134X ALSA SoC Audio board driver
5 *
6 * Copyright 2007 Dension Audio Systems Ltd.
7 * Author: Zoltan Devai
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
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/module.h>
15#include <linux/clk.h>
16#include <linux/mutex.h>
17#include <linux/gpio.h>
18#include <sound/pcm.h>
19#include <sound/pcm_params.h>
20#include <sound/soc.h>
21#include <sound/soc-dapm.h>
22#include <sound/s3c24xx_uda134x.h>
23#include <sound/uda134x.h>
24
25#include <asm/plat-s3c24xx/regs-iis.h>
26
27#include "s3c24xx-pcm.h"
28#include "s3c24xx-i2s.h"
29#include "../codecs/uda134x.h"
30
31
32/* #define ENFORCE_RATES 1 */
33/*
34 Unfortunately the S3C24XX in master mode has a limited capacity of
35 generating the clock for the codec. If you define this only rates
36 that are really available will be enforced. But be careful, most
37 user level application just want the usual sampling frequencies (8,
38 11.025, 22.050, 44.1 kHz) and anyway resampling is a costly
39 operation for embedded systems. So if you aren't very lucky or your
40 hardware engineer wasn't very forward-looking it's better to leave
41 this undefined. If you do so an approximate value for the requested
42 sampling rate in the range -/+ 5% will be chosen. If this in not
43 possible an error will be returned.
44*/
45
46static struct clk *xtal;
47static struct clk *pclk;
48/* this is need because we don't have a place where to keep the
49 * pointers to the clocks in each substream. We get the clocks only
50 * when we are actually using them so we don't block stuff like
51 * frequency change or oscillator power-off */
52static int clk_users;
53static DEFINE_MUTEX(clk_lock);
54
55static unsigned int rates[33 * 2];
56#ifdef ENFORCE_RATES
57static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
58 .count = ARRAY_SIZE(rates),
59 .list = rates,
60 .mask = 0,
61};
62#endif
63
64static struct platform_device *s3c24xx_uda134x_snd_device;
65
66static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream)
67{
68 int ret = 0;
69#ifdef ENFORCE_RATES
70 struct snd_pcm_runtime *runtime = substream->runtime;;
71#endif
72
73 mutex_lock(&clk_lock);
74 pr_debug("%s %d\n", __func__, clk_users);
75 if (clk_users == 0) {
76 xtal = clk_get(&s3c24xx_uda134x_snd_device->dev, "xtal");
77 if (!xtal) {
78 printk(KERN_ERR "%s cannot get xtal\n", __func__);
79 ret = -EBUSY;
80 } else {
81 pclk = clk_get(&s3c24xx_uda134x_snd_device->dev,
82 "pclk");
83 if (!pclk) {
84 printk(KERN_ERR "%s cannot get pclk\n",
85 __func__);
86 clk_put(xtal);
87 ret = -EBUSY;
88 }
89 }
90 if (!ret) {
91 int i, j;
92
93 for (i = 0; i < 2; i++) {
94 int fs = i ? 256 : 384;
95
96 rates[i*33] = clk_get_rate(xtal) / fs;
97 for (j = 1; j < 33; j++)
98 rates[i*33 + j] = clk_get_rate(pclk) /
99 (j * fs);
100 }
101 }
102 }
103 clk_users += 1;
104 mutex_unlock(&clk_lock);
105 if (!ret) {
106#ifdef ENFORCE_RATES
107 ret = snd_pcm_hw_constraint_list(runtime, 0,
108 SNDRV_PCM_HW_PARAM_RATE,
109 &hw_constraints_rates);
110 if (ret < 0)
111 printk(KERN_ERR "%s cannot set constraints\n",
112 __func__);
113#endif
114 }
115 return ret;
116}
117
118static void s3c24xx_uda134x_shutdown(struct snd_pcm_substream *substream)
119{
120 mutex_lock(&clk_lock);
121 pr_debug("%s %d\n", __func__, clk_users);
122 clk_users -= 1;
123 if (clk_users == 0) {
124 clk_put(xtal);
125 xtal = NULL;
126 clk_put(pclk);
127 pclk = NULL;
128 }
129 mutex_unlock(&clk_lock);
130}
131
132static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream,
133 struct snd_pcm_hw_params *params)
134{
135 struct snd_soc_pcm_runtime *rtd = substream->private_data;
136 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
137 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
138 unsigned int clk = 0;
139 int ret = 0;
140 int clk_source, fs_mode;
141 unsigned long rate = params_rate(params);
142 long err, cerr;
143 unsigned int div;
144 int i, bi;
145
146 err = 999999;
147 bi = 0;
148 for (i = 0; i < 2*33; i++) {
149 cerr = rates[i] - rate;
150 if (cerr < 0)
151 cerr = -cerr;
152 if (cerr < err) {
153 err = cerr;
154 bi = i;
155 }
156 }
157 if (bi / 33 == 1)
158 fs_mode = S3C2410_IISMOD_256FS;
159 else
160 fs_mode = S3C2410_IISMOD_384FS;
161 if (bi % 33 == 0) {
162 clk_source = S3C24XX_CLKSRC_MPLL;
163 div = 1;
164 } else {
165 clk_source = S3C24XX_CLKSRC_PCLK;
166 div = bi % 33;
167 }
168 pr_debug("%s desired rate %lu, %d\n", __func__, rate, bi);
169
170 clk = (fs_mode == S3C2410_IISMOD_384FS ? 384 : 256) * rate;
171 pr_debug("%s will use: %s %s %d sysclk %d err %ld\n", __func__,
172 fs_mode == S3C2410_IISMOD_384FS ? "384FS" : "256FS",
173 clk_source == S3C24XX_CLKSRC_MPLL ? "MPLLin" : "PCLK",
174 div, clk, err);
175
176 if ((err * 100 / rate) > 5) {
177 printk(KERN_ERR "S3C24XX_UDA134X: effective frequency "
178 "too different from desired (%ld%%)\n",
179 err * 100 / rate);
180 return -EINVAL;
181 }
182
183 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
184 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
185 if (ret < 0)
186 return ret;
187
188 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
189 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
190 if (ret < 0)
191 return ret;
192
193 ret = snd_soc_dai_set_sysclk(cpu_dai, clk_source , clk,
194 SND_SOC_CLOCK_IN);
195 if (ret < 0)
196 return ret;
197
198 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, fs_mode);
199 if (ret < 0)
200 return ret;
201
202 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK,
203 S3C2410_IISMOD_32FS);
204 if (ret < 0)
205 return ret;
206
207 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
208 S3C24XX_PRESCALE(div, div));
209 if (ret < 0)
210 return ret;
211
212 /* set the codec system clock for DAC and ADC */
213 ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk,
214 SND_SOC_CLOCK_OUT);
215 if (ret < 0)
216 return ret;
217
218 return 0;
219}
220
221static struct snd_soc_ops s3c24xx_uda134x_ops = {
222 .startup = s3c24xx_uda134x_startup,
223 .shutdown = s3c24xx_uda134x_shutdown,
224 .hw_params = s3c24xx_uda134x_hw_params,
225};
226
227static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {
228 .name = "UDA134X",
229 .stream_name = "UDA134X",
230 .codec_dai = &uda134x_dai,
231 .cpu_dai = &s3c24xx_i2s_dai,
232 .ops = &s3c24xx_uda134x_ops,
233};
234
235static struct snd_soc_card snd_soc_s3c24xx_uda134x = {
236 .name = "S3C24XX_UDA134X",
237 .platform = &s3c24xx_soc_platform,
238 .dai_link = &s3c24xx_uda134x_dai_link,
239 .num_links = 1,
240};
241
242static struct s3c24xx_uda134x_platform_data *s3c24xx_uda134x_l3_pins;
243
244static void setdat(int v)
245{
246 gpio_set_value(s3c24xx_uda134x_l3_pins->l3_data, v > 0);
247}
248
249static void setclk(int v)
250{
251 gpio_set_value(s3c24xx_uda134x_l3_pins->l3_clk, v > 0);
252}
253
254static void setmode(int v)
255{
256 gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0);
257}
258
259static struct uda134x_platform_data s3c24xx_uda134x = {
260 .l3 = {
261 .setdat = setdat,
262 .setclk = setclk,
263 .setmode = setmode,
264 .data_hold = 1,
265 .data_setup = 1,
266 .clock_high = 1,
267 .mode_hold = 1,
268 .mode = 1,
269 .mode_setup = 1,
270 },
271};
272
273static struct snd_soc_device s3c24xx_uda134x_snd_devdata = {
274 .card = &snd_soc_s3c24xx_uda134x,
275 .codec_dev = &soc_codec_dev_uda134x,
276 .codec_data = &s3c24xx_uda134x,
277};
278
279static int s3c24xx_uda134x_setup_pin(int pin, char *fun)
280{
281 if (gpio_request(pin, "s3c24xx_uda134x") < 0) {
282 printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
283 "l3 %s pin already in use", fun);
284 return -EBUSY;
285 }
286 gpio_direction_output(pin, 0);
287 return 0;
288}
289
290static int s3c24xx_uda134x_probe(struct platform_device *pdev)
291{
292 int ret;
293
294 printk(KERN_INFO "S3C24XX_UDA134X SoC Audio driver\n");
295
296 s3c24xx_uda134x_l3_pins = pdev->dev.platform_data;
297 if (s3c24xx_uda134x_l3_pins == NULL) {
298 printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
299 "unable to find platform data\n");
300 return -ENODEV;
301 }
302 s3c24xx_uda134x.power = s3c24xx_uda134x_l3_pins->power;
303 s3c24xx_uda134x.model = s3c24xx_uda134x_l3_pins->model;
304
305 if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_data,
306 "data") < 0)
307 return -EBUSY;
308 if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_clk,
309 "clk") < 0) {
310 gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
311 return -EBUSY;
312 }
313 if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_mode,
314 "mode") < 0) {
315 gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
316 gpio_free(s3c24xx_uda134x_l3_pins->l3_clk);
317 return -EBUSY;
318 }
319
320 s3c24xx_uda134x_snd_device = platform_device_alloc("soc-audio", -1);
321 if (!s3c24xx_uda134x_snd_device) {
322 printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
323 "Unable to register\n");
324 return -ENOMEM;
325 }
326
327 platform_set_drvdata(s3c24xx_uda134x_snd_device,
328 &s3c24xx_uda134x_snd_devdata);
329 s3c24xx_uda134x_snd_devdata.dev = &s3c24xx_uda134x_snd_device->dev;
330 ret = platform_device_add(s3c24xx_uda134x_snd_device);
331 if (ret) {
332 printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n");
333 platform_device_put(s3c24xx_uda134x_snd_device);
334 }
335
336 return ret;
337}
338
339static int s3c24xx_uda134x_remove(struct platform_device *pdev)
340{
341 platform_device_unregister(s3c24xx_uda134x_snd_device);
342 gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
343 gpio_free(s3c24xx_uda134x_l3_pins->l3_clk);
344 gpio_free(s3c24xx_uda134x_l3_pins->l3_mode);
345 return 0;
346}
347
348static struct platform_driver s3c24xx_uda134x_driver = {
349 .probe = s3c24xx_uda134x_probe,
350 .remove = s3c24xx_uda134x_remove,
351 .driver = {
352 .name = "s3c24xx_uda134x",
353 .owner = THIS_MODULE,
354 },
355};
356
357static int __init s3c24xx_uda134x_init(void)
358{
359 return platform_driver_register(&s3c24xx_uda134x_driver);
360}
361
362static void __exit s3c24xx_uda134x_exit(void)
363{
364 platform_driver_unregister(&s3c24xx_uda134x_driver);
365}
366
367
368module_init(s3c24xx_uda134x_init);
369module_exit(s3c24xx_uda134x_exit);
370
371MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
372MODULE_DESCRIPTION("S3C24XX_UDA134X ALSA SoC audio driver");
373MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/smdk2443_wm9710.c b/sound/soc/s3c24xx/smdk2443_wm9710.c
index 8515d6ff03f2..a2a4f5323c17 100644
--- a/sound/soc/s3c24xx/smdk2443_wm9710.c
+++ b/sound/soc/s3c24xx/smdk2443_wm9710.c
@@ -23,7 +23,7 @@
23#include "s3c24xx-pcm.h" 23#include "s3c24xx-pcm.h"
24#include "s3c24xx-ac97.h" 24#include "s3c24xx-ac97.h"
25 25
26static struct snd_soc_machine smdk2443; 26static struct snd_soc_card smdk2443;
27 27
28static struct snd_soc_dai_link smdk2443_dai[] = { 28static struct snd_soc_dai_link smdk2443_dai[] = {
29{ 29{
@@ -34,15 +34,15 @@ static struct snd_soc_dai_link smdk2443_dai[] = {
34}, 34},
35}; 35};
36 36
37static struct snd_soc_machine smdk2443 = { 37static struct snd_soc_card smdk2443 = {
38 .name = "SMDK2443", 38 .name = "SMDK2443",
39 .platform = &s3c24xx_soc_platform,
39 .dai_link = smdk2443_dai, 40 .dai_link = smdk2443_dai,
40 .num_links = ARRAY_SIZE(smdk2443_dai), 41 .num_links = ARRAY_SIZE(smdk2443_dai),
41}; 42};
42 43
43static struct snd_soc_device smdk2443_snd_ac97_devdata = { 44static struct snd_soc_device smdk2443_snd_ac97_devdata = {
44 .machine = &smdk2443, 45 .card = &smdk2443,
45 .platform = &s3c24xx_soc_platform,
46 .codec_dev = &soc_codec_dev_ac97, 46 .codec_dev = &soc_codec_dev_ac97,
47}; 47};
48 48
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c
index 9faa12622d09..0dad3a0bb920 100644
--- a/sound/soc/sh/dma-sh7760.c
+++ b/sound/soc/sh/dma-sh7760.c
@@ -348,6 +348,18 @@ struct snd_soc_platform sh7760_soc_platform = {
348}; 348};
349EXPORT_SYMBOL_GPL(sh7760_soc_platform); 349EXPORT_SYMBOL_GPL(sh7760_soc_platform);
350 350
351static int __init sh7760_soc_platform_init(void)
352{
353 return snd_soc_register_platform(&sh7760_soc_platform);
354}
355module_init(sh7760_soc_platform_init);
356
357static void __exit sh7760_soc_platform_exit(void)
358{
359 snd_soc_unregister_platform(&sh7760_soc_platform);
360}
361module_exit(sh7760_soc_platform_exit);
362
351MODULE_LICENSE("GPL"); 363MODULE_LICENSE("GPL");
352MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver"); 364MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver");
353MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); 365MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c
index df7bc345c320..eab31838badf 100644
--- a/sound/soc/sh/hac.c
+++ b/sound/soc/sh/hac.c
@@ -236,7 +236,8 @@ struct snd_ac97_bus_ops soc_ac97_ops = {
236EXPORT_SYMBOL_GPL(soc_ac97_ops); 236EXPORT_SYMBOL_GPL(soc_ac97_ops);
237 237
238static int hac_hw_params(struct snd_pcm_substream *substream, 238static int hac_hw_params(struct snd_pcm_substream *substream,
239 struct snd_pcm_hw_params *params) 239 struct snd_pcm_hw_params *params,
240 struct snd_soc_dai *dai)
240{ 241{
241 struct snd_soc_pcm_runtime *rtd = substream->private_data; 242 struct snd_soc_pcm_runtime *rtd = substream->private_data;
242 struct hac_priv *hac = &hac_cpu_data[rtd->dai->cpu_dai->id]; 243 struct hac_priv *hac = &hac_cpu_data[rtd->dai->cpu_dai->id];
@@ -270,7 +271,7 @@ struct snd_soc_dai sh4_hac_dai[] = {
270{ 271{
271 .name = "HAC0", 272 .name = "HAC0",
272 .id = 0, 273 .id = 0,
273 .type = SND_SOC_DAI_AC97, 274 .ac97_control = 1,
274 .playback = { 275 .playback = {
275 .rates = AC97_RATES, 276 .rates = AC97_RATES,
276 .formats = AC97_FMTS, 277 .formats = AC97_FMTS,
@@ -290,8 +291,8 @@ struct snd_soc_dai sh4_hac_dai[] = {
290#ifdef CONFIG_CPU_SUBTYPE_SH7760 291#ifdef CONFIG_CPU_SUBTYPE_SH7760
291{ 292{
292 .name = "HAC1", 293 .name = "HAC1",
294 .ac97_control = 1,
293 .id = 1, 295 .id = 1,
294 .type = SND_SOC_DAI_AC97,
295 .playback = { 296 .playback = {
296 .rates = AC97_RATES, 297 .rates = AC97_RATES,
297 .formats = AC97_FMTS, 298 .formats = AC97_FMTS,
@@ -313,6 +314,18 @@ struct snd_soc_dai sh4_hac_dai[] = {
313}; 314};
314EXPORT_SYMBOL_GPL(sh4_hac_dai); 315EXPORT_SYMBOL_GPL(sh4_hac_dai);
315 316
317static int __init sh4_hac_init(void)
318{
319 return snd_soc_register_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai));
320}
321module_init(sh4_hac_init);
322
323static void __exit sh4_hac_exit(void)
324{
325 snd_soc_unregister_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai));
326}
327module_exit(sh4_hac_exit);
328
316MODULE_LICENSE("GPL"); 329MODULE_LICENSE("GPL");
317MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver"); 330MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver");
318MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); 331MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/sh/sh7760-ac97.c b/sound/soc/sh/sh7760-ac97.c
index 92bfaf4774a7..ce7f95b59de3 100644
--- a/sound/soc/sh/sh7760-ac97.c
+++ b/sound/soc/sh/sh7760-ac97.c
@@ -38,15 +38,15 @@ static struct snd_soc_dai_link sh7760_ac97_dai = {
38 .ops = NULL, 38 .ops = NULL,
39}; 39};
40 40
41static struct snd_soc_machine sh7760_ac97_soc_machine = { 41static struct snd_soc_card sh7760_ac97_soc_machine = {
42 .name = "SH7760 AC97", 42 .name = "SH7760 AC97",
43 .platform = &sh7760_soc_platform,
43 .dai_link = &sh7760_ac97_dai, 44 .dai_link = &sh7760_ac97_dai,
44 .num_links = 1, 45 .num_links = 1,
45}; 46};
46 47
47static struct snd_soc_device sh7760_ac97_snd_devdata = { 48static struct snd_soc_device sh7760_ac97_snd_devdata = {
48 .machine = &sh7760_ac97_soc_machine, 49 .card = &sh7760_ac97_soc_machine,
49 .platform = &sh7760_soc_platform,
50 .codec_dev = &soc_codec_dev_ac97, 50 .codec_dev = &soc_codec_dev_ac97,
51}; 51};
52 52
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c
index 55c3464163ab..d1e5390fddeb 100644
--- a/sound/soc/sh/ssi.c
+++ b/sound/soc/sh/ssi.c
@@ -89,7 +89,8 @@ struct ssi_priv {
89 * track usage of the SSI; it is simplex-only so prevent attempts of 89 * track usage of the SSI; it is simplex-only so prevent attempts of
90 * concurrent playback + capture. FIXME: any locking required? 90 * concurrent playback + capture. FIXME: any locking required?
91 */ 91 */
92static int ssi_startup(struct snd_pcm_substream *substream) 92static int ssi_startup(struct snd_pcm_substream *substream,
93 struct snd_soc_dai *dai)
93{ 94{
94 struct snd_soc_pcm_runtime *rtd = substream->private_data; 95 struct snd_soc_pcm_runtime *rtd = substream->private_data;
95 struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; 96 struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
@@ -101,7 +102,8 @@ static int ssi_startup(struct snd_pcm_substream *substream)
101 return 0; 102 return 0;
102} 103}
103 104
104static void ssi_shutdown(struct snd_pcm_substream *substream) 105static void ssi_shutdown(struct snd_pcm_substream *substream,
106 struct snd_soc_dai *dai)
105{ 107{
106 struct snd_soc_pcm_runtime *rtd = substream->private_data; 108 struct snd_soc_pcm_runtime *rtd = substream->private_data;
107 struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; 109 struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
@@ -109,7 +111,8 @@ static void ssi_shutdown(struct snd_pcm_substream *substream)
109 ssi->inuse = 0; 111 ssi->inuse = 0;
110} 112}
111 113
112static int ssi_trigger(struct snd_pcm_substream *substream, int cmd) 114static int ssi_trigger(struct snd_pcm_substream *substream, int cmd,
115 struct snd_soc_dai *dai)
113{ 116{
114 struct snd_soc_pcm_runtime *rtd = substream->private_data; 117 struct snd_soc_pcm_runtime *rtd = substream->private_data;
115 struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; 118 struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
@@ -129,7 +132,8 @@ static int ssi_trigger(struct snd_pcm_substream *substream, int cmd)
129} 132}
130 133
131static int ssi_hw_params(struct snd_pcm_substream *substream, 134static int ssi_hw_params(struct snd_pcm_substream *substream,
132 struct snd_pcm_hw_params *params) 135 struct snd_pcm_hw_params *params,
136 struct snd_soc_dai *dai)
133{ 137{
134 struct snd_soc_pcm_runtime *rtd = substream->private_data; 138 struct snd_soc_pcm_runtime *rtd = substream->private_data;
135 struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; 139 struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
@@ -336,7 +340,6 @@ struct snd_soc_dai sh4_ssi_dai[] = {
336{ 340{
337 .name = "SSI0", 341 .name = "SSI0",
338 .id = 0, 342 .id = 0,
339 .type = SND_SOC_DAI_I2S,
340 .playback = { 343 .playback = {
341 .rates = SSI_RATES, 344 .rates = SSI_RATES,
342 .formats = SSI_FMTS, 345 .formats = SSI_FMTS,
@@ -354,8 +357,6 @@ struct snd_soc_dai sh4_ssi_dai[] = {
354 .shutdown = ssi_shutdown, 357 .shutdown = ssi_shutdown,
355 .trigger = ssi_trigger, 358 .trigger = ssi_trigger,
356 .hw_params = ssi_hw_params, 359 .hw_params = ssi_hw_params,
357 },
358 .dai_ops = {
359 .set_sysclk = ssi_set_sysclk, 360 .set_sysclk = ssi_set_sysclk,
360 .set_clkdiv = ssi_set_clkdiv, 361 .set_clkdiv = ssi_set_clkdiv,
361 .set_fmt = ssi_set_fmt, 362 .set_fmt = ssi_set_fmt,
@@ -365,7 +366,6 @@ struct snd_soc_dai sh4_ssi_dai[] = {
365{ 366{
366 .name = "SSI1", 367 .name = "SSI1",
367 .id = 1, 368 .id = 1,
368 .type = SND_SOC_DAI_I2S,
369 .playback = { 369 .playback = {
370 .rates = SSI_RATES, 370 .rates = SSI_RATES,
371 .formats = SSI_FMTS, 371 .formats = SSI_FMTS,
@@ -383,8 +383,6 @@ struct snd_soc_dai sh4_ssi_dai[] = {
383 .shutdown = ssi_shutdown, 383 .shutdown = ssi_shutdown,
384 .trigger = ssi_trigger, 384 .trigger = ssi_trigger,
385 .hw_params = ssi_hw_params, 385 .hw_params = ssi_hw_params,
386 },
387 .dai_ops = {
388 .set_sysclk = ssi_set_sysclk, 386 .set_sysclk = ssi_set_sysclk,
389 .set_clkdiv = ssi_set_clkdiv, 387 .set_clkdiv = ssi_set_clkdiv,
390 .set_fmt = ssi_set_fmt, 388 .set_fmt = ssi_set_fmt,
@@ -394,6 +392,18 @@ struct snd_soc_dai sh4_ssi_dai[] = {
394}; 392};
395EXPORT_SYMBOL_GPL(sh4_ssi_dai); 393EXPORT_SYMBOL_GPL(sh4_ssi_dai);
396 394
395static int __init sh4_ssi_init(void)
396{
397 return snd_soc_register_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai));
398}
399module_init(sh4_ssi_init);
400
401static void __exit sh4_ssi_exit(void)
402{
403 snd_soc_unregister_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai));
404}
405module_exit(sh4_ssi_exit);
406
397MODULE_LICENSE("GPL"); 407MODULE_LICENSE("GPL");
398MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver"); 408MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver");
399MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); 409MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 16c7453f4946..b098c0b4c584 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -26,6 +26,7 @@
26#include <linux/delay.h> 26#include <linux/delay.h>
27#include <linux/pm.h> 27#include <linux/pm.h>
28#include <linux/bitops.h> 28#include <linux/bitops.h>
29#include <linux/debugfs.h>
29#include <linux/platform_device.h> 30#include <linux/platform_device.h>
30#include <sound/core.h> 31#include <sound/core.h>
31#include <sound/pcm.h> 32#include <sound/pcm.h>
@@ -34,18 +35,23 @@
34#include <sound/soc-dapm.h> 35#include <sound/soc-dapm.h>
35#include <sound/initval.h> 36#include <sound/initval.h>
36 37
37/* debug */
38#define SOC_DEBUG 0
39#if SOC_DEBUG
40#define dbg(format, arg...) printk(format, ## arg)
41#else
42#define dbg(format, arg...)
43#endif
44
45static DEFINE_MUTEX(pcm_mutex); 38static DEFINE_MUTEX(pcm_mutex);
46static DEFINE_MUTEX(io_mutex); 39static DEFINE_MUTEX(io_mutex);
47static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); 40static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
48 41
42#ifdef CONFIG_DEBUG_FS
43static struct dentry *debugfs_root;
44#endif
45
46static DEFINE_MUTEX(client_mutex);
47static LIST_HEAD(card_list);
48static LIST_HEAD(dai_list);
49static LIST_HEAD(platform_list);
50static LIST_HEAD(codec_list);
51
52static int snd_soc_register_card(struct snd_soc_card *card);
53static int snd_soc_unregister_card(struct snd_soc_card *card);
54
49/* 55/*
50 * This is a timeout to do a DAPM powerdown after a stream is closed(). 56 * This is a timeout to do a DAPM powerdown after a stream is closed().
51 * It can be used to eliminate pops between different playback streams, e.g. 57 * It can be used to eliminate pops between different playback streams, e.g.
@@ -107,20 +113,6 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
107} 113}
108#endif 114#endif
109 115
110static inline const char *get_dai_name(int type)
111{
112 switch (type) {
113 case SND_SOC_DAI_AC97_BUS:
114 case SND_SOC_DAI_AC97:
115 return "AC97";
116 case SND_SOC_DAI_I2S:
117 return "I2S";
118 case SND_SOC_DAI_PCM:
119 return "PCM";
120 }
121 return NULL;
122}
123
124/* 116/*
125 * Called by ALSA when a PCM substream is opened, the runtime->hw record is 117 * Called by ALSA when a PCM substream is opened, the runtime->hw record is
126 * then initialized and any private data can be allocated. This also calls 118 * then initialized and any private data can be allocated. This also calls
@@ -130,9 +122,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
130{ 122{
131 struct snd_soc_pcm_runtime *rtd = substream->private_data; 123 struct snd_soc_pcm_runtime *rtd = substream->private_data;
132 struct snd_soc_device *socdev = rtd->socdev; 124 struct snd_soc_device *socdev = rtd->socdev;
125 struct snd_soc_card *card = socdev->card;
133 struct snd_pcm_runtime *runtime = substream->runtime; 126 struct snd_pcm_runtime *runtime = substream->runtime;
134 struct snd_soc_dai_link *machine = rtd->dai; 127 struct snd_soc_dai_link *machine = rtd->dai;
135 struct snd_soc_platform *platform = socdev->platform; 128 struct snd_soc_platform *platform = card->platform;
136 struct snd_soc_dai *cpu_dai = machine->cpu_dai; 129 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
137 struct snd_soc_dai *codec_dai = machine->codec_dai; 130 struct snd_soc_dai *codec_dai = machine->codec_dai;
138 int ret = 0; 131 int ret = 0;
@@ -141,7 +134,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
141 134
142 /* startup the audio subsystem */ 135 /* startup the audio subsystem */
143 if (cpu_dai->ops.startup) { 136 if (cpu_dai->ops.startup) {
144 ret = cpu_dai->ops.startup(substream); 137 ret = cpu_dai->ops.startup(substream, cpu_dai);
145 if (ret < 0) { 138 if (ret < 0) {
146 printk(KERN_ERR "asoc: can't open interface %s\n", 139 printk(KERN_ERR "asoc: can't open interface %s\n",
147 cpu_dai->name); 140 cpu_dai->name);
@@ -158,7 +151,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
158 } 151 }
159 152
160 if (codec_dai->ops.startup) { 153 if (codec_dai->ops.startup) {
161 ret = codec_dai->ops.startup(substream); 154 ret = codec_dai->ops.startup(substream, codec_dai);
162 if (ret < 0) { 155 if (ret < 0) {
163 printk(KERN_ERR "asoc: can't open codec %s\n", 156 printk(KERN_ERR "asoc: can't open codec %s\n",
164 codec_dai->name); 157 codec_dai->name);
@@ -228,12 +221,12 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
228 goto machine_err; 221 goto machine_err;
229 } 222 }
230 223
231 dbg("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); 224 pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name);
232 dbg("asoc: rate mask 0x%x\n", runtime->hw.rates); 225 pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
233 dbg("asoc: min ch %d max ch %d\n", runtime->hw.channels_min, 226 pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
234 runtime->hw.channels_max); 227 runtime->hw.channels_max);
235 dbg("asoc: min rate %d max rate %d\n", runtime->hw.rate_min, 228 pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
236 runtime->hw.rate_max); 229 runtime->hw.rate_max);
237 230
238 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 231 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
239 cpu_dai->playback.active = codec_dai->playback.active = 1; 232 cpu_dai->playback.active = codec_dai->playback.active = 1;
@@ -255,7 +248,7 @@ codec_dai_err:
255 248
256platform_err: 249platform_err:
257 if (cpu_dai->ops.shutdown) 250 if (cpu_dai->ops.shutdown)
258 cpu_dai->ops.shutdown(substream); 251 cpu_dai->ops.shutdown(substream, cpu_dai);
259out: 252out:
260 mutex_unlock(&pcm_mutex); 253 mutex_unlock(&pcm_mutex);
261 return ret; 254 return ret;
@@ -268,8 +261,9 @@ out:
268 */ 261 */
269static void close_delayed_work(struct work_struct *work) 262static void close_delayed_work(struct work_struct *work)
270{ 263{
271 struct snd_soc_device *socdev = 264 struct snd_soc_card *card = container_of(work, struct snd_soc_card,
272 container_of(work, struct snd_soc_device, delayed_work.work); 265 delayed_work.work);
266 struct snd_soc_device *socdev = card->socdev;
273 struct snd_soc_codec *codec = socdev->codec; 267 struct snd_soc_codec *codec = socdev->codec;
274 struct snd_soc_dai *codec_dai; 268 struct snd_soc_dai *codec_dai;
275 int i; 269 int i;
@@ -278,18 +272,18 @@ static void close_delayed_work(struct work_struct *work)
278 for (i = 0; i < codec->num_dai; i++) { 272 for (i = 0; i < codec->num_dai; i++) {
279 codec_dai = &codec->dai[i]; 273 codec_dai = &codec->dai[i];
280 274
281 dbg("pop wq checking: %s status: %s waiting: %s\n", 275 pr_debug("pop wq checking: %s status: %s waiting: %s\n",
282 codec_dai->playback.stream_name, 276 codec_dai->playback.stream_name,
283 codec_dai->playback.active ? "active" : "inactive", 277 codec_dai->playback.active ? "active" : "inactive",
284 codec_dai->pop_wait ? "yes" : "no"); 278 codec_dai->pop_wait ? "yes" : "no");
285 279
286 /* are we waiting on this codec DAI stream */ 280 /* are we waiting on this codec DAI stream */
287 if (codec_dai->pop_wait == 1) { 281 if (codec_dai->pop_wait == 1) {
288 282
289 /* Reduce power if no longer active */ 283 /* Reduce power if no longer active */
290 if (codec->active == 0) { 284 if (codec->active == 0) {
291 dbg("pop wq D1 %s %s\n", codec->name, 285 pr_debug("pop wq D1 %s %s\n", codec->name,
292 codec_dai->playback.stream_name); 286 codec_dai->playback.stream_name);
293 snd_soc_dapm_set_bias_level(socdev, 287 snd_soc_dapm_set_bias_level(socdev,
294 SND_SOC_BIAS_PREPARE); 288 SND_SOC_BIAS_PREPARE);
295 } 289 }
@@ -301,8 +295,8 @@ static void close_delayed_work(struct work_struct *work)
301 295
302 /* Fall into standby if no longer active */ 296 /* Fall into standby if no longer active */
303 if (codec->active == 0) { 297 if (codec->active == 0) {
304 dbg("pop wq D3 %s %s\n", codec->name, 298 pr_debug("pop wq D3 %s %s\n", codec->name,
305 codec_dai->playback.stream_name); 299 codec_dai->playback.stream_name);
306 snd_soc_dapm_set_bias_level(socdev, 300 snd_soc_dapm_set_bias_level(socdev,
307 SND_SOC_BIAS_STANDBY); 301 SND_SOC_BIAS_STANDBY);
308 } 302 }
@@ -320,8 +314,9 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
320{ 314{
321 struct snd_soc_pcm_runtime *rtd = substream->private_data; 315 struct snd_soc_pcm_runtime *rtd = substream->private_data;
322 struct snd_soc_device *socdev = rtd->socdev; 316 struct snd_soc_device *socdev = rtd->socdev;
317 struct snd_soc_card *card = socdev->card;
323 struct snd_soc_dai_link *machine = rtd->dai; 318 struct snd_soc_dai_link *machine = rtd->dai;
324 struct snd_soc_platform *platform = socdev->platform; 319 struct snd_soc_platform *platform = card->platform;
325 struct snd_soc_dai *cpu_dai = machine->cpu_dai; 320 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
326 struct snd_soc_dai *codec_dai = machine->codec_dai; 321 struct snd_soc_dai *codec_dai = machine->codec_dai;
327 struct snd_soc_codec *codec = socdev->codec; 322 struct snd_soc_codec *codec = socdev->codec;
@@ -346,10 +341,10 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
346 snd_soc_dai_digital_mute(codec_dai, 1); 341 snd_soc_dai_digital_mute(codec_dai, 1);
347 342
348 if (cpu_dai->ops.shutdown) 343 if (cpu_dai->ops.shutdown)
349 cpu_dai->ops.shutdown(substream); 344 cpu_dai->ops.shutdown(substream, cpu_dai);
350 345
351 if (codec_dai->ops.shutdown) 346 if (codec_dai->ops.shutdown)
352 codec_dai->ops.shutdown(substream); 347 codec_dai->ops.shutdown(substream, codec_dai);
353 348
354 if (machine->ops && machine->ops->shutdown) 349 if (machine->ops && machine->ops->shutdown)
355 machine->ops->shutdown(substream); 350 machine->ops->shutdown(substream);
@@ -361,7 +356,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
361 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 356 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
362 /* start delayed pop wq here for playback streams */ 357 /* start delayed pop wq here for playback streams */
363 codec_dai->pop_wait = 1; 358 codec_dai->pop_wait = 1;
364 schedule_delayed_work(&socdev->delayed_work, 359 schedule_delayed_work(&card->delayed_work,
365 msecs_to_jiffies(pmdown_time)); 360 msecs_to_jiffies(pmdown_time));
366 } else { 361 } else {
367 /* capture streams can be powered down now */ 362 /* capture streams can be powered down now */
@@ -387,8 +382,9 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
387{ 382{
388 struct snd_soc_pcm_runtime *rtd = substream->private_data; 383 struct snd_soc_pcm_runtime *rtd = substream->private_data;
389 struct snd_soc_device *socdev = rtd->socdev; 384 struct snd_soc_device *socdev = rtd->socdev;
385 struct snd_soc_card *card = socdev->card;
390 struct snd_soc_dai_link *machine = rtd->dai; 386 struct snd_soc_dai_link *machine = rtd->dai;
391 struct snd_soc_platform *platform = socdev->platform; 387 struct snd_soc_platform *platform = card->platform;
392 struct snd_soc_dai *cpu_dai = machine->cpu_dai; 388 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
393 struct snd_soc_dai *codec_dai = machine->codec_dai; 389 struct snd_soc_dai *codec_dai = machine->codec_dai;
394 struct snd_soc_codec *codec = socdev->codec; 390 struct snd_soc_codec *codec = socdev->codec;
@@ -413,7 +409,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
413 } 409 }
414 410
415 if (codec_dai->ops.prepare) { 411 if (codec_dai->ops.prepare) {
416 ret = codec_dai->ops.prepare(substream); 412 ret = codec_dai->ops.prepare(substream, codec_dai);
417 if (ret < 0) { 413 if (ret < 0) {
418 printk(KERN_ERR "asoc: codec DAI prepare error\n"); 414 printk(KERN_ERR "asoc: codec DAI prepare error\n");
419 goto out; 415 goto out;
@@ -421,58 +417,49 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
421 } 417 }
422 418
423 if (cpu_dai->ops.prepare) { 419 if (cpu_dai->ops.prepare) {
424 ret = cpu_dai->ops.prepare(substream); 420 ret = cpu_dai->ops.prepare(substream, cpu_dai);
425 if (ret < 0) { 421 if (ret < 0) {
426 printk(KERN_ERR "asoc: cpu DAI prepare error\n"); 422 printk(KERN_ERR "asoc: cpu DAI prepare error\n");
427 goto out; 423 goto out;
428 } 424 }
429 } 425 }
430 426
431 /* we only want to start a DAPM playback stream if we are not waiting 427 /* cancel any delayed stream shutdown that is pending */
432 * on an existing one stopping */ 428 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
433 if (codec_dai->pop_wait) { 429 codec_dai->pop_wait) {
434 /* we are waiting for the delayed work to start */ 430 codec_dai->pop_wait = 0;
435 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 431 cancel_delayed_work(&card->delayed_work);
436 snd_soc_dapm_stream_event(socdev->codec, 432 }
437 codec_dai->capture.stream_name,
438 SND_SOC_DAPM_STREAM_START);
439 else {
440 codec_dai->pop_wait = 0;
441 cancel_delayed_work(&socdev->delayed_work);
442 snd_soc_dai_digital_mute(codec_dai, 0);
443 }
444 } else {
445 /* no delayed work - do we need to power up codec */
446 if (codec->bias_level != SND_SOC_BIAS_ON) {
447 433
448 snd_soc_dapm_set_bias_level(socdev, 434 /* do we need to power up codec */
449 SND_SOC_BIAS_PREPARE); 435 if (codec->bias_level != SND_SOC_BIAS_ON) {
436 snd_soc_dapm_set_bias_level(socdev,
437 SND_SOC_BIAS_PREPARE);
450 438
451 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 439 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
452 snd_soc_dapm_stream_event(codec, 440 snd_soc_dapm_stream_event(codec,
453 codec_dai->playback.stream_name, 441 codec_dai->playback.stream_name,
454 SND_SOC_DAPM_STREAM_START); 442 SND_SOC_DAPM_STREAM_START);
455 else 443 else
456 snd_soc_dapm_stream_event(codec, 444 snd_soc_dapm_stream_event(codec,
457 codec_dai->capture.stream_name, 445 codec_dai->capture.stream_name,
458 SND_SOC_DAPM_STREAM_START); 446 SND_SOC_DAPM_STREAM_START);
459 447
460 snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_ON); 448 snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_ON);
461 snd_soc_dai_digital_mute(codec_dai, 0); 449 snd_soc_dai_digital_mute(codec_dai, 0);
462 450
463 } else { 451 } else {
464 /* codec already powered - power on widgets */ 452 /* codec already powered - power on widgets */
465 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 453 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
466 snd_soc_dapm_stream_event(codec, 454 snd_soc_dapm_stream_event(codec,
467 codec_dai->playback.stream_name, 455 codec_dai->playback.stream_name,
468 SND_SOC_DAPM_STREAM_START); 456 SND_SOC_DAPM_STREAM_START);
469 else 457 else
470 snd_soc_dapm_stream_event(codec, 458 snd_soc_dapm_stream_event(codec,
471 codec_dai->capture.stream_name, 459 codec_dai->capture.stream_name,
472 SND_SOC_DAPM_STREAM_START); 460 SND_SOC_DAPM_STREAM_START);
473 461
474 snd_soc_dai_digital_mute(codec_dai, 0); 462 snd_soc_dai_digital_mute(codec_dai, 0);
475 }
476 } 463 }
477 464
478out: 465out:
@@ -491,7 +478,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
491 struct snd_soc_pcm_runtime *rtd = substream->private_data; 478 struct snd_soc_pcm_runtime *rtd = substream->private_data;
492 struct snd_soc_device *socdev = rtd->socdev; 479 struct snd_soc_device *socdev = rtd->socdev;
493 struct snd_soc_dai_link *machine = rtd->dai; 480 struct snd_soc_dai_link *machine = rtd->dai;
494 struct snd_soc_platform *platform = socdev->platform; 481 struct snd_soc_card *card = socdev->card;
482 struct snd_soc_platform *platform = card->platform;
495 struct snd_soc_dai *cpu_dai = machine->cpu_dai; 483 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
496 struct snd_soc_dai *codec_dai = machine->codec_dai; 484 struct snd_soc_dai *codec_dai = machine->codec_dai;
497 int ret = 0; 485 int ret = 0;
@@ -507,7 +495,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
507 } 495 }
508 496
509 if (codec_dai->ops.hw_params) { 497 if (codec_dai->ops.hw_params) {
510 ret = codec_dai->ops.hw_params(substream, params); 498 ret = codec_dai->ops.hw_params(substream, params, codec_dai);
511 if (ret < 0) { 499 if (ret < 0) {
512 printk(KERN_ERR "asoc: can't set codec %s hw params\n", 500 printk(KERN_ERR "asoc: can't set codec %s hw params\n",
513 codec_dai->name); 501 codec_dai->name);
@@ -516,7 +504,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
516 } 504 }
517 505
518 if (cpu_dai->ops.hw_params) { 506 if (cpu_dai->ops.hw_params) {
519 ret = cpu_dai->ops.hw_params(substream, params); 507 ret = cpu_dai->ops.hw_params(substream, params, cpu_dai);
520 if (ret < 0) { 508 if (ret < 0) {
521 printk(KERN_ERR "asoc: interface %s hw params failed\n", 509 printk(KERN_ERR "asoc: interface %s hw params failed\n",
522 cpu_dai->name); 510 cpu_dai->name);
@@ -539,11 +527,11 @@ out:
539 527
540platform_err: 528platform_err:
541 if (cpu_dai->ops.hw_free) 529 if (cpu_dai->ops.hw_free)
542 cpu_dai->ops.hw_free(substream); 530 cpu_dai->ops.hw_free(substream, cpu_dai);
543 531
544interface_err: 532interface_err:
545 if (codec_dai->ops.hw_free) 533 if (codec_dai->ops.hw_free)
546 codec_dai->ops.hw_free(substream); 534 codec_dai->ops.hw_free(substream, codec_dai);
547 535
548codec_err: 536codec_err:
549 if (machine->ops && machine->ops->hw_free) 537 if (machine->ops && machine->ops->hw_free)
@@ -561,7 +549,8 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
561 struct snd_soc_pcm_runtime *rtd = substream->private_data; 549 struct snd_soc_pcm_runtime *rtd = substream->private_data;
562 struct snd_soc_device *socdev = rtd->socdev; 550 struct snd_soc_device *socdev = rtd->socdev;
563 struct snd_soc_dai_link *machine = rtd->dai; 551 struct snd_soc_dai_link *machine = rtd->dai;
564 struct snd_soc_platform *platform = socdev->platform; 552 struct snd_soc_card *card = socdev->card;
553 struct snd_soc_platform *platform = card->platform;
565 struct snd_soc_dai *cpu_dai = machine->cpu_dai; 554 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
566 struct snd_soc_dai *codec_dai = machine->codec_dai; 555 struct snd_soc_dai *codec_dai = machine->codec_dai;
567 struct snd_soc_codec *codec = socdev->codec; 556 struct snd_soc_codec *codec = socdev->codec;
@@ -582,10 +571,10 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
582 571
583 /* now free hw params for the DAI's */ 572 /* now free hw params for the DAI's */
584 if (codec_dai->ops.hw_free) 573 if (codec_dai->ops.hw_free)
585 codec_dai->ops.hw_free(substream); 574 codec_dai->ops.hw_free(substream, codec_dai);
586 575
587 if (cpu_dai->ops.hw_free) 576 if (cpu_dai->ops.hw_free)
588 cpu_dai->ops.hw_free(substream); 577 cpu_dai->ops.hw_free(substream, cpu_dai);
589 578
590 mutex_unlock(&pcm_mutex); 579 mutex_unlock(&pcm_mutex);
591 return 0; 580 return 0;
@@ -595,14 +584,15 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
595{ 584{
596 struct snd_soc_pcm_runtime *rtd = substream->private_data; 585 struct snd_soc_pcm_runtime *rtd = substream->private_data;
597 struct snd_soc_device *socdev = rtd->socdev; 586 struct snd_soc_device *socdev = rtd->socdev;
587 struct snd_soc_card *card= socdev->card;
598 struct snd_soc_dai_link *machine = rtd->dai; 588 struct snd_soc_dai_link *machine = rtd->dai;
599 struct snd_soc_platform *platform = socdev->platform; 589 struct snd_soc_platform *platform = card->platform;
600 struct snd_soc_dai *cpu_dai = machine->cpu_dai; 590 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
601 struct snd_soc_dai *codec_dai = machine->codec_dai; 591 struct snd_soc_dai *codec_dai = machine->codec_dai;
602 int ret; 592 int ret;
603 593
604 if (codec_dai->ops.trigger) { 594 if (codec_dai->ops.trigger) {
605 ret = codec_dai->ops.trigger(substream, cmd); 595 ret = codec_dai->ops.trigger(substream, cmd, codec_dai);
606 if (ret < 0) 596 if (ret < 0)
607 return ret; 597 return ret;
608 } 598 }
@@ -614,7 +604,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
614 } 604 }
615 605
616 if (cpu_dai->ops.trigger) { 606 if (cpu_dai->ops.trigger) {
617 ret = cpu_dai->ops.trigger(substream, cmd); 607 ret = cpu_dai->ops.trigger(substream, cmd, cpu_dai);
618 if (ret < 0) 608 if (ret < 0)
619 return ret; 609 return ret;
620 } 610 }
@@ -636,8 +626,8 @@ static struct snd_pcm_ops soc_pcm_ops = {
636static int soc_suspend(struct platform_device *pdev, pm_message_t state) 626static int soc_suspend(struct platform_device *pdev, pm_message_t state)
637{ 627{
638 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 628 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
639 struct snd_soc_machine *machine = socdev->machine; 629 struct snd_soc_card *card = socdev->card;
640 struct snd_soc_platform *platform = socdev->platform; 630 struct snd_soc_platform *platform = card->platform;
641 struct snd_soc_codec_device *codec_dev = socdev->codec_dev; 631 struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
642 struct snd_soc_codec *codec = socdev->codec; 632 struct snd_soc_codec *codec = socdev->codec;
643 int i; 633 int i;
@@ -653,29 +643,29 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
653 snd_power_change_state(codec->card, SNDRV_CTL_POWER_D3hot); 643 snd_power_change_state(codec->card, SNDRV_CTL_POWER_D3hot);
654 644
655 /* mute any active DAC's */ 645 /* mute any active DAC's */
656 for (i = 0; i < machine->num_links; i++) { 646 for (i = 0; i < card->num_links; i++) {
657 struct snd_soc_dai *dai = machine->dai_link[i].codec_dai; 647 struct snd_soc_dai *dai = card->dai_link[i].codec_dai;
658 if (dai->dai_ops.digital_mute && dai->playback.active) 648 if (dai->ops.digital_mute && dai->playback.active)
659 dai->dai_ops.digital_mute(dai, 1); 649 dai->ops.digital_mute(dai, 1);
660 } 650 }
661 651
662 /* suspend all pcms */ 652 /* suspend all pcms */
663 for (i = 0; i < machine->num_links; i++) 653 for (i = 0; i < card->num_links; i++)
664 snd_pcm_suspend_all(machine->dai_link[i].pcm); 654 snd_pcm_suspend_all(card->dai_link[i].pcm);
665 655
666 if (machine->suspend_pre) 656 if (card->suspend_pre)
667 machine->suspend_pre(pdev, state); 657 card->suspend_pre(pdev, state);
668 658
669 for (i = 0; i < machine->num_links; i++) { 659 for (i = 0; i < card->num_links; i++) {
670 struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; 660 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
671 if (cpu_dai->suspend && cpu_dai->type != SND_SOC_DAI_AC97) 661 if (cpu_dai->suspend && !cpu_dai->ac97_control)
672 cpu_dai->suspend(pdev, cpu_dai); 662 cpu_dai->suspend(cpu_dai);
673 if (platform->suspend) 663 if (platform->suspend)
674 platform->suspend(pdev, cpu_dai); 664 platform->suspend(cpu_dai);
675 } 665 }
676 666
677 /* close any waiting streams and save state */ 667 /* close any waiting streams and save state */
678 run_delayed_work(&socdev->delayed_work); 668 run_delayed_work(&card->delayed_work);
679 codec->suspend_bias_level = codec->bias_level; 669 codec->suspend_bias_level = codec->bias_level;
680 670
681 for (i = 0; i < codec->num_dai; i++) { 671 for (i = 0; i < codec->num_dai; i++) {
@@ -692,14 +682,14 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
692 if (codec_dev->suspend) 682 if (codec_dev->suspend)
693 codec_dev->suspend(pdev, state); 683 codec_dev->suspend(pdev, state);
694 684
695 for (i = 0; i < machine->num_links; i++) { 685 for (i = 0; i < card->num_links; i++) {
696 struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; 686 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
697 if (cpu_dai->suspend && cpu_dai->type == SND_SOC_DAI_AC97) 687 if (cpu_dai->suspend && cpu_dai->ac97_control)
698 cpu_dai->suspend(pdev, cpu_dai); 688 cpu_dai->suspend(cpu_dai);
699 } 689 }
700 690
701 if (machine->suspend_post) 691 if (card->suspend_post)
702 machine->suspend_post(pdev, state); 692 card->suspend_post(pdev, state);
703 693
704 return 0; 694 return 0;
705} 695}
@@ -709,11 +699,11 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
709 */ 699 */
710static void soc_resume_deferred(struct work_struct *work) 700static void soc_resume_deferred(struct work_struct *work)
711{ 701{
712 struct snd_soc_device *socdev = container_of(work, 702 struct snd_soc_card *card = container_of(work,
713 struct snd_soc_device, 703 struct snd_soc_card,
714 deferred_resume_work); 704 deferred_resume_work);
715 struct snd_soc_machine *machine = socdev->machine; 705 struct snd_soc_device *socdev = card->socdev;
716 struct snd_soc_platform *platform = socdev->platform; 706 struct snd_soc_platform *platform = card->platform;
717 struct snd_soc_codec_device *codec_dev = socdev->codec_dev; 707 struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
718 struct snd_soc_codec *codec = socdev->codec; 708 struct snd_soc_codec *codec = socdev->codec;
719 struct platform_device *pdev = to_platform_device(socdev->dev); 709 struct platform_device *pdev = to_platform_device(socdev->dev);
@@ -723,15 +713,15 @@ static void soc_resume_deferred(struct work_struct *work)
723 * so userspace apps are blocked from touching us 713 * so userspace apps are blocked from touching us
724 */ 714 */
725 715
726 dev_info(socdev->dev, "starting resume work\n"); 716 dev_dbg(socdev->dev, "starting resume work\n");
727 717
728 if (machine->resume_pre) 718 if (card->resume_pre)
729 machine->resume_pre(pdev); 719 card->resume_pre(pdev);
730 720
731 for (i = 0; i < machine->num_links; i++) { 721 for (i = 0; i < card->num_links; i++) {
732 struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; 722 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
733 if (cpu_dai->resume && cpu_dai->type == SND_SOC_DAI_AC97) 723 if (cpu_dai->resume && cpu_dai->ac97_control)
734 cpu_dai->resume(pdev, cpu_dai); 724 cpu_dai->resume(cpu_dai);
735 } 725 }
736 726
737 if (codec_dev->resume) 727 if (codec_dev->resume)
@@ -749,24 +739,24 @@ static void soc_resume_deferred(struct work_struct *work)
749 } 739 }
750 740
751 /* unmute any active DACs */ 741 /* unmute any active DACs */
752 for (i = 0; i < machine->num_links; i++) { 742 for (i = 0; i < card->num_links; i++) {
753 struct snd_soc_dai *dai = machine->dai_link[i].codec_dai; 743 struct snd_soc_dai *dai = card->dai_link[i].codec_dai;
754 if (dai->dai_ops.digital_mute && dai->playback.active) 744 if (dai->ops.digital_mute && dai->playback.active)
755 dai->dai_ops.digital_mute(dai, 0); 745 dai->ops.digital_mute(dai, 0);
756 } 746 }
757 747
758 for (i = 0; i < machine->num_links; i++) { 748 for (i = 0; i < card->num_links; i++) {
759 struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; 749 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
760 if (cpu_dai->resume && cpu_dai->type != SND_SOC_DAI_AC97) 750 if (cpu_dai->resume && !cpu_dai->ac97_control)
761 cpu_dai->resume(pdev, cpu_dai); 751 cpu_dai->resume(cpu_dai);
762 if (platform->resume) 752 if (platform->resume)
763 platform->resume(pdev, cpu_dai); 753 platform->resume(cpu_dai);
764 } 754 }
765 755
766 if (machine->resume_post) 756 if (card->resume_post)
767 machine->resume_post(pdev); 757 card->resume_post(pdev);
768 758
769 dev_info(socdev->dev, "resume work completed\n"); 759 dev_dbg(socdev->dev, "resume work completed\n");
770 760
771 /* userspace can access us now we are back as we were before */ 761 /* userspace can access us now we are back as we were before */
772 snd_power_change_state(codec->card, SNDRV_CTL_POWER_D0); 762 snd_power_change_state(codec->card, SNDRV_CTL_POWER_D0);
@@ -776,11 +766,12 @@ static void soc_resume_deferred(struct work_struct *work)
776static int soc_resume(struct platform_device *pdev) 766static int soc_resume(struct platform_device *pdev)
777{ 767{
778 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 768 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
769 struct snd_soc_card *card = socdev->card;
779 770
780 dev_info(socdev->dev, "scheduling resume work\n"); 771 dev_dbg(socdev->dev, "scheduling resume work\n");
781 772
782 if (!schedule_work(&socdev->deferred_resume_work)) 773 if (!schedule_work(&card->deferred_resume_work))
783 dev_err(socdev->dev, "work item may be lost\n"); 774 dev_err(socdev->dev, "resume work item may be lost\n");
784 775
785 return 0; 776 return 0;
786} 777}
@@ -790,23 +781,83 @@ static int soc_resume(struct platform_device *pdev)
790#define soc_resume NULL 781#define soc_resume NULL
791#endif 782#endif
792 783
793/* probes a new socdev */ 784static void snd_soc_instantiate_card(struct snd_soc_card *card)
794static int soc_probe(struct platform_device *pdev)
795{ 785{
796 int ret = 0, i; 786 struct platform_device *pdev = container_of(card->dev,
797 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 787 struct platform_device,
798 struct snd_soc_machine *machine = socdev->machine; 788 dev);
799 struct snd_soc_platform *platform = socdev->platform; 789 struct snd_soc_codec_device *codec_dev = card->socdev->codec_dev;
800 struct snd_soc_codec_device *codec_dev = socdev->codec_dev; 790 struct snd_soc_platform *platform;
791 struct snd_soc_dai *dai;
792 int i, found, ret, ac97;
793
794 if (card->instantiated)
795 return;
796
797 found = 0;
798 list_for_each_entry(platform, &platform_list, list)
799 if (card->platform == platform) {
800 found = 1;
801 break;
802 }
803 if (!found) {
804 dev_dbg(card->dev, "Platform %s not registered\n",
805 card->platform->name);
806 return;
807 }
808
809 ac97 = 0;
810 for (i = 0; i < card->num_links; i++) {
811 found = 0;
812 list_for_each_entry(dai, &dai_list, list)
813 if (card->dai_link[i].cpu_dai == dai) {
814 found = 1;
815 break;
816 }
817 if (!found) {
818 dev_dbg(card->dev, "DAI %s not registered\n",
819 card->dai_link[i].cpu_dai->name);
820 return;
821 }
801 822
802 if (machine->probe) { 823 if (card->dai_link[i].cpu_dai->ac97_control)
803 ret = machine->probe(pdev); 824 ac97 = 1;
825 }
826
827 /* If we have AC97 in the system then don't wait for the
828 * codec. This will need revisiting if we have to handle
829 * systems with mixed AC97 and non-AC97 parts. Only check for
830 * DAIs currently; we can't do this per link since some AC97
831 * codecs have non-AC97 DAIs.
832 */
833 if (!ac97)
834 for (i = 0; i < card->num_links; i++) {
835 found = 0;
836 list_for_each_entry(dai, &dai_list, list)
837 if (card->dai_link[i].codec_dai == dai) {
838 found = 1;
839 break;
840 }
841 if (!found) {
842 dev_dbg(card->dev, "DAI %s not registered\n",
843 card->dai_link[i].codec_dai->name);
844 return;
845 }
846 }
847
848 /* Note that we do not current check for codec components */
849
850 dev_dbg(card->dev, "All components present, instantiating\n");
851
852 /* Found everything, bring it up */
853 if (card->probe) {
854 ret = card->probe(pdev);
804 if (ret < 0) 855 if (ret < 0)
805 return ret; 856 return;
806 } 857 }
807 858
808 for (i = 0; i < machine->num_links; i++) { 859 for (i = 0; i < card->num_links; i++) {
809 struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; 860 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
810 if (cpu_dai->probe) { 861 if (cpu_dai->probe) {
811 ret = cpu_dai->probe(pdev, cpu_dai); 862 ret = cpu_dai->probe(pdev, cpu_dai);
812 if (ret < 0) 863 if (ret < 0)
@@ -827,13 +878,15 @@ static int soc_probe(struct platform_device *pdev)
827 } 878 }
828 879
829 /* DAPM stream work */ 880 /* DAPM stream work */
830 INIT_DELAYED_WORK(&socdev->delayed_work, close_delayed_work); 881 INIT_DELAYED_WORK(&card->delayed_work, close_delayed_work);
831#ifdef CONFIG_PM 882#ifdef CONFIG_PM
832 /* deferred resume work */ 883 /* deferred resume work */
833 INIT_WORK(&socdev->deferred_resume_work, soc_resume_deferred); 884 INIT_WORK(&card->deferred_resume_work, soc_resume_deferred);
834#endif 885#endif
835 886
836 return 0; 887 card->instantiated = 1;
888
889 return;
837 890
838platform_err: 891platform_err:
839 if (codec_dev->remove) 892 if (codec_dev->remove)
@@ -841,15 +894,45 @@ platform_err:
841 894
842cpu_dai_err: 895cpu_dai_err:
843 for (i--; i >= 0; i--) { 896 for (i--; i >= 0; i--) {
844 struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; 897 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
845 if (cpu_dai->remove) 898 if (cpu_dai->remove)
846 cpu_dai->remove(pdev, cpu_dai); 899 cpu_dai->remove(pdev, cpu_dai);
847 } 900 }
848 901
849 if (machine->remove) 902 if (card->remove)
850 machine->remove(pdev); 903 card->remove(pdev);
904}
851 905
852 return ret; 906/*
907 * Attempt to initialise any uninitalised cards. Must be called with
908 * client_mutex.
909 */
910static void snd_soc_instantiate_cards(void)
911{
912 struct snd_soc_card *card;
913 list_for_each_entry(card, &card_list, list)
914 snd_soc_instantiate_card(card);
915}
916
917/* probes a new socdev */
918static int soc_probe(struct platform_device *pdev)
919{
920 int ret = 0;
921 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
922 struct snd_soc_card *card = socdev->card;
923
924 /* Bodge while we push things out of socdev */
925 card->socdev = socdev;
926
927 /* Bodge while we unpick instantiation */
928 card->dev = &pdev->dev;
929 ret = snd_soc_register_card(card);
930 if (ret != 0) {
931 dev_err(&pdev->dev, "Failed to register card\n");
932 return ret;
933 }
934
935 return 0;
853} 936}
854 937
855/* removes a socdev */ 938/* removes a socdev */
@@ -857,11 +940,11 @@ static int soc_remove(struct platform_device *pdev)
857{ 940{
858 int i; 941 int i;
859 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 942 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
860 struct snd_soc_machine *machine = socdev->machine; 943 struct snd_soc_card *card = socdev->card;
861 struct snd_soc_platform *platform = socdev->platform; 944 struct snd_soc_platform *platform = card->platform;
862 struct snd_soc_codec_device *codec_dev = socdev->codec_dev; 945 struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
863 946
864 run_delayed_work(&socdev->delayed_work); 947 run_delayed_work(&card->delayed_work);
865 948
866 if (platform->remove) 949 if (platform->remove)
867 platform->remove(pdev); 950 platform->remove(pdev);
@@ -869,14 +952,16 @@ static int soc_remove(struct platform_device *pdev)
869 if (codec_dev->remove) 952 if (codec_dev->remove)
870 codec_dev->remove(pdev); 953 codec_dev->remove(pdev);
871 954
872 for (i = 0; i < machine->num_links; i++) { 955 for (i = 0; i < card->num_links; i++) {
873 struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; 956 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
874 if (cpu_dai->remove) 957 if (cpu_dai->remove)
875 cpu_dai->remove(pdev, cpu_dai); 958 cpu_dai->remove(pdev, cpu_dai);
876 } 959 }
877 960
878 if (machine->remove) 961 if (card->remove)
879 machine->remove(pdev); 962 card->remove(pdev);
963
964 snd_soc_unregister_card(card);
880 965
881 return 0; 966 return 0;
882} 967}
@@ -898,6 +983,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
898 struct snd_soc_dai_link *dai_link, int num) 983 struct snd_soc_dai_link *dai_link, int num)
899{ 984{
900 struct snd_soc_codec *codec = socdev->codec; 985 struct snd_soc_codec *codec = socdev->codec;
986 struct snd_soc_card *card = socdev->card;
987 struct snd_soc_platform *platform = card->platform;
901 struct snd_soc_dai *codec_dai = dai_link->codec_dai; 988 struct snd_soc_dai *codec_dai = dai_link->codec_dai;
902 struct snd_soc_dai *cpu_dai = dai_link->cpu_dai; 989 struct snd_soc_dai *cpu_dai = dai_link->cpu_dai;
903 struct snd_soc_pcm_runtime *rtd; 990 struct snd_soc_pcm_runtime *rtd;
@@ -914,8 +1001,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
914 codec_dai->codec = socdev->codec; 1001 codec_dai->codec = socdev->codec;
915 1002
916 /* check client and interface hw capabilities */ 1003 /* check client and interface hw capabilities */
917 sprintf(new_name, "%s %s-%s-%d", dai_link->stream_name, codec_dai->name, 1004 sprintf(new_name, "%s %s-%d", dai_link->stream_name, codec_dai->name,
918 get_dai_name(cpu_dai->type), num); 1005 num);
919 1006
920 if (codec_dai->playback.channels_min) 1007 if (codec_dai->playback.channels_min)
921 playback = 1; 1008 playback = 1;
@@ -933,13 +1020,13 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
933 1020
934 dai_link->pcm = pcm; 1021 dai_link->pcm = pcm;
935 pcm->private_data = rtd; 1022 pcm->private_data = rtd;
936 soc_pcm_ops.mmap = socdev->platform->pcm_ops->mmap; 1023 soc_pcm_ops.mmap = platform->pcm_ops->mmap;
937 soc_pcm_ops.pointer = socdev->platform->pcm_ops->pointer; 1024 soc_pcm_ops.pointer = platform->pcm_ops->pointer;
938 soc_pcm_ops.ioctl = socdev->platform->pcm_ops->ioctl; 1025 soc_pcm_ops.ioctl = platform->pcm_ops->ioctl;
939 soc_pcm_ops.copy = socdev->platform->pcm_ops->copy; 1026 soc_pcm_ops.copy = platform->pcm_ops->copy;
940 soc_pcm_ops.silence = socdev->platform->pcm_ops->silence; 1027 soc_pcm_ops.silence = platform->pcm_ops->silence;
941 soc_pcm_ops.ack = socdev->platform->pcm_ops->ack; 1028 soc_pcm_ops.ack = platform->pcm_ops->ack;
942 soc_pcm_ops.page = socdev->platform->pcm_ops->page; 1029 soc_pcm_ops.page = platform->pcm_ops->page;
943 1030
944 if (playback) 1031 if (playback)
945 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops); 1032 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
@@ -947,24 +1034,22 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
947 if (capture) 1034 if (capture)
948 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); 1035 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
949 1036
950 ret = socdev->platform->pcm_new(codec->card, codec_dai, pcm); 1037 ret = platform->pcm_new(codec->card, codec_dai, pcm);
951 if (ret < 0) { 1038 if (ret < 0) {
952 printk(KERN_ERR "asoc: platform pcm constructor failed\n"); 1039 printk(KERN_ERR "asoc: platform pcm constructor failed\n");
953 kfree(rtd); 1040 kfree(rtd);
954 return ret; 1041 return ret;
955 } 1042 }
956 1043
957 pcm->private_free = socdev->platform->pcm_free; 1044 pcm->private_free = platform->pcm_free;
958 printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name, 1045 printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
959 cpu_dai->name); 1046 cpu_dai->name);
960 return ret; 1047 return ret;
961} 1048}
962 1049
963/* codec register dump */ 1050/* codec register dump */
964static ssize_t codec_reg_show(struct device *dev, 1051static ssize_t soc_codec_reg_show(struct snd_soc_device *devdata, char *buf)
965 struct device_attribute *attr, char *buf)
966{ 1052{
967 struct snd_soc_device *devdata = dev_get_drvdata(dev);
968 struct snd_soc_codec *codec = devdata->codec; 1053 struct snd_soc_codec *codec = devdata->codec;
969 int i, step = 1, count = 0; 1054 int i, step = 1, count = 0;
970 1055
@@ -1001,8 +1086,110 @@ static ssize_t codec_reg_show(struct device *dev,
1001 1086
1002 return count; 1087 return count;
1003} 1088}
1089static ssize_t codec_reg_show(struct device *dev,
1090 struct device_attribute *attr, char *buf)
1091{
1092 struct snd_soc_device *devdata = dev_get_drvdata(dev);
1093 return soc_codec_reg_show(devdata, buf);
1094}
1095
1004static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); 1096static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
1005 1097
1098#ifdef CONFIG_DEBUG_FS
1099static int codec_reg_open_file(struct inode *inode, struct file *file)
1100{
1101 file->private_data = inode->i_private;
1102 return 0;
1103}
1104
1105static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf,
1106 size_t count, loff_t *ppos)
1107{
1108 ssize_t ret;
1109 struct snd_soc_codec *codec = file->private_data;
1110 struct device *card_dev = codec->card->dev;
1111 struct snd_soc_device *devdata = card_dev->driver_data;
1112 char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
1113 if (!buf)
1114 return -ENOMEM;
1115 ret = soc_codec_reg_show(devdata, buf);
1116 if (ret >= 0)
1117 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
1118 kfree(buf);
1119 return ret;
1120}
1121
1122static ssize_t codec_reg_write_file(struct file *file,
1123 const char __user *user_buf, size_t count, loff_t *ppos)
1124{
1125 char buf[32];
1126 int buf_size;
1127 char *start = buf;
1128 unsigned long reg, value;
1129 int step = 1;
1130 struct snd_soc_codec *codec = file->private_data;
1131
1132 buf_size = min(count, (sizeof(buf)-1));
1133 if (copy_from_user(buf, user_buf, buf_size))
1134 return -EFAULT;
1135 buf[buf_size] = 0;
1136
1137 if (codec->reg_cache_step)
1138 step = codec->reg_cache_step;
1139
1140 while (*start == ' ')
1141 start++;
1142 reg = simple_strtoul(start, &start, 16);
1143 if ((reg >= codec->reg_cache_size) || (reg % step))
1144 return -EINVAL;
1145 while (*start == ' ')
1146 start++;
1147 if (strict_strtoul(start, 16, &value))
1148 return -EINVAL;
1149 codec->write(codec, reg, value);
1150 return buf_size;
1151}
1152
1153static const struct file_operations codec_reg_fops = {
1154 .open = codec_reg_open_file,
1155 .read = codec_reg_read_file,
1156 .write = codec_reg_write_file,
1157};
1158
1159static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
1160{
1161 codec->debugfs_reg = debugfs_create_file("codec_reg", 0644,
1162 debugfs_root, codec,
1163 &codec_reg_fops);
1164 if (!codec->debugfs_reg)
1165 printk(KERN_WARNING
1166 "ASoC: Failed to create codec register debugfs file\n");
1167
1168 codec->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0744,
1169 debugfs_root,
1170 &codec->pop_time);
1171 if (!codec->debugfs_pop_time)
1172 printk(KERN_WARNING
1173 "Failed to create pop time debugfs file\n");
1174}
1175
1176static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
1177{
1178 debugfs_remove(codec->debugfs_pop_time);
1179 debugfs_remove(codec->debugfs_reg);
1180}
1181
1182#else
1183
1184static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec)
1185{
1186}
1187
1188static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
1189{
1190}
1191#endif
1192
1006/** 1193/**
1007 * snd_soc_new_ac97_codec - initailise AC97 device 1194 * snd_soc_new_ac97_codec - initailise AC97 device
1008 * @codec: audio codec 1195 * @codec: audio codec
@@ -1121,7 +1308,7 @@ EXPORT_SYMBOL_GPL(snd_soc_test_bits);
1121int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid) 1308int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
1122{ 1309{
1123 struct snd_soc_codec *codec = socdev->codec; 1310 struct snd_soc_codec *codec = socdev->codec;
1124 struct snd_soc_machine *machine = socdev->machine; 1311 struct snd_soc_card *card = socdev->card;
1125 int ret = 0, i; 1312 int ret = 0, i;
1126 1313
1127 mutex_lock(&codec->mutex); 1314 mutex_lock(&codec->mutex);
@@ -1140,11 +1327,11 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
1140 strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver)); 1327 strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));
1141 1328
1142 /* create the pcms */ 1329 /* create the pcms */
1143 for (i = 0; i < machine->num_links; i++) { 1330 for (i = 0; i < card->num_links; i++) {
1144 ret = soc_new_pcm(socdev, &machine->dai_link[i], i); 1331 ret = soc_new_pcm(socdev, &card->dai_link[i], i);
1145 if (ret < 0) { 1332 if (ret < 0) {
1146 printk(KERN_ERR "asoc: can't create pcm %s\n", 1333 printk(KERN_ERR "asoc: can't create pcm %s\n",
1147 machine->dai_link[i].stream_name); 1334 card->dai_link[i].stream_name);
1148 mutex_unlock(&codec->mutex); 1335 mutex_unlock(&codec->mutex);
1149 return ret; 1336 return ret;
1150 } 1337 }
@@ -1156,7 +1343,7 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
1156EXPORT_SYMBOL_GPL(snd_soc_new_pcms); 1343EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
1157 1344
1158/** 1345/**
1159 * snd_soc_register_card - register sound card 1346 * snd_soc_init_card - register sound card
1160 * @socdev: the SoC audio device 1347 * @socdev: the SoC audio device
1161 * 1348 *
1162 * Register a SoC sound card. Also registers an AC97 device if the 1349 * Register a SoC sound card. Also registers an AC97 device if the
@@ -1164,29 +1351,28 @@ EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
1164 * 1351 *
1165 * Returns 0 for success, else error. 1352 * Returns 0 for success, else error.
1166 */ 1353 */
1167int snd_soc_register_card(struct snd_soc_device *socdev) 1354int snd_soc_init_card(struct snd_soc_device *socdev)
1168{ 1355{
1169 struct snd_soc_codec *codec = socdev->codec; 1356 struct snd_soc_codec *codec = socdev->codec;
1170 struct snd_soc_machine *machine = socdev->machine; 1357 struct snd_soc_card *card = socdev->card;
1171 int ret = 0, i, ac97 = 0, err = 0; 1358 int ret = 0, i, ac97 = 0, err = 0;
1172 1359
1173 for (i = 0; i < machine->num_links; i++) { 1360 for (i = 0; i < card->num_links; i++) {
1174 if (socdev->machine->dai_link[i].init) { 1361 if (card->dai_link[i].init) {
1175 err = socdev->machine->dai_link[i].init(codec); 1362 err = card->dai_link[i].init(codec);
1176 if (err < 0) { 1363 if (err < 0) {
1177 printk(KERN_ERR "asoc: failed to init %s\n", 1364 printk(KERN_ERR "asoc: failed to init %s\n",
1178 socdev->machine->dai_link[i].stream_name); 1365 card->dai_link[i].stream_name);
1179 continue; 1366 continue;
1180 } 1367 }
1181 } 1368 }
1182 if (socdev->machine->dai_link[i].codec_dai->type == 1369 if (card->dai_link[i].codec_dai->ac97_control)
1183 SND_SOC_DAI_AC97_BUS)
1184 ac97 = 1; 1370 ac97 = 1;
1185 } 1371 }
1186 snprintf(codec->card->shortname, sizeof(codec->card->shortname), 1372 snprintf(codec->card->shortname, sizeof(codec->card->shortname),
1187 "%s", machine->name); 1373 "%s", card->name);
1188 snprintf(codec->card->longname, sizeof(codec->card->longname), 1374 snprintf(codec->card->longname, sizeof(codec->card->longname),
1189 "%s (%s)", machine->name, codec->name); 1375 "%s (%s)", card->name, codec->name);
1190 1376
1191 ret = snd_card_register(codec->card); 1377 ret = snd_card_register(codec->card);
1192 if (ret < 0) { 1378 if (ret < 0) {
@@ -1216,12 +1402,13 @@ int snd_soc_register_card(struct snd_soc_device *socdev)
1216 if (err < 0) 1402 if (err < 0)
1217 printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); 1403 printk(KERN_WARNING "asoc: failed to add codec sysfs files\n");
1218 1404
1405 soc_init_codec_debugfs(socdev->codec);
1219 mutex_unlock(&codec->mutex); 1406 mutex_unlock(&codec->mutex);
1220 1407
1221out: 1408out:
1222 return ret; 1409 return ret;
1223} 1410}
1224EXPORT_SYMBOL_GPL(snd_soc_register_card); 1411EXPORT_SYMBOL_GPL(snd_soc_init_card);
1225 1412
1226/** 1413/**
1227 * snd_soc_free_pcms - free sound card and pcms 1414 * snd_soc_free_pcms - free sound card and pcms
@@ -1239,10 +1426,11 @@ void snd_soc_free_pcms(struct snd_soc_device *socdev)
1239#endif 1426#endif
1240 1427
1241 mutex_lock(&codec->mutex); 1428 mutex_lock(&codec->mutex);
1429 soc_cleanup_codec_debugfs(socdev->codec);
1242#ifdef CONFIG_SND_SOC_AC97_BUS 1430#ifdef CONFIG_SND_SOC_AC97_BUS
1243 for (i = 0; i < codec->num_dai; i++) { 1431 for (i = 0; i < codec->num_dai; i++) {
1244 codec_dai = &codec->dai[i]; 1432 codec_dai = &codec->dai[i];
1245 if (codec_dai->type == SND_SOC_DAI_AC97_BUS && codec->ac97) { 1433 if (codec_dai->ac97_control && codec->ac97) {
1246 soc_ac97_dev_unregister(codec); 1434 soc_ac97_dev_unregister(codec);
1247 goto free_card; 1435 goto free_card;
1248 } 1436 }
@@ -1756,8 +1944,8 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
1756int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, 1944int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
1757 unsigned int freq, int dir) 1945 unsigned int freq, int dir)
1758{ 1946{
1759 if (dai->dai_ops.set_sysclk) 1947 if (dai->ops.set_sysclk)
1760 return dai->dai_ops.set_sysclk(dai, clk_id, freq, dir); 1948 return dai->ops.set_sysclk(dai, clk_id, freq, dir);
1761 else 1949 else
1762 return -EINVAL; 1950 return -EINVAL;
1763} 1951}
@@ -1776,8 +1964,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
1776int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, 1964int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
1777 int div_id, int div) 1965 int div_id, int div)
1778{ 1966{
1779 if (dai->dai_ops.set_clkdiv) 1967 if (dai->ops.set_clkdiv)
1780 return dai->dai_ops.set_clkdiv(dai, div_id, div); 1968 return dai->ops.set_clkdiv(dai, div_id, div);
1781 else 1969 else
1782 return -EINVAL; 1970 return -EINVAL;
1783} 1971}
@@ -1795,8 +1983,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
1795int snd_soc_dai_set_pll(struct snd_soc_dai *dai, 1983int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
1796 int pll_id, unsigned int freq_in, unsigned int freq_out) 1984 int pll_id, unsigned int freq_in, unsigned int freq_out)
1797{ 1985{
1798 if (dai->dai_ops.set_pll) 1986 if (dai->ops.set_pll)
1799 return dai->dai_ops.set_pll(dai, pll_id, freq_in, freq_out); 1987 return dai->ops.set_pll(dai, pll_id, freq_in, freq_out);
1800 else 1988 else
1801 return -EINVAL; 1989 return -EINVAL;
1802} 1990}
@@ -1805,15 +1993,14 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
1805/** 1993/**
1806 * snd_soc_dai_set_fmt - configure DAI hardware audio format. 1994 * snd_soc_dai_set_fmt - configure DAI hardware audio format.
1807 * @dai: DAI 1995 * @dai: DAI
1808 * @clk_id: DAI specific clock ID
1809 * @fmt: SND_SOC_DAIFMT_ format value. 1996 * @fmt: SND_SOC_DAIFMT_ format value.
1810 * 1997 *
1811 * Configures the DAI hardware format and clocking. 1998 * Configures the DAI hardware format and clocking.
1812 */ 1999 */
1813int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 2000int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1814{ 2001{
1815 if (dai->dai_ops.set_fmt) 2002 if (dai->ops.set_fmt)
1816 return dai->dai_ops.set_fmt(dai, fmt); 2003 return dai->ops.set_fmt(dai, fmt);
1817 else 2004 else
1818 return -EINVAL; 2005 return -EINVAL;
1819} 2006}
@@ -1831,8 +2018,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
1831int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, 2018int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
1832 unsigned int mask, int slots) 2019 unsigned int mask, int slots)
1833{ 2020{
1834 if (dai->dai_ops.set_sysclk) 2021 if (dai->ops.set_sysclk)
1835 return dai->dai_ops.set_tdm_slot(dai, mask, slots); 2022 return dai->ops.set_tdm_slot(dai, mask, slots);
1836 else 2023 else
1837 return -EINVAL; 2024 return -EINVAL;
1838} 2025}
@@ -1847,8 +2034,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
1847 */ 2034 */
1848int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) 2035int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
1849{ 2036{
1850 if (dai->dai_ops.set_sysclk) 2037 if (dai->ops.set_sysclk)
1851 return dai->dai_ops.set_tristate(dai, tristate); 2038 return dai->ops.set_tristate(dai, tristate);
1852 else 2039 else
1853 return -EINVAL; 2040 return -EINVAL;
1854} 2041}
@@ -1863,21 +2050,242 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
1863 */ 2050 */
1864int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute) 2051int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
1865{ 2052{
1866 if (dai->dai_ops.digital_mute) 2053 if (dai->ops.digital_mute)
1867 return dai->dai_ops.digital_mute(dai, mute); 2054 return dai->ops.digital_mute(dai, mute);
1868 else 2055 else
1869 return -EINVAL; 2056 return -EINVAL;
1870} 2057}
1871EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); 2058EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
1872 2059
1873static int __devinit snd_soc_init(void) 2060/**
2061 * snd_soc_register_card - Register a card with the ASoC core
2062 *
2063 * @param card Card to register
2064 *
2065 * Note that currently this is an internal only function: it will be
2066 * exposed to machine drivers after further backporting of ASoC v2
2067 * registration APIs.
2068 */
2069static int snd_soc_register_card(struct snd_soc_card *card)
2070{
2071 if (!card->name || !card->dev)
2072 return -EINVAL;
2073
2074 INIT_LIST_HEAD(&card->list);
2075 card->instantiated = 0;
2076
2077 mutex_lock(&client_mutex);
2078 list_add(&card->list, &card_list);
2079 snd_soc_instantiate_cards();
2080 mutex_unlock(&client_mutex);
2081
2082 dev_dbg(card->dev, "Registered card '%s'\n", card->name);
2083
2084 return 0;
2085}
2086
2087/**
2088 * snd_soc_unregister_card - Unregister a card with the ASoC core
2089 *
2090 * @param card Card to unregister
2091 *
2092 * Note that currently this is an internal only function: it will be
2093 * exposed to machine drivers after further backporting of ASoC v2
2094 * registration APIs.
2095 */
2096static int snd_soc_unregister_card(struct snd_soc_card *card)
2097{
2098 mutex_lock(&client_mutex);
2099 list_del(&card->list);
2100 mutex_unlock(&client_mutex);
2101
2102 dev_dbg(card->dev, "Unregistered card '%s'\n", card->name);
2103
2104 return 0;
2105}
2106
2107/**
2108 * snd_soc_register_dai - Register a DAI with the ASoC core
2109 *
2110 * @param dai DAI to register
2111 */
2112int snd_soc_register_dai(struct snd_soc_dai *dai)
2113{
2114 if (!dai->name)
2115 return -EINVAL;
2116
2117 /* The device should become mandatory over time */
2118 if (!dai->dev)
2119 printk(KERN_WARNING "No device for DAI %s\n", dai->name);
2120
2121 INIT_LIST_HEAD(&dai->list);
2122
2123 mutex_lock(&client_mutex);
2124 list_add(&dai->list, &dai_list);
2125 snd_soc_instantiate_cards();
2126 mutex_unlock(&client_mutex);
2127
2128 pr_debug("Registered DAI '%s'\n", dai->name);
2129
2130 return 0;
2131}
2132EXPORT_SYMBOL_GPL(snd_soc_register_dai);
2133
2134/**
2135 * snd_soc_unregister_dai - Unregister a DAI from the ASoC core
2136 *
2137 * @param dai DAI to unregister
2138 */
2139void snd_soc_unregister_dai(struct snd_soc_dai *dai)
2140{
2141 mutex_lock(&client_mutex);
2142 list_del(&dai->list);
2143 mutex_unlock(&client_mutex);
2144
2145 pr_debug("Unregistered DAI '%s'\n", dai->name);
2146}
2147EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
2148
2149/**
2150 * snd_soc_register_dais - Register multiple DAIs with the ASoC core
2151 *
2152 * @param dai Array of DAIs to register
2153 * @param count Number of DAIs
2154 */
2155int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count)
2156{
2157 int i, ret;
2158
2159 for (i = 0; i < count; i++) {
2160 ret = snd_soc_register_dai(&dai[i]);
2161 if (ret != 0)
2162 goto err;
2163 }
2164
2165 return 0;
2166
2167err:
2168 for (i--; i >= 0; i--)
2169 snd_soc_unregister_dai(&dai[i]);
2170
2171 return ret;
2172}
2173EXPORT_SYMBOL_GPL(snd_soc_register_dais);
2174
2175/**
2176 * snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core
2177 *
2178 * @param dai Array of DAIs to unregister
2179 * @param count Number of DAIs
2180 */
2181void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count)
2182{
2183 int i;
2184
2185 for (i = 0; i < count; i++)
2186 snd_soc_unregister_dai(&dai[i]);
2187}
2188EXPORT_SYMBOL_GPL(snd_soc_unregister_dais);
2189
2190/**
2191 * snd_soc_register_platform - Register a platform with the ASoC core
2192 *
2193 * @param platform platform to register
2194 */
2195int snd_soc_register_platform(struct snd_soc_platform *platform)
2196{
2197 if (!platform->name)
2198 return -EINVAL;
2199
2200 INIT_LIST_HEAD(&platform->list);
2201
2202 mutex_lock(&client_mutex);
2203 list_add(&platform->list, &platform_list);
2204 snd_soc_instantiate_cards();
2205 mutex_unlock(&client_mutex);
2206
2207 pr_debug("Registered platform '%s'\n", platform->name);
2208
2209 return 0;
2210}
2211EXPORT_SYMBOL_GPL(snd_soc_register_platform);
2212
2213/**
2214 * snd_soc_unregister_platform - Unregister a platform from the ASoC core
2215 *
2216 * @param platform platform to unregister
2217 */
2218void snd_soc_unregister_platform(struct snd_soc_platform *platform)
1874{ 2219{
1875 printk(KERN_INFO "ASoC version %s\n", SND_SOC_VERSION); 2220 mutex_lock(&client_mutex);
2221 list_del(&platform->list);
2222 mutex_unlock(&client_mutex);
2223
2224 pr_debug("Unregistered platform '%s'\n", platform->name);
2225}
2226EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
2227
2228/**
2229 * snd_soc_register_codec - Register a codec with the ASoC core
2230 *
2231 * @param codec codec to register
2232 */
2233int snd_soc_register_codec(struct snd_soc_codec *codec)
2234{
2235 if (!codec->name)
2236 return -EINVAL;
2237
2238 /* The device should become mandatory over time */
2239 if (!codec->dev)
2240 printk(KERN_WARNING "No device for codec %s\n", codec->name);
2241
2242 INIT_LIST_HEAD(&codec->list);
2243
2244 mutex_lock(&client_mutex);
2245 list_add(&codec->list, &codec_list);
2246 snd_soc_instantiate_cards();
2247 mutex_unlock(&client_mutex);
2248
2249 pr_debug("Registered codec '%s'\n", codec->name);
2250
2251 return 0;
2252}
2253EXPORT_SYMBOL_GPL(snd_soc_register_codec);
2254
2255/**
2256 * snd_soc_unregister_codec - Unregister a codec from the ASoC core
2257 *
2258 * @param codec codec to unregister
2259 */
2260void snd_soc_unregister_codec(struct snd_soc_codec *codec)
2261{
2262 mutex_lock(&client_mutex);
2263 list_del(&codec->list);
2264 mutex_unlock(&client_mutex);
2265
2266 pr_debug("Unregistered codec '%s'\n", codec->name);
2267}
2268EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
2269
2270static int __init snd_soc_init(void)
2271{
2272#ifdef CONFIG_DEBUG_FS
2273 debugfs_root = debugfs_create_dir("asoc", NULL);
2274 if (IS_ERR(debugfs_root) || !debugfs_root) {
2275 printk(KERN_WARNING
2276 "ASoC: Failed to create debugfs directory\n");
2277 debugfs_root = NULL;
2278 }
2279#endif
2280
1876 return platform_driver_register(&soc_driver); 2281 return platform_driver_register(&soc_driver);
1877} 2282}
1878 2283
1879static void snd_soc_exit(void) 2284static void __exit snd_soc_exit(void)
1880{ 2285{
2286#ifdef CONFIG_DEBUG_FS
2287 debugfs_remove_recursive(debugfs_root);
2288#endif
1881 platform_driver_unregister(&soc_driver); 2289 platform_driver_unregister(&soc_driver);
1882} 2290}
1883 2291
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 7351db9606e4..8863eddbac02 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -37,7 +37,6 @@
37#include <linux/bitops.h> 37#include <linux/bitops.h>
38#include <linux/platform_device.h> 38#include <linux/platform_device.h>
39#include <linux/jiffies.h> 39#include <linux/jiffies.h>
40#include <linux/debugfs.h>
41#include <sound/core.h> 40#include <sound/core.h>
42#include <sound/pcm.h> 41#include <sound/pcm.h>
43#include <sound/pcm_params.h> 42#include <sound/pcm_params.h>
@@ -67,17 +66,13 @@ static int dapm_status = 1;
67module_param(dapm_status, int, 0); 66module_param(dapm_status, int, 0);
68MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries"); 67MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries");
69 68
70static struct dentry *asoc_debugfs; 69static void pop_wait(u32 pop_time)
71
72static u32 pop_time;
73
74static void pop_wait(void)
75{ 70{
76 if (pop_time) 71 if (pop_time)
77 schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time)); 72 schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
78} 73}
79 74
80static void pop_dbg(const char *fmt, ...) 75static void pop_dbg(u32 pop_time, const char *fmt, ...)
81{ 76{
82 va_list args; 77 va_list args;
83 78
@@ -85,7 +80,7 @@ static void pop_dbg(const char *fmt, ...)
85 80
86 if (pop_time) { 81 if (pop_time) {
87 vprintk(fmt, args); 82 vprintk(fmt, args);
88 pop_wait(); 83 pop_wait(pop_time);
89 } 84 }
90 85
91 va_end(args); 86 va_end(args);
@@ -230,10 +225,11 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
230 225
231 change = old != new; 226 change = old != new;
232 if (change) { 227 if (change) {
233 pop_dbg("pop test %s : %s in %d ms\n", widget->name, 228 pop_dbg(codec->pop_time, "pop test %s : %s in %d ms\n",
234 widget->power ? "on" : "off", pop_time); 229 widget->name, widget->power ? "on" : "off",
230 codec->pop_time);
235 snd_soc_write(codec, widget->reg, new); 231 snd_soc_write(codec, widget->reg, new);
236 pop_wait(); 232 pop_wait(codec->pop_time);
237 } 233 }
238 pr_debug("reg %x old %x new %x change %d\n", widget->reg, 234 pr_debug("reg %x old %x new %x change %d\n", widget->reg,
239 old, new, change); 235 old, new, change);
@@ -293,7 +289,7 @@ static int dapm_new_mixer(struct snd_soc_codec *codec,
293 struct snd_soc_dapm_widget *w) 289 struct snd_soc_dapm_widget *w)
294{ 290{
295 int i, ret = 0; 291 int i, ret = 0;
296 char name[32]; 292 size_t name_len;
297 struct snd_soc_dapm_path *path; 293 struct snd_soc_dapm_path *path;
298 294
299 /* add kcontrol */ 295 /* add kcontrol */
@@ -307,11 +303,16 @@ static int dapm_new_mixer(struct snd_soc_codec *codec,
307 continue; 303 continue;
308 304
309 /* add dapm control with long name */ 305 /* add dapm control with long name */
310 snprintf(name, 32, "%s %s", w->name, w->kcontrols[i].name); 306 name_len = 2 + strlen(w->name)
311 path->long_name = kstrdup (name, GFP_KERNEL); 307 + strlen(w->kcontrols[i].name);
308 path->long_name = kmalloc(name_len, GFP_KERNEL);
312 if (path->long_name == NULL) 309 if (path->long_name == NULL)
313 return -ENOMEM; 310 return -ENOMEM;
314 311
312 snprintf(path->long_name, name_len, "%s %s",
313 w->name, w->kcontrols[i].name);
314 path->long_name[name_len - 1] = '\0';
315
315 path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, 316 path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
316 path->long_name); 317 path->long_name);
317 ret = snd_ctl_add(codec->card, path->kcontrol); 318 ret = snd_ctl_add(codec->card, path->kcontrol);
@@ -821,23 +822,9 @@ static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
821 822
822int snd_soc_dapm_sys_add(struct device *dev) 823int snd_soc_dapm_sys_add(struct device *dev)
823{ 824{
824 int ret = 0;
825
826 if (!dapm_status) 825 if (!dapm_status)
827 return 0; 826 return 0;
828 827 return device_create_file(dev, &dev_attr_dapm_widget);
829 ret = device_create_file(dev, &dev_attr_dapm_widget);
830 if (ret != 0)
831 return ret;
832
833 asoc_debugfs = debugfs_create_dir("asoc", NULL);
834 if (!IS_ERR(asoc_debugfs) && asoc_debugfs)
835 debugfs_create_u32("dapm_pop_time", 0744, asoc_debugfs,
836 &pop_time);
837 else
838 asoc_debugfs = NULL;
839
840 return 0;
841} 828}
842 829
843static void snd_soc_dapm_sys_remove(struct device *dev) 830static void snd_soc_dapm_sys_remove(struct device *dev)
@@ -845,9 +832,6 @@ static void snd_soc_dapm_sys_remove(struct device *dev)
845 if (dapm_status) { 832 if (dapm_status) {
846 device_remove_file(dev, &dev_attr_dapm_widget); 833 device_remove_file(dev, &dev_attr_dapm_widget);
847 } 834 }
848
849 if (asoc_debugfs)
850 debugfs_remove_recursive(asoc_debugfs);
851} 835}
852 836
853/* free all dapm widgets and resources */ 837/* free all dapm widgets and resources */
@@ -1007,28 +991,6 @@ err:
1007} 991}
1008 992
1009/** 993/**
1010 * snd_soc_dapm_connect_input - connect dapm widgets
1011 * @codec: audio codec
1012 * @sink: name of target widget
1013 * @control: mixer control name
1014 * @source: name of source name
1015 *
1016 * Connects 2 dapm widgets together via a named audio path. The sink is
1017 * the widget receiving the audio signal, whilst the source is the sender
1018 * of the audio signal.
1019 *
1020 * This function has been deprecated in favour of snd_soc_dapm_add_routes().
1021 *
1022 * Returns 0 for success else error.
1023 */
1024int snd_soc_dapm_connect_input(struct snd_soc_codec *codec, const char *sink,
1025 const char *control, const char *source)
1026{
1027 return snd_soc_dapm_add_route(codec, sink, control, source);
1028}
1029EXPORT_SYMBOL_GPL(snd_soc_dapm_connect_input);
1030
1031/**
1032 * snd_soc_dapm_add_routes - Add routes between DAPM widgets 994 * snd_soc_dapm_add_routes - Add routes between DAPM widgets
1033 * @codec: codec 995 * @codec: codec
1034 * @route: audio routes 996 * @route: audio routes
@@ -1358,8 +1320,12 @@ int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
1358 1320
1359 for (i = 0; i < num; i++) { 1321 for (i = 0; i < num; i++) {
1360 ret = snd_soc_dapm_new_control(codec, widget); 1322 ret = snd_soc_dapm_new_control(codec, widget);
1361 if (ret < 0) 1323 if (ret < 0) {
1324 printk(KERN_ERR
1325 "ASoC: Failed to create DAPM control %s: %d\n",
1326 widget->name, ret);
1362 return ret; 1327 return ret;
1328 }
1363 widget++; 1329 widget++;
1364 } 1330 }
1365 return 0; 1331 return 0;
@@ -1440,11 +1406,11 @@ int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
1440 enum snd_soc_bias_level level) 1406 enum snd_soc_bias_level level)
1441{ 1407{
1442 struct snd_soc_codec *codec = socdev->codec; 1408 struct snd_soc_codec *codec = socdev->codec;
1443 struct snd_soc_machine *machine = socdev->machine; 1409 struct snd_soc_card *card = socdev->card;
1444 int ret = 0; 1410 int ret = 0;
1445 1411
1446 if (machine->set_bias_level) 1412 if (card->set_bias_level)
1447 ret = machine->set_bias_level(machine, level); 1413 ret = card->set_bias_level(card, level);
1448 if (ret == 0 && codec->set_bias_level) 1414 if (ret == 0 && codec->set_bias_level)
1449 ret = codec->set_bias_level(codec, level); 1415 ret = codec->set_bias_level(codec, level);
1450 1416