Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * oxfw_pcm.c - a part of driver for OXFW970/971 based devices
0004  *
0005  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
0006  */
0007 
0008 #include "oxfw.h"
0009 
0010 static int hw_rule_rate(struct snd_pcm_hw_params *params,
0011             struct snd_pcm_hw_rule *rule)
0012 {
0013     u8 **formats = 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     struct snd_oxfw_stream_formation formation;
0022     int i, err;
0023 
0024     for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
0025         if (formats[i] == NULL)
0026             continue;
0027 
0028         err = snd_oxfw_stream_parse_format(formats[i], &formation);
0029         if (err < 0)
0030             continue;
0031         if (!snd_interval_test(c, formation.pcm))
0032             continue;
0033 
0034         t.min = min(t.min, formation.rate);
0035         t.max = max(t.max, formation.rate);
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     u8 **formats = 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_oxfw_stream_formation formation;
0050     int i, j, err;
0051     unsigned int count, list[SND_OXFW_STREAM_FORMAT_ENTRIES] = {0};
0052 
0053     count = 0;
0054     for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
0055         if (formats[i] == NULL)
0056             break;
0057 
0058         err = snd_oxfw_stream_parse_format(formats[i], &formation);
0059         if (err < 0)
0060             continue;
0061         if (!snd_interval_test(r, formation.rate))
0062             continue;
0063         if (list[count] == formation.pcm)
0064             continue;
0065 
0066         for (j = 0; j < ARRAY_SIZE(list); j++) {
0067             if (list[j] == formation.pcm)
0068                 break;
0069         }
0070         if (j == ARRAY_SIZE(list)) {
0071             list[count] = formation.pcm;
0072             if (++count == ARRAY_SIZE(list))
0073                 break;
0074         }
0075     }
0076 
0077     return snd_interval_list(c, count, list, 0);
0078 }
0079 
0080 static void limit_channels_and_rates(struct snd_pcm_hardware *hw, u8 **formats)
0081 {
0082     struct snd_oxfw_stream_formation formation;
0083     int i, err;
0084 
0085     hw->channels_min = UINT_MAX;
0086     hw->channels_max = 0;
0087 
0088     hw->rate_min = UINT_MAX;
0089     hw->rate_max = 0;
0090     hw->rates = 0;
0091 
0092     for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
0093         if (formats[i] == NULL)
0094             break;
0095 
0096         err = snd_oxfw_stream_parse_format(formats[i], &formation);
0097         if (err < 0)
0098             continue;
0099 
0100         hw->channels_min = min(hw->channels_min, formation.pcm);
0101         hw->channels_max = max(hw->channels_max, formation.pcm);
0102 
0103         hw->rate_min = min(hw->rate_min, formation.rate);
0104         hw->rate_max = max(hw->rate_max, formation.rate);
0105         hw->rates |= snd_pcm_rate_to_rate_bit(formation.rate);
0106     }
0107 }
0108 
0109 static int init_hw_params(struct snd_oxfw *oxfw,
0110               struct snd_pcm_substream *substream)
0111 {
0112     struct snd_pcm_runtime *runtime = substream->runtime;
0113     u8 **formats;
0114     struct amdtp_stream *stream;
0115     int err;
0116 
0117     if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
0118         runtime->hw.formats = AM824_IN_PCM_FORMAT_BITS;
0119         stream = &oxfw->tx_stream;
0120         formats = oxfw->tx_stream_formats;
0121     } else {
0122         runtime->hw.formats = AM824_OUT_PCM_FORMAT_BITS;
0123         stream = &oxfw->rx_stream;
0124         formats = oxfw->rx_stream_formats;
0125     }
0126 
0127     limit_channels_and_rates(&runtime->hw, formats);
0128 
0129     err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
0130                   hw_rule_channels, formats,
0131                   SNDRV_PCM_HW_PARAM_RATE, -1);
0132     if (err < 0)
0133         goto end;
0134 
0135     err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
0136                   hw_rule_rate, formats,
0137                   SNDRV_PCM_HW_PARAM_CHANNELS, -1);
0138     if (err < 0)
0139         goto end;
0140 
0141     err = amdtp_am824_add_pcm_hw_constraints(stream, runtime);
0142 end:
0143     return err;
0144 }
0145 
0146 static int limit_to_current_params(struct snd_pcm_substream *substream)
0147 {
0148     struct snd_oxfw *oxfw = substream->private_data;
0149     struct snd_oxfw_stream_formation formation;
0150     enum avc_general_plug_dir dir;
0151     int err;
0152 
0153     if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
0154         dir = AVC_GENERAL_PLUG_DIR_OUT;
0155     else
0156         dir = AVC_GENERAL_PLUG_DIR_IN;
0157 
0158     err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation);
0159     if (err < 0)
0160         goto end;
0161 
0162     substream->runtime->hw.channels_min = formation.pcm;
0163     substream->runtime->hw.channels_max = formation.pcm;
0164     substream->runtime->hw.rate_min = formation.rate;
0165     substream->runtime->hw.rate_max = formation.rate;
0166 end:
0167     return err;
0168 }
0169 
0170 static int pcm_open(struct snd_pcm_substream *substream)
0171 {
0172     struct snd_oxfw *oxfw = substream->private_data;
0173     struct amdtp_domain *d = &oxfw->domain;
0174     int err;
0175 
0176     err = snd_oxfw_stream_lock_try(oxfw);
0177     if (err < 0)
0178         return err;
0179 
0180     err = init_hw_params(oxfw, substream);
0181     if (err < 0)
0182         goto err_locked;
0183 
0184     mutex_lock(&oxfw->mutex);
0185 
0186     // When source of clock is not internal or any stream is reserved for
0187     // transmission of PCM frames, the available sampling rate is limited
0188     // at current one.
0189     if (oxfw->substreams_count > 0 && d->events_per_period > 0) {
0190         unsigned int frames_per_period = d->events_per_period;
0191         unsigned int frames_per_buffer = d->events_per_buffer;
0192 
0193         err = limit_to_current_params(substream);
0194         if (err < 0) {
0195             mutex_unlock(&oxfw->mutex);
0196             goto err_locked;
0197         }
0198 
0199         if (frames_per_period > 0) {
0200             err = snd_pcm_hw_constraint_minmax(substream->runtime,
0201                     SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
0202                     frames_per_period, frames_per_period);
0203             if (err < 0) {
0204                 mutex_unlock(&oxfw->mutex);
0205                 goto err_locked;
0206             }
0207 
0208             err = snd_pcm_hw_constraint_minmax(substream->runtime,
0209                     SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
0210                     frames_per_buffer, frames_per_buffer);
0211             if (err < 0) {
0212                 mutex_unlock(&oxfw->mutex);
0213                 goto err_locked;
0214             }
0215         }
0216     }
0217 
0218     mutex_unlock(&oxfw->mutex);
0219 
0220     snd_pcm_set_sync(substream);
0221 
0222     return 0;
0223 err_locked:
0224     snd_oxfw_stream_lock_release(oxfw);
0225     return err;
0226 }
0227 
0228 static int pcm_close(struct snd_pcm_substream *substream)
0229 {
0230     struct snd_oxfw *oxfw = substream->private_data;
0231 
0232     snd_oxfw_stream_lock_release(oxfw);
0233     return 0;
0234 }
0235 
0236 static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
0237                  struct snd_pcm_hw_params *hw_params)
0238 {
0239     struct snd_oxfw *oxfw = substream->private_data;
0240     int err = 0;
0241 
0242     if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
0243         unsigned int rate = params_rate(hw_params);
0244         unsigned int channels = params_channels(hw_params);
0245         unsigned int frames_per_period = params_period_size(hw_params);
0246         unsigned int frames_per_buffer = params_buffer_size(hw_params);
0247 
0248         mutex_lock(&oxfw->mutex);
0249         err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream,
0250                     rate, channels, frames_per_period,
0251                     frames_per_buffer);
0252         if (err >= 0)
0253             ++oxfw->substreams_count;
0254         mutex_unlock(&oxfw->mutex);
0255     }
0256 
0257     return err;
0258 }
0259 static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
0260                   struct snd_pcm_hw_params *hw_params)
0261 {
0262     struct snd_oxfw *oxfw = substream->private_data;
0263     int err = 0;
0264 
0265     if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
0266         unsigned int rate = params_rate(hw_params);
0267         unsigned int channels = params_channels(hw_params);
0268         unsigned int frames_per_period = params_period_size(hw_params);
0269         unsigned int frames_per_buffer = params_buffer_size(hw_params);
0270 
0271         mutex_lock(&oxfw->mutex);
0272         err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->rx_stream,
0273                     rate, channels, frames_per_period,
0274                     frames_per_buffer);
0275         if (err >= 0)
0276             ++oxfw->substreams_count;
0277         mutex_unlock(&oxfw->mutex);
0278     }
0279 
0280     return err;
0281 }
0282 
0283 static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
0284 {
0285     struct snd_oxfw *oxfw = substream->private_data;
0286 
0287     mutex_lock(&oxfw->mutex);
0288 
0289     if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
0290         --oxfw->substreams_count;
0291 
0292     snd_oxfw_stream_stop_duplex(oxfw);
0293 
0294     mutex_unlock(&oxfw->mutex);
0295 
0296     return 0;
0297 }
0298 static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
0299 {
0300     struct snd_oxfw *oxfw = substream->private_data;
0301 
0302     mutex_lock(&oxfw->mutex);
0303 
0304     if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
0305         --oxfw->substreams_count;
0306 
0307     snd_oxfw_stream_stop_duplex(oxfw);
0308 
0309     mutex_unlock(&oxfw->mutex);
0310 
0311     return 0;
0312 }
0313 
0314 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
0315 {
0316     struct snd_oxfw *oxfw = substream->private_data;
0317     int err;
0318 
0319     mutex_lock(&oxfw->mutex);
0320     err = snd_oxfw_stream_start_duplex(oxfw);
0321     mutex_unlock(&oxfw->mutex);
0322     if (err < 0)
0323         goto end;
0324 
0325     amdtp_stream_pcm_prepare(&oxfw->tx_stream);
0326 end:
0327     return err;
0328 }
0329 static int pcm_playback_prepare(struct snd_pcm_substream *substream)
0330 {
0331     struct snd_oxfw *oxfw = substream->private_data;
0332     int err;
0333 
0334     mutex_lock(&oxfw->mutex);
0335     err = snd_oxfw_stream_start_duplex(oxfw);
0336     mutex_unlock(&oxfw->mutex);
0337     if (err < 0)
0338         goto end;
0339 
0340     amdtp_stream_pcm_prepare(&oxfw->rx_stream);
0341 end:
0342     return err;
0343 }
0344 
0345 static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
0346 {
0347     struct snd_oxfw *oxfw = substream->private_data;
0348     struct snd_pcm_substream *pcm;
0349 
0350     switch (cmd) {
0351     case SNDRV_PCM_TRIGGER_START:
0352         pcm = substream;
0353         break;
0354     case SNDRV_PCM_TRIGGER_STOP:
0355         pcm = NULL;
0356         break;
0357     default:
0358         return -EINVAL;
0359     }
0360     amdtp_stream_pcm_trigger(&oxfw->tx_stream, pcm);
0361     return 0;
0362 }
0363 static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
0364 {
0365     struct snd_oxfw *oxfw = substream->private_data;
0366     struct snd_pcm_substream *pcm;
0367 
0368     switch (cmd) {
0369     case SNDRV_PCM_TRIGGER_START:
0370         pcm = substream;
0371         break;
0372     case SNDRV_PCM_TRIGGER_STOP:
0373         pcm = NULL;
0374         break;
0375     default:
0376         return -EINVAL;
0377     }
0378     amdtp_stream_pcm_trigger(&oxfw->rx_stream, pcm);
0379     return 0;
0380 }
0381 
0382 static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstm)
0383 {
0384     struct snd_oxfw *oxfw = sbstm->private_data;
0385 
0386     return amdtp_domain_stream_pcm_pointer(&oxfw->domain, &oxfw->tx_stream);
0387 }
0388 static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstm)
0389 {
0390     struct snd_oxfw *oxfw = sbstm->private_data;
0391 
0392     return amdtp_domain_stream_pcm_pointer(&oxfw->domain, &oxfw->rx_stream);
0393 }
0394 
0395 static int pcm_capture_ack(struct snd_pcm_substream *substream)
0396 {
0397     struct snd_oxfw *oxfw = substream->private_data;
0398 
0399     return amdtp_domain_stream_pcm_ack(&oxfw->domain, &oxfw->tx_stream);
0400 }
0401 
0402 static int pcm_playback_ack(struct snd_pcm_substream *substream)
0403 {
0404     struct snd_oxfw *oxfw = substream->private_data;
0405 
0406     return amdtp_domain_stream_pcm_ack(&oxfw->domain, &oxfw->rx_stream);
0407 }
0408 
0409 int snd_oxfw_create_pcm(struct snd_oxfw *oxfw)
0410 {
0411     static const struct snd_pcm_ops capture_ops = {
0412         .open      = pcm_open,
0413         .close     = pcm_close,
0414         .hw_params = pcm_capture_hw_params,
0415         .hw_free   = pcm_capture_hw_free,
0416         .prepare   = pcm_capture_prepare,
0417         .trigger   = pcm_capture_trigger,
0418         .pointer   = pcm_capture_pointer,
0419         .ack       = pcm_capture_ack,
0420     };
0421     static const struct snd_pcm_ops playback_ops = {
0422         .open      = pcm_open,
0423         .close     = pcm_close,
0424         .hw_params = pcm_playback_hw_params,
0425         .hw_free   = pcm_playback_hw_free,
0426         .prepare   = pcm_playback_prepare,
0427         .trigger   = pcm_playback_trigger,
0428         .pointer   = pcm_playback_pointer,
0429         .ack       = pcm_playback_ack,
0430     };
0431     struct snd_pcm *pcm;
0432     unsigned int cap = 0;
0433     int err;
0434 
0435     if (oxfw->has_output)
0436         cap = 1;
0437 
0438     err = snd_pcm_new(oxfw->card, oxfw->card->driver, 0, 1, cap, &pcm);
0439     if (err < 0)
0440         return err;
0441 
0442     pcm->private_data = oxfw;
0443     strcpy(pcm->name, oxfw->card->shortname);
0444     snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
0445     if (cap > 0)
0446         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
0447     snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
0448 
0449     return 0;
0450 }