brintos

brintos / linux-shallow public Read only

0
0
Text · 24.3 KiB · f3c97da Raw
890 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * es8328.c  --  ES8328 ALSA SoC Audio driver4 *5 * Copyright 2014 Sutajio Ko-Usagi PTE LTD6 *7 * Author: Sean Cross <xobs@kosagi.com>8 */9 10#include <linux/clk.h>11#include <linux/delay.h>12#include <linux/module.h>13#include <linux/pm.h>14#include <linux/regmap.h>15#include <linux/slab.h>16#include <linux/regulator/consumer.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 "es8328.h"24 25static const unsigned int rates_12288[] = {26	8000, 12000, 16000, 24000, 32000, 48000, 96000,27};28 29static const int ratios_12288[] = {30	10, 7, 6, 4, 3, 2, 0,31};32 33static const struct snd_pcm_hw_constraint_list constraints_12288 = {34	.count	= ARRAY_SIZE(rates_12288),35	.list	= rates_12288,36};37 38static const unsigned int rates_11289[] = {39	8018, 11025, 22050, 44100, 88200,40};41 42static const int ratios_11289[] = {43	9, 7, 4, 2, 0,44};45 46static const struct snd_pcm_hw_constraint_list constraints_11289 = {47	.count	= ARRAY_SIZE(rates_11289),48	.list	= rates_11289,49};50 51/* regulator supplies for sgtl5000, VDDD is an optional external supply */52enum sgtl5000_regulator_supplies {53	DVDD,54	AVDD,55	PVDD,56	HPVDD,57	ES8328_SUPPLY_NUM58};59 60/* vddd is optional supply */61static const char * const supply_names[ES8328_SUPPLY_NUM] = {62	"DVDD",63	"AVDD",64	"PVDD",65	"HPVDD",66};67 68#define ES8328_RATES (SNDRV_PCM_RATE_192000 | \69		SNDRV_PCM_RATE_96000 | \70		SNDRV_PCM_RATE_88200 | \71		SNDRV_PCM_RATE_8000_48000)72#define ES8328_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \73		SNDRV_PCM_FMTBIT_S18_3LE | \74		SNDRV_PCM_FMTBIT_S20_3LE | \75		SNDRV_PCM_FMTBIT_S24_LE | \76		SNDRV_PCM_FMTBIT_S32_LE)77 78struct es8328_priv {79	struct regmap *regmap;80	struct clk *clk;81	int playback_fs;82	bool deemph;83	int mclkdiv2;84	const struct snd_pcm_hw_constraint_list *sysclk_constraints;85	const int *mclk_ratios;86	bool provider;87	struct regulator_bulk_data supplies[ES8328_SUPPLY_NUM];88};89 90/*91 * ES8328 Controls92 */93 94static const char * const adcpol_txt[] = {"Normal", "L Invert", "R Invert",95					  "L + R Invert"};96static SOC_ENUM_SINGLE_DECL(adcpol,97			    ES8328_ADCCONTROL6, 6, adcpol_txt);98 99static const DECLARE_TLV_DB_SCALE(play_tlv, -3000, 100, 0);100static const DECLARE_TLV_DB_SCALE(dac_adc_tlv, -9600, 50, 0);101static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);102static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 300, 0);103 104static const struct {105	int rate;106	unsigned int val;107} deemph_settings[] = {108	{ 0,     ES8328_DACCONTROL6_DEEMPH_OFF },109	{ 32000, ES8328_DACCONTROL6_DEEMPH_32k },110	{ 44100, ES8328_DACCONTROL6_DEEMPH_44_1k },111	{ 48000, ES8328_DACCONTROL6_DEEMPH_48k },112};113 114static int es8328_set_deemph(struct snd_soc_component *component)115{116	struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);117	int val, i, best;118 119	/*120	 * If we're using deemphasis select the nearest available sample121	 * rate.122	 */123	if (es8328->deemph) {124		best = 0;125		for (i = 1; i < ARRAY_SIZE(deemph_settings); i++) {126			if (abs(deemph_settings[i].rate - es8328->playback_fs) <127			    abs(deemph_settings[best].rate - es8328->playback_fs))128				best = i;129		}130 131		val = deemph_settings[best].val;132	} else {133		val = ES8328_DACCONTROL6_DEEMPH_OFF;134	}135 136	dev_dbg(component->dev, "Set deemphasis %d\n", val);137 138	return snd_soc_component_update_bits(component, ES8328_DACCONTROL6,139			ES8328_DACCONTROL6_DEEMPH_MASK, val);140}141 142static int es8328_get_deemph(struct snd_kcontrol *kcontrol,143			     struct snd_ctl_elem_value *ucontrol)144{145	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);146	struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);147 148	ucontrol->value.integer.value[0] = es8328->deemph;149	return 0;150}151 152static int es8328_put_deemph(struct snd_kcontrol *kcontrol,153			     struct snd_ctl_elem_value *ucontrol)154{155	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);156	struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);157	unsigned int deemph = ucontrol->value.integer.value[0];158	int ret;159 160	if (deemph > 1)161		return -EINVAL;162 163	if (es8328->deemph == deemph)164		return 0;165 166	ret = es8328_set_deemph(component);167	if (ret < 0)168		return ret;169 170	es8328->deemph = deemph;171 172	return 1;173}174 175 176 177static const struct snd_kcontrol_new es8328_snd_controls[] = {178	SOC_DOUBLE_R_TLV("Capture Digital Volume",179		ES8328_ADCCONTROL8, ES8328_ADCCONTROL9,180		 0, 0xc0, 1, dac_adc_tlv),181	SOC_SINGLE("Capture ZC Switch", ES8328_ADCCONTROL7, 6, 1, 0),182 183	SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0,184		    es8328_get_deemph, es8328_put_deemph),185 186	SOC_ENUM("Capture Polarity", adcpol),187 188	SOC_SINGLE_TLV("Left Mixer Left Bypass Volume",189			ES8328_DACCONTROL17, 3, 7, 1, bypass_tlv),190	SOC_SINGLE_TLV("Left Mixer Right Bypass Volume",191			ES8328_DACCONTROL19, 3, 7, 1, bypass_tlv),192	SOC_SINGLE_TLV("Right Mixer Left Bypass Volume",193			ES8328_DACCONTROL18, 3, 7, 1, bypass_tlv),194	SOC_SINGLE_TLV("Right Mixer Right Bypass Volume",195			ES8328_DACCONTROL20, 3, 7, 1, bypass_tlv),196 197	SOC_DOUBLE_R_TLV("PCM Volume",198			ES8328_LDACVOL, ES8328_RDACVOL,199			0, ES8328_DACVOL_MAX, 1, dac_adc_tlv),200 201	SOC_DOUBLE_R_TLV("Output 1 Playback Volume",202			ES8328_LOUT1VOL, ES8328_ROUT1VOL,203			0, ES8328_OUT1VOL_MAX, 0, play_tlv),204 205	SOC_DOUBLE_R_TLV("Output 2 Playback Volume",206			ES8328_LOUT2VOL, ES8328_ROUT2VOL,207			0, ES8328_OUT2VOL_MAX, 0, play_tlv),208 209	SOC_DOUBLE_TLV("Mic PGA Volume", ES8328_ADCCONTROL1,210			4, 0, 8, 0, mic_tlv),211};212 213/*214 * DAPM Controls215 */216 217static const char * const es8328_line_texts[] = {218	"Line 1", "Line 2", "PGA", "Differential"};219 220static const struct soc_enum es8328_lline_enum =221	SOC_ENUM_SINGLE(ES8328_DACCONTROL16, 3,222			      ARRAY_SIZE(es8328_line_texts),223			      es8328_line_texts);224static const struct snd_kcontrol_new es8328_left_line_controls =225	SOC_DAPM_ENUM("Route", es8328_lline_enum);226 227static const struct soc_enum es8328_rline_enum =228	SOC_ENUM_SINGLE(ES8328_DACCONTROL16, 0,229			      ARRAY_SIZE(es8328_line_texts),230			      es8328_line_texts);231static const struct snd_kcontrol_new es8328_right_line_controls =232	SOC_DAPM_ENUM("Route", es8328_rline_enum);233 234/* Left Mixer */235static const struct snd_kcontrol_new es8328_left_mixer_controls[] = {236	SOC_DAPM_SINGLE("Playback Switch", ES8328_DACCONTROL17, 7, 1, 0),237	SOC_DAPM_SINGLE("Left Bypass Switch", ES8328_DACCONTROL17, 6, 1, 0),238	SOC_DAPM_SINGLE("Right Playback Switch", ES8328_DACCONTROL18, 7, 1, 0),239	SOC_DAPM_SINGLE("Right Bypass Switch", ES8328_DACCONTROL18, 6, 1, 0),240};241 242/* Right Mixer */243static const struct snd_kcontrol_new es8328_right_mixer_controls[] = {244	SOC_DAPM_SINGLE("Left Playback Switch", ES8328_DACCONTROL19, 7, 1, 0),245	SOC_DAPM_SINGLE("Left Bypass Switch", ES8328_DACCONTROL19, 6, 1, 0),246	SOC_DAPM_SINGLE("Playback Switch", ES8328_DACCONTROL20, 7, 1, 0),247	SOC_DAPM_SINGLE("Right Bypass Switch", ES8328_DACCONTROL20, 6, 1, 0),248};249 250static const char * const es8328_pga_sel[] = {251	"Line 1", "Line 2", "Line 3", "Differential"};252 253/* Left PGA Mux */254static const struct soc_enum es8328_lpga_enum =255	SOC_ENUM_SINGLE(ES8328_ADCCONTROL2, 6,256			      ARRAY_SIZE(es8328_pga_sel),257			      es8328_pga_sel);258static const struct snd_kcontrol_new es8328_left_pga_controls =259	SOC_DAPM_ENUM("Route", es8328_lpga_enum);260 261/* Right PGA Mux */262static const struct soc_enum es8328_rpga_enum =263	SOC_ENUM_SINGLE(ES8328_ADCCONTROL2, 4,264			      ARRAY_SIZE(es8328_pga_sel),265			      es8328_pga_sel);266static const struct snd_kcontrol_new es8328_right_pga_controls =267	SOC_DAPM_ENUM("Route", es8328_rpga_enum);268 269/* Differential Mux */270static const char * const es8328_diff_sel[] = {"Line 1", "Line 2"};271static SOC_ENUM_SINGLE_DECL(diffmux,272			    ES8328_ADCCONTROL3, 7, es8328_diff_sel);273static const struct snd_kcontrol_new es8328_diffmux_controls =274	SOC_DAPM_ENUM("Route", diffmux);275 276/* Mono ADC Mux */277static const char * const es8328_mono_mux[] = {"Stereo", "Mono (Left)",278	"Mono (Right)", "Digital Mono"};279static SOC_ENUM_SINGLE_DECL(monomux,280			    ES8328_ADCCONTROL3, 3, es8328_mono_mux);281static const struct snd_kcontrol_new es8328_monomux_controls =282	SOC_DAPM_ENUM("Route", monomux);283 284static const struct snd_soc_dapm_widget es8328_dapm_widgets[] = {285	SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,286		&es8328_diffmux_controls),287	SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0,288		&es8328_monomux_controls),289	SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0,290		&es8328_monomux_controls),291 292	SND_SOC_DAPM_MUX("Left PGA Mux", ES8328_ADCPOWER,293			ES8328_ADCPOWER_AINL_OFF, 1,294			&es8328_left_pga_controls),295	SND_SOC_DAPM_MUX("Right PGA Mux", ES8328_ADCPOWER,296			ES8328_ADCPOWER_AINR_OFF, 1,297			&es8328_right_pga_controls),298 299	SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0,300		&es8328_left_line_controls),301	SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0,302		&es8328_right_line_controls),303 304	SND_SOC_DAPM_ADC("Right ADC", "Right Capture", ES8328_ADCPOWER,305			ES8328_ADCPOWER_ADCR_OFF, 1),306	SND_SOC_DAPM_ADC("Left ADC", "Left Capture", ES8328_ADCPOWER,307			ES8328_ADCPOWER_ADCL_OFF, 1),308 309	SND_SOC_DAPM_SUPPLY("Mic Bias", ES8328_ADCPOWER,310			ES8328_ADCPOWER_MIC_BIAS_OFF, 1, NULL, 0),311	SND_SOC_DAPM_SUPPLY("Mic Bias Gen", ES8328_ADCPOWER,312			ES8328_ADCPOWER_ADC_BIAS_GEN_OFF, 1, NULL, 0),313 314	SND_SOC_DAPM_SUPPLY("DAC STM", ES8328_CHIPPOWER,315			ES8328_CHIPPOWER_DACSTM_RESET, 1, NULL, 0),316	SND_SOC_DAPM_SUPPLY("ADC STM", ES8328_CHIPPOWER,317			ES8328_CHIPPOWER_ADCSTM_RESET, 1, NULL, 0),318 319	SND_SOC_DAPM_SUPPLY("DAC DIG", ES8328_CHIPPOWER,320			ES8328_CHIPPOWER_DACDIG_OFF, 1, NULL, 0),321	SND_SOC_DAPM_SUPPLY("ADC DIG", ES8328_CHIPPOWER,322			ES8328_CHIPPOWER_ADCDIG_OFF, 1, NULL, 0),323 324	SND_SOC_DAPM_SUPPLY("DAC DLL", ES8328_CHIPPOWER,325			ES8328_CHIPPOWER_DACDLL_OFF, 1, NULL, 0),326	SND_SOC_DAPM_SUPPLY("ADC DLL", ES8328_CHIPPOWER,327			ES8328_CHIPPOWER_ADCDLL_OFF, 1, NULL, 0),328 329	SND_SOC_DAPM_SUPPLY("ADC Vref", ES8328_CHIPPOWER,330			ES8328_CHIPPOWER_ADCVREF_OFF, 1, NULL, 0),331	SND_SOC_DAPM_SUPPLY("DAC Vref", ES8328_CHIPPOWER,332			ES8328_CHIPPOWER_DACVREF_OFF, 1, NULL, 0),333 334	SND_SOC_DAPM_DAC("Right DAC", "Right Playback", ES8328_DACPOWER,335			ES8328_DACPOWER_RDAC_OFF, 1),336	SND_SOC_DAPM_DAC("Left DAC", "Left Playback", ES8328_DACPOWER,337			ES8328_DACPOWER_LDAC_OFF, 1),338 339	SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,340		&es8328_left_mixer_controls[0],341		ARRAY_SIZE(es8328_left_mixer_controls)),342	SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0,343		&es8328_right_mixer_controls[0],344		ARRAY_SIZE(es8328_right_mixer_controls)),345 346	SND_SOC_DAPM_PGA("Right Out 2", ES8328_DACPOWER,347			ES8328_DACPOWER_ROUT2_ON, 0, NULL, 0),348	SND_SOC_DAPM_PGA("Left Out 2", ES8328_DACPOWER,349			ES8328_DACPOWER_LOUT2_ON, 0, NULL, 0),350	SND_SOC_DAPM_PGA("Right Out 1", ES8328_DACPOWER,351			ES8328_DACPOWER_ROUT1_ON, 0, NULL, 0),352	SND_SOC_DAPM_PGA("Left Out 1", ES8328_DACPOWER,353			ES8328_DACPOWER_LOUT1_ON, 0, NULL, 0),354 355	SND_SOC_DAPM_OUTPUT("LOUT1"),356	SND_SOC_DAPM_OUTPUT("ROUT1"),357	SND_SOC_DAPM_OUTPUT("LOUT2"),358	SND_SOC_DAPM_OUTPUT("ROUT2"),359 360	SND_SOC_DAPM_INPUT("LINPUT1"),361	SND_SOC_DAPM_INPUT("LINPUT2"),362	SND_SOC_DAPM_INPUT("RINPUT1"),363	SND_SOC_DAPM_INPUT("RINPUT2"),364};365 366static const struct snd_soc_dapm_route es8328_dapm_routes[] = {367 368	{ "Left Line Mux", "Line 1", "LINPUT1" },369	{ "Left Line Mux", "Line 2", "LINPUT2" },370	{ "Left Line Mux", "PGA", "Left PGA Mux" },371	{ "Left Line Mux", "Differential", "Differential Mux" },372 373	{ "Right Line Mux", "Line 1", "RINPUT1" },374	{ "Right Line Mux", "Line 2", "RINPUT2" },375	{ "Right Line Mux", "PGA", "Right PGA Mux" },376	{ "Right Line Mux", "Differential", "Differential Mux" },377 378	{ "Left PGA Mux", "Line 1", "LINPUT1" },379	{ "Left PGA Mux", "Line 2", "LINPUT2" },380	{ "Left PGA Mux", "Differential", "Differential Mux" },381 382	{ "Right PGA Mux", "Line 1", "RINPUT1" },383	{ "Right PGA Mux", "Line 2", "RINPUT2" },384	{ "Right PGA Mux", "Differential", "Differential Mux" },385 386	{ "Differential Mux", "Line 1", "LINPUT1" },387	{ "Differential Mux", "Line 1", "RINPUT1" },388	{ "Differential Mux", "Line 2", "LINPUT2" },389	{ "Differential Mux", "Line 2", "RINPUT2" },390 391	{ "Left ADC Mux", "Stereo", "Left PGA Mux" },392	{ "Left ADC Mux", "Mono (Left)", "Left PGA Mux" },393	{ "Left ADC Mux", "Digital Mono", "Left PGA Mux" },394 395	{ "Right ADC Mux", "Stereo", "Right PGA Mux" },396	{ "Right ADC Mux", "Mono (Right)", "Right PGA Mux" },397	{ "Right ADC Mux", "Digital Mono", "Right PGA Mux" },398 399	{ "Left ADC", NULL, "Left ADC Mux" },400	{ "Right ADC", NULL, "Right ADC Mux" },401 402	{ "ADC DIG", NULL, "ADC STM" },403	{ "ADC DIG", NULL, "ADC Vref" },404	{ "ADC DIG", NULL, "ADC DLL" },405 406	{ "Left ADC", NULL, "ADC DIG" },407	{ "Right ADC", NULL, "ADC DIG" },408 409	{ "Mic Bias", NULL, "Mic Bias Gen" },410 411	{ "Left Line Mux", "Line 1", "LINPUT1" },412	{ "Left Line Mux", "Line 2", "LINPUT2" },413	{ "Left Line Mux", "PGA", "Left PGA Mux" },414	{ "Left Line Mux", "Differential", "Differential Mux" },415 416	{ "Right Line Mux", "Line 1", "RINPUT1" },417	{ "Right Line Mux", "Line 2", "RINPUT2" },418	{ "Right Line Mux", "PGA", "Right PGA Mux" },419	{ "Right Line Mux", "Differential", "Differential Mux" },420 421	{ "Left Out 1", NULL, "Left DAC" },422	{ "Right Out 1", NULL, "Right DAC" },423	{ "Left Out 2", NULL, "Left DAC" },424	{ "Right Out 2", NULL, "Right DAC" },425 426	{ "Left Mixer", "Playback Switch", "Left DAC" },427	{ "Left Mixer", "Left Bypass Switch", "Left Line Mux" },428	{ "Left Mixer", "Right Playback Switch", "Right DAC" },429	{ "Left Mixer", "Right Bypass Switch", "Right Line Mux" },430 431	{ "Right Mixer", "Left Playback Switch", "Left DAC" },432	{ "Right Mixer", "Left Bypass Switch", "Left Line Mux" },433	{ "Right Mixer", "Playback Switch", "Right DAC" },434	{ "Right Mixer", "Right Bypass Switch", "Right Line Mux" },435 436	{ "DAC DIG", NULL, "DAC STM" },437	{ "DAC DIG", NULL, "DAC Vref" },438	{ "DAC DIG", NULL, "DAC DLL" },439 440	{ "Left DAC", NULL, "DAC DIG" },441	{ "Right DAC", NULL, "DAC DIG" },442 443	{ "Left Out 1", NULL, "Left Mixer" },444	{ "LOUT1", NULL, "Left Out 1" },445	{ "Right Out 1", NULL, "Right Mixer" },446	{ "ROUT1", NULL, "Right Out 1" },447 448	{ "Left Out 2", NULL, "Left Mixer" },449	{ "LOUT2", NULL, "Left Out 2" },450	{ "Right Out 2", NULL, "Right Mixer" },451	{ "ROUT2", NULL, "Right Out 2" },452};453 454static int es8328_mute(struct snd_soc_dai *dai, int mute, int direction)455{456	return snd_soc_component_update_bits(dai->component, ES8328_DACCONTROL3,457			ES8328_DACCONTROL3_DACMUTE,458			mute ? ES8328_DACCONTROL3_DACMUTE : 0);459}460 461static int es8328_startup(struct snd_pcm_substream *substream,462			  struct snd_soc_dai *dai)463{464	struct snd_soc_component *component = dai->component;465	struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);466 467	if (es8328->provider && es8328->sysclk_constraints)468		snd_pcm_hw_constraint_list(substream->runtime, 0,469				SNDRV_PCM_HW_PARAM_RATE,470				es8328->sysclk_constraints);471 472	return 0;473}474 475static int es8328_hw_params(struct snd_pcm_substream *substream,476	struct snd_pcm_hw_params *params,477	struct snd_soc_dai *dai)478{479	struct snd_soc_component *component = dai->component;480	struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);481	int i;482	int reg;483	int wl;484	int ratio;485 486	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)487		reg = ES8328_DACCONTROL2;488	else489		reg = ES8328_ADCCONTROL5;490 491	if (es8328->provider) {492		if (!es8328->sysclk_constraints) {493			dev_err(component->dev, "No MCLK configured\n");494			return -EINVAL;495		}496 497		for (i = 0; i < es8328->sysclk_constraints->count; i++)498			if (es8328->sysclk_constraints->list[i] ==499			    params_rate(params))500				break;501 502		if (i == es8328->sysclk_constraints->count) {503			dev_err(component->dev,504				"LRCLK %d unsupported with current clock\n",505				params_rate(params));506			return -EINVAL;507		}508		ratio = es8328->mclk_ratios[i];509	} else {510		ratio = 0;511		es8328->mclkdiv2 = 0;512	}513 514	snd_soc_component_update_bits(component, ES8328_MASTERMODE,515			ES8328_MASTERMODE_MCLKDIV2,516			es8328->mclkdiv2 ? ES8328_MASTERMODE_MCLKDIV2 : 0);517 518	switch (params_width(params)) {519	case 16:520		wl = 3;521		break;522	case 18:523		wl = 2;524		break;525	case 20:526		wl = 1;527		break;528	case 24:529		wl = 0;530		break;531	case 32:532		wl = 4;533		break;534	default:535		return -EINVAL;536	}537 538	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {539		snd_soc_component_update_bits(component, ES8328_DACCONTROL1,540				ES8328_DACCONTROL1_DACWL_MASK,541				wl << ES8328_DACCONTROL1_DACWL_SHIFT);542 543		es8328->playback_fs = params_rate(params);544		es8328_set_deemph(component);545	} else546		snd_soc_component_update_bits(component, ES8328_ADCCONTROL4,547				ES8328_ADCCONTROL4_ADCWL_MASK,548				wl << ES8328_ADCCONTROL4_ADCWL_SHIFT);549 550	return snd_soc_component_update_bits(component, reg, ES8328_RATEMASK, ratio);551}552 553static int es8328_set_sysclk(struct snd_soc_dai *codec_dai,554		int clk_id, unsigned int freq, int dir)555{556	struct snd_soc_component *component = codec_dai->component;557	struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);558	int mclkdiv2 = 0;559	unsigned int round_freq;560 561	/*562	 * Allow a small tolerance for frequencies within 100hz. Note563	 * this value is chosen arbitrarily.564	 */565	round_freq = DIV_ROUND_CLOSEST(freq, 100) * 100;566 567	switch (round_freq) {568	case 0:569		es8328->sysclk_constraints = NULL;570		es8328->mclk_ratios = NULL;571		break;572	case 22579200:573		mclkdiv2 = 1;574		fallthrough;575	case 11289600:576		es8328->sysclk_constraints = &constraints_11289;577		es8328->mclk_ratios = ratios_11289;578		break;579	case 24576000:580		mclkdiv2 = 1;581		fallthrough;582	case 12288000:583		es8328->sysclk_constraints = &constraints_12288;584		es8328->mclk_ratios = ratios_12288;585		break;586	default:587		return -EINVAL;588	}589 590	es8328->mclkdiv2 = mclkdiv2;591	return 0;592}593 594static int es8328_set_dai_fmt(struct snd_soc_dai *codec_dai,595		unsigned int fmt)596{597	struct snd_soc_component *component = codec_dai->component;598	struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);599	u8 dac_mode = 0;600	u8 adc_mode = 0;601 602	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {603	case SND_SOC_DAIFMT_CBP_CFP:604		/* Master serial port mode, with BCLK generated automatically */605		snd_soc_component_update_bits(component, ES8328_MASTERMODE,606				    ES8328_MASTERMODE_MSC,607				    ES8328_MASTERMODE_MSC);608		es8328->provider = true;609		break;610	case SND_SOC_DAIFMT_CBC_CFC:611		/* Slave serial port mode */612		snd_soc_component_update_bits(component, ES8328_MASTERMODE,613				    ES8328_MASTERMODE_MSC, 0);614		es8328->provider = false;615		break;616	default:617		return -EINVAL;618	}619 620	/* interface format */621	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {622	case SND_SOC_DAIFMT_I2S:623		dac_mode |= ES8328_DACCONTROL1_DACFORMAT_I2S;624		adc_mode |= ES8328_ADCCONTROL4_ADCFORMAT_I2S;625		break;626	case SND_SOC_DAIFMT_RIGHT_J:627		dac_mode |= ES8328_DACCONTROL1_DACFORMAT_RJUST;628		adc_mode |= ES8328_ADCCONTROL4_ADCFORMAT_RJUST;629		break;630	case SND_SOC_DAIFMT_LEFT_J:631		dac_mode |= ES8328_DACCONTROL1_DACFORMAT_LJUST;632		adc_mode |= ES8328_ADCCONTROL4_ADCFORMAT_LJUST;633		break;634	default:635		return -EINVAL;636	}637 638	/* clock inversion */639	if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF)640		return -EINVAL;641 642	snd_soc_component_update_bits(component, ES8328_DACCONTROL1,643			ES8328_DACCONTROL1_DACFORMAT_MASK, dac_mode);644	snd_soc_component_update_bits(component, ES8328_ADCCONTROL4,645			ES8328_ADCCONTROL4_ADCFORMAT_MASK, adc_mode);646 647	return 0;648}649 650static int es8328_set_bias_level(struct snd_soc_component *component,651				 enum snd_soc_bias_level level)652{653	switch (level) {654	case SND_SOC_BIAS_ON:655		break;656 657	case SND_SOC_BIAS_PREPARE:658		/* VREF, VMID=2x50k, digital enabled */659		snd_soc_component_write(component, ES8328_CHIPPOWER, 0);660		snd_soc_component_update_bits(component, ES8328_CONTROL1,661				ES8328_CONTROL1_VMIDSEL_MASK |662				ES8328_CONTROL1_ENREF,663				ES8328_CONTROL1_VMIDSEL_50k |664				ES8328_CONTROL1_ENREF);665		break;666 667	case SND_SOC_BIAS_STANDBY:668		if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {669			snd_soc_component_update_bits(component, ES8328_CONTROL1,670					ES8328_CONTROL1_VMIDSEL_MASK |671					ES8328_CONTROL1_ENREF,672					ES8328_CONTROL1_VMIDSEL_5k |673					ES8328_CONTROL1_ENREF);674 675			/* Charge caps */676			msleep(100);677		}678 679		snd_soc_component_write(component, ES8328_CONTROL2,680				ES8328_CONTROL2_OVERCURRENT_ON |681				ES8328_CONTROL2_THERMAL_SHUTDOWN_ON);682 683		/* VREF, VMID=2*500k, digital stopped */684		snd_soc_component_update_bits(component, ES8328_CONTROL1,685				ES8328_CONTROL1_VMIDSEL_MASK |686				ES8328_CONTROL1_ENREF,687				ES8328_CONTROL1_VMIDSEL_500k |688				ES8328_CONTROL1_ENREF);689		break;690 691	case SND_SOC_BIAS_OFF:692		snd_soc_component_update_bits(component, ES8328_CONTROL1,693				ES8328_CONTROL1_VMIDSEL_MASK |694				ES8328_CONTROL1_ENREF,695				0);696		break;697	}698	return 0;699}700 701static const struct snd_soc_dai_ops es8328_dai_ops = {702	.startup	= es8328_startup,703	.hw_params	= es8328_hw_params,704	.mute_stream	= es8328_mute,705	.set_sysclk	= es8328_set_sysclk,706	.set_fmt	= es8328_set_dai_fmt,707	.no_capture_mute = 1,708};709 710static struct snd_soc_dai_driver es8328_dai = {711	.name = "es8328-hifi-analog",712	.playback = {713		.stream_name = "Playback",714		.channels_min = 2,715		.channels_max = 2,716		.rates = ES8328_RATES,717		.formats = ES8328_FORMATS,718	},719	.capture = {720		.stream_name = "Capture",721		.channels_min = 2,722		.channels_max = 2,723		.rates = ES8328_RATES,724		.formats = ES8328_FORMATS,725	},726	.ops = &es8328_dai_ops,727	.symmetric_rate = 1,728};729 730static int es8328_suspend(struct snd_soc_component *component)731{732	struct es8328_priv *es8328;733	int ret;734 735	es8328 = snd_soc_component_get_drvdata(component);736 737	clk_disable_unprepare(es8328->clk);738 739	ret = regulator_bulk_disable(ARRAY_SIZE(es8328->supplies),740			es8328->supplies);741	if (ret) {742		dev_err(component->dev, "unable to disable regulators\n");743		return ret;744	}745	return 0;746}747 748static int es8328_resume(struct snd_soc_component *component)749{750	struct regmap *regmap = dev_get_regmap(component->dev, NULL);751	struct es8328_priv *es8328;752	int ret;753 754	es8328 = snd_soc_component_get_drvdata(component);755 756	ret = clk_prepare_enable(es8328->clk);757	if (ret) {758		dev_err(component->dev, "unable to enable clock\n");759		return ret;760	}761 762	ret = regulator_bulk_enable(ARRAY_SIZE(es8328->supplies),763					es8328->supplies);764	if (ret) {765		dev_err(component->dev, "unable to enable regulators\n");766		return ret;767	}768 769	regcache_mark_dirty(regmap);770	ret = regcache_sync(regmap);771	if (ret) {772		dev_err(component->dev, "unable to sync regcache\n");773		return ret;774	}775 776	return 0;777}778 779static int es8328_component_probe(struct snd_soc_component *component)780{781	struct es8328_priv *es8328;782	int ret;783 784	es8328 = snd_soc_component_get_drvdata(component);785 786	ret = regulator_bulk_enable(ARRAY_SIZE(es8328->supplies),787					es8328->supplies);788	if (ret) {789		dev_err(component->dev, "unable to enable regulators\n");790		return ret;791	}792 793	/* Setup clocks */794	es8328->clk = devm_clk_get(component->dev, NULL);795	if (IS_ERR(es8328->clk)) {796		dev_err(component->dev, "codec clock missing or invalid\n");797		ret = PTR_ERR(es8328->clk);798		goto clk_fail;799	}800 801	ret = clk_prepare_enable(es8328->clk);802	if (ret) {803		dev_err(component->dev, "unable to prepare codec clk\n");804		goto clk_fail;805	}806 807	return 0;808 809clk_fail:810	regulator_bulk_disable(ARRAY_SIZE(es8328->supplies),811			       es8328->supplies);812	return ret;813}814 815static void es8328_remove(struct snd_soc_component *component)816{817	struct es8328_priv *es8328;818 819	es8328 = snd_soc_component_get_drvdata(component);820 821	clk_disable_unprepare(es8328->clk);822 823	regulator_bulk_disable(ARRAY_SIZE(es8328->supplies),824			       es8328->supplies);825}826 827const struct regmap_config es8328_regmap_config = {828	.reg_bits	= 8,829	.val_bits	= 8,830	.max_register	= ES8328_REG_MAX,831	.cache_type	= REGCACHE_MAPLE,832	.use_single_read = true,833	.use_single_write = true,834};835EXPORT_SYMBOL_GPL(es8328_regmap_config);836 837static const struct snd_soc_component_driver es8328_component_driver = {838	.probe			= es8328_component_probe,839	.remove			= es8328_remove,840	.suspend		= es8328_suspend,841	.resume			= es8328_resume,842	.set_bias_level		= es8328_set_bias_level,843	.controls		= es8328_snd_controls,844	.num_controls		= ARRAY_SIZE(es8328_snd_controls),845	.dapm_widgets		= es8328_dapm_widgets,846	.num_dapm_widgets	= ARRAY_SIZE(es8328_dapm_widgets),847	.dapm_routes		= es8328_dapm_routes,848	.num_dapm_routes	= ARRAY_SIZE(es8328_dapm_routes),849	.suspend_bias_off	= 1,850	.idle_bias_on		= 1,851	.use_pmdown_time	= 1,852	.endianness		= 1,853};854 855int es8328_probe(struct device *dev, struct regmap *regmap)856{857	struct es8328_priv *es8328;858	int ret;859	int i;860 861	if (IS_ERR(regmap))862		return PTR_ERR(regmap);863 864	es8328 = devm_kzalloc(dev, sizeof(*es8328), GFP_KERNEL);865	if (es8328 == NULL)866		return -ENOMEM;867 868	es8328->regmap = regmap;869 870	for (i = 0; i < ARRAY_SIZE(es8328->supplies); i++)871		es8328->supplies[i].supply = supply_names[i];872 873	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(es8328->supplies),874				es8328->supplies);875	if (ret) {876		dev_err(dev, "unable to get regulators\n");877		return ret;878	}879 880	dev_set_drvdata(dev, es8328);881 882	return devm_snd_soc_register_component(dev,883			&es8328_component_driver, &es8328_dai, 1);884}885EXPORT_SYMBOL_GPL(es8328_probe);886 887MODULE_DESCRIPTION("ASoC ES8328 driver");888MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>");889MODULE_LICENSE("GPL");890