xref: /linux/sound/soc/codecs/sma1307.c (revision 25768de50b1f2dbb6ea44bd5148a87fe2c9c3688)
1576c57e6SKiseok Jo // SPDX-License-Identifier: GPL-2.0-or-later
2576c57e6SKiseok Jo // sma1307.c -- sma1307 ALSA SoC Audio driver
3576c57e6SKiseok Jo //
4576c57e6SKiseok Jo // Copyright 2024 Iron Device Corporation
5576c57e6SKiseok Jo //
6576c57e6SKiseok Jo // Auther: Gyuhwa Park <gyuwha.park@irondevice.com>
7576c57e6SKiseok Jo // Auther: Kiseok Jo <kiseok.jo@irondevice.com>
8576c57e6SKiseok Jo 
9576c57e6SKiseok Jo #include <linux/firmware.h>
10576c57e6SKiseok Jo #include <linux/i2c.h>
11576c57e6SKiseok Jo #include <linux/of_gpio.h>
12576c57e6SKiseok Jo #include <linux/regmap.h>
13576c57e6SKiseok Jo #include <sound/pcm_params.h>
14576c57e6SKiseok Jo #include <sound/tlv.h>
15576c57e6SKiseok Jo #include "sma1307.h"
16576c57e6SKiseok Jo 
17576c57e6SKiseok Jo #define CHECK_PERIOD_TIME 1	/* sec per HZ */
18576c57e6SKiseok Jo #define PLL_MATCH(_input_clk_name, _output_clk_name, _input_clk,\
19576c57e6SKiseok Jo 		_post_n, _n, _vco,  _p_cp)\
20576c57e6SKiseok Jo {\
21576c57e6SKiseok Jo 	.input_clk_name		= _input_clk_name,\
22576c57e6SKiseok Jo 	.output_clk_name	= _output_clk_name,\
23576c57e6SKiseok Jo 	.input_clk		= _input_clk,\
24576c57e6SKiseok Jo 	.post_n			= _post_n,\
25576c57e6SKiseok Jo 	.n			= _n,\
26576c57e6SKiseok Jo 	.vco			= _vco,\
27576c57e6SKiseok Jo 	.p_cp			= _p_cp,\
28576c57e6SKiseok Jo }
29576c57e6SKiseok Jo 
30576c57e6SKiseok Jo static const char *setting_file = "sma1307_setting.bin";
31576c57e6SKiseok Jo #define SMA1307_SETTING_CHECKSUM 0x100000
32576c57e6SKiseok Jo 
33576c57e6SKiseok Jo /* PLL clock setting Table */
34576c57e6SKiseok Jo struct sma1307_pll_match {
35576c57e6SKiseok Jo 	char *input_clk_name;
36576c57e6SKiseok Jo 	char *output_clk_name;
37576c57e6SKiseok Jo 	unsigned int input_clk;
38576c57e6SKiseok Jo 	unsigned int post_n;
39576c57e6SKiseok Jo 	unsigned int n;
40576c57e6SKiseok Jo 	unsigned int vco;
41576c57e6SKiseok Jo 	unsigned int p_cp;
42576c57e6SKiseok Jo };
43576c57e6SKiseok Jo 
44576c57e6SKiseok Jo struct sma1307_data {
45576c57e6SKiseok Jo 	char *name;
46576c57e6SKiseok Jo 	void (*init)(struct regmap *regmap);
47576c57e6SKiseok Jo };
48576c57e6SKiseok Jo 
49576c57e6SKiseok Jo struct sma1307_priv {
50576c57e6SKiseok Jo 	bool check_fault_status;
51576c57e6SKiseok Jo 	bool force_mute_status;
52576c57e6SKiseok Jo 	bool sw_ot1_prot;
53576c57e6SKiseok Jo 	char *name;
54576c57e6SKiseok Jo 	enum sma1307_mode amp_mode;
55576c57e6SKiseok Jo 	int binary_mode;
56576c57e6SKiseok Jo 	int dapm_aif_in;
57576c57e6SKiseok Jo 	int dapm_aif_out0;
58576c57e6SKiseok Jo 	int dapm_aif_out1;
59576c57e6SKiseok Jo 	int dapm_sdo_en;
60576c57e6SKiseok Jo 	int dapm_sdo_setting;
61576c57e6SKiseok Jo 	int num_of_pll_matches;
62576c57e6SKiseok Jo 	int check_fault_period;
63576c57e6SKiseok Jo 	struct delayed_work check_fault_work;
64576c57e6SKiseok Jo 	struct device *dev;
65576c57e6SKiseok Jo 	struct kobject *kobj;
66576c57e6SKiseok Jo 	struct mutex default_lock;
67576c57e6SKiseok Jo 	struct regmap *regmap;
68576c57e6SKiseok Jo 	struct sma1307_setting_file set;
69576c57e6SKiseok Jo 	const struct sma1307_pll_match *pll_matches;
70576c57e6SKiseok Jo 	const struct sma1307_data *data;
71576c57e6SKiseok Jo 	unsigned int cur_vol;
72576c57e6SKiseok Jo 	unsigned int format;
73576c57e6SKiseok Jo 	unsigned int frame_size;
74576c57e6SKiseok Jo 	unsigned int init_vol;
75576c57e6SKiseok Jo 	unsigned int last_bclk;
76576c57e6SKiseok Jo 	unsigned int otp_trm2;
77576c57e6SKiseok Jo 	unsigned int otp_trm3;
78576c57e6SKiseok Jo 	unsigned int rev_num;
79576c57e6SKiseok Jo 	unsigned int sys_clk_id;
80576c57e6SKiseok Jo 	unsigned int tdm_slot0_rx;
81576c57e6SKiseok Jo 	unsigned int tdm_slot1_rx;
82576c57e6SKiseok Jo 	unsigned int tdm_slot0_tx;
83576c57e6SKiseok Jo 	unsigned int tdm_slot1_tx;
84576c57e6SKiseok Jo 	unsigned int tsdw_cnt;
85576c57e6SKiseok Jo };
86576c57e6SKiseok Jo 
87576c57e6SKiseok Jo static const struct sma1307_pll_match sma1307_pll_matches[] = {
88576c57e6SKiseok Jo 	/* in_clk_name, out_clk_name, input_clk post_n, n, vco, p_cp */
89576c57e6SKiseok Jo 	PLL_MATCH("1.411MHz", "24.554MHz",
90576c57e6SKiseok Jo 		  1411200, 0x06, 0xD1, 0x88, 0x00),
91576c57e6SKiseok Jo 	PLL_MATCH("1.536MHz", "24.576MHz",
92576c57e6SKiseok Jo 		  1536000, 0x06, 0xC0, 0x88, 0x00),
93576c57e6SKiseok Jo 	PLL_MATCH("2.822MHz", "24.554MHz",
94576c57e6SKiseok Jo 		  2822400, 0x06, 0xD1, 0x88, 0x04),
95576c57e6SKiseok Jo 	PLL_MATCH("3.072MHz", "24.576MHz",
96576c57e6SKiseok Jo 		  3072000, 0x06, 0x60, 0x88, 0x00),
97576c57e6SKiseok Jo 	PLL_MATCH("6.144MHz", "24.576MHz",
98576c57e6SKiseok Jo 		  6144000, 0x06, 0x60, 0x88, 0x04),
99576c57e6SKiseok Jo 	PLL_MATCH("12.288MHz", "24.576MHz",
100576c57e6SKiseok Jo 		  12288000, 0x06, 0x60, 0x88, 0x08),
101576c57e6SKiseok Jo 	PLL_MATCH("19.2MHz", "24.48MHz",
102576c57e6SKiseok Jo 		  19200000, 0x06, 0x7B, 0x88, 0x0C),
103576c57e6SKiseok Jo 	PLL_MATCH("24.576MHz", "24.576MHz",
104576c57e6SKiseok Jo 		  24576000, 0x06, 0x60, 0x88, 0x0C),
105576c57e6SKiseok Jo };
106576c57e6SKiseok Jo 
107576c57e6SKiseok Jo static struct snd_soc_component *sma1307_amp_component;
108576c57e6SKiseok Jo 
109576c57e6SKiseok Jo static void sma1307_startup(struct snd_soc_component *);
110576c57e6SKiseok Jo static void sma1307_shutdown(struct snd_soc_component *);
111576c57e6SKiseok Jo static void sma1307_reset(struct snd_soc_component *);
112576c57e6SKiseok Jo static void sma1307_set_binary(struct snd_soc_component *);
113576c57e6SKiseok Jo static void sma1307_set_default(struct snd_soc_component *);
114576c57e6SKiseok Jo 
115576c57e6SKiseok Jo /* Initial register value - 6.0W SPK (8ohm load)  */
116576c57e6SKiseok Jo static const struct reg_default sma1307_reg_def[] = {
117576c57e6SKiseok Jo 	{ 0x00, 0x80 },
118576c57e6SKiseok Jo 	{ 0x01, 0x00 },
119576c57e6SKiseok Jo 	{ 0x02, 0x52 },
120576c57e6SKiseok Jo 	{ 0x03, 0x4C },
121576c57e6SKiseok Jo 	{ 0x04, 0x47 },
122576c57e6SKiseok Jo 	{ 0x05, 0x42 },
123576c57e6SKiseok Jo 	{ 0x06, 0x40 },
124576c57e6SKiseok Jo 	{ 0x07, 0x40 },
125576c57e6SKiseok Jo 	{ 0x08, 0x3C },
126576c57e6SKiseok Jo 	{ 0x09, 0x2F },
127576c57e6SKiseok Jo 	{ 0x0A, 0x32 },
128576c57e6SKiseok Jo 	{ 0x0B, 0x50 },
129576c57e6SKiseok Jo 	{ 0x0C, 0x8C },
130576c57e6SKiseok Jo 	{ 0x0D, 0x00 },
131576c57e6SKiseok Jo 	{ 0x0E, 0x3F },
132576c57e6SKiseok Jo 	{ 0x0F, 0x00 },
133576c57e6SKiseok Jo 	{ 0x10, 0x00 },
134576c57e6SKiseok Jo 	{ 0x11, 0x00 },
135576c57e6SKiseok Jo 	{ 0x12, 0x00 },
136576c57e6SKiseok Jo 	{ 0x13, 0x09 },
137576c57e6SKiseok Jo 	{ 0x14, 0x12 },
138576c57e6SKiseok Jo 	{ 0x1C, 0x00 },
139576c57e6SKiseok Jo 	{ 0x1D, 0x85 },
140576c57e6SKiseok Jo 	{ 0x1E, 0xA1 },
141576c57e6SKiseok Jo 	{ 0x1F, 0x67 },
142576c57e6SKiseok Jo 	{ 0x22, 0x00 },
143576c57e6SKiseok Jo 	{ 0x23, 0x1F },
144576c57e6SKiseok Jo 	{ 0x24, 0x7A },
145576c57e6SKiseok Jo 	{ 0x25, 0x00 },
146576c57e6SKiseok Jo 	{ 0x26, 0xFF },
147576c57e6SKiseok Jo 	{ 0x27, 0x39 },
148576c57e6SKiseok Jo 	{ 0x28, 0x54 },
149576c57e6SKiseok Jo 	{ 0x29, 0x92 },
150576c57e6SKiseok Jo 	{ 0x2A, 0xB0 },
151576c57e6SKiseok Jo 	{ 0x2B, 0xED },
152576c57e6SKiseok Jo 	{ 0x2C, 0xED },
153576c57e6SKiseok Jo 	{ 0x2D, 0xFF },
154576c57e6SKiseok Jo 	{ 0x2E, 0xFF },
155576c57e6SKiseok Jo 	{ 0x2F, 0xFF },
156576c57e6SKiseok Jo 	{ 0x30, 0xFF },
157576c57e6SKiseok Jo 	{ 0x31, 0xFF },
158576c57e6SKiseok Jo 	{ 0x32, 0xFF },
159576c57e6SKiseok Jo 	{ 0x34, 0x01 },
160576c57e6SKiseok Jo 	{ 0x35, 0x17 },
161576c57e6SKiseok Jo 	{ 0x36, 0x92 },
162576c57e6SKiseok Jo 	{ 0x37, 0x00 },
163576c57e6SKiseok Jo 	{ 0x38, 0x01 },
164576c57e6SKiseok Jo 	{ 0x39, 0x10 },
165576c57e6SKiseok Jo 	{ 0x3E, 0x01 },
166576c57e6SKiseok Jo 	{ 0x3F, 0x08 },
167576c57e6SKiseok Jo 	{ 0x8B, 0x05 },
168576c57e6SKiseok Jo 	{ 0x8C, 0x50 },
169576c57e6SKiseok Jo 	{ 0x8D, 0x80 },
170576c57e6SKiseok Jo 	{ 0x8E, 0x10 },
171576c57e6SKiseok Jo 	{ 0x8F, 0x02 },
172576c57e6SKiseok Jo 	{ 0x90, 0x02 },
173576c57e6SKiseok Jo 	{ 0x91, 0x83 },
174576c57e6SKiseok Jo 	{ 0x92, 0xC0 },
175576c57e6SKiseok Jo 	{ 0x93, 0x00 },
176576c57e6SKiseok Jo 	{ 0x94, 0xA4 },
177576c57e6SKiseok Jo 	{ 0x95, 0x74 },
178576c57e6SKiseok Jo 	{ 0x96, 0x57 },
179576c57e6SKiseok Jo 	{ 0xA2, 0xCC },
180576c57e6SKiseok Jo 	{ 0xA3, 0x28 },
181576c57e6SKiseok Jo 	{ 0xA4, 0x40 },
182576c57e6SKiseok Jo 	{ 0xA5, 0x01 },
183576c57e6SKiseok Jo 	{ 0xA6, 0x41 },
184576c57e6SKiseok Jo 	{ 0xA7, 0x08 },
185576c57e6SKiseok Jo 	{ 0xA8, 0x04 },
186576c57e6SKiseok Jo 	{ 0xA9, 0x27 },
187576c57e6SKiseok Jo 	{ 0xAA, 0x10 },
188576c57e6SKiseok Jo 	{ 0xAB, 0x10 },
189576c57e6SKiseok Jo 	{ 0xAC, 0x10 },
190576c57e6SKiseok Jo 	{ 0xAD, 0x0F },
191576c57e6SKiseok Jo 	{ 0xAE, 0xCD },
192576c57e6SKiseok Jo 	{ 0xAF, 0x70 },
193576c57e6SKiseok Jo 	{ 0xB0, 0x03 },
194576c57e6SKiseok Jo 	{ 0xB1, 0xEF },
195576c57e6SKiseok Jo 	{ 0xB2, 0x03 },
196576c57e6SKiseok Jo 	{ 0xB3, 0xEF },
197576c57e6SKiseok Jo 	{ 0xB4, 0xF3 },
198576c57e6SKiseok Jo 	{ 0xB5, 0x3D },
199576c57e6SKiseok Jo };
200576c57e6SKiseok Jo 
201576c57e6SKiseok Jo static bool sma1307_readable_register(struct device *dev, unsigned int reg)
202576c57e6SKiseok Jo {
203576c57e6SKiseok Jo 	if (reg > SMA1307_FF_DEVICE_INDEX)
204576c57e6SKiseok Jo 		return false;
205576c57e6SKiseok Jo 
206576c57e6SKiseok Jo 	switch (reg) {
207576c57e6SKiseok Jo 	case SMA1307_00_SYSTEM_CTRL ... SMA1307_1F_TONE_FINE_VOLUME:
208576c57e6SKiseok Jo 	case SMA1307_22_COMP_HYS_SEL ... SMA1307_32_BROWN_OUT_PROT19:
209576c57e6SKiseok Jo 	case SMA1307_34_OCP_SPK ... SMA1307_39_PMT_NZ_VAL:
210576c57e6SKiseok Jo 	case SMA1307_3B_TEST1 ... SMA1307_3F_ATEST2:
211576c57e6SKiseok Jo 	case SMA1307_8B_PLL_POST_N ... SMA1307_9A_OTP_TRM3:
212576c57e6SKiseok Jo 	case SMA1307_A0_PAD_CTRL0 ... SMA1307_BE_MCBS_CTRL2:
213576c57e6SKiseok Jo 	case SMA1307_F5_READY_FOR_V_SAR:
214576c57e6SKiseok Jo 	case SMA1307_F7_READY_FOR_T_SAR ... SMA1307_FF_DEVICE_INDEX:
215576c57e6SKiseok Jo 		break;
216576c57e6SKiseok Jo 	default:
217576c57e6SKiseok Jo 		return false;
218576c57e6SKiseok Jo 	}
219576c57e6SKiseok Jo 	return true;
220576c57e6SKiseok Jo }
221576c57e6SKiseok Jo 
222576c57e6SKiseok Jo static bool sma1307_writeable_register(struct device *dev, unsigned int reg)
223576c57e6SKiseok Jo {
224576c57e6SKiseok Jo 	if (reg > SMA1307_FF_DEVICE_INDEX)
225576c57e6SKiseok Jo 		return false;
226576c57e6SKiseok Jo 
227576c57e6SKiseok Jo 	switch (reg) {
228576c57e6SKiseok Jo 	case SMA1307_00_SYSTEM_CTRL ... SMA1307_1F_TONE_FINE_VOLUME:
229576c57e6SKiseok Jo 	case SMA1307_22_COMP_HYS_SEL ... SMA1307_32_BROWN_OUT_PROT19:
230576c57e6SKiseok Jo 	case SMA1307_34_OCP_SPK ... SMA1307_39_PMT_NZ_VAL:
231576c57e6SKiseok Jo 	case SMA1307_3B_TEST1 ... SMA1307_3F_ATEST2:
232576c57e6SKiseok Jo 	case SMA1307_8B_PLL_POST_N ... SMA1307_9A_OTP_TRM3:
233576c57e6SKiseok Jo 	case SMA1307_A0_PAD_CTRL0 ... SMA1307_BE_MCBS_CTRL2:
234576c57e6SKiseok Jo 		break;
235576c57e6SKiseok Jo 	default:
236576c57e6SKiseok Jo 		return false;
237576c57e6SKiseok Jo 	}
238576c57e6SKiseok Jo 	return true;
239576c57e6SKiseok Jo }
240576c57e6SKiseok Jo 
241576c57e6SKiseok Jo static bool sma1307_volatile_register(struct device *dev, unsigned int reg)
242576c57e6SKiseok Jo {
243576c57e6SKiseok Jo 	if (reg > SMA1307_FF_DEVICE_INDEX)
244576c57e6SKiseok Jo 		return false;
245576c57e6SKiseok Jo 
246576c57e6SKiseok Jo 	switch (reg) {
247576c57e6SKiseok Jo 	case SMA1307_F8_STATUS_T1 ... SMA1307_FF_DEVICE_INDEX:
248576c57e6SKiseok Jo 		break;
249576c57e6SKiseok Jo 	default:
250576c57e6SKiseok Jo 		return false;
251576c57e6SKiseok Jo 	}
252576c57e6SKiseok Jo 	return true;
253576c57e6SKiseok Jo }
254576c57e6SKiseok Jo 
255576c57e6SKiseok Jo /* DB scale conversion of speaker volume */
256576c57e6SKiseok Jo static const DECLARE_TLV_DB_SCALE(sma1307_spk_tlv, -6000, 50, 0);
257576c57e6SKiseok Jo 
258576c57e6SKiseok Jo static const char *const sma1307_aif_in_source_text[] = {
259576c57e6SKiseok Jo 	"Mono", "Left", "Right"
260576c57e6SKiseok Jo };
261576c57e6SKiseok Jo 
262576c57e6SKiseok Jo static const char *const sma1307_sdo_setting_text[] = {
263576c57e6SKiseok Jo 	"Data_One_48k", "Data_Two_48k", "Data_Two_24k",
264576c57e6SKiseok Jo 	"Clk_PLL", "Clk_OSC"
265576c57e6SKiseok Jo };
266576c57e6SKiseok Jo 
267576c57e6SKiseok Jo static const char *const sma1307_aif_out_source_text[] = {
268576c57e6SKiseok Jo 	"Disable", "After_FmtC", "After_Mixer", "After_DSP",
269576c57e6SKiseok Jo 	"Vrms2_Avg", "Battery", "Temperature", "After_Delay"
270576c57e6SKiseok Jo };
271576c57e6SKiseok Jo 
272576c57e6SKiseok Jo static const char *const sma1307_tdm_slot_text[] = {
273576c57e6SKiseok Jo 	"Slot0", "Slot1", "Slot2", "Slot3",
274576c57e6SKiseok Jo 	"Slot4", "Slot5", "Slot6", "Slot7"
275576c57e6SKiseok Jo };
276576c57e6SKiseok Jo 
277576c57e6SKiseok Jo static const char *const sma1307_binary_mode_text[] = {
278576c57e6SKiseok Jo 	"Mode0", "Mode1", "Mode2", "Mode3", "Mode4"
279576c57e6SKiseok Jo };
280576c57e6SKiseok Jo 
281576c57e6SKiseok Jo static const char *const sma1307_reset_text[] = {
282576c57e6SKiseok Jo 	"Reset"
283576c57e6SKiseok Jo };
284576c57e6SKiseok Jo 
285576c57e6SKiseok Jo static const struct soc_enum sma1307_aif_in_source_enum =
286576c57e6SKiseok Jo SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sma1307_aif_in_source_text),
287576c57e6SKiseok Jo 		    sma1307_aif_in_source_text);
288576c57e6SKiseok Jo static const struct soc_enum sma1307_sdo_setting_enum =
289576c57e6SKiseok Jo SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sma1307_sdo_setting_text),
290576c57e6SKiseok Jo 		    sma1307_sdo_setting_text);
291576c57e6SKiseok Jo static const struct soc_enum sma1307_aif_out_source_enum =
292576c57e6SKiseok Jo SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sma1307_aif_out_source_text),
293576c57e6SKiseok Jo 		    sma1307_aif_out_source_text);
294576c57e6SKiseok Jo static const struct soc_enum sma1307_tdm_slot_enum =
295576c57e6SKiseok Jo SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sma1307_tdm_slot_text),
296576c57e6SKiseok Jo 		    sma1307_tdm_slot_text);
297576c57e6SKiseok Jo static const struct soc_enum sma1307_binary_mode_enum =
298576c57e6SKiseok Jo SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sma1307_binary_mode_text),
299576c57e6SKiseok Jo 		    sma1307_binary_mode_text);
300576c57e6SKiseok Jo static const struct soc_enum sma1307_reset_enum =
301576c57e6SKiseok Jo SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(sma1307_reset_text),
302576c57e6SKiseok Jo 		    sma1307_reset_text);
303576c57e6SKiseok Jo 
304576c57e6SKiseok Jo static int sma1307_force_mute_get(struct snd_kcontrol *kcontrol,
305576c57e6SKiseok Jo 				  struct snd_ctl_elem_value *ucontrol)
306576c57e6SKiseok Jo {
307576c57e6SKiseok Jo 	struct snd_soc_component *component =
308576c57e6SKiseok Jo 	    snd_soc_kcontrol_component(kcontrol);
309576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
310576c57e6SKiseok Jo 
311576c57e6SKiseok Jo 	ucontrol->value.integer.value[0] = (int)sma1307->force_mute_status;
312576c57e6SKiseok Jo 
313576c57e6SKiseok Jo 	return 0;
314576c57e6SKiseok Jo }
315576c57e6SKiseok Jo 
316576c57e6SKiseok Jo static int sma1307_force_mute_put(struct snd_kcontrol *kcontrol,
317576c57e6SKiseok Jo 				  struct snd_ctl_elem_value *ucontrol)
318576c57e6SKiseok Jo {
319576c57e6SKiseok Jo 	struct snd_soc_component *component =
320576c57e6SKiseok Jo 	    snd_soc_kcontrol_component(kcontrol);
321576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
322576c57e6SKiseok Jo 	bool change = false, val = (bool)ucontrol->value.integer.value[0];
323576c57e6SKiseok Jo 
324576c57e6SKiseok Jo 	if (sma1307->force_mute_status == val) {
325576c57e6SKiseok Jo 		change = false;
326576c57e6SKiseok Jo 	} else {
327576c57e6SKiseok Jo 		change = true;
328576c57e6SKiseok Jo 		sma1307->force_mute_status = val;
329576c57e6SKiseok Jo 	}
330576c57e6SKiseok Jo 
331576c57e6SKiseok Jo 	return change;
332576c57e6SKiseok Jo }
333576c57e6SKiseok Jo 
334576c57e6SKiseok Jo static int sma1307_tdm_slot_get(struct snd_kcontrol *kcontrol,
335576c57e6SKiseok Jo 				struct snd_ctl_elem_value *ucontrol)
336576c57e6SKiseok Jo {
337576c57e6SKiseok Jo 	struct snd_soc_component *component =
338576c57e6SKiseok Jo 	    snd_soc_kcontrol_component(kcontrol);
339576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
340576c57e6SKiseok Jo 	int val1, val2;
341576c57e6SKiseok Jo 
342576c57e6SKiseok Jo 	regmap_read(sma1307->regmap, SMA1307_A5_TDM1, &val1);
343576c57e6SKiseok Jo 	regmap_read(sma1307->regmap, SMA1307_A6_TDM2, &val2);
344576c57e6SKiseok Jo 
345576c57e6SKiseok Jo 	if (!strcmp(kcontrol->id.name, SMA1307_TDM_RX0_POS_NAME)) {
346576c57e6SKiseok Jo 		ucontrol->value.integer.value[0]
347576c57e6SKiseok Jo 		    = (val1 & SMA1307_TDM_SLOT0_RX_POS_MASK) >> 3;
348576c57e6SKiseok Jo 		sma1307->tdm_slot0_rx = ucontrol->value.integer.value[0];
349576c57e6SKiseok Jo 	} else if (!strcmp(kcontrol->id.name, SMA1307_TDM_RX1_POS_NAME)) {
350576c57e6SKiseok Jo 		ucontrol->value.integer.value[0]
351576c57e6SKiseok Jo 		    = val1 & SMA1307_TDM_SLOT1_RX_POS_MASK;
352576c57e6SKiseok Jo 		sma1307->tdm_slot1_rx = ucontrol->value.integer.value[0];
353576c57e6SKiseok Jo 	} else if (!strcmp(kcontrol->id.name, SMA1307_TDM_TX0_POS_NAME)) {
354576c57e6SKiseok Jo 		ucontrol->value.integer.value[0]
355576c57e6SKiseok Jo 		    = (val2 & SMA1307_TDM_SLOT0_TX_POS_MASK) >> 3;
356576c57e6SKiseok Jo 		sma1307->tdm_slot0_tx = ucontrol->value.integer.value[0];
357576c57e6SKiseok Jo 	} else if (!strcmp(kcontrol->id.name, SMA1307_TDM_TX1_POS_NAME)) {
358576c57e6SKiseok Jo 		ucontrol->value.integer.value[0]
359576c57e6SKiseok Jo 		    = val2 & SMA1307_TDM_SLOT1_TX_POS_MASK;
360576c57e6SKiseok Jo 		sma1307->tdm_slot1_tx = ucontrol->value.integer.value[0];
361576c57e6SKiseok Jo 	} else {
362576c57e6SKiseok Jo 		return -EINVAL;
363576c57e6SKiseok Jo 	}
364576c57e6SKiseok Jo 
365576c57e6SKiseok Jo 	return 0;
366576c57e6SKiseok Jo }
367576c57e6SKiseok Jo 
368576c57e6SKiseok Jo static int sma1307_tdm_slot_put(struct snd_kcontrol *kcontrol,
369576c57e6SKiseok Jo 				struct snd_ctl_elem_value *ucontrol)
370576c57e6SKiseok Jo {
371576c57e6SKiseok Jo 	struct snd_soc_component *component =
372576c57e6SKiseok Jo 	    snd_soc_kcontrol_component(kcontrol);
373576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
374576c57e6SKiseok Jo 	int val = (int)ucontrol->value.integer.value[0];
375576c57e6SKiseok Jo 	bool change;
376576c57e6SKiseok Jo 
377576c57e6SKiseok Jo 	if (!strcmp(kcontrol->id.name, SMA1307_TDM_RX0_POS_NAME)) {
378576c57e6SKiseok Jo 		if (sma1307->tdm_slot0_rx == val)
379576c57e6SKiseok Jo 			change = false;
380576c57e6SKiseok Jo 		else {
381576c57e6SKiseok Jo 			change = true;
382576c57e6SKiseok Jo 			sma1307->tdm_slot0_rx = val;
383576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap, SMA1307_A5_TDM1,
384576c57e6SKiseok Jo 				SMA1307_TDM_SLOT0_RX_POS_MASK, val << 3);
385576c57e6SKiseok Jo 		}
386576c57e6SKiseok Jo 	} else if (!strcmp(kcontrol->id.name, SMA1307_TDM_RX1_POS_NAME)) {
387576c57e6SKiseok Jo 		if (sma1307->tdm_slot1_rx == val)
388576c57e6SKiseok Jo 			change = false;
389576c57e6SKiseok Jo 		else {
390576c57e6SKiseok Jo 			change = true;
391576c57e6SKiseok Jo 			sma1307->tdm_slot1_rx = val;
392576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap, SMA1307_A5_TDM1,
393576c57e6SKiseok Jo 				SMA1307_TDM_SLOT1_RX_POS_MASK, val);
394576c57e6SKiseok Jo 		}
395576c57e6SKiseok Jo 	} else if (!strcmp(kcontrol->id.name, SMA1307_TDM_TX0_POS_NAME)) {
396576c57e6SKiseok Jo 		if (sma1307->tdm_slot0_tx == val)
397576c57e6SKiseok Jo 			change = false;
398576c57e6SKiseok Jo 		else {
399576c57e6SKiseok Jo 			change = true;
400576c57e6SKiseok Jo 			sma1307->tdm_slot0_tx = val;
401576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap, SMA1307_A6_TDM2,
402576c57e6SKiseok Jo 				SMA1307_TDM_SLOT0_TX_POS_MASK, val << 3);
403576c57e6SKiseok Jo 		}
404576c57e6SKiseok Jo 	} else if (!strcmp(kcontrol->id.name, SMA1307_TDM_TX1_POS_NAME)) {
405576c57e6SKiseok Jo 		if (sma1307->tdm_slot1_tx == val)
406576c57e6SKiseok Jo 			change = false;
407576c57e6SKiseok Jo 		else {
408576c57e6SKiseok Jo 			change = true;
409576c57e6SKiseok Jo 			sma1307->tdm_slot1_tx = val;
410576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap, SMA1307_A6_TDM2,
411576c57e6SKiseok Jo 				SMA1307_TDM_SLOT1_TX_POS_MASK, val);
412576c57e6SKiseok Jo 		}
413576c57e6SKiseok Jo 	} else {
414576c57e6SKiseok Jo 		dev_err(sma1307->dev, "%s: Invalid Control ID - %s\n",
415576c57e6SKiseok Jo 			__func__, kcontrol->id.name);
416576c57e6SKiseok Jo 		return -EINVAL;
417576c57e6SKiseok Jo 	}
418576c57e6SKiseok Jo 
419576c57e6SKiseok Jo 	return change;
420576c57e6SKiseok Jo }
421576c57e6SKiseok Jo 
422576c57e6SKiseok Jo static int sma1307_sw_ot1_prot_get(struct snd_kcontrol *kcontrol,
423576c57e6SKiseok Jo 				   struct snd_ctl_elem_value *ucontrol)
424576c57e6SKiseok Jo {
425576c57e6SKiseok Jo 	struct snd_soc_component *component =
426576c57e6SKiseok Jo 	    snd_soc_kcontrol_component(kcontrol);
427576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
428576c57e6SKiseok Jo 
429576c57e6SKiseok Jo 	ucontrol->value.integer.value[0] = (int)sma1307->sw_ot1_prot;
430576c57e6SKiseok Jo 
431576c57e6SKiseok Jo 	return 0;
432576c57e6SKiseok Jo }
433576c57e6SKiseok Jo 
434576c57e6SKiseok Jo static int sma1307_sw_ot1_prot_put(struct snd_kcontrol *kcontrol,
435576c57e6SKiseok Jo 				   struct snd_ctl_elem_value *ucontrol)
436576c57e6SKiseok Jo {
437576c57e6SKiseok Jo 	struct snd_soc_component *component =
438576c57e6SKiseok Jo 	    snd_soc_kcontrol_component(kcontrol);
439576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
440576c57e6SKiseok Jo 	bool change = false, val = (bool)ucontrol->value.integer.value[0];
441576c57e6SKiseok Jo 
442576c57e6SKiseok Jo 	if (sma1307->sw_ot1_prot == val)
443576c57e6SKiseok Jo 		change = false;
444576c57e6SKiseok Jo 	else {
445576c57e6SKiseok Jo 		change = true;
446576c57e6SKiseok Jo 		sma1307->sw_ot1_prot = val;
447576c57e6SKiseok Jo 	}
448576c57e6SKiseok Jo 
449576c57e6SKiseok Jo 	return change;
450576c57e6SKiseok Jo }
451576c57e6SKiseok Jo 
452576c57e6SKiseok Jo static int sma1307_check_fault_status_get(struct snd_kcontrol *kcontrol,
453576c57e6SKiseok Jo 				   struct snd_ctl_elem_value *ucontrol)
454576c57e6SKiseok Jo {
455576c57e6SKiseok Jo 	struct snd_soc_component *component =
456576c57e6SKiseok Jo 	    snd_soc_kcontrol_component(kcontrol);
457576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
458576c57e6SKiseok Jo 
459576c57e6SKiseok Jo 	ucontrol->value.integer.value[0] = (int)sma1307->check_fault_status;
460576c57e6SKiseok Jo 
461576c57e6SKiseok Jo 	return 0;
462576c57e6SKiseok Jo }
463576c57e6SKiseok Jo 
464576c57e6SKiseok Jo static int sma1307_check_fault_status_put(struct snd_kcontrol *kcontrol,
465576c57e6SKiseok Jo 				   struct snd_ctl_elem_value *ucontrol)
466576c57e6SKiseok Jo {
467576c57e6SKiseok Jo 	struct snd_soc_component *component =
468576c57e6SKiseok Jo 	    snd_soc_kcontrol_component(kcontrol);
469576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
470576c57e6SKiseok Jo 	bool change = false, val = (bool)ucontrol->value.integer.value[0];
471576c57e6SKiseok Jo 
472576c57e6SKiseok Jo 	if (sma1307->check_fault_status == val) {
473576c57e6SKiseok Jo 		change = false;
474576c57e6SKiseok Jo 	} else {
475576c57e6SKiseok Jo 		change = true;
476576c57e6SKiseok Jo 		sma1307->check_fault_status = val;
477576c57e6SKiseok Jo 	}
478576c57e6SKiseok Jo 
479576c57e6SKiseok Jo 	return change;
480576c57e6SKiseok Jo }
481576c57e6SKiseok Jo 
482576c57e6SKiseok Jo static int sma1307_check_fault_period_get(struct snd_kcontrol *kcontrol,
483576c57e6SKiseok Jo 				   struct snd_ctl_elem_value *ucontrol)
484576c57e6SKiseok Jo {
485576c57e6SKiseok Jo 	struct snd_soc_component *component =
486576c57e6SKiseok Jo 	    snd_soc_kcontrol_component(kcontrol);
487576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
488576c57e6SKiseok Jo 
489576c57e6SKiseok Jo 	ucontrol->value.integer.value[0] = sma1307->check_fault_period;
490576c57e6SKiseok Jo 
491576c57e6SKiseok Jo 	return 0;
492576c57e6SKiseok Jo }
493576c57e6SKiseok Jo 
494576c57e6SKiseok Jo static int sma1307_check_fault_period_put(struct snd_kcontrol *kcontrol,
495576c57e6SKiseok Jo 				   struct snd_ctl_elem_value *ucontrol)
496576c57e6SKiseok Jo {
497576c57e6SKiseok Jo 	struct snd_soc_component *component =
498576c57e6SKiseok Jo 	    snd_soc_kcontrol_component(kcontrol);
499576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
500576c57e6SKiseok Jo 	struct soc_mixer_control *mc =
501576c57e6SKiseok Jo 		(struct soc_mixer_control *)kcontrol->private_value;
502576c57e6SKiseok Jo 	bool change = false;
503576c57e6SKiseok Jo 	int val  = ucontrol->value.integer.value[0];
504576c57e6SKiseok Jo 
505576c57e6SKiseok Jo 	if (val < mc->min || val > mc->max)
506576c57e6SKiseok Jo 		return -EINVAL;
507576c57e6SKiseok Jo 	if (sma1307->check_fault_period == val) {
508576c57e6SKiseok Jo 		change = false;
509576c57e6SKiseok Jo 	} else {
510576c57e6SKiseok Jo 		change = true;
511576c57e6SKiseok Jo 		sma1307->check_fault_period = val;
512576c57e6SKiseok Jo 	}
513576c57e6SKiseok Jo 
514576c57e6SKiseok Jo 	return change;
515576c57e6SKiseok Jo }
516576c57e6SKiseok Jo 
517576c57e6SKiseok Jo static int sma1307_reset_put(struct snd_kcontrol *kcontrol,
518576c57e6SKiseok Jo 			     struct snd_ctl_elem_value *ucontrol)
519576c57e6SKiseok Jo {
520576c57e6SKiseok Jo 	struct snd_soc_component *component =
521576c57e6SKiseok Jo 	    snd_soc_kcontrol_component(kcontrol);
522576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
523576c57e6SKiseok Jo 
524576c57e6SKiseok Jo 	regmap_update_bits(sma1307->regmap, SMA1307_00_SYSTEM_CTRL,
525576c57e6SKiseok Jo 				   SMA1307_RESET_MASK, SMA1307_RESET_ON);
526576c57e6SKiseok Jo 	sma1307_reset(component);
527576c57e6SKiseok Jo 
528576c57e6SKiseok Jo 	snd_ctl_notify(component->card->snd_card, SNDRV_CTL_EVENT_MASK_VALUE,
529576c57e6SKiseok Jo 					&kcontrol->id);
530576c57e6SKiseok Jo 
531576c57e6SKiseok Jo 	return true;
532576c57e6SKiseok Jo }
533576c57e6SKiseok Jo 
534576c57e6SKiseok Jo static int sma1307_binary_mode_put(struct snd_kcontrol *kcontrol,
535576c57e6SKiseok Jo 				   struct snd_ctl_elem_value *ucontrol)
536576c57e6SKiseok Jo {
537576c57e6SKiseok Jo 	struct snd_soc_component *component =
538576c57e6SKiseok Jo 	    snd_soc_kcontrol_component(kcontrol);
539576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_kcontrol_chip(kcontrol);
540576c57e6SKiseok Jo 
541576c57e6SKiseok Jo 	sma1307->binary_mode = (int)ucontrol->value.enumerated.item[0];
542576c57e6SKiseok Jo 	if (sma1307->set.status)
543576c57e6SKiseok Jo 		sma1307_set_binary(component);
544576c57e6SKiseok Jo 
545576c57e6SKiseok Jo 	return snd_soc_put_enum_double(kcontrol, ucontrol);
546576c57e6SKiseok Jo }
547576c57e6SKiseok Jo 
548576c57e6SKiseok Jo static void sma1307_startup(struct snd_soc_component *component)
549576c57e6SKiseok Jo {
550576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
551576c57e6SKiseok Jo 
552576c57e6SKiseok Jo 	regmap_update_bits(sma1307->regmap, SMA1307_A2_TOP_MAN1,
553576c57e6SKiseok Jo 				   SMA1307_PLL_MASK, SMA1307_PLL_ON);
554576c57e6SKiseok Jo 	regmap_update_bits(sma1307->regmap, SMA1307_00_SYSTEM_CTRL,
555576c57e6SKiseok Jo 				   SMA1307_POWER_MASK, SMA1307_POWER_ON);
556576c57e6SKiseok Jo 
557576c57e6SKiseok Jo 	if (sma1307->amp_mode == SMA1307_MONO_MODE) {
558576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
559576c57e6SKiseok Jo 					   SMA1307_10_SYSTEM_CTRL1,
560576c57e6SKiseok Jo 					   SMA1307_SPK_MODE_MASK,
561576c57e6SKiseok Jo 					   SMA1307_SPK_MONO);
562576c57e6SKiseok Jo 	} else {
563576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
564576c57e6SKiseok Jo 					   SMA1307_10_SYSTEM_CTRL1,
565576c57e6SKiseok Jo 					   SMA1307_SPK_MODE_MASK,
566576c57e6SKiseok Jo 					   SMA1307_SPK_STEREO);
567576c57e6SKiseok Jo 	}
568576c57e6SKiseok Jo 
569576c57e6SKiseok Jo 	if (sma1307->check_fault_status) {
570576c57e6SKiseok Jo 		if (sma1307->check_fault_period > 0)
571576c57e6SKiseok Jo 			queue_delayed_work(system_freezable_wq,
572576c57e6SKiseok Jo 					   &sma1307->check_fault_work,
573576c57e6SKiseok Jo 					   sma1307->check_fault_period * HZ);
574576c57e6SKiseok Jo 		else
575576c57e6SKiseok Jo 			queue_delayed_work(system_freezable_wq,
576576c57e6SKiseok Jo 					   &sma1307->check_fault_work,
577576c57e6SKiseok Jo 					   CHECK_PERIOD_TIME * HZ);
578576c57e6SKiseok Jo 	}
579576c57e6SKiseok Jo }
580576c57e6SKiseok Jo 
581576c57e6SKiseok Jo static void sma1307_shutdown(struct snd_soc_component *component)
582576c57e6SKiseok Jo {
583576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
584576c57e6SKiseok Jo 
585576c57e6SKiseok Jo 	/* for SMA1307A */
586576c57e6SKiseok Jo 	cancel_delayed_work_sync(&sma1307->check_fault_work);
587576c57e6SKiseok Jo 
588576c57e6SKiseok Jo 	regmap_update_bits(sma1307->regmap, SMA1307_0E_MUTE_VOL_CTRL,
589576c57e6SKiseok Jo 				   SMA1307_SPK_MUTE_MASK, SMA1307_SPK_MUTE);
590576c57e6SKiseok Jo 	/* Need to wait time for mute slope */
591576c57e6SKiseok Jo 	msleep(55);
592576c57e6SKiseok Jo 
593576c57e6SKiseok Jo 	regmap_update_bits(sma1307->regmap, SMA1307_10_SYSTEM_CTRL1,
594576c57e6SKiseok Jo 				   SMA1307_SPK_MODE_MASK, SMA1307_SPK_OFF);
595576c57e6SKiseok Jo 	regmap_update_bits(sma1307->regmap, SMA1307_A2_TOP_MAN1,
596576c57e6SKiseok Jo 				   SMA1307_PLL_MASK, SMA1307_PLL_OFF);
597576c57e6SKiseok Jo 	regmap_update_bits(sma1307->regmap, SMA1307_00_SYSTEM_CTRL,
598576c57e6SKiseok Jo 				   SMA1307_POWER_MASK, SMA1307_POWER_OFF);
599576c57e6SKiseok Jo }
600576c57e6SKiseok Jo 
601576c57e6SKiseok Jo static int sma1307_aif_in_event(struct snd_soc_dapm_widget *w,
602576c57e6SKiseok Jo 				struct snd_kcontrol *kcontrol, int event)
603576c57e6SKiseok Jo {
604576c57e6SKiseok Jo 	struct snd_soc_component *component =
605576c57e6SKiseok Jo 	    snd_soc_dapm_to_component(w->dapm);
606576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
607576c57e6SKiseok Jo 	unsigned int mux = sma1307->dapm_aif_in;
608576c57e6SKiseok Jo 
609576c57e6SKiseok Jo 	switch (event) {
610576c57e6SKiseok Jo 	case SND_SOC_DAPM_PRE_PMU:
611576c57e6SKiseok Jo 		switch (mux) {
612576c57e6SKiseok Jo 		case SMA1307_MONO_MODE:
613576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
614576c57e6SKiseok Jo 						   SMA1307_11_SYSTEM_CTRL2,
615576c57e6SKiseok Jo 						   SMA1307_MONOMIX_MASK,
616576c57e6SKiseok Jo 						   SMA1307_MONOMIX_ON);
617576c57e6SKiseok Jo 			break;
618576c57e6SKiseok Jo 		case SMA1307_LEFT_MODE:
619576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
620576c57e6SKiseok Jo 						   SMA1307_11_SYSTEM_CTRL2,
621576c57e6SKiseok Jo 						   SMA1307_MONOMIX_MASK,
622576c57e6SKiseok Jo 						   SMA1307_MONOMIX_OFF);
623576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
624576c57e6SKiseok Jo 						   SMA1307_11_SYSTEM_CTRL2,
625576c57e6SKiseok Jo 						   SMA1307_LR_DATA_SW_MASK,
626576c57e6SKiseok Jo 						   SMA1307_LR_DATA_SW_NORMAL);
627576c57e6SKiseok Jo 			break;
628576c57e6SKiseok Jo 		case SMA1307_RIGHT_MODE:
629576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
630576c57e6SKiseok Jo 						   SMA1307_11_SYSTEM_CTRL2,
631576c57e6SKiseok Jo 						   SMA1307_MONOMIX_MASK,
632576c57e6SKiseok Jo 						   SMA1307_MONOMIX_OFF);
633576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
634576c57e6SKiseok Jo 						   SMA1307_11_SYSTEM_CTRL2,
635576c57e6SKiseok Jo 						   SMA1307_LR_DATA_SW_MASK,
636576c57e6SKiseok Jo 						   SMA1307_LR_DATA_SW_SWAP);
637576c57e6SKiseok Jo 			break;
638576c57e6SKiseok Jo 		default:
639576c57e6SKiseok Jo 
640576c57e6SKiseok Jo 			dev_err(sma1307->dev, "%s: Invalid value (%d)\n",
641576c57e6SKiseok Jo 				__func__, mux);
642576c57e6SKiseok Jo 			return -EINVAL;
643576c57e6SKiseok Jo 		}
644576c57e6SKiseok Jo 		sma1307->amp_mode = mux;
645576c57e6SKiseok Jo 		break;
646576c57e6SKiseok Jo 	}
647576c57e6SKiseok Jo 	return 0;
648576c57e6SKiseok Jo }
649576c57e6SKiseok Jo 
650576c57e6SKiseok Jo static int sma1307_sdo_setting_event(struct snd_soc_dapm_widget *w,
651576c57e6SKiseok Jo 				     struct snd_kcontrol *kcontrol, int event)
652576c57e6SKiseok Jo {
653576c57e6SKiseok Jo 	struct snd_soc_component *component =
654576c57e6SKiseok Jo 	    snd_soc_dapm_to_component(w->dapm);
655576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
656576c57e6SKiseok Jo 	unsigned int mux = sma1307->dapm_sdo_setting;
657576c57e6SKiseok Jo 
658576c57e6SKiseok Jo 	switch (event) {
659576c57e6SKiseok Jo 	case SND_SOC_DAPM_PRE_PMU:
660576c57e6SKiseok Jo 		switch (mux) {
661576c57e6SKiseok Jo 		case SMA1307_OUT_DATA_ONE_48K:
662576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
663576c57e6SKiseok Jo 						   SMA1307_A2_TOP_MAN1,
664576c57e6SKiseok Jo 						   SMA1307_SDO_OUTPUT2_MASK,
665576c57e6SKiseok Jo 						   SMA1307_ONE_SDO_PER_CH);
666576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
667576c57e6SKiseok Jo 						   SMA1307_A3_TOP_MAN2,
668576c57e6SKiseok Jo 						   SMA1307_SDO_OUTPUT3_MASK
669576c57e6SKiseok Jo 						   |
670576c57e6SKiseok Jo 						   SMA1307_DATA_CLK_SEL_MASK,
671576c57e6SKiseok Jo 						   SMA1307_SDO_OUTPUT3_DIS
672576c57e6SKiseok Jo 						   | SMA1307_SDO_DATA);
673576c57e6SKiseok Jo 			break;
674576c57e6SKiseok Jo 		case SMA1307_OUT_DATA_TWO_48K:
675576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
676576c57e6SKiseok Jo 						   SMA1307_A2_TOP_MAN1,
677576c57e6SKiseok Jo 						   SMA1307_SDO_OUTPUT2_MASK,
678576c57e6SKiseok Jo 						   SMA1307_TWO_SDO_PER_CH);
679576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
680576c57e6SKiseok Jo 						   SMA1307_A3_TOP_MAN2,
681576c57e6SKiseok Jo 						   SMA1307_SDO_OUTPUT3_MASK
682576c57e6SKiseok Jo 						   |
683576c57e6SKiseok Jo 						   SMA1307_DATA_CLK_SEL_MASK,
684576c57e6SKiseok Jo 						   SMA1307_SDO_OUTPUT3_DIS
685576c57e6SKiseok Jo 						   | SMA1307_SDO_DATA);
686576c57e6SKiseok Jo 			break;
687576c57e6SKiseok Jo 		case SMA1307_OUT_DATA_TWO_24K:
688576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
689576c57e6SKiseok Jo 						   SMA1307_A2_TOP_MAN1,
690576c57e6SKiseok Jo 						   SMA1307_SDO_OUTPUT2_MASK,
691576c57e6SKiseok Jo 						   SMA1307_TWO_SDO_PER_CH);
692576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
693576c57e6SKiseok Jo 						   SMA1307_A3_TOP_MAN2,
694576c57e6SKiseok Jo 						   SMA1307_SDO_OUTPUT3_MASK
695576c57e6SKiseok Jo 						   |
696576c57e6SKiseok Jo 						   SMA1307_DATA_CLK_SEL_MASK,
697576c57e6SKiseok Jo 						   SMA1307_TWO_SDO_PER_CH_24K
698576c57e6SKiseok Jo 						   | SMA1307_SDO_DATA);
699576c57e6SKiseok Jo 			break;
700576c57e6SKiseok Jo 		case SMA1307_OUT_CLK_PLL:
701576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
702576c57e6SKiseok Jo 						   SMA1307_A3_TOP_MAN2,
703576c57e6SKiseok Jo 						   SMA1307_DATA_CLK_SEL_MASK,
704576c57e6SKiseok Jo 						   SMA1307_SDO_CLK_PLL);
705576c57e6SKiseok Jo 
706576c57e6SKiseok Jo 			break;
707576c57e6SKiseok Jo 		case SMA1307_OUT_CLK_OSC:
708576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
709576c57e6SKiseok Jo 						   SMA1307_A3_TOP_MAN2,
710576c57e6SKiseok Jo 						   SMA1307_DATA_CLK_SEL_MASK,
711576c57e6SKiseok Jo 						   SMA1307_SDO_CLK_OSC);
712576c57e6SKiseok Jo 
713576c57e6SKiseok Jo 			break;
714576c57e6SKiseok Jo 		default:
715576c57e6SKiseok Jo 			dev_err(sma1307->dev, "%s: Invalid value (%d)\n",
716576c57e6SKiseok Jo 				__func__, mux);
717576c57e6SKiseok Jo 			return -EINVAL;
718576c57e6SKiseok Jo 		}
719576c57e6SKiseok Jo 		break;
720576c57e6SKiseok Jo 	}
721576c57e6SKiseok Jo 	return 0;
722576c57e6SKiseok Jo }
723576c57e6SKiseok Jo 
724576c57e6SKiseok Jo static int sma1307_aif_out_event(struct snd_soc_dapm_widget *w,
725576c57e6SKiseok Jo 				 struct snd_kcontrol *kcontrol, int event)
726576c57e6SKiseok Jo {
727576c57e6SKiseok Jo 	struct snd_soc_component *component =
728576c57e6SKiseok Jo 	    snd_soc_dapm_to_component(w->dapm);
729576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
730576c57e6SKiseok Jo 	unsigned int mux = 0, val = 0, mask = 0;
731576c57e6SKiseok Jo 
732576c57e6SKiseok Jo 	if (!strcmp(w->name, SMA1307_AIF_OUT0_NAME)) {
733576c57e6SKiseok Jo 		mux = sma1307->dapm_aif_out0;
734576c57e6SKiseok Jo 		val = mux;
735576c57e6SKiseok Jo 		mask = SMA1307_SDO_OUT0_SEL_MASK;
736576c57e6SKiseok Jo 	} else if (!strcmp(w->name, SMA1307_AIF_OUT1_NAME)) {
737576c57e6SKiseok Jo 		mux = sma1307->dapm_aif_out1;
738576c57e6SKiseok Jo 		val = mux << 3;
739576c57e6SKiseok Jo 		mask = SMA1307_SDO_OUT1_SEL_MASK;
740576c57e6SKiseok Jo 	} else {
741576c57e6SKiseok Jo 		dev_err(sma1307->dev, "%s: Invalid widget - %s\n",
742576c57e6SKiseok Jo 			__func__, w->name);
743576c57e6SKiseok Jo 		return -EINVAL;
744576c57e6SKiseok Jo 	}
745576c57e6SKiseok Jo 	switch (event) {
746576c57e6SKiseok Jo 	case SND_SOC_DAPM_PRE_PMU:
747576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap, SMA1307_09_OUTPUT_CTRL,
748576c57e6SKiseok Jo 					   mask, val);
749576c57e6SKiseok Jo 		break;
750576c57e6SKiseok Jo 	}
751576c57e6SKiseok Jo 	return 0;
752576c57e6SKiseok Jo }
753576c57e6SKiseok Jo 
754576c57e6SKiseok Jo static int sma1307_sdo_event(struct snd_soc_dapm_widget *w,
755576c57e6SKiseok Jo 			     struct snd_kcontrol *kcontrol, int event)
756576c57e6SKiseok Jo {
757576c57e6SKiseok Jo 	struct snd_soc_component *component =
758576c57e6SKiseok Jo 	    snd_soc_dapm_to_component(w->dapm);
759576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
760576c57e6SKiseok Jo 
761576c57e6SKiseok Jo 	switch (event) {
762576c57e6SKiseok Jo 	case SND_SOC_DAPM_PRE_PMU:
763576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
764576c57e6SKiseok Jo 					   SMA1307_09_OUTPUT_CTRL,
765576c57e6SKiseok Jo 					   SMA1307_PORT_CONFIG_MASK,
766576c57e6SKiseok Jo 					   SMA1307_OUTPUT_PORT_ENABLE);
767576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
768576c57e6SKiseok Jo 					   SMA1307_A3_TOP_MAN2,
769576c57e6SKiseok Jo 					   SMA1307_SDO_OUTPUT_MASK,
770576c57e6SKiseok Jo 					   SMA1307_LOGIC_OUTPUT);
771576c57e6SKiseok Jo 		break;
772576c57e6SKiseok Jo 	case SND_SOC_DAPM_POST_PMD:
773576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
774576c57e6SKiseok Jo 					   SMA1307_09_OUTPUT_CTRL,
775576c57e6SKiseok Jo 					   SMA1307_PORT_CONFIG_MASK,
776576c57e6SKiseok Jo 					   SMA1307_INPUT_PORT_ONLY);
777576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
778576c57e6SKiseok Jo 					   SMA1307_A3_TOP_MAN2,
779576c57e6SKiseok Jo 					   SMA1307_SDO_OUTPUT_MASK,
780576c57e6SKiseok Jo 					   SMA1307_HIGH_Z_OUTPUT);
781576c57e6SKiseok Jo 		break;
782576c57e6SKiseok Jo 	}
783576c57e6SKiseok Jo 	return 0;
784576c57e6SKiseok Jo }
785576c57e6SKiseok Jo 
786576c57e6SKiseok Jo static int sma1307_power_event(struct snd_soc_dapm_widget *w,
787576c57e6SKiseok Jo 			       struct snd_kcontrol *kcontrol, int event)
788576c57e6SKiseok Jo {
789576c57e6SKiseok Jo 	struct snd_soc_component *component =
790576c57e6SKiseok Jo 	    snd_soc_dapm_to_component(w->dapm);
791576c57e6SKiseok Jo 
792576c57e6SKiseok Jo 	switch (event) {
793576c57e6SKiseok Jo 	case SND_SOC_DAPM_POST_PMU:
794576c57e6SKiseok Jo 		sma1307_startup(component);
795576c57e6SKiseok Jo 		break;
796576c57e6SKiseok Jo 	case SND_SOC_DAPM_PRE_PMD:
797576c57e6SKiseok Jo 		sma1307_shutdown(component);
798576c57e6SKiseok Jo 		break;
799576c57e6SKiseok Jo 	}
800576c57e6SKiseok Jo 	return 0;
801576c57e6SKiseok Jo }
802576c57e6SKiseok Jo 
803576c57e6SKiseok Jo static int sma1307_dapm_aif_in_get(struct snd_kcontrol *kcontrol,
804576c57e6SKiseok Jo 				   struct snd_ctl_elem_value *ucontrol)
805576c57e6SKiseok Jo {
806576c57e6SKiseok Jo 	struct snd_soc_dapm_context *dapm =
807576c57e6SKiseok Jo 	    snd_soc_dapm_kcontrol_dapm(kcontrol);
808576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 =
809576c57e6SKiseok Jo 	    snd_soc_component_get_drvdata(dapm->component);
810576c57e6SKiseok Jo 
811576c57e6SKiseok Jo 	ucontrol->value.enumerated.item[0] = (unsigned int)sma1307->dapm_aif_in;
812576c57e6SKiseok Jo 	snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
813576c57e6SKiseok Jo 
814576c57e6SKiseok Jo 	return 0;
815576c57e6SKiseok Jo }
816576c57e6SKiseok Jo 
817576c57e6SKiseok Jo static int sma1307_dapm_aif_in_put(struct snd_kcontrol *kcontrol,
818576c57e6SKiseok Jo 				   struct snd_ctl_elem_value *ucontrol)
819576c57e6SKiseok Jo {
820576c57e6SKiseok Jo 	struct snd_soc_dapm_context *dapm =
821576c57e6SKiseok Jo 	    snd_soc_dapm_kcontrol_dapm(kcontrol);
822576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 =
823576c57e6SKiseok Jo 	    snd_soc_component_get_drvdata(dapm->component);
824576c57e6SKiseok Jo 	int val = (int)ucontrol->value.enumerated.item[0];
825576c57e6SKiseok Jo 	bool change;
826576c57e6SKiseok Jo 
827576c57e6SKiseok Jo 	if ((val < 0) || (val >= ARRAY_SIZE(sma1307_aif_in_source_text))) {
828576c57e6SKiseok Jo 		dev_err(sma1307->dev, "%s: Out of range\n", __func__);
829576c57e6SKiseok Jo 		return -EINVAL;
830576c57e6SKiseok Jo 	}
831576c57e6SKiseok Jo 
832576c57e6SKiseok Jo 	if (sma1307->dapm_aif_in != val) {
833576c57e6SKiseok Jo 		change = true;
834576c57e6SKiseok Jo 		sma1307->dapm_aif_in = val;
835576c57e6SKiseok Jo 	} else
836576c57e6SKiseok Jo 		change = false;
837576c57e6SKiseok Jo 
838576c57e6SKiseok Jo 	snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
839576c57e6SKiseok Jo 
840576c57e6SKiseok Jo 	return change;
841576c57e6SKiseok Jo }
842576c57e6SKiseok Jo 
843576c57e6SKiseok Jo static int sma1307_dapm_sdo_setting_get(struct snd_kcontrol *kcontrol,
844576c57e6SKiseok Jo 					struct snd_ctl_elem_value *ucontrol)
845576c57e6SKiseok Jo {
846576c57e6SKiseok Jo 	struct snd_soc_dapm_context *dapm =
847576c57e6SKiseok Jo 	    snd_soc_dapm_kcontrol_dapm(kcontrol);
848576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 =
849576c57e6SKiseok Jo 	    snd_soc_component_get_drvdata(dapm->component);
850576c57e6SKiseok Jo 
851576c57e6SKiseok Jo 	ucontrol->value.enumerated.item[0] =
852576c57e6SKiseok Jo 	    (unsigned int)sma1307->dapm_sdo_setting;
853576c57e6SKiseok Jo 	snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
854576c57e6SKiseok Jo 
855576c57e6SKiseok Jo 	return 0;
856576c57e6SKiseok Jo }
857576c57e6SKiseok Jo 
858576c57e6SKiseok Jo static int sma1307_dapm_sdo_setting_put(struct snd_kcontrol *kcontrol,
859576c57e6SKiseok Jo 					struct snd_ctl_elem_value *ucontrol)
860576c57e6SKiseok Jo {
861576c57e6SKiseok Jo 	struct snd_soc_dapm_context *dapm =
862576c57e6SKiseok Jo 	    snd_soc_dapm_kcontrol_dapm(kcontrol);
863576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 =
864576c57e6SKiseok Jo 	    snd_soc_component_get_drvdata(dapm->component);
865576c57e6SKiseok Jo 	int val = (int)ucontrol->value.enumerated.item[0];
866576c57e6SKiseok Jo 	bool change;
867576c57e6SKiseok Jo 
868576c57e6SKiseok Jo 	if ((val < 0) || (val >= ARRAY_SIZE(sma1307_sdo_setting_text))) {
869576c57e6SKiseok Jo 		dev_err(sma1307->dev, "%s: Out of range\n", __func__);
870576c57e6SKiseok Jo 		return -EINVAL;
871576c57e6SKiseok Jo 	}
872576c57e6SKiseok Jo 
873576c57e6SKiseok Jo 	if (sma1307->dapm_sdo_setting != val) {
874576c57e6SKiseok Jo 		change = true;
875576c57e6SKiseok Jo 		sma1307->dapm_sdo_setting = val;
876576c57e6SKiseok Jo 	} else
877576c57e6SKiseok Jo 		change = false;
878576c57e6SKiseok Jo 
879576c57e6SKiseok Jo 	snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
880576c57e6SKiseok Jo 
881576c57e6SKiseok Jo 	return change;
882576c57e6SKiseok Jo }
883576c57e6SKiseok Jo 
884576c57e6SKiseok Jo static int sma1307_dapm_aif_out_get(struct snd_kcontrol *kcontrol,
885576c57e6SKiseok Jo 				    struct snd_ctl_elem_value *ucontrol)
886576c57e6SKiseok Jo {
887576c57e6SKiseok Jo 	struct snd_soc_dapm_context *dapm =
888576c57e6SKiseok Jo 	    snd_soc_dapm_kcontrol_dapm(kcontrol);
889576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 =
890576c57e6SKiseok Jo 	    snd_soc_component_get_drvdata(dapm->component);
891576c57e6SKiseok Jo 	unsigned int val = 0;
892576c57e6SKiseok Jo 
893576c57e6SKiseok Jo 	if (!strcmp(kcontrol->id.name, SMA1307_AIF_OUT0_NAME)) {
894576c57e6SKiseok Jo 		val = (unsigned int)sma1307->dapm_aif_out0;
895576c57e6SKiseok Jo 	} else if (!strcmp(kcontrol->id.name, SMA1307_AIF_OUT1_NAME)) {
896576c57e6SKiseok Jo 		val = (unsigned int)sma1307->dapm_aif_out1;
897576c57e6SKiseok Jo 	} else {
898576c57e6SKiseok Jo 		dev_err(sma1307->dev, "%s: Invalid Control ID - %s\n",
899576c57e6SKiseok Jo 			__func__, kcontrol->id.name);
900576c57e6SKiseok Jo 		return -EINVAL;
901576c57e6SKiseok Jo 	}
902576c57e6SKiseok Jo 	ucontrol->value.enumerated.item[0] = val;
903576c57e6SKiseok Jo 	snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
904576c57e6SKiseok Jo 
905576c57e6SKiseok Jo 	return 0;
906576c57e6SKiseok Jo }
907576c57e6SKiseok Jo 
908576c57e6SKiseok Jo static int sma1307_dapm_aif_out_put(struct snd_kcontrol *kcontrol,
909576c57e6SKiseok Jo 				    struct snd_ctl_elem_value *ucontrol)
910576c57e6SKiseok Jo {
911576c57e6SKiseok Jo 	struct snd_soc_dapm_context *dapm =
912576c57e6SKiseok Jo 	    snd_soc_dapm_kcontrol_dapm(kcontrol);
913576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 =
914576c57e6SKiseok Jo 	    snd_soc_component_get_drvdata(dapm->component);
915576c57e6SKiseok Jo 	int val = (int)ucontrol->value.enumerated.item[0];
916576c57e6SKiseok Jo 	bool change;
917576c57e6SKiseok Jo 
918576c57e6SKiseok Jo 	if ((val < 0) || (val >= ARRAY_SIZE(sma1307_aif_out_source_text))) {
919576c57e6SKiseok Jo 		dev_err(sma1307->dev, "%s: Out of range\n", __func__);
920576c57e6SKiseok Jo 		return -EINVAL;
921576c57e6SKiseok Jo 	}
922576c57e6SKiseok Jo 
923576c57e6SKiseok Jo 	if (!strcmp(kcontrol->id.name, SMA1307_AIF_OUT0_NAME)) {
924576c57e6SKiseok Jo 		if (sma1307->dapm_aif_out0 != val) {
925576c57e6SKiseok Jo 			change = true;
926576c57e6SKiseok Jo 			sma1307->dapm_aif_out0 = val;
927576c57e6SKiseok Jo 		} else
928576c57e6SKiseok Jo 			change = false;
929576c57e6SKiseok Jo 	} else if (!strcmp(kcontrol->id.name, SMA1307_AIF_OUT1_NAME)) {
930576c57e6SKiseok Jo 		if (sma1307->dapm_aif_out1 != val) {
931576c57e6SKiseok Jo 			change = true;
932576c57e6SKiseok Jo 			sma1307->dapm_aif_out1 = val;
933576c57e6SKiseok Jo 		} else
934576c57e6SKiseok Jo 			change = false;
935576c57e6SKiseok Jo 	} else {
936576c57e6SKiseok Jo 		dev_err(sma1307->dev, "%s: Invalid Control ID - %s\n",
937576c57e6SKiseok Jo 			__func__, kcontrol->id.name);
938576c57e6SKiseok Jo 		return -EINVAL;
939576c57e6SKiseok Jo 	}
940576c57e6SKiseok Jo 
941576c57e6SKiseok Jo 	snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
942576c57e6SKiseok Jo 
943576c57e6SKiseok Jo 	return change;
944576c57e6SKiseok Jo }
945576c57e6SKiseok Jo 
946576c57e6SKiseok Jo static int sma1307_dapm_sdo_enable_get(struct snd_kcontrol *kcontrol,
947576c57e6SKiseok Jo 				       struct snd_ctl_elem_value *ucontrol)
948576c57e6SKiseok Jo {
949576c57e6SKiseok Jo 	struct snd_soc_dapm_context *dapm =
950576c57e6SKiseok Jo 	    snd_soc_dapm_kcontrol_dapm(kcontrol);
951576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 =
952576c57e6SKiseok Jo 	    snd_soc_component_get_drvdata(dapm->component);
953576c57e6SKiseok Jo 
954576c57e6SKiseok Jo 	ucontrol->value.integer.value[0] = (long)sma1307->dapm_sdo_en;
955576c57e6SKiseok Jo 	snd_soc_dapm_put_volsw(kcontrol, ucontrol);
956576c57e6SKiseok Jo 
957576c57e6SKiseok Jo 	return 0;
958576c57e6SKiseok Jo }
959576c57e6SKiseok Jo 
960576c57e6SKiseok Jo static int sma1307_dapm_sdo_enable_put(struct snd_kcontrol *kcontrol,
961576c57e6SKiseok Jo 				       struct snd_ctl_elem_value *ucontrol)
962576c57e6SKiseok Jo {
963576c57e6SKiseok Jo 	struct snd_soc_dapm_context *dapm =
964576c57e6SKiseok Jo 	    snd_soc_dapm_kcontrol_dapm(kcontrol);
965576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 =
966576c57e6SKiseok Jo 	    snd_soc_component_get_drvdata(dapm->component);
967576c57e6SKiseok Jo 	int val = (int)ucontrol->value.integer.value[0];
968576c57e6SKiseok Jo 	bool change;
969576c57e6SKiseok Jo 
970576c57e6SKiseok Jo 	if ((val < 0) || (val > 1)) {
971576c57e6SKiseok Jo 		dev_err(sma1307->dev, "%s: Out of range\n", __func__);
972576c57e6SKiseok Jo 		return -EINVAL;
973576c57e6SKiseok Jo 	}
974576c57e6SKiseok Jo 
975576c57e6SKiseok Jo 	if (sma1307->dapm_sdo_en != val) {
976576c57e6SKiseok Jo 		change = true;
977576c57e6SKiseok Jo 		sma1307->dapm_sdo_en = val;
978576c57e6SKiseok Jo 	} else
979576c57e6SKiseok Jo 		change = false;
980576c57e6SKiseok Jo 
981576c57e6SKiseok Jo 	snd_soc_dapm_put_volsw(kcontrol, ucontrol);
982576c57e6SKiseok Jo 
983576c57e6SKiseok Jo 	return change;
984576c57e6SKiseok Jo }
985576c57e6SKiseok Jo 
986576c57e6SKiseok Jo static const struct snd_kcontrol_new sma1307_aif_in_source_control = {
987576c57e6SKiseok Jo 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
988576c57e6SKiseok Jo 	.name = SMA1307_AIF_IN_NAME,
989576c57e6SKiseok Jo 	.info = snd_soc_info_enum_double,
990576c57e6SKiseok Jo 	.get = sma1307_dapm_aif_in_get,
991576c57e6SKiseok Jo 	.put = sma1307_dapm_aif_in_put,
992576c57e6SKiseok Jo 	.private_value = (unsigned long)&sma1307_aif_in_source_enum
993576c57e6SKiseok Jo };
994576c57e6SKiseok Jo 
995576c57e6SKiseok Jo static const struct snd_kcontrol_new sma1307_sdo_setting_control = {
996576c57e6SKiseok Jo 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
997576c57e6SKiseok Jo 	.name = "SDO Setting",
998576c57e6SKiseok Jo 	.info = snd_soc_info_enum_double,
999576c57e6SKiseok Jo 	.get = sma1307_dapm_sdo_setting_get,
1000576c57e6SKiseok Jo 	.put = sma1307_dapm_sdo_setting_put,
1001576c57e6SKiseok Jo 	.private_value = (unsigned long)&sma1307_sdo_setting_enum
1002576c57e6SKiseok Jo };
1003576c57e6SKiseok Jo 
1004576c57e6SKiseok Jo static const struct snd_kcontrol_new sma1307_aif_out0_source_control = {
1005576c57e6SKiseok Jo 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1006576c57e6SKiseok Jo 	.name = SMA1307_AIF_OUT0_NAME,
1007576c57e6SKiseok Jo 	.info = snd_soc_info_enum_double,
1008576c57e6SKiseok Jo 	.get = sma1307_dapm_aif_out_get,
1009576c57e6SKiseok Jo 	.put = sma1307_dapm_aif_out_put,
1010576c57e6SKiseok Jo 	.private_value = (unsigned long)&sma1307_aif_out_source_enum
1011576c57e6SKiseok Jo };
1012576c57e6SKiseok Jo 
1013576c57e6SKiseok Jo static const struct snd_kcontrol_new sma1307_aif_out1_source_control = {
1014576c57e6SKiseok Jo 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1015576c57e6SKiseok Jo 	.name = SMA1307_AIF_OUT1_NAME,
1016576c57e6SKiseok Jo 	.info = snd_soc_info_enum_double,
1017576c57e6SKiseok Jo 	.get = sma1307_dapm_aif_out_get,
1018576c57e6SKiseok Jo 	.put = sma1307_dapm_aif_out_put,
1019576c57e6SKiseok Jo 	.private_value = (unsigned long)&sma1307_aif_out_source_enum
1020576c57e6SKiseok Jo };
1021576c57e6SKiseok Jo 
1022576c57e6SKiseok Jo static const struct snd_kcontrol_new sma1307_sdo_control = {
1023576c57e6SKiseok Jo 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1024576c57e6SKiseok Jo 	.name = "Switch",
1025576c57e6SKiseok Jo 	.info = snd_soc_info_volsw,
1026576c57e6SKiseok Jo 	.get = sma1307_dapm_sdo_enable_get,
1027576c57e6SKiseok Jo 	.put = sma1307_dapm_sdo_enable_put,
1028576c57e6SKiseok Jo 	.private_value = SOC_SINGLE_VALUE(SND_SOC_NOPM, 0, 1, 0, 0)
1029576c57e6SKiseok Jo };
1030576c57e6SKiseok Jo 
1031576c57e6SKiseok Jo static const struct snd_kcontrol_new sma1307_enable_control =
1032576c57e6SKiseok Jo 	SOC_DAPM_SINGLE("Switch", SMA1307_00_SYSTEM_CTRL, 0, 1, 0);
1033576c57e6SKiseok Jo 
1034576c57e6SKiseok Jo static const struct snd_kcontrol_new sma1307_binary_mode_control[] = {
1035576c57e6SKiseok Jo 	SOC_ENUM_EXT("Binary Mode", sma1307_binary_mode_enum,
1036576c57e6SKiseok Jo 			snd_soc_get_enum_double, sma1307_binary_mode_put),
1037576c57e6SKiseok Jo };
1038576c57e6SKiseok Jo 
1039576c57e6SKiseok Jo static const struct snd_kcontrol_new sma1307_snd_controls[] = {
1040576c57e6SKiseok Jo 	SOC_SINGLE_TLV(SMA1307_VOL_CTRL_NAME, SMA1307_0A_SPK_VOL,
1041576c57e6SKiseok Jo 		       0, 167, 1, sma1307_spk_tlv),
1042576c57e6SKiseok Jo 	SOC_ENUM_EXT(SMA1307_TDM_RX0_POS_NAME, sma1307_tdm_slot_enum,
1043576c57e6SKiseok Jo 		     sma1307_tdm_slot_get, sma1307_tdm_slot_put),
1044576c57e6SKiseok Jo 	SOC_ENUM_EXT(SMA1307_TDM_RX1_POS_NAME, sma1307_tdm_slot_enum,
1045576c57e6SKiseok Jo 		     sma1307_tdm_slot_get, sma1307_tdm_slot_put),
1046576c57e6SKiseok Jo 	SOC_ENUM_EXT(SMA1307_TDM_TX0_POS_NAME, sma1307_tdm_slot_enum,
1047576c57e6SKiseok Jo 		     sma1307_tdm_slot_get, sma1307_tdm_slot_put),
1048576c57e6SKiseok Jo 	SOC_ENUM_EXT(SMA1307_TDM_TX1_POS_NAME, sma1307_tdm_slot_enum,
1049576c57e6SKiseok Jo 		     sma1307_tdm_slot_get, sma1307_tdm_slot_put),
1050576c57e6SKiseok Jo 	SOC_ENUM_EXT(SMA1307_RESET_CTRL_NAME, sma1307_reset_enum,
1051576c57e6SKiseok Jo 			    snd_soc_get_enum_double, sma1307_reset_put),
1052576c57e6SKiseok Jo 	SOC_SINGLE_BOOL_EXT(SMA1307_FORCE_MUTE_CTRL_NAME, 0,
1053576c57e6SKiseok Jo 			    sma1307_force_mute_get, sma1307_force_mute_put),
1054576c57e6SKiseok Jo 	SOC_SINGLE_BOOL_EXT(SMA1307_OT1_SW_PROT_CTRL_NAME, 0,
1055576c57e6SKiseok Jo 			    sma1307_sw_ot1_prot_get, sma1307_sw_ot1_prot_put),
1056576c57e6SKiseok Jo 	SOC_SINGLE_BOOL_EXT(SMA1307_CHECK_FAULT_STATUS_NAME, 0,
1057576c57e6SKiseok Jo 			sma1307_check_fault_status_get,
1058576c57e6SKiseok Jo 			sma1307_check_fault_status_put),
1059576c57e6SKiseok Jo 	SOC_SINGLE_EXT(SMA1307_CHECK_FAULT_PERIOD_NAME, SND_SOC_NOPM, 0, 600, 0,
1060576c57e6SKiseok Jo 			sma1307_check_fault_period_get,
1061576c57e6SKiseok Jo 			sma1307_check_fault_period_put),
1062576c57e6SKiseok Jo };
1063576c57e6SKiseok Jo 
1064576c57e6SKiseok Jo static const struct snd_soc_dapm_widget sma1307_dapm_widgets[] = {
1065576c57e6SKiseok Jo 	/* platform domain */
1066576c57e6SKiseok Jo 	SND_SOC_DAPM_OUTPUT("SPK"),
1067576c57e6SKiseok Jo 	SND_SOC_DAPM_INPUT("SDO"),
1068576c57e6SKiseok Jo 
1069576c57e6SKiseok Jo 	/* path domain */
1070576c57e6SKiseok Jo 	SND_SOC_DAPM_MUX_E(SMA1307_AIF_IN_NAME, SND_SOC_NOPM, 0, 0,
1071576c57e6SKiseok Jo 			   &sma1307_aif_in_source_control,
1072576c57e6SKiseok Jo 			   sma1307_aif_in_event,
1073576c57e6SKiseok Jo 			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
1074576c57e6SKiseok Jo 	SND_SOC_DAPM_MUX_E("SDO Setting", SND_SOC_NOPM, 0, 0,
1075576c57e6SKiseok Jo 			   &sma1307_sdo_setting_control,
1076576c57e6SKiseok Jo 			   sma1307_sdo_setting_event,
1077576c57e6SKiseok Jo 			   SND_SOC_DAPM_PRE_PMU),
1078576c57e6SKiseok Jo 	SND_SOC_DAPM_MUX_E(SMA1307_AIF_OUT0_NAME, SND_SOC_NOPM, 0, 0,
1079576c57e6SKiseok Jo 			   &sma1307_aif_out0_source_control,
1080576c57e6SKiseok Jo 			   sma1307_aif_out_event,
1081576c57e6SKiseok Jo 			   SND_SOC_DAPM_PRE_PMU),
1082576c57e6SKiseok Jo 	SND_SOC_DAPM_MUX_E(SMA1307_AIF_OUT1_NAME, SND_SOC_NOPM, 0, 0,
1083576c57e6SKiseok Jo 			   &sma1307_aif_out1_source_control,
1084576c57e6SKiseok Jo 			   sma1307_aif_out_event,
1085576c57e6SKiseok Jo 			   SND_SOC_DAPM_PRE_PMU),
1086576c57e6SKiseok Jo 	SND_SOC_DAPM_SWITCH_E("SDO Enable", SND_SOC_NOPM, 0, 0,
1087576c57e6SKiseok Jo 			      &sma1307_sdo_control,
1088576c57e6SKiseok Jo 			      sma1307_sdo_event,
1089576c57e6SKiseok Jo 			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1090576c57e6SKiseok Jo 	SND_SOC_DAPM_MIXER("Entry", SND_SOC_NOPM, 0, 0, NULL, 0),
1091576c57e6SKiseok Jo 	SND_SOC_DAPM_OUT_DRV_E("AMP Power", SND_SOC_NOPM, 0, 0, NULL, 0,
1092576c57e6SKiseok Jo 			       sma1307_power_event,
1093576c57e6SKiseok Jo 			       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
1094576c57e6SKiseok Jo 			       SND_SOC_DAPM_POST_PMU),
1095576c57e6SKiseok Jo 	SND_SOC_DAPM_SWITCH("AMP Enable", SND_SOC_NOPM, 0, 0,
1096576c57e6SKiseok Jo 			    &sma1307_enable_control),
1097576c57e6SKiseok Jo 
1098576c57e6SKiseok Jo 	/* stream domain */
1099576c57e6SKiseok Jo 	SND_SOC_DAPM_AIF_IN("AIF IN", "Playback", 0, SND_SOC_NOPM, 0, 0),
1100576c57e6SKiseok Jo 	SND_SOC_DAPM_AIF_OUT("AIF OUT", "Capture", 0, SND_SOC_NOPM, 0, 0),
1101576c57e6SKiseok Jo };
1102576c57e6SKiseok Jo 
1103576c57e6SKiseok Jo static const struct snd_soc_dapm_route sma1307_audio_map[] = {
1104576c57e6SKiseok Jo 	/* Playback */
1105576c57e6SKiseok Jo 	{ "AIF IN Source", "Mono", "AIF IN" },
1106576c57e6SKiseok Jo 	{ "AIF IN Source", "Left", "AIF IN" },
1107576c57e6SKiseok Jo 	{ "AIF IN Source", "Right", "AIF IN" },
1108576c57e6SKiseok Jo 
1109576c57e6SKiseok Jo 	{ "SDO Enable", "Switch", "AIF IN" },
1110576c57e6SKiseok Jo 
1111576c57e6SKiseok Jo 	{ "SDO Setting", "Data_One_48k", "SDO Enable" },
1112576c57e6SKiseok Jo 	{ "SDO Setting", "Data_Two_48k", "SDO Enable" },
1113576c57e6SKiseok Jo 	{ "SDO Setting", "Data_Two_24k", "SDO Enable" },
1114576c57e6SKiseok Jo 	{ "SDO Setting", "Clk_PLL", "SDO Enable" },
1115576c57e6SKiseok Jo 	{ "SDO Setting", "Clk_OSC", "SDO Enable" },
1116576c57e6SKiseok Jo 
1117576c57e6SKiseok Jo 	{ "AIF OUT0 Source", "Disable", "SDO Setting" },
1118576c57e6SKiseok Jo 	{ "AIF OUT0 Source", "After_FmtC", "SDO Setting" },
1119576c57e6SKiseok Jo 	{ "AIF OUT0 Source", "After_Mixer", "SDO Setting" },
1120576c57e6SKiseok Jo 	{ "AIF OUT0 Source", "After_DSP", "SDO Setting" },
1121576c57e6SKiseok Jo 	{ "AIF OUT0 Source", "Vrms2_Avg", "SDO Setting" },
1122576c57e6SKiseok Jo 	{ "AIF OUT0 Source", "Battery", "SDO Setting" },
1123576c57e6SKiseok Jo 	{ "AIF OUT0 Source", "Temperature", "SDO Setting" },
1124576c57e6SKiseok Jo 	{ "AIF OUT0 Source", "After_Delay", "SDO Setting" },
1125576c57e6SKiseok Jo 
1126576c57e6SKiseok Jo 	{ "AIF OUT1 Source", "Disable", "SDO Setting" },
1127576c57e6SKiseok Jo 	{ "AIF OUT1 Source", "After_FmtC", "SDO Setting" },
1128576c57e6SKiseok Jo 	{ "AIF OUT1 Source", "After_Mixer", "SDO Setting" },
1129576c57e6SKiseok Jo 	{ "AIF OUT1 Source", "After_DSP", "SDO Setting" },
1130576c57e6SKiseok Jo 	{ "AIF OUT1 Source", "Vrms2_Avg", "SDO Setting" },
1131576c57e6SKiseok Jo 	{ "AIF OUT1 Source", "Battery", "SDO Setting" },
1132576c57e6SKiseok Jo 	{ "AIF OUT1 Source", "Temperature", "SDO Setting" },
1133576c57e6SKiseok Jo 	{ "AIF OUT1 Source", "After_Delay", "SDO Setting" },
1134576c57e6SKiseok Jo 
1135576c57e6SKiseok Jo 	{ "Entry", NULL, "AIF OUT0 Source" },
1136576c57e6SKiseok Jo 	{ "Entry", NULL, "AIF OUT1 Source" },
1137576c57e6SKiseok Jo 	{ "Entry", NULL, "AIF IN Source" },
1138576c57e6SKiseok Jo 
1139576c57e6SKiseok Jo 	{ "AMP Power", NULL, "Entry" },
1140576c57e6SKiseok Jo 
1141576c57e6SKiseok Jo 	{ "AMP Enable", "Switch", "AMP Power" },
1142576c57e6SKiseok Jo 	{ "SPK", NULL, "AMP Enable" },
1143576c57e6SKiseok Jo 
1144576c57e6SKiseok Jo 	/* Capture */
1145576c57e6SKiseok Jo 	{ "AIF OUT", NULL, "AMP Enable" },
1146576c57e6SKiseok Jo };
1147576c57e6SKiseok Jo 
1148576c57e6SKiseok Jo static void sma1307_setup_pll(struct snd_soc_component *component,
1149576c57e6SKiseok Jo 			      unsigned int bclk)
1150576c57e6SKiseok Jo {
1151576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
1152576c57e6SKiseok Jo 
1153576c57e6SKiseok Jo 	int i = 0;
1154576c57e6SKiseok Jo 
1155576c57e6SKiseok Jo 	dev_dbg(component->dev, "%s: BCLK = %dHz\n", __func__, bclk);
1156576c57e6SKiseok Jo 
1157576c57e6SKiseok Jo 	if (sma1307->sys_clk_id == SMA1307_PLL_CLKIN_MCLK) {
1158576c57e6SKiseok Jo 		dev_warn(component->dev, "%s: MCLK is not supported\n",
1159576c57e6SKiseok Jo 			 __func__);
1160576c57e6SKiseok Jo 	} else if (sma1307->sys_clk_id == SMA1307_PLL_CLKIN_BCLK) {
1161576c57e6SKiseok Jo 		for (i = 0; i < sma1307->num_of_pll_matches; i++) {
1162576c57e6SKiseok Jo 			if (sma1307->pll_matches[i].input_clk == bclk)
1163576c57e6SKiseok Jo 				break;
1164576c57e6SKiseok Jo 		}
1165576c57e6SKiseok Jo 		if (i == sma1307->num_of_pll_matches) {
1166576c57e6SKiseok Jo 			dev_warn(component->dev,
1167576c57e6SKiseok Jo 				 "%s: No matching value between pll table and SCK\n",
1168576c57e6SKiseok Jo 				 __func__);
1169576c57e6SKiseok Jo 			return;
1170576c57e6SKiseok Jo 		}
1171576c57e6SKiseok Jo 
1172576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1173576c57e6SKiseok Jo 					   SMA1307_A2_TOP_MAN1,
1174576c57e6SKiseok Jo 					   SMA1307_PLL_MASK, SMA1307_PLL_ON);
1175576c57e6SKiseok Jo 	}
1176576c57e6SKiseok Jo 
1177576c57e6SKiseok Jo 	regmap_write(sma1307->regmap, SMA1307_8B_PLL_POST_N,
1178576c57e6SKiseok Jo 			     sma1307->pll_matches[i].post_n);
1179576c57e6SKiseok Jo 	regmap_write(sma1307->regmap, SMA1307_8C_PLL_N,
1180576c57e6SKiseok Jo 			     sma1307->pll_matches[i].n);
1181576c57e6SKiseok Jo 	regmap_write(sma1307->regmap, SMA1307_8D_PLL_A_SETTING,
1182576c57e6SKiseok Jo 			     sma1307->pll_matches[i].vco);
1183576c57e6SKiseok Jo 	regmap_write(sma1307->regmap, SMA1307_8E_PLL_P_CP,
1184576c57e6SKiseok Jo 			     sma1307->pll_matches[i].p_cp);
1185576c57e6SKiseok Jo }
1186576c57e6SKiseok Jo 
1187576c57e6SKiseok Jo static int sma1307_dai_hw_params_amp(struct snd_pcm_substream *substream,
1188576c57e6SKiseok Jo 				     struct snd_pcm_hw_params *params,
1189576c57e6SKiseok Jo 				     struct snd_soc_dai *dai)
1190576c57e6SKiseok Jo {
1191576c57e6SKiseok Jo 	struct snd_soc_component *component = dai->component;
1192576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
1193576c57e6SKiseok Jo 	unsigned int bclk = 0;
1194576c57e6SKiseok Jo 
1195576c57e6SKiseok Jo 	if (sma1307->format == SND_SOC_DAIFMT_DSP_A)
1196576c57e6SKiseok Jo 		bclk = params_rate(params) * sma1307->frame_size;
1197576c57e6SKiseok Jo 	else
1198576c57e6SKiseok Jo 		bclk = params_rate(params) * params_physical_width(params)
1199576c57e6SKiseok Jo 		    * params_channels(params);
1200576c57e6SKiseok Jo 
1201576c57e6SKiseok Jo 	dev_dbg(component->dev,
1202576c57e6SKiseok Jo 		 "%s: rate = %d : bit size = %d : channel = %d\n",
1203576c57e6SKiseok Jo 		 __func__, params_rate(params), params_width(params),
1204576c57e6SKiseok Jo 		 params_channels(params));
1205576c57e6SKiseok Jo 
1206576c57e6SKiseok Jo 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1207576c57e6SKiseok Jo 		if (sma1307->sys_clk_id == SMA1307_PLL_CLKIN_BCLK) {
1208576c57e6SKiseok Jo 			if (sma1307->last_bclk != bclk) {
1209576c57e6SKiseok Jo 				sma1307_setup_pll(component, bclk);
1210576c57e6SKiseok Jo 				sma1307->last_bclk = bclk;
1211576c57e6SKiseok Jo 			}
1212576c57e6SKiseok Jo 		}
1213576c57e6SKiseok Jo 
1214576c57e6SKiseok Jo 		switch (params_rate(params)) {
1215576c57e6SKiseok Jo 		case 8000:
1216576c57e6SKiseok Jo 		case 12000:
1217576c57e6SKiseok Jo 		case 16000:
1218576c57e6SKiseok Jo 		case 24000:
1219576c57e6SKiseok Jo 		case 32000:
1220576c57e6SKiseok Jo 		case 44100:
1221576c57e6SKiseok Jo 		case 48000:
1222576c57e6SKiseok Jo 			break;
1223576c57e6SKiseok Jo 
1224576c57e6SKiseok Jo 		case 96000:
1225576c57e6SKiseok Jo 			dev_warn(component->dev,
1226576c57e6SKiseok Jo 				 "%s: %d rate not support SDO\n", __func__,
1227576c57e6SKiseok Jo 				 params_rate(params));
1228576c57e6SKiseok Jo 			break;
1229576c57e6SKiseok Jo 
1230576c57e6SKiseok Jo 		default:
1231576c57e6SKiseok Jo 			dev_err(component->dev, "%s: not support rate : %d\n",
1232576c57e6SKiseok Jo 				__func__, params_rate(params));
1233576c57e6SKiseok Jo 
1234576c57e6SKiseok Jo 			return -EINVAL;
1235576c57e6SKiseok Jo 		}
1236576c57e6SKiseok Jo 
1237576c57e6SKiseok Jo 		/* substream->stream is SNDRV_PCM_STREAM_CAPTURE */
1238576c57e6SKiseok Jo 	} else {
1239576c57e6SKiseok Jo 
1240576c57e6SKiseok Jo 		switch (params_format(params)) {
1241576c57e6SKiseok Jo 		case SNDRV_PCM_FORMAT_S16_LE:
1242576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
1243576c57e6SKiseok Jo 						   SMA1307_A4_TOP_MAN3,
1244576c57e6SKiseok Jo 						   SMA1307_SCK_RATE_MASK
1245576c57e6SKiseok Jo 						   |
1246576c57e6SKiseok Jo 						   SMA1307_DATA_WIDTH_MASK,
1247576c57e6SKiseok Jo 						   SMA1307_SCK_32FS |
1248576c57e6SKiseok Jo 						   SMA1307_DATA_16BIT);
1249576c57e6SKiseok Jo 			break;
1250576c57e6SKiseok Jo 
1251576c57e6SKiseok Jo 		case SNDRV_PCM_FORMAT_S24_LE:
1252576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
1253576c57e6SKiseok Jo 						   SMA1307_A4_TOP_MAN3,
1254576c57e6SKiseok Jo 						   SMA1307_SCK_RATE_MASK
1255576c57e6SKiseok Jo 						   |
1256576c57e6SKiseok Jo 						   SMA1307_DATA_WIDTH_MASK,
1257576c57e6SKiseok Jo 						   SMA1307_SCK_64FS |
1258576c57e6SKiseok Jo 						   SMA1307_DATA_24BIT);
1259576c57e6SKiseok Jo 			break;
1260576c57e6SKiseok Jo 
1261576c57e6SKiseok Jo 		case SNDRV_PCM_FORMAT_S32_LE:
1262576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
1263576c57e6SKiseok Jo 						   SMA1307_A4_TOP_MAN3,
1264576c57e6SKiseok Jo 						   SMA1307_SCK_RATE_MASK
1265576c57e6SKiseok Jo 						   |
1266576c57e6SKiseok Jo 						   SMA1307_DATA_WIDTH_MASK,
1267576c57e6SKiseok Jo 						   SMA1307_SCK_64FS |
1268576c57e6SKiseok Jo 						   SMA1307_DATA_24BIT);
1269576c57e6SKiseok Jo 			break;
1270576c57e6SKiseok Jo 		default:
1271576c57e6SKiseok Jo 			dev_err(component->dev,
1272576c57e6SKiseok Jo 				"%s: not support data bit : %d\n", __func__,
1273576c57e6SKiseok Jo 				params_format(params));
1274576c57e6SKiseok Jo 			return -EINVAL;
1275576c57e6SKiseok Jo 		}
1276576c57e6SKiseok Jo 	}
1277576c57e6SKiseok Jo 
1278576c57e6SKiseok Jo 	switch (sma1307->format) {
1279576c57e6SKiseok Jo 	case SND_SOC_DAIFMT_I2S:
1280576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1281576c57e6SKiseok Jo 					   SMA1307_01_INPUT_CTRL1,
1282576c57e6SKiseok Jo 					   SMA1307_I2S_MODE_MASK,
1283576c57e6SKiseok Jo 					   SMA1307_STANDARD_I2S);
1284576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1285576c57e6SKiseok Jo 					   SMA1307_A4_TOP_MAN3,
1286576c57e6SKiseok Jo 					   SMA1307_INTERFACE_MASK,
1287576c57e6SKiseok Jo 					   SMA1307_I2S_FORMAT);
1288576c57e6SKiseok Jo 		break;
1289576c57e6SKiseok Jo 	case SND_SOC_DAIFMT_LEFT_J:
1290576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1291576c57e6SKiseok Jo 					   SMA1307_01_INPUT_CTRL1,
1292576c57e6SKiseok Jo 					   SMA1307_I2S_MODE_MASK, SMA1307_LJ);
1293576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1294576c57e6SKiseok Jo 					   SMA1307_A4_TOP_MAN3,
1295576c57e6SKiseok Jo 					   SMA1307_INTERFACE_MASK,
1296576c57e6SKiseok Jo 					   SMA1307_LJ_FORMAT);
1297576c57e6SKiseok Jo 		break;
1298576c57e6SKiseok Jo 	case SND_SOC_DAIFMT_RIGHT_J:
1299576c57e6SKiseok Jo 		switch (params_width(params)) {
1300576c57e6SKiseok Jo 		case 16:
1301576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
1302576c57e6SKiseok Jo 						   SMA1307_01_INPUT_CTRL1,
1303576c57e6SKiseok Jo 						   SMA1307_I2S_MODE_MASK,
1304576c57e6SKiseok Jo 						   SMA1307_RJ_16BIT);
1305576c57e6SKiseok Jo 			break;
1306576c57e6SKiseok Jo 		case 24:
1307576c57e6SKiseok Jo 		case 32:
1308576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
1309576c57e6SKiseok Jo 						   SMA1307_01_INPUT_CTRL1,
1310576c57e6SKiseok Jo 						   SMA1307_I2S_MODE_MASK,
1311576c57e6SKiseok Jo 						   SMA1307_RJ_24BIT);
1312576c57e6SKiseok Jo 			break;
1313576c57e6SKiseok Jo 		}
1314576c57e6SKiseok Jo 		break;
1315576c57e6SKiseok Jo 	case SND_SOC_DAIFMT_DSP_A:
1316576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1317576c57e6SKiseok Jo 					   SMA1307_01_INPUT_CTRL1,
1318576c57e6SKiseok Jo 					   SMA1307_I2S_MODE_MASK,
1319576c57e6SKiseok Jo 					   SMA1307_STANDARD_I2S);
1320576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1321576c57e6SKiseok Jo 					   SMA1307_A4_TOP_MAN3,
1322576c57e6SKiseok Jo 					   SMA1307_INTERFACE_MASK,
1323576c57e6SKiseok Jo 					   SMA1307_TDM_FORMAT);
1324576c57e6SKiseok Jo 		break;
1325576c57e6SKiseok Jo 	}
1326576c57e6SKiseok Jo 
1327576c57e6SKiseok Jo 	switch (params_width(params)) {
1328576c57e6SKiseok Jo 	case 16:
1329576c57e6SKiseok Jo 	case 24:
1330576c57e6SKiseok Jo 	case 32:
1331576c57e6SKiseok Jo 		break;
1332576c57e6SKiseok Jo 	default:
1333576c57e6SKiseok Jo 		dev_err(component->dev,
1334576c57e6SKiseok Jo 			"%s: not support data bit : %d\n", __func__,
1335576c57e6SKiseok Jo 			params_format(params));
1336576c57e6SKiseok Jo 		return -EINVAL;
1337576c57e6SKiseok Jo 	}
1338576c57e6SKiseok Jo 
1339576c57e6SKiseok Jo 	return 0;
1340576c57e6SKiseok Jo }
1341576c57e6SKiseok Jo 
1342576c57e6SKiseok Jo static int sma1307_dai_set_sysclk_amp(struct snd_soc_dai *dai,
1343576c57e6SKiseok Jo 				      int clk_id, unsigned int freq, int dir)
1344576c57e6SKiseok Jo {
1345576c57e6SKiseok Jo 	struct snd_soc_component *component = dai->component;
1346576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
1347576c57e6SKiseok Jo 
1348576c57e6SKiseok Jo 	switch (clk_id) {
1349576c57e6SKiseok Jo 	case SMA1307_EXTERNAL_CLOCK_19_2:
1350576c57e6SKiseok Jo 	case SMA1307_EXTERNAL_CLOCK_24_576:
1351576c57e6SKiseok Jo 	case SMA1307_PLL_CLKIN_MCLK:
1352576c57e6SKiseok Jo 	case SMA1307_PLL_CLKIN_BCLK:
1353576c57e6SKiseok Jo 		break;
1354576c57e6SKiseok Jo 	default:
1355576c57e6SKiseok Jo 		dev_err(component->dev, "%s: Invalid clk id: %d\n",
1356576c57e6SKiseok Jo 			__func__, clk_id);
1357576c57e6SKiseok Jo 		return -EINVAL;
1358576c57e6SKiseok Jo 	}
1359576c57e6SKiseok Jo 	sma1307->sys_clk_id = clk_id;
1360576c57e6SKiseok Jo 
1361576c57e6SKiseok Jo 	return 0;
1362576c57e6SKiseok Jo }
1363576c57e6SKiseok Jo 
1364576c57e6SKiseok Jo static int sma1307_dai_set_fmt_amp(struct snd_soc_dai *dai, unsigned int fmt)
1365576c57e6SKiseok Jo {
1366576c57e6SKiseok Jo 	struct snd_soc_component *component = dai->component;
1367576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
1368576c57e6SKiseok Jo 
1369576c57e6SKiseok Jo 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1370576c57e6SKiseok Jo 
1371576c57e6SKiseok Jo 	case SND_SOC_DAIFMT_CBC_CFC:
1372576c57e6SKiseok Jo 		dev_dbg(component->dev,
1373576c57e6SKiseok Jo 			 "%s: %s\n", __func__, "I2S/TDM Device mode");
1374576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1375576c57e6SKiseok Jo 					   SMA1307_01_INPUT_CTRL1,
1376576c57e6SKiseok Jo 					   SMA1307_CONTROLLER_DEVICE_MASK,
1377576c57e6SKiseok Jo 					   SMA1307_DEVICE_MODE);
1378576c57e6SKiseok Jo 		break;
1379576c57e6SKiseok Jo 
1380576c57e6SKiseok Jo 	case SND_SOC_DAIFMT_CBP_CFP:
1381576c57e6SKiseok Jo 		dev_dbg(component->dev,
1382576c57e6SKiseok Jo 			 "%s: %s\n", __func__, "I2S/TDM Controller mode");
1383576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1384576c57e6SKiseok Jo 					   SMA1307_01_INPUT_CTRL1,
1385576c57e6SKiseok Jo 					   SMA1307_CONTROLLER_DEVICE_MASK,
1386576c57e6SKiseok Jo 					   SMA1307_CONTROLLER_MODE);
1387576c57e6SKiseok Jo 		break;
1388576c57e6SKiseok Jo 
1389576c57e6SKiseok Jo 	default:
1390576c57e6SKiseok Jo 		dev_err(component->dev,
1391576c57e6SKiseok Jo 			"%s: Unsupported Controller/Device : 0x%x\n",
1392576c57e6SKiseok Jo 			__func__, fmt);
1393576c57e6SKiseok Jo 		return -EINVAL;
1394576c57e6SKiseok Jo 	}
1395576c57e6SKiseok Jo 
1396576c57e6SKiseok Jo 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1397576c57e6SKiseok Jo 	case SND_SOC_DAIFMT_I2S:
1398576c57e6SKiseok Jo 	case SND_SOC_DAIFMT_RIGHT_J:
1399576c57e6SKiseok Jo 	case SND_SOC_DAIFMT_LEFT_J:
1400576c57e6SKiseok Jo 	case SND_SOC_DAIFMT_DSP_A:
1401576c57e6SKiseok Jo 	case SND_SOC_DAIFMT_DSP_B:
1402576c57e6SKiseok Jo 		sma1307->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
1403576c57e6SKiseok Jo 		break;
1404576c57e6SKiseok Jo 	default:
1405576c57e6SKiseok Jo 		dev_err(component->dev,
1406576c57e6SKiseok Jo 			"%s: Unsupported Audio Interface Format : 0x%x\n",
1407576c57e6SKiseok Jo 			__func__, fmt);
1408576c57e6SKiseok Jo 		return -EINVAL;
1409576c57e6SKiseok Jo 	}
1410576c57e6SKiseok Jo 
1411576c57e6SKiseok Jo 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1412576c57e6SKiseok Jo 
1413576c57e6SKiseok Jo 	case SND_SOC_DAIFMT_IB_NF:
1414576c57e6SKiseok Jo 		dev_dbg(component->dev, "%s: %s\n",
1415576c57e6SKiseok Jo 			 __func__, "Invert BCLK + Normal Frame");
1416576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1417576c57e6SKiseok Jo 					   SMA1307_01_INPUT_CTRL1,
1418576c57e6SKiseok Jo 					   SMA1307_SCK_RISING_MASK,
1419576c57e6SKiseok Jo 					   SMA1307_SCK_RISING_EDGE);
1420576c57e6SKiseok Jo 		break;
1421576c57e6SKiseok Jo 	case SND_SOC_DAIFMT_IB_IF:
1422576c57e6SKiseok Jo 		dev_dbg(component->dev, "%s: %s\n",
1423576c57e6SKiseok Jo 			 __func__, "Invert BCLK + Invert Frame");
1424576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1425576c57e6SKiseok Jo 					   SMA1307_01_INPUT_CTRL1,
1426576c57e6SKiseok Jo 					   SMA1307_LEFTPOL_MASK
1427576c57e6SKiseok Jo 					   | SMA1307_SCK_RISING_MASK,
1428576c57e6SKiseok Jo 					   SMA1307_HIGH_FIRST_CH
1429576c57e6SKiseok Jo 					   | SMA1307_SCK_RISING_EDGE);
1430576c57e6SKiseok Jo 		break;
1431576c57e6SKiseok Jo 	case SND_SOC_DAIFMT_NB_IF:
1432576c57e6SKiseok Jo 		dev_dbg(component->dev, "%s: %s\n",
1433576c57e6SKiseok Jo 			 __func__, "Normal BCLK + Invert Frame");
1434576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1435576c57e6SKiseok Jo 					   SMA1307_01_INPUT_CTRL1,
1436576c57e6SKiseok Jo 					   SMA1307_LEFTPOL_MASK,
1437576c57e6SKiseok Jo 					   SMA1307_HIGH_FIRST_CH);
1438576c57e6SKiseok Jo 		break;
1439576c57e6SKiseok Jo 	case SND_SOC_DAIFMT_NB_NF:
1440576c57e6SKiseok Jo 		dev_dbg(component->dev, "%s: %s\n",
1441576c57e6SKiseok Jo 			 __func__, "Normal BCLK + Normal Frame");
1442576c57e6SKiseok Jo 		break;
1443576c57e6SKiseok Jo 	default:
1444576c57e6SKiseok Jo 		dev_err(component->dev,
1445576c57e6SKiseok Jo 			"%s: Unsupported Bit & Frameclock : 0x%x\n",
1446576c57e6SKiseok Jo 			__func__, fmt);
1447576c57e6SKiseok Jo 		return -EINVAL;
1448576c57e6SKiseok Jo 	}
1449576c57e6SKiseok Jo 
1450576c57e6SKiseok Jo 	return 0;
1451576c57e6SKiseok Jo }
1452576c57e6SKiseok Jo 
1453576c57e6SKiseok Jo static int sma1307_dai_set_tdm_slot(struct snd_soc_dai *dai,
1454576c57e6SKiseok Jo 				    unsigned int tx_mask, unsigned int rx_mask,
1455576c57e6SKiseok Jo 				    int slots, int slot_width)
1456576c57e6SKiseok Jo {
1457576c57e6SKiseok Jo 	struct snd_soc_component *component = dai->component;
1458576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
1459576c57e6SKiseok Jo 
1460576c57e6SKiseok Jo 	dev_dbg(component->dev, "%s: slots = %d, slot_width - %d\n",
1461576c57e6SKiseok Jo 		 __func__, slots, slot_width);
1462576c57e6SKiseok Jo 
1463576c57e6SKiseok Jo 	sma1307->frame_size = slot_width * slots;
1464576c57e6SKiseok Jo 
1465576c57e6SKiseok Jo 	regmap_update_bits(sma1307->regmap,
1466576c57e6SKiseok Jo 				   SMA1307_A4_TOP_MAN3,
1467576c57e6SKiseok Jo 				   SMA1307_INTERFACE_MASK, SMA1307_TDM_FORMAT);
1468576c57e6SKiseok Jo 
1469576c57e6SKiseok Jo 	regmap_update_bits(sma1307->regmap,
1470576c57e6SKiseok Jo 				   SMA1307_A5_TDM1,
1471576c57e6SKiseok Jo 				   SMA1307_TDM_TX_MODE_MASK,
1472576c57e6SKiseok Jo 				   SMA1307_TDM_TX_MONO);
1473576c57e6SKiseok Jo 
1474576c57e6SKiseok Jo 	switch (slot_width) {
1475576c57e6SKiseok Jo 	case 16:
1476576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1477576c57e6SKiseok Jo 					   SMA1307_A6_TDM2,
1478576c57e6SKiseok Jo 					   SMA1307_TDM_DL_MASK,
1479576c57e6SKiseok Jo 					   SMA1307_TDM_DL_16);
1480576c57e6SKiseok Jo 		break;
1481576c57e6SKiseok Jo 	case 32:
1482576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1483576c57e6SKiseok Jo 					   SMA1307_A6_TDM2,
1484576c57e6SKiseok Jo 					   SMA1307_TDM_DL_MASK,
1485576c57e6SKiseok Jo 					   SMA1307_TDM_DL_32);
1486576c57e6SKiseok Jo 		break;
1487576c57e6SKiseok Jo 	default:
1488576c57e6SKiseok Jo 		dev_err(component->dev, "%s: not support TDM %d slot_width\n",
1489576c57e6SKiseok Jo 			__func__, slot_width);
1490576c57e6SKiseok Jo 		return -EINVAL;
1491576c57e6SKiseok Jo 	}
1492576c57e6SKiseok Jo 
1493576c57e6SKiseok Jo 	switch (slots) {
1494576c57e6SKiseok Jo 	case 4:
1495576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1496576c57e6SKiseok Jo 					   SMA1307_A6_TDM2,
1497576c57e6SKiseok Jo 					   SMA1307_TDM_N_SLOT_MASK,
1498576c57e6SKiseok Jo 					   SMA1307_TDM_N_SLOT_4);
1499576c57e6SKiseok Jo 		break;
1500576c57e6SKiseok Jo 	case 8:
1501576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1502576c57e6SKiseok Jo 					   SMA1307_A6_TDM2,
1503576c57e6SKiseok Jo 					   SMA1307_TDM_N_SLOT_MASK,
1504576c57e6SKiseok Jo 					   SMA1307_TDM_N_SLOT_8);
1505576c57e6SKiseok Jo 		break;
1506576c57e6SKiseok Jo 	default:
1507576c57e6SKiseok Jo 		dev_err(component->dev, "%s: not support TDM %d slots\n",
1508576c57e6SKiseok Jo 			__func__, slots);
1509576c57e6SKiseok Jo 		return -EINVAL;
1510576c57e6SKiseok Jo 	}
1511576c57e6SKiseok Jo 
1512576c57e6SKiseok Jo 	if (sma1307->tdm_slot0_rx < slots)
1513576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1514576c57e6SKiseok Jo 					   SMA1307_A5_TDM1,
1515576c57e6SKiseok Jo 					   SMA1307_TDM_SLOT0_RX_POS_MASK,
1516576c57e6SKiseok Jo 					   sma1307->tdm_slot0_rx << 3);
1517576c57e6SKiseok Jo 	else
1518576c57e6SKiseok Jo 		dev_err(component->dev, "%s: Incorrect tdm-slot0-rx %d set\n",
1519576c57e6SKiseok Jo 			__func__, sma1307->tdm_slot0_rx);
1520576c57e6SKiseok Jo 
1521576c57e6SKiseok Jo 	if (sma1307->tdm_slot1_rx < slots)
1522576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1523576c57e6SKiseok Jo 					   SMA1307_A5_TDM1,
1524576c57e6SKiseok Jo 					   SMA1307_TDM_SLOT1_RX_POS_MASK,
1525576c57e6SKiseok Jo 					   sma1307->tdm_slot1_rx);
1526576c57e6SKiseok Jo 	else
1527576c57e6SKiseok Jo 		dev_err(component->dev, "%s: Incorrect tdm-slot1-rx %d set\n",
1528576c57e6SKiseok Jo 			__func__, sma1307->tdm_slot1_rx);
1529576c57e6SKiseok Jo 
1530576c57e6SKiseok Jo 	if (sma1307->tdm_slot0_tx < slots)
1531576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1532576c57e6SKiseok Jo 					   SMA1307_A6_TDM2,
1533576c57e6SKiseok Jo 					   SMA1307_TDM_SLOT0_TX_POS_MASK,
1534576c57e6SKiseok Jo 					   sma1307->tdm_slot0_tx << 3);
1535576c57e6SKiseok Jo 	else
1536576c57e6SKiseok Jo 		dev_err(component->dev, "%s: Incorrect tdm-slot0-tx %d set\n",
1537576c57e6SKiseok Jo 			__func__, sma1307->tdm_slot0_tx);
1538576c57e6SKiseok Jo 
1539576c57e6SKiseok Jo 	if (sma1307->tdm_slot1_tx < slots)
1540576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1541576c57e6SKiseok Jo 					   SMA1307_A6_TDM2,
1542576c57e6SKiseok Jo 					   SMA1307_TDM_SLOT1_TX_POS_MASK,
1543576c57e6SKiseok Jo 					   sma1307->tdm_slot1_tx);
1544576c57e6SKiseok Jo 	else
1545576c57e6SKiseok Jo 		dev_err(component->dev, "%s: Incorrect tdm-slot1-tx %d set\n",
1546576c57e6SKiseok Jo 			__func__, sma1307->tdm_slot1_tx);
1547576c57e6SKiseok Jo 
1548576c57e6SKiseok Jo 	return 0;
1549576c57e6SKiseok Jo }
1550576c57e6SKiseok Jo 
1551576c57e6SKiseok Jo static int sma1307_dai_mute_stream(struct snd_soc_dai *dai, int mute,
1552576c57e6SKiseok Jo 				   int stream)
1553576c57e6SKiseok Jo {
1554576c57e6SKiseok Jo 	struct snd_soc_component *component = dai->component;
1555576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
1556576c57e6SKiseok Jo 
1557576c57e6SKiseok Jo 	if (stream == SNDRV_PCM_STREAM_CAPTURE)
1558576c57e6SKiseok Jo 		return 0;
1559576c57e6SKiseok Jo 	if (mute) {
1560576c57e6SKiseok Jo 		dev_dbg(component->dev, "%s: %s\n", __func__, "MUTE");
1561576c57e6SKiseok Jo 		regmap_update_bits(sma1307->regmap,
1562576c57e6SKiseok Jo 					   SMA1307_0E_MUTE_VOL_CTRL,
1563576c57e6SKiseok Jo 					   SMA1307_SPK_MUTE_MASK,
1564576c57e6SKiseok Jo 					   SMA1307_SPK_MUTE);
1565576c57e6SKiseok Jo 	} else {
1566576c57e6SKiseok Jo 		if (!sma1307->force_mute_status) {
1567576c57e6SKiseok Jo 			dev_dbg(component->dev, "%s: %s\n", __func__,
1568576c57e6SKiseok Jo 					 "UNMUTE");
1569576c57e6SKiseok Jo 			regmap_update_bits(sma1307->regmap,
1570576c57e6SKiseok Jo 						SMA1307_0E_MUTE_VOL_CTRL,
1571576c57e6SKiseok Jo 						SMA1307_SPK_MUTE_MASK,
1572576c57e6SKiseok Jo 						SMA1307_SPK_UNMUTE);
1573576c57e6SKiseok Jo 		} else {
1574576c57e6SKiseok Jo 			dev_dbg(sma1307->dev, "%s: FORCE MUTE!!!\n", __func__);
1575576c57e6SKiseok Jo 		}
1576576c57e6SKiseok Jo 	}
1577576c57e6SKiseok Jo 
1578576c57e6SKiseok Jo 	return 0;
1579576c57e6SKiseok Jo }
1580576c57e6SKiseok Jo 
1581576c57e6SKiseok Jo static const struct snd_soc_dai_ops sma1307_dai_ops_amp = {
1582576c57e6SKiseok Jo 	.hw_params = sma1307_dai_hw_params_amp,
1583576c57e6SKiseok Jo 	.set_fmt = sma1307_dai_set_fmt_amp,
1584576c57e6SKiseok Jo 	.set_sysclk = sma1307_dai_set_sysclk_amp,
1585576c57e6SKiseok Jo 	.set_tdm_slot = sma1307_dai_set_tdm_slot,
1586576c57e6SKiseok Jo 	.mute_stream = sma1307_dai_mute_stream,
1587576c57e6SKiseok Jo };
1588576c57e6SKiseok Jo 
1589576c57e6SKiseok Jo #define SMA1307_RATES_PLAYBACK SNDRV_PCM_RATE_8000_96000
1590576c57e6SKiseok Jo #define SMA1307_RATES_CAPTURE SNDRV_PCM_RATE_8000_48000
1591576c57e6SKiseok Jo #define SMA1307_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \
1592576c57e6SKiseok Jo 		SNDRV_PCM_FMTBIT_S32_LE)
1593576c57e6SKiseok Jo 
1594576c57e6SKiseok Jo static struct snd_soc_dai_driver sma1307_dai[] = {
1595576c57e6SKiseok Jo 	{
1596576c57e6SKiseok Jo 	 .name = "sma1307-amplifier",
1597576c57e6SKiseok Jo 	 .id = 0,
1598576c57e6SKiseok Jo 	 .playback = {
1599576c57e6SKiseok Jo 		      .stream_name = "Playback",
1600576c57e6SKiseok Jo 		      .channels_min = 1,
1601576c57e6SKiseok Jo 		      .channels_max = 2,
1602576c57e6SKiseok Jo 		      .rates = SMA1307_RATES_PLAYBACK,
1603576c57e6SKiseok Jo 		      .formats = SMA1307_FORMATS,
1604576c57e6SKiseok Jo 		      },
1605576c57e6SKiseok Jo 	 .capture = {
1606576c57e6SKiseok Jo 		     .stream_name = "Capture",
1607576c57e6SKiseok Jo 		     .channels_min = 1,
1608576c57e6SKiseok Jo 		     .channels_max = 2,
1609576c57e6SKiseok Jo 		     .rates = SMA1307_RATES_CAPTURE,
1610576c57e6SKiseok Jo 		     .formats = SMA1307_FORMATS,
1611576c57e6SKiseok Jo 		     },
1612576c57e6SKiseok Jo 	 .ops = &sma1307_dai_ops_amp,
1613576c57e6SKiseok Jo 	  },
1614576c57e6SKiseok Jo };
1615576c57e6SKiseok Jo 
1616576c57e6SKiseok Jo static void sma1307_check_fault_worker(struct work_struct *work)
1617576c57e6SKiseok Jo {
1618576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 =
1619576c57e6SKiseok Jo 	    container_of(work, struct sma1307_priv, check_fault_work.work);
1620576c57e6SKiseok Jo 	unsigned int status1_val, status2_val;
1621576c57e6SKiseok Jo 	char *envp[3] = { NULL, NULL, NULL };
1622576c57e6SKiseok Jo 
1623576c57e6SKiseok Jo 	if (sma1307->tsdw_cnt)
1624576c57e6SKiseok Jo 		regmap_read(sma1307->regmap,
1625576c57e6SKiseok Jo 			SMA1307_0A_SPK_VOL, &sma1307->cur_vol);
1626576c57e6SKiseok Jo 	else
1627576c57e6SKiseok Jo 		regmap_read(sma1307->regmap,
1628576c57e6SKiseok Jo 			SMA1307_0A_SPK_VOL, &sma1307->init_vol);
1629576c57e6SKiseok Jo 
1630576c57e6SKiseok Jo 	regmap_read(sma1307->regmap, SMA1307_FA_STATUS1, &status1_val);
1631576c57e6SKiseok Jo 	regmap_read(sma1307->regmap, SMA1307_FB_STATUS2, &status2_val);
1632576c57e6SKiseok Jo 
1633576c57e6SKiseok Jo 	if (~status1_val & SMA1307_OT1_OK_STATUS) {
1634576c57e6SKiseok Jo 		dev_crit(sma1307->dev,
1635576c57e6SKiseok Jo 			 "%s: OT1(Over Temperature Level 1)\n", __func__);
1636576c57e6SKiseok Jo 		envp[0] = kasprintf(GFP_KERNEL, "STATUS=OT1");
1637576c57e6SKiseok Jo 		if (sma1307->sw_ot1_prot) {
1638576c57e6SKiseok Jo 			/* Volume control (Current Volume -3dB) */
1639576c57e6SKiseok Jo 			if ((sma1307->cur_vol + 6) <= 0xFA) {
1640576c57e6SKiseok Jo 				sma1307->cur_vol += 6;
1641576c57e6SKiseok Jo 				regmap_write(sma1307->regmap,
1642576c57e6SKiseok Jo 						     SMA1307_0A_SPK_VOL,
1643576c57e6SKiseok Jo 						     sma1307->cur_vol);
1644576c57e6SKiseok Jo 				envp[1] = kasprintf(GFP_KERNEL,
1645576c57e6SKiseok Jo 					"VOLUME=0x%02X", sma1307->cur_vol);
1646576c57e6SKiseok Jo 			}
1647576c57e6SKiseok Jo 		}
1648576c57e6SKiseok Jo 		sma1307->tsdw_cnt++;
1649576c57e6SKiseok Jo 	} else if (sma1307->tsdw_cnt) {
1650576c57e6SKiseok Jo 		regmap_write(sma1307->regmap,
1651576c57e6SKiseok Jo 				     SMA1307_0A_SPK_VOL, sma1307->init_vol);
1652576c57e6SKiseok Jo 		sma1307->tsdw_cnt = 0;
1653576c57e6SKiseok Jo 		sma1307->cur_vol = sma1307->init_vol;
1654576c57e6SKiseok Jo 		envp[0] = kasprintf(GFP_KERNEL, "STATUS=OT1_CLEAR");
1655576c57e6SKiseok Jo 		envp[1] = kasprintf(GFP_KERNEL,
1656576c57e6SKiseok Jo 				"VOLUME=0x%02X", sma1307->cur_vol);
1657576c57e6SKiseok Jo 	}
1658576c57e6SKiseok Jo 
1659576c57e6SKiseok Jo 	if (~status1_val & SMA1307_OT2_OK_STATUS) {
1660576c57e6SKiseok Jo 		dev_crit(sma1307->dev,
1661576c57e6SKiseok Jo 			 "%s: OT2(Over Temperature Level 2)\n", __func__);
1662576c57e6SKiseok Jo 		envp[0] = kasprintf(GFP_KERNEL, "STATUS=OT2");
1663576c57e6SKiseok Jo 	}
1664576c57e6SKiseok Jo 	if (status1_val & SMA1307_UVLO_STATUS) {
1665576c57e6SKiseok Jo 		dev_crit(sma1307->dev,
1666576c57e6SKiseok Jo 			 "%s: UVLO(Under Voltage Lock Out)\n", __func__);
1667576c57e6SKiseok Jo 		envp[0] = kasprintf(GFP_KERNEL, "STATUS=UVLO");
1668576c57e6SKiseok Jo 	}
1669576c57e6SKiseok Jo 	if (status1_val & SMA1307_OVP_BST_STATUS) {
1670576c57e6SKiseok Jo 		dev_crit(sma1307->dev,
1671576c57e6SKiseok Jo 			 "%s: OVP_BST(Over Voltage Protection)\n", __func__);
1672576c57e6SKiseok Jo 		envp[0] = kasprintf(GFP_KERNEL, "STATUS=OVP_BST");
1673576c57e6SKiseok Jo 	}
1674576c57e6SKiseok Jo 	if (status2_val & SMA1307_OCP_SPK_STATUS) {
1675576c57e6SKiseok Jo 		dev_crit(sma1307->dev,
1676576c57e6SKiseok Jo 			 "%s: OCP_SPK(Over Current Protect SPK)\n", __func__);
1677576c57e6SKiseok Jo 		envp[0] = kasprintf(GFP_KERNEL, "STATUS=OCP_SPK");
1678576c57e6SKiseok Jo 	}
1679576c57e6SKiseok Jo 	if (status2_val & SMA1307_OCP_BST_STATUS) {
1680576c57e6SKiseok Jo 		dev_crit(sma1307->dev,
1681576c57e6SKiseok Jo 			 "%s: OCP_BST(Over Current Protect Boost)\n", __func__);
1682576c57e6SKiseok Jo 		envp[0] = kasprintf(GFP_KERNEL, "STATUS=OCP_BST");
1683576c57e6SKiseok Jo 	}
1684576c57e6SKiseok Jo 	if (status2_val & SMA1307_CLK_MON_STATUS) {
1685576c57e6SKiseok Jo 		dev_crit(sma1307->dev,
1686576c57e6SKiseok Jo 			 "%s: CLK_FAULT(No clock input)\n", __func__);
1687576c57e6SKiseok Jo 		envp[0] = kasprintf(GFP_KERNEL, "STATUS=CLK_FAULT");
1688576c57e6SKiseok Jo 	}
1689576c57e6SKiseok Jo 
1690576c57e6SKiseok Jo 	if (envp[0] != NULL) {
1691576c57e6SKiseok Jo 		if (kobject_uevent_env(sma1307->kobj, KOBJ_CHANGE, envp))
1692576c57e6SKiseok Jo 			dev_err(sma1307->dev,
1693576c57e6SKiseok Jo 				"%s: Error sending uevent\n", __func__);
1694576c57e6SKiseok Jo 		kfree(envp[0]);
1695576c57e6SKiseok Jo 		kfree(envp[1]);
1696576c57e6SKiseok Jo 	}
1697576c57e6SKiseok Jo 
1698576c57e6SKiseok Jo 	if (sma1307->check_fault_status) {
1699576c57e6SKiseok Jo 		if (sma1307->check_fault_period > 0)
1700576c57e6SKiseok Jo 			queue_delayed_work(system_freezable_wq,
1701576c57e6SKiseok Jo 					   &sma1307->check_fault_work,
1702576c57e6SKiseok Jo 					   sma1307->check_fault_period * HZ);
1703576c57e6SKiseok Jo 		else
1704576c57e6SKiseok Jo 			queue_delayed_work(system_freezable_wq,
1705576c57e6SKiseok Jo 					   &sma1307->check_fault_work,
1706576c57e6SKiseok Jo 					   CHECK_PERIOD_TIME * HZ);
1707576c57e6SKiseok Jo 	}
1708576c57e6SKiseok Jo }
1709576c57e6SKiseok Jo 
1710576c57e6SKiseok Jo static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *file)
1711576c57e6SKiseok Jo {
1712576c57e6SKiseok Jo 	const struct firmware *fw;
1713576c57e6SKiseok Jo 	int *data, size, offset, num_mode;
1714*c48a4497SArnd Bergmann 	int ret;
1715576c57e6SKiseok Jo 
1716*c48a4497SArnd Bergmann 	ret = request_firmware(&fw, file, sma1307->dev);
1717576c57e6SKiseok Jo 
1718*c48a4497SArnd Bergmann 	if (ret) {
1719*c48a4497SArnd Bergmann 		dev_err(sma1307->dev, "%s: failed to read \"%s\": %pe\n",
1720*c48a4497SArnd Bergmann 			__func__, setting_file, ERR_PTR(ret));
1721576c57e6SKiseok Jo 		sma1307->set.status = false;
1722576c57e6SKiseok Jo 		return;
1723576c57e6SKiseok Jo 	} else if ((fw->size) < SMA1307_SETTING_HEADER_SIZE) {
1724576c57e6SKiseok Jo 		dev_err(sma1307->dev, "%s: Invalid file\n", __func__);
1725576c57e6SKiseok Jo 		release_firmware(fw);
1726576c57e6SKiseok Jo 		sma1307->set.status = false;
1727576c57e6SKiseok Jo 		return;
1728576c57e6SKiseok Jo 	}
1729576c57e6SKiseok Jo 
1730576c57e6SKiseok Jo 	data = kzalloc(fw->size, GFP_KERNEL);
1731576c57e6SKiseok Jo 	size = fw->size >> 2;
1732576c57e6SKiseok Jo 	memcpy(data, fw->data, fw->size);
1733576c57e6SKiseok Jo 
1734576c57e6SKiseok Jo 	release_firmware(fw);
1735576c57e6SKiseok Jo 
1736576c57e6SKiseok Jo 	/* HEADER */
1737576c57e6SKiseok Jo 	sma1307->set.header_size = SMA1307_SETTING_HEADER_SIZE;
1738576c57e6SKiseok Jo 	sma1307->set.checksum = data[sma1307->set.header_size - 2];
1739576c57e6SKiseok Jo 	sma1307->set.num_mode = data[sma1307->set.header_size - 1];
1740576c57e6SKiseok Jo 	num_mode = sma1307->set.num_mode;
1741576c57e6SKiseok Jo 	sma1307->set.header = devm_kzalloc(sma1307->dev,
1742576c57e6SKiseok Jo 					   sma1307->set.header_size,
1743576c57e6SKiseok Jo 					   GFP_KERNEL);
1744576c57e6SKiseok Jo 	memcpy(sma1307->set.header, data,
1745576c57e6SKiseok Jo 	       sma1307->set.header_size * sizeof(int));
1746576c57e6SKiseok Jo 
1747576c57e6SKiseok Jo 	if ((sma1307->set.checksum >> 8) != SMA1307_SETTING_CHECKSUM) {
1748576c57e6SKiseok Jo 		dev_err(sma1307->dev, "%s: failed by dismatch \"%s\"\n",
1749576c57e6SKiseok Jo 			__func__, setting_file);
1750576c57e6SKiseok Jo 		sma1307->set.status = false;
1751576c57e6SKiseok Jo 		return;
1752576c57e6SKiseok Jo 	}
1753576c57e6SKiseok Jo 
1754576c57e6SKiseok Jo 	/* DEFAULT */
1755576c57e6SKiseok Jo 	sma1307->set.def_size = SMA1307_SETTING_DEFAULT_SIZE;
1756576c57e6SKiseok Jo 	sma1307->set.def
1757576c57e6SKiseok Jo 	    = devm_kzalloc(sma1307->dev,
1758576c57e6SKiseok Jo 			   sma1307->set.def_size * sizeof(int), GFP_KERNEL);
1759576c57e6SKiseok Jo 	memcpy(sma1307->set.def,
1760576c57e6SKiseok Jo 	       &data[sma1307->set.header_size],
1761576c57e6SKiseok Jo 	       sma1307->set.def_size * sizeof(int));
1762576c57e6SKiseok Jo 
1763576c57e6SKiseok Jo 	/* MODE */
1764576c57e6SKiseok Jo 	offset = sma1307->set.header_size + sma1307->set.def_size;
1765576c57e6SKiseok Jo 	sma1307->set.mode_size = DIV_ROUND_CLOSEST(size - offset, num_mode + 1);
1766576c57e6SKiseok Jo 	for (int i = 0; i < num_mode; i++) {
1767576c57e6SKiseok Jo 		sma1307->set.mode_set[i]
1768576c57e6SKiseok Jo 		    = devm_kzalloc(sma1307->dev,
1769576c57e6SKiseok Jo 				   sma1307->set.mode_size * 2 * sizeof(int),
1770576c57e6SKiseok Jo 				   GFP_KERNEL);
1771576c57e6SKiseok Jo 		for (int j = 0; j < sma1307->set.mode_size; j++) {
1772576c57e6SKiseok Jo 			sma1307->set.mode_set[i][2 * j]
1773576c57e6SKiseok Jo 			    = data[offset + ((num_mode + 1) * j)];
1774576c57e6SKiseok Jo 			sma1307->set.mode_set[i][2 * j + 1]
1775576c57e6SKiseok Jo 			    = data[offset + ((num_mode + 1) * j + i + 1)];
1776576c57e6SKiseok Jo 		}
1777576c57e6SKiseok Jo 	}
1778576c57e6SKiseok Jo 
1779576c57e6SKiseok Jo 	kfree(data);
1780576c57e6SKiseok Jo 	sma1307->set.status = true;
1781576c57e6SKiseok Jo 
1782576c57e6SKiseok Jo }
1783576c57e6SKiseok Jo 
1784576c57e6SKiseok Jo static void sma1307_reset(struct snd_soc_component *component)
1785576c57e6SKiseok Jo {
1786576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
1787576c57e6SKiseok Jo 	unsigned int status = 0;
1788576c57e6SKiseok Jo 
1789576c57e6SKiseok Jo 	regmap_read(sma1307->regmap, SMA1307_FF_DEVICE_INDEX, &status);
1790576c57e6SKiseok Jo 
1791576c57e6SKiseok Jo 	sma1307->rev_num = status & SMA1307_REV_NUM_STATUS;
1792576c57e6SKiseok Jo 	dev_dbg(component->dev, "%s: SMA1307 Revision %d\n",
1793576c57e6SKiseok Jo 			 __func__, sma1307->rev_num);
1794576c57e6SKiseok Jo 	regmap_read(sma1307->regmap, SMA1307_99_OTP_TRM2, &sma1307->otp_trm2);
1795576c57e6SKiseok Jo 	regmap_read(sma1307->regmap, SMA1307_9A_OTP_TRM3, &sma1307->otp_trm3);
1796576c57e6SKiseok Jo 
1797576c57e6SKiseok Jo 	if ((sma1307->otp_trm2 & SMA1307_OTP_STAT_MASK) != SMA1307_OTP_STAT_1)
1798576c57e6SKiseok Jo 		dev_warn(component->dev, "%s: SMA1307 OTP Status Fail\n",
1799576c57e6SKiseok Jo 			 __func__);
1800576c57e6SKiseok Jo 
1801576c57e6SKiseok Jo 	/* Register Initial Value Setting */
1802576c57e6SKiseok Jo 	sma1307_setting_loaded(sma1307, setting_file);
1803576c57e6SKiseok Jo 	if (sma1307->set.status)
1804576c57e6SKiseok Jo 		sma1307_set_binary(component);
1805576c57e6SKiseok Jo 	else
1806576c57e6SKiseok Jo 		sma1307_set_default(component);
1807576c57e6SKiseok Jo 
1808576c57e6SKiseok Jo 	regmap_update_bits(sma1307->regmap,
1809576c57e6SKiseok Jo 				   SMA1307_93_INT_CTRL,
1810576c57e6SKiseok Jo 				   SMA1307_DIS_INT_MASK, SMA1307_HIGH_Z_INT);
1811576c57e6SKiseok Jo 	regmap_write(sma1307->regmap, SMA1307_0A_SPK_VOL, sma1307->init_vol);
1812576c57e6SKiseok Jo }
1813576c57e6SKiseok Jo 
1814576c57e6SKiseok Jo static void sma1307_set_binary(struct snd_soc_component *component)
1815576c57e6SKiseok Jo {
1816576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
1817576c57e6SKiseok Jo 	int i = 0, mode = 0;
1818576c57e6SKiseok Jo 
1819576c57e6SKiseok Jo 	for (i = 0; i < (sma1307->set.def_size); i++) {
1820576c57e6SKiseok Jo 		if (sma1307_writeable_register(sma1307->dev, i)
1821576c57e6SKiseok Jo 		    && ((i < SMA1307_97_OTP_TRM0)
1822576c57e6SKiseok Jo 			|| (i > SMA1307_9A_OTP_TRM3))) {
1823576c57e6SKiseok Jo 			regmap_write(sma1307->regmap, i, sma1307->set.def[i]);
1824576c57e6SKiseok Jo 
1825576c57e6SKiseok Jo 		}
1826576c57e6SKiseok Jo 	}
1827576c57e6SKiseok Jo 	for (i = 0; i < (sma1307->set.mode_size); i++) {
1828576c57e6SKiseok Jo 		if (sma1307_writeable_register(sma1307->dev, i)
1829576c57e6SKiseok Jo 		    && ((i < SMA1307_97_OTP_TRM0)
1830576c57e6SKiseok Jo 			|| (i > SMA1307_9A_OTP_TRM3))) {
1831576c57e6SKiseok Jo 			mode = sma1307->binary_mode;
1832576c57e6SKiseok Jo 			regmap_write(sma1307->regmap,
1833576c57e6SKiseok Jo 					     sma1307->set.mode_set[mode][2 * i],
1834576c57e6SKiseok Jo 					     sma1307->set.mode_set[mode][2 * i +
1835576c57e6SKiseok Jo 									 1]);
1836576c57e6SKiseok Jo 		}
1837576c57e6SKiseok Jo 	}
1838576c57e6SKiseok Jo }
1839576c57e6SKiseok Jo 
1840576c57e6SKiseok Jo static void sma1307_set_default(struct snd_soc_component *component)
1841576c57e6SKiseok Jo {
1842576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 = snd_soc_component_get_drvdata(component);
1843576c57e6SKiseok Jo 	int i = 0;
1844576c57e6SKiseok Jo 
1845576c57e6SKiseok Jo 	for (i = 0; i < (unsigned int)ARRAY_SIZE(sma1307_reg_def); i++)
1846576c57e6SKiseok Jo 		regmap_write(sma1307->regmap,
1847576c57e6SKiseok Jo 				     sma1307_reg_def[i].reg,
1848576c57e6SKiseok Jo 				     sma1307_reg_def[i].def);
1849576c57e6SKiseok Jo 
1850576c57e6SKiseok Jo 	if (!strcmp(sma1307->name, DEVICE_NAME_SMA1307AQ))
1851576c57e6SKiseok Jo 		sma1307->data->init(sma1307->regmap);
1852576c57e6SKiseok Jo }
1853576c57e6SKiseok Jo 
1854576c57e6SKiseok Jo static int sma1307_probe(struct snd_soc_component *component)
1855576c57e6SKiseok Jo {
1856576c57e6SKiseok Jo 	struct snd_soc_dapm_context *dapm =
1857576c57e6SKiseok Jo 	    snd_soc_component_get_dapm(component);
1858576c57e6SKiseok Jo 
1859576c57e6SKiseok Jo 	snd_soc_dapm_sync(dapm);
1860576c57e6SKiseok Jo 
1861576c57e6SKiseok Jo 	sma1307_amp_component = component;
1862576c57e6SKiseok Jo 
1863576c57e6SKiseok Jo 	snd_soc_add_component_controls(component, sma1307_binary_mode_control,
1864576c57e6SKiseok Jo 			ARRAY_SIZE(sma1307_binary_mode_control));
1865576c57e6SKiseok Jo 	sma1307_reset(component);
1866576c57e6SKiseok Jo 
1867576c57e6SKiseok Jo 	return 0;
1868576c57e6SKiseok Jo }
1869576c57e6SKiseok Jo 
1870576c57e6SKiseok Jo static const struct snd_soc_component_driver sma1307_component = {
1871576c57e6SKiseok Jo 	.probe = sma1307_probe,
1872576c57e6SKiseok Jo 	.controls = sma1307_snd_controls,
1873576c57e6SKiseok Jo 	.num_controls = ARRAY_SIZE(sma1307_snd_controls),
1874576c57e6SKiseok Jo 	.dapm_widgets = sma1307_dapm_widgets,
1875576c57e6SKiseok Jo 	.num_dapm_widgets = ARRAY_SIZE(sma1307_dapm_widgets),
1876576c57e6SKiseok Jo 	.dapm_routes = sma1307_audio_map,
1877576c57e6SKiseok Jo 	.num_dapm_routes = ARRAY_SIZE(sma1307_audio_map),
1878576c57e6SKiseok Jo };
1879576c57e6SKiseok Jo 
1880576c57e6SKiseok Jo static const struct regmap_config sma_i2c_regmap = {
1881576c57e6SKiseok Jo 	.reg_bits = 8,
1882576c57e6SKiseok Jo 	.val_bits = 8,
1883576c57e6SKiseok Jo 
1884576c57e6SKiseok Jo 	.max_register = SMA1307_FF_DEVICE_INDEX,
1885576c57e6SKiseok Jo 	.readable_reg = sma1307_readable_register,
1886576c57e6SKiseok Jo 	.writeable_reg = sma1307_writeable_register,
1887576c57e6SKiseok Jo 	.volatile_reg = sma1307_volatile_register,
1888576c57e6SKiseok Jo 
1889576c57e6SKiseok Jo 	.reg_defaults = sma1307_reg_def,
1890576c57e6SKiseok Jo 	.num_reg_defaults = ARRAY_SIZE(sma1307_reg_def),
1891576c57e6SKiseok Jo };
1892576c57e6SKiseok Jo 
1893576c57e6SKiseok Jo static void sma1307aq_init(struct regmap *regmap)
1894576c57e6SKiseok Jo {
1895576c57e6SKiseok Jo 	/* Guidelines for driving 4ohm load */
1896576c57e6SKiseok Jo 	/* Brown Out Protection */
1897576c57e6SKiseok Jo 	regmap_write(regmap, SMA1307_02_BROWN_OUT_PROT1, 0x62);
1898576c57e6SKiseok Jo 	regmap_write(regmap, SMA1307_03_BROWN_OUT_PROT2, 0x5D);
1899576c57e6SKiseok Jo 	regmap_write(regmap, SMA1307_04_BROWN_OUT_PROT3, 0x57);
1900576c57e6SKiseok Jo 	regmap_write(regmap, SMA1307_05_BROWN_OUT_PROT8, 0x54);
1901576c57e6SKiseok Jo 	regmap_write(regmap, SMA1307_06_BROWN_OUT_PROT9, 0x51);
1902576c57e6SKiseok Jo 	regmap_write(regmap,
1903576c57e6SKiseok Jo 			     SMA1307_07_BROWN_OUT_PROT10, 0x4D);
1904576c57e6SKiseok Jo 	regmap_write(regmap,
1905576c57e6SKiseok Jo 			     SMA1307_08_BROWN_OUT_PROT11, 0x4B);
1906576c57e6SKiseok Jo 	regmap_write(regmap, SMA1307_27_BROWN_OUT_PROT4, 0x3C);
1907576c57e6SKiseok Jo 	regmap_write(regmap, SMA1307_28_BROWN_OUT_PROT5, 0x5B);
1908576c57e6SKiseok Jo 	regmap_write(regmap,
1909576c57e6SKiseok Jo 			     SMA1307_29_BROWN_OUT_PROT12, 0x78);
1910576c57e6SKiseok Jo 	regmap_write(regmap,
1911576c57e6SKiseok Jo 			     SMA1307_2A_BROWN_OUT_PROT13, 0x96);
1912576c57e6SKiseok Jo 	regmap_write(regmap,
1913576c57e6SKiseok Jo 			     SMA1307_2B_BROWN_OUT_PROT14, 0xB4);
1914576c57e6SKiseok Jo 	regmap_write(regmap,
1915576c57e6SKiseok Jo 			     SMA1307_2C_BROWN_OUT_PROT15, 0xD3);
1916576c57e6SKiseok Jo 	/* FDPEC Gain */
1917576c57e6SKiseok Jo 	regmap_write(regmap, SMA1307_35_FDPEC_CTRL0, 0x16);
1918576c57e6SKiseok Jo 	/* FLT Vdd */
1919576c57e6SKiseok Jo 	regmap_write(regmap, SMA1307_92_FDPEC_CTRL1, 0xA0);
1920576c57e6SKiseok Jo 	/* Boost Max */
1921576c57e6SKiseok Jo 	regmap_write(regmap, SMA1307_AB_BOOST_CTRL4, 0x0F);
1922576c57e6SKiseok Jo }
1923576c57e6SKiseok Jo 
1924576c57e6SKiseok Jo static const struct sma1307_data sma1307aq_data = {
1925576c57e6SKiseok Jo 	.name = DEVICE_NAME_SMA1307AQ,
1926576c57e6SKiseok Jo 	.init = sma1307aq_init,
1927576c57e6SKiseok Jo };
1928576c57e6SKiseok Jo 
1929576c57e6SKiseok Jo static int sma1307_i2c_probe(struct i2c_client *client)
1930576c57e6SKiseok Jo {
1931576c57e6SKiseok Jo 	struct sma1307_priv *sma1307;
1932576c57e6SKiseok Jo 	const struct sma1307_data *data;
1933576c57e6SKiseok Jo 	int ret = 0;
1934576c57e6SKiseok Jo 	unsigned int device_info;
1935576c57e6SKiseok Jo 
1936576c57e6SKiseok Jo 	sma1307 = devm_kzalloc(&client->dev,
1937576c57e6SKiseok Jo 			       sizeof(*sma1307), GFP_KERNEL);
1938576c57e6SKiseok Jo 	if (!sma1307)
1939576c57e6SKiseok Jo 		return -ENOMEM;
1940576c57e6SKiseok Jo 
1941576c57e6SKiseok Jo 	sma1307->regmap = devm_regmap_init_i2c(client, &sma_i2c_regmap);
1942576c57e6SKiseok Jo 	if (IS_ERR(sma1307->regmap)) {
1943576c57e6SKiseok Jo 		return dev_err_probe(&client->dev, PTR_ERR(sma1307->regmap),
1944576c57e6SKiseok Jo 			"%s: failed to allocate register map\n", __func__);
1945576c57e6SKiseok Jo 	}
1946576c57e6SKiseok Jo 
1947576c57e6SKiseok Jo 	data = device_get_match_data(&client->dev);
1948576c57e6SKiseok Jo 	if (!data)
1949576c57e6SKiseok Jo 		return -ENODEV;
1950576c57e6SKiseok Jo 
1951576c57e6SKiseok Jo 	sma1307->data = data;
1952576c57e6SKiseok Jo 
1953576c57e6SKiseok Jo 	/* set initial value as normal AMP IC status */
1954576c57e6SKiseok Jo 	sma1307->name = client->name;
1955576c57e6SKiseok Jo 	sma1307->format = SND_SOC_DAIFMT_I2S;
1956576c57e6SKiseok Jo 	sma1307->sys_clk_id = SMA1307_PLL_CLKIN_BCLK;
1957576c57e6SKiseok Jo 	sma1307->num_of_pll_matches = ARRAY_SIZE(sma1307_pll_matches);
1958576c57e6SKiseok Jo 
1959576c57e6SKiseok Jo 	sma1307->check_fault_period = CHECK_PERIOD_TIME;
1960576c57e6SKiseok Jo 	sma1307->check_fault_status = true;
1961576c57e6SKiseok Jo 	sma1307->init_vol = 0x32;
1962576c57e6SKiseok Jo 	sma1307->cur_vol = sma1307->init_vol;
1963576c57e6SKiseok Jo 	sma1307->sw_ot1_prot = true;
1964576c57e6SKiseok Jo 
1965576c57e6SKiseok Jo 	mutex_init(&sma1307->default_lock);
1966576c57e6SKiseok Jo 
1967576c57e6SKiseok Jo 	INIT_DELAYED_WORK(&sma1307->check_fault_work,
1968576c57e6SKiseok Jo 			  sma1307_check_fault_worker);
1969576c57e6SKiseok Jo 
1970576c57e6SKiseok Jo 	sma1307->dev = &client->dev;
1971576c57e6SKiseok Jo 	sma1307->kobj = &client->dev.kobj;
1972576c57e6SKiseok Jo 
1973576c57e6SKiseok Jo 	i2c_set_clientdata(client, sma1307);
1974576c57e6SKiseok Jo 
1975576c57e6SKiseok Jo 	sma1307->pll_matches = sma1307_pll_matches;
1976576c57e6SKiseok Jo 
1977576c57e6SKiseok Jo 	regmap_read(sma1307->regmap,
1978576c57e6SKiseok Jo 				  SMA1307_FF_DEVICE_INDEX, &device_info);
1979576c57e6SKiseok Jo 
1980576c57e6SKiseok Jo 	if ((device_info & 0xF8) != SMA1307_DEVICE_ID) {
1981576c57e6SKiseok Jo 		dev_err(&client->dev,
1982576c57e6SKiseok Jo 			"%s: device initialization error (0x%02X)",
1983576c57e6SKiseok Jo 				__func__, device_info);
1984576c57e6SKiseok Jo 		return -ENODEV;
1985576c57e6SKiseok Jo 	}
1986576c57e6SKiseok Jo 	dev_dbg(&client->dev, "%s: chip version 0x%02X\n",
1987576c57e6SKiseok Jo 		 __func__, device_info);
1988576c57e6SKiseok Jo 
1989576c57e6SKiseok Jo 	i2c_set_clientdata(client, sma1307);
1990576c57e6SKiseok Jo 
1991576c57e6SKiseok Jo 	ret = devm_snd_soc_register_component(&client->dev,
1992576c57e6SKiseok Jo 					      &sma1307_component, sma1307_dai,
1993576c57e6SKiseok Jo 					      1);
1994576c57e6SKiseok Jo 
1995576c57e6SKiseok Jo 	if (ret) {
1996576c57e6SKiseok Jo 		dev_err(&client->dev, "%s: failed to register component\n",
1997576c57e6SKiseok Jo 			__func__);
1998576c57e6SKiseok Jo 
1999576c57e6SKiseok Jo 		return ret;
2000576c57e6SKiseok Jo 	}
2001576c57e6SKiseok Jo 
2002576c57e6SKiseok Jo 	return ret;
2003576c57e6SKiseok Jo }
2004576c57e6SKiseok Jo 
2005576c57e6SKiseok Jo static void sma1307_i2c_remove(struct i2c_client *client)
2006576c57e6SKiseok Jo {
2007576c57e6SKiseok Jo 	struct sma1307_priv *sma1307 =
2008576c57e6SKiseok Jo 	    (struct sma1307_priv *)i2c_get_clientdata(client);
2009576c57e6SKiseok Jo 
2010576c57e6SKiseok Jo 	cancel_delayed_work_sync(&sma1307->check_fault_work);
2011576c57e6SKiseok Jo }
2012576c57e6SKiseok Jo 
2013576c57e6SKiseok Jo static const struct i2c_device_id sma1307_i2c_id[] = {
2014576c57e6SKiseok Jo 	{ "sma1307a", 0 },
2015576c57e6SKiseok Jo 	{ "sma1307aq", 0 },
2016576c57e6SKiseok Jo 	{ }
2017576c57e6SKiseok Jo };
2018576c57e6SKiseok Jo 
2019576c57e6SKiseok Jo MODULE_DEVICE_TABLE(i2c, sma1307_i2c_id);
2020576c57e6SKiseok Jo 
2021576c57e6SKiseok Jo static const struct of_device_id sma1307_of_match[] = {
2022576c57e6SKiseok Jo 	{
2023576c57e6SKiseok Jo 		.compatible = "irondevice,sma1307a",
2024576c57e6SKiseok Jo 	},
2025576c57e6SKiseok Jo 	{
2026576c57e6SKiseok Jo 		.compatible = "irondevice,sma1307aq",
2027576c57e6SKiseok Jo 		.data = &sma1307aq_data //AEC-Q100 Qualificated
2028576c57e6SKiseok Jo 	},
2029576c57e6SKiseok Jo 	{ }
2030576c57e6SKiseok Jo };
2031576c57e6SKiseok Jo 
2032576c57e6SKiseok Jo MODULE_DEVICE_TABLE(of, sma1307_of_match);
2033576c57e6SKiseok Jo 
2034576c57e6SKiseok Jo static struct i2c_driver sma1307_i2c_driver = {
2035576c57e6SKiseok Jo 	.driver = {
2036576c57e6SKiseok Jo 		   .name = "sma1307",
2037576c57e6SKiseok Jo 		   .of_match_table = sma1307_of_match,
2038576c57e6SKiseok Jo 		    },
2039576c57e6SKiseok Jo 	.probe = sma1307_i2c_probe,
2040576c57e6SKiseok Jo 	.remove = sma1307_i2c_remove,
2041576c57e6SKiseok Jo 	.id_table = sma1307_i2c_id,
2042576c57e6SKiseok Jo };
2043576c57e6SKiseok Jo 
2044576c57e6SKiseok Jo module_i2c_driver(sma1307_i2c_driver);
2045576c57e6SKiseok Jo 
2046576c57e6SKiseok Jo MODULE_DESCRIPTION("ALSA SoC SMA1307 driver");
2047576c57e6SKiseok Jo MODULE_AUTHOR("Gyuhwa Park, <gyuhwa.park@irondevice.com>");
2048576c57e6SKiseok Jo MODULE_AUTHOR("KS Jo, <kiseok.jo@irondevice.com>");
2049576c57e6SKiseok Jo MODULE_LICENSE("GPL");
2050