sound/soc/meson/axg-frddr.c

Source file repositories/reference/linux-study-clean/sound/soc/meson/axg-frddr.c

File Facts

System
Linux kernel
Corpus path
sound/soc/meson/axg-frddr.c
Extension
.c
Size
13989 bytes
Lines
401
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

// SPDX-License-Identifier: (GPL-2.0 OR MIT)
//
// Copyright (c) 2018 BayLibre, SAS.
// Author: Jerome Brunet <jbrunet@baylibre.com>

/*
 * This driver implements the frontend playback DAI of AXG and G12A based SoCs
 */

#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/regmap.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dai.h>

#include "axg-fifo.h"

#define CTRL0_FRDDR_PP_MODE		BIT(30)
#define CTRL0_SEL1_EN_SHIFT		3
#define CTRL0_SEL2_SHIFT		4
#define CTRL0_SEL2_EN_SHIFT		7
#define CTRL0_SEL3_SHIFT		8
#define CTRL0_SEL3_EN_SHIFT		11
#define CTRL1_FRDDR_FORCE_FINISH	BIT(12)
#define CTRL2_SEL1_SHIFT		0
#define CTRL2_SEL1_EN_SHIFT		4
#define CTRL2_SEL2_SHIFT		8
#define CTRL2_SEL2_EN_SHIFT		12
#define CTRL2_SEL3_SHIFT		16
#define CTRL2_SEL3_EN_SHIFT		20

static int g12a_frddr_dai_prepare(struct snd_pcm_substream *substream,
				  struct snd_soc_dai *dai)
{
	struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai);

	/* Reset the read pointer to the FIFO_INIT_ADDR */
	regmap_update_bits(fifo->map, FIFO_CTRL1,
			   CTRL1_FRDDR_FORCE_FINISH, 0);
	regmap_update_bits(fifo->map, FIFO_CTRL1,
			   CTRL1_FRDDR_FORCE_FINISH, CTRL1_FRDDR_FORCE_FINISH);
	regmap_update_bits(fifo->map, FIFO_CTRL1,
			   CTRL1_FRDDR_FORCE_FINISH, 0);

	return 0;
}

static int axg_frddr_dai_hw_params(struct snd_pcm_substream *substream,
				   struct snd_pcm_hw_params *params,
				   struct snd_soc_dai *dai)
{
	struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai);
	unsigned int period, depth, val;

	period = params_period_bytes(params);

	/* Trim the FIFO depth if the period is small to improve latency */
	depth = min(period, fifo->depth);
	val = (depth / AXG_FIFO_BURST) - 1;
	regmap_update_bits(fifo->map, FIFO_CTRL1, CTRL1_FRDDR_DEPTH,
			   FIELD_PREP(CTRL1_FRDDR_DEPTH, val));

	return 0;
}

static int axg_frddr_dai_startup(struct snd_pcm_substream *substream,
				 struct snd_soc_dai *dai)
{
	struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai);
	int ret;

	/* Enable pclk to access registers and clock the fifo ip */
	ret = clk_prepare_enable(fifo->pclk);
	if (ret)
		return ret;

	/* Apply single buffer mode to the interface */
	regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_FRDDR_PP_MODE, 0);

	return 0;
}

static void axg_frddr_dai_shutdown(struct snd_pcm_substream *substream,
				   struct snd_soc_dai *dai)
{
	struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai);

Annotation

Implementation Notes