ALSA: dice: enable to change current sampling transmission frequency
This is a preparation for userspace applications to change current sampling transmission frequency via ALSA PCM interface. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
20b9454479
commit
afa617f219
@ -62,9 +62,11 @@ int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate,
|
|||||||
* This operation has an effect to synchronize GLOBAL_STATUS/GLOBAL_SAMPLE_RATE
|
* This operation has an effect to synchronize GLOBAL_STATUS/GLOBAL_SAMPLE_RATE
|
||||||
* to GLOBAL_STATUS. Especially, just after powering on, these are different.
|
* to GLOBAL_STATUS. Especially, just after powering on, these are different.
|
||||||
*/
|
*/
|
||||||
static int ensure_phase_lock(struct snd_dice *dice)
|
static int ensure_phase_lock(struct snd_dice *dice, unsigned int rate)
|
||||||
{
|
{
|
||||||
__be32 reg, nominal;
|
__be32 reg, nominal;
|
||||||
|
u32 data;
|
||||||
|
int i;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT,
|
err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT,
|
||||||
@ -72,9 +74,21 @@ static int ensure_phase_lock(struct snd_dice *dice)
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
data = be32_to_cpu(reg);
|
||||||
|
|
||||||
|
data &= ~CLOCK_RATE_MASK;
|
||||||
|
for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
|
||||||
|
if (snd_dice_rates[i] == rate)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == ARRAY_SIZE(snd_dice_rates))
|
||||||
|
return -EINVAL;
|
||||||
|
data |= i << CLOCK_RATE_SHIFT;
|
||||||
|
|
||||||
if (completion_done(&dice->clock_accepted))
|
if (completion_done(&dice->clock_accepted))
|
||||||
reinit_completion(&dice->clock_accepted);
|
reinit_completion(&dice->clock_accepted);
|
||||||
|
|
||||||
|
reg = cpu_to_be32(data);
|
||||||
err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT,
|
err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT,
|
||||||
®, sizeof(reg));
|
®, sizeof(reg));
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@ -220,6 +234,7 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
|
|||||||
unsigned int rate, struct reg_params *params)
|
unsigned int rate, struct reg_params *params)
|
||||||
{
|
{
|
||||||
__be32 reg[2];
|
__be32 reg[2];
|
||||||
|
enum snd_dice_rate_mode mode;
|
||||||
unsigned int i, pcm_chs, midi_ports;
|
unsigned int i, pcm_chs, midi_ports;
|
||||||
struct amdtp_stream *streams;
|
struct amdtp_stream *streams;
|
||||||
struct fw_iso_resources *resources;
|
struct fw_iso_resources *resources;
|
||||||
@ -234,12 +249,23 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
|
|||||||
resources = dice->rx_resources;
|
resources = dice->rx_resources;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
for (i = 0; i < params->count; i++) {
|
for (i = 0; i < params->count; i++) {
|
||||||
|
unsigned int pcm_cache;
|
||||||
|
unsigned int midi_cache;
|
||||||
|
|
||||||
if (dir == AMDTP_IN_STREAM) {
|
if (dir == AMDTP_IN_STREAM) {
|
||||||
|
pcm_cache = dice->tx_pcm_chs[i][mode];
|
||||||
|
midi_cache = dice->tx_midi_ports[i];
|
||||||
err = snd_dice_transaction_read_tx(dice,
|
err = snd_dice_transaction_read_tx(dice,
|
||||||
params->size * i + TX_NUMBER_AUDIO,
|
params->size * i + TX_NUMBER_AUDIO,
|
||||||
reg, sizeof(reg));
|
reg, sizeof(reg));
|
||||||
} else {
|
} else {
|
||||||
|
pcm_cache = dice->rx_pcm_chs[i][mode];
|
||||||
|
midi_cache = dice->rx_midi_ports[i];
|
||||||
err = snd_dice_transaction_read_rx(dice,
|
err = snd_dice_transaction_read_rx(dice,
|
||||||
params->size * i + RX_NUMBER_AUDIO,
|
params->size * i + RX_NUMBER_AUDIO,
|
||||||
reg, sizeof(reg));
|
reg, sizeof(reg));
|
||||||
@ -249,6 +275,14 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
|
|||||||
pcm_chs = be32_to_cpu(reg[0]);
|
pcm_chs = be32_to_cpu(reg[0]);
|
||||||
midi_ports = be32_to_cpu(reg[1]);
|
midi_ports = be32_to_cpu(reg[1]);
|
||||||
|
|
||||||
|
/* These are important for developer of this driver. */
|
||||||
|
if (pcm_chs != pcm_cache || midi_ports != midi_cache) {
|
||||||
|
dev_info(&dice->unit->device,
|
||||||
|
"cache mismatch: pcm: %u:%u, midi: %u:%u\n",
|
||||||
|
pcm_chs, pcm_cache, midi_ports, midi_cache);
|
||||||
|
return -EPROTO;
|
||||||
|
}
|
||||||
|
|
||||||
err = keep_resources(dice, dir, i, rate, pcm_chs, midi_ports);
|
err = keep_resources(dice, dir, i, rate, pcm_chs, midi_ports);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
@ -300,12 +334,17 @@ static int start_duplex_streams(struct snd_dice *dice, unsigned int rate)
|
|||||||
snd_dice_transaction_clear_enable(dice);
|
snd_dice_transaction_clear_enable(dice);
|
||||||
release_resources(dice);
|
release_resources(dice);
|
||||||
|
|
||||||
err = ensure_phase_lock(dice);
|
err = ensure_phase_lock(dice, rate);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(&dice->unit->device, "fail to ensure phase lock\n");
|
dev_err(&dice->unit->device, "fail to ensure phase lock\n");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Likely to have changed stream formats. */
|
||||||
|
err = get_register_params(dice, &tx_params, &rx_params);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
/* Start both streams. */
|
/* Start both streams. */
|
||||||
err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);
|
err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@ -366,7 +405,7 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
|
|||||||
if (rate == 0)
|
if (rate == 0)
|
||||||
rate = curr_rate;
|
rate = curr_rate;
|
||||||
if (rate != curr_rate)
|
if (rate != curr_rate)
|
||||||
return -EINVAL;
|
goto restart;
|
||||||
|
|
||||||
/* Check error of packet streaming. */
|
/* Check error of packet streaming. */
|
||||||
for (i = 0; i < MAX_STREAMS; ++i) {
|
for (i = 0; i < MAX_STREAMS; ++i) {
|
||||||
@ -560,7 +599,7 @@ int snd_dice_stream_detect_current_formats(struct snd_dice *dice)
|
|||||||
* invalid stream formats. Selecting clock parameters have an effect
|
* invalid stream formats. Selecting clock parameters have an effect
|
||||||
* for the unit to refine it.
|
* for the unit to refine it.
|
||||||
*/
|
*/
|
||||||
err = ensure_phase_lock(dice);
|
err = ensure_phase_lock(dice, rate);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user