Merge git://git.infradead.org/~dwmw2/ideapad-2.6
[sfrench/cifs-2.6.git] / arch / arm / mach-s3c64xx / dev-audio.c
1 /* linux/arch/arm/plat-s3c/dev-audio.c
2  *
3  * Copyright 2009 Wolfson Microelectronics
4  *      Mark Brown <broonie@opensource.wolfsonmicro.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/string.h>
13 #include <linux/platform_device.h>
14 #include <linux/dma-mapping.h>
15 #include <linux/gpio.h>
16
17 #include <mach/irqs.h>
18 #include <mach/map.h>
19 #include <mach/dma.h>
20
21 #include <plat/devs.h>
22 #include <plat/audio.h>
23 #include <plat/gpio-cfg.h>
24
25 #include <mach/gpio-bank-c.h>
26 #include <mach/gpio-bank-d.h>
27 #include <mach/gpio-bank-e.h>
28 #include <mach/gpio-bank-h.h>
29
30 static int s3c64xx_i2sv3_cfg_gpio(struct platform_device *pdev)
31 {
32         switch (pdev->id) {
33         case 0:
34                 s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK);
35                 s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK);
36                 s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_I2S0_LRCLK);
37                 s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_I2S0_DI);
38                 s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_I2S0_D0);
39                 break;
40         case 1:
41                 s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_I2S1_CLK);
42                 s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_I2S1_CDCLK);
43                 s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_I2S1_LRCLK);
44                 s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_I2S1_DI);
45                 s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_I2S1_D0);
46         default:
47                 printk(KERN_DEBUG "Invalid I2S Controller number!");
48                 return -EINVAL;
49         }
50
51         return 0;
52 }
53
54 static int s3c64xx_i2sv4_cfg_gpio(struct platform_device *pdev)
55 {
56         s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C64XX_GPC4_I2S_V40_DO0);
57         s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C64XX_GPC5_I2S_V40_DO1);
58         s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C64XX_GPC7_I2S_V40_DO2);
59         s3c_gpio_cfgpin(S3C64XX_GPH(6), S3C64XX_GPH6_I2S_V40_BCLK);
60         s3c_gpio_cfgpin(S3C64XX_GPH(7), S3C64XX_GPH7_I2S_V40_CDCLK);
61         s3c_gpio_cfgpin(S3C64XX_GPH(8), S3C64XX_GPH8_I2S_V40_LRCLK);
62         s3c_gpio_cfgpin(S3C64XX_GPH(9), S3C64XX_GPH9_I2S_V40_DI);
63
64         return 0;
65 }
66
67 static struct resource s3c64xx_iis0_resource[] = {
68         [0] = {
69                 .start = S3C64XX_PA_IIS0,
70                 .end   = S3C64XX_PA_IIS0 + 0x100 - 1,
71                 .flags = IORESOURCE_MEM,
72         },
73         [1] = {
74                 .start = DMACH_I2S0_OUT,
75                 .end   = DMACH_I2S0_OUT,
76                 .flags = IORESOURCE_DMA,
77         },
78         [2] = {
79                 .start = DMACH_I2S0_IN,
80                 .end   = DMACH_I2S0_IN,
81                 .flags = IORESOURCE_DMA,
82         },
83 };
84
85 static struct s3c_audio_pdata s3c_i2s0_pdata = {
86         .cfg_gpio = s3c64xx_i2sv3_cfg_gpio,
87 };
88
89 struct platform_device s3c64xx_device_iis0 = {
90         .name             = "s3c64xx-iis",
91         .id               = 0,
92         .num_resources    = ARRAY_SIZE(s3c64xx_iis0_resource),
93         .resource         = s3c64xx_iis0_resource,
94         .dev = {
95                 .platform_data = &s3c_i2s0_pdata,
96         },
97 };
98 EXPORT_SYMBOL(s3c64xx_device_iis0);
99
100 static struct resource s3c64xx_iis1_resource[] = {
101         [0] = {
102                 .start = S3C64XX_PA_IIS1,
103                 .end   = S3C64XX_PA_IIS1 + 0x100 - 1,
104                 .flags = IORESOURCE_MEM,
105         },
106         [1] = {
107                 .start = DMACH_I2S1_OUT,
108                 .end   = DMACH_I2S1_OUT,
109                 .flags = IORESOURCE_DMA,
110         },
111         [2] = {
112                 .start = DMACH_I2S1_IN,
113                 .end   = DMACH_I2S1_IN,
114                 .flags = IORESOURCE_DMA,
115         },
116 };
117
118 static struct s3c_audio_pdata s3c_i2s1_pdata = {
119         .cfg_gpio = s3c64xx_i2sv3_cfg_gpio,
120 };
121
122 struct platform_device s3c64xx_device_iis1 = {
123         .name             = "s3c64xx-iis",
124         .id               = 1,
125         .num_resources    = ARRAY_SIZE(s3c64xx_iis1_resource),
126         .resource         = s3c64xx_iis1_resource,
127         .dev = {
128                 .platform_data = &s3c_i2s1_pdata,
129         },
130 };
131 EXPORT_SYMBOL(s3c64xx_device_iis1);
132
133 static struct resource s3c64xx_iisv4_resource[] = {
134         [0] = {
135                 .start = S3C64XX_PA_IISV4,
136                 .end   = S3C64XX_PA_IISV4 + 0x100 - 1,
137                 .flags = IORESOURCE_MEM,
138         },
139         [1] = {
140                 .start = DMACH_HSI_I2SV40_TX,
141                 .end   = DMACH_HSI_I2SV40_TX,
142                 .flags = IORESOURCE_DMA,
143         },
144         [2] = {
145                 .start = DMACH_HSI_I2SV40_RX,
146                 .end   = DMACH_HSI_I2SV40_RX,
147                 .flags = IORESOURCE_DMA,
148         },
149 };
150
151 static struct s3c_audio_pdata s3c_i2sv4_pdata = {
152         .cfg_gpio = s3c64xx_i2sv4_cfg_gpio,
153 };
154
155 struct platform_device s3c64xx_device_iisv4 = {
156         .name             = "s3c64xx-iis-v4",
157         .id               = -1,
158         .num_resources    = ARRAY_SIZE(s3c64xx_iisv4_resource),
159         .resource         = s3c64xx_iisv4_resource,
160         .dev = {
161                 .platform_data = &s3c_i2sv4_pdata,
162         },
163 };
164 EXPORT_SYMBOL(s3c64xx_device_iisv4);
165
166
167 /* PCM Controller platform_devices */
168
169 static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev)
170 {
171         switch (pdev->id) {
172         case 0:
173                 s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_PCM0_SCLK);
174                 s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_PCM0_EXTCLK);
175                 s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_PCM0_FSYNC);
176                 s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_PCM0_SIN);
177                 s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_PCM0_SOUT);
178                 break;
179         case 1:
180                 s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_PCM1_SCLK);
181                 s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_PCM1_EXTCLK);
182                 s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_PCM1_FSYNC);
183                 s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_PCM1_SIN);
184                 s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_PCM1_SOUT);
185                 break;
186         default:
187                 printk(KERN_DEBUG "Invalid PCM Controller number!");
188                 return -EINVAL;
189         }
190
191         return 0;
192 }
193
194 static struct resource s3c64xx_pcm0_resource[] = {
195         [0] = {
196                 .start = S3C64XX_PA_PCM0,
197                 .end   = S3C64XX_PA_PCM0 + 0x100 - 1,
198                 .flags = IORESOURCE_MEM,
199         },
200         [1] = {
201                 .start = DMACH_PCM0_TX,
202                 .end   = DMACH_PCM0_TX,
203                 .flags = IORESOURCE_DMA,
204         },
205         [2] = {
206                 .start = DMACH_PCM0_RX,
207                 .end   = DMACH_PCM0_RX,
208                 .flags = IORESOURCE_DMA,
209         },
210 };
211
212 static struct s3c_audio_pdata s3c_pcm0_pdata = {
213         .cfg_gpio = s3c64xx_pcm_cfg_gpio,
214 };
215
216 struct platform_device s3c64xx_device_pcm0 = {
217         .name             = "samsung-pcm",
218         .id               = 0,
219         .num_resources    = ARRAY_SIZE(s3c64xx_pcm0_resource),
220         .resource         = s3c64xx_pcm0_resource,
221         .dev = {
222                 .platform_data = &s3c_pcm0_pdata,
223         },
224 };
225 EXPORT_SYMBOL(s3c64xx_device_pcm0);
226
227 static struct resource s3c64xx_pcm1_resource[] = {
228         [0] = {
229                 .start = S3C64XX_PA_PCM1,
230                 .end   = S3C64XX_PA_PCM1 + 0x100 - 1,
231                 .flags = IORESOURCE_MEM,
232         },
233         [1] = {
234                 .start = DMACH_PCM1_TX,
235                 .end   = DMACH_PCM1_TX,
236                 .flags = IORESOURCE_DMA,
237         },
238         [2] = {
239                 .start = DMACH_PCM1_RX,
240                 .end   = DMACH_PCM1_RX,
241                 .flags = IORESOURCE_DMA,
242         },
243 };
244
245 static struct s3c_audio_pdata s3c_pcm1_pdata = {
246         .cfg_gpio = s3c64xx_pcm_cfg_gpio,
247 };
248
249 struct platform_device s3c64xx_device_pcm1 = {
250         .name             = "samsung-pcm",
251         .id               = 1,
252         .num_resources    = ARRAY_SIZE(s3c64xx_pcm1_resource),
253         .resource         = s3c64xx_pcm1_resource,
254         .dev = {
255                 .platform_data = &s3c_pcm1_pdata,
256         },
257 };
258 EXPORT_SYMBOL(s3c64xx_device_pcm1);
259
260 /* AC97 Controller platform devices */
261
262 static int s3c64xx_ac97_cfg_gpd(struct platform_device *pdev)
263 {
264         s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_AC97_BITCLK);
265         s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_AC97_nRESET);
266         s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_AC97_SYNC);
267         s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_AC97_SDI);
268         s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_AC97_SDO);
269
270         return 0;
271 }
272
273 static int s3c64xx_ac97_cfg_gpe(struct platform_device *pdev)
274 {
275         s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_AC97_BITCLK);
276         s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_AC97_nRESET);
277         s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_AC97_SYNC);
278         s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_AC97_SDI);
279         s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_AC97_SDO);
280
281         return 0;
282 }
283
284 static struct resource s3c64xx_ac97_resource[] = {
285         [0] = {
286                 .start = S3C64XX_PA_AC97,
287                 .end   = S3C64XX_PA_AC97 + 0x100 - 1,
288                 .flags = IORESOURCE_MEM,
289         },
290         [1] = {
291                 .start = DMACH_AC97_PCMOUT,
292                 .end   = DMACH_AC97_PCMOUT,
293                 .flags = IORESOURCE_DMA,
294         },
295         [2] = {
296                 .start = DMACH_AC97_PCMIN,
297                 .end   = DMACH_AC97_PCMIN,
298                 .flags = IORESOURCE_DMA,
299         },
300         [3] = {
301                 .start = DMACH_AC97_MICIN,
302                 .end   = DMACH_AC97_MICIN,
303                 .flags = IORESOURCE_DMA,
304         },
305         [4] = {
306                 .start = IRQ_AC97,
307                 .end   = IRQ_AC97,
308                 .flags = IORESOURCE_IRQ,
309         },
310 };
311
312 static struct s3c_audio_pdata s3c_ac97_pdata;
313
314 static u64 s3c64xx_ac97_dmamask = DMA_BIT_MASK(32);
315
316 struct platform_device s3c64xx_device_ac97 = {
317         .name             = "s3c-ac97",
318         .id               = -1,
319         .num_resources    = ARRAY_SIZE(s3c64xx_ac97_resource),
320         .resource         = s3c64xx_ac97_resource,
321         .dev = {
322                 .platform_data = &s3c_ac97_pdata,
323                 .dma_mask = &s3c64xx_ac97_dmamask,
324                 .coherent_dma_mask = DMA_BIT_MASK(32),
325         },
326 };
327 EXPORT_SYMBOL(s3c64xx_device_ac97);
328
329 void __init s3c64xx_ac97_setup_gpio(int num)
330 {
331         if (num == S3C64XX_AC97_GPD)
332                 s3c_ac97_pdata.cfg_gpio = s3c64xx_ac97_cfg_gpd;
333         else
334                 s3c_ac97_pdata.cfg_gpio = s3c64xx_ac97_cfg_gpe;
335 }