#include <linux/io.h>
#include <linux/init.h>
#include <linux/bug.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/gameport.h>
#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/rawmidi.h>
#include <sound/mpu401.h>
#include <sound/opl3.h>
#include <sound/initval.h>
#define AZF_USE_AC97_LAYER …
#ifdef AZF_USE_AC97_LAYER
#include <sound/ac97_codec.h>
#endif
#include "azt3328.h"
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;
#if IS_REACHABLE(CONFIG_GAMEPORT)
#define SUPPORT_GAMEPORT …
#endif
static int index[SNDRV_CARDS] = …;
module_param_array(…);
MODULE_PARM_DESC(…) …;
static char *id[SNDRV_CARDS] = …;
module_param_array(…);
MODULE_PARM_DESC(…) …;
static bool enable[SNDRV_CARDS] = …;
module_param_array(…);
MODULE_PARM_DESC(…) …;
static int seqtimer_scaling = …;
module_param(seqtimer_scaling, int, 0444);
MODULE_PARM_DESC(…) …;
enum snd_azf3328_codec_type { … };
struct snd_azf3328_codec_data { … };
struct snd_azf3328 { … };
static const struct pci_device_id snd_azf3328_ids[] = …;
MODULE_DEVICE_TABLE(pci, snd_azf3328_ids);
static int
snd_azf3328_io_reg_setb(unsigned reg, u8 mask, bool do_set)
{ … }
static inline void
snd_azf3328_codec_outb(const struct snd_azf3328_codec_data *codec,
unsigned reg,
u8 value
)
{ … }
static inline u8
snd_azf3328_codec_inb(const struct snd_azf3328_codec_data *codec, unsigned reg)
{ … }
static inline void
snd_azf3328_codec_outw(const struct snd_azf3328_codec_data *codec,
unsigned reg,
u16 value
)
{ … }
static inline u16
snd_azf3328_codec_inw(const struct snd_azf3328_codec_data *codec, unsigned reg)
{ … }
static inline void
snd_azf3328_codec_outl_multi(const struct snd_azf3328_codec_data *codec,
unsigned reg, const void *buffer, int count
)
{ … }
static inline u32
snd_azf3328_codec_inl(const struct snd_azf3328_codec_data *codec, unsigned reg)
{ … }
static inline void
snd_azf3328_ctrl_outb(const struct snd_azf3328 *chip, unsigned reg, u8 value)
{ … }
static inline u8
snd_azf3328_ctrl_inb(const struct snd_azf3328 *chip, unsigned reg)
{ … }
static inline u16
snd_azf3328_ctrl_inw(const struct snd_azf3328 *chip, unsigned reg)
{ … }
static inline void
snd_azf3328_ctrl_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value)
{ … }
static inline void
snd_azf3328_ctrl_outl(const struct snd_azf3328 *chip, unsigned reg, u32 value)
{ … }
static inline void
snd_azf3328_game_outb(const struct snd_azf3328 *chip, unsigned reg, u8 value)
{ … }
static inline void
snd_azf3328_game_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value)
{ … }
static inline u8
snd_azf3328_game_inb(const struct snd_azf3328 *chip, unsigned reg)
{ … }
static inline u16
snd_azf3328_game_inw(const struct snd_azf3328 *chip, unsigned reg)
{ … }
static inline void
snd_azf3328_mixer_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value)
{ … }
static inline u16
snd_azf3328_mixer_inw(const struct snd_azf3328 *chip, unsigned reg)
{ … }
#define AZF_MUTE_BIT …
static bool
snd_azf3328_mixer_mute_control(const struct snd_azf3328 *chip,
unsigned reg, bool do_mute
)
{ … }
static inline bool
snd_azf3328_mixer_mute_control_master(const struct snd_azf3328 *chip,
bool do_mute
)
{ … }
static inline bool
snd_azf3328_mixer_mute_control_pcm(const struct snd_azf3328 *chip,
bool do_mute
)
{ … }
static inline void
snd_azf3328_mixer_reset(const struct snd_azf3328 *chip)
{ … }
#ifdef AZF_USE_AC97_LAYER
static inline void
snd_azf3328_mixer_ac97_map_unsupported(const struct snd_azf3328 *chip,
unsigned short reg, const char *mode)
{ … }
#define AZF_REG_MASK …
#define AZF_AC97_REG_UNSUPPORTED …
#define AZF_AC97_REG_REAL_IO_READ …
#define AZF_AC97_REG_REAL_IO_WRITE …
#define AZF_AC97_REG_REAL_IO_RW …
#define AZF_AC97_REG_EMU_IO_READ …
#define AZF_AC97_REG_EMU_IO_WRITE …
#define AZF_AC97_REG_EMU_IO_RW …
static unsigned short
snd_azf3328_mixer_ac97_map_reg_idx(unsigned short reg)
{ … }
static const unsigned short
azf_emulated_ac97_caps = …;
static const unsigned short
azf_emulated_ac97_powerdown = …
AC97_PD_ADC_STATUS |
AC97_PD_DAC_STATUS |
AC97_PD_MIXER_STATUS |
AC97_PD_VREF_STATUS;
static const unsigned int
azf_emulated_ac97_vendor_id = …;
static unsigned short
snd_azf3328_mixer_ac97_read(struct snd_ac97 *ac97, unsigned short reg_ac97)
{ … }
static void
snd_azf3328_mixer_ac97_write(struct snd_ac97 *ac97,
unsigned short reg_ac97, unsigned short val)
{ … }
static int
snd_azf3328_mixer_new(struct snd_azf3328 *chip)
{ … }
#else
static void
snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip,
unsigned reg,
unsigned char dst_vol_left,
unsigned char dst_vol_right,
int chan_sel, int delay
)
{
unsigned long portbase = chip->mixer_io + reg;
unsigned char curr_vol_left = 0, curr_vol_right = 0;
int left_change = 0, right_change = 0;
if (chan_sel & SET_CHAN_LEFT) {
curr_vol_left = inb(portbase + 1);
if (curr_vol_left & AZF_MUTE_BIT)
dst_vol_left |= AZF_MUTE_BIT;
else
dst_vol_left &= ~AZF_MUTE_BIT;
left_change = (curr_vol_left > dst_vol_left) ? -1 : 1;
}
if (chan_sel & SET_CHAN_RIGHT) {
curr_vol_right = inb(portbase + 0);
right_change = (curr_vol_right > dst_vol_right) ? -1 : 1;
}
do {
if (left_change) {
if (curr_vol_left != dst_vol_left) {
curr_vol_left += left_change;
outb(curr_vol_left, portbase + 1);
} else
left_change = 0;
}
if (right_change) {
if (curr_vol_right != dst_vol_right) {
curr_vol_right += right_change;
outb(curr_vol_right, portbase + 0);
} else
right_change = 0;
}
if (delay)
mdelay(delay);
} while ((left_change) || (right_change));
}
struct azf3328_mixer_reg {
unsigned reg;
unsigned int lchan_shift, rchan_shift;
unsigned int mask;
unsigned int invert: 1;
unsigned int stereo: 1;
unsigned int enum_c: 4;
};
#define COMPOSE_MIXER_REG …
static void snd_azf3328_mixer_reg_decode(struct azf3328_mixer_reg *r, unsigned long val)
{
r->reg = val & 0xff;
r->lchan_shift = (val >> 8) & 0x0f;
r->rchan_shift = (val >> 12) & 0x0f;
r->mask = (val >> 16) & 0xff;
r->invert = (val >> 24) & 1;
r->stereo = (val >> 25) & 1;
r->enum_c = (val >> 26) & 0x0f;
}
#define AZF3328_MIXER_SWITCH …
#define AZF3328_MIXER_VOL_STEREO …
#define AZF3328_MIXER_VOL_MONO …
#define AZF3328_MIXER_VOL_SPECIAL …
#define AZF3328_MIXER_ENUM …
static int
snd_azf3328_info_mixer(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
struct azf3328_mixer_reg reg;
snd_azf3328_mixer_reg_decode(®, kcontrol->private_value);
uinfo->type = reg.mask == 1 ?
SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = reg.stereo + 1;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = reg.mask;
return 0;
}
static int
snd_azf3328_get_mixer(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
struct azf3328_mixer_reg reg;
u16 oreg, val;
snd_azf3328_mixer_reg_decode(®, kcontrol->private_value);
oreg = snd_azf3328_mixer_inw(chip, reg.reg);
val = (oreg >> reg.lchan_shift) & reg.mask;
if (reg.invert)
val = reg.mask - val;
ucontrol->value.integer.value[0] = val;
if (reg.stereo) {
val = (oreg >> reg.rchan_shift) & reg.mask;
if (reg.invert)
val = reg.mask - val;
ucontrol->value.integer.value[1] = val;
}
dev_dbg(chip->card->dev,
"get: %02x is %04x -> vol %02lx|%02lx (shift %02d|%02d, mask %02x, inv. %d, stereo %d)\n",
reg.reg, oreg,
ucontrol->value.integer.value[0], ucontrol->value.integer.value[1],
reg.lchan_shift, reg.rchan_shift, reg.mask, reg.invert, reg.stereo);
return 0;
}
static int
snd_azf3328_put_mixer(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
struct azf3328_mixer_reg reg;
u16 oreg, nreg, val;
snd_azf3328_mixer_reg_decode(®, kcontrol->private_value);
oreg = snd_azf3328_mixer_inw(chip, reg.reg);
val = ucontrol->value.integer.value[0] & reg.mask;
if (reg.invert)
val = reg.mask - val;
nreg = oreg & ~(reg.mask << reg.lchan_shift);
nreg |= (val << reg.lchan_shift);
if (reg.stereo) {
val = ucontrol->value.integer.value[1] & reg.mask;
if (reg.invert)
val = reg.mask - val;
nreg &= ~(reg.mask << reg.rchan_shift);
nreg |= (val << reg.rchan_shift);
}
if (reg.mask >= 0x07)
snd_azf3328_mixer_write_volume_gradually(
chip, reg.reg, nreg >> 8, nreg & 0xff,
SET_CHAN_LEFT|SET_CHAN_RIGHT,
0);
else
snd_azf3328_mixer_outw(chip, reg.reg, nreg);
dev_dbg(chip->card->dev,
"put: %02x to %02lx|%02lx, oreg %04x; shift %02d|%02d -> nreg %04x; after: %04x\n",
reg.reg, ucontrol->value.integer.value[0], ucontrol->value.integer.value[1],
oreg, reg.lchan_shift, reg.rchan_shift,
nreg, snd_azf3328_mixer_inw(chip, reg.reg));
return (nreg != oreg);
}
static int
snd_azf3328_info_mixer_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
static const char * const texts1[] = {
"Mic1", "Mic2"
};
static const char * const texts2[] = {
"Mix", "Mic"
};
static const char * const texts3[] = {
"Mic", "CD", "Video", "Aux",
"Line", "Mix", "Mix Mono", "Phone"
};
static const char * const texts4[] = {
"pre 3D", "post 3D"
};
struct azf3328_mixer_reg reg;
const char * const *p = NULL;
snd_azf3328_mixer_reg_decode(®, kcontrol->private_value);
if (reg.reg == IDX_MIXER_ADVCTL2) {
switch(reg.lchan_shift) {
case 8:
p = texts1;
break;
case 9:
p = texts2;
break;
case 15:
p = texts4;
break;
}
} else if (reg.reg == IDX_MIXER_REC_SELECT)
p = texts3;
return snd_ctl_enum_info(uinfo,
(reg.reg == IDX_MIXER_REC_SELECT) ? 2 : 1,
reg.enum_c, p);
}
static int
snd_azf3328_get_mixer_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
struct azf3328_mixer_reg reg;
unsigned short val;
snd_azf3328_mixer_reg_decode(®, kcontrol->private_value);
val = snd_azf3328_mixer_inw(chip, reg.reg);
if (reg.reg == IDX_MIXER_REC_SELECT) {
ucontrol->value.enumerated.item[0] = (val >> 8) & (reg.enum_c - 1);
ucontrol->value.enumerated.item[1] = (val >> 0) & (reg.enum_c - 1);
} else
ucontrol->value.enumerated.item[0] = (val >> reg.lchan_shift) & (reg.enum_c - 1);
dev_dbg(chip->card->dev,
"get_enum: %02x is %04x -> %d|%d (shift %02d, enum_c %d)\n",
reg.reg, val, ucontrol->value.enumerated.item[0], ucontrol->value.enumerated.item[1],
reg.lchan_shift, reg.enum_c);
return 0;
}
static int
snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
struct azf3328_mixer_reg reg;
u16 oreg, nreg, val;
snd_azf3328_mixer_reg_decode(®, kcontrol->private_value);
oreg = snd_azf3328_mixer_inw(chip, reg.reg);
val = oreg;
if (reg.reg == IDX_MIXER_REC_SELECT) {
if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U ||
ucontrol->value.enumerated.item[1] > reg.enum_c - 1U)
return -EINVAL;
val = (ucontrol->value.enumerated.item[0] << 8) |
(ucontrol->value.enumerated.item[1] << 0);
} else {
if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U)
return -EINVAL;
val &= ~((reg.enum_c - 1) << reg.lchan_shift);
val |= (ucontrol->value.enumerated.item[0] << reg.lchan_shift);
}
snd_azf3328_mixer_outw(chip, reg.reg, val);
nreg = val;
dev_dbg(chip->card->dev,
"put_enum: %02x to %04x, oreg %04x\n", reg.reg, val, oreg);
return (nreg != oreg);
}
static const struct snd_kcontrol_new snd_azf3328_mixer_controls[] = {
AZF3328_MIXER_SWITCH("Master Playback Switch", IDX_MIXER_PLAY_MASTER, 15, 1),
AZF3328_MIXER_VOL_STEREO("Master Playback Volume", IDX_MIXER_PLAY_MASTER, 0x1f, 1),
AZF3328_MIXER_SWITCH("PCM Playback Switch", IDX_MIXER_WAVEOUT, 15, 1),
AZF3328_MIXER_VOL_STEREO("PCM Playback Volume",
IDX_MIXER_WAVEOUT, 0x1f, 1),
AZF3328_MIXER_SWITCH("PCM 3D Bypass Playback Switch",
IDX_MIXER_ADVCTL2, 7, 1),
AZF3328_MIXER_SWITCH("FM Playback Switch", IDX_MIXER_FMSYNTH, 15, 1),
AZF3328_MIXER_VOL_STEREO("FM Playback Volume", IDX_MIXER_FMSYNTH, 0x1f, 1),
AZF3328_MIXER_SWITCH("CD Playback Switch", IDX_MIXER_CDAUDIO, 15, 1),
AZF3328_MIXER_VOL_STEREO("CD Playback Volume", IDX_MIXER_CDAUDIO, 0x1f, 1),
AZF3328_MIXER_SWITCH("Capture Switch", IDX_MIXER_REC_VOLUME, 15, 1),
AZF3328_MIXER_VOL_STEREO("Capture Volume", IDX_MIXER_REC_VOLUME, 0x0f, 0),
AZF3328_MIXER_ENUM("Capture Source", IDX_MIXER_REC_SELECT, 8, 0),
AZF3328_MIXER_SWITCH("Mic Playback Switch", IDX_MIXER_MIC, 15, 1),
AZF3328_MIXER_VOL_MONO("Mic Playback Volume", IDX_MIXER_MIC, 0x1f, 1),
AZF3328_MIXER_SWITCH("Mic Boost (+20dB)", IDX_MIXER_MIC, 6, 0),
AZF3328_MIXER_SWITCH("Line Playback Switch", IDX_MIXER_LINEIN, 15, 1),
AZF3328_MIXER_VOL_STEREO("Line Playback Volume", IDX_MIXER_LINEIN, 0x1f, 1),
AZF3328_MIXER_SWITCH("Beep Playback Switch", IDX_MIXER_PCBEEP, 15, 1),
AZF3328_MIXER_VOL_SPECIAL("Beep Playback Volume", IDX_MIXER_PCBEEP, 0x0f, 1, 1),
AZF3328_MIXER_SWITCH("Video Playback Switch", IDX_MIXER_VIDEO, 15, 1),
AZF3328_MIXER_VOL_STEREO("Video Playback Volume", IDX_MIXER_VIDEO, 0x1f, 1),
AZF3328_MIXER_SWITCH("Aux Playback Switch", IDX_MIXER_AUX, 15, 1),
AZF3328_MIXER_VOL_STEREO("Aux Playback Volume", IDX_MIXER_AUX, 0x1f, 1),
AZF3328_MIXER_SWITCH("Modem Playback Switch", IDX_MIXER_MODEMOUT, 15, 1),
AZF3328_MIXER_VOL_MONO("Modem Playback Volume", IDX_MIXER_MODEMOUT, 0x1f, 1),
AZF3328_MIXER_SWITCH("Modem Capture Switch", IDX_MIXER_MODEMIN, 15, 1),
AZF3328_MIXER_VOL_MONO("Modem Capture Volume", IDX_MIXER_MODEMIN, 0x1f, 1),
AZF3328_MIXER_ENUM("Mic Select", IDX_MIXER_ADVCTL2, 2, 8),
AZF3328_MIXER_ENUM("Mono Output Select", IDX_MIXER_ADVCTL2, 2, 9),
AZF3328_MIXER_ENUM("PCM Output Route", IDX_MIXER_ADVCTL2, 2, 15),
AZF3328_MIXER_VOL_SPECIAL("Tone Control - Treble", IDX_MIXER_BASSTREBLE, 0x07, 1, 0),
AZF3328_MIXER_VOL_SPECIAL("Tone Control - Bass", IDX_MIXER_BASSTREBLE, 0x07, 9, 0),
AZF3328_MIXER_SWITCH("3D Control - Switch", IDX_MIXER_ADVCTL2, 13, 0),
AZF3328_MIXER_VOL_SPECIAL("3D Control - Width", IDX_MIXER_ADVCTL1, 0x07, 1, 0),
AZF3328_MIXER_VOL_SPECIAL("3D Control - Depth", IDX_MIXER_ADVCTL1, 0x03, 8, 0),
#if MIXER_TESTING
AZF3328_MIXER_SWITCH("0", IDX_MIXER_ADVCTL2, 0, 0),
AZF3328_MIXER_SWITCH("1", IDX_MIXER_ADVCTL2, 1, 0),
AZF3328_MIXER_SWITCH("2", IDX_MIXER_ADVCTL2, 2, 0),
AZF3328_MIXER_SWITCH("3", IDX_MIXER_ADVCTL2, 3, 0),
AZF3328_MIXER_SWITCH("4", IDX_MIXER_ADVCTL2, 4, 0),
AZF3328_MIXER_SWITCH("5", IDX_MIXER_ADVCTL2, 5, 0),
AZF3328_MIXER_SWITCH("6", IDX_MIXER_ADVCTL2, 6, 0),
AZF3328_MIXER_SWITCH("7", IDX_MIXER_ADVCTL2, 7, 0),
AZF3328_MIXER_SWITCH("8", IDX_MIXER_ADVCTL2, 8, 0),
AZF3328_MIXER_SWITCH("9", IDX_MIXER_ADVCTL2, 9, 0),
AZF3328_MIXER_SWITCH("10", IDX_MIXER_ADVCTL2, 10, 0),
AZF3328_MIXER_SWITCH("11", IDX_MIXER_ADVCTL2, 11, 0),
AZF3328_MIXER_SWITCH("12", IDX_MIXER_ADVCTL2, 12, 0),
AZF3328_MIXER_SWITCH("13", IDX_MIXER_ADVCTL2, 13, 0),
AZF3328_MIXER_SWITCH("14", IDX_MIXER_ADVCTL2, 14, 0),
AZF3328_MIXER_SWITCH("15", IDX_MIXER_ADVCTL2, 15, 0),
#endif
};
static const u16 snd_azf3328_init_values[][2] = {
{ IDX_MIXER_PLAY_MASTER, MIXER_MUTE_MASK|0x1f1f },
{ IDX_MIXER_MODEMOUT, MIXER_MUTE_MASK|0x1f1f },
{ IDX_MIXER_BASSTREBLE, 0x0000 },
{ IDX_MIXER_PCBEEP, MIXER_MUTE_MASK|0x1f1f },
{ IDX_MIXER_MODEMIN, MIXER_MUTE_MASK|0x1f1f },
{ IDX_MIXER_MIC, MIXER_MUTE_MASK|0x001f },
{ IDX_MIXER_LINEIN, MIXER_MUTE_MASK|0x1f1f },
{ IDX_MIXER_CDAUDIO, MIXER_MUTE_MASK|0x1f1f },
{ IDX_MIXER_VIDEO, MIXER_MUTE_MASK|0x1f1f },
{ IDX_MIXER_AUX, MIXER_MUTE_MASK|0x1f1f },
{ IDX_MIXER_WAVEOUT, MIXER_MUTE_MASK|0x1f1f },
{ IDX_MIXER_FMSYNTH, MIXER_MUTE_MASK|0x1f1f },
{ IDX_MIXER_REC_VOLUME, MIXER_MUTE_MASK|0x0707 },
};
static int
snd_azf3328_mixer_new(struct snd_azf3328 *chip)
{
struct snd_card *card;
const struct snd_kcontrol_new *sw;
unsigned int idx;
int err;
if (snd_BUG_ON(!chip || !chip->card))
return -EINVAL;
card = chip->card;
snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000);
for (idx = 0; idx < ARRAY_SIZE(snd_azf3328_init_values); ++idx) {
snd_azf3328_mixer_outw(chip,
snd_azf3328_init_values[idx][0],
snd_azf3328_init_values[idx][1]);
}
sw = snd_azf3328_mixer_controls;
for (idx = 0; idx < ARRAY_SIZE(snd_azf3328_mixer_controls);
++idx, ++sw) {
err = snd_ctl_add(chip->card, snd_ctl_new1(sw, chip));
if (err < 0)
return err;
}
snd_component_add(card, "AZF3328 mixer");
strcpy(card->mixername, "AZF3328 mixer");
return 0;
}
#endif
static void
snd_azf3328_codec_setfmt(struct snd_azf3328_codec_data *codec,
enum azf_freq_t bitrate,
unsigned int format_width,
unsigned int channels
)
{ … }
static inline void
snd_azf3328_codec_setfmt_lowpower(struct snd_azf3328_codec_data *codec
)
{ … }
static void
snd_azf3328_ctrl_reg_6AH_update(struct snd_azf3328 *chip,
unsigned bitmask,
bool enable
)
{ … }
static inline void
snd_azf3328_ctrl_enable_codecs(struct snd_azf3328 *chip, bool enable)
{ … }
static void
snd_azf3328_ctrl_codec_activity(struct snd_azf3328 *chip,
enum snd_azf3328_codec_type codec_type,
bool enable
)
{ … }
static void
snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip,
struct snd_azf3328_codec_data *codec,
unsigned long addr,
unsigned int period_bytes,
unsigned int buffer_bytes
)
{ … }
static int
snd_azf3328_pcm_prepare(struct snd_pcm_substream *substream)
{ … }
static int
snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{ … }
static snd_pcm_uframes_t
snd_azf3328_pcm_pointer(struct snd_pcm_substream *substream
)
{ … }
#ifdef SUPPORT_GAMEPORT
static inline void
snd_azf3328_gameport_irq_enable(struct snd_azf3328 *chip,
bool enable
)
{ … }
static inline void
snd_azf3328_gameport_legacy_address_enable(struct snd_azf3328 *chip,
bool enable
)
{ … }
static void
snd_azf3328_gameport_set_counter_frequency(struct snd_azf3328 *chip,
unsigned int freq_cfg
)
{ … }
static inline void
snd_azf3328_gameport_axis_circuit_enable(struct snd_azf3328 *chip, bool enable)
{ … }
static inline void
snd_azf3328_gameport_interrupt(struct snd_azf3328 *chip)
{ … }
static int
snd_azf3328_gameport_open(struct gameport *gameport, int mode)
{ … }
static void
snd_azf3328_gameport_close(struct gameport *gameport)
{ … }
static int
snd_azf3328_gameport_cooked_read(struct gameport *gameport,
int *axes,
int *buttons
)
{ … }
static int
snd_azf3328_gameport(struct snd_azf3328 *chip, int dev)
{ … }
static void
snd_azf3328_gameport_free(struct snd_azf3328 *chip)
{ … }
#else
static inline int
snd_azf3328_gameport(struct snd_azf3328 *chip, int dev) { return -ENOSYS; }
static inline void
snd_azf3328_gameport_free(struct snd_azf3328 *chip) { }
static inline void
snd_azf3328_gameport_interrupt(struct snd_azf3328 *chip)
{
dev_warn(chip->card->dev, "huh, game port IRQ occurred!?\n");
}
#endif
static inline void
snd_azf3328_irq_log_unknown_type(struct snd_azf3328 *chip, u8 which)
{ … }
static inline void
snd_azf3328_pcm_interrupt(struct snd_azf3328 *chip,
const struct snd_azf3328_codec_data *first_codec,
u8 status
)
{ … }
static irqreturn_t
snd_azf3328_interrupt(int irq, void *dev_id)
{ … }
static const struct snd_pcm_hardware snd_azf3328_hardware = …;
static const unsigned int snd_azf3328_fixed_rates[] = …;
static const struct snd_pcm_hw_constraint_list snd_azf3328_hw_constraints_rates = …;
static int
snd_azf3328_pcm_open(struct snd_pcm_substream *substream,
enum snd_azf3328_codec_type codec_type
)
{ … }
static int
snd_azf3328_pcm_playback_open(struct snd_pcm_substream *substream)
{ … }
static int
snd_azf3328_pcm_capture_open(struct snd_pcm_substream *substream)
{ … }
static int
snd_azf3328_pcm_i2s_out_open(struct snd_pcm_substream *substream)
{ … }
static int
snd_azf3328_pcm_close(struct snd_pcm_substream *substream
)
{ … }
static const struct snd_pcm_ops snd_azf3328_playback_ops = …;
static const struct snd_pcm_ops snd_azf3328_capture_ops = …;
static const struct snd_pcm_ops snd_azf3328_i2s_out_ops = …;
static int
snd_azf3328_pcm(struct snd_azf3328 *chip)
{ … }
static int
snd_azf3328_timer_start(struct snd_timer *timer)
{ … }
static int
snd_azf3328_timer_stop(struct snd_timer *timer)
{ … }
static int
snd_azf3328_timer_precise_resolution(struct snd_timer *timer,
unsigned long *num, unsigned long *den)
{ … }
static struct snd_timer_hardware snd_azf3328_timer_hw = …;
static int
snd_azf3328_timer(struct snd_azf3328 *chip, int device)
{ … }
static void
snd_azf3328_free(struct snd_card *card)
{ … }
#if 0
static void
snd_azf3328_test_bit(unsigned unsigned reg, int bit)
{
unsigned char val, valoff, valon;
val = inb(reg);
outb(val & ~(1 << bit), reg);
valoff = inb(reg);
outb(val|(1 << bit), reg);
valon = inb(reg);
outb(val, reg);
printk(KERN_DEBUG "reg %04x bit %d: %02x %02x %02x\n",
reg, bit, val, valoff, valon
);
}
#endif
static inline void
snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip)
{ … }
static int
snd_azf3328_create(struct snd_card *card,
struct pci_dev *pci,
unsigned long device_type)
{ … }
static int
__snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
{ … }
static int
snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
{ … }
static inline void
snd_azf3328_suspend_regs(const struct snd_azf3328 *chip,
unsigned long io_addr, unsigned count, u32 *saved_regs)
{ … }
static inline void
snd_azf3328_resume_regs(const struct snd_azf3328 *chip,
const u32 *saved_regs,
unsigned long io_addr,
unsigned count
)
{ … }
static inline void
snd_azf3328_suspend_ac97(struct snd_azf3328 *chip)
{ … }
static inline void
snd_azf3328_resume_ac97(const struct snd_azf3328 *chip)
{ … }
static int
snd_azf3328_suspend(struct device *dev)
{ … }
static int
snd_azf3328_resume(struct device *dev)
{ … }
static DEFINE_SIMPLE_DEV_PM_OPS(snd_azf3328_pm, snd_azf3328_suspend, snd_azf3328_resume);
static struct pci_driver azf3328_driver = …;
module_pci_driver(…) …;