linux/sound/mips/au1x00.c
<<
>>
Prefs
   1/*
   2 * BRIEF MODULE DESCRIPTION
   3 *  Driver for AMD Au1000 MIPS Processor, AC'97 Sound Port
   4 *
   5 * Copyright 2004 Cooper Street Innovations Inc.
   6 * Author: Charles Eidsness     <charles@cooper-street.com>
   7 *
   8 *  This program is free software; you can redistribute  it and/or modify it
   9 *  under  the terms of  the GNU General  Public License as published by the
  10 *  Free Software Foundation;  either version 2 of the  License, or (at your
  11 *  option) any later version.
  12 *
  13 *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
  14 *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
  15 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
  16 *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
  17 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  18 *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
  19 *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  20 *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
  21 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  22 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23 *
  24 *  You should have received a copy of the  GNU General Public License along
  25 *  with this program; if not, write  to the Free Software Foundation, Inc.,
  26 *  675 Mass Ave, Cambridge, MA 02139, USA.
  27 *
  28 * History:
  29 *
  30 * 2004-09-09 Charles Eidsness  -- Original verion -- based on
  31 *                                sa11xx-uda1341.c ALSA driver and the
  32 *                                au1000.c OSS driver.
  33 * 2004-09-09 Matt Porter       -- Added support for ALSA 1.0.6
  34 *
  35 */
  36
  37#include <linux/ioport.h>
  38#include <linux/interrupt.h>
  39#include <linux/init.h>
  40#include <linux/slab.h>
  41#include <linux/version.h>
  42#include <sound/core.h>
  43#include <sound/initval.h>
  44#include <sound/pcm.h>
  45#include <sound/pcm_params.h>
  46#include <sound/ac97_codec.h>
  47#include <asm/mach-au1x00/au1000.h>
  48#include <asm/mach-au1x00/au1000_dma.h>
  49
  50MODULE_AUTHOR("Charles Eidsness <charles@cooper-street.com>");
  51MODULE_DESCRIPTION("Au1000 AC'97 ALSA Driver");
  52MODULE_LICENSE("GPL");
  53MODULE_SUPPORTED_DEVICE("{{AMD,Au1000 AC'97}}");
  54
  55#define PLAYBACK 0
  56#define CAPTURE 1
  57#define AC97_SLOT_3 0x01
  58#define AC97_SLOT_4 0x02
  59#define AC97_SLOT_6 0x08
  60#define AC97_CMD_IRQ 31
  61#define READ 0
  62#define WRITE 1
  63#define READ_WAIT 2
  64#define RW_DONE 3
  65
  66struct au1000_period
  67{
  68        u32 start;
  69        u32 relative_end;       /*realtive to start of buffer*/
  70        struct au1000_period * next;
  71};
  72
  73/*Au1000 AC97 Port Control Reisters*/
  74struct au1000_ac97_reg {
  75        u32 volatile config;
  76        u32 volatile status;
  77        u32 volatile data;
  78        u32 volatile cmd;
  79        u32 volatile cntrl;
  80};
  81
  82struct audio_stream {
  83        struct snd_pcm_substream *substream;
  84        int dma;
  85        spinlock_t dma_lock;
  86        struct au1000_period * buffer;
  87        unsigned int period_size;
  88        unsigned int periods;
  89};
  90
  91struct snd_au1000 {
  92        struct snd_card *card;
  93        struct au1000_ac97_reg volatile *ac97_ioport;
  94
  95        struct resource *ac97_res_port;
  96        spinlock_t ac97_lock;
  97        struct snd_ac97 *ac97;
  98
  99        struct snd_pcm *pcm;
 100        struct audio_stream *stream[2]; /* playback & capture */
 101};
 102
 103/*--------------------------- Local Functions --------------------------------*/
 104static void
 105au1000_set_ac97_xmit_slots(struct snd_au1000 *au1000, long xmit_slots)
 106{
 107        u32 volatile ac97_config;
 108
 109        spin_lock(&au1000->ac97_lock);
 110        ac97_config = au1000->ac97_ioport->config;
 111        ac97_config = ac97_config & ~AC97C_XMIT_SLOTS_MASK;
 112        ac97_config |= (xmit_slots << AC97C_XMIT_SLOTS_BIT);
 113        au1000->ac97_ioport->config = ac97_config;
 114        spin_unlock(&au1000->ac97_lock);
 115}
 116
 117static void
 118au1000_set_ac97_recv_slots(struct snd_au1000 *au1000, long recv_slots)
 119{
 120        u32 volatile ac97_config;
 121
 122        spin_lock(&au1000->ac97_lock);
 123        ac97_config = au1000->ac97_ioport->config;
 124        ac97_config = ac97_config & ~AC97C_RECV_SLOTS_MASK;
 125        ac97_config |= (recv_slots << AC97C_RECV_SLOTS_BIT);
 126        au1000->ac97_ioport->config = ac97_config;
 127        spin_unlock(&au1000->ac97_lock);
 128}
 129
 130
 131static void
 132au1000_release_dma_link(struct audio_stream *stream)
 133{
 134        struct au1000_period * pointer;
 135        struct au1000_period * pointer_next;
 136
 137        stream->period_size = 0;
 138        stream->periods = 0;
 139        pointer = stream->buffer;
 140        if (! pointer)
 141                return;
 142        do {
 143                pointer_next = pointer->next;
 144                kfree(pointer);
 145                pointer = pointer_next;
 146        } while (pointer != stream->buffer);
 147        stream->buffer = NULL;
 148}
 149
 150static int
 151au1000_setup_dma_link(struct audio_stream *stream, unsigned int period_bytes,
 152                      unsigned int periods)
 153{
 154        struct snd_pcm_substream *substream = stream->substream;
 155        struct snd_pcm_runtime *runtime = substream->runtime;
 156        struct au1000_period *pointer;
 157        unsigned long dma_start;
 158        int i;
 159
 160        dma_start = virt_to_phys(runtime->dma_area);
 161
 162        if (stream->period_size == period_bytes &&
 163            stream->periods == periods)
 164                return 0; /* not changed */
 165
 166        au1000_release_dma_link(stream);
 167
 168        stream->period_size = period_bytes;
 169        stream->periods = periods;
 170
 171        stream->buffer = kmalloc(sizeof(struct au1000_period), GFP_KERNEL);
 172        if (! stream->buffer)
 173                return -ENOMEM;
 174        pointer = stream->buffer;
 175        for (i = 0; i < periods; i++) {
 176                pointer->start = (u32)(dma_start + (i * period_bytes));
 177                pointer->relative_end = (u32) (((i+1) * period_bytes) - 0x1);
 178                if (i < periods - 1) {
 179                        pointer->next = kmalloc(sizeof(struct au1000_period), GFP_KERNEL);
 180                        if (! pointer->next) {
 181                                au1000_release_dma_link(stream);
 182                                return -ENOMEM;
 183                        }
 184                        pointer = pointer->next;
 185                }
 186        }
 187        pointer->next = stream->buffer;
 188        return 0;
 189}
 190
 191static void
 192au1000_dma_stop(struct audio_stream *stream)
 193{
 194        snd_assert(stream->buffer, return);
 195        disable_dma(stream->dma);
 196}
 197
 198static void
 199au1000_dma_start(struct audio_stream *stream)
 200{
 201        snd_assert(stream->buffer, return);
 202
 203        init_dma(stream->dma);
 204        if (get_dma_active_buffer(stream->dma) == 0) {
 205                clear_dma_done0(stream->dma);
 206                set_dma_addr0(stream->dma, stream->buffer->start);
 207                set_dma_count0(stream->dma, stream->period_size >> 1);
 208                set_dma_addr1(stream->dma, stream->buffer->next->start);
 209                set_dma_count1(stream->dma, stream->period_size >> 1);
 210        } else {
 211                clear_dma_done1(stream->dma);
 212                set_dma_addr1(stream->dma, stream->buffer->start);
 213                set_dma_count1(stream->dma, stream->period_size >> 1);
 214                set_dma_addr0(stream->dma, stream->buffer->next->start);
 215                set_dma_count0(stream->dma, stream->period_size >> 1);
 216        }
 217        enable_dma_buffers(stream->dma);
 218        start_dma(stream->dma);
 219}
 220
 221static irqreturn_t
 222au1000_dma_interrupt(int irq, void *dev_id)
 223{
 224        struct audio_stream *stream = (struct audio_stream *) dev_id;
 225        struct snd_pcm_substream *substream = stream->substream;
 226
 227        spin_lock(&stream->dma_lock);
 228        switch (get_dma_buffer_done(stream->dma)) {
 229        case DMA_D0:
 230                stream->buffer = stream->buffer->next;
 231                clear_dma_done0(stream->dma);
 232                set_dma_addr0(stream->dma, stream->buffer->next->start);
 233                set_dma_count0(stream->dma, stream->period_size >> 1);
 234                enable_dma_buffer0(stream->dma);
 235                break;
 236        case DMA_D1:
 237                stream->buffer = stream->buffer->next;
 238                clear_dma_done1(stream->dma);
 239                set_dma_addr1(stream->dma, stream->buffer->next->start);
 240                set_dma_count1(stream->dma, stream->period_size >> 1);
 241                enable_dma_buffer1(stream->dma);
 242                break;
 243        case (DMA_D0 | DMA_D1):
 244                printk(KERN_ERR "DMA %d missed interrupt.\n",stream->dma);
 245                au1000_dma_stop(stream);
 246                au1000_dma_start(stream);
 247                break;
 248        case (~DMA_D0 & ~DMA_D1):
 249                printk(KERN_ERR "DMA %d empty irq.\n",stream->dma);
 250        }
 251        spin_unlock(&stream->dma_lock);
 252        snd_pcm_period_elapsed(substream);
 253        return IRQ_HANDLED;
 254}
 255
 256/*-------------------------- PCM Audio Streams -------------------------------*/
 257
 258static unsigned int rates[] = {8000, 11025, 16000, 22050};
 259static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
 260        .count  = ARRAY_SIZE(rates),
 261        .list   = rates,
 262        .mask   = 0,
 263};
 264
 265static struct snd_pcm_hardware snd_au1000_hw =
 266{
 267        .info                   = (SNDRV_PCM_INFO_INTERLEAVED | \
 268                                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
 269        .formats                = SNDRV_PCM_FMTBIT_S16_LE,
 270        .rates                  = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
 271                                SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050),
 272        .rate_min               = 8000,
 273        .rate_max               = 22050,
 274        .channels_min           = 1,
 275        .channels_max           = 2,
 276        .buffer_bytes_max       = 128*1024,
 277        .period_bytes_min       = 32,
 278        .period_bytes_max       = 16*1024,
 279        .periods_min            = 8,
 280        .periods_max            = 255,
 281        .fifo_size              = 16,
 282};
 283
 284static int
 285snd_au1000_playback_open(struct snd_pcm_substream *substream)
 286{
 287        struct snd_au1000 *au1000 = substream->pcm->private_data;
 288
 289        au1000->stream[PLAYBACK]->substream = substream;
 290        au1000->stream[PLAYBACK]->buffer = NULL;
 291        substream->private_data = au1000->stream[PLAYBACK];
 292        substream->runtime->hw = snd_au1000_hw;
 293        return (snd_pcm_hw_constraint_list(substream->runtime, 0,
 294                SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0);
 295}
 296
 297static int
 298snd_au1000_capture_open(struct snd_pcm_substream *substream)
 299{
 300        struct snd_au1000 *au1000 = substream->pcm->private_data;
 301
 302        au1000->stream[CAPTURE]->substream = substream;
 303        au1000->stream[CAPTURE]->buffer = NULL;
 304        substream->private_data = au1000->stream[CAPTURE];
 305        substream->runtime->hw = snd_au1000_hw;
 306        return (snd_pcm_hw_constraint_list(substream->runtime, 0,
 307                SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0);
 308}
 309
 310static int
 311snd_au1000_playback_close(struct snd_pcm_substream *substream)
 312{
 313        struct snd_au1000 *au1000 = substream->pcm->private_data;
 314
 315        au1000->stream[PLAYBACK]->substream = NULL;
 316        return 0;
 317}
 318
 319static int
 320snd_au1000_capture_close(struct snd_pcm_substream *substream)
 321{
 322        struct snd_au1000 *au1000 = substream->pcm->private_data;
 323
 324        au1000->stream[CAPTURE]->substream = NULL;
 325        return 0;
 326}
 327
 328static int
 329snd_au1000_hw_params(struct snd_pcm_substream *substream,
 330                                        struct snd_pcm_hw_params *hw_params)
 331{
 332        struct audio_stream *stream = substream->private_data;
 333        int err;
 334
 335        err = snd_pcm_lib_malloc_pages(substream,
 336                                       params_buffer_bytes(hw_params));
 337        if (err < 0)
 338                return err;
 339        return au1000_setup_dma_link(stream,
 340                                     params_period_bytes(hw_params),
 341                                     params_periods(hw_params));
 342}
 343
 344static int
 345snd_au1000_hw_free(struct snd_pcm_substream *substream)
 346{
 347        struct audio_stream *stream = substream->private_data;
 348        au1000_release_dma_link(stream);
 349        return snd_pcm_lib_free_pages(substream);
 350}
 351
 352static int
 353snd_au1000_playback_prepare(struct snd_pcm_substream *substream)
 354{
 355        struct snd_au1000 *au1000 = substream->pcm->private_data;
 356        struct snd_pcm_runtime *runtime = substream->runtime;
 357
 358        if (runtime->channels == 1)
 359                au1000_set_ac97_xmit_slots(au1000, AC97_SLOT_4);
 360        else
 361                au1000_set_ac97_xmit_slots(au1000, AC97_SLOT_3 | AC97_SLOT_4);
 362        snd_ac97_set_rate(au1000->ac97, AC97_PCM_FRONT_DAC_RATE, runtime->rate);
 363        return 0;
 364}
 365
 366static int
 367snd_au1000_capture_prepare(struct snd_pcm_substream *substream)
 368{
 369        struct snd_au1000 *au1000 = substream->pcm->private_data;
 370        struct snd_pcm_runtime *runtime = substream->runtime;
 371
 372        if (runtime->channels == 1)
 373                au1000_set_ac97_recv_slots(au1000, AC97_SLOT_4);
 374        else
 375                au1000_set_ac97_recv_slots(au1000, AC97_SLOT_3 | AC97_SLOT_4);
 376        snd_ac97_set_rate(au1000->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
 377        return 0;
 378}
 379
 380static int
 381snd_au1000_trigger(struct snd_pcm_substream *substream, int cmd)
 382{
 383        struct audio_stream *stream = substream->private_data;
 384        int err = 0;
 385
 386        spin_lock(&stream->dma_lock);
 387        switch (cmd) {
 388        case SNDRV_PCM_TRIGGER_START:
 389                au1000_dma_start(stream);
 390                break;
 391        case SNDRV_PCM_TRIGGER_STOP:
 392                au1000_dma_stop(stream);
 393                break;
 394        default:
 395                err = -EINVAL;
 396                break;
 397        }
 398        spin_unlock(&stream->dma_lock);
 399        return err;
 400}
 401
 402static snd_pcm_uframes_t
 403snd_au1000_pointer(struct snd_pcm_substream *substream)
 404{
 405        struct audio_stream *stream = substream->private_data;
 406        struct snd_pcm_runtime *runtime = substream->runtime;
 407        long location;
 408
 409        spin_lock(&stream->dma_lock);
 410        location = get_dma_residue(stream->dma);
 411        spin_unlock(&stream->dma_lock);
 412        location = stream->buffer->relative_end - location;
 413        if (location == -1)
 414                location = 0;
 415        return bytes_to_frames(runtime,location);
 416}
 417
 418static struct snd_pcm_ops snd_card_au1000_playback_ops = {
 419        .open                   = snd_au1000_playback_open,
 420        .close                  = snd_au1000_playback_close,
 421        .ioctl                  = snd_pcm_lib_ioctl,
 422        .hw_params              = snd_au1000_hw_params,
 423        .hw_free                = snd_au1000_hw_free,
 424        .prepare                = snd_au1000_playback_prepare,
 425        .trigger                = snd_au1000_trigger,
 426        .pointer                = snd_au1000_pointer,
 427};
 428
 429static struct snd_pcm_ops snd_card_au1000_capture_ops = {
 430        .open                   = snd_au1000_capture_open,
 431        .close                  = snd_au1000_capture_close,
 432        .ioctl                  = snd_pcm_lib_ioctl,
 433        .hw_params              = snd_au1000_hw_params,
 434        .hw_free                = snd_au1000_hw_free,
 435        .prepare                = snd_au1000_capture_prepare,
 436        .trigger                = snd_au1000_trigger,
 437        .pointer                = snd_au1000_pointer,
 438};
 439
 440static int __devinit
 441snd_au1000_pcm_new(struct snd_au1000 *au1000)
 442{
 443        struct snd_pcm *pcm;
 444        int err;
 445        unsigned long flags;
 446
 447        if ((err = snd_pcm_new(au1000->card, "AU1000 AC97 PCM", 0, 1, 1, &pcm)) < 0)
 448                return err;
 449
 450        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
 451                snd_dma_continuous_data(GFP_KERNEL), 128*1024, 128*1024);
 452
 453        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 454                &snd_card_au1000_playback_ops);
 455        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
 456                &snd_card_au1000_capture_ops);
 457
 458        pcm->private_data = au1000;
 459        pcm->info_flags = 0;
 460        strcpy(pcm->name, "Au1000 AC97 PCM");
 461
 462        spin_lock_init(&au1000->stream[PLAYBACK]->dma_lock);
 463        spin_lock_init(&au1000->stream[CAPTURE]->dma_lock);
 464
 465        flags = claim_dma_lock();
 466        if ((au1000->stream[PLAYBACK]->dma = request_au1000_dma(DMA_ID_AC97C_TX,
 467                        "AC97 TX", au1000_dma_interrupt, IRQF_DISABLED,
 468                        au1000->stream[PLAYBACK])) < 0) {
 469                release_dma_lock(flags);
 470                return -EBUSY;
 471        }
 472        if ((au1000->stream[CAPTURE]->dma = request_au1000_dma(DMA_ID_AC97C_RX,
 473                        "AC97 RX", au1000_dma_interrupt, IRQF_DISABLED,
 474                        au1000->stream[CAPTURE])) < 0){
 475                release_dma_lock(flags);
 476                return -EBUSY;
 477        }
 478        /* enable DMA coherency in read/write DMA channels */
 479        set_dma_mode(au1000->stream[PLAYBACK]->dma,
 480                     get_dma_mode(au1000->stream[PLAYBACK]->dma) & ~DMA_NC);
 481        set_dma_mode(au1000->stream[CAPTURE]->dma,
 482                     get_dma_mode(au1000->stream[CAPTURE]->dma) & ~DMA_NC);
 483        release_dma_lock(flags);
 484        au1000->pcm = pcm;
 485        return 0;
 486}
 487
 488
 489/*-------------------------- AC97 CODEC Control ------------------------------*/
 490
 491static unsigned short
 492snd_au1000_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
 493{
 494        struct snd_au1000 *au1000 = ac97->private_data;
 495        u32 volatile cmd;
 496        u16 volatile data;
 497        int             i;
 498
 499        spin_lock(&au1000->ac97_lock);
 500/* would rather use the interrupt than this polling but it works and I can't
 501get the interrupt driven case to work efficiently */
 502        for (i = 0; i < 0x5000; i++)
 503                if (!(au1000->ac97_ioport->status & AC97C_CP))
 504                        break;
 505        if (i == 0x5000)
 506                printk(KERN_ERR "au1000 AC97: AC97 command read timeout\n");
 507
 508        cmd = (u32) reg & AC97C_INDEX_MASK;
 509        cmd |= AC97C_READ;
 510        au1000->ac97_ioport->cmd = cmd;
 511
 512        /* now wait for the data */
 513        for (i = 0; i < 0x5000; i++)
 514                if (!(au1000->ac97_ioport->status & AC97C_CP))
 515                        break;
 516        if (i == 0x5000) {
 517                printk(KERN_ERR "au1000 AC97: AC97 command read timeout\n");
 518                return 0;
 519        }
 520
 521        data = au1000->ac97_ioport->cmd & 0xffff;
 522        spin_unlock(&au1000->ac97_lock);
 523
 524        return data;
 525
 526}
 527
 528
 529static void
 530snd_au1000_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
 531{
 532        struct snd_au1000 *au1000 = ac97->private_data;
 533        u32 cmd;
 534        int i;
 535
 536        spin_lock(&au1000->ac97_lock);
 537/* would rather use the interrupt than this polling but it works and I can't
 538get the interrupt driven case to work efficiently */
 539        for (i = 0; i < 0x5000; i++)
 540                if (!(au1000->ac97_ioport->status & AC97C_CP))
 541                        break;
 542        if (i == 0x5000)
 543                printk(KERN_ERR "au1000 AC97: AC97 command write timeout\n");
 544
 545        cmd = (u32) reg & AC97C_INDEX_MASK;
 546        cmd &= ~AC97C_READ;
 547        cmd |= ((u32) val << AC97C_WD_BIT);
 548        au1000->ac97_ioport->cmd = cmd;
 549        spin_unlock(&au1000->ac97_lock);
 550}
 551
 552static int __devinit
 553snd_au1000_ac97_new(struct snd_au1000 *au1000)
 554{
 555        int err;
 556        struct snd_ac97_bus *pbus;
 557        struct snd_ac97_template ac97;
 558        static struct snd_ac97_bus_ops ops = {
 559                .write = snd_au1000_ac97_write,
 560                .read = snd_au1000_ac97_read,
 561        };
 562
 563        if ((au1000->ac97_res_port = request_mem_region(CPHYSADDR(AC97C_CONFIG),
 564                        0x100000, "Au1x00 AC97")) == NULL) {
 565                snd_printk(KERN_ERR "ALSA AC97: can't grap AC97 port\n");
 566                return -EBUSY;
 567        }
 568        au1000->ac97_ioport = (struct au1000_ac97_reg *)
 569                KSEG1ADDR(au1000->ac97_res_port->start);
 570
 571        spin_lock_init(&au1000->ac97_lock);
 572
 573        /* configure pins for AC'97
 574        TODO: move to board_setup.c */
 575        au_writel(au_readl(SYS_PINFUNC) & ~0x02, SYS_PINFUNC);
 576
 577        /* Initialise Au1000's AC'97 Control Block */
 578        au1000->ac97_ioport->cntrl = AC97C_RS | AC97C_CE;
 579        udelay(10);
 580        au1000->ac97_ioport->cntrl = AC97C_CE;
 581        udelay(10);
 582
 583        /* Initialise External CODEC -- cold reset */
 584        au1000->ac97_ioport->config = AC97C_RESET;
 585        udelay(10);
 586        au1000->ac97_ioport->config = 0x0;
 587        mdelay(5);
 588
 589        /* Initialise AC97 middle-layer */
 590        if ((err = snd_ac97_bus(au1000->card, 0, &ops, au1000, &pbus)) < 0)
 591                return err;
 592
 593        memset(&ac97, 0, sizeof(ac97));
 594        ac97.private_data = au1000;
 595        if ((err = snd_ac97_mixer(pbus, &ac97, &au1000->ac97)) < 0)
 596                return err;
 597
 598        return 0;
 599}
 600
 601/*------------------------------ Setup / Destroy ----------------------------*/
 602
 603void
 604snd_au1000_free(struct snd_card *card)
 605{
 606        struct snd_au1000 *au1000 = card->private_data;
 607
 608        if (au1000->ac97_res_port) {
 609                /* put internal AC97 block into reset */
 610                au1000->ac97_ioport->cntrl = AC97C_RS;
 611                au1000->ac97_ioport = NULL;
 612                release_and_free_resource(au1000->ac97_res_port);
 613        }
 614
 615        if (au1000->stream[PLAYBACK]) {
 616                if (au1000->stream[PLAYBACK]->dma >= 0)
 617                        free_au1000_dma(au1000->stream[PLAYBACK]->dma);
 618                kfree(au1000->stream[PLAYBACK]);
 619        }
 620
 621        if (au1000->stream[CAPTURE]) {
 622                if (au1000->stream[CAPTURE]->dma >= 0)
 623                        free_au1000_dma(au1000->stream[CAPTURE]->dma);
 624                kfree(au1000->stream[CAPTURE]);
 625        }
 626}
 627
 628
 629static struct snd_card *au1000_card;
 630
 631static int __init
 632au1000_init(void)
 633{
 634        int err;
 635        struct snd_card *card;
 636        struct snd_au1000 *au1000;
 637
 638        card = snd_card_new(-1, "AC97", THIS_MODULE, sizeof(struct snd_au1000));
 639        if (card == NULL)
 640                return -ENOMEM;
 641
 642        card->private_free = snd_au1000_free;
 643        au1000 = card->private_data;
 644        au1000->card = card;
 645
 646        au1000->stream[PLAYBACK] = kmalloc(sizeof(struct audio_stream), GFP_KERNEL);
 647        au1000->stream[CAPTURE ] = kmalloc(sizeof(struct audio_stream), GFP_KERNEL);
 648        /* so that snd_au1000_free will work as intended */
 649        au1000->ac97_res_port = NULL;
 650        if (au1000->stream[PLAYBACK])
 651                au1000->stream[PLAYBACK]->dma = -1;
 652        if (au1000->stream[CAPTURE ])
 653                au1000->stream[CAPTURE ]->dma = -1;
 654
 655        if (au1000->stream[PLAYBACK] == NULL ||
 656            au1000->stream[CAPTURE ] == NULL) {
 657                snd_card_free(card);
 658                return -ENOMEM;
 659        }
 660
 661        if ((err = snd_au1000_ac97_new(au1000)) < 0 ) {
 662                snd_card_free(card);
 663                return err;
 664        }
 665
 666        if ((err = snd_au1000_pcm_new(au1000)) < 0) {
 667                snd_card_free(card);
 668                return err;
 669        }
 670
 671        strcpy(card->driver, "Au1000-AC97");
 672        strcpy(card->shortname, "AMD Au1000-AC97");
 673        sprintf(card->longname, "AMD Au1000--AC97 ALSA Driver");
 674
 675        if ((err = snd_card_register(card)) < 0) {
 676                snd_card_free(card);
 677                return err;
 678        }
 679
 680        printk( KERN_INFO "ALSA AC97: Driver Initialized\n" );
 681        au1000_card = card;
 682        return 0;
 683}
 684
 685static void __exit au1000_exit(void)
 686{
 687        snd_card_free(au1000_card);
 688}
 689
 690module_init(au1000_init);
 691module_exit(au1000_exit);
 692
 693
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.