#include <sound/pcm_params.h>
#include "oxygen.h"
-static struct snd_pcm_hardware oxygen_hardware[PCM_COUNT] = {
- [PCM_A] = {
- .info = SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_SYNC_START,
- .formats = SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_S32_LE,
- .rates = SNDRV_PCM_RATE_32000 |
- SNDRV_PCM_RATE_44100 |
- SNDRV_PCM_RATE_48000 |
- SNDRV_PCM_RATE_64000 |
- SNDRV_PCM_RATE_88200 |
- SNDRV_PCM_RATE_96000 |
- SNDRV_PCM_RATE_176400 |
- SNDRV_PCM_RATE_192000,
- .rate_min = 32000,
- .rate_max = 192000,
- .channels_min = 2,
- .channels_max = 2,
- .buffer_bytes_max = 256 * 1024,
- .period_bytes_min = 128,
- .period_bytes_max = 128 * 1024,
- .periods_min = 2,
- .periods_max = 2048,
- },
- [PCM_B] = {
- .info = SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_SYNC_START,
- .formats = SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_S32_LE,
- .rates = SNDRV_PCM_RATE_32000 |
- SNDRV_PCM_RATE_44100 |
- SNDRV_PCM_RATE_48000 |
- SNDRV_PCM_RATE_64000 |
- SNDRV_PCM_RATE_88200 |
- SNDRV_PCM_RATE_96000 |
- SNDRV_PCM_RATE_176400 |
- SNDRV_PCM_RATE_192000,
- .rate_min = 32000,
- .rate_max = 192000,
- .channels_min = 2,
- .channels_max = 2,
- .buffer_bytes_max = 256 * 1024,
- .period_bytes_min = 128,
- .period_bytes_max = 128 * 1024,
- .periods_min = 2,
- .periods_max = 2048,
- },
- [PCM_C] = {
- .info = SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_SYNC_START,
- .formats = SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_S32_LE,
- .rates = SNDRV_PCM_RATE_44100 |
- SNDRV_PCM_RATE_48000 |
- SNDRV_PCM_RATE_88200 |
- SNDRV_PCM_RATE_96000,
- .rate_min = 44100,
- .rate_max = 96000,
- .channels_min = 2,
- .channels_max = 2,
- .buffer_bytes_max = 256 * 1024,
- .period_bytes_min = 128,
- .period_bytes_max = 128 * 1024,
- .periods_min = 2,
- .periods_max = 2048,
- },
- [PCM_SPDIF] = {
- .info = SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_SYNC_START,
- .formats = SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_S32_LE,
- .rates = SNDRV_PCM_RATE_32000 |
- SNDRV_PCM_RATE_44100 |
- SNDRV_PCM_RATE_48000 |
- SNDRV_PCM_RATE_64000 |
- SNDRV_PCM_RATE_88200 |
- SNDRV_PCM_RATE_96000 |
- SNDRV_PCM_RATE_176400 |
- SNDRV_PCM_RATE_192000,
- .rate_min = 32000,
- .rate_max = 192000,
- .channels_min = 2,
- .channels_max = 2,
- .buffer_bytes_max = 256 * 1024,
- .period_bytes_min = 128,
- .period_bytes_max = 128 * 1024,
- .periods_min = 2,
- .periods_max = 2048,
- },
- [PCM_MULTICH] = {
- .info = SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_SYNC_START,
- .formats = SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_S32_LE,
- .rates = SNDRV_PCM_RATE_32000 |
- SNDRV_PCM_RATE_44100 |
- SNDRV_PCM_RATE_48000 |
- SNDRV_PCM_RATE_64000 |
- SNDRV_PCM_RATE_88200 |
- SNDRV_PCM_RATE_96000 |
- SNDRV_PCM_RATE_176400 |
- SNDRV_PCM_RATE_192000,
- .rate_min = 32000,
- .rate_max = 192000,
- .channels_min = 2,
- .channels_max = 8,
- .buffer_bytes_max = 2048 * 1024,
- .period_bytes_min = 128,
- .period_bytes_max = 256 * 1024,
- .periods_min = 2,
- .periods_max = 16384,
- },
- [PCM_AC97] = {
- .info = SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_SYNC_START,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_48000,
- .rate_min = 48000,
- .rate_max = 48000,
- .channels_min = 2,
- .channels_max = 2,
- .buffer_bytes_max = 256 * 1024,
- .period_bytes_min = 128,
- .period_bytes_max = 128 * 1024,
- .periods_min = 2,
- .periods_max = 2048,
- },
+/* most DMA channels have a 16-bit counter for 32-bit words */
+#define BUFFER_BYTES_MAX ((1 << 16) * 4)
+/* the multichannel DMA channel has a 24-bit counter */
+#define BUFFER_BYTES_MAX_MULTICH ((1 << 24) * 4)
+
+#define PERIOD_BYTES_MIN 64
+
+#define DEFAULT_BUFFER_BYTES (BUFFER_BYTES_MAX / 2)
+#define DEFAULT_BUFFER_BYTES_MULTICH (1024 * 1024)
+
+static const struct snd_pcm_hardware oxygen_stereo_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_SYNC_START,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ .rates = SNDRV_PCM_RATE_32000 |
+ SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_64000 |
+ SNDRV_PCM_RATE_88200 |
+ SNDRV_PCM_RATE_96000 |
+ SNDRV_PCM_RATE_176400 |
+ SNDRV_PCM_RATE_192000,
+ .rate_min = 32000,
+ .rate_max = 192000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = BUFFER_BYTES_MAX,
+ .period_bytes_min = PERIOD_BYTES_MIN,
+ .period_bytes_max = BUFFER_BYTES_MAX / 2,
+ .periods_min = 2,
+ .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
+};
+static const struct snd_pcm_hardware oxygen_multichannel_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_SYNC_START,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ .rates = SNDRV_PCM_RATE_32000 |
+ SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_64000 |
+ SNDRV_PCM_RATE_88200 |
+ SNDRV_PCM_RATE_96000 |
+ SNDRV_PCM_RATE_176400 |
+ SNDRV_PCM_RATE_192000,
+ .rate_min = 32000,
+ .rate_max = 192000,
+ .channels_min = 2,
+ .channels_max = 8,
+ .buffer_bytes_max = BUFFER_BYTES_MAX_MULTICH,
+ .period_bytes_min = PERIOD_BYTES_MIN,
+ .period_bytes_max = BUFFER_BYTES_MAX_MULTICH / 2,
+ .periods_min = 2,
+ .periods_max = BUFFER_BYTES_MAX_MULTICH / PERIOD_BYTES_MIN,
+};
+static const struct snd_pcm_hardware oxygen_ac97_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_SYNC_START,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = BUFFER_BYTES_MAX,
+ .period_bytes_min = PERIOD_BYTES_MIN,
+ .period_bytes_max = BUFFER_BYTES_MAX / 2,
+ .periods_min = 2,
+ .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
+};
+
+static const struct snd_pcm_hardware *const oxygen_hardware[PCM_COUNT] = {
+ [PCM_A] = &oxygen_stereo_hardware,
+ [PCM_B] = &oxygen_stereo_hardware,
+ [PCM_C] = &oxygen_stereo_hardware,
+ [PCM_SPDIF] = &oxygen_stereo_hardware,
+ [PCM_MULTICH] = &oxygen_multichannel_hardware,
+ [PCM_AC97] = &oxygen_ac97_hardware,
};
static inline unsigned int
int err;
runtime->private_data = (void *)(uintptr_t)channel;
- runtime->hw = oxygen_hardware[channel];
- if (chip->model->pcm_hardware_filter)
- chip->model->pcm_hardware_filter(channel, &runtime->hw);
+ if (channel == PCM_B && chip->has_ac97_1 &&
+ (chip->model.device_config & CAPTURE_2_FROM_AC97_1))
+ runtime->hw = oxygen_ac97_hardware;
+ else
+ runtime->hw = *oxygen_hardware[channel];
+ switch (channel) {
+ case PCM_C:
+ runtime->hw.rates &= ~(SNDRV_PCM_RATE_32000 |
+ SNDRV_PCM_RATE_64000);
+ runtime->hw.rate_min = 44100;
+ break;
+ case PCM_MULTICH:
+ runtime->hw.channels_max = chip->model.dac_channels;
+ break;
+ }
+ if (chip->model.pcm_hardware_filter)
+ chip->model.pcm_hardware_filter(channel, &runtime->hw);
err = snd_pcm_hw_constraint_step(runtime, 0,
SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
if (err < 0)
if (err < 0)
return err;
}
+ if (channel == PCM_MULTICH) {
+ err = snd_pcm_hw_constraint_minmax
+ (runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 0, 8192000);
+ if (err < 0)
+ return err;
+ }
snd_pcm_set_sync(substream);
chip->streams[channel] = substream;
}
}
-static unsigned int oxygen_i2s_mclk(struct snd_pcm_hw_params *hw_params)
+unsigned int oxygen_default_i2s_mclk(struct oxygen *chip,
+ unsigned int channel,
+ struct snd_pcm_hw_params *hw_params)
{
- return params_rate(hw_params) <= 96000
- ? OXYGEN_I2S_MCLK_256 : OXYGEN_I2S_MCLK_128;
+ if (params_rate(hw_params) <= 96000)
+ return OXYGEN_I2S_MCLK_256;
+ else
+ return OXYGEN_I2S_MCLK_128;
}
+EXPORT_SYMBOL(oxygen_default_i2s_mclk);
static unsigned int oxygen_i2s_bits(struct snd_pcm_hw_params *hw_params)
{
OXYGEN_REC_FORMAT_A_MASK);
oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT,
oxygen_rate(hw_params) |
- oxygen_i2s_mclk(hw_params) |
- chip->model->adc_i2s_format |
+ chip->model.get_i2s_mclk(chip, PCM_A, hw_params) |
+ chip->model.adc_i2s_format |
oxygen_i2s_bits(hw_params),
OXYGEN_I2S_RATE_MASK |
OXYGEN_I2S_FORMAT_MASK |
OXYGEN_I2S_MCLK_MASK |
OXYGEN_I2S_BITS_MASK);
- oxygen_write8_masked(chip, OXYGEN_REC_ROUTING,
- OXYGEN_REC_A_ROUTE_I2S_ADC_1,
- OXYGEN_REC_A_ROUTE_MASK);
spin_unlock_irq(&chip->reg_lock);
mutex_lock(&chip->mutex);
- chip->model->set_adc_params(chip, hw_params);
+ chip->model.set_adc_params(chip, hw_params);
mutex_unlock(&chip->mutex);
return 0;
}
struct snd_pcm_hw_params *hw_params)
{
struct oxygen *chip = snd_pcm_substream_chip(substream);
+ int is_ac97;
int err;
err = oxygen_hw_params(substream, hw_params);
if (err < 0)
return err;
+ is_ac97 = chip->has_ac97_1 &&
+ (chip->model.device_config & CAPTURE_2_FROM_AC97_1);
+
spin_lock_irq(&chip->reg_lock);
oxygen_write8_masked(chip, OXYGEN_REC_FORMAT,
oxygen_format(hw_params) << OXYGEN_REC_FORMAT_B_SHIFT,
OXYGEN_REC_FORMAT_B_MASK);
- oxygen_write16_masked(chip, OXYGEN_I2S_B_FORMAT,
- oxygen_rate(hw_params) |
- oxygen_i2s_mclk(hw_params) |
- chip->model->adc_i2s_format |
- oxygen_i2s_bits(hw_params),
- OXYGEN_I2S_RATE_MASK |
- OXYGEN_I2S_FORMAT_MASK |
- OXYGEN_I2S_MCLK_MASK |
- OXYGEN_I2S_BITS_MASK);
- oxygen_write8_masked(chip, OXYGEN_REC_ROUTING,
- OXYGEN_REC_B_ROUTE_I2S_ADC_2,
- OXYGEN_REC_B_ROUTE_MASK);
+ if (!is_ac97)
+ oxygen_write16_masked(chip, OXYGEN_I2S_B_FORMAT,
+ oxygen_rate(hw_params) |
+ chip->model.get_i2s_mclk(chip, PCM_B,
+ hw_params) |
+ chip->model.adc_i2s_format |
+ oxygen_i2s_bits(hw_params),
+ OXYGEN_I2S_RATE_MASK |
+ OXYGEN_I2S_FORMAT_MASK |
+ OXYGEN_I2S_MCLK_MASK |
+ OXYGEN_I2S_BITS_MASK);
spin_unlock_irq(&chip->reg_lock);
- mutex_lock(&chip->mutex);
- chip->model->set_adc_params(chip, hw_params);
- mutex_unlock(&chip->mutex);
+ if (!is_ac97) {
+ mutex_lock(&chip->mutex);
+ chip->model.set_adc_params(chip, hw_params);
+ mutex_unlock(&chip->mutex);
+ }
return 0;
}
oxygen_write8_masked(chip, OXYGEN_REC_FORMAT,
oxygen_format(hw_params) << OXYGEN_REC_FORMAT_C_SHIFT,
OXYGEN_REC_FORMAT_C_MASK);
- oxygen_write8_masked(chip, OXYGEN_REC_ROUTING,
- OXYGEN_REC_C_ROUTE_SPDIF,
- OXYGEN_REC_C_ROUTE_MASK);
spin_unlock_irq(&chip->reg_lock);
return 0;
}
if (err < 0)
return err;
+ mutex_lock(&chip->mutex);
spin_lock_irq(&chip->reg_lock);
oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL,
OXYGEN_SPDIF_OUT_ENABLE);
OXYGEN_SPDIF_OUT_RATE_MASK);
oxygen_update_spdif_source(chip);
spin_unlock_irq(&chip->reg_lock);
+ mutex_unlock(&chip->mutex);
return 0;
}
if (err < 0)
return err;
+ mutex_lock(&chip->mutex);
spin_lock_irq(&chip->reg_lock);
oxygen_write8_masked(chip, OXYGEN_PLAY_CHANNELS,
oxygen_play_channels(hw_params),
OXYGEN_MULTICH_FORMAT_MASK);
oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT,
oxygen_rate(hw_params) |
- chip->model->dac_i2s_format |
+ chip->model.dac_i2s_format |
+ chip->model.get_i2s_mclk(chip, PCM_MULTICH,
+ hw_params) |
oxygen_i2s_bits(hw_params),
OXYGEN_I2S_RATE_MASK |
OXYGEN_I2S_FORMAT_MASK |
+ OXYGEN_I2S_MCLK_MASK |
OXYGEN_I2S_BITS_MASK);
- oxygen_write16_masked(chip, OXYGEN_PLAY_ROUTING,
- OXYGEN_PLAY_MULTICH_I2S_DAC,
- OXYGEN_PLAY_MUTE01 | OXYGEN_PLAY_MUTE23 |
- OXYGEN_PLAY_MUTE45 | OXYGEN_PLAY_MUTE67 |
- OXYGEN_PLAY_MULTICH_MASK);
- oxygen_update_dac_routing(chip);
oxygen_update_spdif_source(chip);
spin_unlock_irq(&chip->reg_lock);
- mutex_lock(&chip->mutex);
- chip->model->set_dac_params(chip, hw_params);
+ chip->model.set_dac_params(chip, hw_params);
+ oxygen_update_dac_routing(chip);
mutex_unlock(&chip->mutex);
return 0;
}
{
struct oxygen *chip = snd_pcm_substream_chip(substream);
unsigned int channel = oxygen_substream_channel(substream);
+ unsigned int channel_mask = 1 << channel;
spin_lock_irq(&chip->reg_lock);
- chip->interrupt_mask &= ~(1 << channel);
+ chip->interrupt_mask &= ~channel_mask;
oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask);
+
+ oxygen_set_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask);
+ oxygen_clear_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask);
spin_unlock_irq(&chip->reg_lock);
return snd_pcm_lib_free_pages(substream);
struct oxygen *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_substream *s;
unsigned int mask = 0;
- int running;
+ int pausing;
switch (cmd) {
case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- running = 0;
- break;
case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ pausing = 0;
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- running = 1;
+ pausing = 1;
break;
default:
return -EINVAL;
}
spin_lock(&chip->reg_lock);
- if (running)
- chip->pcm_running |= mask;
- else
- chip->pcm_running &= ~mask;
- oxygen_write8(chip, OXYGEN_DMA_STATUS, chip->pcm_running);
+ if (!pausing) {
+ if (cmd == SNDRV_PCM_TRIGGER_START)
+ chip->pcm_running |= mask;
+ else
+ chip->pcm_running &= ~mask;
+ oxygen_write8(chip, OXYGEN_DMA_STATUS, chip->pcm_running);
+ } else {
+ if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH)
+ oxygen_set_bits8(chip, OXYGEN_DMA_PAUSE, mask);
+ else
+ oxygen_clear_bits8(chip, OXYGEN_DMA_PAUSE, mask);
+ }
spin_unlock(&chip->reg_lock);
return 0;
}
snd_pcm_lib_preallocate_free_for_all(pcm);
}
-int __devinit oxygen_pcm_init(struct oxygen *chip)
+int oxygen_pcm_init(struct oxygen *chip)
{
struct snd_pcm *pcm;
int outs, ins;
int err;
- outs = 1; /* OXYGEN_CHANNEL_MULTICH is always used */
- ins = !!(chip->model->used_channels & (OXYGEN_CHANNEL_A |
- OXYGEN_CHANNEL_B));
- err = snd_pcm_new(chip->card, "Analog", 0, outs, ins, &pcm);
- if (err < 0)
- return err;
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &oxygen_multich_ops);
- if (chip->model->used_channels & OXYGEN_CHANNEL_A)
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
- &oxygen_rec_a_ops);
- else if (chip->model->used_channels & OXYGEN_CHANNEL_B)
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
- &oxygen_rec_b_ops);
- pcm->private_data = chip;
- pcm->private_free = oxygen_pcm_free;
- strcpy(pcm->name, "Analog");
- snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
- SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(chip->pci),
- 512 * 1024, 2048 * 1024);
- if (ins)
- snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
- SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(chip->pci),
- 128 * 1024, 256 * 1024);
-
- outs = !!(chip->model->used_channels & OXYGEN_CHANNEL_SPDIF);
- ins = !!(chip->model->used_channels & OXYGEN_CHANNEL_C);
+ outs = !!(chip->model.device_config & PLAYBACK_0_TO_I2S);
+ ins = !!(chip->model.device_config & (CAPTURE_0_FROM_I2S_1 |
+ CAPTURE_0_FROM_I2S_2));
+ if (outs | ins) {
+ err = snd_pcm_new(chip->card, "Multichannel",
+ 0, outs, ins, &pcm);
+ if (err < 0)
+ return err;
+ if (outs)
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ &oxygen_multich_ops);
+ if (chip->model.device_config & CAPTURE_0_FROM_I2S_1)
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &oxygen_rec_a_ops);
+ else if (chip->model.device_config & CAPTURE_0_FROM_I2S_2)
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &oxygen_rec_b_ops);
+ pcm->private_data = chip;
+ pcm->private_free = oxygen_pcm_free;
+ strcpy(pcm->name, "Multichannel");
+ if (outs)
+ snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
+ SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ DEFAULT_BUFFER_BYTES_MULTICH,
+ BUFFER_BYTES_MAX_MULTICH);
+ if (ins)
+ snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
+ SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ DEFAULT_BUFFER_BYTES,
+ BUFFER_BYTES_MAX);
+ }
+
+ outs = !!(chip->model.device_config & PLAYBACK_1_TO_SPDIF);
+ ins = !!(chip->model.device_config & CAPTURE_1_FROM_SPDIF);
if (outs | ins) {
err = snd_pcm_new(chip->card, "Digital", 1, outs, ins, &pcm);
if (err < 0)
strcpy(pcm->name, "Digital");
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(chip->pci),
- 128 * 1024, 256 * 1024);
+ DEFAULT_BUFFER_BYTES,
+ BUFFER_BYTES_MAX);
}
- outs = chip->has_ac97_1 &&
- (chip->model->used_channels & OXYGEN_CHANNEL_AC97);
- ins = (chip->model->used_channels & (OXYGEN_CHANNEL_A |
- OXYGEN_CHANNEL_B))
- == (OXYGEN_CHANNEL_A | OXYGEN_CHANNEL_B);
+ if (chip->has_ac97_1) {
+ outs = !!(chip->model.device_config & PLAYBACK_2_TO_AC97_1);
+ ins = !!(chip->model.device_config & CAPTURE_2_FROM_AC97_1);
+ } else {
+ outs = 0;
+ ins = !!(chip->model.device_config & CAPTURE_2_FROM_I2S_2);
+ }
if (outs | ins) {
- err = snd_pcm_new(chip->card, ins ? "Analog2" : "AC97",
+ err = snd_pcm_new(chip->card, outs ? "AC97" : "Analog2",
2, outs, ins, &pcm);
if (err < 0)
return err;
- if (outs)
+ if (outs) {
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
&oxygen_ac97_ops);
+ oxygen_write8_masked(chip, OXYGEN_REC_ROUTING,
+ OXYGEN_REC_B_ROUTE_AC97_1,
+ OXYGEN_REC_B_ROUTE_MASK);
+ }
if (ins)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
&oxygen_rec_b_ops);
pcm->private_data = chip;
pcm->private_free = oxygen_pcm_free;
- strcpy(pcm->name, ins ? "Analog 2" : "Front Panel");
+ strcpy(pcm->name, outs ? "Front Panel" : "Analog 2");
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(chip->pci),
- 128 * 1024, 256 * 1024);
+ DEFAULT_BUFFER_BYTES,
+ BUFFER_BYTES_MAX);
}
return 0;
}