0001
0002
0003
0004
0005
0006
0007
0008 #include "ff.h"
0009
0010 static int hw_rule_rate(struct snd_pcm_hw_params *params,
0011 struct snd_pcm_hw_rule *rule)
0012 {
0013 const unsigned int *pcm_channels = rule->private;
0014 struct snd_interval *r =
0015 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
0016 const struct snd_interval *c =
0017 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
0018 struct snd_interval t = {
0019 .min = UINT_MAX, .max = 0, .integer = 1
0020 };
0021 unsigned int i;
0022
0023 for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); i++) {
0024 enum snd_ff_stream_mode mode;
0025 int err;
0026
0027 err = snd_ff_stream_get_multiplier_mode(i, &mode);
0028 if (err < 0)
0029 continue;
0030
0031 if (!snd_interval_test(c, pcm_channels[mode]))
0032 continue;
0033
0034 t.min = min(t.min, amdtp_rate_table[i]);
0035 t.max = max(t.max, amdtp_rate_table[i]);
0036 }
0037
0038 return snd_interval_refine(r, &t);
0039 }
0040
0041 static int hw_rule_channels(struct snd_pcm_hw_params *params,
0042 struct snd_pcm_hw_rule *rule)
0043 {
0044 const unsigned int *pcm_channels = rule->private;
0045 struct snd_interval *c =
0046 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
0047 const struct snd_interval *r =
0048 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
0049 struct snd_interval t = {
0050 .min = UINT_MAX, .max = 0, .integer = 1
0051 };
0052 unsigned int i;
0053
0054 for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); i++) {
0055 enum snd_ff_stream_mode mode;
0056 int err;
0057
0058 err = snd_ff_stream_get_multiplier_mode(i, &mode);
0059 if (err < 0)
0060 continue;
0061
0062 if (!snd_interval_test(r, amdtp_rate_table[i]))
0063 continue;
0064
0065 t.min = min(t.min, pcm_channels[mode]);
0066 t.max = max(t.max, pcm_channels[mode]);
0067 }
0068
0069 return snd_interval_refine(c, &t);
0070 }
0071
0072 static void limit_channels_and_rates(struct snd_pcm_hardware *hw,
0073 const unsigned int *pcm_channels)
0074 {
0075 unsigned int rate, channels;
0076 int i;
0077
0078 hw->channels_min = UINT_MAX;
0079 hw->channels_max = 0;
0080 hw->rate_min = UINT_MAX;
0081 hw->rate_max = 0;
0082
0083 for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); i++) {
0084 enum snd_ff_stream_mode mode;
0085 int err;
0086
0087 err = snd_ff_stream_get_multiplier_mode(i, &mode);
0088 if (err < 0)
0089 continue;
0090
0091 channels = pcm_channels[mode];
0092 if (pcm_channels[mode] == 0)
0093 continue;
0094 hw->channels_min = min(hw->channels_min, channels);
0095 hw->channels_max = max(hw->channels_max, channels);
0096
0097 rate = amdtp_rate_table[i];
0098 hw->rates |= snd_pcm_rate_to_rate_bit(rate);
0099 hw->rate_min = min(hw->rate_min, rate);
0100 hw->rate_max = max(hw->rate_max, rate);
0101 }
0102 }
0103
0104 static int pcm_init_hw_params(struct snd_ff *ff,
0105 struct snd_pcm_substream *substream)
0106 {
0107 struct snd_pcm_runtime *runtime = substream->runtime;
0108 struct amdtp_stream *s;
0109 const unsigned int *pcm_channels;
0110 int err;
0111
0112 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
0113 runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
0114 s = &ff->tx_stream;
0115 pcm_channels = ff->spec->pcm_capture_channels;
0116 } else {
0117 runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
0118 s = &ff->rx_stream;
0119 pcm_channels = ff->spec->pcm_playback_channels;
0120 }
0121
0122 limit_channels_and_rates(&runtime->hw, pcm_channels);
0123
0124 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
0125 hw_rule_channels, (void *)pcm_channels,
0126 SNDRV_PCM_HW_PARAM_RATE, -1);
0127 if (err < 0)
0128 return err;
0129
0130 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
0131 hw_rule_rate, (void *)pcm_channels,
0132 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
0133 if (err < 0)
0134 return err;
0135
0136 return amdtp_ff_add_pcm_hw_constraints(s, runtime);
0137 }
0138
0139 static int pcm_open(struct snd_pcm_substream *substream)
0140 {
0141 struct snd_ff *ff = substream->private_data;
0142 struct amdtp_domain *d = &ff->domain;
0143 unsigned int rate;
0144 enum snd_ff_clock_src src;
0145 int i, err;
0146
0147 err = snd_ff_stream_lock_try(ff);
0148 if (err < 0)
0149 return err;
0150
0151 err = pcm_init_hw_params(ff, substream);
0152 if (err < 0)
0153 goto release_lock;
0154
0155 err = ff->spec->protocol->get_clock(ff, &rate, &src);
0156 if (err < 0)
0157 goto release_lock;
0158
0159 mutex_lock(&ff->mutex);
0160
0161
0162
0163
0164 if (src != SND_FF_CLOCK_SRC_INTERNAL) {
0165 for (i = 0; i < CIP_SFC_COUNT; ++i) {
0166 if (amdtp_rate_table[i] == rate)
0167 break;
0168 }
0169
0170
0171
0172 if (i >= CIP_SFC_COUNT) {
0173 mutex_unlock(&ff->mutex);
0174 err = -EIO;
0175 goto release_lock;
0176 }
0177
0178 substream->runtime->hw.rate_min = rate;
0179 substream->runtime->hw.rate_max = rate;
0180 } else {
0181 if (ff->substreams_counter > 0) {
0182 unsigned int frames_per_period = d->events_per_period;
0183 unsigned int frames_per_buffer = d->events_per_buffer;
0184
0185 rate = amdtp_rate_table[ff->rx_stream.sfc];
0186 substream->runtime->hw.rate_min = rate;
0187 substream->runtime->hw.rate_max = rate;
0188
0189 err = snd_pcm_hw_constraint_minmax(substream->runtime,
0190 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
0191 frames_per_period, frames_per_period);
0192 if (err < 0) {
0193 mutex_unlock(&ff->mutex);
0194 goto release_lock;
0195 }
0196
0197 err = snd_pcm_hw_constraint_minmax(substream->runtime,
0198 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
0199 frames_per_buffer, frames_per_buffer);
0200 if (err < 0) {
0201 mutex_unlock(&ff->mutex);
0202 goto release_lock;
0203 }
0204 }
0205 }
0206
0207 mutex_unlock(&ff->mutex);
0208
0209 snd_pcm_set_sync(substream);
0210
0211 return 0;
0212
0213 release_lock:
0214 snd_ff_stream_lock_release(ff);
0215 return err;
0216 }
0217
0218 static int pcm_close(struct snd_pcm_substream *substream)
0219 {
0220 struct snd_ff *ff = substream->private_data;
0221
0222 snd_ff_stream_lock_release(ff);
0223
0224 return 0;
0225 }
0226
0227 static int pcm_hw_params(struct snd_pcm_substream *substream,
0228 struct snd_pcm_hw_params *hw_params)
0229 {
0230 struct snd_ff *ff = substream->private_data;
0231 int err = 0;
0232
0233 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
0234 unsigned int rate = params_rate(hw_params);
0235 unsigned int frames_per_period = params_period_size(hw_params);
0236 unsigned int frames_per_buffer = params_buffer_size(hw_params);
0237
0238 mutex_lock(&ff->mutex);
0239 err = snd_ff_stream_reserve_duplex(ff, rate, frames_per_period,
0240 frames_per_buffer);
0241 if (err >= 0)
0242 ++ff->substreams_counter;
0243 mutex_unlock(&ff->mutex);
0244 }
0245
0246 return err;
0247 }
0248
0249 static int pcm_hw_free(struct snd_pcm_substream *substream)
0250 {
0251 struct snd_ff *ff = substream->private_data;
0252
0253 mutex_lock(&ff->mutex);
0254
0255 if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
0256 --ff->substreams_counter;
0257
0258 snd_ff_stream_stop_duplex(ff);
0259
0260 mutex_unlock(&ff->mutex);
0261
0262 return 0;
0263 }
0264
0265 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
0266 {
0267 struct snd_ff *ff = substream->private_data;
0268 struct snd_pcm_runtime *runtime = substream->runtime;
0269 int err;
0270
0271 mutex_lock(&ff->mutex);
0272
0273 err = snd_ff_stream_start_duplex(ff, runtime->rate);
0274 if (err >= 0)
0275 amdtp_stream_pcm_prepare(&ff->tx_stream);
0276
0277 mutex_unlock(&ff->mutex);
0278
0279 return err;
0280 }
0281
0282 static int pcm_playback_prepare(struct snd_pcm_substream *substream)
0283 {
0284 struct snd_ff *ff = substream->private_data;
0285 struct snd_pcm_runtime *runtime = substream->runtime;
0286 int err;
0287
0288 mutex_lock(&ff->mutex);
0289
0290 err = snd_ff_stream_start_duplex(ff, runtime->rate);
0291 if (err >= 0)
0292 amdtp_stream_pcm_prepare(&ff->rx_stream);
0293
0294 mutex_unlock(&ff->mutex);
0295
0296 return err;
0297 }
0298
0299 static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
0300 {
0301 struct snd_ff *ff = substream->private_data;
0302
0303 switch (cmd) {
0304 case SNDRV_PCM_TRIGGER_START:
0305 amdtp_stream_pcm_trigger(&ff->tx_stream, substream);
0306 break;
0307 case SNDRV_PCM_TRIGGER_STOP:
0308 amdtp_stream_pcm_trigger(&ff->tx_stream, NULL);
0309 break;
0310 default:
0311 return -EINVAL;
0312 }
0313
0314 return 0;
0315 }
0316
0317 static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
0318 {
0319 struct snd_ff *ff = substream->private_data;
0320
0321 switch (cmd) {
0322 case SNDRV_PCM_TRIGGER_START:
0323 amdtp_stream_pcm_trigger(&ff->rx_stream, substream);
0324 break;
0325 case SNDRV_PCM_TRIGGER_STOP:
0326 amdtp_stream_pcm_trigger(&ff->rx_stream, NULL);
0327 break;
0328 default:
0329 return -EINVAL;
0330 }
0331
0332 return 0;
0333 }
0334
0335 static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm)
0336 {
0337 struct snd_ff *ff = sbstrm->private_data;
0338
0339 return amdtp_domain_stream_pcm_pointer(&ff->domain, &ff->tx_stream);
0340 }
0341
0342 static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
0343 {
0344 struct snd_ff *ff = sbstrm->private_data;
0345
0346 return amdtp_domain_stream_pcm_pointer(&ff->domain, &ff->rx_stream);
0347 }
0348
0349 static int pcm_capture_ack(struct snd_pcm_substream *substream)
0350 {
0351 struct snd_ff *ff = substream->private_data;
0352
0353 return amdtp_domain_stream_pcm_ack(&ff->domain, &ff->tx_stream);
0354 }
0355
0356 static int pcm_playback_ack(struct snd_pcm_substream *substream)
0357 {
0358 struct snd_ff *ff = substream->private_data;
0359
0360 return amdtp_domain_stream_pcm_ack(&ff->domain, &ff->rx_stream);
0361 }
0362
0363 int snd_ff_create_pcm_devices(struct snd_ff *ff)
0364 {
0365 static const struct snd_pcm_ops pcm_capture_ops = {
0366 .open = pcm_open,
0367 .close = pcm_close,
0368 .hw_params = pcm_hw_params,
0369 .hw_free = pcm_hw_free,
0370 .prepare = pcm_capture_prepare,
0371 .trigger = pcm_capture_trigger,
0372 .pointer = pcm_capture_pointer,
0373 .ack = pcm_capture_ack,
0374 };
0375 static const struct snd_pcm_ops pcm_playback_ops = {
0376 .open = pcm_open,
0377 .close = pcm_close,
0378 .hw_params = pcm_hw_params,
0379 .hw_free = pcm_hw_free,
0380 .prepare = pcm_playback_prepare,
0381 .trigger = pcm_playback_trigger,
0382 .pointer = pcm_playback_pointer,
0383 .ack = pcm_playback_ack,
0384 };
0385 struct snd_pcm *pcm;
0386 int err;
0387
0388 err = snd_pcm_new(ff->card, ff->card->driver, 0, 1, 1, &pcm);
0389 if (err < 0)
0390 return err;
0391
0392 pcm->private_data = ff;
0393 snprintf(pcm->name, sizeof(pcm->name),
0394 "%s PCM", ff->card->shortname);
0395 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops);
0396 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops);
0397 snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
0398
0399 return 0;
0400 }