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		dev_err(atc->card->dev,
221			"Preparing pcm playback failed!!!\n");
222		return err;
223	}
224
225	return 0;
226}
227
228static int
229ct_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
230{
231	struct ct_atc *atc = snd_pcm_substream_chip(substream);
232	struct snd_pcm_runtime *runtime = substream->runtime;
233	struct ct_atc_pcm *apcm = runtime->private_data;
234
235	switch (cmd) {
236	case SNDRV_PCM_TRIGGER_START:
237	case SNDRV_PCM_TRIGGER_RESUME:
238	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
239		atc->pcm_playback_start(atc, apcm);
240		break;
241	case SNDRV_PCM_TRIGGER_STOP:
242	case SNDRV_PCM_TRIGGER_SUSPEND:
243	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
244		atc->pcm_playback_stop(atc, apcm);
245		break;
246	default:
247		break;
248	}
249
250	return 0;
251}
252
253static snd_pcm_uframes_t
254ct_pcm_playback_pointer(struct snd_pcm_substream *substream)
255{
256	unsigned long position;
257	struct ct_atc *atc = snd_pcm_substream_chip(substream);
258	struct snd_pcm_runtime *runtime = substream->runtime;
259	struct ct_atc_pcm *apcm = runtime->private_data;
260
261	/* Read out playback position */
262	position = atc->pcm_playback_position(atc, apcm);
263	position = bytes_to_frames(runtime, position);
264	if (position >= runtime->buffer_size)
265		position = 0;
266	return position;
267}
268
269/* pcm capture operations */
270static int ct_pcm_capture_open(struct snd_pcm_substream *substream)
271{
272	struct ct_atc *atc = snd_pcm_substream_chip(substream);
273	struct snd_pcm_runtime *runtime = substream->runtime;
274	struct ct_atc_pcm *apcm;
275	int err;
276
277	apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
278	if (!apcm)
279		return -ENOMEM;
280
281	apcm->started = 0;
282	apcm->substream = substream;
283	apcm->interrupt = ct_atc_pcm_interrupt;
284	runtime->hw = ct_pcm_capture_hw;
285	runtime->hw.rate_max = atc->rsr * atc->msr;
286
287	err = snd_pcm_hw_constraint_integer(runtime,
288					    SNDRV_PCM_HW_PARAM_PERIODS);
289	if (err < 0) {
290		kfree(apcm);
291		return err;
292	}
293	err = snd_pcm_hw_constraint_minmax(runtime,
294					   SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
295					   1024, UINT_MAX);
296	if (err < 0) {
297		kfree(apcm);
298		return err;
299	}
300
301	apcm->timer = ct_timer_instance_new(atc->timer, apcm);
302	if (!apcm->timer) {
303		kfree(apcm);
304		return -ENOMEM;
305	}
306	runtime->private_data = apcm;
307	runtime->private_free = ct_atc_pcm_free_substream;
308
309	return 0;
310}
311
312static int ct_pcm_capture_close(struct snd_pcm_substream *substream)
313{
314	/* The ct_atc_pcm object will be freed by runtime->private_free */
315	/* TODO: Notify mixer inactive. */
316	return 0;
317}
318
319static int ct_pcm_capture_prepare(struct snd_pcm_substream *substream)
320{
321	int err;
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	err = atc->pcm_capture_prepare(atc, apcm);
327	if (err < 0) {
328		dev_err(atc->card->dev,
329			"Preparing pcm capture failed!!!\n");
330		return err;
331	}
332
333	return 0;
334}
335
336static int
337ct_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
338{
339	struct ct_atc *atc = snd_pcm_substream_chip(substream);
340	struct snd_pcm_runtime *runtime = substream->runtime;
341	struct ct_atc_pcm *apcm = runtime->private_data;
342
343	switch (cmd) {
344	case SNDRV_PCM_TRIGGER_START:
345		atc->pcm_capture_start(atc, apcm);
346		break;
347	case SNDRV_PCM_TRIGGER_STOP:
348		atc->pcm_capture_stop(atc, apcm);
349		break;
350	default:
351		atc->pcm_capture_stop(atc, apcm);
352		break;
353	}
354
355	return 0;
356}
357
358static snd_pcm_uframes_t
359ct_pcm_capture_pointer(struct snd_pcm_substream *substream)
360{
361	unsigned long position;
362	struct ct_atc *atc = snd_pcm_substream_chip(substream);
363	struct snd_pcm_runtime *runtime = substream->runtime;
364	struct ct_atc_pcm *apcm = runtime->private_data;
365
366	/* Read out playback position */
367	position = atc->pcm_capture_position(atc, apcm);
368	position = bytes_to_frames(runtime, position);
369	if (position >= runtime->buffer_size)
370		position = 0;
371	return position;
372}
373
374/* PCM operators for playback */
375static struct snd_pcm_ops ct_pcm_playback_ops = {
376	.open	 	= ct_pcm_playback_open,
377	.close		= ct_pcm_playback_close,
378	.ioctl		= snd_pcm_lib_ioctl,
379	.hw_params	= ct_pcm_hw_params,
380	.hw_free	= ct_pcm_hw_free,
381	.prepare	= ct_pcm_playback_prepare,
382	.trigger	= ct_pcm_playback_trigger,
383	.pointer	= ct_pcm_playback_pointer,
384	.page		= snd_pcm_sgbuf_ops_page,
385};
386
387/* PCM operators for capture */
388static struct snd_pcm_ops ct_pcm_capture_ops = {
389	.open	 	= ct_pcm_capture_open,
390	.close		= ct_pcm_capture_close,
391	.ioctl		= snd_pcm_lib_ioctl,
392	.hw_params	= ct_pcm_hw_params,
393	.hw_free	= ct_pcm_hw_free,
394	.prepare	= ct_pcm_capture_prepare,
395	.trigger	= ct_pcm_capture_trigger,
396	.pointer	= ct_pcm_capture_pointer,
397	.page		= snd_pcm_sgbuf_ops_page,
398};
399
400static const struct snd_pcm_chmap_elem surround_map[] = {
401	{ .channels = 1,
402	  .map = { SNDRV_CHMAP_MONO } },
403	{ .channels = 2,
404	  .map = { SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
405	{ }
406};
407
408static const struct snd_pcm_chmap_elem clfe_map[] = {
409	{ .channels = 1,
410	  .map = { SNDRV_CHMAP_MONO } },
411	{ .channels = 2,
412	  .map = { SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } },
413	{ }
414};
415
416static const struct snd_pcm_chmap_elem side_map[] = {
417	{ .channels = 1,
418	  .map = { SNDRV_CHMAP_MONO } },
419	{ .channels = 2,
420	  .map = { SNDRV_CHMAP_SL, SNDRV_CHMAP_SR } },
421	{ }
422};
423
424/* Create ALSA pcm device */
425int ct_alsa_pcm_create(struct ct_atc *atc,
426		       enum CTALSADEVS device,
427		       const char *device_name)
428{
429	struct snd_pcm *pcm;
430	const struct snd_pcm_chmap_elem *map;
431	int chs;
432	int err;
433	int playback_count, capture_count;
434
435	playback_count = (IEC958 == device) ? 1 : 256;
436	capture_count = (FRONT == device) ? 1 : 0;
437	err = snd_pcm_new(atc->card, "ctxfi", device,
438			  playback_count, capture_count, &pcm);
439	if (err < 0) {
440		dev_err(atc->card->dev, "snd_pcm_new failed!! Err=%d\n",
441			err);
442		return err;
443	}
444
445	pcm->private_data = atc;
446	pcm->info_flags = 0;
447	pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
448	strlcpy(pcm->name, device_name, sizeof(pcm->name));
449
450	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ct_pcm_playback_ops);
451
452	if (FRONT == device)
453		snd_pcm_set_ops(pcm,
454				SNDRV_PCM_STREAM_CAPTURE, &ct_pcm_capture_ops);
455
456	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
457			snd_dma_pci_data(atc->pci), 128*1024, 128*1024);
458
459	chs = 2;
460	switch (device) {
461	case FRONT:
462		chs = 8;
463		map = snd_pcm_std_chmaps;
464		break;
465	case SURROUND:
466		map = surround_map;
467		break;
468	case CLFE:
469		map = clfe_map;
470		break;
471	case SIDE:
472		map = side_map;
473		break;
474	default:
475		map = snd_pcm_std_chmaps;
476		break;
477	}
478	err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, chs,
479				     0, NULL);
480	if (err < 0)
481		return err;
482
483#ifdef CONFIG_PM_SLEEP
484	atc->pcms[device] = pcm;
485#endif
486
487	return 0;
488}
489