diff options
Diffstat (limited to 'sound/pci/oxygen')
-rw-r--r-- | sound/pci/oxygen/oxygen_lib.c | 75 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen_pcm.c | 12 |
2 files changed, 63 insertions, 24 deletions
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 0927e0423777..49eabdadc679 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
@@ -74,7 +74,9 @@ static irqreturn_t oxygen_interrupt(int dummy, void *dev_id) | |||
74 | if (status & OXYGEN_INT_SPDIF_IN_DETECT) { | 74 | if (status & OXYGEN_INT_SPDIF_IN_DETECT) { |
75 | spin_lock(&chip->reg_lock); | 75 | spin_lock(&chip->reg_lock); |
76 | i = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); | 76 | i = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); |
77 | if (i & OXYGEN_SPDIF_RATE_INT) { | 77 | if (i & (OXYGEN_SPDIF_SENSE_INT | OXYGEN_SPDIF_LOCK_INT | |
78 | OXYGEN_SPDIF_RATE_INT)) { | ||
79 | /* write the interrupt bit(s) to clear */ | ||
78 | oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, i); | 80 | oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, i); |
79 | schedule_work(&chip->spdif_input_bits_work); | 81 | schedule_work(&chip->spdif_input_bits_work); |
80 | } | 82 | } |
@@ -94,30 +96,46 @@ static void oxygen_spdif_input_bits_changed(struct work_struct *work) | |||
94 | { | 96 | { |
95 | struct oxygen *chip = container_of(work, struct oxygen, | 97 | struct oxygen *chip = container_of(work, struct oxygen, |
96 | spdif_input_bits_work); | 98 | spdif_input_bits_work); |
99 | u32 reg; | ||
97 | 100 | ||
98 | spin_lock_irq(&chip->reg_lock); | 101 | /* |
99 | oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL, | 102 | * This function gets called when there is new activity on the SPDIF |
100 | OXYGEN_SPDIF_IN_CLOCK_96, | 103 | * input, or when we lose lock on the input signal, or when the rate |
101 | OXYGEN_SPDIF_IN_CLOCK_MASK); | 104 | * changes. |
102 | spin_unlock_irq(&chip->reg_lock); | 105 | */ |
103 | msleep(1); | 106 | msleep(1); |
104 | if (!(oxygen_read32(chip, OXYGEN_SPDIF_CONTROL) | 107 | spin_lock_irq(&chip->reg_lock); |
105 | & OXYGEN_SPDIF_LOCK_STATUS)) { | 108 | reg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); |
106 | spin_lock_irq(&chip->reg_lock); | 109 | if ((reg & (OXYGEN_SPDIF_SENSE_STATUS | |
107 | oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL, | 110 | OXYGEN_SPDIF_LOCK_STATUS)) |
108 | OXYGEN_SPDIF_IN_CLOCK_192, | 111 | == OXYGEN_SPDIF_SENSE_STATUS) { |
109 | OXYGEN_SPDIF_IN_CLOCK_MASK); | 112 | /* |
113 | * If we detect activity on the SPDIF input but cannot lock to | ||
114 | * a signal, the clock bit is likely to be wrong. | ||
115 | */ | ||
116 | reg ^= OXYGEN_SPDIF_IN_CLOCK_MASK; | ||
117 | oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, reg); | ||
110 | spin_unlock_irq(&chip->reg_lock); | 118 | spin_unlock_irq(&chip->reg_lock); |
111 | msleep(1); | 119 | msleep(1); |
112 | if (!(oxygen_read32(chip, OXYGEN_SPDIF_CONTROL) | 120 | spin_lock_irq(&chip->reg_lock); |
113 | & OXYGEN_SPDIF_LOCK_STATUS)) { | 121 | reg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); |
114 | spin_lock_irq(&chip->reg_lock); | 122 | if ((reg & (OXYGEN_SPDIF_SENSE_STATUS | |
115 | oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL, | 123 | OXYGEN_SPDIF_LOCK_STATUS)) |
116 | OXYGEN_SPDIF_IN_CLOCK_96, | 124 | == OXYGEN_SPDIF_SENSE_STATUS) { |
117 | OXYGEN_SPDIF_IN_CLOCK_MASK); | 125 | /* nothing detected with either clock; give up */ |
118 | spin_unlock_irq(&chip->reg_lock); | 126 | if ((reg & OXYGEN_SPDIF_IN_CLOCK_MASK) |
127 | == OXYGEN_SPDIF_IN_CLOCK_192) { | ||
128 | /* | ||
129 | * Reset clock to <= 96 kHz because this is | ||
130 | * more likely to be received next time. | ||
131 | */ | ||
132 | reg &= ~OXYGEN_SPDIF_IN_CLOCK_MASK; | ||
133 | reg |= OXYGEN_SPDIF_IN_CLOCK_96; | ||
134 | oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, reg); | ||
135 | } | ||
119 | } | 136 | } |
120 | } | 137 | } |
138 | spin_unlock_irq(&chip->reg_lock); | ||
121 | 139 | ||
122 | if (chip->controls[CONTROL_SPDIF_INPUT_BITS]) { | 140 | if (chip->controls[CONTROL_SPDIF_INPUT_BITS]) { |
123 | spin_lock_irq(&chip->reg_lock); | 141 | spin_lock_irq(&chip->reg_lock); |
@@ -126,6 +144,10 @@ static void oxygen_spdif_input_bits_changed(struct work_struct *work) | |||
126 | chip->interrupt_mask); | 144 | chip->interrupt_mask); |
127 | spin_unlock_irq(&chip->reg_lock); | 145 | spin_unlock_irq(&chip->reg_lock); |
128 | 146 | ||
147 | /* | ||
148 | * We don't actually know that any channel status bits have | ||
149 | * changed, but let's send a notification just to be sure. | ||
150 | */ | ||
129 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | 151 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, |
130 | &chip->controls[CONTROL_SPDIF_INPUT_BITS]->id); | 152 | &chip->controls[CONTROL_SPDIF_INPUT_BITS]->id); |
131 | } | 153 | } |
@@ -225,7 +247,20 @@ static void __devinit oxygen_init(struct oxygen *chip) | |||
225 | OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST | | 247 | OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST | |
226 | OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 | | 248 | OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 | |
227 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); | 249 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); |
228 | oxygen_set_bits32(chip, OXYGEN_SPDIF_CONTROL, OXYGEN_SPDIF_RATE_MASK); | 250 | oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL, |
251 | OXYGEN_SPDIF_SENSE_MASK | | ||
252 | OXYGEN_SPDIF_LOCK_MASK | | ||
253 | OXYGEN_SPDIF_RATE_MASK | | ||
254 | OXYGEN_SPDIF_LOCK_PAR | | ||
255 | OXYGEN_SPDIF_IN_CLOCK_96, | ||
256 | OXYGEN_SPDIF_OUT_ENABLE | | ||
257 | OXYGEN_SPDIF_LOOPBACK | | ||
258 | OXYGEN_SPDIF_SENSE_MASK | | ||
259 | OXYGEN_SPDIF_LOCK_MASK | | ||
260 | OXYGEN_SPDIF_RATE_MASK | | ||
261 | OXYGEN_SPDIF_SENSE_PAR | | ||
262 | OXYGEN_SPDIF_LOCK_PAR | | ||
263 | OXYGEN_SPDIF_IN_CLOCK_MASK); | ||
229 | oxygen_write32(chip, OXYGEN_SPDIF_OUTPUT_BITS, chip->spdif_bits); | 264 | oxygen_write32(chip, OXYGEN_SPDIF_OUTPUT_BITS, chip->spdif_bits); |
230 | oxygen_write16(chip, OXYGEN_PLAY_ROUTING, | 265 | oxygen_write16(chip, OXYGEN_PLAY_ROUTING, |
231 | OXYGEN_PLAY_MULTICH_I2S_DAC | OXYGEN_PLAY_SPDIF_SPDIF | | 266 | OXYGEN_PLAY_MULTICH_I2S_DAC | OXYGEN_PLAY_SPDIF_SPDIF | |
diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c index 31b0ccdca9a8..200290099cbc 100644 --- a/sound/pci/oxygen/oxygen_pcm.c +++ b/sound/pci/oxygen/oxygen_pcm.c | |||
@@ -85,12 +85,16 @@ static struct snd_pcm_hardware oxygen_hardware[PCM_COUNT] = { | |||
85 | SNDRV_PCM_INFO_SYNC_START, | 85 | SNDRV_PCM_INFO_SYNC_START, |
86 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | 86 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
87 | SNDRV_PCM_FMTBIT_S32_LE, | 87 | SNDRV_PCM_FMTBIT_S32_LE, |
88 | .rates = SNDRV_PCM_RATE_44100 | | 88 | .rates = SNDRV_PCM_RATE_32000 | |
89 | SNDRV_PCM_RATE_44100 | | ||
89 | SNDRV_PCM_RATE_48000 | | 90 | SNDRV_PCM_RATE_48000 | |
91 | SNDRV_PCM_RATE_64000 | | ||
90 | SNDRV_PCM_RATE_88200 | | 92 | SNDRV_PCM_RATE_88200 | |
91 | SNDRV_PCM_RATE_96000, | 93 | SNDRV_PCM_RATE_96000 | |
92 | .rate_min = 44100, | 94 | SNDRV_PCM_RATE_176400 | |
93 | .rate_max = 96000, | 95 | SNDRV_PCM_RATE_192000, |
96 | .rate_min = 32000, | ||
97 | .rate_max = 192000, | ||
94 | .channels_min = 2, | 98 | .channels_min = 2, |
95 | .channels_max = 2, | 99 | .channels_max = 2, |
96 | .buffer_bytes_max = 256 * 1024, | 100 | .buffer_bytes_max = 256 * 1024, |