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 /* 104 * This function should be called before starting the stream or after stopping 105 * the streams. 106 */ 107 static void 108 destroy_stream(struct snd_efw *efw, struct amdtp_stream *stream) 109 { 110 struct cmp_connection *conn; 111 112 if (stream == &efw->tx_stream) 113 conn = &efw->out_conn; 114 else 115 conn = &efw->in_conn; 116 117 amdtp_stream_destroy(stream); 118 cmp_connection_destroy(&efw->out_conn); 119 } 120 121 static int 122 get_sync_mode(struct snd_efw *efw, enum cip_flags *sync_mode) 123 { 124 enum snd_efw_clock_source clock_source; 125 int err; 126 127 err = snd_efw_command_get_clock_source(efw, &clock_source); 128 if (err < 0) 129 return err; 130 131 if (clock_source == SND_EFW_CLOCK_SOURCE_SYTMATCH) 132 return -ENOSYS; 133 134 *sync_mode = CIP_SYNC_TO_DEVICE; 135 return 0; 136 } 137 138 static int 139 check_connection_used_by_others(struct snd_efw *efw, struct amdtp_stream *s) 140 { 141 struct cmp_connection *conn; 142 bool used; 143 int err; 144 145 if (s == &efw->tx_stream) 146 conn = &efw->out_conn; 147 else 148 conn = &efw->in_conn; 149 150 err = cmp_connection_check_used(conn, &used); 151 if ((err >= 0) && used && !amdtp_stream_running(s)) { 152 dev_err(&efw->unit->device, 153 "Connection established by others: %cPCR[%d]\n", 154 (conn->direction == CMP_OUTPUT) ? 'o' : 'i', 155 conn->pcr_index); 156 err = -EBUSY; 157 } 158 159 return err; 160 } 161 162 int snd_efw_stream_init_duplex(struct snd_efw *efw) 163 { 164 int err; 165 166 err = init_stream(efw, &efw->tx_stream); 167 if (err < 0) 168 goto end; 169 /* Fireworks transmits NODATA packets with TAG0. */ 170 efw->tx_stream.flags |= CIP_EMPTY_WITH_TAG0; 171 /* Fireworks has its own meaning for dbc. */ 172 efw->tx_stream.flags |= CIP_DBC_IS_END_EVENT; 173 /* Fireworks reset dbc at bus reset. */ 174 efw->tx_stream.flags |= CIP_SKIP_DBC_ZERO_CHECK; 175 /* 176 * But Recent firmwares starts packets with non-zero dbc. 177 * Driver version 5.7.6 installs firmware version 5.7.3. 178 */ 179 if (efw->is_fireworks3 && 180 (efw->firmware_version == 0x5070000 || 181 efw->firmware_version == 0x5070300 || 182 efw->firmware_version == 0x5080000)) 183 efw->tx_stream.tx_first_dbc = 0x02; 184 /* AudioFire9 always reports wrong dbs. */ 185 if (efw->is_af9) 186 efw->tx_stream.flags |= CIP_WRONG_DBS; 187 /* Firmware version 5.5 reports fixed interval for dbc. */ 188 if (efw->firmware_version == 0x5050000) 189 efw->tx_stream.tx_dbc_interval = 8; 190 191 err = init_stream(efw, &efw->rx_stream); 192 if (err < 0) { 193 destroy_stream(efw, &efw->tx_stream); 194 goto end; 195 } 196 197 /* set IEC61883 compliant mode (actually not fully compliant...) */ 198 err = snd_efw_command_set_tx_mode(efw, SND_EFW_TRANSPORT_MODE_IEC61883); 199 if (err < 0) { 200 destroy_stream(efw, &efw->tx_stream); 201 destroy_stream(efw, &efw->rx_stream); 202 } 203 end: 204 return err; 205 } 206 207 int snd_efw_stream_start_duplex(struct snd_efw *efw, unsigned int rate) 208 { 209 struct amdtp_stream *master, *slave; 210 atomic_t *slave_substreams; 211 enum cip_flags sync_mode; 212 unsigned int curr_rate; 213 int err = 0; 214 215 mutex_lock(&efw->mutex); 216 217 /* Need no substreams */ 218 if ((atomic_read(&efw->playback_substreams) == 0) && 219 (atomic_read(&efw->capture_substreams) == 0)) 220 goto end; 221 222 err = get_sync_mode(efw, &sync_mode); 223 if (err < 0) 224 goto end; 225 if (sync_mode == CIP_SYNC_TO_DEVICE) { 226 master = &efw->tx_stream; 227 slave = &efw->rx_stream; 228 slave_substreams = &efw->playback_substreams; 229 } else { 230 master = &efw->rx_stream; 231 slave = &efw->tx_stream; 232 slave_substreams = &efw->capture_substreams; 233 } 234 235 /* 236 * Considering JACK/FFADO streaming: 237 * TODO: This can be removed hwdep functionality becomes popular. 238 */ 239 err = check_connection_used_by_others(efw, master); 240 if (err < 0) 241 goto end; 242 243 /* packet queueing error */ 244 if (amdtp_streaming_error(slave)) 245 stop_stream(efw, slave); 246 if (amdtp_streaming_error(master)) 247 stop_stream(efw, master); 248 249 /* stop streams if rate is different */ 250 err = snd_efw_command_get_sampling_rate(efw, &curr_rate); 251 if (err < 0) 252 goto end; 253 if (rate == 0) 254 rate = curr_rate; 255 if (rate != curr_rate) { 256 stop_stream(efw, slave); 257 stop_stream(efw, master); 258 } 259 260 /* master should be always running */ 261 if (!amdtp_stream_running(master)) { 262 amdtp_stream_set_sync(sync_mode, master, slave); 263 efw->master = master; 264 265 err = snd_efw_command_set_sampling_rate(efw, rate); 266 if (err < 0) 267 goto end; 268 269 err = start_stream(efw, master, rate); 270 if (err < 0) { 271 dev_err(&efw->unit->device, 272 "fail to start AMDTP master stream:%d\n", err); 273 goto end; 274 } 275 } 276 277 /* start slave if needed */ 278 if (atomic_read(slave_substreams) > 0 && !amdtp_stream_running(slave)) { 279 err = start_stream(efw, slave, rate); 280 if (err < 0) { 281 dev_err(&efw->unit->device, 282 "fail to start AMDTP slave stream:%d\n", err); 283 stop_stream(efw, master); 284 } 285 } 286 end: 287 mutex_unlock(&efw->mutex); 288 return err; 289 } 290 291 void snd_efw_stream_stop_duplex(struct snd_efw *efw) 292 { 293 struct amdtp_stream *master, *slave; 294 atomic_t *master_substreams, *slave_substreams; 295 296 if (efw->master == &efw->rx_stream) { 297 slave = &efw->tx_stream; 298 master = &efw->rx_stream; 299 slave_substreams = &efw->capture_substreams; 300 master_substreams = &efw->playback_substreams; 301 } else { 302 slave = &efw->rx_stream; 303 master = &efw->tx_stream; 304 slave_substreams = &efw->playback_substreams; 305 master_substreams = &efw->capture_substreams; 306 } 307 308 mutex_lock(&efw->mutex); 309 310 if (atomic_read(slave_substreams) == 0) { 311 stop_stream(efw, slave); 312 313 if (atomic_read(master_substreams) == 0) 314 stop_stream(efw, master); 315 } 316 317 mutex_unlock(&efw->mutex); 318 } 319 320 void snd_efw_stream_update_duplex(struct snd_efw *efw) 321 { 322 if ((cmp_connection_update(&efw->out_conn) < 0) || 323 (cmp_connection_update(&efw->in_conn) < 0)) { 324 mutex_lock(&efw->mutex); 325 stop_stream(efw, &efw->rx_stream); 326 stop_stream(efw, &efw->tx_stream); 327 mutex_unlock(&efw->mutex); 328 } else { 329 amdtp_stream_update(&efw->rx_stream); 330 amdtp_stream_update(&efw->tx_stream); 331 } 332 } 333 334 void snd_efw_stream_destroy_duplex(struct snd_efw *efw) 335 { 336 destroy_stream(efw, &efw->rx_stream); 337 destroy_stream(efw, &efw->tx_stream); 338 } 339 340 void snd_efw_stream_lock_changed(struct snd_efw *efw) 341 { 342 efw->dev_lock_changed = true; 343 wake_up(&efw->hwdep_wait); 344 } 345 346 int snd_efw_stream_lock_try(struct snd_efw *efw) 347 { 348 int err; 349 350 spin_lock_irq(&efw->lock); 351 352 /* user land lock this */ 353 if (efw->dev_lock_count < 0) { 354 err = -EBUSY; 355 goto end; 356 } 357 358 /* this is the first time */ 359 if (efw->dev_lock_count++ == 0) 360 snd_efw_stream_lock_changed(efw); 361 err = 0; 362 end: 363 spin_unlock_irq(&efw->lock); 364 return err; 365 } 366 367 void snd_efw_stream_lock_release(struct snd_efw *efw) 368 { 369 spin_lock_irq(&efw->lock); 370 371 if (WARN_ON(efw->dev_lock_count <= 0)) 372 goto end; 373 if (--efw->dev_lock_count == 0) 374 snd_efw_stream_lock_changed(efw); 375 end: 376 spin_unlock_irq(&efw->lock); 377 } 378