sound/firewire/bebob/bebob_maudio.c

Source file repositories/reference/linux-study-clean/sound/firewire/bebob/bebob_maudio.c

File Facts

System
Linux kernel
Corpus path
sound/firewire/bebob/bebob_maudio.c
Extension
.c
Size
21411 bytes
Lines
786
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 special_params {
	bool is1814;
	unsigned int clk_src;
	unsigned int dig_in_fmt;
	unsigned int dig_out_fmt;
	unsigned int clk_lock;
	struct snd_ctl_elem_id *ctl_id_sync;
};

/*
 * For some M-Audio devices, this module just send cue to load firmware. After
 * loading, the device generates bus reset and newly detected.
 *
 * If we make any transactions to load firmware, the operation may failed.
 */
int snd_bebob_maudio_load_firmware(struct fw_unit *unit)
{
	struct fw_device *device = fw_parent_device(unit);
	int err, rcode;
	u64 date;
	__le32 *cues;

	/* check date of software used to build */
	err = snd_bebob_read_block(unit, INFO_OFFSET_SW_DATE,
				   &date, sizeof(u64));
	if (err < 0)
		return err;
	/*
	 * firmware version 5058 or later has date later than "20070401", but
	 * 'date' is not null-terminated.
	 */
	if (date < 0x3230303730343031LL) {
		dev_err(&unit->device,
			"Use firmware version 5058 or later\n");
		return -ENXIO;
	}

	cues = kmalloc_array(3, sizeof(*cues), GFP_KERNEL);
	if (!cues)
		return -ENOMEM;

	cues[0] = cpu_to_le32(MAUDIO_BOOTLOADER_CUE1);
	cues[1] = cpu_to_le32(MAUDIO_BOOTLOADER_CUE2);
	cues[2] = cpu_to_le32(MAUDIO_BOOTLOADER_CUE3);

	rcode = fw_run_transaction(device->card, TCODE_WRITE_BLOCK_REQUEST,
				   device->node_id, device->generation,
				   device->max_speed, BEBOB_ADDR_REG_REQ,
				   cues, 3 * sizeof(*cues));
	kfree(cues);
	if (rcode != RCODE_COMPLETE) {
		dev_err(&unit->device,
			"Failed to send a cue to load firmware\n");
		err = -EIO;
	}

	return err;
}

static inline int
get_meter(struct snd_bebob *bebob, void *buf, unsigned int size)
{
	return snd_fw_transaction(bebob->unit, TCODE_READ_BLOCK_REQUEST,
				  MAUDIO_SPECIFIC_ADDRESS + METER_OFFSET,
				  buf, size, 0);
}

static int
check_clk_sync(struct snd_bebob *bebob, unsigned int size, bool *sync)
{
	int err;
	u8 *buf;

	buf = kmalloc(size, GFP_KERNEL);
	if (buf == NULL)
		return -ENOMEM;

	err = get_meter(bebob, buf, size);
	if (err < 0)
		goto end;

	/* if synced, this value is the same as SFC of FDF in CIP header */
	*sync = (buf[size - 2] != 0xff);
end:
	kfree(buf);
	return err;
}

/*
 * dig_fmt: 0x00:S/PDIF, 0x01:ADAT

Annotation

Implementation Notes