Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * digi00x-stream.c - a part of driver for Digidesign Digi 002/003 family
0004  *
0005  * Copyright (c) 2014-2015 Takashi Sakamoto
0006  */
0007 
0008 #include "digi00x.h"
0009 
0010 #define READY_TIMEOUT_MS    200
0011 
0012 const unsigned int snd_dg00x_stream_rates[SND_DG00X_RATE_COUNT] = {
0013     [SND_DG00X_RATE_44100] = 44100,
0014     [SND_DG00X_RATE_48000] = 48000,
0015     [SND_DG00X_RATE_88200] = 88200,
0016     [SND_DG00X_RATE_96000] = 96000,
0017 };
0018 
0019 /* Multi Bit Linear Audio data channels for each sampling transfer frequency. */
0020 const unsigned int
0021 snd_dg00x_stream_pcm_channels[SND_DG00X_RATE_COUNT] = {
0022     /* Analog/ADAT/SPDIF */
0023     [SND_DG00X_RATE_44100] = (8 + 8 + 2),
0024     [SND_DG00X_RATE_48000] = (8 + 8 + 2),
0025     /* Analog/SPDIF */
0026     [SND_DG00X_RATE_88200] = (8 + 2),
0027     [SND_DG00X_RATE_96000] = (8 + 2),
0028 };
0029 
0030 int snd_dg00x_stream_get_local_rate(struct snd_dg00x *dg00x, unsigned int *rate)
0031 {
0032     u32 data;
0033     __be32 reg;
0034     int err;
0035 
0036     err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
0037                  DG00X_ADDR_BASE + DG00X_OFFSET_LOCAL_RATE,
0038                  &reg, sizeof(reg), 0);
0039     if (err < 0)
0040         return err;
0041 
0042     data = be32_to_cpu(reg) & 0x0f;
0043     if (data < ARRAY_SIZE(snd_dg00x_stream_rates))
0044         *rate = snd_dg00x_stream_rates[data];
0045     else
0046         err = -EIO;
0047 
0048     return err;
0049 }
0050 
0051 int snd_dg00x_stream_set_local_rate(struct snd_dg00x *dg00x, unsigned int rate)
0052 {
0053     __be32 reg;
0054     unsigned int i;
0055 
0056     for (i = 0; i < ARRAY_SIZE(snd_dg00x_stream_rates); i++) {
0057         if (rate == snd_dg00x_stream_rates[i])
0058             break;
0059     }
0060     if (i == ARRAY_SIZE(snd_dg00x_stream_rates))
0061         return -EINVAL;
0062 
0063     reg = cpu_to_be32(i);
0064     return snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
0065                   DG00X_ADDR_BASE + DG00X_OFFSET_LOCAL_RATE,
0066                   &reg, sizeof(reg), 0);
0067 }
0068 
0069 int snd_dg00x_stream_get_clock(struct snd_dg00x *dg00x,
0070                    enum snd_dg00x_clock *clock)
0071 {
0072     __be32 reg;
0073     int err;
0074 
0075     err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
0076                  DG00X_ADDR_BASE + DG00X_OFFSET_CLOCK_SOURCE,
0077                  &reg, sizeof(reg), 0);
0078     if (err < 0)
0079         return err;
0080 
0081     *clock = be32_to_cpu(reg) & 0x0f;
0082     if (*clock >= SND_DG00X_CLOCK_COUNT)
0083         err = -EIO;
0084 
0085     return err;
0086 }
0087 
0088 int snd_dg00x_stream_check_external_clock(struct snd_dg00x *dg00x, bool *detect)
0089 {
0090     __be32 reg;
0091     int err;
0092 
0093     err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
0094                  DG00X_ADDR_BASE + DG00X_OFFSET_DETECT_EXTERNAL,
0095                  &reg, sizeof(reg), 0);
0096     if (err >= 0)
0097         *detect = be32_to_cpu(reg) > 0;
0098 
0099     return err;
0100 }
0101 
0102 int snd_dg00x_stream_get_external_rate(struct snd_dg00x *dg00x,
0103                        unsigned int *rate)
0104 {
0105     u32 data;
0106     __be32 reg;
0107     int err;
0108 
0109     err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
0110                  DG00X_ADDR_BASE + DG00X_OFFSET_EXTERNAL_RATE,
0111                  &reg, sizeof(reg), 0);
0112     if (err < 0)
0113         return err;
0114 
0115     data = be32_to_cpu(reg) & 0x0f;
0116     if (data < ARRAY_SIZE(snd_dg00x_stream_rates))
0117         *rate = snd_dg00x_stream_rates[data];
0118     /* This means desync. */
0119     else
0120         err = -EBUSY;
0121 
0122     return err;
0123 }
0124 
0125 static void finish_session(struct snd_dg00x *dg00x)
0126 {
0127     __be32 data;
0128 
0129     data = cpu_to_be32(0x00000003);
0130     snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
0131                DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_SET,
0132                &data, sizeof(data), 0);
0133 
0134     // Unregister isochronous channels for both direction.
0135     data = 0;
0136     snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
0137                DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS,
0138                &data, sizeof(data), 0);
0139 
0140     // Just after finishing the session, the device may lost transmitting
0141     // functionality for a short time.
0142     msleep(50);
0143 }
0144 
0145 static int begin_session(struct snd_dg00x *dg00x)
0146 {
0147     __be32 data;
0148     u32 curr;
0149     int err;
0150 
0151     // Register isochronous channels for both direction.
0152     data = cpu_to_be32((dg00x->tx_resources.channel << 16) |
0153                dg00x->rx_resources.channel);
0154     err = snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST,
0155                  DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS,
0156                  &data, sizeof(data), 0);
0157     if (err < 0)
0158         return err;
0159 
0160     err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST,
0161                  DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_STATE,
0162                  &data, sizeof(data), 0);
0163     if (err < 0)
0164         return err;
0165     curr = be32_to_cpu(data);
0166 
0167     if (curr == 0)
0168         curr = 2;
0169 
0170     curr--;
0171     while (curr > 0) {
0172         data = cpu_to_be32(curr);
0173         err = snd_fw_transaction(dg00x->unit,
0174                      TCODE_WRITE_QUADLET_REQUEST,
0175                      DG00X_ADDR_BASE +
0176                      DG00X_OFFSET_STREAMING_SET,
0177                      &data, sizeof(data), 0);
0178         if (err < 0)
0179             break;
0180 
0181         msleep(20);
0182         curr--;
0183     }
0184 
0185     return err;
0186 }
0187 
0188 static int keep_resources(struct snd_dg00x *dg00x, struct amdtp_stream *stream,
0189               unsigned int rate)
0190 {
0191     struct fw_iso_resources *resources;
0192     int i;
0193     int err;
0194 
0195     // Check sampling rate.
0196     for (i = 0; i < SND_DG00X_RATE_COUNT; i++) {
0197         if (snd_dg00x_stream_rates[i] == rate)
0198             break;
0199     }
0200     if (i == SND_DG00X_RATE_COUNT)
0201         return -EINVAL;
0202 
0203     if (stream == &dg00x->tx_stream)
0204         resources = &dg00x->tx_resources;
0205     else
0206         resources = &dg00x->rx_resources;
0207 
0208     err = amdtp_dot_set_parameters(stream, rate,
0209                        snd_dg00x_stream_pcm_channels[i]);
0210     if (err < 0)
0211         return err;
0212 
0213     return fw_iso_resources_allocate(resources,
0214                 amdtp_stream_get_max_payload(stream),
0215                 fw_parent_device(dg00x->unit)->max_speed);
0216 }
0217 
0218 static int init_stream(struct snd_dg00x *dg00x, struct amdtp_stream *s)
0219 {
0220     struct fw_iso_resources *resources;
0221     enum amdtp_stream_direction dir;
0222     int err;
0223 
0224     if (s == &dg00x->tx_stream) {
0225         resources = &dg00x->tx_resources;
0226         dir = AMDTP_IN_STREAM;
0227     } else {
0228         resources = &dg00x->rx_resources;
0229         dir = AMDTP_OUT_STREAM;
0230     }
0231 
0232     err = fw_iso_resources_init(resources, dg00x->unit);
0233     if (err < 0)
0234         return err;
0235 
0236     err = amdtp_dot_init(s, dg00x->unit, dir);
0237     if (err < 0)
0238         fw_iso_resources_destroy(resources);
0239 
0240     return err;
0241 }
0242 
0243 static void destroy_stream(struct snd_dg00x *dg00x, struct amdtp_stream *s)
0244 {
0245     amdtp_stream_destroy(s);
0246 
0247     if (s == &dg00x->tx_stream)
0248         fw_iso_resources_destroy(&dg00x->tx_resources);
0249     else
0250         fw_iso_resources_destroy(&dg00x->rx_resources);
0251 }
0252 
0253 int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x)
0254 {
0255     int err;
0256 
0257     err = init_stream(dg00x, &dg00x->rx_stream);
0258     if (err < 0)
0259         return err;
0260 
0261     err = init_stream(dg00x, &dg00x->tx_stream);
0262     if (err < 0)
0263         destroy_stream(dg00x, &dg00x->rx_stream);
0264 
0265     err = amdtp_domain_init(&dg00x->domain);
0266     if (err < 0) {
0267         destroy_stream(dg00x, &dg00x->rx_stream);
0268         destroy_stream(dg00x, &dg00x->tx_stream);
0269     }
0270 
0271     return err;
0272 }
0273 
0274 /*
0275  * This function should be called before starting streams or after stopping
0276  * streams.
0277  */
0278 void snd_dg00x_stream_destroy_duplex(struct snd_dg00x *dg00x)
0279 {
0280     amdtp_domain_destroy(&dg00x->domain);
0281 
0282     destroy_stream(dg00x, &dg00x->rx_stream);
0283     destroy_stream(dg00x, &dg00x->tx_stream);
0284 }
0285 
0286 int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate,
0287                     unsigned int frames_per_period,
0288                     unsigned int frames_per_buffer)
0289 {
0290     unsigned int curr_rate;
0291     int err;
0292 
0293     err = snd_dg00x_stream_get_local_rate(dg00x, &curr_rate);
0294     if (err < 0)
0295         return err;
0296     if (rate == 0)
0297         rate = curr_rate;
0298 
0299     if (dg00x->substreams_counter == 0 || curr_rate != rate) {
0300         amdtp_domain_stop(&dg00x->domain);
0301 
0302         finish_session(dg00x);
0303 
0304         fw_iso_resources_free(&dg00x->tx_resources);
0305         fw_iso_resources_free(&dg00x->rx_resources);
0306 
0307         err = snd_dg00x_stream_set_local_rate(dg00x, rate);
0308         if (err < 0)
0309             return err;
0310 
0311         err = keep_resources(dg00x, &dg00x->rx_stream, rate);
0312         if (err < 0)
0313             return err;
0314 
0315         err = keep_resources(dg00x, &dg00x->tx_stream, rate);
0316         if (err < 0) {
0317             fw_iso_resources_free(&dg00x->rx_resources);
0318             return err;
0319         }
0320 
0321         err = amdtp_domain_set_events_per_period(&dg00x->domain,
0322                     frames_per_period, frames_per_buffer);
0323         if (err < 0) {
0324             fw_iso_resources_free(&dg00x->rx_resources);
0325             fw_iso_resources_free(&dg00x->tx_resources);
0326             return err;
0327         }
0328     }
0329 
0330     return 0;
0331 }
0332 
0333 int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x)
0334 {
0335     unsigned int generation = dg00x->rx_resources.generation;
0336     int err = 0;
0337 
0338     if (dg00x->substreams_counter == 0)
0339         return 0;
0340 
0341     if (amdtp_streaming_error(&dg00x->tx_stream) ||
0342         amdtp_streaming_error(&dg00x->rx_stream)) {
0343         amdtp_domain_stop(&dg00x->domain);
0344         finish_session(dg00x);
0345     }
0346 
0347     if (generation != fw_parent_device(dg00x->unit)->card->generation) {
0348         err = fw_iso_resources_update(&dg00x->tx_resources);
0349         if (err < 0)
0350             goto error;
0351 
0352         err = fw_iso_resources_update(&dg00x->rx_resources);
0353         if (err < 0)
0354             goto error;
0355     }
0356 
0357     /*
0358      * No packets are transmitted without receiving packets, reagardless of
0359      * which source of clock is used.
0360      */
0361     if (!amdtp_stream_running(&dg00x->rx_stream)) {
0362         int spd = fw_parent_device(dg00x->unit)->max_speed;
0363 
0364         err = begin_session(dg00x);
0365         if (err < 0)
0366             goto error;
0367 
0368         err = amdtp_domain_add_stream(&dg00x->domain, &dg00x->rx_stream,
0369                           dg00x->rx_resources.channel, spd);
0370         if (err < 0)
0371             goto error;
0372 
0373         err = amdtp_domain_add_stream(&dg00x->domain, &dg00x->tx_stream,
0374                           dg00x->tx_resources.channel, spd);
0375         if (err < 0)
0376             goto error;
0377 
0378         // NOTE: The device doesn't start packet transmission till receiving any packet.
0379         // It ignores presentation time expressed by the value of syt field of CIP header
0380         // in received packets. The sequence of the number of data blocks per packet is
0381         // important for media clock recovery.
0382         err = amdtp_domain_start(&dg00x->domain, 0, true, true);
0383         if (err < 0)
0384             goto error;
0385 
0386         if (!amdtp_domain_wait_ready(&dg00x->domain, READY_TIMEOUT_MS)) {
0387             err = -ETIMEDOUT;
0388             goto error;
0389         }
0390     }
0391 
0392     return 0;
0393 error:
0394     amdtp_domain_stop(&dg00x->domain);
0395     finish_session(dg00x);
0396 
0397     return err;
0398 }
0399 
0400 void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x)
0401 {
0402     if (dg00x->substreams_counter == 0) {
0403         amdtp_domain_stop(&dg00x->domain);
0404         finish_session(dg00x);
0405 
0406         fw_iso_resources_free(&dg00x->tx_resources);
0407         fw_iso_resources_free(&dg00x->rx_resources);
0408     }
0409 }
0410 
0411 void snd_dg00x_stream_update_duplex(struct snd_dg00x *dg00x)
0412 {
0413     fw_iso_resources_update(&dg00x->tx_resources);
0414     fw_iso_resources_update(&dg00x->rx_resources);
0415 
0416     amdtp_stream_update(&dg00x->tx_stream);
0417     amdtp_stream_update(&dg00x->rx_stream);
0418 }
0419 
0420 void snd_dg00x_stream_lock_changed(struct snd_dg00x *dg00x)
0421 {
0422     dg00x->dev_lock_changed = true;
0423     wake_up(&dg00x->hwdep_wait);
0424 }
0425 
0426 int snd_dg00x_stream_lock_try(struct snd_dg00x *dg00x)
0427 {
0428     int err;
0429 
0430     spin_lock_irq(&dg00x->lock);
0431 
0432     /* user land lock this */
0433     if (dg00x->dev_lock_count < 0) {
0434         err = -EBUSY;
0435         goto end;
0436     }
0437 
0438     /* this is the first time */
0439     if (dg00x->dev_lock_count++ == 0)
0440         snd_dg00x_stream_lock_changed(dg00x);
0441     err = 0;
0442 end:
0443     spin_unlock_irq(&dg00x->lock);
0444     return err;
0445 }
0446 
0447 void snd_dg00x_stream_lock_release(struct snd_dg00x *dg00x)
0448 {
0449     spin_lock_irq(&dg00x->lock);
0450 
0451     if (WARN_ON(dg00x->dev_lock_count <= 0))
0452         goto end;
0453     if (--dg00x->dev_lock_count == 0)
0454         snd_dg00x_stream_lock_changed(dg00x);
0455 end:
0456     spin_unlock_irq(&dg00x->lock);
0457 }