sound/soc/fsl/fsl_easrc.c

Source file repositories/reference/linux-study-clean/sound/soc/fsl/fsl_easrc.c

File Facts

System
Linux kernel
Corpus path
sound/soc/fsl/fsl_easrc.c
Extension
.c
Size
67553 bytes
Lines
2426
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

if (ctx_id >= EASRC_CTX_MAX_NUM) {
			dev_err(dev, "Invalid context id[%d]\n", ctx_id);
			return -EINVAL;
		}

		reg = REG_EASRC_CCE1(ctx_id);
		mask = EASRC_CCE1_COEF_MEM_RST_MASK;
		val = EASRC_CCE1_COEF_MEM_RST;
		break;
	case EASRC_RS_COEFF_MEM:
		/* This resets the resampling memory pointer addr */
		reg = REG_EASRC_CRCC;
		mask = EASRC_CRCC_RS_CPR_MASK;
		val = EASRC_CRCC_RS_CPR;
		break;
	default:
		dev_err(dev, "Unknown memory type\n");
		return -EINVAL;
	}

	/*
	 * To reset the write pointer back to zero, the register field
	 * ASRC_CTX_CTRL_EXT1x[PF_COEFF_MEM_RST] can be toggled from
	 * 0x0 to 0x1 to 0x0.
	 */
	regmap_update_bits(easrc->regmap, reg, mask, 0);
	regmap_update_bits(easrc->regmap, reg, mask, val);
	regmap_update_bits(easrc->regmap, reg, mask, 0);

	return 0;
}

static inline uint32_t bits_taps_to_val(unsigned int t)
{
	switch (t) {
	case EASRC_RS_32_TAPS:
		return 32;
	case EASRC_RS_64_TAPS:
		return 64;
	case EASRC_RS_128_TAPS:
		return 128;
	}

	return 0;
}

static int fsl_easrc_resampler_config(struct fsl_asrc *easrc)
{
	struct device *dev = &easrc->pdev->dev;
	struct fsl_easrc_priv *easrc_priv = easrc->private;
	struct asrc_firmware_hdr *hdr =  easrc_priv->firmware_hdr;
	struct interp_params *interp = easrc_priv->interp;
	struct interp_params *selected_interp = NULL;
	unsigned int num_coeff;
	unsigned int i;
	u64 *coef;
	u32 *r;
	int ret;

	if (!hdr) {
		dev_err(dev, "firmware not loaded!\n");
		return -ENODEV;
	}

	for (i = 0; i < hdr->interp_scen; i++) {
		if ((interp[i].num_taps - 1) !=
		    bits_taps_to_val(easrc_priv->rs_num_taps))
			continue;

		coef = interp[i].coeff;
		selected_interp = &interp[i];
		dev_dbg(dev, "Selected interp_filter: %u taps - %u phases\n",
			selected_interp->num_taps,
			selected_interp->num_phases);
		break;
	}

	if (!selected_interp) {
		dev_err(dev, "failed to get interpreter configuration\n");
		return -EINVAL;
	}

	/*
	 * RS_LOW - first half of center tap of the sinc function
	 * RS_HIGH - second half of center tap of the sinc function
	 * This is due to the fact the resampling function must be
	 * symetrical - i.e. odd number of taps
	 */
	r = (uint32_t *)&selected_interp->center_tap;
	regmap_write(easrc->regmap, REG_EASRC_RCTCL, EASRC_RCTCL_RS_CL(r[0]));

Annotation

Implementation Notes