0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/module.h>
0011 #include <linux/moduleparam.h>
0012 #include <linux/init.h>
0013 #include <linux/delay.h>
0014 #include <linux/pm.h>
0015 #include <linux/i2c.h>
0016 #include <linux/regmap.h>
0017 #include <linux/regulator/consumer.h>
0018 #include <linux/slab.h>
0019 #include <linux/of_device.h>
0020 #include <sound/core.h>
0021 #include <sound/pcm.h>
0022 #include <sound/pcm_params.h>
0023 #include <sound/soc.h>
0024 #include <sound/initval.h>
0025 #include <sound/tlv.h>
0026
0027 #include "wm8523.h"
0028
0029 #define WM8523_NUM_SUPPLIES 2
0030 static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = {
0031 "AVDD",
0032 "LINEVDD",
0033 };
0034
0035 #define WM8523_NUM_RATES 7
0036
0037
0038 struct wm8523_priv {
0039 struct regmap *regmap;
0040 struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES];
0041 unsigned int sysclk;
0042 unsigned int rate_constraint_list[WM8523_NUM_RATES];
0043 struct snd_pcm_hw_constraint_list rate_constraint;
0044 };
0045
0046 static const struct reg_default wm8523_reg_defaults[] = {
0047 { 2, 0x0000 },
0048 { 3, 0x1812 },
0049 { 4, 0x0000 },
0050 { 5, 0x0001 },
0051 { 6, 0x0190 },
0052 { 7, 0x0190 },
0053 { 8, 0x0000 },
0054 };
0055
0056 static bool wm8523_volatile_register(struct device *dev, unsigned int reg)
0057 {
0058 switch (reg) {
0059 case WM8523_DEVICE_ID:
0060 case WM8523_REVISION:
0061 return true;
0062 default:
0063 return false;
0064 }
0065 }
0066
0067 static const DECLARE_TLV_DB_SCALE(dac_tlv, -10000, 25, 0);
0068
0069 static const char *wm8523_zd_count_text[] = {
0070 "1024",
0071 "2048",
0072 };
0073
0074 static SOC_ENUM_SINGLE_DECL(wm8523_zc_count, WM8523_ZERO_DETECT, 0,
0075 wm8523_zd_count_text);
0076
0077 static const struct snd_kcontrol_new wm8523_controls[] = {
0078 SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR,
0079 0, 448, 0, dac_tlv),
0080 SOC_SINGLE("ZC Switch", WM8523_DAC_CTRL3, 4, 1, 0),
0081 SOC_SINGLE("Playback Deemphasis Switch", WM8523_AIF_CTRL1, 8, 1, 0),
0082 SOC_DOUBLE("Playback Switch", WM8523_DAC_CTRL3, 2, 3, 1, 1),
0083 SOC_SINGLE("Volume Ramp Up Switch", WM8523_DAC_CTRL3, 1, 1, 0),
0084 SOC_SINGLE("Volume Ramp Down Switch", WM8523_DAC_CTRL3, 0, 1, 0),
0085 SOC_ENUM("Zero Detect Count", wm8523_zc_count),
0086 };
0087
0088 static const struct snd_soc_dapm_widget wm8523_dapm_widgets[] = {
0089 SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
0090 SND_SOC_DAPM_OUTPUT("LINEVOUTL"),
0091 SND_SOC_DAPM_OUTPUT("LINEVOUTR"),
0092 };
0093
0094 static const struct snd_soc_dapm_route wm8523_dapm_routes[] = {
0095 { "LINEVOUTL", NULL, "DAC" },
0096 { "LINEVOUTR", NULL, "DAC" },
0097 };
0098
0099 static const struct {
0100 int value;
0101 int ratio;
0102 } lrclk_ratios[WM8523_NUM_RATES] = {
0103 { 1, 128 },
0104 { 2, 192 },
0105 { 3, 256 },
0106 { 4, 384 },
0107 { 5, 512 },
0108 { 6, 768 },
0109 { 7, 1152 },
0110 };
0111
0112 static const struct {
0113 int value;
0114 int ratio;
0115 } bclk_ratios[] = {
0116 { 2, 32 },
0117 { 3, 64 },
0118 { 4, 128 },
0119 };
0120
0121 static int wm8523_startup(struct snd_pcm_substream *substream,
0122 struct snd_soc_dai *dai)
0123 {
0124 struct snd_soc_component *component = dai->component;
0125 struct wm8523_priv *wm8523 = snd_soc_component_get_drvdata(component);
0126
0127
0128
0129
0130 if (!wm8523->sysclk) {
0131 dev_err(component->dev,
0132 "No MCLK configured, call set_sysclk() on init\n");
0133 return -EINVAL;
0134 }
0135
0136 snd_pcm_hw_constraint_list(substream->runtime, 0,
0137 SNDRV_PCM_HW_PARAM_RATE,
0138 &wm8523->rate_constraint);
0139
0140 return 0;
0141 }
0142
0143 static int wm8523_hw_params(struct snd_pcm_substream *substream,
0144 struct snd_pcm_hw_params *params,
0145 struct snd_soc_dai *dai)
0146 {
0147 struct snd_soc_component *component = dai->component;
0148 struct wm8523_priv *wm8523 = snd_soc_component_get_drvdata(component);
0149 int i;
0150 u16 aifctrl1 = snd_soc_component_read(component, WM8523_AIF_CTRL1);
0151 u16 aifctrl2 = snd_soc_component_read(component, WM8523_AIF_CTRL2);
0152
0153
0154 for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
0155 if (wm8523->sysclk / params_rate(params) ==
0156 lrclk_ratios[i].ratio)
0157 break;
0158 }
0159
0160
0161 if (i == ARRAY_SIZE(lrclk_ratios)) {
0162 dev_err(component->dev, "MCLK/fs ratio %d unsupported\n",
0163 wm8523->sysclk / params_rate(params));
0164 return -EINVAL;
0165 }
0166
0167 aifctrl2 &= ~WM8523_SR_MASK;
0168 aifctrl2 |= lrclk_ratios[i].value;
0169
0170 if (aifctrl1 & WM8523_AIF_MSTR) {
0171
0172 for (i = 0; i < ARRAY_SIZE(bclk_ratios); i++)
0173 if (params_width(params) * 2 <= bclk_ratios[i].ratio)
0174 break;
0175
0176 if (i == ARRAY_SIZE(bclk_ratios)) {
0177 dev_err(component->dev,
0178 "No matching BCLK/fs ratio for word length %d\n",
0179 params_width(params));
0180 return -EINVAL;
0181 }
0182
0183 aifctrl2 &= ~WM8523_BCLKDIV_MASK;
0184 aifctrl2 |= bclk_ratios[i].value << WM8523_BCLKDIV_SHIFT;
0185 }
0186
0187 aifctrl1 &= ~WM8523_WL_MASK;
0188 switch (params_width(params)) {
0189 case 16:
0190 break;
0191 case 20:
0192 aifctrl1 |= 0x8;
0193 break;
0194 case 24:
0195 aifctrl1 |= 0x10;
0196 break;
0197 case 32:
0198 aifctrl1 |= 0x18;
0199 break;
0200 }
0201
0202 snd_soc_component_write(component, WM8523_AIF_CTRL1, aifctrl1);
0203 snd_soc_component_write(component, WM8523_AIF_CTRL2, aifctrl2);
0204
0205 return 0;
0206 }
0207
0208 static int wm8523_set_dai_sysclk(struct snd_soc_dai *codec_dai,
0209 int clk_id, unsigned int freq, int dir)
0210 {
0211 struct snd_soc_component *component = codec_dai->component;
0212 struct wm8523_priv *wm8523 = snd_soc_component_get_drvdata(component);
0213 unsigned int val;
0214 int i;
0215
0216 wm8523->sysclk = freq;
0217
0218 wm8523->rate_constraint.count = 0;
0219 for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
0220 val = freq / lrclk_ratios[i].ratio;
0221
0222
0223
0224
0225 switch (val) {
0226 case 8000:
0227 case 11025:
0228 case 16000:
0229 case 22050:
0230 case 32000:
0231 case 44100:
0232 case 48000:
0233 case 64000:
0234 case 88200:
0235 case 96000:
0236 case 176400:
0237 case 192000:
0238 dev_dbg(component->dev, "Supported sample rate: %dHz\n",
0239 val);
0240 wm8523->rate_constraint_list[i] = val;
0241 wm8523->rate_constraint.count++;
0242 break;
0243 default:
0244 dev_dbg(component->dev, "Skipping sample rate: %dHz\n",
0245 val);
0246 }
0247 }
0248
0249
0250 if (wm8523->rate_constraint.count == 0)
0251 return -EINVAL;
0252
0253 return 0;
0254 }
0255
0256
0257 static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai,
0258 unsigned int fmt)
0259 {
0260 struct snd_soc_component *component = codec_dai->component;
0261 u16 aifctrl1 = snd_soc_component_read(component, WM8523_AIF_CTRL1);
0262
0263 aifctrl1 &= ~(WM8523_BCLK_INV_MASK | WM8523_LRCLK_INV_MASK |
0264 WM8523_FMT_MASK | WM8523_AIF_MSTR_MASK);
0265
0266 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
0267 case SND_SOC_DAIFMT_CBM_CFM:
0268 aifctrl1 |= WM8523_AIF_MSTR;
0269 break;
0270 case SND_SOC_DAIFMT_CBS_CFS:
0271 break;
0272 default:
0273 return -EINVAL;
0274 }
0275
0276 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
0277 case SND_SOC_DAIFMT_I2S:
0278 aifctrl1 |= 0x0002;
0279 break;
0280 case SND_SOC_DAIFMT_RIGHT_J:
0281 break;
0282 case SND_SOC_DAIFMT_LEFT_J:
0283 aifctrl1 |= 0x0001;
0284 break;
0285 case SND_SOC_DAIFMT_DSP_A:
0286 aifctrl1 |= 0x0003;
0287 break;
0288 case SND_SOC_DAIFMT_DSP_B:
0289 aifctrl1 |= 0x0023;
0290 break;
0291 default:
0292 return -EINVAL;
0293 }
0294
0295 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
0296 case SND_SOC_DAIFMT_NB_NF:
0297 break;
0298 case SND_SOC_DAIFMT_IB_IF:
0299 aifctrl1 |= WM8523_BCLK_INV | WM8523_LRCLK_INV;
0300 break;
0301 case SND_SOC_DAIFMT_IB_NF:
0302 aifctrl1 |= WM8523_BCLK_INV;
0303 break;
0304 case SND_SOC_DAIFMT_NB_IF:
0305 aifctrl1 |= WM8523_LRCLK_INV;
0306 break;
0307 default:
0308 return -EINVAL;
0309 }
0310
0311 snd_soc_component_write(component, WM8523_AIF_CTRL1, aifctrl1);
0312
0313 return 0;
0314 }
0315
0316 static int wm8523_set_bias_level(struct snd_soc_component *component,
0317 enum snd_soc_bias_level level)
0318 {
0319 struct wm8523_priv *wm8523 = snd_soc_component_get_drvdata(component);
0320 int ret;
0321
0322 switch (level) {
0323 case SND_SOC_BIAS_ON:
0324 break;
0325
0326 case SND_SOC_BIAS_PREPARE:
0327
0328 snd_soc_component_update_bits(component, WM8523_PSCTRL1,
0329 WM8523_SYS_ENA_MASK, 3);
0330 break;
0331
0332 case SND_SOC_BIAS_STANDBY:
0333 if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
0334 ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
0335 wm8523->supplies);
0336 if (ret != 0) {
0337 dev_err(component->dev,
0338 "Failed to enable supplies: %d\n",
0339 ret);
0340 return ret;
0341 }
0342
0343
0344 regcache_sync(wm8523->regmap);
0345
0346
0347 snd_soc_component_update_bits(component, WM8523_PSCTRL1,
0348 WM8523_SYS_ENA_MASK, 1);
0349
0350 msleep(100);
0351 }
0352
0353
0354 snd_soc_component_update_bits(component, WM8523_PSCTRL1,
0355 WM8523_SYS_ENA_MASK, 2);
0356
0357 break;
0358
0359 case SND_SOC_BIAS_OFF:
0360
0361 snd_soc_component_update_bits(component, WM8523_PSCTRL1,
0362 WM8523_SYS_ENA_MASK, 0);
0363 msleep(100);
0364
0365 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies),
0366 wm8523->supplies);
0367 break;
0368 }
0369 return 0;
0370 }
0371
0372 #define WM8523_RATES SNDRV_PCM_RATE_8000_192000
0373
0374 #define WM8523_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
0375 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
0376
0377 static const struct snd_soc_dai_ops wm8523_dai_ops = {
0378 .startup = wm8523_startup,
0379 .hw_params = wm8523_hw_params,
0380 .set_sysclk = wm8523_set_dai_sysclk,
0381 .set_fmt = wm8523_set_dai_fmt,
0382 };
0383
0384 static struct snd_soc_dai_driver wm8523_dai = {
0385 .name = "wm8523-hifi",
0386 .playback = {
0387 .stream_name = "Playback",
0388 .channels_min = 2,
0389 .channels_max = 2,
0390 .rates = WM8523_RATES,
0391 .formats = WM8523_FORMATS,
0392 },
0393 .ops = &wm8523_dai_ops,
0394 };
0395
0396 static int wm8523_probe(struct snd_soc_component *component)
0397 {
0398 struct wm8523_priv *wm8523 = snd_soc_component_get_drvdata(component);
0399
0400 wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0];
0401 wm8523->rate_constraint.count =
0402 ARRAY_SIZE(wm8523->rate_constraint_list);
0403
0404
0405 snd_soc_component_update_bits(component, WM8523_DAC_GAINR,
0406 WM8523_DACR_VU, WM8523_DACR_VU);
0407 snd_soc_component_update_bits(component, WM8523_DAC_CTRL3, WM8523_ZC, WM8523_ZC);
0408
0409 return 0;
0410 }
0411
0412 static const struct snd_soc_component_driver soc_component_dev_wm8523 = {
0413 .probe = wm8523_probe,
0414 .set_bias_level = wm8523_set_bias_level,
0415 .controls = wm8523_controls,
0416 .num_controls = ARRAY_SIZE(wm8523_controls),
0417 .dapm_widgets = wm8523_dapm_widgets,
0418 .num_dapm_widgets = ARRAY_SIZE(wm8523_dapm_widgets),
0419 .dapm_routes = wm8523_dapm_routes,
0420 .num_dapm_routes = ARRAY_SIZE(wm8523_dapm_routes),
0421 .suspend_bias_off = 1,
0422 .idle_bias_on = 1,
0423 .use_pmdown_time = 1,
0424 .endianness = 1,
0425 };
0426
0427 static const struct of_device_id wm8523_of_match[] = {
0428 { .compatible = "wlf,wm8523" },
0429 { },
0430 };
0431 MODULE_DEVICE_TABLE(of, wm8523_of_match);
0432
0433 static const struct regmap_config wm8523_regmap = {
0434 .reg_bits = 8,
0435 .val_bits = 16,
0436 .max_register = WM8523_ZERO_DETECT,
0437
0438 .reg_defaults = wm8523_reg_defaults,
0439 .num_reg_defaults = ARRAY_SIZE(wm8523_reg_defaults),
0440 .cache_type = REGCACHE_RBTREE,
0441
0442 .volatile_reg = wm8523_volatile_register,
0443 };
0444
0445 static int wm8523_i2c_probe(struct i2c_client *i2c)
0446 {
0447 struct wm8523_priv *wm8523;
0448 unsigned int val;
0449 int ret, i;
0450
0451 wm8523 = devm_kzalloc(&i2c->dev, sizeof(struct wm8523_priv),
0452 GFP_KERNEL);
0453 if (wm8523 == NULL)
0454 return -ENOMEM;
0455
0456 wm8523->regmap = devm_regmap_init_i2c(i2c, &wm8523_regmap);
0457 if (IS_ERR(wm8523->regmap)) {
0458 ret = PTR_ERR(wm8523->regmap);
0459 dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret);
0460 return ret;
0461 }
0462
0463 for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++)
0464 wm8523->supplies[i].supply = wm8523_supply_names[i];
0465
0466 ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8523->supplies),
0467 wm8523->supplies);
0468 if (ret != 0) {
0469 dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
0470 return ret;
0471 }
0472
0473 ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
0474 wm8523->supplies);
0475 if (ret != 0) {
0476 dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
0477 return ret;
0478 }
0479
0480 ret = regmap_read(wm8523->regmap, WM8523_DEVICE_ID, &val);
0481 if (ret < 0) {
0482 dev_err(&i2c->dev, "Failed to read ID register\n");
0483 goto err_enable;
0484 }
0485 if (val != 0x8523) {
0486 dev_err(&i2c->dev, "Device is not a WM8523, ID is %x\n", ret);
0487 ret = -EINVAL;
0488 goto err_enable;
0489 }
0490
0491 ret = regmap_read(wm8523->regmap, WM8523_REVISION, &val);
0492 if (ret < 0) {
0493 dev_err(&i2c->dev, "Failed to read revision register\n");
0494 goto err_enable;
0495 }
0496 dev_info(&i2c->dev, "revision %c\n",
0497 (val & WM8523_CHIP_REV_MASK) + 'A');
0498
0499 ret = regmap_write(wm8523->regmap, WM8523_DEVICE_ID, 0x8523);
0500 if (ret != 0) {
0501 dev_err(&i2c->dev, "Failed to reset device: %d\n", ret);
0502 goto err_enable;
0503 }
0504
0505 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
0506
0507 i2c_set_clientdata(i2c, wm8523);
0508
0509 ret = devm_snd_soc_register_component(&i2c->dev,
0510 &soc_component_dev_wm8523, &wm8523_dai, 1);
0511
0512 return ret;
0513
0514 err_enable:
0515 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
0516 return ret;
0517 }
0518
0519 static const struct i2c_device_id wm8523_i2c_id[] = {
0520 { "wm8523", 0 },
0521 { }
0522 };
0523 MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id);
0524
0525 static struct i2c_driver wm8523_i2c_driver = {
0526 .driver = {
0527 .name = "wm8523",
0528 .of_match_table = wm8523_of_match,
0529 },
0530 .probe_new = wm8523_i2c_probe,
0531 .id_table = wm8523_i2c_id,
0532 };
0533
0534 module_i2c_driver(wm8523_i2c_driver);
0535
0536 MODULE_DESCRIPTION("ASoC WM8523 driver");
0537 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
0538 MODULE_LICENSE("GPL");