0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/module.h>
0010 #include <linux/init.h>
0011 #include <linux/i2c.h>
0012 #include <linux/regmap.h>
0013 #include <linux/slab.h>
0014 #include <linux/gpio.h>
0015 #include <linux/of_gpio.h>
0016 #include <linux/platform_data/ssm2518.h>
0017 #include <sound/core.h>
0018 #include <sound/pcm.h>
0019 #include <sound/pcm_params.h>
0020 #include <sound/soc.h>
0021 #include <sound/initval.h>
0022 #include <sound/tlv.h>
0023
0024 #include "ssm2518.h"
0025
0026 #define SSM2518_REG_POWER1 0x00
0027 #define SSM2518_REG_CLOCK 0x01
0028 #define SSM2518_REG_SAI_CTRL1 0x02
0029 #define SSM2518_REG_SAI_CTRL2 0x03
0030 #define SSM2518_REG_CHAN_MAP 0x04
0031 #define SSM2518_REG_LEFT_VOL 0x05
0032 #define SSM2518_REG_RIGHT_VOL 0x06
0033 #define SSM2518_REG_MUTE_CTRL 0x07
0034 #define SSM2518_REG_FAULT_CTRL 0x08
0035 #define SSM2518_REG_POWER2 0x09
0036 #define SSM2518_REG_DRC_1 0x0a
0037 #define SSM2518_REG_DRC_2 0x0b
0038 #define SSM2518_REG_DRC_3 0x0c
0039 #define SSM2518_REG_DRC_4 0x0d
0040 #define SSM2518_REG_DRC_5 0x0e
0041 #define SSM2518_REG_DRC_6 0x0f
0042 #define SSM2518_REG_DRC_7 0x10
0043 #define SSM2518_REG_DRC_8 0x11
0044 #define SSM2518_REG_DRC_9 0x12
0045
0046 #define SSM2518_POWER1_RESET BIT(7)
0047 #define SSM2518_POWER1_NO_BCLK BIT(5)
0048 #define SSM2518_POWER1_MCS_MASK (0xf << 1)
0049 #define SSM2518_POWER1_MCS_64FS (0x0 << 1)
0050 #define SSM2518_POWER1_MCS_128FS (0x1 << 1)
0051 #define SSM2518_POWER1_MCS_256FS (0x2 << 1)
0052 #define SSM2518_POWER1_MCS_384FS (0x3 << 1)
0053 #define SSM2518_POWER1_MCS_512FS (0x4 << 1)
0054 #define SSM2518_POWER1_MCS_768FS (0x5 << 1)
0055 #define SSM2518_POWER1_MCS_100FS (0x6 << 1)
0056 #define SSM2518_POWER1_MCS_200FS (0x7 << 1)
0057 #define SSM2518_POWER1_MCS_400FS (0x8 << 1)
0058 #define SSM2518_POWER1_SPWDN BIT(0)
0059
0060 #define SSM2518_CLOCK_ASR BIT(0)
0061
0062 #define SSM2518_SAI_CTRL1_FMT_MASK (0x3 << 5)
0063 #define SSM2518_SAI_CTRL1_FMT_I2S (0x0 << 5)
0064 #define SSM2518_SAI_CTRL1_FMT_LJ (0x1 << 5)
0065 #define SSM2518_SAI_CTRL1_FMT_RJ_24BIT (0x2 << 5)
0066 #define SSM2518_SAI_CTRL1_FMT_RJ_16BIT (0x3 << 5)
0067
0068 #define SSM2518_SAI_CTRL1_SAI_MASK (0x7 << 2)
0069 #define SSM2518_SAI_CTRL1_SAI_I2S (0x0 << 2)
0070 #define SSM2518_SAI_CTRL1_SAI_TDM_2 (0x1 << 2)
0071 #define SSM2518_SAI_CTRL1_SAI_TDM_4 (0x2 << 2)
0072 #define SSM2518_SAI_CTRL1_SAI_TDM_8 (0x3 << 2)
0073 #define SSM2518_SAI_CTRL1_SAI_TDM_16 (0x4 << 2)
0074 #define SSM2518_SAI_CTRL1_SAI_MONO (0x5 << 2)
0075
0076 #define SSM2518_SAI_CTRL1_FS_MASK (0x3)
0077 #define SSM2518_SAI_CTRL1_FS_8000_12000 (0x0)
0078 #define SSM2518_SAI_CTRL1_FS_16000_24000 (0x1)
0079 #define SSM2518_SAI_CTRL1_FS_32000_48000 (0x2)
0080 #define SSM2518_SAI_CTRL1_FS_64000_96000 (0x3)
0081
0082 #define SSM2518_SAI_CTRL2_BCLK_INTERAL BIT(7)
0083 #define SSM2518_SAI_CTRL2_LRCLK_PULSE BIT(6)
0084 #define SSM2518_SAI_CTRL2_LRCLK_INVERT BIT(5)
0085 #define SSM2518_SAI_CTRL2_MSB BIT(4)
0086 #define SSM2518_SAI_CTRL2_SLOT_WIDTH_MASK (0x3 << 2)
0087 #define SSM2518_SAI_CTRL2_SLOT_WIDTH_32 (0x0 << 2)
0088 #define SSM2518_SAI_CTRL2_SLOT_WIDTH_24 (0x1 << 2)
0089 #define SSM2518_SAI_CTRL2_SLOT_WIDTH_16 (0x2 << 2)
0090 #define SSM2518_SAI_CTRL2_BCLK_INVERT BIT(1)
0091
0092 #define SSM2518_CHAN_MAP_RIGHT_SLOT_OFFSET 4
0093 #define SSM2518_CHAN_MAP_RIGHT_SLOT_MASK 0xf0
0094 #define SSM2518_CHAN_MAP_LEFT_SLOT_OFFSET 0
0095 #define SSM2518_CHAN_MAP_LEFT_SLOT_MASK 0x0f
0096
0097 #define SSM2518_MUTE_CTRL_ANA_GAIN BIT(5)
0098 #define SSM2518_MUTE_CTRL_MUTE_MASTER BIT(0)
0099
0100 #define SSM2518_POWER2_APWDN BIT(0)
0101
0102 #define SSM2518_DAC_MUTE BIT(6)
0103 #define SSM2518_DAC_FS_MASK 0x07
0104 #define SSM2518_DAC_FS_8000 0x00
0105 #define SSM2518_DAC_FS_16000 0x01
0106 #define SSM2518_DAC_FS_32000 0x02
0107 #define SSM2518_DAC_FS_64000 0x03
0108 #define SSM2518_DAC_FS_128000 0x04
0109
0110 struct ssm2518 {
0111 struct regmap *regmap;
0112 bool right_j;
0113
0114 unsigned int sysclk;
0115 const struct snd_pcm_hw_constraint_list *constraints;
0116
0117 int enable_gpio;
0118 };
0119
0120 static const struct reg_default ssm2518_reg_defaults[] = {
0121 { 0x00, 0x05 },
0122 { 0x01, 0x00 },
0123 { 0x02, 0x02 },
0124 { 0x03, 0x00 },
0125 { 0x04, 0x10 },
0126 { 0x05, 0x40 },
0127 { 0x06, 0x40 },
0128 { 0x07, 0x81 },
0129 { 0x08, 0x0c },
0130 { 0x09, 0x99 },
0131 { 0x0a, 0x7c },
0132 { 0x0b, 0x5b },
0133 { 0x0c, 0x57 },
0134 { 0x0d, 0x89 },
0135 { 0x0e, 0x8c },
0136 { 0x0f, 0x77 },
0137 { 0x10, 0x26 },
0138 { 0x11, 0x1c },
0139 { 0x12, 0x97 },
0140 };
0141
0142 static const DECLARE_TLV_DB_MINMAX_MUTE(ssm2518_vol_tlv, -7125, 2400);
0143 static const DECLARE_TLV_DB_SCALE(ssm2518_compressor_tlv, -3400, 200, 0);
0144 static const DECLARE_TLV_DB_SCALE(ssm2518_expander_tlv, -8100, 300, 0);
0145 static const DECLARE_TLV_DB_SCALE(ssm2518_noise_gate_tlv, -9600, 300, 0);
0146 static const DECLARE_TLV_DB_SCALE(ssm2518_post_drc_tlv, -2400, 300, 0);
0147
0148 static const DECLARE_TLV_DB_RANGE(ssm2518_limiter_tlv,
0149 0, 7, TLV_DB_SCALE_ITEM(-2200, 200, 0),
0150 7, 15, TLV_DB_SCALE_ITEM(-800, 100, 0),
0151 );
0152
0153 static const char * const ssm2518_drc_peak_detector_attack_time_text[] = {
0154 "0 ms", "0.1 ms", "0.19 ms", "0.37 ms", "0.75 ms", "1.5 ms", "3 ms",
0155 "6 ms", "12 ms", "24 ms", "48 ms", "96 ms", "192 ms", "384 ms",
0156 "768 ms", "1536 ms",
0157 };
0158
0159 static const char * const ssm2518_drc_peak_detector_release_time_text[] = {
0160 "0 ms", "1.5 ms", "3 ms", "6 ms", "12 ms", "24 ms", "48 ms", "96 ms",
0161 "192 ms", "384 ms", "768 ms", "1536 ms", "3072 ms", "6144 ms",
0162 "12288 ms", "24576 ms"
0163 };
0164
0165 static const char * const ssm2518_drc_hold_time_text[] = {
0166 "0 ms", "0.67 ms", "1.33 ms", "2.67 ms", "5.33 ms", "10.66 ms",
0167 "21.32 ms", "42.64 ms", "85.28 ms", "170.56 ms", "341.12 ms",
0168 "682.24 ms", "1364 ms",
0169 };
0170
0171 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum,
0172 SSM2518_REG_DRC_2, 4, ssm2518_drc_peak_detector_attack_time_text);
0173 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum,
0174 SSM2518_REG_DRC_2, 0, ssm2518_drc_peak_detector_release_time_text);
0175 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum,
0176 SSM2518_REG_DRC_6, 4, ssm2518_drc_peak_detector_attack_time_text);
0177 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum,
0178 SSM2518_REG_DRC_6, 0, ssm2518_drc_peak_detector_release_time_text);
0179 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum,
0180 SSM2518_REG_DRC_7, 4, ssm2518_drc_hold_time_text);
0181 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum,
0182 SSM2518_REG_DRC_7, 0, ssm2518_drc_hold_time_text);
0183 static SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum,
0184 SSM2518_REG_DRC_9, 0, ssm2518_drc_peak_detector_release_time_text);
0185
0186 static const struct snd_kcontrol_new ssm2518_snd_controls[] = {
0187 SOC_SINGLE("Playback De-emphasis Switch", SSM2518_REG_MUTE_CTRL,
0188 4, 1, 0),
0189 SOC_DOUBLE_R_TLV("Master Playback Volume", SSM2518_REG_LEFT_VOL,
0190 SSM2518_REG_RIGHT_VOL, 0, 0xff, 1, ssm2518_vol_tlv),
0191 SOC_DOUBLE("Master Playback Switch", SSM2518_REG_MUTE_CTRL, 2, 1, 1, 1),
0192
0193 SOC_SINGLE("Amp Low Power Mode Switch", SSM2518_REG_POWER2, 4, 1, 0),
0194 SOC_SINGLE("DAC Low Power Mode Switch", SSM2518_REG_POWER2, 3, 1, 0),
0195
0196 SOC_SINGLE("DRC Limiter Switch", SSM2518_REG_DRC_1, 5, 1, 0),
0197 SOC_SINGLE("DRC Compressor Switch", SSM2518_REG_DRC_1, 4, 1, 0),
0198 SOC_SINGLE("DRC Expander Switch", SSM2518_REG_DRC_1, 3, 1, 0),
0199 SOC_SINGLE("DRC Noise Gate Switch", SSM2518_REG_DRC_1, 2, 1, 0),
0200 SOC_DOUBLE("DRC Switch", SSM2518_REG_DRC_1, 0, 1, 1, 0),
0201
0202 SOC_SINGLE_TLV("DRC Limiter Threshold Volume",
0203 SSM2518_REG_DRC_3, 4, 15, 1, ssm2518_limiter_tlv),
0204 SOC_SINGLE_TLV("DRC Compressor Lower Threshold Volume",
0205 SSM2518_REG_DRC_3, 0, 15, 1, ssm2518_compressor_tlv),
0206 SOC_SINGLE_TLV("DRC Expander Upper Threshold Volume", SSM2518_REG_DRC_4,
0207 4, 15, 1, ssm2518_expander_tlv),
0208 SOC_SINGLE_TLV("DRC Noise Gate Threshold Volume",
0209 SSM2518_REG_DRC_4, 0, 15, 1, ssm2518_noise_gate_tlv),
0210 SOC_SINGLE_TLV("DRC Upper Output Threshold Volume",
0211 SSM2518_REG_DRC_5, 4, 15, 1, ssm2518_limiter_tlv),
0212 SOC_SINGLE_TLV("DRC Lower Output Threshold Volume",
0213 SSM2518_REG_DRC_5, 0, 15, 1, ssm2518_noise_gate_tlv),
0214 SOC_SINGLE_TLV("DRC Post Volume", SSM2518_REG_DRC_8,
0215 2, 15, 1, ssm2518_post_drc_tlv),
0216
0217 SOC_ENUM("DRC Peak Detector Attack Time",
0218 ssm2518_drc_peak_detector_attack_time_enum),
0219 SOC_ENUM("DRC Peak Detector Release Time",
0220 ssm2518_drc_peak_detector_release_time_enum),
0221 SOC_ENUM("DRC Attack Time", ssm2518_drc_attack_time_enum),
0222 SOC_ENUM("DRC Decay Time", ssm2518_drc_decay_time_enum),
0223 SOC_ENUM("DRC Hold Time", ssm2518_drc_hold_time_enum),
0224 SOC_ENUM("DRC Noise Gate Hold Time",
0225 ssm2518_drc_noise_gate_hold_time_enum),
0226 SOC_ENUM("DRC RMS Averaging Time", ssm2518_drc_rms_averaging_time_enum),
0227 };
0228
0229 static const struct snd_soc_dapm_widget ssm2518_dapm_widgets[] = {
0230 SND_SOC_DAPM_DAC("DACL", "HiFi Playback", SSM2518_REG_POWER2, 1, 1),
0231 SND_SOC_DAPM_DAC("DACR", "HiFi Playback", SSM2518_REG_POWER2, 2, 1),
0232
0233 SND_SOC_DAPM_OUTPUT("OUTL"),
0234 SND_SOC_DAPM_OUTPUT("OUTR"),
0235 };
0236
0237 static const struct snd_soc_dapm_route ssm2518_routes[] = {
0238 { "OUTL", NULL, "DACL" },
0239 { "OUTR", NULL, "DACR" },
0240 };
0241
0242 struct ssm2518_mcs_lut {
0243 unsigned int rate;
0244 const unsigned int *sysclks;
0245 };
0246
0247 static const unsigned int ssm2518_sysclks_2048000[] = {
0248 2048000, 4096000, 8192000, 12288000, 16384000, 24576000,
0249 3200000, 6400000, 12800000, 0
0250 };
0251
0252 static const unsigned int ssm2518_sysclks_2822000[] = {
0253 2822000, 5644800, 11289600, 16934400, 22579200, 33868800,
0254 4410000, 8820000, 17640000, 0
0255 };
0256
0257 static const unsigned int ssm2518_sysclks_3072000[] = {
0258 3072000, 6144000, 12288000, 16384000, 24576000, 38864000,
0259 4800000, 9600000, 19200000, 0
0260 };
0261
0262 static const struct ssm2518_mcs_lut ssm2518_mcs_lut[] = {
0263 { 8000, ssm2518_sysclks_2048000, },
0264 { 11025, ssm2518_sysclks_2822000, },
0265 { 12000, ssm2518_sysclks_3072000, },
0266 { 16000, ssm2518_sysclks_2048000, },
0267 { 24000, ssm2518_sysclks_3072000, },
0268 { 22050, ssm2518_sysclks_2822000, },
0269 { 32000, ssm2518_sysclks_2048000, },
0270 { 44100, ssm2518_sysclks_2822000, },
0271 { 48000, ssm2518_sysclks_3072000, },
0272 { 96000, ssm2518_sysclks_3072000, },
0273 };
0274
0275 static const unsigned int ssm2518_rates_2048000[] = {
0276 8000, 16000, 32000,
0277 };
0278
0279 static const struct snd_pcm_hw_constraint_list ssm2518_constraints_2048000 = {
0280 .list = ssm2518_rates_2048000,
0281 .count = ARRAY_SIZE(ssm2518_rates_2048000),
0282 };
0283
0284 static const unsigned int ssm2518_rates_2822000[] = {
0285 11025, 22050, 44100,
0286 };
0287
0288 static const struct snd_pcm_hw_constraint_list ssm2518_constraints_2822000 = {
0289 .list = ssm2518_rates_2822000,
0290 .count = ARRAY_SIZE(ssm2518_rates_2822000),
0291 };
0292
0293 static const unsigned int ssm2518_rates_3072000[] = {
0294 12000, 24000, 48000, 96000,
0295 };
0296
0297 static const struct snd_pcm_hw_constraint_list ssm2518_constraints_3072000 = {
0298 .list = ssm2518_rates_3072000,
0299 .count = ARRAY_SIZE(ssm2518_rates_3072000),
0300 };
0301
0302 static const unsigned int ssm2518_rates_12288000[] = {
0303 8000, 12000, 16000, 24000, 32000, 48000, 96000,
0304 };
0305
0306 static const struct snd_pcm_hw_constraint_list ssm2518_constraints_12288000 = {
0307 .list = ssm2518_rates_12288000,
0308 .count = ARRAY_SIZE(ssm2518_rates_12288000),
0309 };
0310
0311 static int ssm2518_lookup_mcs(struct ssm2518 *ssm2518,
0312 unsigned int rate)
0313 {
0314 const unsigned int *sysclks = NULL;
0315 int i;
0316
0317 for (i = 0; i < ARRAY_SIZE(ssm2518_mcs_lut); i++) {
0318 if (ssm2518_mcs_lut[i].rate == rate) {
0319 sysclks = ssm2518_mcs_lut[i].sysclks;
0320 break;
0321 }
0322 }
0323
0324 if (!sysclks)
0325 return -EINVAL;
0326
0327 for (i = 0; sysclks[i]; i++) {
0328 if (sysclks[i] == ssm2518->sysclk)
0329 return i;
0330 }
0331
0332 return -EINVAL;
0333 }
0334
0335 static int ssm2518_hw_params(struct snd_pcm_substream *substream,
0336 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
0337 {
0338 struct snd_soc_component *component = dai->component;
0339 struct ssm2518 *ssm2518 = snd_soc_component_get_drvdata(component);
0340 unsigned int rate = params_rate(params);
0341 unsigned int ctrl1, ctrl1_mask;
0342 int mcs;
0343 int ret;
0344
0345 mcs = ssm2518_lookup_mcs(ssm2518, rate);
0346 if (mcs < 0)
0347 return mcs;
0348
0349 ctrl1_mask = SSM2518_SAI_CTRL1_FS_MASK;
0350
0351 if (rate >= 8000 && rate <= 12000)
0352 ctrl1 = SSM2518_SAI_CTRL1_FS_8000_12000;
0353 else if (rate >= 16000 && rate <= 24000)
0354 ctrl1 = SSM2518_SAI_CTRL1_FS_16000_24000;
0355 else if (rate >= 32000 && rate <= 48000)
0356 ctrl1 = SSM2518_SAI_CTRL1_FS_32000_48000;
0357 else if (rate >= 64000 && rate <= 96000)
0358 ctrl1 = SSM2518_SAI_CTRL1_FS_64000_96000;
0359 else
0360 return -EINVAL;
0361
0362 if (ssm2518->right_j) {
0363 switch (params_width(params)) {
0364 case 16:
0365 ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_16BIT;
0366 break;
0367 case 24:
0368 ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_24BIT;
0369 break;
0370 default:
0371 return -EINVAL;
0372 }
0373 ctrl1_mask |= SSM2518_SAI_CTRL1_FMT_MASK;
0374 }
0375
0376
0377 ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_CLOCK,
0378 SSM2518_CLOCK_ASR, SSM2518_CLOCK_ASR);
0379 if (ret < 0)
0380 return ret;
0381
0382 ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_SAI_CTRL1,
0383 ctrl1_mask, ctrl1);
0384 if (ret < 0)
0385 return ret;
0386
0387 return regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1,
0388 SSM2518_POWER1_MCS_MASK, mcs << 1);
0389 }
0390
0391 static int ssm2518_mute(struct snd_soc_dai *dai, int mute, int direction)
0392 {
0393 struct ssm2518 *ssm2518 = snd_soc_component_get_drvdata(dai->component);
0394 unsigned int val;
0395
0396 if (mute)
0397 val = SSM2518_MUTE_CTRL_MUTE_MASTER;
0398 else
0399 val = 0;
0400
0401 return regmap_update_bits(ssm2518->regmap, SSM2518_REG_MUTE_CTRL,
0402 SSM2518_MUTE_CTRL_MUTE_MASTER, val);
0403 }
0404
0405 static int ssm2518_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
0406 {
0407 struct ssm2518 *ssm2518 = snd_soc_component_get_drvdata(dai->component);
0408 unsigned int ctrl1 = 0, ctrl2 = 0;
0409 bool invert_fclk;
0410 int ret;
0411
0412 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
0413 case SND_SOC_DAIFMT_CBC_CFC:
0414 break;
0415 default:
0416 return -EINVAL;
0417 }
0418
0419 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
0420 case SND_SOC_DAIFMT_NB_NF:
0421 invert_fclk = false;
0422 break;
0423 case SND_SOC_DAIFMT_IB_NF:
0424 ctrl2 |= SSM2518_SAI_CTRL2_BCLK_INVERT;
0425 invert_fclk = false;
0426 break;
0427 case SND_SOC_DAIFMT_NB_IF:
0428 invert_fclk = true;
0429 break;
0430 case SND_SOC_DAIFMT_IB_IF:
0431 ctrl2 |= SSM2518_SAI_CTRL2_BCLK_INVERT;
0432 invert_fclk = true;
0433 break;
0434 default:
0435 return -EINVAL;
0436 }
0437
0438 ssm2518->right_j = false;
0439 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
0440 case SND_SOC_DAIFMT_I2S:
0441 ctrl1 |= SSM2518_SAI_CTRL1_FMT_I2S;
0442 break;
0443 case SND_SOC_DAIFMT_LEFT_J:
0444 ctrl1 |= SSM2518_SAI_CTRL1_FMT_LJ;
0445 invert_fclk = !invert_fclk;
0446 break;
0447 case SND_SOC_DAIFMT_RIGHT_J:
0448 ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_24BIT;
0449 ssm2518->right_j = true;
0450 invert_fclk = !invert_fclk;
0451 break;
0452 case SND_SOC_DAIFMT_DSP_A:
0453 ctrl2 |= SSM2518_SAI_CTRL2_LRCLK_PULSE;
0454 ctrl1 |= SSM2518_SAI_CTRL1_FMT_I2S;
0455 invert_fclk = false;
0456 break;
0457 case SND_SOC_DAIFMT_DSP_B:
0458 ctrl2 |= SSM2518_SAI_CTRL2_LRCLK_PULSE;
0459 ctrl1 |= SSM2518_SAI_CTRL1_FMT_LJ;
0460 invert_fclk = false;
0461 break;
0462 default:
0463 return -EINVAL;
0464 }
0465
0466 if (invert_fclk)
0467 ctrl2 |= SSM2518_SAI_CTRL2_LRCLK_INVERT;
0468
0469 ret = regmap_write(ssm2518->regmap, SSM2518_REG_SAI_CTRL1, ctrl1);
0470 if (ret)
0471 return ret;
0472
0473 return regmap_write(ssm2518->regmap, SSM2518_REG_SAI_CTRL2, ctrl2);
0474 }
0475
0476 static int ssm2518_set_power(struct ssm2518 *ssm2518, bool enable)
0477 {
0478 int ret = 0;
0479
0480 if (!enable) {
0481 ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1,
0482 SSM2518_POWER1_SPWDN, SSM2518_POWER1_SPWDN);
0483 regcache_mark_dirty(ssm2518->regmap);
0484 }
0485
0486 if (gpio_is_valid(ssm2518->enable_gpio))
0487 gpio_set_value(ssm2518->enable_gpio, enable);
0488
0489 regcache_cache_only(ssm2518->regmap, !enable);
0490
0491 if (enable) {
0492 ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1,
0493 SSM2518_POWER1_SPWDN | SSM2518_POWER1_RESET, 0x00);
0494 regcache_sync(ssm2518->regmap);
0495 }
0496
0497 return ret;
0498 }
0499
0500 static int ssm2518_set_bias_level(struct snd_soc_component *component,
0501 enum snd_soc_bias_level level)
0502 {
0503 struct ssm2518 *ssm2518 = snd_soc_component_get_drvdata(component);
0504 int ret = 0;
0505
0506 switch (level) {
0507 case SND_SOC_BIAS_ON:
0508 break;
0509 case SND_SOC_BIAS_PREPARE:
0510 break;
0511 case SND_SOC_BIAS_STANDBY:
0512 if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
0513 ret = ssm2518_set_power(ssm2518, true);
0514 break;
0515 case SND_SOC_BIAS_OFF:
0516 ret = ssm2518_set_power(ssm2518, false);
0517 break;
0518 }
0519
0520 return ret;
0521 }
0522
0523 static int ssm2518_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
0524 unsigned int rx_mask, int slots, int width)
0525 {
0526 struct ssm2518 *ssm2518 = snd_soc_component_get_drvdata(dai->component);
0527 unsigned int ctrl1, ctrl2;
0528 int left_slot, right_slot;
0529 int ret;
0530
0531 if (slots == 0)
0532 return regmap_update_bits(ssm2518->regmap,
0533 SSM2518_REG_SAI_CTRL1, SSM2518_SAI_CTRL1_SAI_MASK,
0534 SSM2518_SAI_CTRL1_SAI_I2S);
0535
0536 if (tx_mask == 0 || rx_mask != 0)
0537 return -EINVAL;
0538
0539 if (slots == 1) {
0540 if (tx_mask != 1)
0541 return -EINVAL;
0542 left_slot = 0;
0543 right_slot = 0;
0544 } else {
0545
0546 left_slot = __ffs(tx_mask);
0547 tx_mask &= ~(1 << left_slot);
0548 if (tx_mask == 0) {
0549 right_slot = left_slot;
0550 } else {
0551 right_slot = __ffs(tx_mask);
0552 tx_mask &= ~(1 << right_slot);
0553 }
0554 }
0555
0556 if (tx_mask != 0 || left_slot >= slots || right_slot >= slots)
0557 return -EINVAL;
0558
0559 switch (width) {
0560 case 16:
0561 ctrl2 = SSM2518_SAI_CTRL2_SLOT_WIDTH_16;
0562 break;
0563 case 24:
0564 ctrl2 = SSM2518_SAI_CTRL2_SLOT_WIDTH_24;
0565 break;
0566 case 32:
0567 ctrl2 = SSM2518_SAI_CTRL2_SLOT_WIDTH_32;
0568 break;
0569 default:
0570 return -EINVAL;
0571 }
0572
0573 switch (slots) {
0574 case 1:
0575 ctrl1 = SSM2518_SAI_CTRL1_SAI_MONO;
0576 break;
0577 case 2:
0578 ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_2;
0579 break;
0580 case 4:
0581 ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_4;
0582 break;
0583 case 8:
0584 ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_8;
0585 break;
0586 case 16:
0587 ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_16;
0588 break;
0589 default:
0590 return -EINVAL;
0591 }
0592
0593 ret = regmap_write(ssm2518->regmap, SSM2518_REG_CHAN_MAP,
0594 (left_slot << SSM2518_CHAN_MAP_LEFT_SLOT_OFFSET) |
0595 (right_slot << SSM2518_CHAN_MAP_RIGHT_SLOT_OFFSET));
0596 if (ret)
0597 return ret;
0598
0599 ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_SAI_CTRL1,
0600 SSM2518_SAI_CTRL1_SAI_MASK, ctrl1);
0601 if (ret)
0602 return ret;
0603
0604 return regmap_update_bits(ssm2518->regmap, SSM2518_REG_SAI_CTRL2,
0605 SSM2518_SAI_CTRL2_SLOT_WIDTH_MASK, ctrl2);
0606 }
0607
0608 static int ssm2518_startup(struct snd_pcm_substream *substream,
0609 struct snd_soc_dai *dai)
0610 {
0611 struct ssm2518 *ssm2518 = snd_soc_component_get_drvdata(dai->component);
0612
0613 if (ssm2518->constraints)
0614 snd_pcm_hw_constraint_list(substream->runtime, 0,
0615 SNDRV_PCM_HW_PARAM_RATE, ssm2518->constraints);
0616
0617 return 0;
0618 }
0619
0620 #define SSM2518_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
0621 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32)
0622
0623 static const struct snd_soc_dai_ops ssm2518_dai_ops = {
0624 .startup = ssm2518_startup,
0625 .hw_params = ssm2518_hw_params,
0626 .mute_stream = ssm2518_mute,
0627 .set_fmt = ssm2518_set_dai_fmt,
0628 .set_tdm_slot = ssm2518_set_tdm_slot,
0629 .no_capture_mute = 1,
0630 };
0631
0632 static struct snd_soc_dai_driver ssm2518_dai = {
0633 .name = "ssm2518-hifi",
0634 .playback = {
0635 .stream_name = "Playback",
0636 .channels_min = 2,
0637 .channels_max = 2,
0638 .rates = SNDRV_PCM_RATE_8000_96000,
0639 .formats = SSM2518_FORMATS,
0640 },
0641 .ops = &ssm2518_dai_ops,
0642 };
0643
0644 static int ssm2518_set_sysclk(struct snd_soc_component *component, int clk_id,
0645 int source, unsigned int freq, int dir)
0646 {
0647 struct ssm2518 *ssm2518 = snd_soc_component_get_drvdata(component);
0648 unsigned int val;
0649
0650 if (clk_id != SSM2518_SYSCLK)
0651 return -EINVAL;
0652
0653 switch (source) {
0654 case SSM2518_SYSCLK_SRC_MCLK:
0655 val = 0;
0656 break;
0657 case SSM2518_SYSCLK_SRC_BCLK:
0658
0659
0660
0661 val = SSM2518_POWER1_NO_BCLK;
0662 break;
0663 default:
0664 return -EINVAL;
0665 }
0666
0667 switch (freq) {
0668 case 0:
0669 ssm2518->constraints = NULL;
0670 break;
0671 case 2048000:
0672 case 4096000:
0673 case 8192000:
0674 case 3200000:
0675 case 6400000:
0676 case 12800000:
0677 ssm2518->constraints = &ssm2518_constraints_2048000;
0678 break;
0679 case 2822000:
0680 case 5644800:
0681 case 11289600:
0682 case 16934400:
0683 case 22579200:
0684 case 33868800:
0685 case 4410000:
0686 case 8820000:
0687 case 17640000:
0688 ssm2518->constraints = &ssm2518_constraints_2822000;
0689 break;
0690 case 3072000:
0691 case 6144000:
0692 case 38864000:
0693 case 4800000:
0694 case 9600000:
0695 case 19200000:
0696 ssm2518->constraints = &ssm2518_constraints_3072000;
0697 break;
0698 case 12288000:
0699 case 16384000:
0700 case 24576000:
0701 ssm2518->constraints = &ssm2518_constraints_12288000;
0702 break;
0703 default:
0704 return -EINVAL;
0705 }
0706
0707 ssm2518->sysclk = freq;
0708
0709 return regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1,
0710 SSM2518_POWER1_NO_BCLK, val);
0711 }
0712
0713 static const struct snd_soc_component_driver ssm2518_component_driver = {
0714 .set_bias_level = ssm2518_set_bias_level,
0715 .set_sysclk = ssm2518_set_sysclk,
0716 .controls = ssm2518_snd_controls,
0717 .num_controls = ARRAY_SIZE(ssm2518_snd_controls),
0718 .dapm_widgets = ssm2518_dapm_widgets,
0719 .num_dapm_widgets = ARRAY_SIZE(ssm2518_dapm_widgets),
0720 .dapm_routes = ssm2518_routes,
0721 .num_dapm_routes = ARRAY_SIZE(ssm2518_routes),
0722 .use_pmdown_time = 1,
0723 .endianness = 1,
0724 };
0725
0726 static const struct regmap_config ssm2518_regmap_config = {
0727 .val_bits = 8,
0728 .reg_bits = 8,
0729
0730 .max_register = SSM2518_REG_DRC_9,
0731
0732 .cache_type = REGCACHE_RBTREE,
0733 .reg_defaults = ssm2518_reg_defaults,
0734 .num_reg_defaults = ARRAY_SIZE(ssm2518_reg_defaults),
0735 };
0736
0737 static int ssm2518_i2c_probe(struct i2c_client *i2c)
0738 {
0739 struct ssm2518_platform_data *pdata = i2c->dev.platform_data;
0740 struct ssm2518 *ssm2518;
0741 int ret;
0742
0743 ssm2518 = devm_kzalloc(&i2c->dev, sizeof(*ssm2518), GFP_KERNEL);
0744 if (ssm2518 == NULL)
0745 return -ENOMEM;
0746
0747 if (pdata) {
0748 ssm2518->enable_gpio = pdata->enable_gpio;
0749 } else if (i2c->dev.of_node) {
0750 ssm2518->enable_gpio = of_get_gpio(i2c->dev.of_node, 0);
0751 if (ssm2518->enable_gpio < 0 && ssm2518->enable_gpio != -ENOENT)
0752 return ssm2518->enable_gpio;
0753 } else {
0754 ssm2518->enable_gpio = -1;
0755 }
0756
0757 if (gpio_is_valid(ssm2518->enable_gpio)) {
0758 ret = devm_gpio_request_one(&i2c->dev, ssm2518->enable_gpio,
0759 GPIOF_OUT_INIT_HIGH, "SSM2518 nSD");
0760 if (ret)
0761 return ret;
0762 }
0763
0764 i2c_set_clientdata(i2c, ssm2518);
0765
0766 ssm2518->regmap = devm_regmap_init_i2c(i2c, &ssm2518_regmap_config);
0767 if (IS_ERR(ssm2518->regmap))
0768 return PTR_ERR(ssm2518->regmap);
0769
0770
0771
0772
0773
0774
0775
0776 regcache_cache_bypass(ssm2518->regmap, true);
0777 ret = regmap_write(ssm2518->regmap, SSM2518_REG_POWER1,
0778 SSM2518_POWER1_RESET);
0779 regcache_cache_bypass(ssm2518->regmap, false);
0780 if (ret)
0781 return ret;
0782
0783 ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER2,
0784 SSM2518_POWER2_APWDN, 0x00);
0785 if (ret)
0786 return ret;
0787
0788 ret = ssm2518_set_power(ssm2518, false);
0789 if (ret)
0790 return ret;
0791
0792 return devm_snd_soc_register_component(&i2c->dev,
0793 &ssm2518_component_driver,
0794 &ssm2518_dai, 1);
0795 }
0796
0797 #ifdef CONFIG_OF
0798 static const struct of_device_id ssm2518_dt_ids[] = {
0799 { .compatible = "adi,ssm2518", },
0800 { }
0801 };
0802 MODULE_DEVICE_TABLE(of, ssm2518_dt_ids);
0803 #endif
0804
0805 static const struct i2c_device_id ssm2518_i2c_ids[] = {
0806 { "ssm2518", 0 },
0807 { }
0808 };
0809 MODULE_DEVICE_TABLE(i2c, ssm2518_i2c_ids);
0810
0811 static struct i2c_driver ssm2518_driver = {
0812 .driver = {
0813 .name = "ssm2518",
0814 .of_match_table = of_match_ptr(ssm2518_dt_ids),
0815 },
0816 .probe_new = ssm2518_i2c_probe,
0817 .id_table = ssm2518_i2c_ids,
0818 };
0819 module_i2c_driver(ssm2518_driver);
0820
0821 MODULE_DESCRIPTION("ASoC SSM2518 driver");
0822 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
0823 MODULE_LICENSE("GPL");