18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * ASoC codec driver for spear platform
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * sound/soc/codecs/sta529.c -- spear ALSA Soc codec driver
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Copyright (C) 2012 ST Microelectronics
78c2ecf20Sopenharmony_ci * Rajeev Kumar <rajeevkumar.linux@gmail.com>
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * This file is licensed under the terms of the GNU General Public
108c2ecf20Sopenharmony_ci * License version 2. This program is licensed "as is" without any
118c2ecf20Sopenharmony_ci * warranty of any kind, whether express or implied.
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <linux/clk.h>
158c2ecf20Sopenharmony_ci#include <linux/init.h>
168c2ecf20Sopenharmony_ci#include <linux/i2c.h>
178c2ecf20Sopenharmony_ci#include <linux/io.h>
188c2ecf20Sopenharmony_ci#include <linux/module.h>
198c2ecf20Sopenharmony_ci#include <linux/moduleparam.h>
208c2ecf20Sopenharmony_ci#include <linux/pm.h>
218c2ecf20Sopenharmony_ci#include <linux/regmap.h>
228c2ecf20Sopenharmony_ci#include <linux/slab.h>
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#include <sound/core.h>
258c2ecf20Sopenharmony_ci#include <sound/initval.h>
268c2ecf20Sopenharmony_ci#include <sound/pcm.h>
278c2ecf20Sopenharmony_ci#include <sound/pcm_params.h>
288c2ecf20Sopenharmony_ci#include <sound/soc.h>
298c2ecf20Sopenharmony_ci#include <sound/soc-dapm.h>
308c2ecf20Sopenharmony_ci#include <sound/tlv.h>
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/* STA529 Register offsets */
338c2ecf20Sopenharmony_ci#define	 STA529_FFXCFG0		0x00
348c2ecf20Sopenharmony_ci#define	 STA529_FFXCFG1		0x01
358c2ecf20Sopenharmony_ci#define	 STA529_MVOL		0x02
368c2ecf20Sopenharmony_ci#define	 STA529_LVOL		0x03
378c2ecf20Sopenharmony_ci#define	 STA529_RVOL		0x04
388c2ecf20Sopenharmony_ci#define	 STA529_TTF0		0x05
398c2ecf20Sopenharmony_ci#define	 STA529_TTF1		0x06
408c2ecf20Sopenharmony_ci#define	 STA529_TTP0		0x07
418c2ecf20Sopenharmony_ci#define	 STA529_TTP1		0x08
428c2ecf20Sopenharmony_ci#define	 STA529_S2PCFG0		0x0A
438c2ecf20Sopenharmony_ci#define	 STA529_S2PCFG1		0x0B
448c2ecf20Sopenharmony_ci#define	 STA529_P2SCFG0		0x0C
458c2ecf20Sopenharmony_ci#define	 STA529_P2SCFG1		0x0D
468c2ecf20Sopenharmony_ci#define	 STA529_PLLCFG0		0x14
478c2ecf20Sopenharmony_ci#define	 STA529_PLLCFG1		0x15
488c2ecf20Sopenharmony_ci#define	 STA529_PLLCFG2		0x16
498c2ecf20Sopenharmony_ci#define	 STA529_PLLCFG3		0x17
508c2ecf20Sopenharmony_ci#define	 STA529_PLLPFE		0x18
518c2ecf20Sopenharmony_ci#define	 STA529_PLLST		0x19
528c2ecf20Sopenharmony_ci#define	 STA529_ADCCFG		0x1E /*mic_select*/
538c2ecf20Sopenharmony_ci#define	 STA529_CKOCFG		0x1F
548c2ecf20Sopenharmony_ci#define	 STA529_MISC		0x20
558c2ecf20Sopenharmony_ci#define	 STA529_PADST0		0x21
568c2ecf20Sopenharmony_ci#define	 STA529_PADST1		0x22
578c2ecf20Sopenharmony_ci#define	 STA529_FFXST		0x23
588c2ecf20Sopenharmony_ci#define	 STA529_PWMIN1		0x2D
598c2ecf20Sopenharmony_ci#define	 STA529_PWMIN2		0x2E
608c2ecf20Sopenharmony_ci#define	 STA529_POWST		0x32
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci#define STA529_MAX_REGISTER	0x32
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci#define STA529_RATES		(SNDRV_PCM_RATE_8000 | \
658c2ecf20Sopenharmony_ci				SNDRV_PCM_RATE_11025 | \
668c2ecf20Sopenharmony_ci				SNDRV_PCM_RATE_16000 | \
678c2ecf20Sopenharmony_ci				SNDRV_PCM_RATE_22050 | \
688c2ecf20Sopenharmony_ci				SNDRV_PCM_RATE_32000 | \
698c2ecf20Sopenharmony_ci				SNDRV_PCM_RATE_44100 | \
708c2ecf20Sopenharmony_ci				SNDRV_PCM_RATE_48000)
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci#define STA529_FORMAT		(SNDRV_PCM_FMTBIT_S16_LE | \
738c2ecf20Sopenharmony_ci				SNDRV_PCM_FMTBIT_S24_LE | \
748c2ecf20Sopenharmony_ci				SNDRV_PCM_FMTBIT_S32_LE)
758c2ecf20Sopenharmony_ci#define	S2PC_VALUE		0x98
768c2ecf20Sopenharmony_ci#define CLOCK_OUT		0x60
778c2ecf20Sopenharmony_ci#define DATA_FORMAT_MSK		0x0E
788c2ecf20Sopenharmony_ci#define LEFT_J_DATA_FORMAT	0x00
798c2ecf20Sopenharmony_ci#define I2S_DATA_FORMAT		0x02
808c2ecf20Sopenharmony_ci#define RIGHT_J_DATA_FORMAT	0x04
818c2ecf20Sopenharmony_ci#define CODEC_MUTE_VAL		0x80
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci#define POWER_CNTLMSAK		0x40
848c2ecf20Sopenharmony_ci#define POWER_STDBY		0x40
858c2ecf20Sopenharmony_ci#define FFX_MASK		0x80
868c2ecf20Sopenharmony_ci#define FFX_OFF			0x80
878c2ecf20Sopenharmony_ci#define POWER_UP		0x00
888c2ecf20Sopenharmony_ci#define FFX_CLK_ENB		0x01
898c2ecf20Sopenharmony_ci#define FFX_CLK_DIS		0x00
908c2ecf20Sopenharmony_ci#define FFX_CLK_MSK		0x01
918c2ecf20Sopenharmony_ci#define PLAY_FREQ_RANGE_MSK	0x70
928c2ecf20Sopenharmony_ci#define CAP_FREQ_RANGE_MSK	0x0C
938c2ecf20Sopenharmony_ci#define PDATA_LEN_MSK		0xC0
948c2ecf20Sopenharmony_ci#define BCLK_TO_FS_MSK		0x30
958c2ecf20Sopenharmony_ci#define AUDIO_MUTE_MSK		0x80
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cistatic const struct reg_default sta529_reg_defaults[] = {
988c2ecf20Sopenharmony_ci	{ 0,  0x35 },     /* R0   - FFX Configuration reg 0 */
998c2ecf20Sopenharmony_ci	{ 1,  0xc8 },     /* R1   - FFX Configuration reg 1 */
1008c2ecf20Sopenharmony_ci	{ 2,  0x50 },     /* R2   - Master Volume */
1018c2ecf20Sopenharmony_ci	{ 3,  0x00 },     /* R3   - Left Volume */
1028c2ecf20Sopenharmony_ci	{ 4,  0x00 },     /* R4  -  Right Volume */
1038c2ecf20Sopenharmony_ci	{ 10, 0xb2 },     /* R10  - S2P Config Reg 0 */
1048c2ecf20Sopenharmony_ci	{ 11, 0x41 },     /* R11  - S2P Config Reg 1 */
1058c2ecf20Sopenharmony_ci	{ 12, 0x92 },     /* R12  - P2S Config Reg 0 */
1068c2ecf20Sopenharmony_ci	{ 13, 0x41 },     /* R13  - P2S Config Reg 1 */
1078c2ecf20Sopenharmony_ci	{ 30, 0xd2 },     /* R30  - ADC Config Reg */
1088c2ecf20Sopenharmony_ci	{ 31, 0x40 },     /* R31  - clock Out Reg */
1098c2ecf20Sopenharmony_ci	{ 32, 0x21 },     /* R32  - Misc Register */
1108c2ecf20Sopenharmony_ci};
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_cistruct sta529 {
1138c2ecf20Sopenharmony_ci	struct regmap *regmap;
1148c2ecf20Sopenharmony_ci};
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_cistatic bool sta529_readable(struct device *dev, unsigned int reg)
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci	switch (reg) {
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	case STA529_FFXCFG0:
1218c2ecf20Sopenharmony_ci	case STA529_FFXCFG1:
1228c2ecf20Sopenharmony_ci	case STA529_MVOL:
1238c2ecf20Sopenharmony_ci	case STA529_LVOL:
1248c2ecf20Sopenharmony_ci	case STA529_RVOL:
1258c2ecf20Sopenharmony_ci	case STA529_S2PCFG0:
1268c2ecf20Sopenharmony_ci	case STA529_S2PCFG1:
1278c2ecf20Sopenharmony_ci	case STA529_P2SCFG0:
1288c2ecf20Sopenharmony_ci	case STA529_P2SCFG1:
1298c2ecf20Sopenharmony_ci	case STA529_ADCCFG:
1308c2ecf20Sopenharmony_ci	case STA529_CKOCFG:
1318c2ecf20Sopenharmony_ci	case STA529_MISC:
1328c2ecf20Sopenharmony_ci		return true;
1338c2ecf20Sopenharmony_ci	default:
1348c2ecf20Sopenharmony_ci		return false;
1358c2ecf20Sopenharmony_ci	}
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_cistatic const char *pwm_mode_text[] = { "Binary", "Headphone", "Ternary",
1408c2ecf20Sopenharmony_ci	"Phase-shift"};
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(out_gain_tlv, -9150, 50, 0);
1438c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(master_vol_tlv, -12750, 50, 0);
1448c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text);
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new sta529_snd_controls[] = {
1478c2ecf20Sopenharmony_ci	SOC_DOUBLE_R_TLV("Digital Playback Volume", STA529_LVOL, STA529_RVOL, 0,
1488c2ecf20Sopenharmony_ci			127, 0, out_gain_tlv),
1498c2ecf20Sopenharmony_ci	SOC_SINGLE_TLV("Master Playback Volume", STA529_MVOL, 0, 127, 1,
1508c2ecf20Sopenharmony_ci			master_vol_tlv),
1518c2ecf20Sopenharmony_ci	SOC_ENUM("PWM Select", pwm_src),
1528c2ecf20Sopenharmony_ci};
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_cistatic int sta529_set_bias_level(struct snd_soc_component *component, enum
1558c2ecf20Sopenharmony_ci		snd_soc_bias_level level)
1568c2ecf20Sopenharmony_ci{
1578c2ecf20Sopenharmony_ci	struct sta529 *sta529 = snd_soc_component_get_drvdata(component);
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	switch (level) {
1608c2ecf20Sopenharmony_ci	case SND_SOC_BIAS_ON:
1618c2ecf20Sopenharmony_ci	case SND_SOC_BIAS_PREPARE:
1628c2ecf20Sopenharmony_ci		snd_soc_component_update_bits(component, STA529_FFXCFG0, POWER_CNTLMSAK,
1638c2ecf20Sopenharmony_ci				POWER_UP);
1648c2ecf20Sopenharmony_ci		snd_soc_component_update_bits(component, STA529_MISC,	FFX_CLK_MSK,
1658c2ecf20Sopenharmony_ci				FFX_CLK_ENB);
1668c2ecf20Sopenharmony_ci		break;
1678c2ecf20Sopenharmony_ci	case SND_SOC_BIAS_STANDBY:
1688c2ecf20Sopenharmony_ci		if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
1698c2ecf20Sopenharmony_ci			regcache_sync(sta529->regmap);
1708c2ecf20Sopenharmony_ci		snd_soc_component_update_bits(component, STA529_FFXCFG0,
1718c2ecf20Sopenharmony_ci					POWER_CNTLMSAK, POWER_STDBY);
1728c2ecf20Sopenharmony_ci		/* Making FFX output to zero */
1738c2ecf20Sopenharmony_ci		snd_soc_component_update_bits(component, STA529_FFXCFG0, FFX_MASK,
1748c2ecf20Sopenharmony_ci				FFX_OFF);
1758c2ecf20Sopenharmony_ci		snd_soc_component_update_bits(component, STA529_MISC, FFX_CLK_MSK,
1768c2ecf20Sopenharmony_ci				FFX_CLK_DIS);
1778c2ecf20Sopenharmony_ci		break;
1788c2ecf20Sopenharmony_ci	case SND_SOC_BIAS_OFF:
1798c2ecf20Sopenharmony_ci		break;
1808c2ecf20Sopenharmony_ci	}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	return 0;
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci}
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_cistatic int sta529_hw_params(struct snd_pcm_substream *substream,
1878c2ecf20Sopenharmony_ci		struct snd_pcm_hw_params *params,
1888c2ecf20Sopenharmony_ci		struct snd_soc_dai *dai)
1898c2ecf20Sopenharmony_ci{
1908c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
1918c2ecf20Sopenharmony_ci	int pdata, play_freq_val, record_freq_val;
1928c2ecf20Sopenharmony_ci	int bclk_to_fs_ratio;
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	switch (params_width(params)) {
1958c2ecf20Sopenharmony_ci	case 16:
1968c2ecf20Sopenharmony_ci		pdata = 1;
1978c2ecf20Sopenharmony_ci		bclk_to_fs_ratio = 0;
1988c2ecf20Sopenharmony_ci		break;
1998c2ecf20Sopenharmony_ci	case 24:
2008c2ecf20Sopenharmony_ci		pdata = 2;
2018c2ecf20Sopenharmony_ci		bclk_to_fs_ratio = 1;
2028c2ecf20Sopenharmony_ci		break;
2038c2ecf20Sopenharmony_ci	case 32:
2048c2ecf20Sopenharmony_ci		pdata = 3;
2058c2ecf20Sopenharmony_ci		bclk_to_fs_ratio = 2;
2068c2ecf20Sopenharmony_ci		break;
2078c2ecf20Sopenharmony_ci	default:
2088c2ecf20Sopenharmony_ci		dev_err(component->dev, "Unsupported format\n");
2098c2ecf20Sopenharmony_ci		return -EINVAL;
2108c2ecf20Sopenharmony_ci	}
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	switch (params_rate(params)) {
2138c2ecf20Sopenharmony_ci	case 8000:
2148c2ecf20Sopenharmony_ci	case 11025:
2158c2ecf20Sopenharmony_ci		play_freq_val = 0;
2168c2ecf20Sopenharmony_ci		record_freq_val = 2;
2178c2ecf20Sopenharmony_ci		break;
2188c2ecf20Sopenharmony_ci	case 16000:
2198c2ecf20Sopenharmony_ci	case 22050:
2208c2ecf20Sopenharmony_ci		play_freq_val = 1;
2218c2ecf20Sopenharmony_ci		record_freq_val = 0;
2228c2ecf20Sopenharmony_ci		break;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	case 32000:
2258c2ecf20Sopenharmony_ci	case 44100:
2268c2ecf20Sopenharmony_ci	case 48000:
2278c2ecf20Sopenharmony_ci		play_freq_val = 2;
2288c2ecf20Sopenharmony_ci		record_freq_val = 0;
2298c2ecf20Sopenharmony_ci		break;
2308c2ecf20Sopenharmony_ci	default:
2318c2ecf20Sopenharmony_ci		dev_err(component->dev, "Unsupported rate\n");
2328c2ecf20Sopenharmony_ci		return -EINVAL;
2338c2ecf20Sopenharmony_ci	}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
2368c2ecf20Sopenharmony_ci		snd_soc_component_update_bits(component, STA529_S2PCFG1, PDATA_LEN_MSK,
2378c2ecf20Sopenharmony_ci				pdata << 6);
2388c2ecf20Sopenharmony_ci		snd_soc_component_update_bits(component, STA529_S2PCFG1, BCLK_TO_FS_MSK,
2398c2ecf20Sopenharmony_ci				bclk_to_fs_ratio << 4);
2408c2ecf20Sopenharmony_ci		snd_soc_component_update_bits(component, STA529_MISC, PLAY_FREQ_RANGE_MSK,
2418c2ecf20Sopenharmony_ci				play_freq_val << 4);
2428c2ecf20Sopenharmony_ci	} else {
2438c2ecf20Sopenharmony_ci		snd_soc_component_update_bits(component, STA529_P2SCFG1, PDATA_LEN_MSK,
2448c2ecf20Sopenharmony_ci				pdata << 6);
2458c2ecf20Sopenharmony_ci		snd_soc_component_update_bits(component, STA529_P2SCFG1, BCLK_TO_FS_MSK,
2468c2ecf20Sopenharmony_ci				bclk_to_fs_ratio << 4);
2478c2ecf20Sopenharmony_ci		snd_soc_component_update_bits(component, STA529_MISC, CAP_FREQ_RANGE_MSK,
2488c2ecf20Sopenharmony_ci				record_freq_val << 2);
2498c2ecf20Sopenharmony_ci	}
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	return 0;
2528c2ecf20Sopenharmony_ci}
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_cistatic int sta529_mute(struct snd_soc_dai *dai, int mute, int direction)
2558c2ecf20Sopenharmony_ci{
2568c2ecf20Sopenharmony_ci	u8 val = 0;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	if (mute)
2598c2ecf20Sopenharmony_ci		val |= CODEC_MUTE_VAL;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	snd_soc_component_update_bits(dai->component, STA529_FFXCFG0, AUDIO_MUTE_MSK, val);
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	return 0;
2648c2ecf20Sopenharmony_ci}
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_cistatic int sta529_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
2678c2ecf20Sopenharmony_ci{
2688c2ecf20Sopenharmony_ci	struct snd_soc_component *component = codec_dai->component;
2698c2ecf20Sopenharmony_ci	u8 mode = 0;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	/* interface format */
2728c2ecf20Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
2738c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_LEFT_J:
2748c2ecf20Sopenharmony_ci		mode = LEFT_J_DATA_FORMAT;
2758c2ecf20Sopenharmony_ci		break;
2768c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_I2S:
2778c2ecf20Sopenharmony_ci		mode = I2S_DATA_FORMAT;
2788c2ecf20Sopenharmony_ci		break;
2798c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_RIGHT_J:
2808c2ecf20Sopenharmony_ci		mode = RIGHT_J_DATA_FORMAT;
2818c2ecf20Sopenharmony_ci		break;
2828c2ecf20Sopenharmony_ci	default:
2838c2ecf20Sopenharmony_ci		return -EINVAL;
2848c2ecf20Sopenharmony_ci	}
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	snd_soc_component_update_bits(component, STA529_S2PCFG0, DATA_FORMAT_MSK, mode);
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	return 0;
2898c2ecf20Sopenharmony_ci}
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_cistatic const struct snd_soc_dai_ops sta529_dai_ops = {
2928c2ecf20Sopenharmony_ci	.hw_params	=	sta529_hw_params,
2938c2ecf20Sopenharmony_ci	.set_fmt	=	sta529_set_dai_fmt,
2948c2ecf20Sopenharmony_ci	.mute_stream	=	sta529_mute,
2958c2ecf20Sopenharmony_ci	.no_capture_mute = 1,
2968c2ecf20Sopenharmony_ci};
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver sta529_dai = {
2998c2ecf20Sopenharmony_ci	.name = "sta529-audio",
3008c2ecf20Sopenharmony_ci	.playback = {
3018c2ecf20Sopenharmony_ci		.stream_name = "Playback",
3028c2ecf20Sopenharmony_ci		.channels_min = 2,
3038c2ecf20Sopenharmony_ci		.channels_max = 2,
3048c2ecf20Sopenharmony_ci		.rates = STA529_RATES,
3058c2ecf20Sopenharmony_ci		.formats = STA529_FORMAT,
3068c2ecf20Sopenharmony_ci	},
3078c2ecf20Sopenharmony_ci	.capture = {
3088c2ecf20Sopenharmony_ci		.stream_name = "Capture",
3098c2ecf20Sopenharmony_ci		.channels_min = 2,
3108c2ecf20Sopenharmony_ci		.channels_max = 2,
3118c2ecf20Sopenharmony_ci		.rates = STA529_RATES,
3128c2ecf20Sopenharmony_ci		.formats = STA529_FORMAT,
3138c2ecf20Sopenharmony_ci	},
3148c2ecf20Sopenharmony_ci	.ops	= &sta529_dai_ops,
3158c2ecf20Sopenharmony_ci};
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_cistatic const struct snd_soc_component_driver sta529_component_driver = {
3188c2ecf20Sopenharmony_ci	.set_bias_level		= sta529_set_bias_level,
3198c2ecf20Sopenharmony_ci	.controls		= sta529_snd_controls,
3208c2ecf20Sopenharmony_ci	.num_controls		= ARRAY_SIZE(sta529_snd_controls),
3218c2ecf20Sopenharmony_ci	.suspend_bias_off	= 1,
3228c2ecf20Sopenharmony_ci	.idle_bias_on		= 1,
3238c2ecf20Sopenharmony_ci	.use_pmdown_time	= 1,
3248c2ecf20Sopenharmony_ci	.endianness		= 1,
3258c2ecf20Sopenharmony_ci	.non_legacy_dai_naming	= 1,
3268c2ecf20Sopenharmony_ci};
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_cistatic const struct regmap_config sta529_regmap = {
3298c2ecf20Sopenharmony_ci	.reg_bits = 8,
3308c2ecf20Sopenharmony_ci	.val_bits = 8,
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	.max_register = STA529_MAX_REGISTER,
3338c2ecf20Sopenharmony_ci	.readable_reg = sta529_readable,
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	.cache_type = REGCACHE_RBTREE,
3368c2ecf20Sopenharmony_ci	.reg_defaults = sta529_reg_defaults,
3378c2ecf20Sopenharmony_ci	.num_reg_defaults = ARRAY_SIZE(sta529_reg_defaults),
3388c2ecf20Sopenharmony_ci};
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_cistatic int sta529_i2c_probe(struct i2c_client *i2c,
3418c2ecf20Sopenharmony_ci			    const struct i2c_device_id *id)
3428c2ecf20Sopenharmony_ci{
3438c2ecf20Sopenharmony_ci	struct sta529 *sta529;
3448c2ecf20Sopenharmony_ci	int ret;
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	sta529 = devm_kzalloc(&i2c->dev, sizeof(struct sta529), GFP_KERNEL);
3478c2ecf20Sopenharmony_ci	if (!sta529)
3488c2ecf20Sopenharmony_ci		return -ENOMEM;
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	sta529->regmap = devm_regmap_init_i2c(i2c, &sta529_regmap);
3518c2ecf20Sopenharmony_ci	if (IS_ERR(sta529->regmap)) {
3528c2ecf20Sopenharmony_ci		ret = PTR_ERR(sta529->regmap);
3538c2ecf20Sopenharmony_ci		dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
3548c2ecf20Sopenharmony_ci		return ret;
3558c2ecf20Sopenharmony_ci	}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	i2c_set_clientdata(i2c, sta529);
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	ret = devm_snd_soc_register_component(&i2c->dev,
3608c2ecf20Sopenharmony_ci			&sta529_component_driver, &sta529_dai, 1);
3618c2ecf20Sopenharmony_ci	if (ret != 0)
3628c2ecf20Sopenharmony_ci		dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	return ret;
3658c2ecf20Sopenharmony_ci}
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_cistatic const struct i2c_device_id sta529_i2c_id[] = {
3688c2ecf20Sopenharmony_ci	{ "sta529", 0 },
3698c2ecf20Sopenharmony_ci	{ }
3708c2ecf20Sopenharmony_ci};
3718c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, sta529_i2c_id);
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_cistatic const struct of_device_id sta529_of_match[] = {
3748c2ecf20Sopenharmony_ci	{ .compatible = "st,sta529", },
3758c2ecf20Sopenharmony_ci	{ }
3768c2ecf20Sopenharmony_ci};
3778c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, sta529_of_match);
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_cistatic struct i2c_driver sta529_i2c_driver = {
3808c2ecf20Sopenharmony_ci	.driver = {
3818c2ecf20Sopenharmony_ci		.name = "sta529",
3828c2ecf20Sopenharmony_ci		.of_match_table = sta529_of_match,
3838c2ecf20Sopenharmony_ci	},
3848c2ecf20Sopenharmony_ci	.probe		= sta529_i2c_probe,
3858c2ecf20Sopenharmony_ci	.id_table	= sta529_i2c_id,
3868c2ecf20Sopenharmony_ci};
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_cimodule_i2c_driver(sta529_i2c_driver);
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ASoC STA529 codec driver");
3918c2ecf20Sopenharmony_ciMODULE_AUTHOR("Rajeev Kumar <rajeevkumar.linux@gmail.com>");
3928c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
393