sound/soc/img/img-spdif-in.c

Source file repositories/reference/linux-study-clean/sound/soc/img/img-spdif-in.c

File Facts

System
Linux kernel
Corpus path
sound/soc/img/img-spdif-in.c
Extension
.c
Size
21924 bytes
Lines
849
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 img_spdif_in {
	spinlock_t lock;
	void __iomem *base;
	struct clk *clk_sys;
	struct snd_dmaengine_dai_dma_data dma_data;
	struct device *dev;
	unsigned int trk;
	bool multi_freq;
	int lock_acquire;
	int lock_release;
	unsigned int single_freq;
	unsigned int multi_freqs[IMG_SPDIF_IN_NUM_ACLKGEN];
	bool active;
	u32 suspend_clkgen;
	u32 suspend_ctl;

	/* Write-only registers */
	unsigned int aclkgen_regs[IMG_SPDIF_IN_NUM_ACLKGEN];
};

static int img_spdif_in_runtime_suspend(struct device *dev)
{
	struct img_spdif_in *spdif = dev_get_drvdata(dev);

	clk_disable_unprepare(spdif->clk_sys);

	return 0;
}

static int img_spdif_in_runtime_resume(struct device *dev)
{
	struct img_spdif_in *spdif = dev_get_drvdata(dev);
	int ret;

	ret = clk_prepare_enable(spdif->clk_sys);
	if (ret) {
		dev_err(dev, "Unable to enable sys clock\n");
		return ret;
	}

	return 0;
}

static inline void img_spdif_in_writel(struct img_spdif_in *spdif,
					u32 val, u32 reg)
{
	writel(val, spdif->base + reg);
}

static inline u32 img_spdif_in_readl(struct img_spdif_in *spdif, u32 reg)
{
	return readl(spdif->base + reg);
}

static inline void img_spdif_in_aclkgen_writel(struct img_spdif_in *spdif,
						u32 index)
{
	img_spdif_in_writel(spdif, spdif->aclkgen_regs[index],
			IMG_SPDIF_IN_ACLKGEN_START + (index * 0x4));
}

static int img_spdif_in_check_max_rate(struct img_spdif_in *spdif,
		unsigned int sample_rate, unsigned long *actual_freq)
{
	unsigned long min_freq, freq_t;

	/* Clock rate must be at least 24x the bit rate */
	min_freq = sample_rate * 2 * 32 * 24;

	freq_t = clk_get_rate(spdif->clk_sys);

	if (freq_t < min_freq)
		return -EINVAL;

	*actual_freq = freq_t;

	return 0;
}

static int img_spdif_in_do_clkgen_calc(unsigned int rate, unsigned int *pnom,
		unsigned int *phld, unsigned long clk_rate)
{
	unsigned int ori, nom, hld;

	/*
	 * Calculate oversampling ratio, nominal phase increment and hold
	 * increment for the given rate / frequency
	 */

	if (!rate)

Annotation

Implementation Notes