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