1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Intel Baytrail SST PCM Support 4 * Copyright (c) 2014, Intel Corporation. 5 */ 6 7 #include <linux/module.h> 8 #include <linux/dma-mapping.h> 9 #include <linux/slab.h> 10 #include <sound/core.h> 11 #include <sound/pcm.h> 12 #include <sound/pcm_params.h> 13 #include <sound/soc.h> 14 #include "sst-baytrail-ipc.h" 15 #include "../common/sst-dsp-priv.h" 16 #include "../common/sst-dsp.h" 17 18 #define DRV_NAME "byt-dai" 19 #define BYT_PCM_COUNT 2 20 21 static const struct snd_pcm_hardware sst_byt_pcm_hardware = { 22 .info = SNDRV_PCM_INFO_MMAP | 23 SNDRV_PCM_INFO_MMAP_VALID | 24 SNDRV_PCM_INFO_INTERLEAVED | 25 SNDRV_PCM_INFO_PAUSE | 26 SNDRV_PCM_INFO_RESUME, 27 .formats = SNDRV_PCM_FMTBIT_S16_LE | 28 SNDRV_PCM_FMTBIT_S24_LE, 29 .period_bytes_min = 384, 30 .period_bytes_max = 48000, 31 .periods_min = 2, 32 .periods_max = 250, 33 .buffer_bytes_max = 96000, 34 }; 35 36 /* private data for each PCM DSP stream */ 37 struct sst_byt_pcm_data { 38 struct sst_byt_stream *stream; 39 struct snd_pcm_substream *substream; 40 struct mutex mutex; 41 42 /* latest DSP DMA hw pointer */ 43 u32 hw_ptr; 44 45 struct work_struct work; 46 }; 47 48 /* private data for the driver */ 49 struct sst_byt_priv_data { 50 /* runtime DSP */ 51 struct sst_byt *byt; 52 53 /* DAI data */ 54 struct sst_byt_pcm_data pcm[BYT_PCM_COUNT]; 55 56 /* flag indicating is stream context restore needed after suspend */ 57 bool restore_stream; 58 }; 59 60 /* this may get called several times by oss emulation */ 61 static int sst_byt_pcm_hw_params(struct snd_soc_component *component, 62 struct snd_pcm_substream *substream, 63 struct snd_pcm_hw_params *params) 64 { 65 struct snd_soc_pcm_runtime *rtd = substream->private_data; 66 struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); 67 struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; 68 struct sst_byt *byt = pdata->byt; 69 u32 rate, bits; 70 u8 channels; 71 int ret, playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); 72 73 dev_dbg(rtd->dev, "PCM: hw_params, pcm_data %p\n", pcm_data); 74 75 ret = sst_byt_stream_type(byt, pcm_data->stream, 76 1, 1, !playback); 77 if (ret < 0) { 78 dev_err(rtd->dev, "failed to set stream format %d\n", ret); 79 return ret; 80 } 81 82 rate = params_rate(params); 83 ret = sst_byt_stream_set_rate(byt, pcm_data->stream, rate); 84 if (ret < 0) { 85 dev_err(rtd->dev, "could not set rate %d\n", rate); 86 return ret; 87 } 88 89 bits = snd_pcm_format_width(params_format(params)); 90 ret = sst_byt_stream_set_bits(byt, pcm_data->stream, bits); 91 if (ret < 0) { 92 dev_err(rtd->dev, "could not set formats %d\n", 93 params_rate(params)); 94 return ret; 95 } 96 97 channels = (u8)(params_channels(params) & 0xF); 98 ret = sst_byt_stream_set_channels(byt, pcm_data->stream, channels); 99 if (ret < 0) { 100 dev_err(rtd->dev, "could not set channels %d\n", 101 params_rate(params)); 102 return ret; 103 } 104 105 snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); 106 107 ret = sst_byt_stream_buffer(byt, pcm_data->stream, 108 substream->dma_buffer.addr, 109 params_buffer_bytes(params)); 110 if (ret < 0) { 111 dev_err(rtd->dev, "PCM: failed to set DMA buffer %d\n", ret); 112 return ret; 113 } 114 115 ret = sst_byt_stream_commit(byt, pcm_data->stream); 116 if (ret < 0) { 117 dev_err(rtd->dev, "PCM: failed stream commit %d\n", ret); 118 return ret; 119 } 120 121 return 0; 122 } 123 124 static int sst_byt_pcm_hw_free(struct snd_soc_component *component, 125 struct snd_pcm_substream *substream) 126 { 127 struct snd_soc_pcm_runtime *rtd = substream->private_data; 128 129 dev_dbg(rtd->dev, "PCM: hw_free\n"); 130 snd_pcm_lib_free_pages(substream); 131 132 return 0; 133 } 134 135 static int sst_byt_pcm_restore_stream_context(struct snd_pcm_substream *substream) 136 { 137 struct snd_soc_pcm_runtime *rtd = substream->private_data; 138 struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); 139 struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); 140 struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; 141 struct sst_byt *byt = pdata->byt; 142 int ret; 143 144 /* commit stream using existing stream params */ 145 ret = sst_byt_stream_commit(byt, pcm_data->stream); 146 if (ret < 0) { 147 dev_err(rtd->dev, "PCM: failed stream commit %d\n", ret); 148 return ret; 149 } 150 151 sst_byt_stream_start(byt, pcm_data->stream, pcm_data->hw_ptr); 152 153 dev_dbg(rtd->dev, "stream context restored at offset %d\n", 154 pcm_data->hw_ptr); 155 156 return 0; 157 } 158 159 static void sst_byt_pcm_work(struct work_struct *work) 160 { 161 struct sst_byt_pcm_data *pcm_data = 162 container_of(work, struct sst_byt_pcm_data, work); 163 164 if (snd_pcm_running(pcm_data->substream)) 165 sst_byt_pcm_restore_stream_context(pcm_data->substream); 166 } 167 168 static int sst_byt_pcm_trigger(struct snd_soc_component *component, 169 struct snd_pcm_substream *substream, int cmd) 170 { 171 struct snd_soc_pcm_runtime *rtd = substream->private_data; 172 struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); 173 struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; 174 struct sst_byt *byt = pdata->byt; 175 176 dev_dbg(rtd->dev, "PCM: trigger %d\n", cmd); 177 178 switch (cmd) { 179 case SNDRV_PCM_TRIGGER_START: 180 pcm_data->hw_ptr = 0; 181 sst_byt_stream_start(byt, pcm_data->stream, 0); 182 break; 183 case SNDRV_PCM_TRIGGER_RESUME: 184 if (pdata->restore_stream) 185 schedule_work(&pcm_data->work); 186 else 187 sst_byt_stream_resume(byt, pcm_data->stream); 188 break; 189 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 190 sst_byt_stream_resume(byt, pcm_data->stream); 191 break; 192 case SNDRV_PCM_TRIGGER_STOP: 193 sst_byt_stream_stop(byt, pcm_data->stream); 194 break; 195 case SNDRV_PCM_TRIGGER_SUSPEND: 196 pdata->restore_stream = false; 197 /* fallthrough */ 198 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 199 sst_byt_stream_pause(byt, pcm_data->stream); 200 break; 201 default: 202 break; 203 } 204 205 return 0; 206 } 207 208 static u32 byt_notify_pointer(struct sst_byt_stream *stream, void *data) 209 { 210 struct sst_byt_pcm_data *pcm_data = data; 211 struct snd_pcm_substream *substream = pcm_data->substream; 212 struct snd_pcm_runtime *runtime = substream->runtime; 213 struct snd_soc_pcm_runtime *rtd = substream->private_data; 214 struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); 215 struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); 216 struct sst_byt *byt = pdata->byt; 217 u32 pos, hw_pos; 218 219 hw_pos = sst_byt_get_dsp_position(byt, pcm_data->stream, 220 snd_pcm_lib_buffer_bytes(substream)); 221 pcm_data->hw_ptr = hw_pos; 222 pos = frames_to_bytes(runtime, 223 (runtime->control->appl_ptr % 224 runtime->buffer_size)); 225 226 dev_dbg(rtd->dev, "PCM: App/DMA pointer %u/%u bytes\n", pos, hw_pos); 227 228 snd_pcm_period_elapsed(substream); 229 return pos; 230 } 231 232 static snd_pcm_uframes_t sst_byt_pcm_pointer(struct snd_soc_component *component, 233 struct snd_pcm_substream *substream) 234 { 235 struct snd_soc_pcm_runtime *rtd = substream->private_data; 236 struct snd_pcm_runtime *runtime = substream->runtime; 237 struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); 238 struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; 239 240 dev_dbg(rtd->dev, "PCM: DMA pointer %u bytes\n", pcm_data->hw_ptr); 241 242 return bytes_to_frames(runtime, pcm_data->hw_ptr); 243 } 244 245 static int sst_byt_pcm_open(struct snd_soc_component *component, 246 struct snd_pcm_substream *substream) 247 { 248 struct snd_soc_pcm_runtime *rtd = substream->private_data; 249 struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); 250 struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; 251 struct sst_byt *byt = pdata->byt; 252 253 dev_dbg(rtd->dev, "PCM: open\n"); 254 255 mutex_lock(&pcm_data->mutex); 256 257 pcm_data->substream = substream; 258 259 snd_soc_set_runtime_hwparams(substream, &sst_byt_pcm_hardware); 260 261 pcm_data->stream = sst_byt_stream_new(byt, substream->stream + 1, 262 byt_notify_pointer, pcm_data); 263 if (pcm_data->stream == NULL) { 264 dev_err(rtd->dev, "failed to create stream\n"); 265 mutex_unlock(&pcm_data->mutex); 266 return -EINVAL; 267 } 268 269 mutex_unlock(&pcm_data->mutex); 270 return 0; 271 } 272 273 static int sst_byt_pcm_close(struct snd_soc_component *component, 274 struct snd_pcm_substream *substream) 275 { 276 struct snd_soc_pcm_runtime *rtd = substream->private_data; 277 struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component); 278 struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream]; 279 struct sst_byt *byt = pdata->byt; 280 int ret; 281 282 dev_dbg(rtd->dev, "PCM: close\n"); 283 284 cancel_work_sync(&pcm_data->work); 285 mutex_lock(&pcm_data->mutex); 286 ret = sst_byt_stream_free(byt, pcm_data->stream); 287 if (ret < 0) { 288 dev_dbg(rtd->dev, "Free stream fail\n"); 289 goto out; 290 } 291 pcm_data->stream = NULL; 292 293 out: 294 mutex_unlock(&pcm_data->mutex); 295 return ret; 296 } 297 298 static int sst_byt_pcm_mmap(struct snd_soc_component *component, 299 struct snd_pcm_substream *substream, 300 struct vm_area_struct *vma) 301 { 302 struct snd_soc_pcm_runtime *rtd = substream->private_data; 303 304 dev_dbg(rtd->dev, "PCM: mmap\n"); 305 return snd_pcm_lib_default_mmap(substream, vma); 306 } 307 308 static int sst_byt_pcm_new(struct snd_soc_component *component, 309 struct snd_soc_pcm_runtime *rtd) 310 { 311 struct snd_pcm *pcm = rtd->pcm; 312 size_t size; 313 struct sst_pdata *pdata = dev_get_platdata(component->dev); 314 315 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream || 316 pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { 317 size = sst_byt_pcm_hardware.buffer_bytes_max; 318 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 319 pdata->dma_dev, 320 size, size); 321 } 322 323 return 0; 324 } 325 326 static struct snd_soc_dai_driver byt_dais[] = { 327 { 328 .name = "Baytrail PCM", 329 .playback = { 330 .stream_name = "System Playback", 331 .channels_min = 2, 332 .channels_max = 2, 333 .rates = SNDRV_PCM_RATE_48000, 334 .formats = SNDRV_PCM_FMTBIT_S24_3LE | 335 SNDRV_PCM_FMTBIT_S16_LE, 336 }, 337 .capture = { 338 .stream_name = "Analog Capture", 339 .channels_min = 2, 340 .channels_max = 2, 341 .rates = SNDRV_PCM_RATE_48000, 342 .formats = SNDRV_PCM_FMTBIT_S16_LE, 343 }, 344 }, 345 }; 346 347 static int sst_byt_pcm_probe(struct snd_soc_component *component) 348 { 349 struct sst_pdata *plat_data = dev_get_platdata(component->dev); 350 struct sst_byt_priv_data *priv_data; 351 int i; 352 353 if (!plat_data) 354 return -ENODEV; 355 356 priv_data = devm_kzalloc(component->dev, sizeof(*priv_data), 357 GFP_KERNEL); 358 if (!priv_data) 359 return -ENOMEM; 360 priv_data->byt = plat_data->dsp; 361 snd_soc_component_set_drvdata(component, priv_data); 362 363 for (i = 0; i < BYT_PCM_COUNT; i++) { 364 mutex_init(&priv_data->pcm[i].mutex); 365 INIT_WORK(&priv_data->pcm[i].work, sst_byt_pcm_work); 366 } 367 368 return 0; 369 } 370 371 static const struct snd_soc_component_driver byt_dai_component = { 372 .name = DRV_NAME, 373 .probe = sst_byt_pcm_probe, 374 .open = sst_byt_pcm_open, 375 .close = sst_byt_pcm_close, 376 .ioctl = snd_soc_pcm_lib_ioctl, 377 .hw_params = sst_byt_pcm_hw_params, 378 .hw_free = sst_byt_pcm_hw_free, 379 .trigger = sst_byt_pcm_trigger, 380 .pointer = sst_byt_pcm_pointer, 381 .mmap = sst_byt_pcm_mmap, 382 .pcm_construct = sst_byt_pcm_new, 383 }; 384 385 #ifdef CONFIG_PM 386 static int sst_byt_pcm_dev_suspend_late(struct device *dev) 387 { 388 struct sst_pdata *sst_pdata = dev_get_platdata(dev); 389 struct sst_byt_priv_data *priv_data = dev_get_drvdata(dev); 390 int ret; 391 392 dev_dbg(dev, "suspending late\n"); 393 394 ret = sst_byt_dsp_suspend_late(dev, sst_pdata); 395 if (ret < 0) { 396 dev_err(dev, "failed to suspend %d\n", ret); 397 return ret; 398 } 399 400 priv_data->restore_stream = true; 401 402 return ret; 403 } 404 405 static int sst_byt_pcm_dev_resume_early(struct device *dev) 406 { 407 struct sst_pdata *sst_pdata = dev_get_platdata(dev); 408 int ret; 409 410 dev_dbg(dev, "resume early\n"); 411 412 /* load fw and boot DSP */ 413 ret = sst_byt_dsp_boot(dev, sst_pdata); 414 if (ret) 415 return ret; 416 417 /* wait for FW to finish booting */ 418 return sst_byt_dsp_wait_for_ready(dev, sst_pdata); 419 } 420 421 static const struct dev_pm_ops sst_byt_pm_ops = { 422 .suspend_late = sst_byt_pcm_dev_suspend_late, 423 .resume_early = sst_byt_pcm_dev_resume_early, 424 }; 425 426 #define SST_BYT_PM_OPS (&sst_byt_pm_ops) 427 #else 428 #define SST_BYT_PM_OPS NULL 429 #endif 430 431 static int sst_byt_pcm_dev_probe(struct platform_device *pdev) 432 { 433 struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev); 434 int ret; 435 436 ret = sst_byt_dsp_init(&pdev->dev, sst_pdata); 437 if (ret < 0) 438 return -ENODEV; 439 440 ret = devm_snd_soc_register_component(&pdev->dev, &byt_dai_component, 441 byt_dais, ARRAY_SIZE(byt_dais)); 442 if (ret < 0) 443 goto err_plat; 444 445 return 0; 446 447 err_plat: 448 sst_byt_dsp_free(&pdev->dev, sst_pdata); 449 return ret; 450 } 451 452 static int sst_byt_pcm_dev_remove(struct platform_device *pdev) 453 { 454 struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev); 455 456 sst_byt_dsp_free(&pdev->dev, sst_pdata); 457 458 return 0; 459 } 460 461 static struct platform_driver sst_byt_pcm_driver = { 462 .driver = { 463 .name = "baytrail-pcm-audio", 464 .pm = SST_BYT_PM_OPS, 465 }, 466 467 .probe = sst_byt_pcm_dev_probe, 468 .remove = sst_byt_pcm_dev_remove, 469 }; 470 module_platform_driver(sst_byt_pcm_driver); 471 472 MODULE_AUTHOR("Jarkko Nikula"); 473 MODULE_DESCRIPTION("Baytrail PCM"); 474 MODULE_LICENSE("GPL v2"); 475 MODULE_ALIAS("platform:baytrail-pcm-audio"); 476
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.