brintos

brintos / linux-shallow public Read only

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