901 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2//3// nau8325.c -- Nuvoton NAU8325 audio codec driver4//5// Copyright 2023 Nuvoton Technology Crop.6// Author: Seven Lee <WTLI@nuvoton.com>7// David Lin <CTLIN0@nuvoton.com>8//9 10#include <linux/clk.h>11#include <linux/delay.h>12#include <linux/init.h>13#include <linux/i2c.h>14#include <linux/module.h>15#include <linux/regmap.h>16#include <linux/slab.h>17#include <sound/core.h>18#include <sound/initval.h>19#include <sound/pcm.h>20#include <sound/pcm_params.h>21#include <sound/soc.h>22#include <sound/tlv.h>23#include "nau8325.h"24 25/* Range of Master Clock MCLK (Hz) */26#define MASTER_CLK_MAX 4915200027#define MASTER_CLK_MIN 204800028 29/* scaling for MCLK source */30#define CLK_PROC_BYPASS (-1)31 32/* the maximum CLK_DAC */33#define CLK_DA_AD_MAX 614400034 35/* from MCLK input */36#define MCLK_SRC 437 38static const struct nau8325_src_attr mclk_n1_div[] = {39 { 1, 0x0 },40 { 2, 0x1 },41 { 3, 0x2 },42};43 44/* over sampling rate */45static const struct nau8325_osr_attr osr_dac_sel[] = {46 { 64, 2 }, /* OSR 64, SRC 1/4 */47 { 256, 0 }, /* OSR 256, SRC 1 */48 { 128, 1 }, /* OSR 128, SRC 1/2 */49 { 0, 0 },50 { 32, 3 }, /* OSR 32, SRC 1/8 */51};52 53static const struct nau8325_src_attr mclk_n2_div[] = {54 { 0, 0x0 },55 { 1, 0x1 },56 { 2, 0x2 },57 { 3, 0x3 },58 { 4, 0x4 },59};60 61static const struct nau8325_src_attr mclk_n3_mult[] = {62 { 0, 0x1 },63 { 1, 0x2 },64 { 2, 0x3 },65 { 3, 0x4 },66};67 68/* Sample Rate and MCLK_SRC selections */69static const struct nau8325_srate_attr target_srate_table[] = {70 /* { FS, range, max, { MCLK source }} */71 { 48000, 2, true, { 12288000, 19200000, 24000000 } },72 { 16000, 1, false, { 4096000, 6400000, 8000000 } },73 { 8000, 0, false, { 2048000, 3200000, 4000000 }},74 { 44100, 2, true, { 11289600, 17640000, 22050000 }},75 { 64000, 3, false, { 16384000, 25600000, 32000000 } },76 { 96000, 3, true, { 24576000, 38400000, 48000000 } },77 { 12000, 0, true, { 3072000, 4800000, 6000000 } },78 { 24000, 1, true, { 6144000, 9600000, 12000000 } },79 { 32000, 2, false, { 8192000, 12800000, 16000000 } },80};81 82static const struct reg_default nau8325_reg_defaults[] = {83 { NAU8325_R00_HARDWARE_RST, 0x0000 },84 { NAU8325_R01_SOFTWARE_RST, 0x0000 },85 { NAU8325_R03_CLK_CTRL, 0x0000 },86 { NAU8325_R04_ENA_CTRL, 0x0000 },87 { NAU8325_R05_INTERRUPT_CTRL, 0x007f },88 { NAU8325_R09_IRQOUT, 0x0000 },89 { NAU8325_R0A_IO_CTRL, 0x0000 },90 { NAU8325_R0B_PDM_CTRL, 0x0000 },91 { NAU8325_R0C_TDM_CTRL, 0x0000 },92 { NAU8325_R0D_I2S_PCM_CTRL1, 0x000a },93 { NAU8325_R0E_I2S_PCM_CTRL2, 0x0000 },94 { NAU8325_R0F_L_TIME_SLOT, 0x0000 },95 { NAU8325_R10_R_TIME_SLOT, 0x0000 },96 { NAU8325_R11_HPF_CTRL, 0x0000 },97 { NAU8325_R12_MUTE_CTRL, 0x0000 },98 { NAU8325_R13_DAC_VOLUME, 0xf3f3 },99 { NAU8325_R29_DAC_CTRL1, 0x0081 },100 { NAU8325_R2A_DAC_CTRL2, 0x0000 },101 { NAU8325_R2C_ALC_CTRL1, 0x000e },102 { NAU8325_R2D_ALC_CTRL2, 0x8400 },103 { NAU8325_R2E_ALC_CTRL3, 0x0000 },104 { NAU8325_R2F_ALC_CTRL4, 0x003f },105 { NAU8325_R40_CLK_DET_CTRL, 0xa801 },106 { NAU8325_R50_MIXER_CTRL, 0x0000 },107 { NAU8325_R55_MISC_CTRL, 0x0000 },108 { NAU8325_R60_BIAS_ADJ, 0x0000 },109 { NAU8325_R61_ANALOG_CONTROL_1, 0x0000 },110 { NAU8325_R62_ANALOG_CONTROL_2, 0x0000 },111 { NAU8325_R63_ANALOG_CONTROL_3, 0x0000 },112 { NAU8325_R64_ANALOG_CONTROL_4, 0x0000 },113 { NAU8325_R65_ANALOG_CONTROL_5, 0x0000 },114 { NAU8325_R66_ANALOG_CONTROL_6, 0x0000 },115 { NAU8325_R69_CLIP_CTRL, 0x0000 },116 { NAU8325_R73_RDAC, 0x0008 },117};118 119static bool nau8325_readable_reg(struct device *dev, unsigned int reg)120{121 switch (reg) {122 case NAU8325_R02_DEVICE_ID ... NAU8325_R06_INT_CLR_STATUS:123 case NAU8325_R09_IRQOUT ... NAU8325_R13_DAC_VOLUME:124 case NAU8325_R1D_DEBUG_READ1:125 case NAU8325_R1F_DEBUG_READ2:126 case NAU8325_R22_DEBUG_READ3:127 case NAU8325_R29_DAC_CTRL1 ... NAU8325_R2A_DAC_CTRL2:128 case NAU8325_R2C_ALC_CTRL1 ... NAU8325_R2F_ALC_CTRL4:129 case NAU8325_R40_CLK_DET_CTRL:130 case NAU8325_R49_TEST_STATUS ... NAU8325_R4A_ANALOG_READ:131 case NAU8325_R50_MIXER_CTRL:132 case NAU8325_R55_MISC_CTRL:133 case NAU8325_R60_BIAS_ADJ ... NAU8325_R66_ANALOG_CONTROL_6:134 case NAU8325_R69_CLIP_CTRL:135 case NAU8325_R73_RDAC:136 return true;137 default:138 return false;139 }140}141 142static bool nau8325_writeable_reg(struct device *dev, unsigned int reg)143{144 switch (reg) {145 case NAU8325_R00_HARDWARE_RST:146 case NAU8325_R03_CLK_CTRL ... NAU8325_R06_INT_CLR_STATUS:147 case NAU8325_R09_IRQOUT ... NAU8325_R13_DAC_VOLUME:148 case NAU8325_R29_DAC_CTRL1 ... NAU8325_R2A_DAC_CTRL2:149 case NAU8325_R2C_ALC_CTRL1 ... NAU8325_R2F_ALC_CTRL4:150 case NAU8325_R40_CLK_DET_CTRL:151 case NAU8325_R50_MIXER_CTRL:152 case NAU8325_R55_MISC_CTRL:153 case NAU8325_R60_BIAS_ADJ ... NAU8325_R66_ANALOG_CONTROL_6:154 case NAU8325_R69_CLIP_CTRL:155 case NAU8325_R73_RDAC:156 return true;157 default:158 return false;159 }160}161 162static bool nau8325_volatile_reg(struct device *dev, unsigned int reg)163{164 switch (reg) {165 case NAU8325_R00_HARDWARE_RST ... NAU8325_R02_DEVICE_ID:166 case NAU8325_R06_INT_CLR_STATUS:167 case NAU8325_R1D_DEBUG_READ1:168 case NAU8325_R1F_DEBUG_READ2:169 case NAU8325_R22_DEBUG_READ3:170 case NAU8325_R4A_ANALOG_READ:171 return true;172 default:173 return false;174 }175}176 177static const char * const nau8325_dac_oversampl_texts[] = {178 "64", "256", "128", "32",179};180 181static const unsigned int nau8325_dac_oversampl_values[] = {182 0, 1, 2, 4,183};184 185static const struct soc_enum nau8325_dac_oversampl_enum =186 SOC_VALUE_ENUM_SINGLE(NAU8325_R29_DAC_CTRL1,187 NAU8325_DAC_OVERSAMPLE_SFT, 0x7,188 ARRAY_SIZE(nau8325_dac_oversampl_texts),189 nau8325_dac_oversampl_texts,190 nau8325_dac_oversampl_values);191 192static const DECLARE_TLV_DB_MINMAX_MUTE(dac_vol_tlv, -8000, 600);193 194static const struct snd_kcontrol_new nau8325_snd_controls[] = {195 SOC_ENUM("DAC Oversampling Rate", nau8325_dac_oversampl_enum),196 SOC_DOUBLE_TLV("Speaker Volume", NAU8325_R13_DAC_VOLUME,197 NAU8325_DAC_VOLUME_L_SFT, NAU8325_DAC_VOLUME_R_SFT,198 NAU8325_DAC_VOLUME_R_EN, 0, dac_vol_tlv),199 SOC_SINGLE("ALC Max Gain", NAU8325_R2C_ALC_CTRL1,200 NAU8325_ALC_MAXGAIN_SFT, NAU8325_ALC_MAXGAIN_MAX, 0),201 SOC_SINGLE("ALC Min Gain", NAU8325_R2C_ALC_CTRL1,202 NAU8325_ALC_MINGAIN_SFT, NAU8325_ALC_MINGAIN_MAX, 0),203 SOC_SINGLE("ALC Decay Timer", NAU8325_R2D_ALC_CTRL2,204 NAU8325_ALC_DCY_SFT, NAU8325_ALC_DCY_MAX, 0),205 SOC_SINGLE("ALC Attack Timer", NAU8325_R2D_ALC_CTRL2,206 NAU8325_ALC_ATK_SFT, NAU8325_ALC_ATK_MAX, 0),207 SOC_SINGLE("ALC Hold Time", NAU8325_R2D_ALC_CTRL2,208 NAU8325_ALC_HLD_SFT, NAU8325_ALC_HLD_MAX, 0),209 SOC_SINGLE("ALC Target Level", NAU8325_R2D_ALC_CTRL2,210 NAU8325_ALC_LVL_SFT, NAU8325_ALC_LVL_MAX, 0),211 SOC_SINGLE("ALC Enable Switch", NAU8325_R2E_ALC_CTRL3,212 NAU8325_ALC_EN_SFT, 1, 0),213};214 215static int nau8325_dac_event(struct snd_soc_dapm_widget *w,216 struct snd_kcontrol *kcontrol, int event)217{218 struct snd_soc_component *component =219 snd_soc_dapm_to_component(w->dapm);220 struct nau8325 *nau8325 = snd_soc_component_get_drvdata(component);221 222 switch (event) {223 case SND_SOC_DAPM_POST_PMU:224 regmap_update_bits(nau8325->regmap, NAU8325_R12_MUTE_CTRL,225 NAU8325_SOFT_MUTE, 0);226 msleep(30);227 break;228 case SND_SOC_DAPM_PRE_PMD:229 /* Soft mute the output to prevent the pop noise. */230 regmap_update_bits(nau8325->regmap, NAU8325_R12_MUTE_CTRL,231 NAU8325_SOFT_MUTE, NAU8325_SOFT_MUTE);232 msleep(30);233 break;234 default:235 return -EINVAL;236 }237 238 return 0;239}240 241static int nau8325_powerup_event(struct snd_soc_dapm_widget *w,242 struct snd_kcontrol *kcontrol, int event)243{244 struct snd_soc_component *component =245 snd_soc_dapm_to_component(w->dapm);246 struct nau8325 *nau8325 = snd_soc_component_get_drvdata(component);247 248 if (nau8325->clock_detection)249 return 0;250 251 switch (event) {252 case SND_SOC_DAPM_POST_PMU:253 regmap_update_bits(nau8325->regmap, NAU8325_R40_CLK_DET_CTRL,254 NAU8325_PWRUP_DFT, NAU8325_PWRUP_DFT);255 break;256 case SND_SOC_DAPM_POST_PMD:257 regmap_update_bits(nau8325->regmap, NAU8325_R40_CLK_DET_CTRL,258 NAU8325_PWRUP_DFT, 0);259 break;260 default:261 return -EINVAL;262 }263 264 return 0;265}266 267static const struct snd_soc_dapm_widget nau8325_dapm_widgets[] = {268 SND_SOC_DAPM_SUPPLY("Power Up", SND_SOC_NOPM, 0, 0,269 nau8325_powerup_event, SND_SOC_DAPM_POST_PMU |270 SND_SOC_DAPM_POST_PMD),271 SND_SOC_DAPM_DAC_E("DACL", NULL, NAU8325_R04_ENA_CTRL,272 NAU8325_DAC_LEFT_CH_EN_SFT, 0, nau8325_dac_event,273 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),274 SND_SOC_DAPM_DAC_E("DACR", NULL, NAU8325_R04_ENA_CTRL,275 NAU8325_DAC_RIGHT_CH_EN_SFT, 0, nau8325_dac_event,276 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),277 SND_SOC_DAPM_AIF_IN("AIFRX", "Playback", 0, SND_SOC_NOPM, 0, 0),278 279 SND_SOC_DAPM_OUTPUT("SPKL"),280 SND_SOC_DAPM_OUTPUT("SPKR"),281};282 283static const struct snd_soc_dapm_route nau8325_dapm_routes[] = {284 { "DACL", NULL, "Power Up" },285 { "DACR", NULL, "Power Up" },286 287 { "DACL", NULL, "AIFRX" },288 { "DACR", NULL, "AIFRX" },289 { "SPKL", NULL, "DACL" },290 { "SPKR", NULL, "DACR" },291};292 293static int nau8325_srate_clk_apply(struct nau8325 *nau8325,294 const struct nau8325_srate_attr *srate_table,295 int n1_sel, int mclk_mult_sel, int n2_sel)296{297 if (!srate_table || n2_sel < 0 || n2_sel >= ARRAY_SIZE(mclk_n2_div) ||298 n1_sel < 0 || n1_sel >= ARRAY_SIZE(mclk_n1_div)) {299 dev_dbg(nau8325->dev, "The CLK isn't supported.");300 return -EINVAL;301 }302 303 regmap_update_bits(nau8325->regmap, NAU8325_R40_CLK_DET_CTRL,304 NAU8325_REG_SRATE_MASK | NAU8325_REG_DIV_MAX,305 (srate_table->range << NAU8325_REG_SRATE_SFT) |306 (srate_table->max ? NAU8325_REG_DIV_MAX : 0));307 regmap_update_bits(nau8325->regmap, NAU8325_R03_CLK_CTRL,308 NAU8325_MCLK_SRC_MASK, mclk_n2_div[n2_sel].val);309 regmap_update_bits(nau8325->regmap, NAU8325_R03_CLK_CTRL,310 NAU8325_CLK_MUL_SRC_MASK,311 mclk_n1_div[n1_sel].val << NAU8325_CLK_MUL_SRC_SFT);312 313 if (mclk_mult_sel != CLK_PROC_BYPASS) {314 regmap_update_bits(nau8325->regmap, NAU8325_R03_CLK_CTRL,315 NAU8325_MCLK_SEL_MASK,316 mclk_n3_mult[mclk_mult_sel].val <<317 NAU8325_MCLK_SEL_SFT);318 } else {319 regmap_update_bits(nau8325->regmap, NAU8325_R03_CLK_CTRL,320 NAU8325_MCLK_SEL_MASK, 0);321 }322 323 switch (mclk_mult_sel) {324 case 2:325 regmap_update_bits(nau8325->regmap, NAU8325_R65_ANALOG_CONTROL_5,326 NAU8325_MCLK4XEN_EN, NAU8325_MCLK4XEN_EN);327 break;328 case 3:329 regmap_update_bits(nau8325->regmap, NAU8325_R65_ANALOG_CONTROL_5,330 NAU8325_MCLK4XEN_EN | NAU8325_MCLK8XEN_EN,331 NAU8325_MCLK4XEN_EN | NAU8325_MCLK8XEN_EN);332 break;333 default:334 regmap_update_bits(nau8325->regmap, NAU8325_R65_ANALOG_CONTROL_5,335 NAU8325_MCLK4XEN_EN | NAU8325_MCLK8XEN_EN, 0);336 break;337 }338 339 return 0;340}341 342static int nau8325_clksrc_n2(struct nau8325 *nau8325,343 const struct nau8325_srate_attr *srate_table,344 int mclk, int *n2_sel)345{346 int i, mclk_src, ratio;347 348 ratio = NAU8325_MCLK_FS_RATIO_NUM;349 for (i = 0; i < ARRAY_SIZE(mclk_n2_div); i++) {350 mclk_src = mclk >> mclk_n2_div[i].param;351 if (srate_table->mclk_src[NAU8325_MCLK_FS_RATIO_256] == mclk_src) {352 ratio = NAU8325_MCLK_FS_RATIO_256;353 break;354 } else if (srate_table->mclk_src[NAU8325_MCLK_FS_RATIO_400] == mclk_src) {355 ratio = NAU8325_MCLK_FS_RATIO_400;356 break;357 } else if (srate_table->mclk_src[NAU8325_MCLK_FS_RATIO_500] == mclk_src) {358 ratio = NAU8325_MCLK_FS_RATIO_500;359 break;360 }361 }362 if (ratio != NAU8325_MCLK_FS_RATIO_NUM)363 *n2_sel = i;364 365 return ratio;366}367 368static const struct nau8325_srate_attr *target_srate_attribute(int srate)369{370 int i;371 372 for (i = 0; i < ARRAY_SIZE(target_srate_table); i++)373 if (target_srate_table[i].fs == srate)374 break;375 376 if (i == ARRAY_SIZE(target_srate_table))377 goto proc_err;378 379 return &target_srate_table[i];380 381proc_err:382 return NULL;383}384 385static int nau8325_clksrc_choose(struct nau8325 *nau8325,386 const struct nau8325_srate_attr **srate_table,387 int *n1_sel, int *mult_sel, int *n2_sel)388{389 int i, j, mclk, mclk_max, ratio, ratio_sel, n2_max;390 391 if (!nau8325->mclk || !nau8325->fs)392 goto proc_err;393 394 /* select sampling rate and MCLK_SRC */395 *srate_table = target_srate_attribute(nau8325->fs);396 if (!*srate_table)397 goto proc_err;398 399 /* First check clock from MCLK directly, decide N2 for MCLK_SRC.400 * If not good, consider 1/N1 and Multiplier.401 */402 ratio = nau8325_clksrc_n2(nau8325, *srate_table, nau8325->mclk, n2_sel);403 if (ratio != NAU8325_MCLK_FS_RATIO_NUM) {404 *n1_sel = 0;405 *mult_sel = CLK_PROC_BYPASS;406 *n2_sel = MCLK_SRC;407 goto proc_done;408 }409 410 /* Get MCLK_SRC through 1/N, Multiplier, and then 1/N2. */411 mclk_max = 0;412 for (i = 0; i < ARRAY_SIZE(mclk_n1_div); i++) {413 for (j = 0; j < ARRAY_SIZE(mclk_n3_mult); j++) {414 mclk = nau8325->mclk << mclk_n3_mult[j].param;415 mclk = mclk / mclk_n1_div[i].param;416 ratio = nau8325_clksrc_n2(nau8325,417 *srate_table, mclk, n2_sel);418 if (ratio != NAU8325_MCLK_FS_RATIO_NUM &&419 (mclk_max < mclk || i > *n1_sel)) {420 mclk_max = mclk;421 n2_max = *n2_sel;422 *n1_sel = i;423 *mult_sel = j;424 ratio_sel = ratio;425 goto proc_done;426 }427 }428 }429 if (mclk_max) {430 *n2_sel = n2_max;431 ratio = ratio_sel;432 goto proc_done;433 }434 435proc_err:436 dev_dbg(nau8325->dev, "The MCLK %d is invalid. It can't get MCLK_SRC of 256/400/500 FS (%d)",437 nau8325->mclk, nau8325->fs);438 return -EINVAL;439proc_done:440 dev_dbg(nau8325->dev, "nau8325->fs=%d,range=0x%x, %s, (n1,mu,n2,dmu):(%d,%d,%d), MCLK_SRC=%uHz (%d)",441 nau8325->fs, (*srate_table)->range,442 (*srate_table)->max ? "MAX" : "MIN",443 *n1_sel == CLK_PROC_BYPASS ?444 CLK_PROC_BYPASS : mclk_n1_div[*n1_sel].param,445 *mult_sel == CLK_PROC_BYPASS ?446 CLK_PROC_BYPASS : 1 << mclk_n3_mult[*mult_sel].param,447 1 << mclk_n2_div[*n2_sel].param,448 (*srate_table)->mclk_src[ratio],449 (*srate_table)->mclk_src[ratio] / nau8325->fs);450 451 return 0;452}453 454static int nau8325_clock_config(struct nau8325 *nau8325)455{456 const struct nau8325_srate_attr *srate_table;457 int ret, n1_sel, mult_sel, n2_sel;458 459 ret = nau8325_clksrc_choose(nau8325, &srate_table,460 &n1_sel, &mult_sel, &n2_sel);461 if (ret)462 goto err;463 464 ret = nau8325_srate_clk_apply(nau8325, srate_table,465 n1_sel, mult_sel, n2_sel);466 if (ret)467 goto err;468 469 return 0;470err:471 return ret;472}473 474static const struct nau8325_osr_attr *nau8325_get_osr(struct nau8325 *nau8325)475{476 unsigned int osr;477 478 regmap_read(nau8325->regmap, NAU8325_R29_DAC_CTRL1, &osr);479 osr &= NAU8325_DAC_OVERSAMPLE_MASK;480 if (osr >= ARRAY_SIZE(osr_dac_sel))481 return NULL;482 483 return &osr_dac_sel[osr];484}485 486static int nau8325_dai_startup(struct snd_pcm_substream *substream,487 struct snd_soc_dai *dai)488{489 struct snd_soc_component *component = dai->component;490 struct nau8325 *nau8325 = snd_soc_component_get_drvdata(component);491 const struct nau8325_osr_attr *osr;492 493 osr = nau8325_get_osr(nau8325);494 if (!osr || !osr->osr)495 return -EINVAL;496 497 return snd_pcm_hw_constraint_minmax(substream->runtime,498 SNDRV_PCM_HW_PARAM_RATE,499 0, CLK_DA_AD_MAX / osr->osr);500}501 502static int nau8325_hw_params(struct snd_pcm_substream *substream,503 struct snd_pcm_hw_params *params,504 struct snd_soc_dai *dai)505{506 struct snd_soc_component *component = dai->component;507 struct nau8325 *nau8325 = snd_soc_component_get_drvdata(component);508 unsigned int val_len = 0;509 const struct nau8325_osr_attr *osr;510 int ret;511 512 nau8325->fs = params_rate(params);513 osr = nau8325_get_osr(nau8325);514 if (!osr || !osr->osr || nau8325->fs * osr->osr > CLK_DA_AD_MAX) {515 ret = -EINVAL;516 goto err;517 }518 regmap_update_bits(nau8325->regmap, NAU8325_R03_CLK_CTRL,519 NAU8325_CLK_DAC_SRC_MASK,520 osr->clk_src << NAU8325_CLK_DAC_SRC_SFT);521 522 ret = nau8325_clock_config(nau8325);523 if (ret)524 goto err;525 526 switch (params_width(params)) {527 case 16:528 val_len |= NAU8325_I2S_DL_16;529 break;530 case 20:531 val_len |= NAU8325_I2S_DL_20;532 break;533 case 24:534 val_len |= NAU8325_I2S_DL_24;535 break;536 case 32:537 val_len |= NAU8325_I2S_DL_32;538 break;539 default:540 ret = -EINVAL;541 goto err;542 }543 544 regmap_update_bits(nau8325->regmap, NAU8325_R0D_I2S_PCM_CTRL1,545 NAU8325_I2S_DL_MASK, val_len);546 547 return 0;548 549err:550 return ret;551}552 553static int nau8325_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)554{555 struct snd_soc_component *component = dai->component;556 struct nau8325 *nau8325 = snd_soc_component_get_drvdata(component);557 unsigned int ctrl1_val = 0;558 559 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {560 case SND_SOC_DAIFMT_CBC_CFC:561 break;562 default:563 return -EINVAL;564 }565 566 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {567 case SND_SOC_DAIFMT_NB_NF:568 break;569 case SND_SOC_DAIFMT_IB_NF:570 ctrl1_val |= NAU8325_I2S_BP_INV;571 break;572 default:573 return -EINVAL;574 }575 576 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {577 case SND_SOC_DAIFMT_I2S:578 ctrl1_val |= NAU8325_I2S_DF_I2S;579 break;580 case SND_SOC_DAIFMT_LEFT_J:581 ctrl1_val |= NAU8325_I2S_DF_LEFT;582 break;583 case SND_SOC_DAIFMT_RIGHT_J:584 ctrl1_val |= NAU8325_I2S_DF_RIGTH;585 break;586 case SND_SOC_DAIFMT_DSP_A:587 ctrl1_val |= NAU8325_I2S_DF_PCM_AB;588 break;589 case SND_SOC_DAIFMT_DSP_B:590 ctrl1_val |= NAU8325_I2S_DF_PCM_AB;591 ctrl1_val |= NAU8325_I2S_PCMB_EN;592 break;593 default:594 return -EINVAL;595 }596 597 regmap_update_bits(nau8325->regmap, NAU8325_R0D_I2S_PCM_CTRL1,598 NAU8325_I2S_DF_MASK | NAU8325_I2S_BP_MASK |599 NAU8325_I2S_PCMB_EN, ctrl1_val);600 601 return 0;602}603 604static int nau8325_set_sysclk(struct snd_soc_component *component, int clk_id,605 int source, unsigned int freq, int dir)606{607 struct nau8325 *nau8325 = snd_soc_component_get_drvdata(component);608 609 if (freq < MASTER_CLK_MIN || freq > MASTER_CLK_MAX) {610 dev_dbg(nau8325->dev, "MCLK exceeds the range, MCLK:%d", freq);611 return -EINVAL;612 }613 614 nau8325->mclk = freq;615 dev_dbg(nau8325->dev, "MCLK %dHz", nau8325->mclk);616 617 return 0;618}619 620static const struct snd_soc_component_driver nau8325_component_driver = {621 .set_sysclk = nau8325_set_sysclk,622 .suspend_bias_off = true,623 .controls = nau8325_snd_controls,624 .num_controls = ARRAY_SIZE(nau8325_snd_controls),625 .dapm_widgets = nau8325_dapm_widgets,626 .num_dapm_widgets = ARRAY_SIZE(nau8325_dapm_widgets),627 .dapm_routes = nau8325_dapm_routes,628 .num_dapm_routes = ARRAY_SIZE(nau8325_dapm_routes),629};630 631static const struct snd_soc_dai_ops nau8325_dai_ops = {632 .startup = nau8325_dai_startup,633 .hw_params = nau8325_hw_params,634 .set_fmt = nau8325_set_fmt,635};636 637#define NAU8325_RATES SNDRV_PCM_RATE_8000_96000638#define NAU8325_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \639 | SNDRV_PCM_FMTBIT_S24_3LE)640 641static struct snd_soc_dai_driver nau8325_dai = {642 .name = NAU8325_CODEC_DAI,643 .playback = {644 .stream_name = "Playback",645 .channels_min = 1,646 .channels_max = 2,647 .rates = NAU8325_RATES,648 .formats = NAU8325_FORMATS,649 },650 .ops = &nau8325_dai_ops,651};652 653static const struct regmap_config nau8325_regmap_config = {654 .reg_bits = NAU8325_REG_ADDR_LEN,655 .val_bits = NAU8325_REG_DATA_LEN,656 657 .max_register = NAU8325_REG_MAX,658 .readable_reg = nau8325_readable_reg,659 .writeable_reg = nau8325_writeable_reg,660 .volatile_reg = nau8325_volatile_reg,661 662 .cache_type = REGCACHE_RBTREE,663 .reg_defaults = nau8325_reg_defaults,664 .num_reg_defaults = ARRAY_SIZE(nau8325_reg_defaults),665};666 667static void nau8325_reset_chip(struct regmap *regmap)668{669 regmap_write(regmap, NAU8325_R00_HARDWARE_RST, 0x0001);670 regmap_write(regmap, NAU8325_R00_HARDWARE_RST, 0x0000);671}672 673static void nau8325_init_regs(struct nau8325 *nau8325)674{675 struct regmap *regmap = nau8325->regmap;676 struct device *dev = nau8325->dev;677 678 /* set ALC parameters */679 regmap_update_bits(regmap, NAU8325_R2C_ALC_CTRL1,680 NAU8325_ALC_MAXGAIN_MASK,681 0x7 << NAU8325_ALC_MAXGAIN_SFT);682 regmap_update_bits(regmap, NAU8325_R2D_ALC_CTRL2,683 NAU8325_ALC_DCY_MASK | NAU8325_ALC_ATK_MASK |684 NAU8325_ALC_HLD_MASK, (0x5 << NAU8325_ALC_DCY_SFT) |685 (0x3 << NAU8325_ALC_ATK_SFT) |686 (0x5 << NAU8325_ALC_HLD_SFT));687 /* Enable ALC to avoid signal distortion when battery low. */688 if (nau8325->alc_enable)689 regmap_update_bits(regmap, NAU8325_R2E_ALC_CTRL3,690 NAU8325_ALC_EN, NAU8325_ALC_EN);691 if (nau8325->clock_detection)692 regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL,693 NAU8325_CLKPWRUP_DIS |694 NAU8325_PWRUP_DFT, 0);695 else696 regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL,697 NAU8325_CLKPWRUP_DIS | NAU8325_PWRUP_DFT,698 NAU8325_CLKPWRUP_DIS);699 if (nau8325->clock_det_data)700 regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL,701 NAU8325_APWRUP_EN, NAU8325_APWRUP_EN);702 else703 regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL,704 NAU8325_APWRUP_EN, 0);705 706 /* DAC Reference Voltage Setting */707 switch (nau8325->dac_vref_microvolt) {708 case 1800000:709 regmap_update_bits(regmap, NAU8325_R73_RDAC,710 NAU8325_DACVREFSEL_MASK, 0 << NAU8325_DACVREFSEL_SFT);711 break;712 case 2700000:713 regmap_update_bits(regmap, NAU8325_R73_RDAC,714 NAU8325_DACVREFSEL_MASK, 1 << NAU8325_DACVREFSEL_SFT);715 break;716 case 2880000:717 regmap_update_bits(regmap, NAU8325_R73_RDAC,718 NAU8325_DACVREFSEL_MASK, 2 << NAU8325_DACVREFSEL_SFT);719 break;720 case 3060000:721 regmap_update_bits(regmap, NAU8325_R73_RDAC,722 NAU8325_DACVREFSEL_MASK, 3 << NAU8325_DACVREFSEL_SFT);723 break;724 default:725 dev_dbg(dev, "Invalid dac-vref-microvolt %d", nau8325->dac_vref_microvolt);726 727 }728 729 /* DAC Reference Voltage Decoupling Capacitors. */730 regmap_update_bits(regmap, NAU8325_R63_ANALOG_CONTROL_3,731 NAU8325_CLASSD_COARSE_GAIN_MASK, 0x4);732 /* Auto-Att Min Gain 0dB, Class-D N Driver Slew Rate -25%. */733 regmap_update_bits(regmap, NAU8325_R64_ANALOG_CONTROL_4,734 NAU8325_CLASSD_SLEWN_MASK, 0x7);735 736 /* VMID Tieoff (VMID Resistor Selection) */737 switch (nau8325->vref_impedance_ohms) {738 case 0:739 regmap_update_bits(regmap, NAU8325_R60_BIAS_ADJ,740 NAU8325_BIAS_VMID_SEL_MASK, 0 << NAU8325_BIAS_VMID_SEL_SFT);741 break;742 case 25000:743 regmap_update_bits(regmap, NAU8325_R60_BIAS_ADJ,744 NAU8325_BIAS_VMID_SEL_MASK, 1 << NAU8325_BIAS_VMID_SEL_SFT);745 break;746 case 125000:747 regmap_update_bits(regmap, NAU8325_R60_BIAS_ADJ,748 NAU8325_BIAS_VMID_SEL_MASK, 2 << NAU8325_BIAS_VMID_SEL_SFT);749 break;750 case 2500:751 regmap_update_bits(regmap, NAU8325_R60_BIAS_ADJ,752 NAU8325_BIAS_VMID_SEL_MASK, 3 << NAU8325_BIAS_VMID_SEL_SFT);753 break;754 default:755 dev_dbg(dev, "Invalid vref-impedance-ohms %d", nau8325->vref_impedance_ohms);756 }757 758 759 /* enable VMID, BIAS, DAC, DCA CLOCK, Voltage/Current Amps760 */761 regmap_update_bits(regmap, NAU8325_R61_ANALOG_CONTROL_1,762 NAU8325_DACEN_MASK | NAU8325_DACCLKEN_MASK |763 NAU8325_DACEN_R_MASK | NAU8325_DACCLKEN_R_MASK |764 NAU8325_CLASSDEN_MASK | NAU8325_VMDFSTENB_MASK |765 NAU8325_BIASEN_MASK | NAU8325_VMIDEN_MASK,766 (0x1 << NAU8325_DACEN_SFT) |767 (0x1 << NAU8325_DACCLKEN_SFT) |768 (0x1 << NAU8325_DACEN_R_SFT) |769 (0x1 << NAU8325_DACCLKEN_R_SFT) |770 (0x1 << NAU8325_CLASSDEN_SFT) |771 (0x1 << NAU8325_VMDFSTENB_SFT) |772 (0x1 << NAU8325_BIASEN_SFT) | 0x3);773 774 /* Enable ALC to avoid signal distortion when battery low. */775 if (nau8325->alc_enable)776 regmap_update_bits(regmap, NAU8325_R2E_ALC_CTRL3,777 NAU8325_ALC_EN, NAU8325_ALC_EN);778 if (nau8325->clock_det_data)779 regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL,780 NAU8325_APWRUP_EN, NAU8325_APWRUP_EN);781 else782 regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL,783 NAU8325_APWRUP_EN, 0);784 if (nau8325->clock_detection)785 regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL,786 NAU8325_CLKPWRUP_DIS |787 NAU8325_PWRUP_DFT, 0);788 else789 regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL,790 NAU8325_CLKPWRUP_DIS | NAU8325_PWRUP_DFT,791 NAU8325_CLKPWRUP_DIS);792 regmap_update_bits(regmap, NAU8325_R29_DAC_CTRL1,793 NAU8325_DAC_OVERSAMPLE_MASK,794 NAU8325_DAC_OVERSAMPLE_128);795}796 797static void nau8325_print_device_properties(struct nau8325 *nau8325)798{799 struct device *dev = nau8325->dev;800 801 dev_dbg(dev, "vref-impedance-ohms: %d", nau8325->vref_impedance_ohms);802 dev_dbg(dev, "dac-vref-microvolt: %d", nau8325->dac_vref_microvolt);803 dev_dbg(dev, "alc-enable: %d", nau8325->alc_enable);804 dev_dbg(dev, "clock-det-data: %d", nau8325->clock_det_data);805 dev_dbg(dev, "clock-detection-disable: %d", nau8325->clock_detection);806}807 808static int nau8325_read_device_properties(struct device *dev,809 struct nau8325 *nau8325)810{811 int ret;812 813 nau8325->alc_enable =814 device_property_read_bool(dev, "nuvoton,alc-enable");815 nau8325->clock_det_data =816 device_property_read_bool(dev, "nuvoton,clock-det-data");817 nau8325->clock_detection =818 !device_property_read_bool(dev, "nuvoton,clock-detection-disable");819 820 ret = device_property_read_u32(dev, "nuvoton,vref-impedance-ohms",821 &nau8325->vref_impedance_ohms);822 if (ret)823 nau8325->vref_impedance_ohms = 125000;824 ret = device_property_read_u32(dev, "nuvoton,dac-vref-microvolt",825 &nau8325->dac_vref_microvolt);826 if (ret)827 nau8325->dac_vref_microvolt = 2880000;828 829 return 0;830}831 832static int nau8325_i2c_probe(struct i2c_client *i2c,833 const struct i2c_device_id *id)834{835 struct device *dev = &i2c->dev;836 struct nau8325 *nau8325 = dev_get_platdata(dev);837 int ret, value;838 839 if (!nau8325) {840 nau8325 = devm_kzalloc(dev, sizeof(*nau8325), GFP_KERNEL);841 if (!nau8325) {842 ret = -ENOMEM;843 goto err;844 }845 ret = nau8325_read_device_properties(dev, nau8325);846 if (ret)847 goto err;848 }849 i2c_set_clientdata(i2c, nau8325);850 851 nau8325->regmap = devm_regmap_init_i2c(i2c, &nau8325_regmap_config);852 if (IS_ERR(nau8325->regmap)) {853 ret = PTR_ERR(nau8325->regmap);854 goto err;855 }856 nau8325->dev = dev;857 nau8325_print_device_properties(nau8325);858 859 nau8325_reset_chip(nau8325->regmap);860 ret = regmap_read(nau8325->regmap, NAU8325_R02_DEVICE_ID, &value);861 if (ret) {862 dev_dbg(dev, "Failed to read device id (%d)", ret);863 goto err;864 }865 nau8325_init_regs(nau8325);866 867 ret = devm_snd_soc_register_component(dev, &nau8325_component_driver,868 &nau8325_dai, 1);869err:870 return ret;871}872 873static const struct i2c_device_id nau8325_i2c_ids[] = {874 { "nau8325" },875 { }876};877MODULE_DEVICE_TABLE(i2c, nau8325_i2c_ids);878 879#ifdef CONFIG_OF880static const struct of_device_id nau8325_of_ids[] = {881 { .compatible = "nuvoton,nau8325", },882 {}883};884MODULE_DEVICE_TABLE(of, nau8325_of_ids);885#endif886 887static struct i2c_driver nau8325_i2c_driver = {888 .driver = {889 .name = "nau8325",890 .of_match_table = of_match_ptr(nau8325_of_ids),891 },892 .probe = nau8325_i2c_probe,893 .id_table = nau8325_i2c_ids,894};895module_i2c_driver(nau8325_i2c_driver);896 897MODULE_DESCRIPTION("ASoC NAU8325 driver");898MODULE_AUTHOR("Seven Lee <WTLI@nuvoton.com>");899MODULE_AUTHOR("David Lin <CTLIN0@nuvoton.com>");900MODULE_LICENSE("GPL");901