Commit 7f0b8946 authored by Clemens Ladisch's avatar Clemens Ladisch Committed by Jaroslav Kysela

[ALSA] oxygen: add 192 kHz SPDIF input support

Change the oxygen_spdif_input_bits_changed() function so that clock
changes on the SPDIF input are correctly detected.  This means that
sample rates greater than 96 kHz are now supported.
Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
Signed-off-by: default avatarJaroslav Kysela <perex@perex.cz>
parent 5a256f86
...@@ -74,7 +74,9 @@ static irqreturn_t oxygen_interrupt(int dummy, void *dev_id) ...@@ -74,7 +74,9 @@ static irqreturn_t oxygen_interrupt(int dummy, void *dev_id)
if (status & OXYGEN_INT_SPDIF_IN_DETECT) { if (status & OXYGEN_INT_SPDIF_IN_DETECT) {
spin_lock(&chip->reg_lock); spin_lock(&chip->reg_lock);
i = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); i = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL);
if (i & OXYGEN_SPDIF_RATE_INT) { if (i & (OXYGEN_SPDIF_SENSE_INT | OXYGEN_SPDIF_LOCK_INT |
OXYGEN_SPDIF_RATE_INT)) {
/* write the interrupt bit(s) to clear */
oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, i); oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, i);
schedule_work(&chip->spdif_input_bits_work); schedule_work(&chip->spdif_input_bits_work);
} }
...@@ -94,30 +96,46 @@ static void oxygen_spdif_input_bits_changed(struct work_struct *work) ...@@ -94,30 +96,46 @@ static void oxygen_spdif_input_bits_changed(struct work_struct *work)
{ {
struct oxygen *chip = container_of(work, struct oxygen, struct oxygen *chip = container_of(work, struct oxygen,
spdif_input_bits_work); spdif_input_bits_work);
u32 reg;
spin_lock_irq(&chip->reg_lock); /*
oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL, * This function gets called when there is new activity on the SPDIF
OXYGEN_SPDIF_IN_CLOCK_96, * input, or when we lose lock on the input signal, or when the rate
OXYGEN_SPDIF_IN_CLOCK_MASK); * changes.
spin_unlock_irq(&chip->reg_lock); */
msleep(1); msleep(1);
if (!(oxygen_read32(chip, OXYGEN_SPDIF_CONTROL)
& OXYGEN_SPDIF_LOCK_STATUS)) {
spin_lock_irq(&chip->reg_lock); spin_lock_irq(&chip->reg_lock);
oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL, reg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL);
OXYGEN_SPDIF_IN_CLOCK_192, if ((reg & (OXYGEN_SPDIF_SENSE_STATUS |
OXYGEN_SPDIF_IN_CLOCK_MASK); OXYGEN_SPDIF_LOCK_STATUS))
== OXYGEN_SPDIF_SENSE_STATUS) {
/*
* If we detect activity on the SPDIF input but cannot lock to
* a signal, the clock bit is likely to be wrong.
*/
reg ^= OXYGEN_SPDIF_IN_CLOCK_MASK;
oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, reg);
spin_unlock_irq(&chip->reg_lock); spin_unlock_irq(&chip->reg_lock);
msleep(1); msleep(1);
if (!(oxygen_read32(chip, OXYGEN_SPDIF_CONTROL)
& OXYGEN_SPDIF_LOCK_STATUS)) {
spin_lock_irq(&chip->reg_lock); spin_lock_irq(&chip->reg_lock);
oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL, reg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL);
OXYGEN_SPDIF_IN_CLOCK_96, if ((reg & (OXYGEN_SPDIF_SENSE_STATUS |
OXYGEN_SPDIF_IN_CLOCK_MASK); OXYGEN_SPDIF_LOCK_STATUS))
spin_unlock_irq(&chip->reg_lock); == OXYGEN_SPDIF_SENSE_STATUS) {
/* nothing detected with either clock; give up */
if ((reg & OXYGEN_SPDIF_IN_CLOCK_MASK)
== OXYGEN_SPDIF_IN_CLOCK_192) {
/*
* Reset clock to <= 96 kHz because this is
* more likely to be received next time.
*/
reg &= ~OXYGEN_SPDIF_IN_CLOCK_MASK;
reg |= OXYGEN_SPDIF_IN_CLOCK_96;
oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, reg);
}
} }
} }
spin_unlock_irq(&chip->reg_lock);
if (chip->controls[CONTROL_SPDIF_INPUT_BITS]) { if (chip->controls[CONTROL_SPDIF_INPUT_BITS]) {
spin_lock_irq(&chip->reg_lock); spin_lock_irq(&chip->reg_lock);
...@@ -126,6 +144,10 @@ static void oxygen_spdif_input_bits_changed(struct work_struct *work) ...@@ -126,6 +144,10 @@ static void oxygen_spdif_input_bits_changed(struct work_struct *work)
chip->interrupt_mask); chip->interrupt_mask);
spin_unlock_irq(&chip->reg_lock); spin_unlock_irq(&chip->reg_lock);
/*
* We don't actually know that any channel status bits have
* changed, but let's send a notification just to be sure.
*/
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
&chip->controls[CONTROL_SPDIF_INPUT_BITS]->id); &chip->controls[CONTROL_SPDIF_INPUT_BITS]->id);
} }
...@@ -225,7 +247,20 @@ static void __devinit oxygen_init(struct oxygen *chip) ...@@ -225,7 +247,20 @@ static void __devinit oxygen_init(struct oxygen *chip)
OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST | OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST |
OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 | OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 |
OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
oxygen_set_bits32(chip, OXYGEN_SPDIF_CONTROL, OXYGEN_SPDIF_RATE_MASK); oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL,
OXYGEN_SPDIF_SENSE_MASK |
OXYGEN_SPDIF_LOCK_MASK |
OXYGEN_SPDIF_RATE_MASK |
OXYGEN_SPDIF_LOCK_PAR |
OXYGEN_SPDIF_IN_CLOCK_96,
OXYGEN_SPDIF_OUT_ENABLE |
OXYGEN_SPDIF_LOOPBACK |
OXYGEN_SPDIF_SENSE_MASK |
OXYGEN_SPDIF_LOCK_MASK |
OXYGEN_SPDIF_RATE_MASK |
OXYGEN_SPDIF_SENSE_PAR |
OXYGEN_SPDIF_LOCK_PAR |
OXYGEN_SPDIF_IN_CLOCK_MASK);
oxygen_write32(chip, OXYGEN_SPDIF_OUTPUT_BITS, chip->spdif_bits); oxygen_write32(chip, OXYGEN_SPDIF_OUTPUT_BITS, chip->spdif_bits);
oxygen_write16(chip, OXYGEN_PLAY_ROUTING, oxygen_write16(chip, OXYGEN_PLAY_ROUTING,
OXYGEN_PLAY_MULTICH_I2S_DAC | OXYGEN_PLAY_SPDIF_SPDIF | OXYGEN_PLAY_MULTICH_I2S_DAC | OXYGEN_PLAY_SPDIF_SPDIF |
......
...@@ -85,12 +85,16 @@ static struct snd_pcm_hardware oxygen_hardware[PCM_COUNT] = { ...@@ -85,12 +85,16 @@ static struct snd_pcm_hardware oxygen_hardware[PCM_COUNT] = {
SNDRV_PCM_INFO_SYNC_START, SNDRV_PCM_INFO_SYNC_START,
.formats = SNDRV_PCM_FMTBIT_S16_LE | .formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S32_LE, SNDRV_PCM_FMTBIT_S32_LE,
.rates = SNDRV_PCM_RATE_44100 | .rates = SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_48000 |
SNDRV_PCM_RATE_64000 |
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_88200 |
SNDRV_PCM_RATE_96000, SNDRV_PCM_RATE_96000 |
.rate_min = 44100, SNDRV_PCM_RATE_176400 |
.rate_max = 96000, SNDRV_PCM_RATE_192000,
.rate_min = 32000,
.rate_max = 192000,
.channels_min = 2, .channels_min = 2,
.channels_max = 2, .channels_max = 2,
.buffer_bytes_max = 256 * 1024, .buffer_bytes_max = 256 * 1024,
......
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