aboutsummaryrefslogtreecommitdiff
path: root/sound/pci/ctxfi/ctpcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/ctxfi/ctpcm.c')
-rw-r--r--sound/pci/ctxfi/ctpcm.c70
1 files changed, 62 insertions, 8 deletions
diff --git a/sound/pci/ctxfi/ctpcm.c b/sound/pci/ctxfi/ctpcm.c
index 85ab43e8921..e8a4feb1ed8 100644
--- a/sound/pci/ctxfi/ctpcm.c
+++ b/sound/pci/ctxfi/ctpcm.c
@@ -129,8 +129,6 @@ static int ct_pcm_playback_open(struct snd_pcm_substream *substream)
apcm->substream = substream;
apcm->interrupt = ct_atc_pcm_interrupt;
- runtime->private_data = apcm;
- runtime->private_free = ct_atc_pcm_free_substream;
if (IEC958 == substream->pcm->device) {
runtime->hw = ct_spdif_passthru_playback_hw;
atc->spdif_out_passthru(atc, 1);
@@ -155,8 +153,12 @@ static int ct_pcm_playback_open(struct snd_pcm_substream *substream)
}
apcm->timer = ct_timer_instance_new(atc->timer, apcm);
- if (!apcm->timer)
+ if (!apcm->timer) {
+ kfree(apcm);
return -ENOMEM;
+ }
+ runtime->private_data = apcm;
+ runtime->private_free = ct_atc_pcm_free_substream;
return 0;
}
@@ -278,8 +280,6 @@ static int ct_pcm_capture_open(struct snd_pcm_substream *substream)
apcm->started = 0;
apcm->substream = substream;
apcm->interrupt = ct_atc_pcm_interrupt;
- runtime->private_data = apcm;
- runtime->private_free = ct_atc_pcm_free_substream;
runtime->hw = ct_pcm_capture_hw;
runtime->hw.rate_max = atc->rsr * atc->msr;
@@ -298,8 +298,12 @@ static int ct_pcm_capture_open(struct snd_pcm_substream *substream)
}
apcm->timer = ct_timer_instance_new(atc->timer, apcm);
- if (!apcm->timer)
+ if (!apcm->timer) {
+ kfree(apcm);
return -ENOMEM;
+ }
+ runtime->private_data = apcm;
+ runtime->private_free = ct_atc_pcm_free_substream;
return 0;
}
@@ -391,16 +395,42 @@ static struct snd_pcm_ops ct_pcm_capture_ops = {
.page = snd_pcm_sgbuf_ops_page,
};
+static const struct snd_pcm_chmap_elem surround_map[] = {
+ { .channels = 1,
+ .map = { SNDRV_CHMAP_MONO } },
+ { .channels = 2,
+ .map = { SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
+ { }
+};
+
+static const struct snd_pcm_chmap_elem clfe_map[] = {
+ { .channels = 1,
+ .map = { SNDRV_CHMAP_MONO } },
+ { .channels = 2,
+ .map = { SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } },
+ { }
+};
+
+static const struct snd_pcm_chmap_elem side_map[] = {
+ { .channels = 1,
+ .map = { SNDRV_CHMAP_MONO } },
+ { .channels = 2,
+ .map = { SNDRV_CHMAP_SL, SNDRV_CHMAP_SR } },
+ { }
+};
+
/* Create ALSA pcm device */
int ct_alsa_pcm_create(struct ct_atc *atc,
enum CTALSADEVS device,
const char *device_name)
{
struct snd_pcm *pcm;
+ const struct snd_pcm_chmap_elem *map;
+ int chs;
int err;
int playback_count, capture_count;
- playback_count = (IEC958 == device) ? 1 : 8;
+ playback_count = (IEC958 == device) ? 1 : 256;
capture_count = (FRONT == device) ? 1 : 0;
err = snd_pcm_new(atc->card, "ctxfi", device,
playback_count, capture_count, &pcm);
@@ -423,7 +453,31 @@ int ct_alsa_pcm_create(struct ct_atc *atc,
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
snd_dma_pci_data(atc->pci), 128*1024, 128*1024);
-#ifdef CONFIG_PM
+ 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;
+
+#ifdef CONFIG_PM_SLEEP
atc->pcms[device] = pcm;
#endif