linux/drivers/media/pci/tw686x/tw686x-audio.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2015 VanguardiaSur - www.vanguardiasur.com.ar
   3 *
   4 * Based on the audio support from the tw6869 driver:
   5 * Copyright 2015 www.starterkit.ru <info@starterkit.ru>
   6 *
   7 * Based on:
   8 * Driver for Intersil|Techwell TW6869 based DVR cards
   9 * (c) 2011-12 liran <jli11@intersil.com> [Intersil|Techwell China]
  10 *
  11 * This program is free software; you can redistribute it and/or modify it
  12 * under the terms of version 2 of the GNU General Public License
  13 * as published by the Free Software Foundation.
  14 */
  15
  16#include <linux/types.h>
  17#include <linux/kernel.h>
  18#include <linux/module.h>
  19#include <linux/init.h>
  20#include <linux/kmod.h>
  21#include <linux/mutex.h>
  22#include <linux/pci.h>
  23#include <linux/delay.h>
  24
  25#include <sound/core.h>
  26#include <sound/initval.h>
  27#include <sound/pcm.h>
  28#include <sound/control.h>
  29#include "tw686x.h"
  30#include "tw686x-regs.h"
  31
  32#define AUDIO_CHANNEL_OFFSET 8
  33
  34void tw686x_audio_irq(struct tw686x_dev *dev, unsigned long requests,
  35                      unsigned int pb_status)
  36{
  37        unsigned long flags;
  38        unsigned int ch, pb;
  39
  40        for_each_set_bit(ch, &requests, max_channels(dev)) {
  41                struct tw686x_audio_channel *ac = &dev->audio_channels[ch];
  42                struct tw686x_audio_buf *done = NULL;
  43                struct tw686x_audio_buf *next = NULL;
  44                struct tw686x_dma_desc *desc;
  45
  46                pb = !!(pb_status & BIT(AUDIO_CHANNEL_OFFSET + ch));
  47
  48                spin_lock_irqsave(&ac->lock, flags);
  49
  50                /* Sanity check */
  51                if (!ac->ss || !ac->curr_bufs[0] || !ac->curr_bufs[1]) {
  52                        spin_unlock_irqrestore(&ac->lock, flags);
  53                        continue;
  54                }
  55
  56                if (!list_empty(&ac->buf_list)) {
  57                        next = list_first_entry(&ac->buf_list,
  58                                        struct tw686x_audio_buf, list);
  59                        list_move_tail(&next->list, &ac->buf_list);
  60                        done = ac->curr_bufs[!pb];
  61                        ac->curr_bufs[pb] = next;
  62                }
  63                spin_unlock_irqrestore(&ac->lock, flags);
  64
  65                if (!done || !next)
  66                        continue;
  67                /*
  68                 * Checking for a non-nil dma_desc[pb]->virt buffer is
  69                 * the same as checking for memcpy DMA mode.
  70                 */
  71                desc = &ac->dma_descs[pb];
  72                if (desc->virt) {
  73                        memcpy(done->virt, desc->virt,
  74                               dev->period_size);
  75                } else {
  76                        u32 reg = pb ? ADMA_B_ADDR[ch] : ADMA_P_ADDR[ch];
  77                        reg_write(dev, reg, next->dma);
  78                }
  79                ac->ptr = done->dma - ac->buf[0].dma;
  80                snd_pcm_period_elapsed(ac->ss);
  81        }
  82}
  83
  84static int tw686x_pcm_hw_params(struct snd_pcm_substream *ss,
  85                                struct snd_pcm_hw_params *hw_params)
  86{
  87        return snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(hw_params));
  88}
  89
  90static int tw686x_pcm_hw_free(struct snd_pcm_substream *ss)
  91{
  92        return snd_pcm_lib_free_pages(ss);
  93}
  94
  95/*
  96 * Audio parameters are global and shared among all
  97 * capture channels. The driver prevents changes to
  98 * the parameters if any audio channel is capturing.
  99 */
 100static const struct snd_pcm_hardware tw686x_capture_hw = {
 101        .info                   = (SNDRV_PCM_INFO_MMAP |
 102                                   SNDRV_PCM_INFO_INTERLEAVED |
 103                                   SNDRV_PCM_INFO_BLOCK_TRANSFER |
 104                                   SNDRV_PCM_INFO_MMAP_VALID),
 105        .formats                = SNDRV_PCM_FMTBIT_S16_LE,
 106        .rates                  = SNDRV_PCM_RATE_8000_48000,
 107        .rate_min               = 8000,
 108        .rate_max               = 48000,
 109        .channels_min           = 1,
 110        .channels_max           = 1,
 111        .buffer_bytes_max       = TW686X_AUDIO_PAGE_MAX * AUDIO_DMA_SIZE_MAX,
 112        .period_bytes_min       = AUDIO_DMA_SIZE_MIN,
 113        .period_bytes_max       = AUDIO_DMA_SIZE_MAX,
 114        .periods_min            = TW686X_AUDIO_PERIODS_MIN,
 115        .periods_max            = TW686X_AUDIO_PERIODS_MAX,
 116};
 117
 118static int tw686x_pcm_open(struct snd_pcm_substream *ss)
 119{
 120        struct tw686x_dev *dev = snd_pcm_substream_chip(ss);
 121        struct tw686x_audio_channel *ac = &dev->audio_channels[ss->number];
 122        struct snd_pcm_runtime *rt = ss->runtime;
 123        int err;
 124
 125        ac->ss = ss;
 126        rt->hw = tw686x_capture_hw;
 127
 128        err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS);
 129        if (err < 0)
 130                return err;
 131
 132        return 0;
 133}
 134
 135static int tw686x_pcm_close(struct snd_pcm_substream *ss)
 136{
 137        struct tw686x_dev *dev = snd_pcm_substream_chip(ss);
 138        struct tw686x_audio_channel *ac = &dev->audio_channels[ss->number];
 139
 140        ac->ss = NULL;
 141        return 0;
 142}
 143
 144static int tw686x_pcm_prepare(struct snd_pcm_substream *ss)
 145{
 146        struct tw686x_dev *dev = snd_pcm_substream_chip(ss);
 147        struct tw686x_audio_channel *ac = &dev->audio_channels[ss->number];
 148        struct snd_pcm_runtime *rt = ss->runtime;
 149        unsigned int period_size = snd_pcm_lib_period_bytes(ss);
 150        struct tw686x_audio_buf *p_buf, *b_buf;
 151        unsigned long flags;
 152        int i;
 153
 154        spin_lock_irqsave(&dev->lock, flags);
 155        /*
 156         * Given the audio parameters are global (i.e. shared across
 157         * DMA channels), we need to check new params are allowed.
 158         */
 159        if (((dev->audio_rate != rt->rate) ||
 160             (dev->period_size != period_size)) && dev->audio_enabled)
 161                goto err_audio_busy;
 162
 163        tw686x_disable_channel(dev, AUDIO_CHANNEL_OFFSET + ac->ch);
 164        spin_unlock_irqrestore(&dev->lock, flags);
 165
 166        if (dev->audio_rate != rt->rate) {
 167                u32 reg;
 168
 169                dev->audio_rate = rt->rate;
 170                reg = ((125000000 / rt->rate) << 16) +
 171                       ((125000000 % rt->rate) << 16) / rt->rate;
 172
 173                reg_write(dev, AUDIO_CONTROL2, reg);
 174        }
 175
 176        if (dev->period_size != period_size) {
 177                u32 reg;
 178
 179                dev->period_size = period_size;
 180                reg = reg_read(dev, AUDIO_CONTROL1);
 181                reg &= ~(AUDIO_DMA_SIZE_MASK << AUDIO_DMA_SIZE_SHIFT);
 182                reg |= period_size << AUDIO_DMA_SIZE_SHIFT;
 183
 184                reg_write(dev, AUDIO_CONTROL1, reg);
 185        }
 186
 187        if (rt->periods < TW686X_AUDIO_PERIODS_MIN ||
 188            rt->periods > TW686X_AUDIO_PERIODS_MAX)
 189                return -EINVAL;
 190
 191        spin_lock_irqsave(&ac->lock, flags);
 192        INIT_LIST_HEAD(&ac->buf_list);
 193
 194        for (i = 0; i < rt->periods; i++) {
 195                ac->buf[i].dma = rt->dma_addr + period_size * i;
 196                ac->buf[i].virt = rt->dma_area + period_size * i;
 197                INIT_LIST_HEAD(&ac->buf[i].list);
 198                list_add_tail(&ac->buf[i].list, &ac->buf_list);
 199        }
 200
 201        p_buf = list_first_entry(&ac->buf_list, struct tw686x_audio_buf, list);
 202        list_move_tail(&p_buf->list, &ac->buf_list);
 203
 204        b_buf = list_first_entry(&ac->buf_list, struct tw686x_audio_buf, list);
 205        list_move_tail(&b_buf->list, &ac->buf_list);
 206
 207        ac->curr_bufs[0] = p_buf;
 208        ac->curr_bufs[1] = b_buf;
 209        ac->ptr = 0;
 210
 211        if (dev->dma_mode != TW686X_DMA_MODE_MEMCPY) {
 212                reg_write(dev, ADMA_P_ADDR[ac->ch], p_buf->dma);
 213                reg_write(dev, ADMA_B_ADDR[ac->ch], b_buf->dma);
 214        }
 215
 216        spin_unlock_irqrestore(&ac->lock, flags);
 217
 218        return 0;
 219
 220err_audio_busy:
 221        spin_unlock_irqrestore(&dev->lock, flags);
 222        return -EBUSY;
 223}
 224
 225static int tw686x_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
 226{
 227        struct tw686x_dev *dev = snd_pcm_substream_chip(ss);
 228        struct tw686x_audio_channel *ac = &dev->audio_channels[ss->number];
 229        unsigned long flags;
 230        int err = 0;
 231
 232        switch (cmd) {
 233        case SNDRV_PCM_TRIGGER_START:
 234                if (ac->curr_bufs[0] && ac->curr_bufs[1]) {
 235                        spin_lock_irqsave(&dev->lock, flags);
 236                        dev->audio_enabled = 1;
 237                        tw686x_enable_channel(dev,
 238                                AUDIO_CHANNEL_OFFSET + ac->ch);
 239                        spin_unlock_irqrestore(&dev->lock, flags);
 240
 241                        mod_timer(&dev->dma_delay_timer,
 242                                  jiffies + msecs_to_jiffies(100));
 243                } else {
 244                        err = -EIO;
 245                }
 246                break;
 247        case SNDRV_PCM_TRIGGER_STOP:
 248                spin_lock_irqsave(&dev->lock, flags);
 249                dev->audio_enabled = 0;
 250                tw686x_disable_channel(dev, AUDIO_CHANNEL_OFFSET + ac->ch);
 251                spin_unlock_irqrestore(&dev->lock, flags);
 252
 253                spin_lock_irqsave(&ac->lock, flags);
 254                ac->curr_bufs[0] = NULL;
 255                ac->curr_bufs[1] = NULL;
 256                spin_unlock_irqrestore(&ac->lock, flags);
 257                break;
 258        default:
 259                err = -EINVAL;
 260        }
 261        return err;
 262}
 263
 264static snd_pcm_uframes_t tw686x_pcm_pointer(struct snd_pcm_substream *ss)
 265{
 266        struct tw686x_dev *dev = snd_pcm_substream_chip(ss);
 267        struct tw686x_audio_channel *ac = &dev->audio_channels[ss->number];
 268
 269        return bytes_to_frames(ss->runtime, ac->ptr);
 270}
 271
 272static const struct snd_pcm_ops tw686x_pcm_ops = {
 273        .open = tw686x_pcm_open,
 274        .close = tw686x_pcm_close,
 275        .ioctl = snd_pcm_lib_ioctl,
 276        .hw_params = tw686x_pcm_hw_params,
 277        .hw_free = tw686x_pcm_hw_free,
 278        .prepare = tw686x_pcm_prepare,
 279        .trigger = tw686x_pcm_trigger,
 280        .pointer = tw686x_pcm_pointer,
 281};
 282
 283static int tw686x_snd_pcm_init(struct tw686x_dev *dev)
 284{
 285        struct snd_card *card = dev->snd_card;
 286        struct snd_pcm *pcm;
 287        struct snd_pcm_substream *ss;
 288        unsigned int i;
 289        int err;
 290
 291        err = snd_pcm_new(card, card->driver, 0, 0, max_channels(dev), &pcm);
 292        if (err < 0)
 293                return err;
 294
 295        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &tw686x_pcm_ops);
 296        snd_pcm_chip(pcm) = dev;
 297        pcm->info_flags = 0;
 298        strlcpy(pcm->name, "tw686x PCM", sizeof(pcm->name));
 299
 300        for (i = 0, ss = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
 301             ss; ss = ss->next, i++)
 302                snprintf(ss->name, sizeof(ss->name), "vch%u audio", i);
 303
 304        return snd_pcm_lib_preallocate_pages_for_all(pcm,
 305                                SNDRV_DMA_TYPE_DEV,
 306                                snd_dma_pci_data(dev->pci_dev),
 307                                TW686X_AUDIO_PAGE_MAX * AUDIO_DMA_SIZE_MAX,
 308                                TW686X_AUDIO_PAGE_MAX * AUDIO_DMA_SIZE_MAX);
 309}
 310
 311static void tw686x_audio_dma_free(struct tw686x_dev *dev,
 312                                  struct tw686x_audio_channel *ac)
 313{
 314        int pb;
 315
 316        for (pb = 0; pb < 2; pb++) {
 317                if (!ac->dma_descs[pb].virt)
 318                        continue;
 319                pci_free_consistent(dev->pci_dev, ac->dma_descs[pb].size,
 320                                    ac->dma_descs[pb].virt,
 321                                    ac->dma_descs[pb].phys);
 322                ac->dma_descs[pb].virt = NULL;
 323        }
 324}
 325
 326static int tw686x_audio_dma_alloc(struct tw686x_dev *dev,
 327                                  struct tw686x_audio_channel *ac)
 328{
 329        int pb;
 330
 331        /*
 332         * In the memcpy DMA mode we allocate a consistent buffer
 333         * and use it for the DMA capture. Otherwise, DMA
 334         * acts on the ALSA buffers as received in pcm_prepare.
 335         */
 336        if (dev->dma_mode != TW686X_DMA_MODE_MEMCPY)
 337                return 0;
 338
 339        for (pb = 0; pb < 2; pb++) {
 340                u32 reg = pb ? ADMA_B_ADDR[ac->ch] : ADMA_P_ADDR[ac->ch];
 341                void *virt;
 342
 343                virt = pci_alloc_consistent(dev->pci_dev, AUDIO_DMA_SIZE_MAX,
 344                                            &ac->dma_descs[pb].phys);
 345                if (!virt) {
 346                        dev_err(&dev->pci_dev->dev,
 347                                "dma%d: unable to allocate audio DMA %s-buffer\n",
 348                                ac->ch, pb ? "B" : "P");
 349                        return -ENOMEM;
 350                }
 351                ac->dma_descs[pb].virt = virt;
 352                ac->dma_descs[pb].size = AUDIO_DMA_SIZE_MAX;
 353                reg_write(dev, reg, ac->dma_descs[pb].phys);
 354        }
 355        return 0;
 356}
 357
 358void tw686x_audio_free(struct tw686x_dev *dev)
 359{
 360        unsigned long flags;
 361        u32 dma_ch_mask;
 362        u32 dma_cmd;
 363
 364        spin_lock_irqsave(&dev->lock, flags);
 365        dma_cmd = reg_read(dev, DMA_CMD);
 366        dma_ch_mask = reg_read(dev, DMA_CHANNEL_ENABLE);
 367        reg_write(dev, DMA_CMD, dma_cmd & ~0xff00);
 368        reg_write(dev, DMA_CHANNEL_ENABLE, dma_ch_mask & ~0xff00);
 369        spin_unlock_irqrestore(&dev->lock, flags);
 370
 371        if (!dev->snd_card)
 372                return;
 373        snd_card_free(dev->snd_card);
 374        dev->snd_card = NULL;
 375}
 376
 377int tw686x_audio_init(struct tw686x_dev *dev)
 378{
 379        struct pci_dev *pci_dev = dev->pci_dev;
 380        struct snd_card *card;
 381        int err, ch;
 382
 383        /* Enable external audio */
 384        reg_write(dev, AUDIO_CONTROL1, BIT(0));
 385
 386        err = snd_card_new(&pci_dev->dev, SNDRV_DEFAULT_IDX1,
 387                           SNDRV_DEFAULT_STR1,
 388                           THIS_MODULE, 0, &card);
 389        if (err < 0)
 390                return err;
 391
 392        dev->snd_card = card;
 393        strlcpy(card->driver, "tw686x", sizeof(card->driver));
 394        strlcpy(card->shortname, "tw686x", sizeof(card->shortname));
 395        strlcpy(card->longname, pci_name(pci_dev), sizeof(card->longname));
 396        snd_card_set_dev(card, &pci_dev->dev);
 397
 398        for (ch = 0; ch < max_channels(dev); ch++) {
 399                struct tw686x_audio_channel *ac;
 400
 401                ac = &dev->audio_channels[ch];
 402                spin_lock_init(&ac->lock);
 403                ac->dev = dev;
 404                ac->ch = ch;
 405
 406                err = tw686x_audio_dma_alloc(dev, ac);
 407                if (err < 0)
 408                        goto err_cleanup;
 409        }
 410
 411        err = tw686x_snd_pcm_init(dev);
 412        if (err < 0)
 413                goto err_cleanup;
 414
 415        err = snd_card_register(card);
 416        if (!err)
 417                return 0;
 418
 419err_cleanup:
 420        for (ch = 0; ch < max_channels(dev); ch++) {
 421                if (!dev->audio_channels[ch].dev)
 422                        continue;
 423                tw686x_audio_dma_free(dev, &dev->audio_channels[ch]);
 424        }
 425        snd_card_free(card);
 426        dev->snd_card = NULL;
 427        return err;
 428}
 429