linux/sound/soc/codecs/wm8753.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * wm8753.c  --  WM8753 ALSA Soc Audio driver
 *
 * Copyright 2003-11 Wolfson Microelectronics PLC.
 * Author: Liam Girdwood <[email protected]>
 *
 * Notes:
 *  The WM8753 is a low power, high quality stereo codec with integrated PCM
 *  codec designed for portable digital telephony applications.
 *
 * Dual DAI:-
 *
 * This driver support 2 DAI PCM's. This makes the default PCM available for
 * HiFi audio (e.g. MP3, ogg) playback/capture and the other PCM available for
 * voice.
 *
 * Please note that the voice PCM can be connected directly to a Bluetooth
 * codec or GSM modem and thus cannot be read or written to, although it is
 * available to be configured with snd_hw_params(), etc and kcontrols in the
 * normal alsa manner.
 *
 * Fast DAI switching:-
 *
 * The driver can now fast switch between the DAI configurations via a
 * an alsa kcontrol. This allows the PCM to remain open.
 */

#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include <asm/div64.h>

#include "wm8753.h"

static int caps_charge =;
module_param(caps_charge, int, 0);
MODULE_PARM_DESC();

static int wm8753_hifi_write_dai_fmt(struct snd_soc_component *component,
		unsigned int fmt);
static int wm8753_voice_write_dai_fmt(struct snd_soc_component *component,
		unsigned int fmt);

/*
 * wm8753 register cache
 * We can't read the WM8753 register space when we
 * are using 2 wire for device control, so we cache them instead.
 */
static const struct reg_default wm8753_reg_defaults[] =;

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

/* codec private data */
struct wm8753_priv {};

#define wm8753_reset(c)

/*
 * WM8753 Controls
 */
static const char *wm8753_base[] =;
static const char *wm8753_base_filter[] =;
static const char *wm8753_treble[] =;
static const char *wm8753_alc_func[] =;
static const char *wm8753_ng_type[] =;
static const char *wm8753_3d_func[] =;
static const char *wm8753_3d_uc[] =;
static const char *wm8753_3d_lc[] =;
static const char *wm8753_deemp[] =;
static const char *wm8753_mono_mix[] =;
static const char *wm8753_dac_phase[] =;
static const char *wm8753_line_mix[] =;
static const char *wm8753_mono_mux[] =;
static const char *wm8753_right_mux[] =;
static const char *wm8753_left_mux[] =;
static const char *wm8753_rxmsel[] =;
static const char *wm8753_sidetone_mux[] =;
static const char *wm8753_mono2_src[] =;
static const char *wm8753_out3[] =;
static const char *wm8753_out4[] =;
static const char *wm8753_radcsel[] =;
static const char *wm8753_ladcsel[] =;
static const char *wm8753_mono_adc[] =;
static const char *wm8753_adc_hp[] =;
static const char *wm8753_adc_filter[] =;
static const char *wm8753_mic_sel[] =;
static const char *wm8753_dai_mode[] =;
static const char *wm8753_dat_sel[] =;
static const char *wm8753_rout2_phase[] =;

static const struct soc_enum wm8753_enum[] =;


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

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

static const DECLARE_TLV_DB_SCALE(rec_mix_tlv, -1500, 300, 0);
static const DECLARE_TLV_DB_SCALE(mic_preamp_tlv, 1200, 600, 0);
static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1);
static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
static const DECLARE_TLV_DB_RANGE(out_tlv,
	/* 0000000 - 0101111 = "Analogue mute" */
	0, 48, TLV_DB_SCALE_ITEM(-25500, 0, 0),
	48, 127, TLV_DB_SCALE_ITEM(-7300, 100, 0)
);
static const DECLARE_TLV_DB_SCALE(mix_tlv, -1500, 300, 0);
static const DECLARE_TLV_DB_SCALE(voice_mix_tlv, -1200, 300, 0);
static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0);

static const struct snd_kcontrol_new wm8753_snd_controls[] =;

/*
 * _DAPM_ Controls
 */

/* Left Mixer */
static const struct snd_kcontrol_new wm8753_left_mixer_controls[] =;

/* Right mixer */
static const struct snd_kcontrol_new wm8753_right_mixer_controls[] =;

/* Mono mixer */
static const struct snd_kcontrol_new wm8753_mono_mixer_controls[] =;

/* Mono 2 Mux */
static const struct snd_kcontrol_new wm8753_mono2_controls =;

/* Out 3 Mux */
static const struct snd_kcontrol_new wm8753_out3_controls =;

/* Out 4 Mux */
static const struct snd_kcontrol_new wm8753_out4_controls =;

/* ADC Mono Mix */
static const struct snd_kcontrol_new wm8753_adc_mono_controls =;

/* Record mixer */
static const struct snd_kcontrol_new wm8753_record_mixer_controls[] =;

/* Left ADC mux */
static const struct snd_kcontrol_new wm8753_adc_left_controls =;

/* Right ADC mux */
static const struct snd_kcontrol_new wm8753_adc_right_controls =;

/* MIC mux */
static const struct snd_kcontrol_new wm8753_mic_mux_controls =;

/* ALC mixer */
static const struct snd_kcontrol_new wm8753_alc_mixer_controls[] =;

/* Left Line mux */
static const struct snd_kcontrol_new wm8753_line_left_controls =;

/* Right Line mux */
static const struct snd_kcontrol_new wm8753_line_right_controls =;

/* Mono Line mux */
static const struct snd_kcontrol_new wm8753_line_mono_controls =;

/* Line mux and mixer */
static const struct snd_kcontrol_new wm8753_line_mux_mix_controls =;

/* Rx mux and mixer */
static const struct snd_kcontrol_new wm8753_rx_mux_mix_controls =;

/* Mic Selector Mux */
static const struct snd_kcontrol_new wm8753_mic_sel_mux_controls =;

static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] =;

static const struct snd_soc_dapm_route wm8753_dapm_routes[] =;

/* PLL divisors */
struct _pll_div {};

/* The size in bits of the pll divide multiplied by 10
 * to allow rounding later */
#define FIXED_PLL_SIZE

static void pll_factors(struct _pll_div *pll_div, unsigned int target,
	unsigned int source)
{}

static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
		int source, unsigned int freq_in, unsigned int freq_out)
{}

struct _coeff_div {};

/* codec hifi mclk (after PLL) clock divider coefficients */
static const struct _coeff_div coeff_div[] =;

static int get_coeff(int mclk, int rate)
{}

/*
 * Clock after PLL and dividers
 */
static int wm8753_set_dai_sysclk(struct snd_soc_dai *codec_dai,
		int clk_id, unsigned int freq, int dir)
{}

/*
 * Set's ADC and Voice DAC format.
 */
static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_component *component,
		unsigned int fmt)
{}

/*
 * Set PCM DAI bit size and sample rate.
 */
static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
				struct snd_pcm_hw_params *params,
				struct snd_soc_dai *dai)
{}

/*
 * Set's PCM dai fmt and BCLK.
 */
static int wm8753_pcm_set_dai_fmt(struct snd_soc_component *component,
		unsigned int fmt)
{}

static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
		int div_id, int div)
{}

/*
 * Set's HiFi DAC format.
 */
static int wm8753_hdac_set_dai_fmt(struct snd_soc_component *component,
		unsigned int fmt)
{}

/*
 * Set's I2S DAI format.
 */
static int wm8753_i2s_set_dai_fmt(struct snd_soc_component *component,
		unsigned int fmt)
{}

/*
 * Set PCM DAI bit size and sample rate.
 */
static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
				struct snd_pcm_hw_params *params,
				struct snd_soc_dai *dai)
{}

static int wm8753_mode1v_set_dai_fmt(struct snd_soc_component *component,
		unsigned int fmt)
{}

static int wm8753_mode1h_set_dai_fmt(struct snd_soc_component *component,
		unsigned int fmt)
{}

static int wm8753_mode2_set_dai_fmt(struct snd_soc_component *component,
		unsigned int fmt)
{}

static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_component *component,
		unsigned int fmt)
{}

static int wm8753_hifi_write_dai_fmt(struct snd_soc_component *component,
		unsigned int fmt)
{}

static int wm8753_hifi_set_dai_fmt(struct snd_soc_dai *codec_dai,
		unsigned int fmt)
{
	struct snd_soc_component *component = codec_dai->component;
	struct wm8753_priv *wm8753 = snd_soc_component_get_drvdata(component);

	wm8753->hifi_fmt = fmt;

	return wm8753_hifi_write_dai_fmt(component, fmt);
};

static int wm8753_voice_write_dai_fmt(struct snd_soc_component *component,
		unsigned int fmt)
{
	struct wm8753_priv *wm8753 = snd_soc_component_get_drvdata(component);
	int ret = 0;

	if (wm8753->dai_func != 0)
		return 0;

	ret = wm8753_mode1v_set_dai_fmt(component, fmt);
	if (ret)
		return ret;
	ret = wm8753_pcm_set_dai_fmt(component, fmt);
	if (ret)
		return ret;

	return 0;
};

static int wm8753_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
		unsigned int fmt)
{
	struct snd_soc_component *component = codec_dai->component;
	struct wm8753_priv *wm8753 = snd_soc_component_get_drvdata(component);

	wm8753->voice_fmt = fmt;

	return wm8753_voice_write_dai_fmt(component, fmt);
};

static int wm8753_mute(struct snd_soc_dai *dai, int mute, int direction)
{}

static void wm8753_charge_work(struct work_struct *work)
{}

static int wm8753_set_bias_level(struct snd_soc_component *component,
				 enum snd_soc_bias_level level)
{}

#define WM8753_RATES

#define WM8753_FORMATS

/*
 * The WM8753 supports up to 4 different and mutually exclusive DAI
 * configurations. This gives 2 PCM's available for use, hifi and voice.
 * NOTE: The Voice PCM cannot play or capture audio to the CPU as it's DAI
 * is connected between the wm8753 and a BT codec or GSM modem.
 *
 * 1. Voice over PCM DAI - HIFI DAC over HIFI DAI
 * 2. Voice over HIFI DAI - HIFI disabled
 * 3. Voice disabled - HIFI over HIFI
 * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture
 */
static const struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode =;

static const struct snd_soc_dai_ops wm8753_dai_ops_voice_mode =;

static struct snd_soc_dai_driver wm8753_dai[] =;

static int wm8753_resume(struct snd_soc_component *component)
{}

static int wm8753_probe(struct snd_soc_component *component)
{}

static const struct snd_soc_component_driver soc_component_dev_wm8753 =;

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

static const struct regmap_config wm8753_regmap =;

#if defined(CONFIG_SPI_MASTER)
static int wm8753_spi_probe(struct spi_device *spi)
{}

static struct spi_driver wm8753_spi_driver =;
#endif /* CONFIG_SPI_MASTER */

#if IS_ENABLED(CONFIG_I2C)
static int wm8753_i2c_probe(struct i2c_client *i2c)
{}

static const struct i2c_device_id wm8753_i2c_id[] =;
MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id);

static struct i2c_driver wm8753_i2c_driver =;
#endif

static int __init wm8753_modinit(void)
{}
module_init();

static void __exit wm8753_exit(void)
{}
module_exit(wm8753_exit);

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