sound/firewire/dice/dice-extension.c

Source file repositories/reference/linux-study-clean/sound/firewire/dice/dice-extension.c

File Facts

System
Linux kernel
Corpus path
sound/firewire/dice/dice-extension.c
Extension
.c
Size
4844 bytes
Lines
176
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

if (mode == 2) {
			cap = CLOCK_CAP_RATE_176400 | CLOCK_CAP_RATE_192000;
		} else if (mode == 1) {
			cap = CLOCK_CAP_RATE_88200 | CLOCK_CAP_RATE_96000;
		} else {
			cap = CLOCK_CAP_RATE_32000 | CLOCK_CAP_RATE_44100 |
			      CLOCK_CAP_RATE_48000;
		}
		if (!(cap & dice->clock_caps))
			continue;

		base_offset = 0x2000 * mode + 0x1000;

		err = read_transaction(dice, section_addr,
				       base_offset + EXT_APP_STREAM_TX_NUMBER,
				       &reg, sizeof(reg));
		if (err < 0)
			break;

		base_offset += EXT_APP_STREAM_ENTRIES;
		stream_count = min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
		err = read_stream_entries(dice, section_addr, base_offset,
					  stream_count, mode,
					  dice->tx_pcm_chs,
					  dice->tx_midi_ports);
		if (err < 0)
			break;

		base_offset += stream_count * EXT_APP_STREAM_ENTRY_SIZE;
		stream_count = min_t(unsigned int, be32_to_cpu(reg[1]), MAX_STREAMS);
		err = read_stream_entries(dice, section_addr, base_offset,
					  stream_count,
					  mode, dice->rx_pcm_chs,
					  dice->rx_midi_ports);
		if (err < 0)
			break;
	}

	return err;
}

int snd_dice_detect_extension_formats(struct snd_dice *dice)
{
	__be32 *pointers;
	unsigned int i;
	u64 section_addr;
	int err;

	pointers = kmalloc_array(9, sizeof(__be32) * 2, GFP_KERNEL);
	if (pointers == NULL)
		return -ENOMEM;

	err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
				 DICE_EXT_APP_SPACE, pointers,
				 9 * sizeof(__be32) * 2, 0);
	if (err < 0)
		goto end;

	/* Check two of them for offset have the same value or not. */
	for (i = 0; i < 9; ++i) {
		int j;

		for (j = i + 1; j < 9; ++j) {
			if (pointers[i * 2] == pointers[j * 2]) {
				// Fallback to limited functionality.
				err = -ENXIO;
				goto end;
			}
		}
	}

	section_addr = DICE_EXT_APP_SPACE + be32_to_cpu(pointers[12]) * 4;
	err = detect_stream_formats(dice, section_addr);
end:
	kfree(pointers);
	return err;
}

Annotation

Implementation Notes