1 /* 2 * Copyright (C) ST-Ericsson SA 2012 3 * 4 * Author: Ola Lilja <ola.o.lilja@stericsson.com>, 5 * Roger Nilsson <roger.xr.nilsson@stericsson.com> 6 * for ST-Ericsson. 7 * 8 * License terms: 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as published 12 * by the Free Software Foundation. 13 */ 14 15 #include <asm/page.h> 16 17 #include <linux/module.h> 18 #include <linux/dma-mapping.h> 19 #include <linux/dmaengine.h> 20 #include <linux/slab.h> 21 22 #include <plat/ste_dma40.h> 23 24 #include <sound/pcm.h> 25 #include <sound/pcm_params.h> 26 #include <sound/soc.h> 27 #include <sound/dmaengine_pcm.h> 28 29 #include "ux500_msp_i2s.h" 30 #include "ux500_pcm.h" 31 32 static struct snd_pcm_hardware ux500_pcm_hw_playback = { 33 .info = SNDRV_PCM_INFO_INTERLEAVED | 34 SNDRV_PCM_INFO_MMAP | 35 SNDRV_PCM_INFO_RESUME | 36 SNDRV_PCM_INFO_PAUSE, 37 .formats = SNDRV_PCM_FMTBIT_S16_LE | 38 SNDRV_PCM_FMTBIT_U16_LE | 39 SNDRV_PCM_FMTBIT_S16_BE | 40 SNDRV_PCM_FMTBIT_U16_BE, 41 .rates = SNDRV_PCM_RATE_KNOT, 42 .rate_min = UX500_PLATFORM_MIN_RATE_PLAYBACK, 43 .rate_max = UX500_PLATFORM_MAX_RATE_PLAYBACK, 44 .channels_min = UX500_PLATFORM_MIN_CHANNELS, 45 .channels_max = UX500_PLATFORM_MAX_CHANNELS, 46 .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX, 47 .period_bytes_min = UX500_PLATFORM_PERIODS_BYTES_MIN, 48 .period_bytes_max = UX500_PLATFORM_PERIODS_BYTES_MAX, 49 .periods_min = UX500_PLATFORM_PERIODS_MIN, 50 .periods_max = UX500_PLATFORM_PERIODS_MAX, 51 }; 52 53 static struct snd_pcm_hardware ux500_pcm_hw_capture = { 54 .info = SNDRV_PCM_INFO_INTERLEAVED | 55 SNDRV_PCM_INFO_MMAP | 56 SNDRV_PCM_INFO_RESUME | 57 SNDRV_PCM_INFO_PAUSE, 58 .formats = SNDRV_PCM_FMTBIT_S16_LE | 59 SNDRV_PCM_FMTBIT_U16_LE | 60 SNDRV_PCM_FMTBIT_S16_BE | 61 SNDRV_PCM_FMTBIT_U16_BE, 62 .rates = SNDRV_PCM_RATE_KNOT, 63 .rate_min = UX500_PLATFORM_MIN_RATE_CAPTURE, 64 .rate_max = UX500_PLATFORM_MAX_RATE_CAPTURE, 65 .channels_min = UX500_PLATFORM_MIN_CHANNELS, 66 .channels_max = UX500_PLATFORM_MAX_CHANNELS, 67 .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX, 68 .period_bytes_min = UX500_PLATFORM_PERIODS_BYTES_MIN, 69 .period_bytes_max = UX500_PLATFORM_PERIODS_BYTES_MAX, 70 .periods_min = UX500_PLATFORM_PERIODS_MIN, 71 .periods_max = UX500_PLATFORM_PERIODS_MAX, 72 }; 73 74 static void ux500_pcm_dma_hw_free(struct device *dev, 75 struct snd_pcm_substream *substream) 76 { 77 struct snd_pcm_runtime *runtime = substream->runtime; 78 struct snd_dma_buffer *buf = runtime->dma_buffer_p; 79 80 if (runtime->dma_area == NULL) 81 return; 82 83 if (buf != &substream->dma_buffer) { 84 dma_free_coherent(buf->dev.dev, buf->bytes, buf->area, 85 buf->addr); 86 kfree(runtime->dma_buffer_p); 87 } 88 89 snd_pcm_set_runtime_buffer(substream, NULL); 90 } 91 92 static int ux500_pcm_open(struct snd_pcm_substream *substream) 93 { 94 int stream_id = substream->pstr->stream; 95 struct snd_pcm_runtime *runtime = substream->runtime; 96 struct snd_soc_pcm_runtime *rtd = substream->private_data; 97 struct snd_soc_dai *dai = rtd->cpu_dai; 98 struct device *dev = dai->dev; 99 int ret; 100 struct ux500_msp_dma_params *dma_params; 101 u16 per_data_width, mem_data_width; 102 struct stedma40_chan_cfg *dma_cfg; 103 104 dev_dbg(dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id, 105 snd_pcm_stream_str(substream)); 106 107 dev_dbg(dev, "%s: Set runtime hwparams.\n", __func__); 108 if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) 109 snd_soc_set_runtime_hwparams(substream, 110 &ux500_pcm_hw_playback); 111 else 112 snd_soc_set_runtime_hwparams(substream, 113 &ux500_pcm_hw_capture); 114 115 /* ensure that buffer size is a multiple of period size */ 116 ret = snd_pcm_hw_constraint_integer(runtime, 117 SNDRV_PCM_HW_PARAM_PERIODS); 118 if (ret < 0) { 119 dev_err(dev, "%s: Error: snd_pcm_hw_constraints failed (%d)\n", 120 __func__, ret); 121 return ret; 122 } 123 124 dev_dbg(dev, "%s: Set hw-struct for %s.\n", __func__, 125 snd_pcm_stream_str(substream)); 126 runtime->hw = (stream_id == SNDRV_PCM_STREAM_PLAYBACK) ? 127 ux500_pcm_hw_playback : ux500_pcm_hw_capture; 128 129 mem_data_width = STEDMA40_HALFWORD_WIDTH; 130 131 dma_params = snd_soc_dai_get_dma_data(dai, substream); 132 switch (dma_params->data_size) { 133 case 32: 134 per_data_width = STEDMA40_WORD_WIDTH; 135 break; 136 case 16: 137 per_data_width = STEDMA40_HALFWORD_WIDTH; 138 break; 139 case 8: 140 per_data_width = STEDMA40_BYTE_WIDTH; 141 break; 142 default: 143 per_data_width = STEDMA40_WORD_WIDTH; 144 dev_warn(rtd->platform->dev, 145 "%s: Unknown data-size (%d)! Assuming 32 bits.\n", 146 __func__, dma_params->data_size); 147 } 148 149 dma_cfg = dma_params->dma_cfg; 150 151 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 152 dma_cfg->src_info.data_width = mem_data_width; 153 dma_cfg->dst_info.data_width = per_data_width; 154 } else { 155 dma_cfg->src_info.data_width = per_data_width; 156 dma_cfg->dst_info.data_width = mem_data_width; 157 } 158 159 160 ret = snd_dmaengine_pcm_open(substream, stedma40_filter, dma_cfg); 161 if (ret) { 162 dev_dbg(dai->dev, 163 "%s: ERROR: snd_dmaengine_pcm_open failed (%d)!\n", 164 __func__, ret); 165 return ret; 166 } 167 168 snd_dmaengine_pcm_set_data(substream, dma_cfg); 169 170 return 0; 171 } 172 173 static int ux500_pcm_close(struct snd_pcm_substream *substream) 174 { 175 struct snd_soc_pcm_runtime *rtd = substream->private_data; 176 struct snd_soc_dai *dai = rtd->cpu_dai; 177 178 dev_dbg(dai->dev, "%s: Enter\n", __func__); 179 180 snd_dmaengine_pcm_close(substream); 181 182 return 0; 183 } 184 185 static int ux500_pcm_hw_params(struct snd_pcm_substream *substream, 186 struct snd_pcm_hw_params *hw_params) 187 { 188 struct snd_pcm_runtime *runtime = substream->runtime; 189 struct snd_dma_buffer *buf = runtime->dma_buffer_p; 190 struct snd_soc_pcm_runtime *rtd = substream->private_data; 191 int ret = 0; 192 int size; 193 194 dev_dbg(rtd->platform->dev, "%s: Enter\n", __func__); 195 196 size = params_buffer_bytes(hw_params); 197 198 if (buf) { 199 if (buf->bytes >= size) 200 goto out; 201 ux500_pcm_dma_hw_free(NULL, substream); 202 } 203 204 if (substream->dma_buffer.area != NULL && 205 substream->dma_buffer.bytes >= size) { 206 buf = &substream->dma_buffer; 207 } else { 208 buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL); 209 if (!buf) 210 goto nomem; 211 212 buf->dev.type = SNDRV_DMA_TYPE_DEV; 213 buf->dev.dev = NULL; 214 buf->area = dma_alloc_coherent(NULL, size, &buf->addr, 215 GFP_KERNEL); 216 buf->bytes = size; 217 buf->private_data = NULL; 218 219 if (!buf->area) 220 goto free; 221 } 222 snd_pcm_set_runtime_buffer(substream, buf); 223 ret = 1; 224 out: 225 runtime->dma_bytes = size; 226 return ret; 227 228 free: 229 kfree(buf); 230 nomem: 231 return -ENOMEM; 232 } 233 234 static int ux500_pcm_hw_free(struct snd_pcm_substream *substream) 235 { 236 struct snd_soc_pcm_runtime *rtd = substream->private_data; 237 238 dev_dbg(rtd->platform->dev, "%s: Enter\n", __func__); 239 240 ux500_pcm_dma_hw_free(NULL, substream); 241 242 return 0; 243 } 244 245 static int ux500_pcm_mmap(struct snd_pcm_substream *substream, 246 struct vm_area_struct *vma) 247 { 248 struct snd_pcm_runtime *runtime = substream->runtime; 249 struct snd_soc_pcm_runtime *rtd = substream->private_data; 250 251 dev_dbg(rtd->platform->dev, "%s: Enter.\n", __func__); 252 253 return dma_mmap_coherent(NULL, vma, runtime->dma_area, 254 runtime->dma_addr, runtime->dma_bytes); 255 } 256 257 static struct snd_pcm_ops ux500_pcm_ops = { 258 .open = ux500_pcm_open, 259 .close = ux500_pcm_close, 260 .ioctl = snd_pcm_lib_ioctl, 261 .hw_params = ux500_pcm_hw_params, 262 .hw_free = ux500_pcm_hw_free, 263 .trigger = snd_dmaengine_pcm_trigger, 264 .pointer = snd_dmaengine_pcm_pointer_no_residue, 265 .mmap = ux500_pcm_mmap 266 }; 267 268 int ux500_pcm_new(struct snd_soc_pcm_runtime *rtd) 269 { 270 struct snd_pcm *pcm = rtd->pcm; 271 272 dev_dbg(rtd->platform->dev, "%s: Enter (id = '%s').\n", __func__, 273 pcm->id); 274 275 pcm->info_flags = 0; 276 277 return 0; 278 } 279 280 static struct snd_soc_platform_driver ux500_pcm_soc_drv = { 281 .ops = &ux500_pcm_ops, 282 .pcm_new = ux500_pcm_new, 283 }; 284 285 static int __devexit ux500_pcm_drv_probe(struct platform_device *pdev) 286 { 287 int ret; 288 289 ret = snd_soc_register_platform(&pdev->dev, &ux500_pcm_soc_drv); 290 if (ret < 0) { 291 dev_err(&pdev->dev, 292 "%s: ERROR: Failed to register platform '%s' (%d)!\n", 293 __func__, pdev->name, ret); 294 return ret; 295 } 296 297 return 0; 298 } 299 300 static int __devinit ux500_pcm_drv_remove(struct platform_device *pdev) 301 { 302 snd_soc_unregister_platform(&pdev->dev); 303 304 return 0; 305 } 306 307 static struct platform_driver ux500_pcm_driver = { 308 .driver = { 309 .name = "ux500-pcm", 310 .owner = THIS_MODULE, 311 }, 312 313 .probe = ux500_pcm_drv_probe, 314 .remove = __devexit_p(ux500_pcm_drv_remove), 315 }; 316 module_platform_driver(ux500_pcm_driver); 317 318 MODULE_LICENSE("GPL v2"); 319