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