Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.6-rc2 408 lines 10 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2// 3// Audio driver for AK5558 ADC 4// 5// Copyright (C) 2015 Asahi Kasei Microdevices Corporation 6// Copyright 2018 NXP 7 8#include <linux/delay.h> 9#include <linux/gpio/consumer.h> 10#include <linux/i2c.h> 11#include <linux/module.h> 12#include <linux/pm_runtime.h> 13#include <linux/regmap.h> 14#include <linux/slab.h> 15 16#include <sound/initval.h> 17#include <sound/pcm.h> 18#include <sound/pcm_params.h> 19#include <sound/soc.h> 20#include <sound/soc-dapm.h> 21#include <sound/tlv.h> 22 23#include "ak5558.h" 24 25/* AK5558 Codec Private Data */ 26struct ak5558_priv { 27 struct snd_soc_component component; 28 struct regmap *regmap; 29 struct i2c_client *i2c; 30 struct gpio_desc *reset_gpiod; /* Reset & Power down GPIO */ 31 int slots; 32 int slot_width; 33}; 34 35/* ak5558 register cache & default register settings */ 36static const struct reg_default ak5558_reg[] = { 37 { 0x0, 0xFF }, /* 0x00 AK5558_00_POWER_MANAGEMENT1 */ 38 { 0x1, 0x01 }, /* 0x01 AK5558_01_POWER_MANAGEMENT2 */ 39 { 0x2, 0x01 }, /* 0x02 AK5558_02_CONTROL1 */ 40 { 0x3, 0x00 }, /* 0x03 AK5558_03_CONTROL2 */ 41 { 0x4, 0x00 }, /* 0x04 AK5558_04_CONTROL3 */ 42 { 0x5, 0x00 } /* 0x05 AK5558_05_DSD */ 43}; 44 45static const char * const mono_texts[] = { 46 "8 Slot", "2 Slot", "4 Slot", "1 Slot", 47}; 48 49static const struct soc_enum ak5558_mono_enum[] = { 50 SOC_ENUM_SINGLE(AK5558_01_POWER_MANAGEMENT2, 1, 51 ARRAY_SIZE(mono_texts), mono_texts), 52}; 53 54static const char * const digfil_texts[] = { 55 "Sharp Roll-Off", "Show Roll-Off", 56 "Short Delay Sharp Roll-Off", "Short Delay Show Roll-Off", 57}; 58 59static const struct soc_enum ak5558_adcset_enum[] = { 60 SOC_ENUM_SINGLE(AK5558_04_CONTROL3, 0, 61 ARRAY_SIZE(digfil_texts), digfil_texts), 62}; 63 64static const struct snd_kcontrol_new ak5558_snd_controls[] = { 65 SOC_ENUM("AK5558 Monaural Mode", ak5558_mono_enum[0]), 66 SOC_ENUM("AK5558 Digital Filter", ak5558_adcset_enum[0]), 67}; 68 69static const struct snd_soc_dapm_widget ak5558_dapm_widgets[] = { 70 /* Analog Input */ 71 SND_SOC_DAPM_INPUT("AIN1"), 72 SND_SOC_DAPM_INPUT("AIN2"), 73 SND_SOC_DAPM_INPUT("AIN3"), 74 SND_SOC_DAPM_INPUT("AIN4"), 75 SND_SOC_DAPM_INPUT("AIN5"), 76 SND_SOC_DAPM_INPUT("AIN6"), 77 SND_SOC_DAPM_INPUT("AIN7"), 78 SND_SOC_DAPM_INPUT("AIN8"), 79 80 SND_SOC_DAPM_ADC("ADC Ch1", NULL, AK5558_00_POWER_MANAGEMENT1, 0, 0), 81 SND_SOC_DAPM_ADC("ADC Ch2", NULL, AK5558_00_POWER_MANAGEMENT1, 1, 0), 82 SND_SOC_DAPM_ADC("ADC Ch3", NULL, AK5558_00_POWER_MANAGEMENT1, 2, 0), 83 SND_SOC_DAPM_ADC("ADC Ch4", NULL, AK5558_00_POWER_MANAGEMENT1, 3, 0), 84 SND_SOC_DAPM_ADC("ADC Ch5", NULL, AK5558_00_POWER_MANAGEMENT1, 4, 0), 85 SND_SOC_DAPM_ADC("ADC Ch6", NULL, AK5558_00_POWER_MANAGEMENT1, 5, 0), 86 SND_SOC_DAPM_ADC("ADC Ch7", NULL, AK5558_00_POWER_MANAGEMENT1, 6, 0), 87 SND_SOC_DAPM_ADC("ADC Ch8", NULL, AK5558_00_POWER_MANAGEMENT1, 7, 0), 88 89 SND_SOC_DAPM_AIF_OUT("SDTO", "Capture", 0, SND_SOC_NOPM, 0, 0), 90}; 91 92static const struct snd_soc_dapm_route ak5558_intercon[] = { 93 {"ADC Ch1", NULL, "AIN1"}, 94 {"SDTO", NULL, "ADC Ch1"}, 95 96 {"ADC Ch2", NULL, "AIN2"}, 97 {"SDTO", NULL, "ADC Ch2"}, 98 99 {"ADC Ch3", NULL, "AIN3"}, 100 {"SDTO", NULL, "ADC Ch3"}, 101 102 {"ADC Ch4", NULL, "AIN4"}, 103 {"SDTO", NULL, "ADC Ch4"}, 104 105 {"ADC Ch5", NULL, "AIN5"}, 106 {"SDTO", NULL, "ADC Ch5"}, 107 108 {"ADC Ch6", NULL, "AIN6"}, 109 {"SDTO", NULL, "ADC Ch6"}, 110 111 {"ADC Ch7", NULL, "AIN7"}, 112 {"SDTO", NULL, "ADC Ch7"}, 113 114 {"ADC Ch8", NULL, "AIN8"}, 115 {"SDTO", NULL, "ADC Ch8"}, 116}; 117 118static int ak5558_set_mcki(struct snd_soc_component *component) 119{ 120 return snd_soc_component_update_bits(component, AK5558_02_CONTROL1, AK5558_CKS, 121 AK5558_CKS_AUTO); 122} 123 124static int ak5558_hw_params(struct snd_pcm_substream *substream, 125 struct snd_pcm_hw_params *params, 126 struct snd_soc_dai *dai) 127{ 128 struct snd_soc_component *component = dai->component; 129 struct ak5558_priv *ak5558 = snd_soc_component_get_drvdata(component); 130 u8 bits; 131 int pcm_width = max(params_physical_width(params), ak5558->slot_width); 132 133 switch (pcm_width) { 134 case 16: 135 bits = AK5558_DIF_24BIT_MODE; 136 break; 137 case 32: 138 bits = AK5558_DIF_32BIT_MODE; 139 break; 140 default: 141 return -EINVAL; 142 } 143 144 snd_soc_component_update_bits(component, AK5558_02_CONTROL1, AK5558_BITS, bits); 145 146 return 0; 147} 148 149static int ak5558_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 150{ 151 struct snd_soc_component *component = dai->component; 152 u8 format; 153 154 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 155 case SND_SOC_DAIFMT_CBS_CFS: 156 break; 157 case SND_SOC_DAIFMT_CBM_CFM: 158 break; 159 case SND_SOC_DAIFMT_CBS_CFM: 160 case SND_SOC_DAIFMT_CBM_CFS: 161 default: 162 dev_err(dai->dev, "Clock mode unsupported"); 163 return -EINVAL; 164 } 165 166 /* set master/slave audio interface */ 167 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 168 case SND_SOC_DAIFMT_I2S: 169 format = AK5558_DIF_I2S_MODE; 170 break; 171 case SND_SOC_DAIFMT_LEFT_J: 172 format = AK5558_DIF_MSB_MODE; 173 break; 174 case SND_SOC_DAIFMT_DSP_B: 175 format = AK5558_DIF_MSB_MODE; 176 break; 177 default: 178 return -EINVAL; 179 } 180 181 snd_soc_component_update_bits(component, AK5558_02_CONTROL1, AK5558_DIF, format); 182 183 return 0; 184} 185 186static int ak5558_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 187 unsigned int rx_mask, int slots, 188 int slot_width) 189{ 190 struct snd_soc_component *component = dai->component; 191 struct ak5558_priv *ak5558 = snd_soc_component_get_drvdata(component); 192 int tdm_mode; 193 194 ak5558->slots = slots; 195 ak5558->slot_width = slot_width; 196 197 switch (slots * slot_width) { 198 case 128: 199 tdm_mode = AK5558_MODE_TDM128; 200 break; 201 case 256: 202 tdm_mode = AK5558_MODE_TDM256; 203 break; 204 case 512: 205 tdm_mode = AK5558_MODE_TDM512; 206 break; 207 default: 208 tdm_mode = AK5558_MODE_NORMAL; 209 break; 210 } 211 212 snd_soc_component_update_bits(component, AK5558_03_CONTROL2, AK5558_MODE_BITS, 213 tdm_mode); 214 return 0; 215} 216 217#define AK5558_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ 218 SNDRV_PCM_FMTBIT_S24_LE |\ 219 SNDRV_PCM_FMTBIT_S32_LE) 220 221static const unsigned int ak5558_rates[] = { 222 8000, 11025, 16000, 22050, 223 32000, 44100, 48000, 88200, 224 96000, 176400, 192000, 352800, 225 384000, 705600, 768000, 1411200, 226 2822400, 227}; 228 229static const struct snd_pcm_hw_constraint_list ak5558_rate_constraints = { 230 .count = ARRAY_SIZE(ak5558_rates), 231 .list = ak5558_rates, 232}; 233 234static int ak5558_startup(struct snd_pcm_substream *substream, 235 struct snd_soc_dai *dai) 236{ 237 return snd_pcm_hw_constraint_list(substream->runtime, 0, 238 SNDRV_PCM_HW_PARAM_RATE, 239 &ak5558_rate_constraints); 240} 241 242static const struct snd_soc_dai_ops ak5558_dai_ops = { 243 .startup = ak5558_startup, 244 .hw_params = ak5558_hw_params, 245 246 .set_fmt = ak5558_set_dai_fmt, 247 .set_tdm_slot = ak5558_set_tdm_slot, 248}; 249 250static struct snd_soc_dai_driver ak5558_dai = { 251 .name = "ak5558-aif", 252 .capture = { 253 .stream_name = "Capture", 254 .channels_min = 1, 255 .channels_max = 8, 256 .rates = SNDRV_PCM_RATE_KNOT, 257 .formats = AK5558_FORMATS, 258 }, 259 .ops = &ak5558_dai_ops, 260}; 261 262static void ak5558_power_off(struct ak5558_priv *ak5558) 263{ 264 if (!ak5558->reset_gpiod) 265 return; 266 267 gpiod_set_value_cansleep(ak5558->reset_gpiod, 0); 268 usleep_range(1000, 2000); 269} 270 271static void ak5558_power_on(struct ak5558_priv *ak5558) 272{ 273 if (!ak5558->reset_gpiod) 274 return; 275 276 gpiod_set_value_cansleep(ak5558->reset_gpiod, 1); 277 usleep_range(1000, 2000); 278} 279 280static int ak5558_probe(struct snd_soc_component *component) 281{ 282 struct ak5558_priv *ak5558 = snd_soc_component_get_drvdata(component); 283 284 ak5558_power_on(ak5558); 285 return ak5558_set_mcki(component); 286} 287 288static void ak5558_remove(struct snd_soc_component *component) 289{ 290 struct ak5558_priv *ak5558 = snd_soc_component_get_drvdata(component); 291 292 ak5558_power_off(ak5558); 293} 294 295static int __maybe_unused ak5558_runtime_suspend(struct device *dev) 296{ 297 struct ak5558_priv *ak5558 = dev_get_drvdata(dev); 298 299 regcache_cache_only(ak5558->regmap, true); 300 ak5558_power_off(ak5558); 301 302 return 0; 303} 304 305static int __maybe_unused ak5558_runtime_resume(struct device *dev) 306{ 307 struct ak5558_priv *ak5558 = dev_get_drvdata(dev); 308 309 ak5558_power_off(ak5558); 310 ak5558_power_on(ak5558); 311 312 regcache_cache_only(ak5558->regmap, false); 313 regcache_mark_dirty(ak5558->regmap); 314 315 return regcache_sync(ak5558->regmap); 316} 317 318static const struct dev_pm_ops ak5558_pm = { 319 SET_RUNTIME_PM_OPS(ak5558_runtime_suspend, ak5558_runtime_resume, NULL) 320 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 321 pm_runtime_force_resume) 322}; 323 324static const struct snd_soc_component_driver soc_codec_dev_ak5558 = { 325 .probe = ak5558_probe, 326 .remove = ak5558_remove, 327 .controls = ak5558_snd_controls, 328 .num_controls = ARRAY_SIZE(ak5558_snd_controls), 329 .dapm_widgets = ak5558_dapm_widgets, 330 .num_dapm_widgets = ARRAY_SIZE(ak5558_dapm_widgets), 331 .dapm_routes = ak5558_intercon, 332 .num_dapm_routes = ARRAY_SIZE(ak5558_intercon), 333 .idle_bias_on = 1, 334 .use_pmdown_time = 1, 335 .endianness = 1, 336 .non_legacy_dai_naming = 1, 337}; 338 339static const struct regmap_config ak5558_regmap = { 340 .reg_bits = 8, 341 .val_bits = 8, 342 343 .max_register = AK5558_05_DSD, 344 .reg_defaults = ak5558_reg, 345 .num_reg_defaults = ARRAY_SIZE(ak5558_reg), 346 .cache_type = REGCACHE_RBTREE, 347}; 348 349static int ak5558_i2c_probe(struct i2c_client *i2c) 350{ 351 struct ak5558_priv *ak5558; 352 int ret = 0; 353 354 ak5558 = devm_kzalloc(&i2c->dev, sizeof(*ak5558), GFP_KERNEL); 355 if (!ak5558) 356 return -ENOMEM; 357 358 ak5558->regmap = devm_regmap_init_i2c(i2c, &ak5558_regmap); 359 if (IS_ERR(ak5558->regmap)) 360 return PTR_ERR(ak5558->regmap); 361 362 i2c_set_clientdata(i2c, ak5558); 363 ak5558->i2c = i2c; 364 365 ak5558->reset_gpiod = devm_gpiod_get_optional(&i2c->dev, "reset", 366 GPIOD_OUT_LOW); 367 if (IS_ERR(ak5558->reset_gpiod)) 368 return PTR_ERR(ak5558->reset_gpiod); 369 370 ret = devm_snd_soc_register_component(&i2c->dev, 371 &soc_codec_dev_ak5558, 372 &ak5558_dai, 1); 373 if (ret) 374 return ret; 375 376 pm_runtime_enable(&i2c->dev); 377 378 return 0; 379} 380 381static int ak5558_i2c_remove(struct i2c_client *i2c) 382{ 383 pm_runtime_disable(&i2c->dev); 384 385 return 0; 386} 387 388static const struct of_device_id ak5558_i2c_dt_ids[] = { 389 { .compatible = "asahi-kasei,ak5558"}, 390 { } 391}; 392 393static struct i2c_driver ak5558_i2c_driver = { 394 .driver = { 395 .name = "ak5558", 396 .of_match_table = of_match_ptr(ak5558_i2c_dt_ids), 397 .pm = &ak5558_pm, 398 }, 399 .probe_new = ak5558_i2c_probe, 400 .remove = ak5558_i2c_remove, 401}; 402 403module_i2c_driver(ak5558_i2c_driver); 404 405MODULE_AUTHOR("Junichi Wakasugi <wakasugi.jb@om.asahi-kasei.co.jp>"); 406MODULE_AUTHOR("Mihai Serban <mihai.serban@nxp.com>"); 407MODULE_DESCRIPTION("ASoC AK5558 ADC driver"); 408MODULE_LICENSE("GPL v2");