diff --git a/Documentation/devicetree/bindings/sound/rockchip,multicodecs.txt b/Documentation/devicetree/bindings/sound/rockchip,multicodecs.txt index 5db94c347663..51bc058471ea 100644 --- a/Documentation/devicetree/bindings/sound/rockchip,multicodecs.txt +++ b/Documentation/devicetree/bindings/sound/rockchip,multicodecs.txt @@ -35,9 +35,15 @@ Optional dai-link subnode properties: dai-link uses bit clock inversion. - rockchip,frame-inversion : bool property. Add this if the dai-link uses frame clock inversion. -- rockchip,mclk-fs : Multiplication factor between stream +- rockchip,mclk-fs : Multiplication factor between stream rate and codec mclk, applied only for the dai-link. +- rockchip,mclk-fs-mapping : u32 properties. Multiplication factor + between steam rate and codec mclk, + these values will overwrite the mclk-fs. + mclk-fs-mapping = <256 1024> means: + (mclk of first codec) = 256 * fs, + (mclk of second codec) = 1024 * fs. Example: @@ -86,3 +92,41 @@ es8388_sound: es8388-sound { press-threshold-microvolt = <2000>; }; }; + +Example 3 for rockchip,mclk-fs-mapping: + +sai_dais: sai-dais { + status = "okay"; + compatible = "rockchip,multi-dais"; + dais = <&sai1>, <&sai4>; + capture,channel-mapping = <2 2>; + playback,channel-mapping = <2 0>; + bitclock-inversion = <0 0>; + mclk-fs-mapping = <256 1024>; +}; + +es8388_sound: es8388-sound { + status = "okay"; + compatible = "rockchip,multicodecs-card"; + rockchip,card-name = "rockchip-es8388"; + spk-con-gpio = <&gpio1 RK_PC6 GPIO_ACTIVE_HIGH>; + rockchip,pre-power-on-delay-ms = <30>; + rockchip,post-power-down-delay-ms = <40>; + rockchip,format = "i2s"; + rockchip,cpu = <&sai_dais>; + rockchip,codec = <&es8388>, <&audio_codec>; + rockchip,mclk-fs = <256>; + rockchip,mclk-fs-mapping = <256 1024>; + rockchip,audio-routing = + "Speaker", "LOUT1", + "Speaker", "ROUT1", + "Speaker", "Speaker Power", + "Speaker", "Speaker Power", + "LINPUT1", "Main Mic", + "LINPUT2", "Main Mic", + "RINPUT1", "Main Mic", + "RINPUT2", "Main Mic"; + pinctrl-names = "default"; + pinctrl-0 = <&spk_ctrl>; +}; + diff --git a/Documentation/devicetree/bindings/sound/rockchip,multidais.txt b/Documentation/devicetree/bindings/sound/rockchip,multidais.txt index f1aafcf929fc..ee38620b1557 100644 --- a/Documentation/devicetree/bindings/sound/rockchip,multidais.txt +++ b/Documentation/devicetree/bindings/sound/rockchip,multidais.txt @@ -19,6 +19,11 @@ Optional properties: - bitclock-master: bool properties, bit clock master, one for each in dais. - bitclock-inversion: bool properties, bit clock inversion, one for each in dais. - frame-inversion: bool properties, frame clock inversion, one for each in dais. +- mclk-fs-mapping: u32 properties, multiplication factor between stream + rate and codec mclk, one for each in dais. + mclk-fs-mapping = <256 1024> means: + (mclk of first dai) = 256 * fs, + (mclk of second dai) = 1024 * fs. Example: @@ -52,3 +57,41 @@ vad-sound { rockchip,cpu = <&multi_dais>; rockchip,codec = <&acodec>, <&vad>; }; + +Example 2 for mclk-fs-mapping: + +sai_dais: sai-dais { + status = "okay"; + compatible = "rockchip,multi-dais"; + dais = <&sai1>, <&sai4>; + capture,channel-mapping = <2 2>; + playback,channel-mapping = <2 0>; + bitclock-inversion = <0 0>; + mclk-fs-mapping = <256 1024>; +}; + +es8388_sound: es8388-sound { + status = "okay"; + compatible = "rockchip,multicodecs-card"; + rockchip,card-name = "rockchip-es8388"; + spk-con-gpio = <&gpio1 RK_PC6 GPIO_ACTIVE_HIGH>; + rockchip,pre-power-on-delay-ms = <30>; + rockchip,post-power-down-delay-ms = <40>; + rockchip,format = "i2s"; + rockchip,cpu = <&sai_dais>; + rockchip,codec = <&es8388>, <&audio_codec>; + rockchip,mclk-fs = <256>; + rockchip,mclk-fs-mapping = <256 1024>; + rockchip,audio-routing = + "Speaker", "LOUT1", + "Speaker", "ROUT1", + "Speaker", "Speaker Power", + "Speaker", "Speaker Power", + "LINPUT1", "Main Mic", + "LINPUT2", "Main Mic", + "RINPUT1", "Main Mic", + "RINPUT2", "Main Mic"; + pinctrl-names = "default"; + pinctrl-0 = <&spk_ctrl>; +}; + diff --git a/arch/arm/boot/dts/rk3502-evb1-v10.dtsi b/arch/arm/boot/dts/rk3502-evb1-v10.dtsi index c789d3c966de..51bb81b69aa1 100644 --- a/arch/arm/boot/dts/rk3502-evb1-v10.dtsi +++ b/arch/arm/boot/dts/rk3502-evb1-v10.dtsi @@ -427,11 +427,15 @@ }; &sai1 { - pinctrl-names = "default"; + pinctrl-names = "default", "sleep"; pinctrl-0 = <&rm_io9_sai1_sclk &rm_io10_sai1_lrck &rm_io11_sai1_sdi &rm_io12_sai1_sdo0>; + pinctrl-1 = <&rm_io9_idle_pins + &rm_io10_idle_pins + &rm_io11_idle_pins + &rm_io12_idle_pins>; }; &sai4 { diff --git a/arch/arm/boot/dts/rk3506-pinctrl.dtsi b/arch/arm/boot/dts/rk3506-pinctrl.dtsi index fcf918370ea6..0da9f08b27f1 100644 --- a/arch/arm/boot/dts/rk3506-pinctrl.dtsi +++ b/arch/arm/boot/dts/rk3506-pinctrl.dtsi @@ -1385,6 +1385,29 @@ }; }; + rm_io_idle { + /omit-if-no-ref/ + rm_io9_idle_pins: rm-io9-idle-pins { + rockchip,pins = + <0 RK_PB1 RK_FUNC_GPIO &pcfg_input_enable_pull_down>; + }; + /omit-if-no-ref/ + rm_io10_idle_pins: rm-io10-idle-pins { + rockchip,pins = + <0 RK_PB2 RK_FUNC_GPIO &pcfg_input_enable_pull_down>; + }; + /omit-if-no-ref/ + rm_io11_idle_pins: rm-io11-idle-pins { + rockchip,pins = + <0 RK_PB3 RK_FUNC_GPIO &pcfg_input_enable_pull_down>; + }; + /omit-if-no-ref/ + rm_io12_idle_pins: rm-io12-idle-pins { + rockchip,pins = + <0 RK_PB4 RK_FUNC_GPIO &pcfg_input_enable_pull_down>; + }; + }; + vo_lcdc { /omit-if-no-ref/ bt1120_pins: bt1120-pins { diff --git a/arch/arm/boot/dts/rk3506g-demo-display-control.dts b/arch/arm/boot/dts/rk3506g-demo-display-control.dts index 2d50527ae23a..585739483ce0 100644 --- a/arch/arm/boot/dts/rk3506g-demo-display-control.dts +++ b/arch/arm/boot/dts/rk3506g-demo-display-control.dts @@ -143,8 +143,9 @@ rockchip,post-power-down-delay-ms = <40>; rockchip,format = "i2s"; rockchip,mclk-fs = <256>; - rockchip,cpu = <&sai1>; - rockchip,codec = <&rk730>; + rockchip,mclk-fs-mapping = <256 1024>; + rockchip,cpu = <&sai_dais>; + rockchip,codec = <&rk730>, <&audio_codec>; rockchip,audio-routing = "Headphone", "LOUT1", "Headphone", "ROUT1", @@ -158,6 +159,15 @@ "MIC1", "Headset Mic"; }; + sai_dais: sai-dais { + status = "okay"; + compatible = "rockchip,multi-dais"; + dais = <&sai1>, <&sai4>; + capture,channel-mapping = <2 2>; + playback,channel-mapping = <2 0>; + mclk-fs-mapping = <256 1024>; + }; + sdio_pwrseq: sdio-pwrseq { compatible = "mmc-pwrseq-simple"; pinctrl-names = "default"; @@ -223,6 +233,10 @@ }; }; +&audio_codec { + status = "okay"; +}; + &can0 { assigned-clocks = <&cru CLK_CAN0>; assigned-clock-rates = <300000000>; @@ -584,6 +598,10 @@ &rm_io12_sai1_sdo0>; }; +&sai4 { + status = "okay"; +}; + &saradc { vref-supply = <&vcc_1v8>; status = "okay"; diff --git a/arch/arm/boot/dts/rk3506g-evb1-v10.dts b/arch/arm/boot/dts/rk3506g-evb1-v10.dts index 2f19e89ee2e8..847373c24e13 100644 --- a/arch/arm/boot/dts/rk3506g-evb1-v10.dts +++ b/arch/arm/boot/dts/rk3506g-evb1-v10.dts @@ -20,6 +20,15 @@ status = "okay"; }; + sai_dais: sai-dais { + status = "okay"; + compatible = "rockchip,multi-dais"; + dais = <&sai1>, <&sai4>; + capture,channel-mapping = <2 2>; + playback,channel-mapping = <2 0>; + mclk-fs-mapping = <256 1024>; + }; + vcc3v3_lcd_n: vcc3v3-lcd0-n { compatible = "regulator-fixed"; enable-active-high; @@ -58,6 +67,10 @@ }; }; +&acodec_sound { + status = "disabled"; +}; + &cma { size = <0x1600000>; }; @@ -84,6 +97,9 @@ &es8388_sound { status = "okay"; + rockchip,cpu = <&sai_dais>; + rockchip,codec = <&es8388>, <&audio_codec>; + rockchip,mclk-fs-mapping = <256 1024>; }; >1x { diff --git a/arch/arm/boot/dts/rockchip-pinconf.dtsi b/arch/arm/boot/dts/rockchip-pinconf.dtsi index fc0145333257..ca3b313c4d28 100644 --- a/arch/arm/boot/dts/rockchip-pinconf.dtsi +++ b/arch/arm/boot/dts/rockchip-pinconf.dtsi @@ -333,6 +333,12 @@ input-schmitt-enable; }; + /omit-if-no-ref/ + pcfg_input_enable_pull_down: pcfg-input-enable-pull-down { + input-enable; + bias-pull-down; + }; + /omit-if-no-ref/ pcfg_output_high: pcfg-output-high { output-high; diff --git a/arch/arm/configs/rk3506-display.config b/arch/arm/configs/rk3506-display.config index 529edaaac1cd..36985c54945c 100644 --- a/arch/arm/configs/rk3506-display.config +++ b/arch/arm/configs/rk3506-display.config @@ -221,6 +221,7 @@ CONFIG_MEDIA_SUPPORT_FILTER=y # CONFIG_ROCKCHIP_DW_HDCP2 is not set # CONFIG_ROCKCHIP_DW_HDMI is not set CONFIG_ROCKCHIP_DW_MIPI_DSI=y +# CONFIG_ROCKCHIP_DW_MIPI_DSI2 is not set CONFIG_ROCKCHIP_FLEXBUS_CIF=y CONFIG_ROCKCHIP_FLEXBUS_CIF_USE_DUMMY_BUF=y # CONFIG_ROCKCHIP_FLEXBUS_CIF_USE_NONE_DUMMY_BUF is not set diff --git a/drivers/clk/rockchip/clk-rk3568.c b/drivers/clk/rockchip/clk-rk3568.c index d0a90b1a614c..2545a4fbdc10 100644 --- a/drivers/clk/rockchip/clk-rk3568.c +++ b/drivers/clk/rockchip/clk-rk3568.c @@ -1626,8 +1626,6 @@ static void rk3568_dump_cru(void) } static int protect_clocks[] = { - CLK_PWM0, - PCLK_PWM0, CLK_PWM1, PCLK_PWM1, CLK_PWM2, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index 28c9e7e27732..4439ae144306 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -33,6 +33,11 @@ struct page_info { #define PG_ROUND 8 +#define FAIL_LIMIT 3 +static u64 fail_count; +static u64 fail_iova = U64_MAX; +static u64 fail_time; + static int rockchip_gem_iommu_map(struct rockchip_gem_object *rk_obj) { struct drm_device *drm = rk_obj->base.dev; @@ -40,6 +45,7 @@ static int rockchip_gem_iommu_map(struct rockchip_gem_object *rk_obj) int prot = IOMMU_READ | IOMMU_WRITE; ssize_t ret; +retry: mutex_lock(&private->mm_lock); ret = drm_mm_insert_node_generic(&private->mm, &rk_obj->mm, rk_obj->base.size, PAGE_SIZE, @@ -56,15 +62,31 @@ static int rockchip_gem_iommu_map(struct rockchip_gem_object *rk_obj) rockchip_drm_dbg(drm->dev, VOP_DEBUG_IOMMU_MAP, "iommu map: iova: %pad size: 0x%zx", &rk_obj->dma_addr, rk_obj->base.size); + if (fail_iova == U64_MAX) + fail_iova = rk_obj->dma_addr; + ret = iommu_map_sgtable(private->domain, rk_obj->dma_addr, rk_obj->sgt, prot); if (ret < (ssize_t)rk_obj->base.size) { DRM_ERROR("failed to map buffer: size=%zd request_size=%zd\n", ret, rk_obj->base.size); ret = -ENOMEM; + if (rk_obj->dma_addr == fail_iova) { + if (++fail_count >= FAIL_LIMIT) { + DRM_ERROR("IOVA:%pad map failed, retry other, retried:%lld\n", + &rk_obj->dma_addr, ++fail_time); + fail_count = 0; + fail_iova = U64_MAX; + goto retry; + } + } goto err_remove_node; } + fail_count = 0; + fail_iova = U64_MAX; + fail_time = 0; + iommu_flush_iotlb_all(private->domain); rk_obj->size = ret; diff --git a/sound/soc/codecs/rk3506_codec.c b/sound/soc/codecs/rk3506_codec.c index 02172c6dbd86..44bbb7c89906 100644 --- a/sound/soc/codecs/rk3506_codec.c +++ b/sound/soc/codecs/rk3506_codec.c @@ -211,6 +211,9 @@ static int rk3506_hw_params(struct snd_pcm_substream *substream, unsigned int width, rate; int ratio; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return 0; + if ((params_rate(params) % 12000) == 0) { clk_set_rate(rk3506->mclk, MCLK_REFERENCE_12000); ratio = MCLK_REFERENCE_12000 / MCLK_I2S_REFERENCE_DIV / @@ -283,6 +286,9 @@ static void rk3506_pcm_shutdown(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct rk3506_codec_priv *rk3506 = snd_soc_component_get_drvdata(component); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return; + rk3506_codec_capture_off(component); regcache_cache_only(rk3506->regmap, false); regcache_sync(rk3506->regmap); diff --git a/sound/soc/rockchip/rockchip_multi_dais.c b/sound/soc/rockchip/rockchip_multi_dais.c index d3dffb45b98b..ce085ed175b7 100644 --- a/sound/soc/rockchip/rockchip_multi_dais.c +++ b/sound/soc/rockchip/rockchip_multi_dais.c @@ -58,6 +58,7 @@ static int rockchip_mdais_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *cparams; struct snd_soc_dai *child; unsigned int *channel_maps; + unsigned int freq; int ret = 0, i = 0; cparams = kmemdup(params, sizeof(*params), GFP_KERNEL); @@ -71,6 +72,16 @@ static int rockchip_mdais_hw_params(struct snd_pcm_substream *substream, if (!channel_maps[i]) continue; + if (mdais->mclk_fs_maps[i] > 0) { + freq = params_rate(params) * mdais->mclk_fs_maps[i]; + ret = snd_soc_dai_set_sysclk(child, substream->stream, freq, + SND_SOC_CLOCK_OUT); + if (ret && ret != -ENOTSUPP) { + dev_err(dai->dev, "Set sysclk(%uHZ) failed: %d\n", freq, ret); + break; + } + } + hw_refine_channels(cparams, channel_maps[i]); if (child->driver->ops && child->driver->ops->hw_params) { ret = child->driver->ops->hw_params(substream, cparams, child); @@ -219,9 +230,13 @@ static int rockchip_mdais_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, for (i = 0; i < mdais->num_dais; i++) { child = mdais->dais[i].dai; + if (mdais->mclk_fs_maps[i] > 0) + continue; ret = snd_soc_dai_set_sysclk(child, clk_id, freq, dir); - if (ret && ret != -ENOTSUPP) + if (ret && ret != -ENOTSUPP) { + dev_err(cpu_dai->dev, "Set soc_dai sysclk(%uHZ) failed: %d\n", freq, ret); return ret; + } } return 0; @@ -565,6 +580,15 @@ static int rockchip_mdais_probe(struct platform_device *pdev) if (ret) return -EINVAL; mdais->playback_channel_maps = map; + map = devm_kcalloc(&pdev->dev, count, + sizeof(*map), GFP_KERNEL); + if (!map) + return -ENOMEM; + ret = of_property_read_u32_array(np, "mclk-fs-mapping", + map, count); + if (ret) + memset(map, 0x0, sizeof(*map) * count); + mdais->mclk_fs_maps = map; for (i = 0; i < count; i++) { node = of_parse_phandle(np, "dais", i); diff --git a/sound/soc/rockchip/rockchip_multi_dais.h b/sound/soc/rockchip/rockchip_multi_dais.h index c0a8ef3e4845..9320366c98e3 100644 --- a/sound/soc/rockchip/rockchip_multi_dais.h +++ b/sound/soc/rockchip/rockchip_multi_dais.h @@ -25,6 +25,7 @@ struct rk_mdais_dev { struct rk_dai *dais; unsigned int *playback_channel_maps; unsigned int *capture_channel_maps; + unsigned int *mclk_fs_maps; int num_dais; }; diff --git a/sound/soc/rockchip/rockchip_multicodecs.c b/sound/soc/rockchip/rockchip_multicodecs.c index c2d37c9a5ebc..9e346f105fae 100644 --- a/sound/soc/rockchip/rockchip_multicodecs.c +++ b/sound/soc/rockchip/rockchip_multicodecs.c @@ -67,6 +67,7 @@ struct multicodecs_data { struct extcon_dev *extcon; struct delayed_work handler; unsigned int mclk_fs; + unsigned int *mclk_fs_map; bool codec_hp_det; u32 num_keys; u32 last_key; @@ -372,15 +373,20 @@ static int rk_multicodecs_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai; struct multicodecs_data *mc_data = snd_soc_card_get_drvdata(rtd->card); unsigned int mclk; + unsigned int codec_mclk; int ret, i; mclk = params_rate(params) * mc_data->mclk_fs; for_each_rtd_codec_dais(rtd, i, codec_dai) { - ret = snd_soc_dai_set_sysclk(codec_dai, substream->stream, mclk, + if (mc_data->mclk_fs_map[i] > 0) + codec_mclk = params_rate(params) * mc_data->mclk_fs_map[i]; + else + codec_mclk = mclk; + ret = snd_soc_dai_set_sysclk(codec_dai, substream->stream, codec_mclk, SND_SOC_CLOCK_IN); if (ret && ret != -ENOTSUPP) { - pr_err("Set codec_dai sysclk failed: %d\n", ret); + pr_err("Set codec_dai sysclk(%uHZ) failed: %d\n", codec_mclk, ret); goto out; } } @@ -388,7 +394,7 @@ static int rk_multicodecs_hw_params(struct snd_pcm_substream *substream, ret = snd_soc_dai_set_sysclk(cpu_dai, substream->stream, mclk, SND_SOC_CLOCK_OUT); if (ret && ret != -ENOTSUPP) { - pr_err("Set cpu_dai sysclk failed: %d\n", ret); + pr_err("Set cpu_dai sysclk(%uHZ) failed: %d\n", mclk, ret); goto out; } @@ -741,6 +747,7 @@ static int rk_multicodecs_probe(struct platform_device *pdev) struct snd_soc_dai_link_component *codecs; struct multicodecs_data *mc_data; struct of_phandle_args args; + unsigned int *map; u32 val; int count, irq; int ret = 0, i = 0, idx = 0; @@ -858,6 +865,14 @@ static int rk_multicodecs_probe(struct platform_device *pdev) card->num_links = 3; } + map = devm_kcalloc(&pdev->dev, count, sizeof(*map), GFP_KERNEL); + if (!map) + return -ENOMEM; + ret = of_property_read_u32_array(np, "rockchip,mclk-fs-mapping", map, count); + if (ret) + memset(map, 0x0, sizeof(*map) * count); + mc_data->mclk_fs_map = map; + mc_data->mclk_fs = DEFAULT_MCLK_FS; if (!of_property_read_u32(np, "rockchip,mclk-fs", &val)) mc_data->mclk_fs = val;