sound/soc/tegra/tegra_audio_graph_card.c

Source file repositories/reference/linux-study-clean/sound/soc/tegra/tegra_audio_graph_card.c

File Facts

System
Linux kernel
Corpus path
sound/soc/tegra/tegra_audio_graph_card.c
Extension
.c
Size
7516 bytes
Lines
282
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 tegra_audio_priv {
	struct simple_util_priv simple;
	struct clk *clk_plla_out0;
	struct clk *clk_plla;
};

/* Tegra audio chip data */
struct tegra_audio_cdata {
	unsigned int plla_rates[NUM_RATE_TYPE];
	unsigned int plla_out0_rates[NUM_RATE_TYPE];
};

static bool need_clk_update(struct snd_soc_dai *dai)
{
	if (snd_soc_dai_is_dummy(dai) ||
	    !dai->driver->ops ||
	    !dai->driver->name)
		return false;

	if (strstr(dai->driver->name, "I2S") ||
	    strstr(dai->driver->name, "DMIC") ||
	    strstr(dai->driver->name, "DSPK"))
		return true;

	return false;
}

/* Setup PLL clock as per the given sample rate */
static int tegra_audio_graph_update_pll(struct snd_pcm_substream *substream,
					struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
	struct simple_util_priv *simple = snd_soc_card_get_drvdata(rtd->card);
	struct tegra_audio_priv *priv = simple_to_tegra_priv(simple);
	struct device *dev = rtd->card->dev;
	const struct tegra_audio_cdata *data = of_device_get_match_data(dev);
	unsigned int plla_rate, plla_out0_rate, bclk;
	unsigned int srate = params_rate(params);
	int err;

	switch (srate) {
	case 11025:
	case 22050:
	case 44100:
	case 88200:
	case 176400:
		plla_out0_rate = data->plla_out0_rates[x11_RATE];
		plla_rate = data->plla_rates[x11_RATE];
		break;
	case 8000:
	case 16000:
	case 32000:
	case 48000:
	case 96000:
	case 192000:
		plla_out0_rate = data->plla_out0_rates[x8_RATE];
		plla_rate = data->plla_rates[x8_RATE];
		break;
	default:
		dev_err(rtd->card->dev, "Unsupported sample rate %u\n",
			srate);
		return -EINVAL;
	}

	/*
	 * Below is the clock relation:
	 *
	 *	PLLA
	 *	  |
	 *	  |--> PLLA_OUT0
	 *		  |
	 *		  |---> I2S modules
	 *		  |
	 *		  |---> DMIC modules
	 *		  |
	 *		  |---> DSPK modules
	 *
	 *
	 * Default PLLA_OUT0 rate might be too high when I/O is running
	 * at minimum PCM configurations. This may result in incorrect
	 * clock rates and glitchy audio. The maximum divider is 128
	 * and any thing higher than that won't work. Thus reduce PLLA_OUT0
	 * to work for lower configurations.
	 *
	 * This problem is seen for I2S only, as DMIC and DSPK minimum
	 * clock requirements are under allowed divider limits.
	 */
	bclk = srate * params_channels(params) * params_width(params);
	if (div_u64(plla_out0_rate, bclk) > MAX_PLLA_OUT0_DIV)
		plla_out0_rate >>= 1;

Annotation

Implementation Notes