linux/sound/soc/codecs/tfa989x.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2021 Stephan Gerhold
 *
 * Register definitions/sequences taken from various tfa98xx kernel drivers:
 * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
 * Copyright (C) 2013 Sony Mobile Communications Inc.
 */

#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <sound/soc.h>

#define TFA989X_STATUSREG
#define TFA989X_BATTERYVOLTAGE
#define TFA989X_TEMPERATURE
#define TFA989X_REVISIONNUMBER
#define TFA989X_REVISIONNUMBER_REV_MSK
#define TFA989X_I2SREG
#define TFA989X_I2SREG_RCV
#define TFA989X_I2SREG_CHSA
#define TFA989X_I2SREG_CHSA_MSK
#define TFA989X_I2SREG_I2SSR
#define TFA989X_I2SREG_I2SSR_MSK
#define TFA989X_BAT_PROT
#define TFA989X_AUDIO_CTR
#define TFA989X_DCDCBOOST
#define TFA989X_SPKR_CALIBRATION
#define TFA989X_SYS_CTRL
#define TFA989X_SYS_CTRL_PWDN
#define TFA989X_SYS_CTRL_I2CR
#define TFA989X_SYS_CTRL_CFE
#define TFA989X_SYS_CTRL_AMPE
#define TFA989X_SYS_CTRL_DCA
#define TFA989X_SYS_CTRL_SBSL
#define TFA989X_SYS_CTRL_AMPC
#define TFA989X_I2S_SEL_REG
#define TFA989X_I2S_SEL_REG_SPKR_MSK
#define TFA989X_I2S_SEL_REG_DCFG_MSK
#define TFA989X_HIDE_UNHIDE_KEY
#define TFA989X_PWM_CONTROL
#define TFA989X_CURRENTSENSE1
#define TFA989X_CURRENTSENSE2
#define TFA989X_CURRENTSENSE3
#define TFA989X_CURRENTSENSE4

#define TFA9890_REVISION
#define TFA9895_REVISION
#define TFA9897_REVISION

struct tfa989x_rev {};

struct tfa989x {};

static bool tfa989x_writeable_reg(struct device *dev, unsigned int reg)
{}

static bool tfa989x_volatile_reg(struct device *dev, unsigned int reg)
{}

static const struct regmap_config tfa989x_regmap =;

static const char * const chsa_text[] =;
static SOC_ENUM_SINGLE_DECL(chsa_enum, TFA989X_I2SREG, TFA989X_I2SREG_CHSA, chsa_text);
static const struct snd_kcontrol_new chsa_mux =;

static const struct snd_soc_dapm_widget tfa989x_dapm_widgets[] =;

static const struct snd_soc_dapm_route tfa989x_dapm_routes[] =;

static int tfa989x_put_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{}

static const char * const mode_text[] =;
static SOC_ENUM_SINGLE_DECL(mode_enum, TFA989X_I2SREG, TFA989X_I2SREG_RCV, mode_text);
static const struct snd_kcontrol_new tfa989x_mode_controls[] =;

static int tfa989x_probe(struct snd_soc_component *component)
{}

static const struct snd_soc_component_driver tfa989x_component =;

static const unsigned int tfa989x_rates[] =;

static int tfa989x_find_sample_rate(unsigned int rate)
{}

static int tfa989x_hw_params(struct snd_pcm_substream *substream,
			     struct snd_pcm_hw_params *params,
			     struct snd_soc_dai *dai)
{}

static const struct snd_soc_dai_ops tfa989x_dai_ops =;

static struct snd_soc_dai_driver tfa989x_dai =;

static int tfa9890_init(struct regmap *regmap)
{}

static const struct tfa989x_rev tfa9890_rev =;

static const struct reg_sequence tfa9895_reg_init[] =;

static int tfa9895_init(struct regmap *regmap)
{}

static const struct tfa989x_rev tfa9895_rev =;

static int tfa9897_init(struct regmap *regmap)
{}

static const struct tfa989x_rev tfa9897_rev =;

/*
 * Note: At the moment this driver bypasses the "CoolFlux DSP" built into the
 * TFA989X amplifiers. Unfortunately, there seems to be absolutely
 * no documentation for it - the public "short datasheets" do not provide
 * any information about the DSP or available registers.
 *
 * Usually the TFA989X amplifiers are configured through proprietary userspace
 * libraries. There are also some (rather complex) kernel drivers but even those
 * rely on obscure firmware blobs for configuration (so-called "containers").
 * They seem to contain different "profiles" with tuned speaker settings, sample
 * rates and volume steps (which would be better exposed as separate ALSA mixers).
 *
 * Bypassing the DSP disables volume control (and perhaps some speaker
 * optimization?), but at least allows using the speaker without obscure
 * kernel drivers and firmware.
 *
 * Ideally NXP (or now Goodix) should release proper documentation for these
 * amplifiers so that support for the "CoolFlux DSP" can be implemented properly.
 */
static int tfa989x_dsp_bypass(struct regmap *regmap)
{}

static void tfa989x_regulator_disable(void *data)
{}

static int tfa989x_i2c_probe(struct i2c_client *i2c)
{}

static const struct of_device_id tfa989x_of_match[] =;
MODULE_DEVICE_TABLE(of, tfa989x_of_match);

static struct i2c_driver tfa989x_i2c_driver =;
module_i2c_driver();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();