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