linux/sound/soc/uniphier/aio-compress.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// Socionext UniPhier AIO Compress Audio driver.
   4//
   5// Copyright (c) 2017-2018 Socionext Inc.
   6
   7#include <linux/bitfield.h>
   8#include <linux/circ_buf.h>
   9#include <linux/dma-mapping.h>
  10#include <linux/errno.h>
  11#include <linux/kernel.h>
  12#include <linux/module.h>
  13#include <sound/core.h>
  14#include <sound/pcm.h>
  15#include <sound/soc.h>
  16
  17#include "aio.h"
  18
  19static int uniphier_aio_compr_prepare(struct snd_soc_component *component,
  20                                      struct snd_compr_stream *cstream);
  21static int uniphier_aio_compr_hw_free(struct snd_soc_component *component,
  22                                      struct snd_compr_stream *cstream);
  23
  24static int uniphier_aio_comprdma_new(struct snd_soc_pcm_runtime *rtd)
  25{
  26        struct snd_compr *compr = rtd->compr;
  27        struct device *dev = compr->card->dev;
  28        struct uniphier_aio *aio = uniphier_priv(snd_soc_rtd_to_cpu(rtd, 0));
  29        struct uniphier_aio_sub *sub = &aio->sub[compr->direction];
  30        size_t size = AUD_RING_SIZE;
  31        int dma_dir = DMA_FROM_DEVICE, ret;
  32
  33        ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(33));
  34        if (ret)
  35                return ret;
  36
  37        sub->compr_area = kzalloc(size, GFP_KERNEL);
  38        if (!sub->compr_area)
  39                return -ENOMEM;
  40
  41        if (sub->swm->dir == PORT_DIR_OUTPUT)
  42                dma_dir = DMA_TO_DEVICE;
  43
  44        sub->compr_addr = dma_map_single(dev, sub->compr_area, size, dma_dir);
  45        if (dma_mapping_error(dev, sub->compr_addr)) {
  46                kfree(sub->compr_area);
  47                sub->compr_area = NULL;
  48
  49                return -ENOMEM;
  50        }
  51
  52        sub->compr_bytes = size;
  53
  54        return 0;
  55}
  56
  57static int uniphier_aio_comprdma_free(struct snd_soc_pcm_runtime *rtd)
  58{
  59        struct snd_compr *compr = rtd->compr;
  60        struct device *dev = compr->card->dev;
  61        struct uniphier_aio *aio = uniphier_priv(snd_soc_rtd_to_cpu(rtd, 0));
  62        struct uniphier_aio_sub *sub = &aio->sub[compr->direction];
  63        int dma_dir = DMA_FROM_DEVICE;
  64
  65        if (sub->swm->dir == PORT_DIR_OUTPUT)
  66                dma_dir = DMA_TO_DEVICE;
  67
  68        dma_unmap_single(dev, sub->compr_addr, sub->compr_bytes, dma_dir);
  69        kfree(sub->compr_area);
  70        sub->compr_area = NULL;
  71
  72        return 0;
  73}
  74
  75static int uniphier_aio_compr_open(struct snd_soc_component *component,
  76                                   struct snd_compr_stream *cstream)
  77{
  78        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  79        struct uniphier_aio *aio = uniphier_priv(snd_soc_rtd_to_cpu(rtd, 0));
  80        struct uniphier_aio_sub *sub = &aio->sub[cstream->direction];
  81        int ret;
  82
  83        if (sub->cstream)
  84                return -EBUSY;
  85
  86        sub->cstream = cstream;
  87        sub->pass_through = 1;
  88        sub->use_mmap = false;
  89
  90        ret = uniphier_aio_comprdma_new(rtd);
  91        if (ret)
  92                return ret;
  93
  94        ret = aio_init(sub);
  95        if (ret)
  96                return ret;
  97
  98        return 0;
  99}
 100
 101static int uniphier_aio_compr_free(struct snd_soc_component *component,
 102                                   struct snd_compr_stream *cstream)
 103{
 104        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 105        struct uniphier_aio *aio = uniphier_priv(snd_soc_rtd_to_cpu(rtd, 0));
 106        struct uniphier_aio_sub *sub = &aio->sub[cstream->direction];
 107        int ret;
 108
 109        ret = uniphier_aio_compr_hw_free(component, cstream);
 110        if (ret)
 111                return ret;
 112        ret = uniphier_aio_comprdma_free(rtd);
 113        if (ret)
 114                return ret;
 115
 116        sub->cstream = NULL;
 117
 118        return 0;
 119}
 120
 121static int uniphier_aio_compr_get_params(struct snd_soc_component *component,
 122                                         struct snd_compr_stream *cstream,
 123                                         struct snd_codec *params)
 124{
 125        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 126        struct uniphier_aio *aio = uniphier_priv(snd_soc_rtd_to_cpu(rtd, 0));
 127        struct uniphier_aio_sub *sub = &aio->sub[cstream->direction];
 128
 129        *params = sub->cparams.codec;
 130
 131        return 0;
 132}
 133
 134static int uniphier_aio_compr_set_params(struct snd_soc_component *component,
 135                                         struct snd_compr_stream *cstream,
 136                                         struct snd_compr_params *params)
 137{
 138        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 139        struct uniphier_aio *aio = uniphier_priv(snd_soc_rtd_to_cpu(rtd, 0));
 140        struct uniphier_aio_sub *sub = &aio->sub[cstream->direction];
 141        struct device *dev = &aio->chip->pdev->dev;
 142
 143        if (params->codec.id != SND_AUDIOCODEC_IEC61937) {
 144                dev_err(dev, "Codec ID is not supported(%d)\n",
 145                        params->codec.id);
 146                return -EINVAL;
 147        }
 148        if (params->codec.profile != SND_AUDIOPROFILE_IEC61937_SPDIF) {
 149                dev_err(dev, "Codec profile is not supported(%d)\n",
 150                        params->codec.profile);
 151                return -EINVAL;
 152        }
 153
 154        /* IEC frame type will be changed after received valid data */
 155        sub->iec_pc = IEC61937_PC_AAC;
 156
 157        sub->cparams = *params;
 158        sub->setting = 1;
 159
 160        aio_port_reset(sub);
 161        aio_src_reset(sub);
 162
 163        return uniphier_aio_compr_prepare(component, cstream);
 164}
 165
 166static int uniphier_aio_compr_hw_free(struct snd_soc_component *component,
 167                                      struct snd_compr_stream *cstream)
 168{
 169        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 170        struct uniphier_aio *aio = uniphier_priv(snd_soc_rtd_to_cpu(rtd, 0));
 171        struct uniphier_aio_sub *sub = &aio->sub[cstream->direction];
 172
 173        sub->setting = 0;
 174
 175        return 0;
 176}
 177
 178static int uniphier_aio_compr_prepare(struct snd_soc_component *component,
 179                                      struct snd_compr_stream *cstream)
 180{
 181        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 182        struct snd_compr_runtime *runtime = cstream->runtime;
 183        struct uniphier_aio *aio = uniphier_priv(snd_soc_rtd_to_cpu(rtd, 0));
 184        struct uniphier_aio_sub *sub = &aio->sub[cstream->direction];
 185        int bytes = runtime->fragment_size;
 186        unsigned long flags;
 187        int ret;
 188
 189        ret = aiodma_ch_set_param(sub);
 190        if (ret)
 191                return ret;
 192
 193        spin_lock_irqsave(&sub->lock, flags);
 194        ret = aiodma_rb_set_buffer(sub, sub->compr_addr,
 195                                   sub->compr_addr + sub->compr_bytes,
 196                                   bytes);
 197        spin_unlock_irqrestore(&sub->lock, flags);
 198        if (ret)
 199                return ret;
 200
 201        ret = aio_port_set_param(sub, sub->pass_through, &sub->params);
 202        if (ret)
 203                return ret;
 204        ret = aio_oport_set_stream_type(sub, sub->iec_pc);
 205        if (ret)
 206                return ret;
 207        aio_port_set_enable(sub, 1);
 208
 209        ret = aio_if_set_param(sub, sub->pass_through);
 210        if (ret)
 211                return ret;
 212
 213        return 0;
 214}
 215
 216static int uniphier_aio_compr_trigger(struct snd_soc_component *component,
 217                                      struct snd_compr_stream *cstream,
 218                                      int cmd)
 219{
 220        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 221        struct snd_compr_runtime *runtime = cstream->runtime;
 222        struct uniphier_aio *aio = uniphier_priv(snd_soc_rtd_to_cpu(rtd, 0));
 223        struct uniphier_aio_sub *sub = &aio->sub[cstream->direction];
 224        struct device *dev = &aio->chip->pdev->dev;
 225        int bytes = runtime->fragment_size, ret = 0;
 226        unsigned long flags;
 227
 228        spin_lock_irqsave(&sub->lock, flags);
 229        switch (cmd) {
 230        case SNDRV_PCM_TRIGGER_START:
 231                aiodma_rb_sync(sub, sub->compr_addr, sub->compr_bytes, bytes);
 232                aiodma_ch_set_enable(sub, 1);
 233                sub->running = 1;
 234
 235                break;
 236        case SNDRV_PCM_TRIGGER_STOP:
 237                sub->running = 0;
 238                aiodma_ch_set_enable(sub, 0);
 239
 240                break;
 241        default:
 242                dev_warn(dev, "Unknown trigger(%d)\n", cmd);
 243                ret = -EINVAL;
 244        }
 245        spin_unlock_irqrestore(&sub->lock, flags);
 246
 247        return ret;
 248}
 249
 250static int uniphier_aio_compr_pointer(struct snd_soc_component *component,
 251                                      struct snd_compr_stream *cstream,
 252                                      struct snd_compr_tstamp *tstamp)
 253{
 254        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 255        struct snd_compr_runtime *runtime = cstream->runtime;
 256        struct uniphier_aio *aio = uniphier_priv(snd_soc_rtd_to_cpu(rtd, 0));
 257        struct uniphier_aio_sub *sub = &aio->sub[cstream->direction];
 258        int bytes = runtime->fragment_size;
 259        unsigned long flags;
 260        u32 pos;
 261
 262        spin_lock_irqsave(&sub->lock, flags);
 263
 264        aiodma_rb_sync(sub, sub->compr_addr, sub->compr_bytes, bytes);
 265
 266        if (sub->swm->dir == PORT_DIR_OUTPUT) {
 267                pos = sub->rd_offs;
 268                /* Size of AIO output format is double of IEC61937 */
 269                tstamp->copied_total = sub->rd_total / 2;
 270        } else {
 271                pos = sub->wr_offs;
 272                tstamp->copied_total = sub->rd_total;
 273        }
 274        tstamp->byte_offset = pos;
 275
 276        spin_unlock_irqrestore(&sub->lock, flags);
 277
 278        return 0;
 279}
 280
 281static int aio_compr_send_to_hw(struct uniphier_aio_sub *sub,
 282                                char __user *buf, size_t dstsize)
 283{
 284        u32 __user *srcbuf = (u32 __user *)buf;
 285        u32 *dstbuf = (u32 *)(sub->compr_area + sub->wr_offs);
 286        int src = 0, dst = 0, ret;
 287        u32 frm, frm_a, frm_b;
 288
 289        while (dstsize > 0) {
 290                ret = get_user(frm, srcbuf + src);
 291                if (ret)
 292                        return ret;
 293                src++;
 294
 295                frm_a = frm & 0xffff;
 296                frm_b = (frm >> 16) & 0xffff;
 297
 298                if (frm == IEC61937_HEADER_SIGN) {
 299                        frm_a |= 0x01000000;
 300
 301                        /* Next data is Pc and Pd */
 302                        sub->iec_header = true;
 303                } else {
 304                        u16 pc = be16_to_cpu((__be16)frm_a);
 305
 306                        if (sub->iec_header && sub->iec_pc != pc) {
 307                                /* Force overwrite IEC frame type */
 308                                sub->iec_pc = pc;
 309                                ret = aio_oport_set_stream_type(sub, pc);
 310                                if (ret)
 311                                        return ret;
 312                        }
 313                        sub->iec_header = false;
 314                }
 315                dstbuf[dst++] = frm_a;
 316                dstbuf[dst++] = frm_b;
 317
 318                dstsize -= sizeof(u32) * 2;
 319        }
 320
 321        return 0;
 322}
 323
 324static int uniphier_aio_compr_copy(struct snd_soc_component *component,
 325                                   struct snd_compr_stream *cstream,
 326                                   char __user *buf, size_t count)
 327{
 328        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 329        struct snd_compr_runtime *runtime = cstream->runtime;
 330        struct device *carddev = rtd->compr->card->dev;
 331        struct uniphier_aio *aio = uniphier_priv(snd_soc_rtd_to_cpu(rtd, 0));
 332        struct uniphier_aio_sub *sub = &aio->sub[cstream->direction];
 333        size_t cnt = min_t(size_t, count, aio_rb_space_to_end(sub) / 2);
 334        int bytes = runtime->fragment_size;
 335        unsigned long flags;
 336        size_t s;
 337        int ret;
 338
 339        if (cnt < sizeof(u32))
 340                return 0;
 341
 342        if (sub->swm->dir == PORT_DIR_OUTPUT) {
 343                dma_addr_t dmapos = sub->compr_addr + sub->wr_offs;
 344
 345                /* Size of AIO output format is double of IEC61937 */
 346                s = cnt * 2;
 347
 348                dma_sync_single_for_cpu(carddev, dmapos, s, DMA_TO_DEVICE);
 349                ret = aio_compr_send_to_hw(sub, buf, s);
 350                dma_sync_single_for_device(carddev, dmapos, s, DMA_TO_DEVICE);
 351        } else {
 352                dma_addr_t dmapos = sub->compr_addr + sub->rd_offs;
 353
 354                s = cnt;
 355
 356                dma_sync_single_for_cpu(carddev, dmapos, s, DMA_FROM_DEVICE);
 357                ret = copy_to_user(buf, sub->compr_area + sub->rd_offs, s);
 358                dma_sync_single_for_device(carddev, dmapos, s, DMA_FROM_DEVICE);
 359        }
 360        if (ret)
 361                return -EFAULT;
 362
 363        spin_lock_irqsave(&sub->lock, flags);
 364
 365        sub->threshold = 2 * bytes;
 366        aiodma_rb_set_threshold(sub, sub->compr_bytes, 2 * bytes);
 367
 368        if (sub->swm->dir == PORT_DIR_OUTPUT) {
 369                sub->wr_offs += s;
 370                if (sub->wr_offs >= sub->compr_bytes)
 371                        sub->wr_offs -= sub->compr_bytes;
 372        } else {
 373                sub->rd_offs += s;
 374                if (sub->rd_offs >= sub->compr_bytes)
 375                        sub->rd_offs -= sub->compr_bytes;
 376        }
 377        aiodma_rb_sync(sub, sub->compr_addr, sub->compr_bytes, bytes);
 378
 379        spin_unlock_irqrestore(&sub->lock, flags);
 380
 381        return cnt;
 382}
 383
 384static int uniphier_aio_compr_get_caps(struct snd_soc_component *component,
 385                                       struct snd_compr_stream *cstream,
 386                                       struct snd_compr_caps *caps)
 387{
 388        caps->num_codecs = 1;
 389        caps->min_fragment_size = AUD_MIN_FRAGMENT_SIZE;
 390        caps->max_fragment_size = AUD_MAX_FRAGMENT_SIZE;
 391        caps->min_fragments = AUD_MIN_FRAGMENT;
 392        caps->max_fragments = AUD_MAX_FRAGMENT;
 393        caps->codecs[0] = SND_AUDIOCODEC_IEC61937;
 394
 395        return 0;
 396}
 397
 398static const struct snd_compr_codec_caps caps_iec = {
 399        .num_descriptors = 1,
 400        .descriptor[0].max_ch = 8,
 401        .descriptor[0].num_sample_rates = 0,
 402        .descriptor[0].num_bitrates = 0,
 403        .descriptor[0].profiles = SND_AUDIOPROFILE_IEC61937_SPDIF,
 404        .descriptor[0].modes = SND_AUDIOMODE_IEC_AC3 |
 405                                SND_AUDIOMODE_IEC_MPEG1 |
 406                                SND_AUDIOMODE_IEC_MP3 |
 407                                SND_AUDIOMODE_IEC_DTS,
 408        .descriptor[0].formats = 0,
 409};
 410
 411static int uniphier_aio_compr_get_codec_caps(struct snd_soc_component *component,
 412                                             struct snd_compr_stream *stream,
 413                                             struct snd_compr_codec_caps *codec)
 414{
 415        if (codec->codec == SND_AUDIOCODEC_IEC61937)
 416                *codec = caps_iec;
 417        else
 418                return -EINVAL;
 419
 420        return 0;
 421}
 422
 423const struct snd_compress_ops uniphier_aio_compress_ops = {
 424        .open           = uniphier_aio_compr_open,
 425        .free           = uniphier_aio_compr_free,
 426        .get_params     = uniphier_aio_compr_get_params,
 427        .set_params     = uniphier_aio_compr_set_params,
 428        .trigger        = uniphier_aio_compr_trigger,
 429        .pointer        = uniphier_aio_compr_pointer,
 430        .copy           = uniphier_aio_compr_copy,
 431        .get_caps       = uniphier_aio_compr_get_caps,
 432        .get_codec_caps = uniphier_aio_compr_get_codec_caps,
 433};
 434