Commit da237f35 authored by Andreas Mohr's avatar Andreas Mohr Committed by Takashi Iwai

ALSA: azt3328: use proper private_data hookup for codec identification

- much improved implementation due to clean codec hierarchy
- preparation for potential per-codec spinlock change

NOTE: additionally removes a chip->pcm[codec_type] NULL ptr check
(due to it requiring access to external chip struct),
however I believe this to be ok since this condition should not occur
and most drivers don't check against that either.
Signed-off-by: default avatarAndreas Mohr <andi@lisas.de>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 34585595
...@@ -292,14 +292,6 @@ static int seqtimer_scaling = 128; ...@@ -292,14 +292,6 @@ static int seqtimer_scaling = 128;
module_param(seqtimer_scaling, int, 0444); module_param(seqtimer_scaling, int, 0444);
MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128."); MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128.");
struct snd_azf3328_codec_data {
unsigned long io_base;
unsigned int dma_base; /* helper to avoid an indirection in hotpath */
struct snd_pcm_substream *substream;
bool running;
const char *name;
};
enum snd_azf3328_codec_type { enum snd_azf3328_codec_type {
/* warning: fixed indices (also used for bitmask checks!) */ /* warning: fixed indices (also used for bitmask checks!) */
AZF_CODEC_PLAYBACK = 0, AZF_CODEC_PLAYBACK = 0,
...@@ -307,6 +299,16 @@ enum snd_azf3328_codec_type { ...@@ -307,6 +299,16 @@ enum snd_azf3328_codec_type {
AZF_CODEC_I2S_OUT = 2, AZF_CODEC_I2S_OUT = 2,
}; };
struct snd_azf3328_codec_data {
unsigned long io_base; /* keep first! (avoid offset calc) */
unsigned int dma_base; /* helper to avoid an indirection in hotpath */
spinlock_t *lock; /* TODO: convert to our own per-codec lock member */
struct snd_pcm_substream *substream;
bool running;
enum snd_azf3328_codec_type type;
const char *name;
};
struct snd_azf3328 { struct snd_azf3328 {
/* often-used fields towards beginning, then grouped */ /* often-used fields towards beginning, then grouped */
...@@ -949,15 +951,13 @@ snd_azf3328_hw_free(struct snd_pcm_substream *substream) ...@@ -949,15 +951,13 @@ snd_azf3328_hw_free(struct snd_pcm_substream *substream)
} }
static void static void
snd_azf3328_codec_setfmt(struct snd_azf3328 *chip, snd_azf3328_codec_setfmt(struct snd_azf3328_codec_data *codec,
enum snd_azf3328_codec_type codec_type,
enum azf_freq_t bitrate, enum azf_freq_t bitrate,
unsigned int format_width, unsigned int format_width,
unsigned int channels unsigned int channels
) )
{ {
unsigned long flags; unsigned long flags;
const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
u16 val = 0xff00; u16 val = 0xff00;
u8 freq = 0; u8 freq = 0;
...@@ -1007,7 +1007,7 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip, ...@@ -1007,7 +1007,7 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip,
if (format_width == 16) if (format_width == 16)
val |= SOUNDFORMAT_FLAG_16BIT; val |= SOUNDFORMAT_FLAG_16BIT;
spin_lock_irqsave(&chip->reg_lock, flags); spin_lock_irqsave(codec->lock, flags);
/* set bitrate/format */ /* set bitrate/format */
snd_azf3328_codec_outw(codec, IDX_IO_CODEC_SOUNDFORMAT, val); snd_azf3328_codec_outw(codec, IDX_IO_CODEC_SOUNDFORMAT, val);
...@@ -1020,7 +1020,7 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip, ...@@ -1020,7 +1020,7 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip,
* FIXME: does this have some side effects for full-duplex * FIXME: does this have some side effects for full-duplex
* or other dramatic side effects? */ * or other dramatic side effects? */
/* do it for non-capture codecs only */ /* do it for non-capture codecs only */
if (codec_type == AZF_CODEC_PLAYBACK) if (codec->type != AZF_CODEC_CAPTURE)
snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS) | snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS) |
DMA_RUN_SOMETHING1 | DMA_RUN_SOMETHING1 |
...@@ -1030,20 +1030,19 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip, ...@@ -1030,20 +1030,19 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip,
DMA_SOMETHING_ELSE DMA_SOMETHING_ELSE
); );
spin_unlock_irqrestore(&chip->reg_lock, flags); spin_unlock_irqrestore(codec->lock, flags);
snd_azf3328_dbgcallleave(); snd_azf3328_dbgcallleave();
} }
static inline void static inline void
snd_azf3328_codec_setfmt_lowpower(struct snd_azf3328 *chip, snd_azf3328_codec_setfmt_lowpower(struct snd_azf3328_codec_data *codec
enum snd_azf3328_codec_type codec_type
) )
{ {
/* choose lowest frequency for low power consumption. /* choose lowest frequency for low power consumption.
* While this will cause louder noise due to rather coarse frequency, * While this will cause louder noise due to rather coarse frequency,
* it should never matter since output should always * it should never matter since output should always
* get disabled properly when idle anyway. */ * get disabled properly when idle anyway. */
snd_azf3328_codec_setfmt(chip, codec_type, AZF_FREQ_4000, 8, 1); snd_azf3328_codec_setfmt(codec, AZF_FREQ_4000, 8, 1);
} }
static void static void
...@@ -1117,23 +1116,18 @@ snd_azf3328_ctrl_codec_activity(struct snd_azf3328 *chip, ...@@ -1117,23 +1116,18 @@ snd_azf3328_ctrl_codec_activity(struct snd_azf3328 *chip,
/* ...and adjust clock, too /* ...and adjust clock, too
* (reduce noise and power consumption) */ * (reduce noise and power consumption) */
if (!enable) if (!enable)
snd_azf3328_codec_setfmt_lowpower( snd_azf3328_codec_setfmt_lowpower(codec);
chip,
codec_type
);
codec->running = enable; codec->running = enable;
} }
} }
static void static void
snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip, snd_azf3328_codec_setdmaa(struct snd_azf3328_codec_data *codec,
enum snd_azf3328_codec_type codec_type,
unsigned long addr, unsigned long addr,
unsigned int count, unsigned int count,
unsigned int size unsigned int size
) )
{ {
const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
snd_azf3328_dbgcallenter(); snd_azf3328_dbgcallenter();
if (!codec->running) { if (!codec->running) {
/* AZF3328 uses a two buffer pointer DMA transfer approach */ /* AZF3328 uses a two buffer pointer DMA transfer approach */
...@@ -1152,22 +1146,22 @@ snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip, ...@@ -1152,22 +1146,22 @@ snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip,
/* build combined I/O buffer length word */ /* build combined I/O buffer length word */
lengths = (count_areas << 16) | (count_areas); lengths = (count_areas << 16) | (count_areas);
spin_lock_irqsave(&chip->reg_lock, flags); spin_lock_irqsave(codec->lock, flags);
snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_1, addr); snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_1, addr);
snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_2, snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_2,
addr_area2); addr_area2);
snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_LENGTHS, snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_LENGTHS,
lengths); lengths);
spin_unlock_irqrestore(&chip->reg_lock, flags); spin_unlock_irqrestore(codec->lock, flags);
} }
snd_azf3328_dbgcallleave(); snd_azf3328_dbgcallleave();
} }
static int static int
snd_azf3328_codec_prepare(struct snd_pcm_substream *substream) snd_azf3328_pcm_prepare(struct snd_pcm_substream *substream)
{ {
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_azf3328_codec *codec = runtime->private_data; struct snd_azf3328_codec_data *codec = runtime->private_data;
#if 0 #if 0
unsigned int size = snd_pcm_lib_buffer_bytes(substream); unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream); unsigned int count = snd_pcm_lib_period_bytes(substream);
...@@ -1178,11 +1172,11 @@ snd_azf3328_codec_prepare(struct snd_pcm_substream *substream) ...@@ -1178,11 +1172,11 @@ snd_azf3328_codec_prepare(struct snd_pcm_substream *substream)
codec->dma_base = runtime->dma_addr; codec->dma_base = runtime->dma_addr;
#if 0 #if 0
snd_azf3328_codec_setfmt(chip, AZF_CODEC_..., snd_azf3328_codec_setfmt(codec,
runtime->rate, runtime->rate,
snd_pcm_format_width(runtime->format), snd_pcm_format_width(runtime->format),
runtime->channels); runtime->channels);
snd_azf3328_codec_setdmaa(chip, AZF_CODEC_..., snd_azf3328_codec_setdmaa(codec,
runtime->dma_addr, count, size); runtime->dma_addr, count, size);
#endif #endif
snd_azf3328_dbgcallleave(); snd_azf3328_dbgcallleave();
...@@ -1190,24 +1184,23 @@ snd_azf3328_codec_prepare(struct snd_pcm_substream *substream) ...@@ -1190,24 +1184,23 @@ snd_azf3328_codec_prepare(struct snd_pcm_substream *substream)
} }
static int static int
snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
struct snd_pcm_substream *substream, int cmd)
{ {
struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_azf3328_codec_data *codec = runtime->private_data;
int result = 0; int result = 0;
u16 flags1; u16 flags1;
bool previously_muted = 0; bool previously_muted = 0;
bool is_playback_codec = (AZF_CODEC_PLAYBACK == codec_type); bool is_main_mixer_playback_codec = (AZF_CODEC_PLAYBACK == codec->type);
snd_azf3328_dbgcalls("snd_azf3328_codec_trigger cmd %d\n", cmd); snd_azf3328_dbgcalls("snd_azf3328_pcm_trigger cmd %d\n", cmd);
switch (cmd) { switch (cmd) {
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:
snd_azf3328_dbgcodec("START %s\n", codec->name); snd_azf3328_dbgcodec("START %s\n", codec->name);
if (is_playback_codec) { if (is_main_mixer_playback_codec) {
/* mute WaveOut (avoid clicking during setup) */ /* mute WaveOut (avoid clicking during setup) */
previously_muted = previously_muted =
snd_azf3328_mixer_set_mute( snd_azf3328_mixer_set_mute(
...@@ -1215,12 +1208,12 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, ...@@ -1215,12 +1208,12 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type,
); );
} }
snd_azf3328_codec_setfmt(chip, codec_type, snd_azf3328_codec_setfmt(codec,
runtime->rate, runtime->rate,
snd_pcm_format_width(runtime->format), snd_pcm_format_width(runtime->format),
runtime->channels); runtime->channels);
spin_lock(&chip->reg_lock); spin_lock(codec->lock);
/* first, remember current value: */ /* first, remember current value: */
flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS); flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS);
...@@ -1230,14 +1223,14 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, ...@@ -1230,14 +1223,14 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type,
/* FIXME: clear interrupts or what??? */ /* FIXME: clear interrupts or what??? */
snd_azf3328_codec_outw(codec, IDX_IO_CODEC_IRQTYPE, 0xffff); snd_azf3328_codec_outw(codec, IDX_IO_CODEC_IRQTYPE, 0xffff);
spin_unlock(&chip->reg_lock); spin_unlock(codec->lock);
snd_azf3328_codec_setdmaa(chip, codec_type, runtime->dma_addr, snd_azf3328_codec_setdmaa(codec, runtime->dma_addr,
snd_pcm_lib_period_bytes(substream), snd_pcm_lib_period_bytes(substream),
snd_pcm_lib_buffer_bytes(substream) snd_pcm_lib_buffer_bytes(substream)
); );
spin_lock(&chip->reg_lock); spin_lock(codec->lock);
#ifdef WIN9X #ifdef WIN9X
/* FIXME: enable playback/recording??? */ /* FIXME: enable playback/recording??? */
flags1 |= DMA_RUN_SOMETHING1 | DMA_RUN_SOMETHING2; flags1 |= DMA_RUN_SOMETHING1 | DMA_RUN_SOMETHING2;
...@@ -1261,10 +1254,10 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, ...@@ -1261,10 +1254,10 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type,
DMA_EPILOGUE_SOMETHING | DMA_EPILOGUE_SOMETHING |
DMA_SOMETHING_ELSE); DMA_SOMETHING_ELSE);
#endif #endif
spin_unlock(&chip->reg_lock); spin_unlock(codec->lock);
snd_azf3328_ctrl_codec_activity(chip, codec_type, 1); snd_azf3328_ctrl_codec_activity(chip, codec->type, 1);
if (is_playback_codec) { if (is_main_mixer_playback_codec) {
/* now unmute WaveOut */ /* now unmute WaveOut */
if (!previously_muted) if (!previously_muted)
snd_azf3328_mixer_set_mute( snd_azf3328_mixer_set_mute(
...@@ -1277,19 +1270,19 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, ...@@ -1277,19 +1270,19 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type,
case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_RESUME:
snd_azf3328_dbgcodec("RESUME %s\n", codec->name); snd_azf3328_dbgcodec("RESUME %s\n", codec->name);
/* resume codec if we were active */ /* resume codec if we were active */
spin_lock(&chip->reg_lock); spin_lock(codec->lock);
if (codec->running) if (codec->running)
snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
snd_azf3328_codec_inw( snd_azf3328_codec_inw(
codec, IDX_IO_CODEC_DMA_FLAGS codec, IDX_IO_CODEC_DMA_FLAGS
) | DMA_RESUME ) | DMA_RESUME
); );
spin_unlock(&chip->reg_lock); spin_unlock(codec->lock);
break; break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
snd_azf3328_dbgcodec("STOP %s\n", codec->name); snd_azf3328_dbgcodec("STOP %s\n", codec->name);
if (is_playback_codec) { if (is_main_mixer_playback_codec) {
/* mute WaveOut (avoid clicking during setup) */ /* mute WaveOut (avoid clicking during setup) */
previously_muted = previously_muted =
snd_azf3328_mixer_set_mute( snd_azf3328_mixer_set_mute(
...@@ -1297,7 +1290,7 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, ...@@ -1297,7 +1290,7 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type,
); );
} }
spin_lock(&chip->reg_lock); spin_lock(codec->lock);
/* first, remember current value: */ /* first, remember current value: */
flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS); flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS);
...@@ -1312,10 +1305,10 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, ...@@ -1312,10 +1305,10 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type,
flags1 &= ~DMA_RUN_SOMETHING1; flags1 &= ~DMA_RUN_SOMETHING1;
snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
spin_unlock(&chip->reg_lock); spin_unlock(codec->lock);
snd_azf3328_ctrl_codec_activity(chip, codec_type, 0); snd_azf3328_ctrl_codec_activity(chip, codec->type, 0);
if (is_playback_codec) { if (is_main_mixer_playback_codec) {
/* now unmute WaveOut */ /* now unmute WaveOut */
if (!previously_muted) if (!previously_muted)
snd_azf3328_mixer_set_mute( snd_azf3328_mixer_set_mute(
...@@ -1349,31 +1342,12 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, ...@@ -1349,31 +1342,12 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type,
return result; return result;
} }
static int
snd_azf3328_codec_playback_trigger(struct snd_pcm_substream *substream, int cmd)
{
return snd_azf3328_codec_trigger(AZF_CODEC_PLAYBACK, substream, cmd);
}
static int
snd_azf3328_codec_capture_trigger(struct snd_pcm_substream *substream, int cmd)
{
return snd_azf3328_codec_trigger(AZF_CODEC_CAPTURE, substream, cmd);
}
static int
snd_azf3328_codec_i2s_out_trigger(struct snd_pcm_substream *substream, int cmd)
{
return snd_azf3328_codec_trigger(AZF_CODEC_I2S_OUT, substream, cmd);
}
static snd_pcm_uframes_t static snd_pcm_uframes_t
snd_azf3328_codec_pointer(struct snd_pcm_substream *substream, snd_azf3328_pcm_pointer(struct snd_pcm_substream *substream
enum snd_azf3328_codec_type codec_type
) )
{ {
const struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); const struct snd_azf3328_codec_data *codec =
const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; substream->runtime->private_data;
unsigned long result; unsigned long result;
snd_pcm_uframes_t frmres; snd_pcm_uframes_t frmres;
...@@ -1391,24 +1365,6 @@ snd_azf3328_codec_pointer(struct snd_pcm_substream *substream, ...@@ -1391,24 +1365,6 @@ snd_azf3328_codec_pointer(struct snd_pcm_substream *substream,
return frmres; return frmres;
} }
static snd_pcm_uframes_t
snd_azf3328_codec_playback_pointer(struct snd_pcm_substream *substream)
{
return snd_azf3328_codec_pointer(substream, AZF_CODEC_PLAYBACK);
}
static snd_pcm_uframes_t
snd_azf3328_codec_capture_pointer(struct snd_pcm_substream *substream)
{
return snd_azf3328_codec_pointer(substream, AZF_CODEC_CAPTURE);
}
static snd_pcm_uframes_t
snd_azf3328_codec_i2s_out_pointer(struct snd_pcm_substream *substream)
{
return snd_azf3328_codec_pointer(substream, AZF_CODEC_I2S_OUT);
}
/******************************************************************/ /******************************************************************/
#ifdef SUPPORT_GAMEPORT #ifdef SUPPORT_GAMEPORT
...@@ -1642,29 +1598,29 @@ snd_azf3328_irq_log_unknown_type(u8 which) ...@@ -1642,29 +1598,29 @@ snd_azf3328_irq_log_unknown_type(u8 which)
} }
static inline void static inline void
snd_azf3328_codec_interrupt(struct snd_azf3328 *chip, u8 status) snd_azf3328_pcm_interrupt(const struct snd_azf3328_codec_data *first_codec,
u8 status
)
{ {
u8 which; u8 which;
enum snd_azf3328_codec_type codec_type; enum snd_azf3328_codec_type codec_type;
const struct snd_azf3328_codec_data *codec; const struct snd_azf3328_codec_data *codec = first_codec;
for (codec_type = AZF_CODEC_PLAYBACK; for (codec_type = AZF_CODEC_PLAYBACK;
codec_type <= AZF_CODEC_I2S_OUT; codec_type <= AZF_CODEC_I2S_OUT;
++codec_type) { ++codec_type, ++codec) {
/* skip codec if there's no interrupt for it */ /* skip codec if there's no interrupt for it */
if (!(status & (1 << codec_type))) if (!(status & (1 << codec_type)))
continue; continue;
codec = &chip->codecs[codec_type]; spin_lock(codec->lock);
spin_lock(&chip->reg_lock);
which = snd_azf3328_codec_inb(codec, IDX_IO_CODEC_IRQTYPE); which = snd_azf3328_codec_inb(codec, IDX_IO_CODEC_IRQTYPE);
/* ack all IRQ types immediately */ /* ack all IRQ types immediately */
snd_azf3328_codec_outb(codec, IDX_IO_CODEC_IRQTYPE, which); snd_azf3328_codec_outb(codec, IDX_IO_CODEC_IRQTYPE, which);
spin_unlock(&chip->reg_lock); spin_unlock(codec->lock);
if ((chip->pcm[codec_type]) && (codec->substream)) { if (codec->substream) {
snd_pcm_period_elapsed(codec->substream); snd_pcm_period_elapsed(codec->substream);
snd_azf3328_dbgcodec("%s period done (#%x), @ %x\n", snd_azf3328_dbgcodec("%s period done (#%x), @ %x\n",
codec->name, codec->name,
...@@ -1719,7 +1675,7 @@ snd_azf3328_interrupt(int irq, void *dev_id) ...@@ -1719,7 +1675,7 @@ snd_azf3328_interrupt(int irq, void *dev_id)
} }
if (status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT)) if (status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT))
snd_azf3328_codec_interrupt(chip, status); snd_azf3328_pcm_interrupt(chip->codecs, status);
if (status & IRQ_GAMEPORT) if (status & IRQ_GAMEPORT)
snd_azf3328_gameport_interrupt(chip); snd_azf3328_gameport_interrupt(chip);
...@@ -1807,101 +1763,85 @@ snd_azf3328_pcm_open(struct snd_pcm_substream *substream, ...@@ -1807,101 +1763,85 @@ snd_azf3328_pcm_open(struct snd_pcm_substream *substream,
{ {
struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
snd_azf3328_dbgcallenter(); snd_azf3328_dbgcallenter();
chip->codecs[codec_type].substream = substream; codec->substream = substream;
/* same parameters for all our codecs - at least we think so... */ /* same parameters for all our codecs - at least we think so... */
runtime->hw = snd_azf3328_hardware; runtime->hw = snd_azf3328_hardware;
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&snd_azf3328_hw_constraints_rates); &snd_azf3328_hw_constraints_rates);
runtime->private_data = codec;
snd_azf3328_dbgcallleave(); snd_azf3328_dbgcallleave();
return 0; return 0;
} }
static int static int
snd_azf3328_playback_open(struct snd_pcm_substream *substream) snd_azf3328_pcm_playback_open(struct snd_pcm_substream *substream)
{ {
return snd_azf3328_pcm_open(substream, AZF_CODEC_PLAYBACK); return snd_azf3328_pcm_open(substream, AZF_CODEC_PLAYBACK);
} }
static int static int
snd_azf3328_capture_open(struct snd_pcm_substream *substream) snd_azf3328_pcm_capture_open(struct snd_pcm_substream *substream)
{ {
return snd_azf3328_pcm_open(substream, AZF_CODEC_CAPTURE); return snd_azf3328_pcm_open(substream, AZF_CODEC_CAPTURE);
} }
static int static int
snd_azf3328_i2s_out_open(struct snd_pcm_substream *substream) snd_azf3328_pcm_i2s_out_open(struct snd_pcm_substream *substream)
{ {
return snd_azf3328_pcm_open(substream, AZF_CODEC_I2S_OUT); return snd_azf3328_pcm_open(substream, AZF_CODEC_I2S_OUT);
} }
static int static int
snd_azf3328_pcm_close(struct snd_pcm_substream *substream, snd_azf3328_pcm_close(struct snd_pcm_substream *substream
enum snd_azf3328_codec_type codec_type
) )
{ {
struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); struct snd_azf3328_codec_data *codec =
substream->runtime->private_data;
snd_azf3328_dbgcallenter(); snd_azf3328_dbgcallenter();
chip->codecs[codec_type].substream = NULL; codec->substream = NULL;
snd_azf3328_dbgcallleave(); snd_azf3328_dbgcallleave();
return 0; return 0;
} }
static int
snd_azf3328_playback_close(struct snd_pcm_substream *substream)
{
return snd_azf3328_pcm_close(substream, AZF_CODEC_PLAYBACK);
}
static int
snd_azf3328_capture_close(struct snd_pcm_substream *substream)
{
return snd_azf3328_pcm_close(substream, AZF_CODEC_CAPTURE);
}
static int
snd_azf3328_i2s_out_close(struct snd_pcm_substream *substream)
{
return snd_azf3328_pcm_close(substream, AZF_CODEC_I2S_OUT);
}
/******************************************************************/ /******************************************************************/
static struct snd_pcm_ops snd_azf3328_playback_ops = { static struct snd_pcm_ops snd_azf3328_playback_ops = {
.open = snd_azf3328_playback_open, .open = snd_azf3328_pcm_playback_open,
.close = snd_azf3328_playback_close, .close = snd_azf3328_pcm_close,
.ioctl = snd_pcm_lib_ioctl, .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_azf3328_hw_params, .hw_params = snd_azf3328_hw_params,
.hw_free = snd_azf3328_hw_free, .hw_free = snd_azf3328_hw_free,
.prepare = snd_azf3328_codec_prepare, .prepare = snd_azf3328_pcm_prepare,
.trigger = snd_azf3328_codec_playback_trigger, .trigger = snd_azf3328_pcm_trigger,
.pointer = snd_azf3328_codec_playback_pointer .pointer = snd_azf3328_pcm_pointer
}; };
static struct snd_pcm_ops snd_azf3328_capture_ops = { static struct snd_pcm_ops snd_azf3328_capture_ops = {
.open = snd_azf3328_capture_open, .open = snd_azf3328_pcm_capture_open,
.close = snd_azf3328_capture_close, .close = snd_azf3328_pcm_close,
.ioctl = snd_pcm_lib_ioctl, .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_azf3328_hw_params, .hw_params = snd_azf3328_hw_params,
.hw_free = snd_azf3328_hw_free, .hw_free = snd_azf3328_hw_free,
.prepare = snd_azf3328_codec_prepare, .prepare = snd_azf3328_pcm_prepare,
.trigger = snd_azf3328_codec_capture_trigger, .trigger = snd_azf3328_pcm_trigger,
.pointer = snd_azf3328_codec_capture_pointer .pointer = snd_azf3328_pcm_pointer
}; };
static struct snd_pcm_ops snd_azf3328_i2s_out_ops = { static struct snd_pcm_ops snd_azf3328_i2s_out_ops = {
.open = snd_azf3328_i2s_out_open, .open = snd_azf3328_pcm_i2s_out_open,
.close = snd_azf3328_i2s_out_close, .close = snd_azf3328_pcm_close,
.ioctl = snd_pcm_lib_ioctl, .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_azf3328_hw_params, .hw_params = snd_azf3328_hw_params,
.hw_free = snd_azf3328_hw_free, .hw_free = snd_azf3328_hw_free,
.prepare = snd_azf3328_codec_prepare, .prepare = snd_azf3328_pcm_prepare,
.trigger = snd_azf3328_codec_i2s_out_trigger, .trigger = snd_azf3328_pcm_trigger,
.pointer = snd_azf3328_codec_i2s_out_pointer .pointer = snd_azf3328_pcm_pointer
}; };
static int __devinit static int __devinit
...@@ -2198,7 +2138,7 @@ snd_azf3328_create(struct snd_card *card, ...@@ -2198,7 +2138,7 @@ snd_azf3328_create(struct snd_card *card,
}; };
u8 dma_init; u8 dma_init;
enum snd_azf3328_codec_type codec_type; enum snd_azf3328_codec_type codec_type;
struct snd_azf3328_codec *codec_setup; struct snd_azf3328_codec_data *codec_setup;
*rchip = NULL; *rchip = NULL;
...@@ -2238,14 +2178,20 @@ snd_azf3328_create(struct snd_card *card, ...@@ -2238,14 +2178,20 @@ snd_azf3328_create(struct snd_card *card,
codec_setup = &chip->codecs[AZF_CODEC_PLAYBACK]; codec_setup = &chip->codecs[AZF_CODEC_PLAYBACK];
codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_PLAYBACK; codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_PLAYBACK;
codec_setup->lock = &chip->reg_lock;
codec_setup->type = AZF_CODEC_PLAYBACK;
codec_setup->name = "PLAYBACK"; codec_setup->name = "PLAYBACK";
codec_setup = &chip->codecs[AZF_CODEC_CAPTURE]; codec_setup = &chip->codecs[AZF_CODEC_CAPTURE];
codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_CAPTURE; codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_CAPTURE;
codec_setup->lock = &chip->reg_lock;
codec_setup->type = AZF_CODEC_CAPTURE;
codec_setup->name = "CAPTURE"; codec_setup->name = "CAPTURE";
codec_setup = &chip->codecs[AZF_CODEC_I2S_OUT]; codec_setup = &chip->codecs[AZF_CODEC_I2S_OUT];
codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_I2S_OUT; codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_I2S_OUT;
codec_setup->lock = &chip->reg_lock;
codec_setup->type = AZF_CODEC_I2S_OUT;
codec_setup->name = "I2S_OUT"; codec_setup->name = "I2S_OUT";
if (request_irq(pci->irq, snd_azf3328_interrupt, if (request_irq(pci->irq, snd_azf3328_interrupt,
...@@ -2283,10 +2229,10 @@ snd_azf3328_create(struct snd_card *card, ...@@ -2283,10 +2229,10 @@ snd_azf3328_create(struct snd_card *card,
codec->running = 1; codec->running = 1;
snd_azf3328_ctrl_codec_activity(chip, codec_type, 0); snd_azf3328_ctrl_codec_activity(chip, codec_type, 0);
spin_lock_irq(&chip->reg_lock); spin_lock_irq(codec->lock);
snd_azf3328_codec_outb(codec, IDX_IO_CODEC_DMA_FLAGS, snd_azf3328_codec_outb(codec, IDX_IO_CODEC_DMA_FLAGS,
dma_init); dma_init);
spin_unlock_irq(&chip->reg_lock); spin_unlock_irq(codec->lock);
} }
snd_card_set_dev(card, &pci->dev); snd_card_set_dev(card, &pci->dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment