brintos

brintos / linux-shallow public Read only

0
0
Text · 16.3 KiB · a196341 Raw
653 lines · c
1// SPDX-License-Identifier: GPL-2.02// Driver for the Texas Instruments TAS2780 Mono3//		Audio amplifier4// Copyright (C) 2022 Texas Instruments Inc.5 6#include <linux/module.h>7#include <linux/err.h>8#include <linux/pm.h>9#include <linux/i2c.h>10#include <linux/gpio/consumer.h>11#include <linux/regmap.h>12#include <linux/of.h>13#include <sound/soc.h>14#include <sound/pcm.h>15#include <sound/pcm_params.h>16#include <sound/tlv.h>17 18#include "tas2780.h"19 20struct tas2780_priv {21	struct snd_soc_component *component;22	struct gpio_desc *reset_gpio;23	struct regmap *regmap;24	struct device *dev;25	int v_sense_slot;26	int i_sense_slot;27};28 29static void tas2780_reset(struct tas2780_priv *tas2780)30{31	int ret = 0;32 33	if (tas2780->reset_gpio) {34		gpiod_set_value_cansleep(tas2780->reset_gpio, 0);35		usleep_range(2000, 2050);36		gpiod_set_value_cansleep(tas2780->reset_gpio, 1);37		usleep_range(2000, 2050);38	}39 40	ret = snd_soc_component_write(tas2780->component, TAS2780_SW_RST,41				TAS2780_RST);42	if (ret)43		dev_err(tas2780->dev, "%s:errCode:0x%x Reset error!\n",44			__func__, ret);45}46 47#ifdef CONFIG_PM48static int tas2780_codec_suspend(struct snd_soc_component *component)49{50	struct tas2780_priv *tas2780 =51		snd_soc_component_get_drvdata(component);52	int ret = 0;53 54	ret = snd_soc_component_update_bits(component, TAS2780_PWR_CTRL,55		TAS2780_PWR_CTRL_MASK, TAS2780_PWR_CTRL_SHUTDOWN);56	if (ret < 0) {57		dev_err(tas2780->dev, "%s:errCode:0x%0x:power down error\n",58			__func__, ret);59		goto err;60	}61	ret = 0;62	regcache_cache_only(tas2780->regmap, true);63	regcache_mark_dirty(tas2780->regmap);64err:65	return ret;66}67 68static int tas2780_codec_resume(struct snd_soc_component *component)69{70	struct tas2780_priv *tas2780 =71		snd_soc_component_get_drvdata(component);72	int ret;73 74	ret = snd_soc_component_update_bits(component, TAS2780_PWR_CTRL,75		TAS2780_PWR_CTRL_MASK, TAS2780_PWR_CTRL_ACTIVE);76 77	if (ret < 0) {78		dev_err(tas2780->dev, "%s:errCode:0x%0x:power down error\n",79			__func__, ret);80		goto err;81	}82	regcache_cache_only(tas2780->regmap, false);83	ret = regcache_sync(tas2780->regmap);84err:85	return ret;86}87#endif88 89static const char * const tas2780_ASI1_src[] = {90	"I2C offset", "Left", "Right", "LeftRightDiv2",91};92 93static SOC_ENUM_SINGLE_DECL(94	tas2780_ASI1_src_enum, TAS2780_TDM_CFG2, 4, tas2780_ASI1_src);95 96static const struct snd_kcontrol_new tas2780_asi1_mux =97	SOC_DAPM_ENUM("ASI1 Source", tas2780_ASI1_src_enum);98 99static const struct snd_kcontrol_new isense_switch =100	SOC_DAPM_SINGLE("Switch", TAS2780_PWR_CTRL,101			TAS2780_ISENSE_POWER_EN, 1, 1);102static const struct snd_kcontrol_new vsense_switch =103	SOC_DAPM_SINGLE("Switch", TAS2780_PWR_CTRL,104			TAS2780_VSENSE_POWER_EN, 1, 1);105 106static const struct snd_soc_dapm_widget tas2780_dapm_widgets[] = {107	SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),108	SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2780_asi1_mux),109	SND_SOC_DAPM_SWITCH("ISENSE", TAS2780_PWR_CTRL,110		TAS2780_ISENSE_POWER_EN, 1, &isense_switch),111	SND_SOC_DAPM_SWITCH("VSENSE", TAS2780_PWR_CTRL,112		TAS2780_VSENSE_POWER_EN, 1, &vsense_switch),113	SND_SOC_DAPM_OUTPUT("OUT"),114	SND_SOC_DAPM_SIGGEN("VMON"),115	SND_SOC_DAPM_SIGGEN("IMON")116};117 118static const struct snd_soc_dapm_route tas2780_audio_map[] = {119	{"ASI1 Sel", "I2C offset", "ASI1"},120	{"ASI1 Sel", "Left", "ASI1"},121	{"ASI1 Sel", "Right", "ASI1"},122	{"ASI1 Sel", "LeftRightDiv2", "ASI1"},123	{"OUT", NULL, "ASI1 Sel"},124	{"ISENSE", "Switch", "IMON"},125	{"VSENSE", "Switch", "VMON"},126};127 128static int tas2780_mute(struct snd_soc_dai *dai, int mute, int direction)129{130	struct snd_soc_component *component = dai->component;131	struct tas2780_priv *tas2780 =132		snd_soc_component_get_drvdata(component);133	int ret = 0;134 135	ret = snd_soc_component_update_bits(component, TAS2780_PWR_CTRL,136		TAS2780_PWR_CTRL_MASK,137		mute ? TAS2780_PWR_CTRL_MUTE : 0);138	if (ret < 0) {139		dev_err(tas2780->dev, "%s: Failed to set powercontrol\n",140			__func__);141		goto err;142	}143	ret = 0;144err:145	return ret;146}147 148static int tas2780_set_bitwidth(struct tas2780_priv *tas2780, int bitwidth)149{150	struct snd_soc_component *component = tas2780->component;151	int sense_en;152	int val;153	int ret;154	int slot_size;155 156	switch (bitwidth) {157	case SNDRV_PCM_FORMAT_S16_LE:158		ret = snd_soc_component_update_bits(component,159			TAS2780_TDM_CFG2,160			TAS2780_TDM_CFG2_RXW_MASK,161			TAS2780_TDM_CFG2_RXW_16BITS);162		slot_size = TAS2780_TDM_CFG2_RXS_16BITS;163		break;164	case SNDRV_PCM_FORMAT_S24_LE:165		ret = snd_soc_component_update_bits(component,166			TAS2780_TDM_CFG2,167			TAS2780_TDM_CFG2_RXW_MASK,168			TAS2780_TDM_CFG2_RXW_24BITS);169		slot_size = TAS2780_TDM_CFG2_RXS_24BITS;170		break;171	case SNDRV_PCM_FORMAT_S32_LE:172		ret = snd_soc_component_update_bits(component,173			TAS2780_TDM_CFG2,174			TAS2780_TDM_CFG2_RXW_MASK,175			TAS2780_TDM_CFG2_RXW_32BITS);176		slot_size = TAS2780_TDM_CFG2_RXS_32BITS;177		break;178 179	default:180		ret = -EINVAL;181	}182 183	if (ret < 0) {184		dev_err(tas2780->dev, "%s:errCode:0x%x set bitwidth error\n",185			__func__, ret);186		goto err;187	}188 189	ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG2,190		TAS2780_TDM_CFG2_RXS_MASK, slot_size);191	if (ret < 0) {192		dev_err(tas2780->dev,193			"%s:errCode:0x%x set RX slot size error\n",194			__func__, ret);195		goto err;196	}197 198	val = snd_soc_component_read(tas2780->component, TAS2780_PWR_CTRL);199	if (val < 0) {200		dev_err(tas2780->dev, "%s:errCode:0x%x read PWR_CTRL error\n",201			__func__, val);202		ret = val;203		goto err;204	}205 206	if (val & (1 << TAS2780_VSENSE_POWER_EN))207		sense_en = 0;208	else209		sense_en = TAS2780_TDM_CFG5_VSNS_ENABLE;210 211	ret = snd_soc_component_update_bits(tas2780->component,212		TAS2780_TDM_CFG5, TAS2780_TDM_CFG5_VSNS_ENABLE, sense_en);213	if (ret < 0) {214		dev_err(tas2780->dev, "%s:errCode:0x%x enable vSNS error\n",215			__func__, ret);216		goto err;217	}218 219	if (val & (1 << TAS2780_ISENSE_POWER_EN))220		sense_en = 0;221	else222		sense_en = TAS2780_TDM_CFG6_ISNS_ENABLE;223 224	ret = snd_soc_component_update_bits(tas2780->component,225		TAS2780_TDM_CFG6, TAS2780_TDM_CFG6_ISNS_ENABLE, sense_en);226	if (ret < 0) {227		dev_err(tas2780->dev, "%s:errCode:0x%x enable iSNS error\n",228			__func__, ret);229		goto err;230	}231	ret = 0;232err:233	return ret;234}235 236static int tas2780_set_samplerate(237	struct tas2780_priv *tas2780, int samplerate)238{239	struct snd_soc_component *component = tas2780->component;240	int ramp_rate_val;241	int ret;242 243	switch (samplerate) {244	case 48000:245		ramp_rate_val = TAS2780_TDM_CFG0_SMP_48KHZ |246				TAS2780_TDM_CFG0_44_1_48KHZ;247		break;248	case 44100:249		ramp_rate_val = TAS2780_TDM_CFG0_SMP_44_1KHZ |250				TAS2780_TDM_CFG0_44_1_48KHZ;251		break;252	case 96000:253		ramp_rate_val = TAS2780_TDM_CFG0_SMP_48KHZ |254				TAS2780_TDM_CFG0_88_2_96KHZ;255		break;256	case 88200:257		ramp_rate_val = TAS2780_TDM_CFG0_SMP_44_1KHZ |258				TAS2780_TDM_CFG0_88_2_96KHZ;259		break;260	default:261		return -EINVAL;262	}263	ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG0,264		TAS2780_TDM_CFG0_SMP_MASK | TAS2780_TDM_CFG0_MASK,265		ramp_rate_val);266	if (ret < 0) {267		dev_err(tas2780->dev,268			"%s:errCode:0x%x Failed to set ramp_rate_val\n",269			__func__, ret);270		goto err;271	}272	ret = 0;273err:274	return ret;275}276 277static int tas2780_hw_params(struct snd_pcm_substream *substream,278	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)279{280	struct snd_soc_component *component = dai->component;281	struct tas2780_priv *tas2780 =282		snd_soc_component_get_drvdata(component);283	int ret;284 285	ret = tas2780_set_bitwidth(tas2780, params_format(params));286	if (ret < 0)287		return ret;288 289	return tas2780_set_samplerate(tas2780, params_rate(params));290}291 292static int tas2780_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)293{294	struct snd_soc_component *component = dai->component;295	struct tas2780_priv *tas2780 =296		snd_soc_component_get_drvdata(component);297	u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;298	int iface;299	int ret = 0;300 301	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {302	case SND_SOC_DAIFMT_NB_NF:303		asi_cfg_1 = TAS2780_TDM_CFG1_RX_RISING;304		break;305	case SND_SOC_DAIFMT_IB_NF:306		asi_cfg_1 = TAS2780_TDM_CFG1_RX_FALLING;307		break;308	default:309		dev_err(tas2780->dev, "ASI format Inverse is not found\n");310		return -EINVAL;311	}312 313	ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG1,314		TAS2780_TDM_CFG1_RX_MASK, asi_cfg_1);315	if (ret < 0) {316		dev_err(tas2780->dev,317			"%s:errCode:0x%x Failed to set asi_cfg_1\n",318			__func__, ret);319		goto err;320	}321 322	if (((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S)323		|| ((fmt & SND_SOC_DAIFMT_FORMAT_MASK)324		== SND_SOC_DAIFMT_DSP_A)){325		iface = TAS2780_TDM_CFG2_SCFG_I2S;326		tdm_rx_start_slot = 1;327	} else {328		if (((fmt & SND_SOC_DAIFMT_FORMAT_MASK)329			== SND_SOC_DAIFMT_DSP_B)330			|| ((fmt & SND_SOC_DAIFMT_FORMAT_MASK)331			== SND_SOC_DAIFMT_LEFT_J)) {332			iface = TAS2780_TDM_CFG2_SCFG_LEFT_J;333			tdm_rx_start_slot = 0;334		} else {335			dev_err(tas2780->dev,336				"%s:DAI Format is not found, fmt=0x%x\n",337				__func__, fmt);338			ret = -EINVAL;339			goto err;340		}341	}342	ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG1,343		TAS2780_TDM_CFG1_MASK,344		(tdm_rx_start_slot << TAS2780_TDM_CFG1_51_SHIFT));345	if (ret < 0) {346		dev_err(tas2780->dev,347			"%s:errCode:0x%x Failed to set tdm_rx_start_slot\n",348			__func__, ret);349		goto err;350	}351 352	ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG2,353		TAS2780_TDM_CFG2_SCFG_MASK, iface);354	if (ret < 0) {355		dev_err(tas2780->dev, "%s:errCode:0x%x Failed to set iface\n",356			__func__, ret);357		goto err;358	}359	ret = 0;360err:361	return ret;362}363 364static int tas2780_set_dai_tdm_slot(struct snd_soc_dai *dai,365				unsigned int tx_mask,366				unsigned int rx_mask,367				int slots, int slot_width)368{369	struct snd_soc_component *component = dai->component;370	struct tas2780_priv *tas2780 =371		snd_soc_component_get_drvdata(component);372	int left_slot, right_slot;373	int slots_cfg;374	int slot_size;375	int ret = 0;376 377	if (tx_mask == 0 || rx_mask != 0)378		return -EINVAL;379 380	left_slot = __ffs(tx_mask);381	tx_mask &= ~(1 << left_slot);382	if (tx_mask == 0) {383		right_slot = left_slot;384	} else {385		right_slot = __ffs(tx_mask);386		tx_mask &= ~(1 << right_slot);387	}388 389	if (tx_mask != 0 || left_slot >= slots || right_slot >= slots)390		return -EINVAL;391 392	slots_cfg = (right_slot << TAS2780_TDM_CFG3_RXS_SHIFT) | left_slot;393	ret = snd_soc_component_write(component, TAS2780_TDM_CFG3, slots_cfg);394	if (ret) {395		dev_err(tas2780->dev,396			"%s:errCode:0x%x Failed to set slots_cfg\n",397			__func__, ret);398		goto err;399	}400 401	switch (slot_width) {402	case 16:403		slot_size = TAS2780_TDM_CFG2_RXS_16BITS;404		break;405	case 24:406		slot_size = TAS2780_TDM_CFG2_RXS_24BITS;407		break;408	case 32:409		slot_size = TAS2780_TDM_CFG2_RXS_32BITS;410		break;411	default:412		ret = -EINVAL;413		goto err;414	}415 416	ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG2,417		TAS2780_TDM_CFG2_RXS_MASK, slot_size);418	if (ret < 0) {419		dev_err(tas2780->dev,420			"%s:errCode:0x%x Failed to set slot_size\n",421			__func__, ret);422		goto err;423	}424 425	ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG5,426		TAS2780_TDM_CFG5_50_MASK, tas2780->v_sense_slot);427	if (ret < 0) {428		dev_err(tas2780->dev,429			"%s:errCode:0x%x Failed to set v_sense_slot\n",430			__func__, ret);431		goto err;432	}433 434	ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG6,435		TAS2780_TDM_CFG6_50_MASK, tas2780->i_sense_slot);436	if (ret < 0) {437		dev_err(tas2780->dev,438			"%s:errCode:0x%x Failed to set i_sense_slot\n",439			__func__, ret);440		goto err;441	}442	ret = 0;443err:444	return ret;445}446 447static const struct snd_soc_dai_ops tas2780_dai_ops = {448	.mute_stream = tas2780_mute,449	.hw_params  = tas2780_hw_params,450	.set_fmt    = tas2780_set_fmt,451	.set_tdm_slot = tas2780_set_dai_tdm_slot,452	.no_capture_mute = 1,453};454 455#define TAS2780_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\456			 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)457 458#define TAS2780_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\459		       SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_88200)460 461static struct snd_soc_dai_driver tas2780_dai_driver[] = {462	{463		.name = "tas2780 ASI1",464		.id = 0,465		.playback = {466			.stream_name    = "ASI1 Playback",467			.channels_min   = 2,468			.channels_max   = 2,469			.rates      = TAS2780_RATES,470			.formats    = TAS2780_FORMATS,471		},472		.capture = {473			.stream_name    = "ASI1 Capture",474			.channels_min   = 1,475			.channels_max   = 2,476			.rates = TAS2780_RATES,477			.formats = TAS2780_FORMATS,478		},479		.ops = &tas2780_dai_ops,480		.symmetric_rate = 1,481	},482};483 484static int tas2780_codec_probe(struct snd_soc_component *component)485{486	struct tas2780_priv *tas2780 =487		snd_soc_component_get_drvdata(component);488	int ret = 0;489 490	tas2780->component = component;491 492	tas2780_reset(tas2780);493	ret = snd_soc_component_update_bits(component,494			TAS2780_IC_CFG, TAS2780_IC_CFG_MASK,495			TAS2780_IC_CFG_ENABLE);496	if (ret < 0)497		dev_err(tas2780->dev, "%s:errCode:0x%0x\n",498			__func__, ret);499 500	return ret;501}502 503static DECLARE_TLV_DB_SCALE(tas2780_digital_tlv, 1100, 50, 0);504static DECLARE_TLV_DB_SCALE(tas2780_playback_volume, -10000, 50, 0);505 506static const struct snd_kcontrol_new tas2780_snd_controls[] = {507	SOC_SINGLE_TLV("Speaker Volume", TAS2780_DVC, 0,508		       TAS2780_DVC_MAX, 1, tas2780_playback_volume),509	SOC_SINGLE_TLV("Amp Gain Volume", TAS2780_CHNL_0, 0, 0x14, 0,510		       tas2780_digital_tlv),511};512 513static const struct snd_soc_component_driver soc_component_driver_tas2780 = {514	.probe			= tas2780_codec_probe,515#ifdef CONFIG_PM516	.suspend		= tas2780_codec_suspend,517	.resume			= tas2780_codec_resume,518#endif519	.controls		= tas2780_snd_controls,520	.num_controls		= ARRAY_SIZE(tas2780_snd_controls),521	.dapm_widgets		= tas2780_dapm_widgets,522	.num_dapm_widgets	= ARRAY_SIZE(tas2780_dapm_widgets),523	.dapm_routes		= tas2780_audio_map,524	.num_dapm_routes	= ARRAY_SIZE(tas2780_audio_map),525	.idle_bias_on		= 1,526	.endianness		= 1,527};528 529static const struct reg_default tas2780_reg_defaults[] = {530	{ TAS2780_PAGE, 0x00 },531	{ TAS2780_SW_RST, 0x00 },532	{ TAS2780_PWR_CTRL, 0x1a },533	{ TAS2780_DVC, 0x00 },534	{ TAS2780_CHNL_0, 0x00 },535	{ TAS2780_TDM_CFG0, 0x09 },536	{ TAS2780_TDM_CFG1, 0x02 },537	{ TAS2780_TDM_CFG2, 0x0a },538	{ TAS2780_TDM_CFG3, 0x10 },539	{ TAS2780_TDM_CFG5, 0x42 },540};541 542static const struct regmap_range_cfg tas2780_regmap_ranges[] = {543	{544		.range_min = 0,545		.range_max = 1 * 128,546		.selector_reg = TAS2780_PAGE,547		.selector_mask = 0xff,548		.selector_shift = 0,549		.window_start = 0,550		.window_len = 128,551	},552};553 554static const struct regmap_config tas2780_i2c_regmap = {555	.reg_bits = 8,556	.val_bits = 8,557	.reg_defaults = tas2780_reg_defaults,558	.num_reg_defaults = ARRAY_SIZE(tas2780_reg_defaults),559	.cache_type = REGCACHE_RBTREE,560	.ranges = tas2780_regmap_ranges,561	.num_ranges = ARRAY_SIZE(tas2780_regmap_ranges),562	.max_register = 1 * 128,563};564 565static int tas2780_parse_dt(struct device *dev, struct tas2780_priv *tas2780)566{567	int ret = 0;568 569	tas2780->reset_gpio = devm_gpiod_get_optional(tas2780->dev, "reset",570		GPIOD_OUT_HIGH);571	if (IS_ERR(tas2780->reset_gpio)) {572		if (PTR_ERR(tas2780->reset_gpio) == -EPROBE_DEFER) {573			tas2780->reset_gpio = NULL;574			return -EPROBE_DEFER;575		}576	}577 578	ret = fwnode_property_read_u32(dev->fwnode, "ti,imon-slot-no",579		&tas2780->i_sense_slot);580	if (ret)581		tas2780->i_sense_slot = 0;582 583	ret = fwnode_property_read_u32(dev->fwnode, "ti,vmon-slot-no",584		&tas2780->v_sense_slot);585	if (ret)586		tas2780->v_sense_slot = 2;587 588	return 0;589}590 591static int tas2780_i2c_probe(struct i2c_client *client)592{593	struct tas2780_priv *tas2780;594	int result;595 596	tas2780 = devm_kzalloc(&client->dev, sizeof(struct tas2780_priv),597		GFP_KERNEL);598	if (!tas2780)599		return -ENOMEM;600	tas2780->dev = &client->dev;601	i2c_set_clientdata(client, tas2780);602	dev_set_drvdata(&client->dev, tas2780);603 604	tas2780->regmap = devm_regmap_init_i2c(client, &tas2780_i2c_regmap);605	if (IS_ERR(tas2780->regmap)) {606		result = PTR_ERR(tas2780->regmap);607		dev_err(&client->dev, "Failed to allocate register map: %d\n",608			result);609		return result;610	}611 612	if (client->dev.of_node) {613		result = tas2780_parse_dt(&client->dev, tas2780);614		if (result) {615			dev_err(tas2780->dev,616				"%s: Failed to parse devicetree\n", __func__);617			return result;618		}619	}620 621	return devm_snd_soc_register_component(tas2780->dev,622		&soc_component_driver_tas2780, tas2780_dai_driver,623		ARRAY_SIZE(tas2780_dai_driver));624}625 626static const struct i2c_device_id tas2780_i2c_id[] = {627	{ "tas2780"},628	{ }629};630MODULE_DEVICE_TABLE(i2c, tas2780_i2c_id);631 632#if defined(CONFIG_OF)633static const struct of_device_id tas2780_of_match[] = {634	{ .compatible = "ti,tas2780" },635	{},636};637MODULE_DEVICE_TABLE(of, tas2780_of_match);638#endif639 640static struct i2c_driver tas2780_i2c_driver = {641	.driver = {642		.name   = "tas2780",643		.of_match_table = of_match_ptr(tas2780_of_match),644	},645	.probe      = tas2780_i2c_probe,646	.id_table   = tas2780_i2c_id,647};648module_i2c_driver(tas2780_i2c_driver);649 650MODULE_AUTHOR("Raphael Xu <raphael-xu@ti.com>");651MODULE_DESCRIPTION("TAS2780 I2C Smart Amplifier driver");652MODULE_LICENSE("GPL");653