// SPDX-License-Identifier: GPL-2.0-or-later
/*
* 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>
*/
/* 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/module.h>
#include <linux/platform_device.h>
#include <linux/ioport.h>
#include <linux/slab.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 bool 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_printd(KERN_DEBUG SND_ML403_AC97CR_DRIVER ": " \
fmt, ##args); \
} while (0)
#else
#define PDEBUG(fac, fmt, args...) /* nothing */
#endif
/* Defines for "waits"/timeouts (portions of HZ=250 on arch/ppc by default) */
#define CODEC_TIMEOUT_ON_INIT 5 /* timeout for checking for codec
* readiness (after insmod)
*/
#ifndef CODEC_WRITE_CHECK_RAF
#define CODEC_WAIT_AFTER_WRITE 100 /* general, static wait after a write
* access to a codec register, may be
* 0 to completely remove wait
*/
#else
#define CODEC_TIMEOUT_AFTER_WRITE 5 /* timeout after a write access to a
* codec register, if RAF bit is used
*/
#endif
#define CODEC_TIMEOUT_AFTER_READ 5 /* timeout after a read access to a
* codec register (checking RAF bit)
*/
/* Infrastructure for codec register shadowing */
#define LM4550_REG_OK (1<<0) /* register exists */
#define LM4550_REG_DONEREAD (1<<1) /* read register once, value should be
* the same currently in the register
*/
#define LM4550_REG_NOSAVE (1<<2) /* values written to this register will
* not be saved in the register
*/
#define LM4550_REG_NOSHADOW (1<<3) /* don't do register shadowing, use plain
* hardware access
*/
#define LM4550_REG_READONLY (1<<4) /* register is read only */
#define LM4550_REG_FAKEPROBE (1<<5) /* fake write _and_ read actions during
* probe() correctly
*/
#define LM4550_REG_FAKEREAD (1<<6) /* fake read access, always retu