linux/sound/soc/codecs/ak4613.c

// SPDX-License-Identifier: GPL-2.0
//
// ak4613.c  --  Asahi Kasei ALSA Soc Audio driver
//
// Copyright (C) 2015 Renesas Electronics Corporation
// Kuninori Morimoto <[email protected]>
//
// Based on ak4642.c by Kuninori Morimoto
// Based on wm8731.c by Richard Purdie
// Based on ak4535.c by Richard Purdie
// Based on wm8753.c by Liam Girdwood

/*
 *		+-------+
 *		|AK4613	|
 *	SDTO1 <-|	|
 *		|	|
 *	SDTI1 ->|	|
 *	SDTI2 ->|	|
 *	SDTI3 ->|	|
 *		+-------+
 *
 *	  +---+
 * clk	  |   |___________________________________________...
 *
 * [TDM512]
 * SDTO1  [L1][R1][L2][R2]
 * SDTI1  [L1][R1][L2][R2][L3][R3][L4][R4][L5][R5][L6][R6]
 *
 * [TDM256]
 * SDTO1  [L1][R1][L2][R2]
 * SDTI1  [L1][R1][L2][R2][L3][R3][L4][R4]
 * SDTI2  [L5][R5][L6][R6]
 *
 * [TDM128]
 * SDTO1  [L1][R1][L2][R2]
 * SDTI1  [L1][R1][L2][R2]
 * SDTI2  [L3][R3][L4][R4]
 * SDTI3  [L5][R5][L6][R6]
 *
 * [STEREO]
 *	Playback  2ch : SDTI1
 *	Capture   2ch : SDTO1
 *
 * [TDM512]
 *	Playback 12ch : SDTI1
 *	Capture   4ch : SDTO1
 *
 * [TDM256]
 *	Playback 12ch : SDTI1 + SDTI2
 *	Playback  8ch : SDTI1
 *	Capture   4ch : SDTO1
 *
 * [TDM128]
 *	Playback 12ch : SDTI1 + SDTI2 + SDTI3
 *	Playback  8ch : SDTI1 + SDTI2
 *	Playback  4ch : SDTI1
 *	Capture   4ch : SDTO1
 *
 *
 * !!! NOTE !!!
 *
 * Renesas is the only user of ak4613 on upstream so far,
 * but the chip connection is like below.
 * Thus, Renesas can't test all connection case.
 * Tested TDM is very limited.
 *
 * +-----+	+-----------+
 * | SoC |	|  AK4613   |
 * |     |<-----|SDTO1	 IN1|<-- Mic
 * |     |	|	 IN2|
 * |     |	|	    |
 * |     |----->|SDTI1	OUT1|--> Headphone
 * +-----+	|SDTI2	OUT2|
 *		|SDTI3	OUT3|
 *		|	OUT4|
 *		|	OUT5|
 *		|	OUT6|
 *		+-----------+
 *
 * Renesas SoC can handle [2,  6,8]    channels.
 * Ak4613      can handle [2,4,  8,12] channels.
 *
 * Because of above HW connection and available channels number,
 * Renesas could test are ...
 *
 *	[STEREO] Playback  2ch : SDTI1
 *		 Capture   2ch : SDTO1
 *	[TDM256] Playback  8ch : SDTI1 (*)
 *
 * (*) it used 8ch data between SoC <-> AK4613 on TDM256 mode,
 *     but could confirm is only first 2ch because only 1
 *     Headphone is connected.
 *
 * see
 *	AK4613_ENABLE_TDM_TEST
 */
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
#include <sound/tlv.h>

#define PW_MGMT1
#define PW_MGMT2
#define PW_MGMT3
#define CTRL1
#define CTRL2
#define DEMP1
#define DEMP2
#define OFD
#define ZRD
#define ICTRL
#define OCTRL
#define LOUT1
#define ROUT1
#define LOUT2
#define ROUT2
#define LOUT3
#define ROUT3
#define LOUT4
#define ROUT4
#define LOUT5
#define ROUT5
#define LOUT6
#define ROUT6

/* PW_MGMT1 */
#define RSTN
#define PMDAC
#define PMADC
#define PMVR

/* PW_MGMT2 */
#define PMAD_ALL

/* PW_MGMT3 */
#define PMDA_ALL

/* CTRL1 */
#define DIF0
#define DIF1
#define DIF2
#define TDM0
#define TDM1
#define NO_FMT
#define FMT_MASK

/* CTRL2 */
#define DFS_MASK
#define DFS_NORMAL_SPEED
#define DFS_DOUBLE_SPEED
#define DFS_QUAD_SPEED

/* ICTRL */
#define ICTRL_MASK

/* OCTRL */
#define OCTRL_MASK

/*
 * configs
 *
 * 0x000000BA
 *
 * B : AK4613_CONFIG_SDTI_x
 * A : AK4613_CONFIG_MODE_x
 */
#define AK4613_CONFIG_SET(priv, x)
#define AK4613_CONFIG_GET(priv, x)

/*
 * AK4613_CONFIG_SDTI_x
 *
 * It indicates how many SDTIx is connected.
 */
#define AK4613_CONFIG_SDTI_MASK
#define AK4613_CONFIG_SDTI(x)
#define AK4613_CONFIG_SDTI_set(priv, x)
#define AK4613_CONFIG_SDTI_get(priv)

/*
 * AK4613_CONFIG_MODE_x
 *
 * Same as Ctrl1 :: TDM1/TDM0
 * No shift is requested
 * see
 *	AK4613_CTRL1_TO_MODE()
 *	Table 11/12/13/14
 */
#define AK4613_CONFIG_MODE_MASK
#define AK4613_CONFIG_MODE_STEREO
#define AK4613_CONFIG_MODE_TDM512
#define AK4613_CONFIG_MODE_TDM256
#define AK4613_CONFIG_MODE_TDM128

/*
 * !!!! FIXME !!!!
 *
 * Because of testable HW limitation, TDM256 8ch TDM was only tested.
 * This driver uses AK4613_ENABLE_TDM_TEST instead of new DT property so far.
 * Don't hesitate to update driver, you don't need to care compatible
 * with Renesas.
 *
 * #define AK4613_ENABLE_TDM_TEST
 */

struct ak4613_interface {};

struct ak4613_priv {};

/*
 * Playback Volume
 *
 * max : 0x00 : 0 dB
 *       ( 0.5 dB step )
 * min : 0xFE : -127.0 dB
 * mute: 0xFF
 */
static const DECLARE_TLV_DB_SCALE(out_tlv, -12750, 50, 1);

static const struct snd_kcontrol_new ak4613_snd_controls[] =;

static const struct reg_default ak4613_reg[] =;

/*
 * CTRL1 register
 * see
 *	Table 11/12/13/14
 */
#define AUDIO_IFACE(_dif, _width, _fmt)
static const struct ak4613_interface ak4613_iface[] =;
#define AK4613_CTRL1_TO_MODE(priv)

static const struct regmap_config ak4613_regmap_cfg =;

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

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

static const struct snd_soc_dapm_widget ak4613_dapm_widgets[] =;

static const struct snd_soc_dapm_route ak4613_intercon[] =;

static void ak4613_dai_shutdown(struct snd_pcm_substream *substream,
			       struct snd_soc_dai *dai)
{}

static void ak4613_hw_constraints(struct ak4613_priv *priv,
				  struct snd_pcm_substream *substream)
{}

static int ak4613_dai_startup(struct snd_pcm_substream *substream,
			      struct snd_soc_dai *dai)
{}

static int ak4613_dai_set_sysclk(struct snd_soc_dai *codec_dai,
				 int clk_id, unsigned int freq, int dir)
{}

static int ak4613_dai_set_fmt(struct snd_soc_dai *dai, unsigned int format)
{}

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

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

static void ak4613_dummy_write(struct work_struct *work)
{}

static int ak4613_dai_trigger(struct snd_pcm_substream *substream, int cmd,
			      struct snd_soc_dai *dai)
{}

/*
 * Select below from Sound Card, not Auto
 *	SND_SOC_DAIFMT_CBC_CFC
 *	SND_SOC_DAIFMT_CBP_CFP
 */
static const u64 ak4613_dai_formats =;

static const struct snd_soc_dai_ops ak4613_dai_ops =;

#define AK4613_PCM_RATE
#define AK4613_PCM_FMTBIT

static struct snd_soc_dai_driver ak4613_dai =;

static int ak4613_suspend(struct snd_soc_component *component)
{}

static int ak4613_resume(struct snd_soc_component *component)
{}

static const struct snd_soc_component_driver soc_component_dev_ak4613 =;

static void ak4613_parse_of(struct ak4613_priv *priv,
			    struct device *dev)
{}

static int ak4613_i2c_probe(struct i2c_client *i2c)
{}

static struct i2c_driver ak4613_i2c_driver =;

module_i2c_driver();

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