1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * digi00x-stream.c - a part of driver for Digidesign Digi 002/003 family 4 * 5 * Copyright (c) 2014-2015 Takashi Sakamoto 6 */ 7 8 #include "digi00x.h" 9 10 #define CALLBACK_TIMEOUT 500 11 12 const unsigned int snd_dg00x_stream_rates[SND_DG00X_RATE_COUNT] = { 13 [SND_DG00X_RATE_44100] = 44100, 14 [SND_DG00X_RATE_48000] = 48000, 15 [SND_DG00X_RATE_88200] = 88200, 16 [SND_DG00X_RATE_96000] = 96000, 17 }; 18 19 /* Multi Bit Linear Audio data channels for each sampling transfer frequency. */ 20 const unsigned int 21 snd_dg00x_stream_pcm_channels[SND_DG00X_RATE_COUNT] = { 22 /* Analog/ADAT/SPDIF */ 23 [SND_DG00X_RATE_44100] = (8 + 8 + 2), 24 [SND_DG00X_RATE_48000] = (8 + 8 + 2), 25 /* Analog/SPDIF */ 26 [SND_DG00X_RATE_88200] = (8 + 2), 27 [SND_DG00X_RATE_96000] = (8 + 2), 28 }; 29 30 int snd_dg00x_stream_get_local_rate(struct snd_dg00x *dg00x, unsigned int *rate) 31 { 32 u32 data; 33 __be32 reg; 34 int err; 35 36 err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST, 37 DG00X_ADDR_BASE + DG00X_OFFSET_LOCAL_RATE, 38 ®, sizeof(reg), 0); 39 if (err < 0) 40 return err; 41 42 data = be32_to_cpu(reg) & 0x0f; 43 if (data < ARRAY_SIZE(snd_dg00x_stream_rates)) 44 *rate = snd_dg00x_stream_rates[data]; 45 else 46 err = -EIO; 47 48 return err; 49 } 50 51 int snd_dg00x_stream_set_local_rate(struct snd_dg00x *dg00x, unsigned int rate) 52 { 53 __be32 reg; 54 unsigned int i; 55 56 for (i = 0; i < ARRAY_SIZE(snd_dg00x_stream_rates); i++) { 57 if (rate == snd_dg00x_stream_rates[i]) 58 break; 59 } 60 if (i == ARRAY_SIZE(snd_dg00x_stream_rates)) 61 return -EINVAL; 62 63 reg = cpu_to_be32(i); 64 return snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST, 65 DG00X_ADDR_BASE + DG00X_OFFSET_LOCAL_RATE, 66 ®, sizeof(reg), 0); 67 } 68 69 int snd_dg00x_stream_get_clock(struct snd_dg00x *dg00x, 70 enum snd_dg00x_clock *clock) 71 { 72 __be32 reg; 73 int err; 74 75 err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST, 76 DG00X_ADDR_BASE + DG00X_OFFSET_CLOCK_SOURCE, 77 ®, sizeof(reg), 0); 78 if (err < 0) 79 return err; 80 81 *clock = be32_to_cpu(reg) & 0x0f; 82 if (*clock >= SND_DG00X_CLOCK_COUNT) 83 err = -EIO; 84 85 return err; 86 } 87 88 int snd_dg00x_stream_check_external_clock(struct snd_dg00x *dg00x, bool *detect) 89 { 90 __be32 reg; 91 int err; 92 93 err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST, 94 DG00X_ADDR_BASE + DG00X_OFFSET_DETECT_EXTERNAL, 95 ®, sizeof(reg), 0); 96 if (err >= 0) 97 *detect = be32_to_cpu(reg) > 0; 98 99 return err; 100 } 101 102 int snd_dg00x_stream_get_external_rate(struct snd_dg00x *dg00x, 103 unsigned int *rate) 104 { 105 u32 data; 106 __be32 reg; 107 int err; 108 109 err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST, 110 DG00X_ADDR_BASE + DG00X_OFFSET_EXTERNAL_RATE, 111 ®, sizeof(reg), 0); 112 if (err < 0) 113 return err; 114 115 data = be32_to_cpu(reg) & 0x0f; 116 if (data < ARRAY_SIZE(snd_dg00x_stream_rates)) 117 *rate = snd_dg00x_stream_rates[data]; 118 /* This means desync. */ 119 else 120 err = -EBUSY; 121 122 return err; 123 } 124 125 static void finish_session(struct snd_dg00x *dg00x) 126 { 127 __be32 data = cpu_to_be32(0x00000003); 128 129 snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST, 130 DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_SET, 131 &data, sizeof(data), 0); 132 } 133 134 static int begin_session(struct snd_dg00x *dg00x) 135 { 136 __be32 data; 137 u32 curr; 138 int err; 139 140 err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST, 141 DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_STATE, 142 &data, sizeof(data), 0); 143 if (err < 0) 144 goto error; 145 curr = be32_to_cpu(data); 146 147 if (curr == 0) 148 curr = 2; 149 150 curr--; 151 while (curr > 0) { 152 data = cpu_to_be32(curr); 153 err = snd_fw_transaction(dg00x->unit, 154 TCODE_WRITE_QUADLET_REQUEST, 155 DG00X_ADDR_BASE + 156 DG00X_OFFSET_STREAMING_SET, 157 &data, sizeof(data), 0); 158 if (err < 0) 159 goto error; 160 161 msleep(20); 162 curr--; 163 } 164 165 return 0; 166 error: 167 finish_session(dg00x); 168 return err; 169 } 170 171 static void release_resources(struct snd_dg00x *dg00x) 172 { 173 __be32 data = 0; 174 175 /* Unregister isochronous channels for both direction. */ 176 snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST, 177 DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS, 178 &data, sizeof(data), 0); 179 180 /* Release isochronous resources. */ 181 fw_iso_resources_free(&dg00x->tx_resources); 182 fw_iso_resources_free(&dg00x->rx_resources); 183 } 184 185 static int keep_resources(struct snd_dg00x *dg00x, unsigned int rate) 186 { 187 unsigned int i; 188 __be32 data; 189 int err; 190 191 /* Check sampling rate. */ 192 for (i = 0; i < SND_DG00X_RATE_COUNT; i++) { 193 if (snd_dg00x_stream_rates[i] == rate) 194 break; 195 } 196 if (i == SND_DG00X_RATE_COUNT) 197 return -EINVAL; 198 199 /* Keep resources for out-stream. */ 200 err = amdtp_dot_set_parameters(&dg00x->rx_stream, rate, 201 snd_dg00x_stream_pcm_channels[i]); 202 if (err < 0) 203 return err; 204 err = fw_iso_resources_allocate(&dg00x->rx_resources, 205 amdtp_stream_get_max_payload(&dg00x->rx_stream), 206 fw_parent_device(dg00x->unit)->max_speed); 207 if (err < 0) 208 return err; 209 210 /* Keep resources for in-stream. */ 211 err = amdtp_dot_set_parameters(&dg00x->tx_stream, rate, 212 snd_dg00x_stream_pcm_channels[i]); 213 if (err < 0) 214 return err; 215 err = fw_iso_resources_allocate(&dg00x->tx_resources, 216 amdtp_stream_get_max_payload(&dg00x->tx_stream), 217 fw_parent_device(dg00x->unit)->max_speed); 218 if (err < 0) 219 goto error; 220 221 /* Register isochronous channels for both direction. */ 222 data = cpu_to_be32((dg00x->tx_resources.channel << 16) | 223 dg00x->rx_resources.channel); 224 err = snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST, 225 DG00X_ADDR_BASE + DG00X_OFFSET_ISOC_CHANNELS, 226 &data, sizeof(data), 0); 227 if (err < 0) 228 goto error; 229 230 return 0; 231 error: 232 release_resources(dg00x); 233 return err; 234 } 235 236 int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x) 237 { 238 int err; 239 240 /* For out-stream. */ 241 err = fw_iso_resources_init(&dg00x->rx_resources, dg00x->unit); 242 if (err < 0) 243 goto error; 244 err = amdtp_dot_init(&dg00x->rx_stream, dg00x->unit, AMDTP_OUT_STREAM); 245 if (err < 0) 246 goto error; 247 248 /* For in-stream. */ 249 err = fw_iso_resources_init(&dg00x->tx_resources, dg00x->unit); 250 if (err < 0) 251 goto error; 252 err = amdtp_dot_init(&dg00x->tx_stream, dg00x->unit, AMDTP_IN_STREAM); 253 if (err < 0) 254 goto error; 255 256 return 0; 257 error: 258 snd_dg00x_stream_destroy_duplex(dg00x); 259 return err; 260 } 261 262 /* 263 * This function should be called before starting streams or after stopping 264 * streams. 265 */ 266 void snd_dg00x_stream_destroy_duplex(struct snd_dg00x *dg00x) 267 { 268 amdtp_stream_destroy(&dg00x->rx_stream); 269 fw_iso_resources_destroy(&dg00x->rx_resources); 270 271 amdtp_stream_destroy(&dg00x->tx_stream); 272 fw_iso_resources_destroy(&dg00x->tx_resources); 273 } 274 275 int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x, unsigned int rate) 276 { 277 unsigned int curr_rate; 278 int err = 0; 279 280 if (dg00x->substreams_counter == 0) 281 goto end; 282 283 /* Check current sampling rate. */ 284 err = snd_dg00x_stream_get_local_rate(dg00x, &curr_rate); 285 if (err < 0) 286 goto error; 287 if (rate == 0) 288 rate = curr_rate; 289 if (curr_rate != rate || 290 amdtp_streaming_error(&dg00x->tx_stream) || 291 amdtp_streaming_error(&dg00x->rx_stream)) { 292 finish_session(dg00x); 293 294 amdtp_stream_stop(&dg00x->tx_stream); 295 amdtp_stream_stop(&dg00x->rx_stream); 296 release_resources(dg00x); 297 } 298 299 /* 300 * No packets are transmitted without receiving packets, reagardless of 301 * which source of clock is used. 302 */ 303 if (!amdtp_stream_running(&dg00x->rx_stream)) { 304 err = snd_dg00x_stream_set_local_rate(dg00x, rate); 305 if (err < 0) 306 goto error; 307 308 err = keep_resources(dg00x, rate); 309 if (err < 0) 310 goto error; 311 312 err = begin_session(dg00x); 313 if (err < 0) 314 goto error; 315 316 err = amdtp_stream_start(&dg00x->rx_stream, 317 dg00x->rx_resources.channel, 318 fw_parent_device(dg00x->unit)->max_speed); 319 if (err < 0) 320 goto error; 321 322 if (!amdtp_stream_wait_callback(&dg00x->rx_stream, 323 CALLBACK_TIMEOUT)) { 324 err = -ETIMEDOUT; 325 goto error; 326 } 327 } 328 329 /* 330 * The value of SYT field in transmitted packets is always 0x0000. Thus, 331 * duplex streams with timestamp synchronization cannot be built. 332 */ 333 if (!amdtp_stream_running(&dg00x->tx_stream)) { 334 err = amdtp_stream_start(&dg00x->tx_stream, 335 dg00x->tx_resources.channel, 336 fw_parent_device(dg00x->unit)->max_speed); 337 if (err < 0) 338 goto error; 339 340 if (!amdtp_stream_wait_callback(&dg00x->tx_stream, 341 CALLBACK_TIMEOUT)) { 342 err = -ETIMEDOUT; 343 goto error; 344 } 345 } 346 end: 347 return err; 348 error: 349 finish_session(dg00x); 350 351 amdtp_stream_stop(&dg00x->tx_stream); 352 amdtp_stream_stop(&dg00x->rx_stream); 353 release_resources(dg00x); 354 355 return err; 356 } 357 358 void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x) 359 { 360 if (dg00x->substreams_counter > 0) 361 return; 362 363 amdtp_stream_stop(&dg00x->tx_stream); 364 amdtp_stream_stop(&dg00x->rx_stream); 365 finish_session(dg00x); 366 release_resources(dg00x); 367 368 /* 369 * Just after finishing the session, the device may lost transmitting 370 * functionality for a short time. 371 */ 372 msleep(50); 373 } 374 375 void snd_dg00x_stream_update_duplex(struct snd_dg00x *dg00x) 376 { 377 fw_iso_resources_update(&dg00x->tx_resources); 378 fw_iso_resources_update(&dg00x->rx_resources); 379 380 amdtp_stream_update(&dg00x->tx_stream); 381 amdtp_stream_update(&dg00x->rx_stream); 382 } 383 384 void snd_dg00x_stream_lock_changed(struct snd_dg00x *dg00x) 385 { 386 dg00x->dev_lock_changed = true; 387 wake_up(&dg00x->hwdep_wait); 388 } 389 390 int snd_dg00x_stream_lock_try(struct snd_dg00x *dg00x) 391 { 392 int err; 393 394 spin_lock_irq(&dg00x->lock); 395 396 /* user land lock this */ 397 if (dg00x->dev_lock_count < 0) { 398 err = -EBUSY; 399 goto end; 400 } 401 402 /* this is the first time */ 403 if (dg00x->dev_lock_count++ == 0) 404 snd_dg00x_stream_lock_changed(dg00x); 405 err = 0; 406 end: 407 spin_unlock_irq(&dg00x->lock); 408 return err; 409 } 410 411 void snd_dg00x_stream_lock_release(struct snd_dg00x *dg00x) 412 { 413 spin_lock_irq(&dg00x->lock); 414 415 if (WARN_ON(dg00x->dev_lock_count <= 0)) 416 goto end; 417 if (--dg00x->dev_lock_count == 0) 418 snd_dg00x_stream_lock_changed(dg00x); 419 end: 420 spin_unlock_irq(&dg00x->lock); 421 } 422