ALSA: ctxfi - Clear PCM resources at hw_params and hw_free
[sfrench/cifs-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 "cttimer.h"
20 #include <sound/pcm.h>
21
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,
46 };
47
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,
68 };
69
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,
94 };
95
96 static void ct_atc_pcm_interrupt(struct ct_atc_pcm *atc_pcm)
97 {
98         struct ct_atc_pcm *apcm = atc_pcm;
99
100         if (NULL == apcm->substream)
101                 return;
102
103         snd_pcm_period_elapsed(apcm->substream);
104 }
105
106 static void ct_atc_pcm_free_substream(struct snd_pcm_runtime *runtime)
107 {
108         struct ct_atc_pcm *apcm = runtime->private_data;
109         struct ct_atc *atc = snd_pcm_substream_chip(apcm->substream);
110
111         atc->pcm_release_resources(atc, apcm);
112         ct_timer_instance_free(apcm->timer);
113         kfree(apcm);
114         runtime->private_data = NULL;
115 }
116
117 /* pcm playback operations */
118 static int ct_pcm_playback_open(struct snd_pcm_substream *substream)
119 {
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;
124
125         apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
126         if (NULL == apcm)
127                 return -ENOMEM;
128
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         apcm->timer = ct_timer_instance_new(atc->timer, apcm);
157         if (!apcm->timer)
158                 return -ENOMEM;
159
160         return 0;
161 }
162
163 static 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
176 static 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         int err;
182
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;
190 }
191
192 static int ct_pcm_hw_free(struct snd_pcm_substream *substream)
193 {
194         struct ct_atc *atc = snd_pcm_substream_chip(substream);
195         struct ct_atc_pcm *apcm = substream->runtime->private_data;
196
197         /* clear previous resources */
198         atc->pcm_release_resources(atc, apcm);
199         /* Free snd-allocated pages */
200         return snd_pcm_lib_free_pages(substream);
201 }
202
203
204 static int ct_pcm_playback_prepare(struct snd_pcm_substream *substream)
205 {
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;
210
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);
215
216         if (err < 0) {
217                 printk(KERN_ERR "ctxfi: Preparing pcm playback failed!!!\n");
218                 return err;
219         }
220
221         return 0;
222 }
223
224 static int
225 ct_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
226 {
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;
230
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;
244         }
245
246         return 0;
247 }
248
249 static snd_pcm_uframes_t
250 ct_pcm_playback_pointer(struct snd_pcm_substream *substream)
251 {
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;
256
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;
263 }
264
265 /* pcm capture operations */
266 static int ct_pcm_capture_open(struct snd_pcm_substream *substream)
267 {
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;
272
273         apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
274         if (NULL == apcm)
275                 return -ENOMEM;
276
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;
284
285         err = snd_pcm_hw_constraint_integer(runtime,
286                                             SNDRV_PCM_HW_PARAM_PERIODS);
287         if (err < 0) {
288                 kfree(apcm);
289                 return err;
290         }
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;
297         }
298
299         apcm->timer = ct_timer_instance_new(atc->timer, apcm);
300         if (!apcm->timer)
301                 return -ENOMEM;
302
303         return 0;
304 }
305
306 static int ct_pcm_capture_close(struct snd_pcm_substream *substream)
307 {
308         /* The ct_atc_pcm object will be freed by runtime->private_free */
309         /* TODO: Notify mixer inactive. */
310         return 0;
311 }
312
313 static int ct_pcm_capture_prepare(struct snd_pcm_substream *substream)
314 {
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;
319
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;
324         }
325
326         return 0;
327 }
328
329 static int
330 ct_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
331 {
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;
335
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;
346         }
347
348         return 0;
349 }
350
351 static snd_pcm_uframes_t
352 ct_pcm_capture_pointer(struct snd_pcm_substream *substream)
353 {
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;
358
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;
365 }
366
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,
378 };
379
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,
391 };
392
393 /* Create ALSA pcm device */
394 int ct_alsa_pcm_create(struct ct_atc *atc,
395                        enum CTALSADEVS device,
396                        const char *device_name)
397 {
398         struct snd_pcm *pcm;
399         int err;
400         int playback_count, capture_count;
401
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;
409         }
410
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));
415
416         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ct_pcm_playback_ops);
417
418         if (FRONT == device)
419                 snd_pcm_set_ops(pcm,
420                                 SNDRV_PCM_STREAM_CAPTURE, &ct_pcm_capture_ops);
421
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);
424
425         return 0;
426 }