Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 341682cd authored by Clemens Ladisch's avatar Clemens Ladisch
Browse files

ALSA: dice: allow all sample rates



Instead of forcing a constant 44.1 kHz, read the current sample rate
from the device when opening the PCM device.

Actually changing the sample rate requires some separate controller
application.

Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
parent 6abce9e6
Loading
Loading
Loading
Loading
+42 −13
Original line number Original line Diff line number Diff line
@@ -75,6 +75,7 @@
#define  CLOCK_RATE_ANY_MID		0x00000800
#define  CLOCK_RATE_ANY_MID		0x00000800
#define  CLOCK_RATE_ANY_HIGH		0x00000900
#define  CLOCK_RATE_ANY_HIGH		0x00000900
#define  CLOCK_RATE_NONE		0x00000a00
#define  CLOCK_RATE_NONE		0x00000a00
#define  CLOCK_RATE_SHIFT		8
#define GLOBAL_ENABLE			0x050
#define GLOBAL_ENABLE			0x050
#define  ENABLE				0x00000001
#define  ENABLE				0x00000001
#define GLOBAL_STATUS			0x054
#define GLOBAL_STATUS			0x054
@@ -248,6 +249,16 @@ MODULE_DESCRIPTION("DICE driver");
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_LICENSE("GPL v2");
MODULE_LICENSE("GPL v2");


static const unsigned int dice_rates[] = {
	[0] =  32000,
	[1] =  44100,
	[2] =  48000,
	[3] =  88200,
	[4] =  96000,
	[5] = 176400,
	[6] = 192000,
};

static inline u64 global_address(struct dice *dice, unsigned int offset)
static inline u64 global_address(struct dice *dice, unsigned int offset)
{
{
	return DICE_PRIVATE_SPACE + dice->global_offset + offset;
	return DICE_PRIVATE_SPACE + dice->global_offset + offset;
@@ -508,9 +519,6 @@ static int dice_open(struct snd_pcm_substream *substream)
			SNDRV_PCM_INFO_INTERLEAVED |
			SNDRV_PCM_INFO_INTERLEAVED |
			SNDRV_PCM_INFO_BLOCK_TRANSFER,
			SNDRV_PCM_INFO_BLOCK_TRANSFER,
		.formats = AMDTP_OUT_PCM_FORMAT_BITS,
		.formats = AMDTP_OUT_PCM_FORMAT_BITS,
		.rates = SNDRV_PCM_RATE_44100,
		.rate_min = 44100,
		.rate_max = 44100,
		.buffer_bytes_max = 16 * 1024 * 1024,
		.buffer_bytes_max = 16 * 1024 * 1024,
		.period_bytes_min = 1,
		.period_bytes_min = 1,
		.period_bytes_max = UINT_MAX,
		.period_bytes_max = UINT_MAX,
@@ -519,9 +527,20 @@ static int dice_open(struct snd_pcm_substream *substream)
	};
	};
	struct dice *dice = substream->private_data;
	struct dice *dice = substream->private_data;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct snd_pcm_runtime *runtime = substream->runtime;
	__be32 number_audio, number_midi;
	__be32 clock_sel, number_audio, number_midi;
	unsigned int rate;
	int err;
	int err;


	err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST,
				 global_address(dice, GLOBAL_CLOCK_SELECT),
				 &clock_sel, 4);
	if (err < 0)
		return err;
	rate = (be32_to_cpu(clock_sel) & CLOCK_RATE_MASK) >> CLOCK_RATE_SHIFT;
	if (rate >= ARRAY_SIZE(dice_rates))
		return -ENXIO;
	rate = dice_rates[rate];

	err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST,
	err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST,
				 rx_address(dice, RX_NUMBER_AUDIO),
				 rx_address(dice, RX_NUMBER_AUDIO),
				 &number_audio, 4);
				 &number_audio, 4);
@@ -534,10 +553,14 @@ static int dice_open(struct snd_pcm_substream *substream)
		return err;
		return err;


	runtime->hw = hardware;
	runtime->hw = hardware;

	runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
	snd_pcm_limit_hw_rates(runtime);

	runtime->hw.channels_min = be32_to_cpu(number_audio);
	runtime->hw.channels_min = be32_to_cpu(number_audio);
	runtime->hw.channels_max = be32_to_cpu(number_audio);
	runtime->hw.channels_max = be32_to_cpu(number_audio);


	amdtp_out_stream_set_rate(&dice->stream, 44100);
	amdtp_out_stream_set_rate(&dice->stream, rate);
	amdtp_out_stream_set_pcm(&dice->stream, be32_to_cpu(number_audio));
	amdtp_out_stream_set_pcm(&dice->stream, be32_to_cpu(number_audio));
	amdtp_out_stream_set_midi(&dice->stream, be32_to_cpu(number_midi));
	amdtp_out_stream_set_midi(&dice->stream, be32_to_cpu(number_midi));


@@ -746,17 +769,9 @@ static int dice_create_pcm(struct dice *dice)
		.page      = snd_pcm_lib_get_vmalloc_page,
		.page      = snd_pcm_lib_get_vmalloc_page,
		.mmap      = snd_pcm_lib_mmap_vmalloc,
		.mmap      = snd_pcm_lib_mmap_vmalloc,
	};
	};
	__be32 clock;
	struct snd_pcm *pcm;
	struct snd_pcm *pcm;
	int err;
	int err;


	clock = cpu_to_be32(CLOCK_SOURCE_ARX1 | CLOCK_RATE_44100);
	err = snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST,
				 global_address(dice, GLOBAL_CLOCK_SELECT),
				 &clock, 4);
	if (err < 0)
		return err;

	err = snd_pcm_new(dice->card, "DICE", 0, 1, 0, &pcm);
	err = snd_pcm_new(dice->card, "DICE", 0, 1, 0, &pcm);
	if (err < 0)
	if (err < 0)
		return err;
		return err;
@@ -897,6 +912,7 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
{
{
	struct snd_card *card;
	struct snd_card *card;
	struct dice *dice;
	struct dice *dice;
	__be32 clock_sel;
	int err;
	int err;


	err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*dice), &card);
	err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*dice), &card);
@@ -938,6 +954,19 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)


	dice_card_strings(dice);
	dice_card_strings(dice);


	err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
				 global_address(dice, GLOBAL_CLOCK_SELECT),
				 &clock_sel, 4);
	if (err < 0)
		goto error;
	clock_sel &= cpu_to_be32(~CLOCK_SOURCE_MASK);
	clock_sel |= cpu_to_be32(CLOCK_SOURCE_ARX1);
	err = snd_fw_transaction(unit, TCODE_WRITE_QUADLET_REQUEST,
				 global_address(dice, GLOBAL_CLOCK_SELECT),
				 &clock_sel, 4);
	if (err < 0)
		goto error;

	err = dice_create_pcm(dice);
	err = dice_create_pcm(dice);
	if (err < 0)
	if (err < 0)
		goto error;
		goto error;