2 * SSM2518 amplifier audio driver
4 * Copyright 2013 Analog Devices Inc.
5 * Author: Lars-Peter Clausen <lars@metafoo.de>
7 * Licensed under the GPL-2.
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>
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
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)
61 #define SSM2518_CLOCK_ASR BIT(0)
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)
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)
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)
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)
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
98 #define SSM2518_MUTE_CTRL_ANA_GAIN BIT(5)
99 #define SSM2518_MUTE_CTRL_MUTE_MASTER BIT(0)
101 #define SSM2518_POWER2_APWDN BIT(0)
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
112 struct regmap
*regmap
;
116 const struct snd_pcm_hw_constraint_list
*constraints
;
121 static const struct reg_default ssm2518_reg_defaults
[] = {
143 static const DECLARE_TLV_DB_MINMAX_MUTE(ssm2518_vol_tlv
, -7125, 2400);
144 static const DECLARE_TLV_DB_SCALE(ssm2518_compressor_tlv
, -3400, 200, 0);
145 static const DECLARE_TLV_DB_SCALE(ssm2518_expander_tlv
, -8100, 300, 0);
146 static const DECLARE_TLV_DB_SCALE(ssm2518_noise_gate_tlv
, -9600, 300, 0);
147 static const DECLARE_TLV_DB_SCALE(ssm2518_post_drc_tlv
, -2400, 300, 0);
149 static 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),
154 static 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",
160 static 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"
166 static 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",
172 static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum
,
173 SSM2518_REG_DRC_2
, 4, ssm2518_drc_peak_detector_attack_time_text
);
174 static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum
,
175 SSM2518_REG_DRC_2
, 0, ssm2518_drc_peak_detector_release_time_text
);
176 static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum
,
177 SSM2518_REG_DRC_6
, 4, ssm2518_drc_peak_detector_attack_time_text
);
178 static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum
,
179 SSM2518_REG_DRC_6
, 0, ssm2518_drc_peak_detector_release_time_text
);
180 static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum
,
181 SSM2518_REG_DRC_7
, 4, ssm2518_drc_hold_time_text
);
182 static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum
,
183 SSM2518_REG_DRC_7
, 0, ssm2518_drc_hold_time_text
);
184 static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum
,
185 SSM2518_REG_DRC_9
, 0, ssm2518_drc_peak_detector_release_time_text
);
187 static const struct snd_kcontrol_new ssm2518_snd_controls
[] = {
188 SOC_SINGLE("Playback De-emphasis Switch", SSM2518_REG_MUTE_CTRL
,
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),
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),
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),
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
),
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
),
230 static 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),
234 SND_SOC_DAPM_OUTPUT("OUTL"),
235 SND_SOC_DAPM_OUTPUT("OUTR"),
238 static const struct snd_soc_dapm_route ssm2518_routes
[] = {
239 { "OUTL", NULL
, "DACL" },
240 { "OUTR", NULL
, "DACR" },
243 struct ssm2518_mcs_lut
{
245 const unsigned int *sysclks
;
248 static const unsigned int ssm2518_sysclks_2048000
[] = {
249 2048000, 4096000, 8192000, 12288000, 16384000, 24576000,
250 3200000, 6400000, 12800000, 0
253 static const unsigned int ssm2518_sysclks_2822000
[] = {
254 2822000, 5644800, 11289600, 16934400, 22579200, 33868800,
255 4410000, 8820000, 17640000, 0
258 static const unsigned int ssm2518_sysclks_3072000
[] = {
259 3072000, 6144000, 12288000, 16384000, 24576000, 38864000,
260 4800000, 9600000, 19200000, 0
263 static 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
, },
276 static const unsigned int ssm2518_rates_2048000
[] = {
280 static const struct snd_pcm_hw_constraint_list ssm2518_constraints_2048000
= {
281 .list
= ssm2518_rates_2048000
,
282 .count
= ARRAY_SIZE(ssm2518_rates_2048000
),
285 static const unsigned int ssm2518_rates_2822000
[] = {
289 static const struct snd_pcm_hw_constraint_list ssm2518_constraints_2822000
= {
290 .list
= ssm2518_rates_2822000
,
291 .count
= ARRAY_SIZE(ssm2518_rates_2822000
),
294 static const unsigned int ssm2518_rates_3072000
[] = {
295 12000, 24000, 48000, 96000,
298 static const struct snd_pcm_hw_constraint_list ssm2518_constraints_3072000
= {
299 .list
= ssm2518_rates_3072000
,
300 .count
= ARRAY_SIZE(ssm2518_rates_3072000
),
303 static const unsigned int ssm2518_rates_12288000
[] = {
304 8000, 12000, 16000, 24000, 32000, 48000, 96000,
307 static const struct snd_pcm_hw_constraint_list ssm2518_constraints_12288000
= {
308 .list
= ssm2518_rates_12288000
,
309 .count
= ARRAY_SIZE(ssm2518_rates_12288000
),
312 static unsigned int ssm2518_lookup_mcs(struct ssm2518
*ssm2518
,
315 const unsigned int *sysclks
= NULL
;
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
;
328 for (i
= 0; sysclks
[i
]; i
++) {
329 if (sysclks
[i
] == ssm2518
->sysclk
)
336 static int ssm2518_hw_params(struct snd_pcm_substream
*substream
,
337 struct snd_pcm_hw_params
*params
, struct snd_soc_dai
*dai
)
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
;
346 mcs
= ssm2518_lookup_mcs(ssm2518
, rate
);
350 ctrl1_mask
= SSM2518_SAI_CTRL1_FS_MASK
;
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
;
363 if (ssm2518
->right_j
) {
364 switch (params_format(params
)) {
365 case SNDRV_PCM_FORMAT_S16_LE
:
366 ctrl1
|= SSM2518_SAI_CTRL1_FMT_RJ_16BIT
;
368 case SNDRV_PCM_FORMAT_S24_LE
:
369 ctrl1
|= SSM2518_SAI_CTRL1_FMT_RJ_24BIT
;
374 ctrl1_mask
|= SSM2518_SAI_CTRL1_FMT_MASK
;
377 /* Disable auto samplerate detection */
378 ret
= regmap_update_bits(ssm2518
->regmap
, SSM2518_REG_CLOCK
,
379 SSM2518_CLOCK_ASR
, SSM2518_CLOCK_ASR
);
383 ret
= regmap_update_bits(ssm2518
->regmap
, SSM2518_REG_SAI_CTRL1
,
388 return regmap_update_bits(ssm2518
->regmap
, SSM2518_REG_POWER1
,
389 SSM2518_POWER1_MCS_MASK
, mcs
<< 1);
392 static int ssm2518_mute(struct snd_soc_dai
*dai
, int mute
)
394 struct ssm2518
*ssm2518
= snd_soc_codec_get_drvdata(dai
->codec
);
398 val
= SSM2518_MUTE_CTRL_MUTE_MASTER
;
402 return regmap_update_bits(ssm2518
->regmap
, SSM2518_REG_MUTE_CTRL
,
403 SSM2518_MUTE_CTRL_MUTE_MASTER
, val
);
406 static int ssm2518_set_dai_fmt(struct snd_soc_dai
*dai
, unsigned int fmt
)
408 struct ssm2518
*ssm2518
= snd_soc_codec_get_drvdata(dai
->codec
);
409 unsigned int ctrl1
= 0, ctrl2
= 0;
413 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
414 case SND_SOC_DAIFMT_CBS_CFS
:
420 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
421 case SND_SOC_DAIFMT_NB_NF
:
424 case SND_SOC_DAIFMT_IB_NF
:
425 ctrl2
|= SSM2518_SAI_CTRL2_BCLK_INVERT
;
428 case SND_SOC_DAIFMT_NB_IF
:
431 case SND_SOC_DAIFMT_IB_IF
:
432 ctrl2
|= SSM2518_SAI_CTRL2_BCLK_INVERT
;
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
;
444 case SND_SOC_DAIFMT_LEFT_J
:
445 ctrl1
|= SSM2518_SAI_CTRL1_FMT_LJ
;
446 invert_fclk
= !invert_fclk
;
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
;
453 case SND_SOC_DAIFMT_DSP_A
:
454 ctrl2
|= SSM2518_SAI_CTRL2_LRCLK_PULSE
;
455 ctrl1
|= SSM2518_SAI_CTRL1_FMT_I2S
;
458 case SND_SOC_DAIFMT_DSP_B
:
459 ctrl2
|= SSM2518_SAI_CTRL2_LRCLK_PULSE
;
460 ctrl1
|= SSM2518_SAI_CTRL1_FMT_LJ
;
468 ctrl2
|= SSM2518_SAI_CTRL2_LRCLK_INVERT
;
470 ret
= regmap_write(ssm2518
->regmap
, SSM2518_REG_SAI_CTRL1
, ctrl1
);
474 return regmap_write(ssm2518
->regmap
, SSM2518_REG_SAI_CTRL2
, ctrl2
);
477 static int ssm2518_set_power(struct ssm2518
*ssm2518
, bool enable
)
482 ret
= regmap_update_bits(ssm2518
->regmap
, SSM2518_REG_POWER1
,
483 SSM2518_POWER1_SPWDN
, SSM2518_POWER1_SPWDN
);
484 regcache_mark_dirty(ssm2518
->regmap
);
487 if (gpio_is_valid(ssm2518
->enable_gpio
))
488 gpio_set_value(ssm2518
->enable_gpio
, enable
);
490 regcache_cache_only(ssm2518
->regmap
, !enable
);
493 ret
= regmap_update_bits(ssm2518
->regmap
, SSM2518_REG_POWER1
,
494 SSM2518_POWER1_SPWDN
| SSM2518_POWER1_RESET
, 0x00);
495 regcache_sync(ssm2518
->regmap
);
501 static int ssm2518_set_bias_level(struct snd_soc_codec
*codec
,
502 enum snd_soc_bias_level level
)
504 struct ssm2518
*ssm2518
= snd_soc_codec_get_drvdata(codec
);
508 case SND_SOC_BIAS_ON
:
510 case SND_SOC_BIAS_PREPARE
:
512 case SND_SOC_BIAS_STANDBY
:
513 if (codec
->dapm
.bias_level
== SND_SOC_BIAS_OFF
)
514 ret
= ssm2518_set_power(ssm2518
, true);
516 case SND_SOC_BIAS_OFF
:
517 ret
= ssm2518_set_power(ssm2518
, false);
524 codec
->dapm
.bias_level
= level
;
529 static int ssm2518_set_tdm_slot(struct snd_soc_dai
*dai
, unsigned int tx_mask
,
530 unsigned int rx_mask
, int slots
, int width
)
532 struct ssm2518
*ssm2518
= snd_soc_codec_get_drvdata(dai
->codec
);
533 unsigned int ctrl1
, ctrl2
;
534 int left_slot
, right_slot
;
538 return regmap_update_bits(ssm2518
->regmap
,
539 SSM2518_REG_SAI_CTRL1
, SSM2518_SAI_CTRL1_SAI_MASK
,
540 SSM2518_SAI_CTRL1_SAI_I2S
);
542 if (tx_mask
== 0 || rx_mask
!= 0)
551 /* We assume the left channel < right channel */
552 left_slot
= ffs(tx_mask
);
553 tx_mask
&= ~(1 << tx_mask
);
555 right_slot
= left_slot
;
557 right_slot
= ffs(tx_mask
);
558 tx_mask
&= ~(1 << tx_mask
);
562 if (tx_mask
!= 0 || left_slot
>= slots
|| right_slot
>= slots
)
567 ctrl2
= SSM2518_SAI_CTRL2_SLOT_WIDTH_16
;
570 ctrl2
= SSM2518_SAI_CTRL2_SLOT_WIDTH_24
;
573 ctrl2
= SSM2518_SAI_CTRL2_SLOT_WIDTH_32
;
581 ctrl1
= SSM2518_SAI_CTRL1_SAI_MONO
;
584 ctrl1
= SSM2518_SAI_CTRL1_SAI_TDM_2
;
587 ctrl1
= SSM2518_SAI_CTRL1_SAI_TDM_4
;
590 ctrl1
= SSM2518_SAI_CTRL1_SAI_TDM_8
;
593 ctrl1
= SSM2518_SAI_CTRL1_SAI_TDM_16
;
599 ret
= regmap_write(ssm2518
->regmap
, SSM2518_REG_CHAN_MAP
,
600 (left_slot
<< SSM2518_CHAN_MAP_LEFT_SLOT_OFFSET
) |
601 (right_slot
<< SSM2518_CHAN_MAP_RIGHT_SLOT_OFFSET
));
605 ret
= regmap_update_bits(ssm2518
->regmap
, SSM2518_REG_SAI_CTRL1
,
606 SSM2518_SAI_CTRL1_SAI_MASK
, ctrl1
);
610 return regmap_update_bits(ssm2518
->regmap
, SSM2518_REG_SAI_CTRL2
,
611 SSM2518_SAI_CTRL2_SLOT_WIDTH_MASK
, ctrl2
);
614 static int ssm2518_startup(struct snd_pcm_substream
*substream
,
615 struct snd_soc_dai
*dai
)
617 struct ssm2518
*ssm2518
= snd_soc_codec_get_drvdata(dai
->codec
);
619 if (ssm2518
->constraints
)
620 snd_pcm_hw_constraint_list(substream
->runtime
, 0,
621 SNDRV_PCM_HW_PARAM_RATE
, ssm2518
->constraints
);
626 #define SSM2518_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
627 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32)
629 static const struct snd_soc_dai_ops ssm2518_dai_ops
= {
630 .startup
= ssm2518_startup
,
631 .hw_params
= ssm2518_hw_params
,
632 .digital_mute
= ssm2518_mute
,
633 .set_fmt
= ssm2518_set_dai_fmt
,
634 .set_tdm_slot
= ssm2518_set_tdm_slot
,
637 static struct snd_soc_dai_driver ssm2518_dai
= {
638 .name
= "ssm2518-hifi",
640 .stream_name
= "Playback",
643 .rates
= SNDRV_PCM_RATE_8000_96000
,
644 .formats
= SSM2518_FORMATS
,
646 .ops
= &ssm2518_dai_ops
,
649 static int ssm2518_probe(struct snd_soc_codec
*codec
)
651 struct ssm2518
*ssm2518
= snd_soc_codec_get_drvdata(codec
);
654 codec
->control_data
= ssm2518
->regmap
;
655 ret
= snd_soc_codec_set_cache_io(codec
, 0, 0, SND_SOC_REGMAP
);
657 dev_err(codec
->dev
, "Failed to set cache I/O: %d\n", ret
);
661 return ssm2518_set_bias_level(codec
, SND_SOC_BIAS_OFF
);
664 static int ssm2518_remove(struct snd_soc_codec
*codec
)
666 ssm2518_set_bias_level(codec
, SND_SOC_BIAS_OFF
);
670 static int ssm2518_set_sysclk(struct snd_soc_codec
*codec
, int clk_id
,
671 int source
, unsigned int freq
, int dir
)
673 struct ssm2518
*ssm2518
= snd_soc_codec_get_drvdata(codec
);
676 if (clk_id
!= SSM2518_SYSCLK
)
680 case SSM2518_SYSCLK_SRC_MCLK
:
683 case SSM2518_SYSCLK_SRC_BCLK
:
684 /* In this case the bitclock is used as the system clock, and
685 * the bitclock signal needs to be connected to the MCLK pin and
686 * the BCLK pin is left unconnected */
687 val
= SSM2518_POWER1_NO_BCLK
;
695 ssm2518
->constraints
= NULL
;
703 ssm2518
->constraints
= &ssm2518_constraints_2048000
;
714 ssm2518
->constraints
= &ssm2518_constraints_2822000
;
722 ssm2518
->constraints
= &ssm2518_constraints_3072000
;
727 ssm2518
->constraints
= &ssm2518_constraints_12288000
;
733 ssm2518
->sysclk
= freq
;
735 return regmap_update_bits(ssm2518
->regmap
, SSM2518_REG_POWER1
,
736 SSM2518_POWER1_NO_BCLK
, val
);
739 static struct snd_soc_codec_driver ssm2518_codec_driver
= {
740 .probe
= ssm2518_probe
,
741 .remove
= ssm2518_remove
,
742 .set_bias_level
= ssm2518_set_bias_level
,
743 .set_sysclk
= ssm2518_set_sysclk
,
744 .idle_bias_off
= true,
746 .controls
= ssm2518_snd_controls
,
747 .num_controls
= ARRAY_SIZE(ssm2518_snd_controls
),
748 .dapm_widgets
= ssm2518_dapm_widgets
,
749 .num_dapm_widgets
= ARRAY_SIZE(ssm2518_dapm_widgets
),
750 .dapm_routes
= ssm2518_routes
,
751 .num_dapm_routes
= ARRAY_SIZE(ssm2518_routes
),
754 static bool ssm2518_register_volatile(struct device
*dev
, unsigned int reg
)
759 static const struct regmap_config ssm2518_regmap_config
= {
763 .max_register
= SSM2518_REG_DRC_9
,
764 .volatile_reg
= ssm2518_register_volatile
,
766 .cache_type
= REGCACHE_RBTREE
,
767 .reg_defaults
= ssm2518_reg_defaults
,
768 .num_reg_defaults
= ARRAY_SIZE(ssm2518_reg_defaults
),
771 static int ssm2518_i2c_probe(struct i2c_client
*i2c
,
772 const struct i2c_device_id
*id
)
774 struct ssm2518_platform_data
*pdata
= i2c
->dev
.platform_data
;
775 struct ssm2518
*ssm2518
;
778 ssm2518
= devm_kzalloc(&i2c
->dev
, sizeof(*ssm2518
), GFP_KERNEL
);
783 ssm2518
->enable_gpio
= pdata
->enable_gpio
;
784 } else if (i2c
->dev
.of_node
) {
785 ssm2518
->enable_gpio
= of_get_gpio(i2c
->dev
.of_node
, 0);
786 if (ssm2518
->enable_gpio
< 0 && ssm2518
->enable_gpio
!= -ENOENT
)
787 return ssm2518
->enable_gpio
;
789 ssm2518
->enable_gpio
= -1;
792 if (gpio_is_valid(ssm2518
->enable_gpio
)) {
793 ret
= devm_gpio_request_one(&i2c
->dev
, ssm2518
->enable_gpio
,
794 GPIOF_OUT_INIT_HIGH
, "SSM2518 nSD");
799 i2c_set_clientdata(i2c
, ssm2518
);
801 ssm2518
->regmap
= devm_regmap_init_i2c(i2c
, &ssm2518_regmap_config
);
802 if (IS_ERR(ssm2518
->regmap
))
803 return PTR_ERR(ssm2518
->regmap
);
806 * The reset bit is obviously volatile, but we need to be able to cache
807 * the other bits in the register, so we can't just mark the whole
808 * register as volatile. Since this is the only place where we'll ever
809 * touch the reset bit just bypass the cache for this operation.
811 regcache_cache_bypass(ssm2518
->regmap
, true);
812 ret
= regmap_write(ssm2518
->regmap
, SSM2518_REG_POWER1
,
813 SSM2518_POWER1_RESET
);
814 regcache_cache_bypass(ssm2518
->regmap
, false);
818 ret
= regmap_update_bits(ssm2518
->regmap
, SSM2518_REG_POWER2
,
819 SSM2518_POWER2_APWDN
, 0x00);
823 ret
= ssm2518_set_power(ssm2518
, false);
827 return snd_soc_register_codec(&i2c
->dev
, &ssm2518_codec_driver
,
831 static int ssm2518_i2c_remove(struct i2c_client
*client
)
833 snd_soc_unregister_codec(&client
->dev
);
837 static const struct i2c_device_id ssm2518_i2c_ids
[] = {
841 MODULE_DEVICE_TABLE(i2c
, ssm2518_i2c_ids
);
843 static struct i2c_driver ssm2518_driver
= {
846 .owner
= THIS_MODULE
,
848 .probe
= ssm2518_i2c_probe
,
849 .remove
= ssm2518_i2c_remove
,
850 .id_table
= ssm2518_i2c_ids
,
852 module_i2c_driver(ssm2518_driver
);
854 MODULE_DESCRIPTION("ASoC SSM2518 driver");
855 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
856 MODULE_LICENSE("GPL");