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

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

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

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp