linux/drivers/media/video/saa7134/saa7134-oss.c
<<
>>
Prefs
   1/*
   2 *
   3 * device driver for philips saa7134 based TV cards
   4 * oss dsp interface
   5 *
   6 * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
   7 *     2005 conversion to standalone module:
   8 *         Ricardo Cerqueira <v4l@cerqueira.org>
   9 *
  10 *  This program is free software; you can redistribute it and/or modify
  11 *  it under the terms of the GNU General Public License as published by
  12 *  the Free Software Foundation; either version 2 of the License, or
  13 *  (at your option) any later version.
  14 *
  15 *  This program is distributed in the hope that it will be useful,
  16 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 *  GNU General Public License for more details.
  19 *
  20 *  You should have received a copy of the GNU General Public License
  21 *  along with this program; if not, write to the Free Software
  22 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23 */
  24
  25#include <linux/init.h>
  26#include <linux/list.h>
  27#include <linux/module.h>
  28#include <linux/moduleparam.h>
  29#include <linux/kernel.h>
  30#include <linux/interrupt.h>
  31#include <linux/slab.h>
  32#include <linux/sound.h>
  33#include <linux/soundcard.h>
  34
  35#include "saa7134-reg.h"
  36#include "saa7134.h"
  37
  38/* ------------------------------------------------------------------ */
  39
  40static unsigned int debug  = 0;
  41module_param(debug, int, 0644);
  42MODULE_PARM_DESC(debug,"enable debug messages [oss]");
  43
  44static unsigned int rate  = 0;
  45module_param(rate, int, 0444);
  46MODULE_PARM_DESC(rate,"sample rate (valid are: 32000,48000)");
  47
  48static unsigned int dsp_nr[]   = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
  49MODULE_PARM_DESC(dsp_nr, "device numbers for SAA7134 capture interface(s).");
  50module_param_array(dsp_nr,   int, NULL, 0444);
  51
  52static unsigned int mixer_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
  53MODULE_PARM_DESC(mixer_nr, "mixer numbers for SAA7134 capture interface(s).");
  54module_param_array(mixer_nr, int, NULL, 0444);
  55
  56#define dprintk(fmt, arg...)    if (debug) \
  57        printk(KERN_DEBUG "%s/oss: " fmt, dev->name , ## arg)
  58
  59
  60/* ------------------------------------------------------------------ */
  61
  62static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks)
  63{
  64        if (blksize < 0x100)
  65                blksize = 0x100;
  66        if (blksize > 0x10000)
  67                blksize = 0x10000;
  68
  69        if (blocks < 2)
  70                blocks = 2;
  71        if ((blksize * blocks) > 1024*1024)
  72                blocks = 1024*1024 / blksize;
  73
  74        dev->dmasound.blocks  = blocks;
  75        dev->dmasound.blksize = blksize;
  76        dev->dmasound.bufsize = blksize * blocks;
  77
  78        dprintk("buffer config: %d blocks / %d bytes, %d kB total\n",
  79                blocks,blksize,blksize * blocks / 1024);
  80        return 0;
  81}
  82
  83static int dsp_buffer_init(struct saa7134_dev *dev)
  84{
  85        int err;
  86
  87        BUG_ON(!dev->dmasound.bufsize);
  88        videobuf_dma_init(&dev->dmasound.dma);
  89        err = videobuf_dma_init_kernel(&dev->dmasound.dma, PCI_DMA_FROMDEVICE,
  90                                       (dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT);
  91        if (0 != err)
  92                return err;
  93        return 0;
  94}
  95
  96static int dsp_buffer_free(struct saa7134_dev *dev)
  97{
  98        BUG_ON(!dev->dmasound.blksize);
  99        videobuf_dma_free(&dev->dmasound.dma);
 100        dev->dmasound.blocks  = 0;
 101        dev->dmasound.blksize = 0;
 102        dev->dmasound.bufsize = 0;
 103        return 0;
 104}
 105
 106static void dsp_dma_start(struct saa7134_dev *dev)
 107{
 108        dev->dmasound.dma_blk     = 0;
 109        dev->dmasound.dma_running = 1;
 110        saa7134_set_dmabits(dev);
 111}
 112
 113static void dsp_dma_stop(struct saa7134_dev *dev)
 114{
 115        dev->dmasound.dma_blk     = -1;
 116        dev->dmasound.dma_running = 0;
 117        saa7134_set_dmabits(dev);
 118}
 119
 120static int dsp_rec_start(struct saa7134_dev *dev)
 121{
 122        int err, bswap, sign;
 123        u32 fmt, control;
 124        unsigned long flags;
 125
 126        /* prepare buffer */
 127        if (0 != (err = videobuf_pci_dma_map(dev->pci,&dev->dmasound.dma)))
 128                return err;
 129        if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt)))
 130                goto fail1;
 131        if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt,
 132                                              dev->dmasound.dma.sglist,
 133                                              dev->dmasound.dma.sglen,
 134                                              0)))
 135                goto fail2;
 136
 137        /* sample format */
 138        switch (dev->dmasound.afmt) {
 139        case AFMT_U8:
 140        case AFMT_S8:     fmt = 0x00;  break;
 141        case AFMT_U16_LE:
 142        case AFMT_U16_BE:
 143        case AFMT_S16_LE:
 144        case AFMT_S16_BE: fmt = 0x01;  break;
 145        default:
 146                err = -EINVAL;
 147                goto fail2;
 148        }
 149
 150        switch (dev->dmasound.afmt) {
 151        case AFMT_S8:
 152        case AFMT_S16_LE:
 153        case AFMT_S16_BE: sign = 1; break;
 154        default:          sign = 0; break;
 155        }
 156
 157        switch (dev->dmasound.afmt) {
 158        case AFMT_U16_BE:
 159        case AFMT_S16_BE: bswap = 1; break;
 160        default:          bswap = 0; break;
 161        }
 162
 163        switch (dev->pci->device) {
 164        case PCI_DEVICE_ID_PHILIPS_SAA7134:
 165                if (1 == dev->dmasound.channels)
 166                        fmt |= (1 << 3);
 167                if (2 == dev->dmasound.channels)
 168                        fmt |= (3 << 3);
 169                if (sign)
 170                        fmt |= 0x04;
 171                fmt |= (TV == dev->dmasound.input) ? 0xc0 : 0x80;
 172
 173                saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->dmasound.blksize - 1) & 0x0000ff));
 174                saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->dmasound.blksize - 1) & 0x00ff00) >>  8);
 175                saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->dmasound.blksize - 1) & 0xff0000) >> 16);
 176                saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt);
 177
 178                break;
 179        case PCI_DEVICE_ID_PHILIPS_SAA7133:
 180        case PCI_DEVICE_ID_PHILIPS_SAA7135:
 181                if (1 == dev->dmasound.channels)
 182                        fmt |= (1 << 4);
 183                if (2 == dev->dmasound.channels)
 184                        fmt |= (2 << 4);
 185                if (!sign)
 186                        fmt |= 0x04;
 187                saa_writel(SAA7133_NUM_SAMPLES, dev->dmasound.blksize -4);
 188                saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24));
 189                break;
 190        }
 191        dprintk("rec_start: afmt=%d ch=%d  =>  fmt=0x%x swap=%c\n",
 192                dev->dmasound.afmt, dev->dmasound.channels, fmt,
 193                bswap ? 'b' : '-');
 194
 195        /* dma: setup channel 6 (= AUDIO) */
 196        control = SAA7134_RS_CONTROL_BURST_16 |
 197                SAA7134_RS_CONTROL_ME |
 198                (dev->dmasound.pt.dma >> 12);
 199        if (bswap)
 200                control |= SAA7134_RS_CONTROL_BSWAP;
 201        saa_writel(SAA7134_RS_BA1(6),0);
 202        saa_writel(SAA7134_RS_BA2(6),dev->dmasound.blksize);
 203        saa_writel(SAA7134_RS_PITCH(6),0);
 204        saa_writel(SAA7134_RS_CONTROL(6),control);
 205
 206        /* start dma */
 207        dev->dmasound.recording_on = 1;
 208        spin_lock_irqsave(&dev->slock,flags);
 209        dsp_dma_start(dev);
 210        spin_unlock_irqrestore(&dev->slock,flags);
 211        return 0;
 212
 213 fail2:
 214        saa7134_pgtable_free(dev->pci,&dev->dmasound.pt);
 215 fail1:
 216        videobuf_pci_dma_unmap(dev->pci,&dev->dmasound.dma);
 217        return err;
 218}
 219
 220static int dsp_rec_stop(struct saa7134_dev *dev)
 221{
 222        unsigned long flags;
 223
 224        dprintk("rec_stop dma_blk=%d\n",dev->dmasound.dma_blk);
 225
 226        /* stop dma */
 227        dev->dmasound.recording_on = 0;
 228        spin_lock_irqsave(&dev->slock,flags);
 229        dsp_dma_stop(dev);
 230        spin_unlock_irqrestore(&dev->slock,flags);
 231
 232        /* unlock buffer */
 233        saa7134_pgtable_free(dev->pci,&dev->dmasound.pt);
 234        videobuf_pci_dma_unmap(dev->pci,&dev->dmasound.dma);
 235        return 0;
 236}
 237
 238/* ------------------------------------------------------------------ */
 239
 240static int dsp_open(struct inode *inode, struct file *file)
 241{
 242        int minor = iminor(inode);
 243        struct saa7134_dev *h,*dev = NULL;
 244        struct list_head *list;
 245        int err;
 246
 247        list_for_each(list,&saa7134_devlist) {
 248                h = list_entry(list, struct saa7134_dev, devlist);
 249                if (h->dmasound.minor_dsp == minor)
 250                        dev = h;
 251        }
 252        if (NULL == dev)
 253                return -ENODEV;
 254
 255        mutex_lock(&dev->dmasound.lock);
 256        err = -EBUSY;
 257        if (dev->dmasound.users_dsp)
 258                goto fail1;
 259        dev->dmasound.users_dsp++;
 260        file->private_data = dev;
 261
 262        dev->dmasound.afmt        = AFMT_U8;
 263        dev->dmasound.channels    = 1;
 264        dev->dmasound.read_count  = 0;
 265        dev->dmasound.read_offset = 0;
 266        dsp_buffer_conf(dev,PAGE_SIZE,64);
 267        err = dsp_buffer_init(dev);
 268        if (0 != err)
 269                goto fail2;
 270
 271        mutex_unlock(&dev->dmasound.lock);
 272        return 0;
 273
 274 fail2:
 275        dev->dmasound.users_dsp--;
 276 fail1:
 277        mutex_unlock(&dev->dmasound.lock);
 278        return err;
 279}
 280
 281static int dsp_release(struct inode *inode, struct file *file)
 282{
 283        struct saa7134_dev *dev = file->private_data;
 284
 285        mutex_lock(&dev->dmasound.lock);
 286        if (dev->dmasound.recording_on)
 287                dsp_rec_stop(dev);
 288        dsp_buffer_free(dev);
 289        dev->dmasound.users_dsp--;
 290        file->private_data = NULL;
 291        mutex_unlock(&dev->dmasound.lock);
 292        return 0;
 293}
 294
 295static ssize_t dsp_read(struct file *file, char __user *buffer,
 296                        size_t count, loff_t *ppos)
 297{
 298        struct saa7134_dev *dev = file->private_data;
 299        DECLARE_WAITQUEUE(wait, current);
 300        unsigned int bytes;
 301        unsigned long flags;
 302        int err,ret = 0;
 303
 304        add_wait_queue(&dev->dmasound.wq, &wait);
 305        mutex_lock(&dev->dmasound.lock);
 306        while (count > 0) {
 307                /* wait for data if needed */
 308                if (0 == dev->dmasound.read_count) {
 309                        if (!dev->dmasound.recording_on) {
 310                                err = dsp_rec_start(dev);
 311                                if (err < 0) {
 312                                        if (0 == ret)
 313                                                ret = err;
 314                                        break;
 315                                }
 316                        }
 317                        if (dev->dmasound.recording_on &&
 318                            !dev->dmasound.dma_running) {
 319                                /* recover from overruns */
 320                                spin_lock_irqsave(&dev->slock,flags);
 321                                dsp_dma_start(dev);
 322                                spin_unlock_irqrestore(&dev->slock,flags);
 323                        }
 324                        if (file->f_flags & O_NONBLOCK) {
 325                                if (0 == ret)
 326                                        ret = -EAGAIN;
 327                                break;
 328                        }
 329                        mutex_unlock(&dev->dmasound.lock);
 330                        set_current_state(TASK_INTERRUPTIBLE);
 331                        if (0 == dev->dmasound.read_count)
 332                                schedule();
 333                        set_current_state(TASK_RUNNING);
 334                        mutex_lock(&dev->dmasound.lock);
 335                        if (signal_pending(current)) {
 336                                if (0 == ret)
 337                                        ret = -EINTR;
 338                                break;
 339                        }
 340                }
 341
 342                /* copy data to userspace */
 343                bytes = count;
 344                if (bytes > dev->dmasound.read_count)
 345                        bytes = dev->dmasound.read_count;
 346                if (bytes > dev->dmasound.bufsize - dev->dmasound.read_offset)
 347                        bytes = dev->dmasound.bufsize - dev->dmasound.read_offset;
 348                if (copy_to_user(buffer + ret,
 349                                 dev->dmasound.dma.vmalloc + dev->dmasound.read_offset,
 350                                 bytes)) {
 351                        if (0 == ret)
 352                                ret = -EFAULT;
 353                        break;
 354                }
 355
 356                ret   += bytes;
 357                count -= bytes;
 358                dev->dmasound.read_count  -= bytes;
 359                dev->dmasound.read_offset += bytes;
 360                if (dev->dmasound.read_offset == dev->dmasound.bufsize)
 361                        dev->dmasound.read_offset = 0;
 362        }
 363        mutex_unlock(&dev->dmasound.lock);
 364        remove_wait_queue(&dev->dmasound.wq, &wait);
 365        return ret;
 366}
 367
 368static ssize_t dsp_write(struct file *file, const char __user *buffer,
 369                         size_t count, loff_t *ppos)
 370{
 371        return -EINVAL;
 372}
 373
 374static const char *osspcm_ioctls[] = {
 375        "RESET", "SYNC", "SPEED", "STEREO", "GETBLKSIZE", "SETFMT",
 376        "CHANNELS", "?", "POST", "SUBDIVIDE", "SETFRAGMENT", "GETFMTS",
 377        "GETOSPACE", "GETISPACE", "NONBLOCK", "GETCAPS", "GET/SETTRIGGER",
 378        "GETIPTR", "GETOPTR", "MAPINBUF", "MAPOUTBUF", "SETSYNCRO",
 379        "SETDUPLEX", "GETODELAY"
 380};
 381#define OSSPCM_IOCTLS ARRAY_SIZE(osspcm_ioctls)
 382
 383static void saa7134_oss_print_ioctl(char *name, unsigned int cmd)
 384{
 385        char *dir;
 386
 387        switch (_IOC_DIR(cmd)) {
 388        case _IOC_NONE:              dir = "--"; break;
 389        case _IOC_READ:              dir = "r-"; break;
 390        case _IOC_WRITE:             dir = "-w"; break;
 391        case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
 392        default:                     dir = "??"; break;
 393        }
 394        switch (_IOC_TYPE(cmd)) {
 395        case 'P':
 396                printk(KERN_DEBUG "%s: ioctl 0x%08x (oss dsp, %s, SNDCTL_DSP_%s)\n",
 397                       name, cmd, dir, (_IOC_NR(cmd) < OSSPCM_IOCTLS) ?
 398                       osspcm_ioctls[_IOC_NR(cmd)] : "???");
 399                break;
 400        case 'M':
 401                printk(KERN_DEBUG "%s: ioctl 0x%08x (oss mixer, %s, #%d)\n",
 402                       name, cmd, dir, _IOC_NR(cmd));
 403                break;
 404        default:
 405                printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n",
 406                       name, cmd, dir, _IOC_NR(cmd));
 407        }
 408}
 409
 410static int dsp_ioctl(struct inode *inode, struct file *file,
 411                     unsigned int cmd, unsigned long arg)
 412{
 413        struct saa7134_dev *dev = file->private_data;
 414        void __user *argp = (void __user *) arg;
 415        int __user *p = argp;
 416        int val = 0;
 417
 418        if (debug > 1)
 419                saa7134_oss_print_ioctl(dev->name,cmd);
 420        switch (cmd) {
 421        case OSS_GETVERSION:
 422                return put_user(SOUND_VERSION, p);
 423        case SNDCTL_DSP_GETCAPS:
 424                return 0;
 425
 426        case SNDCTL_DSP_SPEED:
 427                if (get_user(val, p))
 428                        return -EFAULT;
 429                /* fall through */
 430        case SOUND_PCM_READ_RATE:
 431                return put_user(dev->dmasound.rate, p);
 432
 433        case SNDCTL_DSP_STEREO:
 434                if (get_user(val, p))
 435                        return -EFAULT;
 436                mutex_lock(&dev->dmasound.lock);
 437                dev->dmasound.channels = val ? 2 : 1;
 438                if (dev->dmasound.recording_on) {
 439                        dsp_rec_stop(dev);
 440                        dsp_rec_start(dev);
 441                }
 442                mutex_unlock(&dev->dmasound.lock);
 443                return put_user(dev->dmasound.channels-1, p);
 444
 445        case SNDCTL_DSP_CHANNELS:
 446                if (get_user(val, p))
 447                        return -EFAULT;
 448                if (val != 1 && val != 2)
 449                        return -EINVAL;
 450                mutex_lock(&dev->dmasound.lock);
 451                dev->dmasound.channels = val;
 452                if (dev->dmasound.recording_on) {
 453                        dsp_rec_stop(dev);
 454                        dsp_rec_start(dev);
 455                }
 456                mutex_unlock(&dev->dmasound.lock);
 457                /* fall through */
 458        case SOUND_PCM_READ_CHANNELS:
 459                return put_user(dev->dmasound.channels, p);
 460
 461        case SNDCTL_DSP_GETFMTS: /* Returns a mask */
 462                return put_user(AFMT_U8     | AFMT_S8     |
 463                                AFMT_U16_LE | AFMT_U16_BE |
 464                                AFMT_S16_LE | AFMT_S16_BE, p);
 465
 466        case SNDCTL_DSP_SETFMT: /* Selects ONE fmt */
 467                if (get_user(val, p))
 468                        return -EFAULT;
 469                switch (val) {
 470                case AFMT_QUERY:
 471                        /* nothing to do */
 472                        break;
 473                case AFMT_U8:
 474                case AFMT_S8:
 475                case AFMT_U16_LE:
 476                case AFMT_U16_BE:
 477                case AFMT_S16_LE:
 478                case AFMT_S16_BE:
 479                        mutex_lock(&dev->dmasound.lock);
 480                        dev->dmasound.afmt = val;
 481                        if (dev->dmasound.recording_on) {
 482                                dsp_rec_stop(dev);
 483                                dsp_rec_start(dev);
 484                        }
 485                        mutex_unlock(&dev->dmasound.lock);
 486                        return put_user(dev->dmasound.afmt, p);
 487                default:
 488                        return -EINVAL;
 489                }
 490
 491        case SOUND_PCM_READ_BITS:
 492                switch (dev->dmasound.afmt) {
 493                case AFMT_U8:
 494                case AFMT_S8:
 495                        return put_user(8, p);
 496                case AFMT_U16_LE:
 497                case AFMT_U16_BE:
 498                case AFMT_S16_LE:
 499                case AFMT_S16_BE:
 500                        return put_user(16, p);
 501                default:
 502                        return -EINVAL;
 503                }
 504
 505        case SNDCTL_DSP_NONBLOCK:
 506                file->f_flags |= O_NONBLOCK;
 507                return 0;
 508
 509        case SNDCTL_DSP_RESET:
 510                mutex_lock(&dev->dmasound.lock);
 511                if (dev->dmasound.recording_on)
 512                        dsp_rec_stop(dev);
 513                mutex_unlock(&dev->dmasound.lock);
 514                return 0;
 515        case SNDCTL_DSP_GETBLKSIZE:
 516                return put_user(dev->dmasound.blksize, p);
 517
 518        case SNDCTL_DSP_SETFRAGMENT:
 519                if (get_user(val, p))
 520                        return -EFAULT;
 521                if (dev->dmasound.recording_on)
 522                        return -EBUSY;
 523                dsp_buffer_free(dev);
 524                /* used to be arg >> 16 instead of val >> 16; fixed */
 525                dsp_buffer_conf(dev,1 << (val & 0xffff), (val >> 16) & 0xffff);
 526                dsp_buffer_init(dev);
 527                return 0;
 528
 529        case SNDCTL_DSP_SYNC:
 530                /* NOP */
 531                return 0;
 532
 533        case SNDCTL_DSP_GETISPACE:
 534        {
 535                audio_buf_info info;
 536                info.fragsize   = dev->dmasound.blksize;
 537                info.fragstotal = dev->dmasound.blocks;
 538                info.bytes      = dev->dmasound.read_count;
 539                info.fragments  = info.bytes / info.fragsize;
 540                if (copy_to_user(argp, &info, sizeof(info)))
 541                        return -EFAULT;
 542                return 0;
 543        }
 544        default:
 545                return -EINVAL;
 546        }
 547}
 548
 549static unsigned int dsp_poll(struct file *file, struct poll_table_struct *wait)
 550{
 551        struct saa7134_dev *dev = file->private_data;
 552        unsigned int mask = 0;
 553
 554        poll_wait(file, &dev->dmasound.wq, wait);
 555
 556        if (0 == dev->dmasound.read_count) {
 557                mutex_lock(&dev->dmasound.lock);
 558                if (!dev->dmasound.recording_on)
 559                        dsp_rec_start(dev);
 560                mutex_unlock(&dev->dmasound.lock);
 561        } else
 562                mask |= (POLLIN | POLLRDNORM);
 563        return mask;
 564}
 565
 566struct file_operations saa7134_dsp_fops = {
 567        .owner   = THIS_MODULE,
 568        .open    = dsp_open,
 569        .release = dsp_release,
 570        .read    = dsp_read,
 571        .write   = dsp_write,
 572        .ioctl   = dsp_ioctl,
 573        .poll    = dsp_poll,
 574        .llseek  = no_llseek,
 575};
 576
 577/* ------------------------------------------------------------------ */
 578
 579static int
 580mixer_recsrc_7134(struct saa7134_dev *dev)
 581{
 582        int analog_io,rate;
 583
 584        switch (dev->dmasound.input) {
 585        case TV:
 586                saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0);
 587                saa_andorb(SAA7134_SIF_SAMPLE_FREQ,   0x03, 0x00);
 588                break;
 589        case LINE1:
 590        case LINE2:
 591        case LINE2_LEFT:
 592                analog_io = (LINE1 == dev->dmasound.input) ? 0x00 : 0x08;
 593                rate = (32000 == dev->dmasound.rate) ? 0x01 : 0x03;
 594                saa_andorb(SAA7134_ANALOG_IO_SELECT,  0x08, analog_io);
 595                saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0x80);
 596                saa_andorb(SAA7134_SIF_SAMPLE_FREQ,   0x03, rate);
 597                break;
 598        }
 599        return 0;
 600}
 601
 602static int
 603mixer_recsrc_7133(struct saa7134_dev *dev)
 604{
 605        u32 anabar, xbarin;
 606
 607        xbarin = 0x03; // adc
 608    anabar = 0;
 609        switch (dev->dmasound.input) {
 610        case TV:
 611                xbarin = 0; // Demodulator
 612        anabar = 2; // DACs
 613                break;
 614        case LINE1:
 615                anabar = 0;  // aux1, aux1
 616                break;
 617        case LINE2:
 618        case LINE2_LEFT:
 619                anabar = 9;  // aux2, aux2
 620                break;
 621        }
 622    /* output xbar always main channel */
 623        saa_dsp_writel(dev, 0x46c >> 2, 0xbbbb10);
 624        saa_dsp_writel(dev, 0x464 >> 2, xbarin);
 625        saa_writel(0x594 >> 2, anabar);
 626
 627        return 0;
 628}
 629
 630static int
 631mixer_recsrc(struct saa7134_dev *dev, enum saa7134_audio_in src)
 632{
 633        static const char *iname[] = { "Oops", "TV", "LINE1", "LINE2" };
 634
 635        dev->dmasound.count++;
 636        dev->dmasound.input = src;
 637        dprintk("mixer input = %s\n",iname[dev->dmasound.input]);
 638
 639        switch (dev->pci->device) {
 640        case PCI_DEVICE_ID_PHILIPS_SAA7134:
 641                mixer_recsrc_7134(dev);
 642                break;
 643        case PCI_DEVICE_ID_PHILIPS_SAA7133:
 644        case PCI_DEVICE_ID_PHILIPS_SAA7135:
 645                mixer_recsrc_7133(dev);
 646                break;
 647        }
 648        return 0;
 649}
 650
 651static int
 652mixer_level(struct saa7134_dev *dev, enum saa7134_audio_in src, int level)
 653{
 654        switch (dev->pci->device) {
 655        case PCI_DEVICE_ID_PHILIPS_SAA7134:
 656                switch (src) {
 657                case TV:
 658                        /* nothing */
 659                        break;
 660                case LINE1:
 661                        saa_andorb(SAA7134_ANALOG_IO_SELECT,  0x10,
 662                                   (100 == level) ? 0x00 : 0x10);
 663                        break;
 664                case LINE2:
 665                case LINE2_LEFT:
 666                        saa_andorb(SAA7134_ANALOG_IO_SELECT,  0x20,
 667                                   (100 == level) ? 0x00 : 0x20);
 668                        break;
 669                }
 670                break;
 671        case PCI_DEVICE_ID_PHILIPS_SAA7133:
 672        case PCI_DEVICE_ID_PHILIPS_SAA7135:
 673                /* nothing */
 674                break;
 675        }
 676        return 0;
 677}
 678
 679/* ------------------------------------------------------------------ */
 680
 681static int mixer_open(struct inode *inode, struct file *file)
 682{
 683        int minor = iminor(inode);
 684        struct saa7134_dev *h,*dev = NULL;
 685        struct list_head *list;
 686
 687        list_for_each(list,&saa7134_devlist) {
 688                h = list_entry(list, struct saa7134_dev, devlist);
 689                if (h->dmasound.minor_mixer == minor)
 690                        dev = h;
 691        }
 692        if (NULL == dev)
 693                return -ENODEV;
 694
 695        file->private_data = dev;
 696        return 0;
 697}
 698
 699static int mixer_release(struct inode *inode, struct file *file)
 700{
 701        file->private_data = NULL;
 702        return 0;
 703}
 704
 705static int mixer_ioctl(struct inode *inode, struct file *file,
 706                     unsigned int cmd, unsigned long arg)
 707{
 708        struct saa7134_dev *dev = file->private_data;
 709        enum saa7134_audio_in input;
 710        int val,ret;
 711        void __user *argp = (void __user *) arg;
 712        int __user *p = argp;
 713
 714        if (debug > 1)
 715                saa7134_oss_print_ioctl(dev->name,cmd);
 716        switch (cmd) {
 717        case OSS_GETVERSION:
 718                return put_user(SOUND_VERSION, p);
 719        case SOUND_MIXER_INFO:
 720        {
 721                mixer_info info;
 722                memset(&info,0,sizeof(info));
 723                strlcpy(info.id,   "TV audio", sizeof(info.id));
 724                strlcpy(info.name, dev->name,  sizeof(info.name));
 725                info.modify_counter = dev->dmasound.count;
 726                if (copy_to_user(argp, &info, sizeof(info)))
 727                        return -EFAULT;
 728                return 0;
 729        }
 730        case SOUND_OLD_MIXER_INFO:
 731        {
 732                _old_mixer_info info;
 733                memset(&info,0,sizeof(info));
 734                strlcpy(info.id,   "TV audio", sizeof(info.id));
 735                strlcpy(info.name, dev->name,  sizeof(info.name));
 736                if (copy_to_user(argp, &info, sizeof(info)))
 737                        return -EFAULT;
 738                return 0;
 739        }
 740        case MIXER_READ(SOUND_MIXER_CAPS):
 741                return put_user(SOUND_CAP_EXCL_INPUT, p);
 742        case MIXER_READ(SOUND_MIXER_STEREODEVS):
 743                return put_user(0, p);
 744        case MIXER_READ(SOUND_MIXER_RECMASK):
 745        case MIXER_READ(SOUND_MIXER_DEVMASK):
 746                val = SOUND_MASK_LINE1 | SOUND_MASK_LINE2;
 747                if (32000 == dev->dmasound.rate)
 748                        val |= SOUND_MASK_VIDEO;
 749                return put_user(val, p);
 750
 751        case MIXER_WRITE(SOUND_MIXER_RECSRC):
 752                if (get_user(val, p))
 753                        return -EFAULT;
 754                input = dev->dmasound.input;
 755                if (32000 == dev->dmasound.rate  &&
 756                    val & SOUND_MASK_VIDEO  &&  dev->dmasound.input != TV)
 757                        input = TV;
 758                if (val & SOUND_MASK_LINE1  &&  dev->dmasound.input != LINE1)
 759                        input = LINE1;
 760                if (val & SOUND_MASK_LINE2  &&  dev->dmasound.input != LINE2)
 761                        input = LINE2;
 762                if (input != dev->dmasound.input)
 763                        mixer_recsrc(dev,input);
 764                /* fall throuth */
 765        case MIXER_READ(SOUND_MIXER_RECSRC):
 766                switch (dev->dmasound.input) {
 767                case TV:    ret = SOUND_MASK_VIDEO; break;
 768                case LINE1: ret = SOUND_MASK_LINE1; break;
 769                case LINE2: ret = SOUND_MASK_LINE2; break;
 770                default:    ret = 0;
 771                }
 772                return put_user(ret, p);
 773
 774        case MIXER_WRITE(SOUND_MIXER_VIDEO):
 775        case MIXER_READ(SOUND_MIXER_VIDEO):
 776                if (32000 != dev->dmasound.rate)
 777                        return -EINVAL;
 778                return put_user(100 | 100 << 8, p);
 779
 780        case MIXER_WRITE(SOUND_MIXER_LINE1):
 781                if (get_user(val, p))
 782                        return -EFAULT;
 783                val &= 0xff;
 784                val = (val <= 50) ? 50 : 100;
 785                dev->dmasound.line1 = val;
 786                mixer_level(dev,LINE1,dev->dmasound.line1);
 787                /* fall throuth */
 788        case MIXER_READ(SOUND_MIXER_LINE1):
 789                return put_user(dev->dmasound.line1 | dev->dmasound.line1 << 8, p);
 790
 791        case MIXER_WRITE(SOUND_MIXER_LINE2):
 792                if (get_user(val, p))
 793                        return -EFAULT;
 794                val &= 0xff;
 795                val = (val <= 50) ? 50 : 100;
 796                dev->dmasound.line2 = val;
 797                mixer_level(dev,LINE2,dev->dmasound.line2);
 798                /* fall throuth */
 799        case MIXER_READ(SOUND_MIXER_LINE2):
 800                return put_user(dev->dmasound.line2 | dev->dmasound.line2 << 8, p);
 801
 802        default:
 803                return -EINVAL;
 804        }
 805}
 806
 807struct file_operations saa7134_mixer_fops = {
 808        .owner   = THIS_MODULE,
 809        .open    = mixer_open,
 810        .release = mixer_release,
 811        .ioctl   = mixer_ioctl,
 812        .llseek  = no_llseek,
 813};
 814
 815/* ------------------------------------------------------------------ */
 816
 817static irqreturn_t saa7134_oss_irq(int irq, void *dev_id)
 818{
 819        struct saa7134_dmasound *dmasound = dev_id;
 820        struct saa7134_dev *dev = dmasound->priv_data;
 821        unsigned long report, status;
 822        int loop, handled = 0;
 823
 824        for (loop = 0; loop < 10; loop++) {
 825                report = saa_readl(SAA7134_IRQ_REPORT);
 826                status = saa_readl(SAA7134_IRQ_STATUS);
 827
 828                if (report & SAA7134_IRQ_REPORT_DONE_RA3) {
 829                        handled = 1;
 830                        saa_writel(SAA7134_IRQ_REPORT,report);
 831                        saa7134_irq_oss_done(dev, status);
 832                } else {
 833                        goto out;
 834                }
 835        }
 836
 837        if (loop == 10) {
 838                dprintk("error! looping IRQ!");
 839        }
 840out:
 841        return IRQ_RETVAL(handled);
 842}
 843
 844int saa7134_oss_init1(struct saa7134_dev *dev)
 845{
 846
 847        if ((request_irq(dev->pci->irq, saa7134_oss_irq,
 848                         IRQF_SHARED | IRQF_DISABLED, dev->name,
 849                        (void*) &dev->dmasound)) < 0)
 850                return -1;
 851
 852        /* general */
 853        mutex_init(&dev->dmasound.lock);
 854        init_waitqueue_head(&dev->dmasound.wq);
 855
 856        switch (dev->pci->device) {
 857        case PCI_DEVICE_ID_PHILIPS_SAA7133:
 858        case PCI_DEVICE_ID_PHILIPS_SAA7135:
 859                saa_writel(0x588 >> 2, 0x00000fff);
 860                saa_writel(0x58c >> 2, 0x00543210);
 861                saa_dsp_writel(dev, 0x46c >> 2, 0xbbbbbb);
 862                break;
 863        }
 864
 865        /* dsp */
 866        dev->dmasound.rate = 32000;
 867        if (rate)
 868                dev->dmasound.rate = rate;
 869        dev->dmasound.rate = (dev->dmasound.rate > 40000) ? 48000 : 32000;
 870
 871        /* mixer */
 872        dev->dmasound.line1 = 50;
 873        dev->dmasound.line2 = 50;
 874        mixer_level(dev,LINE1,dev->dmasound.line1);
 875        mixer_level(dev,LINE2,dev->dmasound.line2);
 876        mixer_recsrc(dev, (dev->dmasound.rate == 32000) ? TV : LINE2);
 877
 878        return 0;
 879}
 880
 881int saa7134_oss_fini(struct saa7134_dev *dev)
 882{
 883        /* nothing */
 884        return 0;
 885}
 886
 887void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status)
 888{
 889        int next_blk, reg = 0;
 890
 891        spin_lock(&dev->slock);
 892        if (UNSET == dev->dmasound.dma_blk) {
 893                dprintk("irq: recording stopped\n");
 894                goto done;
 895        }
 896        if (0 != (status & 0x0f000000))
 897                dprintk("irq: lost %ld\n", (status >> 24) & 0x0f);
 898        if (0 == (status & 0x10000000)) {
 899                /* odd */
 900                if (0 == (dev->dmasound.dma_blk & 0x01))
 901                        reg = SAA7134_RS_BA1(6);
 902        } else {
 903                /* even */
 904                if (1 == (dev->dmasound.dma_blk & 0x01))
 905                        reg = SAA7134_RS_BA2(6);
 906        }
 907        if (0 == reg) {
 908                dprintk("irq: field oops [%s]\n",
 909                        (status & 0x10000000) ? "even" : "odd");
 910                goto done;
 911        }
 912        if (dev->dmasound.read_count >= dev->dmasound.blksize * (dev->dmasound.blocks-2)) {
 913                dprintk("irq: overrun [full=%d/%d]\n",dev->dmasound.read_count,
 914                        dev->dmasound.bufsize);
 915                dsp_dma_stop(dev);
 916                goto done;
 917        }
 918
 919        /* next block addr */
 920        next_blk = (dev->dmasound.dma_blk + 2) % dev->dmasound.blocks;
 921        saa_writel(reg,next_blk * dev->dmasound.blksize);
 922        if (debug > 2)
 923                dprintk("irq: ok, %s, next_blk=%d, addr=%x\n",
 924                        (status & 0x10000000) ? "even" : "odd ", next_blk,
 925                        next_blk * dev->dmasound.blksize);
 926
 927        /* update status & wake waiting readers */
 928        dev->dmasound.dma_blk = (dev->dmasound.dma_blk + 1) % dev->dmasound.blocks;
 929        dev->dmasound.read_count += dev->dmasound.blksize;
 930        wake_up(&dev->dmasound.wq);
 931
 932 done:
 933        spin_unlock(&dev->slock);
 934}
 935
 936static int saa7134_dsp_create(struct saa7134_dev *dev)
 937{
 938        int err;
 939
 940        err = dev->dmasound.minor_dsp =
 941                register_sound_dsp(&saa7134_dsp_fops,
 942                                   dsp_nr[dev->nr]);
 943        if (err < 0) {
 944                goto fail;
 945        }
 946        printk(KERN_INFO "%s: registered device dsp%d\n",
 947               dev->name,dev->dmasound.minor_dsp >> 4);
 948
 949        err = dev->dmasound.minor_mixer =
 950                register_sound_mixer(&saa7134_mixer_fops,
 951                                     mixer_nr[dev->nr]);
 952        if (err < 0)
 953                goto fail;
 954        printk(KERN_INFO "%s: registered device mixer%d\n",
 955               dev->name,dev->dmasound.minor_mixer >> 4);
 956
 957        return 0;
 958
 959fail:
 960        unregister_sound_dsp(dev->dmasound.minor_dsp);
 961        return 0;
 962
 963
 964}
 965
 966static int oss_device_init(struct saa7134_dev *dev)
 967{
 968        dev->dmasound.priv_data = dev;
 969        saa7134_oss_init1(dev);
 970        saa7134_dsp_create(dev);
 971        return 1;
 972}
 973
 974static int oss_device_exit(struct saa7134_dev *dev)
 975{
 976
 977        unregister_sound_mixer(dev->dmasound.minor_mixer);
 978        unregister_sound_dsp(dev->dmasound.minor_dsp);
 979
 980        saa7134_oss_fini(dev);
 981
 982        if (dev->pci->irq > 0) {
 983                synchronize_irq(dev->pci->irq);
 984                free_irq(dev->pci->irq,&dev->dmasound);
 985        }
 986
 987        dev->dmasound.priv_data = NULL;
 988        return 1;
 989}
 990
 991static int saa7134_oss_init(void)
 992{
 993        struct saa7134_dev *dev = NULL;
 994        struct list_head *list;
 995
 996        if (!saa7134_dmasound_init && !saa7134_dmasound_exit) {
 997                saa7134_dmasound_init = oss_device_init;
 998                saa7134_dmasound_exit = oss_device_exit;
 999        } else {
1000                printk(KERN_WARNING "saa7134 OSS: can't load, DMA sound handler already assigned (probably to ALSA)\n");
1001                return -EBUSY;
1002        }
1003
1004        printk(KERN_INFO "saa7134 OSS driver for DMA sound loaded\n");
1005
1006
1007        list_for_each(list,&saa7134_devlist) {
1008                dev = list_entry(list, struct saa7134_dev, devlist);
1009                if (dev->dmasound.priv_data == NULL) {
1010                        oss_device_init(dev);
1011                } else {
1012                        printk(KERN_ERR "saa7134 OSS: DMA sound is being handled by ALSA, ignoring %s\n",dev->name);
1013                        return -EBUSY;
1014                }
1015        }
1016
1017        if (dev == NULL)
1018                printk(KERN_INFO "saa7134 OSS: no saa7134 cards found\n");
1019
1020        return 0;
1021
1022}
1023
1024static void saa7134_oss_exit(void)
1025{
1026        struct saa7134_dev *dev = NULL;
1027        struct list_head *list;
1028
1029        list_for_each(list,&saa7134_devlist) {
1030                dev = list_entry(list, struct saa7134_dev, devlist);
1031
1032                /* Device isn't registered by OSS, probably ALSA's */
1033                if (!dev->dmasound.minor_dsp)
1034                        continue;
1035
1036                oss_device_exit(dev);
1037
1038        }
1039
1040        saa7134_dmasound_init = NULL;
1041        saa7134_dmasound_exit = NULL;
1042
1043        printk(KERN_INFO "saa7134 OSS driver for DMA sound unloaded\n");
1044
1045        return;
1046}
1047
1048/* We initialize this late, to make sure the sound system is up and running */
1049late_initcall(saa7134_oss_init);
1050module_exit(saa7134_oss_exit);
1051MODULE_LICENSE("GPL");
1052MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
1053
1054/* ----------------------------------------------------------- */
1055/*
1056 * Local variables:
1057 * c-basic-offset: 8
1058 * End:
1059 */
1060
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.