blob: 5f67a799a034763ebf94435313cd7ee8f6b1b072 [file] [log] [blame]
Clemens Ladischd0ce9942007-12-23 19:50:57 +01001/*
2 * C-Media CMI8788 driver - PCM code
3 *
4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5 *
6 *
7 * This driver is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License, version 2.
9 *
10 * This driver is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this driver; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
Clemens Ladischd0ce9942007-12-23 19:50:57 +010020#include <linux/pci.h>
21#include <sound/control.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include "oxygen.h"
26
27static struct snd_pcm_hardware oxygen_hardware[PCM_COUNT] = {
28 [PCM_A] = {
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 .formats = SNDRV_PCM_FMTBIT_S16_LE |
35 SNDRV_PCM_FMTBIT_S32_LE,
36 .rates = SNDRV_PCM_RATE_44100 |
37 SNDRV_PCM_RATE_48000 |
38 SNDRV_PCM_RATE_96000 |
39 SNDRV_PCM_RATE_192000,
40 .rate_min = 44100,
41 .rate_max = 192000,
42 .channels_min = 2,
43 .channels_max = 2,
44 .buffer_bytes_max = 256 * 1024,
45 .period_bytes_min = 128,
46 .period_bytes_max = 128 * 1024,
47 .periods_min = 2,
48 .periods_max = 2048,
49 },
50 [PCM_B] = {
51 .info = SNDRV_PCM_INFO_MMAP |
52 SNDRV_PCM_INFO_MMAP_VALID |
53 SNDRV_PCM_INFO_INTERLEAVED |
54 SNDRV_PCM_INFO_PAUSE |
55 SNDRV_PCM_INFO_SYNC_START,
56 .formats = SNDRV_PCM_FMTBIT_S16_LE |
57 SNDRV_PCM_FMTBIT_S32_LE,
58 .rates = SNDRV_PCM_RATE_32000 |
59 SNDRV_PCM_RATE_44100 |
60 SNDRV_PCM_RATE_48000 |
61 SNDRV_PCM_RATE_64000 |
62 SNDRV_PCM_RATE_88200 |
63 SNDRV_PCM_RATE_96000 |
64 SNDRV_PCM_RATE_176400 |
65 SNDRV_PCM_RATE_192000,
66 .rate_min = 32000,
67 .rate_max = 192000,
68 .channels_min = 2,
69 .channels_max = 2,
70 .buffer_bytes_max = 256 * 1024,
71 .period_bytes_min = 128,
72 .period_bytes_max = 128 * 1024,
73 .periods_min = 2,
74 .periods_max = 2048,
75 },
76 [PCM_C] = {
77 .info = SNDRV_PCM_INFO_MMAP |
78 SNDRV_PCM_INFO_MMAP_VALID |
79 SNDRV_PCM_INFO_INTERLEAVED |
80 SNDRV_PCM_INFO_PAUSE |
81 SNDRV_PCM_INFO_SYNC_START,
82 .formats = SNDRV_PCM_FMTBIT_S16_LE |
83 SNDRV_PCM_FMTBIT_S32_LE,
84 .rates = SNDRV_PCM_RATE_44100 |
85 SNDRV_PCM_RATE_48000 |
86 SNDRV_PCM_RATE_88200 |
87 SNDRV_PCM_RATE_96000,
88 .rate_min = 44100,
89 .rate_max = 96000,
90 .channels_min = 2,
91 .channels_max = 2,
92 .buffer_bytes_max = 256 * 1024,
93 .period_bytes_min = 128,
94 .period_bytes_max = 128 * 1024,
95 .periods_min = 2,
96 .periods_max = 2048,
97 },
98 [PCM_SPDIF] = {
99 .info = SNDRV_PCM_INFO_MMAP |
100 SNDRV_PCM_INFO_MMAP_VALID |
101 SNDRV_PCM_INFO_INTERLEAVED |
102 SNDRV_PCM_INFO_PAUSE |
103 SNDRV_PCM_INFO_SYNC_START,
104 .formats = SNDRV_PCM_FMTBIT_S16_LE |
105 SNDRV_PCM_FMTBIT_S32_LE,
106 .rates = SNDRV_PCM_RATE_32000 |
107 SNDRV_PCM_RATE_44100 |
108 SNDRV_PCM_RATE_48000 |
109 SNDRV_PCM_RATE_64000 |
110 SNDRV_PCM_RATE_88200 |
111 SNDRV_PCM_RATE_96000 |
112 SNDRV_PCM_RATE_176400 |
113 SNDRV_PCM_RATE_192000,
114 .rate_min = 32000,
115 .rate_max = 192000,
116 .channels_min = 2,
117 .channels_max = 2,
118 .buffer_bytes_max = 256 * 1024,
119 .period_bytes_min = 128,
120 .period_bytes_max = 128 * 1024,
121 .periods_min = 2,
122 .periods_max = 2048,
123 },
124 [PCM_MULTICH] = {
125 .info = SNDRV_PCM_INFO_MMAP |
126 SNDRV_PCM_INFO_MMAP_VALID |
127 SNDRV_PCM_INFO_INTERLEAVED |
128 SNDRV_PCM_INFO_PAUSE |
129 SNDRV_PCM_INFO_SYNC_START,
130 .formats = SNDRV_PCM_FMTBIT_S16_LE |
131 SNDRV_PCM_FMTBIT_S32_LE,
132 .rates = SNDRV_PCM_RATE_32000 |
133 SNDRV_PCM_RATE_44100 |
134 SNDRV_PCM_RATE_48000 |
135 SNDRV_PCM_RATE_64000 |
136 SNDRV_PCM_RATE_88200 |
137 SNDRV_PCM_RATE_96000 |
138 SNDRV_PCM_RATE_176400 |
139 SNDRV_PCM_RATE_192000,
140 .rate_min = 32000,
141 .rate_max = 192000,
142 .channels_min = 2,
143 .channels_max = 8,
144 .buffer_bytes_max = 2048 * 1024,
145 .period_bytes_min = 128,
146 .period_bytes_max = 256 * 1024,
147 .periods_min = 2,
148 .periods_max = 16384,
149 },
150 [PCM_AC97] = {
151 .info = SNDRV_PCM_INFO_MMAP |
152 SNDRV_PCM_INFO_MMAP_VALID |
153 SNDRV_PCM_INFO_INTERLEAVED |
154 SNDRV_PCM_INFO_PAUSE |
155 SNDRV_PCM_INFO_SYNC_START,
156 .formats = SNDRV_PCM_FMTBIT_S16_LE,
157 .rates = SNDRV_PCM_RATE_48000,
158 .rate_min = 48000,
159 .rate_max = 48000,
160 .channels_min = 2,
161 .channels_max = 2,
162 .buffer_bytes_max = 256 * 1024,
163 .period_bytes_min = 128,
164 .period_bytes_max = 128 * 1024,
165 .periods_min = 2,
166 .periods_max = 2048,
167 },
168};
169
Clemens Ladisch740eb832008-01-04 09:22:20 +0100170static inline unsigned int
171oxygen_substream_channel(struct snd_pcm_substream *substream)
172{
173 return (unsigned int)(uintptr_t)substream->runtime->private_data;
174}
175
Clemens Ladischd0ce9942007-12-23 19:50:57 +0100176static int oxygen_open(struct snd_pcm_substream *substream,
177 unsigned int channel)
178{
179 struct oxygen *chip = snd_pcm_substream_chip(substream);
180 struct snd_pcm_runtime *runtime = substream->runtime;
181 int err;
182
Clemens Ladisch740eb832008-01-04 09:22:20 +0100183 runtime->private_data = (void *)(uintptr_t)channel;
Clemens Ladischd0ce9942007-12-23 19:50:57 +0100184 runtime->hw = oxygen_hardware[channel];
185 err = snd_pcm_hw_constraint_step(runtime, 0,
186 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
187 if (err < 0)
188 return err;
189 err = snd_pcm_hw_constraint_step(runtime, 0,
190 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
191 if (err < 0)
192 return err;
193 if (runtime->hw.formats & SNDRV_PCM_FMTBIT_S32_LE) {
194 err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
195 if (err < 0)
196 return err;
197 }
198 if (runtime->hw.channels_max > 2) {
199 err = snd_pcm_hw_constraint_step(runtime, 0,
200 SNDRV_PCM_HW_PARAM_CHANNELS,
201 2);
202 if (err < 0)
203 return err;
204 }
205 snd_pcm_set_sync(substream);
206 chip->streams[channel] = substream;
207
208 mutex_lock(&chip->mutex);
209 chip->pcm_active |= 1 << channel;
210 if (channel == PCM_SPDIF) {
211 chip->spdif_pcm_bits = chip->spdif_bits;
Clemens Ladisch01a3aff2008-01-14 08:56:01 +0100212 chip->controls[CONTROL_SPDIF_PCM]->vd[0].access &=
Clemens Ladischd0ce9942007-12-23 19:50:57 +0100213 ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
214 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE |
215 SNDRV_CTL_EVENT_MASK_INFO,
Clemens Ladisch01a3aff2008-01-14 08:56:01 +0100216 &chip->controls[CONTROL_SPDIF_PCM]->id);
Clemens Ladischd0ce9942007-12-23 19:50:57 +0100217 }
218 mutex_unlock(&chip->mutex);
219
220 return 0;
221}
222
223static int oxygen_rec_a_open(struct snd_pcm_substream *substream)
224{
225 return oxygen_open(substream, PCM_A);
226}
227
228static int oxygen_rec_b_open(struct snd_pcm_substream *substream)
229{
230 return oxygen_open(substream, PCM_B);
231}
232
233static int oxygen_rec_c_open(struct snd_pcm_substream *substream)
234{
235 return oxygen_open(substream, PCM_C);
236}
237
238static int oxygen_spdif_open(struct snd_pcm_substream *substream)
239{
240 return oxygen_open(substream, PCM_SPDIF);
241}
242
243static int oxygen_multich_open(struct snd_pcm_substream *substream)
244{
245 return oxygen_open(substream, PCM_MULTICH);
246}
247
248static int oxygen_ac97_open(struct snd_pcm_substream *substream)
249{
250 return oxygen_open(substream, PCM_AC97);
251}
252
253static int oxygen_close(struct snd_pcm_substream *substream)
254{
255 struct oxygen *chip = snd_pcm_substream_chip(substream);
Clemens Ladisch740eb832008-01-04 09:22:20 +0100256 unsigned int channel = oxygen_substream_channel(substream);
Clemens Ladischd0ce9942007-12-23 19:50:57 +0100257
258 mutex_lock(&chip->mutex);
259 chip->pcm_active &= ~(1 << channel);
260 if (channel == PCM_SPDIF) {
Clemens Ladisch01a3aff2008-01-14 08:56:01 +0100261 chip->controls[CONTROL_SPDIF_PCM]->vd[0].access |=
Clemens Ladischd0ce9942007-12-23 19:50:57 +0100262 SNDRV_CTL_ELEM_ACCESS_INACTIVE;
263 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE |
264 SNDRV_CTL_EVENT_MASK_INFO,
Clemens Ladisch01a3aff2008-01-14 08:56:01 +0100265 &chip->controls[CONTROL_SPDIF_PCM]->id);
Clemens Ladischd0ce9942007-12-23 19:50:57 +0100266 }
267 if (channel == PCM_SPDIF || channel == PCM_MULTICH)
268 oxygen_update_spdif_source(chip);
269 mutex_unlock(&chip->mutex);
270
271 chip->streams[channel] = NULL;
272 return 0;
273}
274
275static unsigned int oxygen_format(struct snd_pcm_hw_params *hw_params)
276{
277 if (params_format(hw_params) == SNDRV_PCM_FORMAT_S32_LE)
278 return OXYGEN_FORMAT_24;
279 else
280 return OXYGEN_FORMAT_16;
281}
282
283static unsigned int oxygen_rate(struct snd_pcm_hw_params *hw_params)
284{
285 switch (params_rate(hw_params)) {
286 case 32000:
287 return OXYGEN_RATE_32000;
288 case 44100:
289 return OXYGEN_RATE_44100;
290 default: /* 48000 */
291 return OXYGEN_RATE_48000;
292 case 64000:
293 return OXYGEN_RATE_64000;
294 case 88200:
295 return OXYGEN_RATE_88200;
296 case 96000:
297 return OXYGEN_RATE_96000;
298 case 176400:
299 return OXYGEN_RATE_176400;
300 case 192000:
301 return OXYGEN_RATE_192000;
302 }
303}
304
305static unsigned int oxygen_i2s_magic2(struct snd_pcm_hw_params *hw_params)
306{
307 return params_rate(hw_params) <= 96000 ? 0x10 : 0x00;
308}
309
310static unsigned int oxygen_i2s_format(struct snd_pcm_hw_params *hw_params)
311{
312 if (params_format(hw_params) == SNDRV_PCM_FORMAT_S32_LE)
313 return OXYGEN_I2S_FORMAT_24;
314 else
315 return OXYGEN_I2S_FORMAT_16;
316}
317
318static unsigned int oxygen_play_channels(struct snd_pcm_hw_params *hw_params)
319{
320 switch (params_channels(hw_params)) {
321 default: /* 2 */
322 return OXYGEN_PLAY_CHANNELS_2;
323 case 4:
324 return OXYGEN_PLAY_CHANNELS_4;
325 case 6:
326 return OXYGEN_PLAY_CHANNELS_6;
327 case 8:
328 return OXYGEN_PLAY_CHANNELS_8;
329 }
330}
331
332static const unsigned int channel_base_registers[PCM_COUNT] = {
333 [PCM_A] = OXYGEN_DMA_A_ADDRESS,
334 [PCM_B] = OXYGEN_DMA_B_ADDRESS,
335 [PCM_C] = OXYGEN_DMA_C_ADDRESS,
336 [PCM_SPDIF] = OXYGEN_DMA_SPDIF_ADDRESS,
337 [PCM_MULTICH] = OXYGEN_DMA_MULTICH_ADDRESS,
338 [PCM_AC97] = OXYGEN_DMA_AC97_ADDRESS,
339};
340
341static int oxygen_hw_params(struct snd_pcm_substream *substream,
342 struct snd_pcm_hw_params *hw_params)
343{
344 struct oxygen *chip = snd_pcm_substream_chip(substream);
Clemens Ladisch740eb832008-01-04 09:22:20 +0100345 unsigned int channel = oxygen_substream_channel(substream);
Clemens Ladischd0ce9942007-12-23 19:50:57 +0100346 int err;
347
348 err = snd_pcm_lib_malloc_pages(substream,
349 params_buffer_bytes(hw_params));
350 if (err < 0)
351 return err;
352
353 oxygen_write32(chip, channel_base_registers[channel],
354 (u32)substream->runtime->dma_addr);
355 if (channel == PCM_MULTICH) {
356 oxygen_write32(chip, OXYGEN_DMA_MULTICH_COUNT,
357 params_buffer_bytes(hw_params) / 4 - 1);
358 oxygen_write32(chip, OXYGEN_DMA_MULTICH_TCOUNT,
359 params_period_bytes(hw_params) / 4 - 1);
360 } else {
361 oxygen_write16(chip, channel_base_registers[channel] + 4,
362 params_buffer_bytes(hw_params) / 4 - 1);
363 oxygen_write16(chip, channel_base_registers[channel] + 6,
364 params_period_bytes(hw_params) / 4 - 1);
365 }
366 return 0;
367}
368
369static int oxygen_rec_a_hw_params(struct snd_pcm_substream *substream,
370 struct snd_pcm_hw_params *hw_params)
371{
372 struct oxygen *chip = snd_pcm_substream_chip(substream);
373 int err;
374
375 err = oxygen_hw_params(substream, hw_params);
376 if (err < 0)
377 return err;
378
379 spin_lock_irq(&chip->reg_lock);
380 oxygen_write8_masked(chip, OXYGEN_REC_FORMAT,
381 oxygen_format(hw_params) << OXYGEN_REC_FORMAT_A_SHIFT,
382 OXYGEN_REC_FORMAT_A_MASK);
383 oxygen_write8_masked(chip, OXYGEN_I2S_A_FORMAT,
384 oxygen_rate(hw_params) |
385 oxygen_i2s_magic2(hw_params) |
386 oxygen_i2s_format(hw_params),
387 OXYGEN_I2S_RATE_MASK |
388 OXYGEN_I2S_MAGIC2_MASK |
389 OXYGEN_I2S_FORMAT_MASK);
390 oxygen_clear_bits8(chip, OXYGEN_REC_ROUTING, 0x08);
391 spin_unlock_irq(&chip->reg_lock);
392
393 mutex_lock(&chip->mutex);
394 chip->model->set_adc_params(chip, hw_params);
395 mutex_unlock(&chip->mutex);
396 return 0;
397}
398
399static int oxygen_rec_b_hw_params(struct snd_pcm_substream *substream,
400 struct snd_pcm_hw_params *hw_params)
401{
402 struct oxygen *chip = snd_pcm_substream_chip(substream);
403 int err;
404
405 err = oxygen_hw_params(substream, hw_params);
406 if (err < 0)
407 return err;
408
409 spin_lock_irq(&chip->reg_lock);
410 oxygen_write8_masked(chip, OXYGEN_REC_FORMAT,
411 oxygen_format(hw_params) << OXYGEN_REC_FORMAT_B_SHIFT,
412 OXYGEN_REC_FORMAT_B_MASK);
413 oxygen_write8_masked(chip, OXYGEN_I2S_B_FORMAT,
414 oxygen_rate(hw_params) |
415 oxygen_i2s_magic2(hw_params) |
416 oxygen_i2s_format(hw_params),
417 OXYGEN_I2S_RATE_MASK |
418 OXYGEN_I2S_MAGIC2_MASK |
419 OXYGEN_I2S_FORMAT_MASK);
420 oxygen_clear_bits8(chip, OXYGEN_REC_ROUTING, 0x10);
421 spin_unlock_irq(&chip->reg_lock);
422
423 mutex_lock(&chip->mutex);
424 chip->model->set_adc_params(chip, hw_params);
425 mutex_unlock(&chip->mutex);
426 return 0;
427}
428
429static int oxygen_rec_c_hw_params(struct snd_pcm_substream *substream,
430 struct snd_pcm_hw_params *hw_params)
431{
432 struct oxygen *chip = snd_pcm_substream_chip(substream);
433 int err;
434
435 err = oxygen_hw_params(substream, hw_params);
436 if (err < 0)
437 return err;
438
439 spin_lock_irq(&chip->reg_lock);
440 oxygen_write8_masked(chip, OXYGEN_REC_FORMAT,
441 oxygen_format(hw_params) << OXYGEN_REC_FORMAT_C_SHIFT,
442 OXYGEN_REC_FORMAT_C_MASK);
443 oxygen_clear_bits8(chip, OXYGEN_REC_ROUTING, 0x20);
444 spin_unlock_irq(&chip->reg_lock);
445 return 0;
446}
447
448static int oxygen_spdif_hw_params(struct snd_pcm_substream *substream,
449 struct snd_pcm_hw_params *hw_params)
450{
451 struct oxygen *chip = snd_pcm_substream_chip(substream);
452 int err;
453
454 err = oxygen_hw_params(substream, hw_params);
455 if (err < 0)
456 return err;
457
458 spin_lock_irq(&chip->reg_lock);
459 oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL,
460 OXYGEN_SPDIF_OUT_ENABLE);
461 oxygen_write8_masked(chip, OXYGEN_PLAY_FORMAT,
462 oxygen_format(hw_params) << OXYGEN_SPDIF_FORMAT_SHIFT,
463 OXYGEN_SPDIF_FORMAT_MASK);
464 oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL,
465 oxygen_rate(hw_params) << OXYGEN_SPDIF_OUT_RATE_SHIFT,
466 OXYGEN_SPDIF_OUT_RATE_MASK);
467 oxygen_update_spdif_source(chip);
468 spin_unlock_irq(&chip->reg_lock);
469 return 0;
470}
471
472static int oxygen_multich_hw_params(struct snd_pcm_substream *substream,
473 struct snd_pcm_hw_params *hw_params)
474{
475 struct oxygen *chip = snd_pcm_substream_chip(substream);
476 int err;
477
478 err = oxygen_hw_params(substream, hw_params);
479 if (err < 0)
480 return err;
481
482 spin_lock_irq(&chip->reg_lock);
483 oxygen_write8_masked(chip, OXYGEN_PLAY_CHANNELS,
484 oxygen_play_channels(hw_params),
485 OXYGEN_PLAY_CHANNELS_MASK);
486 oxygen_write8_masked(chip, OXYGEN_PLAY_FORMAT,
487 oxygen_format(hw_params) << OXYGEN_MULTICH_FORMAT_SHIFT,
488 OXYGEN_MULTICH_FORMAT_MASK);
489 oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT,
490 oxygen_rate(hw_params) | oxygen_i2s_format(hw_params),
491 OXYGEN_I2S_RATE_MASK | OXYGEN_I2S_FORMAT_MASK);
492 oxygen_clear_bits16(chip, OXYGEN_PLAY_ROUTING, 0x001f);
493 oxygen_update_dac_routing(chip);
494 oxygen_update_spdif_source(chip);
495 spin_unlock_irq(&chip->reg_lock);
496
497 mutex_lock(&chip->mutex);
498 chip->model->set_dac_params(chip, hw_params);
499 mutex_unlock(&chip->mutex);
500 return 0;
501}
502
503static int oxygen_ac97_hw_params(struct snd_pcm_substream *substream,
504 struct snd_pcm_hw_params *hw_params)
505{
506 struct oxygen *chip = snd_pcm_substream_chip(substream);
507 int err;
508
509 err = oxygen_hw_params(substream, hw_params);
510 if (err < 0)
511 return err;
512
513 spin_lock_irq(&chip->reg_lock);
514 oxygen_write8_masked(chip, OXYGEN_PLAY_FORMAT,
515 oxygen_format(hw_params) << OXYGEN_AC97_FORMAT_SHIFT,
516 OXYGEN_AC97_FORMAT_MASK);
517 spin_unlock_irq(&chip->reg_lock);
518 return 0;
519}
520
521static int oxygen_hw_free(struct snd_pcm_substream *substream)
522{
523 struct oxygen *chip = snd_pcm_substream_chip(substream);
Clemens Ladisch740eb832008-01-04 09:22:20 +0100524 unsigned int channel = oxygen_substream_channel(substream);
Clemens Ladischd0ce9942007-12-23 19:50:57 +0100525
526 spin_lock_irq(&chip->reg_lock);
527 chip->interrupt_mask &= ~(1 << channel);
528 oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask);
529 spin_unlock_irq(&chip->reg_lock);
530
531 return snd_pcm_lib_free_pages(substream);
532}
533
534static int oxygen_spdif_hw_free(struct snd_pcm_substream *substream)
535{
536 struct oxygen *chip = snd_pcm_substream_chip(substream);
537
538 spin_lock_irq(&chip->reg_lock);
539 oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL,
540 OXYGEN_SPDIF_OUT_ENABLE);
541 spin_unlock_irq(&chip->reg_lock);
542 return oxygen_hw_free(substream);
543}
544
545static int oxygen_prepare(struct snd_pcm_substream *substream)
546{
547 struct oxygen *chip = snd_pcm_substream_chip(substream);
Clemens Ladisch740eb832008-01-04 09:22:20 +0100548 unsigned int channel = oxygen_substream_channel(substream);
Clemens Ladischd0ce9942007-12-23 19:50:57 +0100549 unsigned int channel_mask = 1 << channel;
550
551 spin_lock_irq(&chip->reg_lock);
552 oxygen_set_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask);
553 oxygen_clear_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask);
554
555 chip->interrupt_mask |= channel_mask;
556 oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask);
557 spin_unlock_irq(&chip->reg_lock);
558 return 0;
559}
560
561static int oxygen_trigger(struct snd_pcm_substream *substream, int cmd)
562{
563 struct oxygen *chip = snd_pcm_substream_chip(substream);
564 struct snd_pcm_substream *s;
565 unsigned int mask = 0;
566 int running;
567
568 switch (cmd) {
569 case SNDRV_PCM_TRIGGER_STOP:
570 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
571 running = 0;
572 break;
573 case SNDRV_PCM_TRIGGER_START:
574 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
575 running = 1;
576 break;
577 default:
578 return -EINVAL;
579 }
580
581 snd_pcm_group_for_each_entry(s, substream) {
582 if (snd_pcm_substream_chip(s) == chip) {
Clemens Ladisch740eb832008-01-04 09:22:20 +0100583 mask |= 1 << oxygen_substream_channel(s);
Clemens Ladischd0ce9942007-12-23 19:50:57 +0100584 snd_pcm_trigger_done(s, substream);
585 }
586 }
587
588 spin_lock(&chip->reg_lock);
589 if (running)
590 chip->pcm_running |= mask;
591 else
592 chip->pcm_running &= ~mask;
593 oxygen_write8(chip, OXYGEN_DMA_STATUS, chip->pcm_running);
594 spin_unlock(&chip->reg_lock);
595 return 0;
596}
597
598static snd_pcm_uframes_t oxygen_pointer(struct snd_pcm_substream *substream)
599{
600 struct oxygen *chip = snd_pcm_substream_chip(substream);
601 struct snd_pcm_runtime *runtime = substream->runtime;
Clemens Ladisch740eb832008-01-04 09:22:20 +0100602 unsigned int channel = oxygen_substream_channel(substream);
Clemens Ladischd0ce9942007-12-23 19:50:57 +0100603 u32 curr_addr;
604
605 /* no spinlock, this read should be atomic */
606 curr_addr = oxygen_read32(chip, channel_base_registers[channel]);
607 return bytes_to_frames(runtime, curr_addr - (u32)runtime->dma_addr);
608}
609
610static struct snd_pcm_ops oxygen_rec_a_ops = {
611 .open = oxygen_rec_a_open,
612 .close = oxygen_close,
613 .ioctl = snd_pcm_lib_ioctl,
614 .hw_params = oxygen_rec_a_hw_params,
615 .hw_free = oxygen_hw_free,
616 .prepare = oxygen_prepare,
617 .trigger = oxygen_trigger,
618 .pointer = oxygen_pointer,
619};
620
621static struct snd_pcm_ops oxygen_rec_b_ops = {
622 .open = oxygen_rec_b_open,
623 .close = oxygen_close,
624 .ioctl = snd_pcm_lib_ioctl,
625 .hw_params = oxygen_rec_b_hw_params,
626 .hw_free = oxygen_hw_free,
627 .prepare = oxygen_prepare,
628 .trigger = oxygen_trigger,
629 .pointer = oxygen_pointer,
630};
631
632static struct snd_pcm_ops oxygen_rec_c_ops = {
633 .open = oxygen_rec_c_open,
634 .close = oxygen_close,
635 .ioctl = snd_pcm_lib_ioctl,
636 .hw_params = oxygen_rec_c_hw_params,
637 .hw_free = oxygen_hw_free,
638 .prepare = oxygen_prepare,
639 .trigger = oxygen_trigger,
640 .pointer = oxygen_pointer,
641};
642
643static struct snd_pcm_ops oxygen_spdif_ops = {
644 .open = oxygen_spdif_open,
645 .close = oxygen_close,
646 .ioctl = snd_pcm_lib_ioctl,
647 .hw_params = oxygen_spdif_hw_params,
648 .hw_free = oxygen_spdif_hw_free,
649 .prepare = oxygen_prepare,
650 .trigger = oxygen_trigger,
651 .pointer = oxygen_pointer,
652};
653
654static struct snd_pcm_ops oxygen_multich_ops = {
655 .open = oxygen_multich_open,
656 .close = oxygen_close,
657 .ioctl = snd_pcm_lib_ioctl,
658 .hw_params = oxygen_multich_hw_params,
659 .hw_free = oxygen_hw_free,
660 .prepare = oxygen_prepare,
661 .trigger = oxygen_trigger,
662 .pointer = oxygen_pointer,
663};
664
665static struct snd_pcm_ops oxygen_ac97_ops = {
666 .open = oxygen_ac97_open,
667 .close = oxygen_close,
668 .ioctl = snd_pcm_lib_ioctl,
669 .hw_params = oxygen_ac97_hw_params,
670 .hw_free = oxygen_hw_free,
671 .prepare = oxygen_prepare,
672 .trigger = oxygen_trigger,
673 .pointer = oxygen_pointer,
674};
675
676static void oxygen_pcm_free(struct snd_pcm *pcm)
677{
678 snd_pcm_lib_preallocate_free_for_all(pcm);
679}
680
681int __devinit oxygen_pcm_init(struct oxygen *chip)
682{
683 struct snd_pcm *pcm;
684 int err;
685
686 err = snd_pcm_new(chip->card, "Analog", 0, 1, 1, &pcm);
687 if (err < 0)
688 return err;
689 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &oxygen_multich_ops);
690 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
691 chip->model->record_from_dma_b ?
692 &oxygen_rec_b_ops : &oxygen_rec_a_ops);
693 pcm->private_data = chip;
694 pcm->private_free = oxygen_pcm_free;
695 strcpy(pcm->name, "Analog");
696 snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
697 SNDRV_DMA_TYPE_DEV,
698 snd_dma_pci_data(chip->pci),
699 512 * 1024, 2048 * 1024);
700 snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
701 SNDRV_DMA_TYPE_DEV,
702 snd_dma_pci_data(chip->pci),
703 128 * 1024, 256 * 1024);
704
705 err = snd_pcm_new(chip->card, "Digital", 1, 1, 1, &pcm);
706 if (err < 0)
707 return err;
708 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &oxygen_spdif_ops);
709 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &oxygen_rec_c_ops);
710 pcm->private_data = chip;
711 pcm->private_free = oxygen_pcm_free;
712 strcpy(pcm->name, "Digital");
713 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
714 snd_dma_pci_data(chip->pci),
715 128 * 1024, 256 * 1024);
716
717 if (chip->has_2nd_ac97_codec) {
718 err = snd_pcm_new(chip->card, "AC97", 2, 1, 0, &pcm);
719 if (err < 0)
720 return err;
721 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
722 &oxygen_ac97_ops);
723 pcm->private_data = chip;
724 pcm->private_free = oxygen_pcm_free;
725 strcpy(pcm->name, "Front Panel");
726 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
727 snd_dma_pci_data(chip->pci),
728 128 * 1024, 256 * 1024);
729 }
730 return 0;
731}