sound/soc/codecs/rt1320-sdw.c

Source file repositories/reference/linux-study-clean/sound/soc/codecs/rt1320-sdw.c

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/rt1320-sdw.c
Extension
.c
Size
92676 bytes
Lines
3092
Domain
Driver Families
Bucket
sound/soc
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 rt1320_imageinfo {
	unsigned int addr;
	unsigned int size;
};

struct rt1320_dspfwheader {
	unsigned int sync;
	short num;
	short crc;
};

	struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(rt1320->component);
	struct device *dev = &rt1320->sdw_slave->dev;
	unsigned int val, i, fw_offset, fw_ready;
	unsigned int fw_status_addr;
	struct rt1320_dspfwheader *fwheader;
	struct rt1320_imageinfo *ptr_img;
	struct sdw_bpt_section sec[10];
	const struct firmware *fw = NULL;
	unsigned char *fw_data;
	bool dev_fw_match = false;
	static const char hdr_sig[] = "AFX";
	unsigned int hdr_size = 0;
	const char *dmi_vendor, *dmi_product, *dmi_sku;
	int len_vendor, len_product, len_sku;
	char filename[512];

	switch (rt1320->dev_id) {
	case RT1320_DEV_ID:
		fw_status_addr = RT1320_DSPFW_STATUS_ADDR;
		break;
	case RT1321_DEV_ID:
		fw_status_addr = RT1321_DSPFW_STATUS_ADDR;
		break;
	default:
		dev_err(dev, "%s: Unknown device ID %d\n", __func__, rt1320->dev_id);
		return;
	}

	dmi_vendor = dmi_get_system_info(DMI_SYS_VENDOR);
	dmi_product = dmi_get_system_info(DMI_PRODUCT_NAME);
	dmi_sku = dmi_get_system_info(DMI_PRODUCT_SKU);

	if (dmi_vendor && dmi_product && dmi_sku) {
		len_vendor = strchrnul(dmi_vendor, ' ') - dmi_vendor;
		len_product = strchrnul(dmi_product, ' ') - dmi_product;
		len_sku = strchrnul(dmi_sku, ' ') - dmi_sku;

		snprintf(filename, sizeof(filename),
			 "realtek/rt1320/rt1320_%.*s_%.*s_%.*s.dat",
			 len_vendor, dmi_vendor, len_product, dmi_product, len_sku, dmi_sku);

		dev_dbg(dev, "%s: try to load FW file %s\n", __func__, filename);
	} else if (rt1320->dspfw_name) {
		snprintf(filename, sizeof(filename), "rt1320_%s.dat",
			 rt1320->dspfw_name);
		dev_dbg(dev, "%s: try to load FW file %s\n", __func__, filename);
	} else {
		dev_warn(dev, "%s: Can't find proper FW file name\n", __func__);
		return;
	}

	snd_soc_dapm_mutex_lock(dapm);
	regmap_write(rt1320->regmap,
			SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23,
				RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x00);
	rt1320_pde_transition_delay(rt1320, FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, 0x00);

	regmap_read(rt1320->regmap, fw_status_addr, &fw_ready);
	fw_ready &= 0x1;
	if (fw_ready) {
		dev_dbg(dev, "%s, DSP FW was already\n", __func__);
		rt1320->fw_load_done = true;
		goto _exit_;
	}

	/* change to IRAM */
	regmap_update_bits(rt1320->regmap, 0xf01e, 0x80, 0x00);

	request_firmware(&fw, filename, dev);
	if (fw) {
		fwheader = (struct rt1320_dspfwheader *)fw->data;
		dev_dbg(dev, "%s, fw sync = 0x%x, num=%d, crc=0x%x\n", __func__,
			fwheader->sync, fwheader->num, fwheader->crc);

		if (fwheader->sync != 0x0a1c5679) {
			dev_err(dev, "%s: FW sync error\n", __func__);
			release_firmware(fw);
			goto _exit_;
		}

Annotation

Implementation Notes