ALSA: ctxfi - Support SG-buffers
[linux-2.6.git] / sound / pci / ctxfi / ctpcm.c
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 <sound/pcm.h>
20
21 /* Hardware descriptions for playback */
22 static struct snd_pcm_hardware ct_pcm_playback_hw = {
23         .info                   = (SNDRV_PCM_INFO_MMAP |
24                                    SNDRV_PCM_INFO_INTERLEAVED |
25                                    SNDRV_PCM_INFO_BLOCK_TRANSFER |
26                                    SNDRV_PCM_INFO_MMAP_VALID |
27                                    SNDRV_PCM_INFO_PAUSE),
28         .formats                = (SNDRV_PCM_FMTBIT_U8 |
29                                    SNDRV_PCM_FMTBIT_S16_LE |
30                                    SNDRV_PCM_FMTBIT_S24_3LE |
31                                    SNDRV_PCM_FMTBIT_S32_LE |
32                                    SNDRV_PCM_FMTBIT_FLOAT_LE),
33         .rates                  = (SNDRV_PCM_RATE_CONTINUOUS |
34                                    SNDRV_PCM_RATE_8000_192000),
35         .rate_min               = 8000,
36         .rate_max               = 192000,
37         .channels_min           = 1,
38         .channels_max           = 2,
39         .buffer_bytes_max       = (128*1024),
40         .period_bytes_min       = (64),
41         .period_bytes_max       = (128*1024),
42         .periods_min            = 1,
43         .periods_max            = 1024,
44         .fifo_size              = 0,
45 };
46
47 static struct snd_pcm_hardware ct_spdif_passthru_playback_hw = {
48         .info                   = (SNDRV_PCM_INFO_MMAP |
49                                    SNDRV_PCM_INFO_INTERLEAVED |
50                                    SNDRV_PCM_INFO_BLOCK_TRANSFER |
51                                    SNDRV_PCM_INFO_MMAP_VALID |
52                                    SNDRV_PCM_INFO_PAUSE),
53         .formats                = SNDRV_PCM_FMTBIT_S16_LE,
54         .rates                  = (SNDRV_PCM_RATE_48000 |
55                                    SNDRV_PCM_RATE_44100 |
56                                    SNDRV_PCM_RATE_32000),
57         .rate_min               = 32000,
58         .rate_max               = 48000,
59         .channels_min           = 2,
60         .channels_max           = 2,
61         .buffer_bytes_max       = (128*1024),
62         .period_bytes_min       = (64),
63         .period_bytes_max       = (128*1024),
64         .periods_min            = 1,
65         .periods_max            = 1024,
66         .fifo_size              = 0,
67 };
68
69 /* Hardware descriptions for capture */
70 static struct snd_pcm_hardware ct_pcm_capture_hw = {
71         .info                   = (SNDRV_PCM_INFO_MMAP |
72                                    SNDRV_PCM_INFO_INTERLEAVED |
73                                    SNDRV_PCM_INFO_BLOCK_TRANSFER |
74                                    SNDRV_PCM_INFO_PAUSE |
75                                    SNDRV_PCM_INFO_MMAP_VALID),
76         .formats                = (SNDRV_PCM_FMTBIT_U8 |
77                                    SNDRV_PCM_FMTBIT_S16_LE |
78                                    SNDRV_PCM_FMTBIT_S24_3LE |
79                                    SNDRV_PCM_FMTBIT_S32_LE |
80                                    SNDRV_PCM_FMTBIT_FLOAT_LE),
81         .rates                  = (SNDRV_PCM_RATE_CONTINUOUS |
82                                    SNDRV_PCM_RATE_8000_96000),
83         .rate_min               = 8000,
84         .rate_max               = 96000,
85         .channels_min           = 1,
86         .channels_max           = 2,
87         .buffer_bytes_max       = (128*1024),
88         .period_bytes_min       = (384),
89         .period_bytes_max       = (64*1024),
90         .periods_min            = 2,
91         .periods_max            = 1024,
92         .fifo_size              = 0,
93 };
94
95 static void ct_atc_pcm_interrupt(struct ct_atc_pcm *atc_pcm)
96 {
97         struct ct_atc_pcm *apcm = atc_pcm;
98
99         if (NULL == apcm->substream)
100                 return;
101
102         snd_pcm_period_elapsed(apcm->substream);
103 }
104
105 static void ct_atc_pcm_free_substream(struct snd_pcm_runtime *runtime)
106 {
107         struct ct_atc_pcm *apcm = runtime->private_data;
108         struct ct_atc *atc = snd_pcm_substream_chip(apcm->substream);
109
110         atc->pcm_release_resources(atc, apcm);
111         kfree(apcm);
112         runtime->private_data = NULL;
113 }
114
115 /* pcm playback operations */
116 static int ct_pcm_playback_open(struct snd_pcm_substream *substream)
117 {
118         struct ct_atc *atc = snd_pcm_substream_chip(substream);
119         struct snd_pcm_runtime *runtime = substream->runtime;
120         struct ct_atc_pcm *apcm;
121         int err;
122
123         apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
124         if (NULL == apcm)
125                 return -ENOMEM;
126
127         spin_lock_init(&apcm->timer_lock);
128         apcm->stop_timer = 0;
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;
140         }
141
142         err = snd_pcm_hw_constraint_integer(runtime,
143                                             SNDRV_PCM_HW_PARAM_PERIODS);
144         if (err < 0) {
145                 kfree(apcm);
146                 return err;
147         }
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;
154         }
155
156         return 0;
157 }
158
159 static int ct_pcm_playback_close(struct snd_pcm_substream *substream)
160 {
161         struct ct_atc *atc = snd_pcm_substream_chip(substream);
162
163         /* TODO: Notify mixer inactive. */
164         if (IEC958 == substream->pcm->device)
165                 atc->spdif_out_passthru(atc, 0);
166
167         /* The ct_atc_pcm object will be freed by runtime->private_free */
168
169         return 0;
170 }
171
172 static int ct_pcm_hw_params(struct snd_pcm_substream *substream,
173                                      struct snd_pcm_hw_params *hw_params)
174 {
175         return snd_pcm_lib_malloc_pages(substream,
176                                         params_buffer_bytes(hw_params));
177 }
178
179 static int ct_pcm_hw_free(struct snd_pcm_substream *substream)
180 {
181         /* Free snd-allocated pages */
182         return snd_pcm_lib_free_pages(substream);
183 }
184
185 static void ct_pcm_timer_callback(unsigned long data)
186 {
187         struct ct_atc_pcm *apcm = (struct ct_atc_pcm *)data;
188         struct snd_pcm_substream *substream = apcm->substream;
189         struct snd_pcm_runtime *runtime = substream->runtime;
190         unsigned int period_size = runtime->period_size;
191         unsigned int buffer_size = runtime->buffer_size;
192         unsigned long flags;
193         unsigned int position = 0, dist = 0, interval = 0;
194
195         position = substream->ops->pointer(substream);
196         dist = (position + buffer_size - apcm->position) % buffer_size;
197         if ((dist >= period_size) ||
198                 (position/period_size != apcm->position/period_size)) {
199                 apcm->interrupt(apcm);
200                 apcm->position = position;
201         }
202         /* Add extra HZ*5/1000 to avoid overrun issue when recording
203          * at 8kHz in 8-bit format or at 88kHz in 24-bit format. */
204         interval = ((period_size - (position % period_size))
205                    * HZ + (runtime->rate - 1)) / runtime->rate + HZ * 5 / 1000;
206         spin_lock_irqsave(&apcm->timer_lock, flags);
207         apcm->timer.expires = jiffies + interval;
208         if (!apcm->stop_timer)
209                 add_timer(&apcm->timer);
210
211         spin_unlock_irqrestore(&apcm->timer_lock, flags);
212 }
213
214 static int ct_pcm_timer_prepare(struct ct_atc_pcm *apcm)
215 {
216         unsigned long flags;
217
218         spin_lock_irqsave(&apcm->timer_lock, flags);
219         if (timer_pending(&apcm->timer)) {
220                 /* The timer has already been started. */
221                 spin_unlock_irqrestore(&apcm->timer_lock, flags);
222                 return 0;
223         }
224
225         init_timer(&apcm->timer);
226         apcm->timer.data = (unsigned long)apcm;
227         apcm->timer.function = ct_pcm_timer_callback;
228         spin_unlock_irqrestore(&apcm->timer_lock, flags);
229         apcm->position = 0;
230
231         return 0;
232 }
233
234 static int ct_pcm_timer_start(struct ct_atc_pcm *apcm)
235 {
236         struct snd_pcm_runtime *runtime = apcm->substream->runtime;
237         unsigned long flags;
238
239         spin_lock_irqsave(&apcm->timer_lock, flags);
240         if (timer_pending(&apcm->timer)) {
241                 /* The timer has already been started. */
242                 spin_unlock_irqrestore(&apcm->timer_lock, flags);
243                 return 0;
244         }
245
246         apcm->timer.expires = jiffies + (runtime->period_size * HZ +
247                                 (runtime->rate - 1)) / runtime->rate;
248         apcm->stop_timer = 0;
249         add_timer(&apcm->timer);
250         spin_unlock_irqrestore(&apcm->timer_lock, flags);
251
252         return 0;
253 }
254
255 static int ct_pcm_timer_stop(struct ct_atc_pcm *apcm)
256 {
257         unsigned long flags;
258
259         spin_lock_irqsave(&apcm->timer_lock, flags);
260         apcm->stop_timer = 1;
261         del_timer(&apcm->timer);
262         spin_unlock_irqrestore(&apcm->timer_lock, flags);
263
264         try_to_del_timer_sync(&apcm->timer);
265
266         return 0;
267 }
268
269 static int ct_pcm_playback_prepare(struct snd_pcm_substream *substream)
270 {
271         int err;
272         struct ct_atc *atc = snd_pcm_substream_chip(substream);
273         struct snd_pcm_runtime *runtime = substream->runtime;
274         struct ct_atc_pcm *apcm = runtime->private_data;
275
276         if (IEC958 == substream->pcm->device)
277                 err = atc->spdif_passthru_playback_prepare(atc, apcm);
278         else
279                 err = atc->pcm_playback_prepare(atc, apcm);
280
281         if (err < 0) {
282                 printk(KERN_ERR "ctxfi: Preparing pcm playback failed!!!\n");
283                 return err;
284         }
285
286         ct_pcm_timer_prepare(apcm);
287
288         return 0;
289 }
290
291 static int
292 ct_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
293 {
294         struct ct_atc *atc = snd_pcm_substream_chip(substream);
295         struct snd_pcm_runtime *runtime = substream->runtime;
296         struct ct_atc_pcm *apcm = runtime->private_data;
297
298         switch (cmd) {
299         case SNDRV_PCM_TRIGGER_START:
300         case SNDRV_PCM_TRIGGER_RESUME:
301         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
302                 atc->pcm_playback_start(atc, apcm);
303                 ct_pcm_timer_start(apcm);
304                 break;
305         case SNDRV_PCM_TRIGGER_STOP:
306         case SNDRV_PCM_TRIGGER_SUSPEND:
307         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
308                 ct_pcm_timer_stop(apcm);
309                 atc->pcm_playback_stop(atc, apcm);
310                 break;
311         default:
312                 break;
313         }
314
315         return 0;
316 }
317
318 static snd_pcm_uframes_t
319 ct_pcm_playback_pointer(struct snd_pcm_substream *substream)
320 {
321         unsigned long position;
322         struct ct_atc *atc = snd_pcm_substream_chip(substream);
323         struct snd_pcm_runtime *runtime = substream->runtime;
324         struct ct_atc_pcm *apcm = runtime->private_data;
325
326         /* Read out playback position */
327         position = atc->pcm_playback_position(atc, apcm);
328         position = bytes_to_frames(runtime, position);
329         return position;
330 }
331
332 /* pcm capture operations */
333 static int ct_pcm_capture_open(struct snd_pcm_substream *substream)
334 {
335         struct ct_atc *atc = snd_pcm_substream_chip(substream);
336         struct snd_pcm_runtime *runtime = substream->runtime;
337         struct ct_atc_pcm *apcm;
338         int err;
339
340         apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
341         if (NULL == apcm)
342                 return -ENOMEM;
343
344         spin_lock_init(&apcm->timer_lock);
345         apcm->started = 0;
346         apcm->stop_timer = 0;
347         apcm->substream = substream;
348         apcm->interrupt = ct_atc_pcm_interrupt;
349         runtime->private_data = apcm;
350         runtime->private_free = ct_atc_pcm_free_substream;
351         runtime->hw = ct_pcm_capture_hw;
352         runtime->hw.rate_max = atc->rsr * atc->msr;
353
354         err = snd_pcm_hw_constraint_integer(runtime,
355                                             SNDRV_PCM_HW_PARAM_PERIODS);
356         if (err < 0) {
357                 kfree(apcm);
358                 return err;
359         }
360         err = snd_pcm_hw_constraint_minmax(runtime,
361                                            SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
362                                            1024, UINT_MAX);
363         if (err < 0) {
364                 kfree(apcm);
365                 return err;
366         }
367
368         return 0;
369 }
370
371 static int ct_pcm_capture_close(struct snd_pcm_substream *substream)
372 {
373         /* The ct_atc_pcm object will be freed by runtime->private_free */
374         /* TODO: Notify mixer inactive. */
375         return 0;
376 }
377
378 static int ct_pcm_capture_prepare(struct snd_pcm_substream *substream)
379 {
380         int err;
381         struct ct_atc *atc = snd_pcm_substream_chip(substream);
382         struct snd_pcm_runtime *runtime = substream->runtime;
383         struct ct_atc_pcm *apcm = runtime->private_data;
384
385         err = atc->pcm_capture_prepare(atc, apcm);
386         if (err < 0) {
387                 printk(KERN_ERR "ctxfi: Preparing pcm capture failed!!!\n");
388                 return err;
389         }
390
391         ct_pcm_timer_prepare(apcm);
392
393         return 0;
394 }
395
396 static int
397 ct_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
398 {
399         struct ct_atc *atc = snd_pcm_substream_chip(substream);
400         struct snd_pcm_runtime *runtime = substream->runtime;
401         struct ct_atc_pcm *apcm = runtime->private_data;
402
403         switch (cmd) {
404         case SNDRV_PCM_TRIGGER_START:
405                 atc->pcm_capture_start(atc, apcm);
406                 ct_pcm_timer_start(apcm);
407                 break;
408         case SNDRV_PCM_TRIGGER_STOP:
409                 ct_pcm_timer_stop(apcm);
410                 atc->pcm_capture_stop(atc, apcm);
411                 break;
412         default:
413                 ct_pcm_timer_stop(apcm);
414                 atc->pcm_capture_stop(atc, apcm);
415                 break;
416         }
417
418         return 0;
419 }
420
421 static snd_pcm_uframes_t
422 ct_pcm_capture_pointer(struct snd_pcm_substream *substream)
423 {
424         unsigned long position;
425         struct ct_atc *atc = snd_pcm_substream_chip(substream);
426         struct snd_pcm_runtime *runtime = substream->runtime;
427         struct ct_atc_pcm *apcm = runtime->private_data;
428
429         /* Read out playback position */
430         position = atc->pcm_capture_position(atc, apcm);
431         position = bytes_to_frames(runtime, position);
432         return position;
433 }
434
435 /* PCM operators for playback */
436 static struct snd_pcm_ops ct_pcm_playback_ops = {
437         .open           = ct_pcm_playback_open,
438         .close          = ct_pcm_playback_close,
439         .ioctl          = snd_pcm_lib_ioctl,
440         .hw_params      = ct_pcm_hw_params,
441         .hw_free        = ct_pcm_hw_free,
442         .prepare        = ct_pcm_playback_prepare,
443         .trigger        = ct_pcm_playback_trigger,
444         .pointer        = ct_pcm_playback_pointer,
445         .page           = snd_pcm_sgbuf_ops_page,
446 };
447
448 /* PCM operators for capture */
449 static struct snd_pcm_ops ct_pcm_capture_ops = {
450         .open           = ct_pcm_capture_open,
451         .close          = ct_pcm_capture_close,
452         .ioctl          = snd_pcm_lib_ioctl,
453         .hw_params      = ct_pcm_hw_params,
454         .hw_free        = ct_pcm_hw_free,
455         .prepare        = ct_pcm_capture_prepare,
456         .trigger        = ct_pcm_capture_trigger,
457         .pointer        = ct_pcm_capture_pointer,
458         .page           = snd_pcm_sgbuf_ops_page,
459 };
460
461 /* Create ALSA pcm device */
462 int ct_alsa_pcm_create(struct ct_atc *atc,
463                        enum CTALSADEVS device,
464                        const char *device_name)
465 {
466         struct snd_pcm *pcm;
467         int err;
468         int playback_count, capture_count;
469
470         playback_count = (IEC958 == device) ? 1 : 8;
471         capture_count = (FRONT == device) ? 1 : 0;
472         err = snd_pcm_new(atc->card, "ctxfi", device,
473                           playback_count, capture_count, &pcm);
474         if (err < 0) {
475                 printk(KERN_ERR "ctxfi: snd_pcm_new failed!! Err=%d\n", err);
476                 return err;
477         }
478
479         pcm->private_data = atc;
480         pcm->info_flags = 0;
481         pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
482         strlcpy(pcm->name, device_name, sizeof(pcm->name));
483
484         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ct_pcm_playback_ops);
485
486         if (FRONT == device)
487                 snd_pcm_set_ops(pcm,
488                                 SNDRV_PCM_STREAM_CAPTURE, &ct_pcm_capture_ops);
489
490         snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
491                         snd_dma_pci_data(atc->pci), 128*1024, 128*1024);
492
493         return 0;
494 }