diff options
author | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2014-11-28 10:59:18 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-11-29 14:17:06 -0500 |
commit | 2c2416c83e7345fc51af49132c40ec7d337d4132 (patch) | |
tree | 8e7429e9c5b4abd80a0a097e4ef0e2804cd17510 /sound/firewire | |
parent | 04d426a039691bf114997a8af877682fdffcebd7 (diff) |
ALSA: dice: Add new functions for constraints of PCM parameters
This commit adds a new functions and some arrangement for PCM restriction.
This arrangement is due to the number of channels which each Dice device has.
I note that minimum number for period becomes 2, instead of 1 because its PCM
functionality has SNDRV_PCM_INFO_BATCH, this means that the driver uses double
(or more) buffering so the minimum number for period should be 2.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire')
-rw-r--r-- | sound/firewire/dice/dice-pcm.c | 109 |
1 files changed, 65 insertions, 44 deletions
diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index deacb537eb81..2e531bd30e28 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c | |||
@@ -67,71 +67,92 @@ static int dice_channels_constraint(struct snd_pcm_hw_params *params, | |||
67 | return snd_interval_refine(c, &channels); | 67 | return snd_interval_refine(c, &channels); |
68 | } | 68 | } |
69 | 69 | ||
70 | 70 | static void limit_channels_and_rates(struct snd_dice *dice, | |
71 | static int pcm_open(struct snd_pcm_substream *substream) | 71 | struct snd_pcm_runtime *runtime, |
72 | unsigned int *pcm_channels) | ||
72 | { | 73 | { |
73 | static const struct snd_pcm_hardware hardware = { | 74 | struct snd_pcm_hardware *hw = &runtime->hw; |
74 | .info = SNDRV_PCM_INFO_MMAP | | 75 | unsigned int i, rate, mode; |
75 | SNDRV_PCM_INFO_MMAP_VALID | | ||
76 | SNDRV_PCM_INFO_BATCH | | ||
77 | SNDRV_PCM_INFO_INTERLEAVED | | ||
78 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | ||
79 | .formats = AMDTP_OUT_PCM_FORMAT_BITS, | ||
80 | .channels_min = UINT_MAX, | ||
81 | .channels_max = 0, | ||
82 | .buffer_bytes_max = 16 * 1024 * 1024, | ||
83 | .period_bytes_min = 1, | ||
84 | .period_bytes_max = UINT_MAX, | ||
85 | .periods_min = 1, | ||
86 | .periods_max = UINT_MAX, | ||
87 | }; | ||
88 | struct snd_dice *dice = substream->private_data; | ||
89 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
90 | unsigned int i; | ||
91 | int err; | ||
92 | 76 | ||
93 | err = snd_dice_stream_lock_try(dice); | 77 | hw->channels_min = UINT_MAX; |
94 | if (err < 0) | 78 | hw->channels_max = 0; |
95 | goto error; | ||
96 | |||
97 | runtime->hw = hardware; | ||
98 | 79 | ||
99 | for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) { | 80 | for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) { |
100 | if (dice->clock_caps & (1 << i)) | 81 | rate = snd_dice_rates[i]; |
101 | runtime->hw.rates |= | 82 | if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0) |
102 | snd_pcm_rate_to_rate_bit(snd_dice_rates[i]); | 83 | continue; |
84 | hw->rates |= snd_pcm_rate_to_rate_bit(rate); | ||
85 | |||
86 | if (pcm_channels[mode] == 0) | ||
87 | continue; | ||
88 | hw->channels_min = min(hw->channels_min, pcm_channels[mode]); | ||
89 | hw->channels_max = max(hw->channels_max, pcm_channels[mode]); | ||
103 | } | 90 | } |
91 | |||
104 | snd_pcm_limit_hw_rates(runtime); | 92 | snd_pcm_limit_hw_rates(runtime); |
93 | } | ||
105 | 94 | ||
106 | for (i = 0; i < 3; ++i) { | 95 | static void limit_period_and_buffer(struct snd_pcm_hardware *hw) |
107 | if (dice->rx_channels[i]) { | 96 | { |
108 | runtime->hw.channels_min = min(runtime->hw.channels_min, | 97 | hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ |
109 | dice->rx_channels[i]); | 98 | hw->periods_max = UINT_MAX; |
110 | runtime->hw.channels_max = max(runtime->hw.channels_max, | 99 | |
111 | dice->rx_channels[i]); | 100 | hw->period_bytes_min = 4 * hw->channels_max; /* byte for a frame */ |
112 | } | 101 | |
113 | } | 102 | /* Just to prevent from allocating much pages. */ |
103 | hw->period_bytes_max = hw->period_bytes_min * 2048; | ||
104 | hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; | ||
105 | } | ||
106 | |||
107 | static int init_hw_info(struct snd_dice *dice, | ||
108 | struct snd_pcm_substream *substream) | ||
109 | { | ||
110 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
111 | struct snd_pcm_hardware *hw = &runtime->hw; | ||
112 | int err; | ||
113 | |||
114 | hw->info = SNDRV_PCM_INFO_MMAP | | ||
115 | SNDRV_PCM_INFO_MMAP_VALID | | ||
116 | SNDRV_PCM_INFO_BATCH | | ||
117 | SNDRV_PCM_INFO_INTERLEAVED | | ||
118 | SNDRV_PCM_INFO_BLOCK_TRANSFER; | ||
119 | hw->formats = AMDTP_OUT_PCM_FORMAT_BITS; | ||
120 | |||
121 | limit_channels_and_rates(dice, runtime, dice->rx_channels); | ||
122 | limit_period_and_buffer(hw); | ||
114 | 123 | ||
115 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 124 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
116 | dice_rate_constraint, dice, | 125 | dice_rate_constraint, dice, |
117 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | 126 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); |
118 | if (err < 0) | 127 | if (err < 0) |
119 | goto err_lock; | 128 | goto end; |
120 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 129 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
121 | dice_channels_constraint, dice, | 130 | dice_channels_constraint, dice, |
122 | SNDRV_PCM_HW_PARAM_RATE, -1); | 131 | SNDRV_PCM_HW_PARAM_RATE, -1); |
123 | if (err < 0) | 132 | if (err < 0) |
124 | goto err_lock; | 133 | goto end; |
125 | 134 | ||
126 | err = amdtp_stream_add_pcm_hw_constraints(&dice->rx_stream, runtime); | 135 | err = amdtp_stream_add_pcm_hw_constraints(&dice->rx_stream, runtime); |
127 | if (err < 0) | 136 | end: |
128 | goto err_lock; | 137 | return err; |
138 | } | ||
129 | 139 | ||
130 | return 0; | 140 | static int pcm_open(struct snd_pcm_substream *substream) |
141 | { | ||
142 | struct snd_dice *dice = substream->private_data; | ||
143 | int err; | ||
131 | 144 | ||
132 | err_lock: | 145 | err = snd_dice_stream_lock_try(dice); |
146 | if (err < 0) | ||
147 | goto end; | ||
148 | |||
149 | err = init_hw_info(dice, substream); | ||
150 | if (err < 0) | ||
151 | goto err_locked; | ||
152 | end: | ||
153 | return err; | ||
154 | err_locked: | ||
133 | snd_dice_stream_lock_release(dice); | 155 | snd_dice_stream_lock_release(dice); |
134 | error: | ||
135 | return err; | 156 | return err; |
136 | } | 157 | } |
137 | 158 | ||