sound/soc/codecs/ssm3515.c

Source file repositories/reference/linux-study-clean/sound/soc/codecs/ssm3515.c

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/ssm3515.c
Extension
.c
Size
11406 bytes
Lines
449
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 ssm3515_data {
	struct device *dev;
	struct regmap *regmap;
};

// The specced range is -71.25...24.00 dB with step size of 0.375 dB,
// and a mute item below that. This is represented by -71.62...24.00 dB
// with the mute item mapped onto the low end.
static DECLARE_TLV_DB_MINMAX_MUTE(ssm3515_dac_volume, -7162, 2400);

static const char * const ssm3515_ana_gain_text[] = {
	"8.4 V Span", "12.6 V Span", "14 V Span", "15 V Span",
};

static SOC_ENUM_SINGLE_DECL(ssm3515_ana_gain_enum, SSM3515_GEC,
			    __bf_shf(SSM3515_GEC_ANA_GAIN),
			    ssm3515_ana_gain_text);

static const struct snd_kcontrol_new ssm3515_snd_controls[] = {
	SOC_SINGLE_TLV("DAC Playback Volume", SSM3515_DAC_VOL,
		       0, 255, 1, ssm3515_dac_volume),
	SOC_SINGLE("Low EMI Mode Switch", SSM3515_GEC,
		   __bf_shf(SSM3515_GEC_EDGE), 1, 0),
	SOC_SINGLE("Soft Volume Ramping Switch", SSM3515_DAC,
		   __bf_shf(SSM3515_DAC_HV), 1, 1),
	SOC_SINGLE("HPF Switch", SSM3515_DAC,
		   __bf_shf(SSM3515_DAC_HPF), 1, 0),
	SOC_SINGLE("DAC Invert Switch", SSM3515_SAI1,
		   __bf_shf(SSM3515_SAI1_DAC_POL), 1, 0),
	SOC_ENUM("DAC Analog Gain Select", ssm3515_ana_gain_enum),
};

static void ssm3515_read_faults(struct snd_soc_component *component)
{
	int ret;

	ret = snd_soc_component_read(component, SSM3515_STATUS);
	if (ret <= 0) {
		/*
		 * If the read was erroneous, ASoC core has printed a message,
		 * and that's all that's appropriate in handling the error here.
		 */
		return;
	}

	dev_err(component->dev, "device reports:%s%s%s%s%s%s%s\n",
		FIELD_GET(SSM3515_STATUS_UVLO_REG, ret) ? " voltage regulator fault" : "",
		FIELD_GET(SSM3515_STATUS_LIM_EG, ret)   ? " limiter engaged" : "",
		FIELD_GET(SSM3515_STATUS_CLIP, ret)     ? " clipping detected" : "",
		FIELD_GET(SSM3515_STATUS_AMP_OC, ret)   ? " amp over-current fault" : "",
		FIELD_GET(SSM3515_STATUS_OTF, ret)      ? " overtemperature fault" : "",
		FIELD_GET(SSM3515_STATUS_OTW, ret)      ? " overtemperature warning" : "",
		FIELD_GET(SSM3515_STATUS_BAT_WARN, ret) ? " bat voltage low warning" : "");
}

static int ssm3515_probe(struct snd_soc_component *component)
{
	int ret;

	/* Start out muted */
	ret = snd_soc_component_update_bits(component, SSM3515_DAC,
			SSM3515_DAC_MUTE, SSM3515_DAC_MUTE);
	if (ret < 0)
		return ret;

	/* Disable the 'master power-down' */
	ret = snd_soc_component_update_bits(component, SSM3515_PWR,
			SSM3515_PWR_SPWDN, 0);
	if (ret < 0)
		return ret;

	return 0;
}

static int ssm3515_mute(struct snd_soc_dai *dai, int mute, int direction)
{
	int ret;

	ret = snd_soc_component_update_bits(dai->component,
					    SSM3515_DAC,
					    SSM3515_DAC_MUTE,
					    FIELD_PREP(SSM3515_DAC_MUTE, mute));
	if (ret < 0)
		return ret;
	return 0;
}

static int ssm3515_hw_params(struct snd_pcm_substream *substream,
			     struct snd_pcm_hw_params *params,
			     struct snd_soc_dai *dai)

Annotation

Implementation Notes