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