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

ASoC: codecs: Add FourSemi FS2104/5S audio amplifier driver

The FS2104/5S are FourSemi digital audio amplifiers
with I2C control. They are Inductor-Less, Stereo, Closed-Loop,
Digital Input Class-D Power Amplifiers with Enhanced Signal Processing.

Signed-off-by: Nick Li <nick.li@foursemi.com>
Link: https://patch.msgid.link/75A0F7CC495E9662+20250811104610.8993-5-nick.li@foursemi.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Nick Li and committed by
Mark Brown
75611770 e0bbbcac

+1673
+13
sound/soc/codecs/Kconfig
··· 125 125 imply SND_SOC_ES7134 126 126 imply SND_SOC_ES7241 127 127 imply SND_SOC_FRAMER 128 + imply SND_SOC_FS210X 128 129 imply SND_SOC_GTM601 129 130 imply SND_SOC_HDAC_HDMI 130 131 imply SND_SOC_HDAC_HDA ··· 1236 1235 config SND_SOC_FS_AMP_LIB 1237 1236 select CRC16 1238 1237 tristate 1238 + 1239 + config SND_SOC_FS210X 1240 + tristate 'FourSemi FS2104/5S digital audio amplifier' 1241 + depends on I2C 1242 + select GPIOLIB 1243 + select REGMAP_I2C 1244 + select SND_SOC_FS_AMP_LIB 1245 + help 1246 + Enable support for FourSemi FS2104/5S digital audio amplifier. 1247 + The FS2104/5S are Inductor-Less, Stereo, Closed-Loop, 1248 + Digital Input Class-D Power Amplifiers with Enhanced Signal Processing. 1249 + The amplifiers support I2C and I2S/TDM. 1239 1250 1240 1251 config SND_SOC_GTM601 1241 1252 tristate 'GTM601 UMTS modem audio codec'
+2
sound/soc/codecs/Makefile
··· 138 138 snd-soc-es8389-y := es8389.o 139 139 snd-soc-framer-y := framer-codec.o 140 140 snd-soc-fs-amp-lib-y := fs-amp-lib.o 141 + snd-soc-fs210x-y := fs210x.o 141 142 snd-soc-gtm601-y := gtm601.o 142 143 snd-soc-hdac-hdmi-y := hdac_hdmi.o 143 144 snd-soc-hdac-hda-y := hdac_hda.o ··· 565 564 obj-$(CONFIG_SND_SOC_ES8389) += snd-soc-es8389.o 566 565 obj-$(CONFIG_SND_SOC_FRAMER) += snd-soc-framer.o 567 566 obj-$(CONFIG_SND_SOC_FS_AMP_LIB)+= snd-soc-fs-amp-lib.o 567 + obj-$(CONFIG_SND_SOC_FS210X) += snd-soc-fs210x.o 568 568 obj-$(CONFIG_SND_SOC_GTM601) += snd-soc-gtm601.o 569 569 obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-soc-hdac-hdmi.o 570 570 obj-$(CONFIG_SND_SOC_HDAC_HDA) += snd-soc-hdac-hda.o
+1583
sound/soc/codecs/fs210x.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // fs210x.c -- Driver for the FS2104/5S Audio Amplifier 4 + // 5 + // Copyright (C) 2016-2025 Shanghai FourSemi Semiconductor Co.,Ltd. 6 + 7 + #include <linux/clk.h> 8 + #include <linux/delay.h> 9 + #include <linux/i2c.h> 10 + #include <linux/gpio/consumer.h> 11 + #include <linux/module.h> 12 + #include <linux/mutex.h> 13 + #include <linux/of.h> 14 + #include <linux/regmap.h> 15 + #include <linux/regulator/consumer.h> 16 + #include <linux/workqueue.h> 17 + #include <sound/soc.h> 18 + #include <sound/tlv.h> 19 + 20 + #include "fs210x.h" 21 + #include "fs-amp-lib.h" 22 + 23 + #define FS210X_DEFAULT_FWM_NAME "fs210x_fwm.bin" 24 + #define FS210X_DEFAULT_DAI_NAME "fs210x-aif" 25 + #define FS2105S_DEVICE_ID 0x20 /* FS2105S */ 26 + #define FS210X_DEVICE_ID 0x45 /* FS2104 */ 27 + #define FS210X_REG_MAX 0xF8 28 + #define FS210X_INIT_SCENE 0 29 + #define FS210X_DEFAULT_SCENE 1 30 + #define FS210X_START_DELAY_MS 5 31 + #define FS210X_FAULT_CHECK_INTERVAL_MS 2000 32 + #define FS2105S_RATES (SNDRV_PCM_RATE_32000 | \ 33 + SNDRV_PCM_RATE_44100 | \ 34 + SNDRV_PCM_RATE_48000 | \ 35 + SNDRV_PCM_RATE_88200 | \ 36 + SNDRV_PCM_RATE_96000) 37 + #define FS210X_RATES (SNDRV_PCM_RATE_16000 | FS2105S_RATES) 38 + #define FS210X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ 39 + SNDRV_PCM_FMTBIT_S24_LE | \ 40 + SNDRV_PCM_FMTBIT_S24_3LE | \ 41 + SNDRV_PCM_FMTBIT_S32_LE) 42 + #define FS210X_NUM_SUPPLIES ARRAY_SIZE(fs210x_supply_names) 43 + 44 + static const char *const fs210x_supply_names[] = { 45 + "pvdd", 46 + "dvdd", 47 + }; 48 + 49 + struct fs210x_platform_data { 50 + const char *fwm_name; 51 + }; 52 + 53 + struct fs210x_priv { 54 + struct i2c_client *i2c; 55 + struct device *dev; 56 + struct regmap *regmap; 57 + struct fs210x_platform_data pdata; 58 + struct regulator_bulk_data supplies[FS210X_NUM_SUPPLIES]; 59 + struct gpio_desc *gpio_sdz; 60 + struct delayed_work start_work; 61 + struct delayed_work fault_check_work; 62 + struct fs_amp_lib amp_lib; 63 + const struct fs_amp_scene *cur_scene; 64 + struct clk *clk_bclk; 65 + /* 66 + * @lock: Mutex ensuring exclusive access for critical device operations 67 + * 68 + * This lock serializes access between the following actions: 69 + * - Device initialization procedures(probe) 70 + * - Enable/disable device(DAPM event) 71 + * - Suspend/resume device(PM) 72 + * - Runtime scene switching(control) 73 + * - Scheduling/execution of delayed works items(delayed works) 74 + */ 75 + struct mutex lock; 76 + unsigned int check_interval_ms; 77 + unsigned int bclk; 78 + unsigned int srate; 79 + int scene_id; 80 + u16 devid; 81 + bool is_inited; 82 + bool is_suspended; 83 + bool is_bclk_on; 84 + bool is_playing; 85 + }; 86 + 87 + static const unsigned int fs2105s_rates[] = { 88 + 32000, 44100, 48000, 88200, 96000 89 + }; 90 + 91 + static const struct snd_pcm_hw_constraint_list fs2105s_constraints = { 92 + .count = ARRAY_SIZE(fs2105s_rates), 93 + .list = fs2105s_rates, 94 + }; 95 + 96 + static const unsigned int fs210x_rates[] = { 97 + 16000, 32000, 44100, 48000, 88200, 96000 98 + }; 99 + 100 + static const struct snd_pcm_hw_constraint_list fs210x_constraints = { 101 + .count = ARRAY_SIZE(fs210x_rates), 102 + .list = fs210x_rates, 103 + }; 104 + 105 + static const struct fs_pll_div fs210x_pll_div[] = { 106 + /* bclk, pll1, pll2, pll3 */ 107 + { 512000, 0x006C, 0x0120, 0x0001 }, 108 + { 768000, 0x016C, 0x00C0, 0x0001 }, 109 + { 1024000, 0x016C, 0x0090, 0x0001 }, 110 + { 1536000, 0x016C, 0x0060, 0x0001 }, 111 + { 2048000, 0x016C, 0x0090, 0x0002 }, 112 + { 2304000, 0x016C, 0x0080, 0x0002 }, 113 + { 3072000, 0x016C, 0x0090, 0x0003 }, 114 + { 4096000, 0x016C, 0x0090, 0x0004 }, 115 + { 4608000, 0x016C, 0x0080, 0x0004 }, 116 + { 6144000, 0x016C, 0x0090, 0x0006 }, 117 + { 8192000, 0x016C, 0x0090, 0x0008 }, 118 + { 9216000, 0x016C, 0x0090, 0x0009 }, 119 + { 12288000, 0x016C, 0x0090, 0x000C }, 120 + { 16384000, 0x016C, 0x0090, 0x0010 }, 121 + { 18432000, 0x016C, 0x0090, 0x0012 }, 122 + { 24576000, 0x016C, 0x0090, 0x0018 }, 123 + { 1411200, 0x016C, 0x0060, 0x0001 }, 124 + { 2116800, 0x016C, 0x0080, 0x0002 }, 125 + { 2822400, 0x016C, 0x0090, 0x0003 }, 126 + { 4233600, 0x016C, 0x0080, 0x0004 }, 127 + { 5644800, 0x016C, 0x0090, 0x0006 }, 128 + { 8467200, 0x016C, 0x0090, 0x0009 }, 129 + { 11289600, 0x016C, 0x0090, 0x000C }, 130 + { 16934400, 0x016C, 0x0090, 0x0012 }, 131 + { 22579200, 0x016C, 0x0090, 0x0018 }, 132 + { 2000000, 0x017C, 0x0093, 0x0002 }, 133 + }; 134 + 135 + static int fs210x_bclk_set(struct fs210x_priv *fs210x, bool on) 136 + { 137 + int ret = 0; 138 + 139 + if (!fs210x || !fs210x->dev) 140 + return -EINVAL; 141 + 142 + if ((fs210x->is_bclk_on ^ on) == 0) 143 + return 0; 144 + 145 + if (on) { 146 + clk_set_rate(fs210x->clk_bclk, fs210x->bclk); 147 + ret = clk_prepare_enable(fs210x->clk_bclk); 148 + fs210x->is_bclk_on = true; 149 + fsleep(2000); /* >= 2ms */ 150 + } else { 151 + clk_disable_unprepare(fs210x->clk_bclk); 152 + fs210x->is_bclk_on = false; 153 + } 154 + 155 + return ret; 156 + } 157 + 158 + static int fs210x_reg_write(struct fs210x_priv *fs210x, 159 + u8 reg, u16 val) 160 + { 161 + int ret; 162 + 163 + ret = regmap_write(fs210x->regmap, reg, val); 164 + if (ret) { 165 + dev_err(fs210x->dev, "Failed to write %02Xh: %d\n", reg, ret); 166 + return ret; 167 + } 168 + 169 + return 0; 170 + } 171 + 172 + static int fs210x_reg_read(struct fs210x_priv *fs210x, 173 + u8 reg, u16 *pval) 174 + { 175 + unsigned int val; 176 + int ret; 177 + 178 + ret = regmap_read(fs210x->regmap, reg, &val); 179 + if (ret) { 180 + dev_err(fs210x->dev, "Failed to read %02Xh: %d\n", reg, ret); 181 + return ret; 182 + } 183 + 184 + *pval = (u16)val; 185 + 186 + return 0; 187 + } 188 + 189 + static int fs210x_reg_update_bits(struct fs210x_priv *fs210x, 190 + u8 reg, u16 mask, u16 val) 191 + { 192 + int ret; 193 + 194 + ret = regmap_update_bits(fs210x->regmap, reg, mask, val); 195 + if (ret) { 196 + dev_err(fs210x->dev, "Failed to update %02Xh: %d\n", reg, ret); 197 + return ret; 198 + } 199 + 200 + return 0; 201 + } 202 + 203 + static int fs210x_reg_bulk_write(struct fs210x_priv *fs210x, 204 + u8 reg, const void *val, u32 size) 205 + { 206 + int ret; 207 + 208 + ret = regmap_bulk_write(fs210x->regmap, reg, val, size / 2); 209 + if (ret) { 210 + dev_err(fs210x->dev, "Failed to bulk write %02Xh: %d\n", 211 + reg, ret); 212 + return ret; 213 + } 214 + 215 + return 0; 216 + } 217 + 218 + static inline int fs210x_write_reg_val(struct fs210x_priv *fs210x, 219 + const struct fs_reg_val *regv) 220 + { 221 + return fs210x_reg_write(fs210x, regv->reg, regv->val); 222 + } 223 + 224 + static inline int fs210x_write_reg_bits(struct fs210x_priv *fs210x, 225 + const struct fs_reg_bits *regu) 226 + { 227 + return fs210x_reg_update_bits(fs210x, 228 + regu->reg, 229 + regu->mask, 230 + regu->val); 231 + } 232 + 233 + static inline int fs210x_set_cmd_pkg(struct fs210x_priv *fs210x, 234 + const struct fs_cmd_pkg *pkg, 235 + unsigned int *offset) 236 + { 237 + int delay_us; 238 + 239 + if (pkg->cmd >= 0x00 && pkg->cmd <= FS210X_REG_MAX) { 240 + *offset = sizeof(pkg->regv); 241 + return fs210x_write_reg_val(fs210x, &pkg->regv); 242 + } else if (pkg->cmd == FS_CMD_UPDATE) { 243 + *offset = sizeof(pkg->regb); 244 + return fs210x_write_reg_bits(fs210x, &pkg->regb); 245 + } else if (pkg->cmd == FS_CMD_DELAY) { 246 + if (pkg->regv.val > FS_CMD_DELAY_MS_MAX) 247 + return -EOPNOTSUPP; 248 + delay_us = pkg->regv.val * 1000; /* ms -> us */ 249 + fsleep(delay_us); 250 + *offset = sizeof(pkg->regv); 251 + return 0; 252 + } 253 + 254 + dev_err(fs210x->dev, "Invalid pkg cmd: %d\n", pkg->cmd); 255 + 256 + return -EOPNOTSUPP; 257 + } 258 + 259 + static int fs210x_reg_write_table(struct fs210x_priv *fs210x, 260 + const struct fs_reg_table *reg) 261 + { 262 + const struct fs_cmd_pkg *pkg; 263 + unsigned int index, offset; 264 + int ret; 265 + 266 + if (!fs210x || !fs210x->dev) 267 + return -EINVAL; 268 + 269 + if (!reg || reg->size == 0) 270 + return -EFAULT; 271 + 272 + for (index = 0; index < reg->size; index += offset) { 273 + pkg = (struct fs_cmd_pkg *)(reg->buf + index); 274 + ret = fs210x_set_cmd_pkg(fs210x, pkg, &offset); 275 + if (ret) { 276 + dev_err(fs210x->dev, "Failed to set cmd pkg: %02X-%d\n", 277 + pkg->cmd, ret); 278 + return ret; 279 + } 280 + } 281 + 282 + if (index != reg->size) { 283 + dev_err(fs210x->dev, "Invalid reg table size: %d-%d\n", 284 + index, reg->size); 285 + return -EFAULT; 286 + } 287 + 288 + return 0; 289 + } 290 + 291 + static int fs210x_dev_play(struct fs210x_priv *fs210x) 292 + { 293 + int ret; 294 + 295 + if (!fs210x->is_inited) 296 + return -EFAULT; 297 + 298 + if (fs210x->is_playing) 299 + return 0; 300 + 301 + ret = fs210x_reg_write(fs210x, FS210X_11H_SYSCTRL, 302 + FS210X_11H_DPS_PLAY); 303 + if (!ret) 304 + fs210x->is_playing = true; 305 + 306 + fsleep(10000); /* >= 10ms */ 307 + 308 + return ret; 309 + } 310 + 311 + static int fs210x_dev_stop(struct fs210x_priv *fs210x) 312 + { 313 + int ret; 314 + 315 + if (!fs210x->is_inited) 316 + return -EFAULT; 317 + 318 + if (!fs210x->is_playing) 319 + return 0; 320 + 321 + ret = fs210x_reg_write(fs210x, FS210X_11H_SYSCTRL, 322 + FS210X_11H_DPS_PWDN); 323 + fs210x->is_playing = false; 324 + 325 + fsleep(30000); /* >= 30ms */ 326 + 327 + return ret; 328 + } 329 + 330 + static int fs210x_set_reg_table(struct fs210x_priv *fs210x, 331 + const struct fs_amp_scene *scene) 332 + { 333 + const struct fs_amp_scene *cur_scene; 334 + const struct fs_reg_table *reg; 335 + 336 + if (!fs210x || !fs210x->dev || !scene) 337 + return -EINVAL; 338 + 339 + cur_scene = fs210x->cur_scene; 340 + if (!scene->reg || cur_scene == scene) { 341 + dev_dbg(fs210x->dev, "Skip writing reg table\n"); 342 + return 0; 343 + } 344 + 345 + reg = scene->reg; 346 + dev_dbg(fs210x->dev, "reg table size: %d\n", reg->size); 347 + 348 + return fs210x_reg_write_table(fs210x, reg); 349 + } 350 + 351 + static int fs210x_set_woofer_table(struct fs210x_priv *fs210x) 352 + { 353 + const struct fs_file_table *woofer; 354 + const struct fs_fwm_table *table; 355 + int ret; 356 + 357 + if (!fs210x || !fs210x->dev) 358 + return -EINVAL; 359 + 360 + /* NOTE: fs2105s has woofer ram only */ 361 + if (fs210x->devid != FS2105S_DEVICE_ID) 362 + return 0; 363 + 364 + table = fs210x->amp_lib.table[FS_INDEX_WOOFER]; 365 + if (!table) { 366 + dev_dbg(fs210x->dev, "Skip writing woofer table\n"); 367 + return 0; 368 + } 369 + 370 + woofer = (struct fs_file_table *)table->buf; 371 + dev_dbg(fs210x->dev, "woofer table size: %d\n", woofer->size); 372 + /* Unit of woofer data is u32(4 bytes) */ 373 + if (woofer->size == 0 || (woofer->size & 0x3)) { 374 + dev_err(fs210x->dev, "Invalid woofer size: %d\n", 375 + woofer->size); 376 + return -EINVAL; 377 + } 378 + 379 + ret = fs210x_reg_write(fs210x, FS210X_46H_DACEQA, 380 + FS2105S_46H_CAM_BURST_W); 381 + ret |= fs210x_reg_bulk_write(fs210x, FS210X_42H_DACEQWL, 382 + woofer->buf, woofer->size); 383 + 384 + return ret; 385 + } 386 + 387 + static int fs210x_set_effect_table(struct fs210x_priv *fs210x, 388 + const struct fs_amp_scene *scene) 389 + { 390 + const struct fs_amp_scene *cur_scene; 391 + const struct fs_file_table *effect; 392 + int half_size; 393 + int ret; 394 + 395 + if (!fs210x || !fs210x->dev || !scene) 396 + return -EINVAL; 397 + 398 + cur_scene = fs210x->cur_scene; 399 + if (!scene->effect || cur_scene == scene) { 400 + dev_dbg(fs210x->dev, "Skip writing effect table\n"); 401 + return 0; 402 + } 403 + 404 + effect = scene->effect; 405 + dev_dbg(fs210x->dev, "effect table size: %d\n", effect->size); 406 + 407 + /* Unit of effect data is u32(4 bytes), 2 channels */ 408 + if (effect->size == 0 || (effect->size & 0x7)) { 409 + dev_err(fs210x->dev, "Invalid effect size: %d\n", 410 + effect->size); 411 + return -EINVAL; 412 + } 413 + 414 + half_size = effect->size / 2; 415 + 416 + /* Left channel */ 417 + ret = fs210x_reg_write(fs210x, FS210X_46H_DACEQA, 418 + FS210X_46H_CAM_BURST_L); 419 + ret |= fs210x_reg_bulk_write(fs210x, FS210X_42H_DACEQWL, 420 + effect->buf, half_size); 421 + if (ret) 422 + return ret; 423 + 424 + /* Right channel */ 425 + ret = fs210x_reg_write(fs210x, FS210X_46H_DACEQA, 426 + FS210X_46H_CAM_BURST_R); 427 + ret |= fs210x_reg_bulk_write(fs210x, FS210X_42H_DACEQWL, 428 + effect->buf + half_size, half_size); 429 + 430 + return ret; 431 + } 432 + 433 + static int fs210x_access_dsp_ram(struct fs210x_priv *fs210x, bool enable) 434 + { 435 + int ret; 436 + 437 + if (!fs210x || !fs210x->dev) 438 + return -EINVAL; 439 + 440 + if (enable) { 441 + ret = fs210x_reg_write(fs210x, FS210X_11H_SYSCTRL, 442 + FS210X_11H_DPS_HIZ); 443 + ret |= fs210x_reg_write(fs210x, FS210X_0BH_ACCKEY, 444 + FS210X_0BH_ACCKEY_ON); 445 + } else { 446 + ret = fs210x_reg_write(fs210x, FS210X_0BH_ACCKEY, 447 + FS210X_0BH_ACCKEY_OFF); 448 + ret |= fs210x_reg_write(fs210x, FS210X_11H_SYSCTRL, 449 + FS210X_11H_DPS_PWDN); 450 + } 451 + 452 + fsleep(10000); /* >= 10ms */ 453 + 454 + return ret; 455 + } 456 + 457 + static int fs210x_write_dsp_effect(struct fs210x_priv *fs210x, 458 + const struct fs_amp_scene *scene, 459 + int scene_id) 460 + { 461 + int ret; 462 + 463 + if (!fs210x || !scene) 464 + return -EINVAL; 465 + 466 + ret = fs210x_access_dsp_ram(fs210x, true); 467 + if (ret) { 468 + dev_err(fs210x->dev, "Failed to access dsp: %d\n", ret); 469 + goto tag_exit; 470 + } 471 + 472 + ret = fs210x_set_effect_table(fs210x, scene); 473 + if (ret) { 474 + dev_err(fs210x->dev, "Failed to set effect: %d\n", ret); 475 + goto tag_exit; 476 + } 477 + 478 + if (scene_id == FS210X_INIT_SCENE) 479 + ret = fs210x_set_woofer_table(fs210x); 480 + 481 + tag_exit: 482 + fs210x_reg_write(fs210x, FS210X_46H_DACEQA, 483 + FS210X_46H_CAM_CLEAR); 484 + fs210x_access_dsp_ram(fs210x, false); 485 + 486 + return ret; 487 + } 488 + 489 + static int fs210x_check_scene(struct fs210x_priv *fs210x, 490 + int scene_id, bool *skip_set) 491 + { 492 + struct fs_amp_lib *amp_lib; 493 + 494 + if (!fs210x || !skip_set) 495 + return -EINVAL; 496 + 497 + amp_lib = &fs210x->amp_lib; 498 + if (amp_lib->scene_count == 0 || !amp_lib->scene) { 499 + dev_err(fs210x->dev, "There's no scene data\n"); 500 + return -EINVAL; 501 + } 502 + 503 + if (scene_id < 0 || scene_id >= amp_lib->scene_count) { 504 + dev_err(fs210x->dev, "Invalid scene_id: %d\n", scene_id); 505 + return -EINVAL; 506 + } 507 + 508 + if (fs210x->scene_id == scene_id) { 509 + dev_dbg(fs210x->dev, "Skip to set same scene\n"); 510 + return 0; 511 + } 512 + 513 + *skip_set = false; 514 + 515 + return 0; 516 + } 517 + 518 + static int fs210x_set_scene(struct fs210x_priv *fs210x, int scene_id) 519 + { 520 + const struct fs_amp_scene *scene; 521 + bool skip_set = true; 522 + bool is_playing; 523 + int ret; 524 + 525 + if (!fs210x || !fs210x->dev) 526 + return -EINVAL; 527 + 528 + ret = fs210x_check_scene(fs210x, scene_id, &skip_set); 529 + if (ret || skip_set) 530 + return ret; 531 + 532 + scene = fs210x->amp_lib.scene + scene_id; 533 + dev_info(fs210x->dev, "Switch scene.%d: %s\n", 534 + scene_id, scene->name); 535 + 536 + is_playing = fs210x->is_playing; 537 + if (is_playing) 538 + fs210x_dev_stop(fs210x); 539 + 540 + ret = fs210x_set_reg_table(fs210x, scene); 541 + if (ret) { 542 + dev_err(fs210x->dev, "Failed to set reg: %d\n", ret); 543 + return ret; 544 + } 545 + 546 + ret = fs210x_write_dsp_effect(fs210x, scene, scene_id); 547 + if (ret) { 548 + dev_err(fs210x->dev, "Failed to write ram: %d\n", ret); 549 + return ret; 550 + } 551 + 552 + fs210x->cur_scene = scene; 553 + fs210x->scene_id = scene_id; 554 + 555 + if (is_playing) 556 + fs210x_dev_play(fs210x); 557 + 558 + return 0; 559 + } 560 + 561 + static int fs210x_init_chip(struct fs210x_priv *fs210x) 562 + { 563 + int scene_id; 564 + int ret; 565 + 566 + regcache_cache_bypass(fs210x->regmap, true); 567 + 568 + if (!fs210x->gpio_sdz) { 569 + /* Gpio is not found, i2c reset */ 570 + ret = fs210x_reg_write(fs210x, FS210X_10H_PWRCTRL, 571 + FS210X_10H_I2C_RESET); 572 + if (ret) 573 + goto tag_power_down; 574 + } else { 575 + /* gpio reset, deactivate */ 576 + gpiod_set_value_cansleep(fs210x->gpio_sdz, 0); 577 + } 578 + 579 + fsleep(10000); /* >= 10ms */ 580 + 581 + /* Backup scene id */ 582 + scene_id = fs210x->scene_id; 583 + fs210x->scene_id = -1; 584 + 585 + /* Init registers/RAM by init scene */ 586 + ret = fs210x_set_scene(fs210x, FS210X_INIT_SCENE); 587 + if (ret) 588 + goto tag_power_down; 589 + 590 + /* 591 + * If the firmware has effect scene(s), 592 + * we load effect scene by default scene or scene_id 593 + */ 594 + if (fs210x->amp_lib.scene_count > 1) { 595 + if (scene_id < FS210X_DEFAULT_SCENE) 596 + scene_id = FS210X_DEFAULT_SCENE; 597 + ret = fs210x_set_scene(fs210x, scene_id); 598 + if (ret) 599 + goto tag_power_down; 600 + } 601 + 602 + tag_power_down: 603 + /* Power down the device */ 604 + ret |= fs210x_reg_write(fs210x, FS210X_11H_SYSCTRL, 605 + FS210X_11H_DPS_PWDN); 606 + fsleep(10000); /* >= 10ms */ 607 + 608 + regcache_cache_bypass(fs210x->regmap, false); 609 + if (!ret) { 610 + regcache_mark_dirty(fs210x->regmap); 611 + regcache_sync(fs210x->regmap); 612 + fs210x->is_inited = true; 613 + } 614 + 615 + return ret; 616 + } 617 + 618 + static int fs210x_set_i2s_params(struct fs210x_priv *fs210x) 619 + { 620 + const struct fs_i2s_srate params[] = { 621 + { 16000, 0x3 }, 622 + { 32000, 0x7 }, 623 + { 44100, 0x8 }, 624 + { 48000, 0x9 }, 625 + { 88200, 0xA }, 626 + { 96000, 0xB }, 627 + }; 628 + u16 val; 629 + int i, ret; 630 + 631 + for (i = 0; i < ARRAY_SIZE(params); i++) { 632 + if (params[i].srate != fs210x->srate) 633 + continue; 634 + val = params[i].i2ssr << FS210X_17H_I2SSR_SHIFT; 635 + ret = fs210x_reg_update_bits(fs210x, 636 + FS210X_17H_I2SCTRL, 637 + FS210X_17H_I2SSR_MASK, 638 + val); 639 + return ret; 640 + } 641 + 642 + dev_err(fs210x->dev, "Invalid sample rate: %d\n", fs210x->srate); 643 + 644 + return -EINVAL; 645 + } 646 + 647 + static int fs210x_get_pll_div(struct fs210x_priv *fs210x, 648 + const struct fs_pll_div **pll_div) 649 + { 650 + int i; 651 + 652 + if (!fs210x || !pll_div) 653 + return -EINVAL; 654 + 655 + for (i = 0; i < ARRAY_SIZE(fs210x_pll_div); i++) { 656 + if (fs210x_pll_div[i].bclk != fs210x->bclk) 657 + continue; 658 + *pll_div = fs210x_pll_div + i; 659 + return 0; 660 + } 661 + 662 + dev_err(fs210x->dev, "No PLL table for bclk: %d\n", fs210x->bclk); 663 + 664 + return -EFAULT; 665 + } 666 + 667 + static int fs210x_set_hw_params(struct fs210x_priv *fs210x) 668 + { 669 + const struct fs_pll_div *pll_div; 670 + int ret; 671 + 672 + ret = fs210x_set_i2s_params(fs210x); 673 + if (ret) { 674 + dev_err(fs210x->dev, "Failed to set i2s params: %d\n", ret); 675 + return ret; 676 + } 677 + 678 + /* Set pll params */ 679 + ret = fs210x_get_pll_div(fs210x, &pll_div); 680 + if (ret) 681 + return ret; 682 + 683 + ret = fs210x_reg_write(fs210x, FS210X_A1H_PLLCTRL1, pll_div->pll1); 684 + ret |= fs210x_reg_write(fs210x, FS210X_A2H_PLLCTRL2, pll_div->pll2); 685 + ret |= fs210x_reg_write(fs210x, FS210X_A3H_PLLCTRL3, pll_div->pll3); 686 + 687 + return ret; 688 + } 689 + 690 + static int fs210x_dai_startup(struct snd_pcm_substream *substream, 691 + struct snd_soc_dai *dai) 692 + { 693 + const struct snd_pcm_hw_constraint_list *list; 694 + struct fs210x_priv *fs210x; 695 + int ret; 696 + 697 + fs210x = snd_soc_component_get_drvdata(dai->component); 698 + if (!fs210x) { 699 + pr_err("dai_startup: fs210x is null\n"); 700 + return -EINVAL; 701 + } 702 + 703 + if (!substream->runtime) 704 + return 0; 705 + 706 + ret = snd_pcm_hw_constraint_mask64(substream->runtime, 707 + SNDRV_PCM_HW_PARAM_FORMAT, 708 + FS210X_FORMATS); 709 + if (ret < 0) { 710 + dev_err(fs210x->dev, 711 + "Failed to set hw param format: %d\n", ret); 712 + return ret; 713 + } 714 + 715 + if (fs210x->devid == FS2105S_DEVICE_ID) 716 + list = &fs2105s_constraints; 717 + else 718 + list = &fs210x_constraints; 719 + 720 + ret = snd_pcm_hw_constraint_list(substream->runtime, 0, 721 + SNDRV_PCM_HW_PARAM_RATE, 722 + list); 723 + if (ret < 0) { 724 + dev_err(fs210x->dev, 725 + "Failed to set hw param rate: %d\n", ret); 726 + return ret; 727 + } 728 + 729 + return 0; 730 + } 731 + 732 + static int fs210x_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 733 + { 734 + struct fs210x_priv *fs210x; 735 + 736 + fs210x = snd_soc_component_get_drvdata(dai->component); 737 + 738 + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { 739 + case SND_SOC_DAIFMT_CBC_CFC: 740 + /* Only supports consumer mode */ 741 + break; 742 + default: 743 + dev_err(fs210x->dev, "Only supports consumer mode\n"); 744 + return -EINVAL; 745 + } 746 + 747 + return 0; 748 + } 749 + 750 + static int fs210x_dai_hw_params(struct snd_pcm_substream *substream, 751 + struct snd_pcm_hw_params *params, 752 + struct snd_soc_dai *dai) 753 + { 754 + struct fs210x_priv *fs210x; 755 + int chn_num; 756 + int ret; 757 + 758 + if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) 759 + return 0; 760 + 761 + fs210x = snd_soc_component_get_drvdata(dai->component); 762 + 763 + fs210x->srate = params_rate(params); 764 + fs210x->bclk = snd_soc_params_to_bclk(params); 765 + chn_num = params_channels(params); 766 + if (chn_num == 1) /* mono */ 767 + fs210x->bclk *= 2; /* I2S bus has 2 channels */ 768 + 769 + /* The FS2105S can't support 16kHz sample rate. */ 770 + if (fs210x->devid == FS2105S_DEVICE_ID && fs210x->srate == 16000) 771 + return -EOPNOTSUPP; 772 + 773 + mutex_lock(&fs210x->lock); 774 + ret = fs210x_set_hw_params(fs210x); 775 + mutex_unlock(&fs210x->lock); 776 + if (ret) 777 + dev_err(fs210x->dev, "Failed to set hw params: %d\n", ret); 778 + 779 + return ret; 780 + } 781 + 782 + static int fs210x_dai_mute(struct snd_soc_dai *dai, int mute, int stream) 783 + { 784 + struct fs210x_priv *fs210x; 785 + unsigned long delay; 786 + 787 + if (stream != SNDRV_PCM_STREAM_PLAYBACK) 788 + return 0; 789 + 790 + fs210x = snd_soc_component_get_drvdata(dai->component); 791 + 792 + mutex_lock(&fs210x->lock); 793 + 794 + if (!fs210x->is_inited || fs210x->is_suspended) { 795 + mutex_unlock(&fs210x->lock); 796 + return 0; 797 + } 798 + 799 + mutex_unlock(&fs210x->lock); 800 + 801 + if (mute) { 802 + cancel_delayed_work_sync(&fs210x->fault_check_work); 803 + cancel_delayed_work_sync(&fs210x->start_work); 804 + } else { 805 + delay = msecs_to_jiffies(fs210x->check_interval_ms); 806 + schedule_delayed_work(&fs210x->fault_check_work, delay); 807 + } 808 + 809 + return 0; 810 + } 811 + 812 + static int fs210x_dai_trigger(struct snd_pcm_substream *substream, 813 + int cmd, struct snd_soc_dai *dai) 814 + { 815 + struct fs210x_priv *fs210x; 816 + 817 + fs210x = snd_soc_component_get_drvdata(dai->component); 818 + 819 + mutex_lock(&fs210x->lock); 820 + 821 + if (!fs210x->is_inited || fs210x->is_suspended || fs210x->is_playing) { 822 + mutex_unlock(&fs210x->lock); 823 + return 0; 824 + } 825 + 826 + mutex_unlock(&fs210x->lock); 827 + 828 + switch (cmd) { 829 + case SNDRV_PCM_TRIGGER_START: 830 + case SNDRV_PCM_TRIGGER_RESUME: 831 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 832 + /* 833 + * According to the power up/down sequence of FS210x, 834 + * it requests the I2S clock has been present 835 + * and stable(>= 2ms) before playing. 836 + */ 837 + schedule_delayed_work(&fs210x->start_work, 838 + msecs_to_jiffies(FS210X_START_DELAY_MS)); 839 + break; 840 + 841 + default: 842 + break; 843 + } 844 + 845 + return 0; 846 + } 847 + 848 + static void fs210x_start_work(struct work_struct *work) 849 + { 850 + struct fs210x_priv *fs210x; 851 + int ret; 852 + 853 + fs210x = container_of(work, struct fs210x_priv, start_work.work); 854 + 855 + mutex_lock(&fs210x->lock); 856 + 857 + ret = fs210x_dev_play(fs210x); 858 + if (ret) 859 + dev_err(fs210x->dev, "Failed to start playing: %d\n", ret); 860 + 861 + mutex_unlock(&fs210x->lock); 862 + } 863 + 864 + static void fs210x_fault_check_work(struct work_struct *work) 865 + { 866 + struct fs210x_priv *fs210x; 867 + u16 status; 868 + int ret; 869 + 870 + fs210x = container_of(work, struct fs210x_priv, fault_check_work.work); 871 + 872 + mutex_lock(&fs210x->lock); 873 + 874 + if (!fs210x->is_inited || fs210x->is_suspended || !fs210x->is_playing) { 875 + mutex_unlock(&fs210x->lock); 876 + return; 877 + } 878 + 879 + ret = fs210x_reg_read(fs210x, FS210X_05H_ANASTAT, &status); 880 + mutex_unlock(&fs210x->lock); 881 + if (ret) 882 + return; 883 + 884 + if (!(status & FS210X_05H_PVDD_MASK)) 885 + dev_err(fs210x->dev, "PVDD fault\n"); 886 + if (status & FS210X_05H_OCDL_MASK) 887 + dev_err(fs210x->dev, "OC detected\n"); 888 + if (status & FS210X_05H_UVDL_MASK) 889 + dev_err(fs210x->dev, "UV detected\n"); 890 + if (status & FS210X_05H_OVDL_MASK) 891 + dev_err(fs210x->dev, "OV detected\n"); 892 + if (status & FS210X_05H_OTPDL_MASK) 893 + dev_err(fs210x->dev, "OT detected\n"); 894 + if (status & FS210X_05H_OCRDL_MASK) 895 + dev_err(fs210x->dev, "OCR detected\n"); 896 + if (status & FS210X_05H_OCLDL_MASK) 897 + dev_err(fs210x->dev, "OCL detected\n"); 898 + if (status & FS210X_05H_DCRDL_MASK) 899 + dev_err(fs210x->dev, "DCR detected\n"); 900 + if (status & FS210X_05H_DCLDL_MASK) 901 + dev_err(fs210x->dev, "DCL detected\n"); 902 + if (status & FS210X_05H_SRDL_MASK) 903 + dev_err(fs210x->dev, "SR detected\n"); 904 + if (status & FS210X_05H_OTWDL_MASK) 905 + dev_err(fs210x->dev, "OTW detected\n"); 906 + if (!(status & FS210X_05H_AMPS_MASK)) 907 + dev_dbg(fs210x->dev, "Amplifier unready\n"); 908 + if (!(status & FS210X_05H_PLLS_MASK)) 909 + dev_err(fs210x->dev, "PLL unlock\n"); 910 + if (!(status & FS210X_05H_ANAS_MASK)) 911 + dev_err(fs210x->dev, "Analog power fault\n"); 912 + 913 + schedule_delayed_work(&fs210x->fault_check_work, 914 + msecs_to_jiffies(fs210x->check_interval_ms)); 915 + } 916 + 917 + static int fs210x_get_drvdata_from_kctrl(struct snd_kcontrol *kctrl, 918 + struct fs210x_priv **fs210x) 919 + { 920 + struct snd_soc_component *cmpnt; 921 + 922 + if (!kctrl) { 923 + pr_err("fs210x: kcontrol is null\n"); 924 + return -EINVAL; 925 + } 926 + 927 + cmpnt = snd_soc_kcontrol_component(kctrl); 928 + if (!cmpnt) { 929 + pr_err("fs210x: component is null\n"); 930 + return -EINVAL; 931 + } 932 + 933 + *fs210x = snd_soc_component_get_drvdata(cmpnt); 934 + 935 + return 0; 936 + } 937 + 938 + static int fs210x_effect_scene_info(struct snd_kcontrol *kcontrol, 939 + struct snd_ctl_elem_info *uinfo) 940 + { 941 + const struct fs_amp_scene *scene; 942 + struct fs210x_priv *fs210x; 943 + const char *name = "N/A"; 944 + int idx, count; 945 + int ret; 946 + 947 + ret = fs210x_get_drvdata_from_kctrl(kcontrol, &fs210x); 948 + if (ret || !fs210x->dev) { 949 + pr_err("scene_effect_info: fs210x is null\n"); 950 + return -EINVAL; 951 + } 952 + 953 + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 954 + uinfo->count = 1; 955 + 956 + count = fs210x->amp_lib.scene_count - 1; /* Skip init scene */ 957 + if (count < 1) { 958 + uinfo->value.enumerated.items = 0; 959 + return 0; 960 + } 961 + 962 + uinfo->value.enumerated.items = count; 963 + if (uinfo->value.enumerated.item >= count) 964 + uinfo->value.enumerated.item = count - 1; 965 + 966 + idx = uinfo->value.enumerated.item; 967 + scene = fs210x->amp_lib.scene + idx + 1; 968 + if (scene->name) 969 + name = scene->name; 970 + 971 + strscpy(uinfo->value.enumerated.name, name, strlen(name) + 1); 972 + 973 + return 0; 974 + } 975 + 976 + static int fs210x_effect_scene_get(struct snd_kcontrol *kcontrol, 977 + struct snd_ctl_elem_value *ucontrol) 978 + { 979 + struct fs210x_priv *fs210x; 980 + int index; 981 + int ret; 982 + 983 + ret = fs210x_get_drvdata_from_kctrl(kcontrol, &fs210x); 984 + if (ret || !fs210x->dev) { 985 + pr_err("scene_effect_get: fs210x is null\n"); 986 + return -EINVAL; 987 + } 988 + 989 + /* The id of effect scene is from 1 to N. */ 990 + if (fs210x->scene_id < 1) 991 + return -EINVAL; 992 + 993 + mutex_lock(&fs210x->lock); 994 + /* 995 + * FS210x has scene(s) as below: 996 + * init scene: id = 0 997 + * effect scene(s): id = 1~N (optional) 998 + * effect_index = scene_id - 1 999 + */ 1000 + index = fs210x->scene_id - 1; 1001 + ucontrol->value.integer.value[0] = index; 1002 + mutex_unlock(&fs210x->lock); 1003 + 1004 + return 0; 1005 + } 1006 + 1007 + static int fs210x_effect_scene_put(struct snd_kcontrol *kcontrol, 1008 + struct snd_ctl_elem_value *ucontrol) 1009 + { 1010 + struct fs210x_priv *fs210x; 1011 + int scene_id, scene_count; 1012 + bool is_changed = false; 1013 + int ret; 1014 + 1015 + ret = fs210x_get_drvdata_from_kctrl(kcontrol, &fs210x); 1016 + if (ret || !fs210x->dev) { 1017 + pr_err("scene_effect_put: fs210x is null\n"); 1018 + return -EINVAL; 1019 + } 1020 + 1021 + mutex_lock(&fs210x->lock); 1022 + 1023 + /* 1024 + * FS210x has scene(s) as below: 1025 + * init scene: id = 0 (It's set in fs210x_init_chip() only) 1026 + * effect scene(s): id = 1~N (optional) 1027 + * scene_id = effect_index + 1. 1028 + */ 1029 + scene_id = ucontrol->value.integer.value[0] + 1; 1030 + scene_count = fs210x->amp_lib.scene_count - 1; /* Skip init scene */ 1031 + if (scene_id < 1 || scene_id > scene_count) { 1032 + mutex_unlock(&fs210x->lock); 1033 + return -ERANGE; 1034 + } 1035 + 1036 + if (scene_id != fs210x->scene_id) 1037 + is_changed = true; 1038 + 1039 + if (fs210x->is_suspended) { 1040 + fs210x->scene_id = scene_id; 1041 + mutex_unlock(&fs210x->lock); 1042 + return is_changed; 1043 + } 1044 + 1045 + ret = fs210x_set_scene(fs210x, scene_id); 1046 + if (ret) 1047 + dev_err(fs210x->dev, "Failed to set scene: %d\n", ret); 1048 + 1049 + mutex_unlock(&fs210x->lock); 1050 + 1051 + if (!ret && is_changed) 1052 + return 1; 1053 + 1054 + return ret; 1055 + } 1056 + 1057 + static int fs210x_playback_event(struct snd_soc_dapm_widget *w, 1058 + struct snd_kcontrol *kc, int event) 1059 + { 1060 + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); 1061 + struct fs210x_priv *fs210x = snd_soc_component_get_drvdata(cmpnt); 1062 + int ret = 0; 1063 + 1064 + mutex_lock(&fs210x->lock); 1065 + 1066 + if (fs210x->is_suspended) { 1067 + mutex_unlock(&fs210x->lock); 1068 + return 0; 1069 + } 1070 + 1071 + switch (event) { 1072 + case SND_SOC_DAPM_PRE_PMU: 1073 + /* 1074 + * If there is no bclk for us to set the clock output, 1075 + * we will enable the device(start_work) in dai trigger. 1076 + */ 1077 + if (!fs210x->clk_bclk) 1078 + break; 1079 + fs210x_bclk_set(fs210x, true); 1080 + ret = fs210x_dev_play(fs210x); 1081 + break; 1082 + case SND_SOC_DAPM_POST_PMD: 1083 + ret = fs210x_dev_stop(fs210x); 1084 + fs210x_bclk_set(fs210x, false); 1085 + break; 1086 + default: 1087 + break; 1088 + } 1089 + 1090 + mutex_unlock(&fs210x->lock); 1091 + 1092 + return ret; 1093 + } 1094 + 1095 + static const struct snd_soc_dai_ops fs210x_dai_ops = { 1096 + .startup = fs210x_dai_startup, 1097 + .set_fmt = fs210x_dai_set_fmt, 1098 + .hw_params = fs210x_dai_hw_params, 1099 + .mute_stream = fs210x_dai_mute, 1100 + .trigger = fs210x_dai_trigger, 1101 + }; 1102 + 1103 + static const struct snd_soc_dai_driver fs210x_dai = { 1104 + .name = FS210X_DEFAULT_DAI_NAME, 1105 + .playback = { 1106 + .stream_name = "Playback", 1107 + .channels_min = 1, 1108 + .channels_max = 2, 1109 + .rates = FS210X_RATES, 1110 + .formats = FS210X_FORMATS, 1111 + }, 1112 + .capture = { 1113 + .stream_name = "Capture", 1114 + .channels_min = 1, 1115 + .channels_max = 2, 1116 + .rates = FS210X_RATES, 1117 + .formats = FS210X_FORMATS, 1118 + }, 1119 + .ops = &fs210x_dai_ops, 1120 + .symmetric_rate = 1, 1121 + .symmetric_sample_bits = 1, 1122 + }; 1123 + 1124 + static const DECLARE_TLV_DB_SCALE(fs2105s_vol_tlv, -9709, 19, 1); 1125 + static const DECLARE_TLV_DB_SCALE(fs210x_vol_tlv, -13357, 19, 1); 1126 + 1127 + static const struct snd_kcontrol_new fs2105s_vol_control[] = { 1128 + SOC_DOUBLE_R_TLV("PCM Playback Volume", 1129 + FS210X_39H_LVOLCTRL, FS210X_3AH_RVOLCTRL, 1130 + 7, 0x1FF, 0, fs2105s_vol_tlv), 1131 + }; 1132 + 1133 + static const struct snd_kcontrol_new fs210x_vol_control[] = { 1134 + SOC_DOUBLE_R_TLV("PCM Playback Volume", 1135 + FS210X_39H_LVOLCTRL, FS210X_3AH_RVOLCTRL, 1136 + 6, 0x2BF, 0, fs210x_vol_tlv), 1137 + }; 1138 + 1139 + static const struct snd_kcontrol_new fs210x_controls[] = { 1140 + SOC_DOUBLE("DAC Mute Switch", FS210X_30H_DACCTRL, 4, 8, 1, 0), 1141 + SOC_DOUBLE("DAC Fade Switch", FS210X_30H_DACCTRL, 5, 9, 1, 0), 1142 + }; 1143 + 1144 + static const struct snd_kcontrol_new fs210x_scene_control[] = { 1145 + FS_SOC_ENUM_EXT("Effect Scene", 1146 + fs210x_effect_scene_info, 1147 + fs210x_effect_scene_get, 1148 + fs210x_effect_scene_put), 1149 + }; 1150 + 1151 + static const struct snd_soc_dapm_widget fs210x_dapm_widgets[] = { 1152 + SND_SOC_DAPM_AIF_IN_E("AIF IN", "Playback", 0, SND_SOC_NOPM, 0, 0, 1153 + fs210x_playback_event, 1154 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 1155 + SND_SOC_DAPM_AIF_OUT("AIF OUT", "Capture", 0, SND_SOC_NOPM, 0, 0), 1156 + SND_SOC_DAPM_OUTPUT("OUTL"), 1157 + SND_SOC_DAPM_OUTPUT("OUTR"), 1158 + SND_SOC_DAPM_INPUT("SDO"), 1159 + }; 1160 + 1161 + static const struct snd_soc_dapm_route fs210x_dapm_routes[] = { 1162 + { "OUTL", NULL, "AIF IN" }, 1163 + { "OUTR", NULL, "AIF IN" }, 1164 + { "AIF OUT", NULL, "SDO" }, 1165 + }; 1166 + 1167 + static int fs210x_add_mixer_controls(struct fs210x_priv *fs210x, 1168 + struct snd_soc_component *cmpnt) 1169 + { 1170 + const struct snd_kcontrol_new *kctrl; 1171 + int count; 1172 + int ret; 1173 + 1174 + if (!fs210x || !cmpnt) 1175 + return -EINVAL; 1176 + 1177 + if (fs210x->devid == FS2105S_DEVICE_ID) { 1178 + kctrl = fs2105s_vol_control; 1179 + count = ARRAY_SIZE(fs2105s_vol_control); 1180 + } else { 1181 + kctrl = fs210x_vol_control; 1182 + count = ARRAY_SIZE(fs210x_vol_control); 1183 + } 1184 + 1185 + ret = snd_soc_add_component_controls(cmpnt, kctrl, count); 1186 + if (ret) 1187 + return ret; 1188 + 1189 + /* 1190 + * If the firmware has no scene or only init scene, 1191 + * we skip adding this mixer control. 1192 + */ 1193 + if (fs210x->amp_lib.scene_count < 2) 1194 + return 0; 1195 + 1196 + kctrl = fs210x_scene_control; 1197 + count = ARRAY_SIZE(fs210x_scene_control); 1198 + 1199 + return snd_soc_add_component_controls(cmpnt, kctrl, count); 1200 + } 1201 + 1202 + static int fs210x_probe(struct snd_soc_component *cmpnt) 1203 + { 1204 + struct fs210x_priv *fs210x; 1205 + int ret; 1206 + 1207 + fs210x = snd_soc_component_get_drvdata(cmpnt); 1208 + if (!fs210x || !fs210x->dev) 1209 + return -EINVAL; 1210 + 1211 + fs210x->amp_lib.dev = fs210x->dev; 1212 + fs210x->amp_lib.devid = fs210x->devid; 1213 + 1214 + ret = fs_amp_load_firmware(&fs210x->amp_lib, fs210x->pdata.fwm_name); 1215 + if (ret) 1216 + return ret; 1217 + 1218 + ret = fs210x_add_mixer_controls(fs210x, cmpnt); 1219 + if (ret) 1220 + return ret; 1221 + 1222 + mutex_lock(&fs210x->lock); 1223 + ret = fs210x_init_chip(fs210x); 1224 + mutex_unlock(&fs210x->lock); 1225 + 1226 + return ret; 1227 + } 1228 + 1229 + static void fs210x_remove(struct snd_soc_component *cmpnt) 1230 + { 1231 + struct fs210x_priv *fs210x; 1232 + 1233 + fs210x = snd_soc_component_get_drvdata(cmpnt); 1234 + if (!fs210x || !fs210x->dev) 1235 + return; 1236 + 1237 + cancel_delayed_work_sync(&fs210x->start_work); 1238 + cancel_delayed_work_sync(&fs210x->fault_check_work); 1239 + } 1240 + 1241 + #ifdef CONFIG_PM 1242 + static int fs210x_suspend(struct snd_soc_component *cmpnt) 1243 + { 1244 + struct fs210x_priv *fs210x; 1245 + int ret; 1246 + 1247 + fs210x = snd_soc_component_get_drvdata(cmpnt); 1248 + if (!fs210x || !fs210x->dev) 1249 + return -EINVAL; 1250 + 1251 + regcache_cache_only(fs210x->regmap, true); 1252 + 1253 + mutex_lock(&fs210x->lock); 1254 + fs210x->cur_scene = NULL; 1255 + fs210x->is_inited = false; 1256 + fs210x->is_playing = false; 1257 + fs210x->is_suspended = true; 1258 + 1259 + gpiod_set_value_cansleep(fs210x->gpio_sdz, 1); /* Active */ 1260 + fsleep(30000); /* >= 30ms */ 1261 + mutex_unlock(&fs210x->lock); 1262 + 1263 + cancel_delayed_work_sync(&fs210x->start_work); 1264 + cancel_delayed_work_sync(&fs210x->fault_check_work); 1265 + 1266 + ret = regulator_bulk_disable(FS210X_NUM_SUPPLIES, fs210x->supplies); 1267 + if (ret) { 1268 + dev_err(fs210x->dev, "Failed to suspend: %d\n", ret); 1269 + return ret; 1270 + } 1271 + 1272 + return 0; 1273 + } 1274 + 1275 + static int fs210x_resume(struct snd_soc_component *cmpnt) 1276 + { 1277 + struct fs210x_priv *fs210x; 1278 + int ret; 1279 + 1280 + fs210x = snd_soc_component_get_drvdata(cmpnt); 1281 + if (!fs210x || !fs210x->dev) 1282 + return -EINVAL; 1283 + 1284 + ret = regulator_bulk_enable(FS210X_NUM_SUPPLIES, fs210x->supplies); 1285 + if (ret) { 1286 + dev_err(fs210x->dev, "Failed to enable supplies: %d\n", ret); 1287 + return ret; 1288 + } 1289 + 1290 + mutex_lock(&fs210x->lock); 1291 + 1292 + fs210x->is_suspended = false; 1293 + ret = fs210x_init_chip(fs210x); 1294 + 1295 + mutex_unlock(&fs210x->lock); 1296 + 1297 + return ret; 1298 + } 1299 + #else 1300 + #define fs210x_suspend NULL 1301 + #define fs210x_resume NULL 1302 + #endif // CONFIG_PM 1303 + 1304 + static bool fs210x_volatile_registers(struct device *dev, unsigned int reg) 1305 + { 1306 + switch (reg) { 1307 + case FS210X_00H_STATUS ... FS210X_0FH_I2CADDR: 1308 + case FS210X_ABH_INTSTAT: 1309 + case FS210X_ACH_INTSTATR: 1310 + return true; 1311 + default: 1312 + return false; 1313 + } 1314 + } 1315 + 1316 + static const struct snd_soc_component_driver fs210x_soc_component_dev = { 1317 + .probe = fs210x_probe, 1318 + .remove = fs210x_remove, 1319 + .suspend = fs210x_suspend, 1320 + .resume = fs210x_resume, 1321 + .controls = fs210x_controls, 1322 + .num_controls = ARRAY_SIZE(fs210x_controls), 1323 + .dapm_widgets = fs210x_dapm_widgets, 1324 + .num_dapm_widgets = ARRAY_SIZE(fs210x_dapm_widgets), 1325 + .dapm_routes = fs210x_dapm_routes, 1326 + .num_dapm_routes = ARRAY_SIZE(fs210x_dapm_routes), 1327 + }; 1328 + 1329 + static const struct regmap_config fs210x_regmap = { 1330 + .reg_bits = 8, 1331 + .val_bits = 16, 1332 + .max_register = FS210X_REG_MAX, 1333 + .val_format_endian = REGMAP_ENDIAN_BIG, 1334 + .cache_type = REGCACHE_MAPLE, 1335 + .volatile_reg = fs210x_volatile_registers, 1336 + }; 1337 + 1338 + static int fs210x_detect_device(struct fs210x_priv *fs210x) 1339 + { 1340 + u16 devid; 1341 + int ret; 1342 + 1343 + ret = fs210x_reg_read(fs210x, FS210X_03H_DEVID, &devid); 1344 + if (ret) 1345 + return ret; 1346 + 1347 + fs210x->devid = HI_U16(devid); 1348 + 1349 + switch (fs210x->devid) { 1350 + case FS210X_DEVICE_ID: 1351 + dev_info(fs210x->dev, "FS2104 detected\n"); 1352 + break; 1353 + case FS2105S_DEVICE_ID: 1354 + dev_info(fs210x->dev, "FS2105S detected\n"); 1355 + break; 1356 + default: 1357 + dev_err(fs210x->dev, "DEVID: 0x%04X dismatch\n", devid); 1358 + return -ENODEV; 1359 + } 1360 + 1361 + return 0; 1362 + } 1363 + 1364 + static int fs210x_parse_dts(struct fs210x_priv *fs210x, 1365 + struct fs210x_platform_data *pdata) 1366 + { 1367 + struct device_node *node = fs210x->dev->of_node; 1368 + int i, ret; 1369 + 1370 + if (!node) 1371 + return 0; 1372 + 1373 + ret = of_property_read_string(node, "firmware-name", &pdata->fwm_name); 1374 + if (ret) 1375 + pdata->fwm_name = FS210X_DEFAULT_FWM_NAME; 1376 + 1377 + fs210x->gpio_sdz = devm_gpiod_get_optional(fs210x->dev, 1378 + "reset", GPIOD_OUT_HIGH); 1379 + if (IS_ERR(fs210x->gpio_sdz)) 1380 + return dev_err_probe(fs210x->dev, PTR_ERR(fs210x->gpio_sdz), 1381 + "Failed to get reset-gpios\n"); 1382 + 1383 + for (i = 0; i < FS210X_NUM_SUPPLIES; i++) 1384 + fs210x->supplies[i].supply = fs210x_supply_names[i]; 1385 + 1386 + ret = devm_regulator_bulk_get(fs210x->dev, 1387 + ARRAY_SIZE(fs210x->supplies), 1388 + fs210x->supplies); 1389 + if (ret) 1390 + return dev_err_probe(fs210x->dev, ret, 1391 + "Failed to get supplies\n"); 1392 + 1393 + return 0; 1394 + } 1395 + 1396 + static void fs210x_deinit(struct fs210x_priv *fs210x) 1397 + { 1398 + gpiod_set_value_cansleep(fs210x->gpio_sdz, 1); /* Active */ 1399 + fsleep(10000); /* >= 10ms */ 1400 + 1401 + regulator_bulk_disable(FS210X_NUM_SUPPLIES, fs210x->supplies); 1402 + } 1403 + 1404 + static int fs210x_init(struct fs210x_priv *fs210x) 1405 + { 1406 + int ret; 1407 + 1408 + ret = fs210x_parse_dts(fs210x, &fs210x->pdata); 1409 + if (ret) 1410 + return ret; 1411 + 1412 + fs210x->clk_bclk = devm_clk_get_optional(fs210x->dev, "bclk"); 1413 + if (IS_ERR(fs210x->clk_bclk)) 1414 + return dev_err_probe(fs210x->dev, PTR_ERR(fs210x->clk_bclk), 1415 + "Failed to get bclk\n"); 1416 + 1417 + ret = regulator_bulk_enable(FS210X_NUM_SUPPLIES, fs210x->supplies); 1418 + if (ret) 1419 + return dev_err_probe(fs210x->dev, ret, 1420 + "Failed to enable supplies\n"); 1421 + 1422 + /* Make sure the SDZ pin is pulled down enough time. */ 1423 + fsleep(10000); /* >= 10ms */ 1424 + gpiod_set_value_cansleep(fs210x->gpio_sdz, 0); /* Deactivate */ 1425 + fsleep(10000); /* >= 10ms */ 1426 + 1427 + ret = fs210x_detect_device(fs210x); 1428 + if (ret) { 1429 + fs210x_deinit(fs210x); 1430 + return ret; 1431 + } 1432 + 1433 + fs210x->scene_id = -1; /* Invalid scene */ 1434 + fs210x->cur_scene = NULL; 1435 + fs210x->is_playing = false; 1436 + fs210x->is_inited = false; 1437 + fs210x->is_suspended = false; 1438 + fs210x->check_interval_ms = FS210X_FAULT_CHECK_INTERVAL_MS; 1439 + 1440 + INIT_DELAYED_WORK(&fs210x->fault_check_work, fs210x_fault_check_work); 1441 + INIT_DELAYED_WORK(&fs210x->start_work, fs210x_start_work); 1442 + mutex_init(&fs210x->lock); 1443 + 1444 + return 0; 1445 + } 1446 + 1447 + static int fs210x_register_snd_component(struct fs210x_priv *fs210x) 1448 + { 1449 + struct snd_soc_dai_driver *dai_drv; 1450 + static int instance_id; 1451 + int ret; 1452 + 1453 + dai_drv = devm_kmemdup(fs210x->dev, &fs210x_dai, 1454 + sizeof(fs210x_dai), GFP_KERNEL); 1455 + if (!dai_drv) 1456 + return -ENOMEM; 1457 + 1458 + dai_drv->name = devm_kasprintf(fs210x->dev, 1459 + GFP_KERNEL, "%s-%d", 1460 + dai_drv->name, instance_id); 1461 + instance_id++; 1462 + 1463 + if (fs210x->devid == FS2105S_DEVICE_ID) { 1464 + dai_drv->playback.rates = FS2105S_RATES; 1465 + dai_drv->capture.rates = FS2105S_RATES; 1466 + } 1467 + 1468 + ret = snd_soc_register_component(fs210x->dev, 1469 + &fs210x_soc_component_dev, 1470 + dai_drv, 1); 1471 + return ret; 1472 + } 1473 + 1474 + static ssize_t check_interval_ms_show(struct device *dev, 1475 + struct device_attribute *devattr, 1476 + char *buf) 1477 + { 1478 + struct fs210x_priv *fs210x = dev_get_drvdata(dev); 1479 + 1480 + return sysfs_emit(buf, "%d\n", fs210x->check_interval_ms); 1481 + } 1482 + 1483 + static ssize_t check_interval_ms_store(struct device *dev, 1484 + struct device_attribute *devattr, 1485 + const char *buf, 1486 + size_t count) 1487 + { 1488 + struct fs210x_priv *fs210x = dev_get_drvdata(dev); 1489 + int ret; 1490 + 1491 + ret = kstrtouint(buf, 10, &fs210x->check_interval_ms); 1492 + if (ret) 1493 + return -EINVAL; 1494 + 1495 + return (ssize_t)count; 1496 + } 1497 + 1498 + static DEVICE_ATTR_RW(check_interval_ms); 1499 + 1500 + static struct attribute *fs210x_attrs[] = { 1501 + &dev_attr_check_interval_ms.attr, 1502 + NULL, 1503 + }; 1504 + 1505 + static struct attribute_group fs210x_attr_group = { 1506 + .attrs = fs210x_attrs, 1507 + }; 1508 + 1509 + static int fs210x_i2c_probe(struct i2c_client *client) 1510 + { 1511 + struct fs210x_priv *fs210x; 1512 + int ret; 1513 + 1514 + fs210x = devm_kzalloc(&client->dev, sizeof(*fs210x), GFP_KERNEL); 1515 + if (!fs210x) 1516 + return -ENOMEM; 1517 + 1518 + fs210x->i2c = client; 1519 + fs210x->dev = &client->dev; 1520 + i2c_set_clientdata(client, fs210x); 1521 + 1522 + fs210x->regmap = devm_regmap_init_i2c(client, &fs210x_regmap); 1523 + if (IS_ERR(fs210x->regmap)) 1524 + return dev_err_probe(fs210x->dev, PTR_ERR(fs210x->regmap), 1525 + "Failed to get regmap\n"); 1526 + 1527 + ret = fs210x_init(fs210x); 1528 + if (ret) 1529 + return ret; 1530 + 1531 + ret = devm_device_add_group(fs210x->dev, &fs210x_attr_group); 1532 + if (ret) { 1533 + fs210x_deinit(fs210x); 1534 + return dev_err_probe(fs210x->dev, ret, 1535 + "Failed to create sysfs group\n"); 1536 + } 1537 + 1538 + ret = fs210x_register_snd_component(fs210x); 1539 + if (ret) { 1540 + fs210x_deinit(fs210x); 1541 + return dev_err_probe(fs210x->dev, ret, 1542 + "Failed to register component\n"); 1543 + } 1544 + 1545 + return 0; 1546 + } 1547 + 1548 + static void fs210x_i2c_remove(struct i2c_client *client) 1549 + { 1550 + struct fs210x_priv *fs210x = i2c_get_clientdata(client); 1551 + 1552 + snd_soc_unregister_component(fs210x->dev); 1553 + fs210x_deinit(fs210x); 1554 + } 1555 + 1556 + static const struct i2c_device_id fs210x_i2c_id[] = { 1557 + { "fs2104" }, 1558 + { "fs2105s" }, 1559 + {} 1560 + }; 1561 + MODULE_DEVICE_TABLE(i2c, fs210x_i2c_id); 1562 + 1563 + static const struct of_device_id fs210x_of_match[] = { 1564 + { .compatible = "foursemi,fs2105s", }, 1565 + {}, 1566 + }; 1567 + MODULE_DEVICE_TABLE(of, fs210x_of_match); 1568 + 1569 + static struct i2c_driver fs210x_i2c_driver = { 1570 + .driver = { 1571 + .name = "fs210x", 1572 + .of_match_table = fs210x_of_match, 1573 + }, 1574 + .id_table = fs210x_i2c_id, 1575 + .probe = fs210x_i2c_probe, 1576 + .remove = fs210x_i2c_remove, 1577 + }; 1578 + 1579 + module_i2c_driver(fs210x_i2c_driver); 1580 + 1581 + MODULE_AUTHOR("Nick Li <nick.li@foursemi.com>"); 1582 + MODULE_DESCRIPTION("FS2104/5S Audio Amplifier Driver"); 1583 + MODULE_LICENSE("GPL");
+75
sound/soc/codecs/fs210x.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * fs210x.h -- Driver for the FS2104/5S Audio Amplifier 4 + * 5 + * Copyright (C) 2016-2025 Shanghai FourSemi Semiconductor Co.,Ltd. 6 + */ 7 + 8 + #ifndef __FS210X_H__ 9 + #define __FS210X_H__ 10 + 11 + #define FS210X_00H_STATUS 0x00 12 + #define FS210X_03H_DEVID 0x03 13 + #define FS210X_05H_ANASTAT 0x05 14 + #define FS210X_06H_DIGSTAT 0x06 15 + #define FS210X_0BH_ACCKEY 0x0B 16 + #define FS210X_0FH_I2CADDR 0x0F 17 + #define FS210X_10H_PWRCTRL 0x10 18 + #define FS210X_11H_SYSCTRL 0x11 19 + #define FS210X_17H_I2SCTRL 0x17 20 + #define FS210X_30H_DACCTRL 0x30 21 + #define FS210X_39H_LVOLCTRL 0x39 22 + #define FS210X_3AH_RVOLCTRL 0x3A 23 + #define FS210X_42H_DACEQWL 0x42 24 + #define FS210X_46H_DACEQA 0x46 25 + #define FS210X_A1H_PLLCTRL1 0xA1 26 + #define FS210X_A2H_PLLCTRL2 0xA2 27 + #define FS210X_A3H_PLLCTRL3 0xA3 28 + #define FS210X_ABH_INTSTAT 0xAB 29 + #define FS210X_ACH_INTSTATR 0xAC 30 + 31 + #define FS210X_05H_PVDD_SHIFT 14 32 + #define FS210X_05H_PVDD_MASK BIT(14) 33 + #define FS210X_05H_OCDL_SHIFT 13 34 + #define FS210X_05H_OCDL_MASK BIT(13) 35 + #define FS210X_05H_UVDL_SHIFT 12 36 + #define FS210X_05H_UVDL_MASK BIT(12) 37 + #define FS210X_05H_OVDL_SHIFT 11 38 + #define FS210X_05H_OVDL_MASK BIT(11) 39 + #define FS210X_05H_OTPDL_SHIFT 10 40 + #define FS210X_05H_OTPDL_MASK BIT(10) 41 + #define FS210X_05H_OCRDL_SHIFT 9 42 + #define FS210X_05H_OCRDL_MASK BIT(9) 43 + #define FS210X_05H_OCLDL_SHIFT 8 44 + #define FS210X_05H_OCLDL_MASK BIT(8) 45 + #define FS210X_05H_DCRDL_SHIFT 7 46 + #define FS210X_05H_DCRDL_MASK BIT(7) 47 + #define FS210X_05H_DCLDL_SHIFT 6 48 + #define FS210X_05H_DCLDL_MASK BIT(6) 49 + #define FS210X_05H_SRDL_SHIFT 5 50 + #define FS210X_05H_SRDL_MASK BIT(5) 51 + #define FS210X_05H_OTWDL_SHIFT 4 52 + #define FS210X_05H_OTWDL_MASK BIT(4) 53 + #define FS210X_05H_AMPS_SHIFT 3 54 + #define FS210X_05H_AMPS_MASK BIT(3) 55 + #define FS210X_05H_PLLS_SHIFT 1 56 + #define FS210X_05H_PLLS_MASK BIT(1) 57 + #define FS210X_05H_ANAS_SHIFT 0 58 + #define FS210X_05H_ANAS_MASK BIT(0) 59 + #define FS210X_17H_I2SSR_SHIFT 12 60 + #define FS210X_17H_I2SSR_MASK GENMASK(15, 12) 61 + #define FS210X_30H_RMUTE_SHIFT 8 62 + #define FS210X_30H_LMUTE_SHIFT 4 63 + 64 + #define FS210X_0BH_ACCKEY_ON 0x0091 65 + #define FS210X_0BH_ACCKEY_OFF 0x0000 66 + #define FS210X_10H_I2C_RESET 0x0002 67 + #define FS210X_11H_DPS_HIZ 0x0100 68 + #define FS210X_11H_DPS_PWDN 0x0000 69 + #define FS210X_11H_DPS_PLAY 0x0300 70 + #define FS210X_46H_CAM_BURST_L 0x8000 71 + #define FS210X_46H_CAM_BURST_R 0x8200 72 + #define FS2105S_46H_CAM_BURST_W 0x8400 73 + #define FS210X_46H_CAM_CLEAR 0x0000 74 + 75 + #endif /* __FS210X_H__ */