~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/codecs/ssm2518.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
109 struct 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 
119 static 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 
141 static const DECLARE_TLV_DB_MINMAX_MUTE(ssm2518_vol_tlv, -7125, 2400);
142 static const DECLARE_TLV_DB_SCALE(ssm2518_compressor_tlv, -3400, 200, 0);
143 static const DECLARE_TLV_DB_SCALE(ssm2518_expander_tlv, -8100, 300, 0);
144 static const DECLARE_TLV_DB_SCALE(ssm2518_noise_gate_tlv, -9600, 300, 0);
145 static const DECLARE_TLV_DB_SCALE(ssm2518_post_drc_tlv, -2400, 300, 0);
146 
147 static 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 
152 static 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 
158 static 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 
164 static 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 
170 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum,
171         SSM2518_REG_DRC_2, 4, ssm2518_drc_peak_detector_attack_time_text);
172 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum,
173         SSM2518_REG_DRC_2, 0, ssm2518_drc_peak_detector_release_time_text);
174 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum,
175         SSM2518_REG_DRC_6, 4, ssm2518_drc_peak_detector_attack_time_text);
176 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum,
177         SSM2518_REG_DRC_6, 0, ssm2518_drc_peak_detector_release_time_text);
178 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum,
179         SSM2518_REG_DRC_7, 4, ssm2518_drc_hold_time_text);
180 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum,
181         SSM2518_REG_DRC_7, 0, ssm2518_drc_hold_time_text);
182 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum,
183         SSM2518_REG_DRC_9, 0, ssm2518_drc_peak_detector_release_time_text);
184 
185 static 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 
228 static 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 
236 static const struct snd_soc_dapm_route ssm2518_routes[] = {
237         { "OUTL", NULL, "DACL" },
238         { "OUTR", NULL, "DACR" },
239 };
240 
241 struct ssm2518_mcs_lut {
242         unsigned int rate;
243         const unsigned int *sysclks;
244 };
245 
246 static const unsigned int ssm2518_sysclks_2048000[] = {
247         2048000, 4096000, 8192000, 12288000, 16384000, 24576000,
248         3200000, 6400000, 12800000, 0
249 };
250 
251 static const unsigned int ssm2518_sysclks_2822000[] = {
252         2822000, 5644800, 11289600, 16934400, 22579200, 33868800,
253         4410000, 8820000, 17640000, 0
254 };
255 
256 static const unsigned int ssm2518_sysclks_3072000[] = {
257         3072000, 6144000, 12288000, 16384000, 24576000, 38864000,
258         4800000, 9600000, 19200000, 0
259 };
260 
261 static 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 
274 static const unsigned int ssm2518_rates_2048000[] = {
275         8000, 16000, 32000,
276 };
277 
278 static const struct snd_pcm_hw_constraint_list ssm2518_constraints_2048000 = {
279         .list = ssm2518_rates_2048000,
280         .count = ARRAY_SIZE(ssm2518_rates_2048000),
281 };
282 
283 static const unsigned int ssm2518_rates_2822000[] = {
284         11025, 22050, 44100,
285 };
286 
287 static const struct snd_pcm_hw_constraint_list ssm2518_constraints_2822000 = {
288         .list = ssm2518_rates_2822000,
289         .count = ARRAY_SIZE(ssm2518_rates_2822000),
290 };
291 
292 static const unsigned int ssm2518_rates_3072000[] = {
293         12000, 24000, 48000, 96000,
294 };
295 
296 static const struct snd_pcm_hw_constraint_list ssm2518_constraints_3072000 = {
297         .list = ssm2518_rates_3072000,
298         .count = ARRAY_SIZE(ssm2518_rates_3072000),
299 };
300 
301 static const unsigned int ssm2518_rates_12288000[] = {
302         8000, 12000, 16000, 24000, 32000, 48000, 96000,
303 };
304 
305 static const struct snd_pcm_hw_constraint_list ssm2518_constraints_12288000 = {
306         .list = ssm2518_rates_12288000,
307         .count = ARRAY_SIZE(ssm2518_rates_12288000),
308 };
309 
310 static 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 
334 static 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 
390 static 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 
404 static 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 
475 static 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 
499 static 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 
522 static 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 
607 static 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 
622 static 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 
631 static 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 
643 static 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 
712 static 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 
725 static 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 
736 static 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
788 static const struct of_device_id ssm2518_dt_ids[] = {
789         { .compatible = "adi,ssm2518", },
790         { }
791 };
792 MODULE_DEVICE_TABLE(of, ssm2518_dt_ids);
793 #endif
794 
795 static const struct i2c_device_id ssm2518_i2c_ids[] = {
796         { "ssm2518" },
797         { }
798 };
799 MODULE_DEVICE_TABLE(i2c, ssm2518_i2c_ids);
800 
801 static 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 };
809 module_i2c_driver(ssm2518_driver);
810 
811 MODULE_DESCRIPTION("ASoC SSM2518 driver");
812 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
813 MODULE_LICENSE("GPL");
814 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php