Linux 2.6.31.8
[linux/fpc-iii.git] / sound / pci / ctxfi / ctpcm.c
blob60ea23180acbe1f91443f5ad15b8939ec812698c
1 /**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
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.
8 * @File ctpcm.c
10 * @Brief
11 * This file contains the definition of the pcm device functions.
13 * @Author Liu Chun
14 * @Date Apr 2 2008
18 #include "ctpcm.h"
19 #include "cttimer.h"
20 #include <sound/pcm.h>
22 /* Hardware descriptions for playback */
23 static struct snd_pcm_hardware ct_pcm_playback_hw = {
24 .info = (SNDRV_PCM_INFO_MMAP |
25 SNDRV_PCM_INFO_INTERLEAVED |
26 SNDRV_PCM_INFO_BLOCK_TRANSFER |
27 SNDRV_PCM_INFO_MMAP_VALID |
28 SNDRV_PCM_INFO_PAUSE),
29 .formats = (SNDRV_PCM_FMTBIT_U8 |
30 SNDRV_PCM_FMTBIT_S16_LE |
31 SNDRV_PCM_FMTBIT_S24_3LE |
32 SNDRV_PCM_FMTBIT_S32_LE |
33 SNDRV_PCM_FMTBIT_FLOAT_LE),
34 .rates = (SNDRV_PCM_RATE_CONTINUOUS |
35 SNDRV_PCM_RATE_8000_192000),
36 .rate_min = 8000,
37 .rate_max = 192000,
38 .channels_min = 1,
39 .channels_max = 2,
40 .buffer_bytes_max = (128*1024),
41 .period_bytes_min = (64),
42 .period_bytes_max = (128*1024),
43 .periods_min = 2,
44 .periods_max = 1024,
45 .fifo_size = 0,
48 static struct snd_pcm_hardware ct_spdif_passthru_playback_hw = {
49 .info = (SNDRV_PCM_INFO_MMAP |
50 SNDRV_PCM_INFO_INTERLEAVED |
51 SNDRV_PCM_INFO_BLOCK_TRANSFER |
52 SNDRV_PCM_INFO_MMAP_VALID |
53 SNDRV_PCM_INFO_PAUSE),
54 .formats = SNDRV_PCM_FMTBIT_S16_LE,
55 .rates = (SNDRV_PCM_RATE_48000 |
56 SNDRV_PCM_RATE_44100 |
57 SNDRV_PCM_RATE_32000),
58 .rate_min = 32000,
59 .rate_max = 48000,
60 .channels_min = 2,
61 .channels_max = 2,
62 .buffer_bytes_max = (128*1024),
63 .period_bytes_min = (64),
64 .period_bytes_max = (128*1024),
65 .periods_min = 2,
66 .periods_max = 1024,
67 .fifo_size = 0,
70 /* Hardware descriptions for capture */
71 static struct snd_pcm_hardware ct_pcm_capture_hw = {
72 .info = (SNDRV_PCM_INFO_MMAP |
73 SNDRV_PCM_INFO_INTERLEAVED |
74 SNDRV_PCM_INFO_BLOCK_TRANSFER |
75 SNDRV_PCM_INFO_PAUSE |
76 SNDRV_PCM_INFO_MMAP_VALID),
77 .formats = (SNDRV_PCM_FMTBIT_U8 |
78 SNDRV_PCM_FMTBIT_S16_LE |
79 SNDRV_PCM_FMTBIT_S24_3LE |
80 SNDRV_PCM_FMTBIT_S32_LE |
81 SNDRV_PCM_FMTBIT_FLOAT_LE),
82 .rates = (SNDRV_PCM_RATE_CONTINUOUS |
83 SNDRV_PCM_RATE_8000_96000),
84 .rate_min = 8000,
85 .rate_max = 96000,
86 .channels_min = 1,
87 .channels_max = 2,
88 .buffer_bytes_max = (128*1024),
89 .period_bytes_min = (384),
90 .period_bytes_max = (64*1024),
91 .periods_min = 2,
92 .periods_max = 1024,
93 .fifo_size = 0,
96 static void ct_atc_pcm_interrupt(struct ct_atc_pcm *atc_pcm)
98 struct ct_atc_pcm *apcm = atc_pcm;
100 if (NULL == apcm->substream)
101 return;
103 snd_pcm_period_elapsed(apcm->substream);
106 static void ct_atc_pcm_free_substream(struct snd_pcm_runtime *runtime)
108 struct ct_atc_pcm *apcm = runtime->private_data;
109 struct ct_atc *atc = snd_pcm_substream_chip(apcm->substream);
111 atc->pcm_release_resources(atc, apcm);
112 ct_timer_instance_free(apcm->timer);
113 kfree(apcm);
114 runtime->private_data = NULL;
117 /* pcm playback operations */
118 static int ct_pcm_playback_open(struct snd_pcm_substream *substream)
120 struct ct_atc *atc = snd_pcm_substream_chip(substream);
121 struct snd_pcm_runtime *runtime = substream->runtime;
122 struct ct_atc_pcm *apcm;
123 int err;
125 apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
126 if (NULL == apcm)
127 return -ENOMEM;
129 apcm->substream = substream;
130 apcm->interrupt = ct_atc_pcm_interrupt;
131 runtime->private_data = apcm;
132 runtime->private_free = ct_atc_pcm_free_substream;
133 if (IEC958 == substream->pcm->device) {
134 runtime->hw = ct_spdif_passthru_playback_hw;
135 atc->spdif_out_passthru(atc, 1);
136 } else {
137 runtime->hw = ct_pcm_playback_hw;
138 if (FRONT == substream->pcm->device)
139 runtime->hw.channels_max = 8;
142 err = snd_pcm_hw_constraint_integer(runtime,
143 SNDRV_PCM_HW_PARAM_PERIODS);
144 if (err < 0) {
145 kfree(apcm);
146 return err;
148 err = snd_pcm_hw_constraint_minmax(runtime,
149 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
150 1024, UINT_MAX);
151 if (err < 0) {
152 kfree(apcm);
153 return err;
156 apcm->timer = ct_timer_instance_new(atc->timer, apcm);
157 if (!apcm->timer)
158 return -ENOMEM;
160 return 0;
163 static int ct_pcm_playback_close(struct snd_pcm_substream *substream)
165 struct ct_atc *atc = snd_pcm_substream_chip(substream);
167 /* TODO: Notify mixer inactive. */
168 if (IEC958 == substream->pcm->device)
169 atc->spdif_out_passthru(atc, 0);
171 /* The ct_atc_pcm object will be freed by runtime->private_free */
173 return 0;
176 static int ct_pcm_hw_params(struct snd_pcm_substream *substream,
177 struct snd_pcm_hw_params *hw_params)
179 struct ct_atc *atc = snd_pcm_substream_chip(substream);
180 struct ct_atc_pcm *apcm = substream->runtime->private_data;
181 int err;
183 err = snd_pcm_lib_malloc_pages(substream,
184 params_buffer_bytes(hw_params));
185 if (err < 0)
186 return err;
187 /* clear previous resources */
188 atc->pcm_release_resources(atc, apcm);
189 return err;
192 static int ct_pcm_hw_free(struct snd_pcm_substream *substream)
194 struct ct_atc *atc = snd_pcm_substream_chip(substream);
195 struct ct_atc_pcm *apcm = substream->runtime->private_data;
197 /* clear previous resources */
198 atc->pcm_release_resources(atc, apcm);
199 /* Free snd-allocated pages */
200 return snd_pcm_lib_free_pages(substream);
204 static int ct_pcm_playback_prepare(struct snd_pcm_substream *substream)
206 int err;
207 struct ct_atc *atc = snd_pcm_substream_chip(substream);
208 struct snd_pcm_runtime *runtime = substream->runtime;
209 struct ct_atc_pcm *apcm = runtime->private_data;
211 if (IEC958 == substream->pcm->device)
212 err = atc->spdif_passthru_playback_prepare(atc, apcm);
213 else
214 err = atc->pcm_playback_prepare(atc, apcm);
216 if (err < 0) {
217 printk(KERN_ERR "ctxfi: Preparing pcm playback failed!!!\n");
218 return err;
221 return 0;
224 static int
225 ct_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
227 struct ct_atc *atc = snd_pcm_substream_chip(substream);
228 struct snd_pcm_runtime *runtime = substream->runtime;
229 struct ct_atc_pcm *apcm = runtime->private_data;
231 switch (cmd) {
232 case SNDRV_PCM_TRIGGER_START:
233 case SNDRV_PCM_TRIGGER_RESUME:
234 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
235 atc->pcm_playback_start(atc, apcm);
236 break;
237 case SNDRV_PCM_TRIGGER_STOP:
238 case SNDRV_PCM_TRIGGER_SUSPEND:
239 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
240 atc->pcm_playback_stop(atc, apcm);
241 break;
242 default:
243 break;
246 return 0;
249 static snd_pcm_uframes_t
250 ct_pcm_playback_pointer(struct snd_pcm_substream *substream)
252 unsigned long position;
253 struct ct_atc *atc = snd_pcm_substream_chip(substream);
254 struct snd_pcm_runtime *runtime = substream->runtime;
255 struct ct_atc_pcm *apcm = runtime->private_data;
257 /* Read out playback position */
258 position = atc->pcm_playback_position(atc, apcm);
259 position = bytes_to_frames(runtime, position);
260 if (position >= runtime->buffer_size)
261 position = 0;
262 return position;
265 /* pcm capture operations */
266 static int ct_pcm_capture_open(struct snd_pcm_substream *substream)
268 struct ct_atc *atc = snd_pcm_substream_chip(substream);
269 struct snd_pcm_runtime *runtime = substream->runtime;
270 struct ct_atc_pcm *apcm;
271 int err;
273 apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
274 if (NULL == apcm)
275 return -ENOMEM;
277 apcm->started = 0;
278 apcm->substream = substream;
279 apcm->interrupt = ct_atc_pcm_interrupt;
280 runtime->private_data = apcm;
281 runtime->private_free = ct_atc_pcm_free_substream;
282 runtime->hw = ct_pcm_capture_hw;
283 runtime->hw.rate_max = atc->rsr * atc->msr;
285 err = snd_pcm_hw_constraint_integer(runtime,
286 SNDRV_PCM_HW_PARAM_PERIODS);
287 if (err < 0) {
288 kfree(apcm);
289 return err;
291 err = snd_pcm_hw_constraint_minmax(runtime,
292 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
293 1024, UINT_MAX);
294 if (err < 0) {
295 kfree(apcm);
296 return err;
299 apcm->timer = ct_timer_instance_new(atc->timer, apcm);
300 if (!apcm->timer)
301 return -ENOMEM;
303 return 0;
306 static int ct_pcm_capture_close(struct snd_pcm_substream *substream)
308 /* The ct_atc_pcm object will be freed by runtime->private_free */
309 /* TODO: Notify mixer inactive. */
310 return 0;
313 static int ct_pcm_capture_prepare(struct snd_pcm_substream *substream)
315 int err;
316 struct ct_atc *atc = snd_pcm_substream_chip(substream);
317 struct snd_pcm_runtime *runtime = substream->runtime;
318 struct ct_atc_pcm *apcm = runtime->private_data;
320 err = atc->pcm_capture_prepare(atc, apcm);
321 if (err < 0) {
322 printk(KERN_ERR "ctxfi: Preparing pcm capture failed!!!\n");
323 return err;
326 return 0;
329 static int
330 ct_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
332 struct ct_atc *atc = snd_pcm_substream_chip(substream);
333 struct snd_pcm_runtime *runtime = substream->runtime;
334 struct ct_atc_pcm *apcm = runtime->private_data;
336 switch (cmd) {
337 case SNDRV_PCM_TRIGGER_START:
338 atc->pcm_capture_start(atc, apcm);
339 break;
340 case SNDRV_PCM_TRIGGER_STOP:
341 atc->pcm_capture_stop(atc, apcm);
342 break;
343 default:
344 atc->pcm_capture_stop(atc, apcm);
345 break;
348 return 0;
351 static snd_pcm_uframes_t
352 ct_pcm_capture_pointer(struct snd_pcm_substream *substream)
354 unsigned long position;
355 struct ct_atc *atc = snd_pcm_substream_chip(substream);
356 struct snd_pcm_runtime *runtime = substream->runtime;
357 struct ct_atc_pcm *apcm = runtime->private_data;
359 /* Read out playback position */
360 position = atc->pcm_capture_position(atc, apcm);
361 position = bytes_to_frames(runtime, position);
362 if (position >= runtime->buffer_size)
363 position = 0;
364 return position;
367 /* PCM operators for playback */
368 static struct snd_pcm_ops ct_pcm_playback_ops = {
369 .open = ct_pcm_playback_open,
370 .close = ct_pcm_playback_close,
371 .ioctl = snd_pcm_lib_ioctl,
372 .hw_params = ct_pcm_hw_params,
373 .hw_free = ct_pcm_hw_free,
374 .prepare = ct_pcm_playback_prepare,
375 .trigger = ct_pcm_playback_trigger,
376 .pointer = ct_pcm_playback_pointer,
377 .page = snd_pcm_sgbuf_ops_page,
380 /* PCM operators for capture */
381 static struct snd_pcm_ops ct_pcm_capture_ops = {
382 .open = ct_pcm_capture_open,
383 .close = ct_pcm_capture_close,
384 .ioctl = snd_pcm_lib_ioctl,
385 .hw_params = ct_pcm_hw_params,
386 .hw_free = ct_pcm_hw_free,
387 .prepare = ct_pcm_capture_prepare,
388 .trigger = ct_pcm_capture_trigger,
389 .pointer = ct_pcm_capture_pointer,
390 .page = snd_pcm_sgbuf_ops_page,
393 /* Create ALSA pcm device */
394 int ct_alsa_pcm_create(struct ct_atc *atc,
395 enum CTALSADEVS device,
396 const char *device_name)
398 struct snd_pcm *pcm;
399 int err;
400 int playback_count, capture_count;
402 playback_count = (IEC958 == device) ? 1 : 8;
403 capture_count = (FRONT == device) ? 1 : 0;
404 err = snd_pcm_new(atc->card, "ctxfi", device,
405 playback_count, capture_count, &pcm);
406 if (err < 0) {
407 printk(KERN_ERR "ctxfi: snd_pcm_new failed!! Err=%d\n", err);
408 return err;
411 pcm->private_data = atc;
412 pcm->info_flags = 0;
413 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
414 strlcpy(pcm->name, device_name, sizeof(pcm->name));
416 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ct_pcm_playback_ops);
418 if (FRONT == device)
419 snd_pcm_set_ops(pcm,
420 SNDRV_PCM_STREAM_CAPTURE, &ct_pcm_capture_ops);
422 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
423 snd_dma_pci_data(atc->pci), 128*1024, 128*1024);
425 #ifdef CONFIG_PM
426 atc->pcms[device] = pcm;
427 #endif
429 return 0;