From 01573e231f18eb2d99162747186f59511f56b64d Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Fri, 08 Dec 2023 10:40:48 +0000
Subject: [PATCH] 移去rt

---
 kernel/sound/soc/codecs/rk3328_codec.c |  236 +++++++++++++++++++++++++++++++----------------------------
 1 files changed, 124 insertions(+), 112 deletions(-)

diff --git a/kernel/sound/soc/codecs/rk3328_codec.c b/kernel/sound/soc/codecs/rk3328_codec.c
index 5a4184a..e40b979 100644
--- a/kernel/sound/soc/codecs/rk3328_codec.c
+++ b/kernel/sound/soc/codecs/rk3328_codec.c
@@ -1,33 +1,21 @@
-/*
- * rk3328_codec.c  --  rk3328 ALSA Soc Audio driver
- *
- * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
+// SPDX-License-Identifier: GPL-2.0
+//
+// rk3328 ALSA SoC Audio driver
+//
+// Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd All rights reserved.
 
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/of.h>
 #include <linux/clk.h>
-#include <linux/mfd/syscon.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
-#include <sound/pcm_params.h>
+#include <linux/mfd/syscon.h>
 #include <sound/dmaengine_pcm.h>
+#include <sound/pcm_params.h>
 #include "rk3328_codec.h"
 
 /*
@@ -44,7 +32,7 @@
 
 struct rk3328_codec_priv {
 	struct regmap *regmap;
-	struct regmap *grf;
+	struct gpio_desc *mute;
 	struct clk *mclk;
 	struct clk *pclk;
 	unsigned int sclk;
@@ -66,29 +54,27 @@
 	{ HPOUT_POP_CTRL, 0x11 },
 };
 
-static int rk3328_codec_reset(struct snd_soc_component *component)
+static int rk3328_codec_reset(struct rk3328_codec_priv *rk3328)
 {
-	struct rk3328_codec_priv *rk3328 = snd_soc_component_get_drvdata(component);
-
-	regmap_write(rk3328->regmap, CODEC_RESET, 0);
+	regmap_write(rk3328->regmap, CODEC_RESET, 0x00);
 	mdelay(10);
 	regmap_write(rk3328->regmap, CODEC_RESET, 0x03);
 
 	return 0;
 }
 
-static int rk3328_set_dai_fmt(struct snd_soc_dai *dai,
-			      unsigned int fmt)
+static int rk3328_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
-	struct rk3328_codec_priv *rk3328 = snd_soc_component_get_drvdata(dai->component);
-	unsigned int val = 0;
+	struct rk3328_codec_priv *rk3328 =
+		snd_soc_component_get_drvdata(dai->component);
+	unsigned int val;
 
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 	case SND_SOC_DAIFMT_CBS_CFS:
-		val |= PIN_DIRECTION_IN | DAC_I2S_MODE_SLAVE;
+		val = PIN_DIRECTION_IN | DAC_I2S_MODE_SLAVE;
 		break;
 	case SND_SOC_DAIFMT_CBM_CFM:
-		val |= PIN_DIRECTION_OUT | DAC_I2S_MODE_MASTER;
+		val = PIN_DIRECTION_OUT | DAC_I2S_MODE_MASTER;
 		break;
 	default:
 		return -EINVAL;
@@ -97,20 +83,19 @@
 	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL1,
 			   PIN_DIRECTION_MASK | DAC_I2S_MODE_MASK, val);
 
-	val = 0;
 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 	case SND_SOC_DAIFMT_DSP_A:
 	case SND_SOC_DAIFMT_DSP_B:
-		val |= DAC_MODE_PCM;
+		val = DAC_MODE_PCM;
 		break;
 	case SND_SOC_DAIFMT_I2S:
-		val |= DAC_MODE_I2S;
+		val = DAC_MODE_I2S;
 		break;
 	case SND_SOC_DAIFMT_RIGHT_J:
-		val |= DAC_MODE_RJM;
+		val = DAC_MODE_RJM;
 		break;
 	case SND_SOC_DAIFMT_LEFT_J:
-		val |= DAC_MODE_LJM;
+		val = DAC_MODE_LJM;
 		break;
 	default:
 		return -EINVAL;
@@ -118,19 +103,15 @@
 
 	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2,
 			   DAC_MODE_MASK, val);
+
 	return 0;
 }
 
-static void rk3328_analog_output(struct rk3328_codec_priv *rk3328, int mute)
+static int rk3328_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
 {
-	regmap_write(rk3328->grf, RK3328_GRF_SOC_CON10,
-		     (BIT(1) << 16) | (mute << 1));
-}
-
-static int rk3328_digital_mute(struct snd_soc_dai *dai, int mute)
-{
-	struct rk3328_codec_priv *rk3328 = snd_soc_component_get_drvdata(dai->component);
-	unsigned int val = 0;
+	struct rk3328_codec_priv *rk3328 =
+		snd_soc_component_get_drvdata(dai->component);
+	unsigned int val;
 
 	if (mute)
 		val = HPOUTL_MUTE | HPOUTR_MUTE;
@@ -139,46 +120,41 @@
 
 	regmap_update_bits(rk3328->regmap, HPOUT_CTRL,
 			   HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, val);
+
 	return 0;
 }
 
-static int rk3328_codec_power_on(struct snd_soc_component *component, int wait_ms)
+static int rk3328_codec_power_on(struct rk3328_codec_priv *rk3328, int wait_ms)
 {
-	struct rk3328_codec_priv *rk3328 = snd_soc_component_get_drvdata(component);
-
 	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
 			   DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_PRECHARGE);
 	mdelay(10);
 	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
 			   DAC_CHARGE_CURRENT_ALL_MASK,
 			   DAC_CHARGE_CURRENT_ALL_ON);
-
 	mdelay(wait_ms);
 
 	return 0;
 }
 
-static int rk3328_codec_power_off(struct snd_soc_component *component, int wait_ms)
+static int rk3328_codec_power_off(struct rk3328_codec_priv *rk3328, int wait_ms)
 {
-	struct rk3328_codec_priv *rk3328 = snd_soc_component_get_drvdata(component);
-
 	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
 			   DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_DISCHARGE);
 	mdelay(10);
 	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
 			   DAC_CHARGE_CURRENT_ALL_MASK,
 			   DAC_CHARGE_CURRENT_ALL_ON);
-
 	mdelay(wait_ms);
 
 	return 0;
 }
 
-static struct rk3328_reg_msk_val playback_open_list[] = {
+static const struct rk3328_reg_msk_val playback_open_list[] = {
 	{ DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_ON },
 	{ DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,
 	  DACL_PATH_REFV_ON | DACR_PATH_REFV_ON },
-	{ DAC_PWR_CTRL, HPOUTL_ZERO_CROSSING_ON | HPOUTR_ZERO_CROSSING_ON,
+	{ DAC_PWR_CTRL, HPOUTL_ZERO_CROSSING_MASK | HPOUTR_ZERO_CROSSING_MASK,
 	  HPOUTL_ZERO_CROSSING_ON | HPOUTR_ZERO_CROSSING_ON },
 	{ HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,
 	  HPOUTR_POP_WORK | HPOUTL_POP_WORK },
@@ -203,18 +179,15 @@
 	  HPOUTL_UNMUTE | HPOUTR_UNMUTE },
 };
 
-#define PLAYBACK_OPEN_LIST_LEN ARRAY_SIZE(playback_open_list)
-
-static int rk3328_codec_open_playback(struct snd_soc_component *component)
+static int rk3328_codec_open_playback(struct rk3328_codec_priv *rk3328)
 {
-	struct rk3328_codec_priv *rk3328 = snd_soc_component_get_drvdata(component);
-	int i = 0;
+	int i;
 
 	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
 			   DAC_CHARGE_CURRENT_ALL_MASK,
 			   DAC_CHARGE_CURRENT_I);
 
-	for (i = 0; i < PLAYBACK_OPEN_LIST_LEN; i++) {
+	for (i = 0; i < ARRAY_SIZE(playback_open_list); i++) {
 		regmap_update_bits(rk3328->regmap,
 				   playback_open_list[i].reg,
 				   playback_open_list[i].msk,
@@ -223,16 +196,17 @@
 	}
 
 	msleep(rk3328->spk_depop_time);
-	rk3328_analog_output(rk3328, 1);
+	gpiod_set_value(rk3328->mute, 0);
 
 	regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,
 			   HPOUTL_GAIN_MASK, OUT_VOLUME);
 	regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL,
 			   HPOUTR_GAIN_MASK, OUT_VOLUME);
+
 	return 0;
 }
 
-static struct rk3328_reg_msk_val playback_close_list[] = {
+static const struct rk3328_reg_msk_val playback_close_list[] = {
 	{ HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,
 	  HPMIXL_INIT2_DIS | HPMIXR_INIT2_DIS },
 	{ DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,
@@ -259,21 +233,18 @@
 	  DACL_INIT_OFF | DACR_INIT_OFF },
 };
 
-#define PLAYBACK_CLOSE_LIST_LEN ARRAY_SIZE(playback_close_list)
-
-static int rk3328_codec_close_playback(struct snd_soc_component *component)
+static int rk3328_codec_close_playback(struct rk3328_codec_priv *rk3328)
 {
-	struct rk3328_codec_priv *rk3328 = snd_soc_component_get_drvdata(component);
-	int i = 0;
+	size_t i;
 
-	rk3328_analog_output(rk3328, 0);
+	gpiod_set_value(rk3328->mute, 1);
 
 	regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,
 			   HPOUTL_GAIN_MASK, 0);
 	regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL,
 			   HPOUTR_GAIN_MASK, 0);
 
-	for (i = 0; i < PLAYBACK_CLOSE_LIST_LEN; i++) {
+	for (i = 0; i < ARRAY_SIZE(playback_close_list); i++) {
 		regmap_update_bits(rk3328->regmap,
 				   playback_close_list[i].reg,
 				   playback_close_list[i].msk,
@@ -281,9 +252,13 @@
 		mdelay(1);
 	}
 
+	/* Workaround for silence when changed Fs 48 -> 44.1kHz */
+	rk3328_codec_reset(rk3328);
+
 	regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
 			   DAC_CHARGE_CURRENT_ALL_MASK,
-			   DAC_CHARGE_CURRENT_I);
+			   DAC_CHARGE_CURRENT_ALL_ON);
+
 	return 0;
 }
 
@@ -291,27 +266,28 @@
 			    struct snd_pcm_hw_params *params,
 			    struct snd_soc_dai *dai)
 {
-	struct rk3328_codec_priv *rk3328 = snd_soc_component_get_drvdata(dai->component);
+	struct rk3328_codec_priv *rk3328 =
+		snd_soc_component_get_drvdata(dai->component);
 	unsigned int val = 0;
 
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S16_LE:
-		val |= DAC_VDL_16BITS;
+		val = DAC_VDL_16BITS;
 		break;
 	case SNDRV_PCM_FORMAT_S20_3LE:
-		val |= DAC_VDL_20BITS;
+		val = DAC_VDL_20BITS;
 		break;
 	case SNDRV_PCM_FORMAT_S24_LE:
-		val |= DAC_VDL_24BITS;
+		val = DAC_VDL_24BITS;
 		break;
 	case SNDRV_PCM_FORMAT_S32_LE:
-		val |= DAC_VDL_32BITS;
+		val = DAC_VDL_32BITS;
 		break;
 	default:
 		return -EINVAL;
 	}
-
 	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2, DAC_VDL_MASK, val);
+
 	val = DAC_WL_32BITS | DAC_RST_DIS;
 	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL3,
 			   DAC_WL_MASK | DAC_RST_MASK, val);
@@ -322,21 +298,28 @@
 static int rk3328_pcm_startup(struct snd_pcm_substream *substream,
 			      struct snd_soc_dai *dai)
 {
-	return rk3328_codec_open_playback(dai->component);
+	struct rk3328_codec_priv *rk3328 =
+		snd_soc_component_get_drvdata(dai->component);
+
+	return rk3328_codec_open_playback(rk3328);
 }
 
 static void rk3328_pcm_shutdown(struct snd_pcm_substream *substream,
 				struct snd_soc_dai *dai)
 {
-	rk3328_codec_close_playback(dai->component);
+	struct rk3328_codec_priv *rk3328 =
+		snd_soc_component_get_drvdata(dai->component);
+
+	rk3328_codec_close_playback(rk3328);
 }
 
 static const struct snd_soc_dai_ops rk3328_dai_ops = {
 	.hw_params = rk3328_hw_params,
 	.set_fmt = rk3328_set_dai_fmt,
-	.digital_mute = rk3328_digital_mute,
+	.mute_stream = rk3328_mute_stream,
 	.startup = rk3328_pcm_startup,
 	.shutdown = rk3328_pcm_shutdown,
+	.no_capture_mute = 1,
 };
 
 static struct snd_soc_dai_driver rk3328_dai[] = {
@@ -369,19 +352,25 @@
 
 static int rk3328_codec_probe(struct snd_soc_component *component)
 {
-	rk3328_codec_reset(component);
-	rk3328_codec_power_on(component, 0);
+	struct rk3328_codec_priv *rk3328 =
+		snd_soc_component_get_drvdata(component);
+
+	rk3328_codec_reset(rk3328);
+	rk3328_codec_power_on(rk3328, 0);
 
 	return 0;
 }
 
 static void rk3328_codec_remove(struct snd_soc_component *component)
 {
-	rk3328_codec_close_playback(component);
-	rk3328_codec_power_off(component, 0);
+	struct rk3328_codec_priv *rk3328 =
+		snd_soc_component_get_drvdata(component);
+
+	rk3328_codec_close_playback(rk3328);
+	rk3328_codec_power_off(rk3328, 0);
 }
 
-static const struct snd_soc_component_driver soc_codec_dev_rk3328 = {
+static const struct snd_soc_component_driver soc_codec_rk3328 = {
 	.probe = rk3328_codec_probe,
 	.remove = rk3328_codec_remove,
 };
@@ -431,19 +420,10 @@
 	.cache_type = REGCACHE_FLAT,
 };
 
-#ifdef CONFIG_OF
-static const struct of_device_id rk3328codec_of_match[] = {
-		{ .compatible = "rockchip,rk3328-codec", },
-		{},
-};
-MODULE_DEVICE_TABLE(of, rk3328codec_of_match);
-#endif
-
 static int rk3328_platform_probe(struct platform_device *pdev)
 {
 	struct device_node *rk3328_np = pdev->dev.of_node;
 	struct rk3328_codec_priv *rk3328;
-	struct resource *res;
 	struct regmap *grf;
 	void __iomem *base;
 	int ret = 0;
@@ -458,7 +438,6 @@
 		dev_err(&pdev->dev, "missing 'rockchip,grf'\n");
 		return PTR_ERR(grf);
 	}
-	rk3328->grf = grf;
 	/* enable i2s_acodec_en */
 	regmap_write(grf, RK3328_GRF_SOC_CON2,
 		     (BIT(14) << 16 | BIT(14)));
@@ -467,10 +446,21 @@
 				   &rk3328->spk_depop_time);
 	if (ret < 0) {
 		dev_info(&pdev->dev, "spk_depop_time use default value.\n");
-		rk3328->spk_depop_time = 100;
+		rk3328->spk_depop_time = 200;
 	}
 
-	rk3328_analog_output(rk3328, 0);
+	rk3328->mute = gpiod_get_optional(&pdev->dev, "mute", GPIOD_OUT_HIGH);
+	if (IS_ERR(rk3328->mute))
+		return PTR_ERR(rk3328->mute);
+	/*
+	 * Rock64 is the only supported platform to have widely relied on
+	 * this; if we do happen to come across an old DTB, just leave the
+	 * external mute forced off.
+	 */
+	if (!rk3328->mute && of_machine_is_compatible("pine64,rock64")) {
+		dev_warn(&pdev->dev, "assuming implicit control of GPIO_MUTE; update devicetree if possible\n");
+		regmap_write(grf, RK3328_GRF_SOC_CON10, BIT(17) | BIT(1));
+	}
 
 	rk3328->mclk = devm_clk_get(&pdev->dev, "mclk");
 	if (IS_ERR(rk3328->mclk))
@@ -484,35 +474,57 @@
 	rk3328->pclk = devm_clk_get(&pdev->dev, "pclk");
 	if (IS_ERR(rk3328->pclk)) {
 		dev_err(&pdev->dev, "can't get acodec pclk\n");
-		return PTR_ERR(rk3328->pclk);
+		ret = PTR_ERR(rk3328->pclk);
+		goto err_unprepare_mclk;
 	}
 
 	ret = clk_prepare_enable(rk3328->pclk);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to enable acodec pclk\n");
-		return ret;
+		goto err_unprepare_mclk;
 	}
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base)) {
+		ret = PTR_ERR(base);
+		goto err_unprepare_pclk;
+	}
 
 	rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base,
 					       &rk3328_codec_regmap_config);
-	if (IS_ERR(rk3328->regmap))
-		return PTR_ERR(rk3328->regmap);
+	if (IS_ERR(rk3328->regmap)) {
+		ret = PTR_ERR(rk3328->regmap);
+		goto err_unprepare_pclk;
+	}
 
 	platform_set_drvdata(pdev, rk3328);
 
-	return devm_snd_soc_register_component(&pdev->dev, &soc_codec_dev_rk3328,
-				      rk3328_dai, ARRAY_SIZE(rk3328_dai));
+	ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328,
+					       rk3328_dai,
+					       ARRAY_SIZE(rk3328_dai));
+	if (ret)
+		goto err_unprepare_pclk;
+
+	return 0;
+
+err_unprepare_pclk:
+	clk_disable_unprepare(rk3328->pclk);
+
+err_unprepare_mclk:
+	clk_disable_unprepare(rk3328->mclk);
+	return ret;
 }
+
+static const struct of_device_id rk3328_codec_of_match[] = {
+		{ .compatible = "rockchip,rk3328-codec", },
+		{},
+};
+MODULE_DEVICE_TABLE(of, rk3328_codec_of_match);
 
 static struct platform_driver rk3328_codec_driver = {
 	.driver = {
 		   .name = "rk3328-codec",
-		   .of_match_table = of_match_ptr(rk3328codec_of_match),
+		   .of_match_table = of_match_ptr(rk3328_codec_of_match),
 	},
 	.probe = rk3328_platform_probe,
 };

--
Gitblit v1.6.2