Loading...
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
4 *
5 * @File ctpcm.c
6 *
7 * @Brief
8 * This file contains the definition of the pcm device functions.
9 *
10 * @Author Liu Chun
11 * @Date Apr 2 2008
12 */
13
14#include "ctpcm.h"
15#include "cttimer.h"
16#include <linux/slab.h>
17#include <sound/pcm.h>
18
19/* Hardware descriptions for playback */
20static const struct snd_pcm_hardware ct_pcm_playback_hw = {
21 .info = (SNDRV_PCM_INFO_MMAP |
22 SNDRV_PCM_INFO_INTERLEAVED |
23 SNDRV_PCM_INFO_BLOCK_TRANSFER |
24 SNDRV_PCM_INFO_MMAP_VALID |
25 SNDRV_PCM_INFO_PAUSE),
26 .formats = (SNDRV_PCM_FMTBIT_U8 |
27 SNDRV_PCM_FMTBIT_S16_LE |
28 SNDRV_PCM_FMTBIT_S24_3LE |
29 SNDRV_PCM_FMTBIT_S32_LE |
30 SNDRV_PCM_FMTBIT_FLOAT_LE),
31 .rates = (SNDRV_PCM_RATE_CONTINUOUS |
32 SNDRV_PCM_RATE_8000_192000),
33 .rate_min = 8000,
34 .rate_max = 192000,
35 .channels_min = 1,
36 .channels_max = 2,
37 .buffer_bytes_max = (128*1024),
38 .period_bytes_min = (64),
39 .period_bytes_max = (128*1024),
40 .periods_min = 2,
41 .periods_max = 1024,
42 .fifo_size = 0,
43};
44
45static const struct snd_pcm_hardware ct_spdif_passthru_playback_hw = {
46 .info = (SNDRV_PCM_INFO_MMAP |
47 SNDRV_PCM_INFO_INTERLEAVED |
48 SNDRV_PCM_INFO_BLOCK_TRANSFER |
49 SNDRV_PCM_INFO_MMAP_VALID |
50 SNDRV_PCM_INFO_PAUSE),
51 .formats = SNDRV_PCM_FMTBIT_S16_LE,
52 .rates = (SNDRV_PCM_RATE_48000 |
53 SNDRV_PCM_RATE_44100 |
54 SNDRV_PCM_RATE_32000),
55 .rate_min = 32000,
56 .rate_max = 48000,
57 .channels_min = 2,
58 .channels_max = 2,
59 .buffer_bytes_max = (128*1024),
60 .period_bytes_min = (64),
61 .period_bytes_max = (128*1024),
62 .periods_min = 2,
63 .periods_max = 1024,
64 .fifo_size = 0,
65};
66
67/* Hardware descriptions for capture */
68static const struct snd_pcm_hardware ct_pcm_capture_hw = {
69 .info = (SNDRV_PCM_INFO_MMAP |
70 SNDRV_PCM_INFO_INTERLEAVED |
71 SNDRV_PCM_INFO_BLOCK_TRANSFER |
72 SNDRV_PCM_INFO_PAUSE |
73 SNDRV_PCM_INFO_MMAP_VALID),
74 .formats = (SNDRV_PCM_FMTBIT_U8 |
75 SNDRV_PCM_FMTBIT_S16_LE |
76 SNDRV_PCM_FMTBIT_S24_3LE |
77 SNDRV_PCM_FMTBIT_S32_LE |
78 SNDRV_PCM_FMTBIT_FLOAT_LE),
79 .rates = (SNDRV_PCM_RATE_CONTINUOUS |
80 SNDRV_PCM_RATE_8000_96000),
81 .rate_min = 8000,
82 .rate_max = 96000,
83 .channels_min = 1,
84 .channels_max = 2,
85 .buffer_bytes_max = (128*1024),
86 .period_bytes_min = (384),
87 .period_bytes_max = (64*1024),
88 .periods_min = 2,
89 .periods_max = 1024,
90 .fifo_size = 0,
91};
92
93static void ct_atc_pcm_interrupt(struct ct_atc_pcm *atc_pcm)
94{
95 struct ct_atc_pcm *apcm = atc_pcm;
96
97 if (!apcm->substream)
98 return;
99
100 snd_pcm_period_elapsed(apcm->substream);
101}
102
103static void ct_atc_pcm_free_substream(struct snd_pcm_runtime *runtime)
104{
105 struct ct_atc_pcm *apcm = runtime->private_data;
106 struct ct_atc *atc = snd_pcm_substream_chip(apcm->substream);
107
108 atc->pcm_release_resources(atc, apcm);
109 ct_timer_instance_free(apcm->timer);
110 kfree(apcm);
111 runtime->private_data = NULL;
112}
113
114/* pcm playback operations */
115static int ct_pcm_playback_open(struct snd_pcm_substream *substream)
116{
117 struct ct_atc *atc = snd_pcm_substream_chip(substream);
118 struct snd_pcm_runtime *runtime = substream->runtime;
119 struct ct_atc_pcm *apcm;
120 int err;
121
122 apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
123 if (!apcm)
124 return -ENOMEM;
125
126 apcm->substream = substream;
127 apcm->interrupt = ct_atc_pcm_interrupt;
128 if (IEC958 == substream->pcm->device) {
129 runtime->hw = ct_spdif_passthru_playback_hw;
130 atc->spdif_out_passthru(atc, 1);
131 } else {
132 runtime->hw = ct_pcm_playback_hw;
133 if (FRONT == substream->pcm->device)
134 runtime->hw.channels_max = 8;
135 }
136
137 err = snd_pcm_hw_constraint_integer(runtime,
138 SNDRV_PCM_HW_PARAM_PERIODS);
139 if (err < 0)
140 goto free_pcm;
141
142 err = snd_pcm_hw_constraint_minmax(runtime,
143 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
144 1024, UINT_MAX);
145 if (err < 0)
146 goto free_pcm;
147
148 apcm->timer = ct_timer_instance_new(atc->timer, apcm);
149 if (!apcm->timer) {
150 err = -ENOMEM;
151 goto free_pcm;
152 }
153 runtime->private_data = apcm;
154 runtime->private_free = ct_atc_pcm_free_substream;
155
156 return 0;
157
158free_pcm:
159 kfree(apcm);
160 return err;
161}
162
163static int ct_pcm_playback_close(struct snd_pcm_substream *substream)
164{
165 struct ct_atc *atc = snd_pcm_substream_chip(substream);
166
167 /* TODO: Notify mixer inactive. */
168 if (IEC958 == substream->pcm->device)
169 atc->spdif_out_passthru(atc, 0);
170
171 /* The ct_atc_pcm object will be freed by runtime->private_free */
172
173 return 0;
174}
175
176static int ct_pcm_hw_params(struct snd_pcm_substream *substream,
177 struct snd_pcm_hw_params *hw_params)
178{
179 struct ct_atc *atc = snd_pcm_substream_chip(substream);
180 struct ct_atc_pcm *apcm = substream->runtime->private_data;
181
182 /* clear previous resources */
183 atc->pcm_release_resources(atc, apcm);
184 return 0;
185}
186
187static int ct_pcm_hw_free(struct snd_pcm_substream *substream)
188{
189 struct ct_atc *atc = snd_pcm_substream_chip(substream);
190 struct ct_atc_pcm *apcm = substream->runtime->private_data;
191
192 /* clear previous resources */
193 atc->pcm_release_resources(atc, apcm);
194 return 0;
195}
196
197
198static int ct_pcm_playback_prepare(struct snd_pcm_substream *substream)
199{
200 int err;
201 struct ct_atc *atc = snd_pcm_substream_chip(substream);
202 struct snd_pcm_runtime *runtime = substream->runtime;
203 struct ct_atc_pcm *apcm = runtime->private_data;
204
205 if (IEC958 == substream->pcm->device)
206 err = atc->spdif_passthru_playback_prepare(atc, apcm);
207 else
208 err = atc->pcm_playback_prepare(atc, apcm);
209
210 if (err < 0) {
211 dev_err(atc->card->dev,
212 "Preparing pcm playback failed!!!\n");
213 return err;
214 }
215
216 return 0;
217}
218
219static int
220ct_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
221{
222 struct ct_atc *atc = snd_pcm_substream_chip(substream);
223 struct snd_pcm_runtime *runtime = substream->runtime;
224 struct ct_atc_pcm *apcm = runtime->private_data;
225
226 switch (cmd) {
227 case SNDRV_PCM_TRIGGER_START:
228 case SNDRV_PCM_TRIGGER_RESUME:
229 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
230 atc->pcm_playback_start(atc, apcm);
231 break;
232 case SNDRV_PCM_TRIGGER_STOP:
233 case SNDRV_PCM_TRIGGER_SUSPEND:
234 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
235 atc->pcm_playback_stop(atc, apcm);
236 break;
237 default:
238 break;
239 }
240
241 return 0;
242}
243
244static snd_pcm_uframes_t
245ct_pcm_playback_pointer(struct snd_pcm_substream *substream)
246{
247 unsigned long position;
248 struct ct_atc *atc = snd_pcm_substream_chip(substream);
249 struct snd_pcm_runtime *runtime = substream->runtime;
250 struct ct_atc_pcm *apcm = runtime->private_data;
251
252 /* Read out playback position */
253 position = atc->pcm_playback_position(atc, apcm);
254 position = bytes_to_frames(runtime, position);
255 if (position >= runtime->buffer_size)
256 position = 0;
257 return position;
258}
259
260/* pcm capture operations */
261static int ct_pcm_capture_open(struct snd_pcm_substream *substream)
262{
263 struct ct_atc *atc = snd_pcm_substream_chip(substream);
264 struct snd_pcm_runtime *runtime = substream->runtime;
265 struct ct_atc_pcm *apcm;
266 int err;
267
268 apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
269 if (!apcm)
270 return -ENOMEM;
271
272 apcm->started = 0;
273 apcm->substream = substream;
274 apcm->interrupt = ct_atc_pcm_interrupt;
275 runtime->hw = ct_pcm_capture_hw;
276 runtime->hw.rate_max = atc->rsr * atc->msr;
277
278 err = snd_pcm_hw_constraint_integer(runtime,
279 SNDRV_PCM_HW_PARAM_PERIODS);
280 if (err < 0)
281 goto free_pcm;
282
283 err = snd_pcm_hw_constraint_minmax(runtime,
284 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
285 1024, UINT_MAX);
286 if (err < 0)
287 goto free_pcm;
288
289 apcm->timer = ct_timer_instance_new(atc->timer, apcm);
290 if (!apcm->timer) {
291 err = -ENOMEM;
292 goto free_pcm;
293 }
294 runtime->private_data = apcm;
295 runtime->private_free = ct_atc_pcm_free_substream;
296
297 return 0;
298
299free_pcm:
300 kfree(apcm);
301 return err;
302}
303
304static int ct_pcm_capture_close(struct snd_pcm_substream *substream)
305{
306 /* The ct_atc_pcm object will be freed by runtime->private_free */
307 /* TODO: Notify mixer inactive. */
308 return 0;
309}
310
311static int ct_pcm_capture_prepare(struct snd_pcm_substream *substream)
312{
313 int err;
314 struct ct_atc *atc = snd_pcm_substream_chip(substream);
315 struct snd_pcm_runtime *runtime = substream->runtime;
316 struct ct_atc_pcm *apcm = runtime->private_data;
317
318 err = atc->pcm_capture_prepare(atc, apcm);
319 if (err < 0) {
320 dev_err(atc->card->dev,
321 "Preparing pcm capture failed!!!\n");
322 return err;
323 }
324
325 return 0;
326}
327
328static int
329ct_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
330{
331 struct ct_atc *atc = snd_pcm_substream_chip(substream);
332 struct snd_pcm_runtime *runtime = substream->runtime;
333 struct ct_atc_pcm *apcm = runtime->private_data;
334
335 switch (cmd) {
336 case SNDRV_PCM_TRIGGER_START:
337 atc->pcm_capture_start(atc, apcm);
338 break;
339 case SNDRV_PCM_TRIGGER_STOP:
340 atc->pcm_capture_stop(atc, apcm);
341 break;
342 default:
343 atc->pcm_capture_stop(atc, apcm);
344 break;
345 }
346
347 return 0;
348}
349
350static snd_pcm_uframes_t
351ct_pcm_capture_pointer(struct snd_pcm_substream *substream)
352{
353 unsigned long position;
354 struct ct_atc *atc = snd_pcm_substream_chip(substream);
355 struct snd_pcm_runtime *runtime = substream->runtime;
356 struct ct_atc_pcm *apcm = runtime->private_data;
357
358 /* Read out playback position */
359 position = atc->pcm_capture_position(atc, apcm);
360 position = bytes_to_frames(runtime, position);
361 if (position >= runtime->buffer_size)
362 position = 0;
363 return position;
364}
365
366/* PCM operators for playback */
367static const struct snd_pcm_ops ct_pcm_playback_ops = {
368 .open = ct_pcm_playback_open,
369 .close = ct_pcm_playback_close,
370 .hw_params = ct_pcm_hw_params,
371 .hw_free = ct_pcm_hw_free,
372 .prepare = ct_pcm_playback_prepare,
373 .trigger = ct_pcm_playback_trigger,
374 .pointer = ct_pcm_playback_pointer,
375};
376
377/* PCM operators for capture */
378static const struct snd_pcm_ops ct_pcm_capture_ops = {
379 .open = ct_pcm_capture_open,
380 .close = ct_pcm_capture_close,
381 .hw_params = ct_pcm_hw_params,
382 .hw_free = ct_pcm_hw_free,
383 .prepare = ct_pcm_capture_prepare,
384 .trigger = ct_pcm_capture_trigger,
385 .pointer = ct_pcm_capture_pointer,
386};
387
388static const struct snd_pcm_chmap_elem surround_map[] = {
389 { .channels = 1,
390 .map = { SNDRV_CHMAP_MONO } },
391 { .channels = 2,
392 .map = { SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
393 { }
394};
395
396static const struct snd_pcm_chmap_elem clfe_map[] = {
397 { .channels = 1,
398 .map = { SNDRV_CHMAP_MONO } },
399 { .channels = 2,
400 .map = { SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } },
401 { }
402};
403
404static const struct snd_pcm_chmap_elem side_map[] = {
405 { .channels = 1,
406 .map = { SNDRV_CHMAP_MONO } },
407 { .channels = 2,
408 .map = { SNDRV_CHMAP_SL, SNDRV_CHMAP_SR } },
409 { }
410};
411
412/* Create ALSA pcm device */
413int ct_alsa_pcm_create(struct ct_atc *atc,
414 enum CTALSADEVS device,
415 const char *device_name)
416{
417 struct snd_pcm *pcm;
418 const struct snd_pcm_chmap_elem *map;
419 int chs;
420 int err;
421 int playback_count, capture_count;
422
423 playback_count = (IEC958 == device) ? 1 : 256;
424 capture_count = (FRONT == device) ? 1 : 0;
425 err = snd_pcm_new(atc->card, "ctxfi", device,
426 playback_count, capture_count, &pcm);
427 if (err < 0) {
428 dev_err(atc->card->dev, "snd_pcm_new failed!! Err=%d\n",
429 err);
430 return err;
431 }
432
433 pcm->private_data = atc;
434 pcm->info_flags = 0;
435 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
436 strlcpy(pcm->name, device_name, sizeof(pcm->name));
437
438 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ct_pcm_playback_ops);
439
440 if (FRONT == device)
441 snd_pcm_set_ops(pcm,
442 SNDRV_PCM_STREAM_CAPTURE, &ct_pcm_capture_ops);
443
444 snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
445 &atc->pci->dev, 128*1024, 128*1024);
446
447 chs = 2;
448 switch (device) {
449 case FRONT:
450 chs = 8;
451 map = snd_pcm_std_chmaps;
452 break;
453 case SURROUND:
454 map = surround_map;
455 break;
456 case CLFE:
457 map = clfe_map;
458 break;
459 case SIDE:
460 map = side_map;
461 break;
462 default:
463 map = snd_pcm_std_chmaps;
464 break;
465 }
466 err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, chs,
467 0, NULL);
468 if (err < 0)
469 return err;
470
471#ifdef CONFIG_PM_SLEEP
472 atc->pcms[device] = pcm;
473#endif
474
475 return 0;
476}
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File ctpcm.c
9 *
10 * @Brief
11 * This file contains the definition of the pcm device functions.
12 *
13 * @Author Liu Chun
14 * @Date Apr 2 2008
15 *
16 */
17
18#include "ctpcm.h"
19#include "cttimer.h"
20#include <linux/slab.h>
21#include <sound/pcm.h>
22
23/* Hardware descriptions for playback */
24static struct snd_pcm_hardware ct_pcm_playback_hw = {
25 .info = (SNDRV_PCM_INFO_MMAP |
26 SNDRV_PCM_INFO_INTERLEAVED |
27 SNDRV_PCM_INFO_BLOCK_TRANSFER |
28 SNDRV_PCM_INFO_MMAP_VALID |
29 SNDRV_PCM_INFO_PAUSE),
30 .formats = (SNDRV_PCM_FMTBIT_U8 |
31 SNDRV_PCM_FMTBIT_S16_LE |
32 SNDRV_PCM_FMTBIT_S24_3LE |
33 SNDRV_PCM_FMTBIT_S32_LE |
34 SNDRV_PCM_FMTBIT_FLOAT_LE),
35 .rates = (SNDRV_PCM_RATE_CONTINUOUS |
36 SNDRV_PCM_RATE_8000_192000),
37 .rate_min = 8000,
38 .rate_max = 192000,
39 .channels_min = 1,
40 .channels_max = 2,
41 .buffer_bytes_max = (128*1024),
42 .period_bytes_min = (64),
43 .period_bytes_max = (128*1024),
44 .periods_min = 2,
45 .periods_max = 1024,
46 .fifo_size = 0,
47};
48
49static struct snd_pcm_hardware ct_spdif_passthru_playback_hw = {
50 .info = (SNDRV_PCM_INFO_MMAP |
51 SNDRV_PCM_INFO_INTERLEAVED |
52 SNDRV_PCM_INFO_BLOCK_TRANSFER |
53 SNDRV_PCM_INFO_MMAP_VALID |
54 SNDRV_PCM_INFO_PAUSE),
55 .formats = SNDRV_PCM_FMTBIT_S16_LE,
56 .rates = (SNDRV_PCM_RATE_48000 |
57 SNDRV_PCM_RATE_44100 |
58 SNDRV_PCM_RATE_32000),
59 .rate_min = 32000,
60 .rate_max = 48000,
61 .channels_min = 2,
62 .channels_max = 2,
63 .buffer_bytes_max = (128*1024),
64 .period_bytes_min = (64),
65 .period_bytes_max = (128*1024),
66 .periods_min = 2,
67 .periods_max = 1024,
68 .fifo_size = 0,
69};
70
71/* Hardware descriptions for capture */
72static struct snd_pcm_hardware ct_pcm_capture_hw = {
73 .info = (SNDRV_PCM_INFO_MMAP |
74 SNDRV_PCM_INFO_INTERLEAVED |
75 SNDRV_PCM_INFO_BLOCK_TRANSFER |
76 SNDRV_PCM_INFO_PAUSE |
77 SNDRV_PCM_INFO_MMAP_VALID),
78 .formats = (SNDRV_PCM_FMTBIT_U8 |
79 SNDRV_PCM_FMTBIT_S16_LE |
80 SNDRV_PCM_FMTBIT_S24_3LE |
81 SNDRV_PCM_FMTBIT_S32_LE |
82 SNDRV_PCM_FMTBIT_FLOAT_LE),
83 .rates = (SNDRV_PCM_RATE_CONTINUOUS |
84 SNDRV_PCM_RATE_8000_96000),
85 .rate_min = 8000,
86 .rate_max = 96000,
87 .channels_min = 1,
88 .channels_max = 2,
89 .buffer_bytes_max = (128*1024),
90 .period_bytes_min = (384),
91 .period_bytes_max = (64*1024),
92 .periods_min = 2,
93 .periods_max = 1024,
94 .fifo_size = 0,
95};
96
97static void ct_atc_pcm_interrupt(struct ct_atc_pcm *atc_pcm)
98{
99 struct ct_atc_pcm *apcm = atc_pcm;
100
101 if (!apcm->substream)
102 return;
103
104 snd_pcm_period_elapsed(apcm->substream);
105}
106
107static void ct_atc_pcm_free_substream(struct snd_pcm_runtime *runtime)
108{
109 struct ct_atc_pcm *apcm = runtime->private_data;
110 struct ct_atc *atc = snd_pcm_substream_chip(apcm->substream);
111
112 atc->pcm_release_resources(atc, apcm);
113 ct_timer_instance_free(apcm->timer);
114 kfree(apcm);
115 runtime->private_data = NULL;
116}
117
118/* pcm playback operations */
119static int ct_pcm_playback_open(struct snd_pcm_substream *substream)
120{
121 struct ct_atc *atc = snd_pcm_substream_chip(substream);
122 struct snd_pcm_runtime *runtime = substream->runtime;
123 struct ct_atc_pcm *apcm;
124 int err;
125
126 apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
127 if (!apcm)
128 return -ENOMEM;
129
130 apcm->substream = substream;
131 apcm->interrupt = ct_atc_pcm_interrupt;
132 if (IEC958 == substream->pcm->device) {
133 runtime->hw = ct_spdif_passthru_playback_hw;
134 atc->spdif_out_passthru(atc, 1);
135 } else {
136 runtime->hw = ct_pcm_playback_hw;
137 if (FRONT == substream->pcm->device)
138 runtime->hw.channels_max = 8;
139 }
140
141 err = snd_pcm_hw_constraint_integer(runtime,
142 SNDRV_PCM_HW_PARAM_PERIODS);
143 if (err < 0) {
144 kfree(apcm);
145 return err;
146 }
147 err = snd_pcm_hw_constraint_minmax(runtime,
148 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
149 1024, UINT_MAX);
150 if (err < 0) {
151 kfree(apcm);
152 return err;
153 }
154
155 apcm->timer = ct_timer_instance_new(atc->timer, apcm);
156 if (!apcm->timer) {
157 kfree(apcm);
158 return -ENOMEM;
159 }
160 runtime->private_data = apcm;
161 runtime->private_free = ct_atc_pcm_free_substream;
162
163 return 0;
164}
165
166static int ct_pcm_playback_close(struct snd_pcm_substream *substream)
167{
168 struct ct_atc *atc = snd_pcm_substream_chip(substream);
169
170 /* TODO: Notify mixer inactive. */
171 if (IEC958 == substream->pcm->device)
172 atc->spdif_out_passthru(atc, 0);
173
174 /* The ct_atc_pcm object will be freed by runtime->private_free */
175
176 return 0;
177}
178
179static int ct_pcm_hw_params(struct snd_pcm_substream *substream,
180 struct snd_pcm_hw_params *hw_params)
181{
182 struct ct_atc *atc = snd_pcm_substream_chip(substream);
183 struct ct_atc_pcm *apcm = substream->runtime->private_data;
184 int err;
185
186 err = snd_pcm_lib_malloc_pages(substream,
187 params_buffer_bytes(hw_params));
188 if (err < 0)
189 return err;
190 /* clear previous resources */
191 atc->pcm_release_resources(atc, apcm);
192 return err;
193}
194
195static int ct_pcm_hw_free(struct snd_pcm_substream *substream)
196{
197 struct ct_atc *atc = snd_pcm_substream_chip(substream);
198 struct ct_atc_pcm *apcm = substream->runtime->private_data;
199
200 /* clear previous resources */
201 atc->pcm_release_resources(atc, apcm);
202 /* Free snd-allocated pages */
203 return snd_pcm_lib_free_pages(substream);
204}
205
206
207static int ct_pcm_playback_prepare(struct snd_pcm_substream *substream)
208{
209 int err;
210 struct ct_atc *atc = snd_pcm_substream_chip(substream);
211 struct snd_pcm_runtime *runtime = substream->runtime;
212 struct ct_atc_pcm *apcm = runtime->private_data;
213
214 if (IEC958 == substream->pcm->device)
215 err = atc->spdif_passthru_playback_prepare(atc, apcm);
216 else
217 err = atc->pcm_playback_prepare(atc, apcm);
218
219 if (err < 0) {
220 printk(KERN_ERR "ctxfi: Preparing pcm playback failed!!!\n");
221 return err;
222 }
223
224 return 0;
225}
226
227static int
228ct_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
229{
230 struct ct_atc *atc = snd_pcm_substream_chip(substream);
231 struct snd_pcm_runtime *runtime = substream->runtime;
232 struct ct_atc_pcm *apcm = runtime->private_data;
233
234 switch (cmd) {
235 case SNDRV_PCM_TRIGGER_START:
236 case SNDRV_PCM_TRIGGER_RESUME:
237 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
238 atc->pcm_playback_start(atc, apcm);
239 break;
240 case SNDRV_PCM_TRIGGER_STOP:
241 case SNDRV_PCM_TRIGGER_SUSPEND:
242 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
243 atc->pcm_playback_stop(atc, apcm);
244 break;
245 default:
246 break;
247 }
248
249 return 0;
250}
251
252static snd_pcm_uframes_t
253ct_pcm_playback_pointer(struct snd_pcm_substream *substream)
254{
255 unsigned long position;
256 struct ct_atc *atc = snd_pcm_substream_chip(substream);
257 struct snd_pcm_runtime *runtime = substream->runtime;
258 struct ct_atc_pcm *apcm = runtime->private_data;
259
260 /* Read out playback position */
261 position = atc->pcm_playback_position(atc, apcm);
262 position = bytes_to_frames(runtime, position);
263 if (position >= runtime->buffer_size)
264 position = 0;
265 return position;
266}
267
268/* pcm capture operations */
269static int ct_pcm_capture_open(struct snd_pcm_substream *substream)
270{
271 struct ct_atc *atc = snd_pcm_substream_chip(substream);
272 struct snd_pcm_runtime *runtime = substream->runtime;
273 struct ct_atc_pcm *apcm;
274 int err;
275
276 apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
277 if (!apcm)
278 return -ENOMEM;
279
280 apcm->started = 0;
281 apcm->substream = substream;
282 apcm->interrupt = ct_atc_pcm_interrupt;
283 runtime->hw = ct_pcm_capture_hw;
284 runtime->hw.rate_max = atc->rsr * atc->msr;
285
286 err = snd_pcm_hw_constraint_integer(runtime,
287 SNDRV_PCM_HW_PARAM_PERIODS);
288 if (err < 0) {
289 kfree(apcm);
290 return err;
291 }
292 err = snd_pcm_hw_constraint_minmax(runtime,
293 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
294 1024, UINT_MAX);
295 if (err < 0) {
296 kfree(apcm);
297 return err;
298 }
299
300 apcm->timer = ct_timer_instance_new(atc->timer, apcm);
301 if (!apcm->timer) {
302 kfree(apcm);
303 return -ENOMEM;
304 }
305 runtime->private_data = apcm;
306 runtime->private_free = ct_atc_pcm_free_substream;
307
308 return 0;
309}
310
311static int ct_pcm_capture_close(struct snd_pcm_substream *substream)
312{
313 /* The ct_atc_pcm object will be freed by runtime->private_free */
314 /* TODO: Notify mixer inactive. */
315 return 0;
316}
317
318static int ct_pcm_capture_prepare(struct snd_pcm_substream *substream)
319{
320 int err;
321 struct ct_atc *atc = snd_pcm_substream_chip(substream);
322 struct snd_pcm_runtime *runtime = substream->runtime;
323 struct ct_atc_pcm *apcm = runtime->private_data;
324
325 err = atc->pcm_capture_prepare(atc, apcm);
326 if (err < 0) {
327 printk(KERN_ERR "ctxfi: Preparing pcm capture failed!!!\n");
328 return err;
329 }
330
331 return 0;
332}
333
334static int
335ct_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
336{
337 struct ct_atc *atc = snd_pcm_substream_chip(substream);
338 struct snd_pcm_runtime *runtime = substream->runtime;
339 struct ct_atc_pcm *apcm = runtime->private_data;
340
341 switch (cmd) {
342 case SNDRV_PCM_TRIGGER_START:
343 atc->pcm_capture_start(atc, apcm);
344 break;
345 case SNDRV_PCM_TRIGGER_STOP:
346 atc->pcm_capture_stop(atc, apcm);
347 break;
348 default:
349 atc->pcm_capture_stop(atc, apcm);
350 break;
351 }
352
353 return 0;
354}
355
356static snd_pcm_uframes_t
357ct_pcm_capture_pointer(struct snd_pcm_substream *substream)
358{
359 unsigned long position;
360 struct ct_atc *atc = snd_pcm_substream_chip(substream);
361 struct snd_pcm_runtime *runtime = substream->runtime;
362 struct ct_atc_pcm *apcm = runtime->private_data;
363
364 /* Read out playback position */
365 position = atc->pcm_capture_position(atc, apcm);
366 position = bytes_to_frames(runtime, position);
367 if (position >= runtime->buffer_size)
368 position = 0;
369 return position;
370}
371
372/* PCM operators for playback */
373static struct snd_pcm_ops ct_pcm_playback_ops = {
374 .open = ct_pcm_playback_open,
375 .close = ct_pcm_playback_close,
376 .ioctl = snd_pcm_lib_ioctl,
377 .hw_params = ct_pcm_hw_params,
378 .hw_free = ct_pcm_hw_free,
379 .prepare = ct_pcm_playback_prepare,
380 .trigger = ct_pcm_playback_trigger,
381 .pointer = ct_pcm_playback_pointer,
382 .page = snd_pcm_sgbuf_ops_page,
383};
384
385/* PCM operators for capture */
386static struct snd_pcm_ops ct_pcm_capture_ops = {
387 .open = ct_pcm_capture_open,
388 .close = ct_pcm_capture_close,
389 .ioctl = snd_pcm_lib_ioctl,
390 .hw_params = ct_pcm_hw_params,
391 .hw_free = ct_pcm_hw_free,
392 .prepare = ct_pcm_capture_prepare,
393 .trigger = ct_pcm_capture_trigger,
394 .pointer = ct_pcm_capture_pointer,
395 .page = snd_pcm_sgbuf_ops_page,
396};
397
398/* Create ALSA pcm device */
399int ct_alsa_pcm_create(struct ct_atc *atc,
400 enum CTALSADEVS device,
401 const char *device_name)
402{
403 struct snd_pcm *pcm;
404 int err;
405 int playback_count, capture_count;
406
407 playback_count = (IEC958 == device) ? 1 : 8;
408 capture_count = (FRONT == device) ? 1 : 0;
409 err = snd_pcm_new(atc->card, "ctxfi", device,
410 playback_count, capture_count, &pcm);
411 if (err < 0) {
412 printk(KERN_ERR "ctxfi: snd_pcm_new failed!! Err=%d\n", err);
413 return err;
414 }
415
416 pcm->private_data = atc;
417 pcm->info_flags = 0;
418 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
419 strlcpy(pcm->name, device_name, sizeof(pcm->name));
420
421 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ct_pcm_playback_ops);
422
423 if (FRONT == device)
424 snd_pcm_set_ops(pcm,
425 SNDRV_PCM_STREAM_CAPTURE, &ct_pcm_capture_ops);
426
427 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
428 snd_dma_pci_data(atc->pci), 128*1024, 128*1024);
429
430#ifdef CONFIG_PM
431 atc->pcms[device] = pcm;
432#endif
433
434 return 0;
435}