brintos

brintos / linux-shallow public Read only

0
0
Text · 14.1 KiB · 9697aef Raw
535 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// rk3328 ALSA SoC Audio driver4//5// Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd All rights reserved.6 7#include <linux/clk.h>8#include <linux/delay.h>9#include <linux/device.h>10#include <linux/gpio/consumer.h>11#include <linux/module.h>12#include <linux/of.h>13#include <linux/platform_device.h>14#include <linux/regmap.h>15#include <linux/mfd/syscon.h>16#include <sound/dmaengine_pcm.h>17#include <sound/pcm_params.h>18#include "rk3328_codec.h"19 20/*21 * volume setting22 * 0: -39dB23 * 26: 0dB24 * 31: 6dB25 * Step: 1.5dB26 */27#define OUT_VOLUME	(0x18)28#define RK3328_GRF_SOC_CON2	(0x0408)29#define RK3328_GRF_SOC_CON10	(0x0428)30#define INITIAL_FREQ	(11289600)31 32struct rk3328_codec_priv {33	struct regmap *regmap;34	struct gpio_desc *mute;35	struct clk *mclk;36	struct clk *pclk;37	unsigned int sclk;38	int spk_depop_time; /* msec */39};40 41static const struct reg_default rk3328_codec_reg_defaults[] = {42	{ CODEC_RESET, 0x03 },43	{ DAC_INIT_CTRL1, 0x00 },44	{ DAC_INIT_CTRL2, 0x50 },45	{ DAC_INIT_CTRL3, 0x0e },46	{ DAC_PRECHARGE_CTRL, 0x01 },47	{ DAC_PWR_CTRL, 0x00 },48	{ DAC_CLK_CTRL, 0x00 },49	{ HPMIX_CTRL, 0x00 },50	{ HPOUT_CTRL, 0x00 },51	{ HPOUTL_GAIN_CTRL, 0x00 },52	{ HPOUTR_GAIN_CTRL, 0x00 },53	{ HPOUT_POP_CTRL, 0x11 },54};55 56static int rk3328_codec_reset(struct rk3328_codec_priv *rk3328)57{58	regmap_write(rk3328->regmap, CODEC_RESET, 0x00);59	mdelay(10);60	regmap_write(rk3328->regmap, CODEC_RESET, 0x03);61 62	return 0;63}64 65static int rk3328_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)66{67	struct rk3328_codec_priv *rk3328 =68		snd_soc_component_get_drvdata(dai->component);69	unsigned int val;70 71	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {72	case SND_SOC_DAIFMT_CBC_CFC:73		val = PIN_DIRECTION_IN | DAC_I2S_MODE_SLAVE;74		break;75	case SND_SOC_DAIFMT_CBP_CFP:76		val = PIN_DIRECTION_OUT | DAC_I2S_MODE_MASTER;77		break;78	default:79		return -EINVAL;80	}81 82	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL1,83			   PIN_DIRECTION_MASK | DAC_I2S_MODE_MASK, val);84 85	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {86	case SND_SOC_DAIFMT_DSP_A:87	case SND_SOC_DAIFMT_DSP_B:88		val = DAC_MODE_PCM;89		break;90	case SND_SOC_DAIFMT_I2S:91		val = DAC_MODE_I2S;92		break;93	case SND_SOC_DAIFMT_RIGHT_J:94		val = DAC_MODE_RJM;95		break;96	case SND_SOC_DAIFMT_LEFT_J:97		val = DAC_MODE_LJM;98		break;99	default:100		return -EINVAL;101	}102 103	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2,104			   DAC_MODE_MASK, val);105 106	return 0;107}108 109static int rk3328_mute_stream(struct snd_soc_dai *dai, int mute, int direction)110{111	struct rk3328_codec_priv *rk3328 =112		snd_soc_component_get_drvdata(dai->component);113	unsigned int val;114 115	if (mute)116		val = HPOUTL_MUTE | HPOUTR_MUTE;117	else118		val = HPOUTL_UNMUTE | HPOUTR_UNMUTE;119 120	regmap_update_bits(rk3328->regmap, HPOUT_CTRL,121			   HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, val);122 123	return 0;124}125 126static int rk3328_codec_power_on(struct rk3328_codec_priv *rk3328, int wait_ms)127{128	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,129			   DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_PRECHARGE);130	mdelay(10);131	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,132			   DAC_CHARGE_CURRENT_ALL_MASK,133			   DAC_CHARGE_CURRENT_ALL_ON);134	mdelay(wait_ms);135 136	return 0;137}138 139static int rk3328_codec_power_off(struct rk3328_codec_priv *rk3328, int wait_ms)140{141	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,142			   DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_DISCHARGE);143	mdelay(10);144	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,145			   DAC_CHARGE_CURRENT_ALL_MASK,146			   DAC_CHARGE_CURRENT_ALL_ON);147	mdelay(wait_ms);148 149	return 0;150}151 152static const struct rk3328_reg_msk_val playback_open_list[] = {153	{ DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_ON },154	{ DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,155	  DACL_PATH_REFV_ON | DACR_PATH_REFV_ON },156	{ DAC_PWR_CTRL, HPOUTL_ZERO_CROSSING_MASK | HPOUTR_ZERO_CROSSING_MASK,157	  HPOUTL_ZERO_CROSSING_ON | HPOUTR_ZERO_CROSSING_ON },158	{ HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,159	  HPOUTR_POP_WORK | HPOUTL_POP_WORK },160	{ HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_EN | HPMIXR_EN },161	{ HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK,162	  HPMIXL_INIT_EN | HPMIXR_INIT_EN },163	{ HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_EN | HPOUTR_EN },164	{ HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK,165	  HPOUTL_INIT_EN | HPOUTR_INIT_EN },166	{ DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK,167	  DACL_REFV_ON | DACR_REFV_ON },168	{ DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK,169	  DACL_CLK_ON | DACR_CLK_ON },170	{ DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_ON | DACR_ON },171	{ DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK,172	  DACL_INIT_ON | DACR_INIT_ON },173	{ DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,174	  DACL_SELECT | DACR_SELECT },175	{ HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,176	  HPMIXL_INIT2_EN | HPMIXR_INIT2_EN },177	{ HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK,178	  HPOUTL_UNMUTE | HPOUTR_UNMUTE },179};180 181static int rk3328_codec_open_playback(struct rk3328_codec_priv *rk3328)182{183	int i;184 185	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,186			   DAC_CHARGE_CURRENT_ALL_MASK,187			   DAC_CHARGE_CURRENT_I);188 189	for (i = 0; i < ARRAY_SIZE(playback_open_list); i++) {190		regmap_update_bits(rk3328->regmap,191				   playback_open_list[i].reg,192				   playback_open_list[i].msk,193				   playback_open_list[i].val);194		mdelay(1);195	}196 197	msleep(rk3328->spk_depop_time);198	gpiod_set_value(rk3328->mute, 0);199 200	regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,201			   HPOUTL_GAIN_MASK, OUT_VOLUME);202	regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL,203			   HPOUTR_GAIN_MASK, OUT_VOLUME);204 205	return 0;206}207 208static const struct rk3328_reg_msk_val playback_close_list[] = {209	{ HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,210	  HPMIXL_INIT2_DIS | HPMIXR_INIT2_DIS },211	{ DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,212	  DACL_UNSELECT | DACR_UNSELECT },213	{ HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK,214	  HPOUTL_MUTE | HPOUTR_MUTE },215	{ HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK,216	  HPOUTL_INIT_DIS | HPOUTR_INIT_DIS },217	{ HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_DIS | HPOUTR_DIS },218	{ HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_DIS | HPMIXR_DIS },219	{ DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_OFF | DACR_OFF },220	{ DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK,221	  DACL_CLK_OFF | DACR_CLK_OFF },222	{ DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK,223	  DACL_REFV_OFF | DACR_REFV_OFF },224	{ HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,225	  HPOUTR_POP_XCHARGE | HPOUTL_POP_XCHARGE },226	{ DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,227	  DACL_PATH_REFV_OFF | DACR_PATH_REFV_OFF },228	{ DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_OFF },229	{ HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK,230	  HPMIXL_INIT_DIS | HPMIXR_INIT_DIS },231	{ DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK,232	  DACL_INIT_OFF | DACR_INIT_OFF },233};234 235static int rk3328_codec_close_playback(struct rk3328_codec_priv *rk3328)236{237	size_t i;238 239	gpiod_set_value(rk3328->mute, 1);240 241	regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,242			   HPOUTL_GAIN_MASK, 0);243	regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL,244			   HPOUTR_GAIN_MASK, 0);245 246	for (i = 0; i < ARRAY_SIZE(playback_close_list); i++) {247		regmap_update_bits(rk3328->regmap,248				   playback_close_list[i].reg,249				   playback_close_list[i].msk,250				   playback_close_list[i].val);251		mdelay(1);252	}253 254	/* Workaround for silence when changed Fs 48 -> 44.1kHz */255	rk3328_codec_reset(rk3328);256 257	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,258			   DAC_CHARGE_CURRENT_ALL_MASK,259			   DAC_CHARGE_CURRENT_ALL_ON);260 261	return 0;262}263 264static int rk3328_hw_params(struct snd_pcm_substream *substream,265			    struct snd_pcm_hw_params *params,266			    struct snd_soc_dai *dai)267{268	struct rk3328_codec_priv *rk3328 =269		snd_soc_component_get_drvdata(dai->component);270	unsigned int val = 0;271 272	switch (params_format(params)) {273	case SNDRV_PCM_FORMAT_S16_LE:274		val = DAC_VDL_16BITS;275		break;276	case SNDRV_PCM_FORMAT_S20_3LE:277		val = DAC_VDL_20BITS;278		break;279	case SNDRV_PCM_FORMAT_S24_LE:280		val = DAC_VDL_24BITS;281		break;282	case SNDRV_PCM_FORMAT_S32_LE:283		val = DAC_VDL_32BITS;284		break;285	default:286		return -EINVAL;287	}288	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2, DAC_VDL_MASK, val);289 290	val = DAC_WL_32BITS | DAC_RST_DIS;291	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL3,292			   DAC_WL_MASK | DAC_RST_MASK, val);293 294	return 0;295}296 297static int rk3328_pcm_startup(struct snd_pcm_substream *substream,298			      struct snd_soc_dai *dai)299{300	struct rk3328_codec_priv *rk3328 =301		snd_soc_component_get_drvdata(dai->component);302 303	return rk3328_codec_open_playback(rk3328);304}305 306static void rk3328_pcm_shutdown(struct snd_pcm_substream *substream,307				struct snd_soc_dai *dai)308{309	struct rk3328_codec_priv *rk3328 =310		snd_soc_component_get_drvdata(dai->component);311 312	rk3328_codec_close_playback(rk3328);313}314 315static const struct snd_soc_dai_ops rk3328_dai_ops = {316	.hw_params = rk3328_hw_params,317	.set_fmt = rk3328_set_dai_fmt,318	.mute_stream = rk3328_mute_stream,319	.startup = rk3328_pcm_startup,320	.shutdown = rk3328_pcm_shutdown,321	.no_capture_mute = 1,322};323 324static struct snd_soc_dai_driver rk3328_dai[] = {325	{326		.name = "rk3328-hifi",327		.id = RK3328_HIFI,328		.playback = {329			.stream_name = "HIFI Playback",330			.channels_min = 1,331			.channels_max = 2,332			.rates = SNDRV_PCM_RATE_8000_96000,333			.formats = (SNDRV_PCM_FMTBIT_S16_LE |334				    SNDRV_PCM_FMTBIT_S20_3LE |335				    SNDRV_PCM_FMTBIT_S24_LE |336				    SNDRV_PCM_FMTBIT_S32_LE),337		},338		.capture = {339			.stream_name = "HIFI Capture",340			.channels_min = 2,341			.channels_max = 8,342			.rates = SNDRV_PCM_RATE_8000_96000,343			.formats = (SNDRV_PCM_FMTBIT_S16_LE |344				    SNDRV_PCM_FMTBIT_S20_3LE |345				    SNDRV_PCM_FMTBIT_S24_LE |346				    SNDRV_PCM_FMTBIT_S32_LE),347		},348		.ops = &rk3328_dai_ops,349	},350};351 352static int rk3328_codec_probe(struct snd_soc_component *component)353{354	struct rk3328_codec_priv *rk3328 =355		snd_soc_component_get_drvdata(component);356 357	rk3328_codec_reset(rk3328);358	rk3328_codec_power_on(rk3328, 0);359 360	return 0;361}362 363static void rk3328_codec_remove(struct snd_soc_component *component)364{365	struct rk3328_codec_priv *rk3328 =366		snd_soc_component_get_drvdata(component);367 368	rk3328_codec_close_playback(rk3328);369	rk3328_codec_power_off(rk3328, 0);370}371 372static const struct snd_soc_component_driver soc_codec_rk3328 = {373	.probe = rk3328_codec_probe,374	.remove = rk3328_codec_remove,375};376 377static bool rk3328_codec_write_read_reg(struct device *dev, unsigned int reg)378{379	switch (reg) {380	case CODEC_RESET:381	case DAC_INIT_CTRL1:382	case DAC_INIT_CTRL2:383	case DAC_INIT_CTRL3:384	case DAC_PRECHARGE_CTRL:385	case DAC_PWR_CTRL:386	case DAC_CLK_CTRL:387	case HPMIX_CTRL:388	case DAC_SELECT:389	case HPOUT_CTRL:390	case HPOUTL_GAIN_CTRL:391	case HPOUTR_GAIN_CTRL:392	case HPOUT_POP_CTRL:393		return true;394	default:395		return false;396	}397}398 399static bool rk3328_codec_volatile_reg(struct device *dev, unsigned int reg)400{401	switch (reg) {402	case CODEC_RESET:403		return true;404	default:405		return false;406	}407}408 409static const struct regmap_config rk3328_codec_regmap_config = {410	.reg_bits = 32,411	.reg_stride = 4,412	.val_bits = 32,413	.max_register = HPOUT_POP_CTRL,414	.writeable_reg = rk3328_codec_write_read_reg,415	.readable_reg = rk3328_codec_write_read_reg,416	.volatile_reg = rk3328_codec_volatile_reg,417	.reg_defaults = rk3328_codec_reg_defaults,418	.num_reg_defaults = ARRAY_SIZE(rk3328_codec_reg_defaults),419	.cache_type = REGCACHE_FLAT,420};421 422static int rk3328_platform_probe(struct platform_device *pdev)423{424	struct device_node *rk3328_np = pdev->dev.of_node;425	struct rk3328_codec_priv *rk3328;426	struct regmap *grf;427	void __iomem *base;428	int ret = 0;429 430	rk3328 = devm_kzalloc(&pdev->dev, sizeof(*rk3328), GFP_KERNEL);431	if (!rk3328)432		return -ENOMEM;433 434	grf = syscon_regmap_lookup_by_phandle(rk3328_np,435					      "rockchip,grf");436	if (IS_ERR(grf)) {437		dev_err(&pdev->dev, "missing 'rockchip,grf'\n");438		return PTR_ERR(grf);439	}440	/* enable i2s_acodec_en */441	regmap_write(grf, RK3328_GRF_SOC_CON2,442		     (BIT(14) << 16 | BIT(14)));443 444	ret = of_property_read_u32(rk3328_np, "spk-depop-time-ms",445				   &rk3328->spk_depop_time);446	if (ret < 0) {447		dev_info(&pdev->dev, "spk_depop_time use default value.\n");448		rk3328->spk_depop_time = 200;449	}450 451	rk3328->mute = gpiod_get_optional(&pdev->dev, "mute", GPIOD_OUT_HIGH);452	if (IS_ERR(rk3328->mute))453		return PTR_ERR(rk3328->mute);454	/*455	 * Rock64 is the only supported platform to have widely relied on456	 * this; if we do happen to come across an old DTB, just leave the457	 * external mute forced off.458	 */459	if (!rk3328->mute && of_machine_is_compatible("pine64,rock64")) {460		dev_warn(&pdev->dev, "assuming implicit control of GPIO_MUTE; update devicetree if possible\n");461		regmap_write(grf, RK3328_GRF_SOC_CON10, BIT(17) | BIT(1));462	}463 464	rk3328->mclk = devm_clk_get(&pdev->dev, "mclk");465	if (IS_ERR(rk3328->mclk))466		return PTR_ERR(rk3328->mclk);467 468	ret = clk_prepare_enable(rk3328->mclk);469	if (ret)470		return ret;471	clk_set_rate(rk3328->mclk, INITIAL_FREQ);472 473	rk3328->pclk = devm_clk_get(&pdev->dev, "pclk");474	if (IS_ERR(rk3328->pclk)) {475		dev_err(&pdev->dev, "can't get acodec pclk\n");476		ret = PTR_ERR(rk3328->pclk);477		goto err_unprepare_mclk;478	}479 480	ret = clk_prepare_enable(rk3328->pclk);481	if (ret < 0) {482		dev_err(&pdev->dev, "failed to enable acodec pclk\n");483		goto err_unprepare_mclk;484	}485 486	base = devm_platform_ioremap_resource(pdev, 0);487	if (IS_ERR(base)) {488		ret = PTR_ERR(base);489		goto err_unprepare_pclk;490	}491 492	rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base,493					       &rk3328_codec_regmap_config);494	if (IS_ERR(rk3328->regmap)) {495		ret = PTR_ERR(rk3328->regmap);496		goto err_unprepare_pclk;497	}498 499	platform_set_drvdata(pdev, rk3328);500 501	ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328,502					       rk3328_dai,503					       ARRAY_SIZE(rk3328_dai));504	if (ret)505		goto err_unprepare_pclk;506 507	return 0;508 509err_unprepare_pclk:510	clk_disable_unprepare(rk3328->pclk);511 512err_unprepare_mclk:513	clk_disable_unprepare(rk3328->mclk);514	return ret;515}516 517static const struct of_device_id rk3328_codec_of_match[] __maybe_unused = {518		{ .compatible = "rockchip,rk3328-codec", },519		{},520};521MODULE_DEVICE_TABLE(of, rk3328_codec_of_match);522 523static struct platform_driver rk3328_codec_driver = {524	.driver = {525		   .name = "rk3328-codec",526		   .of_match_table = of_match_ptr(rk3328_codec_of_match),527	},528	.probe = rk3328_platform_probe,529};530module_platform_driver(rk3328_codec_driver);531 532MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");533MODULE_DESCRIPTION("ASoC rk3328 codec driver");534MODULE_LICENSE("GPL v2");535