From 77713835a4bfddeccbd957ebfa069426bfd7dcdb Mon Sep 17 00:00:00 2001 From: Jie Dai Date: Fri, 16 Jun 2023 14:20:48 +0800 Subject: [PATCH] lcd: lut_dma driver support [2/2] PD#SWPL-124798 Problem: lut flush dma is better than cpu Solution: add lut dma driver Verify: ay301 Change-Id: Id8d9faf309767f6a7f6ac665081f1d27d34108ad Signed-off-by: Jie Dai --- .../dts/amlogic/mesont5m_ay301-panel.dtsi | 3 +- .../dts/amlogic/mesont5m_ay309-panel.dtsi | 3 +- .../amlogic/mesont5m_reva_ay301-panel.dtsi | 3 +- .../amlogic/mesont5m_reva_ay309-panel.dtsi | 3 +- .../dts/amlogic/t5m_reva_t963d4_ay301_2g.dts | 8 + .../amlogic/t5m_reva_t963d4_ay301_2g_R.dts | 8 + .../dts/amlogic/t5m_reva_t963d4_ay301_3g.dts | 8 + .../amlogic/t5m_reva_t963d4_ay301_3g_R.dts | 8 + .../dts/amlogic/t5m_reva_t963d4_ay309_2g.dts | 8 + .../amlogic/t5m_reva_t963d4_ay309_2g_R.dts | 8 + .../dts/amlogic/t5m_reva_t963d4_ay309_3g.dts | 8 + .../amlogic/t5m_reva_t963d4_ay309_3g_R.dts | 8 + .../boot/dts/amlogic/t5m_t963d4_ay301_2g.dts | 8 + .../dts/amlogic/t5m_t963d4_ay301_2g_R.dts | 8 + .../boot/dts/amlogic/t5m_t963d4_ay301_3g.dts | 8 + .../dts/amlogic/t5m_t963d4_ay301_3g_R.dts | 8 + .../boot/dts/amlogic/t5m_t963d4_ay301_4g.dts | 8 + .../dts/amlogic/t5m_t963d4_ay301_4g_R.dts | 8 + .../boot/dts/amlogic/t5m_t963d4_ay309_2g.dts | 8 + .../dts/amlogic/t5m_t963d4_ay309_2g_R.dts | 8 + .../boot/dts/amlogic/t5m_t963d4_ay309_3g.dts | 8 + .../dts/amlogic/t5m_t963d4_ay309_3g_R.dts | 8 + drivers/media/enhancement/amvecm/amvecm.c | 2 +- drivers/media/vout/lcd/lcd_common.c | 46 ++++++ drivers/media/vout/lcd/lcd_common.h | 5 +- drivers/media/vout/lcd/lcd_tcon.c | 110 +++++++++++--- drivers/media/vout/lcd/lcd_tcon.h | 8 +- drivers/media/vout/lcd/lcd_tcon_debug.c | 77 ++++++---- drivers/media/vout/lcd/lcd_tcon_hw.c | 141 +++++++++++++++--- .../media/vout/lcd/lcd_venc/lcd_venc_dft.c | 5 +- .../media/vout/lcd/lcd_venc/lcd_venc_t3x.c | 5 +- drivers/media/vout/lcd/lcd_venc/lcd_venc_t7.c | 5 +- drivers/media/vout/lcd/lcd_vout.c | 2 + .../amlogic/media/vout/lcd/lcd_tcon_data.h | 24 ++- .../linux/amlogic/media/vout/lcd/lcd_vout.h | 2 + 35 files changed, 509 insertions(+), 79 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/mesont5m_ay301-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesont5m_ay301-panel.dtsi index ff3178b8b..bed33ca45 100644 --- a/arch/arm64/boot/dts/amlogic/mesont5m_ay301-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesont5m_ay301-panel.dtsi @@ -42,7 +42,8 @@ pinctrl-9 = <&ST5461D18_2_pins>; pinctrl-10 = <&ST5461D18_2_off_pins>; pinctrl_version = <2>; /* for uboot */ - memory-region = <&lcd_tcon_reserved>; + memory-region = <&lcd_tcon_reserved &lcd_cma_reserved>; + memory-region-names = "lcd_tcon_reserved","lcd_cma_reserved"; /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ /* power index:(gpios_index, or extern_index, 0xff=invalid) */ diff --git a/arch/arm64/boot/dts/amlogic/mesont5m_ay309-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesont5m_ay309-panel.dtsi index 410924980..6cf5b8726 100644 --- a/arch/arm64/boot/dts/amlogic/mesont5m_ay309-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesont5m_ay309-panel.dtsi @@ -42,7 +42,8 @@ pinctrl-9 = <&ST5461D18_2_pins>; pinctrl-10 = <&ST5461D18_2_off_pins>; pinctrl_version = <2>; /* for uboot */ - memory-region = <&lcd_tcon_reserved>; + memory-region = <&lcd_tcon_reserved &lcd_cma_reserved>; + memory-region-names = "lcd_tcon_reserved", "lcd_cma_reserved"; /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ /* power index:(gpios_index, or extern_index, 0xff=invalid) */ diff --git a/arch/arm64/boot/dts/amlogic/mesont5m_reva_ay301-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesont5m_reva_ay301-panel.dtsi index c4683a6ac..5abbdff0b 100644 --- a/arch/arm64/boot/dts/amlogic/mesont5m_reva_ay301-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesont5m_reva_ay301-panel.dtsi @@ -42,7 +42,8 @@ pinctrl-9 = <&ST5461D18_2_pins>; pinctrl-10 = <&ST5461D18_2_off_pins>; pinctrl_version = <2>; /* for uboot */ - memory-region = <&lcd_tcon_reserved>; + memory-region = <&lcd_tcon_reserved &lcd_cma_reserved>; + memory-region-names = "lcd_tcon_reserved", "lcd_cma_reserved"; /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ /* power index:(gpios_index, or extern_index, 0xff=invalid) */ diff --git a/arch/arm64/boot/dts/amlogic/mesont5m_reva_ay309-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesont5m_reva_ay309-panel.dtsi index c4683a6ac..5abbdff0b 100644 --- a/arch/arm64/boot/dts/amlogic/mesont5m_reva_ay309-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesont5m_reva_ay309-panel.dtsi @@ -42,7 +42,8 @@ pinctrl-9 = <&ST5461D18_2_pins>; pinctrl-10 = <&ST5461D18_2_off_pins>; pinctrl_version = <2>; /* for uboot */ - memory-region = <&lcd_tcon_reserved>; + memory-region = <&lcd_tcon_reserved &lcd_cma_reserved>; + memory-region-names = "lcd_tcon_reserved", "lcd_cma_reserved"; /* power type:(0=cpu_gpio, 2=signal, 3=extern, 0xff=ending) */ /* power index:(gpios_index, or extern_index, 0xff=invalid) */ diff --git a/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay301_2g.dts b/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay301_2g.dts index b767c566f..fe4fb2e3b 100644 --- a/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay301_2g.dts +++ b/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay301_2g.dts @@ -87,6 +87,14 @@ no-map; }; + lcd_cma_reserved:linux,lcd-cma { + compatible = "shared-dma-pool"; + reusable; + /* 512k for lcd dma data */ + size = <0x0 0x00080000>; + reg = <0x0 0x3ea80000 0x0 0x00080000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay301_2g_R.dts b/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay301_2g_R.dts index db9fb1919..71d4673e9 100644 --- a/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay301_2g_R.dts +++ b/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay301_2g_R.dts @@ -87,6 +87,14 @@ no-map; }; + lcd_cma_reserved:linux,lcd-cma { + compatible = "shared-dma-pool"; + reusable; + /* 512k for lcd dma data */ + size = <0x0 0x00080000>; + reg = <0x0 0x3ea80000 0x0 0x00080000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay301_3g.dts b/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay301_3g.dts index 13cd7a5a4..7311f2a0d 100644 --- a/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay301_3g.dts +++ b/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay301_3g.dts @@ -87,6 +87,14 @@ no-map; }; + lcd_cma_reserved:linux,lcd-cma { + compatible = "shared-dma-pool"; + reusable; + /* 512k for lcd dma data */ + size = <0x0 0x00080000>; + reg = <0x0 0x3ea80000 0x0 0x00080000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay301_3g_R.dts b/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay301_3g_R.dts index 5552cffda..9531b2731 100644 --- a/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay301_3g_R.dts +++ b/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay301_3g_R.dts @@ -87,6 +87,14 @@ no-map; }; + lcd_cma_reserved:linux,lcd-cma { + compatible = "shared-dma-pool"; + reusable; + /* 512k for lcd dma data */ + size = <0x0 0x00080000>; + reg = <0x0 0x3ea80000 0x0 0x00080000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay309_2g.dts b/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay309_2g.dts index d9c80dae9..7790210f8 100644 --- a/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay309_2g.dts +++ b/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay309_2g.dts @@ -87,6 +87,14 @@ no-map; }; + lcd_cma_reserved:linux,lcd-cma { + compatible = "shared-dma-pool"; + reusable; + /* 512k for lcd dma data */ + size = <0x0 0x00080000>; + reg = <0x0 0x3ea80000 0x0 0x00080000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay309_2g_R.dts b/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay309_2g_R.dts index cb4f5654c..6ee5fca3d 100644 --- a/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay309_2g_R.dts +++ b/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay309_2g_R.dts @@ -87,6 +87,14 @@ no-map; }; + lcd_cma_reserved:linux,lcd-cma { + compatible = "shared-dma-pool"; + reusable; + /* 512k for lcd dma data */ + size = <0x0 0x00080000>; + reg = <0x0 0x3ea80000 0x0 0x00080000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay309_3g.dts b/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay309_3g.dts index a14daeb57..1af0f3460 100644 --- a/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay309_3g.dts +++ b/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay309_3g.dts @@ -82,6 +82,14 @@ no-map; }; + lcd_cma_reserved:linux,lcd-cma { + compatible = "shared-dma-pool"; + reusable; + /* 512k for lcd dma data */ + size = <0x0 0x00080000>; + reg = <0x0 0x3ea80000 0x0 0x00080000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay309_3g_R.dts b/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay309_3g_R.dts index 74ed89238..f44902af4 100644 --- a/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay309_3g_R.dts +++ b/arch/arm64/boot/dts/amlogic/t5m_reva_t963d4_ay309_3g_R.dts @@ -82,6 +82,14 @@ no-map; }; + lcd_cma_reserved:linux,lcd-cma { + compatible = "shared-dma-pool"; + reusable; + /* 512k for lcd dma data */ + size = <0x0 0x00080000>; + reg = <0x0 0x3ea80000 0x0 0x00080000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_2g.dts b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_2g.dts index c6ee343a1..d9a4e048c 100644 --- a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_2g.dts +++ b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_2g.dts @@ -87,6 +87,14 @@ no-map; }; + lcd_cma_reserved:linux,lcd-cma { + compatible = "shared-dma-pool"; + reusable; + /* 512k for lcd dma data */ + size = <0x0 0x00080000>; + reg = <0x0 0x3ea80000 0x0 0x00080000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_2g_R.dts b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_2g_R.dts index c546e2a9d..f5a040066 100644 --- a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_2g_R.dts +++ b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_2g_R.dts @@ -87,6 +87,14 @@ no-map; }; + lcd_cma_reserved:linux,lcd-cma { + compatible = "shared-dma-pool"; + reusable; + /* 512k for lcd dma data */ + size = <0x0 0x00080000>; + reg = <0x0 0x3ea80000 0x0 0x00080000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_3g.dts b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_3g.dts index f34c94c92..b102b8f16 100644 --- a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_3g.dts +++ b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_3g.dts @@ -87,6 +87,14 @@ no-map; }; + lcd_cma_reserved:linux,lcd-cma { + compatible = "shared-dma-pool"; + reusable; + /* 512k for lcd dma data */ + size = <0x0 0x00080000>; + reg = <0x0 0x3ea80000 0x0 0x00080000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_3g_R.dts b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_3g_R.dts index 3e7be9b0f..25ea8f6fc 100644 --- a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_3g_R.dts +++ b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_3g_R.dts @@ -87,6 +87,14 @@ no-map; }; + lcd_cma_reserved:linux,lcd-cma { + compatible = "shared-dma-pool"; + reusable; + /* 512k for lcd dma data */ + size = <0x0 0x00080000>; + reg = <0x0 0x3ea80000 0x0 0x00080000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_4g.dts b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_4g.dts index 4f468c527..aa83f7adb 100644 --- a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_4g.dts +++ b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_4g.dts @@ -96,6 +96,14 @@ no-map; }; + lcd_cma_reserved:linux,lcd-cma { + compatible = "shared-dma-pool"; + reusable; + /* 512k for lcd dma data */ + size = <0x0 0x00080000>; + reg = <0x0 0x3ea80000 0x0 0x00080000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_4g_R.dts b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_4g_R.dts index 9d7d15cca..fa876d190 100644 --- a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_4g_R.dts +++ b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay301_4g_R.dts @@ -96,6 +96,14 @@ no-map; }; + lcd_cma_reserved:linux,lcd-cma { + compatible = "shared-dma-pool"; + reusable; + /* 512k for lcd dma data */ + size = <0x0 0x00080000>; + reg = <0x0 0x3ea80000 0x0 0x00080000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay309_2g.dts b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay309_2g.dts index d13009df7..b84cb8d8f 100644 --- a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay309_2g.dts +++ b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay309_2g.dts @@ -87,6 +87,14 @@ no-map; }; + lcd_cma_reserved:linux,lcd-cma { + compatible = "shared-dma-pool"; + reusable; + /* 512k for lcd dma data */ + size = <0x0 0x00080000>; + reg = <0x0 0x3ea80000 0x0 0x00080000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay309_2g_R.dts b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay309_2g_R.dts index 32c1ea1a9..2fedf4371 100644 --- a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay309_2g_R.dts +++ b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay309_2g_R.dts @@ -87,6 +87,14 @@ no-map; }; + lcd_cma_reserved:linux,lcd-cma { + compatible = "shared-dma-pool"; + reusable; + /* 512k for lcd dma data */ + size = <0x0 0x00080000>; + reg = <0x0 0x3ea80000 0x0 0x00080000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay309_3g.dts b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay309_3g.dts index 5105e1aac..03582db38 100644 --- a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay309_3g.dts +++ b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay309_3g.dts @@ -82,6 +82,14 @@ no-map; }; + lcd_cma_reserved:linux,lcd-cma { + compatible = "shared-dma-pool"; + reusable; + /* 512k for lcd dma data */ + size = <0x0 0x00080000>; + reg = <0x0 0x3ea80000 0x0 0x00080000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay309_3g_R.dts b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay309_3g_R.dts index 2b90d6b59..8697cbd1b 100644 --- a/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay309_3g_R.dts +++ b/arch/arm64/boot/dts/amlogic/t5m_t963d4_ay309_3g_R.dts @@ -82,6 +82,14 @@ no-map; }; + lcd_cma_reserved:linux,lcd-cma { + compatible = "shared-dma-pool"; + reusable; + /* 512k for lcd dma data */ + size = <0x0 0x00080000>; + reg = <0x0 0x3ea80000 0x0 0x00080000>; + }; + ion_cma_reserved:linux,ion-dev { compatible = "shared-dma-pool"; reusable; diff --git a/drivers/media/enhancement/amvecm/amvecm.c b/drivers/media/enhancement/amvecm/amvecm.c index 7e04776b4..8935a9dc2 100644 --- a/drivers/media/enhancement/amvecm/amvecm.c +++ b/drivers/media/enhancement/amvecm/amvecm.c @@ -12636,7 +12636,7 @@ static int aml_vecm_probe(struct platform_device *pdev) spin_lock_init(&vpp_lcd_gamma_lock); mutex_init(&vpp_lut3d_lock); #ifdef CONFIG_AMLOGIC_LCD - ret = aml_lcd_notifier_register(&aml_lcd_gamma_nb); + ret = aml_lcd_atomic_notifier_register(&aml_lcd_gamma_nb); if (ret) pr_info("register aml_lcd_gamma_notifier failed\n"); diff --git a/drivers/media/vout/lcd/lcd_common.c b/drivers/media/vout/lcd/lcd_common.c index 22af221ba..5717f548d 100644 --- a/drivers/media/vout/lcd/lcd_common.c +++ b/drivers/media/vout/lcd/lcd_common.c @@ -15,6 +15,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -160,6 +164,48 @@ char *lcd_mode_mode_to_str(int mode) return lcd_mode_table[mode]; } +int __of_reserved_mem_device_init_by_name(struct device *dev, + struct device_node *np, + const char *name) +{ + int idx = of_property_match_string(np, "memory-region-names", name); + + return of_reserved_mem_device_init_by_idx(dev, np, idx); +} + +void lcd_cma_pool_init(struct aml_lcd_drv_s *pdrv, struct platform_device *pdev) +{ + struct device *dev; + int ret; + char rsv_mem_name[64]; + + if (!pdev || !pdrv) + return; + + if (pdrv->index) + sprintf(rsv_mem_name, "lcd%d_cma_reserved", pdrv->index); + dev = &pdrv->pdev->dev; + ret = __of_reserved_mem_device_init_by_name(dev, dev->of_node, rsv_mem_name); + if (ret == 0) { + pdrv->lcd_cma_ready = 1; + //dma_set_coherent_mask(dev, 0xffffffff);//4G + } else { + pdrv->lcd_cma_ready = -1; + LCDPR("warning:lcd cma init failed\n"); + } +} + +void *lcd_alloc_dma_buffer(struct aml_lcd_drv_s *pdrv, unsigned int size, dma_addr_t *paddr) +{ + if (!pdrv || !pdrv->pdev) + return NULL; + + if (pdrv->lcd_cma_ready == 0) + lcd_cma_pool_init(pdrv, pdrv->pdev); + + return dma_alloc_coherent(&pdrv->pdev->dev, size, paddr, GFP_KERNEL); +} + u8 *lcd_vmap(ulong addr, u32 size) { u8 *vaddr = NULL; diff --git a/drivers/media/vout/lcd/lcd_common.h b/drivers/media/vout/lcd/lcd_common.h index 1d045db0a..508a6b2de 100644 --- a/drivers/media/vout/lcd/lcd_common.h +++ b/drivers/media/vout/lcd/lcd_common.h @@ -43,7 +43,8 @@ /* 20230815: add full-link-training and EDID-timing for eDP */ /* 20230816: optimize clk accuracy*/ /* 20230821: update clk ss support*/ -#define LCD_DRV_VERSION "20230821" +/* 20230823: add dma driver for tcon lut*/ +#define LCD_DRV_VERSION "20230823" extern struct mutex lcd_vout_mutex; extern spinlock_t lcd_reg_spinlock; @@ -67,6 +68,8 @@ int lcd_type_str_to_type(const char *str); char *lcd_type_type_to_str(int type); unsigned char lcd_mode_str_to_mode(const char *str); char *lcd_mode_mode_to_str(int mode); +void *lcd_alloc_dma_buffer(struct aml_lcd_drv_s *pdrv, + unsigned int size, dma_addr_t *paddr); u8 *lcd_vmap(ulong addr, u32 size); void lcd_unmap_phyaddr(u8 *vaddr); void lcd_debug_parse_param(char *buf_orig, char **parm); diff --git a/drivers/media/vout/lcd/lcd_tcon.c b/drivers/media/vout/lcd/lcd_tcon.c index 2c6055a2e..b714bb322 100644 --- a/drivers/media/vout/lcd/lcd_tcon.c +++ b/drivers/media/vout/lcd/lcd_tcon.c @@ -1009,6 +1009,7 @@ int lcd_tcon_enable(struct aml_lcd_drv_s *pdrv) void lcd_tcon_disable(struct aml_lcd_drv_s *pdrv) { struct lcd_tcon_fw_s *tcon_fw = aml_lcd_tcon_get_fw(); + struct lcd_tcon_data_block_header_s *block_header; unsigned int i; int ret; @@ -1028,8 +1029,21 @@ void lcd_tcon_disable(struct aml_lcd_drv_s *pdrv) tcon_mm_table.block_bit_flag = 0; lcd_tcon_data_multi_remvoe(&tcon_mm_table); for (i = 0; i < tcon_mm_table.block_cnt; i++) { - kfree(tcon_mm_table.data_mem_vaddr[i]); - tcon_mm_table.data_mem_vaddr[i] = NULL; + if (!tcon_mm_table.data_mem_vaddr[i]) + continue; + block_header = (struct lcd_tcon_data_block_header_s *) + tcon_mm_table.data_mem_vaddr[i]; + + if (!is_block_type_basic_init(block_header->block_type) && + is_block_ctrl_dma(block_header->block_ctrl)) { + dma_free_coherent(&pdrv->pdev->dev, + block_header->block_size, + tcon_mm_table.data_mem_vaddr[i], + tcon_mm_table.data_mem_paddr[i]); + } else { + kfree(tcon_mm_table.data_mem_vaddr[i]); + tcon_mm_table.data_mem_vaddr[i] = NULL; + } } } else { lcd_tcon_data_multi_reset(&tcon_mm_table); @@ -1066,6 +1080,7 @@ static int lcd_tcon_data_multi_match_policy(struct aml_lcd_drv_s *pdrv, unsigned switch (data_list->ctrl_method) { case LCD_TCON_DATA_CTRL_MULTI_VFREQ_DIRECT: case LCD_TCON_DATA_CTRL_MULTI_VFREQ_NOTIFY: + if (frame_rate < data_list->min || frame_rate > data_list->max) goto lcd_tcon_data_multi_match_policy_exit; if (!data_multi) @@ -1154,7 +1169,7 @@ static int lcd_tcon_data_multi_match_init(struct aml_lcd_drv_s *pdrv, if (!ctrl_part) return -1; - if (ctrl_part->ctrl_data_flag != LCD_TCON_DATA_CTRL_FLAG_MULTI) + if (!(ctrl_part->ctrl_data_flag & LCD_TCON_DATA_CTRL_FLAG_MULTI)) return -1; data_byte = ctrl_part->data_byte_width; @@ -1266,7 +1281,7 @@ static int lcd_tcon_data_multi_match_check(struct aml_lcd_drv_s *pdrv, if (!ctrl_part) return -1; - if (ctrl_part->ctrl_data_flag != LCD_TCON_DATA_CTRL_FLAG_MULTI) + if (!(ctrl_part->ctrl_data_flag & LCD_TCON_DATA_CTRL_FLAG_MULTI)) return -1; data_byte = ctrl_part->data_byte_width; @@ -1383,8 +1398,9 @@ static int lcd_tcon_data_multi_list_init(struct aml_lcd_drv_s *pdrv, struct lcd_tcon_data_block_header_s *block_header; struct lcd_tcon_data_block_ext_header_s *ext_header; struct lcd_tcon_data_part_ctrl_s *ctrl_part; - unsigned char *data_buf, *p, part_type; + unsigned char *data_buf, *p, *part_start, part_type; unsigned int size, data_offset, offset, i; + unsigned int *part_pos, ext_header_size; unsigned short part_cnt; int ret; @@ -1393,11 +1409,14 @@ static int lcd_tcon_data_multi_list_init(struct aml_lcd_drv_s *pdrv, p = data_buf + LCD_TCON_DATA_BLOCK_HEADER_SIZE; ext_header = (struct lcd_tcon_data_block_ext_header_s *)p; part_cnt = ext_header->part_cnt; + ext_header_size = block_header->ext_header_size; - data_offset = LCD_TCON_DATA_BLOCK_HEADER_SIZE + block_header->ext_header_size; + part_pos = (unsigned int *)(p + LCD_TCON_DATA_BLOCK_EXT_HEADER_SIZE_PRE); + part_start = data_buf + LCD_TCON_DATA_BLOCK_HEADER_SIZE + ext_header_size; size = 0; for (i = 0; i < part_cnt; i++) { - p = data_buf + data_offset; + p = part_start + part_pos[i]; + data_offset = part_pos[i]; part_type = p[LCD_TCON_DATA_PART_NAME_SIZE + 3]; switch (part_type) { @@ -1405,8 +1424,10 @@ static int lcd_tcon_data_multi_list_init(struct aml_lcd_drv_s *pdrv, offset = LCD_TCON_DATA_PART_CTRL_SIZE_PRE; ctrl_part = (struct lcd_tcon_data_part_ctrl_s *)p; size = offset + (ctrl_part->data_cnt * ctrl_part->data_byte_width); - if (ctrl_part->ctrl_data_flag != LCD_TCON_DATA_CTRL_FLAG_MULTI) + if (!(ctrl_part->ctrl_data_flag & LCD_TCON_DATA_CTRL_FLAG_MULTI)) break; + if ((size + data_offset) > block_header->block_size) + return -1; ret = lcd_tcon_data_multi_match_init(pdrv, data_list, ctrl_part, (p + offset)); if (ret == 0) @@ -1417,7 +1438,6 @@ static int lcd_tcon_data_multi_list_init(struct aml_lcd_drv_s *pdrv, default: return -1; } - data_offset += size; } return -1; @@ -1456,7 +1476,7 @@ int lcd_tcon_data_multi_match_find(struct aml_lcd_drv_s *pdrv, unsigned char *da ctrl_part = (struct lcd_tcon_data_part_ctrl_s *)p; size = offset + (ctrl_part->data_cnt * ctrl_part->data_byte_width); - if (ctrl_part->ctrl_data_flag != LCD_TCON_DATA_CTRL_FLAG_MULTI) + if (!(ctrl_part->ctrl_data_flag & LCD_TCON_DATA_CTRL_FLAG_MULTI)) break; ret = lcd_tcon_data_multi_match_check(pdrv, frame_rate, ctrl_part, (p + offset)); @@ -1562,7 +1582,7 @@ static int lcd_tcon_data_multi_update(struct aml_lcd_drv_s *pdrv, for (i = 0; i < mm_table->data_multi_cnt; i++) { data_multi = &mm_table->data_multi[i]; /* bypass LCD_TCON_DATA_BLOCK_TYPE_BASIC_INIT for multi lut switch */ - if (data_multi->block_type == LCD_TCON_DATA_BLOCK_TYPE_BASIC_INIT) + if (is_block_type_basic_init(data_multi->block_type)) continue; /* bypass_flag for debug */ if (data_multi->bypass_flag) @@ -1686,7 +1706,7 @@ static int lcd_tcon_data_multi_set(struct aml_lcd_drv_s *pdrv, data_multi = &mm_table->data_multi[i]; /* bypass LCD_TCON_DATA_BLOCK_TYPE_BASIC_INIT for multi lut switch */ /* bypass LCD_TCON_DATA_BLOCK_TYPE_ACC_LUT for soc gamma update */ - if (data_multi->block_type == LCD_TCON_DATA_BLOCK_TYPE_BASIC_INIT) + if (is_block_type_basic_init(data_multi->block_type)) continue; /* bypass_flag for debug */ if (data_multi->bypass_flag) @@ -1696,7 +1716,9 @@ static int lcd_tcon_data_multi_set(struct aml_lcd_drv_s *pdrv, lut_hit++; ret = lcd_tcon_data_common_parse_set(pdrv, - data_multi->list_update->block_vaddr, 0); + data_multi->list_update->block_vaddr, + data_multi->list_update->block_paddr, 0); + if (ret) //list update failed continue; data_multi->list_cur = data_multi->list_update; @@ -1726,6 +1748,13 @@ void lcd_tcon_vsync_isr(struct aml_lcd_drv_s *pdrv) if (lcd_tcon_conf->tcon_is_busy) return; + lcd_tcon_lut_dma_disable(pdrv); + if (lcd_tcon_get_dma_ref() > 0) { + if (lcd_debug_print_flag & LCD_DBG_PR_ISR) + LCDPR("%s, dma update\n", __func__); + lcd_tcon_dma_update(pdrv); + } + if (tcon_mm_table.version) { if (tcon_mm_table.multi_lut_update) { spin_lock_irqsave(&tcon_local_cfg.multi_list_lock, flags); @@ -2008,7 +2037,9 @@ static int lcd_tcon_data_multi_add(struct aml_lcd_drv_s *pdrv, data_list = kzalloc(sizeof(*data_list), GFP_KERNEL); if (!data_list) return -1; + spin_lock_irqsave(&tcon_local_cfg.multi_list_lock, flags); data_list->block_vaddr = mm_table->data_mem_vaddr[index]; + data_list->block_paddr = mm_table->data_mem_paddr[index]; data_list->next = NULL; data_list->id = index; data_list->block_name = block_header->name; @@ -2020,7 +2051,6 @@ static int lcd_tcon_data_multi_add(struct aml_lcd_drv_s *pdrv, } } - spin_lock_irqsave(&tcon_local_cfg.multi_list_lock, flags); if (!data_multi) { /* create new list */ data_multi = &mm_table->data_multi[mm_table->data_multi_cnt]; mm_table->data_multi_cnt++; @@ -2180,7 +2210,7 @@ int lcd_tcon_data_load(struct aml_lcd_drv_s *pdrv, unsigned char *data_buf, int return -1; } - if (block_header->block_type != LCD_TCON_DATA_BLOCK_TYPE_BASIC_INIT) { + if (!is_block_type_basic_init(block_header->block_type)) { tcon_mm_table.valid_flag |= block_header->block_flag; if (block_header->block_flag == LCD_TCON_DATA_VALID_DEMURA) tcon_mm_table.demura_cnt++; @@ -2225,7 +2255,8 @@ int lcd_tcon_data_load(struct aml_lcd_drv_s *pdrv, unsigned char *data_buf, int tcon_mm_table.data_size[index] = block_header->block_size; /* add data multi list */ - if (block_header->block_ctrl & LCD_TCON_DATA_CTRL_FLAG_MULTI) + if (!is_block_type_basic_init(block_header->block_type) && + is_block_ctrl_multi(block_header->block_ctrl)) lcd_tcon_data_multi_add(pdrv, &tcon_mm_table, block_header, index); if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL) { @@ -2333,8 +2364,16 @@ int lcd_tcon_bin_load(struct aml_lcd_drv_s *pdrv) goto lcd_tcon_bin_load_next; } - tcon_mm_table.data_mem_vaddr[i] = - kcalloc(size, sizeof(unsigned char), GFP_KERNEL); + if (!is_block_type_basic_init(block_header.block_type) && + is_block_ctrl_dma(block_header.block_ctrl)) { + tcon_mm_table.data_mem_vaddr[i] = + lcd_alloc_dma_buffer(pdrv, size, + tcon_mm_table.data_mem_paddr[i]); + } else { + tcon_mm_table.data_mem_vaddr[i] = + kcalloc(size, sizeof(unsigned char), GFP_KERNEL); + tcon_mm_table.data_mem_paddr[i] = 0; + } if (!tcon_mm_table.data_mem_vaddr[i]) { LCDERR("%s: Not enough memory\n", __func__); goto lcd_tcon_bin_load_next; @@ -2355,8 +2394,16 @@ int lcd_tcon_bin_load(struct aml_lcd_drv_s *pdrv) } ret = lcd_tcon_data_load(pdrv, tcon_mm_table.data_mem_vaddr[i], i); if (ret) { - kfree(tcon_mm_table.data_mem_vaddr[i]); - tcon_mm_table.data_mem_vaddr[i] = NULL; + if (!is_block_type_basic_init(block_header.block_type) && + is_block_ctrl_dma(block_header.block_ctrl)) { + dma_free_coherent(&pdrv->pdev->dev, + block_header.block_size, + tcon_mm_table.data_mem_vaddr[i], + tcon_mm_table.data_mem_paddr[i]); + } else { + kfree(tcon_mm_table.data_mem_vaddr[i]); + tcon_mm_table.data_mem_vaddr[i] = NULL; + } } lcd_tcon_bin_load_next: @@ -2520,7 +2567,8 @@ static int lcd_tcon_mm_table_config_v1(void) cnt = tcon_mm_table.block_cnt; tcon_mm_table.data_mem_vaddr = kcalloc(cnt, sizeof(unsigned char *), GFP_KERNEL); - if (!tcon_mm_table.data_mem_vaddr) + tcon_mm_table.data_mem_paddr = kcalloc(cnt, sizeof(dma_addr_t), GFP_KERNEL); + if (!tcon_mm_table.data_mem_vaddr || !tcon_mm_table.data_mem_paddr) return -1; tcon_mm_table.data_priority = @@ -3565,6 +3613,7 @@ int lcd_tcon_probe(struct aml_lcd_drv_s *pdrv) int lcd_tcon_remove(struct aml_lcd_drv_s *pdrv) { int i; + struct lcd_tcon_data_block_header_s *block_header; lcd_tcon_debug_file_remove(&tcon_local_cfg); @@ -3578,11 +3627,28 @@ int lcd_tcon_remove(struct aml_lcd_drv_s *pdrv) lcd_tcon_data_multi_remvoe(&tcon_mm_table); if (tcon_mm_table.data_mem_vaddr) { for (i = 0; i < tcon_mm_table.block_cnt; i++) { - kfree(tcon_mm_table.data_mem_vaddr[i]); + if (!tcon_mm_table.data_mem_vaddr[i]) + continue; + + block_header = (struct lcd_tcon_data_block_header_s *) + tcon_mm_table.data_mem_vaddr[i]; + if (!is_block_type_basic_init(block_header->block_type) && + is_block_ctrl_dma(block_header->block_ctrl)) { + dma_free_coherent(&pdrv->pdev->dev, + block_header->block_size, + tcon_mm_table.data_mem_vaddr[i], + tcon_mm_table.data_mem_paddr[i]); + } else { + kfree(tcon_mm_table.data_mem_vaddr[i]); + } tcon_mm_table.data_mem_vaddr[i] = NULL; + tcon_mm_table.data_mem_paddr[i] = 0; } kfree(tcon_mm_table.data_mem_vaddr); tcon_mm_table.data_mem_vaddr = NULL; + + kfree(tcon_mm_table.data_mem_paddr); + tcon_mm_table.data_mem_paddr = NULL; } } diff --git a/drivers/media/vout/lcd/lcd_tcon.h b/drivers/media/vout/lcd/lcd_tcon.h index f9801e4d7..b877b66ca 100644 --- a/drivers/media/vout/lcd/lcd_tcon.h +++ b/drivers/media/vout/lcd/lcd_tcon.h @@ -100,6 +100,7 @@ struct tcon_data_list_s { unsigned int *ctrl_data; char *block_name; unsigned char *block_vaddr; + phys_addr_t block_paddr; struct tcon_data_list_s *next; }; @@ -147,6 +148,7 @@ struct tcon_mem_map_table_s { struct tcon_data_priority_s *data_priority; unsigned int *data_size; unsigned char **data_mem_vaddr; + dma_addr_t *data_mem_paddr; unsigned int multi_lut_update; unsigned int data_multi_cnt; @@ -249,6 +251,10 @@ void lcd_tcon_fw_base_timing_update(struct aml_lcd_drv_s *pdrv); * ********************************** */ /* internal */ + +int lcd_tcon_get_dma_ref(void); +void lcd_tcon_set_dma_ref(int i); +void lcd_tcon_dma_update(struct aml_lcd_drv_s *pdrv); void lcd_tcon_lut_dma_mif_set(phys_addr_t paddr, unsigned int size); void lcd_tcon_lut_dma_enable(struct aml_lcd_drv_s *pdrv); void lcd_tcon_lut_dma_disable(struct aml_lcd_drv_s *pdrv); @@ -281,7 +287,7 @@ void lcd_tcon_data_multi_current_update(struct tcon_mem_map_table_s *mm_table, void lcd_tcon_data_multi_bypass_set(struct tcon_mem_map_table_s *mm_table, unsigned int block_type, int flag); int lcd_tcon_data_common_parse_set(struct aml_lcd_drv_s *pdrv, - unsigned char *data_buf, int init_flag); + unsigned char *data_buf, phys_addr_t paddr, int init_flag); void lcd_tcon_init_data_version_update(char *data_buf); int lcd_tcon_data_load(struct aml_lcd_drv_s *pdrv, unsigned char *data_buf, int index); int lcd_tcon_bin_load(struct aml_lcd_drv_s *pdrv); diff --git a/drivers/media/vout/lcd/lcd_tcon_debug.c b/drivers/media/vout/lcd/lcd_tcon_debug.c index 5013ddf4b..67992d894 100644 --- a/drivers/media/vout/lcd/lcd_tcon_debug.c +++ b/drivers/media/vout/lcd/lcd_tcon_debug.c @@ -1275,9 +1275,11 @@ long lcd_tcon_ioctl_handler(struct aml_lcd_drv_s *pdrv, int mcd_nr, unsigned lon struct aml_lcd_tcon_bin_s lcd_tcon_buff; struct tcon_rmem_s *tcon_rmem = get_lcd_tcon_rmem(); struct tcon_mem_map_table_s *mm_table = get_lcd_tcon_mm_table(); - struct lcd_tcon_data_block_header_s block_header; - unsigned int size = 0, temp, m = 0; - unsigned char *mem_vaddr = NULL; + struct lcd_tcon_data_block_header_s block_header, block_header_old; + unsigned int size = 0, old_size, temp, m = 0, header_size = 0; + struct device *dev; + phys_addr_t paddr = 0, paddr_old = 0; + unsigned char *mem_vaddr = NULL, *vaddr = NULL, *vaddr_old = NULL; char *str = NULL; int index = 0; int ret = 0; @@ -1360,44 +1362,63 @@ long lcd_tcon_ioctl_handler(struct aml_lcd_drv_s *pdrv, int mcd_nr, unsigned lon str = (char *)&mem_vaddr[m + 4]; temp = *(unsigned int *)&mem_vaddr[m]; - memset(&block_header, 0, sizeof(struct lcd_tcon_data_block_header_s)); + header_size = sizeof(struct lcd_tcon_data_block_header_s); + memset(&block_header, 0, header_size); + memset(&block_header_old, 0, header_size); + vaddr_old = mm_table->data_mem_vaddr[index]; + paddr_old = mm_table->data_mem_paddr[index]; + if (vaddr_old) + memcpy(&block_header_old, vaddr_old, header_size); + argp = (void __user *)lcd_tcon_buff.ptr; - if (copy_from_user(&block_header, argp, - sizeof(struct lcd_tcon_data_block_header_s))) { + if (copy_from_user(&block_header, argp, header_size)) { ret = -EFAULT; break; } + + dev = &pdrv->pdev->dev; + old_size = block_header_old.block_size; size = block_header.block_size; - if (size > lcd_tcon_buff.size || - size < sizeof(struct lcd_tcon_data_block_header_s)) { + if (size > lcd_tcon_buff.size || size < header_size) { LCDERR("%s: block[%d] size 0x%x error\n", __func__, index, size); ret = -EFAULT; break; } - kfree(mm_table->data_mem_vaddr[index]); - mm_table->data_mem_vaddr[index] = - kcalloc(size, sizeof(unsigned char), GFP_KERNEL); - if (!mm_table->data_mem_vaddr[index]) { - ret = -EFAULT; - break; - } - if (copy_from_user(mm_table->data_mem_vaddr[index], argp, size)) { - kfree(mm_table->data_mem_vaddr[index]); - mm_table->data_mem_vaddr[index] = NULL; - ret = -EFAULT; - break; + if (is_block_ctrl_dma(block_header.block_ctrl)) { + vaddr = lcd_alloc_dma_buffer(pdrv, size, &paddr); + if (lcd_debug_print_flag) + LCDPR("alloc for tcon mm_table[%d] form lcd_cma_pool\n" + "pa:0x%llx, va:%p, size:0x%x\n", + index, (unsigned long long)paddr, vaddr, size); + } else { + vaddr = kcalloc(size, sizeof(unsigned char), GFP_KERNEL); + paddr = virt_to_phys(vaddr); } - LCDPR("tcon: load bin_path[%d]: %s, size: 0x%x -> 0x%x\n", - index, str, temp, size); + if (unlikely(!vaddr)) + goto set_tcon_bin_error_break; - ret = lcd_tcon_data_load(pdrv, mm_table->data_mem_vaddr[index], index); - if (ret) { - kfree(mm_table->data_mem_vaddr[index]); - mm_table->data_mem_vaddr[index] = NULL; - ret = -EFAULT; - } + if (unlikely(copy_from_user(vaddr, argp, size))) + goto set_tcon_bin_error_break; + + LCDPR("tcon: load bin_path[%d]: %s, size: 0x%x -> 0x%x\n", index, str, temp, size); + + mm_table->data_mem_vaddr[index] = vaddr; + mm_table->data_mem_paddr[index] = paddr; + ret = lcd_tcon_data_load(pdrv, vaddr, index); + if (unlikely(ret)) + goto set_tcon_bin_error_break; + + break; +set_tcon_bin_error_break: + mm_table->data_mem_vaddr[index] = vaddr_old; + mm_table->data_mem_paddr[index] = paddr_old; + if (is_block_ctrl_dma(block_header.block_ctrl)) + dma_free_coherent(dev, size, vaddr, paddr); + else + kfree(vaddr); + ret = -EFAULT; break; default: LCDERR("tcon: don't support ioctl cmd_nr: 0x%x\n", mcd_nr); diff --git a/drivers/media/vout/lcd/lcd_tcon_hw.c b/drivers/media/vout/lcd/lcd_tcon_hw.c index b0f88244b..9bcc51ba2 100644 --- a/drivers/media/vout/lcd/lcd_tcon_hw.c +++ b/drivers/media/vout/lcd/lcd_tcon_hw.c @@ -21,18 +21,85 @@ #include #endif +struct lcd_tcon_dma_info_s { + phys_addr_t paddr; + unsigned int size; + struct list_head list; +}; + +static struct list_head *lcd_tcon_dma_list_head; +static atomic_t lcd_tcon_dma_ref = ATOMIC_INIT(-1); + +int lcd_tcon_get_dma_ref(void) +{ + return atomic_read(&lcd_tcon_dma_ref); +} + +void lcd_tcon_set_dma_ref(int i) +{ + atomic_set(&lcd_tcon_dma_ref, i); +} + +static void lcd_tcon_dma_update_add(phys_addr_t paddr, unsigned int size) +{ + struct lcd_tcon_dma_info_s *dma_info; + + dma_info = kzalloc(sizeof(*dma_info), GFP_KERNEL); + if (!dma_info) + return; + + dma_info->paddr = paddr; + dma_info->size = size; + if (lcd_tcon_dma_list_head) { + list_add_tail(&dma_info->list, lcd_tcon_dma_list_head); + } else { + dma_info->list.prev = &dma_info->list; + dma_info->list.next = &dma_info->list; + lcd_tcon_dma_list_head = &dma_info->list; + } + + if (atomic_read(&lcd_tcon_dma_ref) < 0) + atomic_set(&lcd_tcon_dma_ref, 0); + atomic_inc(&lcd_tcon_dma_ref); +} + +void lcd_tcon_dma_update(struct aml_lcd_drv_s *pdrv) +{ + struct lcd_tcon_dma_info_s *dma_info; + struct list_head *list_temp; + + lcd_tcon_lut_dma_disable(pdrv); + if (!lcd_tcon_dma_list_head) + return; + + dma_info = list_entry(lcd_tcon_dma_list_head, struct lcd_tcon_dma_info_s, list); + if (lcd_debug_print_flag & LCD_DBG_PR_ISR) + LCDPR("%s, dma_info: paddr:0x%llx, size:0x%x\n", __func__, + (unsigned long long)dma_info->paddr, dma_info->size); + lcd_tcon_lut_dma_mif_set(dma_info->paddr, dma_info->size); + lcd_tcon_lut_dma_enable(pdrv); + + if (lcd_tcon_dma_list_head->next != lcd_tcon_dma_list_head) { + list_temp = lcd_tcon_dma_list_head->next; + __list_del(lcd_tcon_dma_list_head->prev, lcd_tcon_dma_list_head->next); + lcd_tcon_dma_list_head = list_temp; + } else { + lcd_tcon_dma_list_head = NULL; + } + kfree(dma_info); + + atomic_dec(&lcd_tcon_dma_ref); +} + +/* + * must check addr and size before called + * paddr: 16bytes aligned + * size: 16bytes aligned + */ void lcd_tcon_lut_dma_mif_set(phys_addr_t paddr, unsigned int size) { unsigned int cmd_cnt = 0; - /* paddr should be 16 byte align*/ - if (!paddr || (paddr & 0xf)) - return; - - /* size must be 128bit align*/ - if (size & 0xf) - return; - /* 128 bits per cmd */ cmd_cnt = size >> 4; lcd_vcbus_write(VPU_DMA_RDMIF7_BADR0, paddr >> 4); @@ -58,6 +125,9 @@ void lcd_tcon_lut_dma_enable(struct aml_lcd_drv_s *pdrv) lcd_tcon_setb(pdrv, 0x367, 1, 0, 14); // intr trig pixel lcd_tcon_setb(pdrv, 0x367, 1, 16, 1); // enale tcon intr + lcd_tcon_setb(pdrv, 0x367, 1, 16, 1); // enale tcon intr + lcd_tcon_setb(pdrv, 0x367, 1, 16, 1); // enale tcon intr + lcd_tcon_setb(pdrv, 0x367, 1, 16, 1); // enale tcon intr lcd_tcon_setb(pdrv, 0x207, 1, 31, 1); //enable dma clk } @@ -66,6 +136,9 @@ void lcd_tcon_lut_dma_disable(struct aml_lcd_drv_s *pdrv) if (!pdrv) return; + lcd_tcon_setb(pdrv, 0x367, 0, 16, 1); // disable tcon intr + lcd_tcon_setb(pdrv, 0x367, 0, 16, 1); // disable tcon intr + lcd_tcon_setb(pdrv, 0x367, 0, 16, 1); // disable tcon intr lcd_tcon_setb(pdrv, 0x367, 0, 16, 1); // disable tcon intr lcd_tcon_setb(pdrv, 0x207, 0, 31, 1); //disable dma } @@ -539,20 +612,21 @@ static int lcd_tcon_wr_n_data_write(struct aml_lcd_drv_s *pdrv, } int lcd_tcon_data_common_parse_set(struct aml_lcd_drv_s *pdrv, - unsigned char *data_buf, int init_flag) + unsigned char *data_buf, phys_addr_t paddr, int init_flag) { struct lcd_tcon_config_s *tcon_conf = get_lcd_tcon_config(); struct lcd_tcon_data_block_header_s *block_header; struct lcd_tcon_data_block_ext_header_s *ext_header; - unsigned char *p; + unsigned char *p, *part_start; unsigned short part_cnt; unsigned char part_type; unsigned int size, reg, data, mask, temp, reg_base = 0; union lcd_tcon_data_part_u data_part; - unsigned int data_offset, offset, i, j, k, d, m, n, step = 0; + unsigned int data_offset = 0, offset, i, j, k, d, m, n, step = 0; unsigned int reg_cnt, reg_byte, data_cnt, data_byte; unsigned short block_ctrl_flag; unsigned char exe_in_isr = 0, exe_ignore = 0; + unsigned int *part_pos, part_start_offset, ext_header_size; int ret; if (tcon_conf) @@ -566,12 +640,16 @@ int lcd_tcon_data_common_parse_set(struct aml_lcd_drv_s *pdrv, (lcd_debug_print_flag & LCD_DBG_PR_ADV)) { LCDPR("%s: %s, part_cnt: %d\n", __func__, block_header->name, part_cnt); } + part_pos = (unsigned int *)(p + LCD_TCON_DATA_BLOCK_EXT_HEADER_SIZE_PRE); + ext_header_size = block_header->ext_header_size; block_ctrl_flag = block_header->block_ctrl; - data_offset = LCD_TCON_DATA_BLOCK_HEADER_SIZE + block_header->ext_header_size; + part_start = data_buf + LCD_TCON_DATA_BLOCK_HEADER_SIZE + ext_header_size; size = 0; + part_start_offset = LCD_TCON_DATA_BLOCK_HEADER_SIZE + ext_header_size; for (i = 0; i < part_cnt; i++) { - p = data_buf + data_offset; + p = part_start + part_pos[i]; + data_offset = part_start_offset + part_pos[i]; part_type = p[LCD_TCON_DATA_PART_NAME_SIZE + 3]; exe_in_isr = p[LCD_TCON_DATA_PART_NAME_SIZE + 2]; exe_ignore = (exe_in_isr & LCD_TCON_DATA_PART_FLAG_CMD_IGNORE_ISR) && @@ -901,6 +979,32 @@ int lcd_tcon_data_common_parse_set(struct aml_lcd_drv_s *pdrv, break; } break; + case LCD_TCON_DATA_PART_TYPE_DMA: + if (block_ctrl_flag) + goto lcd_tcon_data_common_parse_set_ctrl_err; + data_part.dma = (struct lcd_tcon_data_part_dma_s *)p; + + size = LCD_TCON_DATA_PART_DMA_SIZE_PRE + data_part.dma->dma_data_size; + if ((size + data_offset) > block_header->block_size) + goto lcd_tcon_data_common_parse_set_err_size; + + offset = p - data_buf + LCD_TCON_DATA_PART_DMA_SIZE_PRE; + if ((lcd_debug_print_flag & LCD_DBG_PR_ADV)) + LCDPR("%s: vaddr:0x%px, paddr:0x%llx,\n" + "offset:0x%x, size:0x%x\n", + __func__, data_buf, (unsigned long long)paddr, + offset, data_part.dma->dma_data_size); + paddr += offset; + if (!paddr || paddr & 0xf || data_part.dma->dma_data_size & 0xf) + break; + + lcd_tcon_dma_update_add(paddr, data_part.dma->dma_data_size); + if (exe_ignore) { + if ((lcd_debug_print_flag & LCD_DBG_PR_ADV)) + LCDPR("%s step %d ignored\n", __func__, step); + break; + } + break; default: if (block_ctrl_flag) goto lcd_tcon_data_common_parse_set_ctrl_err; @@ -914,7 +1018,6 @@ int lcd_tcon_data_common_parse_set(struct aml_lcd_drv_s *pdrv, LCDPR("%s: end step %d, %s, type=0x%02x, size=%d\n", __func__, step, p, part_type, size); } - data_offset += size; step++; } @@ -942,6 +1045,7 @@ static int lcd_tcon_data_set(struct aml_lcd_drv_s *pdrv, unsigned char *data_buf; unsigned int temp_crc32; unsigned int i, index, chk_size; + phys_addr_t paddr = 0; int ret; if (!mm_table->data_mem_vaddr) { @@ -967,6 +1071,7 @@ static int lcd_tcon_data_set(struct aml_lcd_drv_s *pdrv, continue; } data_buf = mm_table->data_mem_vaddr[index]; + paddr = mm_table->data_mem_paddr[index]; block_header = (struct lcd_tcon_data_block_header_s *)data_buf; if (block_header->block_size < sizeof(struct lcd_tcon_data_block_header_s)) { LCDERR("%s: block_size[%d] 0x%x is invalid\n", @@ -994,22 +1099,22 @@ static int lcd_tcon_data_set(struct aml_lcd_drv_s *pdrv, } /* apply data */ - if (block_header->block_type == LCD_TCON_DATA_BLOCK_TYPE_BASIC_INIT) { + if (is_block_type_basic_init(block_header->block_type)) { lcd_tcon_data_init_set(pdrv, data_buf); continue; } - if (block_header->block_ctrl == LCD_TCON_DATA_CTRL_FLAG_MULTI) { + if (is_block_ctrl_multi(block_header->block_ctrl)) { ret = lcd_tcon_data_multi_match_find(pdrv, data_buf); if (ret == 0) { - ret = lcd_tcon_data_common_parse_set(pdrv, data_buf, 1); + ret = lcd_tcon_data_common_parse_set(pdrv, data_buf, paddr, 1); if (ret == 0) { lcd_tcon_data_multi_current_update(mm_table, block_header, index); } } } else { - lcd_tcon_data_common_parse_set(pdrv, data_buf, 1); + lcd_tcon_data_common_parse_set(pdrv, data_buf, paddr, 1); } } diff --git a/drivers/media/vout/lcd/lcd_venc/lcd_venc_dft.c b/drivers/media/vout/lcd/lcd_venc/lcd_venc_dft.c index 2169aa162..d57c487de 100644 --- a/drivers/media/vout/lcd/lcd_venc/lcd_venc_dft.c +++ b/drivers/media/vout/lcd/lcd_venc/lcd_venc_dft.c @@ -160,12 +160,15 @@ static void lcd_test_pattern_init(struct aml_lcd_drv_s *pdrv, unsigned int num) static void lcd_venc_gamma_init(struct aml_lcd_drv_s *pdrv) { + unsigned int data[2]; int index = pdrv->index; if (pdrv->lcd_pxp) return; - aml_lcd_notifier_call_chain(LCD_EVENT_GAMMA_UPDATE, &index); + data[0] = index; + data[1] = 0xff; //default gamma lut + aml_lcd_atomic_notifier_call_chain(LCD_EVENT_GAMMA_UPDATE, (void *)data); lcd_venc_gamma_check_en(pdrv); } diff --git a/drivers/media/vout/lcd/lcd_venc/lcd_venc_t3x.c b/drivers/media/vout/lcd/lcd_venc/lcd_venc_t3x.c index ff1bd476a..9aae2b818 100644 --- a/drivers/media/vout/lcd/lcd_venc/lcd_venc_t3x.c +++ b/drivers/media/vout/lcd/lcd_venc/lcd_venc_t3x.c @@ -199,12 +199,15 @@ static int lcd_venc_debug_test(struct aml_lcd_drv_s *pdrv, unsigned int num) static void lcd_venc_gamma_init(struct aml_lcd_drv_s *pdrv) { + unsigned int data[2]; int index = pdrv->index; if (pdrv->lcd_pxp) return; - aml_lcd_notifier_call_chain(LCD_EVENT_GAMMA_UPDATE, &index); + data[0] = index; + data[1] = 0xff; //default gamma lut + aml_lcd_atomic_notifier_call_chain(LCD_EVENT_GAMMA_UPDATE, (void *)data); lcd_venc_gamma_check_en(pdrv); } diff --git a/drivers/media/vout/lcd/lcd_venc/lcd_venc_t7.c b/drivers/media/vout/lcd/lcd_venc/lcd_venc_t7.c index c12383e4e..f87e9bca1 100644 --- a/drivers/media/vout/lcd/lcd_venc/lcd_venc_t7.c +++ b/drivers/media/vout/lcd/lcd_venc/lcd_venc_t7.c @@ -182,12 +182,15 @@ static void lcd_test_pattern_init(struct aml_lcd_drv_s *pdrv, unsigned int num) static void lcd_venc_gamma_init(struct aml_lcd_drv_s *pdrv) { + unsigned int data[2]; int index = pdrv->index; if (pdrv->lcd_pxp) return; - aml_lcd_notifier_call_chain(LCD_EVENT_GAMMA_UPDATE, &index); + data[0] = index; + data[1] = 0xff; //default gamma lut + aml_lcd_atomic_notifier_call_chain(LCD_EVENT_GAMMA_UPDATE, (void *)data); lcd_venc_gamma_check_en(pdrv); } diff --git a/drivers/media/vout/lcd/lcd_vout.c b/drivers/media/vout/lcd/lcd_vout.c index 9738dbe9f..dbe61d427 100644 --- a/drivers/media/vout/lcd/lcd_vout.c +++ b/drivers/media/vout/lcd/lcd_vout.c @@ -2193,6 +2193,7 @@ static int lcd_probe(struct platform_device *pdev) pdrv->data = pdata; //pdrv->of_node = pdev->dev.of_node; platform_set_drvdata(pdev, pdrv); + pdrv->pdev = pdev; #ifdef CONFIG_AMLOGIC_VPU /*vpu dev register for lcd*/ @@ -2212,6 +2213,7 @@ static int lcd_probe(struct platform_device *pdev) ret = lcd_cdev_add(pdrv, &pdev->dev); if (ret) goto lcd_probe_err_2; + ret = lcd_config_probe(pdrv, pdev); if (ret) goto lcd_probe_err_2; diff --git a/include/linux/amlogic/media/vout/lcd/lcd_tcon_data.h b/include/linux/amlogic/media/vout/lcd/lcd_tcon_data.h index 698d1e0e0..ca3df1e2e 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_tcon_data.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_tcon_data.h @@ -26,6 +26,7 @@ #define LCD_TCON_DATA_BLOCK_TYPE_VAC 0x11 #define LCD_TCON_DATA_BLOCK_TYPE_EXT 0xe0 /* pmu */ #define LCD_TCON_DATA_BLOCK_TYPE_MAX 0xff +#define is_block_type_basic_init(type) ((type) == LCD_TCON_DATA_BLOCK_TYPE_BASIC_INIT) /* for tconless data block part type */ #define LCD_TCON_DATA_PART_TYPE_WR_N 0xd0 @@ -34,6 +35,7 @@ #define LCD_TCON_DATA_PART_TYPE_RD_MASK 0xab #define LCD_TCON_DATA_PART_TYPE_CHK_WR_MASK 0xcb #define LCD_TCON_DATA_PART_TYPE_CHK_EXIT 0xce +#define LCD_TCON_DATA_PART_TYPE_DMA 0xc0 #define LCD_TCON_DATA_PART_TYPE_PARAM 0xf0 /* only for tool */ #define LCD_TCON_DATA_PART_TYPE_CONTROL 0xfc #define LCD_TCON_DATA_PART_TYPE_DELAY 0xfd @@ -47,15 +49,23 @@ #define LCD_TCON_DATA_PART_FLAG_CMD_IGNORE_ISR 0x80 #define LCD_TCON_DATA_BLOCK_HEADER_SIZE 64 +#define LCD_TCON_DATA_BLOCK_EXT_HEADER_SIZE_PRE 16 #define LCD_TCON_DATA_BLOCK_NAME_SIZE 36 #define LCD_TCON_DATA_PART_NAME_SIZE 48 #define LCD_TCON_INIT_BIN_NAME_SIZE 28 #define LCD_TCON_INIT_BIN_VERSION_SIZE 8 /* tcon data control define */ -/* block_ctrl */ +/* block_ctrl for normal tcon data*/ #define LCD_TCON_DATA_CTRL_FLAG_MULTI 0x01 +#define LCD_TCON_DATA_CTRL_FLAG_DMA 0x02 +/*FLAG_DLG only for basic init data*/ #define LCD_TCON_DATA_CTRL_FLAG_DLG 0xd0 + +#define is_block_ctrl_dma(block_ctrl) ((block_ctrl) & LCD_TCON_DATA_CTRL_FLAG_DMA) +#define is_block_ctrl_multi(block_ctrl) ((block_ctrl) & LCD_TCON_DATA_CTRL_FLAG_MULTI) +#define is_block_ctrl_dlg(block_ctrl) ((block_ctrl) == LCD_TCON_DATA_CTRL_FLAG_DLG) + /* ctrl_method */ #define LCD_TCON_DATA_CTRL_DEFAULT 0x00 #define LCD_TCON_DATA_CTRL_MULTI_VFREQ_DIRECT 0x01 @@ -197,6 +207,17 @@ struct lcd_tcon_data_part_param_s { unsigned int param_size; }; +#define LCD_TCON_DATA_PART_DMA_SIZE_PRE (LCD_TCON_DATA_PART_NAME_SIZE + 16) +struct lcd_tcon_data_part_dma_s { + char name[LCD_TCON_DATA_PART_NAME_SIZE]; + unsigned short part_id; + unsigned char tuning_flag; + unsigned char part_type; + unsigned int dma_data_size; + unsigned char data_byte; + unsigned char reserved[7]; +}; + union lcd_tcon_data_part_u { struct lcd_tcon_data_part_ctrl_s *ctrl; struct lcd_tcon_data_part_wr_n_s *wr_n; @@ -207,6 +228,7 @@ union lcd_tcon_data_part_u { struct lcd_tcon_data_part_chk_exit_s *chk_exit; struct lcd_tcon_data_part_delay_s *delay; struct lcd_tcon_data_part_param_s *param; + struct lcd_tcon_data_part_dma_s *dma; }; #define LCD_UKEY_TCON_SPI_BLOCK_SIZE_PRE 20 diff --git a/include/linux/amlogic/media/vout/lcd/lcd_vout.h b/include/linux/amlogic/media/vout/lcd/lcd_vout.h index c994c65c8..d1b195622 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_vout.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_vout.h @@ -679,6 +679,7 @@ struct aml_lcd_drv_s { unsigned char gamma_en_flag; unsigned char projection_en; unsigned char vsync_none_timer_flag; + signed char lcd_cma_ready; char vsync_isr_name[3][15]; char vbyone_isr_name[10]; char output_name[30]; @@ -687,6 +688,7 @@ struct aml_lcd_drv_s { struct lcd_data_s *data; struct cdev cdev; struct device *dev; + struct platform_device *pdev; struct lcd_config_s config; struct lcd_duration_s *std_duration; struct lcd_duration_s cur_duration;