1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * ff-stream.c - a part of driver for RME Fireface series 4 * 5 * Copyright (c) 2015-2017 Takashi Sakamoto 6 */ 7 8 #include "ff.h" 9 10 #define CALLBACK_TIMEOUT_MS 200 11 12 int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc, 13 enum snd_ff_stream_mode *mode) 14 { 15 static const enum snd_ff_stream_mode modes[] = { 16 [CIP_SFC_32000] = SND_FF_STREAM_MODE_LOW, 17 [CIP_SFC_44100] = SND_FF_STREAM_MODE_LOW, 18 [CIP_SFC_48000] = SND_FF_STREAM_MODE_LOW, 19 [CIP_SFC_88200] = SND_FF_STREAM_MODE_MID, 20 [CIP_SFC_96000] = SND_FF_STREAM_MODE_MID, 21 [CIP_SFC_176400] = SND_FF_STREAM_MODE_HIGH, 22 [CIP_SFC_192000] = SND_FF_STREAM_MODE_HIGH, 23 }; 24 25 if (sfc >= CIP_SFC_COUNT) 26 return -EINVAL; 27 28 *mode = modes[sfc]; 29 30 return 0; 31 } 32 33 static void release_resources(struct snd_ff *ff) 34 { 35 fw_iso_resources_free(&ff->tx_resources); 36 fw_iso_resources_free(&ff->rx_resources); 37 } 38 39 static inline void finish_session(struct snd_ff *ff) 40 { 41 ff->spec->protocol->finish_session(ff); 42 ff->spec->protocol->switch_fetching_mode(ff, false); 43 } 44 45 static int init_stream(struct snd_ff *ff, enum amdtp_stream_direction dir) 46 { 47 int err; 48 struct fw_iso_resources *resources; 49 struct amdtp_stream *stream; 50 51 if (dir == AMDTP_IN_STREAM) { 52 resources = &ff->tx_resources; 53 stream = &ff->tx_stream; 54 } else { 55 resources = &ff->rx_resources; 56 stream = &ff->rx_stream; 57 } 58 59 err = fw_iso_resources_init(resources, ff->unit); 60 if (err < 0) 61 return err; 62 63 err = amdtp_ff_init(stream, ff->unit, dir); 64 if (err < 0) 65 fw_iso_resources_destroy(resources); 66 67 return err; 68 } 69 70 static void destroy_stream(struct snd_ff *ff, enum amdtp_stream_direction dir) 71 { 72 if (dir == AMDTP_IN_STREAM) { 73 amdtp_stream_destroy(&ff->tx_stream); 74 fw_iso_resources_destroy(&ff->tx_resources); 75 } else { 76 amdtp_stream_destroy(&ff->rx_stream); 77 fw_iso_resources_destroy(&ff->rx_resources); 78 } 79 } 80 81 int snd_ff_stream_init_duplex(struct snd_ff *ff) 82 { 83 int err; 84 85 err = init_stream(ff, AMDTP_OUT_STREAM); 86 if (err < 0) 87 goto end; 88 89 err = init_stream(ff, AMDTP_IN_STREAM); 90 if (err < 0) 91 destroy_stream(ff, AMDTP_OUT_STREAM); 92 end: 93 return err; 94 } 95 96 /* 97 * This function should be called before starting streams or after stopping 98 * streams. 99 */ 100 void snd_ff_stream_destroy_duplex(struct snd_ff *ff) 101 { 102 destroy_stream(ff, AMDTP_IN_STREAM); 103 destroy_stream(ff, AMDTP_OUT_STREAM); 104 } 105 106 int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate) 107 { 108 unsigned int curr_rate; 109 enum snd_ff_clock_src src; 110 int err; 111 112 if (ff->substreams_counter == 0) 113 return 0; 114 115 err = ff->spec->protocol->get_clock(ff, &curr_rate, &src); 116 if (err < 0) 117 return err; 118 if (curr_rate != rate || 119 amdtp_streaming_error(&ff->tx_stream) || 120 amdtp_streaming_error(&ff->rx_stream)) { 121 finish_session(ff); 122 123 amdtp_stream_stop(&ff->tx_stream); 124 amdtp_stream_stop(&ff->rx_stream); 125 126 release_resources(ff); 127 } 128 129 /* 130 * Regardless of current source of clock signal, drivers transfer some 131 * packets. Then, the device transfers packets. 132 */ 133 if (!amdtp_stream_running(&ff->rx_stream)) { 134 enum snd_ff_stream_mode mode; 135 int i; 136 137 for (i = 0; i < CIP_SFC_COUNT; ++i) { 138 if (amdtp_rate_table[i] == rate) 139 break; 140 } 141 if (i >= CIP_SFC_COUNT) 142 return -EINVAL; 143 144 err = snd_ff_stream_get_multiplier_mode(i, &mode); 145 if (err < 0) 146 return err; 147 148 err = amdtp_ff_set_parameters(&ff->tx_stream, rate, 149 ff->spec->pcm_capture_channels[mode]); 150 if (err < 0) 151 return err; 152 153 err = amdtp_ff_set_parameters(&ff->rx_stream, rate, 154 ff->spec->pcm_playback_channels[mode]); 155 if (err < 0) 156 return err; 157 158 err = ff->spec->protocol->begin_session(ff, rate); 159 if (err < 0) 160 goto error; 161 162 err = amdtp_stream_start(&ff->rx_stream, 163 ff->rx_resources.channel, 164 fw_parent_device(ff->unit)->max_speed); 165 if (err < 0) 166 goto error; 167 168 if (!amdtp_stream_wait_callback(&ff->rx_stream, 169 CALLBACK_TIMEOUT_MS)) { 170 err = -ETIMEDOUT; 171 goto error; 172 } 173 174 err = ff->spec->protocol->switch_fetching_mode(ff, true); 175 if (err < 0) 176 goto error; 177 } 178 179 if (!amdtp_stream_running(&ff->tx_stream)) { 180 err = amdtp_stream_start(&ff->tx_stream, 181 ff->tx_resources.channel, 182 fw_parent_device(ff->unit)->max_speed); 183 if (err < 0) 184 goto error; 185 186 if (!amdtp_stream_wait_callback(&ff->tx_stream, 187 CALLBACK_TIMEOUT_MS)) { 188 err = -ETIMEDOUT; 189 goto error; 190 } 191 } 192 193 return 0; 194 error: 195 amdtp_stream_stop(&ff->tx_stream); 196 amdtp_stream_stop(&ff->rx_stream); 197 198 finish_session(ff); 199 release_resources(ff); 200 201 return err; 202 } 203 204 void snd_ff_stream_stop_duplex(struct snd_ff *ff) 205 { 206 if (ff->substreams_counter > 0) 207 return; 208 209 amdtp_stream_stop(&ff->tx_stream); 210 amdtp_stream_stop(&ff->rx_stream); 211 finish_session(ff); 212 release_resources(ff); 213 } 214 215 void snd_ff_stream_update_duplex(struct snd_ff *ff) 216 { 217 /* The device discontinue to transfer packets. */ 218 amdtp_stream_pcm_abort(&ff->tx_stream); 219 amdtp_stream_stop(&ff->tx_stream); 220 221 amdtp_stream_pcm_abort(&ff->rx_stream); 222 amdtp_stream_stop(&ff->rx_stream); 223 224 fw_iso_resources_update(&ff->tx_resources); 225 fw_iso_resources_update(&ff->rx_resources); 226 } 227 228 void snd_ff_stream_lock_changed(struct snd_ff *ff) 229 { 230 ff->dev_lock_changed = true; 231 wake_up(&ff->hwdep_wait); 232 } 233 234 int snd_ff_stream_lock_try(struct snd_ff *ff) 235 { 236 int err; 237 238 spin_lock_irq(&ff->lock); 239 240 /* user land lock this */ 241 if (ff->dev_lock_count < 0) { 242 err = -EBUSY; 243 goto end; 244 } 245 246 /* this is the first time */ 247 if (ff->dev_lock_count++ == 0) 248 snd_ff_stream_lock_changed(ff); 249 err = 0; 250 end: 251 spin_unlock_irq(&ff->lock); 252 return err; 253 } 254 255 void snd_ff_stream_lock_release(struct snd_ff *ff) 256 { 257 spin_lock_irq(&ff->lock); 258 259 if (WARN_ON(ff->dev_lock_count <= 0)) 260 goto end; 261 if (--ff->dev_lock_count == 0) 262 snd_ff_stream_lock_changed(ff); 263 end: 264 spin_unlock_irq(&ff->lock); 265 } 266