sound/firewire/motu/motu-register-dsp-message-parser.c

Source file repositories/reference/linux-study-clean/sound/firewire/motu/motu-register-dsp-message-parser.c

File Facts

System
Linux kernel
Corpus path
sound/firewire/motu/motu-register-dsp-message-parser.c
Extension
.c
Size
12570 bytes
Lines
417
Domain
Driver Families
Bucket
sound/firewire
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct msg_parser {
	spinlock_t lock;
	struct snd_firewire_motu_register_dsp_meter meter;
	bool meter_pos_quirk;

	struct snd_firewire_motu_register_dsp_parameter param;
	u8 prev_mixer_src_type;
	u8 mixer_ch;
	u8 mixer_src_ch;

	u8 input_ch;
	u8 prev_msg_type;

	u32 event_queue[EVENT_QUEUE_SIZE];
	unsigned int push_pos;
	unsigned int pull_pos;
};

int snd_motu_register_dsp_message_parser_new(struct snd_motu *motu)
{
	struct msg_parser *parser;
	parser = devm_kzalloc(&motu->card->card_dev, sizeof(*parser), GFP_KERNEL);
	if (!parser)
		return -ENOMEM;
	spin_lock_init(&parser->lock);
	if (motu->spec == &snd_motu_spec_4pre || motu->spec == &snd_motu_spec_audio_express)
		parser->meter_pos_quirk = true;
	motu->message_parser = parser;
	return 0;
}

int snd_motu_register_dsp_message_parser_init(struct snd_motu *motu)
{
	struct msg_parser *parser = motu->message_parser;

	parser->prev_mixer_src_type = INVALID;
	parser->mixer_ch = 0xff;
	parser->mixer_src_ch = 0xff;
	parser->prev_msg_type = INVALID;

	return 0;
}

// Rough implementaion of queue without overrun check.
static void queue_event(struct snd_motu *motu, u8 msg_type, u8 identifier0, u8 identifier1, u8 val)
{
	struct msg_parser *parser = motu->message_parser;
	unsigned int pos = parser->push_pos;
	u32 entry;

	if (!motu->hwdep || motu->hwdep->used == 0)
		return;

	entry = (msg_type << 24) | (identifier0 << 16) | (identifier1 << 8) | val;
	parser->event_queue[pos] = entry;

	++pos;
	if (pos >= EVENT_QUEUE_SIZE)
		pos = 0;
	parser->push_pos = pos;
}

void snd_motu_register_dsp_message_parser_parse(const struct amdtp_stream *s,
						const struct pkt_desc *desc, unsigned int count)
{
	struct snd_motu *motu = container_of(s, struct snd_motu, tx_stream);
	unsigned int data_block_quadlets = s->data_block_quadlets;
	struct msg_parser *parser = motu->message_parser;
	bool meter_pos_quirk = parser->meter_pos_quirk;
	unsigned int pos = parser->push_pos;
	int i;

	guard(spinlock_irqsave)(&parser->lock);

	for (i = 0; i < count; ++i) {
		__be32 *buffer = desc->ctx_payload;
		unsigned int data_blocks = desc->data_blocks;
		int j;

		desc = amdtp_stream_next_packet_desc(s, desc);

		for (j = 0; j < data_blocks; ++j) {
			u8 *b = (u8 *)buffer;
			u8 msg_type = (b[MSG_FLAG_POS] & MSG_FLAG_TYPE_MASK) >> MSG_FLAG_TYPE_SHIFT;
			u8 val = b[MSG_VALUE_POS];

			buffer += data_block_quadlets;

			switch (msg_type) {
			case MIXER_SELECT:

Annotation

Implementation Notes