root/sound/soc/qcom/qdsp6/q6asm-dai.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. event_handler
  2. q6asm_dai_prepare
  3. q6asm_dai_trigger
  4. q6asm_dai_open
  5. q6asm_dai_close
  6. q6asm_dai_pointer
  7. q6asm_dai_mmap
  8. q6asm_dai_hw_params
  9. compress_event_handler
  10. q6asm_dai_compr_open
  11. q6asm_dai_compr_free
  12. q6asm_dai_compr_set_params
  13. q6asm_dai_compr_trigger
  14. q6asm_dai_compr_pointer
  15. q6asm_dai_compr_ack
  16. q6asm_dai_compr_mmap
  17. q6asm_dai_compr_get_caps
  18. q6asm_dai_compr_get_codec_caps
  19. q6asm_dai_pcm_new
  20. q6asm_dai_pcm_free
  21. of_q6asm_parse_dai_data
  22. q6asm_dai_probe

   1 // SPDX-License-Identifier: GPL-2.0
   2 // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
   3 // Copyright (c) 2018, Linaro Limited
   4 
   5 #include <linux/init.h>
   6 #include <linux/err.h>
   7 #include <linux/module.h>
   8 #include <linux/platform_device.h>
   9 #include <linux/slab.h>
  10 #include <sound/soc.h>
  11 #include <sound/soc-dapm.h>
  12 #include <sound/pcm.h>
  13 #include <linux/spinlock.h>
  14 #include <sound/compress_driver.h>
  15 #include <asm/dma.h>
  16 #include <linux/dma-mapping.h>
  17 #include <linux/of_device.h>
  18 #include <sound/pcm_params.h>
  19 #include "q6asm.h"
  20 #include "q6routing.h"
  21 #include "q6dsp-errno.h"
  22 
  23 #define DRV_NAME        "q6asm-fe-dai"
  24 
  25 #define PLAYBACK_MIN_NUM_PERIODS    2
  26 #define PLAYBACK_MAX_NUM_PERIODS   8
  27 #define PLAYBACK_MAX_PERIOD_SIZE    65536
  28 #define PLAYBACK_MIN_PERIOD_SIZE    128
  29 #define CAPTURE_MIN_NUM_PERIODS     2
  30 #define CAPTURE_MAX_NUM_PERIODS     8
  31 #define CAPTURE_MAX_PERIOD_SIZE     4096
  32 #define CAPTURE_MIN_PERIOD_SIZE     320
  33 #define SID_MASK_DEFAULT        0xF
  34 
  35 /* Default values used if user space does not set */
  36 #define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024)
  37 #define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024)
  38 #define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4)
  39 #define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4)
  40 #define Q6ASM_DAI_TX_RX 0
  41 #define Q6ASM_DAI_TX    1
  42 #define Q6ASM_DAI_RX    2
  43 
  44 enum stream_state {
  45         Q6ASM_STREAM_IDLE = 0,
  46         Q6ASM_STREAM_STOPPED,
  47         Q6ASM_STREAM_RUNNING,
  48 };
  49 
  50 struct q6asm_dai_rtd {
  51         struct snd_pcm_substream *substream;
  52         struct snd_compr_stream *cstream;
  53         struct snd_compr_params codec_param;
  54         struct snd_dma_buffer dma_buffer;
  55         spinlock_t lock;
  56         phys_addr_t phys;
  57         unsigned int pcm_size;
  58         unsigned int pcm_count;
  59         unsigned int pcm_irq_pos;       /* IRQ position */
  60         unsigned int periods;
  61         unsigned int bytes_sent;
  62         unsigned int bytes_received;
  63         unsigned int copied_total;
  64         uint16_t bits_per_sample;
  65         uint16_t source; /* Encoding source bit mask */
  66         struct audio_client *audio_client;
  67         uint16_t session_id;
  68         enum stream_state state;
  69 };
  70 
  71 struct q6asm_dai_data {
  72         long long int sid;
  73 };
  74 
  75 static struct snd_pcm_hardware q6asm_dai_hardware_capture = {
  76         .info =                 (SNDRV_PCM_INFO_MMAP |
  77                                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
  78                                 SNDRV_PCM_INFO_MMAP_VALID |
  79                                 SNDRV_PCM_INFO_INTERLEAVED |
  80                                 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
  81         .formats =              (SNDRV_PCM_FMTBIT_S16_LE |
  82                                 SNDRV_PCM_FMTBIT_S24_LE),
  83         .rates =                SNDRV_PCM_RATE_8000_48000,
  84         .rate_min =             8000,
  85         .rate_max =             48000,
  86         .channels_min =         1,
  87         .channels_max =         4,
  88         .buffer_bytes_max =     CAPTURE_MAX_NUM_PERIODS *
  89                                 CAPTURE_MAX_PERIOD_SIZE,
  90         .period_bytes_min =     CAPTURE_MIN_PERIOD_SIZE,
  91         .period_bytes_max =     CAPTURE_MAX_PERIOD_SIZE,
  92         .periods_min =          CAPTURE_MIN_NUM_PERIODS,
  93         .periods_max =          CAPTURE_MAX_NUM_PERIODS,
  94         .fifo_size =            0,
  95 };
  96 
  97 static struct snd_pcm_hardware q6asm_dai_hardware_playback = {
  98         .info =                 (SNDRV_PCM_INFO_MMAP |
  99                                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
 100                                 SNDRV_PCM_INFO_MMAP_VALID |
 101                                 SNDRV_PCM_INFO_INTERLEAVED |
 102                                 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
 103         .formats =              (SNDRV_PCM_FMTBIT_S16_LE |
 104                                 SNDRV_PCM_FMTBIT_S24_LE),
 105         .rates =                SNDRV_PCM_RATE_8000_192000,
 106         .rate_min =             8000,
 107         .rate_max =             192000,
 108         .channels_min =         1,
 109         .channels_max =         8,
 110         .buffer_bytes_max =     (PLAYBACK_MAX_NUM_PERIODS *
 111                                 PLAYBACK_MAX_PERIOD_SIZE),
 112         .period_bytes_min =     PLAYBACK_MIN_PERIOD_SIZE,
 113         .period_bytes_max =     PLAYBACK_MAX_PERIOD_SIZE,
 114         .periods_min =          PLAYBACK_MIN_NUM_PERIODS,
 115         .periods_max =          PLAYBACK_MAX_NUM_PERIODS,
 116         .fifo_size =            0,
 117 };
 118 
 119 #define Q6ASM_FEDAI_DRIVER(num) { \
 120                 .playback = {                                           \
 121                         .stream_name = "MultiMedia"#num" Playback",     \
 122                         .rates = (SNDRV_PCM_RATE_8000_192000|           \
 123                                         SNDRV_PCM_RATE_KNOT),           \
 124                         .formats = (SNDRV_PCM_FMTBIT_S16_LE |           \
 125                                         SNDRV_PCM_FMTBIT_S24_LE),       \
 126                         .channels_min = 1,                              \
 127                         .channels_max = 8,                              \
 128                         .rate_min =     8000,                           \
 129                         .rate_max =     192000,                         \
 130                 },                                                      \
 131                 .capture = {                                            \
 132                         .stream_name = "MultiMedia"#num" Capture",      \
 133                         .rates = (SNDRV_PCM_RATE_8000_48000|            \
 134                                         SNDRV_PCM_RATE_KNOT),           \
 135                         .formats = (SNDRV_PCM_FMTBIT_S16_LE |           \
 136                                     SNDRV_PCM_FMTBIT_S24_LE),           \
 137                         .channels_min = 1,                              \
 138                         .channels_max = 4,                              \
 139                         .rate_min =     8000,                           \
 140                         .rate_max =     48000,                          \
 141                 },                                                      \
 142                 .name = "MultiMedia"#num,                               \
 143                 .id = MSM_FRONTEND_DAI_MULTIMEDIA##num,                 \
 144         }
 145 
 146 /* Conventional and unconventional sample rate supported */
 147 static unsigned int supported_sample_rates[] = {
 148         8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
 149         88200, 96000, 176400, 192000
 150 };
 151 
 152 static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
 153         .count = ARRAY_SIZE(supported_sample_rates),
 154         .list = supported_sample_rates,
 155         .mask = 0,
 156 };
 157 
 158 static const struct snd_compr_codec_caps q6asm_compr_caps = {
 159         .num_descriptors = 1,
 160         .descriptor[0].max_ch = 2,
 161         .descriptor[0].sample_rates = { 8000, 11025, 12000, 16000, 22050,
 162                                         24000, 32000, 44100, 48000, 88200,
 163                                         96000, 176400, 192000 },
 164         .descriptor[0].num_sample_rates = 13,
 165         .descriptor[0].bit_rate[0] = 320,
 166         .descriptor[0].bit_rate[1] = 128,
 167         .descriptor[0].num_bitrates = 2,
 168         .descriptor[0].profiles = 0,
 169         .descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO,
 170         .descriptor[0].formats = 0,
 171 };
 172 
 173 static void event_handler(uint32_t opcode, uint32_t token,
 174                           uint32_t *payload, void *priv)
 175 {
 176         struct q6asm_dai_rtd *prtd = priv;
 177         struct snd_pcm_substream *substream = prtd->substream;
 178 
 179         switch (opcode) {
 180         case ASM_CLIENT_EVENT_CMD_RUN_DONE:
 181                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 182                         q6asm_write_async(prtd->audio_client,
 183                                    prtd->pcm_count, 0, 0, NO_TIMESTAMP);
 184                 break;
 185         case ASM_CLIENT_EVENT_CMD_EOS_DONE:
 186                 prtd->state = Q6ASM_STREAM_STOPPED;
 187                 break;
 188         case ASM_CLIENT_EVENT_DATA_WRITE_DONE: {
 189                 prtd->pcm_irq_pos += prtd->pcm_count;
 190                 snd_pcm_period_elapsed(substream);
 191                 if (prtd->state == Q6ASM_STREAM_RUNNING)
 192                         q6asm_write_async(prtd->audio_client,
 193                                            prtd->pcm_count, 0, 0, NO_TIMESTAMP);
 194 
 195                 break;
 196                 }
 197         case ASM_CLIENT_EVENT_DATA_READ_DONE:
 198                 prtd->pcm_irq_pos += prtd->pcm_count;
 199                 snd_pcm_period_elapsed(substream);
 200                 if (prtd->state == Q6ASM_STREAM_RUNNING)
 201                         q6asm_read(prtd->audio_client);
 202 
 203                 break;
 204         default:
 205                 break;
 206         }
 207 }
 208 
 209 static int q6asm_dai_prepare(struct snd_pcm_substream *substream)
 210 {
 211         struct snd_pcm_runtime *runtime = substream->runtime;
 212         struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 213         struct q6asm_dai_rtd *prtd = runtime->private_data;
 214         struct snd_soc_component *c = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
 215         struct q6asm_dai_data *pdata;
 216         int ret, i;
 217 
 218         pdata = snd_soc_component_get_drvdata(c);
 219         if (!pdata)
 220                 return -EINVAL;
 221 
 222         if (!prtd || !prtd->audio_client) {
 223                 pr_err("%s: private data null or audio client freed\n",
 224                         __func__);
 225                 return -EINVAL;
 226         }
 227 
 228         prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
 229         prtd->pcm_irq_pos = 0;
 230         /* rate and channels are sent to audio driver */
 231         if (prtd->state) {
 232                 /* clear the previous setup if any  */
 233                 q6asm_cmd(prtd->audio_client, CMD_CLOSE);
 234                 q6asm_unmap_memory_regions(substream->stream,
 235                                            prtd->audio_client);
 236                 q6routing_stream_close(soc_prtd->dai_link->id,
 237                                          substream->stream);
 238         }
 239 
 240         ret = q6asm_map_memory_regions(substream->stream, prtd->audio_client,
 241                                        prtd->phys,
 242                                        (prtd->pcm_size / prtd->periods),
 243                                        prtd->periods);
 244 
 245         if (ret < 0) {
 246                 pr_err("Audio Start: Buffer Allocation failed rc = %d\n",
 247                                                         ret);
 248                 return -ENOMEM;
 249         }
 250 
 251         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 252                 ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM,
 253                                        prtd->bits_per_sample);
 254         } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
 255                 ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM,
 256                                        prtd->bits_per_sample);
 257         }
 258 
 259         if (ret < 0) {
 260                 pr_err("%s: q6asm_open_write failed\n", __func__);
 261                 q6asm_audio_client_free(prtd->audio_client);
 262                 prtd->audio_client = NULL;
 263                 return -ENOMEM;
 264         }
 265 
 266         prtd->session_id = q6asm_get_session_id(prtd->audio_client);
 267         ret = q6routing_stream_open(soc_prtd->dai_link->id, LEGACY_PCM_MODE,
 268                               prtd->session_id, substream->stream);
 269         if (ret) {
 270                 pr_err("%s: stream reg failed ret:%d\n", __func__, ret);
 271                 return ret;
 272         }
 273 
 274         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 275                 ret = q6asm_media_format_block_multi_ch_pcm(
 276                                 prtd->audio_client, runtime->rate,
 277                                 runtime->channels, NULL,
 278                                 prtd->bits_per_sample);
 279         } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
 280                 ret = q6asm_enc_cfg_blk_pcm_format_support(prtd->audio_client,
 281                                         runtime->rate, runtime->channels,
 282                                         prtd->bits_per_sample);
 283 
 284                 /* Queue the buffers */
 285                 for (i = 0; i < runtime->periods; i++)
 286                         q6asm_read(prtd->audio_client);
 287 
 288         }
 289         if (ret < 0)
 290                 pr_info("%s: CMD Format block failed\n", __func__);
 291 
 292         prtd->state = Q6ASM_STREAM_RUNNING;
 293 
 294         return 0;
 295 }
 296 
 297 static int q6asm_dai_trigger(struct snd_pcm_substream *substream, int cmd)
 298 {
 299         int ret = 0;
 300         struct snd_pcm_runtime *runtime = substream->runtime;
 301         struct q6asm_dai_rtd *prtd = runtime->private_data;
 302 
 303         switch (cmd) {
 304         case SNDRV_PCM_TRIGGER_START:
 305         case SNDRV_PCM_TRIGGER_RESUME:
 306         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 307                 ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
 308                 break;
 309         case SNDRV_PCM_TRIGGER_STOP:
 310                 prtd->state = Q6ASM_STREAM_STOPPED;
 311                 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
 312                 break;
 313         case SNDRV_PCM_TRIGGER_SUSPEND:
 314         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 315                 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
 316                 break;
 317         default:
 318                 ret = -EINVAL;
 319                 break;
 320         }
 321 
 322         return ret;
 323 }
 324 
 325 static int q6asm_dai_open(struct snd_pcm_substream *substream)
 326 {
 327         struct snd_pcm_runtime *runtime = substream->runtime;
 328         struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 329         struct snd_soc_dai *cpu_dai = soc_prtd->cpu_dai;
 330         struct snd_soc_component *c = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
 331         struct q6asm_dai_rtd *prtd;
 332         struct q6asm_dai_data *pdata;
 333         struct device *dev = c->dev;
 334         int ret = 0;
 335         int stream_id;
 336 
 337         stream_id = cpu_dai->driver->id;
 338 
 339         pdata = snd_soc_component_get_drvdata(c);
 340         if (!pdata) {
 341                 pr_err("Drv data not found ..\n");
 342                 return -EINVAL;
 343         }
 344 
 345         prtd = kzalloc(sizeof(struct q6asm_dai_rtd), GFP_KERNEL);
 346         if (prtd == NULL)
 347                 return -ENOMEM;
 348 
 349         prtd->substream = substream;
 350         prtd->audio_client = q6asm_audio_client_alloc(dev,
 351                                 (q6asm_cb)event_handler, prtd, stream_id,
 352                                 LEGACY_PCM_MODE);
 353         if (IS_ERR(prtd->audio_client)) {
 354                 pr_info("%s: Could not allocate memory\n", __func__);
 355                 ret = PTR_ERR(prtd->audio_client);
 356                 kfree(prtd);
 357                 return ret;
 358         }
 359 
 360         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 361                 runtime->hw = q6asm_dai_hardware_playback;
 362         else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
 363                 runtime->hw = q6asm_dai_hardware_capture;
 364 
 365         ret = snd_pcm_hw_constraint_list(runtime, 0,
 366                                 SNDRV_PCM_HW_PARAM_RATE,
 367                                 &constraints_sample_rates);
 368         if (ret < 0)
 369                 pr_info("snd_pcm_hw_constraint_list failed\n");
 370         /* Ensure that buffer size is a multiple of period size */
 371         ret = snd_pcm_hw_constraint_integer(runtime,
 372                                             SNDRV_PCM_HW_PARAM_PERIODS);
 373         if (ret < 0)
 374                 pr_info("snd_pcm_hw_constraint_integer failed\n");
 375 
 376         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 377                 ret = snd_pcm_hw_constraint_minmax(runtime,
 378                         SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
 379                         PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE,
 380                         PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE);
 381                 if (ret < 0) {
 382                         pr_err("constraint for buffer bytes min max ret = %d\n",
 383                                                                         ret);
 384                 }
 385         }
 386 
 387         ret = snd_pcm_hw_constraint_step(runtime, 0,
 388                 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
 389         if (ret < 0) {
 390                 pr_err("constraint for period bytes step ret = %d\n",
 391                                                                 ret);
 392         }
 393         ret = snd_pcm_hw_constraint_step(runtime, 0,
 394                 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
 395         if (ret < 0) {
 396                 pr_err("constraint for buffer bytes step ret = %d\n",
 397                                                                 ret);
 398         }
 399 
 400         runtime->private_data = prtd;
 401 
 402         snd_soc_set_runtime_hwparams(substream, &q6asm_dai_hardware_playback);
 403 
 404         runtime->dma_bytes = q6asm_dai_hardware_playback.buffer_bytes_max;
 405 
 406 
 407         if (pdata->sid < 0)
 408                 prtd->phys = substream->dma_buffer.addr;
 409         else
 410                 prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32);
 411 
 412         snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 413 
 414         return 0;
 415 }
 416 
 417 static int q6asm_dai_close(struct snd_pcm_substream *substream)
 418 {
 419         struct snd_pcm_runtime *runtime = substream->runtime;
 420         struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 421         struct q6asm_dai_rtd *prtd = runtime->private_data;
 422 
 423         if (prtd->audio_client) {
 424                 if (prtd->state)
 425                         q6asm_cmd(prtd->audio_client, CMD_CLOSE);
 426 
 427                 q6asm_unmap_memory_regions(substream->stream,
 428                                            prtd->audio_client);
 429                 q6asm_audio_client_free(prtd->audio_client);
 430                 prtd->audio_client = NULL;
 431         }
 432         q6routing_stream_close(soc_prtd->dai_link->id,
 433                                                 substream->stream);
 434         kfree(prtd);
 435         return 0;
 436 }
 437 
 438 static snd_pcm_uframes_t q6asm_dai_pointer(struct snd_pcm_substream *substream)
 439 {
 440 
 441         struct snd_pcm_runtime *runtime = substream->runtime;
 442         struct q6asm_dai_rtd *prtd = runtime->private_data;
 443 
 444         if (prtd->pcm_irq_pos >= prtd->pcm_size)
 445                 prtd->pcm_irq_pos = 0;
 446 
 447         return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
 448 }
 449 
 450 static int q6asm_dai_mmap(struct snd_pcm_substream *substream,
 451                                 struct vm_area_struct *vma)
 452 {
 453 
 454         struct snd_pcm_runtime *runtime = substream->runtime;
 455         struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 456         struct snd_soc_component *c = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
 457         struct device *dev = c->dev;
 458 
 459         return dma_mmap_coherent(dev, vma,
 460                         runtime->dma_area, runtime->dma_addr,
 461                         runtime->dma_bytes);
 462 }
 463 
 464 static int q6asm_dai_hw_params(struct snd_pcm_substream *substream,
 465                                 struct snd_pcm_hw_params *params)
 466 {
 467         struct snd_pcm_runtime *runtime = substream->runtime;
 468         struct q6asm_dai_rtd *prtd = runtime->private_data;
 469 
 470         prtd->pcm_size = params_buffer_bytes(params);
 471         prtd->periods = params_periods(params);
 472 
 473         switch (params_format(params)) {
 474         case SNDRV_PCM_FORMAT_S16_LE:
 475                 prtd->bits_per_sample = 16;
 476                 break;
 477         case SNDRV_PCM_FORMAT_S24_LE:
 478                 prtd->bits_per_sample = 24;
 479                 break;
 480         }
 481 
 482         return 0;
 483 }
 484 
 485 static struct snd_pcm_ops q6asm_dai_ops = {
 486         .open           = q6asm_dai_open,
 487         .hw_params      = q6asm_dai_hw_params,
 488         .close          = q6asm_dai_close,
 489         .ioctl          = snd_pcm_lib_ioctl,
 490         .prepare        = q6asm_dai_prepare,
 491         .trigger        = q6asm_dai_trigger,
 492         .pointer        = q6asm_dai_pointer,
 493         .mmap           = q6asm_dai_mmap,
 494 };
 495 
 496 static void compress_event_handler(uint32_t opcode, uint32_t token,
 497                                    uint32_t *payload, void *priv)
 498 {
 499         struct q6asm_dai_rtd *prtd = priv;
 500         struct snd_compr_stream *substream = prtd->cstream;
 501         unsigned long flags;
 502         uint64_t avail;
 503 
 504         switch (opcode) {
 505         case ASM_CLIENT_EVENT_CMD_RUN_DONE:
 506                 spin_lock_irqsave(&prtd->lock, flags);
 507                 if (!prtd->bytes_sent) {
 508                         q6asm_write_async(prtd->audio_client, prtd->pcm_count,
 509                                           0, 0, NO_TIMESTAMP);
 510                         prtd->bytes_sent += prtd->pcm_count;
 511                 }
 512 
 513                 spin_unlock_irqrestore(&prtd->lock, flags);
 514                 break;
 515 
 516         case ASM_CLIENT_EVENT_CMD_EOS_DONE:
 517                 prtd->state = Q6ASM_STREAM_STOPPED;
 518                 break;
 519 
 520         case ASM_CLIENT_EVENT_DATA_WRITE_DONE:
 521                 spin_lock_irqsave(&prtd->lock, flags);
 522 
 523                 prtd->copied_total += prtd->pcm_count;
 524                 snd_compr_fragment_elapsed(substream);
 525 
 526                 if (prtd->state != Q6ASM_STREAM_RUNNING) {
 527                         spin_unlock_irqrestore(&prtd->lock, flags);
 528                         break;
 529                 }
 530 
 531                 avail = prtd->bytes_received - prtd->bytes_sent;
 532 
 533                 if (avail >= prtd->pcm_count) {
 534                         q6asm_write_async(prtd->audio_client,
 535                                            prtd->pcm_count, 0, 0, NO_TIMESTAMP);
 536                         prtd->bytes_sent += prtd->pcm_count;
 537                 }
 538 
 539                 spin_unlock_irqrestore(&prtd->lock, flags);
 540                 break;
 541 
 542         default:
 543                 break;
 544         }
 545 }
 546 
 547 static int q6asm_dai_compr_open(struct snd_compr_stream *stream)
 548 {
 549         struct snd_soc_pcm_runtime *rtd = stream->private_data;
 550         struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
 551         struct snd_compr_runtime *runtime = stream->runtime;
 552         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 553         struct q6asm_dai_data *pdata;
 554         struct device *dev = c->dev;
 555         struct q6asm_dai_rtd *prtd;
 556         int stream_id, size, ret;
 557 
 558         stream_id = cpu_dai->driver->id;
 559         pdata = snd_soc_component_get_drvdata(c);
 560         if (!pdata) {
 561                 dev_err(dev, "Drv data not found ..\n");
 562                 return -EINVAL;
 563         }
 564 
 565         prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
 566         if (!prtd)
 567                 return -ENOMEM;
 568 
 569         prtd->cstream = stream;
 570         prtd->audio_client = q6asm_audio_client_alloc(dev,
 571                                         (q6asm_cb)compress_event_handler,
 572                                         prtd, stream_id, LEGACY_PCM_MODE);
 573         if (IS_ERR(prtd->audio_client)) {
 574                 dev_err(dev, "Could not allocate memory\n");
 575                 ret = PTR_ERR(prtd->audio_client);
 576                 goto free_prtd;
 577         }
 578 
 579         size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE *
 580                         COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
 581         ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
 582                                   &prtd->dma_buffer);
 583         if (ret) {
 584                 dev_err(dev, "Cannot allocate buffer(s)\n");
 585                 goto free_client;
 586         }
 587 
 588         if (pdata->sid < 0)
 589                 prtd->phys = prtd->dma_buffer.addr;
 590         else
 591                 prtd->phys = prtd->dma_buffer.addr | (pdata->sid << 32);
 592 
 593         snd_compr_set_runtime_buffer(stream, &prtd->dma_buffer);
 594         spin_lock_init(&prtd->lock);
 595         runtime->private_data = prtd;
 596 
 597         return 0;
 598 
 599 free_client:
 600         q6asm_audio_client_free(prtd->audio_client);
 601 free_prtd:
 602         kfree(prtd);
 603 
 604         return ret;
 605 }
 606 
 607 static int q6asm_dai_compr_free(struct snd_compr_stream *stream)
 608 {
 609         struct snd_compr_runtime *runtime = stream->runtime;
 610         struct q6asm_dai_rtd *prtd = runtime->private_data;
 611         struct snd_soc_pcm_runtime *rtd = stream->private_data;
 612 
 613         if (prtd->audio_client) {
 614                 if (prtd->state)
 615                         q6asm_cmd(prtd->audio_client, CMD_CLOSE);
 616 
 617                 snd_dma_free_pages(&prtd->dma_buffer);
 618                 q6asm_unmap_memory_regions(stream->direction,
 619                                            prtd->audio_client);
 620                 q6asm_audio_client_free(prtd->audio_client);
 621                 prtd->audio_client = NULL;
 622         }
 623         q6routing_stream_close(rtd->dai_link->id, stream->direction);
 624         kfree(prtd);
 625 
 626         return 0;
 627 }
 628 
 629 static int q6asm_dai_compr_set_params(struct snd_compr_stream *stream,
 630                                       struct snd_compr_params *params)
 631 {
 632         struct snd_compr_runtime *runtime = stream->runtime;
 633         struct q6asm_dai_rtd *prtd = runtime->private_data;
 634         struct snd_soc_pcm_runtime *rtd = stream->private_data;
 635         struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
 636         int dir = stream->direction;
 637         struct q6asm_dai_data *pdata;
 638         struct device *dev = c->dev;
 639         int ret;
 640 
 641         memcpy(&prtd->codec_param, params, sizeof(*params));
 642 
 643         pdata = snd_soc_component_get_drvdata(c);
 644         if (!pdata)
 645                 return -EINVAL;
 646 
 647         if (!prtd || !prtd->audio_client) {
 648                 dev_err(dev, "private data null or audio client freed\n");
 649                 return -EINVAL;
 650         }
 651 
 652         prtd->periods = runtime->fragments;
 653         prtd->pcm_count = runtime->fragment_size;
 654         prtd->pcm_size = runtime->fragments * runtime->fragment_size;
 655         prtd->bits_per_sample = 16;
 656         if (dir == SND_COMPRESS_PLAYBACK) {
 657                 ret = q6asm_open_write(prtd->audio_client, params->codec.id,
 658                                         prtd->bits_per_sample);
 659 
 660                 if (ret < 0) {
 661                         dev_err(dev, "q6asm_open_write failed\n");
 662                         q6asm_audio_client_free(prtd->audio_client);
 663                         prtd->audio_client = NULL;
 664                         return ret;
 665                 }
 666         }
 667 
 668         prtd->session_id = q6asm_get_session_id(prtd->audio_client);
 669         ret = q6routing_stream_open(rtd->dai_link->id, LEGACY_PCM_MODE,
 670                               prtd->session_id, dir);
 671         if (ret) {
 672                 dev_err(dev, "Stream reg failed ret:%d\n", ret);
 673                 return ret;
 674         }
 675 
 676         ret = q6asm_map_memory_regions(dir, prtd->audio_client, prtd->phys,
 677                                        (prtd->pcm_size / prtd->periods),
 678                                        prtd->periods);
 679 
 680         if (ret < 0) {
 681                 dev_err(dev, "Buffer Mapping failed ret:%d\n", ret);
 682                 return -ENOMEM;
 683         }
 684 
 685         prtd->state = Q6ASM_STREAM_RUNNING;
 686 
 687         return 0;
 688 }
 689 
 690 static int q6asm_dai_compr_trigger(struct snd_compr_stream *stream, int cmd)
 691 {
 692         struct snd_compr_runtime *runtime = stream->runtime;
 693         struct q6asm_dai_rtd *prtd = runtime->private_data;
 694         int ret = 0;
 695 
 696         switch (cmd) {
 697         case SNDRV_PCM_TRIGGER_START:
 698         case SNDRV_PCM_TRIGGER_RESUME:
 699         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 700                 ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
 701                 break;
 702         case SNDRV_PCM_TRIGGER_STOP:
 703                 prtd->state = Q6ASM_STREAM_STOPPED;
 704                 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
 705                 break;
 706         case SNDRV_PCM_TRIGGER_SUSPEND:
 707         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 708                 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
 709                 break;
 710         default:
 711                 ret = -EINVAL;
 712                 break;
 713         }
 714 
 715         return ret;
 716 }
 717 
 718 static int q6asm_dai_compr_pointer(struct snd_compr_stream *stream,
 719                 struct snd_compr_tstamp *tstamp)
 720 {
 721         struct snd_compr_runtime *runtime = stream->runtime;
 722         struct q6asm_dai_rtd *prtd = runtime->private_data;
 723         unsigned long flags;
 724 
 725         spin_lock_irqsave(&prtd->lock, flags);
 726 
 727         tstamp->copied_total = prtd->copied_total;
 728         tstamp->byte_offset = prtd->copied_total % prtd->pcm_size;
 729 
 730         spin_unlock_irqrestore(&prtd->lock, flags);
 731 
 732         return 0;
 733 }
 734 
 735 static int q6asm_dai_compr_ack(struct snd_compr_stream *stream,
 736                                 size_t count)
 737 {
 738         struct snd_compr_runtime *runtime = stream->runtime;
 739         struct q6asm_dai_rtd *prtd = runtime->private_data;
 740         unsigned long flags;
 741 
 742         spin_lock_irqsave(&prtd->lock, flags);
 743         prtd->bytes_received += count;
 744         spin_unlock_irqrestore(&prtd->lock, flags);
 745 
 746         return count;
 747 }
 748 
 749 static int q6asm_dai_compr_mmap(struct snd_compr_stream *stream,
 750                 struct vm_area_struct *vma)
 751 {
 752         struct snd_compr_runtime *runtime = stream->runtime;
 753         struct q6asm_dai_rtd *prtd = runtime->private_data;
 754         struct snd_soc_pcm_runtime *rtd = stream->private_data;
 755         struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
 756         struct device *dev = c->dev;
 757 
 758         return dma_mmap_coherent(dev, vma,
 759                         prtd->dma_buffer.area, prtd->dma_buffer.addr,
 760                         prtd->dma_buffer.bytes);
 761 }
 762 
 763 static int q6asm_dai_compr_get_caps(struct snd_compr_stream *stream,
 764                                     struct snd_compr_caps *caps)
 765 {
 766         caps->direction = SND_COMPRESS_PLAYBACK;
 767         caps->min_fragment_size = COMPR_PLAYBACK_MIN_FRAGMENT_SIZE;
 768         caps->max_fragment_size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE;
 769         caps->min_fragments = COMPR_PLAYBACK_MIN_NUM_FRAGMENTS;
 770         caps->max_fragments = COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
 771         caps->num_codecs = 1;
 772         caps->codecs[0] = SND_AUDIOCODEC_MP3;
 773 
 774         return 0;
 775 }
 776 
 777 static int q6asm_dai_compr_get_codec_caps(struct snd_compr_stream *stream,
 778                                           struct snd_compr_codec_caps *codec)
 779 {
 780         switch (codec->codec) {
 781         case SND_AUDIOCODEC_MP3:
 782                 *codec = q6asm_compr_caps;
 783                 break;
 784         default:
 785                 break;
 786         }
 787 
 788         return 0;
 789 }
 790 
 791 static struct snd_compr_ops q6asm_dai_compr_ops = {
 792         .open           = q6asm_dai_compr_open,
 793         .free           = q6asm_dai_compr_free,
 794         .set_params     = q6asm_dai_compr_set_params,
 795         .pointer        = q6asm_dai_compr_pointer,
 796         .trigger        = q6asm_dai_compr_trigger,
 797         .get_caps       = q6asm_dai_compr_get_caps,
 798         .get_codec_caps = q6asm_dai_compr_get_codec_caps,
 799         .mmap           = q6asm_dai_compr_mmap,
 800         .ack            = q6asm_dai_compr_ack,
 801 };
 802 
 803 static int q6asm_dai_pcm_new(struct snd_soc_pcm_runtime *rtd)
 804 {
 805         struct snd_pcm_substream *psubstream, *csubstream;
 806         struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
 807         struct snd_pcm *pcm = rtd->pcm;
 808         struct device *dev;
 809         int size, ret;
 810 
 811         dev = c->dev;
 812         size = q6asm_dai_hardware_playback.buffer_bytes_max;
 813         psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
 814         if (psubstream) {
 815                 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
 816                                           &psubstream->dma_buffer);
 817                 if (ret) {
 818                         dev_err(dev, "Cannot allocate buffer(s)\n");
 819                         return ret;
 820                 }
 821         }
 822 
 823         csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
 824         if (csubstream) {
 825                 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
 826                                           &csubstream->dma_buffer);
 827                 if (ret) {
 828                         dev_err(dev, "Cannot allocate buffer(s)\n");
 829                         if (psubstream)
 830                                 snd_dma_free_pages(&psubstream->dma_buffer);
 831                         return ret;
 832                 }
 833         }
 834 
 835         return 0;
 836 }
 837 
 838 static void q6asm_dai_pcm_free(struct snd_pcm *pcm)
 839 {
 840         struct snd_pcm_substream *substream;
 841         int i;
 842 
 843         for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) {
 844                 substream = pcm->streams[i].substream;
 845                 if (substream) {
 846                         snd_dma_free_pages(&substream->dma_buffer);
 847                         substream->dma_buffer.area = NULL;
 848                         substream->dma_buffer.addr = 0;
 849                 }
 850         }
 851 }
 852 
 853 static const struct snd_soc_component_driver q6asm_fe_dai_component = {
 854         .name           = DRV_NAME,
 855         .ops            = &q6asm_dai_ops,
 856         .pcm_new        = q6asm_dai_pcm_new,
 857         .pcm_free       = q6asm_dai_pcm_free,
 858         .compr_ops      = &q6asm_dai_compr_ops,
 859 };
 860 
 861 static struct snd_soc_dai_driver q6asm_fe_dais[] = {
 862         Q6ASM_FEDAI_DRIVER(1),
 863         Q6ASM_FEDAI_DRIVER(2),
 864         Q6ASM_FEDAI_DRIVER(3),
 865         Q6ASM_FEDAI_DRIVER(4),
 866         Q6ASM_FEDAI_DRIVER(5),
 867         Q6ASM_FEDAI_DRIVER(6),
 868         Q6ASM_FEDAI_DRIVER(7),
 869         Q6ASM_FEDAI_DRIVER(8),
 870 };
 871 
 872 static int of_q6asm_parse_dai_data(struct device *dev,
 873                                     struct q6asm_dai_data *pdata)
 874 {
 875         static struct snd_soc_dai_driver *dai_drv;
 876         struct snd_soc_pcm_stream empty_stream;
 877         struct device_node *node;
 878         int ret, id, dir;
 879 
 880         memset(&empty_stream, 0, sizeof(empty_stream));
 881 
 882         for_each_child_of_node(dev->of_node, node) {
 883                 ret = of_property_read_u32(node, "reg", &id);
 884                 if (ret || id >= MAX_SESSIONS || id < 0) {
 885                         dev_err(dev, "valid dai id not found:%d\n", ret);
 886                         continue;
 887                 }
 888 
 889                 dai_drv = &q6asm_fe_dais[id];
 890 
 891                 ret = of_property_read_u32(node, "direction", &dir);
 892                 if (ret)
 893                         continue;
 894 
 895                 if (dir == Q6ASM_DAI_RX)
 896                         dai_drv->capture = empty_stream;
 897                 else if (dir == Q6ASM_DAI_TX)
 898                         dai_drv->playback = empty_stream;
 899 
 900                 if (of_property_read_bool(node, "is-compress-dai"))
 901                         dai_drv->compress_new = snd_soc_new_compress;
 902         }
 903 
 904         return 0;
 905 }
 906 
 907 static int q6asm_dai_probe(struct platform_device *pdev)
 908 {
 909         struct device *dev = &pdev->dev;
 910         struct device_node *node = dev->of_node;
 911         struct of_phandle_args args;
 912         struct q6asm_dai_data *pdata;
 913         int rc;
 914 
 915         pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 916         if (!pdata)
 917                 return -ENOMEM;
 918 
 919         rc = of_parse_phandle_with_fixed_args(node, "iommus", 1, 0, &args);
 920         if (rc < 0)
 921                 pdata->sid = -1;
 922         else
 923                 pdata->sid = args.args[0] & SID_MASK_DEFAULT;
 924 
 925         dev_set_drvdata(dev, pdata);
 926 
 927         of_q6asm_parse_dai_data(dev, pdata);
 928 
 929         return devm_snd_soc_register_component(dev, &q6asm_fe_dai_component,
 930                                         q6asm_fe_dais,
 931                                         ARRAY_SIZE(q6asm_fe_dais));
 932 }
 933 
 934 static const struct of_device_id q6asm_dai_device_id[] = {
 935         { .compatible = "qcom,q6asm-dais" },
 936         {},
 937 };
 938 MODULE_DEVICE_TABLE(of, q6asm_dai_device_id);
 939 
 940 static struct platform_driver q6asm_dai_platform_driver = {
 941         .driver = {
 942                 .name = "q6asm-dai",
 943                 .of_match_table = of_match_ptr(q6asm_dai_device_id),
 944         },
 945         .probe = q6asm_dai_probe,
 946 };
 947 module_platform_driver(q6asm_dai_platform_driver);
 948 
 949 MODULE_DESCRIPTION("Q6ASM dai driver");
 950 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */