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