From 336c6579dbd12fdf796730d2910f65f760c2572b Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Mon, 9 Oct 2023 23:25:48 +0800 Subject: [PATCH 01/18] ASoC: rockchip: i2s: Add support for DLP This patch add support DMA-based digital loopback for I2S. Ref: commit 9975bc50f325 ("ASoC: rockchip: Add support for Digital Loopback") Signed-off-by: Sugar Zhang Change-Id: I8a0ea59b216e18ed8c9758f529ef600a333913d7 --- sound/soc/rockchip/rockchip_i2s.c | 43 ++++++++++++++++++++++++++++--- sound/soc/rockchip/rockchip_i2s.h | 10 ++++++- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 9bc29fdd13c5..5c85fefe81e7 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -21,6 +21,7 @@ #include #include "rockchip_i2s.h" +#include "rockchip_dlp_pcm.h" #define DRV_NAME "rockchip-i2s" @@ -798,7 +799,8 @@ static bool rockchip_i2s_rd_reg(struct device *dev, unsigned int reg) case I2S_CLR: case I2S_TXDR: case I2S_RXDR: - case I2S_FIFOLR: + case I2S_TXFIFOLR: + case I2S_RXFIFOLR: case I2S_INTSR: return true; default: @@ -811,7 +813,8 @@ static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg) switch (reg) { case I2S_INTSR: case I2S_CLR: - case I2S_FIFOLR: + case I2S_TXFIFOLR: + case I2S_RXFIFOLR: case I2S_TXDR: case I2S_RXDR: return true; @@ -1016,6 +1019,36 @@ static int rockchip_i2s_keep_clk_always_on(struct rk_i2s_dev *i2s) return 0; } +static int rockchip_i2s_get_fifo_count(struct device *dev, + struct snd_pcm_substream *substream) +{ + struct rk_i2s_dev *i2s = dev_get_drvdata(dev); + unsigned int tx, rx; + int val = 0; + + regmap_read(i2s->regmap, I2S_TXFIFOLR, &tx); + regmap_read(i2s->regmap, I2S_RXFIFOLR, &rx); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + val = I2S_FIFOLR_XFL3(tx) + + I2S_FIFOLR_XFL2(tx) + + I2S_FIFOLR_XFL1(tx) + + I2S_FIFOLR_XFL0(tx); + else + /* XFL4 is compatible for old version */ + val = I2S_FIFOLR_XFL4(tx) + + I2S_FIFOLR_XFL3(rx) + + I2S_FIFOLR_XFL2(rx) + + I2S_FIFOLR_XFL1(rx) + + I2S_FIFOLR_XFL0(rx); + + return val; +} + +static const struct snd_dlp_config dconfig = { + .get_fifo_count = rockchip_i2s_get_fifo_count, +}; + static int rockchip_i2s_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -1141,7 +1174,11 @@ static int rockchip_i2s_probe(struct platform_device *pdev) return 0; } - ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); + if (device_property_read_bool(&pdev->dev, "rockchip,digital-loopback")) + ret = devm_snd_dmaengine_dlp_register(&pdev->dev, &dconfig); + else + ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); + if (ret) { dev_err(&pdev->dev, "Could not register PCM\n"); goto err_suspend; diff --git a/sound/soc/rockchip/rockchip_i2s.h b/sound/soc/rockchip/rockchip_i2s.h index 251851bf4f2c..bf71ea59ab0c 100644 --- a/sound/soc/rockchip/rockchip_i2s.h +++ b/sound/soc/rockchip/rockchip_i2s.h @@ -229,7 +229,7 @@ enum { #define I2S_TXCR (0x0000) #define I2S_RXCR (0x0004) #define I2S_CKR (0x0008) -#define I2S_FIFOLR (0x000c) +#define I2S_TXFIFOLR (0x000c) #define I2S_DMACR (0x0010) #define I2S_INTCR (0x0014) #define I2S_INTSR (0x0018) @@ -237,6 +237,7 @@ enum { #define I2S_CLR (0x0020) #define I2S_TXDR (0x0024) #define I2S_RXDR (0x0028) +#define I2S_RXFIFOLR (0x002c) /* io direction cfg register */ #define I2S_IO_DIRECTION_MASK (7) @@ -245,4 +246,11 @@ enum { #define I2S_IO_4CH_OUT_6CH_IN (6) #define I2S_IO_2CH_OUT_8CH_IN (7) +/* XFL4 is compatible for old version */ +#define I2S_FIFOLR_XFL4(v) (((v) & GENMASK(29, 24)) >> 24) +#define I2S_FIFOLR_XFL3(v) (((v) & GENMASK(23, 18)) >> 18) +#define I2S_FIFOLR_XFL2(v) (((v) & GENMASK(17, 12)) >> 12) +#define I2S_FIFOLR_XFL1(v) (((v) & GENMASK(11, 6)) >> 6) +#define I2S_FIFOLR_XFL0(v) (((v) & GENMASK(5, 0)) >> 0) + #endif /* _ROCKCHIP_IIS_H */ From adf9ddf934a194c6218c1fecf184c0f6eed8a36c Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Wed, 11 Oct 2023 19:10:40 +0800 Subject: [PATCH 02/18] ASoC: rockchip: sai: Add support for DLP This patch add support DMA-based digital loopback for SAI. Ref: commit 9975bc50f325 ("ASoC: rockchip: Add support for Digital Loopback") Signed-off-by: Sugar Zhang Change-Id: I2af1b849b65453f015ed5cc943b2f26622a5efa4 --- sound/soc/rockchip/rockchip_sai.c | 30 +++++++++++++++++++++++++++++- sound/soc/rockchip/rockchip_sai.h | 10 ++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/sound/soc/rockchip/rockchip_sai.c b/sound/soc/rockchip/rockchip_sai.c index 6609c1fa4788..96b92b66190b 100644 --- a/sound/soc/rockchip/rockchip_sai.c +++ b/sound/soc/rockchip/rockchip_sai.c @@ -19,6 +19,7 @@ #include #include "rockchip_sai.h" +#include "rockchip_dlp_pcm.h" #define DRV_NAME "rockchip-sai" @@ -1344,6 +1345,29 @@ static int rockchip_sai_parse_quirks(struct rk_sai_dev *sai) return ret; } +static int rockchip_sai_get_fifo_count(struct device *dev, + struct snd_pcm_substream *substream) +{ + struct rk_sai_dev *sai = dev_get_drvdata(dev); + int val = 0; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + regmap_read(sai->regmap, SAI_TXFIFOLR, &val); + else + regmap_read(sai->regmap, SAI_RXFIFOLR, &val); + + val = ((val & SAI_FIFOLR_XFL3_MASK) >> SAI_FIFOLR_XFL3_SHIFT) + + ((val & SAI_FIFOLR_XFL2_MASK) >> SAI_FIFOLR_XFL2_SHIFT) + + ((val & SAI_FIFOLR_XFL1_MASK) >> SAI_FIFOLR_XFL1_SHIFT) + + ((val & SAI_FIFOLR_XFL0_MASK) >> SAI_FIFOLR_XFL0_SHIFT); + + return val; +} + +static const struct snd_dlp_config dconfig = { + .get_fifo_count = rockchip_sai_get_fifo_count, +}; + static int rockchip_sai_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -1438,7 +1462,11 @@ static int rockchip_sai_probe(struct platform_device *pdev) return 0; } - ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); + if (device_property_read_bool(&pdev->dev, "rockchip,digital-loopback")) + ret = devm_snd_dmaengine_dlp_register(&pdev->dev, &dconfig); + else + ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); + if (ret) goto err_runtime_suspend; diff --git a/sound/soc/rockchip/rockchip_sai.h b/sound/soc/rockchip/rockchip_sai.h index c720fc836521..82288185d64f 100644 --- a/sound/soc/rockchip/rockchip_sai.h +++ b/sound/soc/rockchip/rockchip_sai.h @@ -120,6 +120,16 @@ #define SAI_XSHIFT_SEL_MASK GENMASK(23, 0) #define SAI_XSHIFT_SEL(x) (x) +/* XFIFOLR: Transfer / Receive FIFO Level Register */ +#define SAI_FIFOLR_XFL3_SHIFT 18 +#define SAI_FIFOLR_XFL3_MASK GENMASK(23, 18) +#define SAI_FIFOLR_XFL2_SHIFT 12 +#define SAI_FIFOLR_XFL2_MASK GENMASK(17, 12) +#define SAI_FIFOLR_XFL1_SHIFT 6 +#define SAI_FIFOLR_XFL1_MASK GENMASK(11, 6) +#define SAI_FIFOLR_XFL0_SHIFT 0 +#define SAI_FIFOLR_XFL0_MASK GENMASK(5, 0) + /* SAI Registers */ #define SAI_TXCR (0x0000) #define SAI_FSCR (0x0004) From 1831ca1cdc0bf2e4e33400a5ccf36ee514322653 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Thu, 12 Oct 2023 10:58:41 +0800 Subject: [PATCH 03/18] ASoC: rockchip: sai: Fix mclk rate check Should compare to mclk_req rate, and also increase delta from 1 Hz to 5 Hz. Fixes: bca24656b60d ("ASoC: rockchip: sai: Allow mclk shift around 1 Hz") Signed-off-by: Sugar Zhang Change-Id: I7906c21e670c1dd7f105c025e110af61cbd56299 --- sound/soc/rockchip/rockchip_sai.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sound/soc/rockchip/rockchip_sai.c b/sound/soc/rockchip/rockchip_sai.c index 96b92b66190b..f415ebbdbbef 100644 --- a/sound/soc/rockchip/rockchip_sai.c +++ b/sound/soc/rockchip/rockchip_sai.c @@ -23,7 +23,7 @@ #define DRV_NAME "rockchip-sai" -#define CLK_SHIFT_RATE_HZ_MAX 1 /* 1 Hz */ +#define CLK_SHIFT_RATE_HZ_MAX 5 #define FW_RATIO_MAX 8 #define FW_RATIO_MIN 1 #define MAXBURST_PER_FIFO 8 @@ -423,7 +423,7 @@ static int rockchip_sai_hw_params(struct snd_pcm_substream *substream, { struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai); struct snd_dmaengine_dai_dma_data *dma_data; - unsigned int mclk_rate, bclk_rate, div_bclk; + unsigned int mclk_rate, mclk_req_rate, bclk_rate, div_bclk; unsigned int ch_per_lane, lanes, slot_width; unsigned int val, fscr, reg; @@ -498,15 +498,16 @@ static int rockchip_sai_hw_params(struct snd_pcm_substream *substream, if (sai->is_clk_auto) clk_set_rate(sai->mclk, bclk_rate); mclk_rate = clk_get_rate(sai->mclk); - if (mclk_rate < bclk_rate - CLK_SHIFT_RATE_HZ_MAX || - mclk_rate > bclk_rate + CLK_SHIFT_RATE_HZ_MAX) { + div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate); + mclk_req_rate = bclk_rate * div_bclk; + + if (mclk_rate < mclk_req_rate - CLK_SHIFT_RATE_HZ_MAX || + mclk_rate > mclk_req_rate + CLK_SHIFT_RATE_HZ_MAX) { dev_err(sai->dev, "Mismatch mclk: %u, expected %u (+/- %dHz)\n", - mclk_rate, bclk_rate, CLK_SHIFT_RATE_HZ_MAX); + mclk_rate, mclk_req_rate, CLK_SHIFT_RATE_HZ_MAX); return -EINVAL; } - div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate); - regmap_update_bits(sai->regmap, SAI_CKR, SAI_CKR_MDIV_MASK, SAI_CKR_MDIV(div_bclk)); } From fa9161ee5fe7fa83137a0ed85656cd1e554b4ae2 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Thu, 12 Oct 2023 16:36:52 +0800 Subject: [PATCH 04/18] ASoC: rockchip: multi_dais: Add fifo count for SAI Signed-off-by: Sugar Zhang Change-Id: I5b0e478b9eebbc2a5d1a30594549ba3cff3af435 --- sound/soc/rockchip/rockchip_multi_dais_pcm.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/sound/soc/rockchip/rockchip_multi_dais_pcm.c b/sound/soc/rockchip/rockchip_multi_dais_pcm.c index 6461412faabb..f073e151966a 100644 --- a/sound/soc/rockchip/rockchip_multi_dais_pcm.c +++ b/sound/soc/rockchip/rockchip_multi_dais_pcm.c @@ -20,6 +20,8 @@ #define I2S_TXFIFOLR 0xc #define I2S_RXFIFOLR 0x2c +#define SAI_TXFIFOLR 0x1c +#define SAI_RXFIFOLR 0x20 /* XFL4 is compatible for old version */ #define I2S_FIFOLR_XFL4(v) (((v) & GENMASK(29, 24)) >> 24) @@ -28,6 +30,12 @@ #define I2S_FIFOLR_XFL1(v) (((v) & GENMASK(11, 6)) >> 6) #define I2S_FIFOLR_XFL0(v) (((v) & GENMASK(5, 0)) >> 0) +/* XFIFOLR: Transfer / Receive FIFO Level Register */ +#define SAI_FIFOLR_XFL3(v) (((v) & GENMASK(23, 18)) >> 18) +#define SAI_FIFOLR_XFL2(v) (((v) & GENMASK(17, 12)) >> 12) +#define SAI_FIFOLR_XFL1(v) (((v) & GENMASK(11, 6)) >> 6) +#define SAI_FIFOLR_XFL0(v) (((v) & GENMASK(5, 0)) >> 0) + #define MAX_FIFO_SIZE 32 /* max fifo size in frames */ #define SND_DMAENGINE_MPCM_DRV_NAME "snd_dmaengine_mpcm" @@ -864,7 +872,7 @@ static int dmaengine_mpcm_get_fifo_count(struct device *dev, struct rk_mdais_dev *mdais = dev_get_drvdata(dev); struct dmaengine_mpcm_runtime_data *prtd = substream_to_prtd(substream); struct snd_soc_component *component; - unsigned int tx, rx; + unsigned int tx, rx, reg; int val = 0; if (unlikely(!prtd)) @@ -891,6 +899,13 @@ static int dmaengine_mpcm_get_fifo_count(struct device *dev, I2S_FIFOLR_XFL2(rx) + I2S_FIFOLR_XFL1(rx) + I2S_FIFOLR_XFL0(rx); + } else if (strstr(dev_driver_string(component->dev), "sai")) { + reg = substream->stream ? SAI_RXFIFOLR : SAI_TXFIFOLR; + + val = SAI_FIFOLR_XFL3(reg) + + SAI_FIFOLR_XFL2(reg) + + SAI_FIFOLR_XFL1(reg) + + SAI_FIFOLR_XFL0(reg); } return val; From db80bed04763ac6fead6deafe1e1810418a755f6 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Fri, 13 Oct 2023 09:36:43 +0800 Subject: [PATCH 05/18] arm64: configs: rockchip_linux: Enable SND_SOC_ROCKCHIP_DLP_PCM Audio Products with AEC require loopback for echo cancellation. the hardware LP is not always available on some products, maybe the HW limitation(such as internal acodec) or HW Cost-down. This patch add support software DLP for such products. Ref: commit 9975bc50f325 ("ASoC: rockchip: Add support for Digital Loopback") Signed-off-by: Sugar Zhang Change-Id: Iab070c94c33c3fd47646d07ab38cd9c997a302cf --- arch/arm64/configs/rockchip_linux_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/rockchip_linux_defconfig b/arch/arm64/configs/rockchip_linux_defconfig index 5df82f41cf8f..5bf34e9f0734 100644 --- a/arch/arm64/configs/rockchip_linux_defconfig +++ b/arch/arm64/configs/rockchip_linux_defconfig @@ -398,6 +398,7 @@ CONFIG_SND_SEQ_DUMMY=y CONFIG_SND_USB_AUDIO=y CONFIG_SND_SOC=y CONFIG_SND_SOC_ROCKCHIP=y +CONFIG_SND_SOC_ROCKCHIP_DLP_PCM=y CONFIG_SND_SOC_ROCKCHIP_I2S_TDM=y CONFIG_SND_SOC_ROCKCHIP_MULTI_DAIS=y CONFIG_SND_SOC_ROCKCHIP_PDM=y From e4c5916e13945f18b84813de4d76068d71162da7 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Fri, 13 Oct 2023 09:33:11 +0800 Subject: [PATCH 06/18] arm64: configs: rockchip: Enable SND_SOC_ROCKCHIP_DLP_PCM Audio Products with AEC require loopback for echo cancellation. the hardware LP is not always available on some products, maybe the HW limitation(such as internal acodec) or HW Cost-down. This patch add support software DLP for such products. Ref: commit 9975bc50f325 ("ASoC: rockchip: Add support for Digital Loopback") Signed-off-by: Sugar Zhang Change-Id: Ief55346feb52e264fbc22434c6a3c046b455dfe3 --- arch/arm64/configs/rockchip_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index ccf7e54fc9ed..3bf12675bb19 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -697,6 +697,7 @@ CONFIG_SND_VERBOSE_PRINTK=y CONFIG_SND_USB_AUDIO=y CONFIG_SND_SOC=y CONFIG_SND_SOC_ROCKCHIP=y +CONFIG_SND_SOC_ROCKCHIP_DLP_PCM=y CONFIG_SND_SOC_ROCKCHIP_I2S=y CONFIG_SND_SOC_ROCKCHIP_I2S_TDM=y CONFIG_SND_SOC_ROCKCHIP_I2S_TDM_MULTI_LANES=y From 4a68fd57a9193949aabb198a57c747cc532c36f8 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Fri, 13 Oct 2023 17:15:44 +0800 Subject: [PATCH 07/18] ASoC: rk817: Fix L/R channel order The I2S part of RK817 work as slave mode require BCLK on first, otherwise, there will make the L/R invert. On the stage hw_params, the BCLK maybe off. so, let's move it into mute stage to fix this. Signed-off-by: Sugar Zhang Change-Id: I3b9a7030342281a596e16c025f42c49a79c3a5df --- sound/soc/codecs/rk817_codec.c | 31 ++++++++++++++++++++++++++++--- sound/soc/codecs/rk817_codec.h | 12 ++++++++++-- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/rk817_codec.c b/sound/soc/codecs/rk817_codec.c index ef065580c2af..8c767cec57ac 100644 --- a/sound/soc/codecs/rk817_codec.c +++ b/sound/soc/codecs/rk817_codec.c @@ -422,7 +422,7 @@ static int rk817_codec_power_up(struct snd_soc_component *component, int type) } snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, - ADC_DIG_CLK_MASK, DAC_DIG_CLK_DIS); + ADC_DIG_CLK_MASK, ADC_DIG_CLK_DIS); usleep_range(2000, 2500); snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, ADC_DIG_CLK_MASK, ADC_DIG_CLK_EN); @@ -1034,7 +1034,7 @@ static int rk817_hw_params(struct snd_pcm_substream *substream, return 0; } -static int rk817_digital_mute(struct snd_soc_dai *dai, int mute, int stream) +static int rk817_digital_mute_dac(struct snd_soc_dai *dai, int mute, int stream) { struct snd_soc_component *component = dai->component; struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component); @@ -1056,7 +1056,11 @@ static int rk817_digital_mute(struct snd_soc_dai *dai, int mute, int stream) DAC_DIG_CLK_EN, DAC_DIG_CLK_DIS); snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, DAC_DIG_CLK_EN, DAC_DIG_CLK_EN); + snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, + I2SRX_EN_MASK, I2SRX_DIS); } else { + snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, + I2SRX_EN_MASK, I2SRX_EN); snd_soc_component_update_bits(component, RK817_CODEC_DDAC_MUTE_MIXCTL, DACMT_ENABLE, DACMT_DISABLE); @@ -1106,6 +1110,28 @@ static int rk817_digital_mute(struct snd_soc_dai *dai, int mute, int stream) return 0; } +static int rk817_digital_mute_adc(struct snd_soc_dai *dai, int mute, int stream) +{ + struct snd_soc_component *component = dai->component; + + if (mute) + snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, + I2STX_EN_MASK, I2STX_DIS); + else + snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, + I2STX_EN_MASK, I2STX_EN); + + return 0; +} + +static int rk817_digital_mute(struct snd_soc_dai *dai, int mute, int stream) +{ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + return rk817_digital_mute_dac(dai, mute, stream); + else + return rk817_digital_mute_adc(dai, mute, stream); +} + #define RK817_PLAYBACK_RATES (SNDRV_PCM_RATE_8000 |\ SNDRV_PCM_RATE_16000 | \ SNDRV_PCM_RATE_32000 | \ @@ -1150,7 +1176,6 @@ static struct snd_soc_dai_ops rk817_dai_ops = { .set_sysclk = rk817_set_dai_sysclk, .mute_stream = rk817_digital_mute, .shutdown = rk817_codec_shutdown, - .no_capture_mute = 1, }; static struct snd_soc_dai_driver rk817_dai[] = { diff --git a/sound/soc/codecs/rk817_codec.h b/sound/soc/codecs/rk817_codec.h index c5df0af9a73c..89e095c871d3 100644 --- a/sound/soc/codecs/rk817_codec.h +++ b/sound/soc/codecs/rk817_codec.h @@ -81,7 +81,7 @@ #define ADC_DIG_CLK_MASK (0xf << 4) #define ADC_DIG_CLK_SFT 4 #define ADC_DIG_CLK_DIS (0x0 << 4) -#define ADC_DIG_CLK_EN (0xf << 4) +#define ADC_DIG_CLK_EN (0xe << 4) #define I2STX_CKE_EN (0x1 << 6) #define I2STX_CKE_DIS (0x0 << 6) @@ -89,7 +89,15 @@ #define DAC_DIG_CLK_MASK (0xf << 0) #define DAC_DIG_CLK_SFT 0 #define DAC_DIG_CLK_DIS (0x0 << 0) -#define DAC_DIG_CLK_EN (0xf << 0) +#define DAC_DIG_CLK_EN (0xe << 0) + +#define I2STX_EN_MASK BIT(4) +#define I2STX_EN BIT(4) +#define I2STX_DIS 0 + +#define I2SRX_EN_MASK BIT(0) +#define I2SRX_EN BIT(0) +#define I2SRX_DIS 0 /* RK817_CODEC_APLL_CFG5 */ #define PLL_PW_DOWN (0x01 << 0) From 3db715174191e0f8015b5763f8f30ca78bec5512 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Sun, 15 Oct 2023 11:26:26 +0800 Subject: [PATCH 08/18] ASoC: rockchip: i2s: Use component kcontrol API Fixes: a2d0c7f12f46 ("ASoC: rockchip: i2s: Use add_component_controls") Signed-off-by: Sugar Zhang Change-Id: I8343bf048cd3378e878286661a7c55c1255a532e --- sound/soc/rockchip/rockchip_i2s.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 5c85fefe81e7..f3f1f96d7007 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -572,8 +572,8 @@ static int rockchip_i2s_clk_compensation_info(struct snd_kcontrol *kcontrol, static int rockchip_i2s_clk_compensation_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); - struct rk_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai); + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); + struct rk_i2s_dev *i2s = snd_soc_component_get_drvdata(compnt); ucontrol->value.integer.value[0] = i2s->clk_ppm; @@ -583,8 +583,8 @@ static int rockchip_i2s_clk_compensation_get(struct snd_kcontrol *kcontrol, static int rockchip_i2s_clk_compensation_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); - struct rk_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai); + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); + struct rk_i2s_dev *i2s = snd_soc_component_get_drvdata(compnt); int ppm = ucontrol->value.integer.value[0]; if ((ucontrol->value.integer.value[0] < CLK_PPM_MIN) || From 6788651fa29ffa4dd18446c6728a535d3012214f Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Sun, 15 Oct 2023 11:26:28 +0800 Subject: [PATCH 09/18] ASoC: rockchip: i2s-tdm: Use component kcontrol API Fixes: f7cdb2cfcaa7 ("ASoC: rockchip: i2s-tdm: Use add_component_controls") Signed-off-by: Sugar Zhang Change-Id: I1abf9d698b12396694470017cc8f51e98d8ce2ce --- sound/soc/rockchip/rockchip_i2s_tdm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c index b9dfb70bbe93..6f93e76760b5 100644 --- a/sound/soc/rockchip/rockchip_i2s_tdm.c +++ b/sound/soc/rockchip/rockchip_i2s_tdm.c @@ -1817,8 +1817,8 @@ static int rockchip_i2s_tdm_clk_compensation_info(struct snd_kcontrol *kcontrol, static int rockchip_i2s_tdm_clk_compensation_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); - struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai); + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_component_get_drvdata(component); ucontrol->value.integer.value[0] = i2s_tdm->clk_ppm; @@ -1828,8 +1828,8 @@ static int rockchip_i2s_tdm_clk_compensation_get(struct snd_kcontrol *kcontrol, static int rockchip_i2s_tdm_clk_compensation_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); - struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai); + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_component_get_drvdata(component); int ret = 0, ppm = 0; if ((ucontrol->value.integer.value[0] < CLK_PPM_MIN) || From 06854ed129c23d8e6ac2efa3c9c505a6f1776e5a Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Sun, 15 Oct 2023 11:26:29 +0800 Subject: [PATCH 10/18] ASoC: rockchip: pdm: Use component kcontrol API Fixes: 5c77c0737df7 ("ASoC: rockchip: pdm: Use add_component_controls") Signed-off-by: Sugar Zhang Change-Id: I1a33435d112e1b8288fb4385dcd90261a579bb2d --- sound/soc/rockchip/rockchip_pdm.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c index 43c954d8e11c..86e804578eeb 100644 --- a/sound/soc/rockchip/rockchip_pdm.c +++ b/sound/soc/rockchip/rockchip_pdm.c @@ -508,8 +508,8 @@ static int rockchip_pdm_start_delay_info(struct snd_kcontrol *kcontrol, static int rockchip_pdm_start_delay_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); - struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai); + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rk_pdm_dev *pdm = snd_soc_component_get_drvdata(component); ucontrol->value.integer.value[0] = pdm->start_delay_ms; @@ -519,8 +519,8 @@ static int rockchip_pdm_start_delay_get(struct snd_kcontrol *kcontrol, static int rockchip_pdm_start_delay_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); - struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai); + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rk_pdm_dev *pdm = snd_soc_component_get_drvdata(component); if ((ucontrol->value.integer.value[0] < PDM_START_DELAY_MS_MIN) || (ucontrol->value.integer.value[0] > PDM_START_DELAY_MS_MAX)) @@ -546,8 +546,8 @@ static int rockchip_pdm_filter_delay_info(struct snd_kcontrol *kcontrol, static int rockchip_pdm_filter_delay_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); - struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai); + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rk_pdm_dev *pdm = snd_soc_component_get_drvdata(component); ucontrol->value.integer.value[0] = pdm->filter_delay_ms; @@ -557,8 +557,8 @@ static int rockchip_pdm_filter_delay_get(struct snd_kcontrol *kcontrol, static int rockchip_pdm_filter_delay_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); - struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai); + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rk_pdm_dev *pdm = snd_soc_component_get_drvdata(component); if ((ucontrol->value.integer.value[0] < PDM_FILTER_DELAY_MS_MIN) || (ucontrol->value.integer.value[0] > PDM_FILTER_DELAY_MS_MAX)) @@ -616,8 +616,8 @@ static int rockchip_pdm_clk_compensation_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); - struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai); + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rk_pdm_dev *pdm = snd_soc_component_get_drvdata(component); ucontrol->value.integer.value[0] = pdm->clk_ppm; @@ -627,8 +627,8 @@ static int rockchip_pdm_clk_compensation_get(struct snd_kcontrol *kcontrol, static int rockchip_pdm_clk_compensation_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); - struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai); + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rk_pdm_dev *pdm = snd_soc_component_get_drvdata(component); int ppm = ucontrol->value.integer.value[0]; From 04219ca7f0d6ec6557f4fca3d0ea79b54bb1e381 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Sun, 15 Oct 2023 11:26:31 +0800 Subject: [PATCH 11/18] ASoC: rockchip: pdm: Add support for HPF control This patch add support for HPF control that allow user to change HPF cut off freq or on/off HPF. Signed-off-by: Sugar Zhang Change-Id: I33c4ebe8499eabd0770f5454129391d3aea2e28d --- sound/soc/rockchip/rockchip_pdm.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c index 86e804578eeb..bb4f1e2504dd 100644 --- a/sound/soc/rockchip/rockchip_pdm.c +++ b/sound/soc/rockchip/rockchip_pdm.c @@ -577,12 +577,23 @@ static SOC_ENUM_SINGLE_DECL(rpath2_enum, PDM_CLK_CTRL, 12, rpaths_text); static SOC_ENUM_SINGLE_DECL(rpath1_enum, PDM_CLK_CTRL, 10, rpaths_text); static SOC_ENUM_SINGLE_DECL(rpath0_enum, PDM_CLK_CTRL, 8, rpaths_text); +static const char * const hpf_cutoff_text[] = { + "3.79Hz", "60Hz", "243Hz", "493Hz", +}; + +static SOC_ENUM_SINGLE_DECL(hpf_cutoff_enum, PDM_HPF_CTRL, + 0, hpf_cutoff_text); + static const struct snd_kcontrol_new rockchip_pdm_controls[] = { SOC_ENUM("Receive PATH3 Source Select", rpath3_enum), SOC_ENUM("Receive PATH2 Source Select", rpath2_enum), SOC_ENUM("Receive PATH1 Source Select", rpath1_enum), SOC_ENUM("Receive PATH0 Source Select", rpath0_enum), + SOC_ENUM("HPF Cutoff", hpf_cutoff_enum), + SOC_SINGLE("HPFL Switch", PDM_HPF_CTRL, 3, 1, 0), + SOC_SINGLE("HPFR Switch", PDM_HPF_CTRL, 2, 1, 0), + { .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = "PDM Start Delay Ms", From 873b86c8a45dc6cd66c7523d42562639cceabb40 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Sun, 15 Oct 2023 11:26:32 +0800 Subject: [PATCH 12/18] ASoC: rockchip: pdm: Add support for CLK-ALWAYS-ON quirks This patch add support for keeping PDM-CLK always on. Signed-off-by: Sugar Zhang Change-Id: Ibe5f660b52de6dba493a0046f89e4b2af1b379bb --- sound/soc/rockchip/rockchip_pdm.c | 44 +++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c index bb4f1e2504dd..ad5e8b706c2c 100644 --- a/sound/soc/rockchip/rockchip_pdm.c +++ b/sound/soc/rockchip/rockchip_pdm.c @@ -31,8 +31,10 @@ #define PDM_FILTER_DELAY_MS_MIN (20) #define PDM_FILTER_DELAY_MS_MAX (1000) #define PDM_CLK_SHIFT_PPM_MAX (1000000) /* 1 ppm */ -#define CLK_PPM_MIN (-1000) -#define CLK_PPM_MAX (1000) +#define CLK_PPM_MIN (-1000) +#define CLK_PPM_MAX (1000) + +#define QUIRK_ALWAYS_ON BIT(0) enum rk_pdm_version { RK_PDM_RK3229, @@ -56,6 +58,7 @@ struct rk_pdm_dev { enum rk_pdm_version version; unsigned int clk_root_rate; unsigned int clk_root_initial_rate; + unsigned int quirks; int clk_ppm; bool clk_calibrate; }; @@ -97,6 +100,16 @@ static struct rk_pdm_ds_ratio ds_ratio[] = { { 4, 8000 }, }; +static const struct pdm_of_quirks { + char *quirk; + int id; +} of_quirks[] = { + { + .quirk = "rockchip,always-on", + .id = QUIRK_ALWAYS_ON, + }, +}; + static unsigned int get_pdm_clk(struct rk_pdm_dev *pdm, unsigned int sr, unsigned int *clk_src, unsigned int *clk_out, unsigned int signoff) @@ -957,6 +970,29 @@ static int rockchip_pdm_path_parse(struct rk_pdm_dev *pdm, struct device_node *n return 0; } +static int rockchip_pdm_keep_clk_always_on(struct rk_pdm_dev *pdm) +{ + pm_runtime_forbid(pdm->dev); + + dev_info(pdm->dev, "CLK-ALWAYS-ON: samplerate: %d\n", PDM_DEFAULT_RATE); + + return 0; +} + +static int rockchip_pdm_parse_quirks(struct rk_pdm_dev *pdm) +{ + int ret = 0, i = 0; + + for (i = 0; i < ARRAY_SIZE(of_quirks); i++) + if (device_property_read_bool(pdm->dev, of_quirks[i].quirk)) + pdm->quirks |= of_quirks[i].id; + + if (pdm->quirks & QUIRK_ALWAYS_ON) + ret = rockchip_pdm_keep_clk_always_on(pdm); + + return ret; +} + static int rockchip_pdm_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -1038,6 +1074,10 @@ static int rockchip_pdm_probe(struct platform_device *pdev) if (ret != 0 && ret != -ENOENT) goto err_clk; + ret = rockchip_pdm_parse_quirks(pdm); + if (ret) + goto err_clk; + /* * MUST: after pm_runtime_enable step, any register R/W * should be wrapped with pm_runtime_get_sync/put. From a5edbe8c9352076260a16cbc2ff4f7d29bffa086 Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Tue, 10 Oct 2023 10:31:15 +0800 Subject: [PATCH 13/18] mfd: rxk110_x120: support power supply config Signed-off-by: Zhang Yubing Change-Id: I9f01bf6f4a6fd209aa01d9f41481df57bb83f7b6 --- drivers/mfd/rkx110_x120/rkx110_x120.h | 1 + drivers/mfd/rkx110_x120/rkx110_x120_core.c | 46 +++++++++++++++++----- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/drivers/mfd/rkx110_x120/rkx110_x120.h b/drivers/mfd/rkx110_x120/rkx110_x120.h index 67c2d1fe349d..545cb5b6f044 100644 --- a/drivers/mfd/rkx110_x120/rkx110_x120.h +++ b/drivers/mfd/rkx110_x120/rkx110_x120.h @@ -259,6 +259,7 @@ struct rk_serdes_pt { struct rk_serdes { struct device *dev; struct rk_serdes_chip chip[DEVICE_MAX]; + struct regulator *supply; struct gpio_desc *reset; struct gpio_desc *enable; diff --git a/drivers/mfd/rkx110_x120/rkx110_x120_core.c b/drivers/mfd/rkx110_x120/rkx110_x120_core.c index 2510e652eb4c..5852a4577541 100644 --- a/drivers/mfd/rkx110_x120/rkx110_x120_core.c +++ b/drivers/mfd/rkx110_x120/rkx110_x120_core.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "rkx110_x120.h" #include "rkx110_reg.h" @@ -988,6 +989,16 @@ static int rk_serdes_i2c_probe(struct i2c_client *client, const struct i2c_devic serdes->rate = RATE_2GBPS_83M; + serdes->supply = devm_regulator_get_optional(dev, "power"); + if (IS_ERR(serdes->supply)) { + ret = PTR_ERR(serdes->supply); + + if (ret != -ENODEV) + return dev_err_probe(dev, ret, "failed to request regulator\n"); + + serdes->supply = NULL; + } + serdes->enable = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW); if (IS_ERR(serdes->enable)) { ret = PTR_ERR(serdes->enable); @@ -1002,12 +1013,6 @@ static int rk_serdes_i2c_probe(struct i2c_client *client, const struct i2c_devic return ret; } - gpiod_set_value(serdes->enable, 1); - - gpiod_set_value(serdes->reset, 1); - usleep_range(10000, 11000); - gpiod_set_value(serdes->reset, 0); - if (of_get_child_by_name(dev->of_node, "serdes-panel")) { serdes->stream_type = STREAM_DISPLAY; of_node_put(dev->of_node); @@ -1021,8 +1026,6 @@ static int rk_serdes_i2c_probe(struct i2c_client *client, const struct i2c_devic if (ret) return ret; - msleep(20); - ret = mfd_add_devices(dev, -1, rkx110_x120_devs, ARRAY_SIZE(rkx110_x120_devs), NULL, 0, NULL); if (ret) { @@ -1030,13 +1033,29 @@ static int rk_serdes_i2c_probe(struct i2c_client *client, const struct i2c_devic return ret; } + if (serdes->supply) { + ret = regulator_enable(serdes->supply); + if (ret < 0) { + dev_err(serdes->dev, "failed to enable supply: %d\n", ret); + return ret; + } + } + + gpiod_set_value(serdes->enable, 1); + + gpiod_set_value(serdes->reset, 1); + usleep_range(10000, 11000); + gpiod_set_value(serdes->reset, 0); + + msleep(20); + rk_serdes_wait_link_ready(serdes); rk_serdes_read_chip_id(serdes); ret = rk_serdes_add_hwclk(serdes); if (ret < 0) - return ret; + goto err; rk_serdes_set_rate(serdes, RATE_4GBPS_83M); rk_serdes_pinctrl_init(serdes); @@ -1045,12 +1064,21 @@ out: rk_serdes_debugfs_init(serdes); return 0; + +err: + if (serdes->supply) + ret = regulator_disable(serdes->supply); + + return ret; } static int rk_serdes_i2c_remove(struct i2c_client *client) { struct rk_serdes *rk_serdes = i2c_get_clientdata(client); + if (rk_serdes->supply) + regulator_disable(rk_serdes->supply); + mfd_remove_devices(rk_serdes->dev); return 0; From 4c81ca1ac53e4101b32cfad10b81eb5cbd09c93c Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Tue, 13 Jun 2023 09:09:54 +0800 Subject: [PATCH 14/18] mfd: rkx110_x120: change video packet length The serdes version 1 have a bug when enable video suspend function, which is target to enhance the i2c frequency when transfer video stream. In order to enhance i2c frequency as far as possible, a workaround ways is provided to do this thing, which is to reduce the video packet length. the formula as follow: length = ((hactive x 24 / 32 / 16) + 15) / 16 * 16 It should be noted that reducing video packet length will consume more link bandwidth. Signed-off-by: Zhang Yubing Change-Id: I23b679ec12ff3e2801bfb13cc1836094b6fd4ff9 --- drivers/mfd/rkx110_x120/rkx110_linktx.c | 14 ++++++++++++++ drivers/mfd/rkx110_x120/rkx120_linkrx.c | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/drivers/mfd/rkx110_x120/rkx110_linktx.c b/drivers/mfd/rkx110_x120/rkx110_linktx.c index 007a825ab19e..59135a990deb 100644 --- a/drivers/mfd/rkx110_x120/rkx110_linktx.c +++ b/drivers/mfd/rkx110_x120/rkx110_linktx.c @@ -428,9 +428,11 @@ static int rk_serdes_link_tx_ctrl_enable(struct rk_serdes *serdes, { struct hwclk *hwclk = serdes->chip[remote_id].hwclk; struct i2c_client *client; + struct videomode *vm = &route->vm; u32 ctrl_val, val; u32 rx_src; u32 stream_type; + u32 length; if (route->stream_type == STREAM_DISPLAY) { client = serdes->chip[DEVICE_LOCAL].client; @@ -459,6 +461,18 @@ static int rk_serdes_link_tx_ctrl_enable(struct rk_serdes *serdes, serdes->i2c_read_reg(client, RKLINK_TX_VIDEO_CTRL, &val); rx_src = rk_serdes_get_stream_source(serdes, route->local_port0); val |= rx_src; + if (serdes->version == SERDES_V1) { + /* + * The serdes v1 have a bug when enable video suspend function, which + * is used to enhance the i2c frequency. A workaround ways to do it is + * reducing the video packet length: + * length = ((hactive x 24 / 32 / 16) + 15) / 16 * 16 + */ + length = vm->hactive * 24 / 32 / 16; + length = (length + 15) / 16 * 16; + val &= ~VIDEO_REPKT_LENGTH(0xffff); + val |= VIDEO_REPKT_LENGTH(length); + } serdes->i2c_write_reg(client, RKLINK_TX_VIDEO_CTRL, val); if (route->local_port0 & RK_SERDES_DUAL_LVDS_RX) { diff --git a/drivers/mfd/rkx110_x120/rkx120_linkrx.c b/drivers/mfd/rkx110_x120/rkx120_linkrx.c index 45d965b077be..bae51fdb0cc6 100644 --- a/drivers/mfd/rkx110_x120/rkx120_linkrx.c +++ b/drivers/mfd/rkx110_x120/rkx120_linkrx.c @@ -104,6 +104,9 @@ #define LANE0_LANE_ID(x) UPDATE(x, 1, 1) #define LNAE0_ID_SEL(x) UPDATE(x, 0, 0) +#define DES_RKLINK_REC01_PKT_LENGTH LINK_REG(0x0028) +#define E1_REPKT_LENGTH(x) UPDATE(x, 29, 16) +#define E0_REPKT_LENGTH(x) UPDATE(x, 13, 0) #define RKLINK_DES_REG01_ENGIN_DEL 0x0030 #define E1_ENGINE_DELAY(x) UPDATE(x, 31, 16) #define E0_ENGINE_DELAY(x) UPDATE(x, 15, 0) @@ -476,12 +479,14 @@ static int rk120_link_rx_cfg(struct rk_serdes *serdes, struct rk_serdes_route *r { struct hwclk *hwclk = serdes->chip[remote_id].hwclk; struct i2c_client *client; + struct videomode *vm = &route->vm; u32 stream_type; u32 rx_src; u32 ctrl_val, mask, val; u32 lane0_dsource_id, lane1_dsource_id; bool is_rx_dual_lanes; bool is_rx_dual_channels; + u32 length; if (route->stream_type == STREAM_DISPLAY) { client = serdes->chip[remote_id].client; @@ -530,6 +535,19 @@ static int rk120_link_rx_cfg(struct rk_serdes *serdes, struct rk_serdes_route *r serdes->i2c_update_bits(client, RKLINK_DES_LANE_ENGINE_DST, mask, val); + if (serdes->version == SERDES_V1) { + /* + * The serdes v1 have a bug when enable video suspend function, which + * is used to enhance the i2c frequency. A workaround ways to do it is + * reducing the video packet length: + * length = ((hactive x 24 / 32 / 16) + 15) / 16 * 16 + */ + length = vm->hactive * 24 / 32 / 16; + length = (length + 15) / 16 * 16; + serdes->i2c_write_reg(client, DES_RKLINK_REC01_PKT_LENGTH, E0_REPKT_LENGTH(length) | + E1_REPKT_LENGTH(length)); + } + serdes->i2c_read_reg(client, RKLINK_DES_SOURCE_CFG, &val); val &= ~(LANE0_ENGINE_ID(1) | LANE0_LANE_ID(1) | LANE1_ENGINE_ID(1) | From ff6f7a123929fea5fbb96baca9e24e3fbd695ffc Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Fri, 4 Aug 2023 09:36:58 +0800 Subject: [PATCH 15/18] drm/rockchip: dsi2: support disable hold mode in cmd mode when dsi controller work in cmd mode, it will tell vop work in hold mode and must config te signal for vop. when rk3588 dsi interface connect to rkx111 and work in cmd mode, rkx111 will not provided a te signal, so it need disable hold mode and transfer this config to vop. Signed-off-by: Zhang Yubing Change-Id: I2044ee882bee4be896dc65b9fcf6d502d56661df --- drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c index 46ace54ebab8..05f38f14c0b8 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c @@ -246,6 +246,7 @@ struct dw_mipi_dsi2 { struct phy *dcphy; union phy_configure_opts phy_opts; + bool disable_hold_mode; bool c_option; bool scrambling_en; unsigned int slice_width; @@ -954,7 +955,7 @@ dw_mipi_dsi2_encoder_atomic_check(struct drm_encoder *encoder, if (!(dsi2->mode_flags & MIPI_DSI_MODE_VIDEO)) { s->output_flags |= ROCKCHIP_OUTPUT_MIPI_DS_MODE; s->soft_te = dsi2->te_gpio ? true : false; - s->hold_mode = true; + s->hold_mode = dsi2->disable_hold_mode ? false : true; } if (dsi2->slave) { @@ -1639,6 +1640,9 @@ static int dw_mipi_dsi2_probe(struct platform_device *pdev) dsi2->pdata = of_device_get_match_data(dev); platform_set_drvdata(pdev, dsi2); + if (device_property_read_bool(dev, "disable-hold-mode")) + dsi2->disable_hold_mode = true; + if (device_property_read_bool(dev, "dual-connector-split")) { dsi2->dual_connector_split = true; From d2b9f748b87cd9e47cc721dad5671c4573470c8c Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Wed, 18 Oct 2023 17:45:41 +0800 Subject: [PATCH 16/18] mfd: rkx110_x120: fix dereference the error device node Signed-off-by: Zhang Yubing Change-Id: If37226812da4197413bd30154d194539b13b123e --- drivers/mfd/rkx110_x120/rkx110_x120_core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/rkx110_x120/rkx110_x120_core.c b/drivers/mfd/rkx110_x120/rkx110_x120_core.c index 5852a4577541..5087ae472a91 100644 --- a/drivers/mfd/rkx110_x120/rkx110_x120_core.c +++ b/drivers/mfd/rkx110_x120/rkx110_x120_core.c @@ -959,6 +959,7 @@ static int rk_serdes_pinctrl_init(struct rk_serdes *serdes) static int rk_serdes_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device *dev = &client->dev; + struct device_node *disp_np; struct rk_serdes *serdes; int ret; @@ -1013,9 +1014,10 @@ static int rk_serdes_i2c_probe(struct i2c_client *client, const struct i2c_devic return ret; } - if (of_get_child_by_name(dev->of_node, "serdes-panel")) { + disp_np = of_get_child_by_name(dev->of_node, "serdes-panel"); + if (disp_np) { serdes->stream_type = STREAM_DISPLAY; - of_node_put(dev->of_node); + of_node_put(disp_np); dev_info(dev, "serdes display stream"); } else { serdes->stream_type = STREAM_CAMERA; From 42c10d6d16bfbfed016f15c1d78db152f6a7cf12 Mon Sep 17 00:00:00 2001 From: Cai Wenzhong Date: Wed, 18 Oct 2023 10:09:50 +0800 Subject: [PATCH 17/18] arm64: dts: rockchip: rk3588-vehicle-evb-maxim-max96712-dcphy0(/1): adjust Txphy DPLL Signed-off-by: Cai Wenzhong Change-Id: Ibedf1ca0143288e03ee12eced32f92a6f753de11 --- .../dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy0.dtsi | 2 +- .../dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy1.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy0.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy0.dtsi index 85007840d55a..1f9af40db207 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy0.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy0.dtsi @@ -127,7 +127,7 @@ max-fps-numerator = <10000>; max-fps-denominator = <300000>; bpp = <16>; - link-freq-idx = <12>; + link-freq-idx = <24>; vc-array = <0x10 0x20 0x40 0x80>; // VC0~3: bit4~7 }; /* support mode config end */ diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy1.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy1.dtsi index 9c7b3c7a4677..d7a0a2f46011 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy1.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy1.dtsi @@ -127,7 +127,7 @@ max-fps-numerator = <10000>; max-fps-denominator = <300000>; bpp = <16>; - link-freq-idx = <20>; + link-freq-idx = <24>; vc-array = <0x10 0x20 0x40 0x80>; // VC0~3: bit4~7 }; /* support mode config end */ From 1d32cf5ad0ef75fd639b1cf4061d736d099b9ef5 Mon Sep 17 00:00:00 2001 From: Cody Xie Date: Thu, 12 Oct 2023 15:24:15 +0800 Subject: [PATCH 18/18] media: i2c: maxim4c: MIPI VC count does not affected by data lane count Change-Id: I56938bf429e6b64287aa47acd5c77823c108f18b Signed-off-by: Cody Xie --- drivers/media/i2c/maxim4c/maxim4c_drv.c | 5 +++-- drivers/media/i2c/maxim4c/maxim4c_v4l2.c | 18 +++--------------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/drivers/media/i2c/maxim4c/maxim4c_drv.c b/drivers/media/i2c/maxim4c/maxim4c_drv.c index 9d9df08b4dbd..65650eeb5387 100644 --- a/drivers/media/i2c/maxim4c/maxim4c_drv.c +++ b/drivers/media/i2c/maxim4c/maxim4c_drv.c @@ -29,12 +29,13 @@ * V2.03.00 * 1. remote device add the maxim4c prefix to driver name. * - * V2.04.03 + * V2.04.04 * 1. Add regulator supplier dependencies. * 2. Add config ssc-ratio property * 3. Add debugfs entry to change MIPI timing * 4. Use PM runtime autosuspend feature * 5. Fix unbalanced disabling for PoC regulator + * 6. MIPI VC count does not affected by data lane count * */ #include @@ -65,7 +66,7 @@ #include "maxim4c_api.h" -#define DRIVER_VERSION KERNEL_VERSION(2, 0x04, 0x03) +#define DRIVER_VERSION KERNEL_VERSION(2, 0x04, 0x04) #define MAXIM4C_XVCLK_FREQ 25000000 diff --git a/drivers/media/i2c/maxim4c/maxim4c_v4l2.c b/drivers/media/i2c/maxim4c/maxim4c_v4l2.c index b40fdf2b3632..a331023da0d4 100644 --- a/drivers/media/i2c/maxim4c/maxim4c_v4l2.c +++ b/drivers/media/i2c/maxim4c/maxim4c_v4l2.c @@ -786,21 +786,9 @@ static int maxim4c_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad, val |= V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; val |= (1 << (data_lanes - 1)); - switch (data_lanes) { - case 4: - val |= V4L2_MBUS_CSI2_CHANNEL_3; - fallthrough; - case 3: - val |= V4L2_MBUS_CSI2_CHANNEL_2; - fallthrough; - case 2: - val |= V4L2_MBUS_CSI2_CHANNEL_1; - fallthrough; - case 1: - default: - val |= V4L2_MBUS_CSI2_CHANNEL_0; - break; - } + + val |= V4L2_MBUS_CSI2_CHANNEL_3 | V4L2_MBUS_CSI2_CHANNEL_2 | + V4L2_MBUS_CSI2_CHANNEL_1 | V4L2_MBUS_CSI2_CHANNEL_0; config->type = V4L2_MBUS_CSI2_DPHY; config->flags = val;