linux/sound/oss/kahlua.c
<<
>>
Prefs
   1/*
   2 *      Initialisation code for Cyrix/NatSemi VSA1 softaudio
   3 *
   4 *      (C) Copyright 2003 Red Hat Inc <alan@lxorguk.ukuu.org.uk>
   5 *
   6 * XpressAudio(tm) is used on the Cyrix MediaGX (now NatSemi Geode) systems.
   7 * The older version (VSA1) provides fairly good soundblaster emulation
   8 * although there are a couple of bugs: large DMA buffers break record,
   9 * and the MPU event handling seems suspect. VSA2 allows the native driver
  10 * to control the AC97 audio engine directly and requires a different driver.
  11 *
  12 * Thanks to National Semiconductor for providing the needed information
  13 * on the XpressAudio(tm) internals.
  14 *
  15 * This program is free software; you can redistribute it and/or modify it
  16 * under the terms of the GNU General Public License as published by the
  17 * Free Software Foundation; either version 2, or (at your option) any
  18 * later version.
  19 *
  20 * This program is distributed in the hope that it will be useful, but
  21 * WITHOUT ANY WARRANTY; without even the implied warranty of
  22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  23 * General Public License for more details.
  24 *
  25 * TO DO:
  26 *      Investigate whether we can portably support Cognac (5520) in the
  27 *      same manner.
  28 */
  29
  30#include <linux/delay.h>
  31#include <linux/init.h>
  32#include <linux/module.h>
  33#include <linux/pci.h>
  34#include <linux/slab.h>
  35
  36#include "sound_config.h"
  37
  38#include "sb.h"
  39
  40/*
  41 *      Read a soundblaster compatible mixer register.
  42 *      In this case we are actually reading an SMI trap
  43 *      not real hardware.
  44 */
  45
  46static u8 mixer_read(unsigned long io, u8 reg)
  47{
  48        outb(reg, io + 4);
  49        udelay(20);
  50        reg = inb(io + 5);
  51        udelay(20);
  52        return reg;
  53}
  54
  55static int probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
  56{
  57        struct address_info *hw_config;
  58        unsigned long base;
  59        void __iomem *mem;
  60        unsigned long io;
  61        u16 map;
  62        u8 irq, dma8, dma16;
  63        int oldquiet;
  64        extern int sb_be_quiet;
  65                
  66        base = pci_resource_start(pdev, 0);
  67        if(base == 0UL)
  68                return 1;
  69        
  70        mem = ioremap(base, 128);
  71        if (!mem)
  72                return 1;
  73        map = readw(mem + 0x18);        /* Read the SMI enables */
  74        iounmap(mem);
  75        
  76        /* Map bits
  77                0:1     * 0x20 + 0x200 = sb base
  78                2       sb enable
  79                3       adlib enable
  80                5       MPU enable 0x330
  81                6       MPU enable 0x300
  82                
  83           The other bits may be used internally so must be masked */
  84
  85        io = 0x220 + 0x20 * (map & 3);     
  86        
  87        if(map & (1<<2))
  88                printk(KERN_INFO "kahlua: XpressAudio at 0x%lx\n", io);
  89        else
  90                return 1;
  91                
  92        if(map & (1<<5))
  93                printk(KERN_INFO "kahlua: MPU at 0x300\n");
  94        else if(map & (1<<6))
  95                printk(KERN_INFO "kahlua: MPU at 0x330\n");
  96        
  97        irq = mixer_read(io, 0x80) & 0x0F;
  98        dma8 = mixer_read(io, 0x81);
  99
 100        // printk("IRQ=%x MAP=%x DMA=%x\n", irq, map, dma8);
 101        
 102        if(dma8 & 0x20)
 103                dma16 = 5;
 104        else if(dma8 & 0x40)
 105                dma16 = 6;
 106        else if(dma8 & 0x80)
 107                dma16 = 7;
 108        else
 109        {
 110                printk(KERN_ERR "kahlua: No 16bit DMA enabled.\n");
 111                return 1;
 112        }
 113                
 114        if(dma8 & 0x01)
 115                dma8 = 0;
 116        else if(dma8 & 0x02)
 117                dma8 = 1;
 118        else if(dma8 & 0x08)
 119                dma8 = 3;
 120        else
 121        {
 122                printk(KERN_ERR "kahlua: No 8bit DMA enabled.\n");
 123                return 1;
 124        }
 125        
 126        if(irq & 1)
 127                irq = 9;
 128        else if(irq & 2)
 129                irq = 5;
 130        else if(irq & 4)
 131                irq = 7;
 132        else if(irq & 8)
 133                irq = 10;
 134        else
 135        {
 136                printk(KERN_ERR "kahlua: SB IRQ not set.\n");
 137                return 1;
 138        }
 139        
 140        printk(KERN_INFO "kahlua: XpressAudio on IRQ %d, DMA %d, %d\n",
 141                irq, dma8, dma16);
 142        
 143        hw_config = kzalloc(sizeof(struct address_info), GFP_KERNEL);
 144        if(hw_config == NULL)
 145        {
 146                printk(KERN_ERR "kahlua: out of memory.\n");
 147                return 1;
 148        }
 149        
 150        pci_set_drvdata(pdev, hw_config);
 151        
 152        hw_config->io_base = io;
 153        hw_config->irq = irq;
 154        hw_config->dma = dma8;
 155        hw_config->dma2 = dma16;
 156        hw_config->name = "Cyrix XpressAudio";
 157        hw_config->driver_use_1 = SB_NO_MIDI | SB_PCI_IRQ;
 158
 159        if (!request_region(io, 16, "soundblaster"))
 160                goto err_out_free;
 161        
 162        if(sb_dsp_detect(hw_config, 0, 0, NULL)==0)
 163        {
 164                printk(KERN_ERR "kahlua: audio not responding.\n");
 165                release_region(io, 16);
 166                goto err_out_free;
 167        }
 168
 169        oldquiet = sb_be_quiet; 
 170        sb_be_quiet = 1;
 171        if(sb_dsp_init(hw_config, THIS_MODULE))
 172        {
 173                sb_be_quiet = oldquiet;
 174                goto err_out_free;
 175        }
 176        sb_be_quiet = oldquiet;
 177        
 178        return 0;
 179
 180err_out_free:
 181        kfree(hw_config);
 182        return 1;
 183}
 184
 185static void remove_one(struct pci_dev *pdev)
 186{
 187        struct address_info *hw_config = pci_get_drvdata(pdev);
 188        sb_dsp_unload(hw_config, 0);
 189        kfree(hw_config);
 190}
 191
 192MODULE_AUTHOR("Alan Cox");
 193MODULE_DESCRIPTION("Kahlua VSA1 PCI Audio");
 194MODULE_LICENSE("GPL");
 195
 196/*
 197 *      5530 only. The 5510/5520 decode is different.
 198 */
 199
 200static DEFINE_PCI_DEVICE_TABLE(id_tbl) = {
 201        { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_AUDIO), 0 },
 202        { }
 203};
 204
 205MODULE_DEVICE_TABLE(pci, id_tbl);
 206
 207static struct pci_driver kahlua_driver = {
 208        .name           = "kahlua",
 209        .id_table       = id_tbl,
 210        .probe          = probe_one,
 211        .remove         = remove_one,
 212};
 213
 214
 215static int __init kahlua_init_module(void)
 216{
 217        printk(KERN_INFO "Cyrix Kahlua VSA1 XpressAudio support (c) Copyright 2003 Red Hat Inc\n");
 218        return pci_register_driver(&kahlua_driver);
 219}
 220
 221static void kahlua_cleanup_module(void)
 222{
 223        pci_unregister_driver(&kahlua_driver);
 224}
 225
 226
 227module_init(kahlua_init_module);
 228module_exit(kahlua_cleanup_module);
 229
 230
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.