| OLD | NEW |
| 1 /* | 1 /* |
| 2 * s3c-dma.c -- ALSA Soc Audio Layer | 2 * dma.c -- ALSA Soc Audio Layer |
| 3 * | 3 * |
| 4 * (c) 2006 Wolfson Microelectronics PLC. | 4 * (c) 2006 Wolfson Microelectronics PLC. |
| 5 * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | 5 * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com |
| 6 * | 6 * |
| 7 * Copyright 2004-2005 Simtec Electronics | 7 * Copyright 2004-2005 Simtec Electronics |
| 8 * http://armlinux.simtec.co.uk/ | 8 * http://armlinux.simtec.co.uk/ |
| 9 * Ben Dooks <ben@simtec.co.uk> | 9 * Ben Dooks <ben@simtec.co.uk> |
| 10 * | 10 * |
| 11 * This program is free software; you can redistribute it and/or modify it | 11 * This program is free software; you can redistribute it and/or modify it |
| 12 * under the terms of the GNU General Public License as published by the | 12 * under the terms of the GNU General Public License as published by the |
| 13 * Free Software Foundation; either version 2 of the License, or (at your | 13 * Free Software Foundation; either version 2 of the License, or (at your |
| 14 * option) any later version. | 14 * option) any later version. |
| 15 */ | 15 */ |
| 16 | 16 |
| 17 #include <linux/module.h> | |
| 18 #include <linux/init.h> | |
| 19 #include <linux/io.h> | |
| 20 #include <linux/platform_device.h> | |
| 21 #include <linux/slab.h> | 17 #include <linux/slab.h> |
| 22 #include <linux/dma-mapping.h> | 18 #include <linux/dma-mapping.h> |
| 23 | 19 |
| 24 #include <sound/core.h> | 20 #include <sound/soc.h> |
| 25 #include <sound/pcm.h> | |
| 26 #include <sound/pcm_params.h> | 21 #include <sound/pcm_params.h> |
| 27 #include <sound/soc.h> | |
| 28 | 22 |
| 29 #include <asm/dma.h> | 23 #include <asm/dma.h> |
| 30 #include <mach/hardware.h> | 24 #include <mach/hardware.h> |
| 31 #include <mach/dma.h> | 25 #include <mach/dma.h> |
| 32 | 26 |
| 33 #include "s3c-dma.h" | 27 #include "dma.h" |
| 34 | 28 |
| 35 static const struct snd_pcm_hardware s3c_dma_hardware = { | 29 #define ST_RUNNING» » (1<<0) |
| 30 #define ST_OPENED» » (1<<1) |
| 31 |
| 32 static const struct snd_pcm_hardware dma_hardware = { |
| 36 .info = SNDRV_PCM_INFO_INTERLEAVED | | 33 .info = SNDRV_PCM_INFO_INTERLEAVED | |
| 37 SNDRV_PCM_INFO_BLOCK_TRANSFER | | 34 SNDRV_PCM_INFO_BLOCK_TRANSFER | |
| 38 SNDRV_PCM_INFO_MMAP | | 35 SNDRV_PCM_INFO_MMAP | |
| 39 SNDRV_PCM_INFO_MMAP_VALID | | 36 SNDRV_PCM_INFO_MMAP_VALID | |
| 40 SNDRV_PCM_INFO_PAUSE | | 37 SNDRV_PCM_INFO_PAUSE | |
| 41 SNDRV_PCM_INFO_RESUME, | 38 SNDRV_PCM_INFO_RESUME, |
| 42 .formats = SNDRV_PCM_FMTBIT_S16_LE | | 39 .formats = SNDRV_PCM_FMTBIT_S16_LE | |
| 43 SNDRV_PCM_FMTBIT_U16_LE | | 40 SNDRV_PCM_FMTBIT_U16_LE | |
| 44 SNDRV_PCM_FMTBIT_U8 | | 41 SNDRV_PCM_FMTBIT_U8 | |
| 45 SNDRV_PCM_FMTBIT_S8, | 42 SNDRV_PCM_FMTBIT_S8, |
| 46 .channels_min = 2, | 43 .channels_min = 2, |
| 47 .channels_max = 2, | 44 .channels_max = 2, |
| 48 .buffer_bytes_max = 128*1024, | 45 .buffer_bytes_max = 128*1024, |
| 49 .period_bytes_min = PAGE_SIZE, | 46 .period_bytes_min = PAGE_SIZE, |
| 50 .period_bytes_max = PAGE_SIZE*2, | 47 .period_bytes_max = PAGE_SIZE*2, |
| 51 .periods_min = 2, | 48 .periods_min = 2, |
| 52 .periods_max = 128, | 49 .periods_max = 128, |
| 53 .fifo_size = 32, | 50 .fifo_size = 32, |
| 54 }; | 51 }; |
| 55 | 52 |
| 56 struct s3c24xx_runtime_data { | 53 struct runtime_data { |
| 57 spinlock_t lock; | 54 spinlock_t lock; |
| 58 int state; | 55 int state; |
| 59 unsigned int dma_loaded; | 56 unsigned int dma_loaded; |
| 60 unsigned int dma_limit; | 57 unsigned int dma_limit; |
| 61 unsigned int dma_period; | 58 unsigned int dma_period; |
| 62 dma_addr_t dma_start; | 59 dma_addr_t dma_start; |
| 63 dma_addr_t dma_pos; | 60 dma_addr_t dma_pos; |
| 64 dma_addr_t dma_end; | 61 dma_addr_t dma_end; |
| 65 struct s3c_dma_params *params; | 62 struct s3c_dma_params *params; |
| 66 }; | 63 }; |
| 67 | 64 |
| 68 /* s3c_dma_enqueue | 65 /* dma_enqueue |
| 69 * | 66 * |
| 70 * place a dma buffer onto the queue for the dma system | 67 * place a dma buffer onto the queue for the dma system |
| 71 * to handle. | 68 * to handle. |
| 72 */ | 69 */ |
| 73 static void s3c_dma_enqueue(struct snd_pcm_substream *substream) | 70 static void dma_enqueue(struct snd_pcm_substream *substream) |
| 74 { | 71 { |
| 75 » struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; | 72 » struct runtime_data *prtd = substream->runtime->private_data; |
| 76 dma_addr_t pos = prtd->dma_pos; | 73 dma_addr_t pos = prtd->dma_pos; |
| 77 unsigned int limit; | 74 unsigned int limit; |
| 78 int ret; | 75 int ret; |
| 79 | 76 |
| 80 pr_debug("Entered %s\n", __func__); | 77 pr_debug("Entered %s\n", __func__); |
| 81 | 78 |
| 82 if (s3c_dma_has_circular()) | 79 if (s3c_dma_has_circular()) |
| 83 limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period; | 80 limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period; |
| 84 else | 81 else |
| 85 limit = prtd->dma_limit; | 82 limit = prtd->dma_limit; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 105 pos += prtd->dma_period; | 102 pos += prtd->dma_period; |
| 106 if (pos >= prtd->dma_end) | 103 if (pos >= prtd->dma_end) |
| 107 pos = prtd->dma_start; | 104 pos = prtd->dma_start; |
| 108 } else | 105 } else |
| 109 break; | 106 break; |
| 110 } | 107 } |
| 111 | 108 |
| 112 prtd->dma_pos = pos; | 109 prtd->dma_pos = pos; |
| 113 } | 110 } |
| 114 | 111 |
| 115 static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel, | 112 static void audio_buffdone(struct s3c2410_dma_chan *channel, |
| 116 void *dev_id, int size, | 113 void *dev_id, int size, |
| 117 enum s3c2410_dma_buffresult result) | 114 enum s3c2410_dma_buffresult result) |
| 118 { | 115 { |
| 119 struct snd_pcm_substream *substream = dev_id; | 116 struct snd_pcm_substream *substream = dev_id; |
| 120 » struct s3c24xx_runtime_data *prtd; | 117 » struct runtime_data *prtd; |
| 121 | 118 |
| 122 pr_debug("Entered %s\n", __func__); | 119 pr_debug("Entered %s\n", __func__); |
| 123 | 120 |
| 124 if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR) | 121 if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR) |
| 125 return; | 122 return; |
| 126 | 123 |
| 127 prtd = substream->runtime->private_data; | 124 prtd = substream->runtime->private_data; |
| 128 | 125 |
| 129 if (substream) | 126 if (substream) |
| 130 snd_pcm_period_elapsed(substream); | 127 snd_pcm_period_elapsed(substream); |
| 131 | 128 |
| 132 spin_lock(&prtd->lock); | 129 spin_lock(&prtd->lock); |
| 133 if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) { | 130 if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) { |
| 134 prtd->dma_loaded--; | 131 prtd->dma_loaded--; |
| 135 » » s3c_dma_enqueue(substream); | 132 » » dma_enqueue(substream); |
| 136 } | 133 } |
| 137 | 134 |
| 138 spin_unlock(&prtd->lock); | 135 spin_unlock(&prtd->lock); |
| 139 } | 136 } |
| 140 | 137 |
| 141 static int s3c_dma_hw_params(struct snd_pcm_substream *substream, | 138 static int dma_hw_params(struct snd_pcm_substream *substream, |
| 142 struct snd_pcm_hw_params *params) | 139 struct snd_pcm_hw_params *params) |
| 143 { | 140 { |
| 144 struct snd_pcm_runtime *runtime = substream->runtime; | 141 struct snd_pcm_runtime *runtime = substream->runtime; |
| 145 » struct s3c24xx_runtime_data *prtd = runtime->private_data; | 142 » struct runtime_data *prtd = runtime->private_data; |
| 146 struct snd_soc_pcm_runtime *rtd = substream->private_data; | 143 struct snd_soc_pcm_runtime *rtd = substream->private_data; |
| 147 unsigned long totbytes = params_buffer_bytes(params); | 144 unsigned long totbytes = params_buffer_bytes(params); |
| 148 struct s3c_dma_params *dma = | 145 struct s3c_dma_params *dma = |
| 149 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | 146 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
| 150 int ret = 0; | 147 int ret = 0; |
| 151 | 148 |
| 152 | 149 |
| 153 pr_debug("Entered %s\n", __func__); | 150 pr_debug("Entered %s\n", __func__); |
| 154 | 151 |
| 155 /* return if this is a bufferless transfer e.g. | 152 /* return if this is a bufferless transfer e.g. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 174 return ret; | 171 return ret; |
| 175 } | 172 } |
| 176 | 173 |
| 177 /* use the circular buffering if we have it available. */ | 174 /* use the circular buffering if we have it available. */ |
| 178 if (s3c_dma_has_circular()) | 175 if (s3c_dma_has_circular()) |
| 179 s3c2410_dma_setflags(prtd->params->channel, | 176 s3c2410_dma_setflags(prtd->params->channel, |
| 180 S3C2410_DMAF_CIRCULAR); | 177 S3C2410_DMAF_CIRCULAR); |
| 181 } | 178 } |
| 182 | 179 |
| 183 s3c2410_dma_set_buffdone_fn(prtd->params->channel, | 180 s3c2410_dma_set_buffdone_fn(prtd->params->channel, |
| 184 » » » » s3c24xx_audio_buffdone); | 181 » » » » audio_buffdone); |
| 185 | 182 |
| 186 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | 183 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); |
| 187 | 184 |
| 188 runtime->dma_bytes = totbytes; | 185 runtime->dma_bytes = totbytes; |
| 189 | 186 |
| 190 spin_lock_irq(&prtd->lock); | 187 spin_lock_irq(&prtd->lock); |
| 191 prtd->dma_loaded = 0; | 188 prtd->dma_loaded = 0; |
| 192 prtd->dma_limit = runtime->hw.periods_min; | 189 prtd->dma_limit = runtime->hw.periods_min; |
| 193 prtd->dma_period = params_period_bytes(params); | 190 prtd->dma_period = params_period_bytes(params); |
| 194 prtd->dma_start = runtime->dma_addr; | 191 prtd->dma_start = runtime->dma_addr; |
| 195 prtd->dma_pos = prtd->dma_start; | 192 prtd->dma_pos = prtd->dma_start; |
| 196 prtd->dma_end = prtd->dma_start + totbytes; | 193 prtd->dma_end = prtd->dma_start + totbytes; |
| 197 spin_unlock_irq(&prtd->lock); | 194 spin_unlock_irq(&prtd->lock); |
| 198 | 195 |
| 199 return 0; | 196 return 0; |
| 200 } | 197 } |
| 201 | 198 |
| 202 static int s3c_dma_hw_free(struct snd_pcm_substream *substream) | 199 static int dma_hw_free(struct snd_pcm_substream *substream) |
| 203 { | 200 { |
| 204 » struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; | 201 » struct runtime_data *prtd = substream->runtime->private_data; |
| 205 | 202 |
| 206 pr_debug("Entered %s\n", __func__); | 203 pr_debug("Entered %s\n", __func__); |
| 207 | 204 |
| 208 /* TODO - do we need to ensure DMA flushed */ | 205 /* TODO - do we need to ensure DMA flushed */ |
| 209 snd_pcm_set_runtime_buffer(substream, NULL); | 206 snd_pcm_set_runtime_buffer(substream, NULL); |
| 210 | 207 |
| 211 if (prtd->params) { | 208 if (prtd->params) { |
| 212 s3c2410_dma_free(prtd->params->channel, prtd->params->client); | 209 s3c2410_dma_free(prtd->params->channel, prtd->params->client); |
| 213 prtd->params = NULL; | 210 prtd->params = NULL; |
| 214 } | 211 } |
| 215 | 212 |
| 216 return 0; | 213 return 0; |
| 217 } | 214 } |
| 218 | 215 |
| 219 static int s3c_dma_prepare(struct snd_pcm_substream *substream) | 216 static int dma_prepare(struct snd_pcm_substream *substream) |
| 220 { | 217 { |
| 221 » struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; | 218 » struct runtime_data *prtd = substream->runtime->private_data; |
| 222 int ret = 0; | 219 int ret = 0; |
| 223 | 220 |
| 224 pr_debug("Entered %s\n", __func__); | 221 pr_debug("Entered %s\n", __func__); |
| 225 | 222 |
| 226 /* return if this is a bufferless transfer e.g. | 223 /* return if this is a bufferless transfer e.g. |
| 227 * codec <--> BT codec or GSM modem -- lg FIXME */ | 224 * codec <--> BT codec or GSM modem -- lg FIXME */ |
| 228 if (!prtd->params) | 225 if (!prtd->params) |
| 229 return 0; | 226 return 0; |
| 230 | 227 |
| 231 /* channel needs configuring for mem=>device, increment memory addr, | 228 /* channel needs configuring for mem=>device, increment memory addr, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 242 | 239 |
| 243 s3c2410_dma_config(prtd->params->channel, | 240 s3c2410_dma_config(prtd->params->channel, |
| 244 prtd->params->dma_size); | 241 prtd->params->dma_size); |
| 245 | 242 |
| 246 /* flush the DMA channel */ | 243 /* flush the DMA channel */ |
| 247 s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH); | 244 s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH); |
| 248 prtd->dma_loaded = 0; | 245 prtd->dma_loaded = 0; |
| 249 prtd->dma_pos = prtd->dma_start; | 246 prtd->dma_pos = prtd->dma_start; |
| 250 | 247 |
| 251 /* enqueue dma buffers */ | 248 /* enqueue dma buffers */ |
| 252 » s3c_dma_enqueue(substream); | 249 » dma_enqueue(substream); |
| 253 | 250 |
| 254 return ret; | 251 return ret; |
| 255 } | 252 } |
| 256 | 253 |
| 257 static int s3c_dma_trigger(struct snd_pcm_substream *substream, int cmd) | 254 static int dma_trigger(struct snd_pcm_substream *substream, int cmd) |
| 258 { | 255 { |
| 259 » struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; | 256 » struct runtime_data *prtd = substream->runtime->private_data; |
| 260 int ret = 0; | 257 int ret = 0; |
| 261 | 258 |
| 262 pr_debug("Entered %s\n", __func__); | 259 pr_debug("Entered %s\n", __func__); |
| 263 | 260 |
| 264 spin_lock(&prtd->lock); | 261 spin_lock(&prtd->lock); |
| 265 | 262 |
| 266 switch (cmd) { | 263 switch (cmd) { |
| 267 case SNDRV_PCM_TRIGGER_START: | 264 case SNDRV_PCM_TRIGGER_START: |
| 268 case SNDRV_PCM_TRIGGER_RESUME: | 265 case SNDRV_PCM_TRIGGER_RESUME: |
| 269 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 266 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
| (...skipping 12 matching lines...) Expand all Loading... |
| 282 ret = -EINVAL; | 279 ret = -EINVAL; |
| 283 break; | 280 break; |
| 284 } | 281 } |
| 285 | 282 |
| 286 spin_unlock(&prtd->lock); | 283 spin_unlock(&prtd->lock); |
| 287 | 284 |
| 288 return ret; | 285 return ret; |
| 289 } | 286 } |
| 290 | 287 |
| 291 static snd_pcm_uframes_t | 288 static snd_pcm_uframes_t |
| 292 s3c_dma_pointer(struct snd_pcm_substream *substream) | 289 dma_pointer(struct snd_pcm_substream *substream) |
| 293 { | 290 { |
| 294 struct snd_pcm_runtime *runtime = substream->runtime; | 291 struct snd_pcm_runtime *runtime = substream->runtime; |
| 295 » struct s3c24xx_runtime_data *prtd = runtime->private_data; | 292 » struct runtime_data *prtd = runtime->private_data; |
| 296 unsigned long res; | 293 unsigned long res; |
| 297 dma_addr_t src, dst; | 294 dma_addr_t src, dst; |
| 298 | 295 |
| 299 pr_debug("Entered %s\n", __func__); | 296 pr_debug("Entered %s\n", __func__); |
| 300 | 297 |
| 301 spin_lock(&prtd->lock); | 298 spin_lock(&prtd->lock); |
| 302 s3c2410_dma_getposition(prtd->params->channel, &src, &dst); | 299 s3c2410_dma_getposition(prtd->params->channel, &src, &dst); |
| 303 | 300 |
| 304 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | 301 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) |
| 305 res = dst - prtd->dma_start; | 302 res = dst - prtd->dma_start; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 317 */ | 314 */ |
| 318 | 315 |
| 319 if (res >= snd_pcm_lib_buffer_bytes(substream)) { | 316 if (res >= snd_pcm_lib_buffer_bytes(substream)) { |
| 320 if (res == snd_pcm_lib_buffer_bytes(substream)) | 317 if (res == snd_pcm_lib_buffer_bytes(substream)) |
| 321 res = 0; | 318 res = 0; |
| 322 } | 319 } |
| 323 | 320 |
| 324 return bytes_to_frames(substream->runtime, res); | 321 return bytes_to_frames(substream->runtime, res); |
| 325 } | 322 } |
| 326 | 323 |
| 327 static int s3c_dma_open(struct snd_pcm_substream *substream) | 324 static int dma_open(struct snd_pcm_substream *substream) |
| 328 { | 325 { |
| 329 struct snd_pcm_runtime *runtime = substream->runtime; | 326 struct snd_pcm_runtime *runtime = substream->runtime; |
| 330 » struct s3c24xx_runtime_data *prtd; | 327 » struct runtime_data *prtd; |
| 331 | 328 |
| 332 pr_debug("Entered %s\n", __func__); | 329 pr_debug("Entered %s\n", __func__); |
| 333 | 330 |
| 334 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | 331 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); |
| 335 » snd_soc_set_runtime_hwparams(substream, &s3c_dma_hardware); | 332 » snd_soc_set_runtime_hwparams(substream, &dma_hardware); |
| 336 | 333 |
| 337 » prtd = kzalloc(sizeof(struct s3c24xx_runtime_data), GFP_KERNEL); | 334 » prtd = kzalloc(sizeof(struct runtime_data), GFP_KERNEL); |
| 338 if (prtd == NULL) | 335 if (prtd == NULL) |
| 339 return -ENOMEM; | 336 return -ENOMEM; |
| 340 | 337 |
| 341 spin_lock_init(&prtd->lock); | 338 spin_lock_init(&prtd->lock); |
| 342 | 339 |
| 343 runtime->private_data = prtd; | 340 runtime->private_data = prtd; |
| 344 return 0; | 341 return 0; |
| 345 } | 342 } |
| 346 | 343 |
| 347 static int s3c_dma_close(struct snd_pcm_substream *substream) | 344 static int dma_close(struct snd_pcm_substream *substream) |
| 348 { | 345 { |
| 349 struct snd_pcm_runtime *runtime = substream->runtime; | 346 struct snd_pcm_runtime *runtime = substream->runtime; |
| 350 » struct s3c24xx_runtime_data *prtd = runtime->private_data; | 347 » struct runtime_data *prtd = runtime->private_data; |
| 351 | 348 |
| 352 pr_debug("Entered %s\n", __func__); | 349 pr_debug("Entered %s\n", __func__); |
| 353 | 350 |
| 354 if (!prtd) | 351 if (!prtd) |
| 355 » » pr_debug("s3c_dma_close called with prtd == NULL\n"); | 352 » » pr_debug("dma_close called with prtd == NULL\n"); |
| 356 | 353 |
| 357 kfree(prtd); | 354 kfree(prtd); |
| 358 | 355 |
| 359 return 0; | 356 return 0; |
| 360 } | 357 } |
| 361 | 358 |
| 362 static int s3c_dma_mmap(struct snd_pcm_substream *substream, | 359 static int dma_mmap(struct snd_pcm_substream *substream, |
| 363 struct vm_area_struct *vma) | 360 struct vm_area_struct *vma) |
| 364 { | 361 { |
| 365 struct snd_pcm_runtime *runtime = substream->runtime; | 362 struct snd_pcm_runtime *runtime = substream->runtime; |
| 366 | 363 |
| 367 pr_debug("Entered %s\n", __func__); | 364 pr_debug("Entered %s\n", __func__); |
| 368 | 365 |
| 369 return dma_mmap_writecombine(substream->pcm->card->dev, vma, | 366 return dma_mmap_writecombine(substream->pcm->card->dev, vma, |
| 370 runtime->dma_area, | 367 runtime->dma_area, |
| 371 runtime->dma_addr, | 368 runtime->dma_addr, |
| 372 runtime->dma_bytes); | 369 runtime->dma_bytes); |
| 373 } | 370 } |
| 374 | 371 |
| 375 static struct snd_pcm_ops s3c_dma_ops = { | 372 static struct snd_pcm_ops dma_ops = { |
| 376 » .open» » = s3c_dma_open, | 373 » .open» » = dma_open, |
| 377 » .close» » = s3c_dma_close, | 374 » .close» » = dma_close, |
| 378 .ioctl = snd_pcm_lib_ioctl, | 375 .ioctl = snd_pcm_lib_ioctl, |
| 379 » .hw_params» = s3c_dma_hw_params, | 376 » .hw_params» = dma_hw_params, |
| 380 » .hw_free» = s3c_dma_hw_free, | 377 » .hw_free» = dma_hw_free, |
| 381 » .prepare» = s3c_dma_prepare, | 378 » .prepare» = dma_prepare, |
| 382 » .trigger» = s3c_dma_trigger, | 379 » .trigger» = dma_trigger, |
| 383 » .pointer» = s3c_dma_pointer, | 380 » .pointer» = dma_pointer, |
| 384 » .mmap» » = s3c_dma_mmap, | 381 » .mmap» » = dma_mmap, |
| 385 }; | 382 }; |
| 386 | 383 |
| 387 static int s3c_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | 384 static int preallocate_dma_buffer(struct snd_pcm *pcm, int stream) |
| 388 { | 385 { |
| 389 struct snd_pcm_substream *substream = pcm->streams[stream].substream; | 386 struct snd_pcm_substream *substream = pcm->streams[stream].substream; |
| 390 struct snd_dma_buffer *buf = &substream->dma_buffer; | 387 struct snd_dma_buffer *buf = &substream->dma_buffer; |
| 391 » size_t size = s3c_dma_hardware.buffer_bytes_max; | 388 » size_t size = dma_hardware.buffer_bytes_max; |
| 392 | 389 |
| 393 pr_debug("Entered %s\n", __func__); | 390 pr_debug("Entered %s\n", __func__); |
| 394 | 391 |
| 395 buf->dev.type = SNDRV_DMA_TYPE_DEV; | 392 buf->dev.type = SNDRV_DMA_TYPE_DEV; |
| 396 buf->dev.dev = pcm->card->dev; | 393 buf->dev.dev = pcm->card->dev; |
| 397 buf->private_data = NULL; | 394 buf->private_data = NULL; |
| 398 buf->area = dma_alloc_writecombine(pcm->card->dev, size, | 395 buf->area = dma_alloc_writecombine(pcm->card->dev, size, |
| 399 &buf->addr, GFP_KERNEL); | 396 &buf->addr, GFP_KERNEL); |
| 400 if (!buf->area) | 397 if (!buf->area) |
| 401 return -ENOMEM; | 398 return -ENOMEM; |
| 402 buf->bytes = size; | 399 buf->bytes = size; |
| 403 return 0; | 400 return 0; |
| 404 } | 401 } |
| 405 | 402 |
| 406 static void s3c_dma_free_dma_buffers(struct snd_pcm *pcm) | 403 static void dma_free_dma_buffers(struct snd_pcm *pcm) |
| 407 { | 404 { |
| 408 struct snd_pcm_substream *substream; | 405 struct snd_pcm_substream *substream; |
| 409 struct snd_dma_buffer *buf; | 406 struct snd_dma_buffer *buf; |
| 410 int stream; | 407 int stream; |
| 411 | 408 |
| 412 pr_debug("Entered %s\n", __func__); | 409 pr_debug("Entered %s\n", __func__); |
| 413 | 410 |
| 414 for (stream = 0; stream < 2; stream++) { | 411 for (stream = 0; stream < 2; stream++) { |
| 415 substream = pcm->streams[stream].substream; | 412 substream = pcm->streams[stream].substream; |
| 416 if (!substream) | 413 if (!substream) |
| 417 continue; | 414 continue; |
| 418 | 415 |
| 419 buf = &substream->dma_buffer; | 416 buf = &substream->dma_buffer; |
| 420 if (!buf->area) | 417 if (!buf->area) |
| 421 continue; | 418 continue; |
| 422 | 419 |
| 423 dma_free_writecombine(pcm->card->dev, buf->bytes, | 420 dma_free_writecombine(pcm->card->dev, buf->bytes, |
| 424 buf->area, buf->addr); | 421 buf->area, buf->addr); |
| 425 buf->area = NULL; | 422 buf->area = NULL; |
| 426 } | 423 } |
| 427 } | 424 } |
| 428 | 425 |
| 429 static u64 s3c_dma_mask = DMA_BIT_MASK(32); | 426 static u64 dma_mask = DMA_BIT_MASK(32); |
| 430 | 427 |
| 431 static int s3c_dma_new(struct snd_card *card, | 428 static int dma_new(struct snd_card *card, |
| 432 struct snd_soc_dai *dai, struct snd_pcm *pcm) | 429 struct snd_soc_dai *dai, struct snd_pcm *pcm) |
| 433 { | 430 { |
| 434 int ret = 0; | 431 int ret = 0; |
| 435 | 432 |
| 436 pr_debug("Entered %s\n", __func__); | 433 pr_debug("Entered %s\n", __func__); |
| 437 | 434 |
| 438 if (!card->dev->dma_mask) | 435 if (!card->dev->dma_mask) |
| 439 » » card->dev->dma_mask = &s3c_dma_mask; | 436 » » card->dev->dma_mask = &dma_mask; |
| 440 if (!card->dev->coherent_dma_mask) | 437 if (!card->dev->coherent_dma_mask) |
| 441 card->dev->coherent_dma_mask = 0xffffffff; | 438 card->dev->coherent_dma_mask = 0xffffffff; |
| 442 | 439 |
| 443 if (dai->driver->playback.channels_min) { | 440 if (dai->driver->playback.channels_min) { |
| 444 » » ret = s3c_preallocate_dma_buffer(pcm, | 441 » » ret = preallocate_dma_buffer(pcm, |
| 445 SNDRV_PCM_STREAM_PLAYBACK); | 442 SNDRV_PCM_STREAM_PLAYBACK); |
| 446 if (ret) | 443 if (ret) |
| 447 goto out; | 444 goto out; |
| 448 } | 445 } |
| 449 | 446 |
| 450 if (dai->driver->capture.channels_min) { | 447 if (dai->driver->capture.channels_min) { |
| 451 » » ret = s3c_preallocate_dma_buffer(pcm, | 448 » » ret = preallocate_dma_buffer(pcm, |
| 452 SNDRV_PCM_STREAM_CAPTURE); | 449 SNDRV_PCM_STREAM_CAPTURE); |
| 453 if (ret) | 450 if (ret) |
| 454 goto out; | 451 goto out; |
| 455 } | 452 } |
| 456 out: | 453 out: |
| 457 return ret; | 454 return ret; |
| 458 } | 455 } |
| 459 | 456 |
| 460 static struct snd_soc_platform_driver s3c24xx_soc_platform = { | 457 static struct snd_soc_platform_driver samsung_asoc_platform = { |
| 461 » .ops» » = &s3c_dma_ops, | 458 » .ops» » = &dma_ops, |
| 462 » .pcm_new» = s3c_dma_new, | 459 » .pcm_new» = dma_new, |
| 463 » .pcm_free» = s3c_dma_free_dma_buffers, | 460 » .pcm_free» = dma_free_dma_buffers, |
| 464 }; | 461 }; |
| 465 | 462 |
| 466 static int __devinit s3c24xx_soc_platform_probe(struct platform_device *pdev) | 463 static int __devinit samsung_asoc_platform_probe(struct platform_device *pdev) |
| 467 { | 464 { |
| 468 » return snd_soc_register_platform(&pdev->dev, &s3c24xx_soc_platform); | 465 » return snd_soc_register_platform(&pdev->dev, &samsung_asoc_platform); |
| 469 } | 466 } |
| 470 | 467 |
| 471 static int __devexit s3c24xx_soc_platform_remove(struct platform_device *pdev) | 468 static int __devexit samsung_asoc_platform_remove(struct platform_device *pdev) |
| 472 { | 469 { |
| 473 snd_soc_unregister_platform(&pdev->dev); | 470 snd_soc_unregister_platform(&pdev->dev); |
| 474 return 0; | 471 return 0; |
| 475 } | 472 } |
| 476 | 473 |
| 477 static struct platform_driver s3c24xx_pcm_driver = { | 474 static struct platform_driver asoc_dma_driver = { |
| 478 .driver = { | 475 .driver = { |
| 479 » » .name = "s3c24xx-pcm-audio", | 476 » » .name = "samsung-audio", |
| 480 .owner = THIS_MODULE, | 477 .owner = THIS_MODULE, |
| 481 }, | 478 }, |
| 482 | 479 |
| 483 » .probe = s3c24xx_soc_platform_probe, | 480 » .probe = samsung_asoc_platform_probe, |
| 484 » .remove = __devexit_p(s3c24xx_soc_platform_remove), | 481 » .remove = __devexit_p(samsung_asoc_platform_remove), |
| 485 }; | 482 }; |
| 486 | 483 |
| 487 static int __init snd_s3c24xx_pcm_init(void) | 484 static int __init samsung_asoc_init(void) |
| 488 { | 485 { |
| 489 » return platform_driver_register(&s3c24xx_pcm_driver); | 486 » return platform_driver_register(&asoc_dma_driver); |
| 490 } | 487 } |
| 491 module_init(snd_s3c24xx_pcm_init); | 488 module_init(samsung_asoc_init); |
| 492 | 489 |
| 493 static void __exit snd_s3c24xx_pcm_exit(void) | 490 static void __exit samsung_asoc_exit(void) |
| 494 { | 491 { |
| 495 » platform_driver_unregister(&s3c24xx_pcm_driver); | 492 » platform_driver_unregister(&asoc_dma_driver); |
| 496 } | 493 } |
| 497 module_exit(snd_s3c24xx_pcm_exit); | 494 module_exit(samsung_asoc_exit); |
| 498 | 495 |
| 499 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | 496 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); |
| 500 MODULE_DESCRIPTION("Samsung S3C Audio DMA module"); | 497 MODULE_DESCRIPTION("Samsung ASoC DMA Driver"); |
| 501 MODULE_LICENSE("GPL"); | 498 MODULE_LICENSE("GPL"); |
| 502 MODULE_ALIAS("platform:s3c24xx-pcm-audio"); | 499 MODULE_ALIAS("platform:samsung-audio"); |
| OLD | NEW |