brintos

brintos / linux-shallow public Read only

0
0
Text · 10.5 KiB · 9490771 Raw
410 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2 /*3 * Audio Codec driver supporting:4 *  AD1835A, AD1836, AD1837A, AD1838A, AD1839A5 *6 * Copyright 2009-2011 Analog Devices Inc.7 */8 9#include <linux/init.h>10#include <linux/slab.h>11#include <linux/module.h>12#include <linux/kernel.h>13#include <linux/device.h>14#include <sound/core.h>15#include <sound/pcm.h>16#include <sound/pcm_params.h>17#include <sound/initval.h>18#include <sound/soc.h>19#include <sound/tlv.h>20#include <linux/spi/spi.h>21#include <linux/regmap.h>22 23#include "ad1836.h"24 25enum ad1836_type {26	AD1835,27	AD1836,28	AD1838,29};30 31/* codec private data */32struct ad1836_priv {33	enum ad1836_type type;34	struct regmap *regmap;35};36 37/*38 * AD1836 volume/mute/de-emphasis etc. controls39 */40static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"};41 42static SOC_ENUM_SINGLE_DECL(ad1836_deemp_enum,43			    AD1836_DAC_CTRL1, 8, ad1836_deemp);44 45#define AD1836_DAC_VOLUME(x) \46	SOC_DOUBLE_R("DAC" #x " Playback Volume", AD1836_DAC_L_VOL(x), \47			AD1836_DAC_R_VOL(x), 0, 0x3FF, 0)48 49#define AD1836_DAC_SWITCH(x) \50	SOC_DOUBLE("DAC" #x " Playback Switch", AD1836_DAC_CTRL2, \51			AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1)52 53#define AD1836_ADC_SWITCH(x) \54	SOC_DOUBLE("ADC" #x " Capture Switch", AD1836_ADC_CTRL2, \55		AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1)56 57static const struct snd_kcontrol_new ad183x_dac_controls[] = {58	AD1836_DAC_VOLUME(1),59	AD1836_DAC_SWITCH(1),60	AD1836_DAC_VOLUME(2),61	AD1836_DAC_SWITCH(2),62	AD1836_DAC_VOLUME(3),63	AD1836_DAC_SWITCH(3),64	AD1836_DAC_VOLUME(4),65	AD1836_DAC_SWITCH(4),66};67 68static const struct snd_soc_dapm_widget ad183x_dac_dapm_widgets[] = {69	SND_SOC_DAPM_OUTPUT("DAC1OUT"),70	SND_SOC_DAPM_OUTPUT("DAC2OUT"),71	SND_SOC_DAPM_OUTPUT("DAC3OUT"),72	SND_SOC_DAPM_OUTPUT("DAC4OUT"),73};74 75static const struct snd_soc_dapm_route ad183x_dac_routes[] = {76	{ "DAC1OUT", NULL, "DAC" },77	{ "DAC2OUT", NULL, "DAC" },78	{ "DAC3OUT", NULL, "DAC" },79	{ "DAC4OUT", NULL, "DAC" },80};81 82static const struct snd_kcontrol_new ad183x_adc_controls[] = {83	AD1836_ADC_SWITCH(1),84	AD1836_ADC_SWITCH(2),85	AD1836_ADC_SWITCH(3),86};87 88static const struct snd_soc_dapm_widget ad183x_adc_dapm_widgets[] = {89	SND_SOC_DAPM_INPUT("ADC1IN"),90	SND_SOC_DAPM_INPUT("ADC2IN"),91};92 93static const struct snd_soc_dapm_route ad183x_adc_routes[] = {94	{ "ADC", NULL, "ADC1IN" },95	{ "ADC", NULL, "ADC2IN" },96};97 98static const struct snd_kcontrol_new ad183x_controls[] = {99	/* ADC high-pass filter */100	SOC_SINGLE("ADC High Pass Filter Switch", AD1836_ADC_CTRL1,101			AD1836_ADC_HIGHPASS_FILTER, 1, 0),102 103	/* DAC de-emphasis */104	SOC_ENUM("Playback Deemphasis", ad1836_deemp_enum),105};106 107static const struct snd_soc_dapm_widget ad183x_dapm_widgets[] = {108	SND_SOC_DAPM_DAC("DAC", "Playback", AD1836_DAC_CTRL1,109				AD1836_DAC_POWERDOWN, 1),110	SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),111	SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1836_ADC_CTRL1,112				AD1836_ADC_POWERDOWN, 1, NULL, 0),113};114 115static const struct snd_soc_dapm_route ad183x_dapm_routes[] = {116	{ "DAC", NULL, "ADC_PWR" },117	{ "ADC", NULL, "ADC_PWR" },118};119 120static const DECLARE_TLV_DB_SCALE(ad1836_in_tlv, 0, 300, 0);121 122static const struct snd_kcontrol_new ad1836_controls[] = {123	SOC_DOUBLE_TLV("ADC2 Capture Volume", AD1836_ADC_CTRL1, 3, 0, 4, 0,124	    ad1836_in_tlv),125};126 127/*128 * DAI ops entries129 */130 131static int ad1836_set_dai_fmt(struct snd_soc_dai *codec_dai,132		unsigned int fmt)133{134	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {135	/* at present, we support adc aux mode to interface with136	 * blackfin sport tdm mode137	 */138	case SND_SOC_DAIFMT_DSP_A:139		break;140	default:141		return -EINVAL;142	}143 144	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {145	case SND_SOC_DAIFMT_IB_IF:146		break;147	default:148		return -EINVAL;149	}150 151	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {152	/* ALCLK,ABCLK are both output, AD1836 can only be provider */153	case SND_SOC_DAIFMT_CBP_CFP:154		break;155	default:156		return -EINVAL;157	}158 159	return 0;160}161 162static int ad1836_hw_params(struct snd_pcm_substream *substream,163		struct snd_pcm_hw_params *params,164		struct snd_soc_dai *dai)165{166	struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(dai->component);167	int word_len = 0;168 169	/* bit size */170	switch (params_width(params)) {171	case 16:172		word_len = AD1836_WORD_LEN_16;173		break;174	case 20:175		word_len = AD1836_WORD_LEN_20;176		break;177	case 24:178	case 32:179		word_len = AD1836_WORD_LEN_24;180		break;181	default:182		return -EINVAL;183	}184 185	regmap_update_bits(ad1836->regmap, AD1836_DAC_CTRL1,186		AD1836_DAC_WORD_LEN_MASK,187		word_len << AD1836_DAC_WORD_LEN_OFFSET);188 189	regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2,190		AD1836_ADC_WORD_LEN_MASK,191		word_len << AD1836_ADC_WORD_OFFSET);192 193	return 0;194}195 196static const struct snd_soc_dai_ops ad1836_dai_ops = {197	.hw_params = ad1836_hw_params,198	.set_fmt = ad1836_set_dai_fmt,199};200 201#define AD183X_DAI(_name, num_dacs, num_adcs) \202{ \203	.name = _name "-hifi", \204	.playback = { \205		.stream_name = "Playback", \206		.channels_min = 2, \207		.channels_max = (num_dacs) * 2, \208		.rates = SNDRV_PCM_RATE_48000,  \209		.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \210			SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \211	}, \212	.capture = { \213		.stream_name = "Capture", \214		.channels_min = 2, \215		.channels_max = (num_adcs) * 2, \216		.rates = SNDRV_PCM_RATE_48000, \217		.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \218			SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \219	}, \220	.ops = &ad1836_dai_ops, \221}222 223static struct snd_soc_dai_driver ad183x_dais[] = {224	[AD1835] = AD183X_DAI("ad1835", 4, 1),225	[AD1836] = AD183X_DAI("ad1836", 3, 2),226	[AD1838] = AD183X_DAI("ad1838", 3, 1),227};228 229#ifdef CONFIG_PM230static int ad1836_suspend(struct snd_soc_component *component)231{232	struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(component);233	/* reset clock control mode */234	return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2,235		AD1836_ADC_SERFMT_MASK, 0);236}237 238static int ad1836_resume(struct snd_soc_component *component)239{240	struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(component);241	/* restore clock control mode */242	return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2,243		AD1836_ADC_SERFMT_MASK, AD1836_ADC_AUX);244}245#else246#define ad1836_suspend NULL247#define ad1836_resume  NULL248#endif249 250static int ad1836_probe(struct snd_soc_component *component)251{252	struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(component);253	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);254	int num_dacs, num_adcs;255	int ret = 0;256	int i;257 258	num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2;259	num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2;260 261	/* default setting for ad1836 */262	/* de-emphasis: 48kHz, power-on dac */263	regmap_write(ad1836->regmap, AD1836_DAC_CTRL1, 0x300);264	/* unmute dac channels */265	regmap_write(ad1836->regmap, AD1836_DAC_CTRL2, 0x0);266	/* high-pass filter enable, power-on adc */267	regmap_write(ad1836->regmap, AD1836_ADC_CTRL1, 0x100);268	/* unmute adc channles, adc aux mode */269	regmap_write(ad1836->regmap, AD1836_ADC_CTRL2, 0x180);270	/* volume */271	for (i = 1; i <= num_dacs; ++i) {272		regmap_write(ad1836->regmap, AD1836_DAC_L_VOL(i), 0x3FF);273		regmap_write(ad1836->regmap, AD1836_DAC_R_VOL(i), 0x3FF);274	}275 276	if (ad1836->type == AD1836) {277		/* left/right diff:PGA/MUX */278		regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x3A);279		ret = snd_soc_add_component_controls(component, ad1836_controls,280				ARRAY_SIZE(ad1836_controls));281		if (ret)282			return ret;283	} else {284		regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x00);285	}286 287	ret = snd_soc_add_component_controls(component, ad183x_dac_controls, num_dacs * 2);288	if (ret)289		return ret;290 291	ret = snd_soc_add_component_controls(component, ad183x_adc_controls, num_adcs);292	if (ret)293		return ret;294 295	ret = snd_soc_dapm_new_controls(dapm, ad183x_dac_dapm_widgets, num_dacs);296	if (ret)297		return ret;298 299	ret = snd_soc_dapm_new_controls(dapm, ad183x_adc_dapm_widgets, num_adcs);300	if (ret)301		return ret;302 303	ret = snd_soc_dapm_add_routes(dapm, ad183x_dac_routes, num_dacs);304	if (ret)305		return ret;306 307	ret = snd_soc_dapm_add_routes(dapm, ad183x_adc_routes, num_adcs);308 309	return ret;310}311 312/* power down chip */313static void ad1836_remove(struct snd_soc_component *component)314{315	struct ad1836_priv *ad1836 = snd_soc_component_get_drvdata(component);316	/* reset clock control mode */317	regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2,318		AD1836_ADC_SERFMT_MASK, 0);319}320 321static const struct snd_soc_component_driver soc_component_dev_ad1836 = {322	.probe			= ad1836_probe,323	.remove			= ad1836_remove,324	.suspend		= ad1836_suspend,325	.resume			= ad1836_resume,326	.controls		= ad183x_controls,327	.num_controls		= ARRAY_SIZE(ad183x_controls),328	.dapm_widgets		= ad183x_dapm_widgets,329	.num_dapm_widgets	= ARRAY_SIZE(ad183x_dapm_widgets),330	.dapm_routes		= ad183x_dapm_routes,331	.num_dapm_routes	= ARRAY_SIZE(ad183x_dapm_routes),332	.idle_bias_on		= 1,333	.use_pmdown_time	= 1,334	.endianness		= 1,335};336 337static const struct reg_default ad1836_reg_defaults[] = {338	{ AD1836_DAC_CTRL1, 0x0000 },339	{ AD1836_DAC_CTRL2, 0x0000 },340	{ AD1836_DAC_L_VOL(0), 0x0000 },341	{ AD1836_DAC_R_VOL(0), 0x0000 },342	{ AD1836_DAC_L_VOL(1), 0x0000 },343	{ AD1836_DAC_R_VOL(1), 0x0000 },344	{ AD1836_DAC_L_VOL(2), 0x0000 },345	{ AD1836_DAC_R_VOL(2), 0x0000 },346	{ AD1836_DAC_L_VOL(3), 0x0000 },347	{ AD1836_DAC_R_VOL(3), 0x0000 },348	{ AD1836_ADC_CTRL1, 0x0000 },349	{ AD1836_ADC_CTRL2, 0x0000 },350	{ AD1836_ADC_CTRL3, 0x0000 },351};352 353static const struct regmap_config ad1836_regmap_config = {354	.val_bits = 12,355	.reg_bits = 4,356	.read_flag_mask = 0x08,357 358	.max_register = AD1836_ADC_CTRL3,359	.reg_defaults = ad1836_reg_defaults,360	.num_reg_defaults = ARRAY_SIZE(ad1836_reg_defaults),361	.cache_type = REGCACHE_MAPLE,362};363 364static int ad1836_spi_probe(struct spi_device *spi)365{366	struct ad1836_priv *ad1836;367	int ret;368 369	ad1836 = devm_kzalloc(&spi->dev, sizeof(struct ad1836_priv),370			      GFP_KERNEL);371	if (ad1836 == NULL)372		return -ENOMEM;373 374	ad1836->regmap = devm_regmap_init_spi(spi, &ad1836_regmap_config);375	if (IS_ERR(ad1836->regmap))376		return PTR_ERR(ad1836->regmap);377 378	ad1836->type = spi_get_device_id(spi)->driver_data;379 380	spi_set_drvdata(spi, ad1836);381 382	ret = devm_snd_soc_register_component(&spi->dev,383			&soc_component_dev_ad1836, &ad183x_dais[ad1836->type], 1);384	return ret;385}386 387static const struct spi_device_id ad1836_ids[] = {388	{ "ad1835", AD1835 },389	{ "ad1836", AD1836 },390	{ "ad1837", AD1835 },391	{ "ad1838", AD1838 },392	{ "ad1839", AD1838 },393	{ },394};395MODULE_DEVICE_TABLE(spi, ad1836_ids);396 397static struct spi_driver ad1836_spi_driver = {398	.driver = {399		.name	= "ad1836",400	},401	.probe		= ad1836_spi_probe,402	.id_table	= ad1836_ids,403};404 405module_spi_driver(ad1836_spi_driver);406 407MODULE_DESCRIPTION("ASoC ad1836 driver");408MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");409MODULE_LICENSE("GPL");410