linux/sound/sh/sh_dac_audio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * sh_dac_audio.c - SuperH DAC audio driver for ALSA
   4 *
   5 * Copyright (c) 2009 by Rafael Ignacio Zurita <rizurita@yahoo.com>
   6 *
   7 * Based on sh_dac_audio.c (Copyright (C) 2004, 2005 by Andriy Skulysh)
   8 */
   9
  10#include <linux/hrtimer.h>
  11#include <linux/interrupt.h>
  12#include <linux/io.h>
  13#include <linux/platform_device.h>
  14#include <linux/slab.h>
  15#include <linux/module.h>
  16#include <sound/core.h>
  17#include <sound/initval.h>
  18#include <sound/pcm.h>
  19#include <sound/sh_dac_audio.h>
  20#include <asm/clock.h>
  21#include <asm/hd64461.h>
  22#include <mach/hp6xx.h>
  23#include <cpu/dac.h>
  24
  25MODULE_AUTHOR("Rafael Ignacio Zurita <rizurita@yahoo.com>");
  26MODULE_DESCRIPTION("SuperH DAC audio driver");
  27MODULE_LICENSE("GPL");
  28
  29/* Module Parameters */
  30static int index = SNDRV_DEFAULT_IDX1;
  31static char *id = SNDRV_DEFAULT_STR1;
  32module_param(index, int, 0444);
  33MODULE_PARM_DESC(index, "Index value for SuperH DAC audio.");
  34module_param(id, charp, 0444);
  35MODULE_PARM_DESC(id, "ID string for SuperH DAC audio.");
  36
  37/* main struct */
  38struct snd_sh_dac {
  39        struct snd_card *card;
  40        struct snd_pcm_substream *substream;
  41        struct hrtimer hrtimer;
  42        ktime_t wakeups_per_second;
  43
  44        int rate;
  45        int empty;
  46        char *data_buffer, *buffer_begin, *buffer_end;
  47        int processed; /* bytes proccesed, to compare with period_size */
  48        int buffer_size;
  49        struct dac_audio_pdata *pdata;
  50};
  51
  52
  53static void dac_audio_start_timer(struct snd_sh_dac *chip)
  54{
  55        hrtimer_start(&chip->hrtimer, chip->wakeups_per_second,
  56                      HRTIMER_MODE_REL);
  57}
  58
  59static void dac_audio_stop_timer(struct snd_sh_dac *chip)
  60{
  61        hrtimer_cancel(&chip->hrtimer);
  62}
  63
  64static void dac_audio_reset(struct snd_sh_dac *chip)
  65{
  66        dac_audio_stop_timer(chip);
  67        chip->buffer_begin = chip->buffer_end = chip->data_buffer;
  68        chip->processed = 0;
  69        chip->empty = 1;
  70}
  71
  72static void dac_audio_set_rate(struct snd_sh_dac *chip)
  73{
  74        chip->wakeups_per_second = 1000000000 / chip->rate;
  75}
  76
  77
  78/* PCM INTERFACE */
  79
  80static const struct snd_pcm_hardware snd_sh_dac_pcm_hw = {
  81        .info                   = (SNDRV_PCM_INFO_MMAP |
  82                                        SNDRV_PCM_INFO_MMAP_VALID |
  83                                        SNDRV_PCM_INFO_INTERLEAVED |
  84                                        SNDRV_PCM_INFO_HALF_DUPLEX),
  85        .formats                = SNDRV_PCM_FMTBIT_U8,
  86        .rates                  = SNDRV_PCM_RATE_8000,
  87        .rate_min               = 8000,
  88        .rate_max               = 8000,
  89        .channels_min           = 1,
  90        .channels_max           = 1,
  91        .buffer_bytes_max       = (48*1024),
  92        .period_bytes_min       = 1,
  93        .period_bytes_max       = (48*1024),
  94        .periods_min            = 1,
  95        .periods_max            = 1024,
  96};
  97
  98static int snd_sh_dac_pcm_open(struct snd_pcm_substream *substream)
  99{
 100        struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
 101        struct snd_pcm_runtime *runtime = substream->runtime;
 102
 103        runtime->hw = snd_sh_dac_pcm_hw;
 104
 105        chip->substream = substream;
 106        chip->buffer_begin = chip->buffer_end = chip->data_buffer;
 107        chip->processed = 0;
 108        chip->empty = 1;
 109
 110        chip->pdata->start(chip->pdata);
 111
 112        return 0;
 113}
 114
 115static int snd_sh_dac_pcm_close(struct snd_pcm_substream *substream)
 116{
 117        struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
 118
 119        chip->substream = NULL;
 120
 121        dac_audio_stop_timer(chip);
 122        chip->pdata->stop(chip->pdata);
 123
 124        return 0;
 125}
 126
 127static int snd_sh_dac_pcm_prepare(struct snd_pcm_substream *substream)
 128{
 129        struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
 130        struct snd_pcm_runtime *runtime = chip->substream->runtime;
 131
 132        chip->buffer_size = runtime->buffer_size;
 133        memset(chip->data_buffer, 0, chip->pdata->buffer_size);
 134
 135        return 0;
 136}
 137
 138static int snd_sh_dac_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 139{
 140        struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
 141
 142        switch (cmd) {
 143        case SNDRV_PCM_TRIGGER_START:
 144                dac_audio_start_timer(chip);
 145                break;
 146        case SNDRV_PCM_TRIGGER_STOP:
 147                chip->buffer_begin = chip->buffer_end = chip->data_buffer;
 148                chip->processed = 0;
 149                chip->empty = 1;
 150                dac_audio_stop_timer(chip);
 151                break;
 152        default:
 153                 return -EINVAL;
 154        }
 155
 156        return 0;
 157}
 158
 159static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream,
 160                               int channel, unsigned long pos,
 161                               void __user *src, unsigned long count)
 162{
 163        /* channel is not used (interleaved data) */
 164        struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
 165
 166        if (copy_from_user_toio(chip->data_buffer + pos, src, count))
 167                return -EFAULT;
 168        chip->buffer_end = chip->data_buffer + pos + count;
 169
 170        if (chip->empty) {
 171                chip->empty = 0;
 172                dac_audio_start_timer(chip);
 173        }
 174
 175        return 0;
 176}
 177
 178static int snd_sh_dac_pcm_copy_kernel(struct snd_pcm_substream *substream,
 179                                      int channel, unsigned long pos,
 180                                      void *src, unsigned long count)
 181{
 182        /* channel is not used (interleaved data) */
 183        struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
 184
 185        memcpy_toio(chip->data_buffer + pos, src, count);
 186        chip->buffer_end = chip->data_buffer + pos + count;
 187
 188        if (chip->empty) {
 189                chip->empty = 0;
 190                dac_audio_start_timer(chip);
 191        }
 192
 193        return 0;
 194}
 195
 196static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream,
 197                                  int channel, unsigned long pos,
 198                                  unsigned long count)
 199{
 200        /* channel is not used (interleaved data) */
 201        struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
 202
 203        memset_io(chip->data_buffer + pos, 0, count);
 204        chip->buffer_end = chip->data_buffer + pos + count;
 205
 206        if (chip->empty) {
 207                chip->empty = 0;
 208                dac_audio_start_timer(chip);
 209        }
 210
 211        return 0;
 212}
 213
 214static
 215snd_pcm_uframes_t snd_sh_dac_pcm_pointer(struct snd_pcm_substream *substream)
 216{
 217        struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
 218        int pointer = chip->buffer_begin - chip->data_buffer;
 219
 220        return pointer;
 221}
 222
 223/* pcm ops */
 224static const struct snd_pcm_ops snd_sh_dac_pcm_ops = {
 225        .open           = snd_sh_dac_pcm_open,
 226        .close          = snd_sh_dac_pcm_close,
 227        .prepare        = snd_sh_dac_pcm_prepare,
 228        .trigger        = snd_sh_dac_pcm_trigger,
 229        .pointer        = snd_sh_dac_pcm_pointer,
 230        .copy_user      = snd_sh_dac_pcm_copy,
 231        .copy_kernel    = snd_sh_dac_pcm_copy_kernel,
 232        .fill_silence   = snd_sh_dac_pcm_silence,
 233        .mmap           = snd_pcm_lib_mmap_iomem,
 234};
 235
 236static int snd_sh_dac_pcm(struct snd_sh_dac *chip, int device)
 237{
 238        int err;
 239        struct snd_pcm *pcm;
 240
 241        /* device should be always 0 for us */
 242        err = snd_pcm_new(chip->card, "SH_DAC PCM", device, 1, 0, &pcm);
 243        if (err < 0)
 244                return err;
 245
 246        pcm->private_data = chip;
 247        strcpy(pcm->name, "SH_DAC PCM");
 248        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sh_dac_pcm_ops);
 249
 250        /* buffer size=48K */
 251        snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
 252                                       NULL, 48 * 1024, 48 * 1024);
 253
 254        return 0;
 255}
 256/* END OF PCM INTERFACE */
 257
 258
 259/* driver .remove  --  destructor */
 260static int snd_sh_dac_remove(struct platform_device *devptr)
 261{
 262        snd_card_free(platform_get_drvdata(devptr));
 263        return 0;
 264}
 265
 266/* free -- it has been defined by create */
 267static int snd_sh_dac_free(struct snd_sh_dac *chip)
 268{
 269        /* release the data */
 270        kfree(chip->data_buffer);
 271        kfree(chip);
 272
 273        return 0;
 274}
 275
 276static int snd_sh_dac_dev_free(struct snd_device *device)
 277{
 278        struct snd_sh_dac *chip = device->device_data;
 279
 280        return snd_sh_dac_free(chip);
 281}
 282
 283static enum hrtimer_restart sh_dac_audio_timer(struct hrtimer *handle)
 284{
 285        struct snd_sh_dac *chip = container_of(handle, struct snd_sh_dac,
 286                                               hrtimer);
 287        struct snd_pcm_runtime *runtime = chip->substream->runtime;
 288        ssize_t b_ps = frames_to_bytes(runtime, runtime->period_size);
 289
 290        if (!chip->empty) {
 291                sh_dac_output(*chip->buffer_begin, chip->pdata->channel);
 292                chip->buffer_begin++;
 293
 294                chip->processed++;
 295                if (chip->processed >= b_ps) {
 296                        chip->processed -= b_ps;
 297                        snd_pcm_period_elapsed(chip->substream);
 298                }
 299
 300                if (chip->buffer_begin == (chip->data_buffer +
 301                                           chip->buffer_size - 1))
 302                        chip->buffer_begin = chip->data_buffer;
 303
 304                if (chip->buffer_begin == chip->buffer_end)
 305                        chip->empty = 1;
 306
 307        }
 308
 309        if (!chip->empty)
 310                hrtimer_start(&chip->hrtimer, chip->wakeups_per_second,
 311                              HRTIMER_MODE_REL);
 312
 313        return HRTIMER_NORESTART;
 314}
 315
 316/* create  --  chip-specific constructor for the cards components */
 317static int snd_sh_dac_create(struct snd_card *card,
 318                             struct platform_device *devptr,
 319                             struct snd_sh_dac **rchip)
 320{
 321        struct snd_sh_dac *chip;
 322        int err;
 323
 324        static const struct snd_device_ops ops = {
 325                   .dev_free = snd_sh_dac_dev_free,
 326        };
 327
 328        *rchip = NULL;
 329
 330        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 331        if (chip == NULL)
 332                return -ENOMEM;
 333
 334        chip->card = card;
 335
 336        hrtimer_init(&chip->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 337        chip->hrtimer.function = sh_dac_audio_timer;
 338
 339        dac_audio_reset(chip);
 340        chip->rate = 8000;
 341        dac_audio_set_rate(chip);
 342
 343        chip->pdata = devptr->dev.platform_data;
 344
 345        chip->data_buffer = kmalloc(chip->pdata->buffer_size, GFP_KERNEL);
 346        if (chip->data_buffer == NULL) {
 347                kfree(chip);
 348                return -ENOMEM;
 349        }
 350
 351        err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
 352        if (err < 0) {
 353                snd_sh_dac_free(chip);
 354                return err;
 355        }
 356
 357        *rchip = chip;
 358
 359        return 0;
 360}
 361
 362/* driver .probe  --  constructor */
 363static int snd_sh_dac_probe(struct platform_device *devptr)
 364{
 365        struct snd_sh_dac *chip;
 366        struct snd_card *card;
 367        int err;
 368
 369        err = snd_card_new(&devptr->dev, index, id, THIS_MODULE, 0, &card);
 370        if (err < 0) {
 371                        snd_printk(KERN_ERR "cannot allocate the card\n");
 372                        return err;
 373        }
 374
 375        err = snd_sh_dac_create(card, devptr, &chip);
 376        if (err < 0)
 377                goto probe_error;
 378
 379        err = snd_sh_dac_pcm(chip, 0);
 380        if (err < 0)
 381                goto probe_error;
 382
 383        strcpy(card->driver, "snd_sh_dac");
 384        strcpy(card->shortname, "SuperH DAC audio driver");
 385        printk(KERN_INFO "%s %s", card->longname, card->shortname);
 386
 387        err = snd_card_register(card);
 388        if (err < 0)
 389                goto probe_error;
 390
 391        snd_printk(KERN_INFO "ALSA driver for SuperH DAC audio");
 392
 393        platform_set_drvdata(devptr, card);
 394        return 0;
 395
 396probe_error:
 397        snd_card_free(card);
 398        return err;
 399}
 400
 401/*
 402 * "driver" definition
 403 */
 404static struct platform_driver sh_dac_driver = {
 405        .probe  = snd_sh_dac_probe,
 406        .remove = snd_sh_dac_remove,
 407        .driver = {
 408                .name = "dac_audio",
 409        },
 410};
 411
 412module_platform_driver(sh_dac_driver);
 413