/*
* ALSA driver for Xilinx ML403 AC97 Controller Reference
* IP: opb_ac97_controller_ref_v1_00_a (EDK 8.1i)
* IP: opb_ac97_controller_ref_v1_00_a (EDK 9.1i)
*
* Copyright (c) by 2007 Joachim Foerster <JOFT@gmx.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/* Some notes / status of this driver:
*
* - Don't wonder about some strange implementations of things - especially the
* (heavy) shadowing of codec registers, with which I tried to reduce read
* accesses to a minimum, because after a variable amount of accesses, the AC97
* controller doesn't raise the register access finished bit anymore ...
*
* - Playback support seems to be pretty stable - no issues here.
* - Capture support "works" now, too. Overruns don't happen any longer so often.
* But there might still be some ...
*/
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/interrupt.h>
/* HZ */
#include <linux/param.h>
/* jiffies, time_*() */
#include <linux/jiffies.h>
/* schedule_timeout*() */
#include <linux/sched.h>
/* spin_lock*() */
#include <linux/spinlock.h>
/* struct mutex, mutex_init(), mutex_*lock() */
#include <linux/mutex.h>
/* snd_printk(), snd_printd() */
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <sound/ac97_codec.h>
#include "pcm-indirect2.h"
#define SND_ML403_AC97CR_DRIVER "ml403-ac97cr"
MODULE_AUTHOR("Joachim Foerster <JOFT@gmx.de>");
MODULE_DESCRIPTION("Xilinx ML403 AC97 Controller Reference");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Xilinx,ML403 AC97 Controller Reference}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for ML403 AC97 Controller Reference.");
module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for ML403 AC97 Controller Reference.");
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable this ML403 AC97 Controller Reference.");
/* Special feature options */
/*#define CODEC_WRITE_CHECK_RAF*/ /* don't return after a write to a codec
* register, while RAF bit is not set
*/
/* Debug options for code which may be removed completely in a final version */
#ifdef CONFIG_SND_DEBUG
/*#define CODEC_STAT*/ /* turn on some minimal "statistics"
* about codec register usage
*/
#define SND_PCM_INDIRECT2_STAT /* turn on some "statistics" about the
* process of copying bytes from the
* intermediate buffer to the hardware
* fifo and the other way round
*/
#endif
/* Definition of a "level/facility dependent" printk(); may be removed
* completely in a final version
*/
#undef PDEBUG
#ifdef CONFIG_SND_DEBUG
/* "facilities" for PDEBUG */
#define UNKNOWN (1<<0)
#define CODEC_SUCCESS (1<<1)
#define CODEC_FAKE (1<<2)
#define INIT_INFO (1<<3)
#define INIT_FAILURE (1<<4)
#define WORK_INFO (1<<5)
#define WORK_FAILURE (1<<6)
#define PDEBUG_FACILITIES (UNKNOWN | INIT_FAILURE | WORK_FAILURE)
#define PDEBUG(fac, fmt, args...) do { \
if (fac & PDEBUG_FACILITIES) \
snd_pr