linux/drivers/staging/goldfish/goldfish_audio.c
<<
>>
Prefs
   1/*
   2 * drivers/misc/goldfish_audio.c
   3 *
   4 * Copyright (C) 2007 Google, Inc.
   5 * Copyright (C) 2012 Intel, Inc.
   6 *
   7 * This software is licensed under the terms of the GNU General Public
   8 * License version 2, as published by the Free Software Foundation, and
   9 * may be copied, distributed, and modified under those terms.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 */
  17
  18#include <linux/module.h>
  19#include <linux/miscdevice.h>
  20#include <linux/fs.h>
  21#include <linux/platform_device.h>
  22#include <linux/types.h>
  23#include <linux/pci.h>
  24#include <linux/interrupt.h>
  25#include <linux/io.h>
  26#include <linux/sched.h>
  27#include <linux/dma-mapping.h>
  28#include <linux/uaccess.h>
  29#include <linux/slab.h>
  30#include <linux/goldfish.h>
  31
  32MODULE_AUTHOR("Google, Inc.");
  33MODULE_DESCRIPTION("Android QEMU Audio Driver");
  34MODULE_LICENSE("GPL");
  35MODULE_VERSION("1.0");
  36
  37struct goldfish_audio {
  38        char __iomem *reg_base;
  39        int irq;
  40        /* lock protects access to buffer_status and to device registers */
  41        spinlock_t lock;
  42        wait_queue_head_t wait;
  43
  44        char *buffer_virt;              /* combined buffer virtual address */
  45        unsigned long buffer_phys;      /* combined buffer physical address */
  46
  47        char *write_buffer1;            /* write buffer 1 virtual address */
  48        char *write_buffer2;            /* write buffer 2 virtual address */
  49        char *read_buffer;              /* read buffer virtual address */
  50        int buffer_status;
  51        int read_supported;         /* true if we have audio input support */
  52};
  53
  54/*
  55 *  We will allocate two read buffers and two write buffers.
  56 *  Having two read buffers facilitate stereo -> mono conversion.
  57 *  Having two write buffers facilitate interleaved IO.
  58 */
  59#define READ_BUFFER_SIZE        16384
  60#define WRITE_BUFFER_SIZE       16384
  61#define COMBINED_BUFFER_SIZE    ((2 * READ_BUFFER_SIZE) + \
  62                                        (2 * WRITE_BUFFER_SIZE))
  63
  64#define AUDIO_READ(data, addr)          (readl(data->reg_base + addr))
  65#define AUDIO_WRITE(data, addr, x)      (writel(x, data->reg_base + addr))
  66#define AUDIO_WRITE64(data, addr, addr2, x)     \
  67        (gf_write_dma_addr((x), data->reg_base + addr, data->reg_base + addr2))
  68
  69/*
  70 *  temporary variable used between goldfish_audio_probe() and
  71 *  goldfish_audio_open()
  72 */
  73static struct goldfish_audio *audio_data;
  74
  75enum {
  76        /* audio status register */
  77        AUDIO_INT_STATUS        = 0x00,
  78        /* set this to enable IRQ */
  79        AUDIO_INT_ENABLE        = 0x04,
  80        /* set these to specify buffer addresses */
  81        AUDIO_SET_WRITE_BUFFER_1 = 0x08,
  82        AUDIO_SET_WRITE_BUFFER_2 = 0x0C,
  83        /* set number of bytes in buffer to write */
  84        AUDIO_WRITE_BUFFER_1  = 0x10,
  85        AUDIO_WRITE_BUFFER_2  = 0x14,
  86        AUDIO_SET_WRITE_BUFFER_1_HIGH = 0x28,
  87        AUDIO_SET_WRITE_BUFFER_2_HIGH = 0x30,
  88
  89        /* true if audio input is supported */
  90        AUDIO_READ_SUPPORTED = 0x18,
  91        /* buffer to use for audio input */
  92        AUDIO_SET_READ_BUFFER = 0x1C,
  93        AUDIO_SET_READ_BUFFER_HIGH = 0x34,
  94
  95        /* driver writes number of bytes to read */
  96        AUDIO_START_READ  = 0x20,
  97
  98        /* number of bytes available in read buffer */
  99        AUDIO_READ_BUFFER_AVAILABLE  = 0x24,
 100
 101        /* AUDIO_INT_STATUS bits */
 102
 103        /* this bit set when it is safe to write more bytes to the buffer */
 104        AUDIO_INT_WRITE_BUFFER_1_EMPTY  = 1U << 0,
 105        AUDIO_INT_WRITE_BUFFER_2_EMPTY  = 1U << 1,
 106        AUDIO_INT_READ_BUFFER_FULL      = 1U << 2,
 107
 108        AUDIO_INT_MASK                  = AUDIO_INT_WRITE_BUFFER_1_EMPTY |
 109                                          AUDIO_INT_WRITE_BUFFER_2_EMPTY |
 110                                          AUDIO_INT_READ_BUFFER_FULL,
 111};
 112
 113static atomic_t open_count = ATOMIC_INIT(0);
 114
 115static ssize_t goldfish_audio_read(struct file *fp, char __user *buf,
 116                                   size_t count, loff_t *pos)
 117{
 118        struct goldfish_audio *data = fp->private_data;
 119        int length;
 120        int result = 0;
 121
 122        if (!data->read_supported)
 123                return -ENODEV;
 124
 125        while (count > 0) {
 126                length = (count > READ_BUFFER_SIZE ? READ_BUFFER_SIZE : count);
 127                AUDIO_WRITE(data, AUDIO_START_READ, length);
 128
 129                wait_event_interruptible(data->wait, data->buffer_status &
 130                                         AUDIO_INT_READ_BUFFER_FULL);
 131
 132                length = AUDIO_READ(data, AUDIO_READ_BUFFER_AVAILABLE);
 133
 134                /* copy data to user space */
 135                if (copy_to_user(buf, data->read_buffer, length))
 136                        return -EFAULT;
 137
 138                result += length;
 139                buf += length;
 140                count -= length;
 141        }
 142        return result;
 143}
 144
 145static ssize_t goldfish_audio_write(struct file *fp, const char __user *buf,
 146                                    size_t count, loff_t *pos)
 147{
 148        struct goldfish_audio *data = fp->private_data;
 149        unsigned long irq_flags;
 150        ssize_t result = 0;
 151        char *kbuf;
 152
 153        while (count > 0) {
 154                ssize_t copy = count;
 155
 156                if (copy > WRITE_BUFFER_SIZE)
 157                        copy = WRITE_BUFFER_SIZE;
 158                wait_event_interruptible(data->wait, data->buffer_status &
 159                                        (AUDIO_INT_WRITE_BUFFER_1_EMPTY |
 160                                        AUDIO_INT_WRITE_BUFFER_2_EMPTY));
 161
 162                if ((data->buffer_status & AUDIO_INT_WRITE_BUFFER_1_EMPTY) != 0)
 163                        kbuf = data->write_buffer1;
 164                else
 165                        kbuf = data->write_buffer2;
 166
 167                /* copy from user space to the appropriate buffer */
 168                if (copy_from_user(kbuf, buf, copy)) {
 169                        result = -EFAULT;
 170                        break;
 171                }
 172
 173                spin_lock_irqsave(&data->lock, irq_flags);
 174                /*
 175                 *  clear the buffer empty flag, and signal the emulator
 176                 *  to start writing the buffer
 177                 */
 178                if (kbuf == data->write_buffer1) {
 179                        data->buffer_status &= ~AUDIO_INT_WRITE_BUFFER_1_EMPTY;
 180                        AUDIO_WRITE(data, AUDIO_WRITE_BUFFER_1, copy);
 181                } else {
 182                        data->buffer_status &= ~AUDIO_INT_WRITE_BUFFER_2_EMPTY;
 183                        AUDIO_WRITE(data, AUDIO_WRITE_BUFFER_2, copy);
 184                }
 185                spin_unlock_irqrestore(&data->lock, irq_flags);
 186
 187                buf += copy;
 188                result += copy;
 189                count -= copy;
 190        }
 191        return result;
 192}
 193
 194static int goldfish_audio_open(struct inode *ip, struct file *fp)
 195{
 196        if (!audio_data)
 197                return -ENODEV;
 198
 199        if (atomic_inc_return(&open_count) == 1) {
 200                fp->private_data = audio_data;
 201                audio_data->buffer_status = (AUDIO_INT_WRITE_BUFFER_1_EMPTY |
 202                                             AUDIO_INT_WRITE_BUFFER_2_EMPTY);
 203                AUDIO_WRITE(audio_data, AUDIO_INT_ENABLE, AUDIO_INT_MASK);
 204                return 0;
 205        }
 206
 207        atomic_dec(&open_count);
 208        return -EBUSY;
 209}
 210
 211static int goldfish_audio_release(struct inode *ip, struct file *fp)
 212{
 213        atomic_dec(&open_count);
 214        /* FIXME: surely this is wrong for the multi-opened case */
 215        AUDIO_WRITE(audio_data, AUDIO_INT_ENABLE, 0);
 216        return 0;
 217}
 218
 219static long goldfish_audio_ioctl(struct file *fp, unsigned int cmd,
 220                                 unsigned long arg)
 221{
 222        /* temporary workaround, until we switch to the ALSA API */
 223        if (cmd == 315)
 224                return -1;
 225
 226        return 0;
 227}
 228
 229static irqreturn_t goldfish_audio_interrupt(int irq, void *dev_id)
 230{
 231        unsigned long irq_flags;
 232        struct goldfish_audio   *data = dev_id;
 233        u32 status;
 234
 235        spin_lock_irqsave(&data->lock, irq_flags);
 236
 237        /* read buffer status flags */
 238        status = AUDIO_READ(data, AUDIO_INT_STATUS);
 239        status &= AUDIO_INT_MASK;
 240        /*
 241         *  if buffers are newly empty, wake up blocked
 242         *  goldfish_audio_write() call
 243         */
 244        if (status) {
 245                data->buffer_status = status;
 246                wake_up(&data->wait);
 247        }
 248
 249        spin_unlock_irqrestore(&data->lock, irq_flags);
 250        return status ? IRQ_HANDLED : IRQ_NONE;
 251}
 252
 253/* file operations for /dev/eac */
 254static const struct file_operations goldfish_audio_fops = {
 255        .owner = THIS_MODULE,
 256        .read = goldfish_audio_read,
 257        .write = goldfish_audio_write,
 258        .open = goldfish_audio_open,
 259        .release = goldfish_audio_release,
 260        .unlocked_ioctl = goldfish_audio_ioctl,
 261};
 262
 263static struct miscdevice goldfish_audio_device = {
 264        .minor = MISC_DYNAMIC_MINOR,
 265        .name = "eac",
 266        .fops = &goldfish_audio_fops,
 267};
 268
 269static int goldfish_audio_probe(struct platform_device *pdev)
 270{
 271        int ret;
 272        struct resource *r;
 273        struct goldfish_audio *data;
 274        dma_addr_t buf_addr;
 275
 276        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
 277        if (!data)
 278                return -ENOMEM;
 279        spin_lock_init(&data->lock);
 280        init_waitqueue_head(&data->wait);
 281        platform_set_drvdata(pdev, data);
 282
 283        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 284        if (!r) {
 285                dev_err(&pdev->dev, "platform_get_resource failed\n");
 286                return -ENODEV;
 287        }
 288        data->reg_base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE);
 289        if (!data->reg_base)
 290                return -ENOMEM;
 291
 292        data->irq = platform_get_irq(pdev, 0);
 293        if (data->irq < 0) {
 294                dev_err(&pdev->dev, "platform_get_irq failed\n");
 295                return -ENODEV;
 296        }
 297        data->buffer_virt = dmam_alloc_coherent(&pdev->dev,
 298                                COMBINED_BUFFER_SIZE, &buf_addr, GFP_KERNEL);
 299        if (!data->buffer_virt) {
 300                dev_err(&pdev->dev, "allocate buffer failed\n");
 301                return -ENOMEM;
 302        }
 303        data->buffer_phys = buf_addr;
 304        data->write_buffer1 = data->buffer_virt;
 305        data->write_buffer2 = data->buffer_virt + WRITE_BUFFER_SIZE;
 306        data->read_buffer = data->buffer_virt + 2 * WRITE_BUFFER_SIZE;
 307
 308        ret = devm_request_irq(&pdev->dev, data->irq, goldfish_audio_interrupt,
 309                               IRQF_SHARED, pdev->name, data);
 310        if (ret) {
 311                dev_err(&pdev->dev, "request_irq failed\n");
 312                return ret;
 313        }
 314
 315        ret = misc_register(&goldfish_audio_device);
 316        if (ret) {
 317                dev_err(&pdev->dev,
 318                        "misc_register returned %d in goldfish_audio_init\n",
 319                                                                ret);
 320                return ret;
 321        }
 322
 323        AUDIO_WRITE64(data, AUDIO_SET_WRITE_BUFFER_1,
 324                      AUDIO_SET_WRITE_BUFFER_1_HIGH, buf_addr);
 325        buf_addr += WRITE_BUFFER_SIZE;
 326
 327        AUDIO_WRITE64(data, AUDIO_SET_WRITE_BUFFER_2,
 328                      AUDIO_SET_WRITE_BUFFER_2_HIGH, buf_addr);
 329
 330        buf_addr += WRITE_BUFFER_SIZE;
 331
 332        data->read_supported = AUDIO_READ(data, AUDIO_READ_SUPPORTED);
 333        if (data->read_supported)
 334                AUDIO_WRITE64(data, AUDIO_SET_READ_BUFFER,
 335                              AUDIO_SET_READ_BUFFER_HIGH, buf_addr);
 336
 337        audio_data = data;
 338        return 0;
 339}
 340
 341static int goldfish_audio_remove(struct platform_device *pdev)
 342{
 343        misc_deregister(&goldfish_audio_device);
 344        audio_data = NULL;
 345        return 0;
 346}
 347
 348static const struct of_device_id goldfish_audio_of_match[] = {
 349        { .compatible = "google,goldfish-audio", },
 350        {},
 351};
 352MODULE_DEVICE_TABLE(of, goldfish_audio_of_match);
 353
 354static struct platform_driver goldfish_audio_driver = {
 355        .probe          = goldfish_audio_probe,
 356        .remove         = goldfish_audio_remove,
 357        .driver = {
 358                .name = "goldfish_audio",
 359                .of_match_table = goldfish_audio_of_match,
 360        }
 361};
 362
 363module_platform_driver(goldfish_audio_driver);
 364