Blame view

sound/pci/ctxfi/ctpcm.c 12 KB
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  /**
   * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
   *
   * This source file is released under GPL v2 license (no other versions).
   * See the COPYING file included in the main directory of this source
   * distribution for the license terms and conditions.
   *
   * @File	ctpcm.c
   *
   * @Brief
   * This file contains the definition of the pcm device functions.
   *
   * @Author	Liu Chun
   * @Date 	Apr 2 2008
   *
   */
  
  #include "ctpcm.h"
b7bbf8760   Takashi Iwai   ALSA: ctxfi - Use...
19
  #include "cttimer.h"
5a0e3ad6a   Tejun Heo   include cleanup: ...
20
  #include <linux/slab.h>
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
21
22
23
24
25
26
27
28
29
30
  #include <sound/pcm.h>
  
  /* Hardware descriptions for playback */
  static struct snd_pcm_hardware ct_pcm_playback_hw = {
  	.info			= (SNDRV_PCM_INFO_MMAP |
  				   SNDRV_PCM_INFO_INTERLEAVED |
  				   SNDRV_PCM_INFO_BLOCK_TRANSFER |
  				   SNDRV_PCM_INFO_MMAP_VALID |
  				   SNDRV_PCM_INFO_PAUSE),
  	.formats		= (SNDRV_PCM_FMTBIT_U8 |
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
31
  				   SNDRV_PCM_FMTBIT_S16_LE |
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
32
  				   SNDRV_PCM_FMTBIT_S24_3LE |
d2b9b96c5   Takashi Iwai   ALSA: ctxfi - Fix...
33
34
  				   SNDRV_PCM_FMTBIT_S32_LE |
  				   SNDRV_PCM_FMTBIT_FLOAT_LE),
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
35
36
37
38
39
40
41
42
43
  	.rates			= (SNDRV_PCM_RATE_CONTINUOUS |
  				   SNDRV_PCM_RATE_8000_192000),
  	.rate_min		= 8000,
  	.rate_max		= 192000,
  	.channels_min		= 1,
  	.channels_max		= 2,
  	.buffer_bytes_max	= (128*1024),
  	.period_bytes_min	= (64),
  	.period_bytes_max	= (128*1024),
775ffa1d3   Takashi Iwai   ALSA: ctxfi - Set...
44
  	.periods_min		= 2,
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
45
46
47
48
49
50
51
52
53
54
  	.periods_max		= 1024,
  	.fifo_size		= 0,
  };
  
  static struct snd_pcm_hardware ct_spdif_passthru_playback_hw = {
  	.info			= (SNDRV_PCM_INFO_MMAP |
  				   SNDRV_PCM_INFO_INTERLEAVED |
  				   SNDRV_PCM_INFO_BLOCK_TRANSFER |
  				   SNDRV_PCM_INFO_MMAP_VALID |
  				   SNDRV_PCM_INFO_PAUSE),
d2b9b96c5   Takashi Iwai   ALSA: ctxfi - Fix...
55
  	.formats		= SNDRV_PCM_FMTBIT_S16_LE,
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
56
57
58
59
60
61
62
63
64
65
  	.rates			= (SNDRV_PCM_RATE_48000 |
  				   SNDRV_PCM_RATE_44100 |
  				   SNDRV_PCM_RATE_32000),
  	.rate_min		= 32000,
  	.rate_max		= 48000,
  	.channels_min		= 2,
  	.channels_max		= 2,
  	.buffer_bytes_max	= (128*1024),
  	.period_bytes_min	= (64),
  	.period_bytes_max	= (128*1024),
775ffa1d3   Takashi Iwai   ALSA: ctxfi - Set...
66
  	.periods_min		= 2,
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
67
68
69
70
71
72
73
74
75
76
77
78
  	.periods_max		= 1024,
  	.fifo_size		= 0,
  };
  
  /* Hardware descriptions for capture */
  static struct snd_pcm_hardware ct_pcm_capture_hw = {
  	.info			= (SNDRV_PCM_INFO_MMAP |
  				   SNDRV_PCM_INFO_INTERLEAVED |
  				   SNDRV_PCM_INFO_BLOCK_TRANSFER |
  				   SNDRV_PCM_INFO_PAUSE |
  				   SNDRV_PCM_INFO_MMAP_VALID),
  	.formats		= (SNDRV_PCM_FMTBIT_U8 |
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
79
  				   SNDRV_PCM_FMTBIT_S16_LE |
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
80
  				   SNDRV_PCM_FMTBIT_S24_3LE |
d2b9b96c5   Takashi Iwai   ALSA: ctxfi - Fix...
81
82
  				   SNDRV_PCM_FMTBIT_S32_LE |
  				   SNDRV_PCM_FMTBIT_FLOAT_LE),
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  	.rates			= (SNDRV_PCM_RATE_CONTINUOUS |
  				   SNDRV_PCM_RATE_8000_96000),
  	.rate_min		= 8000,
  	.rate_max		= 96000,
  	.channels_min		= 1,
  	.channels_max		= 2,
  	.buffer_bytes_max	= (128*1024),
  	.period_bytes_min	= (384),
  	.period_bytes_max	= (64*1024),
  	.periods_min		= 2,
  	.periods_max		= 1024,
  	.fifo_size		= 0,
  };
  
  static void ct_atc_pcm_interrupt(struct ct_atc_pcm *atc_pcm)
  {
  	struct ct_atc_pcm *apcm = atc_pcm;
35ebf6e72   Takashi Iwai   ALSA: ctxfi - Sim...
100
  	if (!apcm->substream)
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
101
102
103
104
105
106
107
108
109
110
111
  		return;
  
  	snd_pcm_period_elapsed(apcm->substream);
  }
  
  static void ct_atc_pcm_free_substream(struct snd_pcm_runtime *runtime)
  {
  	struct ct_atc_pcm *apcm = runtime->private_data;
  	struct ct_atc *atc = snd_pcm_substream_chip(apcm->substream);
  
  	atc->pcm_release_resources(atc, apcm);
b7bbf8760   Takashi Iwai   ALSA: ctxfi - Use...
112
  	ct_timer_instance_free(apcm->timer);
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
113
114
115
116
117
118
119
120
121
122
123
124
125
  	kfree(apcm);
  	runtime->private_data = NULL;
  }
  
  /* pcm playback operations */
  static int ct_pcm_playback_open(struct snd_pcm_substream *substream)
  {
  	struct ct_atc *atc = snd_pcm_substream_chip(substream);
  	struct snd_pcm_runtime *runtime = substream->runtime;
  	struct ct_atc_pcm *apcm;
  	int err;
  
  	apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
35ebf6e72   Takashi Iwai   ALSA: ctxfi - Sim...
126
  	if (!apcm)
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
127
  		return -ENOMEM;
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
128
129
  	apcm->substream = substream;
  	apcm->interrupt = ct_atc_pcm_interrupt;
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
  	if (IEC958 == substream->pcm->device) {
  		runtime->hw = ct_spdif_passthru_playback_hw;
  		atc->spdif_out_passthru(atc, 1);
  	} else {
  		runtime->hw = ct_pcm_playback_hw;
  		if (FRONT == substream->pcm->device)
  			runtime->hw.channels_max = 8;
  	}
  
  	err = snd_pcm_hw_constraint_integer(runtime,
  					    SNDRV_PCM_HW_PARAM_PERIODS);
  	if (err < 0) {
  		kfree(apcm);
  		return err;
  	}
  	err = snd_pcm_hw_constraint_minmax(runtime,
  					   SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
  					   1024, UINT_MAX);
  	if (err < 0) {
  		kfree(apcm);
  		return err;
  	}
b7bbf8760   Takashi Iwai   ALSA: ctxfi - Use...
152
  	apcm->timer = ct_timer_instance_new(atc->timer, apcm);
fa2b30af8   Julia Lawall   ALSA: sound/pci/c...
153
154
  	if (!apcm->timer) {
  		kfree(apcm);
b7bbf8760   Takashi Iwai   ALSA: ctxfi - Use...
155
  		return -ENOMEM;
fa2b30af8   Julia Lawall   ALSA: sound/pci/c...
156
157
158
  	}
  	runtime->private_data = apcm;
  	runtime->private_free = ct_atc_pcm_free_substream;
b7bbf8760   Takashi Iwai   ALSA: ctxfi - Use...
159

8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
  	return 0;
  }
  
  static int ct_pcm_playback_close(struct snd_pcm_substream *substream)
  {
  	struct ct_atc *atc = snd_pcm_substream_chip(substream);
  
  	/* TODO: Notify mixer inactive. */
  	if (IEC958 == substream->pcm->device)
  		atc->spdif_out_passthru(atc, 0);
  
  	/* The ct_atc_pcm object will be freed by runtime->private_free */
  
  	return 0;
  }
  
  static int ct_pcm_hw_params(struct snd_pcm_substream *substream,
  				     struct snd_pcm_hw_params *hw_params)
  {
a5990dc5b   Takashi Iwai   ALSA: ctxfi - Cle...
179
180
181
182
183
  	struct ct_atc *atc = snd_pcm_substream_chip(substream);
  	struct ct_atc_pcm *apcm = substream->runtime->private_data;
  	int err;
  
  	err = snd_pcm_lib_malloc_pages(substream,
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
184
  					params_buffer_bytes(hw_params));
a5990dc5b   Takashi Iwai   ALSA: ctxfi - Cle...
185
186
187
188
189
  	if (err < 0)
  		return err;
  	/* clear previous resources */
  	atc->pcm_release_resources(atc, apcm);
  	return err;
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
190
191
192
193
  }
  
  static int ct_pcm_hw_free(struct snd_pcm_substream *substream)
  {
a5990dc5b   Takashi Iwai   ALSA: ctxfi - Cle...
194
195
196
197
198
  	struct ct_atc *atc = snd_pcm_substream_chip(substream);
  	struct ct_atc_pcm *apcm = substream->runtime->private_data;
  
  	/* clear previous resources */
  	atc->pcm_release_resources(atc, apcm);
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
199
200
201
  	/* Free snd-allocated pages */
  	return snd_pcm_lib_free_pages(substream);
  }
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
202
203
204
205
206
207
208
209
210
211
212
213
214
215
  
  static int ct_pcm_playback_prepare(struct snd_pcm_substream *substream)
  {
  	int err;
  	struct ct_atc *atc = snd_pcm_substream_chip(substream);
  	struct snd_pcm_runtime *runtime = substream->runtime;
  	struct ct_atc_pcm *apcm = runtime->private_data;
  
  	if (IEC958 == substream->pcm->device)
  		err = atc->spdif_passthru_playback_prepare(atc, apcm);
  	else
  		err = atc->pcm_playback_prepare(atc, apcm);
  
  	if (err < 0) {
0cae90a96   Sudip Mukherjee   ALSA: ctxfi: pr_*...
216
217
218
  		dev_err(atc->card->dev,
  			"Preparing pcm playback failed!!!
  ");
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
219
220
  		return err;
  	}
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
  	return 0;
  }
  
  static int
  ct_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
  {
  	struct ct_atc *atc = snd_pcm_substream_chip(substream);
  	struct snd_pcm_runtime *runtime = substream->runtime;
  	struct ct_atc_pcm *apcm = runtime->private_data;
  
  	switch (cmd) {
  	case SNDRV_PCM_TRIGGER_START:
  	case SNDRV_PCM_TRIGGER_RESUME:
  	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  		atc->pcm_playback_start(atc, apcm);
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
236
237
238
239
  		break;
  	case SNDRV_PCM_TRIGGER_STOP:
  	case SNDRV_PCM_TRIGGER_SUSPEND:
  	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
  		atc->pcm_playback_stop(atc, apcm);
  		break;
  	default:
  		break;
  	}
  
  	return 0;
  }
  
  static snd_pcm_uframes_t
  ct_pcm_playback_pointer(struct snd_pcm_substream *substream)
  {
  	unsigned long position;
  	struct ct_atc *atc = snd_pcm_substream_chip(substream);
  	struct snd_pcm_runtime *runtime = substream->runtime;
  	struct ct_atc_pcm *apcm = runtime->private_data;
  
  	/* Read out playback position */
  	position = atc->pcm_playback_position(atc, apcm);
  	position = bytes_to_frames(runtime, position);
af8500bbb   Takashi Iwai   ALSA: ctxfi - Fix...
260
261
  	if (position >= runtime->buffer_size)
  		position = 0;
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
262
263
264
265
266
267
268
269
270
271
272
273
  	return position;
  }
  
  /* pcm capture operations */
  static int ct_pcm_capture_open(struct snd_pcm_substream *substream)
  {
  	struct ct_atc *atc = snd_pcm_substream_chip(substream);
  	struct snd_pcm_runtime *runtime = substream->runtime;
  	struct ct_atc_pcm *apcm;
  	int err;
  
  	apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
35ebf6e72   Takashi Iwai   ALSA: ctxfi - Sim...
274
  	if (!apcm)
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
275
  		return -ENOMEM;
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
276
  	apcm->started = 0;
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
277
278
  	apcm->substream = substream;
  	apcm->interrupt = ct_atc_pcm_interrupt;
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
  	runtime->hw = ct_pcm_capture_hw;
  	runtime->hw.rate_max = atc->rsr * atc->msr;
  
  	err = snd_pcm_hw_constraint_integer(runtime,
  					    SNDRV_PCM_HW_PARAM_PERIODS);
  	if (err < 0) {
  		kfree(apcm);
  		return err;
  	}
  	err = snd_pcm_hw_constraint_minmax(runtime,
  					   SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
  					   1024, UINT_MAX);
  	if (err < 0) {
  		kfree(apcm);
  		return err;
  	}
b7bbf8760   Takashi Iwai   ALSA: ctxfi - Use...
295
  	apcm->timer = ct_timer_instance_new(atc->timer, apcm);
fa2b30af8   Julia Lawall   ALSA: sound/pci/c...
296
297
  	if (!apcm->timer) {
  		kfree(apcm);
b7bbf8760   Takashi Iwai   ALSA: ctxfi - Use...
298
  		return -ENOMEM;
fa2b30af8   Julia Lawall   ALSA: sound/pci/c...
299
300
301
  	}
  	runtime->private_data = apcm;
  	runtime->private_free = ct_atc_pcm_free_substream;
b7bbf8760   Takashi Iwai   ALSA: ctxfi - Use...
302

8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
  	return 0;
  }
  
  static int ct_pcm_capture_close(struct snd_pcm_substream *substream)
  {
  	/* The ct_atc_pcm object will be freed by runtime->private_free */
  	/* TODO: Notify mixer inactive. */
  	return 0;
  }
  
  static int ct_pcm_capture_prepare(struct snd_pcm_substream *substream)
  {
  	int err;
  	struct ct_atc *atc = snd_pcm_substream_chip(substream);
  	struct snd_pcm_runtime *runtime = substream->runtime;
  	struct ct_atc_pcm *apcm = runtime->private_data;
  
  	err = atc->pcm_capture_prepare(atc, apcm);
  	if (err < 0) {
0cae90a96   Sudip Mukherjee   ALSA: ctxfi: pr_*...
322
323
324
  		dev_err(atc->card->dev,
  			"Preparing pcm capture failed!!!
  ");
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
325
326
  		return err;
  	}
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
327
328
329
330
331
332
333
334
335
336
337
338
339
  	return 0;
  }
  
  static int
  ct_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
  {
  	struct ct_atc *atc = snd_pcm_substream_chip(substream);
  	struct snd_pcm_runtime *runtime = substream->runtime;
  	struct ct_atc_pcm *apcm = runtime->private_data;
  
  	switch (cmd) {
  	case SNDRV_PCM_TRIGGER_START:
  		atc->pcm_capture_start(atc, apcm);
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
340
341
  		break;
  	case SNDRV_PCM_TRIGGER_STOP:
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
342
343
344
  		atc->pcm_capture_stop(atc, apcm);
  		break;
  	default:
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
  		atc->pcm_capture_stop(atc, apcm);
  		break;
  	}
  
  	return 0;
  }
  
  static snd_pcm_uframes_t
  ct_pcm_capture_pointer(struct snd_pcm_substream *substream)
  {
  	unsigned long position;
  	struct ct_atc *atc = snd_pcm_substream_chip(substream);
  	struct snd_pcm_runtime *runtime = substream->runtime;
  	struct ct_atc_pcm *apcm = runtime->private_data;
  
  	/* Read out playback position */
  	position = atc->pcm_capture_position(atc, apcm);
  	position = bytes_to_frames(runtime, position);
af8500bbb   Takashi Iwai   ALSA: ctxfi - Fix...
363
364
  	if (position >= runtime->buffer_size)
  		position = 0;
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
365
366
367
368
369
370
371
372
373
374
375
376
377
  	return position;
  }
  
  /* PCM operators for playback */
  static struct snd_pcm_ops ct_pcm_playback_ops = {
  	.open	 	= ct_pcm_playback_open,
  	.close		= ct_pcm_playback_close,
  	.ioctl		= snd_pcm_lib_ioctl,
  	.hw_params	= ct_pcm_hw_params,
  	.hw_free	= ct_pcm_hw_free,
  	.prepare	= ct_pcm_playback_prepare,
  	.trigger	= ct_pcm_playback_trigger,
  	.pointer	= ct_pcm_playback_pointer,
c76157d92   Takashi Iwai   ALSA: ctxfi - Sup...
378
  	.page		= snd_pcm_sgbuf_ops_page,
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
379
380
381
382
383
384
385
386
387
388
389
390
  };
  
  /* PCM operators for capture */
  static struct snd_pcm_ops ct_pcm_capture_ops = {
  	.open	 	= ct_pcm_capture_open,
  	.close		= ct_pcm_capture_close,
  	.ioctl		= snd_pcm_lib_ioctl,
  	.hw_params	= ct_pcm_hw_params,
  	.hw_free	= ct_pcm_hw_free,
  	.prepare	= ct_pcm_capture_prepare,
  	.trigger	= ct_pcm_capture_trigger,
  	.pointer	= ct_pcm_capture_pointer,
c76157d92   Takashi Iwai   ALSA: ctxfi - Sup...
391
  	.page		= snd_pcm_sgbuf_ops_page,
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
392
  };
8d50cdc1f   Takashi Iwai   ALSA: ctxfi: Impl...
393
394
  static const struct snd_pcm_chmap_elem surround_map[] = {
  	{ .channels = 1,
7b31d0095   Takashi Iwai   ALSA: Define more...
395
  	  .map = { SNDRV_CHMAP_MONO } },
8d50cdc1f   Takashi Iwai   ALSA: ctxfi: Impl...
396
397
398
399
400
401
402
  	{ .channels = 2,
  	  .map = { SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
  	{ }
  };
  
  static const struct snd_pcm_chmap_elem clfe_map[] = {
  	{ .channels = 1,
7b31d0095   Takashi Iwai   ALSA: Define more...
403
  	  .map = { SNDRV_CHMAP_MONO } },
8d50cdc1f   Takashi Iwai   ALSA: ctxfi: Impl...
404
405
406
407
408
409
410
  	{ .channels = 2,
  	  .map = { SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } },
  	{ }
  };
  
  static const struct snd_pcm_chmap_elem side_map[] = {
  	{ .channels = 1,
7b31d0095   Takashi Iwai   ALSA: Define more...
411
  	  .map = { SNDRV_CHMAP_MONO } },
8d50cdc1f   Takashi Iwai   ALSA: ctxfi: Impl...
412
413
414
415
  	{ .channels = 2,
  	  .map = { SNDRV_CHMAP_SL, SNDRV_CHMAP_SR } },
  	{ }
  };
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
416
417
418
419
420
421
  /* Create ALSA pcm device */
  int ct_alsa_pcm_create(struct ct_atc *atc,
  		       enum CTALSADEVS device,
  		       const char *device_name)
  {
  	struct snd_pcm *pcm;
8d50cdc1f   Takashi Iwai   ALSA: ctxfi: Impl...
422
423
  	const struct snd_pcm_chmap_elem *map;
  	int chs;
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
424
425
  	int err;
  	int playback_count, capture_count;
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
426

391e69143   Maarten Lankhorst   ALSA: ctxfi: Bump...
427
  	playback_count = (IEC958 == device) ? 1 : 256;
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
428
  	capture_count = (FRONT == device) ? 1 : 0;
8372d4980   Takashi Iwai   ALSA: ctxfi - Fix...
429
  	err = snd_pcm_new(atc->card, "ctxfi", device,
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
430
431
  			  playback_count, capture_count, &pcm);
  	if (err < 0) {
0cae90a96   Sudip Mukherjee   ALSA: ctxfi: pr_*...
432
433
434
  		dev_err(atc->card->dev, "snd_pcm_new failed!! Err=%d
  ",
  			err);
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
435
436
437
438
439
440
  		return err;
  	}
  
  	pcm->private_data = atc;
  	pcm->info_flags = 0;
  	pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
8372d4980   Takashi Iwai   ALSA: ctxfi - Fix...
441
  	strlcpy(pcm->name, device_name, sizeof(pcm->name));
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
442
443
444
445
446
447
  
  	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ct_pcm_playback_ops);
  
  	if (FRONT == device)
  		snd_pcm_set_ops(pcm,
  				SNDRV_PCM_STREAM_CAPTURE, &ct_pcm_capture_ops);
c76157d92   Takashi Iwai   ALSA: ctxfi - Sup...
448
  	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
449
  			snd_dma_pci_data(atc->pci), 128*1024, 128*1024);
8d50cdc1f   Takashi Iwai   ALSA: ctxfi: Impl...
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
  	chs = 2;
  	switch (device) {
  	case FRONT:
  		chs = 8;
  		map = snd_pcm_std_chmaps;
  		break;
  	case SURROUND:
  		map = surround_map;
  		break;
  	case CLFE:
  		map = clfe_map;
  		break;
  	case SIDE:
  		map = side_map;
  		break;
  	default:
  		map = snd_pcm_std_chmaps;
  		break;
  	}
  	err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, chs,
  				     0, NULL);
  	if (err < 0)
  		return err;
c7561cd80   Takashi Iwai   ALSA: PCI: Replac...
473
  #ifdef CONFIG_PM_SLEEP
29959a09c   Wai Yew CHAY   ALSA: ctxfi - Add...
474
475
  	atc->pcms[device] = pcm;
  #endif
8cc723614   Wai Yew CHAY   ALSA: SB X-Fi dri...
476
477
  	return 0;
  }