brintos

brintos / linux-shallow public Read only

0
0
Text · 25.5 KiB · 2266f32 Raw
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