diff options
Diffstat (limited to 'sound/firewire/tascam')
-rw-r--r-- | sound/firewire/tascam/amdtp-tascam.c | 34 | ||||
-rw-r--r-- | sound/firewire/tascam/tascam-hwdep.c | 2 | ||||
-rw-r--r-- | sound/firewire/tascam/tascam-midi.c | 12 | ||||
-rw-r--r-- | sound/firewire/tascam/tascam-pcm.c | 4 | ||||
-rw-r--r-- | sound/firewire/tascam/tascam-stream.c | 28 | ||||
-rw-r--r-- | sound/firewire/tascam/tascam-transaction.c | 2 | ||||
-rw-r--r-- | sound/firewire/tascam/tascam.c | 94 | ||||
-rw-r--r-- | sound/firewire/tascam/tascam.h | 3 |
8 files changed, 74 insertions, 105 deletions
diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index f823a2ab3544..0b42d6559008 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -29,7 +29,7 @@ int amdtp_tscm_set_parameters(struct amdtp_stream *s, unsigned int rate) if (s->direction == AMDTP_IN_STREAM) data_channels += 2; - return amdtp_stream_set_parameters(s, rate, data_channels); + return amdtp_stream_set_parameters(s, rate, data_channels, 1); } static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, @@ -176,16 +176,13 @@ static void read_status_messages(struct amdtp_stream *s, } } -static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, - const struct pkt_desc *descs, - unsigned int packets, - struct snd_pcm_substream *pcm) +static void process_ir_ctx_payloads(struct amdtp_stream *s, const struct pkt_desc *desc, + unsigned int count, struct snd_pcm_substream *pcm) { unsigned int pcm_frames = 0; int i; - for (i = 0; i < packets; ++i) { - const struct pkt_desc *desc = descs + i; + for (i = 0; i < count; ++i) { __be32 *buf = desc->ctx_payload; unsigned int data_blocks = desc->data_blocks; @@ -195,21 +192,18 @@ static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, } read_status_messages(s, buf, data_blocks); - } - return pcm_frames; + desc = amdtp_stream_next_packet_desc(s, desc); + } } -static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, - const struct pkt_desc *descs, - unsigned int packets, - struct snd_pcm_substream *pcm) +static void process_it_ctx_payloads(struct amdtp_stream *s, const struct pkt_desc *desc, + unsigned int count, struct snd_pcm_substream *pcm) { unsigned int pcm_frames = 0; int i; - for (i = 0; i < packets; ++i) { - const struct pkt_desc *desc = descs + i; + for (i = 0; i < count; ++i) { __be32 *buf = desc->ctx_payload; unsigned int data_blocks = desc->data_blocks; @@ -219,15 +213,16 @@ static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, } else { write_pcm_silence(s, buf, data_blocks); } - } - return pcm_frames; + desc = amdtp_stream_next_packet_desc(s, desc); + } } int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit, enum amdtp_stream_direction dir, unsigned int pcm_channels) { amdtp_stream_process_ctx_payloads_t process_ctx_payloads; + unsigned int flags = CIP_NONBLOCKING | CIP_SKIP_DBC_ZERO_CHECK | CIP_UNAWARE_SYT; struct amdtp_tscm *p; unsigned int fmt; int err; @@ -240,8 +235,7 @@ int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit, process_ctx_payloads = process_it_ctx_payloads; } - err = amdtp_stream_init(s, unit, dir, - CIP_NONBLOCKING | CIP_SKIP_DBC_ZERO_CHECK, fmt, + err = amdtp_stream_init(s, unit, dir, flags, fmt, process_ctx_payloads, sizeof(struct amdtp_tscm)); if (err < 0) return 0; @@ -249,8 +243,6 @@ int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit, if (dir == AMDTP_OUT_STREAM) { // Use fixed value for FDF field. s->ctx_data.rx.fdf = 0x00; - // Not used. - s->ctx_data.rx.syt_override = 0x0000; } /* This protocol uses fixed number of data channels for PCM samples. */ diff --git a/sound/firewire/tascam/tascam-hwdep.c b/sound/firewire/tascam/tascam-hwdep.c index 6f38335fe10b..74eed9505665 100644 --- a/sound/firewire/tascam/tascam-hwdep.c +++ b/sound/firewire/tascam/tascam-hwdep.c @@ -154,7 +154,7 @@ static int hwdep_get_info(struct snd_tscm *tscm, void __user *arg) info.card = dev->card->index; *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]); *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]); - strlcpy(info.device_name, dev_name(&dev->device), + strscpy(info.device_name, dev_name(&dev->device), sizeof(info.device_name)); if (copy_to_user(arg, &info, sizeof(info))) diff --git a/sound/firewire/tascam/tascam-midi.c b/sound/firewire/tascam/tascam-midi.c index 02eed2dce435..c57fac4f1968 100644 --- a/sound/firewire/tascam/tascam-midi.c +++ b/sound/firewire/tascam/tascam-midi.c @@ -108,9 +108,9 @@ int snd_tscm_create_midi_devices(struct snd_tscm *tscm) /* TODO: support virtual MIDI ports. */ if (subs->number < tscm->spec->midi_capture_ports) { /* Hardware MIDI ports. */ - snprintf(subs->name, sizeof(subs->name), - "%s MIDI %d", - tscm->card->shortname, subs->number + 1); + scnprintf(subs->name, sizeof(subs->name), + "%s MIDI %d", + tscm->card->shortname, subs->number + 1); } } @@ -123,9 +123,9 @@ int snd_tscm_create_midi_devices(struct snd_tscm *tscm) list_for_each_entry(subs, &stream->substreams, list) { if (subs->number < tscm->spec->midi_playback_ports) { /* Hardware MIDI ports only. */ - snprintf(subs->name, sizeof(subs->name), - "%s MIDI %d", - tscm->card->shortname, subs->number + 1); + scnprintf(subs->name, sizeof(subs->name), + "%s MIDI %d", + tscm->card->shortname, subs->number + 1); } } diff --git a/sound/firewire/tascam/tascam-pcm.c b/sound/firewire/tascam/tascam-pcm.c index 36c1353f2494..f6da571707ac 100644 --- a/sound/firewire/tascam/tascam-pcm.c +++ b/sound/firewire/tascam/tascam-pcm.c @@ -119,7 +119,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, struct snd_tscm *tscm = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); @@ -141,7 +141,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) mutex_lock(&tscm->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --tscm->substreams_counter; snd_tscm_stream_stop_duplex(tscm); diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c index eb07e1decf9b..dfe783d01d7d 100644 --- a/sound/firewire/tascam/tascam-stream.c +++ b/sound/firewire/tascam/tascam-stream.c @@ -11,7 +11,7 @@ #define CLOCK_STATUS_MASK 0xffff0000 #define CLOCK_CONFIG_MASK 0x0000ffff -#define CALLBACK_TIMEOUT 500 +#define READY_TIMEOUT_MS 4000 static int get_clock(struct snd_tscm *tscm, u32 *data) { @@ -423,6 +423,8 @@ int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate, fw_iso_resources_free(&tscm->rx_resources); return err; } + + tscm->need_long_tx_init_skip = (rate != curr_rate); } return 0; @@ -454,6 +456,7 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) if (!amdtp_stream_running(&tscm->rx_stream)) { int spd = fw_parent_device(tscm->unit)->max_speed; + unsigned int tx_init_skip_cycles; err = set_stream_formats(tscm, rate); if (err < 0) @@ -473,14 +476,23 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) if (err < 0) goto error; - err = amdtp_domain_start(&tscm->domain, 0); + if (tscm->need_long_tx_init_skip) + tx_init_skip_cycles = 16000; + else + tx_init_skip_cycles = 0; + + // MEMO: Just after starting packet streaming, it transfers packets without any + // event. Enough after receiving the sequence of packets, it multiplexes events into + // the packet. However, just after changing sampling transfer frequency, it stops + // multiplexing during packet transmission. Enough after, it restarts multiplexing + // again. The device ignores presentation time expressed by the value of syt field + // of CIP header in received packets. The sequence of the number of data blocks per + // packet is important for media clock recovery. + err = amdtp_domain_start(&tscm->domain, tx_init_skip_cycles, true, true); if (err < 0) - return err; + goto error; - if (!amdtp_stream_wait_callback(&tscm->rx_stream, - CALLBACK_TIMEOUT) || - !amdtp_stream_wait_callback(&tscm->tx_stream, - CALLBACK_TIMEOUT)) { + if (!amdtp_domain_wait_ready(&tscm->domain, READY_TIMEOUT_MS)) { err = -ETIMEDOUT; goto error; } @@ -502,6 +514,8 @@ void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm) fw_iso_resources_free(&tscm->tx_resources); fw_iso_resources_free(&tscm->rx_resources); + + tscm->need_long_tx_init_skip = false; } } diff --git a/sound/firewire/tascam/tascam-transaction.c b/sound/firewire/tascam/tascam-transaction.c index 90288b4b4637..a073cece4a7d 100644 --- a/sound/firewire/tascam/tascam-transaction.c +++ b/sound/firewire/tascam/tascam-transaction.c @@ -209,7 +209,7 @@ static void midi_port_work(struct work_struct *work) /* Set interval to next transaction. */ port->next_ktime = ktime_add_ns(ktime_get(), - port->consume_bytes * 8 * NSEC_PER_SEC / 31250); + port->consume_bytes * 8 * (NSEC_PER_SEC / 31250)); /* Start this transaction. */ port->idling = false; diff --git a/sound/firewire/tascam/tascam.c b/sound/firewire/tascam/tascam.c index 75f2edd8e78f..86880089de28 100644 --- a/sound/firewire/tascam/tascam.c +++ b/sound/firewire/tascam/tascam.c @@ -9,7 +9,7 @@ MODULE_DESCRIPTION("TASCAM FireWire series Driver"); MODULE_AUTHOR("Takashi Sakamoto <o-takashi@sakamocchi.jp>"); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); static const struct snd_tscm_spec model_specs[] = { { @@ -90,19 +90,31 @@ static void tscm_card_free(struct snd_card *card) snd_tscm_transaction_unregister(tscm); snd_tscm_stream_destroy_duplex(tscm); + + mutex_destroy(&tscm->mutex); + fw_unit_put(tscm->unit); } -static void do_registration(struct work_struct *work) +static int snd_tscm_probe(struct fw_unit *unit, + const struct ieee1394_device_id *entry) { - struct snd_tscm *tscm = container_of(work, struct snd_tscm, dwork.work); + struct snd_card *card; + struct snd_tscm *tscm; int err; - err = snd_card_new(&tscm->unit->device, -1, NULL, THIS_MODULE, 0, - &tscm->card); + err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, sizeof(*tscm), &card); if (err < 0) - return; - tscm->card->private_free = tscm_card_free; - tscm->card->private_data = tscm; + return err; + card->private_free = tscm_card_free; + + tscm = card->private_data; + tscm->unit = fw_unit_get(unit); + dev_set_drvdata(&unit->device, tscm); + tscm->card = card; + + mutex_init(&tscm->mutex); + spin_lock_init(&tscm->lock); + init_waitqueue_head(&tscm->hwdep_wait); err = identify_model(tscm); if (err < 0) @@ -130,81 +142,33 @@ static void do_registration(struct work_struct *work) if (err < 0) goto error; - err = snd_card_register(tscm->card); + err = snd_card_register(card); if (err < 0) goto error; - tscm->registered = true; - - return; -error: - snd_card_free(tscm->card); - dev_info(&tscm->unit->device, - "Sound card registration failed: %d\n", err); -} - -static int snd_tscm_probe(struct fw_unit *unit, - const struct ieee1394_device_id *entry) -{ - struct snd_tscm *tscm; - - /* Allocate this independent of sound card instance. */ - tscm = devm_kzalloc(&unit->device, sizeof(struct snd_tscm), GFP_KERNEL); - if (!tscm) - return -ENOMEM; - tscm->unit = fw_unit_get(unit); - dev_set_drvdata(&unit->device, tscm); - - mutex_init(&tscm->mutex); - spin_lock_init(&tscm->lock); - init_waitqueue_head(&tscm->hwdep_wait); - - /* Allocate and register this sound card later. */ - INIT_DEFERRABLE_WORK(&tscm->dwork, do_registration); - snd_fw_schedule_registration(unit, &tscm->dwork); - return 0; +error: + snd_card_free(card); + return err; } static void snd_tscm_update(struct fw_unit *unit) { struct snd_tscm *tscm = dev_get_drvdata(&unit->device); - /* Postpone a workqueue for deferred registration. */ - if (!tscm->registered) - snd_fw_schedule_registration(unit, &tscm->dwork); - snd_tscm_transaction_reregister(tscm); - /* - * After registration, userspace can start packet streaming, then this - * code block works fine. - */ - if (tscm->registered) { - mutex_lock(&tscm->mutex); - snd_tscm_stream_update_duplex(tscm); - mutex_unlock(&tscm->mutex); - } + mutex_lock(&tscm->mutex); + snd_tscm_stream_update_duplex(tscm); + mutex_unlock(&tscm->mutex); } static void snd_tscm_remove(struct fw_unit *unit) { struct snd_tscm *tscm = dev_get_drvdata(&unit->device); - /* - * Confirm to stop the work for registration before the sound card is - * going to be released. The work is not scheduled again because bus - * reset handler is not called anymore. - */ - cancel_delayed_work_sync(&tscm->dwork); - - if (tscm->registered) { - // Block till all of ALSA character devices are released. - snd_card_free(tscm->card); - } - - mutex_destroy(&tscm->mutex); - fw_unit_put(tscm->unit); + // Block till all of ALSA character devices are released. + snd_card_free(tscm->card); } static const struct ieee1394_device_id snd_tscm_id_table[] = { diff --git a/sound/firewire/tascam/tascam.h b/sound/firewire/tascam/tascam.h index 78b7a08986a1..d07ffcb27be6 100644 --- a/sound/firewire/tascam/tascam.h +++ b/sound/firewire/tascam/tascam.h @@ -70,8 +70,6 @@ struct snd_tscm { struct mutex mutex; spinlock_t lock; - bool registered; - struct delayed_work dwork; const struct snd_tscm_spec *spec; struct fw_iso_resources tx_resources; @@ -99,6 +97,7 @@ struct snd_tscm { unsigned int push_pos; struct amdtp_domain domain; + bool need_long_tx_init_skip; }; #define TSCM_ADDR_BASE 0xffff00000000ull |