1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * fireworks_stream.c - a part of driver for Fireworks based devices 4 * 5 * Copyright (c) 2013-2014 Takashi Sakamoto 6 */ 7 #include "./fireworks.h" 8 9 #define READY_TIMEOUT_MS 1000 10 11 static int init_stream(struct snd_efw *efw, struct amdtp_stream *stream) 12 { 13 struct cmp_connection *conn; 14 enum cmp_direction c_dir; 15 enum amdtp_stream_direction s_dir; 16 int err; 17 18 if (stream == &efw->tx_stream) { 19 conn = &efw->out_conn; 20 c_dir = CMP_OUTPUT; 21 s_dir = AMDTP_IN_STREAM; 22 } else { 23 conn = &efw->in_conn; 24 c_dir = CMP_INPUT; 25 s_dir = AMDTP_OUT_STREAM; 26 } 27 28 err = cmp_connection_init(conn, efw->unit, c_dir, 0); 29 if (err < 0) 30 return err; 31 32 err = amdtp_am824_init(stream, efw->unit, s_dir, CIP_BLOCKING | CIP_UNAWARE_SYT); 33 if (err < 0) { 34 amdtp_stream_destroy(stream); 35 cmp_connection_destroy(conn); 36 return err; 37 } 38 39 if (stream == &efw->tx_stream) { 40 // Fireworks transmits NODATA packets with TAG0. 41 efw->tx_stream.flags |= CIP_EMPTY_WITH_TAG0; 42 // Fireworks has its own meaning for dbc. 43 efw->tx_stream.flags |= CIP_DBC_IS_END_EVENT; 44 // Fireworks reset dbc at bus reset. 45 efw->tx_stream.flags |= CIP_SKIP_DBC_ZERO_CHECK; 46 // But Recent firmwares starts packets with non-zero dbc. 47 // Driver version 5.7.6 installs firmware version 5.7.3. 48 if (efw->is_fireworks3 && 49 (efw->firmware_version == 0x5070000 || 50 efw->firmware_version == 0x5070300 || 51 efw->firmware_version == 0x5080000)) 52 efw->tx_stream.flags |= CIP_UNALIGHED_DBC; 53 // AudioFire9 always reports wrong dbs. 54 if (efw->is_af9) 55 efw->tx_stream.flags |= CIP_WRONG_DBS; 56 // Firmware version 5.5 reports fixed interval for dbc. 57 if (efw->firmware_version == 0x5050000) 58 efw->tx_stream.ctx_data.tx.dbc_interval = 8; 59 } 60 61 return err; 62 } 63 64 static int start_stream(struct snd_efw *efw, struct amdtp_stream *stream, 65 unsigned int rate) 66 { 67 struct cmp_connection *conn; 68 int err; 69 70 if (stream == &efw->tx_stream) 71 conn = &efw->out_conn; 72 else 73 conn = &efw->in_conn; 74 75 // Establish connection via CMP. 76 err = cmp_connection_establish(conn); 77 if (err < 0) 78 return err; 79 80 // Start amdtp stream. 81 err = amdtp_domain_add_stream(&efw->domain, stream, 82 conn->resources.channel, conn->speed); 83 if (err < 0) { 84 cmp_connection_break(conn); 85 return err; 86 } 87 88 return 0; 89 } 90 91 // This function should be called before starting the stream or after stopping 92 // the streams. 93 static void destroy_stream(struct snd_efw *efw, struct amdtp_stream *stream) 94 { 95 amdtp_stream_destroy(stream); 96 97 if (stream == &efw->tx_stream) 98 cmp_connection_destroy(&efw->out_conn); 99 else 100 cmp_connection_destroy(&efw->in_conn); 101 } 102 103 static int 104 check_connection_used_by_others(struct snd_efw *efw, struct amdtp_stream *s) 105 { 106 struct cmp_connection *conn; 107 bool used; 108 int err; 109 110 if (s == &efw->tx_stream) 111 conn = &efw->out_conn; 112 else 113 conn = &efw->in_conn; 114 115 err = cmp_connection_check_used(conn, &used); 116 if ((err >= 0) && used && !amdtp_stream_running(s)) { 117 dev_err(&efw->unit->device, 118 "Connection established by others: %cPCR[%d]\n", 119 (conn->direction == CMP_OUTPUT) ? 'o' : 'i', 120 conn->pcr_index); 121 err = -EBUSY; 122 } 123 124 return err; 125 } 126 127 int snd_efw_stream_init_duplex(struct snd_efw *efw) 128 { 129 int err; 130 131 err = init_stream(efw, &efw->tx_stream); 132 if (err < 0) 133 return err; 134 135 err = init_stream(efw, &efw->rx_stream); 136 if (err < 0) { 137 destroy_stream(efw, &efw->tx_stream); 138 return err; 139 } 140 141 err = amdtp_domain_init(&efw->domain); 142 if (err < 0) { 143 destroy_stream(efw, &efw->tx_stream); 144 destroy_stream(efw, &efw->rx_stream); 145 return err; 146 } 147 148 // set IEC61883 compliant mode (actually not fully compliant...). 149 err = snd_efw_command_set_tx_mode(efw, SND_EFW_TRANSPORT_MODE_IEC61883); 150 if (err < 0) { 151 destroy_stream(efw, &efw->tx_stream); 152 destroy_stream(efw, &efw->rx_stream); 153 } 154 155 return err; 156 } 157 158 static int keep_resources(struct snd_efw *efw, struct amdtp_stream *stream, 159 unsigned int rate, unsigned int mode) 160 { 161 unsigned int pcm_channels; 162 unsigned int midi_ports; 163 struct cmp_connection *conn; 164 int err; 165 166 if (stream == &efw->tx_stream) { 167 pcm_channels = efw->pcm_capture_channels[mode]; 168 midi_ports = efw->midi_out_ports; 169 conn = &efw->out_conn; 170 } else { 171 pcm_channels = efw->pcm_playback_channels[mode]; 172 midi_ports = efw->midi_in_ports; 173 conn = &efw->in_conn; 174 } 175 176 err = amdtp_am824_set_parameters(stream, rate, pcm_channels, 177 midi_ports, false); 178 if (err < 0) 179 return err; 180 181 return cmp_connection_reserve(conn, amdtp_stream_get_max_payload(stream)); 182 } 183 184 int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate, 185 unsigned int frames_per_period, 186 unsigned int frames_per_buffer) 187 { 188 unsigned int curr_rate; 189 int err; 190 191 // Considering JACK/FFADO streaming: 192 // TODO: This can be removed hwdep functionality becomes popular. 193 err = check_connection_used_by_others(efw, &efw->rx_stream); 194 if (err < 0) 195 return err; 196 197 // stop streams if rate is different. 198 err = snd_efw_command_get_sampling_rate(efw, &curr_rate); 199 if (err < 0) 200 return err; 201 if (rate == 0) 202 rate = curr_rate; 203 if (rate != curr_rate) { 204 amdtp_domain_stop(&efw->domain); 205 206 cmp_connection_break(&efw->out_conn); 207 cmp_connection_break(&efw->in_conn); 208 209 cmp_connection_release(&efw->out_conn); 210 cmp_connection_release(&efw->in_conn); 211 } 212 213 if (efw->substreams_counter == 0 || rate != curr_rate) { 214 unsigned int mode; 215 216 err = snd_efw_command_set_sampling_rate(efw, rate); 217 if (err < 0) 218 return err; 219 220 err = snd_efw_get_multiplier_mode(rate, &mode); 221 if (err < 0) 222 return err; 223 224 err = keep_resources(efw, &efw->tx_stream, rate, mode); 225 if (err < 0) 226 return err; 227 228 err = keep_resources(efw, &efw->rx_stream, rate, mode); 229 if (err < 0) { 230 cmp_connection_release(&efw->in_conn); 231 return err; 232 } 233 234 err = amdtp_domain_set_events_per_period(&efw->domain, 235 frames_per_period, frames_per_buffer); 236 if (err < 0) { 237 cmp_connection_release(&efw->in_conn); 238 cmp_connection_release(&efw->out_conn); 239 return err; 240 } 241 } 242 243 return 0; 244 } 245 246 int snd_efw_stream_start_duplex(struct snd_efw *efw) 247 { 248 unsigned int rate; 249 int err = 0; 250 251 // Need no substreams. 252 if (efw->substreams_counter == 0) 253 return -EIO; 254 255 if (amdtp_streaming_error(&efw->rx_stream) || 256 amdtp_streaming_error(&efw->tx_stream)) { 257 amdtp_domain_stop(&efw->domain); 258 cmp_connection_break(&efw->out_conn); 259 cmp_connection_break(&efw->in_conn); 260 } 261 262 err = snd_efw_command_get_sampling_rate(efw, &rate); 263 if (err < 0) 264 return err; 265 266 if (!amdtp_stream_running(&efw->rx_stream)) { 267 unsigned int tx_init_skip_cycles; 268 269 // Audiofire 2/4 skip an isochronous cycle several thousands after starting 270 // packet transmission. 271 if (efw->is_fireworks3 && !efw->is_af9) 272 tx_init_skip_cycles = 6000; 273 else 274 tx_init_skip_cycles = 0; 275 276 err = start_stream(efw, &efw->rx_stream, rate); 277 if (err < 0) 278 goto error; 279 280 err = start_stream(efw, &efw->tx_stream, rate); 281 if (err < 0) 282 goto error; 283 284 // NOTE: The device ignores presentation time expressed by the value of syt field 285 // of CIP header in received packets. The sequence of the number of data blocks per 286 // packet is important for media clock recovery. 287 err = amdtp_domain_start(&efw->domain, tx_init_skip_cycles, true, false); 288 if (err < 0) 289 goto error; 290 291 if (!amdtp_domain_wait_ready(&efw->domain, READY_TIMEOUT_MS)) { 292 err = -ETIMEDOUT; 293 goto error; 294 } 295 } 296 297 return 0; 298 error: 299 amdtp_domain_stop(&efw->domain); 300 301 cmp_connection_break(&efw->out_conn); 302 cmp_connection_break(&efw->in_conn); 303 304 return err; 305 } 306 307 void snd_efw_stream_stop_duplex(struct snd_efw *efw) 308 { 309 if (efw->substreams_counter == 0) { 310 amdtp_domain_stop(&efw->domain); 311 312 cmp_connection_break(&efw->out_conn); 313 cmp_connection_break(&efw->in_conn); 314 315 cmp_connection_release(&efw->out_conn); 316 cmp_connection_release(&efw->in_conn); 317 } 318 } 319 320 void snd_efw_stream_update_duplex(struct snd_efw *efw) 321 { 322 amdtp_domain_stop(&efw->domain); 323 324 cmp_connection_break(&efw->out_conn); 325 cmp_connection_break(&efw->in_conn); 326 327 amdtp_stream_pcm_abort(&efw->rx_stream); 328 amdtp_stream_pcm_abort(&efw->tx_stream); 329 } 330 331 void snd_efw_stream_destroy_duplex(struct snd_efw *efw) 332 { 333 amdtp_domain_destroy(&efw->domain); 334 335 destroy_stream(efw, &efw->rx_stream); 336 destroy_stream(efw, &efw->tx_stream); 337 } 338 339 void snd_efw_stream_lock_changed(struct snd_efw *efw) 340 { 341 efw->dev_lock_changed = true; 342 wake_up(&efw->hwdep_wait); 343 } 344 345 int snd_efw_stream_lock_try(struct snd_efw *efw) 346 { 347 int err; 348 349 spin_lock_irq(&efw->lock); 350 351 /* user land lock this */ 352 if (efw->dev_lock_count < 0) { 353 err = -EBUSY; 354 goto end; 355 } 356 357 /* this is the first time */ 358 if (efw->dev_lock_count++ == 0) 359 snd_efw_stream_lock_changed(efw); 360 err = 0; 361 end: 362 spin_unlock_irq(&efw->lock); 363 return err; 364 } 365 366 void snd_efw_stream_lock_release(struct snd_efw *efw) 367 { 368 spin_lock_irq(&efw->lock); 369 370 if (WARN_ON(efw->dev_lock_count <= 0)) 371 goto end; 372 if (--efw->dev_lock_count == 0) 373 snd_efw_stream_lock_changed(efw); 374 end: 375 spin_unlock_irq(&efw->lock); 376 } 377