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 30static 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 54static 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 67static 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 85static struct s3c_audio_pdata s3c_i2s0_pdata = { 86 .cfg_gpio = s3c64xx_i2sv3_cfg_gpio, 87}; 88 89struct 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}; 98EXPORT_SYMBOL(s3c64xx_device_iis0); 99 100static 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 118static struct s3c_audio_pdata s3c_i2s1_pdata = { 119 .cfg_gpio = s3c64xx_i2sv3_cfg_gpio, 120}; 121 122struct 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}; 131EXPORT_SYMBOL(s3c64xx_device_iis1); 132 133static 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 151static struct s3c_audio_pdata s3c_i2sv4_pdata = { 152 .cfg_gpio = s3c64xx_i2sv4_cfg_gpio, 153}; 154 155struct 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}; 164EXPORT_SYMBOL(s3c64xx_device_iisv4); 165 166 167/* PCM Controller platform_devices */ 168 169static 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 194static 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 212static struct s3c_audio_pdata s3c_pcm0_pdata = { 213 .cfg_gpio = s3c64xx_pcm_cfg_gpio, 214}; 215 216struct 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}; 225EXPORT_SYMBOL(s3c64xx_device_pcm0); 226 227static 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 245static struct s3c_audio_pdata s3c_pcm1_pdata = { 246 .cfg_gpio = s3c64xx_pcm_cfg_gpio, 247}; 248 249struct 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}; 258EXPORT_SYMBOL(s3c64xx_device_pcm1); 259 260/* AC97 Controller platform devices */ 261 262static 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 273static 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 284static 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 312static struct s3c_audio_pdata s3c_ac97_pdata; 313 314static u64 s3c64xx_ac97_dmamask = DMA_BIT_MASK(32); 315 316struct 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}; 327EXPORT_SYMBOL(s3c64xx_device_ac97); 328 329void __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} 336