forked from Minki/linux
Merge branch 'for-next'
This commit is contained in:
commit
641c197a39
@ -52,10 +52,6 @@
|
||||
#define CIP_FMT_AM 0x10
|
||||
#define AMDTP_FDF_NO_DATA 0xff
|
||||
|
||||
/* TODO: make these configurable */
|
||||
#define INTERRUPT_INTERVAL 16
|
||||
#define QUEUE_LENGTH 48
|
||||
|
||||
// For iso header, tstamp and 2 CIP header.
|
||||
#define IR_CTX_HEADER_SIZE_CIP 16
|
||||
// For iso header and tstamp.
|
||||
@ -180,6 +176,8 @@ int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s,
|
||||
struct snd_pcm_runtime *runtime)
|
||||
{
|
||||
struct snd_pcm_hardware *hw = &runtime->hw;
|
||||
unsigned int ctx_header_size;
|
||||
unsigned int maximum_usec_per_period;
|
||||
int err;
|
||||
|
||||
hw->info = SNDRV_PCM_INFO_BATCH |
|
||||
@ -200,19 +198,36 @@ int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s,
|
||||
hw->period_bytes_max = hw->period_bytes_min * 2048;
|
||||
hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min;
|
||||
|
||||
/*
|
||||
* Currently firewire-lib processes 16 packets in one software
|
||||
* interrupt callback. This equals to 2msec but actually the
|
||||
* interval of the interrupts has a jitter.
|
||||
* Additionally, even if adding a constraint to fit period size to
|
||||
* 2msec, actual calculated frames per period doesn't equal to 2msec,
|
||||
* depending on sampling rate.
|
||||
* Anyway, the interval to call snd_pcm_period_elapsed() cannot 2msec.
|
||||
* Here let us use 5msec for safe period interrupt.
|
||||
*/
|
||||
// Linux driver for 1394 OHCI controller voluntarily flushes isoc
|
||||
// context when total size of accumulated context header reaches
|
||||
// PAGE_SIZE. This kicks tasklet for the isoc context and brings
|
||||
// callback in the middle of scheduled interrupts.
|
||||
// Although AMDTP streams in the same domain use the same events per
|
||||
// IRQ, use the largest size of context header between IT/IR contexts.
|
||||
// Here, use the value of context header in IR context is for both
|
||||
// contexts.
|
||||
if (!(s->flags & CIP_NO_HEADER))
|
||||
ctx_header_size = IR_CTX_HEADER_SIZE_CIP;
|
||||
else
|
||||
ctx_header_size = IR_CTX_HEADER_SIZE_NO_CIP;
|
||||
maximum_usec_per_period = USEC_PER_SEC * PAGE_SIZE /
|
||||
CYCLES_PER_SECOND / ctx_header_size;
|
||||
|
||||
// In IEC 61883-6, one isoc packet can transfer events up to the value
|
||||
// of syt interval. This comes from the interval of isoc cycle. As 1394
|
||||
// OHCI controller can generate hardware IRQ per isoc packet, the
|
||||
// interval is 125 usec.
|
||||
// However, there are two ways of transmission in IEC 61883-6; blocking
|
||||
// and non-blocking modes. In blocking mode, the sequence of isoc packet
|
||||
// includes 'empty' or 'NODATA' packets which include no event. In
|
||||
// non-blocking mode, the number of events per packet is variable up to
|
||||
// the syt interval.
|
||||
// Due to the above protocol design, the minimum PCM frames per
|
||||
// interrupt should be double of the value of syt interval, thus it is
|
||||
// 250 usec.
|
||||
err = snd_pcm_hw_constraint_minmax(runtime,
|
||||
SNDRV_PCM_HW_PARAM_PERIOD_TIME,
|
||||
5000, UINT_MAX);
|
||||
250, maximum_usec_per_period);
|
||||
if (err < 0)
|
||||
goto end;
|
||||
|
||||
@ -436,11 +451,12 @@ static void pcm_period_tasklet(unsigned long data)
|
||||
snd_pcm_period_elapsed(pcm);
|
||||
}
|
||||
|
||||
static int queue_packet(struct amdtp_stream *s, struct fw_iso_packet *params)
|
||||
static int queue_packet(struct amdtp_stream *s, struct fw_iso_packet *params,
|
||||
bool sched_irq)
|
||||
{
|
||||
int err;
|
||||
|
||||
params->interrupt = IS_ALIGNED(s->packet_index + 1, INTERRUPT_INTERVAL);
|
||||
params->interrupt = sched_irq;
|
||||
params->tag = s->tag;
|
||||
params->sy = 0;
|
||||
|
||||
@ -451,28 +467,28 @@ static int queue_packet(struct amdtp_stream *s, struct fw_iso_packet *params)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (++s->packet_index >= QUEUE_LENGTH)
|
||||
if (++s->packet_index >= s->queue_size)
|
||||
s->packet_index = 0;
|
||||
end:
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline int queue_out_packet(struct amdtp_stream *s,
|
||||
struct fw_iso_packet *params)
|
||||
struct fw_iso_packet *params, bool sched_irq)
|
||||
{
|
||||
params->skip =
|
||||
!!(params->header_length == 0 && params->payload_length == 0);
|
||||
return queue_packet(s, params);
|
||||
return queue_packet(s, params, sched_irq);
|
||||
}
|
||||
|
||||
static inline int queue_in_packet(struct amdtp_stream *s,
|
||||
struct fw_iso_packet *params)
|
||||
struct fw_iso_packet *params, bool sched_irq)
|
||||
{
|
||||
// Queue one packet for IR context.
|
||||
params->header_length = s->ctx_data.tx.ctx_header_size;
|
||||
params->payload_length = s->ctx_data.tx.max_ctx_payload_length;
|
||||
params->skip = false;
|
||||
return queue_packet(s, params);
|
||||
return queue_packet(s, params, sched_irq);
|
||||
}
|
||||
|
||||
static void generate_cip_header(struct amdtp_stream *s, __be32 cip_header[2],
|
||||
@ -669,13 +685,14 @@ static inline u32 increment_cycle_count(u32 cycle, unsigned int addend)
|
||||
}
|
||||
|
||||
// Align to actual cycle count for the packet which is going to be scheduled.
|
||||
// This module queued the same number of isochronous cycle as QUEUE_LENGTH to
|
||||
// skip isochronous cycle, therefore it's OK to just increment the cycle by
|
||||
// QUEUE_LENGTH for scheduled cycle.
|
||||
static inline u32 compute_it_cycle(const __be32 ctx_header_tstamp)
|
||||
// This module queued the same number of isochronous cycle as the size of queue
|
||||
// to kip isochronous cycle, therefore it's OK to just increment the cycle by
|
||||
// the size of queue for scheduled cycle.
|
||||
static inline u32 compute_it_cycle(const __be32 ctx_header_tstamp,
|
||||
unsigned int queue_size)
|
||||
{
|
||||
u32 cycle = compute_cycle_count(ctx_header_tstamp);
|
||||
return increment_cycle_count(cycle, QUEUE_LENGTH);
|
||||
return increment_cycle_count(cycle, queue_size);
|
||||
}
|
||||
|
||||
static int generate_device_pkt_descs(struct amdtp_stream *s,
|
||||
@ -689,7 +706,7 @@ static int generate_device_pkt_descs(struct amdtp_stream *s,
|
||||
|
||||
for (i = 0; i < packets; ++i) {
|
||||
struct pkt_desc *desc = descs + i;
|
||||
unsigned int index = (s->packet_index + i) % QUEUE_LENGTH;
|
||||
unsigned int index = (s->packet_index + i) % s->queue_size;
|
||||
unsigned int cycle;
|
||||
unsigned int payload_length;
|
||||
unsigned int data_blocks;
|
||||
@ -730,9 +747,9 @@ static void generate_ideal_pkt_descs(struct amdtp_stream *s,
|
||||
|
||||
for (i = 0; i < packets; ++i) {
|
||||
struct pkt_desc *desc = descs + i;
|
||||
unsigned int index = (s->packet_index + i) % QUEUE_LENGTH;
|
||||
unsigned int index = (s->packet_index + i) % s->queue_size;
|
||||
|
||||
desc->cycle = compute_it_cycle(*ctx_header);
|
||||
desc->cycle = compute_it_cycle(*ctx_header, s->queue_size);
|
||||
desc->syt = calculate_syt(s, desc->cycle);
|
||||
desc->data_blocks = calculate_data_blocks(s, desc->syt);
|
||||
|
||||
@ -779,12 +796,17 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp,
|
||||
{
|
||||
struct amdtp_stream *s = private_data;
|
||||
const __be32 *ctx_header = header;
|
||||
unsigned int packets = header_length / sizeof(*ctx_header);
|
||||
unsigned int events_per_period = s->events_per_period;
|
||||
unsigned int event_count = s->event_count;
|
||||
unsigned int packets;
|
||||
int i;
|
||||
|
||||
if (s->packet_index < 0)
|
||||
return;
|
||||
|
||||
// Calculate the number of packets in buffer and check XRUN.
|
||||
packets = header_length / sizeof(*ctx_header);
|
||||
|
||||
generate_ideal_pkt_descs(s, s->pkt_descs, ctx_header, packets);
|
||||
|
||||
process_ctx_payloads(s, s->pkt_descs, packets);
|
||||
@ -796,6 +818,7 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp,
|
||||
struct fw_iso_packet params;
|
||||
__be32 header[IT_PKT_HEADER_SIZE_CIP / sizeof(__be32)];
|
||||
} template = { {0}, {0} };
|
||||
bool sched_irq = false;
|
||||
|
||||
if (s->ctx_data.rx.syt_override < 0)
|
||||
syt = desc->syt;
|
||||
@ -806,12 +829,20 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp,
|
||||
desc->data_blocks, desc->data_block_counter,
|
||||
syt, i);
|
||||
|
||||
if (queue_out_packet(s, &template.params) < 0) {
|
||||
event_count += desc->data_blocks;
|
||||
if (event_count >= events_per_period) {
|
||||
event_count -= events_per_period;
|
||||
sched_irq = true;
|
||||
}
|
||||
|
||||
if (queue_out_packet(s, &template.params, sched_irq) < 0) {
|
||||
cancel_stream(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
s->event_count = event_count;
|
||||
|
||||
fw_iso_context_queue_flush(s->context);
|
||||
}
|
||||
|
||||
@ -820,15 +851,17 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp,
|
||||
void *private_data)
|
||||
{
|
||||
struct amdtp_stream *s = private_data;
|
||||
unsigned int packets;
|
||||
__be32 *ctx_header = header;
|
||||
unsigned int events_per_period = s->events_per_period;
|
||||
unsigned int event_count = s->event_count;
|
||||
unsigned int packets;
|
||||
int i;
|
||||
int err;
|
||||
|
||||
if (s->packet_index < 0)
|
||||
return;
|
||||
|
||||
// The number of packets in buffer.
|
||||
// Calculate the number of packets in buffer and check XRUN.
|
||||
packets = header_length / s->ctx_data.tx.ctx_header_size;
|
||||
|
||||
err = generate_device_pkt_descs(s, s->pkt_descs, ctx_header, packets);
|
||||
@ -842,14 +875,29 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp,
|
||||
}
|
||||
|
||||
for (i = 0; i < packets; ++i) {
|
||||
const struct pkt_desc *desc = s->pkt_descs + i;
|
||||
struct fw_iso_packet params = {0};
|
||||
bool sched_irq = false;
|
||||
|
||||
if (queue_in_packet(s, ¶ms) < 0) {
|
||||
if (err >= 0) {
|
||||
event_count += desc->data_blocks;
|
||||
if (event_count >= events_per_period) {
|
||||
event_count -= events_per_period;
|
||||
sched_irq = true;
|
||||
}
|
||||
} else {
|
||||
sched_irq =
|
||||
!((s->packet_index + 1) % s->idle_irq_interval);
|
||||
}
|
||||
|
||||
if (queue_in_packet(s, ¶ms, sched_irq) < 0) {
|
||||
cancel_stream(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
s->event_count = event_count;
|
||||
|
||||
fw_iso_context_queue_flush(s->context);
|
||||
}
|
||||
|
||||
@ -874,7 +922,7 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context,
|
||||
|
||||
context->callback.sc = in_stream_callback;
|
||||
} else {
|
||||
cycle = compute_it_cycle(*ctx_header);
|
||||
cycle = compute_it_cycle(*ctx_header, s->queue_size);
|
||||
|
||||
context->callback.sc = out_stream_callback;
|
||||
}
|
||||
@ -894,7 +942,8 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context,
|
||||
* amdtp_stream_set_parameters() and it must be started before any PCM or MIDI
|
||||
* device can be started.
|
||||
*/
|
||||
static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed)
|
||||
static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed,
|
||||
struct amdtp_domain *d)
|
||||
{
|
||||
static const struct {
|
||||
unsigned int data_block;
|
||||
@ -908,6 +957,8 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed)
|
||||
[CIP_SFC_88200] = { 0, 67 },
|
||||
[CIP_SFC_176400] = { 0, 67 },
|
||||
};
|
||||
unsigned int events_per_buffer = d->events_per_buffer;
|
||||
unsigned int events_per_period = d->events_per_period;
|
||||
unsigned int ctx_header_size;
|
||||
unsigned int max_ctx_payload_size;
|
||||
enum dma_data_direction dir;
|
||||
@ -953,7 +1004,23 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed)
|
||||
max_ctx_payload_size -= IT_PKT_HEADER_SIZE_CIP;
|
||||
}
|
||||
|
||||
err = iso_packets_buffer_init(&s->buffer, s->unit, QUEUE_LENGTH,
|
||||
// This is a case that AMDTP streams in domain run just for MIDI
|
||||
// substream. Use the number of events equivalent to 10 msec as
|
||||
// interval of hardware IRQ.
|
||||
if (events_per_period == 0)
|
||||
events_per_period = amdtp_rate_table[s->sfc] / 100;
|
||||
if (events_per_buffer == 0)
|
||||
events_per_buffer = events_per_period * 3;
|
||||
|
||||
s->idle_irq_interval =
|
||||
DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_period,
|
||||
amdtp_rate_table[s->sfc]);
|
||||
s->queue_size = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_buffer,
|
||||
amdtp_rate_table[s->sfc]);
|
||||
s->events_per_period = events_per_period;
|
||||
s->event_count = 0;
|
||||
|
||||
err = iso_packets_buffer_init(&s->buffer, s->unit, s->queue_size,
|
||||
max_ctx_payload_size, dir);
|
||||
if (err < 0)
|
||||
goto err_unlock;
|
||||
@ -981,7 +1048,7 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed)
|
||||
else
|
||||
s->tag = TAG_CIP;
|
||||
|
||||
s->pkt_descs = kcalloc(INTERRUPT_INTERVAL, sizeof(*s->pkt_descs),
|
||||
s->pkt_descs = kcalloc(s->queue_size, sizeof(*s->pkt_descs),
|
||||
GFP_KERNEL);
|
||||
if (!s->pkt_descs) {
|
||||
err = -ENOMEM;
|
||||
@ -991,12 +1058,15 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed)
|
||||
s->packet_index = 0;
|
||||
do {
|
||||
struct fw_iso_packet params;
|
||||
bool sched_irq;
|
||||
|
||||
sched_irq = !((s->packet_index + 1) % s->idle_irq_interval);
|
||||
if (s->direction == AMDTP_IN_STREAM) {
|
||||
err = queue_in_packet(s, ¶ms);
|
||||
err = queue_in_packet(s, ¶ms, sched_irq);
|
||||
} else {
|
||||
params.header_length = 0;
|
||||
params.payload_length = 0;
|
||||
err = queue_out_packet(s, ¶ms);
|
||||
err = queue_out_packet(s, ¶ms, sched_irq);
|
||||
}
|
||||
if (err < 0)
|
||||
goto err_pkt_descs;
|
||||
@ -1196,7 +1266,7 @@ int amdtp_domain_start(struct amdtp_domain *d)
|
||||
int err = 0;
|
||||
|
||||
list_for_each_entry(s, &d->streams, list) {
|
||||
err = amdtp_stream_start(s, s->channel, s->speed);
|
||||
err = amdtp_stream_start(s, s->channel, s->speed, d);
|
||||
if (err < 0)
|
||||
break;
|
||||
}
|
||||
|
@ -117,6 +117,7 @@ struct amdtp_stream {
|
||||
/* For packet processing. */
|
||||
struct fw_iso_context *context;
|
||||
struct iso_packets_buffer buffer;
|
||||
unsigned int queue_size;
|
||||
int packet_index;
|
||||
struct pkt_desc *pkt_descs;
|
||||
int tag;
|
||||
@ -144,6 +145,9 @@ struct amdtp_stream {
|
||||
int syt_override;
|
||||
} rx;
|
||||
} ctx_data;
|
||||
unsigned int event_count;
|
||||
unsigned int events_per_period;
|
||||
unsigned int idle_irq_interval;
|
||||
|
||||
/* For CIP headers. */
|
||||
unsigned int source_node_id_field;
|
||||
@ -274,6 +278,7 @@ struct amdtp_domain {
|
||||
struct list_head streams;
|
||||
|
||||
unsigned int events_per_period;
|
||||
unsigned int events_per_buffer;
|
||||
};
|
||||
|
||||
int amdtp_domain_init(struct amdtp_domain *d);
|
||||
@ -286,9 +291,11 @@ int amdtp_domain_start(struct amdtp_domain *d);
|
||||
void amdtp_domain_stop(struct amdtp_domain *d);
|
||||
|
||||
static inline int amdtp_domain_set_events_per_period(struct amdtp_domain *d,
|
||||
unsigned int events_per_period)
|
||||
unsigned int events_per_period,
|
||||
unsigned int events_per_buffer)
|
||||
{
|
||||
d->events_per_period = events_per_period;
|
||||
d->events_per_buffer = events_per_buffer;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -218,7 +218,8 @@ int snd_bebob_stream_get_clock_src(struct snd_bebob *bebob,
|
||||
int snd_bebob_stream_discover(struct snd_bebob *bebob);
|
||||
int snd_bebob_stream_init_duplex(struct snd_bebob *bebob);
|
||||
int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate,
|
||||
unsigned int frames_per_period);
|
||||
unsigned int frames_per_period,
|
||||
unsigned int frames_per_buffer);
|
||||
int snd_bebob_stream_start_duplex(struct snd_bebob *bebob);
|
||||
void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob);
|
||||
void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob);
|
||||
|
@ -17,7 +17,7 @@ static int midi_open(struct snd_rawmidi_substream *substream)
|
||||
return err;
|
||||
|
||||
mutex_lock(&bebob->mutex);
|
||||
err = snd_bebob_stream_reserve_duplex(bebob, 0, 0);
|
||||
err = snd_bebob_stream_reserve_duplex(bebob, 0, 0, 0);
|
||||
if (err >= 0) {
|
||||
++bebob->substreams_counter;
|
||||
err = snd_bebob_stream_start_duplex(bebob);
|
||||
|
@ -157,6 +157,7 @@ static int pcm_open(struct snd_pcm_substream *substream)
|
||||
if (src == SND_BEBOB_CLOCK_TYPE_EXTERNAL ||
|
||||
(bebob->substreams_counter > 0 && d->events_per_period > 0)) {
|
||||
unsigned int frames_per_period = d->events_per_period;
|
||||
unsigned int frames_per_buffer = d->events_per_buffer;
|
||||
unsigned int sampling_rate;
|
||||
|
||||
err = spec->get(bebob, &sampling_rate);
|
||||
@ -178,6 +179,14 @@ static int pcm_open(struct snd_pcm_substream *substream)
|
||||
mutex_unlock(&bebob->mutex);
|
||||
goto err_locked;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
|
||||
frames_per_buffer, frames_per_buffer);
|
||||
if (err < 0) {
|
||||
mutex_unlock(&bebob->mutex);
|
||||
goto err_locked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,10 +222,11 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
if (substream->runtime->status->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);
|
||||
|
||||
mutex_lock(&bebob->mutex);
|
||||
err = snd_bebob_stream_reserve_duplex(bebob, rate,
|
||||
frames_per_period);
|
||||
frames_per_period, frames_per_buffer);
|
||||
if (err >= 0)
|
||||
++bebob->substreams_counter;
|
||||
mutex_unlock(&bebob->mutex);
|
||||
|
@ -555,7 +555,8 @@ static int keep_resources(struct snd_bebob *bebob, struct amdtp_stream *stream,
|
||||
}
|
||||
|
||||
int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate,
|
||||
unsigned int frames_per_period)
|
||||
unsigned int frames_per_period,
|
||||
unsigned int frames_per_buffer)
|
||||
{
|
||||
unsigned int curr_rate;
|
||||
int err;
|
||||
@ -610,7 +611,7 @@ int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate,
|
||||
}
|
||||
|
||||
err = amdtp_domain_set_events_per_period(&bebob->domain,
|
||||
frames_per_period);
|
||||
frames_per_period, frames_per_buffer);
|
||||
if (err < 0) {
|
||||
cmp_connection_release(&bebob->out_conn);
|
||||
cmp_connection_release(&bebob->in_conn);
|
||||
|
@ -17,7 +17,7 @@ static int midi_open(struct snd_rawmidi_substream *substream)
|
||||
|
||||
mutex_lock(&dice->mutex);
|
||||
|
||||
err = snd_dice_stream_reserve_duplex(dice, 0, 0);
|
||||
err = snd_dice_stream_reserve_duplex(dice, 0, 0, 0);
|
||||
if (err >= 0) {
|
||||
++dice->substreams_counter;
|
||||
err = snd_dice_stream_start_duplex(dice);
|
||||
|
@ -204,6 +204,7 @@ static int pcm_open(struct snd_pcm_substream *substream)
|
||||
if (!internal ||
|
||||
(dice->substreams_counter > 0 && d->events_per_period > 0)) {
|
||||
unsigned int frames_per_period = d->events_per_period;
|
||||
unsigned int frames_per_buffer = d->events_per_buffer;
|
||||
unsigned int rate;
|
||||
|
||||
err = snd_dice_transaction_get_rate(dice, &rate);
|
||||
@ -217,8 +218,10 @@ static int pcm_open(struct snd_pcm_substream *substream)
|
||||
|
||||
if (frames_per_period > 0) {
|
||||
// For double_pcm_frame quirk.
|
||||
if (rate > 96000)
|
||||
if (rate > 96000) {
|
||||
frames_per_period *= 2;
|
||||
frames_per_buffer *= 2;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
|
||||
@ -227,6 +230,14 @@ static int pcm_open(struct snd_pcm_substream *substream)
|
||||
mutex_unlock(&dice->mutex);
|
||||
goto err_locked;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
|
||||
frames_per_buffer, frames_per_buffer);
|
||||
if (err < 0) {
|
||||
mutex_unlock(&dice->mutex);
|
||||
goto err_locked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,13 +274,16 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
|
||||
unsigned int rate = params_rate(hw_params);
|
||||
unsigned int events_per_period = params_period_size(hw_params);
|
||||
unsigned int events_per_buffer = params_buffer_size(hw_params);
|
||||
|
||||
mutex_lock(&dice->mutex);
|
||||
// For double_pcm_frame quirk.
|
||||
if (rate > 96000)
|
||||
if (rate > 96000) {
|
||||
events_per_period /= 2;
|
||||
events_per_buffer /= 2;
|
||||
}
|
||||
err = snd_dice_stream_reserve_duplex(dice, rate,
|
||||
events_per_period);
|
||||
events_per_period, events_per_buffer);
|
||||
if (err >= 0)
|
||||
++dice->substreams_counter;
|
||||
mutex_unlock(&dice->mutex);
|
||||
|
@ -279,7 +279,8 @@ static void finish_session(struct snd_dice *dice, struct reg_params *tx_params,
|
||||
}
|
||||
|
||||
int snd_dice_stream_reserve_duplex(struct snd_dice *dice, unsigned int rate,
|
||||
unsigned int events_per_period)
|
||||
unsigned int events_per_period,
|
||||
unsigned int events_per_buffer)
|
||||
{
|
||||
unsigned int curr_rate;
|
||||
int err;
|
||||
@ -327,7 +328,7 @@ int snd_dice_stream_reserve_duplex(struct snd_dice *dice, unsigned int rate,
|
||||
goto error;
|
||||
|
||||
err = amdtp_domain_set_events_per_period(&dice->domain,
|
||||
events_per_period);
|
||||
events_per_period, events_per_buffer);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
}
|
||||
|
@ -211,7 +211,8 @@ void snd_dice_stream_stop_duplex(struct snd_dice *dice);
|
||||
int snd_dice_stream_init_duplex(struct snd_dice *dice);
|
||||
void snd_dice_stream_destroy_duplex(struct snd_dice *dice);
|
||||
int snd_dice_stream_reserve_duplex(struct snd_dice *dice, unsigned int rate,
|
||||
unsigned int events_per_period);
|
||||
unsigned int events_per_period,
|
||||
unsigned int events_per_buffer);
|
||||
void snd_dice_stream_update_duplex(struct snd_dice *dice);
|
||||
int snd_dice_stream_detect_current_formats(struct snd_dice *dice);
|
||||
|
||||
|
@ -17,7 +17,7 @@ static int midi_open(struct snd_rawmidi_substream *substream)
|
||||
return err;
|
||||
|
||||
mutex_lock(&dg00x->mutex);
|
||||
err = snd_dg00x_stream_reserve_duplex(dg00x, 0, 0);
|
||||
err = snd_dg00x_stream_reserve_duplex(dg00x, 0, 0, 0);
|
||||
if (err >= 0) {
|
||||
++dg00x->substreams_counter;
|
||||
err = snd_dg00x_stream_start_duplex(dg00x);
|
||||
|
@ -135,6 +135,7 @@ static int pcm_open(struct snd_pcm_substream *substream)
|
||||
if ((clock != SND_DG00X_CLOCK_INTERNAL) ||
|
||||
(dg00x->substreams_counter > 0 && d->events_per_period > 0)) {
|
||||
unsigned int frames_per_period = d->events_per_period;
|
||||
unsigned int frames_per_buffer = d->events_per_buffer;
|
||||
unsigned int rate;
|
||||
|
||||
err = snd_dg00x_stream_get_external_rate(dg00x, &rate);
|
||||
@ -153,6 +154,14 @@ static int pcm_open(struct snd_pcm_substream *substream)
|
||||
mutex_unlock(&dg00x->mutex);
|
||||
goto err_locked;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
|
||||
frames_per_buffer, frames_per_buffer);
|
||||
if (err < 0) {
|
||||
mutex_unlock(&dg00x->mutex);
|
||||
goto err_locked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,10 +198,11 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
if (substream->runtime->status->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);
|
||||
|
||||
mutex_lock(&dg00x->mutex);
|
||||
err = snd_dg00x_stream_reserve_duplex(dg00x, rate,
|
||||
frames_per_period);
|
||||
frames_per_period, frames_per_buffer);
|
||||
if (err >= 0)
|
||||
++dg00x->substreams_counter;
|
||||
mutex_unlock(&dg00x->mutex);
|
||||
|
@ -284,7 +284,8 @@ void snd_dg00x_stream_destroy_duplex(struct snd_dg00x *dg00x)
|
||||
}
|
||||
|
||||
int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate,
|
||||
unsigned int frames_per_period)
|
||||
unsigned int frames_per_period,
|
||||
unsigned int frames_per_buffer)
|
||||
{
|
||||
unsigned int curr_rate;
|
||||
int err;
|
||||
@ -318,7 +319,7 @@ int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate,
|
||||
}
|
||||
|
||||
err = amdtp_domain_set_events_per_period(&dg00x->domain,
|
||||
frames_per_period);
|
||||
frames_per_period, frames_per_buffer);
|
||||
if (err < 0) {
|
||||
fw_iso_resources_free(&dg00x->rx_resources);
|
||||
fw_iso_resources_free(&dg00x->tx_resources);
|
||||
|
@ -142,7 +142,8 @@ int snd_dg00x_stream_check_external_clock(struct snd_dg00x *dg00x,
|
||||
bool *detect);
|
||||
int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x);
|
||||
int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate,
|
||||
unsigned int frames_per_period);
|
||||
unsigned int frames_per_period,
|
||||
unsigned int frames_per_buffer);
|
||||
int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x);
|
||||
void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x);
|
||||
void snd_dg00x_stream_update_duplex(struct snd_dg00x *dg00x);
|
||||
|
@ -180,6 +180,7 @@ static int pcm_open(struct snd_pcm_substream *substream)
|
||||
} else {
|
||||
if (ff->substreams_counter > 0) {
|
||||
unsigned int frames_per_period = d->events_per_period;
|
||||
unsigned int frames_per_buffer = d->events_per_buffer;
|
||||
|
||||
rate = amdtp_rate_table[ff->rx_stream.sfc];
|
||||
substream->runtime->hw.rate_min = rate;
|
||||
@ -192,6 +193,14 @@ static int pcm_open(struct snd_pcm_substream *substream)
|
||||
mutex_unlock(&ff->mutex);
|
||||
goto release_lock;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
|
||||
frames_per_buffer, frames_per_buffer);
|
||||
if (err < 0) {
|
||||
mutex_unlock(&ff->mutex);
|
||||
goto release_lock;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,9 +238,11 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
if (substream->runtime->status->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);
|
||||
|
||||
mutex_lock(&ff->mutex);
|
||||
err = snd_ff_stream_reserve_duplex(ff, rate, frames_per_period);
|
||||
err = snd_ff_stream_reserve_duplex(ff, rate, frames_per_period,
|
||||
frames_per_buffer);
|
||||
if (err >= 0)
|
||||
++ff->substreams_counter;
|
||||
mutex_unlock(&ff->mutex);
|
||||
|
@ -107,7 +107,8 @@ void snd_ff_stream_destroy_duplex(struct snd_ff *ff)
|
||||
}
|
||||
|
||||
int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate,
|
||||
unsigned int frames_per_period)
|
||||
unsigned int frames_per_period,
|
||||
unsigned int frames_per_buffer)
|
||||
{
|
||||
unsigned int curr_rate;
|
||||
enum snd_ff_clock_src src;
|
||||
@ -153,7 +154,7 @@ int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate,
|
||||
return err;
|
||||
|
||||
err = amdtp_domain_set_events_per_period(&ff->domain,
|
||||
frames_per_period);
|
||||
frames_per_period, frames_per_buffer);
|
||||
if (err < 0) {
|
||||
fw_iso_resources_free(&ff->tx_resources);
|
||||
fw_iso_resources_free(&ff->rx_resources);
|
||||
|
@ -140,7 +140,8 @@ int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc,
|
||||
int snd_ff_stream_init_duplex(struct snd_ff *ff);
|
||||
void snd_ff_stream_destroy_duplex(struct snd_ff *ff);
|
||||
int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate,
|
||||
unsigned int frames_per_period);
|
||||
unsigned int frames_per_period,
|
||||
unsigned int frames_per_buffer);
|
||||
int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate);
|
||||
void snd_ff_stream_stop_duplex(struct snd_ff *ff);
|
||||
void snd_ff_stream_update_duplex(struct snd_ff *ff);
|
||||
|
@ -208,7 +208,8 @@ int snd_efw_command_set_sampling_rate(struct snd_efw *efw, unsigned int rate);
|
||||
|
||||
int snd_efw_stream_init_duplex(struct snd_efw *efw);
|
||||
int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate,
|
||||
unsigned int frames_per_period);
|
||||
unsigned int frames_per_period,
|
||||
unsigned int frames_per_buffer);
|
||||
int snd_efw_stream_start_duplex(struct snd_efw *efw);
|
||||
void snd_efw_stream_stop_duplex(struct snd_efw *efw);
|
||||
void snd_efw_stream_update_duplex(struct snd_efw *efw);
|
||||
|
@ -17,7 +17,7 @@ static int midi_open(struct snd_rawmidi_substream *substream)
|
||||
goto end;
|
||||
|
||||
mutex_lock(&efw->mutex);
|
||||
err = snd_efw_stream_reserve_duplex(efw, 0, 0);
|
||||
err = snd_efw_stream_reserve_duplex(efw, 0, 0, 0);
|
||||
if (err >= 0) {
|
||||
++efw->substreams_counter;
|
||||
err = snd_efw_stream_start_duplex(efw);
|
||||
|
@ -197,6 +197,7 @@ static int pcm_open(struct snd_pcm_substream *substream)
|
||||
if ((clock_source != SND_EFW_CLOCK_SOURCE_INTERNAL) ||
|
||||
(efw->substreams_counter > 0 && d->events_per_period > 0)) {
|
||||
unsigned int frames_per_period = d->events_per_period;
|
||||
unsigned int frames_per_buffer = d->events_per_buffer;
|
||||
unsigned int sampling_rate;
|
||||
|
||||
err = snd_efw_command_get_sampling_rate(efw, &sampling_rate);
|
||||
@ -215,6 +216,14 @@ static int pcm_open(struct snd_pcm_substream *substream)
|
||||
mutex_unlock(&efw->mutex);
|
||||
goto err_locked;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
|
||||
frames_per_buffer, frames_per_buffer);
|
||||
if (err < 0) {
|
||||
mutex_unlock(&efw->mutex);
|
||||
goto err_locked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -249,10 +258,11 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
if (substream->runtime->status->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);
|
||||
|
||||
mutex_lock(&efw->mutex);
|
||||
err = snd_efw_stream_reserve_duplex(efw, rate,
|
||||
frames_per_period);
|
||||
frames_per_period, frames_per_buffer);
|
||||
if (err >= 0)
|
||||
++efw->substreams_counter;
|
||||
mutex_unlock(&efw->mutex);
|
||||
|
@ -182,7 +182,8 @@ static int keep_resources(struct snd_efw *efw, struct amdtp_stream *stream,
|
||||
}
|
||||
|
||||
int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate,
|
||||
unsigned int frames_per_period)
|
||||
unsigned int frames_per_period,
|
||||
unsigned int frames_per_buffer)
|
||||
{
|
||||
unsigned int curr_rate;
|
||||
int err;
|
||||
@ -231,7 +232,7 @@ int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate,
|
||||
}
|
||||
|
||||
err = amdtp_domain_set_events_per_period(&efw->domain,
|
||||
frames_per_period);
|
||||
frames_per_period, frames_per_buffer);
|
||||
if (err < 0) {
|
||||
cmp_connection_release(&efw->in_conn);
|
||||
cmp_connection_release(&efw->out_conn);
|
||||
|
@ -17,7 +17,7 @@ static int midi_open(struct snd_rawmidi_substream *substream)
|
||||
|
||||
mutex_lock(&motu->mutex);
|
||||
|
||||
err = snd_motu_stream_reserve_duplex(motu, 0, 0);
|
||||
err = snd_motu_stream_reserve_duplex(motu, 0, 0, 0);
|
||||
if (err >= 0) {
|
||||
++motu->substreams_counter;
|
||||
err = snd_motu_stream_start_duplex(motu);
|
||||
|
@ -162,6 +162,7 @@ static int pcm_open(struct snd_pcm_substream *substream)
|
||||
if (src != SND_MOTU_CLOCK_SOURCE_INTERNAL ||
|
||||
(motu->substreams_counter > 0 && d->events_per_period > 0)) {
|
||||
unsigned int frames_per_period = d->events_per_period;
|
||||
unsigned int frames_per_buffer = d->events_per_buffer;
|
||||
unsigned int rate;
|
||||
|
||||
err = protocol->get_clock_rate(motu, &rate);
|
||||
@ -179,6 +180,14 @@ static int pcm_open(struct snd_pcm_substream *substream)
|
||||
mutex_unlock(&motu->mutex);
|
||||
goto err_locked;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
|
||||
frames_per_buffer, frames_per_buffer);
|
||||
if (err < 0) {
|
||||
mutex_unlock(&motu->mutex);
|
||||
goto err_locked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,10 +225,11 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
if (substream->runtime->status->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);
|
||||
|
||||
mutex_lock(&motu->mutex);
|
||||
err = snd_motu_stream_reserve_duplex(motu, rate,
|
||||
frames_per_period);
|
||||
frames_per_period, frames_per_buffer);
|
||||
if (err >= 0)
|
||||
++motu->substreams_counter;
|
||||
mutex_unlock(&motu->mutex);
|
||||
|
@ -134,7 +134,8 @@ int snd_motu_stream_cache_packet_formats(struct snd_motu *motu)
|
||||
}
|
||||
|
||||
int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate,
|
||||
unsigned int frames_per_period)
|
||||
unsigned int frames_per_period,
|
||||
unsigned int frames_per_buffer)
|
||||
{
|
||||
unsigned int curr_rate;
|
||||
int err;
|
||||
@ -174,7 +175,7 @@ int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate,
|
||||
}
|
||||
|
||||
err = amdtp_domain_set_events_per_period(&motu->domain,
|
||||
frames_per_period);
|
||||
frames_per_period, frames_per_buffer);
|
||||
if (err < 0) {
|
||||
fw_iso_resources_free(&motu->tx_resources);
|
||||
fw_iso_resources_free(&motu->rx_resources);
|
||||
|
@ -155,7 +155,8 @@ int snd_motu_stream_init_duplex(struct snd_motu *motu);
|
||||
void snd_motu_stream_destroy_duplex(struct snd_motu *motu);
|
||||
int snd_motu_stream_cache_packet_formats(struct snd_motu *motu);
|
||||
int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate,
|
||||
unsigned int frames_per_period);
|
||||
unsigned int frames_per_period,
|
||||
unsigned int frames_per_buffer);
|
||||
int snd_motu_stream_start_duplex(struct snd_motu *motu);
|
||||
void snd_motu_stream_stop_duplex(struct snd_motu *motu);
|
||||
int snd_motu_stream_lock_try(struct snd_motu *motu);
|
||||
|
@ -18,7 +18,7 @@ static int midi_capture_open(struct snd_rawmidi_substream *substream)
|
||||
|
||||
mutex_lock(&oxfw->mutex);
|
||||
|
||||
err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream, 0, 0, 0);
|
||||
err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream, 0, 0, 0, 0);
|
||||
if (err >= 0) {
|
||||
++oxfw->substreams_count;
|
||||
err = snd_oxfw_stream_start_duplex(oxfw);
|
||||
@ -45,7 +45,7 @@ static int midi_playback_open(struct snd_rawmidi_substream *substream)
|
||||
|
||||
mutex_lock(&oxfw->mutex);
|
||||
|
||||
err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->rx_stream, 0, 0, 0);
|
||||
err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->rx_stream, 0, 0, 0, 0);
|
||||
if (err >= 0) {
|
||||
++oxfw->substreams_count;
|
||||
err = snd_oxfw_stream_start_duplex(oxfw);
|
||||
|
@ -188,6 +188,7 @@ static int pcm_open(struct snd_pcm_substream *substream)
|
||||
// at current one.
|
||||
if (oxfw->substreams_count > 0 && d->events_per_period > 0) {
|
||||
unsigned int frames_per_period = d->events_per_period;
|
||||
unsigned int frames_per_buffer = d->events_per_buffer;
|
||||
|
||||
err = limit_to_current_params(substream);
|
||||
if (err < 0) {
|
||||
@ -203,6 +204,14 @@ static int pcm_open(struct snd_pcm_substream *substream)
|
||||
mutex_unlock(&oxfw->mutex);
|
||||
goto err_locked;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
|
||||
frames_per_buffer, frames_per_buffer);
|
||||
if (err < 0) {
|
||||
mutex_unlock(&oxfw->mutex);
|
||||
goto err_locked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,10 +248,12 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
|
||||
unsigned int rate = params_rate(hw_params);
|
||||
unsigned int channels = params_channels(hw_params);
|
||||
unsigned int frames_per_period = params_period_size(hw_params);
|
||||
unsigned int frames_per_buffer = params_buffer_size(hw_params);
|
||||
|
||||
mutex_lock(&oxfw->mutex);
|
||||
err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream,
|
||||
rate, channels, frames_per_period);
|
||||
rate, channels, frames_per_period,
|
||||
frames_per_buffer);
|
||||
if (err >= 0)
|
||||
++oxfw->substreams_count;
|
||||
mutex_unlock(&oxfw->mutex);
|
||||
@ -265,10 +276,12 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
|
||||
unsigned int rate = params_rate(hw_params);
|
||||
unsigned int channels = params_channels(hw_params);
|
||||
unsigned int frames_per_period = params_period_size(hw_params);
|
||||
unsigned int frames_per_buffer = params_buffer_size(hw_params);
|
||||
|
||||
mutex_lock(&oxfw->mutex);
|
||||
err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->rx_stream,
|
||||
rate, channels, frames_per_period);
|
||||
rate, channels, frames_per_period,
|
||||
frames_per_buffer);
|
||||
if (err >= 0)
|
||||
++oxfw->substreams_count;
|
||||
mutex_unlock(&oxfw->mutex);
|
||||
|
@ -245,7 +245,8 @@ static int keep_resources(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
|
||||
int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw,
|
||||
struct amdtp_stream *stream,
|
||||
unsigned int rate, unsigned int pcm_channels,
|
||||
unsigned int frames_per_period)
|
||||
unsigned int frames_per_period,
|
||||
unsigned int frames_per_buffer)
|
||||
{
|
||||
struct snd_oxfw_stream_formation formation;
|
||||
enum avc_general_plug_dir dir;
|
||||
@ -308,7 +309,7 @@ int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw,
|
||||
}
|
||||
|
||||
err = amdtp_domain_set_events_per_period(&oxfw->domain,
|
||||
frames_per_period);
|
||||
frames_per_period, frames_per_buffer);
|
||||
if (err < 0) {
|
||||
cmp_connection_release(&oxfw->in_conn);
|
||||
if (oxfw->has_output)
|
||||
|
@ -104,7 +104,8 @@ int snd_oxfw_stream_init_duplex(struct snd_oxfw *oxfw);
|
||||
int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw,
|
||||
struct amdtp_stream *stream,
|
||||
unsigned int rate, unsigned int pcm_channels,
|
||||
unsigned int frames_per_period);
|
||||
unsigned int frames_per_period,
|
||||
unsigned int frames_per_buffer);
|
||||
int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw);
|
||||
void snd_oxfw_stream_stop_duplex(struct snd_oxfw *oxfw);
|
||||
void snd_oxfw_stream_destroy_duplex(struct snd_oxfw *oxfw);
|
||||
|
@ -66,6 +66,7 @@ static int pcm_open(struct snd_pcm_substream *substream)
|
||||
// at current one.
|
||||
if (clock != SND_TSCM_CLOCK_INTERNAL || tscm->substreams_counter > 0) {
|
||||
unsigned int frames_per_period = d->events_per_period;
|
||||
unsigned int frames_per_buffer = d->events_per_buffer;
|
||||
unsigned int rate;
|
||||
|
||||
err = snd_tscm_stream_get_rate(tscm, &rate);
|
||||
@ -83,6 +84,14 @@ static int pcm_open(struct snd_pcm_substream *substream)
|
||||
mutex_unlock(&tscm->mutex);
|
||||
goto err_locked;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
|
||||
frames_per_buffer, frames_per_buffer);
|
||||
if (err < 0) {
|
||||
mutex_unlock(&tscm->mutex);
|
||||
goto err_locked;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&tscm->mutex);
|
||||
@ -118,10 +127,11 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
if (substream->runtime->status->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);
|
||||
|
||||
mutex_lock(&tscm->mutex);
|
||||
err = snd_tscm_stream_reserve_duplex(tscm, rate,
|
||||
frames_per_period);
|
||||
frames_per_period, frames_per_buffer);
|
||||
if (err >= 0)
|
||||
++tscm->substreams_counter;
|
||||
mutex_unlock(&tscm->mutex);
|
||||
|
@ -384,7 +384,8 @@ void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm)
|
||||
}
|
||||
|
||||
int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate,
|
||||
unsigned int frames_per_period)
|
||||
unsigned int frames_per_period,
|
||||
unsigned int frames_per_buffer)
|
||||
{
|
||||
unsigned int curr_rate;
|
||||
int err;
|
||||
@ -416,7 +417,7 @@ int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate,
|
||||
}
|
||||
|
||||
err = amdtp_domain_set_events_per_period(&tscm->domain,
|
||||
frames_per_period);
|
||||
frames_per_period, frames_per_buffer);
|
||||
if (err < 0) {
|
||||
fw_iso_resources_free(&tscm->tx_resources);
|
||||
fw_iso_resources_free(&tscm->rx_resources);
|
||||
|
@ -169,7 +169,8 @@ int snd_tscm_stream_init_duplex(struct snd_tscm *tscm);
|
||||
void snd_tscm_stream_update_duplex(struct snd_tscm *tscm);
|
||||
void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm);
|
||||
int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate,
|
||||
unsigned int frames_per_period);
|
||||
unsigned int frames_per_period,
|
||||
unsigned int frames_per_buffer);
|
||||
int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate);
|
||||
void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user