mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
ALSA: firewire-lib: use union for directional parameters
Some parameters of struct amdtp_stream is dependent on direction. This commit uses union for such parameters to distinguish from common parameters. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
8d3f1fdf52
commit
d3d10a4a1b
@ -83,7 +83,7 @@ int amdtp_am824_set_parameters(struct amdtp_stream *s, unsigned int rate,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
s->fdf = AMDTP_FDF_AM824 | s->sfc;
|
||||
s->ctx_data.rx.fdf = AMDTP_FDF_AM824 | s->sfc;
|
||||
|
||||
p->pcm_channels = pcm_channels;
|
||||
p->midi_ports = midi_ports;
|
||||
|
@ -260,11 +260,18 @@ int amdtp_stream_set_parameters(struct amdtp_stream *s, unsigned int rate,
|
||||
s->data_block_quadlets = data_block_quadlets;
|
||||
s->syt_interval = amdtp_syt_intervals[sfc];
|
||||
|
||||
/* default buffering in the device */
|
||||
s->transfer_delay = TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE;
|
||||
if (s->flags & CIP_BLOCKING)
|
||||
/* additional buffering needed to adjust for no-data packets */
|
||||
s->transfer_delay += TICKS_PER_SECOND * s->syt_interval / rate;
|
||||
// default buffering in the device.
|
||||
if (s->direction == AMDTP_OUT_STREAM) {
|
||||
s->ctx_data.rx.transfer_delay =
|
||||
TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE;
|
||||
|
||||
if (s->flags & CIP_BLOCKING) {
|
||||
// additional buffering needed to adjust for no-data
|
||||
// packets.
|
||||
s->ctx_data.rx.transfer_delay +=
|
||||
TICKS_PER_SECOND * s->syt_interval / rate;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -321,10 +328,10 @@ static unsigned int calculate_data_blocks(struct amdtp_stream *s,
|
||||
/* Non-blocking mode. */
|
||||
} else {
|
||||
if (!cip_sfc_is_base_44100(s->sfc)) {
|
||||
/* Sample_rate / 8000 is an integer, and precomputed. */
|
||||
data_blocks = s->data_block_state;
|
||||
// Sample_rate / 8000 is an integer, and precomputed.
|
||||
data_blocks = s->ctx_data.rx.data_block_state;
|
||||
} else {
|
||||
phase = s->data_block_state;
|
||||
phase = s->ctx_data.rx.data_block_state;
|
||||
|
||||
/*
|
||||
* This calculates the number of data blocks per packet so that
|
||||
@ -343,7 +350,7 @@ static unsigned int calculate_data_blocks(struct amdtp_stream *s,
|
||||
data_blocks = 11 * (s->sfc >> 1) + (phase == 0);
|
||||
if (++phase >= (80 >> (s->sfc >> 1)))
|
||||
phase = 0;
|
||||
s->data_block_state = phase;
|
||||
s->ctx_data.rx.data_block_state = phase;
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,9 +362,10 @@ static unsigned int calculate_syt(struct amdtp_stream *s,
|
||||
{
|
||||
unsigned int syt_offset, phase, index, syt;
|
||||
|
||||
if (s->last_syt_offset < TICKS_PER_CYCLE) {
|
||||
if (s->ctx_data.rx.last_syt_offset < TICKS_PER_CYCLE) {
|
||||
if (!cip_sfc_is_base_44100(s->sfc))
|
||||
syt_offset = s->last_syt_offset + s->syt_offset_state;
|
||||
syt_offset = s->ctx_data.rx.last_syt_offset +
|
||||
s->ctx_data.rx.syt_offset_state;
|
||||
else {
|
||||
/*
|
||||
* The time, in ticks, of the n'th SYT_INTERVAL sample is:
|
||||
@ -369,21 +377,21 @@ static unsigned int calculate_syt(struct amdtp_stream *s,
|
||||
* 1386 1386 1387 1386 1386 1386 1387 1386 1386 1386 1387 ...
|
||||
* This code generates _exactly_ the same sequence.
|
||||
*/
|
||||
phase = s->syt_offset_state;
|
||||
phase = s->ctx_data.rx.syt_offset_state;
|
||||
index = phase % 13;
|
||||
syt_offset = s->last_syt_offset;
|
||||
syt_offset = s->ctx_data.rx.last_syt_offset;
|
||||
syt_offset += 1386 + ((index && !(index & 3)) ||
|
||||
phase == 146);
|
||||
if (++phase >= 147)
|
||||
phase = 0;
|
||||
s->syt_offset_state = phase;
|
||||
s->ctx_data.rx.syt_offset_state = phase;
|
||||
}
|
||||
} else
|
||||
syt_offset = s->last_syt_offset - TICKS_PER_CYCLE;
|
||||
s->last_syt_offset = syt_offset;
|
||||
syt_offset = s->ctx_data.rx.last_syt_offset - TICKS_PER_CYCLE;
|
||||
s->ctx_data.rx.last_syt_offset = syt_offset;
|
||||
|
||||
if (syt_offset < TICKS_PER_CYCLE) {
|
||||
syt_offset += s->transfer_delay;
|
||||
syt_offset += s->ctx_data.rx.transfer_delay;
|
||||
syt = (cycle + syt_offset / TICKS_PER_CYCLE) << 12;
|
||||
syt += syt_offset % TICKS_PER_CYCLE;
|
||||
|
||||
@ -457,7 +465,8 @@ static inline int queue_out_packet(struct amdtp_stream *s,
|
||||
|
||||
static inline int queue_in_packet(struct amdtp_stream *s)
|
||||
{
|
||||
return queue_packet(s, IR_HEADER_SIZE, s->max_payload_length);
|
||||
return queue_packet(s, s->ctx_data.tx.ctx_header_size,
|
||||
s->ctx_data.tx.max_payload_length);
|
||||
}
|
||||
|
||||
static int handle_out_packet(struct amdtp_stream *s,
|
||||
@ -484,9 +493,9 @@ static int handle_out_packet(struct amdtp_stream *s,
|
||||
((s->sph << CIP_SPH_SHIFT) & CIP_SPH_MASK) |
|
||||
s->data_block_counter);
|
||||
buffer[1] = cpu_to_be32(CIP_EOH |
|
||||
((s->fmt << CIP_FMT_SHIFT) & CIP_FMT_MASK) |
|
||||
((s->fdf << CIP_FDF_SHIFT) & CIP_FDF_MASK) |
|
||||
(syt & CIP_SYT_MASK));
|
||||
((s->fmt << CIP_FMT_SHIFT) & CIP_FMT_MASK) |
|
||||
((s->ctx_data.rx.fdf << CIP_FDF_SHIFT) & CIP_FDF_MASK) |
|
||||
(syt & CIP_SYT_MASK));
|
||||
|
||||
if (!(s->flags & CIP_DBC_IS_END_EVENT))
|
||||
s->data_block_counter =
|
||||
@ -610,14 +619,14 @@ static int handle_in_packet(struct amdtp_stream *s,
|
||||
data_block_counter = s->data_block_counter;
|
||||
|
||||
if (((s->flags & CIP_SKIP_DBC_ZERO_CHECK) &&
|
||||
data_block_counter == s->tx_first_dbc) ||
|
||||
data_block_counter == s->ctx_data.tx.first_dbc) ||
|
||||
s->data_block_counter == UINT_MAX) {
|
||||
lost = false;
|
||||
} else if (!(s->flags & CIP_DBC_IS_END_EVENT)) {
|
||||
lost = data_block_counter != s->data_block_counter;
|
||||
} else {
|
||||
if (data_blocks > 0 && s->tx_dbc_interval > 0)
|
||||
dbc_interval = s->tx_dbc_interval;
|
||||
if (data_blocks > 0 && s->ctx_data.tx.dbc_interval > 0)
|
||||
dbc_interval = s->ctx_data.tx.dbc_interval;
|
||||
else
|
||||
dbc_interval = data_blocks;
|
||||
|
||||
@ -740,11 +749,11 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp,
|
||||
if (s->packet_index < 0)
|
||||
return;
|
||||
|
||||
/* The number of packets in buffer */
|
||||
packets = header_length / IR_HEADER_SIZE;
|
||||
// The number of packets in buffer.
|
||||
packets = header_length / s->ctx_data.tx.ctx_header_size;
|
||||
|
||||
/* For buffer-over-run prevention. */
|
||||
max_payload_length = s->max_payload_length;
|
||||
max_payload_length = s->ctx_data.tx.max_payload_length;
|
||||
|
||||
for (i = 0; i < packets; i++) {
|
||||
u32 iso_header = be32_to_cpu(ctx_header[0]);
|
||||
@ -765,7 +774,7 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp,
|
||||
if (s->handle_packet(s, payload_length, cycle, i) < 0)
|
||||
break;
|
||||
|
||||
ctx_header += IR_HEADER_SIZE / sizeof(__be32);
|
||||
ctx_header += s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header);
|
||||
}
|
||||
|
||||
/* Queueing error or detecting invalid payload. */
|
||||
@ -837,7 +846,7 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed)
|
||||
static const struct {
|
||||
unsigned int data_block;
|
||||
unsigned int syt_offset;
|
||||
} initial_state[] = {
|
||||
} *entry, initial_state[] = {
|
||||
[CIP_SFC_32000] = { 4, 3072 },
|
||||
[CIP_SFC_48000] = { 6, 1024 },
|
||||
[CIP_SFC_96000] = { 12, 1024 },
|
||||
@ -846,7 +855,7 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed)
|
||||
[CIP_SFC_88200] = { 0, 67 },
|
||||
[CIP_SFC_176400] = { 0, 67 },
|
||||
};
|
||||
unsigned int header_size;
|
||||
unsigned int ctx_header_size;
|
||||
enum dma_data_direction dir;
|
||||
int type, tag, err;
|
||||
|
||||
@ -858,23 +867,26 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed)
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
if (s->direction == AMDTP_IN_STREAM)
|
||||
if (s->direction == AMDTP_IN_STREAM) {
|
||||
s->data_block_counter = UINT_MAX;
|
||||
else
|
||||
} else {
|
||||
entry = &initial_state[s->sfc];
|
||||
|
||||
s->data_block_counter = 0;
|
||||
s->data_block_state = initial_state[s->sfc].data_block;
|
||||
s->syt_offset_state = initial_state[s->sfc].syt_offset;
|
||||
s->last_syt_offset = TICKS_PER_CYCLE;
|
||||
s->ctx_data.rx.data_block_state = entry->data_block;
|
||||
s->ctx_data.rx.syt_offset_state = entry->syt_offset;
|
||||
s->ctx_data.rx.last_syt_offset = TICKS_PER_CYCLE;
|
||||
}
|
||||
|
||||
/* initialize packet buffer */
|
||||
if (s->direction == AMDTP_IN_STREAM) {
|
||||
dir = DMA_FROM_DEVICE;
|
||||
type = FW_ISO_CONTEXT_RECEIVE;
|
||||
header_size = IR_HEADER_SIZE;
|
||||
ctx_header_size = IR_HEADER_SIZE;
|
||||
} else {
|
||||
dir = DMA_TO_DEVICE;
|
||||
type = FW_ISO_CONTEXT_TRANSMIT;
|
||||
header_size = OUT_PACKET_HEADER_SIZE;
|
||||
ctx_header_size = OUT_PACKET_HEADER_SIZE;
|
||||
}
|
||||
err = iso_packets_buffer_init(&s->buffer, s->unit, QUEUE_LENGTH,
|
||||
amdtp_stream_get_max_payload(s), dir);
|
||||
@ -882,8 +894,8 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed)
|
||||
goto err_unlock;
|
||||
|
||||
s->context = fw_iso_context_create(fw_parent_device(s->unit)->card,
|
||||
type, channel, speed, header_size,
|
||||
amdtp_stream_first_callback, s);
|
||||
type, channel, speed, ctx_header_size,
|
||||
amdtp_stream_first_callback, s);
|
||||
if (IS_ERR(s->context)) {
|
||||
err = PTR_ERR(s->context);
|
||||
if (err == -EBUSY)
|
||||
@ -894,8 +906,11 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed)
|
||||
|
||||
amdtp_stream_update(s);
|
||||
|
||||
if (s->direction == AMDTP_IN_STREAM)
|
||||
s->max_payload_length = amdtp_stream_get_max_payload(s);
|
||||
if (s->direction == AMDTP_IN_STREAM) {
|
||||
s->ctx_data.tx.max_payload_length =
|
||||
amdtp_stream_get_max_payload(s);
|
||||
s->ctx_data.tx.ctx_header_size = ctx_header_size;
|
||||
}
|
||||
|
||||
if (s->flags & CIP_NO_HEADER)
|
||||
s->tag = TAG_NO_CIP_HEADER;
|
||||
|
@ -111,7 +111,31 @@ struct amdtp_stream {
|
||||
int (*handle_packet)(struct amdtp_stream *s,
|
||||
unsigned int payload_quadlets, unsigned int cycle,
|
||||
unsigned int index);
|
||||
unsigned int max_payload_length;
|
||||
union {
|
||||
struct {
|
||||
unsigned int ctx_header_size;
|
||||
|
||||
// limit for payload of iso packet.
|
||||
unsigned int max_payload_length;
|
||||
|
||||
// For quirks of CIP headers.
|
||||
// Fixed interval of dbc between previos/current
|
||||
// packets.
|
||||
unsigned int dbc_interval;
|
||||
// Indicate the value of dbc field in a first packet.
|
||||
unsigned int first_dbc;
|
||||
} tx;
|
||||
struct {
|
||||
// To calculate CIP data blocks and tstamp.
|
||||
unsigned int transfer_delay;
|
||||
unsigned int data_block_state;
|
||||
unsigned int last_syt_offset;
|
||||
unsigned int syt_offset_state;
|
||||
|
||||
// To generate CIP header.
|
||||
unsigned int fdf;
|
||||
} rx;
|
||||
} ctx_data;
|
||||
|
||||
/* For CIP headers. */
|
||||
unsigned int source_node_id_field;
|
||||
@ -119,19 +143,10 @@ struct amdtp_stream {
|
||||
unsigned int data_block_counter;
|
||||
unsigned int sph;
|
||||
unsigned int fmt;
|
||||
unsigned int fdf;
|
||||
/* quirk: fixed interval of dbc between previos/current packets. */
|
||||
unsigned int tx_dbc_interval;
|
||||
/* quirk: indicate the value of dbc field in a first packet. */
|
||||
unsigned int tx_first_dbc;
|
||||
|
||||
/* Internal flags. */
|
||||
enum cip_sfc sfc;
|
||||
unsigned int syt_interval;
|
||||
unsigned int transfer_delay;
|
||||
unsigned int data_block_state;
|
||||
unsigned int last_syt_offset;
|
||||
unsigned int syt_offset_state;
|
||||
|
||||
/* For a PCM substream processing. */
|
||||
struct snd_pcm_substream *pcm;
|
||||
|
@ -128,7 +128,7 @@ int amdtp_dot_set_parameters(struct amdtp_stream *s, unsigned int rate,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
s->fdf = AMDTP_FDF_AM824 | s->sfc;
|
||||
s->ctx_data.rx.fdf = AMDTP_FDF_AM824 | s->sfc;
|
||||
|
||||
p->pcm_channels = pcm_channels;
|
||||
|
||||
|
@ -165,13 +165,13 @@ int snd_efw_stream_init_duplex(struct snd_efw *efw)
|
||||
(efw->firmware_version == 0x5070000 ||
|
||||
efw->firmware_version == 0x5070300 ||
|
||||
efw->firmware_version == 0x5080000))
|
||||
efw->tx_stream.tx_first_dbc = 0x02;
|
||||
efw->tx_stream.ctx_data.tx.first_dbc = 0x02;
|
||||
/* AudioFire9 always reports wrong dbs. */
|
||||
if (efw->is_af9)
|
||||
efw->tx_stream.flags |= CIP_WRONG_DBS;
|
||||
/* Firmware version 5.5 reports fixed interval for dbc. */
|
||||
if (efw->firmware_version == 0x5050000)
|
||||
efw->tx_stream.tx_dbc_interval = 8;
|
||||
efw->tx_stream.ctx_data.tx.dbc_interval = 8;
|
||||
|
||||
err = init_stream(efw, &efw->rx_stream);
|
||||
if (err < 0) {
|
||||
|
@ -429,7 +429,7 @@ int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit,
|
||||
return err;
|
||||
|
||||
s->sph = 1;
|
||||
s->fdf = MOTU_FDF_AM824;
|
||||
s->ctx_data.rx.fdf = MOTU_FDF_AM824;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -224,7 +224,7 @@ int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit,
|
||||
return 0;
|
||||
|
||||
/* Use fixed value for FDF field. */
|
||||
s->fdf = 0x00;
|
||||
s->ctx_data.rx.fdf = 0x00;
|
||||
|
||||
/* This protocol uses fixed number of data channels for PCM samples. */
|
||||
p = s->protocol;
|
||||
|
Loading…
Reference in New Issue
Block a user