|
@@ -12,6 +12,11 @@
|
|
|
#define CALLBACK_TIMEOUT 200
|
|
|
#define NOTIFICATION_TIMEOUT_MS (2 * MSEC_PER_SEC)
|
|
|
|
|
|
+struct reg_params {
|
|
|
+ unsigned int count;
|
|
|
+ unsigned int size;
|
|
|
+};
|
|
|
+
|
|
|
const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = {
|
|
|
/* mode 0 */
|
|
|
[0] = 32000,
|
|
@@ -65,7 +70,9 @@ static int ensure_phase_lock(struct snd_dice *dice)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int get_register_params(struct snd_dice *dice, unsigned int params[4])
|
|
|
+static int get_register_params(struct snd_dice *dice,
|
|
|
+ struct reg_params *tx_params,
|
|
|
+ struct reg_params *rx_params)
|
|
|
{
|
|
|
__be32 reg[2];
|
|
|
int err;
|
|
@@ -73,14 +80,16 @@ static int get_register_params(struct snd_dice *dice, unsigned int params[4])
|
|
|
err = snd_dice_transaction_read_tx(dice, TX_NUMBER, reg, sizeof(reg));
|
|
|
if (err < 0)
|
|
|
return err;
|
|
|
- params[0] = min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
|
|
|
- params[1] = be32_to_cpu(reg[1]) * 4;
|
|
|
+ tx_params->count =
|
|
|
+ min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
|
|
|
+ tx_params->size = be32_to_cpu(reg[1]) * 4;
|
|
|
|
|
|
err = snd_dice_transaction_read_rx(dice, RX_NUMBER, reg, sizeof(reg));
|
|
|
if (err < 0)
|
|
|
return err;
|
|
|
- params[2] = min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
|
|
|
- params[3] = be32_to_cpu(reg[1]) * 4;
|
|
|
+ rx_params->count =
|
|
|
+ min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
|
|
|
+ rx_params->size = be32_to_cpu(reg[1]) * 4;
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -105,21 +114,21 @@ static void release_resources(struct snd_dice *dice)
|
|
|
}
|
|
|
|
|
|
static void stop_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
|
|
|
- unsigned int count, unsigned int size)
|
|
|
+ struct reg_params *params)
|
|
|
{
|
|
|
__be32 reg;
|
|
|
unsigned int i;
|
|
|
|
|
|
- for (i = 0; i < count; i++) {
|
|
|
+ for (i = 0; i < params->count; i++) {
|
|
|
reg = cpu_to_be32((u32)-1);
|
|
|
if (dir == AMDTP_IN_STREAM) {
|
|
|
snd_dice_transaction_write_tx(dice,
|
|
|
- size * i + TX_ISOCHRONOUS,
|
|
|
- ®, sizeof(reg));
|
|
|
+ params->size * i + TX_ISOCHRONOUS,
|
|
|
+ ®, sizeof(reg));
|
|
|
} else {
|
|
|
snd_dice_transaction_write_rx(dice,
|
|
|
- size * i + RX_ISOCHRONOUS,
|
|
|
- ®, sizeof(reg));
|
|
|
+ params->size * i + RX_ISOCHRONOUS,
|
|
|
+ ®, sizeof(reg));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -180,8 +189,7 @@ static int keep_resources(struct snd_dice *dice,
|
|
|
}
|
|
|
|
|
|
static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
|
|
|
- unsigned int rate, unsigned int count,
|
|
|
- unsigned int size)
|
|
|
+ unsigned int rate, struct reg_params *params)
|
|
|
{
|
|
|
__be32 reg[2];
|
|
|
unsigned int i, pcm_chs, midi_ports;
|
|
@@ -197,15 +205,15 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
|
|
|
resources = dice->rx_resources;
|
|
|
}
|
|
|
|
|
|
- for (i = 0; i < count; i++) {
|
|
|
+ for (i = 0; i < params->count; i++) {
|
|
|
if (dir == AMDTP_IN_STREAM) {
|
|
|
err = snd_dice_transaction_read_tx(dice,
|
|
|
- size * i + TX_NUMBER_AUDIO,
|
|
|
- reg, sizeof(reg));
|
|
|
+ params->size * i + TX_NUMBER_AUDIO,
|
|
|
+ reg, sizeof(reg));
|
|
|
} else {
|
|
|
err = snd_dice_transaction_read_rx(dice,
|
|
|
- size * i + RX_NUMBER_AUDIO,
|
|
|
- reg, sizeof(reg));
|
|
|
+ params->size * i + RX_NUMBER_AUDIO,
|
|
|
+ reg, sizeof(reg));
|
|
|
}
|
|
|
if (err < 0)
|
|
|
return err;
|
|
@@ -219,12 +227,12 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
|
|
|
reg[0] = cpu_to_be32(resources[i].channel);
|
|
|
if (dir == AMDTP_IN_STREAM) {
|
|
|
err = snd_dice_transaction_write_tx(dice,
|
|
|
- size * i + TX_ISOCHRONOUS,
|
|
|
- reg, sizeof(reg[0]));
|
|
|
+ params->size * i + TX_ISOCHRONOUS,
|
|
|
+ reg, sizeof(reg[0]));
|
|
|
} else {
|
|
|
err = snd_dice_transaction_write_rx(dice,
|
|
|
- size * i + RX_ISOCHRONOUS,
|
|
|
- reg, sizeof(reg[0]));
|
|
|
+ params->size * i + RX_ISOCHRONOUS,
|
|
|
+ reg, sizeof(reg[0]));
|
|
|
}
|
|
|
if (err < 0)
|
|
|
return err;
|
|
@@ -247,14 +255,14 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
|
|
|
{
|
|
|
unsigned int curr_rate;
|
|
|
unsigned int i;
|
|
|
- unsigned int reg_params[4];
|
|
|
+ struct reg_params tx_params, rx_params;
|
|
|
bool need_to_start;
|
|
|
int err;
|
|
|
|
|
|
if (dice->substreams_counter == 0)
|
|
|
return -EIO;
|
|
|
|
|
|
- err = get_register_params(dice, reg_params);
|
|
|
+ err = get_register_params(dice, &tx_params, &rx_params);
|
|
|
if (err < 0)
|
|
|
return err;
|
|
|
|
|
@@ -271,12 +279,12 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
|
|
|
|
|
|
/* Judge to need to restart streams. */
|
|
|
for (i = 0; i < MAX_STREAMS; i++) {
|
|
|
- if (i < reg_params[0]) {
|
|
|
+ if (i < tx_params.count) {
|
|
|
if (amdtp_streaming_error(&dice->tx_stream[i]) ||
|
|
|
!amdtp_stream_running(&dice->tx_stream[i]))
|
|
|
break;
|
|
|
}
|
|
|
- if (i < reg_params[2]) {
|
|
|
+ if (i < rx_params.count) {
|
|
|
if (amdtp_streaming_error(&dice->rx_stream[i]) ||
|
|
|
!amdtp_stream_running(&dice->rx_stream[i]))
|
|
|
break;
|
|
@@ -287,10 +295,8 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
|
|
|
if (need_to_start) {
|
|
|
/* Stop transmission. */
|
|
|
snd_dice_transaction_clear_enable(dice);
|
|
|
- stop_streams(dice, AMDTP_IN_STREAM, reg_params[0],
|
|
|
- reg_params[1]);
|
|
|
- stop_streams(dice, AMDTP_OUT_STREAM, reg_params[2],
|
|
|
- reg_params[3]);
|
|
|
+ stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
|
|
|
+ stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
|
|
|
release_resources(dice);
|
|
|
|
|
|
err = ensure_phase_lock(dice);
|
|
@@ -301,12 +307,10 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
|
|
|
}
|
|
|
|
|
|
/* Start both streams. */
|
|
|
- err = start_streams(dice, AMDTP_IN_STREAM, rate, reg_params[0],
|
|
|
- reg_params[1]);
|
|
|
+ err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);
|
|
|
if (err < 0)
|
|
|
goto error;
|
|
|
- err = start_streams(dice, AMDTP_OUT_STREAM, rate, reg_params[2],
|
|
|
- reg_params[3]);
|
|
|
+ err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params);
|
|
|
if (err < 0)
|
|
|
goto error;
|
|
|
|
|
@@ -318,10 +322,10 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
|
|
|
}
|
|
|
|
|
|
for (i = 0; i < MAX_STREAMS; i++) {
|
|
|
- if ((i < reg_params[0] &&
|
|
|
+ if ((i < tx_params.count &&
|
|
|
!amdtp_stream_wait_callback(&dice->tx_stream[i],
|
|
|
CALLBACK_TIMEOUT)) ||
|
|
|
- (i < reg_params[2] &&
|
|
|
+ (i < rx_params.count &&
|
|
|
!amdtp_stream_wait_callback(&dice->rx_stream[i],
|
|
|
CALLBACK_TIMEOUT))) {
|
|
|
err = -ETIMEDOUT;
|
|
@@ -333,8 +337,8 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
|
|
|
return err;
|
|
|
error:
|
|
|
snd_dice_transaction_clear_enable(dice);
|
|
|
- stop_streams(dice, AMDTP_IN_STREAM, reg_params[0], reg_params[1]);
|
|
|
- stop_streams(dice, AMDTP_OUT_STREAM, reg_params[2], reg_params[3]);
|
|
|
+ stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
|
|
|
+ stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
|
|
|
release_resources(dice);
|
|
|
return err;
|
|
|
}
|
|
@@ -346,18 +350,16 @@ error:
|
|
|
*/
|
|
|
void snd_dice_stream_stop_duplex(struct snd_dice *dice)
|
|
|
{
|
|
|
- unsigned int reg_params[4];
|
|
|
+ struct reg_params tx_params, rx_params;
|
|
|
|
|
|
if (dice->substreams_counter > 0)
|
|
|
return;
|
|
|
|
|
|
snd_dice_transaction_clear_enable(dice);
|
|
|
|
|
|
- if (get_register_params(dice, reg_params) == 0) {
|
|
|
- stop_streams(dice, AMDTP_IN_STREAM, reg_params[0],
|
|
|
- reg_params[1]);
|
|
|
- stop_streams(dice, AMDTP_OUT_STREAM, reg_params[2],
|
|
|
- reg_params[3]);
|
|
|
+ if (get_register_params(dice, &tx_params, &rx_params) == 0) {
|
|
|
+ stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
|
|
|
+ stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
|
|
|
}
|
|
|
|
|
|
release_resources(dice);
|
|
@@ -444,15 +446,13 @@ end:
|
|
|
|
|
|
void snd_dice_stream_destroy_duplex(struct snd_dice *dice)
|
|
|
{
|
|
|
- unsigned int reg_params[4];
|
|
|
+ struct reg_params tx_params, rx_params;
|
|
|
|
|
|
snd_dice_transaction_clear_enable(dice);
|
|
|
|
|
|
- if (get_register_params(dice, reg_params) == 0) {
|
|
|
- stop_streams(dice, AMDTP_IN_STREAM, reg_params[0],
|
|
|
- reg_params[1]);
|
|
|
- stop_streams(dice, AMDTP_OUT_STREAM, reg_params[2],
|
|
|
- reg_params[3]);
|
|
|
+ if (get_register_params(dice, &tx_params, &rx_params) == 0) {
|
|
|
+ stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
|
|
|
+ stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
|
|
|
}
|
|
|
|
|
|
release_resources(dice);
|
|
@@ -462,7 +462,7 @@ void snd_dice_stream_destroy_duplex(struct snd_dice *dice)
|
|
|
|
|
|
void snd_dice_stream_update_duplex(struct snd_dice *dice)
|
|
|
{
|
|
|
- unsigned int reg_params[4];
|
|
|
+ struct reg_params tx_params, rx_params;
|
|
|
|
|
|
/*
|
|
|
* On a bus reset, the DICE firmware disables streaming and then goes
|
|
@@ -474,11 +474,9 @@ void snd_dice_stream_update_duplex(struct snd_dice *dice)
|
|
|
*/
|
|
|
dice->global_enabled = false;
|
|
|
|
|
|
- if (get_register_params(dice, reg_params) == 0) {
|
|
|
- stop_streams(dice, AMDTP_IN_STREAM, reg_params[0],
|
|
|
- reg_params[1]);
|
|
|
- stop_streams(dice, AMDTP_OUT_STREAM, reg_params[2],
|
|
|
- reg_params[3]);
|
|
|
+ if (get_register_params(dice, &tx_params, &rx_params) == 0) {
|
|
|
+ stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
|
|
|
+ stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
|
|
|
}
|
|
|
}
|
|
|
|