#include <linux/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/gameport.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/info.h>
#include <sound/tlv.h>
#include <sound/ac97_codec.h>
#include <sound/mpu401.h>
#include <sound/initval.h>
#if 0
#define POINTER_DEBUG
#endif
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;
#if IS_REACHABLE(CONFIG_GAMEPORT)
#define SUPPORT_JOYSTICK …
#endif
static int index = …;
static char *id = …;
static long mpu_port;
#ifdef SUPPORT_JOYSTICK
static bool joystick;
#endif
static int ac97_clock = …;
static char *ac97_quirk;
static int dxs_support;
static int dxs_init_volume = …;
static int nodelay;
module_param(index, int, 0444);
MODULE_PARM_DESC(…) …;
module_param(id, charp, 0444);
MODULE_PARM_DESC(…) …;
module_param_hw(mpu_port, long, ioport, 0444);
MODULE_PARM_DESC(…) …;
#ifdef SUPPORT_JOYSTICK
module_param(joystick, bool, 0444);
MODULE_PARM_DESC(…) …;
#endif
module_param(ac97_clock, int, 0444);
MODULE_PARM_DESC(…) …;
module_param(ac97_quirk, charp, 0444);
MODULE_PARM_DESC(…) …;
module_param(dxs_support, int, 0444);
MODULE_PARM_DESC(…) …;
module_param(dxs_init_volume, int, 0644);
MODULE_PARM_DESC(…) …;
module_param(nodelay, int, 0444);
MODULE_PARM_DESC(…) …;
static bool enable;
module_param(enable, bool, 0444);
#define VIA_REV_686_A …
#define VIA_REV_686_B …
#define VIA_REV_686_C …
#define VIA_REV_686_D …
#define VIA_REV_686_E …
#define VIA_REV_686_H …
#define VIA_REV_PRE_8233 …
#define VIA_REV_8233C …
#define VIA_REV_8233 …
#define VIA_REV_8233A …
#define VIA_REV_8235 …
#define VIA_REV_8237 …
#define VIA_REV_8251 …
#define VIAREG(via, x) …
#define VIADEV_REG(viadev, x) …
#define VIA_REG_OFFSET_STATUS …
#define VIA_REG_STAT_ACTIVE …
#define VIA8233_SHADOW_STAT_ACTIVE …
#define VIA_REG_STAT_PAUSED …
#define VIA_REG_STAT_TRIGGER_QUEUED …
#define VIA_REG_STAT_STOPPED …
#define VIA_REG_STAT_EOL …
#define VIA_REG_STAT_FLAG …
#define VIA_REG_OFFSET_CONTROL …
#define VIA_REG_CTRL_START …
#define VIA_REG_CTRL_TERMINATE …
#define VIA_REG_CTRL_AUTOSTART …
#define VIA_REG_CTRL_PAUSE …
#define VIA_REG_CTRL_INT_STOP …
#define VIA_REG_CTRL_INT_EOL …
#define VIA_REG_CTRL_INT_FLAG …
#define VIA_REG_CTRL_RESET …
#define VIA_REG_CTRL_INT …
#define VIA_REG_OFFSET_TYPE …
#define VIA_REG_TYPE_AUTOSTART …
#define VIA_REG_TYPE_16BIT …
#define VIA_REG_TYPE_STEREO …
#define VIA_REG_TYPE_INT_LLINE …
#define VIA_REG_TYPE_INT_LSAMPLE …
#define VIA_REG_TYPE_INT_LESSONE …
#define VIA_REG_TYPE_INT_MASK …
#define VIA_REG_TYPE_INT_EOL …
#define VIA_REG_TYPE_INT_FLAG …
#define VIA_REG_OFFSET_TABLE_PTR …
#define VIA_REG_OFFSET_CURR_PTR …
#define VIA_REG_OFFSET_STOP_IDX …
#define VIA8233_REG_TYPE_16BIT …
#define VIA8233_REG_TYPE_STEREO …
#define VIA_REG_OFFSET_CURR_COUNT …
#define VIA_REG_OFFSET_CURR_INDEX …
#define DEFINE_VIA_REGSET(name,val) …
DEFINE_VIA_REGSET(PLAYBACK, 0x00);
DEFINE_VIA_REGSET(CAPTURE, 0x10);
DEFINE_VIA_REGSET(FM, 0x20);
#define VIA_REG_AC97 …
#define VIA_REG_AC97_CODEC_ID_MASK …
#define VIA_REG_AC97_CODEC_ID_SHIFT …
#define VIA_REG_AC97_CODEC_ID_PRIMARY …
#define VIA_REG_AC97_CODEC_ID_SECONDARY …
#define VIA_REG_AC97_SECONDARY_VALID …
#define VIA_REG_AC97_PRIMARY_VALID …
#define VIA_REG_AC97_BUSY …
#define VIA_REG_AC97_READ …
#define VIA_REG_AC97_CMD_SHIFT …
#define VIA_REG_AC97_CMD_MASK …
#define VIA_REG_AC97_DATA_SHIFT …
#define VIA_REG_AC97_DATA_MASK …
#define VIA_REG_SGD_SHADOW …
#define VIA_REG_SGD_STAT_PB_FLAG …
#define VIA_REG_SGD_STAT_CP_FLAG …
#define VIA_REG_SGD_STAT_FM_FLAG …
#define VIA_REG_SGD_STAT_PB_EOL …
#define VIA_REG_SGD_STAT_CP_EOL …
#define VIA_REG_SGD_STAT_FM_EOL …
#define VIA_REG_SGD_STAT_PB_STOP …
#define VIA_REG_SGD_STAT_CP_STOP …
#define VIA_REG_SGD_STAT_FM_STOP …
#define VIA_REG_SGD_STAT_PB_ACTIVE …
#define VIA_REG_SGD_STAT_CP_ACTIVE …
#define VIA_REG_SGD_STAT_FM_ACTIVE …
#define VIA8233_REG_SGD_STAT_FLAG …
#define VIA8233_REG_SGD_STAT_EOL …
#define VIA8233_REG_SGD_STAT_STOP …
#define VIA8233_REG_SGD_STAT_ACTIVE …
#define VIA8233_INTR_MASK(chan) …
#define VIA8233_REG_SGD_CHAN_SDX …
#define VIA8233_REG_SGD_CHAN_MULTI …
#define VIA8233_REG_SGD_CHAN_REC …
#define VIA8233_REG_SGD_CHAN_REC1 …
#define VIA_REG_GPI_STATUS …
#define VIA_REG_GPI_INTR …
DEFINE_VIA_REGSET(MULTPLAY, 0x40);
DEFINE_VIA_REGSET(CAPTURE_8233, 0x60);
#define VIA_REG_OFS_PLAYBACK_VOLUME_L …
#define VIA_REG_OFS_PLAYBACK_VOLUME_R …
#define VIA_REG_OFS_MULTPLAY_FORMAT …
#define VIA_REG_MULTPLAY_FMT_8BIT …
#define VIA_REG_MULTPLAY_FMT_16BIT …
#define VIA_REG_MULTPLAY_FMT_CH_MASK …
#define VIA_REG_OFS_CAPTURE_FIFO …
#define VIA_REG_CAPTURE_FIFO_ENABLE …
#define VIA_DXS_MAX_VOLUME …
#define VIA_REG_CAPTURE_CHANNEL …
#define VIA_REG_CAPTURE_CHANNEL_MIC …
#define VIA_REG_CAPTURE_CHANNEL_LINE …
#define VIA_REG_CAPTURE_SELECT_CODEC …
#define VIA_TBL_BIT_FLAG …
#define VIA_TBL_BIT_EOL …
#define VIA_ACLINK_STAT …
#define VIA_ACLINK_C11_READY …
#define VIA_ACLINK_C10_READY …
#define VIA_ACLINK_C01_READY …
#define VIA_ACLINK_LOWPOWER …
#define VIA_ACLINK_C00_READY …
#define VIA_ACLINK_CTRL …
#define VIA_ACLINK_CTRL_ENABLE …
#define VIA_ACLINK_CTRL_RESET …
#define VIA_ACLINK_CTRL_SYNC …
#define VIA_ACLINK_CTRL_SDO …
#define VIA_ACLINK_CTRL_VRA …
#define VIA_ACLINK_CTRL_PCM …
#define VIA_ACLINK_CTRL_FM …
#define VIA_ACLINK_CTRL_SB …
#define VIA_ACLINK_CTRL_INIT …
#define VIA_FUNC_ENABLE …
#define VIA_FUNC_MIDI_PNP …
#define VIA_FUNC_MIDI_IRQMASK …
#define VIA_FUNC_RX2C_WRITE …
#define VIA_FUNC_SB_FIFO_EMPTY …
#define VIA_FUNC_ENABLE_GAME …
#define VIA_FUNC_ENABLE_FM …
#define VIA_FUNC_ENABLE_MIDI …
#define VIA_FUNC_ENABLE_SB …
#define VIA_PNP_CONTROL …
#define VIA_FM_NMI_CTRL …
#define VIA8233_VOLCHG_CTRL …
#define VIA8233_SPDIF_CTRL …
#define VIA8233_SPDIF_DX3 …
#define VIA8233_SPDIF_SLOT_MASK …
#define VIA8233_SPDIF_SLOT_1011 …
#define VIA8233_SPDIF_SLOT_34 …
#define VIA8233_SPDIF_SLOT_78 …
#define VIA8233_SPDIF_SLOT_69 …
#define VIA_DXS_AUTO …
#define VIA_DXS_ENABLE …
#define VIA_DXS_DISABLE …
#define VIA_DXS_48K …
#define VIA_DXS_NO_VRA …
#define VIA_DXS_SRC …
struct snd_via_sg_table { … } ;
#define VIA_TABLE_SIZE …
#define VIA_MAX_BUFSIZE …
struct viadev { … };
enum { … };
enum { … };
#define VIA_MAX_DEVS …
struct via_rate_lock { … };
struct via82xx { … };
static const struct pci_device_id snd_via82xx_ids[] = …;
MODULE_DEVICE_TABLE(pci, snd_via82xx_ids);
static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substream,
struct pci_dev *pci,
unsigned int periods, unsigned int fragsize)
{ … }
static int clean_via_table(struct viadev *dev, struct snd_pcm_substream *substream,
struct pci_dev *pci)
{ … }
static inline unsigned int snd_via82xx_codec_xread(struct via82xx *chip)
{ … }
static inline void snd_via82xx_codec_xwrite(struct via82xx *chip, unsigned int val)
{ … }
static int snd_via82xx_codec_ready(struct via82xx *chip, int secondary)
{ … }
static int snd_via82xx_codec_valid(struct via82xx *chip, int secondary)
{ … }
static void snd_via82xx_codec_wait(struct snd_ac97 *ac97)
{ … }
static void snd_via82xx_codec_write(struct snd_ac97 *ac97,
unsigned short reg,
unsigned short val)
{ … }
static unsigned short snd_via82xx_codec_read(struct snd_ac97 *ac97, unsigned short reg)
{ … }
static void snd_via82xx_channel_reset(struct via82xx *chip, struct viadev *viadev)
{ … }
static irqreturn_t snd_via686_interrupt(int irq, void *dev_id)
{ … }
static irqreturn_t snd_via8233_interrupt(int irq, void *dev_id)
{ … }
static int snd_via82xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{ … }
#define check_invalid_pos(viadev,pos) …
static inline unsigned int calc_linear_pos(struct via82xx *chip,
struct viadev *viadev,
unsigned int idx,
unsigned int count)
{ … }
static snd_pcm_uframes_t snd_via686_pcm_pointer(struct snd_pcm_substream *substream)
{ … }
static snd_pcm_uframes_t snd_via8233_pcm_pointer(struct snd_pcm_substream *substream)
{ … }
static int snd_via82xx_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{ … }
static int snd_via82xx_hw_free(struct snd_pcm_substream *substream)
{ … }
static void snd_via82xx_set_table_ptr(struct via82xx *chip, struct viadev *viadev)
{ … }
static void via686_setup_format(struct via82xx *chip, struct viadev *viadev,
struct snd_pcm_runtime *runtime)
{ … }
static int snd_via686_playback_prepare(struct snd_pcm_substream *substream)
{ … }
static int snd_via686_capture_prepare(struct snd_pcm_substream *substream)
{ … }
static int via_lock_rate(struct via_rate_lock *rec, int rate)
{ … }
static int snd_via8233_playback_prepare(struct snd_pcm_substream *substream)
{ … }
static int snd_via8233_multi_prepare(struct snd_pcm_substream *substream)
{ … }
static int snd_via8233_capture_prepare(struct snd_pcm_substream *substream)
{ … }
static const struct snd_pcm_hardware snd_via82xx_hw = …;
static int snd_via82xx_pcm_open(struct via82xx *chip, struct viadev *viadev,
struct snd_pcm_substream *substream)
{ … }
static int snd_via686_playback_open(struct snd_pcm_substream *substream)
{ … }
static int snd_via8233_playback_open(struct snd_pcm_substream *substream)
{ … }
static int snd_via8233_multi_open(struct snd_pcm_substream *substream)
{ … }
static int snd_via82xx_capture_open(struct snd_pcm_substream *substream)
{ … }
static int snd_via82xx_pcm_close(struct snd_pcm_substream *substream)
{ … }
static int snd_via8233_playback_close(struct snd_pcm_substream *substream)
{ … }
static const struct snd_pcm_ops snd_via686_playback_ops = …;
static const struct snd_pcm_ops snd_via686_capture_ops = …;
static const struct snd_pcm_ops snd_via8233_playback_ops = …;
static const struct snd_pcm_ops snd_via8233_multi_ops = …;
static const struct snd_pcm_ops snd_via8233_capture_ops = …;
static void init_viadev(struct via82xx *chip, int idx, unsigned int reg_offset,
int shadow_pos, int direction)
{ … }
static int snd_via8233_pcm_new(struct via82xx *chip)
{ … }
static int snd_via8233a_pcm_new(struct via82xx *chip)
{ … }
static int snd_via686_pcm_new(struct via82xx *chip)
{ … }
static int snd_via8233_capture_source_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{ … }
static int snd_via8233_capture_source_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{ … }
static int snd_via8233_capture_source_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{ … }
static struct snd_kcontrol_new snd_via8233_capture_source = …;
#define snd_via8233_dxs3_spdif_info …
static int snd_via8233_dxs3_spdif_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{ … }
static int snd_via8233_dxs3_spdif_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{ … }
static const struct snd_kcontrol_new snd_via8233_dxs3_spdif_control = …;
static int snd_via8233_dxs_volume_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{ … }
static int snd_via8233_dxs_volume_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{ … }
static int snd_via8233_pcmdxs_volume_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{ … }
static int snd_via8233_dxs_volume_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{ … }
static int snd_via8233_pcmdxs_volume_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{ … }
static const DECLARE_TLV_DB_SCALE(db_scale_dxs, -4650, 150, 1);
static const struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control = …;
static const struct snd_kcontrol_new snd_via8233_dxs_volume_control = …;
static void snd_via82xx_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
{ … }
static void snd_via82xx_mixer_free_ac97(struct snd_ac97 *ac97)
{ … }
static const struct ac97_quirk ac97_quirks[] = …;
static int snd_via82xx_mixer_new(struct via82xx *chip, const char *quirk_override)
{ … }
#ifdef SUPPORT_JOYSTICK
#define JOYSTICK_ADDR …
static int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legacy)
{ … }
static void snd_via686_free_gameport(struct via82xx *chip)
{ … }
#else
static inline int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legacy)
{
return -ENOSYS;
}
static inline void snd_via686_free_gameport(struct via82xx *chip) { }
#endif
static int snd_via8233_init_misc(struct via82xx *chip)
{ … }
static int snd_via686_init_misc(struct via82xx *chip)
{ … }
static void snd_via82xx_proc_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{ … }
static void snd_via82xx_proc_init(struct via82xx *chip)
{ … }
static int snd_via82xx_chip_init(struct via82xx *chip)
{ … }
static int snd_via82xx_suspend(struct device *dev)
{ … }
static int snd_via82xx_resume(struct device *dev)
{ … }
static DEFINE_SIMPLE_DEV_PM_OPS(snd_via82xx_pm, snd_via82xx_suspend, snd_via82xx_resume);
static void snd_via82xx_free(struct snd_card *card)
{ … }
static int snd_via82xx_create(struct snd_card *card,
struct pci_dev *pci,
int chip_type,
int revision,
unsigned int ac97_clock)
{ … }
struct via823x_info { … };
static const struct via823x_info via823x_cards[] = …;
static const struct snd_pci_quirk dxs_allowlist[] = …;
static int check_dxs_list(struct pci_dev *pci, int revision)
{
const struct snd_pci_quirk *w;
w = snd_pci_quirk_lookup(pci, dxs_allowlist);
if (w) {
dev_dbg(&pci->dev, "DXS allow list for %s found\n",
snd_pci_quirk_name(w));
return w->value;
}
if (revision >= VIA_REV_8235)
return VIA_DXS_SRC;
dev_info(&pci->dev, "Assuming DXS channels with 48k fixed sample rate.\n");
dev_info(&pci->dev, " Please try dxs_support=5 option\n");
dev_info(&pci->dev, " and report if it works on your machine.\n");
dev_info(&pci->dev, " For more details, read ALSA-Configuration.txt.\n");
return VIA_DXS_48K;
};
static int __snd_via82xx_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{ … }
static int snd_via82xx_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{ … }
static struct pci_driver via82xx_driver = …;
module_pci_driver(…) …;