diff options
Diffstat (limited to 'sound/soc/s3c24xx')
-rw-r--r-- | sound/soc/s3c24xx/Kconfig | 12 | ||||
-rw-r--r-- | sound/soc/s3c24xx/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/s3c24xx/jive_wm8750.c | 7 | ||||
-rw-r--r-- | sound/soc/s3c24xx/neo1973_gta02_wm8753.c | 8 | ||||
-rw-r--r-- | sound/soc/s3c24xx/regs-i2s-v2.h | 115 | ||||
-rw-r--r-- | sound/soc/s3c24xx/s3c-i2s-v2.c | 205 | ||||
-rw-r--r-- | sound/soc/s3c24xx/s3c-i2s-v2.h | 15 | ||||
-rw-r--r-- | sound/soc/s3c24xx/s3c2412-i2s.c | 77 | ||||
-rw-r--r-- | sound/soc/s3c24xx/s3c2412-i2s.h | 6 | ||||
-rw-r--r-- | sound/soc/s3c24xx/s3c64xx-i2s-v4.c | 209 | ||||
-rw-r--r-- | sound/soc/s3c24xx/s3c64xx-i2s.c | 69 | ||||
-rw-r--r-- | sound/soc/s3c24xx/s3c64xx-i2s.h | 18 | ||||
-rw-r--r-- | sound/soc/s3c24xx/smdk64xx_wm8580.c | 6 |
13 files changed, 533 insertions, 216 deletions
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig index 15fe57e5a232..2a7cc222d098 100644 --- a/sound/soc/s3c24xx/Kconfig +++ b/sound/soc/s3c24xx/Kconfig | |||
@@ -24,6 +24,11 @@ config SND_S3C64XX_SOC_I2S | |||
24 | select SND_S3C_I2SV2_SOC | 24 | select SND_S3C_I2SV2_SOC |
25 | select S3C64XX_DMA | 25 | select S3C64XX_DMA |
26 | 26 | ||
27 | config SND_S3C64XX_SOC_I2S_V4 | ||
28 | tristate | ||
29 | select SND_S3C_I2SV2_SOC | ||
30 | select S3C64XX_DMA | ||
31 | |||
27 | config SND_S3C_SOC_PCM | 32 | config SND_S3C_SOC_PCM |
28 | tristate | 33 | tristate |
29 | 34 | ||
@@ -59,12 +64,11 @@ config SND_S3C24XX_SOC_JIVE_WM8750 | |||
59 | 64 | ||
60 | config SND_S3C64XX_SOC_WM8580 | 65 | config SND_S3C64XX_SOC_WM8580 |
61 | tristate "SoC I2S Audio support for WM8580 on SMDK64XX" | 66 | tristate "SoC I2S Audio support for WM8580 on SMDK64XX" |
62 | depends on SND_S3C24XX_SOC && (MACH_SMDK6400 || MACH_SMDK6410) | 67 | depends on SND_S3C24XX_SOC && MACH_SMDK6410 |
63 | depends on BROKEN | ||
64 | select SND_SOC_WM8580 | 68 | select SND_SOC_WM8580 |
65 | select SND_S3C64XX_SOC_I2S | 69 | select SND_S3C64XX_SOC_I2S_V4 |
66 | help | 70 | help |
67 | Sat Y if you want to add support for SoC audio on the SMDK64XX. | 71 | Say Y if you want to add support for SoC audio on the SMDK6410. |
68 | 72 | ||
69 | config SND_S3C24XX_SOC_SMDK2443_WM9710 | 73 | config SND_S3C24XX_SOC_SMDK2443_WM9710 |
70 | tristate "SoC AC97 Audio support for SMDK2443 - WM9710" | 74 | tristate "SoC AC97 Audio support for SMDK2443 - WM9710" |
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile index df071a376fa2..81d8dc503f87 100644 --- a/sound/soc/s3c24xx/Makefile +++ b/sound/soc/s3c24xx/Makefile | |||
@@ -4,6 +4,7 @@ snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o | |||
4 | snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o | 4 | snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o |
5 | snd-soc-s3c64xx-i2s-objs := s3c64xx-i2s.o | 5 | snd-soc-s3c64xx-i2s-objs := s3c64xx-i2s.o |
6 | snd-soc-s3c-ac97-objs := s3c-ac97.o | 6 | snd-soc-s3c-ac97-objs := s3c-ac97.o |
7 | snd-soc-s3c64xx-i2s-v4-objs := s3c64xx-i2s-v4.o | ||
7 | snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o | 8 | snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o |
8 | snd-soc-s3c-pcm-objs := s3c-pcm.o | 9 | snd-soc-s3c-pcm-objs := s3c-pcm.o |
9 | 10 | ||
@@ -12,6 +13,7 @@ obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o | |||
12 | obj-$(CONFIG_SND_S3C_SOC_AC97) += snd-soc-s3c-ac97.o | 13 | obj-$(CONFIG_SND_S3C_SOC_AC97) += snd-soc-s3c-ac97.o |
13 | obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o | 14 | obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o |
14 | obj-$(CONFIG_SND_S3C64XX_SOC_I2S) += snd-soc-s3c64xx-i2s.o | 15 | obj-$(CONFIG_SND_S3C64XX_SOC_I2S) += snd-soc-s3c64xx-i2s.o |
16 | obj-$(CONFIG_SND_S3C64XX_SOC_I2S_V4) += snd-soc-s3c64xx-i2s-v4.o | ||
15 | obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o | 17 | obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o |
16 | obj-$(CONFIG_SND_S3C_SOC_PCM) += snd-soc-s3c-pcm.o | 18 | obj-$(CONFIG_SND_S3C_SOC_PCM) += snd-soc-s3c-pcm.o |
17 | 19 | ||
diff --git a/sound/soc/s3c24xx/jive_wm8750.c b/sound/soc/s3c24xx/jive_wm8750.c index 59dc2c6b56d9..8c108b121c10 100644 --- a/sound/soc/s3c24xx/jive_wm8750.c +++ b/sound/soc/s3c24xx/jive_wm8750.c | |||
@@ -70,7 +70,7 @@ static int jive_hw_params(struct snd_pcm_substream *substream, | |||
70 | } | 70 | } |
71 | 71 | ||
72 | s3c_i2sv2_iis_calc_rate(&div, NULL, params_rate(params), | 72 | s3c_i2sv2_iis_calc_rate(&div, NULL, params_rate(params), |
73 | s3c2412_get_iisclk()); | 73 | s3c_i2sv2_get_clock(cpu_dai)); |
74 | 74 | ||
75 | /* set codec DAI configuration */ | 75 | /* set codec DAI configuration */ |
76 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | 76 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | |
@@ -152,15 +152,10 @@ static struct snd_soc_card snd_soc_machine_jive = { | |||
152 | .num_links = 1, | 152 | .num_links = 1, |
153 | }; | 153 | }; |
154 | 154 | ||
155 | /* jive audio private data */ | ||
156 | static struct wm8750_setup_data jive_wm8750_setup = { | ||
157 | }; | ||
158 | |||
159 | /* jive audio subsystem */ | 155 | /* jive audio subsystem */ |
160 | static struct snd_soc_device jive_snd_devdata = { | 156 | static struct snd_soc_device jive_snd_devdata = { |
161 | .card = &snd_soc_machine_jive, | 157 | .card = &snd_soc_machine_jive, |
162 | .codec_dev = &soc_codec_dev_wm8750, | 158 | .codec_dev = &soc_codec_dev_wm8750, |
163 | .codec_data = &jive_wm8750_setup, | ||
164 | }; | 159 | }; |
165 | 160 | ||
166 | static struct platform_device *jive_snd_device; | 161 | static struct platform_device *jive_snd_device; |
diff --git a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c index dea83d30a5c9..209c25994c7e 100644 --- a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c +++ b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c | |||
@@ -362,6 +362,14 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) | |||
362 | snd_soc_dapm_disable_pin(codec, "Handset Mic"); | 362 | snd_soc_dapm_disable_pin(codec, "Handset Mic"); |
363 | snd_soc_dapm_disable_pin(codec, "Handset Spk"); | 363 | snd_soc_dapm_disable_pin(codec, "Handset Spk"); |
364 | 364 | ||
365 | /* allow audio paths from the GSM modem to run during suspend */ | ||
366 | snd_soc_dapm_ignore_suspend(codec, "Stereo Out"); | ||
367 | snd_soc_dapm_ignore_suspend(codec, "GSM Line Out"); | ||
368 | snd_soc_dapm_ignore_suspend(codec, "GSM Line In"); | ||
369 | snd_soc_dapm_ignore_suspend(codec, "Headset Mic"); | ||
370 | snd_soc_dapm_ignore_suspend(codec, "Handset Mic"); | ||
371 | snd_soc_dapm_ignore_suspend(codec, "Handset Spk"); | ||
372 | |||
365 | snd_soc_dapm_sync(codec); | 373 | snd_soc_dapm_sync(codec); |
366 | 374 | ||
367 | return 0; | 375 | return 0; |
diff --git a/sound/soc/s3c24xx/regs-i2s-v2.h b/sound/soc/s3c24xx/regs-i2s-v2.h new file mode 100644 index 000000000000..5e5e5680580b --- /dev/null +++ b/sound/soc/s3c24xx/regs-i2s-v2.h | |||
@@ -0,0 +1,115 @@ | |||
1 | /* linux/include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h | ||
2 | * | ||
3 | * Copyright 2007 Simtec Electronics <linux@simtec.co.uk> | ||
4 | * http://armlinux.simtec.co.uk/ | ||
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 | * S3C2412 IIS register definition | ||
11 | */ | ||
12 | |||
13 | #ifndef __ASM_ARCH_REGS_S3C2412_IIS_H | ||
14 | #define __ASM_ARCH_REGS_S3C2412_IIS_H | ||
15 | |||
16 | #define S3C2412_IISCON (0x00) | ||
17 | #define S3C2412_IISMOD (0x04) | ||
18 | #define S3C2412_IISFIC (0x08) | ||
19 | #define S3C2412_IISPSR (0x0C) | ||
20 | #define S3C2412_IISTXD (0x10) | ||
21 | #define S3C2412_IISRXD (0x14) | ||
22 | |||
23 | #define S5PC1XX_IISFICS 0x18 | ||
24 | #define S5PC1XX_IISTXDS 0x1C | ||
25 | |||
26 | #define S5PC1XX_IISCON_SW_RST (1 << 31) | ||
27 | #define S5PC1XX_IISCON_FRXOFSTATUS (1 << 26) | ||
28 | #define S5PC1XX_IISCON_FRXORINTEN (1 << 25) | ||
29 | #define S5PC1XX_IISCON_FTXSURSTAT (1 << 24) | ||
30 | #define S5PC1XX_IISCON_FTXSURINTEN (1 << 23) | ||
31 | #define S5PC1XX_IISCON_TXSDMAPAUSE (1 << 20) | ||
32 | #define S5PC1XX_IISCON_TXSDMACTIVE (1 << 18) | ||
33 | |||
34 | #define S3C64XX_IISCON_FTXURSTATUS (1 << 17) | ||
35 | #define S3C64XX_IISCON_FTXURINTEN (1 << 16) | ||
36 | #define S3C64XX_IISCON_TXFIFO2_EMPTY (1 << 15) | ||
37 | #define S3C64XX_IISCON_TXFIFO1_EMPTY (1 << 14) | ||
38 | #define S3C64XX_IISCON_TXFIFO2_FULL (1 << 13) | ||
39 | #define S3C64XX_IISCON_TXFIFO1_FULL (1 << 12) | ||
40 | |||
41 | #define S3C2412_IISCON_LRINDEX (1 << 11) | ||
42 | #define S3C2412_IISCON_TXFIFO_EMPTY (1 << 10) | ||
43 | #define S3C2412_IISCON_RXFIFO_EMPTY (1 << 9) | ||
44 | #define S3C2412_IISCON_TXFIFO_FULL (1 << 8) | ||
45 | #define S3C2412_IISCON_RXFIFO_FULL (1 << 7) | ||
46 | #define S3C2412_IISCON_TXDMA_PAUSE (1 << 6) | ||
47 | #define S3C2412_IISCON_RXDMA_PAUSE (1 << 5) | ||
48 | #define S3C2412_IISCON_TXCH_PAUSE (1 << 4) | ||
49 | #define S3C2412_IISCON_RXCH_PAUSE (1 << 3) | ||
50 | #define S3C2412_IISCON_TXDMA_ACTIVE (1 << 2) | ||
51 | #define S3C2412_IISCON_RXDMA_ACTIVE (1 << 1) | ||
52 | #define S3C2412_IISCON_IIS_ACTIVE (1 << 0) | ||
53 | |||
54 | #define S5PC1XX_IISMOD_OPCLK_CDCLK_OUT (0 << 30) | ||
55 | #define S5PC1XX_IISMOD_OPCLK_CDCLK_IN (1 << 30) | ||
56 | #define S5PC1XX_IISMOD_OPCLK_BCLK_OUT (2 << 30) | ||
57 | #define S5PC1XX_IISMOD_OPCLK_PCLK (3 << 30) | ||
58 | #define S5PC1XX_IISMOD_OPCLK_MASK (3 << 30) | ||
59 | #define S5PC1XX_IISMOD_TXS_IDMA (1 << 28) /* Sec_TXFIFO use I-DMA */ | ||
60 | #define S5PC1XX_IISMOD_BLCS_MASK 0x3 | ||
61 | #define S5PC1XX_IISMOD_BLCS_SHIFT 26 | ||
62 | #define S5PC1XX_IISMOD_BLCP_MASK 0x3 | ||
63 | #define S5PC1XX_IISMOD_BLCP_SHIFT 24 | ||
64 | |||
65 | #define S3C64XX_IISMOD_C2DD_HHALF (1 << 21) /* Discard Higher-half */ | ||
66 | #define S3C64XX_IISMOD_C2DD_LHALF (1 << 20) /* Discard Lower-half */ | ||
67 | #define S3C64XX_IISMOD_C1DD_HHALF (1 << 19) | ||
68 | #define S3C64XX_IISMOD_C1DD_LHALF (1 << 18) | ||
69 | #define S3C64XX_IISMOD_DC2_EN (1 << 17) | ||
70 | #define S3C64XX_IISMOD_DC1_EN (1 << 16) | ||
71 | #define S3C64XX_IISMOD_BLC_16BIT (0 << 13) | ||
72 | #define S3C64XX_IISMOD_BLC_8BIT (1 << 13) | ||
73 | #define S3C64XX_IISMOD_BLC_24BIT (2 << 13) | ||
74 | #define S3C64XX_IISMOD_BLC_MASK (3 << 13) | ||
75 | |||
76 | #define S3C2412_IISMOD_IMS_SYSMUX (1 << 10) | ||
77 | #define S3C2412_IISMOD_SLAVE (1 << 11) | ||
78 | #define S3C2412_IISMOD_MODE_TXONLY (0 << 8) | ||
79 | #define S3C2412_IISMOD_MODE_RXONLY (1 << 8) | ||
80 | #define S3C2412_IISMOD_MODE_TXRX (2 << 8) | ||
81 | #define S3C2412_IISMOD_MODE_MASK (3 << 8) | ||
82 | #define S3C2412_IISMOD_LR_LLOW (0 << 7) | ||
83 | #define S3C2412_IISMOD_LR_RLOW (1 << 7) | ||
84 | #define S3C2412_IISMOD_SDF_IIS (0 << 5) | ||
85 | #define S3C2412_IISMOD_SDF_MSB (1 << 5) | ||
86 | #define S3C2412_IISMOD_SDF_LSB (2 << 5) | ||
87 | #define S3C2412_IISMOD_SDF_MASK (3 << 5) | ||
88 | #define S3C2412_IISMOD_RCLK_256FS (0 << 3) | ||
89 | #define S3C2412_IISMOD_RCLK_512FS (1 << 3) | ||
90 | #define S3C2412_IISMOD_RCLK_384FS (2 << 3) | ||
91 | #define S3C2412_IISMOD_RCLK_768FS (3 << 3) | ||
92 | #define S3C2412_IISMOD_RCLK_MASK (3 << 3) | ||
93 | #define S3C2412_IISMOD_BCLK_32FS (0 << 1) | ||
94 | #define S3C2412_IISMOD_BCLK_48FS (1 << 1) | ||
95 | #define S3C2412_IISMOD_BCLK_16FS (2 << 1) | ||
96 | #define S3C2412_IISMOD_BCLK_24FS (3 << 1) | ||
97 | #define S3C2412_IISMOD_BCLK_MASK (3 << 1) | ||
98 | #define S3C2412_IISMOD_8BIT (1 << 0) | ||
99 | |||
100 | #define S3C64XX_IISMOD_CDCLKCON (1 << 12) | ||
101 | |||
102 | #define S3C2412_IISPSR_PSREN (1 << 15) | ||
103 | |||
104 | #define S3C64XX_IISFIC_TX2COUNT(x) (((x) >> 24) & 0xf) | ||
105 | #define S3C64XX_IISFIC_TX1COUNT(x) (((x) >> 16) & 0xf) | ||
106 | |||
107 | #define S3C2412_IISFIC_TXFLUSH (1 << 15) | ||
108 | #define S3C2412_IISFIC_RXFLUSH (1 << 7) | ||
109 | #define S3C2412_IISFIC_TXCOUNT(x) (((x) >> 8) & 0xf) | ||
110 | #define S3C2412_IISFIC_RXCOUNT(x) (((x) >> 0) & 0xf) | ||
111 | |||
112 | #define S5PC1XX_IISFICS_TXFLUSH (1 << 15) | ||
113 | #define S5PC1XX_IISFICS_TXCOUNT(x) (((x) >> 8) & 0x7f) | ||
114 | |||
115 | #endif /* __ASM_ARCH_REGS_S3C2412_IIS_H */ | ||
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c index 88515946b6c0..13311c8cf965 100644 --- a/sound/soc/s3c24xx/s3c-i2s-v2.c +++ b/sound/soc/s3c24xx/s3c-i2s-v2.c | |||
@@ -16,24 +16,17 @@ | |||
16 | * option) any later version. | 16 | * option) any later version. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/device.h> | ||
22 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
23 | #include <linux/clk.h> | 20 | #include <linux/clk.h> |
24 | #include <linux/kernel.h> | ||
25 | #include <linux/io.h> | 21 | #include <linux/io.h> |
26 | 22 | ||
27 | #include <sound/core.h> | ||
28 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
29 | #include <sound/pcm_params.h> | 24 | #include <sound/pcm_params.h> |
30 | #include <sound/initval.h> | ||
31 | #include <sound/soc.h> | 25 | #include <sound/soc.h> |
32 | 26 | ||
33 | #include <plat/regs-s3c2412-iis.h> | ||
34 | |||
35 | #include <mach/dma.h> | 27 | #include <mach/dma.h> |
36 | 28 | ||
29 | #include "regs-i2s-v2.h" | ||
37 | #include "s3c-i2s-v2.h" | 30 | #include "s3c-i2s-v2.h" |
38 | #include "s3c-dma.h" | 31 | #include "s3c-dma.h" |
39 | 32 | ||
@@ -272,35 +265,14 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | |||
272 | iismod = readl(i2s->regs + S3C2412_IISMOD); | 265 | iismod = readl(i2s->regs + S3C2412_IISMOD); |
273 | pr_debug("hw_params r: IISMOD: %x \n", iismod); | 266 | pr_debug("hw_params r: IISMOD: %x \n", iismod); |
274 | 267 | ||
275 | #if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) | ||
276 | #define IISMOD_MASTER_MASK S3C2412_IISMOD_MASTER_MASK | ||
277 | #define IISMOD_SLAVE S3C2412_IISMOD_SLAVE | ||
278 | #define IISMOD_MASTER S3C2412_IISMOD_MASTER_INTERNAL | ||
279 | #endif | ||
280 | |||
281 | #if defined(CONFIG_PLAT_S3C64XX) | ||
282 | /* From Rev1.1 datasheet, we have two master and two slave modes: | ||
283 | * IMS[11:10]: | ||
284 | * 00 = master mode, fed from PCLK | ||
285 | * 01 = master mode, fed from CLKAUDIO | ||
286 | * 10 = slave mode, using PCLK | ||
287 | * 11 = slave mode, using I2SCLK | ||
288 | */ | ||
289 | #define IISMOD_MASTER_MASK (1 << 11) | ||
290 | #define IISMOD_SLAVE (1 << 11) | ||
291 | #define IISMOD_MASTER (0 << 11) | ||
292 | #endif | ||
293 | |||
294 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 268 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
295 | case SND_SOC_DAIFMT_CBM_CFM: | 269 | case SND_SOC_DAIFMT_CBM_CFM: |
296 | i2s->master = 0; | 270 | i2s->master = 0; |
297 | iismod &= ~IISMOD_MASTER_MASK; | 271 | iismod |= S3C2412_IISMOD_SLAVE; |
298 | iismod |= IISMOD_SLAVE; | ||
299 | break; | 272 | break; |
300 | case SND_SOC_DAIFMT_CBS_CFS: | 273 | case SND_SOC_DAIFMT_CBS_CFS: |
301 | i2s->master = 1; | 274 | i2s->master = 1; |
302 | iismod &= ~IISMOD_MASTER_MASK; | 275 | iismod &= ~S3C2412_IISMOD_SLAVE; |
303 | iismod |= IISMOD_MASTER; | ||
304 | break; | 276 | break; |
305 | default: | 277 | default: |
306 | pr_err("unknwon master/slave format\n"); | 278 | pr_err("unknwon master/slave format\n"); |
@@ -332,7 +304,7 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | |||
332 | return 0; | 304 | return 0; |
333 | } | 305 | } |
334 | 306 | ||
335 | static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, | 307 | static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream, |
336 | struct snd_pcm_hw_params *params, | 308 | struct snd_pcm_hw_params *params, |
337 | struct snd_soc_dai *socdai) | 309 | struct snd_soc_dai *socdai) |
338 | { | 310 | { |
@@ -355,37 +327,67 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, | |||
355 | iismod = readl(i2s->regs + S3C2412_IISMOD); | 327 | iismod = readl(i2s->regs + S3C2412_IISMOD); |
356 | pr_debug("%s: r: IISMOD: %x\n", __func__, iismod); | 328 | pr_debug("%s: r: IISMOD: %x\n", __func__, iismod); |
357 | 329 | ||
358 | #if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) | 330 | iismod &= ~S3C64XX_IISMOD_BLC_MASK; |
331 | /* Sample size */ | ||
359 | switch (params_format(params)) { | 332 | switch (params_format(params)) { |
360 | case SNDRV_PCM_FORMAT_S8: | 333 | case SNDRV_PCM_FORMAT_S8: |
361 | iismod |= S3C2412_IISMOD_8BIT; | 334 | iismod |= S3C64XX_IISMOD_BLC_8BIT; |
362 | break; | 335 | break; |
363 | case SNDRV_PCM_FORMAT_S16_LE: | 336 | case SNDRV_PCM_FORMAT_S16_LE: |
364 | iismod &= ~S3C2412_IISMOD_8BIT; | 337 | break; |
338 | case SNDRV_PCM_FORMAT_S24_LE: | ||
339 | iismod |= S3C64XX_IISMOD_BLC_24BIT; | ||
365 | break; | 340 | break; |
366 | } | 341 | } |
367 | #endif | ||
368 | 342 | ||
369 | #ifdef CONFIG_PLAT_S3C64XX | 343 | writel(iismod, i2s->regs + S3C2412_IISMOD); |
370 | iismod &= ~(S3C64XX_IISMOD_BLC_MASK | S3C2412_IISMOD_BCLK_MASK); | 344 | pr_debug("%s: w: IISMOD: %x\n", __func__, iismod); |
371 | /* Sample size */ | 345 | |
372 | switch (params_format(params)) { | 346 | return 0; |
373 | case SNDRV_PCM_FORMAT_S8: | 347 | } |
374 | /* 8 bit sample, 16fs BCLK */ | 348 | |
375 | iismod |= (S3C64XX_IISMOD_BLC_8BIT | S3C2412_IISMOD_BCLK_16FS); | 349 | static int s3c_i2sv2_set_sysclk(struct snd_soc_dai *cpu_dai, |
350 | int clk_id, unsigned int freq, int dir) | ||
351 | { | ||
352 | struct s3c_i2sv2_info *i2s = to_info(cpu_dai); | ||
353 | u32 iismod = readl(i2s->regs + S3C2412_IISMOD); | ||
354 | |||
355 | pr_debug("Entered %s\n", __func__); | ||
356 | pr_debug("%s r: IISMOD: %x\n", __func__, iismod); | ||
357 | |||
358 | switch (clk_id) { | ||
359 | case S3C_I2SV2_CLKSRC_PCLK: | ||
360 | iismod &= ~S3C2412_IISMOD_IMS_SYSMUX; | ||
376 | break; | 361 | break; |
377 | case SNDRV_PCM_FORMAT_S16_LE: | 362 | |
378 | /* 16 bit sample, 32fs BCLK */ | 363 | case S3C_I2SV2_CLKSRC_AUDIOBUS: |
364 | iismod |= S3C2412_IISMOD_IMS_SYSMUX; | ||
379 | break; | 365 | break; |
380 | case SNDRV_PCM_FORMAT_S24_LE: | 366 | |
381 | /* 24 bit sample, 48fs BCLK */ | 367 | case S3C_I2SV2_CLKSRC_CDCLK: |
382 | iismod |= (S3C64XX_IISMOD_BLC_24BIT | S3C2412_IISMOD_BCLK_48FS); | 368 | /* Error if controller doesn't have the CDCLKCON bit */ |
369 | if (!(i2s->feature & S3C_FEATURE_CDCLKCON)) | ||
370 | return -EINVAL; | ||
371 | |||
372 | switch (dir) { | ||
373 | case SND_SOC_CLOCK_IN: | ||
374 | iismod |= S3C64XX_IISMOD_CDCLKCON; | ||
375 | break; | ||
376 | case SND_SOC_CLOCK_OUT: | ||
377 | iismod &= ~S3C64XX_IISMOD_CDCLKCON; | ||
378 | break; | ||
379 | default: | ||
380 | return -EINVAL; | ||
381 | } | ||
383 | break; | 382 | break; |
383 | |||
384 | default: | ||
385 | return -EINVAL; | ||
384 | } | 386 | } |
385 | #endif | ||
386 | 387 | ||
387 | writel(iismod, i2s->regs + S3C2412_IISMOD); | 388 | writel(iismod, i2s->regs + S3C2412_IISMOD); |
388 | pr_debug("%s: w: IISMOD: %x\n", __func__, iismod); | 389 | pr_debug("%s w: IISMOD: %x\n", __func__, iismod); |
390 | |||
389 | return 0; | 391 | return 0; |
390 | } | 392 | } |
391 | 393 | ||
@@ -472,29 +474,25 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, | |||
472 | 474 | ||
473 | switch (div_id) { | 475 | switch (div_id) { |
474 | case S3C_I2SV2_DIV_BCLK: | 476 | case S3C_I2SV2_DIV_BCLK: |
475 | if (div > 3) { | 477 | switch (div) { |
476 | /* convert value to bit field */ | 478 | case 16: |
477 | 479 | div = S3C2412_IISMOD_BCLK_16FS; | |
478 | switch (div) { | 480 | break; |
479 | case 16: | ||
480 | div = S3C2412_IISMOD_BCLK_16FS; | ||
481 | break; | ||
482 | 481 | ||
483 | case 32: | 482 | case 32: |
484 | div = S3C2412_IISMOD_BCLK_32FS; | 483 | div = S3C2412_IISMOD_BCLK_32FS; |
485 | break; | 484 | break; |
486 | 485 | ||
487 | case 24: | 486 | case 24: |
488 | div = S3C2412_IISMOD_BCLK_24FS; | 487 | div = S3C2412_IISMOD_BCLK_24FS; |
489 | break; | 488 | break; |
490 | 489 | ||
491 | case 48: | 490 | case 48: |
492 | div = S3C2412_IISMOD_BCLK_48FS; | 491 | div = S3C2412_IISMOD_BCLK_48FS; |
493 | break; | 492 | break; |
494 | 493 | ||
495 | default: | 494 | default: |
496 | return -EINVAL; | 495 | return -EINVAL; |
497 | } | ||
498 | } | 496 | } |
499 | 497 | ||
500 | reg = readl(i2s->regs + S3C2412_IISMOD); | 498 | reg = readl(i2s->regs + S3C2412_IISMOD); |
@@ -505,29 +503,25 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, | |||
505 | break; | 503 | break; |
506 | 504 | ||
507 | case S3C_I2SV2_DIV_RCLK: | 505 | case S3C_I2SV2_DIV_RCLK: |
508 | if (div > 3) { | 506 | switch (div) { |
509 | /* convert value to bit field */ | 507 | case 256: |
510 | 508 | div = S3C2412_IISMOD_RCLK_256FS; | |
511 | switch (div) { | 509 | break; |
512 | case 256: | ||
513 | div = S3C2412_IISMOD_RCLK_256FS; | ||
514 | break; | ||
515 | 510 | ||
516 | case 384: | 511 | case 384: |
517 | div = S3C2412_IISMOD_RCLK_384FS; | 512 | div = S3C2412_IISMOD_RCLK_384FS; |
518 | break; | 513 | break; |
519 | 514 | ||
520 | case 512: | 515 | case 512: |
521 | div = S3C2412_IISMOD_RCLK_512FS; | 516 | div = S3C2412_IISMOD_RCLK_512FS; |
522 | break; | 517 | break; |
523 | 518 | ||
524 | case 768: | 519 | case 768: |
525 | div = S3C2412_IISMOD_RCLK_768FS; | 520 | div = S3C2412_IISMOD_RCLK_768FS; |
526 | break; | 521 | break; |
527 | 522 | ||
528 | default: | 523 | default: |
529 | return -EINVAL; | 524 | return -EINVAL; |
530 | } | ||
531 | } | 525 | } |
532 | 526 | ||
533 | reg = readl(i2s->regs + S3C2412_IISMOD); | 527 | reg = readl(i2s->regs + S3C2412_IISMOD); |
@@ -553,6 +547,33 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, | |||
553 | return 0; | 547 | return 0; |
554 | } | 548 | } |
555 | 549 | ||
550 | static snd_pcm_sframes_t s3c2412_i2s_delay(struct snd_pcm_substream *substream, | ||
551 | struct snd_soc_dai *dai) | ||
552 | { | ||
553 | struct s3c_i2sv2_info *i2s = to_info(dai); | ||
554 | u32 reg = readl(i2s->regs + S3C2412_IISFIC); | ||
555 | snd_pcm_sframes_t delay; | ||
556 | |||
557 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
558 | delay = S3C2412_IISFIC_TXCOUNT(reg); | ||
559 | else | ||
560 | delay = S3C2412_IISFIC_RXCOUNT(reg); | ||
561 | |||
562 | return delay; | ||
563 | } | ||
564 | |||
565 | struct clk *s3c_i2sv2_get_clock(struct snd_soc_dai *cpu_dai) | ||
566 | { | ||
567 | struct s3c_i2sv2_info *i2s = to_info(cpu_dai); | ||
568 | u32 iismod = readl(i2s->regs + S3C2412_IISMOD); | ||
569 | |||
570 | if (iismod & S3C2412_IISMOD_IMS_SYSMUX) | ||
571 | return i2s->iis_cclk; | ||
572 | else | ||
573 | return i2s->iis_pclk; | ||
574 | } | ||
575 | EXPORT_SYMBOL_GPL(s3c_i2sv2_get_clock); | ||
576 | |||
556 | /* default table of all avaialable root fs divisors */ | 577 | /* default table of all avaialable root fs divisors */ |
557 | static unsigned int iis_fs_tab[] = { 256, 512, 384, 768 }; | 578 | static unsigned int iis_fs_tab[] = { 256, 512, 384, 768 }; |
558 | 579 | ||
@@ -735,9 +756,15 @@ int s3c_i2sv2_register_dai(struct snd_soc_dai *dai) | |||
735 | struct snd_soc_dai_ops *ops = dai->ops; | 756 | struct snd_soc_dai_ops *ops = dai->ops; |
736 | 757 | ||
737 | ops->trigger = s3c2412_i2s_trigger; | 758 | ops->trigger = s3c2412_i2s_trigger; |
738 | ops->hw_params = s3c2412_i2s_hw_params; | 759 | if (!ops->hw_params) |
760 | ops->hw_params = s3c_i2sv2_hw_params; | ||
739 | ops->set_fmt = s3c2412_i2s_set_fmt; | 761 | ops->set_fmt = s3c2412_i2s_set_fmt; |
740 | ops->set_clkdiv = s3c2412_i2s_set_clkdiv; | 762 | ops->set_clkdiv = s3c2412_i2s_set_clkdiv; |
763 | ops->set_sysclk = s3c_i2sv2_set_sysclk; | ||
764 | |||
765 | /* Allow overriding by (for example) IISv4 */ | ||
766 | if (!ops->delay) | ||
767 | ops->delay = s3c2412_i2s_delay; | ||
741 | 768 | ||
742 | dai->suspend = s3c2412_i2s_suspend; | 769 | dai->suspend = s3c2412_i2s_suspend; |
743 | dai->resume = s3c2412_i2s_resume; | 770 | dai->resume = s3c2412_i2s_resume; |
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.h b/sound/soc/s3c24xx/s3c-i2s-v2.h index ecf8eaaed1db..766f43a13d8b 100644 --- a/sound/soc/s3c24xx/s3c-i2s-v2.h +++ b/sound/soc/s3c24xx/s3c-i2s-v2.h | |||
@@ -25,10 +25,20 @@ | |||
25 | #define S3C_I2SV2_DIV_RCLK (2) | 25 | #define S3C_I2SV2_DIV_RCLK (2) |
26 | #define S3C_I2SV2_DIV_PRESCALER (3) | 26 | #define S3C_I2SV2_DIV_PRESCALER (3) |
27 | 27 | ||
28 | #define S3C_I2SV2_CLKSRC_PCLK 0 | ||
29 | #define S3C_I2SV2_CLKSRC_AUDIOBUS 1 | ||
30 | #define S3C_I2SV2_CLKSRC_CDCLK 2 | ||
31 | |||
32 | /* Set this flag for I2S controllers that have the bit IISMOD[12] | ||
33 | * bridge/break RCLK signal and external Xi2sCDCLK pin. | ||
34 | */ | ||
35 | #define S3C_FEATURE_CDCLKCON (1 << 0) | ||
36 | |||
28 | /** | 37 | /** |
29 | * struct s3c_i2sv2_info - S3C I2S-V2 information | 38 | * struct s3c_i2sv2_info - S3C I2S-V2 information |
30 | * @dev: The parent device passed to use from the probe. | 39 | * @dev: The parent device passed to use from the probe. |
31 | * @regs: The pointer to the device registe block. | 40 | * @regs: The pointer to the device registe block. |
41 | * @feature: Set of bit-flags indicating features of the controller. | ||
32 | * @master: True if the I2S core is the I2S bit clock master. | 42 | * @master: True if the I2S core is the I2S bit clock master. |
33 | * @dma_playback: DMA information for playback channel. | 43 | * @dma_playback: DMA information for playback channel. |
34 | * @dma_capture: DMA information for capture channel. | 44 | * @dma_capture: DMA information for capture channel. |
@@ -43,9 +53,10 @@ struct s3c_i2sv2_info { | |||
43 | struct device *dev; | 53 | struct device *dev; |
44 | void __iomem *regs; | 54 | void __iomem *regs; |
45 | 55 | ||
56 | u32 feature; | ||
57 | |||
46 | struct clk *iis_pclk; | 58 | struct clk *iis_pclk; |
47 | struct clk *iis_cclk; | 59 | struct clk *iis_cclk; |
48 | struct clk *iis_clk; | ||
49 | 60 | ||
50 | unsigned char master; | 61 | unsigned char master; |
51 | 62 | ||
@@ -57,6 +68,8 @@ struct s3c_i2sv2_info { | |||
57 | u32 suspend_iispsr; | 68 | u32 suspend_iispsr; |
58 | }; | 69 | }; |
59 | 70 | ||
71 | extern struct clk *s3c_i2sv2_get_clock(struct snd_soc_dai *cpu_dai); | ||
72 | |||
60 | struct s3c_i2sv2_rate_calc { | 73 | struct s3c_i2sv2_rate_calc { |
61 | unsigned int clk_div; /* for prescaler */ | 74 | unsigned int clk_div; /* for prescaler */ |
62 | unsigned int fs_div; /* for root frame clock */ | 75 | unsigned int fs_div; /* for root frame clock */ |
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c index 359e59346ba2..709adef9d043 100644 --- a/sound/soc/s3c24xx/s3c2412-i2s.c +++ b/sound/soc/s3c24xx/s3c2412-i2s.c | |||
@@ -32,12 +32,11 @@ | |||
32 | #include <sound/soc.h> | 32 | #include <sound/soc.h> |
33 | #include <mach/hardware.h> | 33 | #include <mach/hardware.h> |
34 | 34 | ||
35 | #include <plat/regs-s3c2412-iis.h> | ||
36 | |||
37 | #include <mach/regs-gpio.h> | 35 | #include <mach/regs-gpio.h> |
38 | #include <mach/dma.h> | 36 | #include <mach/dma.h> |
39 | 37 | ||
40 | #include "s3c-dma.h" | 38 | #include "s3c-dma.h" |
39 | #include "regs-i2s-v2.h" | ||
41 | #include "s3c2412-i2s.h" | 40 | #include "s3c2412-i2s.h" |
42 | 41 | ||
43 | #define S3C2412_I2S_DEBUG 0 | 42 | #define S3C2412_I2S_DEBUG 0 |
@@ -66,44 +65,11 @@ static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = { | |||
66 | 65 | ||
67 | static struct s3c_i2sv2_info s3c2412_i2s; | 66 | static struct s3c_i2sv2_info s3c2412_i2s; |
68 | 67 | ||
69 | /* | 68 | static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) |
70 | * Set S3C2412 Clock source | ||
71 | */ | ||
72 | static int s3c2412_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, | ||
73 | int clk_id, unsigned int freq, int dir) | ||
74 | { | 69 | { |
75 | u32 iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD); | 70 | return cpu_dai->private_data; |
76 | |||
77 | pr_debug("%s(%p, %d, %u, %d)\n", __func__, cpu_dai, clk_id, | ||
78 | freq, dir); | ||
79 | |||
80 | switch (clk_id) { | ||
81 | case S3C2412_CLKSRC_PCLK: | ||
82 | s3c2412_i2s.master = 1; | ||
83 | iismod &= ~S3C2412_IISMOD_MASTER_MASK; | ||
84 | iismod |= S3C2412_IISMOD_MASTER_INTERNAL; | ||
85 | break; | ||
86 | case S3C2412_CLKSRC_I2SCLK: | ||
87 | s3c2412_i2s.master = 0; | ||
88 | iismod &= ~S3C2412_IISMOD_MASTER_MASK; | ||
89 | iismod |= S3C2412_IISMOD_MASTER_EXTERNAL; | ||
90 | break; | ||
91 | default: | ||
92 | return -EINVAL; | ||
93 | } | ||
94 | |||
95 | writel(iismod, s3c2412_i2s.regs + S3C2412_IISMOD); | ||
96 | return 0; | ||
97 | } | 71 | } |
98 | 72 | ||
99 | |||
100 | struct clk *s3c2412_get_iisclk(void) | ||
101 | { | ||
102 | return s3c2412_i2s.iis_clk; | ||
103 | } | ||
104 | EXPORT_SYMBOL_GPL(s3c2412_get_iisclk); | ||
105 | |||
106 | |||
107 | static int s3c2412_i2s_probe(struct platform_device *pdev, | 73 | static int s3c2412_i2s_probe(struct platform_device *pdev, |
108 | struct snd_soc_dai *dai) | 74 | struct snd_soc_dai *dai) |
109 | { | 75 | { |
@@ -142,13 +108,48 @@ static int s3c2412_i2s_probe(struct platform_device *pdev, | |||
142 | return 0; | 108 | return 0; |
143 | } | 109 | } |
144 | 110 | ||
111 | static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, | ||
112 | struct snd_pcm_hw_params *params, | ||
113 | struct snd_soc_dai *cpu_dai) | ||
114 | { | ||
115 | struct s3c_i2sv2_info *i2s = to_info(cpu_dai); | ||
116 | struct s3c_dma_params *dma_data; | ||
117 | u32 iismod; | ||
118 | |||
119 | pr_debug("Entered %s\n", __func__); | ||
120 | |||
121 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
122 | dma_data = i2s->dma_playback; | ||
123 | else | ||
124 | dma_data = i2s->dma_capture; | ||
125 | |||
126 | snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); | ||
127 | |||
128 | iismod = readl(i2s->regs + S3C2412_IISMOD); | ||
129 | pr_debug("%s: r: IISMOD: %x\n", __func__, iismod); | ||
130 | |||
131 | switch (params_format(params)) { | ||
132 | case SNDRV_PCM_FORMAT_S8: | ||
133 | iismod |= S3C2412_IISMOD_8BIT; | ||
134 | break; | ||
135 | case SNDRV_PCM_FORMAT_S16_LE: | ||
136 | iismod &= ~S3C2412_IISMOD_8BIT; | ||
137 | break; | ||
138 | } | ||
139 | |||
140 | writel(iismod, i2s->regs + S3C2412_IISMOD); | ||
141 | pr_debug("%s: w: IISMOD: %x\n", __func__, iismod); | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
145 | #define S3C2412_I2S_RATES \ | 146 | #define S3C2412_I2S_RATES \ |
146 | (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ | 147 | (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ |
147 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | 148 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ |
148 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) | 149 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) |
149 | 150 | ||
150 | static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = { | 151 | static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = { |
151 | .set_sysclk = s3c2412_i2s_set_sysclk, | 152 | .hw_params = s3c2412_i2s_hw_params, |
152 | }; | 153 | }; |
153 | 154 | ||
154 | struct snd_soc_dai s3c2412_i2s_dai = { | 155 | struct snd_soc_dai s3c2412_i2s_dai = { |
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.h b/sound/soc/s3c24xx/s3c2412-i2s.h index 92848e54be16..0b5686b4d5c3 100644 --- a/sound/soc/s3c24xx/s3c2412-i2s.h +++ b/sound/soc/s3c24xx/s3c2412-i2s.h | |||
@@ -21,10 +21,8 @@ | |||
21 | #define S3C2412_DIV_RCLK S3C_I2SV2_DIV_RCLK | 21 | #define S3C2412_DIV_RCLK S3C_I2SV2_DIV_RCLK |
22 | #define S3C2412_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER | 22 | #define S3C2412_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER |
23 | 23 | ||
24 | #define S3C2412_CLKSRC_PCLK (0) | 24 | #define S3C2412_CLKSRC_PCLK S3C_I2SV2_CLKSRC_PCLK |
25 | #define S3C2412_CLKSRC_I2SCLK (1) | 25 | #define S3C2412_CLKSRC_I2SCLK S3C_I2SV2_CLKSRC_AUDIOBUS |
26 | |||
27 | extern struct clk *s3c2412_get_iisclk(void); | ||
28 | 26 | ||
29 | extern struct snd_soc_dai s3c2412_i2s_dai; | 27 | extern struct snd_soc_dai s3c2412_i2s_dai; |
30 | 28 | ||
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c new file mode 100644 index 000000000000..06db130030a1 --- /dev/null +++ b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c | |||
@@ -0,0 +1,209 @@ | |||
1 | /* sound/soc/s3c24xx/s3c64xx-i2s-v4.c | ||
2 | * | ||
3 | * ALSA SoC Audio Layer - S3C64XX I2Sv4 driver | ||
4 | * Copyright (c) 2010 Samsung Electronics Co. Ltd | ||
5 | * Author: Jaswinder Singh <jassi.brar@samsung.com> | ||
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 | #include <linux/clk.h> | ||
13 | #include <linux/gpio.h> | ||
14 | #include <linux/io.h> | ||
15 | |||
16 | #include <sound/soc.h> | ||
17 | #include <sound/pcm_params.h> | ||
18 | |||
19 | #include <mach/gpio-bank-c.h> | ||
20 | #include <mach/gpio-bank-h.h> | ||
21 | #include <plat/gpio-cfg.h> | ||
22 | |||
23 | #include <mach/map.h> | ||
24 | #include <mach/dma.h> | ||
25 | |||
26 | #include "s3c-dma.h" | ||
27 | #include "regs-i2s-v2.h" | ||
28 | #include "s3c64xx-i2s.h" | ||
29 | |||
30 | static struct s3c2410_dma_client s3c64xx_dma_client_out = { | ||
31 | .name = "I2Sv4 PCM Stereo out" | ||
32 | }; | ||
33 | |||
34 | static struct s3c2410_dma_client s3c64xx_dma_client_in = { | ||
35 | .name = "I2Sv4 PCM Stereo in" | ||
36 | }; | ||
37 | |||
38 | static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_out; | ||
39 | static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_in; | ||
40 | static struct s3c_i2sv2_info s3c64xx_i2sv4; | ||
41 | |||
42 | struct snd_soc_dai s3c64xx_i2s_v4_dai; | ||
43 | EXPORT_SYMBOL_GPL(s3c64xx_i2s_v4_dai); | ||
44 | |||
45 | static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) | ||
46 | { | ||
47 | return cpu_dai->private_data; | ||
48 | } | ||
49 | |||
50 | static int s3c64xx_i2sv4_probe(struct platform_device *pdev, | ||
51 | struct snd_soc_dai *dai) | ||
52 | { | ||
53 | /* configure GPIO for i2s port */ | ||
54 | s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C64XX_GPC4_I2S_V40_DO0); | ||
55 | s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C64XX_GPC5_I2S_V40_DO1); | ||
56 | s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C64XX_GPC7_I2S_V40_DO2); | ||
57 | s3c_gpio_cfgpin(S3C64XX_GPH(6), S3C64XX_GPH6_I2S_V40_BCLK); | ||
58 | s3c_gpio_cfgpin(S3C64XX_GPH(7), S3C64XX_GPH7_I2S_V40_CDCLK); | ||
59 | s3c_gpio_cfgpin(S3C64XX_GPH(8), S3C64XX_GPH8_I2S_V40_LRCLK); | ||
60 | s3c_gpio_cfgpin(S3C64XX_GPH(9), S3C64XX_GPH9_I2S_V40_DI); | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static int s3c_i2sv4_hw_params(struct snd_pcm_substream *substream, | ||
66 | struct snd_pcm_hw_params *params, | ||
67 | struct snd_soc_dai *cpu_dai) | ||
68 | { | ||
69 | struct s3c_i2sv2_info *i2s = to_info(cpu_dai); | ||
70 | struct s3c_dma_params *dma_data; | ||
71 | u32 iismod; | ||
72 | |||
73 | dev_dbg(cpu_dai->dev, "Entered %s\n", __func__); | ||
74 | |||
75 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
76 | dma_data = i2s->dma_playback; | ||
77 | else | ||
78 | dma_data = i2s->dma_capture; | ||
79 | |||
80 | snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); | ||
81 | |||
82 | iismod = readl(i2s->regs + S3C2412_IISMOD); | ||
83 | dev_dbg(cpu_dai->dev, "%s: r: IISMOD: %x\n", __func__, iismod); | ||
84 | |||
85 | iismod &= ~S3C64XX_IISMOD_BLC_MASK; | ||
86 | switch (params_format(params)) { | ||
87 | case SNDRV_PCM_FORMAT_S8: | ||
88 | iismod |= S3C64XX_IISMOD_BLC_8BIT; | ||
89 | break; | ||
90 | case SNDRV_PCM_FORMAT_S16_LE: | ||
91 | break; | ||
92 | case SNDRV_PCM_FORMAT_S24_LE: | ||
93 | iismod |= S3C64XX_IISMOD_BLC_24BIT; | ||
94 | break; | ||
95 | } | ||
96 | |||
97 | writel(iismod, i2s->regs + S3C2412_IISMOD); | ||
98 | dev_dbg(cpu_dai->dev, "%s: w: IISMOD: %x\n", __func__, iismod); | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static struct snd_soc_dai_ops s3c64xx_i2sv4_dai_ops = { | ||
104 | .hw_params = s3c_i2sv4_hw_params, | ||
105 | }; | ||
106 | |||
107 | static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev) | ||
108 | { | ||
109 | struct s3c_i2sv2_info *i2s; | ||
110 | struct snd_soc_dai *dai; | ||
111 | int ret; | ||
112 | |||
113 | i2s = &s3c64xx_i2sv4; | ||
114 | dai = &s3c64xx_i2s_v4_dai; | ||
115 | |||
116 | if (dai->dev) { | ||
117 | dev_dbg(dai->dev, "%s: \ | ||
118 | I2Sv4 instance already registered!\n", __func__); | ||
119 | return -EBUSY; | ||
120 | } | ||
121 | |||
122 | dai->dev = &pdev->dev; | ||
123 | dai->name = "s3c64xx-i2s-v4"; | ||
124 | dai->id = 0; | ||
125 | dai->symmetric_rates = 1; | ||
126 | dai->playback.channels_min = 2; | ||
127 | dai->playback.channels_max = 2; | ||
128 | dai->playback.rates = S3C64XX_I2S_RATES; | ||
129 | dai->playback.formats = S3C64XX_I2S_FMTS; | ||
130 | dai->capture.channels_min = 2; | ||
131 | dai->capture.channels_max = 2; | ||
132 | dai->capture.rates = S3C64XX_I2S_RATES; | ||
133 | dai->capture.formats = S3C64XX_I2S_FMTS; | ||
134 | dai->probe = s3c64xx_i2sv4_probe; | ||
135 | dai->ops = &s3c64xx_i2sv4_dai_ops; | ||
136 | |||
137 | i2s->feature |= S3C_FEATURE_CDCLKCON; | ||
138 | |||
139 | i2s->dma_capture = &s3c64xx_i2sv4_pcm_stereo_in; | ||
140 | i2s->dma_playback = &s3c64xx_i2sv4_pcm_stereo_out; | ||
141 | |||
142 | i2s->dma_capture->channel = DMACH_HSI_I2SV40_RX; | ||
143 | i2s->dma_capture->dma_addr = S3C64XX_PA_IISV4 + S3C2412_IISRXD; | ||
144 | i2s->dma_playback->channel = DMACH_HSI_I2SV40_TX; | ||
145 | i2s->dma_playback->dma_addr = S3C64XX_PA_IISV4 + S3C2412_IISTXD; | ||
146 | |||
147 | i2s->dma_capture->client = &s3c64xx_dma_client_in; | ||
148 | i2s->dma_capture->dma_size = 4; | ||
149 | i2s->dma_playback->client = &s3c64xx_dma_client_out; | ||
150 | i2s->dma_playback->dma_size = 4; | ||
151 | |||
152 | i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus"); | ||
153 | if (IS_ERR(i2s->iis_cclk)) { | ||
154 | dev_err(&pdev->dev, "failed to get audio-bus\n"); | ||
155 | ret = PTR_ERR(i2s->iis_cclk); | ||
156 | goto err; | ||
157 | } | ||
158 | |||
159 | clk_enable(i2s->iis_cclk); | ||
160 | |||
161 | ret = s3c_i2sv2_probe(pdev, dai, i2s, 0); | ||
162 | if (ret) | ||
163 | goto err_clk; | ||
164 | |||
165 | ret = s3c_i2sv2_register_dai(dai); | ||
166 | if (ret != 0) | ||
167 | goto err_i2sv2; | ||
168 | |||
169 | return 0; | ||
170 | |||
171 | err_i2sv2: | ||
172 | /* Not implemented for I2Sv2 core yet */ | ||
173 | err_clk: | ||
174 | clk_put(i2s->iis_cclk); | ||
175 | err: | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | static __devexit int s3c64xx_i2sv4_dev_remove(struct platform_device *pdev) | ||
180 | { | ||
181 | dev_err(&pdev->dev, "Device removal not yet supported\n"); | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static struct platform_driver s3c64xx_i2sv4_driver = { | ||
186 | .probe = s3c64xx_i2sv4_dev_probe, | ||
187 | .remove = s3c64xx_i2sv4_dev_remove, | ||
188 | .driver = { | ||
189 | .name = "s3c64xx-iis-v4", | ||
190 | .owner = THIS_MODULE, | ||
191 | }, | ||
192 | }; | ||
193 | |||
194 | static int __init s3c64xx_i2sv4_init(void) | ||
195 | { | ||
196 | return platform_driver_register(&s3c64xx_i2sv4_driver); | ||
197 | } | ||
198 | module_init(s3c64xx_i2sv4_init); | ||
199 | |||
200 | static void __exit s3c64xx_i2sv4_exit(void) | ||
201 | { | ||
202 | platform_driver_unregister(&s3c64xx_i2sv4_driver); | ||
203 | } | ||
204 | module_exit(s3c64xx_i2sv4_exit); | ||
205 | |||
206 | /* Module information */ | ||
207 | MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>"); | ||
208 | MODULE_DESCRIPTION("S3C64XX I2Sv4 SoC Interface"); | ||
209 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c index a72c251401ac..1d85cb85a7d2 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s.c | |||
@@ -12,16 +12,12 @@ | |||
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
19 | #include <linux/gpio.h> | 16 | #include <linux/gpio.h> |
20 | #include <linux/io.h> | 17 | #include <linux/io.h> |
21 | 18 | ||
22 | #include <sound/soc.h> | 19 | #include <sound/soc.h> |
23 | 20 | ||
24 | #include <plat/regs-s3c2412-iis.h> | ||
25 | #include <mach/gpio-bank-d.h> | 21 | #include <mach/gpio-bank-d.h> |
26 | #include <mach/gpio-bank-e.h> | 22 | #include <mach/gpio-bank-e.h> |
27 | #include <plat/gpio-cfg.h> | 23 | #include <plat/gpio-cfg.h> |
@@ -30,6 +26,7 @@ | |||
30 | #include <mach/dma.h> | 26 | #include <mach/dma.h> |
31 | 27 | ||
32 | #include "s3c-dma.h" | 28 | #include "s3c-dma.h" |
29 | #include "regs-i2s-v2.h" | ||
33 | #include "s3c64xx-i2s.h" | 30 | #include "s3c64xx-i2s.h" |
34 | 31 | ||
35 | /* The value should be set to maximum of the total number | 32 | /* The value should be set to maximum of the total number |
@@ -57,55 +54,6 @@ static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) | |||
57 | return cpu_dai->private_data; | 54 | return cpu_dai->private_data; |
58 | } | 55 | } |
59 | 56 | ||
60 | static int s3c64xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, | ||
61 | int clk_id, unsigned int freq, int dir) | ||
62 | { | ||
63 | struct s3c_i2sv2_info *i2s = to_info(cpu_dai); | ||
64 | u32 iismod = readl(i2s->regs + S3C2412_IISMOD); | ||
65 | |||
66 | switch (clk_id) { | ||
67 | case S3C64XX_CLKSRC_PCLK: | ||
68 | iismod &= ~S3C64XX_IISMOD_IMS_SYSMUX; | ||
69 | break; | ||
70 | |||
71 | case S3C64XX_CLKSRC_MUX: | ||
72 | iismod |= S3C64XX_IISMOD_IMS_SYSMUX; | ||
73 | break; | ||
74 | |||
75 | case S3C64XX_CLKSRC_CDCLK: | ||
76 | switch (dir) { | ||
77 | case SND_SOC_CLOCK_IN: | ||
78 | iismod |= S3C64XX_IISMOD_CDCLKCON; | ||
79 | break; | ||
80 | case SND_SOC_CLOCK_OUT: | ||
81 | iismod &= ~S3C64XX_IISMOD_CDCLKCON; | ||
82 | break; | ||
83 | default: | ||
84 | return -EINVAL; | ||
85 | } | ||
86 | break; | ||
87 | |||
88 | default: | ||
89 | return -EINVAL; | ||
90 | } | ||
91 | |||
92 | writel(iismod, i2s->regs + S3C2412_IISMOD); | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai) | ||
98 | { | ||
99 | struct s3c_i2sv2_info *i2s = to_info(dai); | ||
100 | u32 iismod = readl(i2s->regs + S3C2412_IISMOD); | ||
101 | |||
102 | if (iismod & S3C64XX_IISMOD_IMS_SYSMUX) | ||
103 | return i2s->iis_cclk; | ||
104 | else | ||
105 | return i2s->iis_pclk; | ||
106 | } | ||
107 | EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clock); | ||
108 | |||
109 | static int s3c64xx_i2s_probe(struct platform_device *pdev, | 57 | static int s3c64xx_i2s_probe(struct platform_device *pdev, |
110 | struct snd_soc_dai *dai) | 58 | struct snd_soc_dai *dai) |
111 | { | 59 | { |
@@ -130,18 +78,7 @@ static int s3c64xx_i2s_probe(struct platform_device *pdev, | |||
130 | } | 78 | } |
131 | 79 | ||
132 | 80 | ||
133 | #define S3C64XX_I2S_RATES \ | 81 | static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops; |
134 | (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ | ||
135 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | ||
136 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) | ||
137 | |||
138 | #define S3C64XX_I2S_FMTS \ | ||
139 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ | ||
140 | SNDRV_PCM_FMTBIT_S24_LE) | ||
141 | |||
142 | static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops = { | ||
143 | .set_sysclk = s3c64xx_i2s_set_sysclk, | ||
144 | }; | ||
145 | 82 | ||
146 | static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev) | 83 | static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev) |
147 | { | 84 | { |
@@ -171,6 +108,8 @@ static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev) | |||
171 | dai->probe = s3c64xx_i2s_probe; | 108 | dai->probe = s3c64xx_i2s_probe; |
172 | dai->ops = &s3c64xx_i2s_dai_ops; | 109 | dai->ops = &s3c64xx_i2s_dai_ops; |
173 | 110 | ||
111 | i2s->feature |= S3C_FEATURE_CDCLKCON; | ||
112 | |||
174 | i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id]; | 113 | i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id]; |
175 | i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id]; | 114 | i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id]; |
176 | 115 | ||
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.h b/sound/soc/s3c24xx/s3c64xx-i2s.h index abe7253b55fc..7a40f43d1d51 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s.h +++ b/sound/soc/s3c24xx/s3c64xx-i2s.h | |||
@@ -23,12 +23,20 @@ struct clk; | |||
23 | #define S3C64XX_DIV_RCLK S3C_I2SV2_DIV_RCLK | 23 | #define S3C64XX_DIV_RCLK S3C_I2SV2_DIV_RCLK |
24 | #define S3C64XX_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER | 24 | #define S3C64XX_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER |
25 | 25 | ||
26 | #define S3C64XX_CLKSRC_PCLK (0) | 26 | #define S3C64XX_CLKSRC_PCLK S3C_I2SV2_CLKSRC_PCLK |
27 | #define S3C64XX_CLKSRC_MUX (1) | 27 | #define S3C64XX_CLKSRC_MUX S3C_I2SV2_CLKSRC_AUDIOBUS |
28 | #define S3C64XX_CLKSRC_CDCLK (2) | 28 | #define S3C64XX_CLKSRC_CDCLK S3C_I2SV2_CLKSRC_CDCLK |
29 | 29 | ||
30 | extern struct snd_soc_dai s3c64xx_i2s_dai[]; | 30 | #define S3C64XX_I2S_RATES \ |
31 | (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ | ||
32 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | ||
33 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) | ||
34 | |||
35 | #define S3C64XX_I2S_FMTS \ | ||
36 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ | ||
37 | SNDRV_PCM_FMTBIT_S24_LE) | ||
31 | 38 | ||
32 | extern struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai); | 39 | extern struct snd_soc_dai s3c64xx_i2s_dai[]; |
40 | extern struct snd_soc_dai s3c64xx_i2s_v4_dai; | ||
33 | 41 | ||
34 | #endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */ | 42 | #endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */ |
diff --git a/sound/soc/s3c24xx/smdk64xx_wm8580.c b/sound/soc/s3c24xx/smdk64xx_wm8580.c index efe4901213a3..07e8e51d10d6 100644 --- a/sound/soc/s3c24xx/smdk64xx_wm8580.c +++ b/sound/soc/s3c24xx/smdk64xx_wm8580.c | |||
@@ -22,8 +22,6 @@ | |||
22 | #include "s3c-dma.h" | 22 | #include "s3c-dma.h" |
23 | #include "s3c64xx-i2s.h" | 23 | #include "s3c64xx-i2s.h" |
24 | 24 | ||
25 | #define S3C64XX_I2S_V4 2 | ||
26 | |||
27 | /* SMDK64XX has a 12MHZ crystal attached to WM8580 */ | 25 | /* SMDK64XX has a 12MHZ crystal attached to WM8580 */ |
28 | #define SMDK64XX_WM8580_FREQ 12000000 | 26 | #define SMDK64XX_WM8580_FREQ 12000000 |
29 | 27 | ||
@@ -215,7 +213,7 @@ static struct snd_soc_dai_link smdk64xx_dai[] = { | |||
215 | { /* Primary Playback i/f */ | 213 | { /* Primary Playback i/f */ |
216 | .name = "WM8580 PAIF RX", | 214 | .name = "WM8580 PAIF RX", |
217 | .stream_name = "Playback", | 215 | .stream_name = "Playback", |
218 | .cpu_dai = &s3c64xx_i2s_dai[S3C64XX_I2S_V4], | 216 | .cpu_dai = &s3c64xx_i2s_v4_dai, |
219 | .codec_dai = &wm8580_dai[WM8580_DAI_PAIFRX], | 217 | .codec_dai = &wm8580_dai[WM8580_DAI_PAIFRX], |
220 | .init = smdk64xx_wm8580_init_paifrx, | 218 | .init = smdk64xx_wm8580_init_paifrx, |
221 | .ops = &smdk64xx_ops, | 219 | .ops = &smdk64xx_ops, |
@@ -223,7 +221,7 @@ static struct snd_soc_dai_link smdk64xx_dai[] = { | |||
223 | { /* Primary Capture i/f */ | 221 | { /* Primary Capture i/f */ |
224 | .name = "WM8580 PAIF TX", | 222 | .name = "WM8580 PAIF TX", |
225 | .stream_name = "Capture", | 223 | .stream_name = "Capture", |
226 | .cpu_dai = &s3c64xx_i2s_dai[S3C64XX_I2S_V4], | 224 | .cpu_dai = &s3c64xx_i2s_v4_dai, |
227 | .codec_dai = &wm8580_dai[WM8580_DAI_PAIFTX], | 225 | .codec_dai = &wm8580_dai[WM8580_DAI_PAIFTX], |
228 | .init = smdk64xx_wm8580_init_paiftx, | 226 | .init = smdk64xx_wm8580_init_paiftx, |
229 | .ops = &smdk64xx_ops, | 227 | .ops = &smdk64xx_ops, |