xref: /openbmc/linux/sound/pci/ctxfi/ctpcm.c (revision fd589a8f)
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 (!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 (!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 (!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 #ifdef CONFIG_PM
426 	atc->pcms[device] = pcm;
427 #endif
428 
429 	return 0;
430 }
431