1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * C-Media CMI8788 driver - PCM code |
4 | * |
5 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> |
6 | */ |
7 | |
8 | #include <linux/pci.h> |
9 | #include <sound/control.h> |
10 | #include <sound/core.h> |
11 | #include <sound/pcm.h> |
12 | #include <sound/pcm_params.h> |
13 | #include "oxygen.h" |
14 | |
15 | /* most DMA channels have a 16-bit counter for 32-bit words */ |
16 | #define BUFFER_BYTES_MAX ((1 << 16) * 4) |
17 | /* the multichannel DMA channel has a 24-bit counter */ |
18 | #define BUFFER_BYTES_MAX_MULTICH ((1 << 24) * 4) |
19 | |
20 | #define FIFO_BYTES 256 |
21 | #define FIFO_BYTES_MULTICH 1024 |
22 | |
23 | #define PERIOD_BYTES_MIN 64 |
24 | |
25 | #define DEFAULT_BUFFER_BYTES (BUFFER_BYTES_MAX / 2) |
26 | #define DEFAULT_BUFFER_BYTES_MULTICH (1024 * 1024) |
27 | |
28 | static const struct snd_pcm_hardware oxygen_stereo_hardware = { |
29 | .info = SNDRV_PCM_INFO_MMAP | |
30 | SNDRV_PCM_INFO_MMAP_VALID | |
31 | SNDRV_PCM_INFO_INTERLEAVED | |
32 | SNDRV_PCM_INFO_PAUSE | |
33 | SNDRV_PCM_INFO_SYNC_START | |
34 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, |
35 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
36 | SNDRV_PCM_FMTBIT_S32_LE, |
37 | .rates = SNDRV_PCM_RATE_32000 | |
38 | SNDRV_PCM_RATE_44100 | |
39 | SNDRV_PCM_RATE_48000 | |
40 | SNDRV_PCM_RATE_64000 | |
41 | SNDRV_PCM_RATE_88200 | |
42 | SNDRV_PCM_RATE_96000 | |
43 | SNDRV_PCM_RATE_176400 | |
44 | SNDRV_PCM_RATE_192000, |
45 | .rate_min = 32000, |
46 | .rate_max = 192000, |
47 | .channels_min = 2, |
48 | .channels_max = 2, |
49 | .buffer_bytes_max = BUFFER_BYTES_MAX, |
50 | .period_bytes_min = PERIOD_BYTES_MIN, |
51 | .period_bytes_max = BUFFER_BYTES_MAX, |
52 | .periods_min = 1, |
53 | .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, |
54 | .fifo_size = FIFO_BYTES, |
55 | }; |
56 | static const struct snd_pcm_hardware oxygen_multichannel_hardware = { |
57 | .info = SNDRV_PCM_INFO_MMAP | |
58 | SNDRV_PCM_INFO_MMAP_VALID | |
59 | SNDRV_PCM_INFO_INTERLEAVED | |
60 | SNDRV_PCM_INFO_PAUSE | |
61 | SNDRV_PCM_INFO_SYNC_START | |
62 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, |
63 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
64 | SNDRV_PCM_FMTBIT_S32_LE, |
65 | .rates = SNDRV_PCM_RATE_32000 | |
66 | SNDRV_PCM_RATE_44100 | |
67 | SNDRV_PCM_RATE_48000 | |
68 | SNDRV_PCM_RATE_64000 | |
69 | SNDRV_PCM_RATE_88200 | |
70 | SNDRV_PCM_RATE_96000 | |
71 | SNDRV_PCM_RATE_176400 | |
72 | SNDRV_PCM_RATE_192000, |
73 | .rate_min = 32000, |
74 | .rate_max = 192000, |
75 | .channels_min = 2, |
76 | .channels_max = 8, |
77 | .buffer_bytes_max = BUFFER_BYTES_MAX_MULTICH, |
78 | .period_bytes_min = PERIOD_BYTES_MIN, |
79 | .period_bytes_max = BUFFER_BYTES_MAX_MULTICH, |
80 | .periods_min = 1, |
81 | .periods_max = BUFFER_BYTES_MAX_MULTICH / PERIOD_BYTES_MIN, |
82 | .fifo_size = FIFO_BYTES_MULTICH, |
83 | }; |
84 | static const struct snd_pcm_hardware oxygen_ac97_hardware = { |
85 | .info = SNDRV_PCM_INFO_MMAP | |
86 | SNDRV_PCM_INFO_MMAP_VALID | |
87 | SNDRV_PCM_INFO_INTERLEAVED | |
88 | SNDRV_PCM_INFO_PAUSE | |
89 | SNDRV_PCM_INFO_SYNC_START | |
90 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, |
91 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
92 | .rates = SNDRV_PCM_RATE_48000, |
93 | .rate_min = 48000, |
94 | .rate_max = 48000, |
95 | .channels_min = 2, |
96 | .channels_max = 2, |
97 | .buffer_bytes_max = BUFFER_BYTES_MAX, |
98 | .period_bytes_min = PERIOD_BYTES_MIN, |
99 | .period_bytes_max = BUFFER_BYTES_MAX, |
100 | .periods_min = 1, |
101 | .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, |
102 | .fifo_size = FIFO_BYTES, |
103 | }; |
104 | |
105 | static const struct snd_pcm_hardware *const oxygen_hardware[PCM_COUNT] = { |
106 | [PCM_A] = &oxygen_stereo_hardware, |
107 | [PCM_B] = &oxygen_stereo_hardware, |
108 | [PCM_C] = &oxygen_stereo_hardware, |
109 | [PCM_SPDIF] = &oxygen_stereo_hardware, |
110 | [PCM_MULTICH] = &oxygen_multichannel_hardware, |
111 | [PCM_AC97] = &oxygen_ac97_hardware, |
112 | }; |
113 | |
114 | static inline unsigned int |
115 | oxygen_substream_channel(struct snd_pcm_substream *substream) |
116 | { |
117 | return (unsigned int)(uintptr_t)substream->runtime->private_data; |
118 | } |
119 | |
120 | static int oxygen_open(struct snd_pcm_substream *substream, |
121 | unsigned int channel) |
122 | { |
123 | struct oxygen *chip = snd_pcm_substream_chip(substream); |
124 | struct snd_pcm_runtime *runtime = substream->runtime; |
125 | int err; |
126 | |
127 | runtime->private_data = (void *)(uintptr_t)channel; |
128 | if (channel == PCM_B && chip->has_ac97_1 && |
129 | (chip->model.device_config & CAPTURE_2_FROM_AC97_1)) |
130 | runtime->hw = oxygen_ac97_hardware; |
131 | else |
132 | runtime->hw = *oxygen_hardware[channel]; |
133 | switch (channel) { |
134 | case PCM_C: |
135 | if (chip->model.device_config & CAPTURE_1_FROM_SPDIF) { |
136 | runtime->hw.rates &= ~(SNDRV_PCM_RATE_32000 | |
137 | SNDRV_PCM_RATE_64000); |
138 | runtime->hw.rate_min = 44100; |
139 | } |
140 | fallthrough; |
141 | case PCM_A: |
142 | case PCM_B: |
143 | runtime->hw.fifo_size = 0; |
144 | break; |
145 | case PCM_MULTICH: |
146 | runtime->hw.channels_max = chip->model.dac_channels_pcm; |
147 | break; |
148 | } |
149 | if (chip->model.pcm_hardware_filter) |
150 | chip->model.pcm_hardware_filter(channel, &runtime->hw); |
151 | err = snd_pcm_hw_constraint_step(runtime, cond: 0, |
152 | SNDRV_PCM_HW_PARAM_PERIOD_BYTES, step: 32); |
153 | if (err < 0) |
154 | return err; |
155 | err = snd_pcm_hw_constraint_step(runtime, cond: 0, |
156 | SNDRV_PCM_HW_PARAM_BUFFER_BYTES, step: 32); |
157 | if (err < 0) |
158 | return err; |
159 | if (runtime->hw.formats & SNDRV_PCM_FMTBIT_S32_LE) { |
160 | err = snd_pcm_hw_constraint_msbits(runtime, cond: 0, width: 32, msbits: 24); |
161 | if (err < 0) |
162 | return err; |
163 | } |
164 | if (runtime->hw.channels_max > 2) { |
165 | err = snd_pcm_hw_constraint_step(runtime, cond: 0, |
166 | SNDRV_PCM_HW_PARAM_CHANNELS, |
167 | step: 2); |
168 | if (err < 0) |
169 | return err; |
170 | } |
171 | snd_pcm_set_sync(substream); |
172 | chip->streams[channel] = substream; |
173 | |
174 | mutex_lock(&chip->mutex); |
175 | chip->pcm_active |= 1 << channel; |
176 | if (channel == PCM_SPDIF) { |
177 | chip->spdif_pcm_bits = chip->spdif_bits; |
178 | chip->controls[CONTROL_SPDIF_PCM]->vd[0].access &= |
179 | ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; |
180 | snd_ctl_notify(card: chip->card, SNDRV_CTL_EVENT_MASK_VALUE | |
181 | SNDRV_CTL_EVENT_MASK_INFO, |
182 | id: &chip->controls[CONTROL_SPDIF_PCM]->id); |
183 | } |
184 | mutex_unlock(lock: &chip->mutex); |
185 | |
186 | return 0; |
187 | } |
188 | |
189 | static int oxygen_rec_a_open(struct snd_pcm_substream *substream) |
190 | { |
191 | return oxygen_open(substream, PCM_A); |
192 | } |
193 | |
194 | static int oxygen_rec_b_open(struct snd_pcm_substream *substream) |
195 | { |
196 | return oxygen_open(substream, PCM_B); |
197 | } |
198 | |
199 | static int oxygen_rec_c_open(struct snd_pcm_substream *substream) |
200 | { |
201 | return oxygen_open(substream, PCM_C); |
202 | } |
203 | |
204 | static int oxygen_spdif_open(struct snd_pcm_substream *substream) |
205 | { |
206 | return oxygen_open(substream, PCM_SPDIF); |
207 | } |
208 | |
209 | static int oxygen_multich_open(struct snd_pcm_substream *substream) |
210 | { |
211 | return oxygen_open(substream, PCM_MULTICH); |
212 | } |
213 | |
214 | static int oxygen_ac97_open(struct snd_pcm_substream *substream) |
215 | { |
216 | return oxygen_open(substream, PCM_AC97); |
217 | } |
218 | |
219 | static int oxygen_close(struct snd_pcm_substream *substream) |
220 | { |
221 | struct oxygen *chip = snd_pcm_substream_chip(substream); |
222 | unsigned int channel = oxygen_substream_channel(substream); |
223 | |
224 | mutex_lock(&chip->mutex); |
225 | chip->pcm_active &= ~(1 << channel); |
226 | if (channel == PCM_SPDIF) { |
227 | chip->controls[CONTROL_SPDIF_PCM]->vd[0].access |= |
228 | SNDRV_CTL_ELEM_ACCESS_INACTIVE; |
229 | snd_ctl_notify(card: chip->card, SNDRV_CTL_EVENT_MASK_VALUE | |
230 | SNDRV_CTL_EVENT_MASK_INFO, |
231 | id: &chip->controls[CONTROL_SPDIF_PCM]->id); |
232 | } |
233 | if (channel == PCM_SPDIF || channel == PCM_MULTICH) |
234 | oxygen_update_spdif_source(chip); |
235 | mutex_unlock(lock: &chip->mutex); |
236 | |
237 | chip->streams[channel] = NULL; |
238 | return 0; |
239 | } |
240 | |
241 | static unsigned int oxygen_format(struct snd_pcm_hw_params *hw_params) |
242 | { |
243 | if (params_format(p: hw_params) == SNDRV_PCM_FORMAT_S32_LE) |
244 | return OXYGEN_FORMAT_24; |
245 | else |
246 | return OXYGEN_FORMAT_16; |
247 | } |
248 | |
249 | static unsigned int oxygen_rate(struct snd_pcm_hw_params *hw_params) |
250 | { |
251 | switch (params_rate(p: hw_params)) { |
252 | case 32000: |
253 | return OXYGEN_RATE_32000; |
254 | case 44100: |
255 | return OXYGEN_RATE_44100; |
256 | default: /* 48000 */ |
257 | return OXYGEN_RATE_48000; |
258 | case 64000: |
259 | return OXYGEN_RATE_64000; |
260 | case 88200: |
261 | return OXYGEN_RATE_88200; |
262 | case 96000: |
263 | return OXYGEN_RATE_96000; |
264 | case 176400: |
265 | return OXYGEN_RATE_176400; |
266 | case 192000: |
267 | return OXYGEN_RATE_192000; |
268 | } |
269 | } |
270 | |
271 | static unsigned int oxygen_i2s_bits(struct snd_pcm_hw_params *hw_params) |
272 | { |
273 | if (params_format(p: hw_params) == SNDRV_PCM_FORMAT_S32_LE) |
274 | return OXYGEN_I2S_BITS_24; |
275 | else |
276 | return OXYGEN_I2S_BITS_16; |
277 | } |
278 | |
279 | static unsigned int oxygen_play_channels(struct snd_pcm_hw_params *hw_params) |
280 | { |
281 | switch (params_channels(p: hw_params)) { |
282 | default: /* 2 */ |
283 | return OXYGEN_PLAY_CHANNELS_2; |
284 | case 4: |
285 | return OXYGEN_PLAY_CHANNELS_4; |
286 | case 6: |
287 | return OXYGEN_PLAY_CHANNELS_6; |
288 | case 8: |
289 | return OXYGEN_PLAY_CHANNELS_8; |
290 | } |
291 | } |
292 | |
293 | static const unsigned int channel_base_registers[PCM_COUNT] = { |
294 | [PCM_A] = OXYGEN_DMA_A_ADDRESS, |
295 | [PCM_B] = OXYGEN_DMA_B_ADDRESS, |
296 | [PCM_C] = OXYGEN_DMA_C_ADDRESS, |
297 | [PCM_SPDIF] = OXYGEN_DMA_SPDIF_ADDRESS, |
298 | [PCM_MULTICH] = OXYGEN_DMA_MULTICH_ADDRESS, |
299 | [PCM_AC97] = OXYGEN_DMA_AC97_ADDRESS, |
300 | }; |
301 | |
302 | static int oxygen_hw_params(struct snd_pcm_substream *substream, |
303 | struct snd_pcm_hw_params *hw_params) |
304 | { |
305 | struct oxygen *chip = snd_pcm_substream_chip(substream); |
306 | unsigned int channel = oxygen_substream_channel(substream); |
307 | |
308 | oxygen_write32(chip, reg: channel_base_registers[channel], |
309 | value: (u32)substream->runtime->dma_addr); |
310 | if (channel == PCM_MULTICH) { |
311 | oxygen_write32(chip, OXYGEN_DMA_MULTICH_COUNT, |
312 | value: params_buffer_bytes(p: hw_params) / 4 - 1); |
313 | oxygen_write32(chip, OXYGEN_DMA_MULTICH_TCOUNT, |
314 | value: params_period_bytes(p: hw_params) / 4 - 1); |
315 | } else { |
316 | oxygen_write16(chip, reg: channel_base_registers[channel] + 4, |
317 | value: params_buffer_bytes(p: hw_params) / 4 - 1); |
318 | oxygen_write16(chip, reg: channel_base_registers[channel] + 6, |
319 | value: params_period_bytes(p: hw_params) / 4 - 1); |
320 | } |
321 | return 0; |
322 | } |
323 | |
324 | static u16 get_mclk(struct oxygen *chip, unsigned int channel, |
325 | struct snd_pcm_hw_params *params) |
326 | { |
327 | unsigned int mclks, shift; |
328 | |
329 | if (channel == PCM_MULTICH) |
330 | mclks = chip->model.dac_mclks; |
331 | else |
332 | mclks = chip->model.adc_mclks; |
333 | |
334 | if (params_rate(p: params) <= 48000) |
335 | shift = 0; |
336 | else if (params_rate(p: params) <= 96000) |
337 | shift = 2; |
338 | else |
339 | shift = 4; |
340 | |
341 | return OXYGEN_I2S_MCLK(mclks >> shift); |
342 | } |
343 | |
344 | static int oxygen_rec_a_hw_params(struct snd_pcm_substream *substream, |
345 | struct snd_pcm_hw_params *hw_params) |
346 | { |
347 | struct oxygen *chip = snd_pcm_substream_chip(substream); |
348 | int err; |
349 | |
350 | err = oxygen_hw_params(substream, hw_params); |
351 | if (err < 0) |
352 | return err; |
353 | |
354 | spin_lock_irq(lock: &chip->reg_lock); |
355 | oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, |
356 | value: oxygen_format(hw_params) << OXYGEN_REC_FORMAT_A_SHIFT, |
357 | OXYGEN_REC_FORMAT_A_MASK); |
358 | oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, |
359 | value: oxygen_rate(hw_params) | |
360 | chip->model.adc_i2s_format | |
361 | get_mclk(chip, PCM_A, params: hw_params) | |
362 | oxygen_i2s_bits(hw_params), |
363 | OXYGEN_I2S_RATE_MASK | |
364 | OXYGEN_I2S_FORMAT_MASK | |
365 | OXYGEN_I2S_MCLK_MASK | |
366 | OXYGEN_I2S_BITS_MASK); |
367 | spin_unlock_irq(lock: &chip->reg_lock); |
368 | |
369 | mutex_lock(&chip->mutex); |
370 | chip->model.set_adc_params(chip, hw_params); |
371 | mutex_unlock(lock: &chip->mutex); |
372 | return 0; |
373 | } |
374 | |
375 | static int oxygen_rec_b_hw_params(struct snd_pcm_substream *substream, |
376 | struct snd_pcm_hw_params *hw_params) |
377 | { |
378 | struct oxygen *chip = snd_pcm_substream_chip(substream); |
379 | int is_ac97; |
380 | int err; |
381 | |
382 | err = oxygen_hw_params(substream, hw_params); |
383 | if (err < 0) |
384 | return err; |
385 | |
386 | is_ac97 = chip->has_ac97_1 && |
387 | (chip->model.device_config & CAPTURE_2_FROM_AC97_1); |
388 | |
389 | spin_lock_irq(lock: &chip->reg_lock); |
390 | oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, |
391 | value: oxygen_format(hw_params) << OXYGEN_REC_FORMAT_B_SHIFT, |
392 | OXYGEN_REC_FORMAT_B_MASK); |
393 | if (!is_ac97) |
394 | oxygen_write16_masked(chip, OXYGEN_I2S_B_FORMAT, |
395 | value: oxygen_rate(hw_params) | |
396 | chip->model.adc_i2s_format | |
397 | get_mclk(chip, PCM_B, params: hw_params) | |
398 | oxygen_i2s_bits(hw_params), |
399 | OXYGEN_I2S_RATE_MASK | |
400 | OXYGEN_I2S_FORMAT_MASK | |
401 | OXYGEN_I2S_MCLK_MASK | |
402 | OXYGEN_I2S_BITS_MASK); |
403 | spin_unlock_irq(lock: &chip->reg_lock); |
404 | |
405 | if (!is_ac97) { |
406 | mutex_lock(&chip->mutex); |
407 | chip->model.set_adc_params(chip, hw_params); |
408 | mutex_unlock(lock: &chip->mutex); |
409 | } |
410 | return 0; |
411 | } |
412 | |
413 | static int oxygen_rec_c_hw_params(struct snd_pcm_substream *substream, |
414 | struct snd_pcm_hw_params *hw_params) |
415 | { |
416 | struct oxygen *chip = snd_pcm_substream_chip(substream); |
417 | bool is_spdif; |
418 | int err; |
419 | |
420 | err = oxygen_hw_params(substream, hw_params); |
421 | if (err < 0) |
422 | return err; |
423 | |
424 | is_spdif = chip->model.device_config & CAPTURE_1_FROM_SPDIF; |
425 | |
426 | spin_lock_irq(lock: &chip->reg_lock); |
427 | oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, |
428 | value: oxygen_format(hw_params) << OXYGEN_REC_FORMAT_C_SHIFT, |
429 | OXYGEN_REC_FORMAT_C_MASK); |
430 | if (!is_spdif) |
431 | oxygen_write16_masked(chip, OXYGEN_I2S_C_FORMAT, |
432 | value: oxygen_rate(hw_params) | |
433 | chip->model.adc_i2s_format | |
434 | get_mclk(chip, PCM_B, params: hw_params) | |
435 | oxygen_i2s_bits(hw_params), |
436 | OXYGEN_I2S_RATE_MASK | |
437 | OXYGEN_I2S_FORMAT_MASK | |
438 | OXYGEN_I2S_MCLK_MASK | |
439 | OXYGEN_I2S_BITS_MASK); |
440 | spin_unlock_irq(lock: &chip->reg_lock); |
441 | |
442 | if (!is_spdif) { |
443 | mutex_lock(&chip->mutex); |
444 | chip->model.set_adc_params(chip, hw_params); |
445 | mutex_unlock(lock: &chip->mutex); |
446 | } |
447 | return 0; |
448 | } |
449 | |
450 | static int oxygen_spdif_hw_params(struct snd_pcm_substream *substream, |
451 | struct snd_pcm_hw_params *hw_params) |
452 | { |
453 | struct oxygen *chip = snd_pcm_substream_chip(substream); |
454 | int err; |
455 | |
456 | err = oxygen_hw_params(substream, hw_params); |
457 | if (err < 0) |
458 | return err; |
459 | |
460 | mutex_lock(&chip->mutex); |
461 | spin_lock_irq(lock: &chip->reg_lock); |
462 | oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, |
463 | OXYGEN_SPDIF_OUT_ENABLE); |
464 | oxygen_write8_masked(chip, OXYGEN_PLAY_FORMAT, |
465 | value: oxygen_format(hw_params) << OXYGEN_SPDIF_FORMAT_SHIFT, |
466 | OXYGEN_SPDIF_FORMAT_MASK); |
467 | oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL, |
468 | value: oxygen_rate(hw_params) << OXYGEN_SPDIF_OUT_RATE_SHIFT, |
469 | OXYGEN_SPDIF_OUT_RATE_MASK); |
470 | oxygen_update_spdif_source(chip); |
471 | spin_unlock_irq(lock: &chip->reg_lock); |
472 | mutex_unlock(lock: &chip->mutex); |
473 | return 0; |
474 | } |
475 | |
476 | static int oxygen_multich_hw_params(struct snd_pcm_substream *substream, |
477 | struct snd_pcm_hw_params *hw_params) |
478 | { |
479 | struct oxygen *chip = snd_pcm_substream_chip(substream); |
480 | int err; |
481 | |
482 | err = oxygen_hw_params(substream, hw_params); |
483 | if (err < 0) |
484 | return err; |
485 | |
486 | mutex_lock(&chip->mutex); |
487 | spin_lock_irq(lock: &chip->reg_lock); |
488 | oxygen_write8_masked(chip, OXYGEN_PLAY_CHANNELS, |
489 | value: oxygen_play_channels(hw_params), |
490 | OXYGEN_PLAY_CHANNELS_MASK); |
491 | oxygen_write8_masked(chip, OXYGEN_PLAY_FORMAT, |
492 | value: oxygen_format(hw_params) << OXYGEN_MULTICH_FORMAT_SHIFT, |
493 | OXYGEN_MULTICH_FORMAT_MASK); |
494 | oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT, |
495 | value: oxygen_rate(hw_params) | |
496 | chip->model.dac_i2s_format | |
497 | get_mclk(chip, PCM_MULTICH, params: hw_params) | |
498 | oxygen_i2s_bits(hw_params), |
499 | OXYGEN_I2S_RATE_MASK | |
500 | OXYGEN_I2S_FORMAT_MASK | |
501 | OXYGEN_I2S_MCLK_MASK | |
502 | OXYGEN_I2S_BITS_MASK); |
503 | oxygen_update_spdif_source(chip); |
504 | spin_unlock_irq(lock: &chip->reg_lock); |
505 | |
506 | chip->model.set_dac_params(chip, hw_params); |
507 | oxygen_update_dac_routing(chip); |
508 | mutex_unlock(lock: &chip->mutex); |
509 | return 0; |
510 | } |
511 | |
512 | static int oxygen_hw_free(struct snd_pcm_substream *substream) |
513 | { |
514 | struct oxygen *chip = snd_pcm_substream_chip(substream); |
515 | unsigned int channel = oxygen_substream_channel(substream); |
516 | unsigned int channel_mask = 1 << channel; |
517 | |
518 | spin_lock_irq(lock: &chip->reg_lock); |
519 | chip->interrupt_mask &= ~channel_mask; |
520 | oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, value: chip->interrupt_mask); |
521 | |
522 | oxygen_set_bits8(chip, OXYGEN_DMA_FLUSH, value: channel_mask); |
523 | oxygen_clear_bits8(chip, OXYGEN_DMA_FLUSH, value: channel_mask); |
524 | spin_unlock_irq(lock: &chip->reg_lock); |
525 | |
526 | return 0; |
527 | } |
528 | |
529 | static int oxygen_spdif_hw_free(struct snd_pcm_substream *substream) |
530 | { |
531 | struct oxygen *chip = snd_pcm_substream_chip(substream); |
532 | |
533 | spin_lock_irq(lock: &chip->reg_lock); |
534 | oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, |
535 | OXYGEN_SPDIF_OUT_ENABLE); |
536 | spin_unlock_irq(lock: &chip->reg_lock); |
537 | return oxygen_hw_free(substream); |
538 | } |
539 | |
540 | static int oxygen_prepare(struct snd_pcm_substream *substream) |
541 | { |
542 | struct oxygen *chip = snd_pcm_substream_chip(substream); |
543 | unsigned int channel = oxygen_substream_channel(substream); |
544 | unsigned int channel_mask = 1 << channel; |
545 | |
546 | spin_lock_irq(lock: &chip->reg_lock); |
547 | oxygen_set_bits8(chip, OXYGEN_DMA_FLUSH, value: channel_mask); |
548 | oxygen_clear_bits8(chip, OXYGEN_DMA_FLUSH, value: channel_mask); |
549 | |
550 | if (substream->runtime->no_period_wakeup) |
551 | chip->interrupt_mask &= ~channel_mask; |
552 | else |
553 | chip->interrupt_mask |= channel_mask; |
554 | oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, value: chip->interrupt_mask); |
555 | spin_unlock_irq(lock: &chip->reg_lock); |
556 | return 0; |
557 | } |
558 | |
559 | static int oxygen_trigger(struct snd_pcm_substream *substream, int cmd) |
560 | { |
561 | struct oxygen *chip = snd_pcm_substream_chip(substream); |
562 | struct snd_pcm_substream *s; |
563 | unsigned int mask = 0; |
564 | int pausing; |
565 | |
566 | switch (cmd) { |
567 | case SNDRV_PCM_TRIGGER_STOP: |
568 | case SNDRV_PCM_TRIGGER_START: |
569 | case SNDRV_PCM_TRIGGER_SUSPEND: |
570 | pausing = 0; |
571 | break; |
572 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
573 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
574 | pausing = 1; |
575 | break; |
576 | default: |
577 | return -EINVAL; |
578 | } |
579 | |
580 | snd_pcm_group_for_each_entry(s, substream) { |
581 | if (snd_pcm_substream_chip(s) == chip) { |
582 | mask |= 1 << oxygen_substream_channel(substream: s); |
583 | snd_pcm_trigger_done(substream: s, master: substream); |
584 | } |
585 | } |
586 | |
587 | spin_lock(lock: &chip->reg_lock); |
588 | if (!pausing) { |
589 | if (cmd == SNDRV_PCM_TRIGGER_START) |
590 | chip->pcm_running |= mask; |
591 | else |
592 | chip->pcm_running &= ~mask; |
593 | oxygen_write8(chip, OXYGEN_DMA_STATUS, value: chip->pcm_running); |
594 | } else { |
595 | if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) |
596 | oxygen_set_bits8(chip, OXYGEN_DMA_PAUSE, value: mask); |
597 | else |
598 | oxygen_clear_bits8(chip, OXYGEN_DMA_PAUSE, value: mask); |
599 | } |
600 | spin_unlock(lock: &chip->reg_lock); |
601 | return 0; |
602 | } |
603 | |
604 | static snd_pcm_uframes_t oxygen_pointer(struct snd_pcm_substream *substream) |
605 | { |
606 | struct oxygen *chip = snd_pcm_substream_chip(substream); |
607 | struct snd_pcm_runtime *runtime = substream->runtime; |
608 | unsigned int channel = oxygen_substream_channel(substream); |
609 | u32 curr_addr; |
610 | |
611 | /* no spinlock, this read should be atomic */ |
612 | curr_addr = oxygen_read32(chip, reg: channel_base_registers[channel]); |
613 | return bytes_to_frames(runtime, size: curr_addr - (u32)runtime->dma_addr); |
614 | } |
615 | |
616 | static const struct snd_pcm_ops oxygen_rec_a_ops = { |
617 | .open = oxygen_rec_a_open, |
618 | .close = oxygen_close, |
619 | .hw_params = oxygen_rec_a_hw_params, |
620 | .hw_free = oxygen_hw_free, |
621 | .prepare = oxygen_prepare, |
622 | .trigger = oxygen_trigger, |
623 | .pointer = oxygen_pointer, |
624 | }; |
625 | |
626 | static const struct snd_pcm_ops oxygen_rec_b_ops = { |
627 | .open = oxygen_rec_b_open, |
628 | .close = oxygen_close, |
629 | .hw_params = oxygen_rec_b_hw_params, |
630 | .hw_free = oxygen_hw_free, |
631 | .prepare = oxygen_prepare, |
632 | .trigger = oxygen_trigger, |
633 | .pointer = oxygen_pointer, |
634 | }; |
635 | |
636 | static const struct snd_pcm_ops oxygen_rec_c_ops = { |
637 | .open = oxygen_rec_c_open, |
638 | .close = oxygen_close, |
639 | .hw_params = oxygen_rec_c_hw_params, |
640 | .hw_free = oxygen_hw_free, |
641 | .prepare = oxygen_prepare, |
642 | .trigger = oxygen_trigger, |
643 | .pointer = oxygen_pointer, |
644 | }; |
645 | |
646 | static const struct snd_pcm_ops oxygen_spdif_ops = { |
647 | .open = oxygen_spdif_open, |
648 | .close = oxygen_close, |
649 | .hw_params = oxygen_spdif_hw_params, |
650 | .hw_free = oxygen_spdif_hw_free, |
651 | .prepare = oxygen_prepare, |
652 | .trigger = oxygen_trigger, |
653 | .pointer = oxygen_pointer, |
654 | }; |
655 | |
656 | static const struct snd_pcm_ops oxygen_multich_ops = { |
657 | .open = oxygen_multich_open, |
658 | .close = oxygen_close, |
659 | .hw_params = oxygen_multich_hw_params, |
660 | .hw_free = oxygen_hw_free, |
661 | .prepare = oxygen_prepare, |
662 | .trigger = oxygen_trigger, |
663 | .pointer = oxygen_pointer, |
664 | }; |
665 | |
666 | static const struct snd_pcm_ops oxygen_ac97_ops = { |
667 | .open = oxygen_ac97_open, |
668 | .close = oxygen_close, |
669 | .hw_params = oxygen_hw_params, |
670 | .hw_free = oxygen_hw_free, |
671 | .prepare = oxygen_prepare, |
672 | .trigger = oxygen_trigger, |
673 | .pointer = oxygen_pointer, |
674 | }; |
675 | |
676 | int oxygen_pcm_init(struct oxygen *chip) |
677 | { |
678 | struct snd_pcm *pcm; |
679 | int outs, ins; |
680 | int err; |
681 | |
682 | outs = !!(chip->model.device_config & PLAYBACK_0_TO_I2S); |
683 | ins = !!(chip->model.device_config & (CAPTURE_0_FROM_I2S_1 | |
684 | CAPTURE_0_FROM_I2S_2)); |
685 | if (outs | ins) { |
686 | err = snd_pcm_new(card: chip->card, id: "Multichannel" , |
687 | device: 0, playback_count: outs, capture_count: ins, rpcm: &pcm); |
688 | if (err < 0) |
689 | return err; |
690 | if (outs) |
691 | snd_pcm_set_ops(pcm, direction: SNDRV_PCM_STREAM_PLAYBACK, |
692 | ops: &oxygen_multich_ops); |
693 | if (chip->model.device_config & CAPTURE_0_FROM_I2S_1) |
694 | snd_pcm_set_ops(pcm, direction: SNDRV_PCM_STREAM_CAPTURE, |
695 | ops: &oxygen_rec_a_ops); |
696 | else if (chip->model.device_config & CAPTURE_0_FROM_I2S_2) |
697 | snd_pcm_set_ops(pcm, direction: SNDRV_PCM_STREAM_CAPTURE, |
698 | ops: &oxygen_rec_b_ops); |
699 | pcm->private_data = chip; |
700 | strcpy(p: pcm->name, q: "Multichannel" ); |
701 | if (outs) |
702 | snd_pcm_set_managed_buffer(substream: pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream, |
703 | SNDRV_DMA_TYPE_DEV, |
704 | data: &chip->pci->dev, |
705 | DEFAULT_BUFFER_BYTES_MULTICH, |
706 | BUFFER_BYTES_MAX_MULTICH); |
707 | if (ins) |
708 | snd_pcm_set_managed_buffer(substream: pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream, |
709 | SNDRV_DMA_TYPE_DEV, |
710 | data: &chip->pci->dev, |
711 | DEFAULT_BUFFER_BYTES, |
712 | BUFFER_BYTES_MAX); |
713 | } |
714 | |
715 | outs = !!(chip->model.device_config & PLAYBACK_1_TO_SPDIF); |
716 | ins = !!(chip->model.device_config & CAPTURE_1_FROM_SPDIF); |
717 | if (outs | ins) { |
718 | err = snd_pcm_new(card: chip->card, id: "Digital" , device: 1, playback_count: outs, capture_count: ins, rpcm: &pcm); |
719 | if (err < 0) |
720 | return err; |
721 | if (outs) |
722 | snd_pcm_set_ops(pcm, direction: SNDRV_PCM_STREAM_PLAYBACK, |
723 | ops: &oxygen_spdif_ops); |
724 | if (ins) |
725 | snd_pcm_set_ops(pcm, direction: SNDRV_PCM_STREAM_CAPTURE, |
726 | ops: &oxygen_rec_c_ops); |
727 | pcm->private_data = chip; |
728 | strcpy(p: pcm->name, q: "Digital" ); |
729 | snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, |
730 | data: &chip->pci->dev, |
731 | DEFAULT_BUFFER_BYTES, |
732 | BUFFER_BYTES_MAX); |
733 | } |
734 | |
735 | if (chip->has_ac97_1) { |
736 | outs = !!(chip->model.device_config & PLAYBACK_2_TO_AC97_1); |
737 | ins = !!(chip->model.device_config & CAPTURE_2_FROM_AC97_1); |
738 | } else { |
739 | outs = 0; |
740 | ins = !!(chip->model.device_config & CAPTURE_2_FROM_I2S_2); |
741 | } |
742 | if (outs | ins) { |
743 | err = snd_pcm_new(card: chip->card, id: outs ? "AC97" : "Analog2" , |
744 | device: 2, playback_count: outs, capture_count: ins, rpcm: &pcm); |
745 | if (err < 0) |
746 | return err; |
747 | if (outs) { |
748 | snd_pcm_set_ops(pcm, direction: SNDRV_PCM_STREAM_PLAYBACK, |
749 | ops: &oxygen_ac97_ops); |
750 | oxygen_write8_masked(chip, OXYGEN_REC_ROUTING, |
751 | OXYGEN_REC_B_ROUTE_AC97_1, |
752 | OXYGEN_REC_B_ROUTE_MASK); |
753 | } |
754 | if (ins) |
755 | snd_pcm_set_ops(pcm, direction: SNDRV_PCM_STREAM_CAPTURE, |
756 | ops: &oxygen_rec_b_ops); |
757 | pcm->private_data = chip; |
758 | strcpy(p: pcm->name, q: outs ? "Front Panel" : "Analog 2" ); |
759 | snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, |
760 | data: &chip->pci->dev, |
761 | DEFAULT_BUFFER_BYTES, |
762 | BUFFER_BYTES_MAX); |
763 | } |
764 | |
765 | ins = !!(chip->model.device_config & CAPTURE_3_FROM_I2S_3); |
766 | if (ins) { |
767 | err = snd_pcm_new(card: chip->card, id: "Analog3" , device: 3, playback_count: 0, capture_count: ins, rpcm: &pcm); |
768 | if (err < 0) |
769 | return err; |
770 | snd_pcm_set_ops(pcm, direction: SNDRV_PCM_STREAM_CAPTURE, |
771 | ops: &oxygen_rec_c_ops); |
772 | oxygen_write8_masked(chip, OXYGEN_REC_ROUTING, |
773 | OXYGEN_REC_C_ROUTE_I2S_ADC_3, |
774 | OXYGEN_REC_C_ROUTE_MASK); |
775 | pcm->private_data = chip; |
776 | strcpy(p: pcm->name, q: "Analog 3" ); |
777 | snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, |
778 | data: &chip->pci->dev, |
779 | DEFAULT_BUFFER_BYTES, |
780 | BUFFER_BYTES_MAX); |
781 | } |
782 | return 0; |
783 | } |
784 | |