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#include <linux/export.h> 17 18#include <mach/irqs.h> 19#include <mach/map.h> 20#include <mach/dma.h> 21 22#include <plat/devs.h> 23#include <linux/platform_data/asoc-s3c.h> 24#include <plat/gpio-cfg.h> 25#include <mach/gpio-samsung.h> 26 27static int s3c64xx_i2s_cfg_gpio(struct platform_device *pdev) 28{ 29 unsigned int base; 30 31 switch (pdev->id) { 32 case 0: 33 base = S3C64XX_GPD(0); 34 break; 35 case 1: 36 base = S3C64XX_GPE(0); 37 break; 38 case 2: 39 s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C_GPIO_SFN(5)); 40 s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C_GPIO_SFN(5)); 41 s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C_GPIO_SFN(5)); 42 s3c_gpio_cfgpin_range(S3C64XX_GPH(6), 4, S3C_GPIO_SFN(5)); 43 return 0; 44 default: 45 printk(KERN_DEBUG "Invalid I2S Controller number: %d\n", 46 pdev->id); 47 return -EINVAL; 48 } 49 50 s3c_gpio_cfgpin_range(base, 5, S3C_GPIO_SFN(3)); 51 52 return 0; 53} 54 55static struct resource s3c64xx_iis0_resource[] = { 56 [0] = DEFINE_RES_MEM(S3C64XX_PA_IIS0, SZ_256), 57}; 58 59static struct s3c_audio_pdata i2s0_pdata = { 60 .cfg_gpio = s3c64xx_i2s_cfg_gpio, 61 .dma_playback = DMACH_I2S0_OUT, 62 .dma_capture = DMACH_I2S0_IN, 63}; 64 65struct platform_device s3c64xx_device_iis0 = { 66 .name = "samsung-i2s", 67 .id = 0, 68 .num_resources = ARRAY_SIZE(s3c64xx_iis0_resource), 69 .resource = s3c64xx_iis0_resource, 70 .dev = { 71 .platform_data = &i2s0_pdata, 72 }, 73}; 74EXPORT_SYMBOL(s3c64xx_device_iis0); 75 76static struct resource s3c64xx_iis1_resource[] = { 77 [0] = DEFINE_RES_MEM(S3C64XX_PA_IIS1, SZ_256), 78}; 79 80static struct s3c_audio_pdata i2s1_pdata = { 81 .cfg_gpio = s3c64xx_i2s_cfg_gpio, 82 .dma_playback = DMACH_I2S1_OUT, 83 .dma_capture = DMACH_I2S1_IN, 84}; 85 86struct platform_device s3c64xx_device_iis1 = { 87 .name = "samsung-i2s", 88 .id = 1, 89 .num_resources = ARRAY_SIZE(s3c64xx_iis1_resource), 90 .resource = s3c64xx_iis1_resource, 91 .dev = { 92 .platform_data = &i2s1_pdata, 93 }, 94}; 95EXPORT_SYMBOL(s3c64xx_device_iis1); 96 97static struct resource s3c64xx_iisv4_resource[] = { 98 [0] = DEFINE_RES_MEM(S3C64XX_PA_IISV4, SZ_256), 99}; 100 101static struct s3c_audio_pdata i2sv4_pdata = { 102 .cfg_gpio = s3c64xx_i2s_cfg_gpio, 103 .dma_playback = DMACH_HSI_I2SV40_TX, 104 .dma_capture = DMACH_HSI_I2SV40_RX, 105 .type = { 106 .i2s = { 107 .quirks = QUIRK_PRI_6CHAN, 108 }, 109 }, 110}; 111 112struct platform_device s3c64xx_device_iisv4 = { 113 .name = "samsung-i2s", 114 .id = 2, 115 .num_resources = ARRAY_SIZE(s3c64xx_iisv4_resource), 116 .resource = s3c64xx_iisv4_resource, 117 .dev = { 118 .platform_data = &i2sv4_pdata, 119 }, 120}; 121EXPORT_SYMBOL(s3c64xx_device_iisv4); 122 123 124/* PCM Controller platform_devices */ 125 126static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev) 127{ 128 unsigned int base; 129 130 switch (pdev->id) { 131 case 0: 132 base = S3C64XX_GPD(0); 133 break; 134 case 1: 135 base = S3C64XX_GPE(0); 136 break; 137 default: 138 printk(KERN_DEBUG "Invalid PCM Controller number: %d\n", 139 pdev->id); 140 return -EINVAL; 141 } 142 143 s3c_gpio_cfgpin_range(base, 5, S3C_GPIO_SFN(2)); 144 return 0; 145} 146 147static struct resource s3c64xx_pcm0_resource[] = { 148 [0] = DEFINE_RES_MEM(S3C64XX_PA_PCM0, SZ_256), 149}; 150 151static struct s3c_audio_pdata s3c_pcm0_pdata = { 152 .cfg_gpio = s3c64xx_pcm_cfg_gpio, 153 .dma_capture = DMACH_PCM0_RX, 154 .dma_playback = DMACH_PCM0_TX, 155}; 156 157struct platform_device s3c64xx_device_pcm0 = { 158 .name = "samsung-pcm", 159 .id = 0, 160 .num_resources = ARRAY_SIZE(s3c64xx_pcm0_resource), 161 .resource = s3c64xx_pcm0_resource, 162 .dev = { 163 .platform_data = &s3c_pcm0_pdata, 164 }, 165}; 166EXPORT_SYMBOL(s3c64xx_device_pcm0); 167 168static struct resource s3c64xx_pcm1_resource[] = { 169 [0] = DEFINE_RES_MEM(S3C64XX_PA_PCM1, SZ_256), 170}; 171 172static struct s3c_audio_pdata s3c_pcm1_pdata = { 173 .cfg_gpio = s3c64xx_pcm_cfg_gpio, 174 .dma_playback = DMACH_PCM1_TX, 175 .dma_capture = DMACH_PCM1_RX, 176}; 177 178struct platform_device s3c64xx_device_pcm1 = { 179 .name = "samsung-pcm", 180 .id = 1, 181 .num_resources = ARRAY_SIZE(s3c64xx_pcm1_resource), 182 .resource = s3c64xx_pcm1_resource, 183 .dev = { 184 .platform_data = &s3c_pcm1_pdata, 185 }, 186}; 187EXPORT_SYMBOL(s3c64xx_device_pcm1); 188 189/* AC97 Controller platform devices */ 190 191static int s3c64xx_ac97_cfg_gpd(struct platform_device *pdev) 192{ 193 return s3c_gpio_cfgpin_range(S3C64XX_GPD(0), 5, S3C_GPIO_SFN(4)); 194} 195 196static int s3c64xx_ac97_cfg_gpe(struct platform_device *pdev) 197{ 198 return s3c_gpio_cfgpin_range(S3C64XX_GPE(0), 5, S3C_GPIO_SFN(4)); 199} 200 201static struct resource s3c64xx_ac97_resource[] = { 202 [0] = DEFINE_RES_MEM(S3C64XX_PA_AC97, SZ_256), 203 [1] = DEFINE_RES_IRQ(IRQ_AC97), 204}; 205 206static struct s3c_audio_pdata s3c_ac97_pdata = { 207 .dma_playback = DMACH_AC97_PCMOUT, 208 .dma_capture = DMACH_AC97_PCMIN, 209 .dma_capture_mic = DMACH_AC97_MICIN, 210}; 211 212static u64 s3c64xx_ac97_dmamask = DMA_BIT_MASK(32); 213 214struct platform_device s3c64xx_device_ac97 = { 215 .name = "samsung-ac97", 216 .id = -1, 217 .num_resources = ARRAY_SIZE(s3c64xx_ac97_resource), 218 .resource = s3c64xx_ac97_resource, 219 .dev = { 220 .platform_data = &s3c_ac97_pdata, 221 .dma_mask = &s3c64xx_ac97_dmamask, 222 .coherent_dma_mask = DMA_BIT_MASK(32), 223 }, 224}; 225EXPORT_SYMBOL(s3c64xx_device_ac97); 226 227void __init s3c64xx_ac97_setup_gpio(int num) 228{ 229 if (num == S3C64XX_AC97_GPD) 230 s3c_ac97_pdata.cfg_gpio = s3c64xx_ac97_cfg_gpd; 231 else 232 s3c_ac97_pdata.cfg_gpio = s3c64xx_ac97_cfg_gpe; 233} 234