Loading...
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");
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");