sound/soc/meson/g12a-tohdmitx.c

Source file repositories/reference/linux-study-clean/sound/soc/meson/g12a-tohdmitx.c

File Facts

System
Linux kernel
Corpus path
sound/soc/meson/g12a-tohdmitx.c
Extension
.c
Size
8989 bytes
Lines
284
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
//
// Copyright (c) 2019 BayLibre, SAS.
// Author: Jerome Brunet <jbrunet@baylibre.com>

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

#include <dt-bindings/sound/meson-g12a-tohdmitx.h>
#include "meson-codec-glue.h"

#define G12A_TOHDMITX_DRV_NAME "g12a-tohdmitx"

#define TOHDMITX_CTRL0			0x0
#define  CTRL0_ENABLE_SHIFT		31
#define  CTRL0_I2S_DAT_SEL_SHIFT	12
#define  CTRL0_I2S_DAT_SEL		(0x3 << CTRL0_I2S_DAT_SEL_SHIFT)
#define  CTRL0_I2S_LRCLK_SEL		GENMASK(9, 8)
#define  CTRL0_I2S_BLK_CAP_INV		BIT(7)
#define  CTRL0_I2S_BCLK_O_INV		BIT(6)
#define  CTRL0_I2S_BCLK_SEL		GENMASK(5, 4)
#define  CTRL0_SPDIF_CLK_CAP_INV	BIT(3)
#define  CTRL0_SPDIF_CLK_O_INV		BIT(2)
#define  CTRL0_SPDIF_SEL_SHIFT		1
#define  CTRL0_SPDIF_SEL		(0x1 << CTRL0_SPDIF_SEL_SHIFT)
#define  CTRL0_SPDIF_CLK_SEL		BIT(0)

static const char * const g12a_tohdmitx_i2s_mux_texts[] = {
	"I2S A", "I2S B", "I2S C",
};

static int g12a_tohdmitx_i2s_mux_put_enum(struct snd_kcontrol *kcontrol,
				   struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *component = snd_soc_dapm_kcontrol_to_component(kcontrol);
	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
	unsigned int mux, changed;

	if (ucontrol->value.enumerated.item[0] >= e->items)
		return -EINVAL;

	mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]);
	changed = snd_soc_component_test_bits(component, e->reg,
					      CTRL0_I2S_DAT_SEL,
					      FIELD_PREP(CTRL0_I2S_DAT_SEL,
							 mux));

	if (!changed)
		return 0;

	/* Force disconnect of the mux while updating */
	snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL);

	snd_soc_component_update_bits(component, e->reg,
				      CTRL0_I2S_DAT_SEL |
				      CTRL0_I2S_LRCLK_SEL |
				      CTRL0_I2S_BCLK_SEL,
				      FIELD_PREP(CTRL0_I2S_DAT_SEL, mux) |
				      FIELD_PREP(CTRL0_I2S_LRCLK_SEL, mux) |
				      FIELD_PREP(CTRL0_I2S_BCLK_SEL, mux));

	snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);

	return 1;
}

static SOC_ENUM_SINGLE_DECL(g12a_tohdmitx_i2s_mux_enum, TOHDMITX_CTRL0,
			    CTRL0_I2S_DAT_SEL_SHIFT,
			    g12a_tohdmitx_i2s_mux_texts);

static const struct snd_kcontrol_new g12a_tohdmitx_i2s_mux =
	SOC_DAPM_ENUM_EXT("I2S Source", g12a_tohdmitx_i2s_mux_enum,
			  snd_soc_dapm_get_enum_double,
			  g12a_tohdmitx_i2s_mux_put_enum);

static const char * const g12a_tohdmitx_spdif_mux_texts[] = {
	"SPDIF A", "SPDIF B",
};

static int g12a_tohdmitx_spdif_mux_put_enum(struct snd_kcontrol *kcontrol,
					    struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *component = snd_soc_dapm_kcontrol_to_component(kcontrol);

Annotation

Implementation Notes