Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * SSM2518 amplifier audio driver
  4 *
  5 * Copyright 2013 Analog Devices Inc.
  6 *  Author: Lars-Peter Clausen <lars@metafoo.de>
 
 
  7 */
  8
  9#include <linux/err.h>
 10#include <linux/module.h>
 11#include <linux/init.h>
 12#include <linux/i2c.h>
 13#include <linux/regmap.h>
 14#include <linux/slab.h>
 15#include <linux/gpio/consumer.h>
 
 
 16#include <sound/core.h>
 17#include <sound/pcm.h>
 18#include <sound/pcm_params.h>
 19#include <sound/soc.h>
 20#include <sound/initval.h>
 21#include <sound/tlv.h>
 22
 23#include "ssm2518.h"
 24
 25#define SSM2518_REG_POWER1		0x00
 26#define SSM2518_REG_CLOCK		0x01
 27#define SSM2518_REG_SAI_CTRL1		0x02
 28#define SSM2518_REG_SAI_CTRL2		0x03
 29#define SSM2518_REG_CHAN_MAP		0x04
 30#define SSM2518_REG_LEFT_VOL		0x05
 31#define SSM2518_REG_RIGHT_VOL		0x06
 32#define SSM2518_REG_MUTE_CTRL		0x07
 33#define SSM2518_REG_FAULT_CTRL		0x08
 34#define SSM2518_REG_POWER2		0x09
 35#define SSM2518_REG_DRC_1		0x0a
 36#define SSM2518_REG_DRC_2		0x0b
 37#define SSM2518_REG_DRC_3		0x0c
 38#define SSM2518_REG_DRC_4		0x0d
 39#define SSM2518_REG_DRC_5		0x0e
 40#define SSM2518_REG_DRC_6		0x0f
 41#define SSM2518_REG_DRC_7		0x10
 42#define SSM2518_REG_DRC_8		0x11
 43#define SSM2518_REG_DRC_9		0x12
 44
 45#define SSM2518_POWER1_RESET			BIT(7)
 46#define SSM2518_POWER1_NO_BCLK			BIT(5)
 47#define SSM2518_POWER1_MCS_MASK			(0xf << 1)
 48#define SSM2518_POWER1_MCS_64FS			(0x0 << 1)
 49#define SSM2518_POWER1_MCS_128FS		(0x1 << 1)
 50#define SSM2518_POWER1_MCS_256FS		(0x2 << 1)
 51#define SSM2518_POWER1_MCS_384FS		(0x3 << 1)
 52#define SSM2518_POWER1_MCS_512FS		(0x4 << 1)
 53#define SSM2518_POWER1_MCS_768FS		(0x5 << 1)
 54#define SSM2518_POWER1_MCS_100FS		(0x6 << 1)
 55#define SSM2518_POWER1_MCS_200FS		(0x7 << 1)
 56#define SSM2518_POWER1_MCS_400FS		(0x8 << 1)
 57#define SSM2518_POWER1_SPWDN			BIT(0)
 58
 59#define SSM2518_CLOCK_ASR			BIT(0)
 60
 61#define SSM2518_SAI_CTRL1_FMT_MASK		(0x3 << 5)
 62#define SSM2518_SAI_CTRL1_FMT_I2S		(0x0 << 5)
 63#define SSM2518_SAI_CTRL1_FMT_LJ		(0x1 << 5)
 64#define SSM2518_SAI_CTRL1_FMT_RJ_24BIT		(0x2 << 5)
 65#define SSM2518_SAI_CTRL1_FMT_RJ_16BIT		(0x3 << 5)
 66
 67#define SSM2518_SAI_CTRL1_SAI_MASK		(0x7 << 2)
 68#define SSM2518_SAI_CTRL1_SAI_I2S		(0x0 << 2)
 69#define SSM2518_SAI_CTRL1_SAI_TDM_2		(0x1 << 2)
 70#define SSM2518_SAI_CTRL1_SAI_TDM_4		(0x2 << 2)
 71#define SSM2518_SAI_CTRL1_SAI_TDM_8		(0x3 << 2)
 72#define SSM2518_SAI_CTRL1_SAI_TDM_16		(0x4 << 2)
 73#define SSM2518_SAI_CTRL1_SAI_MONO		(0x5 << 2)
 74
 75#define SSM2518_SAI_CTRL1_FS_MASK		(0x3)
 76#define SSM2518_SAI_CTRL1_FS_8000_12000		(0x0)
 77#define SSM2518_SAI_CTRL1_FS_16000_24000	(0x1)
 78#define SSM2518_SAI_CTRL1_FS_32000_48000	(0x2)
 79#define SSM2518_SAI_CTRL1_FS_64000_96000	(0x3)
 80
 81#define SSM2518_SAI_CTRL2_BCLK_INTERAL		BIT(7)
 82#define SSM2518_SAI_CTRL2_LRCLK_PULSE		BIT(6)
 83#define SSM2518_SAI_CTRL2_LRCLK_INVERT		BIT(5)
 84#define SSM2518_SAI_CTRL2_MSB			BIT(4)
 85#define SSM2518_SAI_CTRL2_SLOT_WIDTH_MASK	(0x3 << 2)
 86#define SSM2518_SAI_CTRL2_SLOT_WIDTH_32		(0x0 << 2)
 87#define SSM2518_SAI_CTRL2_SLOT_WIDTH_24		(0x1 << 2)
 88#define SSM2518_SAI_CTRL2_SLOT_WIDTH_16		(0x2 << 2)
 89#define SSM2518_SAI_CTRL2_BCLK_INVERT		BIT(1)
 90
 91#define SSM2518_CHAN_MAP_RIGHT_SLOT_OFFSET	4
 92#define SSM2518_CHAN_MAP_RIGHT_SLOT_MASK	0xf0
 93#define SSM2518_CHAN_MAP_LEFT_SLOT_OFFSET	0
 94#define SSM2518_CHAN_MAP_LEFT_SLOT_MASK		0x0f
 95
 96#define SSM2518_MUTE_CTRL_ANA_GAIN		BIT(5)
 97#define SSM2518_MUTE_CTRL_MUTE_MASTER		BIT(0)
 98
 99#define SSM2518_POWER2_APWDN			BIT(0)
100
101#define SSM2518_DAC_MUTE			BIT(6)
102#define SSM2518_DAC_FS_MASK			0x07
103#define SSM2518_DAC_FS_8000			0x00
104#define SSM2518_DAC_FS_16000			0x01
105#define SSM2518_DAC_FS_32000			0x02
106#define SSM2518_DAC_FS_64000			0x03
107#define SSM2518_DAC_FS_128000			0x04
108
109struct ssm2518 {
110	struct regmap *regmap;
111	bool right_j;
112
113	unsigned int sysclk;
114	const struct snd_pcm_hw_constraint_list *constraints;
115
116	struct gpio_desc *enable_gpio;
117};
118
119static const struct reg_default ssm2518_reg_defaults[] = {
120	{ 0x00, 0x05 },
121	{ 0x01, 0x00 },
122	{ 0x02, 0x02 },
123	{ 0x03, 0x00 },
124	{ 0x04, 0x10 },
125	{ 0x05, 0x40 },
126	{ 0x06, 0x40 },
127	{ 0x07, 0x81 },
128	{ 0x08, 0x0c },
129	{ 0x09, 0x99 },
130	{ 0x0a, 0x7c },
131	{ 0x0b, 0x5b },
132	{ 0x0c, 0x57 },
133	{ 0x0d, 0x89 },
134	{ 0x0e, 0x8c },
135	{ 0x0f, 0x77 },
136	{ 0x10, 0x26 },
137	{ 0x11, 0x1c },
138	{ 0x12, 0x97 },
139};
140
141static const DECLARE_TLV_DB_MINMAX_MUTE(ssm2518_vol_tlv, -7125, 2400);
142static const DECLARE_TLV_DB_SCALE(ssm2518_compressor_tlv, -3400, 200, 0);
143static const DECLARE_TLV_DB_SCALE(ssm2518_expander_tlv, -8100, 300, 0);
144static const DECLARE_TLV_DB_SCALE(ssm2518_noise_gate_tlv, -9600, 300, 0);
145static const DECLARE_TLV_DB_SCALE(ssm2518_post_drc_tlv, -2400, 300, 0);
146
147static const DECLARE_TLV_DB_RANGE(ssm2518_limiter_tlv,
148	0, 7, TLV_DB_SCALE_ITEM(-2200, 200, 0),
149	7, 15, TLV_DB_SCALE_ITEM(-800, 100, 0),
150);
151
152static const char * const ssm2518_drc_peak_detector_attack_time_text[] = {
153	"0 ms", "0.1 ms", "0.19 ms", "0.37 ms", "0.75 ms", "1.5 ms", "3 ms",
154	"6 ms", "12 ms", "24 ms", "48 ms", "96 ms", "192 ms", "384 ms",
155	"768 ms", "1536 ms",
156};
157
158static const char * const ssm2518_drc_peak_detector_release_time_text[] = {
159	"0 ms", "1.5 ms", "3 ms", "6 ms", "12 ms", "24 ms", "48 ms", "96 ms",
160	"192 ms", "384 ms", "768 ms", "1536 ms", "3072 ms", "6144 ms",
161	"12288 ms", "24576 ms"
162};
163
164static const char * const ssm2518_drc_hold_time_text[] = {
165	"0 ms", "0.67 ms", "1.33 ms", "2.67 ms", "5.33 ms", "10.66 ms",
166	"21.32 ms", "42.64 ms", "85.28 ms", "170.56 ms", "341.12 ms",
167	"682.24 ms", "1364 ms",
168};
169
170static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum,
171	SSM2518_REG_DRC_2, 4, ssm2518_drc_peak_detector_attack_time_text);
172static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum,
173	SSM2518_REG_DRC_2, 0, ssm2518_drc_peak_detector_release_time_text);
174static SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum,
175	SSM2518_REG_DRC_6, 4, ssm2518_drc_peak_detector_attack_time_text);
176static SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum,
177	SSM2518_REG_DRC_6, 0, ssm2518_drc_peak_detector_release_time_text);
178static SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum,
179	SSM2518_REG_DRC_7, 4, ssm2518_drc_hold_time_text);
180static SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum,
181	SSM2518_REG_DRC_7, 0, ssm2518_drc_hold_time_text);
182static SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum,
183	SSM2518_REG_DRC_9, 0, ssm2518_drc_peak_detector_release_time_text);
184
185static const struct snd_kcontrol_new ssm2518_snd_controls[] = {
186	SOC_SINGLE("Playback De-emphasis Switch", SSM2518_REG_MUTE_CTRL,
187			4, 1, 0),
188	SOC_DOUBLE_R_TLV("Master Playback Volume", SSM2518_REG_LEFT_VOL,
189			SSM2518_REG_RIGHT_VOL, 0, 0xff, 1, ssm2518_vol_tlv),
190	SOC_DOUBLE("Master Playback Switch", SSM2518_REG_MUTE_CTRL, 2, 1, 1, 1),
191
192	SOC_SINGLE("Amp Low Power Mode Switch", SSM2518_REG_POWER2, 4, 1, 0),
193	SOC_SINGLE("DAC Low Power Mode Switch", SSM2518_REG_POWER2, 3, 1, 0),
194
195	SOC_SINGLE("DRC Limiter Switch", SSM2518_REG_DRC_1, 5, 1, 0),
196	SOC_SINGLE("DRC Compressor Switch", SSM2518_REG_DRC_1, 4, 1, 0),
197	SOC_SINGLE("DRC Expander Switch", SSM2518_REG_DRC_1, 3, 1, 0),
198	SOC_SINGLE("DRC Noise Gate Switch", SSM2518_REG_DRC_1, 2, 1, 0),
199	SOC_DOUBLE("DRC Switch", SSM2518_REG_DRC_1, 0, 1, 1, 0),
200
201	SOC_SINGLE_TLV("DRC Limiter Threshold Volume",
202			SSM2518_REG_DRC_3, 4, 15, 1, ssm2518_limiter_tlv),
203	SOC_SINGLE_TLV("DRC Compressor Lower Threshold Volume",
204			SSM2518_REG_DRC_3, 0, 15, 1, ssm2518_compressor_tlv),
205	SOC_SINGLE_TLV("DRC Expander Upper Threshold Volume", SSM2518_REG_DRC_4,
206			4, 15, 1, ssm2518_expander_tlv),
207	SOC_SINGLE_TLV("DRC Noise Gate Threshold Volume",
208			SSM2518_REG_DRC_4, 0, 15, 1, ssm2518_noise_gate_tlv),
209	SOC_SINGLE_TLV("DRC Upper Output Threshold Volume",
210			SSM2518_REG_DRC_5, 4, 15, 1, ssm2518_limiter_tlv),
211	SOC_SINGLE_TLV("DRC Lower Output Threshold Volume",
212			SSM2518_REG_DRC_5, 0, 15, 1, ssm2518_noise_gate_tlv),
213	SOC_SINGLE_TLV("DRC Post Volume", SSM2518_REG_DRC_8,
214			2, 15, 1, ssm2518_post_drc_tlv),
215
216	SOC_ENUM("DRC Peak Detector Attack Time",
217		ssm2518_drc_peak_detector_attack_time_enum),
218	SOC_ENUM("DRC Peak Detector Release Time",
219		ssm2518_drc_peak_detector_release_time_enum),
220	SOC_ENUM("DRC Attack Time", ssm2518_drc_attack_time_enum),
221	SOC_ENUM("DRC Decay Time", ssm2518_drc_decay_time_enum),
222	SOC_ENUM("DRC Hold Time", ssm2518_drc_hold_time_enum),
223	SOC_ENUM("DRC Noise Gate Hold Time",
224		ssm2518_drc_noise_gate_hold_time_enum),
225	SOC_ENUM("DRC RMS Averaging Time", ssm2518_drc_rms_averaging_time_enum),
226};
227
228static const struct snd_soc_dapm_widget ssm2518_dapm_widgets[] = {
229	SND_SOC_DAPM_DAC("DACL", "HiFi Playback", SSM2518_REG_POWER2, 1, 1),
230	SND_SOC_DAPM_DAC("DACR", "HiFi Playback", SSM2518_REG_POWER2, 2, 1),
231
232	SND_SOC_DAPM_OUTPUT("OUTL"),
233	SND_SOC_DAPM_OUTPUT("OUTR"),
234};
235
236static const struct snd_soc_dapm_route ssm2518_routes[] = {
237	{ "OUTL", NULL, "DACL" },
238	{ "OUTR", NULL, "DACR" },
239};
240
241struct ssm2518_mcs_lut {
242	unsigned int rate;
243	const unsigned int *sysclks;
244};
245
246static const unsigned int ssm2518_sysclks_2048000[] = {
247	2048000, 4096000, 8192000, 12288000, 16384000, 24576000,
248	3200000, 6400000, 12800000, 0
249};
250
251static const unsigned int ssm2518_sysclks_2822000[] = {
252	2822000, 5644800, 11289600, 16934400, 22579200, 33868800,
253	4410000, 8820000, 17640000, 0
254};
255
256static const unsigned int ssm2518_sysclks_3072000[] = {
257	3072000, 6144000, 12288000, 16384000, 24576000, 38864000,
258	4800000, 9600000, 19200000, 0
259};
260
261static const struct ssm2518_mcs_lut ssm2518_mcs_lut[] = {
262	{ 8000,  ssm2518_sysclks_2048000, },
263	{ 11025, ssm2518_sysclks_2822000, },
264	{ 12000, ssm2518_sysclks_3072000, },
265	{ 16000, ssm2518_sysclks_2048000, },
266	{ 24000, ssm2518_sysclks_3072000, },
267	{ 22050, ssm2518_sysclks_2822000, },
268	{ 32000, ssm2518_sysclks_2048000, },
269	{ 44100, ssm2518_sysclks_2822000, },
270	{ 48000, ssm2518_sysclks_3072000, },
271	{ 96000, ssm2518_sysclks_3072000, },
272};
273
274static const unsigned int ssm2518_rates_2048000[] = {
275	8000, 16000, 32000,
276};
277
278static const struct snd_pcm_hw_constraint_list ssm2518_constraints_2048000 = {
279	.list = ssm2518_rates_2048000,
280	.count = ARRAY_SIZE(ssm2518_rates_2048000),
281};
282
283static const unsigned int ssm2518_rates_2822000[] = {
284	11025, 22050, 44100,
285};
286
287static const struct snd_pcm_hw_constraint_list ssm2518_constraints_2822000 = {
288	.list = ssm2518_rates_2822000,
289	.count = ARRAY_SIZE(ssm2518_rates_2822000),
290};
291
292static const unsigned int ssm2518_rates_3072000[] = {
293	12000, 24000, 48000, 96000,
294};
295
296static const struct snd_pcm_hw_constraint_list ssm2518_constraints_3072000 = {
297	.list = ssm2518_rates_3072000,
298	.count = ARRAY_SIZE(ssm2518_rates_3072000),
299};
300
301static const unsigned int ssm2518_rates_12288000[] = {
302	8000, 12000, 16000, 24000, 32000, 48000, 96000,
303};
304
305static const struct snd_pcm_hw_constraint_list ssm2518_constraints_12288000 = {
306	.list = ssm2518_rates_12288000,
307	.count = ARRAY_SIZE(ssm2518_rates_12288000),
308};
309
310static int ssm2518_lookup_mcs(struct ssm2518 *ssm2518,
311	unsigned int rate)
312{
313	const unsigned int *sysclks = NULL;
314	int i;
315
316	for (i = 0; i < ARRAY_SIZE(ssm2518_mcs_lut); i++) {
317		if (ssm2518_mcs_lut[i].rate == rate) {
318			sysclks = ssm2518_mcs_lut[i].sysclks;
319			break;
320		}
321	}
322
323	if (!sysclks)
324		return -EINVAL;
325
326	for (i = 0; sysclks[i]; i++) {
327		if (sysclks[i] == ssm2518->sysclk)
328			return i;
329	}
330
331	return -EINVAL;
332}
333
334static int ssm2518_hw_params(struct snd_pcm_substream *substream,
335	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
336{
337	struct snd_soc_component *component = dai->component;
338	struct ssm2518 *ssm2518 = snd_soc_component_get_drvdata(component);
339	unsigned int rate = params_rate(params);
340	unsigned int ctrl1, ctrl1_mask;
341	int mcs;
342	int ret;
343
344	mcs = ssm2518_lookup_mcs(ssm2518, rate);
345	if (mcs < 0)
346		return mcs;
347
348	ctrl1_mask = SSM2518_SAI_CTRL1_FS_MASK;
349
350	if (rate >= 8000 && rate <= 12000)
351		ctrl1 = SSM2518_SAI_CTRL1_FS_8000_12000;
352	else if (rate >= 16000 && rate <= 24000)
353		ctrl1 = SSM2518_SAI_CTRL1_FS_16000_24000;
354	else if (rate >= 32000 && rate <= 48000)
355		ctrl1 = SSM2518_SAI_CTRL1_FS_32000_48000;
356	else if (rate >= 64000 && rate <= 96000)
357		ctrl1 = SSM2518_SAI_CTRL1_FS_64000_96000;
358	else
359		return -EINVAL;
360
361	if (ssm2518->right_j) {
362		switch (params_width(params)) {
363		case 16:
364			ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_16BIT;
365			break;
366		case 24:
367			ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_24BIT;
368			break;
369		default:
370			return -EINVAL;
371		}
372		ctrl1_mask |= SSM2518_SAI_CTRL1_FMT_MASK;
373	}
374
375	/* Disable auto samplerate detection */
376	ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_CLOCK,
377				SSM2518_CLOCK_ASR, SSM2518_CLOCK_ASR);
378	if (ret < 0)
379		return ret;
380
381	ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_SAI_CTRL1,
382				ctrl1_mask, ctrl1);
383	if (ret < 0)
384		return ret;
385
386	return regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1,
387				SSM2518_POWER1_MCS_MASK, mcs << 1);
388}
389
390static int ssm2518_mute(struct snd_soc_dai *dai, int mute, int direction)
391{
392	struct ssm2518 *ssm2518 = snd_soc_component_get_drvdata(dai->component);
393	unsigned int val;
394
395	if (mute)
396		val = SSM2518_MUTE_CTRL_MUTE_MASTER;
397	else
398		val = 0;
399
400	return regmap_update_bits(ssm2518->regmap, SSM2518_REG_MUTE_CTRL,
401			SSM2518_MUTE_CTRL_MUTE_MASTER, val);
402}
403
404static int ssm2518_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
405{
406	struct ssm2518 *ssm2518 = snd_soc_component_get_drvdata(dai->component);
407	unsigned int ctrl1 = 0, ctrl2 = 0;
408	bool invert_fclk;
409	int ret;
410
411	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
412	case SND_SOC_DAIFMT_CBC_CFC:
413		break;
414	default:
415		return -EINVAL;
416	}
417
418	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
419	case SND_SOC_DAIFMT_NB_NF:
420		invert_fclk = false;
421		break;
422	case SND_SOC_DAIFMT_IB_NF:
423		ctrl2 |= SSM2518_SAI_CTRL2_BCLK_INVERT;
424		invert_fclk = false;
425		break;
426	case SND_SOC_DAIFMT_NB_IF:
427		invert_fclk = true;
428		break;
429	case SND_SOC_DAIFMT_IB_IF:
430		ctrl2 |= SSM2518_SAI_CTRL2_BCLK_INVERT;
431		invert_fclk = true;
432		break;
433	default:
434		return -EINVAL;
435	}
436
437	ssm2518->right_j = false;
438	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
439	case SND_SOC_DAIFMT_I2S:
440		ctrl1 |= SSM2518_SAI_CTRL1_FMT_I2S;
441		break;
442	case SND_SOC_DAIFMT_LEFT_J:
443		ctrl1 |= SSM2518_SAI_CTRL1_FMT_LJ;
444		invert_fclk = !invert_fclk;
445		break;
446	case SND_SOC_DAIFMT_RIGHT_J:
447		ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_24BIT;
448		ssm2518->right_j = true;
449		invert_fclk = !invert_fclk;
450		break;
451	case SND_SOC_DAIFMT_DSP_A:
452		ctrl2 |= SSM2518_SAI_CTRL2_LRCLK_PULSE;
453		ctrl1 |= SSM2518_SAI_CTRL1_FMT_I2S;
454		invert_fclk = false;
455		break;
456	case SND_SOC_DAIFMT_DSP_B:
457		ctrl2 |= SSM2518_SAI_CTRL2_LRCLK_PULSE;
458		ctrl1 |= SSM2518_SAI_CTRL1_FMT_LJ;
459		invert_fclk = false;
460		break;
461	default:
462		return -EINVAL;
463	}
464
465	if (invert_fclk)
466		ctrl2 |= SSM2518_SAI_CTRL2_LRCLK_INVERT;
467
468	ret = regmap_write(ssm2518->regmap, SSM2518_REG_SAI_CTRL1, ctrl1);
469	if (ret)
470		return ret;
471
472	return regmap_write(ssm2518->regmap, SSM2518_REG_SAI_CTRL2, ctrl2);
473}
474
475static int ssm2518_set_power(struct ssm2518 *ssm2518, bool enable)
476{
477	int ret = 0;
478
479	if (!enable) {
480		ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1,
481			SSM2518_POWER1_SPWDN, SSM2518_POWER1_SPWDN);
482		regcache_mark_dirty(ssm2518->regmap);
483	}
484
485	if (ssm2518->enable_gpio)
486		gpiod_set_value_cansleep(ssm2518->enable_gpio, enable);
487
488	regcache_cache_only(ssm2518->regmap, !enable);
489
490	if (enable) {
491		ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1,
492			SSM2518_POWER1_SPWDN | SSM2518_POWER1_RESET, 0x00);
493		regcache_sync(ssm2518->regmap);
494	}
495
496	return ret;
497}
498
499static int ssm2518_set_bias_level(struct snd_soc_component *component,
500	enum snd_soc_bias_level level)
501{
502	struct ssm2518 *ssm2518 = snd_soc_component_get_drvdata(component);
503	int ret = 0;
504
505	switch (level) {
506	case SND_SOC_BIAS_ON:
507		break;
508	case SND_SOC_BIAS_PREPARE:
509		break;
510	case SND_SOC_BIAS_STANDBY:
511		if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
512			ret = ssm2518_set_power(ssm2518, true);
513		break;
514	case SND_SOC_BIAS_OFF:
515		ret = ssm2518_set_power(ssm2518, false);
516		break;
517	}
518
519	return ret;
520}
521
522static int ssm2518_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
523	unsigned int rx_mask, int slots, int width)
524{
525	struct ssm2518 *ssm2518 = snd_soc_component_get_drvdata(dai->component);
526	unsigned int ctrl1, ctrl2;
527	int left_slot, right_slot;
528	int ret;
529
530	if (slots == 0)
531		return regmap_update_bits(ssm2518->regmap,
532			SSM2518_REG_SAI_CTRL1, SSM2518_SAI_CTRL1_SAI_MASK,
533			SSM2518_SAI_CTRL1_SAI_I2S);
534
535	if (tx_mask == 0 || rx_mask != 0)
536		return -EINVAL;
537
538	if (slots == 1) {
539		if (tx_mask != 1)
540			return -EINVAL;
541		left_slot = 0;
542		right_slot = 0;
543	} else {
544		/* We assume the left channel < right channel */
545		left_slot = __ffs(tx_mask);
546		tx_mask &= ~(1 << left_slot);
547		if (tx_mask == 0) {
548			right_slot = left_slot;
549		} else {
550			right_slot = __ffs(tx_mask);
551			tx_mask &= ~(1 << right_slot);
552		}
553	}
554
555	if (tx_mask != 0 || left_slot >= slots || right_slot >= slots)
556		return -EINVAL;
557
558	switch (width) {
559	case 16:
560		ctrl2 = SSM2518_SAI_CTRL2_SLOT_WIDTH_16;
561		break;
562	case 24:
563		ctrl2 = SSM2518_SAI_CTRL2_SLOT_WIDTH_24;
564		break;
565	case 32:
566		ctrl2 = SSM2518_SAI_CTRL2_SLOT_WIDTH_32;
567		break;
568	default:
569		return -EINVAL;
570	}
571
572	switch (slots) {
573	case 1:
574		ctrl1 = SSM2518_SAI_CTRL1_SAI_MONO;
575		break;
576	case 2:
577		ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_2;
578		break;
579	case 4:
580		ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_4;
581		break;
582	case 8:
583		ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_8;
584		break;
585	case 16:
586		ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_16;
587		break;
588	default:
589		return -EINVAL;
590	}
591
592	ret = regmap_write(ssm2518->regmap, SSM2518_REG_CHAN_MAP,
593		(left_slot << SSM2518_CHAN_MAP_LEFT_SLOT_OFFSET) |
594		(right_slot << SSM2518_CHAN_MAP_RIGHT_SLOT_OFFSET));
595	if (ret)
596		return ret;
597
598	ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_SAI_CTRL1,
599		SSM2518_SAI_CTRL1_SAI_MASK, ctrl1);
600	if (ret)
601		return ret;
602
603	return regmap_update_bits(ssm2518->regmap, SSM2518_REG_SAI_CTRL2,
604		SSM2518_SAI_CTRL2_SLOT_WIDTH_MASK, ctrl2);
605}
606
607static int ssm2518_startup(struct snd_pcm_substream *substream,
608	struct snd_soc_dai *dai)
609{
610	struct ssm2518 *ssm2518 = snd_soc_component_get_drvdata(dai->component);
611
612	if (ssm2518->constraints)
613		snd_pcm_hw_constraint_list(substream->runtime, 0,
614				SNDRV_PCM_HW_PARAM_RATE, ssm2518->constraints);
615
616	return 0;
617}
618
619#define SSM2518_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
620			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32)
621
622static const struct snd_soc_dai_ops ssm2518_dai_ops = {
623	.startup = ssm2518_startup,
624	.hw_params	= ssm2518_hw_params,
625	.mute_stream	= ssm2518_mute,
626	.set_fmt	= ssm2518_set_dai_fmt,
627	.set_tdm_slot	= ssm2518_set_tdm_slot,
628	.no_capture_mute = 1,
629};
630
631static struct snd_soc_dai_driver ssm2518_dai = {
632	.name = "ssm2518-hifi",
633	.playback = {
634		.stream_name = "Playback",
635		.channels_min = 2,
636		.channels_max = 2,
637		.rates = SNDRV_PCM_RATE_8000_96000,
638		.formats = SSM2518_FORMATS,
639	},
640	.ops = &ssm2518_dai_ops,
641};
642
643static int ssm2518_set_sysclk(struct snd_soc_component *component, int clk_id,
644	int source, unsigned int freq, int dir)
645{
646	struct ssm2518 *ssm2518 = snd_soc_component_get_drvdata(component);
647	unsigned int val;
648
649	if (clk_id != SSM2518_SYSCLK)
650		return -EINVAL;
651
652	switch (source) {
653	case SSM2518_SYSCLK_SRC_MCLK:
654		val = 0;
655		break;
656	case SSM2518_SYSCLK_SRC_BCLK:
657		/* In this case the bitclock is used as the system clock, and
658		 * the bitclock signal needs to be connected to the MCLK pin and
659		 * the BCLK pin is left unconnected */
660		val = SSM2518_POWER1_NO_BCLK;
661		break;
662	default:
663		return -EINVAL;
664	}
665
666	switch (freq) {
667	case 0:
668		ssm2518->constraints = NULL;
669		break;
670	case 2048000:
671	case 4096000:
672	case 8192000:
673	case 3200000:
674	case 6400000:
675	case 12800000:
676		ssm2518->constraints = &ssm2518_constraints_2048000;
677		break;
678	case 2822000:
679	case 5644800:
680	case 11289600:
681	case 16934400:
682	case 22579200:
683	case 33868800:
684	case 4410000:
685	case 8820000:
686	case 17640000:
687		ssm2518->constraints = &ssm2518_constraints_2822000;
688		break;
689	case 3072000:
690	case 6144000:
691	case 38864000:
692	case 4800000:
693	case 9600000:
694	case 19200000:
695		ssm2518->constraints = &ssm2518_constraints_3072000;
696		break;
697	case 12288000:
698	case 16384000:
699	case 24576000:
700		ssm2518->constraints = &ssm2518_constraints_12288000;
701		break;
702	default:
703		return -EINVAL;
704	}
705
706	ssm2518->sysclk = freq;
707
708	return regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1,
709			SSM2518_POWER1_NO_BCLK, val);
710}
711
712static const struct snd_soc_component_driver ssm2518_component_driver = {
713	.set_bias_level		= ssm2518_set_bias_level,
714	.set_sysclk		= ssm2518_set_sysclk,
715	.controls		= ssm2518_snd_controls,
716	.num_controls		= ARRAY_SIZE(ssm2518_snd_controls),
717	.dapm_widgets		= ssm2518_dapm_widgets,
718	.num_dapm_widgets	= ARRAY_SIZE(ssm2518_dapm_widgets),
719	.dapm_routes		= ssm2518_routes,
720	.num_dapm_routes	= ARRAY_SIZE(ssm2518_routes),
721	.use_pmdown_time	= 1,
722	.endianness		= 1,
 
 
723};
724
725static const struct regmap_config ssm2518_regmap_config = {
726	.val_bits = 8,
727	.reg_bits = 8,
728
729	.max_register = SSM2518_REG_DRC_9,
730
731	.cache_type = REGCACHE_RBTREE,
732	.reg_defaults = ssm2518_reg_defaults,
733	.num_reg_defaults = ARRAY_SIZE(ssm2518_reg_defaults),
734};
735
736static int ssm2518_i2c_probe(struct i2c_client *i2c)
 
737{
 
738	struct ssm2518 *ssm2518;
739	int ret;
740
741	ssm2518 = devm_kzalloc(&i2c->dev, sizeof(*ssm2518), GFP_KERNEL);
742	if (ssm2518 == NULL)
743		return -ENOMEM;
744
745	/* Start with enabling the chip */
746	ssm2518->enable_gpio = devm_gpiod_get_optional(&i2c->dev, NULL,
747						       GPIOD_OUT_HIGH);
748	ret = PTR_ERR_OR_ZERO(ssm2518->enable_gpio);
749	if (ret)
750		return ret;
 
 
 
751
752	gpiod_set_consumer_name(ssm2518->enable_gpio, "SSM2518 nSD");
 
 
 
 
 
753
754	i2c_set_clientdata(i2c, ssm2518);
755
756	ssm2518->regmap = devm_regmap_init_i2c(i2c, &ssm2518_regmap_config);
757	if (IS_ERR(ssm2518->regmap))
758		return PTR_ERR(ssm2518->regmap);
759
760	/*
761	 * The reset bit is obviously volatile, but we need to be able to cache
762	 * the other bits in the register, so we can't just mark the whole
763	 * register as volatile. Since this is the only place where we'll ever
764	 * touch the reset bit just bypass the cache for this operation.
765	 */
766	regcache_cache_bypass(ssm2518->regmap, true);
767	ret = regmap_write(ssm2518->regmap, SSM2518_REG_POWER1,
768			SSM2518_POWER1_RESET);
769	regcache_cache_bypass(ssm2518->regmap, false);
770	if (ret)
771		return ret;
772
773	ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER2,
774				SSM2518_POWER2_APWDN, 0x00);
775	if (ret)
776		return ret;
777
778	ret = ssm2518_set_power(ssm2518, false);
779	if (ret)
780		return ret;
781
782	return devm_snd_soc_register_component(&i2c->dev,
783			&ssm2518_component_driver,
784			&ssm2518_dai, 1);
785}
786
 
 
 
 
 
 
787#ifdef CONFIG_OF
788static const struct of_device_id ssm2518_dt_ids[] = {
789	{ .compatible = "adi,ssm2518", },
790	{ }
791};
792MODULE_DEVICE_TABLE(of, ssm2518_dt_ids);
793#endif
794
795static const struct i2c_device_id ssm2518_i2c_ids[] = {
796	{ "ssm2518" },
797	{ }
798};
799MODULE_DEVICE_TABLE(i2c, ssm2518_i2c_ids);
800
801static struct i2c_driver ssm2518_driver = {
802	.driver = {
803		.name = "ssm2518",
804		.of_match_table = of_match_ptr(ssm2518_dt_ids),
805	},
806	.probe = ssm2518_i2c_probe,
 
807	.id_table = ssm2518_i2c_ids,
808};
809module_i2c_driver(ssm2518_driver);
810
811MODULE_DESCRIPTION("ASoC SSM2518 driver");
812MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
813MODULE_LICENSE("GPL");
v4.10.11
 
  1/*
  2 * SSM2518 amplifier audio driver
  3 *
  4 * Copyright 2013 Analog Devices Inc.
  5 *  Author: Lars-Peter Clausen <lars@metafoo.de>
  6 *
  7 * Licensed under the GPL-2.
  8 */
  9
 
 10#include <linux/module.h>
 11#include <linux/init.h>
 12#include <linux/i2c.h>
 13#include <linux/regmap.h>
 14#include <linux/slab.h>
 15#include <linux/gpio.h>
 16#include <linux/of_gpio.h>
 17#include <linux/platform_data/ssm2518.h>
 18#include <sound/core.h>
 19#include <sound/pcm.h>
 20#include <sound/pcm_params.h>
 21#include <sound/soc.h>
 22#include <sound/initval.h>
 23#include <sound/tlv.h>
 24
 25#include "ssm2518.h"
 26
 27#define SSM2518_REG_POWER1		0x00
 28#define SSM2518_REG_CLOCK		0x01
 29#define SSM2518_REG_SAI_CTRL1		0x02
 30#define SSM2518_REG_SAI_CTRL2		0x03
 31#define SSM2518_REG_CHAN_MAP		0x04
 32#define SSM2518_REG_LEFT_VOL		0x05
 33#define SSM2518_REG_RIGHT_VOL		0x06
 34#define SSM2518_REG_MUTE_CTRL		0x07
 35#define SSM2518_REG_FAULT_CTRL		0x08
 36#define SSM2518_REG_POWER2		0x09
 37#define SSM2518_REG_DRC_1		0x0a
 38#define SSM2518_REG_DRC_2		0x0b
 39#define SSM2518_REG_DRC_3		0x0c
 40#define SSM2518_REG_DRC_4		0x0d
 41#define SSM2518_REG_DRC_5		0x0e
 42#define SSM2518_REG_DRC_6		0x0f
 43#define SSM2518_REG_DRC_7		0x10
 44#define SSM2518_REG_DRC_8		0x11
 45#define SSM2518_REG_DRC_9		0x12
 46
 47#define SSM2518_POWER1_RESET			BIT(7)
 48#define SSM2518_POWER1_NO_BCLK			BIT(5)
 49#define SSM2518_POWER1_MCS_MASK			(0xf << 1)
 50#define SSM2518_POWER1_MCS_64FS			(0x0 << 1)
 51#define SSM2518_POWER1_MCS_128FS		(0x1 << 1)
 52#define SSM2518_POWER1_MCS_256FS		(0x2 << 1)
 53#define SSM2518_POWER1_MCS_384FS		(0x3 << 1)
 54#define SSM2518_POWER1_MCS_512FS		(0x4 << 1)
 55#define SSM2518_POWER1_MCS_768FS		(0x5 << 1)
 56#define SSM2518_POWER1_MCS_100FS		(0x6 << 1)
 57#define SSM2518_POWER1_MCS_200FS		(0x7 << 1)
 58#define SSM2518_POWER1_MCS_400FS		(0x8 << 1)
 59#define SSM2518_POWER1_SPWDN			BIT(0)
 60
 61#define SSM2518_CLOCK_ASR			BIT(0)
 62
 63#define SSM2518_SAI_CTRL1_FMT_MASK		(0x3 << 5)
 64#define SSM2518_SAI_CTRL1_FMT_I2S		(0x0 << 5)
 65#define SSM2518_SAI_CTRL1_FMT_LJ		(0x1 << 5)
 66#define SSM2518_SAI_CTRL1_FMT_RJ_24BIT		(0x2 << 5)
 67#define SSM2518_SAI_CTRL1_FMT_RJ_16BIT		(0x3 << 5)
 68
 69#define SSM2518_SAI_CTRL1_SAI_MASK		(0x7 << 2)
 70#define SSM2518_SAI_CTRL1_SAI_I2S		(0x0 << 2)
 71#define SSM2518_SAI_CTRL1_SAI_TDM_2		(0x1 << 2)
 72#define SSM2518_SAI_CTRL1_SAI_TDM_4		(0x2 << 2)
 73#define SSM2518_SAI_CTRL1_SAI_TDM_8		(0x3 << 2)
 74#define SSM2518_SAI_CTRL1_SAI_TDM_16		(0x4 << 2)
 75#define SSM2518_SAI_CTRL1_SAI_MONO		(0x5 << 2)
 76
 77#define SSM2518_SAI_CTRL1_FS_MASK		(0x3)
 78#define SSM2518_SAI_CTRL1_FS_8000_12000		(0x0)
 79#define SSM2518_SAI_CTRL1_FS_16000_24000	(0x1)
 80#define SSM2518_SAI_CTRL1_FS_32000_48000	(0x2)
 81#define SSM2518_SAI_CTRL1_FS_64000_96000	(0x3)
 82
 83#define SSM2518_SAI_CTRL2_BCLK_INTERAL		BIT(7)
 84#define SSM2518_SAI_CTRL2_LRCLK_PULSE		BIT(6)
 85#define SSM2518_SAI_CTRL2_LRCLK_INVERT		BIT(5)
 86#define SSM2518_SAI_CTRL2_MSB			BIT(4)
 87#define SSM2518_SAI_CTRL2_SLOT_WIDTH_MASK	(0x3 << 2)
 88#define SSM2518_SAI_CTRL2_SLOT_WIDTH_32		(0x0 << 2)
 89#define SSM2518_SAI_CTRL2_SLOT_WIDTH_24		(0x1 << 2)
 90#define SSM2518_SAI_CTRL2_SLOT_WIDTH_16		(0x2 << 2)
 91#define SSM2518_SAI_CTRL2_BCLK_INVERT		BIT(1)
 92
 93#define SSM2518_CHAN_MAP_RIGHT_SLOT_OFFSET	4
 94#define SSM2518_CHAN_MAP_RIGHT_SLOT_MASK	0xf0
 95#define SSM2518_CHAN_MAP_LEFT_SLOT_OFFSET	0
 96#define SSM2518_CHAN_MAP_LEFT_SLOT_MASK		0x0f
 97
 98#define SSM2518_MUTE_CTRL_ANA_GAIN		BIT(5)
 99#define SSM2518_MUTE_CTRL_MUTE_MASTER		BIT(0)
100
101#define SSM2518_POWER2_APWDN			BIT(0)
102
103#define SSM2518_DAC_MUTE			BIT(6)
104#define SSM2518_DAC_FS_MASK			0x07
105#define SSM2518_DAC_FS_8000			0x00
106#define SSM2518_DAC_FS_16000			0x01
107#define SSM2518_DAC_FS_32000			0x02
108#define SSM2518_DAC_FS_64000			0x03
109#define SSM2518_DAC_FS_128000			0x04
110
111struct ssm2518 {
112	struct regmap *regmap;
113	bool right_j;
114
115	unsigned int sysclk;
116	const struct snd_pcm_hw_constraint_list *constraints;
117
118	int enable_gpio;
119};
120
121static const struct reg_default ssm2518_reg_defaults[] = {
122	{ 0x00, 0x05 },
123	{ 0x01, 0x00 },
124	{ 0x02, 0x02 },
125	{ 0x03, 0x00 },
126	{ 0x04, 0x10 },
127	{ 0x05, 0x40 },
128	{ 0x06, 0x40 },
129	{ 0x07, 0x81 },
130	{ 0x08, 0x0c },
131	{ 0x09, 0x99 },
132	{ 0x0a, 0x7c },
133	{ 0x0b, 0x5b },
134	{ 0x0c, 0x57 },
135	{ 0x0d, 0x89 },
136	{ 0x0e, 0x8c },
137	{ 0x0f, 0x77 },
138	{ 0x10, 0x26 },
139	{ 0x11, 0x1c },
140	{ 0x12, 0x97 },
141};
142
143static const DECLARE_TLV_DB_MINMAX_MUTE(ssm2518_vol_tlv, -7125, 2400);
144static const DECLARE_TLV_DB_SCALE(ssm2518_compressor_tlv, -3400, 200, 0);
145static const DECLARE_TLV_DB_SCALE(ssm2518_expander_tlv, -8100, 300, 0);
146static const DECLARE_TLV_DB_SCALE(ssm2518_noise_gate_tlv, -9600, 300, 0);
147static const DECLARE_TLV_DB_SCALE(ssm2518_post_drc_tlv, -2400, 300, 0);
148
149static const DECLARE_TLV_DB_RANGE(ssm2518_limiter_tlv,
150	0, 7, TLV_DB_SCALE_ITEM(-2200, 200, 0),
151	7, 15, TLV_DB_SCALE_ITEM(-800, 100, 0),
152);
153
154static const char * const ssm2518_drc_peak_detector_attack_time_text[] = {
155	"0 ms", "0.1 ms", "0.19 ms", "0.37 ms", "0.75 ms", "1.5 ms", "3 ms",
156	"6 ms", "12 ms", "24 ms", "48 ms", "96 ms", "192 ms", "384 ms",
157	"768 ms", "1536 ms",
158};
159
160static const char * const ssm2518_drc_peak_detector_release_time_text[] = {
161	"0 ms", "1.5 ms", "3 ms", "6 ms", "12 ms", "24 ms", "48 ms", "96 ms",
162	"192 ms", "384 ms", "768 ms", "1536 ms", "3072 ms", "6144 ms",
163	"12288 ms", "24576 ms"
164};
165
166static const char * const ssm2518_drc_hold_time_text[] = {
167	"0 ms", "0.67 ms", "1.33 ms", "2.67 ms", "5.33 ms", "10.66 ms",
168	"21.32 ms", "42.64 ms", "85.28 ms", "170.56 ms", "341.12 ms",
169	"682.24 ms", "1364 ms",
170};
171
172static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum,
173	SSM2518_REG_DRC_2, 4, ssm2518_drc_peak_detector_attack_time_text);
174static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum,
175	SSM2518_REG_DRC_2, 0, ssm2518_drc_peak_detector_release_time_text);
176static SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum,
177	SSM2518_REG_DRC_6, 4, ssm2518_drc_peak_detector_attack_time_text);
178static SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum,
179	SSM2518_REG_DRC_6, 0, ssm2518_drc_peak_detector_release_time_text);
180static SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum,
181	SSM2518_REG_DRC_7, 4, ssm2518_drc_hold_time_text);
182static SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum,
183	SSM2518_REG_DRC_7, 0, ssm2518_drc_hold_time_text);
184static SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum,
185	SSM2518_REG_DRC_9, 0, ssm2518_drc_peak_detector_release_time_text);
186
187static const struct snd_kcontrol_new ssm2518_snd_controls[] = {
188	SOC_SINGLE("Playback De-emphasis Switch", SSM2518_REG_MUTE_CTRL,
189			4, 1, 0),
190	SOC_DOUBLE_R_TLV("Master Playback Volume", SSM2518_REG_LEFT_VOL,
191			SSM2518_REG_RIGHT_VOL, 0, 0xff, 1, ssm2518_vol_tlv),
192	SOC_DOUBLE("Master Playback Switch", SSM2518_REG_MUTE_CTRL, 2, 1, 1, 1),
193
194	SOC_SINGLE("Amp Low Power Mode Switch", SSM2518_REG_POWER2, 4, 1, 0),
195	SOC_SINGLE("DAC Low Power Mode Switch", SSM2518_REG_POWER2, 3, 1, 0),
196
197	SOC_SINGLE("DRC Limiter Switch", SSM2518_REG_DRC_1, 5, 1, 0),
198	SOC_SINGLE("DRC Compressor Switch", SSM2518_REG_DRC_1, 4, 1, 0),
199	SOC_SINGLE("DRC Expander Switch", SSM2518_REG_DRC_1, 3, 1, 0),
200	SOC_SINGLE("DRC Noise Gate Switch", SSM2518_REG_DRC_1, 2, 1, 0),
201	SOC_DOUBLE("DRC Switch", SSM2518_REG_DRC_1, 0, 1, 1, 0),
202
203	SOC_SINGLE_TLV("DRC Limiter Threshold Volume",
204			SSM2518_REG_DRC_3, 4, 15, 1, ssm2518_limiter_tlv),
205	SOC_SINGLE_TLV("DRC Compressor Lower Threshold Volume",
206			SSM2518_REG_DRC_3, 0, 15, 1, ssm2518_compressor_tlv),
207	SOC_SINGLE_TLV("DRC Expander Upper Threshold Volume", SSM2518_REG_DRC_4,
208			4, 15, 1, ssm2518_expander_tlv),
209	SOC_SINGLE_TLV("DRC Noise Gate Threshold Volume",
210			SSM2518_REG_DRC_4, 0, 15, 1, ssm2518_noise_gate_tlv),
211	SOC_SINGLE_TLV("DRC Upper Output Threshold Volume",
212			SSM2518_REG_DRC_5, 4, 15, 1, ssm2518_limiter_tlv),
213	SOC_SINGLE_TLV("DRC Lower Output Threshold Volume",
214			SSM2518_REG_DRC_5, 0, 15, 1, ssm2518_noise_gate_tlv),
215	SOC_SINGLE_TLV("DRC Post Volume", SSM2518_REG_DRC_8,
216			2, 15, 1, ssm2518_post_drc_tlv),
217
218	SOC_ENUM("DRC Peak Detector Attack Time",
219		ssm2518_drc_peak_detector_attack_time_enum),
220	SOC_ENUM("DRC Peak Detector Release Time",
221		ssm2518_drc_peak_detector_release_time_enum),
222	SOC_ENUM("DRC Attack Time", ssm2518_drc_attack_time_enum),
223	SOC_ENUM("DRC Decay Time", ssm2518_drc_decay_time_enum),
224	SOC_ENUM("DRC Hold Time", ssm2518_drc_hold_time_enum),
225	SOC_ENUM("DRC Noise Gate Hold Time",
226		ssm2518_drc_noise_gate_hold_time_enum),
227	SOC_ENUM("DRC RMS Averaging Time", ssm2518_drc_rms_averaging_time_enum),
228};
229
230static const struct snd_soc_dapm_widget ssm2518_dapm_widgets[] = {
231	SND_SOC_DAPM_DAC("DACL", "HiFi Playback", SSM2518_REG_POWER2, 1, 1),
232	SND_SOC_DAPM_DAC("DACR", "HiFi Playback", SSM2518_REG_POWER2, 2, 1),
233
234	SND_SOC_DAPM_OUTPUT("OUTL"),
235	SND_SOC_DAPM_OUTPUT("OUTR"),
236};
237
238static const struct snd_soc_dapm_route ssm2518_routes[] = {
239	{ "OUTL", NULL, "DACL" },
240	{ "OUTR", NULL, "DACR" },
241};
242
243struct ssm2518_mcs_lut {
244	unsigned int rate;
245	const unsigned int *sysclks;
246};
247
248static const unsigned int ssm2518_sysclks_2048000[] = {
249	2048000, 4096000, 8192000, 12288000, 16384000, 24576000,
250	3200000, 6400000, 12800000, 0
251};
252
253static const unsigned int ssm2518_sysclks_2822000[] = {
254	2822000, 5644800, 11289600, 16934400, 22579200, 33868800,
255	4410000, 8820000, 17640000, 0
256};
257
258static const unsigned int ssm2518_sysclks_3072000[] = {
259	3072000, 6144000, 12288000, 16384000, 24576000, 38864000,
260	4800000, 9600000, 19200000, 0
261};
262
263static const struct ssm2518_mcs_lut ssm2518_mcs_lut[] = {
264	{ 8000,  ssm2518_sysclks_2048000, },
265	{ 11025, ssm2518_sysclks_2822000, },
266	{ 12000, ssm2518_sysclks_3072000, },
267	{ 16000, ssm2518_sysclks_2048000, },
268	{ 24000, ssm2518_sysclks_3072000, },
269	{ 22050, ssm2518_sysclks_2822000, },
270	{ 32000, ssm2518_sysclks_2048000, },
271	{ 44100, ssm2518_sysclks_2822000, },
272	{ 48000, ssm2518_sysclks_3072000, },
273	{ 96000, ssm2518_sysclks_3072000, },
274};
275
276static const unsigned int ssm2518_rates_2048000[] = {
277	8000, 16000, 32000,
278};
279
280static const struct snd_pcm_hw_constraint_list ssm2518_constraints_2048000 = {
281	.list = ssm2518_rates_2048000,
282	.count = ARRAY_SIZE(ssm2518_rates_2048000),
283};
284
285static const unsigned int ssm2518_rates_2822000[] = {
286	11025, 22050, 44100,
287};
288
289static const struct snd_pcm_hw_constraint_list ssm2518_constraints_2822000 = {
290	.list = ssm2518_rates_2822000,
291	.count = ARRAY_SIZE(ssm2518_rates_2822000),
292};
293
294static const unsigned int ssm2518_rates_3072000[] = {
295	12000, 24000, 48000, 96000,
296};
297
298static const struct snd_pcm_hw_constraint_list ssm2518_constraints_3072000 = {
299	.list = ssm2518_rates_3072000,
300	.count = ARRAY_SIZE(ssm2518_rates_3072000),
301};
302
303static const unsigned int ssm2518_rates_12288000[] = {
304	8000, 12000, 16000, 24000, 32000, 48000, 96000,
305};
306
307static const struct snd_pcm_hw_constraint_list ssm2518_constraints_12288000 = {
308	.list = ssm2518_rates_12288000,
309	.count = ARRAY_SIZE(ssm2518_rates_12288000),
310};
311
312static int ssm2518_lookup_mcs(struct ssm2518 *ssm2518,
313	unsigned int rate)
314{
315	const unsigned int *sysclks = NULL;
316	int i;
317
318	for (i = 0; i < ARRAY_SIZE(ssm2518_mcs_lut); i++) {
319		if (ssm2518_mcs_lut[i].rate == rate) {
320			sysclks = ssm2518_mcs_lut[i].sysclks;
321			break;
322		}
323	}
324
325	if (!sysclks)
326		return -EINVAL;
327
328	for (i = 0; sysclks[i]; i++) {
329		if (sysclks[i] == ssm2518->sysclk)
330			return i;
331	}
332
333	return -EINVAL;
334}
335
336static int ssm2518_hw_params(struct snd_pcm_substream *substream,
337	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
338{
339	struct snd_soc_codec *codec = dai->codec;
340	struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(codec);
341	unsigned int rate = params_rate(params);
342	unsigned int ctrl1, ctrl1_mask;
343	int mcs;
344	int ret;
345
346	mcs = ssm2518_lookup_mcs(ssm2518, rate);
347	if (mcs < 0)
348		return mcs;
349
350	ctrl1_mask = SSM2518_SAI_CTRL1_FS_MASK;
351
352	if (rate >= 8000 && rate <= 12000)
353		ctrl1 = SSM2518_SAI_CTRL1_FS_8000_12000;
354	else if (rate >= 16000 && rate <= 24000)
355		ctrl1 = SSM2518_SAI_CTRL1_FS_16000_24000;
356	else if (rate >= 32000 && rate <= 48000)
357		ctrl1 = SSM2518_SAI_CTRL1_FS_32000_48000;
358	else if (rate >= 64000 && rate <= 96000)
359		ctrl1 = SSM2518_SAI_CTRL1_FS_64000_96000;
360	else
361		return -EINVAL;
362
363	if (ssm2518->right_j) {
364		switch (params_width(params)) {
365		case 16:
366			ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_16BIT;
367			break;
368		case 24:
369			ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_24BIT;
370			break;
371		default:
372			return -EINVAL;
373		}
374		ctrl1_mask |= SSM2518_SAI_CTRL1_FMT_MASK;
375	}
376
377	/* Disable auto samplerate detection */
378	ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_CLOCK,
379				SSM2518_CLOCK_ASR, SSM2518_CLOCK_ASR);
380	if (ret < 0)
381		return ret;
382
383	ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_SAI_CTRL1,
384				ctrl1_mask, ctrl1);
385	if (ret < 0)
386		return ret;
387
388	return regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1,
389				SSM2518_POWER1_MCS_MASK, mcs << 1);
390}
391
392static int ssm2518_mute(struct snd_soc_dai *dai, int mute)
393{
394	struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(dai->codec);
395	unsigned int val;
396
397	if (mute)
398		val = SSM2518_MUTE_CTRL_MUTE_MASTER;
399	else
400		val = 0;
401
402	return regmap_update_bits(ssm2518->regmap, SSM2518_REG_MUTE_CTRL,
403			SSM2518_MUTE_CTRL_MUTE_MASTER, val);
404}
405
406static int ssm2518_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
407{
408	struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(dai->codec);
409	unsigned int ctrl1 = 0, ctrl2 = 0;
410	bool invert_fclk;
411	int ret;
412
413	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
414	case SND_SOC_DAIFMT_CBS_CFS:
415		break;
416	default:
417		return -EINVAL;
418	}
419
420	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
421	case SND_SOC_DAIFMT_NB_NF:
422		invert_fclk = false;
423		break;
424	case SND_SOC_DAIFMT_IB_NF:
425		ctrl2 |= SSM2518_SAI_CTRL2_BCLK_INVERT;
426		invert_fclk = false;
427		break;
428	case SND_SOC_DAIFMT_NB_IF:
429		invert_fclk = true;
430		break;
431	case SND_SOC_DAIFMT_IB_IF:
432		ctrl2 |= SSM2518_SAI_CTRL2_BCLK_INVERT;
433		invert_fclk = true;
434		break;
435	default:
436		return -EINVAL;
437	}
438
439	ssm2518->right_j = false;
440	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
441	case SND_SOC_DAIFMT_I2S:
442		ctrl1 |= SSM2518_SAI_CTRL1_FMT_I2S;
443		break;
444	case SND_SOC_DAIFMT_LEFT_J:
445		ctrl1 |= SSM2518_SAI_CTRL1_FMT_LJ;
446		invert_fclk = !invert_fclk;
447		break;
448	case SND_SOC_DAIFMT_RIGHT_J:
449		ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_24BIT;
450		ssm2518->right_j = true;
451		invert_fclk = !invert_fclk;
452		break;
453	case SND_SOC_DAIFMT_DSP_A:
454		ctrl2 |= SSM2518_SAI_CTRL2_LRCLK_PULSE;
455		ctrl1 |= SSM2518_SAI_CTRL1_FMT_I2S;
456		invert_fclk = false;
457		break;
458	case SND_SOC_DAIFMT_DSP_B:
459		ctrl2 |= SSM2518_SAI_CTRL2_LRCLK_PULSE;
460		ctrl1 |= SSM2518_SAI_CTRL1_FMT_LJ;
461		invert_fclk = false;
462		break;
463	default:
464		return -EINVAL;
465	}
466
467	if (invert_fclk)
468		ctrl2 |= SSM2518_SAI_CTRL2_LRCLK_INVERT;
469
470	ret = regmap_write(ssm2518->regmap, SSM2518_REG_SAI_CTRL1, ctrl1);
471	if (ret)
472		return ret;
473
474	return regmap_write(ssm2518->regmap, SSM2518_REG_SAI_CTRL2, ctrl2);
475}
476
477static int ssm2518_set_power(struct ssm2518 *ssm2518, bool enable)
478{
479	int ret = 0;
480
481	if (!enable) {
482		ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1,
483			SSM2518_POWER1_SPWDN, SSM2518_POWER1_SPWDN);
484		regcache_mark_dirty(ssm2518->regmap);
485	}
486
487	if (gpio_is_valid(ssm2518->enable_gpio))
488		gpio_set_value(ssm2518->enable_gpio, enable);
489
490	regcache_cache_only(ssm2518->regmap, !enable);
491
492	if (enable) {
493		ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1,
494			SSM2518_POWER1_SPWDN | SSM2518_POWER1_RESET, 0x00);
495		regcache_sync(ssm2518->regmap);
496	}
497
498	return ret;
499}
500
501static int ssm2518_set_bias_level(struct snd_soc_codec *codec,
502	enum snd_soc_bias_level level)
503{
504	struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(codec);
505	int ret = 0;
506
507	switch (level) {
508	case SND_SOC_BIAS_ON:
509		break;
510	case SND_SOC_BIAS_PREPARE:
511		break;
512	case SND_SOC_BIAS_STANDBY:
513		if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF)
514			ret = ssm2518_set_power(ssm2518, true);
515		break;
516	case SND_SOC_BIAS_OFF:
517		ret = ssm2518_set_power(ssm2518, false);
518		break;
519	}
520
521	return ret;
522}
523
524static int ssm2518_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
525	unsigned int rx_mask, int slots, int width)
526{
527	struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(dai->codec);
528	unsigned int ctrl1, ctrl2;
529	int left_slot, right_slot;
530	int ret;
531
532	if (slots == 0)
533		return regmap_update_bits(ssm2518->regmap,
534			SSM2518_REG_SAI_CTRL1, SSM2518_SAI_CTRL1_SAI_MASK,
535			SSM2518_SAI_CTRL1_SAI_I2S);
536
537	if (tx_mask == 0 || rx_mask != 0)
538		return -EINVAL;
539
540	if (slots == 1) {
541		if (tx_mask != 1)
542			return -EINVAL;
543		left_slot = 0;
544		right_slot = 0;
545	} else {
546		/* We assume the left channel < right channel */
547		left_slot = __ffs(tx_mask);
548		tx_mask &= ~(1 << left_slot);
549		if (tx_mask == 0) {
550			right_slot = left_slot;
551		} else {
552			right_slot = __ffs(tx_mask);
553			tx_mask &= ~(1 << right_slot);
554		}
555	}
556
557	if (tx_mask != 0 || left_slot >= slots || right_slot >= slots)
558		return -EINVAL;
559
560	switch (width) {
561	case 16:
562		ctrl2 = SSM2518_SAI_CTRL2_SLOT_WIDTH_16;
563		break;
564	case 24:
565		ctrl2 = SSM2518_SAI_CTRL2_SLOT_WIDTH_24;
566		break;
567	case 32:
568		ctrl2 = SSM2518_SAI_CTRL2_SLOT_WIDTH_32;
569		break;
570	default:
571		return -EINVAL;
572	}
573
574	switch (slots) {
575	case 1:
576		ctrl1 = SSM2518_SAI_CTRL1_SAI_MONO;
577		break;
578	case 2:
579		ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_2;
580		break;
581	case 4:
582		ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_4;
583		break;
584	case 8:
585		ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_8;
586		break;
587	case 16:
588		ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_16;
589		break;
590	default:
591		return -EINVAL;
592	}
593
594	ret = regmap_write(ssm2518->regmap, SSM2518_REG_CHAN_MAP,
595		(left_slot << SSM2518_CHAN_MAP_LEFT_SLOT_OFFSET) |
596		(right_slot << SSM2518_CHAN_MAP_RIGHT_SLOT_OFFSET));
597	if (ret)
598		return ret;
599
600	ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_SAI_CTRL1,
601		SSM2518_SAI_CTRL1_SAI_MASK, ctrl1);
602	if (ret)
603		return ret;
604
605	return regmap_update_bits(ssm2518->regmap, SSM2518_REG_SAI_CTRL2,
606		SSM2518_SAI_CTRL2_SLOT_WIDTH_MASK, ctrl2);
607}
608
609static int ssm2518_startup(struct snd_pcm_substream *substream,
610	struct snd_soc_dai *dai)
611{
612	struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(dai->codec);
613
614	if (ssm2518->constraints)
615		snd_pcm_hw_constraint_list(substream->runtime, 0,
616				SNDRV_PCM_HW_PARAM_RATE, ssm2518->constraints);
617
618	return 0;
619}
620
621#define SSM2518_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
622			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32)
623
624static const struct snd_soc_dai_ops ssm2518_dai_ops = {
625	.startup = ssm2518_startup,
626	.hw_params	= ssm2518_hw_params,
627	.digital_mute	= ssm2518_mute,
628	.set_fmt	= ssm2518_set_dai_fmt,
629	.set_tdm_slot	= ssm2518_set_tdm_slot,
 
630};
631
632static struct snd_soc_dai_driver ssm2518_dai = {
633	.name = "ssm2518-hifi",
634	.playback = {
635		.stream_name = "Playback",
636		.channels_min = 2,
637		.channels_max = 2,
638		.rates = SNDRV_PCM_RATE_8000_96000,
639		.formats = SSM2518_FORMATS,
640	},
641	.ops = &ssm2518_dai_ops,
642};
643
644static int ssm2518_set_sysclk(struct snd_soc_codec *codec, int clk_id,
645	int source, unsigned int freq, int dir)
646{
647	struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(codec);
648	unsigned int val;
649
650	if (clk_id != SSM2518_SYSCLK)
651		return -EINVAL;
652
653	switch (source) {
654	case SSM2518_SYSCLK_SRC_MCLK:
655		val = 0;
656		break;
657	case SSM2518_SYSCLK_SRC_BCLK:
658		/* In this case the bitclock is used as the system clock, and
659		 * the bitclock signal needs to be connected to the MCLK pin and
660		 * the BCLK pin is left unconnected */
661		val = SSM2518_POWER1_NO_BCLK;
662		break;
663	default:
664		return -EINVAL;
665	}
666
667	switch (freq) {
668	case 0:
669		ssm2518->constraints = NULL;
670		break;
671	case 2048000:
672	case 4096000:
673	case 8192000:
674	case 3200000:
675	case 6400000:
676	case 12800000:
677		ssm2518->constraints = &ssm2518_constraints_2048000;
678		break;
679	case 2822000:
680	case 5644800:
681	case 11289600:
682	case 16934400:
683	case 22579200:
684	case 33868800:
685	case 4410000:
686	case 8820000:
687	case 17640000:
688		ssm2518->constraints = &ssm2518_constraints_2822000;
689		break;
690	case 3072000:
691	case 6144000:
692	case 38864000:
693	case 4800000:
694	case 9600000:
695	case 19200000:
696		ssm2518->constraints = &ssm2518_constraints_3072000;
697		break;
698	case 12288000:
699	case 16384000:
700	case 24576000:
701		ssm2518->constraints = &ssm2518_constraints_12288000;
702		break;
703	default:
704		return -EINVAL;
705	}
706
707	ssm2518->sysclk = freq;
708
709	return regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1,
710			SSM2518_POWER1_NO_BCLK, val);
711}
712
713static struct snd_soc_codec_driver ssm2518_codec_driver = {
714	.set_bias_level = ssm2518_set_bias_level,
715	.set_sysclk = ssm2518_set_sysclk,
716	.idle_bias_off = true,
717
718	.component_driver = {
719		.controls		= ssm2518_snd_controls,
720		.num_controls		= ARRAY_SIZE(ssm2518_snd_controls),
721		.dapm_widgets		= ssm2518_dapm_widgets,
722		.num_dapm_widgets	= ARRAY_SIZE(ssm2518_dapm_widgets),
723		.dapm_routes		= ssm2518_routes,
724		.num_dapm_routes	= ARRAY_SIZE(ssm2518_routes),
725	},
726};
727
728static const struct regmap_config ssm2518_regmap_config = {
729	.val_bits = 8,
730	.reg_bits = 8,
731
732	.max_register = SSM2518_REG_DRC_9,
733
734	.cache_type = REGCACHE_RBTREE,
735	.reg_defaults = ssm2518_reg_defaults,
736	.num_reg_defaults = ARRAY_SIZE(ssm2518_reg_defaults),
737};
738
739static int ssm2518_i2c_probe(struct i2c_client *i2c,
740	const struct i2c_device_id *id)
741{
742	struct ssm2518_platform_data *pdata = i2c->dev.platform_data;
743	struct ssm2518 *ssm2518;
744	int ret;
745
746	ssm2518 = devm_kzalloc(&i2c->dev, sizeof(*ssm2518), GFP_KERNEL);
747	if (ssm2518 == NULL)
748		return -ENOMEM;
749
750	if (pdata) {
751		ssm2518->enable_gpio = pdata->enable_gpio;
752	} else if (i2c->dev.of_node) {
753		ssm2518->enable_gpio = of_get_gpio(i2c->dev.of_node, 0);
754		if (ssm2518->enable_gpio < 0 && ssm2518->enable_gpio != -ENOENT)
755			return ssm2518->enable_gpio;
756	} else {
757		ssm2518->enable_gpio = -1;
758	}
759
760	if (gpio_is_valid(ssm2518->enable_gpio)) {
761		ret = devm_gpio_request_one(&i2c->dev, ssm2518->enable_gpio,
762				GPIOF_OUT_INIT_HIGH, "SSM2518 nSD");
763		if (ret)
764			return ret;
765	}
766
767	i2c_set_clientdata(i2c, ssm2518);
768
769	ssm2518->regmap = devm_regmap_init_i2c(i2c, &ssm2518_regmap_config);
770	if (IS_ERR(ssm2518->regmap))
771		return PTR_ERR(ssm2518->regmap);
772
773	/*
774	 * The reset bit is obviously volatile, but we need to be able to cache
775	 * the other bits in the register, so we can't just mark the whole
776	 * register as volatile. Since this is the only place where we'll ever
777	 * touch the reset bit just bypass the cache for this operation.
778	 */
779	regcache_cache_bypass(ssm2518->regmap, true);
780	ret = regmap_write(ssm2518->regmap, SSM2518_REG_POWER1,
781			SSM2518_POWER1_RESET);
782	regcache_cache_bypass(ssm2518->regmap, false);
783	if (ret)
784		return ret;
785
786	ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER2,
787				SSM2518_POWER2_APWDN, 0x00);
788	if (ret)
789		return ret;
790
791	ret = ssm2518_set_power(ssm2518, false);
792	if (ret)
793		return ret;
794
795	return snd_soc_register_codec(&i2c->dev, &ssm2518_codec_driver,
 
796			&ssm2518_dai, 1);
797}
798
799static int ssm2518_i2c_remove(struct i2c_client *client)
800{
801	snd_soc_unregister_codec(&client->dev);
802	return 0;
803}
804
805#ifdef CONFIG_OF
806static const struct of_device_id ssm2518_dt_ids[] = {
807	{ .compatible = "adi,ssm2518", },
808	{ }
809};
810MODULE_DEVICE_TABLE(of, ssm2518_dt_ids);
811#endif
812
813static const struct i2c_device_id ssm2518_i2c_ids[] = {
814	{ "ssm2518", 0 },
815	{ }
816};
817MODULE_DEVICE_TABLE(i2c, ssm2518_i2c_ids);
818
819static struct i2c_driver ssm2518_driver = {
820	.driver = {
821		.name = "ssm2518",
822		.of_match_table = of_match_ptr(ssm2518_dt_ids),
823	},
824	.probe = ssm2518_i2c_probe,
825	.remove = ssm2518_i2c_remove,
826	.id_table = ssm2518_i2c_ids,
827};
828module_i2c_driver(ssm2518_driver);
829
830MODULE_DESCRIPTION("ASoC SSM2518 driver");
831MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
832MODULE_LICENSE("GPL");