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

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

Version: ~ [ linux-5.3-rc5 ] ~ [ linux-5.2.9 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.67 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.139 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.189 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.189 ] ~ [ 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.72 ] ~ [ 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-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ 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 /*
  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 
111 struct 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 
121 static 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 
143 static const DECLARE_TLV_DB_MINMAX_MUTE(ssm2518_vol_tlv, -7125, 2400);
144 static const DECLARE_TLV_DB_SCALE(ssm2518_compressor_tlv, -3400, 200, 0);
145 static const DECLARE_TLV_DB_SCALE(ssm2518_expander_tlv, -8100, 300, 0);
146 static const DECLARE_TLV_DB_SCALE(ssm2518_noise_gate_tlv, -9600, 300, 0);
147 static const DECLARE_TLV_DB_SCALE(ssm2518_post_drc_tlv, -2400, 300, 0);
148 
149 static const DECLARE_TLV_DB_RANGE(ssm2518_limiter_tlv,
150         0, 7, TLV_DB_SCALE_ITEM(-2200, 200, 0),
151         7, 15, TLV_DB_SCALE_ITEM(-800, 100, 0),
152 );
153 
154 static const char * const ssm2518_drc_peak_detector_attack_time_text[] = {
155         "0 ms", "0.1 ms", "0.19 ms", "0.37 ms", "0.75 ms", "1.5 ms", "3 ms",
156         "6 ms", "12 ms", "24 ms", "48 ms", "96 ms", "192 ms", "384 ms",
157         "768 ms", "1536 ms",
158 };
159 
160 static const char * const ssm2518_drc_peak_detector_release_time_text[] = {
161         "0 ms", "1.5 ms", "3 ms", "6 ms", "12 ms", "24 ms", "48 ms", "96 ms",
162         "192 ms", "384 ms", "768 ms", "1536 ms", "3072 ms", "6144 ms",
163         "12288 ms", "24576 ms"
164 };
165 
166 static const char * const ssm2518_drc_hold_time_text[] = {
167         "0 ms", "0.67 ms", "1.33 ms", "2.67 ms", "5.33 ms", "10.66 ms",
168         "21.32 ms", "42.64 ms", "85.28 ms", "170.56 ms", "341.12 ms",
169         "682.24 ms", "1364 ms",
170 };
171 
172 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum,
173         SSM2518_REG_DRC_2, 4, ssm2518_drc_peak_detector_attack_time_text);
174 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum,
175         SSM2518_REG_DRC_2, 0, ssm2518_drc_peak_detector_release_time_text);
176 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum,
177         SSM2518_REG_DRC_6, 4, ssm2518_drc_peak_detector_attack_time_text);
178 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum,
179         SSM2518_REG_DRC_6, 0, ssm2518_drc_peak_detector_release_time_text);
180 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum,
181         SSM2518_REG_DRC_7, 4, ssm2518_drc_hold_time_text);
182 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum,
183         SSM2518_REG_DRC_7, 0, ssm2518_drc_hold_time_text);
184 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum,
185         SSM2518_REG_DRC_9, 0, ssm2518_drc_peak_detector_release_time_text);
186 
187 static 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 
230 static const struct snd_soc_dapm_widget ssm2518_dapm_widgets[] = {
231         SND_SOC_DAPM_DAC("DACL", "HiFi Playback", SSM2518_REG_POWER2, 1, 1),
232         SND_SOC_DAPM_DAC("DACR", "HiFi Playback", SSM2518_REG_POWER2, 2, 1),
233 
234         SND_SOC_DAPM_OUTPUT("OUTL"),
235         SND_SOC_DAPM_OUTPUT("OUTR"),
236 };
237 
238 static const struct snd_soc_dapm_route ssm2518_routes[] = {
239         { "OUTL", NULL, "DACL" },
240         { "OUTR", NULL, "DACR" },
241 };
242 
243 struct ssm2518_mcs_lut {
244         unsigned int rate;
245         const unsigned int *sysclks;
246 };
247 
248 static const unsigned int ssm2518_sysclks_2048000[] = {
249         2048000, 4096000, 8192000, 12288000, 16384000, 24576000,
250         3200000, 6400000, 12800000, 0
251 };
252 
253 static const unsigned int ssm2518_sysclks_2822000[] = {
254         2822000, 5644800, 11289600, 16934400, 22579200, 33868800,
255         4410000, 8820000, 17640000, 0
256 };
257 
258 static const unsigned int ssm2518_sysclks_3072000[] = {
259         3072000, 6144000, 12288000, 16384000, 24576000, 38864000,
260         4800000, 9600000, 19200000, 0
261 };
262 
263 static const struct ssm2518_mcs_lut ssm2518_mcs_lut[] = {
264         { 8000,  ssm2518_sysclks_2048000, },
265         { 11025, ssm2518_sysclks_2822000, },
266         { 12000, ssm2518_sysclks_3072000, },
267         { 16000, ssm2518_sysclks_2048000, },
268         { 24000, ssm2518_sysclks_3072000, },
269         { 22050, ssm2518_sysclks_2822000, },
270         { 32000, ssm2518_sysclks_2048000, },
271         { 44100, ssm2518_sysclks_2822000, },
272         { 48000, ssm2518_sysclks_3072000, },
273         { 96000, ssm2518_sysclks_3072000, },
274 };
275 
276 static const unsigned int ssm2518_rates_2048000[] = {
277         8000, 16000, 32000,
278 };
279 
280 static const struct snd_pcm_hw_constraint_list ssm2518_constraints_2048000 = {
281         .list = ssm2518_rates_2048000,
282         .count = ARRAY_SIZE(ssm2518_rates_2048000),
283 };
284 
285 static const unsigned int ssm2518_rates_2822000[] = {
286         11025, 22050, 44100,
287 };
288 
289 static const struct snd_pcm_hw_constraint_list ssm2518_constraints_2822000 = {
290         .list = ssm2518_rates_2822000,
291         .count = ARRAY_SIZE(ssm2518_rates_2822000),
292 };
293 
294 static const unsigned int ssm2518_rates_3072000[] = {
295         12000, 24000, 48000, 96000,
296 };
297 
298 static const struct snd_pcm_hw_constraint_list ssm2518_constraints_3072000 = {
299         .list = ssm2518_rates_3072000,
300         .count = ARRAY_SIZE(ssm2518_rates_3072000),
301 };
302 
303 static const unsigned int ssm2518_rates_12288000[] = {
304         8000, 12000, 16000, 24000, 32000, 48000, 96000,
305 };
306 
307 static const struct snd_pcm_hw_constraint_list ssm2518_constraints_12288000 = {
308         .list = ssm2518_rates_12288000,
309         .count = ARRAY_SIZE(ssm2518_rates_12288000),
310 };
311 
312 static 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 
336 static 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 
392 static 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 
406 static 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 
477 static 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 
501 static 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 
524 static 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 
609 static 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 
624 static 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 
632 static 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 
644 static 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 
713 static 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 
728 static 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 
739 static 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 
799 static 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
806 static const struct of_device_id ssm2518_dt_ids[] = {
807         { .compatible = "adi,ssm2518", },
808         { }
809 };
810 MODULE_DEVICE_TABLE(of, ssm2518_dt_ids);
811 #endif
812 
813 static const struct i2c_device_id ssm2518_i2c_ids[] = {
814         { "ssm2518", 0 },
815         { }
816 };
817 MODULE_DEVICE_TABLE(i2c, ssm2518_i2c_ids);
818 
819 static 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 };
828 module_i2c_driver(ssm2518_driver);
829 
830 MODULE_DESCRIPTION("ASoC SSM2518 driver");
831 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
832 MODULE_LICENSE("GPL");
833 

~ [ 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