summaryrefslogtreecommitdiff
authorDezhi Kong <dezhi.kong@amlogic.com>2019-06-11 12:29:40 (GMT)
committer Dezhi Kong <dezhi.kong@amlogic.com>2019-07-11 02:10:57 (GMT)
commit1f1efcfdd85da5a5948432c21e9a2295e65905f5 (patch)
treebfa210afd6f010ae0845c2536a7da59c2b630e02
parent069f36f89710c343e46f7160cf6e8069c8412111 (diff)
downloadcommon-1f1efcfdd85da5a5948432c21e9a2295e65905f5.zip
common-1f1efcfdd85da5a5948432c21e9a2295e65905f5.tar.gz
common-1f1efcfdd85da5a5948432c21e9a2295e65905f5.tar.bz2
drm: add multi-layer support [1/1]
PD#SWPL-9646 Problem: unsupport multi-layer Solution: add multi-layer support Verify: verify by w400 with modetest command Change-Id: I5cd50761d2ab9cfff0f80d38e20455044c7a33fd Signed-off-by: Dezhi Kong <dezhi.kong@amlogic.com>
Diffstat
-rw-r--r--MAINTAINERS28
-rw-r--r--arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts1
-rw-r--r--arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts3
-rw-r--r--arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts1
-rw-r--r--arch/arm/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts1469
-rw-r--r--arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi135
-rw-r--r--arch/arm/boot/dts/amlogic/mesong12b_drm.dtsi241
-rw-r--r--arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts1
-rw-r--r--arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts3
-rw-r--r--arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts1
-rw-r--r--arch/arm64/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts1473
-rw-r--r--arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi137
-rw-r--r--arch/arm64/boot/dts/amlogic/mesong12b_drm.dtsi241
-rw-r--r--drivers/amlogic/Makefile2
-rw-r--r--drivers/amlogic/drm/Kconfig39
-rw-r--r--drivers/amlogic/drm/Makefile36
-rw-r--r--drivers/amlogic/drm/am_meson_fbdev.h24
-rw-r--r--drivers/amlogic/drm/drm-v0/Kconfig52
-rw-r--r--drivers/amlogic/drm/drm-v0/Makefile28
-rw-r--r--drivers/amlogic/drm/drm-v0/am_meson_drv.c (copied from drivers/amlogic/drm/am_meson_drv.c)25
-rw-r--r--drivers/amlogic/drm/drm-v0/am_meson_drv.h (copied from drivers/amlogic/drm/am_meson_drv.h)23
-rw-r--r--drivers/amlogic/drm/drm-v0/am_meson_fb.c (copied from drivers/amlogic/drm/am_meson_fb.c)3
-rw-r--r--drivers/amlogic/drm/drm-v0/am_meson_fb.h (copied from drivers/amlogic/drm/am_meson_fb.h)2
-rw-r--r--drivers/amlogic/drm/drm-v0/am_meson_fbdev.c (copied from drivers/amlogic/drm/am_meson_fbdev.c)18
-rw-r--r--drivers/amlogic/drm/drm-v0/am_meson_fbdev.h (copied from drivers/amlogic/drm/am_meson_lcd.h)12
-rw-r--r--drivers/amlogic/drm/drm-v0/am_meson_gem.c (copied from drivers/amlogic/drm/am_meson_gem.c)15
-rw-r--r--drivers/amlogic/drm/drm-v0/am_meson_gem.h (copied from drivers/amlogic/drm/am_meson_gem.h)4
-rw-r--r--drivers/amlogic/drm/drm-v0/am_meson_hdcp.c (copied from drivers/amlogic/drm/am_meson_hdcp.c)2
-rw-r--r--drivers/amlogic/drm/drm-v0/am_meson_hdcp.h (copied from drivers/amlogic/drm/am_meson_hdcp.h)2
-rw-r--r--drivers/amlogic/drm/drm-v0/am_meson_hdmi.c (copied from drivers/amlogic/drm/am_meson_hdmi.c)3
-rw-r--r--drivers/amlogic/drm/drm-v0/am_meson_hdmi.h (copied from drivers/amlogic/drm/am_meson_hdmi.h)3
-rw-r--r--drivers/amlogic/drm/drm-v0/am_meson_lcd.c (copied from drivers/amlogic/drm/am_meson_lcd.c)4
-rw-r--r--drivers/amlogic/drm/drm-v0/am_meson_lcd.h (copied from drivers/amlogic/drm/am_meson_lcd.h)2
-rw-r--r--drivers/amlogic/drm/drm-v0/am_meson_vpu.c (renamed from drivers/amlogic/drm/am_meson_vpu.c)3
-rw-r--r--drivers/amlogic/drm/drm-v0/am_meson_vpu.h (copied from drivers/amlogic/drm/am_meson_vpu.h)3
-rw-r--r--drivers/amlogic/drm/meson_crtc.c270
-rw-r--r--drivers/amlogic/drm/meson_crtc.h65
-rw-r--r--drivers/amlogic/drm/meson_drv.c (renamed from drivers/amlogic/drm/am_meson_drv.c)55
-rw-r--r--drivers/amlogic/drm/meson_drv.h (renamed from drivers/amlogic/drm/am_meson_drv.h)33
-rw-r--r--drivers/amlogic/drm/meson_fb.c (renamed from drivers/amlogic/drm/am_meson_fb.c)5
-rw-r--r--drivers/amlogic/drm/meson_fb.h (renamed from drivers/amlogic/drm/am_meson_fb.h)4
-rw-r--r--drivers/amlogic/drm/meson_fbdev.c (renamed from drivers/amlogic/drm/am_meson_fbdev.c)26
-rw-r--r--drivers/amlogic/drm/meson_fbdev.h (copied from drivers/amlogic/drm/am_meson_lcd.h)12
-rw-r--r--drivers/amlogic/drm/meson_gem.c (renamed from drivers/amlogic/drm/am_meson_gem.c)18
-rw-r--r--drivers/amlogic/drm/meson_gem.h (renamed from drivers/amlogic/drm/am_meson_gem.h)6
-rw-r--r--drivers/amlogic/drm/meson_hdcp.c (renamed from drivers/amlogic/drm/am_meson_hdcp.c)6
-rw-r--r--drivers/amlogic/drm/meson_hdcp.h (renamed from drivers/amlogic/drm/am_meson_hdcp.h)2
-rw-r--r--drivers/amlogic/drm/meson_hdmi.c (renamed from drivers/amlogic/drm/am_meson_hdmi.c)51
-rw-r--r--drivers/amlogic/drm/meson_hdmi.h (renamed from drivers/amlogic/drm/am_meson_hdmi.h)17
-rw-r--r--drivers/amlogic/drm/meson_lcd.c (renamed from drivers/amlogic/drm/am_meson_lcd.c)32
-rw-r--r--drivers/amlogic/drm/meson_lcd.h (renamed from drivers/amlogic/drm/am_meson_lcd.h)4
-rw-r--r--drivers/amlogic/drm/meson_plane.c498
-rw-r--r--drivers/amlogic/drm/meson_plane.h50
-rw-r--r--drivers/amlogic/drm/meson_vpu.c573
-rw-r--r--drivers/amlogic/drm/meson_vpu.h (copied from drivers/amlogic/drm/am_meson_vpu.h)17
-rw-r--r--drivers/amlogic/drm/meson_vpu_pipeline.c410
-rw-r--r--drivers/amlogic/drm/meson_vpu_pipeline.h451
-rw-r--r--drivers/amlogic/drm/meson_vpu_pipeline_private.c480
-rw-r--r--drivers/amlogic/drm/meson_vpu_pipeline_traverse.c658
-rw-r--r--drivers/amlogic/drm/meson_vpu_util.c177
-rw-r--r--drivers/amlogic/drm/meson_vpu_util.h62
-rw-r--r--drivers/amlogic/drm/vpu-hw/meson_osd_afbc.c626
-rw-r--r--drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c616
-rw-r--r--drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h118
-rw-r--r--drivers/amlogic/drm/vpu-hw/meson_vpu_dev.c (renamed from drivers/amlogic/drm/am_meson_vpu.h)24
-rw-r--r--drivers/amlogic/drm/vpu-hw/meson_vpu_hdr_dv.c110
-rw-r--r--drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c436
-rw-r--r--drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.h153
-rw-r--r--drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.c520
-rw-r--r--drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.h74
-rw-r--r--drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.c184
-rw-r--r--drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.h59
-rw-r--r--drivers/amlogic/drm/vpu-hw/meson_vpu_reg.h1323
-rw-r--r--include/dt-bindings/display/meson-drm-ids.h53
-rw-r--r--include/linux/amlogic/meson_drm.h72
-rw-r--r--include/uapi/drm/drm_fourcc.h4
-rw-r--r--include/uapi/drm/meson_drm.h49
77 files changed, 12117 insertions, 325 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 0f36a16..5f1d410 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15046,3 +15046,31 @@ M: Cheng Wang <cheng.wang@amlogic.com>
F: drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.c
F: drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.h
+AMLOGIC DRM
+M: Ao Xu <ao.xu@amlogic.com>
+M: Dezhi Kong <dezhi.kong@amlogic.com>
+F: include/linux/meson_ion.h
+F: include/uapi/drm/meson_drm.h
+F: include/uapi/drm/drm_fourcc.c
+F: drivers/gpu/Makefile
+F: drivers/amlogic/Kconfig
+F: drivers/amlogic/Makefile
+F: drivers/amlogic/drm/*
+F: drivers/staging/android/ion/ion.h
+F: drivers/staging/android/ion/ion_cma_heap.c
+F: drivers/amlogic/media/osd/osd_fb.c
+F: drivers/amlogic/media/common/ion_dev/dev_ion.c
+F: drivers/amlogic/media/common/ion_dev/dev_ion.h
+F: arch/arm/boot/dts/amlogic/meson-g12a-u200.dts
+F: arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi
+F: arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts
+F: arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts
+F: arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts
+F: arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi
+F: arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts
+F: arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts
+F: arch/arm/configs/meson64_a32_defconfig
+F: arch/arm64/configs/meson64_a64_defconfig
+F: arch/arm/boot/dts/amlogic/Makefile
+F: arch/arm64/boot/dts/amlogic/Makefile
+
diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts
index 7b40c1c..c816c8f 100644
--- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts
+++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts
@@ -819,6 +819,7 @@
&drm_vpu {
status = "okay";
logo_addr = "0x7f800000";
+ osd_ver = /bits/ 8 <OSD_V1>;
};
&drm_amhdmitx {
diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts
index 320f0aa..d9a3ed0 100644
--- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts
+++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts
@@ -19,7 +19,7 @@
#include "mesong12b.dtsi"
#include "mesong12b_skt-panel.dtsi"
-#include "mesong12a_drm.dtsi"
+#include "mesong12b_drm.dtsi"
/ {
model = "Amlogic";
@@ -1515,6 +1515,7 @@
status = "okay";
compatible = "amlogic,meson-g12b-vpu";
logo_addr = "0x7f800000";
+ osd_ver = /bits/ 8 <OSD_V3>;
};
&drm_amhdmitx {
diff --git a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts
index f21d6de..e889c247 100644
--- a/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts
+++ b/arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts
@@ -1481,6 +1481,7 @@
status = "okay";
compatible = "amlogic,meson-g12b-vpu";
logo_addr = "0x7f800000";
+ osd_ver = /bits/ 8 <OSD_V2>;
};
&drm_amhdmitx {
diff --git a/arch/arm/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts b/arch/arm/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts
new file mode 100644
index 0000000..3e069bc
--- a/dev/null
+++ b/arch/arm/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts
@@ -0,0 +1,1469 @@
+/*
+ * arch/arm/boot/dts/amlogic/g12b_a311d_w400_buildroot_a.dts
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+/dts-v1/;
+
+#include "mesong12b_a.dtsi"
+#include "mesong12b_skt-panel.dtsi"
+#include "mesong12b_drm.dtsi"
+
+/ {
+ model = "Amlogic";
+ amlogic-dt-id = "g12b_w400_a";
+ compatible = "amlogic, g12b";
+ interrupt-parent = <&gic>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ aliases {
+ serial0 = &uart_AO;
+ serial1 = &uart_A;
+ serial2 = &uart_B;
+ serial3 = &uart_C;
+ serial4 = &uart_AO_B;
+ i2c0 = &i2c0;
+ i2c1 = &i2c1;
+ i2c2 = &i2c2;
+ i2c3 = &i2c3;
+ i2c4 = &i2c_AO;
+ tsensor0 = &p_tsensor;
+ tsensor1 = &d_tsensor;
+ };
+
+ memory@00000000 {
+ device_type = "memory";
+ linux,usable-memory = <0x100000 0x7ff00000>;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ /* global autoconfigured region for contiguous allocations */
+ ramoops@0x07400000 {
+ compatible = "ramoops";
+ reg = <0x07400000 0x00100000>;
+ record-size = <0x8000>;
+ console-size = <0x8000>;
+ ftrace-size = <0x0>;
+ pmsg-size = <0x8000>;
+ };
+
+ secmon_reserved:linux,secmon {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x400000>;
+ alignment = <0x400000>;
+ alloc-ranges = <0x05000000 0x400000>;
+ clear-map;
+ };
+
+ secos_reserved:linux,secos {
+ status = "disable";
+ compatible = "amlogic, aml_secos_memory";
+ reg = <0x05300000 0x2000000>;
+ no-map;
+ };
+ logo_reserved:linux,meson-fb {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x800000>;
+ alignment = <0x400000>;
+ alloc-ranges = <0x7f800000 0x800000>;
+ };
+ ion_cma_reserved:linux,ion-dev {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x8000000>;
+ alignment = <0x400000>;
+ };
+
+ //di_reserved:linux,di {
+ //compatible = "amlogic, di-mem";
+ /* buffer_size = 3621952(yuv422 8bit) */
+ /* 4179008(yuv422 10bit full pack mode) */
+ /** 10x3621952=34.6M(0x23) support 8bit **/
+ /** 10x4736064=45.2M(0x2e) support 12bit **/
+ /** 10x4179008=40M(0x28) support 10bit **/
+ //size = <0x2800000>;
+ //no-map;
+ //};
+ /*di CMA pool */
+ di_cma_reserved:linux,di_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ /* buffer_size = 3621952(yuv422 8bit)
+ * | 4736064(yuv422 10bit)
+ * | 4074560(yuv422 10bit full pack mode)
+ * 10x3621952=34.6M(0x23) support 8bit
+ * 10x4736064=45.2M(0x2e) support 12bit
+ * 10x4074560=40M(0x28) support 10bit
+ */
+ size = <0x02800000>;
+ alignment = <0x400000>;
+ };
+ /* POST PROCESS MANAGER */
+ ppmgr_reserved:linux,ppmgr {
+ compatible = "shared-dma-pool";
+ size = <0x0>;
+ };
+ codec_mm_cma:linux,codec_mm_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ /* ion_codec_mm max can alloc size 80M*/
+ size = <0x13400000>;
+ alignment = <0x400000>;
+ linux,contiguous-region;
+ };
+ /* codec shared reserved */
+ codec_mm_reserved:linux,codec_mm_reserved {
+ compatible = "amlogic, codec-mm-reserved";
+ size = <0x0>;
+ alignment = <0x100000>;
+ //no-map;
+ };
+ /* vdin0 CMA pool */
+ vdin0_cma_reserved:linux,vdin0_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ /* 1920x1080x2x4 =16+4 M */
+ size = <0x04000000>;
+ alignment = <0x400000>;
+ };
+ /* vdin1 CMA pool */
+ vdin1_cma_reserved:linux,vdin1_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ /* 1920x1080x2x4 =16 M */
+ size = <0x04000000>;
+ alignment = <0x400000>;
+ };
+ galcore_reserved:linux,galcore {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x1000000>;
+ alignment = <0x400000>;
+ linux,contiguous-region;
+ };
+
+ isp_cma_reserved:linux,isp_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ status = "okay";
+ size = <0x1f000000>;
+ alignment = <0x400000>;
+ };
+
+ adapt_cma_reserved:linux,adapt_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ status = "okay";
+ size = <0x03000000>;
+ alignment = <0x400000>;
+ };
+ gdc_cma_reserved:linux,gdc_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ status = "okay";
+ size = <0x04000000>;
+ alignment = <0x400000>;
+ };
+ };
+ galcore {
+ status = "okay";
+ memory-region = <&galcore_reserved>;
+ };
+ gpioleds {
+ compatible = "gpio-leds";
+ status = "okay";
+
+ sys_led {
+ label="sys_led";
+ gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>;
+ default-state ="on";
+ retain-state-suspended;
+ linux,default-trigger="cpu0";
+ };
+ };
+
+ cvbsout {
+ compatible = "amlogic, cvbsout-g12b";
+ dev_name = "cvbsout";
+ status = "okay";
+ clocks = <&clkc CLKID_VCLK2_ENCI
+ &clkc CLKID_VCLK2_VENCI0
+ &clkc CLKID_VCLK2_VENCI1
+ &clkc CLKID_DAC_CLK>;
+ clock-names = "venci_top_gate",
+ "venci_0_gate",
+ "venci_1_gate",
+ "vdac_clk_gate";
+
+ /* performance: reg_address, reg_value */
+ /* g12b */
+ performance = <0x1bf0 0x9
+ 0x1b56 0x333
+ 0x1b12 0x8080
+ 0x1b05 0xfd
+ 0x1c59 0xf850
+ 0xffff 0x0>; /* ending flag */
+ performance_sarft = <0x1bf0 0x9
+ 0x1b56 0x333
+ 0x1b12 0x0
+ 0x1b05 0x9
+ 0x1c59 0xfc48
+ 0xffff 0x0>; /* ending flag */
+ };
+
+ bt-dev{
+ compatible = "amlogic, bt-dev";
+ dev_name = "bt-dev";
+ status = "okay";
+ gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
+ gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>;
+ };
+
+ wifi{
+ compatible = "amlogic, aml_wifi";
+ dev_name = "aml_wifi";
+ status = "okay";
+ interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>;
+ irq_trigger_type = "GPIO_IRQ_LOW";
+ power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>;
+ dhd_static_buf; //if use bcm wifi, config dhd_static_buf
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm_e_pins>;
+ pwm_config = <&wifi_pwm_conf>;
+ };
+
+ wifi_pwm_conf:wifi_pwm_conf{
+ pwm_channel1_conf {
+ pwms = <&pwm_ef MESON_PWM_0 30541 0>;
+ duty-cycle = <15270>;
+ times = <10>;
+ };
+ pwm_channel2_conf {
+ pwms = <&pwm_ef MESON_PWM_2 30500 0>;
+ duty-cycle = <15250>;
+ times = <12>;
+ };
+ };
+
+ codec_mm {
+ compatible = "amlogic, codec, mm";
+ memory-region = <&codec_mm_cma &codec_mm_reserved>;
+ dev_name = "codec_mm";
+ status = "okay";
+ };
+
+ ppmgr {
+ compatible = "amlogic, ppmgr";
+ memory-region = <&ppmgr_reserved>;
+ dev_name = "ppmgr";
+ status = "okay";
+ };
+
+ deinterlace {
+ compatible = "amlogic, deinterlace";
+ status = "okay";
+ /* 0:use reserved; 1:use cma; 2:use cma as reserved */
+ flag_cma = <1>;
+ //memory-region = <&di_reserved>;
+ memory-region = <&di_cma_reserved>;
+ interrupts = <0 46 1
+ 0 40 1>;
+ interrupt-names = "pre_irq", "post_irq";
+ clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>,
+ <&clkc CLKID_VPU_CLKB_COMP>;
+ clock-names = "vpu_clkb_tmp_composite",
+ "vpu_clkb_composite";
+ clock-range = <334 667>;
+ /* buffer-size = <3621952>;(yuv422 8bit) */
+ buffer-size = <4074560>;/*yuv422 fullpack*/
+ /* reserve-iomap = "true"; */
+ /* if enable nr10bit, set nr10bit-support to 1 */
+ post-wr-support = <1>;
+ nr10bit-support = <1>;
+ nrds-enable = <1>;
+ pps-enable = <1>;
+ };
+ ionvideo {
+ compatible = "amlogic, ionvideo";
+ dev_name = "ionvideo";
+ status = "okay";
+ };
+
+
+ partitions: partitions{
+ parts = <14>;
+ part-0 = <&logo>;
+ part-1 = <&recovery>;
+ part-2 = <&misc>;
+ part-3 = <&dto>;
+ part-4 = <&cri_data>;
+ part-5 = <&param>;
+ part-6 = <&boot>;
+ part-7 = <&rsv>;
+ part-8 = <&tee>;
+ part-9 = <&vendor>;
+ part-10 = <&odm>;
+ part-11 = <&system>;
+ part-12 = <&cache>;
+ part-13 = <&data>;
+
+ logo:logo{
+ pname = "logo";
+ size = <0x0 0x800000>;
+ mask = <1>;
+ };
+ recovery:recovery{
+ pname = "recovery";
+ size = <0x0 0x1800000>;
+ mask = <1>;
+ };
+ misc:misc{
+ pname = "misc";
+ size = <0x0 0x800000>;
+ mask = <1>;
+ };
+ dto:dto{
+ pname = "dto";
+ size = <0x0 0x800000>;
+ mask = <1>;
+ };
+ cri_data:cri_data{
+ pname = "cri_data";
+ size = <0x0 0x800000>;
+ mask = <2>;
+ };
+ rsv:rsv{
+ pname = "rsv";
+ size = <0x0 0x1000000>;
+ mask = <1>;
+ };
+ param:param{
+ pname = "param";
+ size = <0x0 0x1000000>;
+ mask = <2>;
+ };
+ boot:boot{
+ pname = "boot";
+ size = <0x0 0x1000000>;
+ mask = <1>;
+ };
+ tee:tee{
+ pname = "tee";
+ size = <0x0 0x2000000>;
+ mask = <1>;
+ };
+ vendor:vendor{
+ pname = "vendor";
+ size = <0x0 0x10000000>;
+ mask = <1>;
+ };
+ odm:odm{
+ pname = "odm";
+ size = <0x0 0x10000000>;
+ mask = <1>;
+ };
+ system:system{
+ pname = "system";
+ size = <0x0 0x80000000>;
+ mask = <1>;
+ };
+ cache:cache{
+ pname = "cache";
+ size = <0x0 0x46000000>;
+ mask = <2>;
+ };
+ data:data{
+ pname = "data";
+ size = <0xffffffff 0xffffffff>;
+ mask = <4>;
+ };
+ };
+
+ gpio_keypad {
+ compatible = "amlogic, gpio_keypad";
+ status = "okay";
+ scan_period = <20>;
+ key_num = <1>;
+ key_name = "power";
+ key_code = <116>;
+ key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>;
+ detect_mode = <0>;/*0:polling mode, 1:irq mode*/
+ };
+
+ adc_keypad {
+ compatible = "amlogic, adc_keypad";
+ status = "okay";
+ key_name = "vol-", "vol+", "enter";
+ key_num = <3>;
+ io-channels = <&saradc SARADC_CH2>;
+ io-channel-names = "key-chan-2";
+ key_chan = <SARADC_CH2 SARADC_CH2 SARADC_CH2>;
+ key_code = <114 115 28>;
+ key_val = <143 266 389>; //val=voltage/1800mV*1023
+ key_tolerance = <40 40 40>;
+ };
+
+ unifykey{
+ compatible = "amlogic, unifykey";
+ status = "ok";
+ unifykey-num = <15>;
+ unifykey-index-0 = <&keysn_0>;
+ unifykey-index-1 = <&keysn_1>;
+ unifykey-index-2 = <&keysn_2>;
+ unifykey-index-3 = <&keysn_3>;
+ unifykey-index-4 = <&keysn_4>;
+ unifykey-index-5 = <&keysn_5>;
+ unifykey-index-6 = <&keysn_6>;
+ unifykey-index-7 = <&keysn_7>;
+ unifykey-index-8 = <&keysn_8>;
+ unifykey-index-9 = <&keysn_9>;
+ unifykey-index-10= <&keysn_10>;
+ unifykey-index-11= <&keysn_11>;
+ unifykey-index-12= <&keysn_12>;
+ unifykey-index-13= <&keysn_13>;
+ unifykey-index-14= <&keysn_14>;
+
+ keysn_0: key_0{
+ key-name = "usid";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_1:key_1{
+ key-name = "mac";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_2:key_2{
+ key-name = "hdcp";
+ key-device = "secure";
+ key-type = "sha1";
+ key-permit = "read","write","del";
+ };
+ keysn_3:key_3{
+ key-name = "secure_boot_set";
+ key-device = "efuse";
+ key-permit = "write";
+ };
+ keysn_4:key_4{
+ key-name = "mac_bt";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ key-type = "mac";
+ };
+ keysn_5:key_5{
+ key-name = "mac_wifi";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ key-type = "mac";
+ };
+ keysn_6:key_6{
+ key-name = "hdcp2_tx";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_7:key_7{
+ key-name = "hdcp2_rx";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_8:key_8{
+ key-name = "widevinekeybox";
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_9:key_9{
+ key-name = "deviceid";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_10:key_10{
+ key-name = "hdcp22_fw_private";
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_11:key_11{
+ key-name = "PlayReadykeybox25";
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_12:key_12{
+ key-name = "prpubkeybox";// PlayReady
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_13:key_13{
+ key-name = "prprivkeybox";// PlayReady
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_14:key_14{
+ key-name = "netflix_mgkid";
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ };//End unifykey
+
+ amlvecm {
+ compatible = "amlogic, vecm";
+ dev_name = "aml_vecm";
+ status = "okay";
+ gamma_en = <0>;/*1:enabel ;0:disable*/
+ wb_en = <0>;/*1:enabel ;0:disable*/
+ cm_en = <0>;/*1:enabel ;0:disable*/
+ };
+ amdolby_vision {
+ compatible = "amlogic, dolby_vision_g12a";
+ dev_name = "aml_amdolby_vision_driver";
+ status = "okay";
+ tv_mode = <0>;/*1:enabel ;0:disable*/
+ };
+
+ /* Audio Related start */
+ pdm_codec:dummy{
+ #sound-dai-cells = <0>;
+ compatible = "amlogic, pdm_dummy_codec";
+ status = "okay";
+ };
+ dummy_codec:dummy{
+ #sound-dai-cells = <0>;
+ compatible = "amlogic, aml_dummy_codec";
+ status = "okay";
+ };
+ amlogic_codec:t9015{
+ #sound-dai-cells = <0>;
+ compatible = "amlogic, aml_codec_T9015";
+ reg = <0xFF632000 0x2000>;
+ is_auge_used = <1>; /* meson or auge chipset used */
+ tdmout_index = <1>;
+ status = "okay";
+ };
+ audio_effect:eqdrc{
+ /*eq_enable = <1>;*/
+ /*drc_enable = <1>;*/
+ /*
+ * 0:tdmout_a
+ * 1:tdmout_b
+ * 2:tdmout_c
+ * 3:spdifout
+ * 4:spdifout_b
+ */
+ eqdrc_module = <1>;
+ /* max 0xf, each bit for one lane, usually one lane */
+ lane_mask = <0x1>;
+ /* max 0xff, each bit for one channel */
+ channel_mask = <0x3>;
+ };
+ auge_sound {
+ compatible = "amlogic, g12a-sound-card";
+ aml-audio-card,name = "AML-AUGESOUND";
+
+ //aml-audio-card,loopback = <&aml_loopback>;
+ //aml-audio-card,aux-devs = <&amlogic_codec>;
+ /*avout mute gpio*/
+ avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>;
+ /*for audio effect ,eqdrc */
+ aml-audio-card,effect = <&audio_effect>;
+
+ aml-audio-card,dai-link@0 {
+ format = "dsp_a";
+ mclk-fs = <512>;
+ //continuous-clock;
+ //bitclock-inversion;
+ //frame-inversion;
+ //bitclock-master = <&tdmacodec>;
+ //frame-master = <&tdmacodec>;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ suffix-name = "alsaPORT-pcm";
+ tdmacpu: cpu {
+ sound-dai = <&aml_tdma>;
+ dai-tdm-slot-tx-mask =
+ <1 1 1 1 1 1 1 1>;
+ dai-tdm-slot-rx-mask =
+ <1 1 1 1 1 1 1 1>;
+ dai-tdm-slot-num = <8>;
+ dai-tdm-slot-width = <32>;
+ system-clock-frequency = <24576000>;
+ };
+ tdmacodec: codec {
+ sound-dai = <&dummy_codec &dummy_codec>;
+ };
+ };
+
+ aml-audio-card,dai-link@1 {
+ format = "i2s";
+ mclk-fs = <256>;
+ continuous-clock;
+ //bitclock-inversion;
+ //frame-inversion;
+ bitclock-master = <&aml_tdmb>;
+ frame-master = <&aml_tdmb>;
+ //bitclock-master = <&tdmbcodec>;
+ //frame-master = <&tdmbcodec>;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ suffix-name = "alsaPORT-i2s";
+ cpu {
+ sound-dai = <&aml_tdmb>;
+ dai-tdm-slot-tx-mask = <1 1>;
+ dai-tdm-slot-rx-mask = <1 1>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <32>;
+ system-clock-frequency = <12288000>;
+ };
+ tdmbcodec: codec {
+ sound-dai = <&dummy_codec &dummy_codec
+ &amlogic_codec &ad82584f_62>;
+ };
+ };
+
+ aml-audio-card,dai-link@2 {
+ format = "i2s";
+ mclk-fs = <256>;
+ //continuous-clock;
+ //bitclock-inversion;
+ //frame-inversion;
+ bitclock-master = <&aml_tdmc>;
+ frame-master = <&aml_tdmc>;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ //suffix-name = "alsaPORT-tdm";
+ cpu {
+ sound-dai = <&aml_tdmc>;
+ dai-tdm-slot-tx-mask = <1 1>;
+ dai-tdm-slot-rx-mask = <1 1>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <32>;
+ system-clock-frequency = <12288000>;
+ };
+ codec {
+ sound-dai = <&dummy_codec &dummy_codec>;
+ };
+ };
+
+ aml-audio-card,dai-link@3 {
+ mclk-fs = <64>;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ suffix-name = "alsaPORT-pdm";
+ cpu {
+ sound-dai = <&aml_pdm>;
+ };
+ codec {
+ sound-dai = <&pdm_codec>;
+ };
+ };
+
+ aml-audio-card,dai-link@4 {
+ mclk-fs = <128>;
+ continuous-clock;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ suffix-name = "alsaPORT-spdif";
+ cpu {
+ sound-dai = <&aml_spdif>;
+ system-clock-frequency = <6144000>;
+ };
+ codec {
+ sound-dai = <&dummy_codec>;
+ };
+ };
+ };
+ audiolocker: locker {
+ compatible = "amlogic, audiolocker";
+ clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT
+ &clkaudio CLKID_AUDIO_LOCKER_IN
+ &clkaudio CLKID_AUDIO_MCLK_D
+ &clkaudio CLKID_AUDIO_MCLK_E
+ &clkc CLKID_MPLL1
+ &clkc CLKID_MPLL2>;
+ clock-names = "lock_out", "lock_in", "out_src",
+ "in_src", "out_calc", "in_ref";
+ interrupts = <GIC_SPI 1 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "irq";
+ frequency = <49000000>; /* pll */
+ dividor = <49>; /* locker's parent */
+ status = "okay";
+ };
+ /* Audio Related end */
+
+ cpu_opp_table0: cpu_opp_table0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp00 {
+ opp-hz = /bits/ 64 <100000000>;
+ opp-microvolt = <731000>;
+ };
+ opp01 {
+ opp-hz = /bits/ 64 <250000000>;
+ opp-microvolt = <731000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <731000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <667000000>;
+ opp-microvolt = <731000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <731000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <731000>;
+ };
+ opp06 {
+ opp-hz = /bits/ 64 <1398000000>;
+ opp-microvolt = <761000>;
+ };
+ opp07 {
+ opp-hz = /bits/ 64 <1512000000>;
+ opp-microvolt = <791000>;
+ };
+ opp08 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <831000>;
+ };
+ opp09 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-microvolt = <861000>;
+ };
+ opp10 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <981000>;
+ };
+ };
+
+ cpu_opp_table1: cpu_opp_table1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp00 {
+ opp-hz = /bits/ 64 <100000000>;
+ opp-microvolt = <751000>;
+ };
+ opp01 {
+ opp-hz = /bits/ 64 <250000000>;
+ opp-microvolt = <751000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <751000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <667000000>;
+ opp-microvolt = <751000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <771000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <771000>;
+ };
+ opp06 {
+ opp-hz = /bits/ 64 <1398000000>;
+ opp-microvolt = <791000>;
+ };
+ opp07 {
+ opp-hz = /bits/ 64 <1512000000>;
+ opp-microvolt = <821000>;
+ };
+ opp08 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <861000>;
+ };
+ opp09 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-microvolt = <891000>;
+ };
+ };
+
+ cpufreq-meson {
+ compatible = "amlogic, cpufreq-meson";
+ status = "okay";
+ };
+
+ sensor: sensor {
+ compatible = "soc, sensor";
+ status = "okay";
+ sensor-name = "imx290"; /*imx290;os08a10;imx227*/
+ pinctrl-names="default";
+ pinctrl-0=<&clk12_24_z_pins>;
+ clocks = <&clkc CLKID_24M>;
+ clock-names = "g12a_24m";
+ reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>;
+ ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH
+ &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>;
+ };
+
+ iq: iq {
+ compatible = "soc, iq";
+ status = "okay";
+ sensor-name = "imx290"; /*imx290;os08a10;imx227*/
+ };
+}; /* end of / */
+
+&i2c2 {
+ status = "okay";
+ pinctrl-names="default";
+ pinctrl-0=<&i2c2_master_pins2>;
+ clock-frequency = <100000>; /* default 100k */
+ sensor-i2c@6c {
+ compatible = "arm, i2c-sensor";
+ reg = <0x6c>;
+ reg-names = "i2c-sensor";
+ slave-addr = <0x6c>;
+ reg-type = <2>;
+ reg-data-type = <1>;
+ link-device = <&phycsi>;
+ };
+};
+
+&isp {
+ status = "okay";
+ memory-region = <&isp_cma_reserved>;
+};
+
+&adapter {
+ status = "okay";
+ memory-region = <&adapt_cma_reserved>;
+};
+
+&gdc {
+ status = "okay";
+ memory-region = <&gdc_cma_reserved>;
+};
+
+&pwm_ab {
+ status = "okay";
+ };
+
+&pwm_ef {
+ status = "okay";
+ };
+
+&pwm_AO_cd {
+ status = "okay";
+ };
+
+&i2c0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_master_pins2>;
+ clock-frequency = <400000>;
+
+ touchscreen@38 {
+ compatible = "focaltech,fts";
+ status = "disabled";
+ reg = <0x38>;
+ reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>;
+ irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>;
+ x_max = <720>;
+ y_max = <1280>;
+ max-touch-number = <10>;
+ };
+};
+
+&i2c3 {
+ status = "okay";
+ pinctrl-names="default";
+ pinctrl-0=<&i2c3_master_pins2>;
+ clock-frequency = <100000>; /* default 100k */
+
+ /* for ref board */
+ ad82584f_62: ad82584f_62@62 {
+ compatible = "ESMT, ad82584f";
+ #sound-dai-cells = <0>;
+ reg = <0x31>;
+ status = "okay";
+ reset_pin = <&gpio GPIOA_5 0>;
+ };
+
+ tlv320adc3101_32: tlv320adc3101_32@32 {
+ compatible = "ti,tlv320adc3101";
+ #sound-dai-cells = <0>;
+ reg = <0x19>;
+ differential_pair = <1>;
+ status = "disabled";
+ };
+
+ bl_extern_i2c {
+ compatible = "bl_extern, i2c";
+ dev_name = "lp8556";
+ reg = <0x2c>;
+ status = "disabled";
+ };
+};
+
+&audiobus {
+ aml_tdma: tdma {
+ compatible = "amlogic, g12a-snd-tdma";
+ #sound-dai-cells = <0>;
+ dai-tdm-lane-slot-mask-in = <0 1>;
+ dai-tdm-oe-lane-slot-mask-out = <1 0>;
+ dai-tdm-clk-sel = <0>;
+ clocks = <&clkaudio CLKID_AUDIO_MCLK_A
+ &clkc CLKID_MPLL0>;
+ clock-names = "mclk", "clk_srcpll";
+ pinctrl-names = "tdm_pins";
+ pinctrl-0 = <&tdmout_a &tdmin_a>;
+ };
+
+ aml_tdmb: tdmb {
+ compatible = "amlogic, g12a-snd-tdmb";
+ #sound-dai-cells = <0>;
+ dai-tdm-lane-slot-mask-in = <0 1 0 0>;
+ dai-tdm-lane-slot-mask-out = <1 0 0 0>;
+ dai-tdm-clk-sel = <1>;
+ clocks = <&clkaudio CLKID_AUDIO_MCLK_B
+ &clkc CLKID_MPLL1
+ &clkc CLKID_MPLL0
+ &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>;
+ clock-names = "mclk", "clk_srcpll",
+ "samesource_srcpll", "samesource_clk";
+ pinctrl-names = "tdm_pins";
+ pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>;
+ /*
+ * 0: tdmout_a;
+ * 1: tdmout_b;
+ * 2: tdmout_c;
+ * 3: spdifout;
+ * 4: spdifout_b;
+ */
+ samesource_sel = <3>;
+ };
+
+ aml_tdmc: tdmc {
+ compatible = "amlogic, g12a-snd-tdmc";
+ #sound-dai-cells = <0>;
+ dai-tdm-lane-slot-mask-in = <1 0 0 0>;
+ #dai-tdm-lane-slot-mask-out = <1 0 1 1>;
+ #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>;
+ #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>;
+ dai-tdm-clk-sel = <2>;
+ clocks = <&clkaudio CLKID_AUDIO_MCLK_C
+ &clkc CLKID_MPLL2>;
+ clock-names = "mclk", "clk_srcpll";
+ pinctrl-names = "tdm_pins";
+ pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>;
+ };
+
+ /* copy a useless tdm to output for hdmi, no pinmux */
+ aml_i2s2hdmi: i2s2hdmi {
+ compatible = "amlogic, g12a-snd-tdmc";
+ #sound-dai-cells = <0>;
+ dai-tdm-lane-slot-mask-out = <1 1 1 1>;
+ dai-tdm-clk-sel = <2>;
+ clocks = <&clkaudio CLKID_AUDIO_MCLK_C
+ &clkc CLKID_MPLL2>;
+ clock-names = "mclk", "clk_srcpll";
+
+ i2s2hdmi = <1>;
+
+ status = "okay";
+ };
+
+ aml_spdif: spdif {
+ compatible = "amlogic, g12a-snd-spdif-a";
+ #sound-dai-cells = <0>;
+ clocks = <&clkc CLKID_MPLL0
+ &clkc CLKID_FCLK_DIV4
+ &clkaudio CLKID_AUDIO_SPDIFIN
+ &clkaudio CLKID_AUDIO_SPDIFOUT
+ &clkaudio CLKID_AUDIO_SPDIFIN_CTRL
+ &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>;
+ clock-names = "sysclk", "fixed_clk", "gate_spdifin",
+ "gate_spdifout", "clk_spdifin", "clk_spdifout";
+ interrupts =
+ <GIC_SPI 151 IRQ_TYPE_EDGE_RISING>;
+
+ interrupt-names = "irq_spdifin";
+ pinctrl-names = "spdif_pins",
+ "spdif_pins_mute";
+ pinctrl-0 = <&spdifout &spdifin>;
+ pinctrl-1 = <&spdifout_a_mute>;
+ status = "okay";
+ };
+ aml_spdif_b: spdif_b {
+ compatible = "amlogic, g12a-snd-spdif-b";
+ #sound-dai-cells = <0>;
+ clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/
+ &clkaudio CLKID_AUDIO_SPDIFOUTB
+ &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>;
+ clock-names = "sysclk",
+ "gate_spdifout", "clk_spdifout";
+ status = "disabled";
+ };
+ aml_pdm: pdm {
+ compatible = "amlogic, g12a-snd-pdm";
+ #sound-dai-cells = <0>;
+ clocks = <&clkaudio CLKID_AUDIO_PDM
+ &clkc CLKID_FCLK_DIV3
+ &clkc CLKID_MPLL3
+ &clkaudio CLKID_AUDIO_PDMIN0
+ &clkaudio CLKID_AUDIO_PDMIN1>;
+ clock-names = "gate",
+ "sysclk_srcpll",
+ "dclk_srcpll",
+ "pdm_dclk",
+ "pdm_sysclk";
+ pinctrl-names = "pdm_pins";
+ pinctrl-0 = <&pdmin>;
+ filter_mode = <1>; /* mode 0~4, defalut:1 */
+ status = "okay";
+ };
+ aml_loopback: loopback {
+ compatible = "amlogic, snd-loopback";
+ /*
+ * 0: out rate = in data rate;
+ * 1: out rate = loopback data rate;
+ */
+ lb_mode = <0>;
+
+ /* datain src
+ * 0: tdmin_a;
+ * 1: tdmin_b;
+ * 2: tdmin_c;
+ * 3: spdifin;
+ * 4: pdmin;
+ */
+ datain_src = <4>;
+ datain_chnum = <8>;
+ datain_chmask = <0x3f>;
+
+ /* tdmin_lb src
+ * 0: tdmoutA
+ * 1: tdmoutB
+ * 2: tdmoutC
+ * 3: PAD_tdminA
+ * 4: PAD_tdminB
+ * 5: PAD_tdminC
+ */
+ datalb_src = <2>;
+ datalb_chnum = <8>;
+ datalb_chmask = <0x3>;
+
+ status = "disabled";
+ };
+
+ audioresample: resample {
+ compatible = "amlogic, g12a-resample";
+ clocks = <&clkc CLKID_MPLL3
+ &clkaudio CLKID_AUDIO_MCLK_F
+ &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>;
+ clock-names = "resample_pll", "resample_src", "resample_clk";
+ /*same with toddr_src
+ * TDMIN_A, 0
+ * TDMIN_B, 1
+ * TDMIN_C, 2
+ * SPDIFIN, 3
+ * PDMIN, 4
+ * NONE,
+ * TDMIN_LB, 6
+ * LOOPBACK, 7
+ */
+ resample_module = <4>;
+ status = "disabled";
+ };
+ aml_pwrdet: pwrdet {
+ compatible = "amlogic, g12a-power-detect";
+
+ interrupts = <GIC_SPI 155 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "pwrdet_irq";
+
+ /* pwrdet source sel
+ * 7: loopback;
+ * 6: tdmin_lb;
+ * 5: reserved;
+ * 4: pdmin;
+ * 3: spdifin;
+ * 2: tdmin_c;
+ * 1: tdmin_b;
+ * 0: tdmin_a;
+ */
+ pwrdet_src = <4>;
+
+ hi_th = <0x70000>;
+ lo_th = <0x16000>;
+
+ status = "disabled";
+ };
+}; /* end of audiobus */
+
+&pinctrl_periphs {
+ tdmout_a: tdmout_a {
+ mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */
+ groups = "tdma_sclk",
+ "tdma_fs",
+ "tdma_dout0";
+ function = "tdma_out";
+ };
+ };
+
+ tdmin_a: tdmin_a {
+ mux { /* GPIOX_8 */
+ groups = "tdma_din1";
+ function = "tdma_in";
+ };
+ };
+
+ tdmb_mclk: tdmb_mclk {
+ mux {
+ groups = "mclk0_a";
+ function = "mclk0";
+ drive-strength = <2>;
+ };
+ };
+ tdmout_b: tdmout_b {
+ mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */
+ groups = "tdmb_sclk",
+ "tdmb_fs",
+ "tdmb_dout0";
+ function = "tdmb_out";
+ drive-strength = <2>;
+ };
+ };
+
+ tdmin_b:tdmin_b {
+ mux { /* GPIOA_4 */
+ groups = "tdmb_din1"
+ /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/;
+ function = "tdmb_in";
+ drive-strength = <2>;
+ };
+ };
+
+ tdmc_mclk: tdmc_mclk {
+ mux { /* GPIOA_11 */
+ groups = "mclk1_a";
+ function = "mclk1";
+ };
+ };
+
+ clk12_24_z_pins:clk12_24_z_pins {
+ mux {
+ groups = "clk12_24_z";
+ function = "clk12_24_ee";
+ drive-strength = <3>;
+ };
+ };
+
+ tdmout_c:tdmout_c {
+ mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/
+ groups = "tdmc_sclk_a",
+ "tdmc_fs_a",
+ "tdmc_dout0_a"
+ /*, "tdmc_dout2",
+ * "tdmc_dout3"
+ */;
+ function = "tdmc_out";
+ };
+ };
+
+ tdmin_c:tdmin_c {
+ mux { /* GPIOA_10 */
+ groups = "tdmc_din0_a";
+ function = "tdmc_in";
+ };
+ };
+
+ spdifin: spdifin {
+ mux {/* GPIOH_5 */
+ groups = "spdif_in_h";
+ function = "spdif_in";
+ };
+ };
+
+ /* GPIOH_4 */
+ /*
+ * spdifout: spdifout {
+ * mux {
+ * groups = "spdif_out_h";
+ * function = "spdif_out";
+ * };
+ *};
+ */
+
+ pdmin: pdmin {
+ mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/
+ groups = "pdm_din0_a",
+ /*"pdm_din1_a",*/
+ "pdm_din2_a",
+ /*"pdm_din3_a",*/
+ "pdm_dclk_a";
+ function = "pdm";
+ };
+ };
+
+ bl_pwm_off_pins:bl_pwm_off_pin {
+ mux {
+ pins = "GPIOH_5";
+ function = "gpio_periphs";
+ output-high;
+ };
+ };
+
+}; /* end of pinctrl_periphs */
+
+&pinctrl_aobus {
+ spdifout: spdifout {
+ mux { /* gpiao_10 */
+ groups = "spdif_out_ao";
+ function = "spdif_out_ao";
+ };
+ };
+
+ spdifout_a_mute: spdifout_a_mute {
+ mux { /* gpiao_10 */
+ groups = "GPIOAO_10";
+ function = "gpio_periphs";
+ };
+ };
+}; /* end of pinctrl_aobus */
+
+&irblaster {
+ status = "disabled";
+};
+
+&audio_data {
+ status = "okay";
+};
+
+/*if you want to use vdin just modify status to "ok"*/
+&vdin0 {
+ memory-region = <&vdin0_cma_reserved>;
+ status = "okay";
+ /*vdin write mem color depth support:
+ *bit0:support 8bit
+ *bit1:support 9bit
+ *bit2:support 10bit
+ *bit3:support 12bit
+ *bit4:support yuv422 10bit full pack mode (from txl new add)
+ */
+ tv_bit_mode = <0x15>;
+};
+&vdin1 {
+ memory-region = <&vdin1_cma_reserved>;
+ status = "okay";
+ /*vdin write mem color depth support:
+ *bit0:support 8bit
+ *bit1:support 9bit
+ *bit2:support 10bit
+ *bit3:support 12bit
+ */
+ tv_bit_mode = <1>;
+};
+
+&sd_emmc_c {
+ status = "okay";
+ emmc {
+ caps = "MMC_CAP_8_BIT_DATA",
+ "MMC_CAP_MMC_HIGHSPEED",
+ "MMC_CAP_SD_HIGHSPEED",
+ "MMC_CAP_NONREMOVABLE",
+ /* "MMC_CAP_1_8V_DDR", */
+ "MMC_CAP_HW_RESET",
+ "MMC_CAP_ERASE",
+ "MMC_CAP_CMD23";
+ caps2 = "MMC_CAP2_HS200";
+ /* "MMC_CAP2_HS400";*/
+ f_min = <400000>;
+ f_max = <200000000>;
+ };
+};
+
+&sd_emmc_b {
+ status = "okay";
+ sd {
+ caps = "MMC_CAP_4_BIT_DATA",
+ "MMC_CAP_MMC_HIGHSPEED",
+ "MMC_CAP_SD_HIGHSPEED";
+ f_min = <400000>;
+ f_max = <50000000>;
+ };
+};
+
+&sd_emmc_a {
+ status = "okay";
+ sdio {
+ caps = "MMC_CAP_4_BIT_DATA",
+ "MMC_CAP_MMC_HIGHSPEED",
+ "MMC_CAP_SD_HIGHSPEED",
+ "MMC_CAP_NONREMOVABLE",
+ "MMC_CAP_UHS_SDR12",
+ "MMC_CAP_UHS_SDR25",
+ "MMC_CAP_UHS_SDR50",
+ "MMC_CAP_UHS_SDR104",
+ "MMC_PM_KEEP_POWER",
+ "MMC_CAP_SDIO_IRQ";
+ f_min = <400000>;
+ f_max = <200000000>;
+ };
+};
+
+&nand {
+ status = "disabled";
+ plat-names = "bootloader","nandnormal";
+ plat-num = <2>;
+ plat-part-0 = <&bootloader>;
+ plat-part-1 = <&nandnormal>;
+ bootloader: bootloader{
+ enable_pad ="ce0";
+ busy_pad = "rb0";
+ timming_mode = "mode5";
+ bch_mode = "bch8_1k";
+ t_rea = <20>;
+ t_rhoh = <15>;
+ chip_num = <1>;
+ part_num = <0>;
+ rb_detect = <1>;
+ };
+ nandnormal: nandnormal{
+ enable_pad ="ce0";
+ busy_pad = "rb0";
+ timming_mode = "mode5";
+ bch_mode = "bch8_1k";
+ plane_mode = "twoplane";
+ t_rea = <20>;
+ t_rhoh = <15>;
+ chip_num = <2>;
+ part_num = <3>;
+ partition = <&nand_partitions>;
+ rb_detect = <1>;
+ };
+ nand_partitions:nand_partition{
+ /*
+ * if bl_mode is 1, tpl size was generate by
+ * fip_copies * fip_size which
+ * will not skip bad when calculating
+ * the partition size;
+ *
+ * if bl_mode is 0,
+ * tpl partition must be comment out.
+ */
+ tpl{
+ offset=<0x0 0x0>;
+ size=<0x0 0x0>;
+ };
+ logo{
+ offset=<0x0 0x0>;
+ size=<0x0 0x200000>;
+ };
+ recovery{
+ offset=<0x0 0x0>;
+ size=<0x0 0x1000000>;
+ };
+ boot{
+ offset=<0x0 0x0>;
+ size=<0x0 0x1000000>;
+ };
+ system{
+ offset=<0x0 0x0>;
+ size=<0x0 0x4000000>;
+ };
+ data{
+ offset=<0xffffffff 0xffffffff>;
+ size=<0x0 0x0>;
+ };
+ };
+};
+&dwc3 {
+ status = "okay";
+};
+
+&usb2_phy_v2 {
+ status = "okay";
+ portnum = <2>;
+};
+
+&usb3_phy_v2 {
+ status = "okay";
+ portnum = <0>;
+ otg = <1>;
+ gpio-vbus-power = "GPIOH_6";
+ gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>;
+};
+
+&dwc2_a {
+ status = "okay";
+ /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/
+ controller-type = <3>;
+};
+&ethmac {
+ status = "okay";
+/* //conflict with isp i2c
+ * pinctrl-names = "internal_eth_pins";
+ * pinctrl-0 = <&internal_eth_pins>;
+ */
+ mc_val = <0x4be04>;
+
+ internal_phy=<1>;
+};
+
+&uart_A {
+ status = "okay";
+};
+
+&pcie_A {
+ reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&saradc {
+ status = "okay";
+};
+
+&spicc1 {
+ status = "disabled";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spicc1_pins>;
+ cs-gpios = <&gpio GPIOH_6 0>;
+};
+
+&meson_fb {
+ status = "disable";
+};
+
+&drm_vpu {
+ status = "okay";
+ compatible = "amlogic,meson-g12b-vpu";
+ logo_addr = "0x7f800000";
+ osd_ver = /bits/ 8 <OSD_V3>;
+};
+
+&drm_amhdmitx {
+ status = "okay";
+ hdcp = "disabled";
+};
+
+&drm_lcd {
+ status = "disable";
+};
diff --git a/arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi b/arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi
index 00beafa..ceb5725 100644
--- a/arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi
+++ b/arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi
@@ -14,11 +14,12 @@
* more details.
*
*/
+#include <dt-bindings/display/meson-drm-ids.h>
/ {
venc-cvbs {
status = "okay";
- compatible = "amlogic,meson-gxbb-cvbs";
+ compatible = "amlogic, meson-g12a-cvbs";
ports {
#address-cells = <1>;
@@ -104,6 +105,138 @@
status = "okay";
compatible = "amlogic,drm-subsystem";
ports = <&vpu_out>;
+
+ vpu_topology: vpu_topology {
+ vpu_blocks {
+ osd1_block: block@0 {
+ id = /bits/ 8 <OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <0>;
+ block_name = "osd1_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd1_block>;
+ };
+ osd2_block: block@1 {
+ id = /bits/ 8 <OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <0>;
+ block_name = "osd2_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd2_block>;
+ };
+ osd3_block: block@2 {
+ id = /bits/ 8 <OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <0>;
+ block_name = "osd3_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd3_block>;
+ };
+ afbc_osd1_block: block@3 {
+ id = /bits/ 8 <AFBC_OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd1_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd1_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &osd_blend_block>;
+ };
+ afbc_osd2_block: block@4 {
+ id = /bits/ 8 <AFBC_OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd2_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd2_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd2_block>;
+ };
+ afbc_osd3_block: block@5 {
+ id = /bits/ 8 <AFBC_OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd3_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd3_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd3_block>;
+ };
+ scaler_osd1_block: block@6 {
+ id = /bits/ 8 <SCALER_OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd1_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd1_hdr_dolby_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &vpp_postblend_block>;
+ };
+ scaler_osd2_block: block@7 {
+ id = /bits/ 8 <SCALER_OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd2_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &afbc_osd2_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <2 &osd_blend_block>;
+ };
+ scaler_osd3_block: block@8 {
+ id = /bits/ 8 <SCALER_OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd3_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &afbc_osd3_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <3 &osd_blend_block>;
+ };
+ osd_blend_block: block@9 {
+ id = /bits/ 8 <OSD_BLEND_BLOCK>;
+ block_name = "osd_blend_block";
+ type = /bits/ 8 <3>;
+ num_in_links = /bits/ 8 <0x3>;
+ in_links = <0 &afbc_osd1_block>,
+ <0 &scaler_osd2_block>,
+ <0 &scaler_osd3_block>;
+ num_out_links = /bits/ 8 <0x2>;
+ out_links = <0 &osd1_hdr_dolby_block>,
+ <1 &vpp_postblend_block>;
+ };
+ osd1_hdr_dolby_block: block@10 {
+ id = /bits/ 8 <OSD1_HDR_BLOCK>;
+ block_name = "osd1_hdr_dolby_block";
+ type = /bits/ 8 <4>;
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd_blend_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd1_block>;
+ };
+ vpp_postblend_block: block@12 {
+ id = /bits/ 8 <VPP_POSTBLEND_BLOCK>;
+ block_name = "vpp_postblend_block";
+ type = /bits/ 8 <6>;
+ num_in_links = /bits/ 8 <0x2>;
+ in_links = <0 &scaler_osd1_block>,
+ <1 &osd_blend_block>;
+ num_out_links = <0x0>;
+ };
+ };
+ };
+
+ vpu_hw_para: vpu_hw_para@0 {
+ osd_ver = /bits/ 8 <0x2>;
+ afbc_type = /bits/ 8 <0x2>;
+ has_deband = /bits/ 8 <0x1>;
+ has_lut = /bits/ 8 <0x1>;
+ has_rdma = /bits/ 8 <0x1>;
+ osd_fifo_len = /bits/ 8 <64>;
+ vpp_fifo_len = /bits/ 32 <0xfff>;
+ };
};
};
diff --git a/arch/arm/boot/dts/amlogic/mesong12b_drm.dtsi b/arch/arm/boot/dts/amlogic/mesong12b_drm.dtsi
new file mode 100644
index 0000000..48794f9d
--- a/dev/null
+++ b/arch/arm/boot/dts/amlogic/mesong12b_drm.dtsi
@@ -0,0 +1,241 @@
+/*
+ * arch/arm/boot/dts/amlogic/meson_drm.dtsi
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+#include <dt-bindings/display/meson-drm-ids.h>
+
+/ {
+ venc-cvbs {
+ status = "okay";
+ compatible = "amlogic, meson-g12b-cvbs";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ enc_cvbs_in: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ //venc_cvbs_in_vpu: endpoint@0 {
+ // reg = <0>;
+ // remote-endpoint = <&vpu_out_venc_cvbs>;
+ //};
+ };
+ };
+ };
+
+ drm_amhdmitx: drm-amhdmitx {
+ status = "disabled";
+ hdcp = "disabled";
+ compatible = "amlogic,drm-amhdmitx";
+ dev_name = "meson-amhdmitx";
+ interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
+ ports {
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ hdmi_in_vpu: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&vpu_out_hdmi>;
+ };
+ };
+ };
+ };
+
+ drm_lcd: drm-lcd {
+ status = "disabled";
+ compatible = "amlogic,drm-lcd";
+ dev_name = "meson-lcd";
+ ports {
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ lcd_in_vpu: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&vpu_out_lcd>;
+ };
+ };
+ };
+ };
+
+ drm_vpu: drm-vpu@0xff900000 {
+ status = "disabled";
+ compatible = "amlogic,meson-g12b-vpu";
+ memory-region = <&logo_reserved>;
+ reg = <0xff900000 0x40000>,
+ <0xff63c000 0x2000>,
+ <0xff638000 0x2000>;
+ reg-names = "base", "hhi", "dmc";
+ interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 56 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "viu-vsync", "viu2-vsync";
+ clocks = <&clkc CLKID_VPU_CLKC_MUX>;
+ clock-names = "vpu_clkc";
+ dma-coherent;
+ vpu_out: port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vpu_out_hdmi: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&hdmi_in_vpu>;
+ };
+ vpu_out_lcd: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&lcd_in_vpu>;
+ };
+ };
+ };
+
+ drm_subsystem: drm-subsystem {
+ status = "okay";
+ compatible = "amlogic,drm-subsystem";
+ ports = <&vpu_out>;
+
+ vpu_topology: vpu_topology {
+ vpu_blocks {
+ osd1_block: block@0 {
+ id = /bits/ 8 <OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <0>;
+ block_name = "osd1_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd1_block>;
+ };
+ osd2_block: block@1 {
+ id = /bits/ 8 <OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <0>;
+ block_name = "osd2_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd2_block>;
+ };
+ osd3_block: block@2 {
+ id = /bits/ 8 <OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <0>;
+ block_name = "osd3_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd3_block>;
+ };
+ afbc_osd1_block: block@3 {
+ id = /bits/ 8 <AFBC_OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd1_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd1_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &osd_blend_block>;
+ };
+ afbc_osd2_block: block@4 {
+ id = /bits/ 8 <AFBC_OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd2_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd2_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd2_block>;
+ };
+ afbc_osd3_block: block@5 {
+ id = /bits/ 8 <AFBC_OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd3_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd3_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd3_block>;
+ };
+ scaler_osd1_block: block@6 {
+ id = /bits/ 8 <SCALER_OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd1_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd1_hdr_dolby_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &vpp_postblend_block>;
+ };
+ scaler_osd2_block: block@7 {
+ id = /bits/ 8 <SCALER_OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd2_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &afbc_osd2_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <2 &osd_blend_block>;
+ };
+ scaler_osd3_block: block@8 {
+ id = /bits/ 8 <SCALER_OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd3_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &afbc_osd3_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <3 &osd_blend_block>;
+ };
+ osd_blend_block: block@9 {
+ id = /bits/ 8 <OSD_BLEND_BLOCK>;
+ block_name = "osd_blend_block";
+ type = /bits/ 8 <3>;
+ num_in_links = /bits/ 8 <0x3>;
+ in_links = <0 &afbc_osd1_block>,
+ <0 &scaler_osd2_block>,
+ <0 &scaler_osd3_block>;
+ num_out_links = /bits/ 8 <0x2>;
+ out_links = <0 &osd1_hdr_dolby_block>,
+ <1 &vpp_postblend_block>;
+ };
+ osd1_hdr_dolby_block: block@10 {
+ id = /bits/ 8 <OSD1_HDR_BLOCK>;
+ block_name = "osd1_hdr_dolby_block";
+ type = /bits/ 8 <4>;
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd_blend_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd1_block>;
+ };
+ vpp_postblend_block: block@12 {
+ id = /bits/ 8 <VPP_POSTBLEND_BLOCK>;
+ block_name = "vpp_postblend_block";
+ type = /bits/ 8 <6>;
+ num_in_links = /bits/ 8 <0x2>;
+ in_links = <0 &scaler_osd1_block>,
+ <1 &osd_blend_block>;
+ num_out_links = <0x0>;
+ };
+ };
+ };
+
+ vpu_hw_para: vpu_hw_para@0 {
+ osd_ver = /bits/ 8 <0x2>;
+ afbc_type = /bits/ 8 <0x2>;
+ has_deband = /bits/ 8 <0x1>;
+ has_lut = /bits/ 8 <0x1>;
+ has_rdma = /bits/ 8 <0x1>;
+ osd_fifo_len = /bits/ 8 <64>;
+ vpp_fifo_len = /bits/ 32 <0xfff>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts
index 380ba94..b43feaf 100644
--- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts
+++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts
@@ -820,6 +820,7 @@
&drm_vpu {
status = "okay";
logo_addr = "0x7f800000";
+ osd_ver = /bits/ 8 <OSD_V1>;
};
&drm_amhdmitx {
diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts
index 512f9f5..adff020 100644
--- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts
+++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts
@@ -19,7 +19,7 @@
#include "mesong12b.dtsi"
#include "mesong12b_skt-panel.dtsi"
-#include "mesong12a_drm.dtsi"
+#include "mesong12b_drm.dtsi"
/ {
model = "Amlogic";
@@ -903,6 +903,7 @@
status = "okay";
compatible = "amlogic,meson-g12b-vpu";
logo_addr = "0x7f800000";
+ osd_ver = /bits/ 8 <OSD_V3>;
};
&drm_amhdmitx {
diff --git a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts
index b7c2bbf..109a044 100644
--- a/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts
+++ b/arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts
@@ -870,6 +870,7 @@
status = "okay";
compatible = "amlogic,meson-g12b-vpu";
logo_addr = "0x7f800000";
+ osd_ver = /bits/ 8 <OSD_V2>;
};
&drm_amhdmitx {
diff --git a/arch/arm64/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts b/arch/arm64/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts
new file mode 100644
index 0000000..207a2da
--- a/dev/null
+++ b/arch/arm64/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts
@@ -0,0 +1,1473 @@
+/*
+ * arch/arm64/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+/dts-v1/;
+
+#include "mesong12b_a.dtsi"
+#include "mesong12b_skt-panel.dtsi"
+#include "mesong12b_drm.dtsi"
+
+/ {
+ model = "Amlogic";
+ amlogic-dt-id = "g12b_w400_a";
+ compatible = "amlogic, g12b";
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ aliases {
+ serial0 = &uart_AO;
+ serial1 = &uart_A;
+ serial2 = &uart_B;
+ serial3 = &uart_C;
+ serial4 = &uart_AO_B;
+ i2c0 = &i2c0;
+ i2c1 = &i2c1;
+ i2c2 = &i2c2;
+ i2c3 = &i2c3;
+ i2c4 = &i2c_AO;
+ tsensor0 = &p_tsensor;
+ tsensor1 = &d_tsensor;
+ };
+
+ memory@00000000 {
+ device_type = "memory";
+ linux,usable-memory = <0x0 0x100000 0x0 0x7ff00000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ /* global autoconfigured region for contiguous allocations */
+ ramoops@0x07400000 {
+ compatible = "ramoops";
+ reg = <0x0 0x07400000 0x0 0x00100000>;
+ record-size = <0x8000>;
+ console-size = <0x8000>;
+ ftrace-size = <0x0>;
+ pmsg-size = <0x8000>;
+ };
+
+ secmon_reserved:linux,secmon {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x0 0x400000>;
+ alignment = <0x0 0x400000>;
+ alloc-ranges = <0x0 0x05000000 0x0 0x400000>;
+ clear-map;
+ };
+
+ secos_reserved:linux,secos {
+ status = "disable";
+ compatible = "amlogic, aml_secos_memory";
+ reg = <0x0 0x05300000 0x0 0x2000000>;
+ no-map;
+ };
+ logo_reserved:linux,meson-fb {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x0 0x800000>;
+ alignment = <0x0 0x400000>;
+ alloc-ranges = <0x0 0x7f800000 0x0 0x800000>;
+ };
+ ion_cma_reserved:linux,ion-dev {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x0 0x8000000>;
+ alignment = <0x0 0x400000>;
+ };
+
+ //di_reserved:linux,di {
+ //compatible = "amlogic, di-mem";
+ /* buffer_size = 3621952(yuv422 8bit) */
+ /* 4179008(yuv422 10bit full pack mode) */
+ /** 10x3621952=34.6M(0x23) support 8bit **/
+ /** 10x4736064=45.2M(0x2e) support 12bit **/
+ /** 10x4179008=40M(0x28) support 10bit **/
+ //size = <0x0 0x2800000>;
+ //no-map;
+ //};
+ /*di CMA pool */
+ di_cma_reserved:linux,di_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ /* buffer_size = 3621952(yuv422 8bit)
+ * | 4736064(yuv422 10bit)
+ * | 4074560(yuv422 10bit full pack mode)
+ * 10x3621952=34.6M(0x23) support 8bit
+ * 10x4736064=45.2M(0x2e) support 12bit
+ * 10x4074560=40M(0x28) support 10bit
+ */
+ size = <0x0 0x02800000>;
+ alignment = <0x0 0x400000>;
+ };
+ /* POST PROCESS MANAGER */
+ ppmgr_reserved:linux,ppmgr {
+ compatible = "shared-dma-pool";
+ size = <0x0 0x0>;
+ };
+ codec_mm_cma:linux,codec_mm_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ /* ion_codec_mm max can alloc size 80M*/
+ size = <0x0 0x13400000>;
+ alignment = <0x0 0x400000>;
+ linux,contiguous-region;
+ };
+ /* codec shared reserved */
+ codec_mm_reserved:linux,codec_mm_reserved {
+ compatible = "amlogic, codec-mm-reserved";
+ size = <0x0 0x0>;
+ alignment = <0x0 0x100000>;
+ //no-map;
+ };
+ /* vdin0 CMA pool */
+ vdin0_cma_reserved:linux,vdin0_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ /* 1920x1080x2x4 =16+4 M */
+ size = <0x0 0x04000000>;
+ alignment = <0x0 0x400000>;
+ };
+ /* vdin1 CMA pool */
+ vdin1_cma_reserved:linux,vdin1_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ /* 1920x1080x2x4 =16 M */
+ size = <0x0 0x04000000>;
+ alignment = <0x0 0x400000>;
+ };
+ galcore_reserved:linux,galcore {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x0 0x0>;
+ alignment = <0x0 0x400000>;
+ linux,contiguous-region;
+ };
+
+ isp_cma_reserved:linux,isp_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ status = "okay";
+ size = <0x0 0x10000000>;
+ alignment = <0x0 0x400000>;
+ };
+
+ adapt_cma_reserved:linux,adapt_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ status = "okay";
+ size = <0x0 0x03000000>;
+ alignment = <0x0 0x400000>;
+ };
+ gdc_cma_reserved:linux,gdc_cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ status = "okay";
+ size = <0x0 0x04000000>;
+ alignment = <0x0 0x400000>;
+ };
+ };
+ galcore {
+ status = "okay";
+ memory-region = <&galcore_reserved>;
+ };
+ gpioleds {
+ compatible = "gpio-leds";
+ status = "okay";
+
+ sys_led {
+ label="sys_led";
+ gpios=<&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>;
+ default-state ="on";
+ retain-state-suspended;
+ linux,default-trigger="cpu0";
+ };
+ };
+
+ cvbsout {
+ compatible = "amlogic, cvbsout-g12b";
+ dev_name = "cvbsout";
+ status = "okay";
+ clocks = <&clkc CLKID_VCLK2_ENCI
+ &clkc CLKID_VCLK2_VENCI0
+ &clkc CLKID_VCLK2_VENCI1
+ &clkc CLKID_DAC_CLK>;
+ clock-names = "venci_top_gate",
+ "venci_0_gate",
+ "venci_1_gate",
+ "vdac_clk_gate";
+
+ /* performance: reg_address, reg_value */
+ /* g12b */
+ performance = <0x1bf0 0x9
+ 0x1b56 0x333
+ 0x1b12 0x8080
+ 0x1b05 0xfd
+ 0x1c59 0xf850
+ 0xffff 0x0>; /* ending flag */
+ performance_sarft = <0x1bf0 0x9
+ 0x1b56 0x333
+ 0x1b12 0x0
+ 0x1b05 0x9
+ 0x1c59 0xfc48
+ 0xffff 0x0>; /* ending flag */
+ };
+
+ bt-dev{
+ compatible = "amlogic, bt-dev";
+ dev_name = "bt-dev";
+ status = "okay";
+ gpio_reset = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
+ gpio_hostwake = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>;
+ };
+
+ wifi{
+ compatible = "amlogic, aml_wifi";
+ dev_name = "aml_wifi";
+ status = "okay";
+ interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>;
+ irq_trigger_type = "GPIO_IRQ_LOW";
+ power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>;
+ dhd_static_buf; //if use bcm wifi, config dhd_static_buf
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm_e_pins>;
+ pwm_config = <&wifi_pwm_conf>;
+ };
+
+ wifi_pwm_conf:wifi_pwm_conf{
+ pwm_channel1_conf {
+ pwms = <&pwm_ef MESON_PWM_0 30541 0>;
+ duty-cycle = <15270>;
+ times = <10>;
+ };
+ pwm_channel2_conf {
+ pwms = <&pwm_ef MESON_PWM_2 30500 0>;
+ duty-cycle = <15250>;
+ times = <12>;
+ };
+ };
+
+ codec_mm {
+ compatible = "amlogic, codec, mm";
+ memory-region = <&codec_mm_cma &codec_mm_reserved>;
+ dev_name = "codec_mm";
+ status = "okay";
+ };
+
+ ppmgr {
+ compatible = "amlogic, ppmgr";
+ memory-region = <&ppmgr_reserved>;
+ dev_name = "ppmgr";
+ status = "okay";
+ };
+
+ deinterlace {
+ compatible = "amlogic, deinterlace";
+ status = "okay";
+ /* 0:use reserved; 1:use cma; 2:use cma as reserved */
+ flag_cma = <1>;
+ //memory-region = <&di_reserved>;
+ memory-region = <&di_cma_reserved>;
+ interrupts = <0 46 1
+ 0 40 1>;
+ interrupt-names = "pre_irq", "post_irq";
+ clocks = <&clkc CLKID_VPU_CLKB_TMP_COMP>,
+ <&clkc CLKID_VPU_CLKB_COMP>;
+ clock-names = "vpu_clkb_tmp_composite",
+ "vpu_clkb_composite";
+ clock-range = <334 667>;
+ /* buffer-size = <3621952>;(yuv422 8bit) */
+ buffer-size = <4074560>;/*yuv422 fullpack*/
+ /* reserve-iomap = "true"; */
+ /* if enable nr10bit, set nr10bit-support to 1 */
+ post-wr-support = <1>;
+ nr10bit-support = <1>;
+ nrds-enable = <1>;
+ pps-enable = <1>;
+ };
+ ionvideo {
+ compatible = "amlogic, ionvideo";
+ dev_name = "ionvideo";
+ status = "okay";
+ };
+
+
+ partitions: partitions{
+ parts = <14>;
+ part-0 = <&logo>;
+ part-1 = <&recovery>;
+ part-2 = <&misc>;
+ part-3 = <&dto>;
+ part-4 = <&cri_data>;
+ part-5 = <&param>;
+ part-6 = <&boot>;
+ part-7 = <&rsv>;
+ part-8 = <&tee>;
+ part-9 = <&vendor>;
+ part-10 = <&odm>;
+ part-11 = <&system>;
+ part-12 = <&cache>;
+ part-13 = <&data>;
+
+ logo:logo{
+ pname = "logo";
+ size = <0x0 0x800000>;
+ mask = <1>;
+ };
+ recovery:recovery{
+ pname = "recovery";
+ size = <0x0 0x1800000>;
+ mask = <1>;
+ };
+ misc:misc{
+ pname = "misc";
+ size = <0x0 0x800000>;
+ mask = <1>;
+ };
+ dto:dto{
+ pname = "dto";
+ size = <0x0 0x800000>;
+ mask = <1>;
+ };
+ cri_data:cri_data{
+ pname = "cri_data";
+ size = <0x0 0x800000>;
+ mask = <2>;
+ };
+ rsv:rsv{
+ pname = "rsv";
+ size = <0x0 0x1000000>;
+ mask = <1>;
+ };
+ param:param{
+ pname = "param";
+ size = <0x0 0x1000000>;
+ mask = <2>;
+ };
+ boot:boot{
+ pname = "boot";
+ size = <0x0 0x1000000>;
+ mask = <1>;
+ };
+ tee:tee{
+ pname = "tee";
+ size = <0x0 0x2000000>;
+ mask = <1>;
+ };
+ vendor:vendor{
+ pname = "vendor";
+ size = <0x0 0x10000000>;
+ mask = <1>;
+ };
+ odm:odm{
+ pname = "odm";
+ size = <0x0 0x10000000>;
+ mask = <1>;
+ };
+ system:system{
+ pname = "system";
+ size = <0x0 0x80000000>;
+ mask = <1>;
+ };
+ cache:cache{
+ pname = "cache";
+ size = <0x0 0x46000000>;
+ mask = <2>;
+ };
+ data:data{
+ pname = "data";
+ size = <0xffffffff 0xffffffff>;
+ mask = <4>;
+ };
+ };
+
+ gpio_keypad {
+ compatible = "amlogic, gpio_keypad";
+ status = "okay";
+ scan_period = <20>;
+ key_num = <1>;
+ key_name = "power";
+ key_code = <116>;
+ key-gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>;
+ detect_mode = <0>;/*0:polling mode, 1:irq mode*/
+ };
+
+ adc_keypad {
+ compatible = "amlogic, adc_keypad";
+ status = "okay";
+ key_name = "vol-", "vol+", "enter";
+ key_num = <3>;
+ io-channels = <&saradc SARADC_CH2>;
+ io-channel-names = "key-chan-2";
+ key_chan = <SARADC_CH2 SARADC_CH2 SARADC_CH2>;
+ key_code = <114 115 28>;
+ key_val = <143 266 389>; //val=voltage/1800mV*1023
+ key_tolerance = <40 40 40>;
+ };
+
+ unifykey{
+ compatible = "amlogic, unifykey";
+ status = "ok";
+ unifykey-num = <15>;
+ unifykey-index-0 = <&keysn_0>;
+ unifykey-index-1 = <&keysn_1>;
+ unifykey-index-2 = <&keysn_2>;
+ unifykey-index-3 = <&keysn_3>;
+ unifykey-index-4 = <&keysn_4>;
+ unifykey-index-5 = <&keysn_5>;
+ unifykey-index-6 = <&keysn_6>;
+ unifykey-index-7 = <&keysn_7>;
+ unifykey-index-8 = <&keysn_8>;
+ unifykey-index-9 = <&keysn_9>;
+ unifykey-index-10= <&keysn_10>;
+ unifykey-index-11= <&keysn_11>;
+ unifykey-index-12= <&keysn_12>;
+ unifykey-index-13= <&keysn_13>;
+ unifykey-index-14= <&keysn_14>;
+
+ keysn_0: key_0{
+ key-name = "usid";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_1:key_1{
+ key-name = "mac";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_2:key_2{
+ key-name = "hdcp";
+ key-device = "secure";
+ key-type = "sha1";
+ key-permit = "read","write","del";
+ };
+ keysn_3:key_3{
+ key-name = "secure_boot_set";
+ key-device = "efuse";
+ key-permit = "write";
+ };
+ keysn_4:key_4{
+ key-name = "mac_bt";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ key-type = "mac";
+ };
+ keysn_5:key_5{
+ key-name = "mac_wifi";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ key-type = "mac";
+ };
+ keysn_6:key_6{
+ key-name = "hdcp2_tx";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_7:key_7{
+ key-name = "hdcp2_rx";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_8:key_8{
+ key-name = "widevinekeybox";
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_9:key_9{
+ key-name = "deviceid";
+ key-device = "normal";
+ key-permit = "read","write","del";
+ };
+ keysn_10:key_10{
+ key-name = "hdcp22_fw_private";
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_11:key_11{
+ key-name = "PlayReadykeybox25";
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_12:key_12{
+ key-name = "prpubkeybox";// PlayReady
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_13:key_13{
+ key-name = "prprivkeybox";// PlayReady
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ keysn_14:key_14{
+ key-name = "netflix_mgkid";
+ key-device = "secure";
+ key-permit = "read","write","del";
+ };
+ };//End unifykey
+
+ amlvecm {
+ compatible = "amlogic, vecm";
+ dev_name = "aml_vecm";
+ status = "okay";
+ gamma_en = <0>;/*1:enabel ;0:disable*/
+ wb_en = <0>;/*1:enabel ;0:disable*/
+ cm_en = <0>;/*1:enabel ;0:disable*/
+ };
+ amdolby_vision {
+ compatible = "amlogic, dolby_vision_g12a";
+ dev_name = "aml_amdolby_vision_driver";
+ status = "okay";
+ tv_mode = <0>;/*1:enabel ;0:disable*/
+ };
+
+ /* Audio Related start */
+ pdm_codec:dummy{
+ #sound-dai-cells = <0>;
+ compatible = "amlogic, pdm_dummy_codec";
+ status = "okay";
+ };
+ dummy_codec:dummy{
+ #sound-dai-cells = <0>;
+ compatible = "amlogic, aml_dummy_codec";
+ status = "okay";
+ };
+ amlogic_codec:t9015{
+ #sound-dai-cells = <0>;
+ compatible = "amlogic, aml_codec_T9015";
+ reg = <0x0 0xFF632000 0x0 0x2000>;
+ is_auge_used = <1>; /* meson or auge chipset used */
+ tdmout_index = <1>;
+ status = "okay";
+ };
+ audio_effect:eqdrc{
+ /*eq_enable = <1>;*/
+ /*drc_enable = <1>;*/
+ /*
+ * 0:tdmout_a
+ * 1:tdmout_b
+ * 2:tdmout_c
+ * 3:spdifout
+ * 4:spdifout_b
+ */
+ eqdrc_module = <1>;
+ /* max 0xf, each bit for one lane, usually one lane */
+ lane_mask = <0x1>;
+ /* max 0xff, each bit for one channel */
+ channel_mask = <0x3>;
+ };
+ auge_sound {
+ compatible = "amlogic, g12a-sound-card";
+ aml-audio-card,name = "AML-AUGESOUND";
+
+ //aml-audio-card,loopback = <&aml_loopback>;
+ //aml-audio-card,aux-devs = <&amlogic_codec>;
+ /*avout mute gpio*/
+ avout_mute-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>;
+ /*for audio effect ,eqdrc */
+ aml-audio-card,effect = <&audio_effect>;
+
+ aml-audio-card,dai-link@0 {
+ format = "dsp_a";
+ mclk-fs = <512>;
+ //continuous-clock;
+ //bitclock-inversion;
+ //frame-inversion;
+ //bitclock-master = <&tdmacodec>;
+ //frame-master = <&tdmacodec>;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ suffix-name = "alsaPORT-pcm";
+ tdmacpu: cpu {
+ sound-dai = <&aml_tdma>;
+ dai-tdm-slot-tx-mask =
+ <1 1 1 1 1 1 1 1>;
+ dai-tdm-slot-rx-mask =
+ <1 1 1 1 1 1 1 1>;
+ dai-tdm-slot-num = <8>;
+ dai-tdm-slot-width = <32>;
+ system-clock-frequency = <24576000>;
+ };
+ tdmacodec: codec {
+ sound-dai = <&dummy_codec &dummy_codec>;
+ };
+ };
+
+ aml-audio-card,dai-link@1 {
+ format = "i2s";
+ mclk-fs = <256>;
+ //continuous-clock;
+ //bitclock-inversion;
+ //frame-inversion;
+ bitclock-master = <&aml_tdmb>;
+ frame-master = <&aml_tdmb>;
+ //bitclock-master = <&tdmbcodec>;
+ //frame-master = <&tdmbcodec>;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ suffix-name = "alsaPORT-i2s";
+ cpu {
+ sound-dai = <&aml_tdmb>;
+ dai-tdm-slot-tx-mask = <1 1>;
+ dai-tdm-slot-rx-mask = <1 1>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <32>;
+ system-clock-frequency = <12288000>;
+ };
+ tdmbcodec: codec {
+ sound-dai = <&dummy_codec &dummy_codec
+ &amlogic_codec &ad82584f_62>;
+ };
+ };
+
+ aml-audio-card,dai-link@2 {
+ format = "i2s";
+ mclk-fs = <256>;
+ //continuous-clock;
+ //bitclock-inversion;
+ //frame-inversion;
+ bitclock-master = <&aml_tdmc>;
+ frame-master = <&aml_tdmc>;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ //suffix-name = "alsaPORT-tdm";
+ cpu {
+ sound-dai = <&aml_tdmc>;
+ dai-tdm-slot-tx-mask = <1 1>;
+ dai-tdm-slot-rx-mask = <1 1>;
+ dai-tdm-slot-num = <2>;
+ dai-tdm-slot-width = <32>;
+ system-clock-frequency = <12288000>;
+ };
+ codec {
+ sound-dai = <&dummy_codec &dummy_codec>;
+ };
+ };
+
+ aml-audio-card,dai-link@3 {
+ mclk-fs = <64>;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ suffix-name = "alsaPORT-pdm";
+ cpu {
+ sound-dai = <&aml_pdm>;
+ };
+ codec {
+ sound-dai = <&pdm_codec>;
+ };
+ };
+
+ aml-audio-card,dai-link@4 {
+ mclk-fs = <128>;
+ /* suffix-name, sync with android audio hal
+ * what's the dai link used for
+ */
+ suffix-name = "alsaPORT-spdif";
+ cpu {
+ sound-dai = <&aml_spdif>;
+ system-clock-frequency = <6144000>;
+ };
+ codec {
+ sound-dai = <&dummy_codec>;
+ };
+ };
+ };
+ audiolocker: locker {
+ compatible = "amlogic, audiolocker";
+ clocks = <&clkaudio CLKID_AUDIO_LOCKER_OUT
+ &clkaudio CLKID_AUDIO_LOCKER_IN
+ &clkaudio CLKID_AUDIO_MCLK_D
+ &clkaudio CLKID_AUDIO_MCLK_E
+ &clkc CLKID_MPLL1
+ &clkc CLKID_MPLL2>;
+ clock-names = "lock_out", "lock_in", "out_src",
+ "in_src", "out_calc", "in_ref";
+ interrupts = <GIC_SPI 1 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "irq";
+ frequency = <49000000>; /* pll */
+ dividor = <49>; /* locker's parent */
+ status = "okay";
+ };
+ /* Audio Related end */
+
+ cpu_opp_table0: cpu_opp_table0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp00 {
+ opp-hz = /bits/ 64 <100000000>;
+ opp-microvolt = <731000>;
+ };
+ opp01 {
+ opp-hz = /bits/ 64 <250000000>;
+ opp-microvolt = <731000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <731000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <667000000>;
+ opp-microvolt = <731000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <731000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <731000>;
+ };
+ opp06 {
+ opp-hz = /bits/ 64 <1398000000>;
+ opp-microvolt = <761000>;
+ };
+ opp07 {
+ opp-hz = /bits/ 64 <1512000000>;
+ opp-microvolt = <791000>;
+ };
+ opp08 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <831000>;
+ };
+ opp09 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-microvolt = <861000>;
+ };
+ opp10 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <981000>;
+ };
+ };
+
+ cpu_opp_table1: cpu_opp_table1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp00 {
+ opp-hz = /bits/ 64 <100000000>;
+ opp-microvolt = <751000>;
+ };
+ opp01 {
+ opp-hz = /bits/ 64 <250000000>;
+ opp-microvolt = <751000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <751000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <667000000>;
+ opp-microvolt = <751000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <771000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <771000>;
+ };
+ opp06 {
+ opp-hz = /bits/ 64 <1398000000>;
+ opp-microvolt = <791000>;
+ };
+ opp07 {
+ opp-hz = /bits/ 64 <1512000000>;
+ opp-microvolt = <821000>;
+ };
+ opp08 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <861000>;
+ };
+ opp09 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-microvolt = <891000>;
+ };
+ };
+
+ cpufreq-meson {
+ compatible = "amlogic, cpufreq-meson";
+ status = "okay";
+ };
+
+ sensor: sensor {
+ compatible = "soc, sensor";
+ status = "okay";
+ sensor-name = "imx290"; /*imx290;os08a10;imx227*/
+ pinctrl-names="default";
+ pinctrl-0=<&clk12_24_z_pins>;
+ clocks = <&clkc CLKID_24M>;
+ clock-names = "g12a_24m";
+ reset = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH>;
+ ir_cut_gpio = <&gpio GPIOZ_11 GPIO_ACTIVE_HIGH
+ &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>;
+ };
+
+ iq: iq {
+ compatible = "soc, iq";
+ status = "okay";
+ sensor-name = "imx290"; /*imx290;os08a10;imx227*/
+ };
+}; /* end of / */
+
+&i2c2 {
+ status = "okay";
+ pinctrl-names="default";
+ pinctrl-0=<&i2c2_master_pins2>;
+ clock-frequency = <100000>; /* default 100k */
+ sensor-i2c@6c {
+ compatible = "arm, i2c-sensor";
+ reg = <0x6c>;
+ reg-names = "i2c-sensor";
+ slave-addr = <0x6c>;
+ reg-type = <2>;
+ reg-data-type = <1>;
+ link-device = <&phycsi>;
+ };
+};
+
+&isp {
+ status = "okay";
+ memory-region = <&isp_cma_reserved>;
+};
+
+&adapter {
+ status = "okay";
+ memory-region = <&adapt_cma_reserved>;
+};
+
+&gdc {
+ status = "okay";
+ memory-region = <&gdc_cma_reserved>;
+};
+
+&meson_fb {
+ status = "disable";
+ display_size_default = <1920 1080 1920 2160 32>;
+ mem_size = <0x00800000 0x1980000 0x100000 0x100000 0x800000>;
+ logo_addr = "0x7f800000";
+ mem_alloc = <1>;
+ pxp_mode = <0>; /** 0:normal mode 1:pxp mode */
+};
+
+&drm_vpu {
+ status = "okay";
+ compatible = "amlogic,meson-g12b-vpu";
+ logo_addr = "0x7f800000";
+ osd_ver = /bits/ 8 <OSD_V3>;
+};
+
+&drm_amhdmitx {
+ status = "okay";
+ hdcp = "disabled";
+};
+
+&drm_lcd {
+ status = "disable";
+};
+
+&pwm_ab {
+ status = "okay";
+ };
+
+&pwm_ef {
+ status = "okay";
+ };
+
+&pwm_AO_cd {
+ status = "okay";
+ };
+
+&i2c0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_master_pins2>;
+ clock-frequency = <400000>;
+
+ touchscreen@38 {
+ compatible = "focaltech,fts";
+ status = "disabled";
+ reg = <0x38>;
+ reset-gpio = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH>;
+ irq-gpio = <&gpio GPIOZ_3 GPIO_ACTIVE_HIGH>;
+ x_max = <720>;
+ y_max = <1280>;
+ max-touch-number = <10>;
+ };
+};
+
+&i2c3 {
+ status = "okay";
+ pinctrl-names="default";
+ pinctrl-0=<&i2c3_master_pins2>;
+ clock-frequency = <100000>; /* default 100k */
+
+ /* for ref board */
+ ad82584f_62: ad82584f_62@62 {
+ compatible = "ESMT, ad82584f";
+ #sound-dai-cells = <0>;
+ reg = <0x31>;
+ status = "okay";
+ reset_pin = <&gpio GPIOA_5 0>;
+ };
+
+ tlv320adc3101_32: tlv320adc3101_32@32 {
+ compatible = "ti,tlv320adc3101";
+ #sound-dai-cells = <0>;
+ reg = <0x19>;
+ differential_pair = <1>;
+ status = "disabled";
+ };
+
+ bl_extern_i2c {
+ compatible = "bl_extern, i2c";
+ dev_name = "lp8556";
+ reg = <0x2c>;
+ status = "disabled";
+ };
+};
+
+&audiobus {
+ aml_tdma: tdma {
+ compatible = "amlogic, g12a-snd-tdma";
+ #sound-dai-cells = <0>;
+ dai-tdm-lane-slot-mask-in = <0 1>;
+ dai-tdm-oe-lane-slot-mask-out = <1 0>;
+ dai-tdm-clk-sel = <0>;
+ clocks = <&clkaudio CLKID_AUDIO_MCLK_A
+ &clkc CLKID_MPLL0>;
+ clock-names = "mclk", "clk_srcpll";
+ pinctrl-names = "tdm_pins";
+ pinctrl-0 = <&tdmout_a &tdmin_a>;
+ };
+
+ aml_tdmb: tdmb {
+ compatible = "amlogic, g12a-snd-tdmb";
+ #sound-dai-cells = <0>;
+ dai-tdm-lane-slot-mask-in = <0 1 0 0>;
+ dai-tdm-lane-slot-mask-out = <1 0 0 0>;
+ dai-tdm-clk-sel = <1>;
+ clocks = <&clkaudio CLKID_AUDIO_MCLK_B
+ &clkc CLKID_MPLL1
+ &clkc CLKID_MPLL0
+ &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>;
+ clock-names = "mclk", "clk_srcpll",
+ "samesource_srcpll", "samesource_clk";
+ pinctrl-names = "tdm_pins";
+ pinctrl-0 = <&tdmb_mclk &tdmout_b &tdmin_b>;
+ /*
+ * 0: tdmout_a;
+ * 1: tdmout_b;
+ * 2: tdmout_c;
+ * 3: spdifout;
+ * 4: spdifout_b;
+ */
+ samesource_sel = <3>;
+ };
+
+ aml_tdmc: tdmc {
+ compatible = "amlogic, g12a-snd-tdmc";
+ #sound-dai-cells = <0>;
+ dai-tdm-lane-slot-mask-in = <1 0 0 0>;
+ #dai-tdm-lane-slot-mask-out = <1 0 1 1>;
+ #dai-tdm-lane-oe-slot-mask-in = <0 0 0 0>;
+ #dai-tdm-lane-oe-slot-mask-out = <1 0 0 0>;
+ dai-tdm-clk-sel = <2>;
+ clocks = <&clkaudio CLKID_AUDIO_MCLK_C
+ &clkc CLKID_MPLL2>;
+ clock-names = "mclk", "clk_srcpll";
+ pinctrl-names = "tdm_pins";
+ pinctrl-0 = <&tdmc_mclk &tdmout_c &tdmin_c>;
+ };
+
+ /* copy a useless tdm to output for hdmi, no pinmux */
+ aml_i2s2hdmi: i2s2hdmi {
+ compatible = "amlogic, g12a-snd-tdmc";
+ #sound-dai-cells = <0>;
+ dai-tdm-lane-slot-mask-out = <1 1 1 1>;
+ dai-tdm-clk-sel = <2>;
+ clocks = <&clkaudio CLKID_AUDIO_MCLK_C
+ &clkc CLKID_MPLL2>;
+ clock-names = "mclk", "clk_srcpll";
+
+ i2s2hdmi = <1>;
+
+ status = "okay";
+ };
+
+ aml_spdif: spdif {
+ compatible = "amlogic, g12a-snd-spdif-a";
+ #sound-dai-cells = <0>;
+ clocks = <&clkc CLKID_MPLL0
+ &clkc CLKID_FCLK_DIV4
+ &clkaudio CLKID_AUDIO_SPDIFIN
+ &clkaudio CLKID_AUDIO_SPDIFOUT
+ &clkaudio CLKID_AUDIO_SPDIFIN_CTRL
+ &clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>;
+ clock-names = "sysclk", "fixed_clk", "gate_spdifin",
+ "gate_spdifout", "clk_spdifin", "clk_spdifout";
+ interrupts =
+ <GIC_SPI 151 IRQ_TYPE_EDGE_RISING>;
+
+ interrupt-names = "irq_spdifin";
+ pinctrl-names = "spdif_pins",
+ "spdif_pins_mute";
+ pinctrl-0 = <&spdifout &spdifin>;
+ pinctrl-1 = <&spdifout_a_mute>;
+ status = "okay";
+ };
+ aml_spdif_b: spdif_b {
+ compatible = "amlogic, g12a-snd-spdif-b";
+ #sound-dai-cells = <0>;
+ clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/
+ &clkaudio CLKID_AUDIO_SPDIFOUTB
+ &clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>;
+ clock-names = "sysclk",
+ "gate_spdifout", "clk_spdifout";
+ status = "disabled";
+ };
+ aml_pdm: pdm {
+ compatible = "amlogic, g12a-snd-pdm";
+ #sound-dai-cells = <0>;
+ clocks = <&clkaudio CLKID_AUDIO_PDM
+ &clkc CLKID_FCLK_DIV3
+ &clkc CLKID_MPLL3
+ &clkaudio CLKID_AUDIO_PDMIN0
+ &clkaudio CLKID_AUDIO_PDMIN1>;
+ clock-names = "gate",
+ "sysclk_srcpll",
+ "dclk_srcpll",
+ "pdm_dclk",
+ "pdm_sysclk";
+ pinctrl-names = "pdm_pins";
+ pinctrl-0 = <&pdmin>;
+ filter_mode = <1>; /* mode 0~4, defalut:1 */
+ status = "okay";
+ };
+ aml_loopback: loopback {
+ compatible = "amlogic, snd-loopback";
+ /*
+ * 0: out rate = in data rate;
+ * 1: out rate = loopback data rate;
+ */
+ lb_mode = <0>;
+
+ /* datain src
+ * 0: tdmin_a;
+ * 1: tdmin_b;
+ * 2: tdmin_c;
+ * 3: spdifin;
+ * 4: pdmin;
+ */
+ datain_src = <4>;
+ datain_chnum = <8>;
+ datain_chmask = <0x3f>;
+
+ /* tdmin_lb src
+ * 0: tdmoutA
+ * 1: tdmoutB
+ * 2: tdmoutC
+ * 3: PAD_tdminA
+ * 4: PAD_tdminB
+ * 5: PAD_tdminC
+ */
+ datalb_src = <2>;
+ datalb_chnum = <8>;
+ datalb_chmask = <0x3>;
+
+ status = "disabled";
+ };
+
+ audioresample: resample {
+ compatible = "amlogic, g12a-resample";
+ clocks = <&clkc CLKID_MPLL3
+ &clkaudio CLKID_AUDIO_MCLK_F
+ &clkaudio CLKID_AUDIO_RESAMPLE_CTRL>;
+ clock-names = "resample_pll", "resample_src", "resample_clk";
+ /*same with toddr_src
+ * TDMIN_A, 0
+ * TDMIN_B, 1
+ * TDMIN_C, 2
+ * SPDIFIN, 3
+ * PDMIN, 4
+ * NONE,
+ * TDMIN_LB, 6
+ * LOOPBACK, 7
+ */
+ resample_module = <4>;
+ status = "disabled";
+ };
+ aml_pwrdet: pwrdet {
+ compatible = "amlogic, g12a-power-detect";
+
+ interrupts = <GIC_SPI 155 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "pwrdet_irq";
+
+ /* pwrdet source sel
+ * 7: loopback;
+ * 6: tdmin_lb;
+ * 5: reserved;
+ * 4: pdmin;
+ * 3: spdifin;
+ * 2: tdmin_c;
+ * 1: tdmin_b;
+ * 0: tdmin_a;
+ */
+ pwrdet_src = <4>;
+
+ hi_th = <0x70000>;
+ lo_th = <0x16000>;
+
+ status = "disabled";
+ };
+}; /* end of audiobus */
+
+&pinctrl_periphs {
+ tdmout_a: tdmout_a {
+ mux { /* GPIOX_11, GPIOX_10, GPIOX_9 */
+ groups = "tdma_sclk",
+ "tdma_fs",
+ "tdma_dout0";
+ function = "tdma_out";
+ };
+ };
+
+ tdmin_a: tdmin_a {
+ mux { /* GPIOX_8 */
+ groups = "tdma_din1";
+ function = "tdma_in";
+ };
+ };
+
+ tdmb_mclk: tdmb_mclk {
+ mux {
+ groups = "mclk0_a";
+ function = "mclk0";
+ drive-strength = <2>;
+ };
+ };
+ tdmout_b: tdmout_b {
+ mux { /* GPIOA_1, GPIOA_2, GPIOA_3 */
+ groups = "tdmb_sclk",
+ "tdmb_fs",
+ "tdmb_dout0";
+ function = "tdmb_out";
+ drive-strength = <2>;
+ };
+ };
+
+ tdmin_b:tdmin_b {
+ mux { /* GPIOA_4 */
+ groups = "tdmb_din1"
+ /*,"tdmb_slv_sclk", "tdmb_slv_fs"*/;
+ function = "tdmb_in";
+ drive-strength = <2>;
+ };
+ };
+
+ tdmc_mclk: tdmc_mclk {
+ mux { /* GPIOA_11 */
+ groups = "mclk1_a";
+ function = "mclk1";
+ };
+ };
+
+ clk12_24_z_pins:clk12_24_z_pins {
+ mux {
+ groups = "clk12_24_z";
+ function = "clk12_24_ee";
+ drive-strength = <3>;
+ };
+ };
+
+ tdmout_c:tdmout_c {
+ mux { /* GPIOA_12, GPIOA_13, GPIOA_8, GPIOA_7*/
+ groups = "tdmc_sclk_a",
+ "tdmc_fs_a",
+ "tdmc_dout0_a"
+ /*, "tdmc_dout2",
+ * "tdmc_dout3"
+ */;
+ function = "tdmc_out";
+ };
+ };
+
+ tdmin_c:tdmin_c {
+ mux { /* GPIOA_10 */
+ groups = "tdmc_din0_a";
+ function = "tdmc_in";
+ };
+ };
+
+ spdifin: spdifin {
+ mux {/* GPIOH_5 */
+ groups = "spdif_in_h";
+ function = "spdif_in";
+ };
+ };
+
+ /* GPIOH_4 */
+ /*
+ * spdifout: spdifout {
+ * mux {
+ * groups = "spdif_out_h";
+ * function = "spdif_out";
+ * };
+ *};
+ */
+
+ pdmin: pdmin {
+ mux { /* gpioa_5, gpioa_6, gpioa_7, gpioa_8, gpioa_9*/
+ groups = "pdm_din0_a",
+ /*"pdm_din1_a",*/
+ "pdm_din2_a",
+ /*"pdm_din3_a",*/
+ "pdm_dclk_a";
+ function = "pdm";
+ };
+ };
+
+ bl_pwm_off_pins:bl_pwm_off_pin {
+ mux {
+ pins = "GPIOH_5";
+ function = "gpio_periphs";
+ output-high;
+ };
+ };
+
+}; /* end of pinctrl_periphs */
+
+&pinctrl_aobus {
+ spdifout: spdifout {
+ mux { /* gpiao_10 */
+ groups = "spdif_out_ao";
+ function = "spdif_out_ao";
+ };
+ };
+
+ spdifout_a_mute: spdifout_a_mute {
+ mux { /* gpiao_10 */
+ groups = "GPIOAO_10";
+ function = "gpio_periphs";
+ };
+ };
+}; /* end of pinctrl_aobus */
+
+&irblaster {
+ status = "disabled";
+};
+
+&audio_data {
+ status = "okay";
+};
+
+/*if you want to use vdin just modify status to "ok"*/
+&vdin0 {
+ memory-region = <&vdin0_cma_reserved>;
+ status = "okay";
+ /*vdin write mem color depth support:
+ *bit0:support 8bit
+ *bit1:support 9bit
+ *bit2:support 10bit
+ *bit3:support 12bit
+ *bit4:support yuv422 10bit full pack mode (from txl new add)
+ */
+ tv_bit_mode = <0x15>;
+};
+&vdin1 {
+ memory-region = <&vdin1_cma_reserved>;
+ status = "okay";
+ /*vdin write mem color depth support:
+ *bit0:support 8bit
+ *bit1:support 9bit
+ *bit2:support 10bit
+ *bit3:support 12bit
+ */
+ tv_bit_mode = <1>;
+};
+
+&sd_emmc_c {
+ status = "okay";
+ emmc {
+ caps = "MMC_CAP_8_BIT_DATA",
+ "MMC_CAP_MMC_HIGHSPEED",
+ "MMC_CAP_SD_HIGHSPEED",
+ "MMC_CAP_NONREMOVABLE",
+ /* "MMC_CAP_1_8V_DDR", */
+ "MMC_CAP_HW_RESET",
+ "MMC_CAP_ERASE",
+ "MMC_CAP_CMD23";
+ caps2 = "MMC_CAP2_HS200";
+ /* "MMC_CAP2_HS400";*/
+ f_min = <400000>;
+ f_max = <200000000>;
+ };
+};
+
+&sd_emmc_b {
+ status = "okay";
+ sd {
+ caps = "MMC_CAP_4_BIT_DATA",
+ "MMC_CAP_MMC_HIGHSPEED",
+ "MMC_CAP_SD_HIGHSPEED";
+ f_min = <400000>;
+ f_max = <50000000>;
+ };
+};
+
+&sd_emmc_a {
+ status = "okay";
+ sdio {
+ caps = "MMC_CAP_4_BIT_DATA",
+ "MMC_CAP_MMC_HIGHSPEED",
+ "MMC_CAP_SD_HIGHSPEED",
+ "MMC_CAP_NONREMOVABLE",
+ "MMC_CAP_UHS_SDR12",
+ "MMC_CAP_UHS_SDR25",
+ "MMC_CAP_UHS_SDR50",
+ "MMC_CAP_UHS_SDR104",
+ "MMC_PM_KEEP_POWER",
+ "MMC_CAP_SDIO_IRQ";
+ f_min = <400000>;
+ f_max = <200000000>;
+ };
+};
+
+&nand {
+ status = "disabled";
+ plat-names = "bootloader","nandnormal";
+ plat-num = <2>;
+ plat-part-0 = <&bootloader>;
+ plat-part-1 = <&nandnormal>;
+ bootloader: bootloader{
+ enable_pad ="ce0";
+ busy_pad = "rb0";
+ timming_mode = "mode5";
+ bch_mode = "bch8_1k";
+ t_rea = <20>;
+ t_rhoh = <15>;
+ chip_num = <1>;
+ part_num = <0>;
+ rb_detect = <1>;
+ };
+ nandnormal: nandnormal{
+ enable_pad ="ce0";
+ busy_pad = "rb0";
+ timming_mode = "mode5";
+ bch_mode = "bch8_1k";
+ plane_mode = "twoplane";
+ t_rea = <20>;
+ t_rhoh = <15>;
+ chip_num = <2>;
+ part_num = <3>;
+ partition = <&nand_partitions>;
+ rb_detect = <1>;
+ };
+ nand_partitions:nand_partition{
+ /*
+ * if bl_mode is 1, tpl size was generate by
+ * fip_copies * fip_size which
+ * will not skip bad when calculating
+ * the partition size;
+ *
+ * if bl_mode is 0,
+ * tpl partition must be comment out.
+ */
+ tpl{
+ offset=<0x0 0x0>;
+ size=<0x0 0x0>;
+ };
+ logo{
+ offset=<0x0 0x0>;
+ size=<0x0 0x200000>;
+ };
+ recovery{
+ offset=<0x0 0x0>;
+ size=<0x0 0x1000000>;
+ };
+ boot{
+ offset=<0x0 0x0>;
+ size=<0x0 0x1000000>;
+ };
+ system{
+ offset=<0x0 0x0>;
+ size=<0x0 0x4000000>;
+ };
+ data{
+ offset=<0xffffffff 0xffffffff>;
+ size=<0x0 0x0>;
+ };
+ };
+};
+&dwc3 {
+ status = "okay";
+};
+
+&usb2_phy_v2 {
+ status = "okay";
+ portnum = <2>;
+};
+
+&usb3_phy_v2 {
+ status = "okay";
+ portnum = <0>;
+ otg = <1>;
+ gpio-vbus-power = "GPIOH_6";
+ gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>;
+};
+
+&dwc2_a {
+ status = "okay";
+ /** 0: normal, 1: otg+dwc3 host only, 2: otg+dwc3 device only*/
+ controller-type = <3>;
+};
+&ethmac {
+ status = "okay";
+/* //conflict with isp i2c
+ * pinctrl-names = "internal_eth_pins";
+ * pinctrl-0 = <&internal_eth_pins>;
+ */
+ mc_val = <0x4be04>;
+
+ internal_phy=<1>;
+};
+
+&uart_A {
+ status = "okay";
+};
+
+&pcie_A {
+ reset-gpio = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&saradc {
+ status = "okay";
+};
+
+&spicc1 {
+ status = "disabled";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spicc1_pins>;
+ cs-gpios = <&gpio GPIOH_6 0>;
+};
diff --git a/arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi
index 60c3cff..175af58 100644
--- a/arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi
+++ b/arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi
@@ -13,12 +13,13 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
-*/
+ */
+#include <dt-bindings/display/meson-drm-ids.h>
/ {
venc-cvbs {
status = "okay";
- compatible = "amlogic,meson-gxbb-cvbs";
+ compatible = "amlogic, meson-g12a-cvbs";
ports {
#address-cells = <1>;
@@ -104,6 +105,138 @@
status = "okay";
compatible = "amlogic,drm-subsystem";
ports = <&vpu_out>;
+
+ vpu_topology: vpu_topology {
+ vpu_blocks {
+ osd1_block: block@0 {
+ id = /bits/ 8 <OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <0>;
+ block_name = "osd1_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd1_block>;
+ };
+ osd2_block: block@1 {
+ id = /bits/ 8 <OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <0>;
+ block_name = "osd2_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd2_block>;
+ };
+ osd3_block: block@2 {
+ id = /bits/ 8 <OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <0>;
+ block_name = "osd3_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd3_block>;
+ };
+ afbc_osd1_block: block@3 {
+ id = /bits/ 8 <AFBC_OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd1_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd1_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &osd_blend_block>;
+ };
+ afbc_osd2_block: block@4 {
+ id = /bits/ 8 <AFBC_OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd2_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd2_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd2_block>;
+ };
+ afbc_osd3_block: block@5 {
+ id = /bits/ 8 <AFBC_OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd3_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd3_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd3_block>;
+ };
+ scaler_osd1_block: block@6 {
+ id = /bits/ 8 <SCALER_OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd1_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd1_hdr_dolby_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &vpp_postblend_block>;
+ };
+ scaler_osd2_block: block@7 {
+ id = /bits/ 8 <SCALER_OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd2_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &afbc_osd2_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <2 &osd_blend_block>;
+ };
+ scaler_osd3_block: block@8 {
+ id = /bits/ 8 <SCALER_OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd3_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &afbc_osd3_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <3 &osd_blend_block>;
+ };
+ osd_blend_block: block@9 {
+ id = /bits/ 8 <OSD_BLEND_BLOCK>;
+ block_name = "osd_blend_block";
+ type = /bits/ 8 <3>;
+ num_in_links = /bits/ 8 <0x3>;
+ in_links = <0 &afbc_osd1_block>,
+ <0 &scaler_osd2_block>,
+ <0 &scaler_osd3_block>;
+ num_out_links = /bits/ 8 <0x2>;
+ out_links = <0 &osd1_hdr_dolby_block>,
+ <1 &vpp_postblend_block>;
+ };
+ osd1_hdr_dolby_block: block@10 {
+ id = /bits/ 8 <OSD1_HDR_BLOCK>;
+ block_name = "osd1_hdr_dolby_block";
+ type = /bits/ 8 <4>;
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd_blend_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd1_block>;
+ };
+ vpp_postblend_block: block@12 {
+ id = /bits/ 8 <VPP_POSTBLEND_BLOCK>;
+ block_name = "vpp_postblend_block";
+ type = /bits/ 8 <6>;
+ num_in_links = /bits/ 8 <0x2>;
+ in_links = <0 &scaler_osd1_block>,
+ <1 &osd_blend_block>;
+ num_out_links = <0x0>;
+ };
+ };
+ };
+
+ vpu_hw_para: vpu_hw_para@0 {
+ osd_ver = /bits/ 8 <0x2>;
+ afbc_type = /bits/ 8 <0x2>;
+ has_deband = /bits/ 8 <0x1>;
+ has_lut = /bits/ 8 <0x1>;
+ has_rdma = /bits/ 8 <0x1>;
+ osd_fifo_len = /bits/ 8 <64>;
+ vpp_fifo_len = /bits/ 32 <0xfff>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/amlogic/mesong12b_drm.dtsi b/arch/arm64/boot/dts/amlogic/mesong12b_drm.dtsi
new file mode 100644
index 0000000..04e6f48
--- a/dev/null
+++ b/arch/arm64/boot/dts/amlogic/mesong12b_drm.dtsi
@@ -0,0 +1,241 @@
+/*
+ * arch/arm64/boot/dts/amlogic/meson_drm.dtsi
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+#include <dt-bindings/display/meson-drm-ids.h>
+
+/ {
+ venc-cvbs {
+ status = "okay";
+ compatible = "amlogic, meson-g12b-cvbs";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ enc_cvbs_in: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ //venc_cvbs_in_vpu: endpoint@0 {
+ // reg = <0>;
+ // remote-endpoint = <&vpu_out_venc_cvbs>;
+ //};
+ };
+ };
+ };
+
+ drm_amhdmitx: drm-amhdmitx {
+ status = "disabled";
+ hdcp = "disabled";
+ compatible = "amlogic,drm-amhdmitx";
+ dev_name = "meson-amhdmitx";
+ interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
+ ports {
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ hdmi_in_vpu: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&vpu_out_hdmi>;
+ };
+ };
+ };
+ };
+
+ drm_lcd: drm-lcd {
+ status = "disabled";
+ compatible = "amlogic,drm-lcd";
+ dev_name = "meson-lcd";
+ ports {
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ lcd_in_vpu: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&vpu_out_lcd>;
+ };
+ };
+ };
+ };
+
+ drm_vpu: drm-vpu@0xff900000 {
+ status = "disabled";
+ compatible = "amlogic,meson-g12b-vpu";
+ memory-region = <&logo_reserved>;
+ reg = <0x0 0xff900000 0x0 0x40000>,
+ <0x0 0xff63c000 0x0 0x2000>,
+ <0x0 0xff638000 0x0 0x2000>;
+ reg-names = "base", "hhi", "dmc";
+ interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 56 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "viu-vsync", "viu2-vsync";
+ clocks = <&clkc CLKID_VPU_CLKC_MUX>;
+ clock-names = "vpu_clkc";
+ dma-coherent;
+ vpu_out: port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vpu_out_hdmi: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&hdmi_in_vpu>;
+ };
+ vpu_out_lcd: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&lcd_in_vpu>;
+ };
+ };
+ };
+
+ drm_subsystem: drm-subsystem {
+ status = "okay";
+ compatible = "amlogic,drm-subsystem";
+ ports = <&vpu_out>;
+
+ vpu_topology: vpu_topology {
+ vpu_blocks {
+ osd1_block: block@0 {
+ id = /bits/ 8 <OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <0>;
+ block_name = "osd1_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd1_block>;
+ };
+ osd2_block: block@1 {
+ id = /bits/ 8 <OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <0>;
+ block_name = "osd2_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd2_block>;
+ };
+ osd3_block: block@2 {
+ id = /bits/ 8 <OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <0>;
+ block_name = "osd3_block";
+ num_in_links = /bits/ 8 <0x0>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &afbc_osd3_block>;
+ };
+ afbc_osd1_block: block@3 {
+ id = /bits/ 8 <AFBC_OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd1_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd1_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &osd_blend_block>;
+ };
+ afbc_osd2_block: block@4 {
+ id = /bits/ 8 <AFBC_OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd2_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd2_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd2_block>;
+ };
+ afbc_osd3_block: block@5 {
+ id = /bits/ 8 <AFBC_OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <1>;
+ block_name = "afbc_osd3_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd3_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd3_block>;
+ };
+ scaler_osd1_block: block@6 {
+ id = /bits/ 8 <SCALER_OSD1_BLOCK>;
+ index = /bits/ 8 <0>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd1_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd1_hdr_dolby_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &vpp_postblend_block>;
+ };
+ scaler_osd2_block: block@7 {
+ id = /bits/ 8 <SCALER_OSD2_BLOCK>;
+ index = /bits/ 8 <1>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd2_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &afbc_osd2_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <2 &osd_blend_block>;
+ };
+ scaler_osd3_block: block@8 {
+ id = /bits/ 8 <SCALER_OSD3_BLOCK>;
+ index = /bits/ 8 <2>;
+ type = /bits/ 8 <2>;
+ block_name = "scaler_osd3_block";
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &afbc_osd3_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <3 &osd_blend_block>;
+ };
+ osd_blend_block: block@9 {
+ id = /bits/ 8 <OSD_BLEND_BLOCK>;
+ block_name = "osd_blend_block";
+ type = /bits/ 8 <3>;
+ num_in_links = /bits/ 8 <0x3>;
+ in_links = <0 &afbc_osd1_block>,
+ <0 &scaler_osd2_block>,
+ <0 &scaler_osd3_block>;
+ num_out_links = /bits/ 8 <0x2>;
+ out_links = <0 &osd1_hdr_dolby_block>,
+ <1 &vpp_postblend_block>;
+ };
+ osd1_hdr_dolby_block: block@10 {
+ id = /bits/ 8 <OSD1_HDR_BLOCK>;
+ block_name = "osd1_hdr_dolby_block";
+ type = /bits/ 8 <4>;
+ num_in_links = /bits/ 8 <0x1>;
+ in_links = <0 &osd_blend_block>;
+ num_out_links = /bits/ 8 <0x1>;
+ out_links = <0 &scaler_osd1_block>;
+ };
+ vpp_postblend_block: block@12 {
+ id = /bits/ 8 <VPP_POSTBLEND_BLOCK>;
+ block_name = "vpp_postblend_block";
+ type = /bits/ 8 <6>;
+ num_in_links = /bits/ 8 <0x2>;
+ in_links = <0 &scaler_osd1_block>,
+ <1 &osd_blend_block>;
+ num_out_links = <0x0>;
+ };
+ };
+ };
+
+ vpu_hw_para: vpu_hw_para@0 {
+ osd_ver = /bits/ 8 <0x2>;
+ afbc_type = /bits/ 8 <0x2>;
+ has_deband = /bits/ 8 <0x1>;
+ has_lut = /bits/ 8 <0x1>;
+ has_rdma = /bits/ 8 <0x1>;
+ osd_fifo_len = /bits/ 8 <64>;
+ vpp_fifo_len = /bits/ 32 <0xfff>;
+ };
+ };
+};
diff --git a/drivers/amlogic/Makefile b/drivers/amlogic/Makefile
index fec14e2..c8d62eb 100644
--- a/drivers/amlogic/Makefile
+++ b/drivers/amlogic/Makefile
@@ -116,7 +116,7 @@ obj-$(CONFIG_AMLOGIC_IIO) += iio/
obj-$(CONFIG_AMLOGIC_DDR_TOOL) += ddr_tool/
-obj-$(CONFIG_DRM_MESON) += drm/
+obj-$(CONFIG_AMLOGIC_DRM) += drm/
obj-$(CONFIG_AMLOGIC_M8B_SM) += secure_monitor/
diff --git a/drivers/amlogic/drm/Kconfig b/drivers/amlogic/drm/Kconfig
index 6298cde..999b650 100644
--- a/drivers/amlogic/drm/Kconfig
+++ b/drivers/amlogic/drm/Kconfig
@@ -1,11 +1,41 @@
+menuconfig AMLOGIC_DRM
+ bool "Amlogic drm support"
+ depends on AMLOGIC_DRIVER && DRM
+ default n
+ help
+ amlogic drm driver provide drm support on Amlogic
+ SOC chips.
+choice
+ prompt "meson drm driver type"
+ depends on AMLOGIC_DRM
+ default DRM_MESON
+
config DRM_MESON
- tristate "DRM Support for Amlogic Meson Display Controller"
+ tristate "DRM Support for Amlogic new Display Controller"
+ depends on DRM && OF && (ARM || ARM64)
+ select DRM_KMS_HELPER
+ select DRM_KMS_CMA_HELPER
+ select DRM_GEM_CMA_HELPER
+ select VIDEOMODE_HELPERS
+ select REGMAP_MMIO
+ help
+ amlogic new soc display controller
+ use the pipeline and modularized
+
+config DRM_MESON_V0
+ tristate "DRM Support for Amlogic old Display Controller"
depends on DRM && OF && (ARM || ARM64)
select DRM_KMS_HELPER
select DRM_KMS_CMA_HELPER
select DRM_GEM_CMA_HELPER
select VIDEOMODE_HELPERS
select REGMAP_MMIO
+ help
+ amlogic old soc display controller
+ use the osd driver
+endchoice
+
+if DRM_MESON
config DRM_MESON_VPU
tristate "support drm vpu function for meson drm display."
@@ -59,3 +89,10 @@ config DRM_MESON_EMULATE_FBDEV
depends on DRM_MESON && DRM_MESON_USE_ION
help
Emulate framebuffer device for device which need use fbdev api.
+endif
+
+if DRM_MESON_V0
+
+source "drivers/amlogic/drm/drm-v0/Kconfig"
+
+endif
diff --git a/drivers/amlogic/drm/Makefile b/drivers/amlogic/drm/Makefile
index 2446575..bdbcd79 100644
--- a/drivers/amlogic/drm/Makefile
+++ b/drivers/amlogic/drm/Makefile
@@ -1,28 +1,38 @@
-meson_drv-y += am_meson_drv.o
-ccflags-y += -Idrivers/amlogic/media/osd/
-
ifeq ($(CONFIG_DRM_MESON_USE_ION),y)
- meson_drv-y += am_meson_gem.o am_meson_fb.o
- ccflags-y += -Idrivers/staging/android/
+ meson-drm-y += meson_gem.o meson_fb.o
+ ccflags-y += -Idrivers/staging/android/
endif
ifeq ($(CONFIG_DRM_MESON_EMULATE_FBDEV),y)
- meson_drv-y += am_meson_fbdev.o
+ meson-drm-y += meson_fbdev.o
endif
ifneq ($(CONFIG_DRM_MESON_VPU),)
- meson_vpu-y += am_meson_vpu.o
+ meson-drm-y += meson_vpu.o
endif
ifneq ($(CONFIG_DRM_MESON_HDMI),)
- meson_hdmi-y += am_meson_hdmi.o am_meson_hdcp.o
+ meson-drm-y += meson_hdmi.o meson_hdcp.o
endif
ifneq ($(CONFIG_DRM_MESON_PANEL),)
- meson_lcd-y += am_meson_lcd.o
+ meson-drm-y += meson_lcd.o
endif
-obj-$(CONFIG_DRM_MESON) += meson_drv.o
-obj-$(CONFIG_DRM_MESON_VPU) += meson_vpu.o
-obj-$(CONFIG_DRM_MESON_HDMI) += meson_hdmi.o
-obj-$(CONFIG_DRM_MESON_PANEL) += meson_lcd.o
+meson-drm-y += meson_drv.o meson_plane.o meson_vpu_pipeline_traverse.o \
+ meson_crtc.o meson_vpu_pipeline.o meson_vpu_pipeline_private.o \
+
+meson-drm-y += \
+ vpu-hw/meson_vpu_osd_mif.o \
+ vpu-hw/meson_osd_afbc.o \
+ vpu-hw/meson_osd_scaler.o \
+ vpu-hw/meson_vpu_osdblend.o \
+ vpu-hw/meson_vpu_hdr_dv.o \
+ vpu-hw/meson_vpu_postblend.o
+
+ifneq ($(CONFIG_DRM_MESON_V0), y)
+ ccflags-y += -Idrivers/amlogic/media/osd/ -I$(src)/vpu-hw -I$(src)
+ obj-y += meson-drm.o
+else
+ obj-y += drm-v0/
+endif
diff --git a/drivers/amlogic/drm/am_meson_fbdev.h b/drivers/amlogic/drm/am_meson_fbdev.h
deleted file mode 100644
index 218ddca..0000000
--- a/drivers/amlogic/drm/am_meson_fbdev.h
+++ b/dev/null
@@ -1,24 +0,0 @@
-/*
- * drivers/amlogic/drm/am_meson_fbdev.h
- *
- * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __AM_MESON_FBDEV_H
-#define __AM_MESON_FBDEV_H
-
-#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
-int am_meson_drm_fbdev_init(struct drm_device *dev);
-void am_meson_drm_fbdev_fini(struct drm_device *dev);
-#endif
-
-#endif /* __AM_MESON_FBDEV_H */
diff --git a/drivers/amlogic/drm/drm-v0/Kconfig b/drivers/amlogic/drm/drm-v0/Kconfig
new file mode 100644
index 0000000..c463c64
--- a/dev/null
+++ b/drivers/amlogic/drm/drm-v0/Kconfig
@@ -0,0 +1,52 @@
+config DRM_MESON_VPU
+ tristate "support drm vpu function for meson drm display."
+ default y
+ depends on DRM_MESON_V0
+ help
+ add drm vpu support.
+ Choose this option if you have a aMLOGIC soc chipset.
+ This driver provides KMS.
+ This driver also provides crtcs and planes management.
+
+config DRM_MESON_HDMI
+ tristate "support drm hdmi function for meson drm display."
+ default y
+ depends on DRM_MESON_V0
+ depends on AMLOGIC_HDMITX
+ help
+ add drm hdmi support.
+ use internal amlogic media vout hdmi driver.
+ We should confirm AMLOGIC_HDMITX is configured if
+ DRM_MESON_HDMI is selected.
+
+config DRM_MESON_PANEL
+ tristate "support drm panel function for meson drm display."
+ default y
+ depends on DRM_MESON_V0
+ depends on AMLOGIC_LCD
+ select DRM_PANEL
+ select DRM_MIPI_DSI
+ help
+ add drm panel support.
+ use internal amlogic media vout lcd driver.
+ We should confirm AMLOGIC_LCD is configured if
+ DRM_MESON_PANEL is selected.
+
+config DRM_MESON_USE_ION
+ bool "gem use ion to alloc/free graphic buffer."
+ default y
+ depends on DRM_MESON_V0
+ help
+ MESON DRM use CMA HELPER to manage framebuffer.
+ It need reserve memory in CMA pool.
+ We implement GEM to allocate/free framebuffer from ion.
+ For dumb used by displaycontrol we alloc from the ION CMA HEAP.
+ For dumb used by app, we can alloc from the ION.
+ SYSTEM HEAP which dont need reserve memory.
+
+config DRM_MESON_EMULATE_FBDEV
+ bool "emulate framebuffer dev by drm."
+ default n
+ depends on DRM_MESON_V0 && DRM_MESON_USE_ION
+ help
+ Emulate framebuffer device for device which need use fbdev api.
diff --git a/drivers/amlogic/drm/drm-v0/Makefile b/drivers/amlogic/drm/drm-v0/Makefile
new file mode 100644
index 0000000..dd06060
--- a/dev/null
+++ b/drivers/amlogic/drm/drm-v0/Makefile
@@ -0,0 +1,28 @@
+meson_drv-y += am_meson_drv.o
+ccflags-y += -Idrivers/amlogic/media/osd/
+
+ifeq ($(CONFIG_DRM_MESON_USE_ION),y)
+ meson_drv-y += am_meson_gem.o am_meson_fb.o
+ ccflags-y += -Idrivers/staging/android/
+endif
+
+ifeq ($(CONFIG_DRM_MESON_EMULATE_FBDEV),y)
+ meson_drv-y += am_meson_fbdev.o
+endif
+
+ifneq ($(CONFIG_DRM_MESON_VPU),)
+ meson_vpu-y += am_meson_vpu.o
+endif
+
+ifneq ($(CONFIG_DRM_MESON_HDMI),)
+ meson_hdmi-y += am_meson_hdmi.o am_meson_hdcp.o
+endif
+
+ifneq ($(CONFIG_DRM_MESON_PANEL),)
+ meson_lcd-y += am_meson_lcd.o
+endif
+
+obj-y += meson_drv.o
+obj-$(CONFIG_DRM_MESON_VPU) += meson_vpu.o
+obj-$(CONFIG_DRM_MESON_HDMI) += meson_hdmi.o
+obj-$(CONFIG_DRM_MESON_PANEL) += meson_lcd.o
diff --git a/drivers/amlogic/drm/am_meson_drv.c b/drivers/amlogic/drm/drm-v0/am_meson_drv.c
index 190cba3..2880b1c 100644
--- a/drivers/amlogic/drm/am_meson_drv.c
+++ b/drivers/amlogic/drm/drm-v0/am_meson_drv.c
@@ -1,23 +1,18 @@
/*
- * Copyright (C) 2016 BayLibre, SAS
- * Author: Neil Armstrong <narmstrong@baylibre.com>
- * Copyright (C) 2014 Endless Mobile
+ * drivers/amlogic/drm/drm-v0/am_meson_drv.c
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
*
- * Written by:
- * Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include <linux/kernel.h>
diff --git a/drivers/amlogic/drm/am_meson_drv.h b/drivers/amlogic/drm/drm-v0/am_meson_drv.h
index 77279a5..c935d91 100644
--- a/drivers/amlogic/drm/am_meson_drv.h
+++ b/drivers/amlogic/drm/drm-v0/am_meson_drv.h
@@ -1,19 +1,18 @@
/*
- * Copyright (C) 2016 BayLibre, SAS
- * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * drivers/amlogic/drm/drm-v0/am_meson_drv.h
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __AM_MESON_DRV_H
diff --git a/drivers/amlogic/drm/am_meson_fb.c b/drivers/amlogic/drm/drm-v0/am_meson_fb.c
index 095f7ac..5ecd9e4 100644
--- a/drivers/amlogic/drm/am_meson_fb.c
+++ b/drivers/amlogic/drm/drm-v0/am_meson_fb.c
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_fb.c
+ * drivers/amlogic/drm/drm-v0/am_meson_fb.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -14,6 +14,7 @@
* more details.
*
*/
+
#include <drm/drm_atomic_helper.h>
#include "am_meson_fb.h"
diff --git a/drivers/amlogic/drm/am_meson_fb.h b/drivers/amlogic/drm/drm-v0/am_meson_fb.h
index faf0fce0..1751f79 100644
--- a/drivers/amlogic/drm/am_meson_fb.h
+++ b/drivers/amlogic/drm/drm-v0/am_meson_fb.h
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_fb.h
+ * drivers/amlogic/drm/drm-v0/am_meson_fb.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
diff --git a/drivers/amlogic/drm/am_meson_fbdev.c b/drivers/amlogic/drm/drm-v0/am_meson_fbdev.c
index 610f3ca..1998697 100644
--- a/drivers/amlogic/drm/am_meson_fbdev.c
+++ b/drivers/amlogic/drm/drm-v0/am_meson_fbdev.c
@@ -1,16 +1,18 @@
/*
- * drivers/amlogic/drm/am_meson_fbdev.c
+ * drivers/amlogic/drm/drm-v0/am_meson_fbdev.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <drm/drm.h>
diff --git a/drivers/amlogic/drm/am_meson_lcd.h b/drivers/amlogic/drm/drm-v0/am_meson_fbdev.h
index 565f8eb..c446f98 100644
--- a/drivers/amlogic/drm/am_meson_lcd.h
+++ b/drivers/amlogic/drm/drm-v0/am_meson_fbdev.h
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_lcd.h
+ * drivers/amlogic/drm/drm-v0/am_meson_fbdev.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -15,10 +15,12 @@
*
*/
-#ifndef __AM_DRM_LCD_H
-#define __AM_DRM_LCD_H
-
-#include "am_meson_drv.h"
+#ifndef __AM_MESON_FBDEV_H
+#define __AM_MESON_FBDEV_H
+#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
+int am_meson_drm_fbdev_init(struct drm_device *dev);
+void am_meson_drm_fbdev_fini(struct drm_device *dev);
#endif
+#endif /* __AM_MESON_FBDEV_H */
diff --git a/drivers/amlogic/drm/am_meson_gem.c b/drivers/amlogic/drm/drm-v0/am_meson_gem.c
index 9d731b8..b06d104 100644
--- a/drivers/amlogic/drm/am_meson_gem.c
+++ b/drivers/amlogic/drm/drm-v0/am_meson_gem.c
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_gem.c
+ * drivers/amlogic/drm/drm-v0/am_meson_gem.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -14,6 +14,7 @@
* more details.
*
*/
+
#include <drm/drmP.h>
#include <drm/drm_gem.h>
#include <drm/drm_vma_manager.h>
@@ -44,12 +45,11 @@ static int am_meson_gem_alloc_ion_buff(
//check flags to set different ion heap type.
//if flags is set to 0, need to use ion dma buffer.
- if (((flags & (BO_USE_SCANOUT | BO_USE_CURSOR)) != 0)
+ if (((flags & (MESON_USE_SCANOUT | MESON_USE_CURSOR)) != 0)
|| (flags == 0)) {
handle = ion_alloc(client, meson_gem_obj->base.size,
0, (1 << ION_HEAP_TYPE_DMA), 0);
- }
- else {
+ } else {
handle = ion_alloc(client, meson_gem_obj->base.size,
0, (1 << ION_HEAP_TYPE_SYSTEM), 0);
bscatter = true;
@@ -415,10 +415,9 @@ struct sg_table *am_meson_gem_prime_get_sg_table(
}
return dst_table;
}
- else {
- DRM_ERROR("Not support import buffer from other driver.\n");
- return NULL;
- }
+
+ DRM_ERROR("Not support import buffer from other driver.\n");
+ return NULL;
}
struct drm_gem_object *am_meson_gem_prime_import_sg_table(
diff --git a/drivers/amlogic/drm/am_meson_gem.h b/drivers/amlogic/drm/drm-v0/am_meson_gem.h
index f6dcc7e..166a73c 100644
--- a/drivers/amlogic/drm/am_meson_gem.h
+++ b/drivers/amlogic/drm/drm-v0/am_meson_gem.h
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_gem.h
+ * drivers/amlogic/drm/drm-v0/am_meson_gem.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -18,7 +18,7 @@
#ifndef __AM_MESON_GEM_H
#define __AM_MESON_GEM_H
#include <drm/drm_gem.h>
-#include <linux/amlogic/meson_drm.h>
+#include <uapi/drm/meson_drm.h>
#include <ion/ion_priv.h>
#include "am_meson_drv.h"
diff --git a/drivers/amlogic/drm/am_meson_hdcp.c b/drivers/amlogic/drm/drm-v0/am_meson_hdcp.c
index 3c45c26..6e2f176 100644
--- a/drivers/amlogic/drm/am_meson_hdcp.c
+++ b/drivers/amlogic/drm/drm-v0/am_meson_hdcp.c
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_hdcp.c
+ * drivers/amlogic/drm/drm-v0/am_meson_hdcp.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
diff --git a/drivers/amlogic/drm/am_meson_hdcp.h b/drivers/amlogic/drm/drm-v0/am_meson_hdcp.h
index f95d13f..accf846 100644
--- a/drivers/amlogic/drm/am_meson_hdcp.h
+++ b/drivers/amlogic/drm/drm-v0/am_meson_hdcp.h
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_hdcp.h
+ * drivers/amlogic/drm/drm-v0/am_meson_hdcp.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
diff --git a/drivers/amlogic/drm/am_meson_hdmi.c b/drivers/amlogic/drm/drm-v0/am_meson_hdmi.c
index a2efd9c..7e1a3ee 100644
--- a/drivers/amlogic/drm/am_meson_hdmi.c
+++ b/drivers/amlogic/drm/drm-v0/am_meson_hdmi.c
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_hdmi.c
+ * drivers/amlogic/drm/drm-v0/am_meson_hdmi.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -14,6 +14,7 @@
* more details.
*
*/
+
#include <drm/drm_modeset_helper.h>
#include <drm/drmP.h>
#include <drm/drm_edid.h>
diff --git a/drivers/amlogic/drm/am_meson_hdmi.h b/drivers/amlogic/drm/drm-v0/am_meson_hdmi.h
index 37542dc..82a7bf0 100644
--- a/drivers/amlogic/drm/am_meson_hdmi.h
+++ b/drivers/amlogic/drm/drm-v0/am_meson_hdmi.h
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_hdmi.h
+ * drivers/amlogic/drm/drm-v0/am_meson_hdmi.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -14,6 +14,7 @@
* more details.
*
*/
+
#ifndef __AM_MESON_HDMI_H
#define __AM_MESON_HDMI_H
diff --git a/drivers/amlogic/drm/am_meson_lcd.c b/drivers/amlogic/drm/drm-v0/am_meson_lcd.c
index 462338f..7613cf6 100644
--- a/drivers/amlogic/drm/am_meson_lcd.c
+++ b/drivers/amlogic/drm/drm-v0/am_meson_lcd.c
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_lcd.c
+ * drivers/amlogic/drm/drm-v0/am_meson_lcd.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -685,8 +685,6 @@ static void am_meson_lcd_unbind(struct device *dev, struct device *master,
drm_panel_remove(&am_drm_lcd->panel);
pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
-
- return;
}
static const struct component_ops am_meson_lcd_ops = {
diff --git a/drivers/amlogic/drm/am_meson_lcd.h b/drivers/amlogic/drm/drm-v0/am_meson_lcd.h
index 565f8eb..39ab4d4 100644
--- a/drivers/amlogic/drm/am_meson_lcd.h
+++ b/drivers/amlogic/drm/drm-v0/am_meson_lcd.h
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_lcd.h
+ * drivers/amlogic/drm/drm-v0/am_meson_lcd.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
diff --git a/drivers/amlogic/drm/am_meson_vpu.c b/drivers/amlogic/drm/drm-v0/am_meson_vpu.c
index 9c7850b..f44cbb3 100644
--- a/drivers/amlogic/drm/am_meson_vpu.c
+++ b/drivers/amlogic/drm/drm-v0/am_meson_vpu.c
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_vpu.c
+ * drivers/amlogic/drm/drm-v0/am_meson_vpu.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -14,6 +14,7 @@
* more details.
*
*/
+
#include <drm/drmP.h>
#include <drm/drm_plane.h>
#include <drm/drm_atomic.h>
diff --git a/drivers/amlogic/drm/am_meson_vpu.h b/drivers/amlogic/drm/drm-v0/am_meson_vpu.h
index 03adbbe..5f94006 100644
--- a/drivers/amlogic/drm/am_meson_vpu.h
+++ b/drivers/amlogic/drm/drm-v0/am_meson_vpu.h
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_vpu.h
+ * drivers/amlogic/drm/drm-v0/am_meson_vpu.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -14,6 +14,7 @@
* more details.
*
*/
+
#ifndef __AM_MESON_VPU_H
#define __AM_MESON_VPU_H
diff --git a/drivers/amlogic/drm/meson_crtc.c b/drivers/amlogic/drm/meson_crtc.c
new file mode 100644
index 0000000..f9a24d6
--- a/dev/null
+++ b/drivers/amlogic/drm/meson_crtc.c
@@ -0,0 +1,270 @@
+/*
+ * drivers/amlogic/drm/meson_crtc.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include "meson_crtc.h"
+#include "meson_vpu_pipeline.h"
+#include "osd_drm.h"
+
+static int meson_crtc_set_mode(struct drm_mode_set *set)
+{
+ struct am_meson_crtc *amcrtc;
+ int ret;
+
+ DRM_DEBUG_DRIVER("%s\n", __func__);
+ amcrtc = to_am_meson_crtc(set->crtc);
+ ret = drm_atomic_helper_set_config(set);
+
+ return ret;
+}
+
+static void meson_crtc_destroy_state(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ struct am_meson_crtc_state *meson_crtc_state;
+
+ meson_crtc_state = to_am_meson_crtc_state(state);
+ __drm_atomic_helper_crtc_destroy_state(&meson_crtc_state->base);
+ kfree(meson_crtc_state);
+}
+
+static struct drm_crtc_state *meson_crtc_duplicate_state(struct drm_crtc *crtc)
+{
+ struct am_meson_crtc_state *meson_crtc_state, *old_crtc_state;
+
+ old_crtc_state = to_am_meson_crtc_state(crtc->state);
+
+ meson_crtc_state = kmemdup(old_crtc_state, sizeof(*old_crtc_state),
+ GFP_KERNEL);
+ if (!meson_crtc_state)
+ return NULL;
+
+ __drm_atomic_helper_crtc_duplicate_state(crtc, &meson_crtc_state->base);
+ return &meson_crtc_state->base;
+}
+
+static int meson_crtc_atomic_get_property(struct drm_crtc *crtc,
+ const struct drm_crtc_state *state,
+ struct drm_property *property,
+ uint64_t *val)
+{
+
+ return 0;
+}
+
+static int meson_crtc_atomic_set_property(struct drm_crtc *crtc,
+ struct drm_crtc_state *state,
+ struct drm_property *property,
+ uint64_t val)
+{
+ return 0;
+}
+
+static const struct drm_crtc_funcs am_meson_crtc_funcs = {
+ .atomic_destroy_state = meson_crtc_destroy_state,
+ .atomic_duplicate_state = meson_crtc_duplicate_state,
+ .destroy = drm_crtc_cleanup,
+ .page_flip = drm_atomic_helper_page_flip,
+ .reset = drm_atomic_helper_crtc_reset,
+ .set_config = meson_crtc_set_mode,
+ .atomic_get_property = meson_crtc_atomic_get_property,
+ .atomic_set_property = meson_crtc_atomic_set_property,
+};
+
+static bool am_meson_crtc_mode_fixup(struct drm_crtc *crtc,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adj_mode)
+{
+ //DRM_INFO("%s !!\n", __func__);
+
+ return true;
+}
+
+static void am_meson_crtc_enable(struct drm_crtc *crtc)
+{
+ unsigned long flags;
+ char *name;
+ enum vmode_e mode;
+ struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
+ struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc);
+ struct meson_vpu_pipeline *pipeline = amcrtc->pipeline;
+
+ DRM_INFO("%s\n", __func__);
+ if (!adjusted_mode) {
+ DRM_ERROR("meson_crtc_enable fail, unsupport mode:%s\n",
+ adjusted_mode->name);
+ return;
+ }
+ DRM_INFO("%s: %s\n", __func__, adjusted_mode->name);
+
+ name = am_meson_crtc_get_voutmode(adjusted_mode);
+ mode = validate_vmode(name);
+ if (mode == VMODE_MAX) {
+ DRM_ERROR("no matched vout mode\n");
+ return;
+ }
+ if (is_meson_g12b_cpu() && is_meson_rev_b())
+ set_reset_rdma_trigger_line();
+ set_vout_init(mode);
+ update_vout_viu();
+ memcpy(&pipeline->mode, adjusted_mode,
+ sizeof(struct drm_display_mode));
+ spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags);
+ amcrtc->vblank_enable = 1;
+ spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags);
+ enable_irq(amcrtc->vblank_irq);
+}
+
+static void am_meson_crtc_disable(struct drm_crtc *crtc)
+{
+ struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc);
+ unsigned long flags;
+
+ DRM_INFO("%s\n", __func__);
+ if (crtc->state->event && !crtc->state->active) {
+ spin_lock_irq(&crtc->dev->event_lock);
+ drm_crtc_send_vblank_event(crtc, crtc->state->event);
+ spin_unlock_irq(&crtc->dev->event_lock);
+ crtc->state->event = NULL;
+ }
+
+ spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags);
+ amcrtc->vblank_enable = 0;
+ spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags);
+
+ disable_irq(amcrtc->vblank_irq);
+}
+
+static void am_meson_crtc_commit(struct drm_crtc *crtc)
+{
+ //DRM_INFO("%s\n", __func__);
+}
+
+static int am_meson_atomic_check(struct drm_crtc *crtc,
+ struct drm_crtc_state *crtc_state)
+{
+ struct am_meson_crtc *amcrtc;
+ struct meson_vpu_pipeline *pipeline;
+ struct drm_atomic_state *state = crtc_state->state;
+
+ amcrtc = to_am_meson_crtc(crtc);
+ pipeline = amcrtc->pipeline;
+
+ return vpu_pipeline_check(pipeline, state);
+
+}
+
+static void am_meson_crtc_atomic_begin(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_crtc_state)
+{
+ struct am_meson_crtc *amcrtc;
+ unsigned long flags;
+
+ amcrtc = to_am_meson_crtc(crtc);
+
+ if (crtc->state->event) {
+ WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+ spin_lock_irqsave(&crtc->dev->event_lock, flags);
+ amcrtc->event = crtc->state->event;
+ spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+ crtc->state->event = NULL;
+ }
+}
+
+static void am_meson_crtc_atomic_flush(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_state)
+{
+ struct drm_color_ctm *ctm;
+ struct drm_color_lut *lut;
+ struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc);
+ struct drm_atomic_state *old_atomic_state = old_state->state;
+
+ struct meson_vpu_pipeline *pipeline = amcrtc->pipeline;
+ #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
+ int gamma_lut_size = 0;
+ #endif
+
+ if (crtc->state->color_mgmt_changed) {
+ DRM_INFO("%s color_mgmt_changed!\n", __func__);
+ if (crtc->state->ctm) {
+ DRM_INFO("%s color_mgmt_changed 1!\n", __func__);
+ ctm = (struct drm_color_ctm *)
+ crtc->state->ctm->data;
+ #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
+ am_meson_ctm_set(0, ctm);
+ #endif
+ }
+ if (crtc->state->gamma_lut) {
+ DRM_INFO("%s color_mgmt_changed 2!\n", __func__);
+ lut = (struct drm_color_lut *)
+ crtc->state->gamma_lut->data;
+ #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
+ gamma_lut_size = amvecm_drm_get_gamma_size(0);
+ amvecm_drm_gamma_set(0, lut, gamma_lut_size);
+ #endif
+ }
+ }
+
+ vpu_pipeline_update(pipeline, old_atomic_state);
+}
+
+static const struct drm_crtc_helper_funcs am_crtc_helper_funcs = {
+ .enable = am_meson_crtc_enable,
+ .disable = am_meson_crtc_disable,
+ .commit = am_meson_crtc_commit,
+ .mode_fixup = am_meson_crtc_mode_fixup,
+ .atomic_check = am_meson_atomic_check,
+ .atomic_begin = am_meson_crtc_atomic_begin,
+ .atomic_flush = am_meson_crtc_atomic_flush,
+};
+
+int am_meson_crtc_create(struct am_meson_crtc *amcrtc)
+{
+ struct meson_drm *priv = amcrtc->priv;
+ struct drm_crtc *crtc = &amcrtc->base;
+ struct meson_vpu_pipeline *pipeline = priv->pipeline;
+ #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
+ int gamma_lut_size = 0;
+ #endif
+ int ret;
+
+ DRM_INFO("%s\n", __func__);
+ ret = drm_crtc_init_with_planes(priv->drm, crtc,
+ priv->primary_plane, priv->cursor_plane,
+ &am_meson_crtc_funcs, "amlogic vpu");
+ if (ret) {
+ dev_err(amcrtc->dev, "Failed to init CRTC\n");
+ return ret;
+ }
+
+ drm_crtc_helper_add(crtc, &am_crtc_helper_funcs);
+ osd_drm_init(&osd_meson_dev);
+
+ #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
+ amvecm_drm_init(0);
+ amvecm_drm_gamma_enable(0);
+ gamma_lut_size = amvecm_drm_get_gamma_size(0);
+ drm_mode_crtc_set_gamma_size(crtc, gamma_lut_size);
+ drm_crtc_enable_color_mgmt(crtc, 0, true, gamma_lut_size);
+ #endif
+
+ amcrtc->pipeline = pipeline;
+ priv->crtc = crtc;
+ priv->crtcs[priv->num_crtcs++] = amcrtc;
+ return 0;
+}
+
diff --git a/drivers/amlogic/drm/meson_crtc.h b/drivers/amlogic/drm/meson_crtc.h
new file mode 100644
index 0000000..c02ff85
--- a/dev/null
+++ b/drivers/amlogic/drm/meson_crtc.h
@@ -0,0 +1,65 @@
+/*
+ * drivers/amlogic/drm/meson_crtc.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __MESON_CRTC_H
+#define __MESON_CRTC_H
+
+#include <linux/kernel.h>
+#include <drm/drmP.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <linux/amlogic/media/vout/vout_notify.h>
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
+#include <linux/amlogic/media/amvecm/amvecm.h>
+#endif
+#include "osd.h"
+#include "osd_drm.h"
+#include "meson_vpu.h"
+#include "meson_drv.h"
+#include "meson_fb.h"
+
+struct am_meson_crtc_state {
+ struct drm_crtc_state base;
+};
+
+struct am_meson_crtc {
+ struct drm_crtc base;
+ struct device *dev;
+ struct drm_device *drm_dev;
+
+ struct meson_drm *priv;
+
+ struct drm_pending_vblank_event *event;
+
+ unsigned int vblank_irq;
+ spinlock_t vblank_irq_lock;/*atomic*/
+ u32 vblank_enable;
+
+ struct dentry *crtc_debugfs_dir;
+
+ struct meson_vpu_pipeline *pipeline;
+};
+
+#define to_am_meson_crtc(x) container_of(x, \
+ struct am_meson_crtc, base)
+#define to_am_meson_crtc_state(x) container_of(x, \
+ struct am_meson_crtc_state, base)
+
+int am_meson_crtc_create(struct am_meson_crtc *amcrtc);
+
+#endif
diff --git a/drivers/amlogic/drm/am_meson_drv.c b/drivers/amlogic/drm/meson_drv.c
index 190cba3..eecde0e 100644
--- a/drivers/amlogic/drm/am_meson_drv.c
+++ b/drivers/amlogic/drm/meson_drv.c
@@ -1,23 +1,18 @@
/*
- * Copyright (C) 2016 BayLibre, SAS
- * Author: Neil Armstrong <narmstrong@baylibre.com>
- * Copyright (C) 2014 Endless Mobile
+ * drivers/amlogic/drm/meson_drv.c
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
*
- * Written by:
- * Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include <linux/kernel.h>
@@ -39,18 +34,18 @@
#include <drm/drm_rect.h>
#include <drm/drm_fb_helper.h>
-#include "am_meson_fbdev.h"
+#include "meson_fbdev.h"
#ifdef CONFIG_DRM_MESON_USE_ION
-#include "am_meson_gem.h"
-#include "am_meson_fb.h"
+#include "meson_gem.h"
+#include "meson_fb.h"
#endif
-#include "am_meson_drv.h"
+#include "meson_drv.h"
+#include "meson_vpu_pipeline.h"
#define DRIVER_NAME "meson"
#define DRIVER_DESC "Amlogic Meson DRM driver"
-
static void am_meson_fb_output_poll_changed(struct drm_device *dev)
{
#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
@@ -102,20 +97,21 @@ static int am_meson_enable_vblank(struct drm_device *dev, unsigned int crtc)
{
struct meson_drm *priv = dev->dev_private;
- if (crtc > MESON_MAX_CRTC)
+ if (crtc >= MESON_MAX_CRTC)
return -EBADFD;
- return priv->crtc_funcs[crtc]->enable_vblank(priv->crtc);
+ priv->crtc_funcs[crtc]->enable_vblank(priv->crtc);
+ return 0;
}
static void am_meson_disable_vblank(struct drm_device *dev, unsigned int crtc)
{
struct meson_drm *priv = dev->dev_private;
- if (crtc > MESON_MAX_CRTC)
+ if (crtc >= MESON_MAX_CRTC)
return;
- return priv->crtc_funcs[crtc]->disable_vblank(priv->crtc);
+ priv->crtc_funcs[crtc]->disable_vblank(priv->crtc);
}
static void am_meson_load(struct drm_device *dev)
@@ -224,6 +220,7 @@ static int am_meson_drm_bind(struct device *dev)
{
struct meson_drm *priv;
struct drm_device *drm;
+ struct platform_device *pdev = to_platform_device(dev);
int ret = 0;
meson_driver.driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM |
@@ -250,6 +247,9 @@ static int am_meson_drm_bind(struct device *dev)
goto err_free2;
#endif
+ vpu_topology_init(pdev, priv);
+ meson_vpu_block_state_init(priv, priv->pipeline);
+
drm_mode_config_init(drm);
/* Try to bind all sub drivers. */
@@ -263,9 +263,10 @@ static int am_meson_drm_bind(struct device *dev)
goto err_unbind_all;
drm_mode_config_reset(drm);
- drm->mode_config.max_width = 8192;
- drm->mode_config.max_height = 8192;
+ drm->mode_config.max_width = 4096;
+ drm->mode_config.max_height = 4096;
drm->mode_config.funcs = &meson_mode_config_funcs;
+ drm->mode_config.allow_fb_modifiers = true;
/*
* irq will init in each crtc, just mark the enable flag here.
*/
@@ -279,9 +280,7 @@ static int am_meson_drm_bind(struct device *dev)
ret = am_meson_drm_fbdev_init(drm);
if (ret)
goto err_poll_fini;
- drm->mode_config.allow_fb_modifiers = true;
#endif
-
ret = drm_dev_register(drm, 0);
if (ret)
goto err_fbdev_fini;
diff --git a/drivers/amlogic/drm/am_meson_drv.h b/drivers/amlogic/drm/meson_drv.h
index 77279a5..40ca261 100644
--- a/drivers/amlogic/drm/am_meson_drv.h
+++ b/drivers/amlogic/drm/meson_drv.h
@@ -1,19 +1,18 @@
/*
- * Copyright (C) 2016 BayLibre, SAS
- * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * drivers/amlogic/drm/meson_drv.h
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __AM_MESON_DRV_H
@@ -27,6 +26,7 @@
#endif
#define MESON_MAX_CRTC 2
+#define MESON_MAX_OSD 4
/*
* Amlogic drm private crtc funcs.
@@ -55,6 +55,15 @@ struct meson_drm {
#ifdef CONFIG_DRM_MESON_USE_ION
struct ion_client *gem_client;
#endif
+
+ struct meson_vpu_pipeline *pipeline;
+ struct meson_vpu_funcs *funcs;
+
+ u32 num_crtcs;
+ struct am_meson_crtc *crtcs[MESON_MAX_CRTC];
+
+ u32 num_planes;
+ struct am_osd_plane *planes[MESON_MAX_OSD];
};
static inline int meson_vpu_is_compatible(struct meson_drm *priv,
diff --git a/drivers/amlogic/drm/am_meson_fb.c b/drivers/amlogic/drm/meson_fb.c
index 095f7ac..1c364da 100644
--- a/drivers/amlogic/drm/am_meson_fb.c
+++ b/drivers/amlogic/drm/meson_fb.c
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_fb.c
+ * drivers/amlogic/drm/meson_fb.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -14,9 +14,10 @@
* more details.
*
*/
+
#include <drm/drm_atomic_helper.h>
-#include "am_meson_fb.h"
+#include "meson_fb.h"
#define to_am_meson_fb(x) container_of(x, struct am_meson_fb, base)
diff --git a/drivers/amlogic/drm/am_meson_fb.h b/drivers/amlogic/drm/meson_fb.h
index faf0fce0..9c76d2e 100644
--- a/drivers/amlogic/drm/am_meson_fb.h
+++ b/drivers/amlogic/drm/meson_fb.h
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_fb.h
+ * drivers/amlogic/drm/meson_fb.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -22,7 +22,7 @@
#include <drm/drm_framebuffer.h>
#include <drm/drm_modeset_helper.h>
-#include "am_meson_gem.h"
+#include "meson_gem.h"
struct am_meson_fb {
struct drm_framebuffer base;
diff --git a/drivers/amlogic/drm/am_meson_fbdev.c b/drivers/amlogic/drm/meson_fbdev.c
index 610f3ca..b43788f 100644
--- a/drivers/amlogic/drm/am_meson_fbdev.c
+++ b/drivers/amlogic/drm/meson_fbdev.c
@@ -1,16 +1,18 @@
/*
- * drivers/amlogic/drm/am_meson_fbdev.c
+ * drivers/amlogic/drm/meson_fbdev.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <drm/drm.h>
@@ -18,10 +20,10 @@
#include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h>
-#include "am_meson_drv.h"
-#include "am_meson_gem.h"
-#include "am_meson_fb.h"
-#include "am_meson_fbdev.h"
+#include "meson_drv.h"
+#include "meson_gem.h"
+#include "meson_fb.h"
+#include "meson_fbdev.h"
#define PREFERRED_BPP 32
#define MESON_DRM_MAX_CONNECTOR 2
diff --git a/drivers/amlogic/drm/am_meson_lcd.h b/drivers/amlogic/drm/meson_fbdev.h
index 565f8eb..898c262 100644
--- a/drivers/amlogic/drm/am_meson_lcd.h
+++ b/drivers/amlogic/drm/meson_fbdev.h
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_lcd.h
+ * drivers/amlogic/drm/meson_fbdev.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -15,10 +15,12 @@
*
*/
-#ifndef __AM_DRM_LCD_H
-#define __AM_DRM_LCD_H
-
-#include "am_meson_drv.h"
+#ifndef __AM_MESON_FBDEV_H
+#define __AM_MESON_FBDEV_H
+#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
+int am_meson_drm_fbdev_init(struct drm_device *dev);
+void am_meson_drm_fbdev_fini(struct drm_device *dev);
#endif
+#endif /* __AM_MESON_FBDEV_H */
diff --git a/drivers/amlogic/drm/am_meson_gem.c b/drivers/amlogic/drm/meson_gem.c
index 9d731b8..051cfce 100644
--- a/drivers/amlogic/drm/am_meson_gem.c
+++ b/drivers/amlogic/drm/meson_gem.c
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_gem.c
+ * drivers/amlogic/drm/meson_gem.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -14,6 +14,7 @@
* more details.
*
*/
+
#include <drm/drmP.h>
#include <drm/drm_gem.h>
#include <drm/drm_vma_manager.h>
@@ -24,7 +25,7 @@
#include <linux/meson_ion.h>
#include <ion/ion.h>
-#include "am_meson_gem.h"
+#include "meson_gem.h"
#define to_am_meson_gem_obj(x) container_of(x, struct am_meson_gem_object, base)
@@ -44,12 +45,11 @@ static int am_meson_gem_alloc_ion_buff(
//check flags to set different ion heap type.
//if flags is set to 0, need to use ion dma buffer.
- if (((flags & (BO_USE_SCANOUT | BO_USE_CURSOR)) != 0)
+ if (((flags & (MESON_USE_SCANOUT | MESON_USE_CURSOR)) != 0)
|| (flags == 0)) {
handle = ion_alloc(client, meson_gem_obj->base.size,
0, (1 << ION_HEAP_TYPE_DMA), 0);
- }
- else {
+ } else {
handle = ion_alloc(client, meson_gem_obj->base.size,
0, (1 << ION_HEAP_TYPE_SYSTEM), 0);
bscatter = true;
@@ -100,8 +100,6 @@ struct am_meson_gem_object *am_meson_gem_object_create(
}
size = roundup(size, PAGE_SIZE);
- if (size == 0)
- return ERR_PTR(-EINVAL);
meson_gem_obj = kzalloc(sizeof(*meson_gem_obj), GFP_KERNEL);
if (!meson_gem_obj)
return ERR_PTR(-ENOMEM);
@@ -415,10 +413,8 @@ struct sg_table *am_meson_gem_prime_get_sg_table(
}
return dst_table;
}
- else {
- DRM_ERROR("Not support import buffer from other driver.\n");
- return NULL;
- }
+ DRM_ERROR("Not support import buffer from other driver.\n");
+ return NULL;
}
struct drm_gem_object *am_meson_gem_prime_import_sg_table(
diff --git a/drivers/amlogic/drm/am_meson_gem.h b/drivers/amlogic/drm/meson_gem.h
index f6dcc7e..212a6aa 100644
--- a/drivers/amlogic/drm/am_meson_gem.h
+++ b/drivers/amlogic/drm/meson_gem.h
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_gem.h
+ * drivers/amlogic/drm/meson_gem.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -18,10 +18,10 @@
#ifndef __AM_MESON_GEM_H
#define __AM_MESON_GEM_H
#include <drm/drm_gem.h>
-#include <linux/amlogic/meson_drm.h>
+#include <uapi/drm/meson_drm.h>
#include <ion/ion_priv.h>
-#include "am_meson_drv.h"
+#include "meson_drv.h"
struct am_meson_gem_object {
struct drm_gem_object base;
diff --git a/drivers/amlogic/drm/am_meson_hdcp.c b/drivers/amlogic/drm/meson_hdcp.c
index 3c45c26..ab098fb 100644
--- a/drivers/amlogic/drm/am_meson_hdcp.c
+++ b/drivers/amlogic/drm/meson_hdcp.c
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_hdcp.c
+ * drivers/amlogic/drm/meson_hdcp.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -31,8 +31,8 @@
#include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h>
#include <linux/arm-smccc.h>
-#include "am_meson_hdmi.h"
-#include "am_meson_hdcp.h"
+#include "meson_hdmi.h"
+#include "meson_hdcp.h"
static int hdcp_topo_st = -1;
static int hdmitx_hdcp_opr(unsigned int val)
diff --git a/drivers/amlogic/drm/am_meson_hdcp.h b/drivers/amlogic/drm/meson_hdcp.h
index f95d13f..9e4ede0 100644
--- a/drivers/amlogic/drm/am_meson_hdcp.h
+++ b/drivers/amlogic/drm/meson_hdcp.h
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_hdcp.h
+ * drivers/amlogic/drm/meson_hdcp.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
diff --git a/drivers/amlogic/drm/am_meson_hdmi.c b/drivers/amlogic/drm/meson_hdmi.c
index a2efd9c..896444a 100644
--- a/drivers/amlogic/drm/am_meson_hdmi.c
+++ b/drivers/amlogic/drm/meson_hdmi.c
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_hdmi.c
+ * drivers/amlogic/drm/meson_hdmi.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -14,6 +14,7 @@
* more details.
*
*/
+
#include <drm/drm_modeset_helper.h>
#include <drm/drmP.h>
#include <drm/drm_edid.h>
@@ -32,8 +33,8 @@
#include <linux/workqueue.h>
#include <linux/amlogic/media/vout/vout_notify.h>
#include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h>
-#include "am_meson_hdmi.h"
-#include "am_meson_hdcp.h"
+#include "meson_hdmi.h"
+#include "meson_hdcp.h"
#define DEVICE_NAME "amhdmitx"
struct am_hdmi_tx am_hdmi_info;
@@ -77,11 +78,11 @@ char *am_meson_hdmi_get_voutmode(struct drm_display_mode *mode)
int i;
for (i = 0; i < ARRAY_SIZE(am_vout_modes); i++) {
- if ((am_vout_modes[i].width == mode->hdisplay)
- && (am_vout_modes[i].height == mode->vdisplay)
- && (am_vout_modes[i].vrefresh == mode->vrefresh)
- && (am_vout_modes[i].flags ==
- (mode->flags&DRM_MODE_FLAG_INTERLACE)))
+ if (am_vout_modes[i].width == mode->hdisplay &&
+ am_vout_modes[i].height == mode->vdisplay &&
+ am_vout_modes[i].vrefresh == mode->vrefresh &&
+ am_vout_modes[i].flags ==
+ (mode->flags & DRM_MODE_FLAG_INTERLACE))
return am_vout_modes[i].name;
}
return NULL;
@@ -253,9 +254,9 @@ void am_hdmi_encoder_mode_set(struct drm_encoder *encoder,
DRM_INFO("the hdmi mode vic : %d\n", am_hdmi->hdmi_info.vic);
/* Store the display mode for plugin/DPMS poweron events */
memcpy(&am_hdmi->previous_mode, adjusted_mode,
- sizeof(am_hdmi->previous_mode));
- if ((vic == 96) || (vic == 97) || (vic == 101) || (vic == 102)
- || (vic == 106) || (vic == 107))
+ sizeof(am_hdmi->previous_mode));
+ if (vic == 96 || vic == 97 || vic == 101 || vic == 102 ||
+ vic == 106 || vic == 107)
setup_attr(attr2);
else
setup_attr(attr1);
@@ -268,9 +269,9 @@ void am_hdmi_encoder_enable(struct drm_encoder *encoder)
struct drm_connector_state *state = am_hdmi->connector.state;
if (vmode == VMODE_HDMI)
- DRM_INFO("am_hdmi_encoder_enable\n");
+ DRM_INFO("enable\n");
else
- DRM_INFO("am_hdmi_encoder_enable fail! vmode:%d\n", vmode);
+ DRM_INFO("enable fail! vmode:%d\n", vmode);
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &vmode);
set_vout_vmode(vmode);
@@ -281,9 +282,11 @@ void am_hdmi_encoder_enable(struct drm_encoder *encoder)
if (am_hdmi->hdcp_tx_type) {
am_hdmi->hdcp_stop_flag = 0;
am_hdmi->hdcp_work = kthread_run(am_hdcp_work,
- (void *)am_hdmi, "kthread_hdcp_task");
- } else
+ (void *)am_hdmi,
+ "kthread_hdcp_task");
+ } else {
DRM_INFO("hdmitx doesn't has hdcp key\n");
+ }
}
}
@@ -344,7 +347,7 @@ static int am_hdmi_i2c_write(struct am_hdmi_tx *am_hdmi,
i2c->slave_reg = buf[0];
length--;
buf++;
- i2c->is_regaddr = true;
+ i2c->is_regaddr = 1;
}
while (length--) {
@@ -374,7 +377,7 @@ static int am_hdmi_i2c_read(struct am_hdmi_tx *am_hdmi,
if (!i2c->is_regaddr) {
dev_dbg(am_hdmi->dev, "set read register address to 0\n");
i2c->slave_reg = 0x00;
- i2c->is_regaddr = true;
+ i2c->is_regaddr = 1;
}
while (length--) {
@@ -396,7 +399,7 @@ static int am_hdmi_i2c_read(struct am_hdmi_tx *am_hdmi,
*buf++ = hdmitx_rd_reg(HDMITX_DWC_I2CM_DATAI);
}
- i2c->is_segment = false;
+ i2c->is_segment = 0;
return 0;
}
@@ -432,16 +435,16 @@ static int am_hdmi_i2c_xfer(struct i2c_adapter *adap,
hdmitx_wr_reg(HDMITX_DWC_I2CM_SLAVE, addr);
/* Set slave device register address on transfer */
- i2c->is_regaddr = false;
+ i2c->is_regaddr = 0;
/* Set segment pointer for I2C extended read mode operation */
- i2c->is_segment = false;
+ i2c->is_segment = 0;
for (i = 0; i < num; i++) {
dev_dbg(am_hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n",
i + 1, num, msgs[i].len, msgs[i].flags);
if (msgs[i].addr == DDC_SEGMENT_ADDR && msgs[i].len == 1) {
- i2c->is_segment = true;
+ i2c->is_segment = 1;
hdmitx_wr_reg(HDMITX_DWC_I2CM_SEGADDR,
DDC_SEGMENT_ADDR);
hdmitx_wr_reg(HDMITX_DWC_I2CM_SEGPTR, *msgs[i].buf);
@@ -558,10 +561,10 @@ static int amhdmitx_get_dt_info(struct am_hdmi_tx *am_hdmi)
hdcp_node = of_find_node_by_path("/drm-amhdmitx");
if (hdcp_node) {
ret = of_property_read_string(hdcp_node, "hdcp",
- (const char **)&(hdcp_status));
- if (ret)
+ (const char **)&(hdcp_status));
+ if (ret) {
DRM_INFO("not find hdcp_feature\n");
- else {
+ } else {
if (memcmp(hdcp_status, "okay", 4) == 0)
am_hdmi->hdcp_feature = 1;
else
diff --git a/drivers/amlogic/drm/am_meson_hdmi.h b/drivers/amlogic/drm/meson_hdmi.h
index 37542dc..d4bea37 100644
--- a/drivers/amlogic/drm/am_meson_hdmi.h
+++ b/drivers/amlogic/drm/meson_hdmi.h
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_hdmi.h
+ * drivers/amlogic/drm/meson_hdmi.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -14,18 +14,19 @@
* more details.
*
*/
+
#ifndef __AM_MESON_HDMI_H
#define __AM_MESON_HDMI_H
-#include "am_meson_drv.h"
+#include "meson_drv.h"
#define DDC_SEGMENT_ADDR 0x30
#define VIC_MAX_NUM 512
#define DRM_HDMITX_VER "20180705"
struct am_hdmi_data {
unsigned int vic;
- bool sink_is_hdmi;
- bool sink_has_audio;
+ u8 sink_is_hdmi;
+ u8 sink_has_audio;
unsigned int colorimetry;
unsigned int cd; /* cd8, cd10 or cd12 */
unsigned int cs; /* rgb, y444, y422, y420 */
@@ -45,8 +46,8 @@ struct am_hdmi_i2c {
u8 segment_addr;
u8 slave_reg;
u8 stat;
- bool is_regaddr;
- bool is_segment;
+ u8 is_regaddr;
+ u8 is_segment;
};
struct am_hdmi_tx {
@@ -85,9 +86,9 @@ struct am_hdmi_tx {
#define BASE_REG_OFFSET 24
#define HDMITX_SEC_REG_ADDR(reg) \
- ((HDMITX_SEC_REG_IDX << BASE_REG_OFFSET) + (reg << 2))
+ ((HDMITX_SEC_REG_IDX << BASE_REG_OFFSET) + ((reg) << 2))
#define HDMITX_REG_ADDR(reg) \
- ((HDMITX_REG_IDX << BASE_REG_OFFSET) + (reg << 2))
+ ((HDMITX_REG_IDX << BASE_REG_OFFSET) + ((reg) << 2))
/* TOP-level wrapper registers addresses
* bit24: 1 means secure access
diff --git a/drivers/amlogic/drm/am_meson_lcd.c b/drivers/amlogic/drm/meson_lcd.c
index 462338f..89f6556 100644
--- a/drivers/amlogic/drm/am_meson_lcd.c
+++ b/drivers/amlogic/drm/meson_lcd.c
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_lcd.c
+ * drivers/amlogic/drm/meson_lcd.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -26,7 +26,7 @@
#include <linux/amlogic/media/vout/lcd/lcd_vout.h>
#include <linux/amlogic/media/vout/lcd/lcd_notify.h>
-#include "am_meson_lcd.h"
+#include "meson_lcd.h"
struct am_drm_lcd_s {
struct drm_panel panel;
@@ -262,9 +262,9 @@ static void am_lcd_encoder_enable(struct drm_encoder *encoder)
return;
if (vmode == VMODE_LCD)
- DRM_INFO("am_lcd_encoder_enable\n");
+ DRM_INFO("enable\n");
else
- DRM_INFO("am_lcd_encoder_enable fail! vmode:%d\n", vmode);
+ DRM_INFO("enable fail! vmode:%d\n", vmode);
pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &vmode);
@@ -341,14 +341,10 @@ static int am_lcd_disable(struct drm_panel *panel)
if (!lcd->lcd_drv)
return -ENODEV;
- pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
-
mutex_lock(&lcd->lcd_drv->power_mutex);
aml_lcd_notifier_call_chain(LCD_EVENT_DISABLE, NULL);
mutex_unlock(&lcd->lcd_drv->power_mutex);
- pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
-
return 0;
}
@@ -361,14 +357,10 @@ static int am_lcd_unprepare(struct drm_panel *panel)
if (!lcd->lcd_drv)
return -ENODEV;
- pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
-
mutex_lock(&lcd->lcd_drv->power_mutex);
aml_lcd_notifier_call_chain(LCD_EVENT_UNPREPARE, NULL);
mutex_unlock(&lcd->lcd_drv->power_mutex);
- pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
-
return 0;
}
@@ -381,14 +373,10 @@ static int am_lcd_prepare(struct drm_panel *panel)
if (!lcd->lcd_drv)
return -ENODEV;
- pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
-
mutex_lock(&lcd->lcd_drv->power_mutex);
aml_lcd_notifier_call_chain(LCD_EVENT_PREPARE, NULL);
mutex_unlock(&lcd->lcd_drv->power_mutex);
- pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
-
return 0;
}
@@ -424,12 +412,8 @@ static int am_lcd_get_modes(struct drm_panel *panel)
return 0;
mode = drm_mode_duplicate(drm, lcd->mode);
- if (!mode) {
- pr_err("error: am_drm_lcd: failed to add mode %ux%u@%u\n",
- mode->hdisplay, mode->vdisplay, mode->vrefresh);
- }
-
- pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+ if (!mode)
+ return 0;
mode->type |= DRM_MODE_TYPE_DRIVER;
mode->type |= DRM_MODE_TYPE_PREFERRED;
@@ -463,8 +447,6 @@ static int am_lcd_get_timings(struct drm_panel *panel,
pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
- num_timings = 1;
-
if (timings)
memcpy(&timings[0], lcd->timing, sizeof(struct display_timing));
@@ -685,8 +667,6 @@ static void am_meson_lcd_unbind(struct device *dev, struct device *master,
drm_panel_remove(&am_drm_lcd->panel);
pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
-
- return;
}
static const struct component_ops am_meson_lcd_ops = {
diff --git a/drivers/amlogic/drm/am_meson_lcd.h b/drivers/amlogic/drm/meson_lcd.h
index 565f8eb..32be56b 100644
--- a/drivers/amlogic/drm/am_meson_lcd.h
+++ b/drivers/amlogic/drm/meson_lcd.h
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_lcd.h
+ * drivers/amlogic/drm/meson_lcd.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -18,7 +18,7 @@
#ifndef __AM_DRM_LCD_H
#define __AM_DRM_LCD_H
-#include "am_meson_drv.h"
+#include "meson_drv.h"
#endif
diff --git a/drivers/amlogic/drm/meson_plane.c b/drivers/amlogic/drm/meson_plane.c
new file mode 100644
index 0000000..4e84a69
--- a/dev/null
+++ b/drivers/amlogic/drm/meson_plane.c
@@ -0,0 +1,498 @@
+/*
+ * drivers/amlogic/drm/meson_plane.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include "meson_plane.h"
+#include "meson_crtc.h"
+#include "meson_vpu.h"
+#include "meson_drv.h"
+#include "meson_vpu_pipeline.h"
+
+static const u32 supported_drm_formats[] = {
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_RGBX8888,
+ DRM_FORMAT_BGRX8888,
+ DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_ABGR8888,
+ DRM_FORMAT_RGBA8888,
+ DRM_FORMAT_BGRA8888,
+ DRM_FORMAT_RGB888,
+ DRM_FORMAT_RGB565,
+ DRM_FORMAT_ARGB1555,
+ DRM_FORMAT_ARGB4444,
+};
+
+static u64 afbc_wb_modifier[] = {
+ DRM_FORMAT_MOD_MESON_AFBC_WB,
+ DRM_FORMAT_MOD_LINEAR,
+ DRM_FORMAT_MOD_INVALID
+};
+
+static void meson_plane_position_calc(
+ struct meson_vpu_osd_layer_info *plane_info,
+ struct drm_plane_state *state,
+ struct drm_display_mode *mode)
+{
+ u32 dst_w, dst_h, src_w, src_h, scan_mode_out;
+
+ scan_mode_out = mode->flags & DRM_MODE_FLAG_INTERLACE;
+ plane_info->src_x = state->src_x;
+ plane_info->src_y = state->src_y;
+ plane_info->src_w = (state->src_w >> 16) & 0xffff;
+ plane_info->src_h = (state->src_h >> 16) & 0xffff;
+
+ plane_info->dst_x = state->crtc_x;
+ plane_info->dst_y = state->crtc_y;
+ plane_info->dst_w = state->crtc_w;
+ plane_info->dst_h = state->crtc_h;
+ if (scan_mode_out) {
+ plane_info->dst_y >>= 1;
+ plane_info->dst_h >>= 1;
+ }
+ /*negative position process*/
+ if (state->crtc_x < 0) {
+ dst_w = state->crtc_w + state->crtc_x;
+ if (dst_w > 0) {
+ src_w = plane_info->src_w * dst_w / state->crtc_w;
+ plane_info->src_x = plane_info->src_w - src_w;
+ plane_info->src_w = src_w;
+ plane_info->dst_w = dst_w;
+ plane_info->dst_x = 0;
+ } else {
+ plane_info->enable = 0;
+ }
+ }
+ if (state->crtc_y < 0) {
+ dst_h = state->crtc_h + state->crtc_y;
+ if (dst_h > 0) {
+ src_h = plane_info->src_h * dst_h / state->crtc_h;
+ plane_info->src_y = plane_info->src_h - src_h;
+ plane_info->src_h = src_h;
+ plane_info->dst_h = dst_h;
+ plane_info->dst_y = 0;
+ } else {
+ plane_info->enable = 0;
+ }
+ }
+ /*overdisplay process*/
+ if ((plane_info->dst_x + plane_info->dst_w) > mode->hdisplay) {
+ if (plane_info->dst_x >= mode->hdisplay)
+ plane_info->enable = 0;
+ else
+ plane_info->dst_w =
+ mode->hdisplay - plane_info->dst_x;
+ }
+ if ((plane_info->dst_y + plane_info->dst_h) > mode->vdisplay) {
+ if (plane_info->dst_y >= mode->vdisplay)
+ plane_info->enable = 0;
+ else
+ plane_info->dst_h = mode->vdisplay - plane_info->dst_y;
+ }
+}
+
+static int
+meson_plane_check_size_range(struct meson_vpu_osd_layer_info *plane_info)
+{
+ u32 dst_w, dst_h, src_w, src_h, ratio_x, ratio_y;
+ int ret;
+
+ src_w = plane_info->src_w;
+ src_h = plane_info->src_h;
+ dst_w = plane_info->dst_w;
+ dst_h = plane_info->dst_h;
+ ratio_x = 0;
+ ratio_y = 0;
+ ret = 0;
+
+ if (src_w > dst_w)
+ ratio_x = (src_w + dst_w - 1) / dst_w;
+ if (src_h > dst_h)
+ ratio_y = (src_h + dst_h - 1) / dst_h;
+ if (ratio_x > MESON_OSD_SCLAE_DOWN_LIMIT ||
+ ratio_y > MESON_OSD_SCLAE_DOWN_LIMIT)
+ ret = -EDOM;
+ if (src_w < dst_w)
+ ratio_x = (dst_w + src_w - 1) / src_w;
+ if (src_h < dst_h)
+ ratio_y = (dst_h + src_h - 1) / src_h;
+ if (ratio_x > MESON_OSD_SCLAE_UP_LIMIT ||
+ ratio_y > MESON_OSD_SCLAE_UP_LIMIT)
+ ret = -EDOM;
+ return ret;
+}
+
+static int meson_plane_fb_check(struct drm_plane *plane,
+ struct drm_plane_state *new_state,
+ struct meson_vpu_osd_layer_info *plane_info)
+{
+ struct drm_framebuffer *fb = new_state->fb;
+ #ifdef CONFIG_DRM_MESON_USE_ION
+ struct am_osd_plane *osd_plane = to_am_osd_plane(plane);
+ struct meson_drm *drv = osd_plane->drv;
+ struct am_meson_fb *meson_fb;
+ #else
+ struct drm_gem_cma_object *gem;
+ #endif
+ dma_addr_t phyaddr;
+
+ #ifdef CONFIG_DRM_MESON_USE_ION
+ meson_fb = container_of(fb, struct am_meson_fb, base);
+ if (!meson_fb) {
+ DRM_INFO("meson_fb is NULL!\n");
+ return -EINVAL;
+ }
+ phyaddr = am_meson_gem_object_get_phyaddr(drv, meson_fb->bufp);
+ if (meson_fb->bufp->bscatter)
+ DRM_ERROR("am_meson_plane meet a scatter framebuffer.\n");
+ #else
+ if (!fb) {
+ DRM_INFO("fb is NULL!\n");
+ return -EINVAL;
+ }
+ /* Update Canvas with buffer address */
+ gem = drm_fb_cma_get_gem_obj(fb, 0);
+ if (!gem) {
+ DRM_INFO("gem is NULL!\n");
+ return -EINVAL;
+ }
+ phyaddr = gem->paddr;
+ #endif
+ plane_info->phy_addr = phyaddr;
+ return 0;
+}
+
+static int meson_plane_get_fb_info(struct drm_plane *plane,
+ struct drm_plane_state *new_state,
+ struct meson_vpu_osd_layer_info *plane_info)
+{
+ struct am_osd_plane *osd_plane = to_am_osd_plane(plane);
+ struct drm_framebuffer *fb = new_state->fb;
+ struct meson_drm *drv = osd_plane->drv;
+ #ifdef CONFIG_DRM_MESON_USE_ION
+ struct am_meson_fb *meson_fb;
+ #else
+ struct drm_gem_cma_object *gem;
+ #endif
+ dma_addr_t phyaddr;
+
+ if (!drv) {
+ DRM_INFO("%s new_state/meson_drm is NULL!\n", __func__);
+ return -EINVAL;
+ }
+ if (osd_plane->plane_index >= MESON_MAX_OSDS) {
+ DRM_INFO("%s invalid plane_index!\n", __func__);
+ return -EINVAL;
+ }
+
+ #ifdef CONFIG_DRM_MESON_USE_ION
+ meson_fb = container_of(fb, struct am_meson_fb, base);
+ if (!meson_fb) {
+ DRM_INFO("meson_fb is NULL!\n");
+ return 0;
+ }
+ phyaddr = am_meson_gem_object_get_phyaddr(drv, meson_fb->bufp);
+ if (meson_fb->bufp->bscatter)
+ DRM_ERROR("ERROR:am_meson_plane meet a scatter framebuffer.\n");
+ #else
+ if (!fb) {
+ DRM_INFO("fb is NULL!\n");
+ return -EINVAL;
+ }
+ /* Update Canvas with buffer address */
+ gem = drm_fb_cma_get_gem_obj(fb, 0);
+ phyaddr = gem->paddr;
+ #endif
+
+ plane_info->pixel_format = fb->pixel_format;
+ plane_info->phy_addr = phyaddr;
+ plane_info->byte_stride = fb->pitches[0];
+
+ /*setup afbc info*/
+ switch (fb->modifier) {
+ case DRM_FORMAT_MOD_MESON_AFBC:
+ plane_info->afbc_en = 1;
+ plane_info->afbc_inter_format = AFBC_EN;
+ break;
+ case DRM_FORMAT_MOD_MESON_AFBC_WB:
+ plane_info->afbc_en = 1;
+ plane_info->afbc_inter_format = AFBC_EN |
+ YUV_TRANSFORM | BLOCK_SPLIT |
+ SUPER_BLOCK_ASPECT;
+ break;
+ case DRM_FORMAT_MOD_INVALID:
+ case DRM_FORMAT_MOD_LINEAR:
+ default:
+ plane_info->afbc_en = 0;
+ plane_info->afbc_inter_format = 0;
+ break;
+ };
+
+ DRM_DEBUG("flags:%d pixel_format:%d,modifer=%llu\n",
+ fb->flags, fb->pixel_format,
+ fb->modifier);
+ DRM_DEBUG("plane afbc_en=%u, afbc_inter_format=%x\n",
+ plane_info->afbc_en, plane_info->afbc_inter_format);
+
+ DRM_DEBUG("phy_addr=0x%x,byte_stride=%d,pixel_format=%d\n",
+ plane_info->phy_addr, plane_info->byte_stride,
+ plane_info->pixel_format);
+ DRM_DEBUG("plane_index %d.\n", osd_plane->plane_index);
+ return 0;
+}
+
+static int meson_plane_atomic_get_property(struct drm_plane *plane,
+ const struct drm_plane_state *state,
+ struct drm_property *property,
+ uint64_t *val)
+{
+ return 0;
+}
+
+static int meson_plane_atomic_set_property(struct drm_plane *plane,
+ struct drm_plane_state *state,
+ struct drm_property *property,
+ uint64_t val)
+{
+ return 0;
+}
+
+static struct drm_plane_state *
+meson_plane_duplicate_state(struct drm_plane *plane)
+{
+ struct am_meson_plane_state *meson_plane_state, *old_plane_state;
+
+ if (WARN_ON(!plane->state))
+ return NULL;
+
+ old_plane_state = to_am_meson_plane_state(plane->state);
+ meson_plane_state = kmemdup(old_plane_state,
+ sizeof(*meson_plane_state), GFP_KERNEL);
+ if (!meson_plane_state)
+ return NULL;
+
+ __drm_atomic_helper_plane_duplicate_state(plane,
+ &meson_plane_state->base);
+
+ return &meson_plane_state->base;
+}
+
+static void meson_plane_destroy_state(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct am_meson_plane_state *amps;
+
+ amps = to_am_meson_plane_state(state);
+ __drm_atomic_helper_plane_destroy_state(state);
+ kfree(amps);
+}
+
+bool am_meson_vpu_check_format_mod(struct drm_plane *plane,
+ u32 format, u64 modifier)
+{
+ bool ret = false;
+
+ switch (modifier) {
+ case DRM_FORMAT_MOD_LINEAR:
+ ret = true;
+ break;
+ case DRM_FORMAT_MOD_MESON_AFBC:
+ if (osd_meson_dev.afbc_type == MESON_AFBC &&
+ plane->type == DRM_PLANE_TYPE_PRIMARY)
+ ret = true;
+ break;
+ case DRM_FORMAT_MOD_MESON_AFBC_WB:
+ if (osd_meson_dev.afbc_type == MALI_AFBC &&
+ plane->type == DRM_PLANE_TYPE_PRIMARY) {
+ if (format == DRM_FORMAT_BGR565)
+ ret = false;
+ else
+ ret = true;
+ }
+ break;
+ };
+
+ DRM_DEBUG("modifier %llu return %d",
+ modifier, ret);
+ return ret;
+}
+
+static const struct drm_plane_funcs am_osd_plane_funs = {
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
+ .destroy = drm_plane_cleanup,
+ .reset = drm_atomic_helper_plane_reset,
+ .atomic_duplicate_state = meson_plane_duplicate_state,
+ .atomic_destroy_state = meson_plane_destroy_state,
+ .atomic_set_property = meson_plane_atomic_set_property,
+ .atomic_get_property = meson_plane_atomic_get_property,
+ .format_mod_supported = am_meson_vpu_check_format_mod,
+};
+
+static int meson_plane_prepare_fb(struct drm_plane *plane,
+ struct drm_plane_state *new_state)
+{
+ return 0;
+}
+
+static void meson_plane_cleanup_fb(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ struct am_osd_plane *osd_plane = to_am_osd_plane(plane);
+
+ DRM_DEBUG("%s osd %d.\n", __func__, osd_plane->plane_index);
+}
+
+static void meson_plane_atomic_update(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ DRM_DEBUG("plane atomic_update.\n");
+}
+
+static int meson_plane_atomic_check(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct meson_vpu_osd_layer_info *plane_info;
+ struct meson_vpu_pipeline_state *mvps;
+ struct am_osd_plane *osd_plane = to_am_osd_plane(plane);
+ struct meson_drm *drv = osd_plane->drv;
+ int ret;
+
+ if (!state || !drv) {
+ DRM_INFO("%s state/meson_drm is NULL!\n", __func__);
+ return -EINVAL;
+ }
+ mvps = meson_vpu_pipeline_get_state(drv->pipeline, state->state);
+ if (!mvps || osd_plane->plane_index >= MESON_MAX_OSDS) {
+ DRM_INFO("%s mvps/osd_plane is NULL!\n", __func__);
+ return -EINVAL;
+ }
+ plane_info = &mvps->plane_info[osd_plane->plane_index];
+ plane_info->plane_index = osd_plane->plane_index;
+ plane_info->zorder = state->zpos;
+
+ mvps->plane_index[osd_plane->plane_index] = osd_plane->plane_index;
+ meson_plane_position_calc(plane_info, state, &mvps->pipeline->mode);
+ ret = meson_plane_check_size_range(plane_info);
+ if (ret < 0) {
+ plane_info->enable = 0;
+ DRM_INFO("plane%d size check unsupport!!!\n",
+ plane_info->plane_index);
+ return ret;
+ }
+ ret = meson_plane_fb_check(plane, state, plane_info);
+ if (ret < 0) {
+ plane_info->enable = 0;
+ DRM_DEBUG("plane%d fb is NULL,disable the plane!\n",
+ plane_info->plane_index);
+ return 0;
+ }
+ ret = meson_plane_get_fb_info(plane, state, plane_info);
+ if (ret < 0 || plane_info->src_w > MESON_OSD_INPUT_W_LIMIT ||
+ plane_info->src_w == 0) {
+ plane_info->enable = 0;
+ return ret;
+ }
+
+ plane_info->enable = 1;
+ DRM_DEBUG("index=%d, zorder=%d\n",
+ plane_info->plane_index, plane_info->zorder);
+ DRM_DEBUG("src_x/y/w/h=%d/%d/%d/%d\n",
+ plane_info->src_x, plane_info->src_y,
+ plane_info->src_w, plane_info->src_h);
+ DRM_DEBUG("dst_x/y/w/h=%d/%d/%d/%d\n",
+ plane_info->dst_x, plane_info->dst_y,
+ plane_info->dst_w, plane_info->dst_h);
+ return 0;
+}
+
+static void meson_plane_atomic_disable(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ struct am_osd_plane *osd_plane = to_am_osd_plane(plane);
+
+ DRM_DEBUG("%s osd %d.\n", __func__, osd_plane->plane_index);
+}
+
+static const struct drm_plane_helper_funcs am_osd_helper_funcs = {
+ .prepare_fb = meson_plane_prepare_fb,
+ .cleanup_fb = meson_plane_cleanup_fb,
+ .atomic_update = meson_plane_atomic_update,
+ .atomic_check = meson_plane_atomic_check,
+ .atomic_disable = meson_plane_atomic_disable,
+};
+
+static struct am_osd_plane *am_plane_create(struct meson_drm *priv, int i)
+{
+ struct am_osd_plane *osd_plane;
+ struct drm_plane *plane;
+ u32 type = 0;
+ char plane_name[8];
+ const u64 *format_modifiers = afbc_wb_modifier;
+
+ osd_plane = devm_kzalloc(priv->drm->dev, sizeof(*osd_plane),
+ GFP_KERNEL);
+ if (!osd_plane)
+ return 0;
+
+ if (i == 0)
+ type = DRM_PLANE_TYPE_PRIMARY;
+ else
+ type = DRM_PLANE_TYPE_OVERLAY;
+
+ osd_plane->drv = priv;
+ osd_plane->plane_index = i;
+
+ plane = &osd_plane->base;
+ sprintf(plane_name, "osd%d", i);
+
+ drm_universal_plane_init(priv->drm, plane, 0xFF,
+ &am_osd_plane_funs,
+ supported_drm_formats,
+ ARRAY_SIZE(supported_drm_formats),
+ format_modifiers,
+ type, plane_name);
+
+ drm_plane_helper_add(plane, &am_osd_helper_funcs);
+ osd_drm_debugfs_add(&osd_plane->plane_debugfs_dir,
+ plane_name, osd_plane->plane_index);
+ return osd_plane;
+}
+
+int am_meson_plane_create(struct meson_drm *priv)
+{
+ struct am_osd_plane *plane;
+ struct meson_vpu_pipeline *pipeline = priv->pipeline;
+ int i, osd_index;
+
+
+ for (i = 0; i < pipeline->num_osds; i++) {
+ osd_index = pipeline->osds[i]->base.index;
+ plane = am_plane_create(priv, osd_index);
+
+ if (!plane)
+ return -ENOMEM;
+
+ if (i == 0)
+ priv->primary_plane = &plane->base;
+
+ priv->planes[priv->num_planes++] = plane;
+ }
+
+ DRM_DEBUG("%s. enter\n", __func__);
+
+ return 0;
+}
diff --git a/drivers/amlogic/drm/meson_plane.h b/drivers/amlogic/drm/meson_plane.h
new file mode 100644
index 0000000..a1e6f4b
--- a/dev/null
+++ b/drivers/amlogic/drm/meson_plane.h
@@ -0,0 +1,50 @@
+/*
+ * drivers/amlogic/drm/meson_plane.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __MESON_PLANE_H
+#define __MESON_PLANE_H
+
+#include <linux/kernel.h>
+#include <drm/drmP.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <linux/amlogic/media/vout/vout_notify.h>
+
+#include "osd.h"
+#include "osd_drm.h"
+#include "meson_fb.h"
+
+struct am_meson_plane_state {
+ struct drm_plane_state base;
+};
+
+struct am_osd_plane {
+ struct drm_plane base; //must be first element.
+ struct meson_drm *drv; //point to struct parent.
+ struct dentry *plane_debugfs_dir;
+ int plane_index;
+};
+
+#define to_am_osd_plane(x) container_of(x, \
+ struct am_osd_plane, base)
+#define to_am_meson_plane_state(x) container_of(x, \
+ struct am_meson_plane_state, base)
+
+int am_meson_plane_create(struct meson_drm *priv);
+
+#endif
diff --git a/drivers/amlogic/drm/meson_vpu.c b/drivers/amlogic/drm/meson_vpu.c
new file mode 100644
index 0000000..31ea494
--- a/dev/null
+++ b/drivers/amlogic/drm/meson_vpu.c
@@ -0,0 +1,573 @@
+/*
+ * drivers/amlogic/drm/meson_vpu.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/component.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/dma-contiguous.h>
+#include <linux/cma.h>
+#ifdef CONFIG_DRM_MESON_USE_ION
+#include <ion/ion_priv.h>
+#endif
+
+/* Amlogic Headers */
+#include <linux/amlogic/media/vout/vout_notify.h>
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
+#include <linux/amlogic/media/amvecm/amvecm.h>
+#endif
+#include "osd.h"
+#include "osd_drm.h"
+#ifdef CONFIG_DRM_MESON_USE_ION
+#include "meson_fb.h"
+#endif
+#include "meson_vpu.h"
+#include "meson_plane.h"
+#include "meson_crtc.h"
+#include "meson_vpu_pipeline.h"
+
+struct vpu_device_data_s {
+ enum cpuid_type_e cpu_id;
+ enum osd_ver_e osd_ver;
+ enum osd_afbc_e afbc_type;
+ u8 osd_count;
+ u8 has_deband;
+ u8 has_lut;
+ u8 has_rdma;
+ u8 osd_fifo_len;
+ u32 vpp_fifo_len;
+ u32 dummy_data;
+ u32 has_viu2;
+ u32 viu1_osd_count;
+ struct clk *vpu_clkc;
+};
+
+static struct am_vout_mode am_vout_modes[] = {
+ { "1080p60hz", VMODE_HDMI, 1920, 1080, 60, 0},
+ { "1080p30hz", VMODE_HDMI, 1920, 1080, 30, 0},
+ { "1080p50hz", VMODE_HDMI, 1920, 1080, 50, 0},
+ { "1080p25hz", VMODE_HDMI, 1920, 1080, 25, 0},
+ { "1080p24hz", VMODE_HDMI, 1920, 1080, 24, 0},
+ { "2160p30hz", VMODE_HDMI, 3840, 2160, 30, 0},
+ { "2160p60hz", VMODE_HDMI, 3840, 2160, 60, 0},
+ { "2160p50hz", VMODE_HDMI, 3840, 2160, 50, 0},
+ { "2160p25hz", VMODE_HDMI, 3840, 2160, 25, 0},
+ { "2160p24hz", VMODE_HDMI, 3840, 2160, 24, 0},
+ { "1080i60hz", VMODE_HDMI, 1920, 1080, 60, DRM_MODE_FLAG_INTERLACE},
+ { "1080i50hz", VMODE_HDMI, 1920, 1080, 50, DRM_MODE_FLAG_INTERLACE},
+ { "720p60hz", VMODE_HDMI, 1280, 720, 60, 0},
+ { "720p50hz", VMODE_HDMI, 1280, 720, 50, 0},
+ { "480p60hz", VMODE_HDMI, 720, 480, 60, 0},
+ { "480i60hz", VMODE_HDMI, 720, 480, 60, DRM_MODE_FLAG_INTERLACE},
+ { "576p50hz", VMODE_HDMI, 720, 576, 50, 0},
+ { "576i50hz", VMODE_HDMI, 720, 576, 50, DRM_MODE_FLAG_INTERLACE},
+ { "480p60hz", VMODE_HDMI, 720, 480, 60, 0},
+};
+
+
+static struct osd_device_data_s osd_gxbb = {
+ .cpu_id = __MESON_CPU_MAJOR_ID_GXBB,
+ .osd_ver = OSD_NORMAL,
+ .afbc_type = NO_AFBC,
+ .osd_count = 2,
+ .has_deband = 0,
+ .has_lut = 0,
+ .has_rdma = 1,
+ .has_dolby_vision = 0,
+ .osd_fifo_len = 32,
+ .vpp_fifo_len = 0x77f,
+ .dummy_data = 0x00808000,
+ .has_viu2 = 0,
+};
+
+static struct osd_device_data_s osd_gxl = {
+ .cpu_id = __MESON_CPU_MAJOR_ID_GXL,
+ .osd_ver = OSD_NORMAL,
+ .afbc_type = NO_AFBC,
+ .osd_count = 2,
+ .has_deband = 0,
+ .has_lut = 0,
+ .has_rdma = 1,
+ .has_dolby_vision = 0,
+ .osd_fifo_len = 32,
+ .vpp_fifo_len = 0x77f,
+ .dummy_data = 0x00808000,
+ .has_viu2 = 0,
+};
+
+static struct osd_device_data_s osd_gxm = {
+ .cpu_id = __MESON_CPU_MAJOR_ID_GXM,
+ .osd_ver = OSD_NORMAL,
+ .afbc_type = MESON_AFBC,
+ .osd_count = 2,
+ .has_deband = 0,
+ .has_lut = 0,
+ .has_rdma = 1,
+ .has_dolby_vision = 0,
+ .osd_fifo_len = 32,
+ .vpp_fifo_len = 0xfff,
+ .dummy_data = 0x00202000,/* dummy data is different */
+ .has_viu2 = 0,
+};
+
+static struct osd_device_data_s osd_txl = {
+ .cpu_id = __MESON_CPU_MAJOR_ID_TXL,
+ .osd_ver = OSD_NORMAL,
+ .afbc_type = NO_AFBC,
+ .osd_count = 2,
+ .has_deband = 0,
+ .has_lut = 0,
+ .has_rdma = 1,
+ .has_dolby_vision = 0,
+ .osd_fifo_len = 64,
+ .vpp_fifo_len = 0x77f,
+ .dummy_data = 0x00808000,
+ .has_viu2 = 0,
+};
+
+static struct osd_device_data_s osd_txlx = {
+ .cpu_id = __MESON_CPU_MAJOR_ID_TXLX,
+ .osd_ver = OSD_NORMAL,
+ .afbc_type = NO_AFBC,
+ .osd_count = 2,
+ .has_deband = 1,
+ .has_lut = 1,
+ .has_rdma = 1,
+ .has_dolby_vision = 1,
+ .osd_fifo_len = 64, /* fifo len 64*8 = 512 */
+ .vpp_fifo_len = 0x77f,
+ .dummy_data = 0x00808000,
+ .has_viu2 = 0,
+};
+
+static struct osd_device_data_s osd_axg = {
+ .cpu_id = __MESON_CPU_MAJOR_ID_AXG,
+ .osd_ver = OSD_SIMPLE,
+ .afbc_type = NO_AFBC,
+ .osd_count = 1,
+ .has_deband = 1,
+ .has_lut = 1,
+ .has_rdma = 0,
+ .has_dolby_vision = 0,
+ /* use iomap its self, no rdma, no canvas, no freescale */
+ .osd_fifo_len = 64, /* fifo len 64*8 = 512 */
+ .vpp_fifo_len = 0x400,
+ .dummy_data = 0x00808000,
+ .has_viu2 = 0,
+};
+
+static struct osd_device_data_s osd_g12a = {
+ .cpu_id = __MESON_CPU_MAJOR_ID_G12A,
+ .osd_ver = OSD_HIGH_ONE,
+ .afbc_type = MALI_AFBC,
+ .osd_count = 4,
+ .has_deband = 1,
+ .has_lut = 1,
+ .has_rdma = 1,
+ .has_dolby_vision = 0,
+ .osd_fifo_len = 64, /* fifo len 64*8 = 512 */
+ .vpp_fifo_len = 0xfff,/* 2048 */
+ .dummy_data = 0x00808000,
+ .has_viu2 = 1,
+};
+
+static struct osd_device_data_s osd_g12b = {
+ .cpu_id = __MESON_CPU_MAJOR_ID_G12B,
+ .osd_ver = OSD_HIGH_ONE,
+ .afbc_type = MALI_AFBC,
+ .osd_count = 4,
+ .has_deband = 1,
+ .has_lut = 1,
+ .has_rdma = 1,
+ .has_dolby_vision = 0,
+ .osd_fifo_len = 64, /* fifo len 64*8 = 512 */
+ .vpp_fifo_len = 0xfff,/* 2048 */
+ .dummy_data = 0x00808000,
+ .has_viu2 = 1,
+};
+
+struct osd_device_data_s osd_meson_dev;
+static u32 logo_memsize;
+static struct page *logo_page;
+static struct delayed_work osd_dwork;
+static struct platform_device *gp_dev;
+static unsigned long gem_mem_start, gem_mem_size;
+
+int am_meson_crtc_dts_info_set(const void *dt_match_data)
+{
+ struct osd_device_data_s *osd_meson;
+
+ osd_meson = (struct osd_device_data_s *)dt_match_data;
+ if (osd_meson) {
+ memcpy(&osd_meson_dev, osd_meson,
+ sizeof(struct osd_device_data_s));
+ osd_meson_dev.viu1_osd_count = osd_meson_dev.osd_count;
+ if (osd_meson_dev.has_viu2) {
+ /* set viu1 osd count */
+ osd_meson_dev.viu1_osd_count--;
+ osd_meson_dev.viu2_index = osd_meson_dev.viu1_osd_count;
+ }
+ } else {
+ DRM_ERROR("%s data NOT match\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int am_meson_crtc_loader_protect(struct drm_crtc *crtc, bool on)
+{
+ struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc);
+
+ DRM_INFO("%s %d\n", __func__, on);
+
+ if (on) {
+ enable_irq(amcrtc->vblank_irq);
+ drm_crtc_vblank_on(crtc);
+ } else {
+ disable_irq(amcrtc->vblank_irq);
+ drm_crtc_vblank_off(crtc);
+ }
+
+ return 0;
+}
+
+static int am_meson_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+ unsigned long flags;
+ struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc);
+
+ spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags);
+ amcrtc->vblank_enable = true;
+ spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags);
+
+ return 0;
+}
+
+static void am_meson_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+ unsigned long flags;
+ struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc);
+
+ spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags);
+ amcrtc->vblank_enable = false;
+ spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags);
+}
+
+const struct meson_crtc_funcs meson_private_crtc_funcs = {
+ .loader_protect = am_meson_crtc_loader_protect,
+ .enable_vblank = am_meson_crtc_enable_vblank,
+ .disable_vblank = am_meson_crtc_disable_vblank,
+};
+
+char *am_meson_crtc_get_voutmode(struct drm_display_mode *mode)
+{
+ int i;
+
+ if (!strcmp(mode->name, "panel"))
+ return "panel";
+
+ for (i = 0; i < ARRAY_SIZE(am_vout_modes); i++) {
+ if (am_vout_modes[i].width == mode->hdisplay &&
+ am_vout_modes[i].height == mode->vdisplay &&
+ am_vout_modes[i].vrefresh == mode->vrefresh &&
+ am_vout_modes[i].flags ==
+ (mode->flags & DRM_MODE_FLAG_INTERLACE))
+ return am_vout_modes[i].name;
+ }
+ return NULL;
+}
+
+void am_meson_crtc_handle_vsync(struct am_meson_crtc *amcrtc)
+{
+ unsigned long flags;
+ struct drm_crtc *crtc;
+
+ crtc = &amcrtc->base;
+ drm_crtc_handle_vblank(crtc);
+
+ spin_lock_irqsave(&crtc->dev->event_lock, flags);
+ if (amcrtc->event) {
+ drm_crtc_send_vblank_event(crtc, amcrtc->event);
+ drm_crtc_vblank_put(crtc);
+ amcrtc->event = NULL;
+ }
+ spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+}
+
+void am_meson_crtc_irq(struct meson_drm *priv)
+{
+ unsigned long flags;
+ struct am_meson_crtc *amcrtc = to_am_meson_crtc(priv->crtc);
+
+ spin_lock_irqsave(&amcrtc->vblank_irq_lock, flags);
+ if (amcrtc->vblank_enable) {
+ osd_drm_vsync_isr_handler();
+ am_meson_crtc_handle_vsync(amcrtc);
+ }
+ spin_unlock_irqrestore(&amcrtc->vblank_irq_lock, flags);
+}
+
+static irqreturn_t am_meson_vpu_irq(int irq, void *arg)
+{
+ struct drm_device *dev = arg;
+ struct meson_drm *priv = dev->dev_private;
+
+ am_meson_crtc_irq(priv);
+
+ return IRQ_HANDLED;
+}
+
+static void mem_free_work(struct work_struct *work)
+{
+ if (logo_memsize > 0) {
+#ifdef CONFIG_CMA
+ pr_info("%s, free memory: addr:0x%x\n",
+ __func__, logo_memsize);
+
+ dma_release_from_contiguous(&gp_dev->dev,
+ logo_page,
+ logo_memsize >> PAGE_SHIFT);
+#endif
+ }
+}
+
+static int am_meson_vpu_bind(struct device *dev,
+ struct device *master, void *data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *drm_dev = data;
+ struct meson_drm *private = drm_dev->dev_private;
+ struct meson_vpu_pipeline *pipeline = private->pipeline;
+ struct am_meson_crtc *amcrtc;
+#ifdef CONFIG_CMA
+ struct cma *cma;
+#endif
+ int ret, irq;
+
+ /* Allocate crtc struct */
+ DRM_DEBUG("%s\n", __func__);
+ pr_info("[%s] in\n", __func__);
+ amcrtc = devm_kzalloc(dev, sizeof(*amcrtc),
+ GFP_KERNEL);
+ if (!amcrtc)
+ return -ENOMEM;
+
+ amcrtc->priv = private;
+ amcrtc->dev = dev;
+ amcrtc->drm_dev = drm_dev;
+
+ dev_set_drvdata(dev, amcrtc);
+
+ /* init reserved memory */
+ ret = of_reserved_mem_device_init(&pdev->dev);
+ if (ret != 0) {
+ dev_err(dev, "failed to init reserved memory\n");
+#ifdef CONFIG_CMA
+ gp_dev = pdev;
+ cma = dev_get_cma_area(&pdev->dev);
+ if (cma) {
+ logo_memsize = cma_get_size(cma);
+ pr_info("reserved memory base:0x%x, size:0x%x\n",
+ (u32)cma_get_base(cma), logo_memsize);
+ if (logo_memsize > 0) {
+ logo_page =
+ dma_alloc_from_contiguous(&pdev->dev,
+ logo_memsize >>
+ PAGE_SHIFT,
+ 0);
+ if (!logo_page) {
+ pr_err("allocate buffer failed:%d\n",
+ logo_memsize);
+ }
+ }
+ } else {
+ pr_info("------ NO CMA\n");
+ }
+#endif
+ } else {
+ dma_declare_coherent_memory(drm_dev->dev, gem_mem_start,
+ gem_mem_start, gem_mem_size,
+ DMA_MEMORY_EXCLUSIVE);
+ pr_info("meson drm mem_start = 0x%x, size = 0x%x\n",
+ (u32)gem_mem_start, (u32)gem_mem_size);
+ }
+
+ ret = am_meson_plane_create(private);
+ if (ret)
+ return ret;
+
+ ret = am_meson_crtc_create(amcrtc);
+ if (ret)
+ return ret;
+
+ am_meson_register_crtc_funcs(private->crtc, &meson_private_crtc_funcs);
+
+ ret = of_property_read_u8(dev->of_node,
+ "osd_ver", &pipeline->osd_version);
+ vpu_pipeline_init(pipeline);
+
+ /*vsync irq.*/
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "cannot find irq for vpu\n");
+ return irq;
+ }
+ amcrtc->vblank_irq = (unsigned int)irq;
+
+ spin_lock_init(&amcrtc->vblank_irq_lock);
+ amcrtc->vblank_enable = false;
+
+ ret = devm_request_irq(dev, amcrtc->vblank_irq, am_meson_vpu_irq,
+ IRQF_SHARED, dev_name(dev), drm_dev);
+ if (ret)
+ return ret;
+
+ disable_irq(amcrtc->vblank_irq);
+
+ INIT_DELAYED_WORK(&osd_dwork, mem_free_work);
+ schedule_delayed_work(&osd_dwork, msecs_to_jiffies(60 * 1000));
+ pr_info("[%s] out\n", __func__);
+ return 0;
+}
+
+static void am_meson_vpu_unbind(struct device *dev,
+ struct device *master, void *data)
+{
+ struct drm_device *drm_dev = data;
+ struct meson_drm *private = drm_dev->dev_private;
+
+ am_meson_unregister_crtc_funcs(private->crtc);
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
+ amvecm_drm_gamma_disable(0);
+ am_meson_ctm_disable();
+#endif
+ osd_drm_debugfs_exit();
+}
+
+static const struct component_ops am_meson_vpu_component_ops = {
+ .bind = am_meson_vpu_bind,
+ .unbind = am_meson_vpu_unbind,
+};
+
+static const struct of_device_id am_meson_vpu_driver_dt_match[] = {
+ { .compatible = "amlogic,meson-gxbb-vpu",
+ .data = &osd_gxbb, },
+ { .compatible = "amlogic,meson-gxl-vpu",
+ .data = &osd_gxl, },
+ { .compatible = "amlogic,meson-gxm-vpu",
+ .data = &osd_gxm, },
+ { .compatible = "amlogic,meson-txl-vpu",
+ .data = &osd_txl, },
+ { .compatible = "amlogic,meson-txlx-vpu",
+ .data = &osd_txlx, },
+ { .compatible = "amlogic,meson-axg-vpu",
+ .data = &osd_axg, },
+ { .compatible = "amlogic,meson-g12a-vpu",
+ .data = &osd_g12a, },
+ { .compatible = "amlogic,meson-g12b-vpu",
+ .data = &osd_g12b, },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, am_meson_vpu_driver_dt_match);
+
+static int am_meson_vpu_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const void *vpu_data;
+ int ret;
+
+ pr_info("[%s] in\n", __func__);
+ if (!dev->of_node) {
+ dev_err(dev, "can't find vpu devices\n");
+ return -ENODEV;
+ }
+
+ vpu_data = of_device_get_match_data(dev);
+ if (vpu_data) {
+ ret = am_meson_crtc_dts_info_set(vpu_data);
+ if (ret < 0)
+ return -ENODEV;
+ } else {
+ dev_err(dev, "%s NOT match\n", __func__);
+ return -ENODEV;
+ }
+ pr_info("[%s] out\n", __func__);
+ return component_add(dev, &am_meson_vpu_component_ops);
+}
+
+static int am_meson_vpu_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &am_meson_vpu_component_ops);
+
+ return 0;
+}
+
+static struct platform_driver am_meson_vpu_platform_driver = {
+ .probe = am_meson_vpu_probe,
+ .remove = am_meson_vpu_remove,
+ .driver = {
+ .name = "meson-vpu",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(am_meson_vpu_driver_dt_match),
+ },
+};
+
+static int gem_mem_device_init(struct reserved_mem *rmem, struct device *dev)
+{
+ s32 ret = 0;
+
+ if (!rmem) {
+ pr_info("Can't get reverse mem!\n");
+ ret = -EFAULT;
+ return ret;
+ }
+ gem_mem_start = rmem->base;
+ gem_mem_size = rmem->size;
+ pr_info("init gem memsource addr:0x%x size:0x%x\n",
+ (u32)gem_mem_start, (u32)gem_mem_size);
+
+ return 0;
+}
+
+static const struct reserved_mem_ops rmem_gem_ops = {
+ .device_init = gem_mem_device_init,
+};
+
+static int __init gem_mem_setup(struct reserved_mem *rmem)
+{
+ rmem->ops = &rmem_gem_ops;
+ pr_info("gem mem setup\n");
+ return 0;
+}
+
+RESERVEDMEM_OF_DECLARE(gem, "amlogic, gem_memory", gem_mem_setup);
+
+module_platform_driver(am_meson_vpu_platform_driver);
+
+MODULE_AUTHOR("MultiMedia Amlogic <multimedia-sh@amlogic.com>");
+MODULE_DESCRIPTION("Amlogic Meson Drm VPU driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/amlogic/drm/am_meson_vpu.h b/drivers/amlogic/drm/meson_vpu.h
index 03adbbe..e288a33 100644
--- a/drivers/amlogic/drm/am_meson_vpu.h
+++ b/drivers/amlogic/drm/meson_vpu.h
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_vpu.h
+ * drivers/amlogic/drm/meson_vpu.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -14,11 +14,24 @@
* more details.
*
*/
+
#ifndef __AM_MESON_VPU_H
#define __AM_MESON_VPU_H
+#include <linux/amlogic/media/vout/vout_notify.h>
+
struct am_meson_vpu_data {
- uint32_t version;
+ u32 version;
};
+struct am_vout_mode {
+ char name[DRM_DISPLAY_MODE_LEN];
+ enum vmode_e mode;
+ int width, height, vrefresh;
+ unsigned int flags;
+};
+
+extern struct osd_device_data_s osd_meson_dev;
+char *am_meson_crtc_get_voutmode(struct drm_display_mode *mode);
+
#endif /* __AM_MESON_VPU_H */
diff --git a/drivers/amlogic/drm/meson_vpu_pipeline.c b/drivers/amlogic/drm/meson_vpu_pipeline.c
new file mode 100644
index 0000000..aef3b8d
--- a/dev/null
+++ b/drivers/amlogic/drm/meson_vpu_pipeline.c
@@ -0,0 +1,410 @@
+/*
+ * drivers/amlogic/drm/meson_vpu_pipeline.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <dt-bindings/display/meson-drm-ids.h>
+
+#include "meson_vpu_pipeline.h"
+#include "meson_drv.h"
+
+#define MAX_LINKS 5
+#define MAX_PORTS 6
+#define MAX_PORT_ID 32
+
+static struct meson_vpu_block **vpu_blocks;
+static int num_blocks;
+
+struct meson_vpu_link_para {
+ u8 id;
+ u8 port;
+};
+
+struct meson_vpu_block_para {
+ char *name;
+ u8 id;
+ u8 index;
+ u8 type;
+ u8 num_inputs;
+ u8 num_outputs;
+ struct meson_vpu_link_para inputs[MESON_BLOCK_MAX_INPUTS];
+ struct meson_vpu_link_para outputs[MESON_BLOCK_MAX_OUTPUTS];
+ u64 inputs_mask;
+ u64 outputs_mask;
+};
+
+static struct meson_vpu_block *create_block(size_t blk_sz,
+ struct meson_vpu_block_para *para,
+ struct meson_vpu_block_ops *ops,
+ struct meson_vpu_pipeline *pipeline)
+{
+ struct meson_vpu_block *mvb;
+ int i;
+
+ mvb = kzalloc(blk_sz, GFP_KERNEL);
+ if (!mvb)
+ return NULL;
+
+ snprintf(mvb->name, MESON_BLOCK_MAX_NAME_LEN, "%s", para->name);
+ mvb->id = para->id;
+ mvb->type = para->type;
+ mvb->index = para->index;
+ mvb->avail_inputs = para->num_inputs;
+ mvb->avail_outputs = para->num_outputs;
+ mvb->max_inputs = para->num_inputs * 2;
+ mvb->max_outputs = para->num_outputs * 2;
+ mvb->inputs_mask = para->inputs_mask;
+ mvb->outputs_mask = para->outputs_mask;
+
+ for (i = 0; i < mvb->avail_inputs; i++) {
+ mvb->inputs[i].port = para->inputs[i].port;
+ mvb->inputs[i].id = para->inputs[i].id;
+ mvb->inputs[i].edges_active = 1;
+ mvb->inputs[i].edges_visited = 0;
+ }
+
+ for (i = 0; i < mvb->avail_outputs; i++) {
+ mvb->outputs[i].port = para->outputs[i].port;
+ mvb->outputs[i].id = para->outputs[i].id;
+ mvb->outputs[i].edges_active = 1;
+ mvb->outputs[i].edges_visited = 0;
+ }
+
+ mvb->ops = ops;
+ mvb->pipeline = pipeline;
+
+ return mvb;
+}
+
+static void parse_vpu_node(struct device_node *child_node,
+ struct meson_vpu_block_para *para)
+{
+ int i, j, ret, size;
+ u8 id;
+ struct device_node *link;
+ const __be32 *list, *phandle;
+ u64 in_mask, out_mask;
+
+ in_mask = 0;
+ out_mask = 0;
+ ret = of_property_read_u8(child_node, "id", &para->id);
+ if (ret)
+ para->id = 0;
+ ret = of_property_read_u8(child_node, "index", &para->index);
+ if (ret)
+ para->index = 0;
+ ret = of_property_read_u8(child_node, "type", &para->type);
+ if (ret)
+ para->type = 0;
+ ret = of_property_read_u8(child_node, "num_in_links",
+ &para->num_inputs);
+ if (ret)
+ para->num_inputs = 0;
+ ret = of_property_read_u8(child_node, "num_out_links",
+ &para->num_outputs);
+ if (ret)
+ para->num_outputs = 0;
+ ret = of_property_read_string(child_node, "block_name",
+ (const char **)&para->name);
+ if (ret)
+ para->name = NULL;
+
+ list = of_get_property(child_node, "in_links", &size);
+ if (list) {
+ size /= sizeof(*list);
+ if (!size || size % 2) {
+ DRM_ERROR("wrong in_links config\n");
+ //return -EINVAL;
+ }
+ for (i = 0, j = 0; i < size; i += 2, j++) {
+ para->inputs[j].port = be32_to_cpu(*list++);
+ phandle = list++;
+ link = of_find_node_by_phandle(be32_to_cpup(phandle));
+ of_property_read_u8(link, "id", &id);
+ para->inputs[j].id = id;
+ in_mask |= 1 << id;
+ }
+ para->inputs_mask = in_mask;
+ }
+
+ list = of_get_property(child_node, "out_links", &size);
+ if (list) {
+ size /= sizeof(*list);
+ if (!size || size % 2) {
+ DRM_ERROR("wrong out_links config\n");
+ //return -EINVAL;
+ }
+ for (i = 0, j = 0; i < size; i += 2, j++) {
+ para->outputs[j].port = be32_to_cpu(*list++);
+ phandle = list++;
+ link = of_find_node_by_phandle(be32_to_cpup(phandle));
+ of_property_read_u8(link, "id", &id);
+ para->outputs[j].id = id;
+ out_mask |= 1 << id;
+ }
+ para->outputs_mask = out_mask;
+ }
+ DRM_INFO("id=%d,index=%d,num_in_links=%d,num_out_links=%d\n",
+ para->id, para->index,
+ para->num_inputs, para->num_outputs);
+ DRM_INFO("in_mask=0x%llx,out_mask=0x%llx\n", in_mask, out_mask);
+}
+
+static struct meson_vpu_block *
+meson_vpu_create_block(struct meson_vpu_block_para *para,
+ struct meson_vpu_pipeline *pipeline)
+{
+ struct meson_vpu_block *mvb;
+ size_t blk_size;
+
+ switch (para->type) {
+ case MESON_BLK_OSD:
+ blk_size = sizeof(struct meson_vpu_osd);
+ mvb = create_block(blk_size, para, &osd_ops, pipeline);
+
+ pipeline->osds[mvb->index] = to_osd_block(mvb);
+ pipeline->num_osds++;
+ break;
+ case MESON_BLK_AFBC:
+ blk_size = sizeof(struct meson_vpu_afbc);
+ mvb = create_block(blk_size, para, &afbc_ops, pipeline);
+
+ pipeline->afbc_osds[mvb->index] = to_afbc_block(mvb);
+ pipeline->num_afbc_osds++;
+ break;
+ case MESON_BLK_SCALER:
+ blk_size = sizeof(struct meson_vpu_scaler);
+ mvb = create_block(blk_size, para, &scaler_ops, pipeline);
+
+ pipeline->scalers[mvb->index] = to_scaler_block(mvb);
+ pipeline->num_scalers++;
+ break;
+ case MESON_BLK_OSDBLEND:
+ blk_size = sizeof(struct meson_vpu_osdblend);
+ mvb = create_block(blk_size, para, &osdblend_ops, pipeline);
+
+ pipeline->osdblend = to_osdblend_block(mvb);
+ break;
+ case MESON_BLK_HDR:
+ blk_size = sizeof(struct meson_vpu_hdr);
+ mvb = create_block(blk_size, para, &hdr_ops, pipeline);
+
+ pipeline->hdr = to_hdr_block(mvb);
+ break;
+ case MESON_BLK_DOVI:
+ blk_size = sizeof(struct meson_vpu_dolby);
+ mvb = create_block(blk_size, para, &dolby_ops, pipeline);
+
+ pipeline->dolby = to_dolby_block(mvb);
+ break;
+ case MESON_BLK_VPPBLEND:
+ blk_size = sizeof(struct meson_vpu_postblend);
+ mvb = create_block(blk_size, para, &postblend_ops, pipeline);
+
+ pipeline->postblend = to_postblend_block(mvb);
+ break;
+ default:
+ return NULL;
+ }
+
+ return mvb;
+}
+
+static void populate_block_link(void)
+{
+ int i, j, id;
+ struct meson_vpu_block *mvb;
+
+ for (i = 0; i < num_blocks; i++) {
+ mvb = vpu_blocks[i];
+
+ if (!mvb)
+ continue;
+
+ for (j = 0; j < mvb->avail_inputs; j++) {
+ id = mvb->inputs[j].id;
+ mvb->inputs[j].link = vpu_blocks[id];
+ }
+
+ for (j = 0; j < mvb->avail_outputs; j++) {
+ id = mvb->outputs[j].id;
+ mvb->outputs[j].link = vpu_blocks[id];
+ }
+ }
+}
+
+static int populate_vpu_pipeline(struct device_node *vpu_block_node,
+ struct meson_vpu_pipeline *pipeline)
+{
+ struct device_node *child_node;
+ struct meson_vpu_block *mvb;
+ struct meson_vpu_block_para para;
+
+ num_blocks = of_get_child_count(vpu_block_node);
+ if (num_blocks <= 0)
+ return -ENODEV;
+
+ vpu_blocks = kcalloc(num_blocks, sizeof(*vpu_blocks), GFP_KERNEL);
+ if (!vpu_blocks)
+ return -ENOMEM;
+
+ for_each_child_of_node(vpu_block_node, child_node) {
+ parse_vpu_node(child_node, &para);
+
+ mvb = meson_vpu_create_block(&para, pipeline);
+
+ if (!mvb)
+ return -ENOMEM;
+ vpu_blocks[mvb->id] = mvb;
+ }
+
+ populate_block_link();
+
+ return 0;
+}
+
+void VPU_PIPELINE_HW_INIT(struct meson_vpu_block *mvb)
+{
+ if (mvb->ops->init)
+ mvb->ops->init(mvb);
+}
+
+static void vpu_pipeline_planes_calc(struct meson_vpu_pipeline *pipeline,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ u8 i;
+
+ mvps->num_plane = 0;
+ mvps->enable_blocks = 0;
+ for (i = 0; i < pipeline->num_osds; i++) {
+ if (mvps->plane_info[i].enable) {
+ if (mvps->plane_info[i].src_w >
+ MESON_OSD_INPUT_W_LIMIT ||
+ mvps->plane_info[i].dst_w == 0) {
+ mvps->plane_info[i].enable = 0;
+ continue;
+ }
+ mvps->num_plane++;
+ }
+ }
+ DRM_DEBUG("num_plane=%d.\n", mvps->num_plane);
+}
+
+int vpu_pipeline_check(struct meson_vpu_pipeline *pipeline,
+ struct drm_atomic_state *state)
+{
+ int ret;
+ struct meson_vpu_pipeline_state *mvps;
+
+ mvps = meson_vpu_pipeline_get_state(pipeline, state);
+
+ vpu_pipeline_planes_calc(pipeline, mvps);
+
+ ret = vpu_pipeline_traverse(mvps, state);
+ DRM_DEBUG("check done--num_plane=%d.\n", mvps->num_plane);
+
+ return ret;
+}
+
+void vpu_pipeline_init(struct meson_vpu_pipeline *pipeline)
+{
+ int i;
+
+ for (i = 0; i < pipeline->num_osds; i++)
+ VPU_PIPELINE_HW_INIT(&pipeline->osds[i]->base);
+
+ for (i = 0; i < pipeline->num_afbc_osds; i++)
+ VPU_PIPELINE_HW_INIT(&pipeline->afbc_osds[i]->base);
+
+ for (i = 0; i < pipeline->num_scalers; i++)
+ VPU_PIPELINE_HW_INIT(&pipeline->scalers[i]->base);
+
+ VPU_PIPELINE_HW_INIT(&pipeline->osdblend->base);
+
+ VPU_PIPELINE_HW_INIT(&pipeline->hdr->base);
+
+ VPU_PIPELINE_HW_INIT(&pipeline->postblend->base);
+}
+
+/* maybe use graph traverse is a good choice */
+int vpu_pipeline_update(struct meson_vpu_pipeline *pipeline,
+ struct drm_atomic_state *old_state)
+{
+ unsigned long id;
+ struct meson_vpu_block *mvb;
+ struct meson_vpu_block_state *mvbs;
+ struct meson_vpu_pipeline_state *old_mvps, *new_mvps;
+ unsigned long affected_blocks = 0;
+
+ old_mvps = meson_vpu_pipeline_get_state(pipeline, old_state);
+ new_mvps = priv_to_pipeline_state(pipeline->obj.state);
+
+ DRM_DEBUG("old_enable_blocks: 0x%llx, new_enable_blocks: 0x%llx.\n",
+ old_mvps->enable_blocks, new_mvps->enable_blocks);
+
+ #ifdef MESON_DRM_VERSION_V0
+ meson_vpu_pipeline_atomic_backup_state(new_mvps);
+ #endif
+ affected_blocks = old_mvps->enable_blocks | new_mvps->enable_blocks;
+ for_each_set_bit(id, &affected_blocks, 32) {
+ mvb = vpu_blocks[id];
+ mvbs = priv_to_block_state(mvb->obj.state);
+
+ if (new_mvps->enable_blocks & BIT(id)) {
+ mvb->ops->update_state(mvb, mvbs);
+ mvb->ops->enable(mvb);
+ } else {
+ mvb->ops->disable(mvb);
+ }
+ }
+
+ return 0;
+}
+
+int vpu_topology_init(struct platform_device *pdev, struct meson_drm *priv)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct device_node *child, *vpu_block_node;
+ struct meson_vpu_pipeline *pipeline;
+
+ child = of_get_child_by_name(np, "vpu_topology");
+ if (!child)
+ return -ENODEV;
+
+ vpu_block_node = of_get_child_by_name(child, "vpu_blocks");
+ if (!vpu_block_node) {
+ of_node_put(child);
+ return -ENODEV;
+ }
+
+ pipeline = kzalloc(sizeof(*pipeline), GFP_KERNEL);
+ if (!pipeline)
+ return -ENOMEM;
+
+ populate_vpu_pipeline(vpu_block_node, pipeline);
+ priv->pipeline = pipeline;
+ of_node_put(vpu_block_node);
+ of_node_put(child);
+
+ return 0;
+}
+EXPORT_SYMBOL(vpu_topology_init);
diff --git a/drivers/amlogic/drm/meson_vpu_pipeline.h b/drivers/amlogic/drm/meson_vpu_pipeline.h
new file mode 100644
index 0000000..258f8e9
--- a/dev/null
+++ b/drivers/amlogic/drm/meson_vpu_pipeline.h
@@ -0,0 +1,451 @@
+/*
+ * drivers/amlogic/drm/meson_vpu_pipeline.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __MESON_VPU_TOPOLOGY_H
+#define __MESON_VPU_TOPOLOGY_H
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <dt-bindings/display/meson-drm-ids.h>
+#include "meson_vpu_reg.h"
+#include "meson_drv.h"
+#include "meson_vpu_util.h"
+
+#define MESON_OSD1 0
+#define MESON_OSD2 1
+#define MESON_OSD3 2
+#define MESON_MAX_OSDS 4
+#define MESON_MAX_OSD_BLEND 3
+#define MESON_MAX_OSD_TO_VPP 2
+#define MESON_MAX_SCALERS 4
+#define MESON_MAX_VIDEO 2
+#define MESON_MAX_BLOCKS 32
+#define MESON_BLOCK_MAX_INPUTS 6
+#define MESON_BLOCK_MAX_OUTPUTS 3
+#define MESON_BLOCK_MAX_NAME_LEN 32
+/*ratio base for scaler calc;maybe need bigger than 1000*/
+#define RATIO_BASE 1000
+#define MESON_OSD_INPUT_W_LIMIT 1920
+
+#define MAX_DIN_NUM 4
+#define MAX_DOUT_NUM 2
+
+#define MAX_DFS_PATH_NUM 2
+/*
+ *according to reg description,scale down limit shold be 4bits=16
+ *but test result is 10,it will display abnormal if bigger than 10.xx
+ *have not get more info from others,so config it as 10 right now.
+ *Todo:if you make sure and test okay,you can rechange it.
+ */
+#define MESON_OSD_SCLAE_DOWN_LIMIT 10
+#define MESON_OSD_SCLAE_UP_LIMIT ((1 << 24) - 1)
+/*
+ *MESON_DRM_VERSION_V0:support modetest and atomictest,
+ *backup last commit state
+ *MESON_DRM_VERSION_V1:support atomictest,
+ *don't support modetest,don't backup last commit state
+ */
+#define MESON_DRM_VERSION_V0 0
+
+#define SCALER_RATIO_X_CALC_DONE BIT(0)
+#define SCALER_RATIO_Y_CALC_DONE BIT(1)
+#define SCALER_IN_W_CALC_DONE BIT(2)
+#define SCALER_IN_H_CALC_DONE BIT(3)
+#define SCALER_OUT_W_CALC_DONE BIT(4)
+#define SCALER_OUT_H_CALC_DONE BIT(5)
+
+#define SCALER_INPUT_WIDTH_CHANGED BIT(0)
+#define SCALER_INPUT_HEIGHT_CHANGED BIT(1)
+#define SCALER_OUTPUT_WIDTH_CHANGED BIT(2)
+#define SCALER_OUTPUT_HEIGHT_CHANGED BIT(3)
+#define SCALER_OUTPUT_SCAN_MODE_CHANGED BIT(4)
+
+enum meson_vpu_blk_type {
+ MESON_BLK_OSD = 0,
+ MESON_BLK_AFBC,
+ MESON_BLK_SCALER,
+ MESON_BLK_OSDBLEND,
+ MESON_BLK_HDR,
+ MESON_BLK_DOVI,
+ MESON_BLK_VPPBLEND,
+};
+
+struct meson_vpu_pipeline;
+struct meson_vpu_block;
+struct meson_vpu_block_state;
+struct meson_vpu_pipeline_state;
+
+/* vpu block ops */
+struct meson_vpu_block_ops {
+ int (*check_state)(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state,
+ struct meson_vpu_pipeline_state *mvps);
+ void (*update_state)(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state);
+ void (*enable)(struct meson_vpu_block *vblk);
+ void (*disable)(struct meson_vpu_block *vblk);
+ void (*init)(struct meson_vpu_block *vblk);
+};
+
+struct meson_vpu_block_link {
+ struct meson_vpu_block *link;
+ u8 id;
+ u8 port;
+ int edges_active;
+ int edges_visited;
+};
+
+/* vpu block */
+struct meson_vpu_block {
+ struct drm_private_obj obj;
+ char name[MESON_BLOCK_MAX_NAME_LEN];
+
+ enum meson_vpu_blk_type type;
+ u8 id;
+ u8 index;
+ u8 max_inputs;
+ u8 max_outputs;
+ u8 avail_inputs;
+ u8 avail_outputs;
+ unsigned long inputs_mask;
+ unsigned long outputs_mask;
+ struct meson_vpu_block_link inputs[MESON_BLOCK_MAX_INPUTS];
+ struct meson_vpu_block_link outputs[MESON_BLOCK_MAX_OUTPUTS];
+ struct meson_vpu_block_ops *ops;
+ struct meson_vpu_pipeline *pipeline;
+};
+
+struct meson_vpu_block_state {
+ struct drm_private_state obj;
+ struct meson_vpu_block *pblk;
+ u32 inputs_mask;
+
+ u32 inputs_changed;
+ u32 outputs_changed;
+ u32 checked;
+
+ u32 state_changed;
+
+ struct meson_vpu_block_link inputs[MESON_BLOCK_MAX_INPUTS];
+ struct meson_vpu_block_link outputs[MESON_BLOCK_MAX_OUTPUTS];
+ int in_stack;
+ int active;
+
+
+};
+
+struct meson_vpu_osd_layer_info {
+ u32 src_x;
+ u32 src_y;
+ u32 src_w;
+ u32 src_h;
+ u32 dst_w;
+ u32 dst_h;
+ int dst_x;
+ int dst_y;
+ u32 zorder;
+ u32 byte_stride;
+ u32 pixel_format;
+ u32 phy_addr;
+ u32 plane_index;
+ u32 enable;
+ u32 ratio_x;/*input_w/output_w*/
+ u32 afbc_inter_format;
+ u32 afbc_en;
+};
+
+struct meson_vpu_osd {
+ struct meson_vpu_block base;
+ struct osd_mif_reg_s *reg;
+};
+
+struct meson_vpu_osd_state {
+ struct meson_vpu_block_state base;
+
+ u32 index;
+ u32 enable;
+ u32 color_key_enable;
+ u32 dimm_enable;
+ u32 mode_3d_enable;
+
+ u32 color_key;
+ u32 alpha;
+ u32 global_alpha;
+ u32 dimm_color;
+ u32 phy_addr;
+ u32 pixel_format;
+ u32 zorder;
+ u32 byte_stride;
+ u32 src_x;
+ u32 src_y;
+ u32 src_w;
+ u32 src_h;
+ u32 dst_w;
+ u32 dst_h;
+ int dst_x;
+ int dst_y;
+ int s_mode;
+ int r_mode;
+ u32 plane_index;
+};
+
+struct meson_vpu_afbc {
+ struct meson_vpu_block base;
+
+};
+
+struct meson_vpu_afbc_state {
+ struct meson_vpu_block_state base;
+
+ u32 format;
+ u32 inter_format;
+ union afbc_osd_reg regs;
+};
+
+struct meson_vpu_scaler {
+ struct meson_vpu_block base;
+ struct osd_scaler_reg_s *reg;
+ u32 linebuffer;/*base pixel*/
+ u32 bank_length;/*base line*/
+};
+
+struct meson_vpu_scaler_state {
+ struct meson_vpu_block_state base;
+
+ u32 free_scale_mode;
+ u32 input_width;
+ u32 input_height;
+ u32 output_width;
+ u32 output_height;
+ u32 ratio_x;
+ u32 ratio_y;
+ u32 scan_mode_out;
+ u32 state_changed;
+ u32 free_scale_enable;
+};
+
+struct meson_vpu_scaler_param {
+ u32 input_width;
+ u32 input_height;
+ u32 output_width;
+ u32 output_height;
+ u32 ratio_x;
+ u32 ratio_y;
+ /*calc_done_mask:
+ *bit0:ratio_x,
+ *bit1:ratio_y
+ *bit2:input_width
+ *bit3:input_height
+ *bit4:output_width
+ *bit5:output_height
+ */
+ u32 calc_done_mask;
+ /*
+ *bit0:plane0
+ *bit1:plane1
+ *bit2:plane2
+ *bit*:plane*
+ */
+ u32 plane_mask;
+ u32 enable;
+ u32 before_osdblend;
+};
+
+struct meson_vpu_osdblend {
+ struct meson_vpu_block base;
+ struct osdblend_reg_s *reg;
+};
+
+struct meson_vpu_osdblend_state {
+ struct meson_vpu_block_state base;
+
+ u32 input_num;
+ /*bit0/bit1/bit2-->osd0/osd1/osd2*/
+ u32 input_osd_mask;
+ /*Din mask:bit0:DIN0;bit1:DIN1;bit2:DIN2;bit3:DIN3*/
+ u32 input_mask;
+ /*Din0~3 select which input channel or osd(0/1/2)*/
+ u32 din_channel_mux[MAX_DIN_NUM];
+ /*osd(0/1/2) go through osdblend to dout0 or dout1*/
+ u32 dout_mux[MAX_DIN_NUM];
+ /*scope position before mux,tied with osd0/osd1/osd2*/
+ struct osd_scope_s din_channel_scope[MAX_DIN_NUM];
+ /*sub-blend0 and sub-blend1 size*/
+ u32 input_width[MESON_MAX_OSD_BLEND];
+ u32 input_height[MESON_MAX_OSD_BLEND];
+ /*0:din0-->blend0;1:din0-->Dout0,bypass OsdBlend*/
+ u32 din0_switch;
+ /*0:din3-->blend1;1:din3-->Dout1,bypass OsdBlend*/
+ u32 din3_switch;
+ /*0:blend1-->blend2;1:blend1-->Dout1,bypass Blend2*/
+ u32 blend1_switch;
+
+};
+
+struct meson_vpu_hdr {
+ struct meson_vpu_block base;
+
+};
+
+struct meson_vpu_hdr_state {
+ struct meson_vpu_block_state base;
+};
+
+struct meson_vpu_dolby {
+ struct meson_vpu_block base;
+};
+
+struct meson_vpu_dolby_state {
+ struct meson_vpu_block_state base;
+};
+
+struct meson_vpu_postblend {
+ struct meson_vpu_block base;
+ struct postblend_reg_s *reg;
+};
+
+struct meson_vpu_postblend_state {
+ struct meson_vpu_block_state base;
+ struct osd_scope_s postblend_scope[MESON_MAX_OSD_TO_VPP];
+};
+
+/* vpu pipeline */
+struct meson_vpu_pipeline {
+ struct drm_private_obj obj;
+ struct drm_display_mode mode;
+ struct meson_vpu_osd *osds[MESON_MAX_OSDS];
+ struct meson_vpu_afbc *afbc_osds[MESON_MAX_OSDS];
+ struct meson_vpu_scaler *scalers[MESON_MAX_SCALERS];
+ struct meson_vpu_osdblend *osdblend;
+ struct meson_vpu_hdr *hdr;
+ struct meson_vpu_dolby *dolby;
+ struct meson_vpu_postblend *postblend;
+ struct meson_vpu_pipeline_state *state;
+ u32 num_osds;
+ u32 num_afbc_osds;
+ u32 num_scalers;
+ u8 osd_version;
+};
+
+struct meson_vpu_common_state {
+ u32 color_format;
+ u64 block_mask;
+};
+
+struct meson_vpu_stack {
+ int num_blocks;
+ int top;
+ struct meson_vpu_block *stack[MESON_MAX_BLOCKS];
+};
+
+struct meson_vpu_traverse {
+ struct meson_vpu_block *path[MAX_DFS_PATH_NUM][MESON_MAX_BLOCKS];
+ int num_path;
+};
+
+struct meson_vpu_pipeline_state {
+ struct drm_private_state obj;
+ struct meson_vpu_common_state common_cfg;
+ struct meson_vpu_pipeline *pipeline;
+ u64 enable_blocks;
+ struct meson_vpu_osd_layer_info plane_info[MESON_MAX_OSDS];
+ u32 num_plane;
+ /*min --> max*/
+ u32 zorder_plane_index[MESON_MAX_OSDS];
+ u32 ratio_plane_index[MESON_MAX_OSDS];
+ struct meson_vpu_scaler_param scaler_param[MESON_MAX_SCALERS];
+ /*pre_osd_scope is before DIN*/
+ struct osd_scope_s osd_scope_pre[MAX_DIN_NUM];
+
+ /*some traverse help structure*/
+ struct meson_vpu_stack osd_stack[MESON_MAX_OSDS];
+
+ /*store traverse result for every path*/
+ struct meson_vpu_traverse osd_traverse[MESON_MAX_OSDS];
+
+ u32 plane_index[MESON_MAX_OSDS];
+ u32 din_index[MAX_DIN_NUM];
+ u32 dout_index[MAX_DIN_NUM];
+ u32 scaler_cnt[MAX_DIN_NUM];
+ struct meson_vpu_block *scale_blk[MESON_MAX_OSDS][MESON_MAX_SCALERS];
+ u32 dout_zorder[MAX_DOUT_NUM];
+};
+
+#define to_osd_block(x) container_of(x, struct meson_vpu_osd, base)
+#define to_afbc_block(x) container_of(x, struct meson_vpu_afbc, base)
+#define to_scaler_block(x) container_of(x, struct meson_vpu_scaler, base)
+#define to_osdblend_block(x) container_of(x, struct meson_vpu_osdblend, base)
+#define to_hdr_block(x) container_of(x, struct meson_vpu_hdr, base)
+#define to_dolby_block(x) container_of(x, struct meson_vpu_dolby, base)
+#define to_postblend_block(x) container_of(x, struct meson_vpu_postblend, base)
+
+#define to_osd_state(x) container_of(x, struct meson_vpu_osd_state, base)
+#define to_afbc_state(x) container_of(x, struct meson_vpu_afbc_state, base)
+#define to_scaler_state(x) container_of(x, struct meson_vpu_scaler_state, base)
+#define to_osdblend_state(x) container_of(x, \
+ struct meson_vpu_osdblend_state, base)
+#define to_hdr_state(x) container_of(x, struct meson_vpu_hdr_state, base)
+#define to_dolby_state(x) container_of(x, struct meson_vpu_dolby_state, base)
+#define to_postblend_state(x) container_of(x, \
+ struct meson_vpu_postblend_state, base)
+
+#define priv_to_block(x) container_of(x, struct meson_vpu_block, obj)
+#define priv_to_block_state(x) container_of(x, \
+ struct meson_vpu_block_state, obj)
+#define priv_to_pipeline(x) container_of(x, struct meson_vpu_pipeline, obj)
+#define priv_to_pipeline_state(x) container_of(x, \
+ struct meson_vpu_pipeline_state, obj)
+
+int vpu_topology_init(struct platform_device *pdev, struct meson_drm *private);
+int vpu_pipeline_check(struct meson_vpu_pipeline *pipeline,
+ struct drm_atomic_state *state);
+int vpu_pipeline_update(struct meson_vpu_pipeline *pipeline,
+ struct drm_atomic_state *old_state);
+void vpu_pipeline_init(struct meson_vpu_pipeline *pipeline);
+
+/* meson_vpu_pipeline_private.c */
+struct meson_vpu_block_state *
+meson_vpu_block_get_state(struct meson_vpu_block *block,
+ struct drm_atomic_state *state);
+struct meson_vpu_pipeline_state *
+meson_vpu_pipeline_get_state(struct meson_vpu_pipeline *pipeline,
+ struct drm_atomic_state *state);
+int meson_vpu_block_state_init(struct meson_drm *private,
+ struct meson_vpu_pipeline *pipeline);
+#ifdef MESON_DRM_VERSION_V0
+void meson_vpu_pipeline_atomic_backup_state(
+ struct meson_vpu_pipeline_state *mvps);
+#endif
+
+int combination_traverse(struct meson_vpu_pipeline_state *mvps,
+ struct drm_atomic_state *state);
+int vpu_pipeline_traverse(struct meson_vpu_pipeline_state *mvps,
+ struct drm_atomic_state *state);
+int vpu_pipeline_check_osdblend(u32 *out_port, int num_planes,
+ struct meson_vpu_pipeline_state *mvps,
+ struct drm_atomic_state *state);
+
+extern struct meson_vpu_block_ops osd_ops;
+extern struct meson_vpu_block_ops afbc_ops;
+extern struct meson_vpu_block_ops scaler_ops;
+extern struct meson_vpu_block_ops osdblend_ops;
+extern struct meson_vpu_block_ops hdr_ops;
+extern struct meson_vpu_block_ops dolby_ops;
+extern struct meson_vpu_block_ops postblend_ops;
+
+
+ #endif
diff --git a/drivers/amlogic/drm/meson_vpu_pipeline_private.c b/drivers/amlogic/drm/meson_vpu_pipeline_private.c
new file mode 100644
index 0000000..a4ecb0e
--- a/dev/null
+++ b/drivers/amlogic/drm/meson_vpu_pipeline_private.c
@@ -0,0 +1,480 @@
+/*
+ * drivers/amlogic/drm/meson_vpu_pipeline_private.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include "meson_vpu_pipeline.h"
+#include "meson_drv.h"
+
+static inline void
+vpu_pipeline_state_set(struct meson_vpu_block *pblk,
+ struct meson_vpu_block_state *state)
+{
+ u8 i;
+
+ for (i = 0; i < pblk->avail_inputs; i++) {
+ memcpy(&state->inputs[i], &pblk->inputs[i],
+ sizeof(struct meson_vpu_block_link));
+ }
+ for (i = 0; i < pblk->avail_outputs; i++) {
+ memcpy(&state->outputs[i], &pblk->outputs[i],
+ sizeof(struct meson_vpu_block_link));
+ }
+ state->in_stack = 0;
+ state->active = 1;
+}
+
+static struct drm_private_state *
+meson_vpu_osd_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+ struct meson_vpu_block *mvb;
+ struct meson_vpu_osd_state *state;
+
+ mvb = priv_to_block(obj);
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ state->base.pblk = mvb;
+
+ __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base.obj);
+ vpu_pipeline_state_set(mvb, &state->base);
+
+ return &state->base.obj;
+}
+
+static void meson_vpu_osd_atomic_destroy_state(struct drm_private_obj *obj,
+ struct drm_private_state *state)
+{
+ struct meson_vpu_block_state *mvbs = priv_to_block_state(state);
+ struct meson_vpu_osd_state *mvos = to_osd_state(mvbs);
+
+ DRM_DEBUG("%s id=%d,index=%d\n",
+ mvbs->pblk->name, mvbs->pblk->id, mvbs->pblk->index);
+ kfree(mvos);
+}
+
+static const struct drm_private_state_funcs meson_vpu_osd_obj_funcs = {
+ .atomic_duplicate_state = meson_vpu_osd_atomic_duplicate_state,
+ .atomic_destroy_state = meson_vpu_osd_atomic_destroy_state,
+};
+
+static int meson_vpu_osd_state_init(struct meson_drm *private,
+ struct meson_vpu_osd *osd)
+{
+ struct meson_vpu_osd_state *state;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ state->base.pblk = &osd->base;
+ drm_atomic_private_obj_init(&osd->base.obj,
+ &state->base.obj,
+ &meson_vpu_osd_obj_funcs);
+
+ return 0;
+}
+
+static struct drm_private_state *
+meson_vpu_afbc_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+ struct meson_vpu_block *mvb;
+ struct meson_vpu_afbc_state *state;
+
+ mvb = priv_to_block(obj);
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ state->base.pblk = mvb;
+
+ __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base.obj);
+ vpu_pipeline_state_set(mvb, &state->base);
+
+ return &state->base.obj;
+}
+
+static void
+meson_vpu_afbc_atomic_destroy_state(struct drm_private_obj *obj,
+ struct drm_private_state *state)
+{
+ struct meson_vpu_block_state *mvbs = priv_to_block_state(state);
+ struct meson_vpu_afbc_state *mvas = to_afbc_state(mvbs);
+
+ kfree(mvas);
+}
+
+static const struct drm_private_state_funcs meson_vpu_afbc_obj_funcs = {
+ .atomic_duplicate_state = meson_vpu_afbc_atomic_duplicate_state,
+ .atomic_destroy_state = meson_vpu_afbc_atomic_destroy_state,
+};
+
+static int meson_vpu_afbc_state_init(struct meson_drm *private,
+ struct meson_vpu_afbc *afbc)
+{
+ struct meson_vpu_afbc_state *state;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ state->base.pblk = &afbc->base;
+ drm_atomic_private_obj_init(&afbc->base.obj,
+ &state->base.obj,
+ &meson_vpu_afbc_obj_funcs);
+
+ return 0;
+}
+
+/*afbc block state ops end
+ */
+
+/*scaler block state ops start
+ */
+
+static struct drm_private_state *
+meson_vpu_scaler_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+ struct meson_vpu_block *mvb;
+ struct meson_vpu_scaler_state *state;
+
+ mvb = priv_to_block(obj);
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ state->base.pblk = mvb;
+
+ __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base.obj);
+ vpu_pipeline_state_set(mvb, &state->base);
+
+ return &state->base.obj;
+}
+
+static void
+meson_vpu_scaler_atomic_destroy_state(struct drm_private_obj *obj,
+ struct drm_private_state *state)
+{
+ struct meson_vpu_block_state *mvbs = priv_to_block_state(state);
+ struct meson_vpu_scaler_state *mvss = to_scaler_state(mvbs);
+
+ kfree(mvss);
+}
+
+static const struct drm_private_state_funcs meson_vpu_scaler_obj_funcs = {
+ .atomic_duplicate_state = meson_vpu_scaler_atomic_duplicate_state,
+ .atomic_destroy_state = meson_vpu_scaler_atomic_destroy_state,
+};
+
+static int meson_vpu_scaler_state_init(struct meson_drm *private,
+ struct meson_vpu_scaler *scaler)
+{
+ struct meson_vpu_scaler_state *state;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ state->base.pblk = &scaler->base;
+ drm_atomic_private_obj_init(&scaler->base.obj,
+ &state->base.obj,
+ &meson_vpu_scaler_obj_funcs);
+
+ return 0;
+}
+
+static struct drm_private_state *
+meson_vpu_osdblend_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+ struct meson_vpu_block *mvb;
+ struct meson_vpu_osdblend_state *state;
+
+ mvb = priv_to_block(obj);
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ state->base.pblk = mvb;
+
+ __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base.obj);
+ vpu_pipeline_state_set(mvb, &state->base);
+
+ return &state->base.obj;
+}
+
+static void
+meson_vpu_osdblend_atomic_destroy_state(struct drm_private_obj *obj,
+ struct drm_private_state *state)
+{
+ struct meson_vpu_block_state *mvbs = priv_to_block_state(state);
+ struct meson_vpu_osdblend_state *mvos = to_osdblend_state(mvbs);
+
+ kfree(mvos);
+}
+
+static const struct drm_private_state_funcs meson_vpu_osdblend_obj_funcs = {
+ .atomic_duplicate_state = meson_vpu_osdblend_atomic_duplicate_state,
+ .atomic_destroy_state = meson_vpu_osdblend_atomic_destroy_state,
+};
+
+static int meson_vpu_osdblend_state_init(struct meson_drm *private,
+ struct meson_vpu_osdblend *osdblend)
+{
+ struct meson_vpu_osdblend_state *state;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ state->base.pblk = &osdblend->base;
+ drm_atomic_private_obj_init(&osdblend->base.obj,
+ &state->base.obj,
+ &meson_vpu_osdblend_obj_funcs);
+
+ return 0;
+}
+
+static struct drm_private_state *
+meson_vpu_hdr_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+ struct meson_vpu_block *mvb;
+ struct meson_vpu_hdr_state *state;
+
+ mvb = priv_to_block(obj);
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ state->base.pblk = mvb;
+
+ __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base.obj);
+ vpu_pipeline_state_set(mvb, &state->base);
+
+ return &state->base.obj;
+}
+
+static void meson_vpu_hdr_atomic_destroy_state(struct drm_private_obj *obj,
+ struct drm_private_state *state)
+{
+ struct meson_vpu_block_state *mvbs = priv_to_block_state(state);
+ struct meson_vpu_hdr_state *mvhs = to_hdr_state(mvbs);
+
+ kfree(mvhs);
+}
+
+static const struct drm_private_state_funcs meson_vpu_hdr_obj_funcs = {
+ .atomic_duplicate_state = meson_vpu_hdr_atomic_duplicate_state,
+ .atomic_destroy_state = meson_vpu_hdr_atomic_destroy_state,
+};
+
+static int meson_vpu_hdr_state_init(struct meson_drm *private,
+ struct meson_vpu_hdr *hdr)
+{
+ struct meson_vpu_hdr_state *state;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ state->base.pblk = &hdr->base;
+ drm_atomic_private_obj_init(&hdr->base.obj,
+ &state->base.obj,
+ &meson_vpu_hdr_obj_funcs);
+
+ return 0;
+}
+
+/*hdr block state ops end
+ */
+
+/*postblend block state ops start
+ */
+
+static struct drm_private_state *
+meson_vpu_postblend_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+ struct meson_vpu_block *mvb;
+ struct meson_vpu_postblend_state *state;
+
+ mvb = priv_to_block(obj);
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ state->base.pblk = mvb;
+
+ __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base.obj);
+ vpu_pipeline_state_set(mvb, &state->base);
+
+ return &state->base.obj;
+}
+
+static void
+meson_vpu_postblend_atomic_destroy_state(struct drm_private_obj *obj,
+ struct drm_private_state *state)
+{
+ struct meson_vpu_block_state *mvbs = priv_to_block_state(state);
+ struct meson_vpu_postblend_state *mvas = to_postblend_state(mvbs);
+
+ kfree(mvas);
+}
+
+static const struct drm_private_state_funcs meson_vpu_postblend_obj_funcs = {
+ .atomic_duplicate_state = meson_vpu_postblend_atomic_duplicate_state,
+ .atomic_destroy_state = meson_vpu_postblend_atomic_destroy_state,
+};
+
+static int
+meson_vpu_postblend_state_init(struct meson_drm *private,
+ struct meson_vpu_postblend *postblend)
+{
+ struct meson_vpu_postblend_state *state;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ state->base.pblk = &postblend->base;
+ drm_atomic_private_obj_init(&postblend->base.obj,
+ &state->base.obj,
+ &meson_vpu_postblend_obj_funcs);
+ return 0;
+}
+
+/*postblend block state ops end
+ */
+#ifdef MESON_DRM_VERSION_V0
+static struct meson_vpu_pipeline_state last_mvps;
+#endif
+static struct drm_private_state *
+meson_vpu_pipeline_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+ struct meson_vpu_pipeline_state *state;
+ struct meson_vpu_pipeline *pipeline = priv_to_pipeline(obj);
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ #ifdef MESON_DRM_VERSION_V0
+ memcpy(state, &last_mvps, sizeof(*state));
+ #endif
+ state->pipeline = pipeline;
+
+ __drm_atomic_helper_private_obj_duplicate_state(obj, &state->obj);
+
+ return &state->obj;
+}
+
+static void meson_vpu_pipeline_atomic_destroy_state(struct drm_private_obj *obj,
+ struct drm_private_state *state)
+{
+ struct meson_vpu_pipeline_state *mvps = priv_to_pipeline_state(state);
+
+ kfree(mvps);
+}
+
+#ifdef MESON_DRM_VERSION_V0
+void meson_vpu_pipeline_atomic_backup_state(
+ struct meson_vpu_pipeline_state *mvps)
+{
+ memcpy(&last_mvps, mvps, sizeof(*mvps));
+}
+#endif
+
+static const struct drm_private_state_funcs meson_vpu_pipeline_obj_funcs = {
+ .atomic_duplicate_state = meson_vpu_pipeline_atomic_duplicate_state,
+ .atomic_destroy_state = meson_vpu_pipeline_atomic_destroy_state,
+};
+
+static int meson_vpu_pipeline_state_init(struct meson_drm *private,
+ struct meson_vpu_pipeline *pipeline)
+{
+ struct meson_vpu_pipeline_state *state;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ state->pipeline = pipeline;
+ drm_atomic_private_obj_init(&pipeline->obj, &state->obj,
+ &meson_vpu_pipeline_obj_funcs);
+
+ return 0;
+}
+
+struct meson_vpu_block_state *
+meson_vpu_block_get_state(struct meson_vpu_block *block,
+ struct drm_atomic_state *state)
+{
+ struct drm_private_state *dps;
+ struct meson_vpu_block_state *mvbs;
+
+ dps = drm_atomic_get_private_obj_state(state, &block->obj);
+ if (dps) {
+ mvbs = priv_to_block_state(dps);
+ return mvbs;
+ }
+
+ return NULL;
+}
+
+struct meson_vpu_pipeline_state *
+meson_vpu_pipeline_get_state(struct meson_vpu_pipeline *pipeline,
+ struct drm_atomic_state *state)
+{
+ struct drm_private_state *dps;
+
+ dps = drm_atomic_get_private_obj_state(state, &pipeline->obj);
+ if (dps) {
+ dps->state = state;
+ return priv_to_pipeline_state(dps);
+ }
+
+ return NULL;
+}
+
+int meson_vpu_block_state_init(struct meson_drm *private,
+ struct meson_vpu_pipeline *pipeline)
+{
+ int i, ret;
+
+ ret = meson_vpu_pipeline_state_init(private, pipeline);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < pipeline->num_osds; i++) {
+ ret = meson_vpu_osd_state_init(private, pipeline->osds[i]);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < pipeline->num_afbc_osds; i++) {
+ ret = meson_vpu_afbc_state_init(private,
+ pipeline->afbc_osds[i]);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < pipeline->num_scalers; i++) {
+ ret = meson_vpu_scaler_state_init(private,
+ pipeline->scalers[i]);
+ if (ret)
+ return ret;
+ }
+
+
+ ret = meson_vpu_osdblend_state_init(private, pipeline->osdblend);
+ if (ret)
+ return ret;
+
+ ret = meson_vpu_hdr_state_init(private, pipeline->hdr);
+ if (ret)
+ return ret;
+
+ ret = meson_vpu_postblend_state_init(private, pipeline->postblend);
+ if (ret)
+ return ret;
+
+ return 0;
+}
diff --git a/drivers/amlogic/drm/meson_vpu_pipeline_traverse.c b/drivers/amlogic/drm/meson_vpu_pipeline_traverse.c
new file mode 100644
index 0000000..2f3b211
--- a/dev/null
+++ b/drivers/amlogic/drm/meson_vpu_pipeline_traverse.c
@@ -0,0 +1,658 @@
+/*
+ * drivers/amlogic/drm/meson_vpu_pipeline_traverse.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <dt-bindings/display/meson-drm-ids.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include "meson_vpu_pipeline.h"
+#include "meson_drv.h"
+
+static void stack_init(struct meson_vpu_stack *mvs)
+{
+ mvs->top = 0;
+ memset(mvs->stack, 0, sizeof(struct meson_vpu_block *) *
+ MESON_MAX_BLOCKS);
+}
+
+static void stack_push(struct meson_vpu_stack *mvs, struct meson_vpu_block *mvb)
+{
+ mvs->stack[mvs->top++] = mvb;
+}
+
+static struct meson_vpu_block *stack_pop(struct meson_vpu_stack *mvs)
+{
+ struct meson_vpu_block *mvb;
+
+ mvb = mvs->stack[--mvs->top];
+ mvs->stack[mvs->top] = NULL;
+ return mvb;
+}
+
+static struct meson_vpu_block *neighbour(struct meson_vpu_block_state *mvbs,
+ int *index,
+ struct drm_atomic_state *state)
+{
+ int i;
+ struct meson_vpu_block_link *mvbl;
+ struct meson_vpu_block_state *next_state;
+
+ for (i = 0; i < MESON_BLOCK_MAX_OUTPUTS; i++) {
+ mvbl = &mvbs->outputs[i];
+
+ if (!mvbl->link)
+ continue;
+ next_state = meson_vpu_block_get_state(mvbl->link, state);
+ if (next_state->in_stack) {
+ //printk("%s already in stack.\n", mvbl->link->name);
+ continue;
+ }
+ if (!next_state->active) {
+ //printk("%s is not active.\n", mvbl->link->name);
+ continue;
+ }
+ if (!mvbl->edges_active) {
+ //printk("edges is not active.\n");
+ continue;
+ }
+ if (mvbl->edges_visited) {
+ //printk("edges is already visited.\n");
+ continue;
+ }
+
+ *index = i;
+ return mvbl->link;
+ }
+
+ return NULL;
+}
+
+static void pipeline_visit_clean(struct meson_vpu_block_state *curr_state)
+{
+ int index;
+
+ for (index = 0; index < MESON_BLOCK_MAX_OUTPUTS; index++)
+ curr_state->outputs[index].edges_visited = 0;
+}
+
+/**
+ * pipeline_dfs - dfs algorithm to search path
+ * @osd_index: osd layer index
+ * @start: the start block of the dfs
+ * @end: the end block of the dfs
+ *
+ * use the non-recursive dfs algorithm to search all paths from the start block
+ * to the end block, the result will be saved to the meson_vpu_traverse struct.
+ *
+ */
+static void pipeline_dfs(int osd_index, struct meson_vpu_pipeline_state *mvps,
+ struct meson_vpu_block *start,
+ struct meson_vpu_block *end,
+ struct drm_atomic_state *state)
+{
+ struct meson_vpu_block *curr, *next, *prev;
+ struct meson_vpu_block_state *curr_state, *next_state, *prev_state;
+ int i, j, index;
+
+ struct meson_vpu_stack *mvs = &mvps->osd_stack[osd_index];
+ struct meson_vpu_traverse *mvt = &mvps->osd_traverse[osd_index];
+
+ stack_init(mvs);
+ stack_push(mvs, start);
+ mvt->num_path = 0;
+ j = 0;
+
+ while (mvs->top) {
+ if (mvs->stack[mvs->top - 1] == end) {
+ for (i = 0; i < mvs->top; i++) {
+ mvt->path[j][i] = mvs->stack[i];
+ DRM_DEBUG("%s->\n", mvs->stack[i]->name);
+ }
+ j++;
+ mvt->num_path++;
+ DRM_DEBUG("\n");
+ prev = stack_pop(mvs);
+ prev_state = meson_vpu_block_get_state(prev, state);
+ prev_state->in_stack = 0;
+ } else {
+ curr = mvs->stack[mvs->top - 1];
+ curr_state = meson_vpu_block_get_state(curr, state);
+ next = neighbour(curr_state, &index, state);
+
+ if (next) {
+ curr_state->outputs[index].edges_visited = 1;
+ next_state =
+ meson_vpu_block_get_state(next, state);
+ stack_push(mvs, next);
+ next_state->in_stack = 1;
+ } else {
+ stack_pop(mvs);
+ curr_state->in_stack = 0;
+ pipeline_visit_clean(curr_state);
+ }
+ }
+ }
+}
+
+static u8 find_out_port(struct meson_vpu_block *in,
+ struct meson_vpu_block *out)
+{
+ int i;
+ struct meson_vpu_block_link *mvbl;
+
+ for (i = 0; i < out->avail_inputs; i++) {
+ mvbl = &out->inputs[i];
+ if (mvbl->link == in)
+ return mvbl->port;
+ }
+ return 0;
+}
+
+void vpu_pipeline_scaler_scope_size_calc(u8 index, u8 osd_index,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ u8 m, i;
+ u32 ratio_x[MESON_MAX_SCALERS], ratio_y[MESON_MAX_SCALERS];
+ struct meson_vpu_scaler_param *scaler_param, *scaler_param_1;
+
+ i = index;
+ if (mvps->scaler_cnt[i] == 0) {
+ /*scope size calc*/
+ mvps->osd_scope_pre[osd_index].h_start =
+ mvps->plane_info[osd_index].src_x;
+ mvps->osd_scope_pre[osd_index].v_start =
+ mvps->plane_info[osd_index].src_y;
+ mvps->osd_scope_pre[osd_index].h_end =
+ mvps->osd_scope_pre[osd_index].h_start
+ + mvps->plane_info[osd_index].src_w - 1;
+ mvps->osd_scope_pre[osd_index].v_end =
+ mvps->osd_scope_pre[osd_index].v_start
+ + mvps->plane_info[osd_index].src_h - 1;
+ } else if (mvps->scaler_cnt[i] == 1) {
+ m = mvps->scale_blk[i][0]->index;
+ scaler_param = &mvps->scaler_param[m];
+ scaler_param->ratio_x =
+ (mvps->plane_info[osd_index].src_w *
+ RATIO_BASE) /
+ mvps->plane_info[osd_index].dst_w;
+ scaler_param->ratio_y =
+ (mvps->plane_info[osd_index].src_h *
+ RATIO_BASE) /
+ mvps->plane_info[osd_index].dst_h;
+ scaler_param->calc_done_mask |=
+ SCALER_RATIO_X_CALC_DONE |
+ SCALER_RATIO_Y_CALC_DONE;
+ if (scaler_param->before_osdblend) {
+ /*scale size calc firstly*/
+ scaler_param->input_width =
+ mvps->plane_info[osd_index].src_w;
+ scaler_param->input_height =
+ mvps->plane_info[osd_index].src_h;
+ scaler_param->output_width =
+ mvps->plane_info[osd_index].dst_w;
+ scaler_param->output_height =
+ mvps->plane_info[osd_index].dst_h;
+ scaler_param->calc_done_mask |=
+ SCALER_IN_W_CALC_DONE |
+ SCALER_IN_H_CALC_DONE |
+ SCALER_OUT_W_CALC_DONE |
+ SCALER_OUT_H_CALC_DONE;
+ /*scope size calc*/
+ mvps->osd_scope_pre[osd_index].h_start =
+ mvps->plane_info[osd_index].dst_x;
+ mvps->osd_scope_pre[osd_index].v_start =
+ mvps->plane_info[osd_index].dst_y;
+ mvps->osd_scope_pre[osd_index].h_end =
+ mvps->osd_scope_pre[osd_index].h_start
+ + scaler_param->output_width - 1;
+ mvps->osd_scope_pre[osd_index].v_end =
+ mvps->osd_scope_pre[osd_index].v_start
+ + scaler_param->output_height - 1;
+ } else {/*scaler position is after osdlend*/
+ /*scope size calc firstly*/
+ mvps->osd_scope_pre[osd_index].h_start =
+ mvps->plane_info[osd_index].src_x;
+ mvps->osd_scope_pre[osd_index].v_start =
+ mvps->plane_info[osd_index].src_y;
+ mvps->osd_scope_pre[osd_index].h_end =
+ mvps->osd_scope_pre[osd_index].h_start
+ + mvps->plane_info[osd_index].src_w - 1;
+ mvps->osd_scope_pre[osd_index].v_end =
+ mvps->osd_scope_pre[osd_index].v_start
+ + mvps->plane_info[osd_index].src_h - 1;
+ /*scaler size calc*/
+ scaler_param->input_width =
+ mvps->osd_scope_pre[osd_index].h_end + 1;
+ scaler_param->input_height =
+ mvps->osd_scope_pre[osd_index].v_end + 1;
+ scaler_param->output_width =
+ mvps->plane_info[osd_index].dst_x +
+ mvps->plane_info[osd_index].dst_w;
+ scaler_param->output_height =
+ mvps->plane_info[osd_index].dst_y +
+ mvps->plane_info[osd_index].dst_h;
+ scaler_param->calc_done_mask |=
+ SCALER_IN_W_CALC_DONE |
+ SCALER_IN_H_CALC_DONE |
+ SCALER_OUT_W_CALC_DONE |
+ SCALER_OUT_H_CALC_DONE;
+ }
+ } else if (mvps->scaler_cnt[i] == 2) {
+ m = mvps->scale_blk[i][0]->index;
+ scaler_param = &mvps->scaler_param[m];
+ m = mvps->scale_blk[i][1]->index;
+ scaler_param_1 = &mvps->scaler_param[m];
+ if (scaler_param_1->calc_done_mask &
+ SCALER_RATIO_X_CALC_DONE) {/*TODO*/
+ ratio_x[1] = scaler_param_1->ratio_x;
+ ratio_y[1] = scaler_param_1->ratio_y;
+ /*recheck scaler size*/
+ } else {/*TODO*/
+ ratio_x[1] = RATIO_BASE;
+ ratio_y[1] = RATIO_BASE;
+ scaler_param_1->calc_done_mask |=
+ SCALER_RATIO_X_CALC_DONE |
+ SCALER_RATIO_Y_CALC_DONE;
+ }
+ /*calculate scaler input/output size and scope*/
+ if (scaler_param->before_osdblend) {
+ scaler_param->input_width =
+ mvps->plane_info[osd_index].src_w;
+ scaler_param->input_height =
+ mvps->plane_info[osd_index].src_h;
+ scaler_param->output_width =
+ mvps->plane_info[osd_index].dst_w *
+ ratio_x[1] / RATIO_BASE;
+ scaler_param->output_height =
+ mvps->plane_info[osd_index].dst_h *
+ ratio_y[1] / RATIO_BASE;
+ scaler_param->calc_done_mask |=
+ SCALER_IN_W_CALC_DONE |
+ SCALER_IN_H_CALC_DONE |
+ SCALER_OUT_W_CALC_DONE |
+ SCALER_OUT_H_CALC_DONE;
+ /*scope size calc*/
+ mvps->osd_scope_pre[osd_index].h_start =
+ mvps->plane_info[osd_index].dst_x *
+ ratio_x[1] / RATIO_BASE;
+ mvps->osd_scope_pre[osd_index].v_start =
+ mvps->plane_info[osd_index].dst_y *
+ ratio_y[1] / RATIO_BASE;
+ mvps->osd_scope_pre[osd_index].h_end =
+ mvps->osd_scope_pre[osd_index].h_start
+ + scaler_param->output_width - 1;
+ mvps->osd_scope_pre[osd_index].v_end =
+ mvps->osd_scope_pre[osd_index].v_start
+ + scaler_param->output_height - 1;
+ } else {
+ /*TODO*/
+ }
+ /*reclac second scaler size*/
+ /*scaler_param_1->before_osdblend == 0*/
+ if (scaler_param_1->input_width <
+ mvps->osd_scope_pre[osd_index].h_end + 1) {
+ scaler_param_1->input_width =
+ mvps->osd_scope_pre[osd_index].h_end + 1;
+ scaler_param_1->output_width =
+ mvps->plane_info[osd_index].dst_x +
+ mvps->plane_info[osd_index].dst_w;
+ }
+ if (scaler_param_1->input_height <
+ mvps->osd_scope_pre[osd_index].v_end + 1) {
+ scaler_param_1->input_height =
+ mvps->osd_scope_pre[osd_index].v_end + 1;
+ scaler_param_1->output_height =
+ mvps->plane_info[osd_index].dst_y +
+ mvps->plane_info[osd_index].dst_h;
+ }
+ }
+}
+static void vpu_osd_shift_recalc(struct meson_vpu_pipeline_state *state)
+{
+ u8 i;
+
+ for (i = 0; i < MESON_MAX_OSDS; i++) {
+ state->osd_scope_pre[i].v_start += 1;
+ state->osd_scope_pre[i].v_end += 1;
+ }
+ state->scaler_param[0].input_height += 1;
+}
+int vpu_pipeline_scaler_check(int *combination, int num_planes,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ int i, j, osd_index, ret, m;
+ struct meson_vpu_traverse *mvt;
+ struct meson_vpu_block **mvb;
+ struct meson_vpu_block *block;
+ struct meson_vpu_scaler_param *scaler_param, *scaler_param_1;
+ u32 ratio_x[MESON_MAX_SCALERS], ratio_y[MESON_MAX_SCALERS];
+ bool have_blend;
+
+ ret = 0;
+ /*clean up scaler and scope size before check & calc*/
+ memset(mvps->scaler_param, 0,
+ MESON_MAX_SCALERS * sizeof(struct meson_vpu_scaler_param));
+ memset(mvps->osd_scope_pre, 0,
+ MESON_MAX_OSDS * sizeof(struct osd_scope_s));
+ for (i = 0; i < MESON_MAX_OSDS && !ret; i++) {
+ if (!mvps->plane_info[i].enable)
+ continue;
+ osd_index = mvps->plane_index[i];
+ mvt = &mvps->osd_traverse[osd_index];
+ mvb = mvt->path[combination[i]];
+ mvps->scaler_cnt[i] = 0;
+ have_blend = 0;
+
+ for (j = 0; j < MESON_MAX_BLOCKS; j++) {
+ block = mvb[j];
+ if (!block)
+ continue;
+ if (block->type == MESON_BLK_OSDBLEND)
+ have_blend = 1;
+ if (block->type == MESON_BLK_SCALER) {
+ m = mvps->scaler_cnt[i];
+ mvps->scale_blk[i][m] = block;
+ mvps->scaler_cnt[i]++;
+ m = block->index;
+ mvps->scaler_param[m].plane_mask |=
+ BIT(osd_index);
+ mvps->scaler_param[m].before_osdblend =
+ have_blend ? 0:1;
+ }
+ }
+
+ if (mvps->scaler_cnt[i] == 0) {
+ ratio_x[0] = (mvps->plane_info[osd_index].src_w *
+ RATIO_BASE) /
+ mvps->plane_info[osd_index].dst_w;
+ ratio_y[0] = (mvps->plane_info[osd_index].src_h *
+ RATIO_BASE) /
+ mvps->plane_info[osd_index].dst_h;
+ if (ratio_x[0] != RATIO_BASE ||
+ ratio_y[0] != RATIO_BASE) {
+ ret = -1;
+ break;
+ }
+ vpu_pipeline_scaler_scope_size_calc(i,
+ osd_index, mvps);
+ } else if (mvps->scaler_cnt[i] == 1) {
+ vpu_pipeline_scaler_scope_size_calc(i,
+ osd_index, mvps);
+ } else if (mvps->scaler_cnt[i] == 2) {
+ /*
+ *check second scaler firstly,
+ *if second scaler have not check,
+ *disable the second scaler.only use first scale.
+ */
+ m = mvps->scale_blk[i][1]->index;
+ scaler_param_1 = &mvps->scaler_param[m];
+ if (scaler_param_1->calc_done_mask &
+ SCALER_RATIO_X_CALC_DONE) {/*TODO*/
+ ratio_x[1] = scaler_param_1->ratio_x;
+ ratio_y[1] = scaler_param_1->ratio_y;
+ /*recheck scaler size*/
+ } else {/*TODO*/
+ ratio_x[1] = RATIO_BASE;
+ ratio_y[1] = RATIO_BASE;
+ scaler_param_1->ratio_x = RATIO_BASE;
+ scaler_param_1->ratio_y = RATIO_BASE;
+ scaler_param_1->calc_done_mask |=
+ SCALER_RATIO_X_CALC_DONE |
+ SCALER_RATIO_Y_CALC_DONE;
+ }
+ ratio_x[0] = (mvps->plane_info[osd_index].src_w *
+ RATIO_BASE) /
+ mvps->plane_info[osd_index].dst_w;
+ ratio_y[0] = (mvps->plane_info[osd_index].src_h *
+ RATIO_BASE) /
+ mvps->plane_info[osd_index].dst_h;
+ m = mvps->scale_blk[i][0]->index;
+ scaler_param = &mvps->scaler_param[m];
+ scaler_param->ratio_x =
+ (ratio_x[0] * RATIO_BASE) / ratio_x[1];
+ scaler_param->ratio_y =
+ (ratio_y[0] * RATIO_BASE) / ratio_y[1];
+ scaler_param->calc_done_mask |=
+ SCALER_RATIO_X_CALC_DONE |
+ SCALER_RATIO_Y_CALC_DONE;
+ ratio_x[0] = scaler_param->ratio_x;
+ ratio_y[0] = scaler_param->ratio_y;
+
+ if ((ratio_x[0] > RATIO_BASE &&
+ ratio_x[1] < RATIO_BASE) ||
+ (ratio_y[0] > RATIO_BASE &&
+ ratio_y[1] < RATIO_BASE)) {
+ ret = -1;
+ break;
+ }
+ vpu_pipeline_scaler_scope_size_calc(i,
+ osd_index, mvps);
+ }
+ }
+ if (ret == 0 && mvps->num_plane > 0 &&
+ mvps->pipeline->osd_version <= OSD_V2)
+ vpu_osd_shift_recalc(mvps);
+ return ret;
+}
+
+/**
+ * vpu_pipeline_check_block: check pipeline block
+ * @combination: index array of every layer path
+ * @num_planes: the number of layer
+ *
+ * For some blocks that have multiple output port,
+ * call the ops->check interface to determain a valid path.
+ *
+ * RETURNS:
+ * 0 for the valid path or -1 for the invalid path
+ */
+int vpu_pipeline_check_block(int *combination, int num_planes,
+ struct meson_vpu_pipeline_state *mvps,
+ struct drm_atomic_state *state)
+{
+ int i, j, osd_index, ret;
+ struct meson_vpu_traverse *mvt;
+ struct meson_vpu_block **mvb;
+ struct meson_vpu_block *block;
+ struct meson_vpu_block *osdblend;
+ struct meson_vpu_block_state *mvbs;
+
+ osdblend = &mvps->pipeline->osdblend->base;
+ ret = vpu_pipeline_scaler_check(combination, num_planes, mvps);
+ if (ret)
+ return -1;
+
+ for (i = 0; i < MESON_MAX_OSDS; i++) {
+ if (!mvps->plane_info[i].enable)
+ continue;
+ osd_index = mvps->plane_index[i];
+ mvt = &mvps->osd_traverse[osd_index];
+ mvb = mvt->path[combination[i]];
+ mvps->scaler_cnt[i] = 0;
+
+ for (j = 0; j < MESON_MAX_BLOCKS; j++) {
+ block = mvb[j];
+ if (!block)
+ break;
+
+ if (block == osdblend) {
+ mvps->dout_index[i] =
+ find_out_port(block, mvb[j+1]);
+ DRM_DEBUG("osd-%d blend out port: %d.\n",
+ i, mvps->dout_index[i]);
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < MESON_MAX_OSDS; i++) {
+ if (!mvps->plane_info[i].enable)
+ continue;
+ osd_index = mvps->plane_index[i];
+ mvt = &mvps->osd_traverse[osd_index];
+ mvb = mvt->path[combination[i]];
+
+ for (j = 0; j < MESON_MAX_BLOCKS; j++) {
+ block = mvb[j];
+ if (!block)
+ break;
+
+ if (block->ops && block->ops->check_state) {
+ mvbs = meson_vpu_block_get_state(block, state);
+ ret = block->ops->check_state(block,
+ mvbs, mvps);
+
+ if (ret) {
+ DRM_ERROR("%s block check error.\n",
+ block->name);
+ return ret;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+void vpu_pipeline_enable_block(int *combination, int num_planes,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ int i, j, osd_index;
+ struct meson_vpu_traverse *mvt;
+ struct meson_vpu_block **mvb;
+ struct meson_vpu_block *block;
+
+ mvps->enable_blocks = 0;
+
+ for (i = 0; i < MESON_MAX_OSDS; i++) {
+ if (!mvps->plane_info[i].enable)
+ continue;
+ osd_index = mvps->plane_index[i];
+ mvt = &mvps->osd_traverse[osd_index];
+ mvb = mvt->path[combination[i]];
+
+ for (j = 0; j < MESON_MAX_BLOCKS; j++) {
+ block = mvb[j];
+ if (!block)
+ break;
+ mvps->enable_blocks |= BIT(block->id);
+ }
+ }
+}
+
+/**
+ * combinate_layer_path - combinate every found layer path
+ * @path_num_array: the number of every layer's found path
+ * @num_planes: the number of layer
+ *
+ * use combination algorithm to check whether the path is valid
+ *
+ * RETURNS:
+ * 0 for the valid path or -1 for the invalid path
+ */
+int combinate_layer_path(int *path_num_array, int num_planes,
+ struct meson_vpu_pipeline_state *mvps,
+ struct drm_atomic_state *state)
+{
+ int i, j, ret;
+ bool is_continue = false;
+ int combination[MESON_MAX_OSDS] = {0};
+
+ i = 0;
+ ret = -1;
+
+ do {
+ // sum the combination result to check osd blend block
+ ret = vpu_pipeline_check_block(combination,
+ num_planes, mvps, state);
+ if (!ret)
+ break;
+
+ i++;
+ combination[num_planes-1] = i;
+
+ for (j = num_planes - 1; j >= 0; j--) {
+ if (combination[j] >= path_num_array[j]) {
+ combination[j] = 0;
+ i = 0;
+ if ((j - 1) >= 0)
+ combination[j - 1] =
+ combination[j - 1] + 1;
+ }
+ }
+
+ is_continue = false;
+
+ for (j = 0; j < num_planes; j++) {
+ if (combination[j] != 0)
+ is_continue = true;
+ }
+ } while (is_continue);
+ if (!ret)
+ vpu_pipeline_enable_block(combination, num_planes, mvps);
+ return ret;
+}
+
+/**
+ * find every layer's path(from start block to the end block) through
+ * pipeline_dfs, combinate every found path of every layer
+ * and check whether the combination is a valid path
+ * that can meet the requirement of hardware limites.
+ *
+ * RETURNS:
+ * 0 for the valid path or -1 for the invalid path
+ */
+int vpu_pipeline_traverse(struct meson_vpu_pipeline_state *mvps,
+ struct drm_atomic_state *state)
+{
+ int i, osd_index, ret;
+ int num_planes;
+ struct meson_vpu_block *start, *end;
+ int path[MESON_MAX_OSDS] = {0};
+ struct meson_vpu_pipeline *mvp = mvps->pipeline;
+
+ end = &mvp->postblend->base;
+ num_planes = mvps->num_plane;
+
+ if (!num_planes)
+ return 0;
+
+ DRM_DEBUG("traverse num: %d %p.\n", num_planes, mvps);
+ for (i = 0; i < MESON_MAX_OSDS; i++) {
+ if (!mvps->plane_info[i].enable)
+ continue;
+ osd_index = mvps->plane_index[i];
+ start = &mvp->osds[osd_index]->base;
+ DRM_DEBUG("do pipeline_dfs: OSD%d.\n", (osd_index + 1));
+ pipeline_dfs(osd_index, mvps, start, end, state);
+ }
+
+ // start to combination every layer case
+ for (i = 0; i < MESON_MAX_OSDS; i++) {
+ if (!mvps->plane_info[i].enable)
+ continue;
+ osd_index = mvps->plane_index[i];
+ path[i] = mvps->osd_traverse[osd_index].num_path;
+ DRM_DEBUG("osd%d traverse path num: %d\n",
+ (osd_index + 1), path[i]);
+ }
+
+ ret = combinate_layer_path(path, num_planes, mvps, state);
+ if (ret)
+ DRM_ERROR("can't find a valid path.\n");
+
+ return ret;
+}
diff --git a/drivers/amlogic/drm/meson_vpu_util.c b/drivers/amlogic/drm/meson_vpu_util.c
new file mode 100644
index 0000000..652af8f
--- a/dev/null
+++ b/drivers/amlogic/drm/meson_vpu_util.c
@@ -0,0 +1,177 @@
+/*
+ * drivers/amlogic/drm/meson_vpu_util.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include "meson_vpu_util.h"
+
+/*****drm reg access by rdma*****/
+
+u32 meson_drm_rdma_read_reg(u32 addr)
+{
+ return VSYNCOSD_RD_MPEG_REG(addr);
+}
+
+int meson_drm_rdma_write_reg(u32 addr, u32 val)
+{
+ return VSYNCOSD_WR_MPEG_REG(addr, val);
+}
+
+int meson_drm_rdma_write_reg_bits(u32 addr, u32 val, u32 start, u32 len)
+{
+ return VSYNCOSD_WR_MPEG_REG(addr, val, start, len);
+}
+
+int meson_drm_rdma_set_reg_mask(u32 addr, u32 mask)
+{
+ return VSYNCOSD_SET_MPEG_REG_MASK(addr, mask);
+}
+
+int meson_drm_rdma_clr_reg_mask(u32 addr, u32 mask)
+{
+ return VSYNCOSD_CLR_MPEG_REG_MASK(addr, mask);
+}
+
+int meson_drm_rdma_irq_write_reg(u32 addr, u32 val)
+{
+ return VSYNCOSD_IRQ_WR_MPEG_REG(addr, val);
+}
+
+/** reg direct access without rdma **/
+
+u32 meson_drm_read_reg(u32 addr)
+{
+ int ret;
+ u32 val;
+
+ ret = aml_reg_read(IO_VAPB_BUS_BASE, addr << 2, &val);
+
+ if (ret) {
+ pr_err("read vcbus reg %x error %d\n", addr, ret);
+ return -1;
+ }
+ return val;
+}
+
+int meson_drm_write_reg(u32 addr, u32 val)
+{
+ int ret;
+
+ ret = aml_reg_write(IO_VAPB_BUS_BASE, addr << 2, val);
+
+ if (ret) {
+ pr_err("write vcbus reg %x error %d\n", addr, ret);
+ return -1;
+ }
+ return 0;
+}
+
+int meson_drm_write_reg_bits(u32 addr, u32 val, u32 start, u32 len)
+{
+ int ret;
+ u32 raw_val;
+
+ ret = aml_reg_read(IO_VAPB_BUS_BASE, addr << 2, &raw_val);
+ if (ret) {
+ pr_err("read vcbus reg %x error %d\n", addr, ret);
+ return -1;
+ }
+
+ raw_val |= val & GENMASK(start, start + len);
+
+ ret = aml_reg_write(IO_VAPB_BUS_BASE, addr << 2, raw_val);
+ if (ret) {
+ pr_err("write vcbus reg %x error %d\n", addr, ret);
+ return -1;
+ }
+ return 0;
+}
+
+int meson_drm_set_reg_mask(u32 addr, u32 mask)
+{
+ int ret;
+ u32 raw_val;
+
+ ret = aml_reg_read(IO_VAPB_BUS_BASE, addr << 2, &raw_val);
+ if (ret) {
+ pr_err("read vcbus reg %x error %d\n", addr, ret);
+ return -1;
+ }
+
+ raw_val |= mask;
+
+ ret = aml_reg_write(IO_VAPB_BUS_BASE, addr << 2, raw_val);
+ if (ret) {
+ pr_err("write vcbus reg %x error %d\n", addr, ret);
+ return -1;
+ }
+ return 0;
+}
+
+int meson_drm_clr_reg_mask(u32 addr, u32 mask)
+{
+ int ret;
+ u32 raw_val;
+
+ ret = aml_reg_read(IO_VAPB_BUS_BASE, addr << 2, &raw_val);
+ if (ret) {
+ pr_err("read vcbus reg %x error %d\n", addr, ret);
+ return -1;
+ }
+
+ raw_val &= ~mask;
+
+ ret = aml_reg_write(IO_VAPB_BUS_BASE, addr << 2, raw_val);
+ if (ret) {
+ pr_err("write vcbus reg %x error %d\n", addr, ret);
+ return -1;
+ }
+ return 0;
+}
+
+/** canvas config **/
+
+void meson_drm_canvas_config(u32 index, unsigned long addr, u32 width,
+ u32 height, u32 wrap, u32 blkmode)
+{
+ canvas_config(index, addr, width, height, wrap, blkmode, 0);
+}
+
+int meson_drm_canvas_pool_alloc_table(const char *owner, u32 *table, int size,
+ enum canvas_map_type_e type)
+{
+ return canvas_pool_alloc_canvas_table(owner, table, size, type);
+}
+
+/** vpu clk and block power domain **/
+unsigned int meson_drm_vpu_get_clk(void)
+{
+ return get_vpu_clk();
+}
+
+unsigned int meson_drm_vpu_get_hwblk_clk(unsigned int vmode)
+{
+ return get_vpu_clk_vmode(vmode);
+}
+
+void meson_drm_vpu_set_hwblk_pd(unsigned int vmode, int flag)
+{
+ switch_vpu_mem_pd_vmode(vmode, flag);
+}
+
+int meson_drm_vpu_get_hwblk_pd(unsigned int vmode)
+{
+ return get_vpu_mem_pd_vmode(vmode);
+}
diff --git a/drivers/amlogic/drm/meson_vpu_util.h b/drivers/amlogic/drm/meson_vpu_util.h
new file mode 100644
index 0000000..8c52df5
--- a/dev/null
+++ b/drivers/amlogic/drm/meson_vpu_util.h
@@ -0,0 +1,62 @@
+/*
+ * drivers/amlogic/drm/meson_vpu_util.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __MESON_VPU_UTIL_H
+#define __MESON_VPU_UTIL_H
+
+#include <linux/types.h>
+#include <linux/amlogic/media/canvas/canvas.h>
+#include <linux/amlogic/media/canvas/canvas_mgr.h>
+#include <linux/amlogic/media/vpu/vpu.h>
+#include "osd_rdma.h"
+#include "osd.h"
+
+/*osd internal channel*/
+enum din_channel_e {
+ DIN0 = 0,
+ DIN1,
+ DIN2,
+ DIN3
+};
+
+struct osd_scope_s {
+ u32 h_start;
+ u32 h_end;
+ u32 v_start;
+ u32 v_end;
+};
+
+u32 meson_util_rdma_read_reg(u32 addr);
+int meson_util_rdma_write_reg(u32 addr, u32 val);
+int meson_util_rdma_write_reg_bits(u32 addr, u32 val, u32 start, u32 len);
+int meson_util_rdma_set_reg_mask(u32 addr, u32 mask);
+int meson_util_rdma_clr_reg_mask(u32 addr, u32 mask);
+int meson_util_rdma_irq_write_reg(u32 addr, u32 val);
+
+void meson_util_canvas_config(u32 index, unsigned long addr, u32 width,
+ u32 height, u32 wrap, u32 blkmode);
+int meson_util_canvas_pool_alloc_table(const char *owner, u32 *table, int size,
+ enum canvas_map_type_e type);
+
+unsigned int meson_util_vpu_get_clk(void);
+unsigned int meson_util_vpu_get_hwblk_clk(unsigned int vmode);
+void meson_util_vpu_set_hwblk_pd(unsigned int vmode, int flag);
+int meson_util_vpu_get_hwblk_pd(unsigned int vmode);
+
+extern const struct color_bit_define_s default_color_format_array_1[];
+
+#endif
diff --git a/drivers/amlogic/drm/vpu-hw/meson_osd_afbc.c b/drivers/amlogic/drm/vpu-hw/meson_osd_afbc.c
new file mode 100644
index 0000000..6fbec27
--- a/dev/null
+++ b/drivers/amlogic/drm/vpu-hw/meson_osd_afbc.c
@@ -0,0 +1,626 @@
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_osd_afbc.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include "meson_vpu_pipeline.h"
+#include "meson_vpu_reg.h"
+#include "meson_vpu_util.h"
+#include "osd.h"
+
+/* osd_mafbc_irq_clear& irq_mask */
+#define OSD_MAFBC_SURFACES_COMPLETED BIT(0)
+#define OSD_MAFBC_CONFI_SWAPPED BIT(1)
+#define OSD_MAFBC_DECODE_ERROR BIT(2)
+#define OSD_MAFBC_DETILING_ERROR BIT(3)
+#define OSD_MAFBC_AXI_ERROR BIT(4)
+#define OSD_MAFBC_SECURE_ID_ERROR BIT(5)
+
+/* osd_mafbc_command */
+#define OSD_MAFBC_DIRECT_SWAP
+#define OSD_MAFBC_PENDING_SWAP
+
+/* osd_mafbc_surface_cfg */
+#define OSD_MAFBC_S0_ENABLE BIT(0)
+#define OSD_MAFBC_S1_ENABLE BIT(1)
+#define OSD_MAFBC_S2_ENABLE BIT(2)
+#define OSD_MAFBC_S3_ENABLE BIT(3)
+#define OSD_MAFBC_DECODE_ENABLE BIT(16)
+
+/* osd_mafbc_axi_cfg */
+#define OSD_MAFBC_AXI_QOS(val) FIELD_PREP(GENMASK(3, 0), val)
+#define OSD_MAFBC_AXI_CACHE(val) FIELD_PREP(GENMASK(7, 4), val)
+
+/* osd_mafbc_format_specifier */
+#define OSD_MAFBC_PIXEL_FORMAT(val) FIELD_PREP(GENMASK(3, 0), val)
+#define OSD_MAFBC_YUV_TRANSFORM BIT(8)
+#define OSD_MAFBC_BLOCK_SPLIT BIT(9)
+#define OSD_MAFBC_SUPER_BLOCK_ASPECT(val) \
+ FIELD_PREP(GENMASK(17, 16), val)
+#define OSD_MAFBC_TILED_HEADER_EN BIT(18)
+#define OSD_MAFBC_PAYLOAD_LIMIT_EN BIT(19)
+
+/* osd_mafbc_prefetch_cfg */
+#define OSD_MAFBC_PREFETCH_READ_DIR_X BIT(0)
+#define OSD_MAFBC_PREFETCH_READ_DIR_Y BIT(1)
+
+static int afbc_pix_format(u32 fmt_mode)
+{
+ u32 pix_format = RGBA8888;
+
+ switch (fmt_mode) {
+ case COLOR_INDEX_YUV_422:
+ pix_format = YUV422_8B;
+ break;
+ case COLOR_INDEX_16_565:
+ pix_format = RGB565;
+ break;
+ case COLOR_INDEX_16_1555_A:
+ pix_format = RGBA5551;
+ break;
+ case COLOR_INDEX_16_4444_R:
+ case COLOR_INDEX_16_4444_A:
+ pix_format = RGBA4444;
+ break;
+ case COLOR_INDEX_32_BGRX:
+ case COLOR_INDEX_32_XBGR:
+ case COLOR_INDEX_32_RGBX:
+ case COLOR_INDEX_32_XRGB:
+ case COLOR_INDEX_32_BGRA:
+ case COLOR_INDEX_32_ABGR:
+ case COLOR_INDEX_32_RGBA:
+ case COLOR_INDEX_32_ARGB:
+ pix_format = RGBA8888;
+ break;
+ case COLOR_INDEX_24_888_B:
+ case COLOR_INDEX_24_RGB:
+ pix_format = RGB888;
+ break;
+ case COLOR_INDEX_RGBA_1010102:
+ pix_format = RGBA1010102;
+ break;
+ default:
+ osd_log_err("unsupport fmt:%x\n", fmt_mode);
+ break;
+ }
+ return pix_format;
+}
+
+static u32 line_stride_calc_afbc(
+ u32 fmt_mode,
+ u32 hsize,
+ u32 stride_align_32bytes)
+{
+ u32 line_stride = 0;
+
+ switch (fmt_mode) {
+ case R8:
+ line_stride = ((hsize << 3) + 127) >> 7;
+ break;
+ case YUV422_8B:
+ case RGB565:
+ case RGBA5551:
+ case RGBA4444:
+ line_stride = ((hsize << 4) + 127) >> 7;
+ break;
+ case RGBA8888:
+ case RGB888:
+ case YUV422_10B:
+ case RGBA1010102:
+ line_stride = ((hsize << 5) + 127) >> 7;
+ break;
+ }
+ /* need wr ddr is 32bytes aligned */
+ if (stride_align_32bytes)
+ line_stride = ((line_stride+1) >> 1) << 1;
+ else
+ line_stride = line_stride;
+ return line_stride;
+}
+
+static void osd_afbc_enable(u32 osd_index, bool flag)
+{
+ if (flag) {
+
+ VSYNCOSD_WR_MPEG_REG_BITS(
+ VPU_MAFBC_SURFACE_CFG,
+ 1, osd_index, 1);
+ VSYNCOSD_WR_MPEG_REG(
+ VPU_MAFBC_IRQ_MASK, 0xf);
+ } else
+ VSYNCOSD_WR_MPEG_REG_BITS(
+ VPU_MAFBC_SURFACE_CFG,
+ 0, osd_index, 1);
+}
+
+static int afbc_check_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ struct meson_vpu_afbc *afbc = to_afbc_block(vblk);
+
+ //vpu_block_check_input(vblk, state, mvps);
+
+ if (state->checked)
+ return 0;
+
+ state->checked = true;
+
+ DRM_DEBUG("%s check_state called.\n", afbc->base.name);
+
+ return 0;
+}
+
+static void osd1_afbc_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ u32 pixel_format, line_stride, output_stride;
+ u32 plane_index, osd_index;
+ u64 header_addr, out_addr;
+ u32 aligned_32, afbc_color_reorder;
+ unsigned int depth;
+ int bpp;
+ struct meson_vpu_afbc *afbc;
+ struct meson_vpu_afbc_state *afbc_state;
+ struct meson_vpu_osd_layer_info *plane_info;
+ struct meson_vpu_pipeline *pipeline;
+ struct meson_vpu_pipeline_state *pipeline_state;
+
+ afbc = to_afbc_block(vblk);
+ afbc_state = to_afbc_state(state);
+ pipeline = vblk->pipeline;
+ osd_index = vblk->index;
+ pipeline_state = priv_to_pipeline_state(pipeline->obj.state);
+ plane_index = pipeline_state->ratio_plane_index[osd_index];
+ plane_info = &pipeline_state->plane_info[plane_index];
+
+ if (!plane_info->afbc_en)
+ return;
+
+ osd_afbc_enable(0, 1);
+
+ aligned_32 = 1;
+ afbc_color_reorder = 0x1234;
+ pixel_format = afbc_pix_format(plane_info->pixel_format);
+ drm_fb_get_bpp_depth(plane_info->pixel_format, &depth, &bpp);
+ header_addr = plane_info->phy_addr;
+
+ line_stride = line_stride_calc_afbc(pixel_format,
+ plane_info->src_w, aligned_32);
+
+ output_stride = plane_info->src_w * bpp;
+
+ header_addr = plane_info->phy_addr;
+ out_addr = ((u64)(vblk->index + 1)) << 24;
+
+ /* set osd path misc ctrl */
+ VSYNCOSD_WR_MPEG_REG_BITS(OSD_PATH_MISC_CTRL, 0x1, (osd_index + 4), 1);
+
+ /* set linear addr */
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_CTRL_STAT, 0x1, 2, 1);
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_CTRL_STAT2, 1, 1, 1);
+
+ /* set read from mali */
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_BLK0_CFG_W0, 0x1, 30, 1);
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_BLK0_CFG_W0, 0, 15, 1);
+
+ /* set line_stride */
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_BLK2_CFG_W4, line_stride, 0, 12);
+
+ /* set frame addr */
+ VSYNCOSD_WR_MPEG_REG(VIU_OSD1_BLK1_CFG_W4, out_addr & 0xffffffff);
+
+ /* set afbc color reorder and mali src*/
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_MALI_UNPACK_CTRL,
+ afbc_color_reorder, 0, 16);
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD1_MALI_UNPACK_CTRL, 0x1, 31, 1);
+
+ /* set header addr */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_HEADER_BUF_ADDR_LOW_S0,
+ header_addr & 0xffffffff);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S0,
+ (header_addr >> 32) & 0xffffffff);
+
+ /* set format specifier */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_FORMAT_SPECIFIER_S0,
+ plane_info->afbc_inter_format | (pixel_format & 0x0f));
+
+ /* set pic size */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BUFFER_WIDTH_S0, plane_info->src_w);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BUFFER_HEIGHT_S0, plane_info->src_h);
+
+ /* set buf stride */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_STRIDE_S0, output_stride);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S0,
+ out_addr & 0xffffffff);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S0,
+ (out_addr >> 32) & 0xffffffff);
+
+ /* set bounding box */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_X_START_S0,
+ plane_info->src_x);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_X_END_S0,
+ (plane_info->src_x + plane_info->src_w - 1));
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_Y_START_S0,
+ plane_info->src_y);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_Y_END_S0,
+ (plane_info->src_y + plane_info->src_h - 1));
+
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_COMMAND, 1);
+
+ DRM_DEBUG("%s set_state called.\n", afbc->base.name);
+}
+
+static void osd2_afbc_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ u32 pixel_format, line_stride, output_stride;
+ u32 plane_index, osd_index;
+ u64 header_addr, out_addr;
+ u32 aligned_32, afbc_color_reorder;
+ unsigned int depth;
+ int bpp;
+ struct meson_vpu_afbc *afbc;
+ struct meson_vpu_afbc_state *afbc_state;
+ struct meson_vpu_osd_layer_info *plane_info;
+ struct meson_vpu_pipeline *pipeline;
+ struct meson_vpu_pipeline_state *pipeline_state;
+
+ afbc = to_afbc_block(vblk);
+ afbc_state = to_afbc_state(state);
+ pipeline = vblk->pipeline;
+ osd_index = vblk->index;
+ pipeline_state = priv_to_pipeline_state(pipeline->obj.state);
+ plane_index = pipeline_state->ratio_plane_index[osd_index];
+ plane_info = &pipeline_state->plane_info[plane_index];
+
+ if (!plane_info->afbc_en)
+ return;
+
+ osd_afbc_enable(1, 1);
+
+ aligned_32 = 1;
+ afbc_color_reorder = 0x1234;
+ pixel_format = afbc_pix_format(plane_info->pixel_format);
+ drm_fb_get_bpp_depth(plane_info->pixel_format, &depth, &bpp);
+ header_addr = plane_info->phy_addr;
+
+ line_stride = line_stride_calc_afbc(pixel_format,
+ plane_info->src_w, aligned_32);
+
+ output_stride = plane_info->src_w * bpp;
+
+ header_addr = plane_info->phy_addr;
+ out_addr = ((u64)(vblk->index + 1)) << 24;
+
+ /* set osd path misc ctrl */
+ VSYNCOSD_WR_MPEG_REG_BITS(OSD_PATH_MISC_CTRL, 0x1, (osd_index + 4), 1);
+
+ /* set linear addr */
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_CTRL_STAT, 0x1, 2, 1);
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_CTRL_STAT2, 1, 1, 1);
+
+ /* set read from mali */
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_BLK0_CFG_W0, 0x1, 30, 1);
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_BLK0_CFG_W0, 0, 15, 1);
+
+ /* set line_stride */
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_BLK2_CFG_W4, line_stride, 0, 12);
+
+ /* set frame addr */
+ VSYNCOSD_WR_MPEG_REG(VIU_OSD2_BLK1_CFG_W4, out_addr & 0xffffffff);
+
+ /* set afbc color reorder and mali src*/
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_MALI_UNPACK_CTRL,
+ afbc_color_reorder, 0, 16);
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD2_MALI_UNPACK_CTRL, 0x1, 31, 1);
+
+ /* set header addr */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_HEADER_BUF_ADDR_LOW_S1,
+ header_addr & 0xffffffff);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S1,
+ (header_addr >> 32) & 0xffffffff);
+
+ /* set format specifier */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_FORMAT_SPECIFIER_S1,
+ plane_info->afbc_inter_format | (pixel_format & 0x0f));
+
+ /* set pic size */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BUFFER_WIDTH_S1, plane_info->src_w);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BUFFER_HEIGHT_S1, plane_info->src_h);
+
+ /* set buf stride */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_STRIDE_S1, output_stride);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S1,
+ out_addr & 0xffffffff);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S1,
+ (out_addr >> 32) & 0xffffffff);
+
+ /* set bounding box */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_X_START_S1,
+ plane_info->src_x);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_X_END_S1,
+ (plane_info->src_x + plane_info->src_w - 1));
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_Y_START_S1,
+ plane_info->src_y);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_Y_END_S1,
+ (plane_info->src_y + plane_info->src_h - 1));
+
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_COMMAND, 1);
+
+ DRM_DEBUG("%s set_state called.\n", afbc->base.name);
+}
+
+static void osd3_afbc_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ u32 pixel_format, line_stride, output_stride;
+ u32 plane_index, osd_index;
+ u64 header_addr, out_addr;
+ u32 aligned_32, afbc_color_reorder;
+ unsigned int depth;
+ int bpp;
+ struct meson_vpu_afbc *afbc;
+ struct meson_vpu_afbc_state *afbc_state;
+ struct meson_vpu_osd_layer_info *plane_info;
+ struct meson_vpu_pipeline *pipeline;
+ struct meson_vpu_pipeline_state *pipeline_state;
+
+ afbc = to_afbc_block(vblk);
+ afbc_state = to_afbc_state(state);
+ pipeline = vblk->pipeline;
+ osd_index = vblk->index;
+ pipeline_state = priv_to_pipeline_state(pipeline->obj.state);
+ plane_index = pipeline_state->ratio_plane_index[osd_index];
+ plane_info = &pipeline_state->plane_info[plane_index];
+
+ if (!plane_info->afbc_en)
+ return;
+
+ osd_afbc_enable(2, 1);
+
+ aligned_32 = 1;
+ afbc_color_reorder = 0x1234;
+ pixel_format = afbc_pix_format(plane_info->pixel_format);
+ drm_fb_get_bpp_depth(plane_info->pixel_format, &depth, &bpp);
+ header_addr = plane_info->phy_addr;
+
+ line_stride = line_stride_calc_afbc(pixel_format,
+ plane_info->src_w, aligned_32);
+
+ output_stride = plane_info->src_w * bpp;
+
+ header_addr = plane_info->phy_addr;
+ out_addr = ((u64)(vblk->index + 1)) << 24;
+
+ /* set osd path misc ctrl */
+ VSYNCOSD_WR_MPEG_REG_BITS(OSD_PATH_MISC_CTRL, 0x1, (osd_index + 4), 1);
+
+ /* set linear addr */
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_CTRL_STAT, 0x1, 2, 1);
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_CTRL_STAT2, 1, 1, 1);
+
+ /* set read from mali */
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_BLK0_CFG_W0, 0x1, 30, 1);
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_BLK0_CFG_W0, 0, 15, 1);
+
+ /* set line_stride */
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_BLK2_CFG_W4, line_stride, 0, 12);
+
+ /* set frame addr */
+ VSYNCOSD_WR_MPEG_REG(VIU_OSD3_BLK1_CFG_W4, out_addr & 0xffffffff);
+
+ /* set afbc color reorder and mali src*/
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_MALI_UNPACK_CTRL,
+ afbc_color_reorder, 0, 16);
+ VSYNCOSD_WR_MPEG_REG_BITS(VIU_OSD3_MALI_UNPACK_CTRL, 0x1, 31, 1);
+
+ /* set header addr */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_HEADER_BUF_ADDR_LOW_S2,
+ header_addr & 0xffffffff);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S2,
+ (header_addr >> 32) & 0xffffffff);
+
+ /* set format specifier */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_FORMAT_SPECIFIER_S2,
+ plane_info->afbc_inter_format | (pixel_format & 0x0f));
+
+ /* set pic size */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BUFFER_WIDTH_S2, plane_info->src_w);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BUFFER_HEIGHT_S2, plane_info->src_h);
+
+ /* set buf stride */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_STRIDE_S2, output_stride);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S2,
+ out_addr & 0xffffffff);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S2,
+ (out_addr >> 32) & 0xffffffff);
+
+ /* set bounding box */
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_X_START_S2,
+ plane_info->src_x);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_X_END_S2,
+ (plane_info->src_x + plane_info->src_w - 1));
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_Y_START_S2,
+ plane_info->src_y);
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_BOUNDING_BOX_Y_END_S2,
+ (plane_info->src_y + plane_info->src_h - 1));
+
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_COMMAND, 1);
+
+ DRM_DEBUG("%s set_state called.\n", afbc->base.name);
+}
+
+#if 0
+static void osd_afbc_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ u32 bpp, pixel_format, line_stride, output_stride;
+ u32 plane_index, osd_index;
+ u64 header_addr, out_addr;
+ const struct color_bit_define_s *color_info;
+ struct meson_vpu_afbc *afbc;
+ struct meson_vpu_afbc_state *afbc_state;
+ struct meson_vpu_osd_layer_info *plane_info;
+ struct meson_vpu_pipeline *pipeline;
+ struct meson_vpu_pipeline_state *pipeline_state;
+ struct hw_osd_reg_s *osd_reg = &hw_osd_reg_array[index];
+
+ afbc = to_afbc_block(vblk);
+ afbc_state = to_afbc_state(state);
+ pipeline = vblk->pipeline;
+ osd_index = vblk->index;
+ pipeline_state = priv_to_pipeline_state(pipeline->obj.state);
+ plane_index = pipeline_state->ratio_plane_index[osd_index];
+ plane_info = pipeline_state->plane_info[plane_index];
+
+ u32 aligned_32 = 1;
+ u32 afbc_color_reorder = 0x1234;
+
+ pixel_format = afbc_pix_format(plane_info->pixel_format);
+ color_info = convert_panel_format(pixel_format);
+ header_addr = plane_info->phy_addr;
+
+ bpp = color_info->bpp >> 3;
+ line_stride = line_stride_calc_afbc(pixel_format,
+ plane_info->src_w, aligned_32);
+
+ output_stride = plane_info->src_w * bpp;
+
+ header_addr = plane_info->phy_addr;
+ out_addr = ((u64)(vblk->index + 1)) << 24;
+
+ /* set osd path misc ctrl */
+ VSYNCOSD_WR_MPEG_REG_BITS(OSD_PATH_MISC_CTRL, 0x1, (osd_index + 4), 1);
+
+ /* set linear addr */
+ VSYNCOSD_WR_MPEG_REG_BITS(osd_reg->osd_ctrl_stat, 0x1, 2, 1);
+
+ /* set read from mali */
+ VSYNCOSD_WR_MPEG_REG_BITS(osd_reg->osd_blk0_cfg_w0, 0x1, 30, 1);
+ VSYNCOSD_WR_MPEG_REG_BITS(osd_reg->osd_blk0_cfg_w0, 0, 15, 1);
+
+ /* set line_stride */
+ VSYNCOSD_WR_MPEG_REG_BITS(osd_reg->osd_blk2_cfg_w4, line_stride, 0, 12);
+
+ /* set frame addr */
+ VSYNCOSD_WR_MPEG_REG(osd_reg->osd_blk1_cfg_w4, out_addr & 0xffffffff);
+
+ /* set afbc color reorder and mali src*/
+ VSYNCOSD_WR_MPEG_REG_BITS(osd_reg->osd_mali_unpack_ctrl,
+ afbc_color_reorder, 0, 16);
+ VSYNCOSD_WR_MPEG_REG_BITS(osd_reg->osd_mali_unpack_ctrl, 0x1, 31, 1);
+
+ /* set header addr */
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_header_buf_addr_low_s,
+ out_addr & 0xffffffff);
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_header_buf_addr_high_s,
+ (out_addr >> 32) & 0xffffffff);
+
+ /* set format specifier */
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_format_specifier_s,
+ plane_info->inter_format | (pixel_format & 0x0f));
+
+ /* set pic size */
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_buffer_width_s, plane_info->src_w);
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_buffer_hight_s, plane_info->src_h);
+
+ /* set buf stride */
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_output_buf_stride_s, output_stride);
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_output_buf_addr_low_s,
+ out_addr & 0xffffffff);
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_output_buf_addr_high_s,
+ (out_addr >> 32) & 0xffffffff);
+
+ /* set bounding box */
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_boundings_box_x_start_s,
+ plane_info->src_x);
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_boundings_box_x_end_s,
+ (palne_info->src_x + plane_info->src_w - 1));
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_boundings_box_y_start_s,
+ plane_info->src_y);
+ VSYNCOSD_WR_MPEG_REG(osd_reg->afbc_boundings_box_y_end_s,
+ (plane_info->src_y + plane_info->src_h - 1));
+
+ VSYNCOSD_WR_MPEG_REG(VPU_MAFBC_COMMAND, 1);
+
+ DRM_DEBUG("%s set_state called.\n", afbc->base.name);
+}
+#endif
+
+static void afbc_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+#if 0
+ osd_afbc_set_state(vblk, state);
+#else
+ switch (vblk->index) {
+ case 0:
+ osd1_afbc_set_state(vblk, state);
+ break;
+ case 1:
+ osd2_afbc_set_state(vblk, state);
+ break;
+ case 2:
+ osd3_afbc_set_state(vblk, state);
+ break;
+ default:
+ break;
+ }
+#endif
+
+}
+
+static void afbc_hw_enable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_afbc *afbc = to_afbc_block(vblk);
+ u32 osd_index = vblk->index;
+
+ osd_afbc_enable(osd_index, 1);
+
+ DRM_DEBUG("%s enable called.\n", afbc->base.name);
+}
+
+static void afbc_hw_disable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_afbc *afbc = to_afbc_block(vblk);
+ u32 osd_index = vblk->index;
+
+ osd_afbc_enable(osd_index, 0);
+
+ DRM_DEBUG("%s disable called.\n", afbc->base.name);
+}
+
+static void afbc_hw_init(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_afbc *afbc = to_afbc_block(vblk);
+
+ switch_vpu_mem_pd_vmod(VPU_MAIL_AFBCD,
+ VPU_MEM_POWER_ON);
+ /* disable osd1 afbc */
+ osd_afbc_enable(0, 0);
+ osd_afbc_enable(1, 0);
+ osd_afbc_enable(2, 0);
+
+ DRM_DEBUG("%s hw_init called.\n", afbc->base.name);
+}
+
+struct meson_vpu_block_ops afbc_ops = {
+ .check_state = afbc_check_state,
+ .update_state = afbc_set_state,
+ .enable = afbc_hw_enable,
+ .disable = afbc_hw_disable,
+ .init = afbc_hw_init,
+};
diff --git a/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c b/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c
new file mode 100644
index 0000000..64eadf8
--- a/dev/null
+++ b/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c
@@ -0,0 +1,616 @@
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include "meson_vpu_pipeline.h"
+#include "meson_vpu_reg.h"
+#include "meson_vpu_util.h"
+#include "meson_osd_scaler.h"
+
+static struct osd_scaler_reg_s osd_scaler_reg[HW_OSD_SCALER_NUM] = {
+ {
+ VPP_OSD_SCALE_COEF_IDX,
+ VPP_OSD_SCALE_COEF,
+ VPP_OSD_VSC_PHASE_STEP,
+ VPP_OSD_VSC_INI_PHASE,
+ VPP_OSD_VSC_CTRL0,
+ VPP_OSD_HSC_PHASE_STEP,
+ VPP_OSD_HSC_INI_PHASE,
+ VPP_OSD_HSC_CTRL0,
+ VPP_OSD_HSC_INI_PAT_CTRL,
+ VPP_OSD_SC_DUMMY_DATA,
+ VPP_OSD_SC_CTRL0,
+ VPP_OSD_SCI_WH_M1,
+ VPP_OSD_SCO_H_START_END,
+ VPP_OSD_SCO_V_START_END,
+ },
+ {
+ OSD2_SCALE_COEF_IDX,
+ OSD2_SCALE_COEF,
+ OSD2_VSC_PHASE_STEP,
+ OSD2_VSC_INI_PHASE,
+ OSD2_VSC_CTRL0,
+ OSD2_HSC_PHASE_STEP,
+ OSD2_HSC_INI_PHASE,
+ OSD2_HSC_CTRL0,
+ OSD2_HSC_INI_PAT_CTRL,
+ OSD2_SC_DUMMY_DATA,
+ OSD2_SC_CTRL0,
+ OSD2_SCI_WH_M1,
+ OSD2_SCO_H_START_END,
+ OSD2_SCO_V_START_END,
+ },
+ {
+ OSD34_SCALE_COEF_IDX,
+ OSD34_SCALE_COEF,
+ OSD34_VSC_PHASE_STEP,
+ OSD34_VSC_INI_PHASE,
+ OSD34_VSC_CTRL0,
+ OSD34_HSC_PHASE_STEP,
+ OSD34_HSC_INI_PHASE,
+ OSD34_HSC_CTRL0,
+ OSD34_HSC_INI_PAT_CTRL,
+ OSD34_SC_DUMMY_DATA,
+ OSD34_SC_CTRL0,
+ OSD34_SCI_WH_M1,
+ OSD34_SCO_H_START_END,
+ OSD34_SCO_V_START_END,
+ }
+};
+
+static unsigned int __osd_filter_coefs_bicubic[] = { /* bicubic coef0 */
+ 0x00800000, 0x007f0100, 0xff7f0200, 0xfe7f0300, 0xfd7e0500, 0xfc7e0600,
+ 0xfb7d0800, 0xfb7c0900, 0xfa7b0b00, 0xfa7a0dff, 0xf9790fff, 0xf97711ff,
+ 0xf87613ff, 0xf87416fe, 0xf87218fe, 0xf8701afe, 0xf76f1dfd, 0xf76d1ffd,
+ 0xf76b21fd, 0xf76824fd, 0xf76627fc, 0xf76429fc, 0xf7612cfc, 0xf75f2ffb,
+ 0xf75d31fb, 0xf75a34fb, 0xf75837fa, 0xf7553afa, 0xf8523cfa, 0xf8503ff9,
+ 0xf84d42f9, 0xf84a45f9, 0xf84848f8
+};
+
+/*********vsc config begin**********/
+/*vsc phase_step=(v_in << 20)/v_out */
+void osd_vsc_phase_step_set(struct osd_scaler_reg_s *reg, u32 phase_step)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_phase_step,
+ phase_step, 0, 28);
+}
+/*vsc init phase*/
+void osd_vsc_init_phase_set(struct osd_scaler_reg_s *reg,
+ u32 bottom_init_phase, u32 top_init_phase)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_vsc_ini_phase,
+ (bottom_init_phase << 16) |
+ (top_init_phase << 0));
+}
+/*vsc control*/
+/*vsc enable last line repeate*/
+void osd_vsc_repate_last_line_enable_set(
+ struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, flag, 25, 1);
+}
+/*vsc enable*/
+void osd_vsc_enable_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, flag, 24, 1);
+}
+/*vsc input Interlaced or Progressive:0->P;1->I*/
+void osd_vsc_output_format_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, flag, 23, 1);
+}
+/*
+ *vsc double line mode
+ *bit0:change line buffer becomes 2 lines
+ *bit1:double input width and half input height
+ */
+void osd_vsc_double_line_mode_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, data, 21, 2);
+}
+/*vsc phase always on*/
+void osd_vsc_phase_always_on_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, flag, 20, 1);
+}
+/*vsc nearest en*/
+void osd_vsc_nearest_en_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, flag, 19, 1);
+}
+/*vsc repeate bottom field line0 num*/
+void osd_vsc_bot_rpt_l0_num_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, data, 16, 2);
+}
+/*vsc bottom field init receive num??*/
+void osd_vsc_bot_ini_rcv_num_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, data, 11, 4);
+}
+/*vsc repeate top field line0 num*/
+void osd_vsc_top_rpt_l0_num_set(struct osd_scaler_reg_s *reg, u32 flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, flag, 8, 2);
+}
+/*vsc top field init receive num??*/
+void osd_vsc_top_ini_rcv_num_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, data, 3, 4);
+}
+/*vsc bank length??*/
+void osd_vsc_bank_length_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_vsc_ctrl0, data, 0, 2);
+}
+/*********vsc config end**********/
+
+/*********hsc config begin**********/
+/*hsc phase_step=(v_in << 20)/v_out */
+void osd_hsc_phase_step_set(struct osd_scaler_reg_s *reg, u32 phase_step)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_phase_step,
+ phase_step, 0, 28);
+}
+/*vsc init phase*/
+void osd_hsc_init_phase_set(struct osd_scaler_reg_s *reg,
+ u32 init_phase0, u32 init_phase1)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_hsc_ini_phase,
+ (init_phase1 << 16) | (init_phase0 << 0));
+}
+/*hsc control*/
+/*hsc enable*/
+void osd_hsc_enable_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, flag, 22, 1);
+}
+/* hsc double pixel mode */
+void osd_hsc_double_line_mode_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, flag, 21, 1);
+}
+/*hsc phase always on*/
+void osd_hsc_phase_always_on_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, flag, 20, 1);
+}
+/*hsc nearest en*/
+void osd_hsc_nearest_en_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, flag, 19, 1);
+}
+/*hsc repeate pixel0 num1??*/
+void osd_hsc_rpt_p0_num1_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, data, 16, 2);
+}
+/*hsc init receive num1*/
+void osd_vsc_ini_rcv_num1_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, data, 11, 4);
+}
+/*hsc repeate pixel0 num0*/
+void osd_hsc_rpt_p0_num0_set(struct osd_scaler_reg_s *reg, u32 flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, flag, 8, 2);
+}
+/*hsc init receive num0*/
+void osd_hsc_ini_rcv_num0_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, data, 3, 4);
+}
+/*hsc bank length*/
+void osd_hsc_bank_length_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_hsc_ctrl0, data, 0, 2);
+}
+/*
+ *hsc init pattern
+ *[15:8]pattern
+ *[6:4]pattern start
+ *[2:0]pattern end
+ */
+void osd_hsc_ini_pat_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_hsc_ini_pat_ctrl, data);
+}
+/*********hsc config end**********/
+
+/*********sc top ctrl start**********/
+/*
+ *dummy data:
+ *[31:24]componet0
+ *[23:16]componet1
+ *[15:8]componet2
+ *[7:0]alpha
+ */
+void osd_sc_dummy_data_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_sc_dummy_data, data);
+}
+/*sc gate clock*/
+void osd_sc_gclk_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sc_ctrl0, data, 16, 12);
+}
+/*
+ *sc input data alpha mode
+ *0:(alpha>=128)?alpha-1:alpha
+ *1:(alpha>=1)?alpha-1:alpha
+ */
+void osd_sc_din_alpha_mode_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sc_ctrl0, flag, 13, 1);
+}
+/*
+ *sc output data alpha mode
+ *0:(alpha>=128)?alpha+1:alpha
+ *1:(alpha>=1)?alpha+1:alpha
+ */
+void osd_sc_dout_alpha_mode_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sc_ctrl0, flag, 12, 1);
+}
+/*sc alpha*/
+void osd_sc_alpha_set(struct osd_scaler_reg_s *reg, u32 data)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sc_ctrl0, data, 4, 8);
+}
+/*sc path en*/
+void osd_sc_path_en_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sc_ctrl0, flag, 3, 1);
+}
+/*sc en*/
+void osd_sc_en_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sc_ctrl0, flag, 2, 1);
+}
+/*sc input width minus 1*/
+void osd_sc_in_w_set(struct osd_scaler_reg_s *reg, u32 size)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sci_wh_m1, (size - 1), 16, 13);
+}
+/*sc input height minus 1*/
+void osd_sc_in_h_set(struct osd_scaler_reg_s *reg, u32 size)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->vpp_osd_sci_wh_m1, (size - 1), 0, 13);
+}
+/*sc output horizontal size = end - start + 1*/
+void osd_sc_out_horz_set(struct osd_scaler_reg_s *reg, u32 start, u32 end)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_sco_h_start_end,
+ (start & 0xfff << 16) | (end & 0xfff));
+}
+
+/*sc output vertical size = end - start + 1*/
+void osd_sc_out_vert_set(struct osd_scaler_reg_s *reg, u32 start, u32 end)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_sco_v_start_end,
+ (start & 0xfff << 16) | (end & 0xfff));
+}
+
+/*
+ *sc h/v coef
+ *1:config horizontal coef
+ *0:config vertical coef
+ */
+void osd_sc_coef_set(struct osd_scaler_reg_s *reg, bool flag)
+{
+ u8 i;
+
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_scale_coef_idx,
+ (0 << 15) |/*index increment. 1bits*/
+ (0 << 14) |/*read coef enable, 1bits*/
+ (0 << 9) |/*coef bit mode 8 or 9. 1bits*/
+ (flag << 8) |
+ (0 << 0)/*coef index 7bits*/);
+ for (i = 0; i < 33; i++)
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd_scale_coef,
+ __osd_filter_coefs_bicubic[i]);
+}
+/*********sc top ctrl end************/
+static void f2v_get_vertical_phase(
+ u32 zoom_ratio, enum f2v_vphase_type_e type,
+ u8 bank_length, struct f2v_vphase_s *vphase)
+{
+ u8 f2v_420_in_pos_luma[F2V_TYPE_MAX] = {
+ 0, 2, 0, 2, 0, 0, 0, 2, 0};
+ u8 f2v_420_out_pos[F2V_TYPE_MAX] = {
+ 0, 2, 2, 0, 0, 2, 0, 0, 0};
+ s32 offset_in, offset_out;
+
+ /* luma */
+ offset_in = f2v_420_in_pos_luma[type]
+ << OSD_PHASE_BITS;
+ offset_out = (f2v_420_out_pos[type] * zoom_ratio)
+ >> (OSD_ZOOM_HEIGHT_BITS - OSD_PHASE_BITS);
+
+ vphase->rcv_num = bank_length;
+ if (bank_length == 4 || bank_length == 3)
+ vphase->rpt_num = 1;
+ else
+ vphase->rpt_num = 0;
+
+ if (offset_in > offset_out) {
+ vphase->rpt_num = vphase->rpt_num + 1;
+ vphase->phase =
+ ((4 << OSD_PHASE_BITS) + offset_out - offset_in)
+ >> 2;
+ } else {
+ while ((offset_in + (4 << OSD_PHASE_BITS))
+ <= offset_out) {
+ if (vphase->rpt_num == 1)
+ vphase->rpt_num = 0;
+ else
+ vphase->rcv_num++;
+ offset_in += 4 << OSD_PHASE_BITS;
+ }
+ vphase->phase = (offset_out - offset_in) >> 2;
+ }
+}
+void osd_scaler_config(struct osd_scaler_reg_s *reg,
+ struct meson_vpu_scaler_state *scaler_state,
+ struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_scaler *scaler = to_scaler_block(vblk);
+ u32 phase_step_v, phase_step_h, vsc_top_init_rec_num, vsc_bank_length;
+ u32 hsc_init_rec_num, hsc_init_rpt_p0_num, hsc_bank_length;
+ u32 vsc_bot_init_rec_num, vsc_top_rpt_l0_num, vsc_bot_rpt_l0_num;
+ u32 vsc_top_init_phase, vsc_bot_init_phase;
+ struct f2v_vphase_s vphase;
+ u8 version = vblk->pipeline->osd_version;
+ u32 linebuffer = scaler->linebuffer;
+ u32 bank_length = scaler->bank_length;
+ u32 width_in = scaler_state->input_width;
+ u32 height_in = scaler_state->input_height;
+ u32 width_out = scaler_state->output_width;
+ u32 height_out = scaler_state->output_height;
+ u32 scan_mode_out = scaler_state->scan_mode_out;
+ bool scaler_enable;
+
+ if (width_in == width_out && height_in == height_out &&
+ version > OSD_V2)
+ scaler_enable = false;
+ else
+ scaler_enable = true;
+
+ if (width_out > linebuffer)
+ vsc_bank_length = bank_length >> 1;
+ else
+ vsc_bank_length = bank_length;
+ hsc_init_rec_num = bank_length;
+ hsc_bank_length = bank_length;
+ hsc_init_rpt_p0_num = bank_length / 2 - 1;
+
+ if (version <= OSD_V2)
+ phase_step_v = ((height_in - 1) << OSD_ZOOM_HEIGHT_BITS) /
+ height_out;
+ else
+ phase_step_v =
+ (height_in << OSD_ZOOM_HEIGHT_BITS) / height_out;
+ if (scan_mode_out) {
+ f2v_get_vertical_phase(phase_step_v, F2V_P2IT,
+ vsc_bank_length, &vphase);
+ vsc_top_init_rec_num = vphase.rcv_num;
+ vsc_top_rpt_l0_num = vphase.rpt_num;
+ vsc_top_init_phase = vphase.phase;
+ f2v_get_vertical_phase(phase_step_v, F2V_P2IB,
+ vsc_bank_length, &vphase);
+ vsc_bot_init_rec_num = vphase.rcv_num;
+ vsc_bot_rpt_l0_num = vphase.rpt_num;
+ vsc_bot_init_phase = vphase.phase;
+ } else {
+ f2v_get_vertical_phase(
+ phase_step_v, F2V_P2P,
+ vsc_bank_length, &vphase);
+ vsc_top_init_rec_num = vphase.rcv_num;
+ vsc_top_rpt_l0_num = vphase.rpt_num;
+ vsc_top_init_phase = vphase.phase;
+ vsc_bot_init_rec_num = 0;
+ vsc_bot_rpt_l0_num = 0;
+ vsc_bot_init_phase = 0;
+ }
+ if (version <= OSD_V2)
+ vsc_top_init_rec_num++;
+ if (version <= OSD_V2 && scan_mode_out)
+ vsc_bot_init_rec_num++;
+ phase_step_v <<= (OSD_ZOOM_TOTAL_BITS - OSD_ZOOM_HEIGHT_BITS);
+ phase_step_h = (width_in << OSD_ZOOM_WIDTH_BITS) / width_out;
+ phase_step_h <<= (OSD_ZOOM_TOTAL_BITS - OSD_ZOOM_WIDTH_BITS);
+
+ /*input size config*/
+ osd_sc_in_h_set(reg, height_in);
+ osd_sc_in_w_set(reg, width_in);
+
+ /*output size config*/
+ osd_sc_out_horz_set(reg, 0, width_out - 1);
+ osd_sc_out_vert_set(reg, 0, height_out - 1);
+
+ /*phase step config*/
+ osd_vsc_phase_step_set(reg, phase_step_v);
+ osd_hsc_phase_step_set(reg, phase_step_h);
+
+ /*dummy data config*/
+ osd_sc_dummy_data_set(reg, 0x80808080);
+
+ /*h/v coef config*/
+ osd_sc_coef_set(reg, 1);
+ osd_sc_coef_set(reg, 0);
+
+ /*init recv line num*/
+ osd_vsc_top_ini_rcv_num_set(reg, vsc_top_init_rec_num);
+ osd_vsc_bot_ini_rcv_num_set(reg, vsc_bot_init_rec_num);
+ osd_hsc_ini_rcv_num0_set(reg, hsc_init_rec_num);
+
+ /*repeate line0 num*/
+ osd_vsc_top_rpt_l0_num_set(reg, vsc_top_rpt_l0_num);
+ osd_vsc_bot_rpt_l0_num_set(reg, vsc_bot_rpt_l0_num);
+ osd_hsc_rpt_p0_num0_set(reg, hsc_init_rpt_p0_num);
+
+ /*init phase*/
+ osd_vsc_init_phase_set(reg, vsc_bot_init_phase, vsc_top_init_phase);
+ osd_hsc_init_phase_set(reg, 0, 0);
+
+ /*vsc bank length*/
+ osd_vsc_bank_length_set(reg, vsc_bank_length);
+ osd_hsc_bank_length_set(reg, hsc_bank_length);
+
+ /*out scan mode*/
+ osd_vsc_output_format_set(reg, scan_mode_out ? 1:0);
+
+ /*repeate last line*/
+ if (version >= OSD_V2)
+ osd_vsc_repate_last_line_enable_set(reg, 1);
+
+ /*eanble sc*/
+ osd_vsc_enable_set(reg, scaler_enable);
+ osd_hsc_enable_set(reg, scaler_enable);
+ osd_sc_en_set(reg, scaler_enable);
+ osd_sc_path_en_set(reg, scaler_enable);
+}
+
+static void scaler_size_check(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ struct meson_vpu_pipeline *pipeline = vblk->pipeline;
+ struct meson_vpu_pipeline_state *pipeline_state;
+ struct meson_vpu_scaler_state *scaler_state = to_scaler_state(state);
+
+ pipeline_state = priv_to_pipeline_state(pipeline->obj.state);
+ if (!pipeline_state) {
+ DRM_DEBUG("pipeline_state is NULL!!\n");
+ return;
+ }
+ if (scaler_state->input_width !=
+ pipeline_state->scaler_param[vblk->index].input_width) {
+ scaler_state->input_width =
+ pipeline_state->scaler_param[vblk->index].input_width;
+ scaler_state->state_changed |= SCALER_INPUT_WIDTH_CHANGED;
+ }
+ if (scaler_state->input_height !=
+ pipeline_state->scaler_param[vblk->index].input_height) {
+ scaler_state->input_height =
+ pipeline_state->scaler_param[vblk->index].input_height;
+ scaler_state->state_changed |= SCALER_INPUT_HEIGHT_CHANGED;
+ }
+ if (scaler_state->output_width !=
+ pipeline_state->scaler_param[vblk->index].output_width) {
+ scaler_state->output_width =
+ pipeline_state->scaler_param[vblk->index].output_width;
+ scaler_state->state_changed |= SCALER_OUTPUT_WIDTH_CHANGED;
+ }
+ if (scaler_state->output_height !=
+ pipeline_state->scaler_param[vblk->index].output_height) {
+ scaler_state->output_height =
+ pipeline_state->scaler_param[vblk->index].output_height;
+ scaler_state->state_changed |= SCALER_OUTPUT_HEIGHT_CHANGED;
+ }
+}
+
+void scan_mode_check(struct meson_vpu_pipeline *pipeline,
+ struct meson_vpu_scaler_state *scaler_state)
+{
+ u32 scan_mode_out = pipeline->mode.flags & DRM_MODE_FLAG_INTERLACE;
+
+ if (scaler_state->scan_mode_out != scan_mode_out) {
+ scaler_state->scan_mode_out = scan_mode_out;
+ scaler_state->state_changed |=
+ SCALER_OUTPUT_SCAN_MODE_CHANGED;
+ }
+}
+
+static int scaler_check_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ struct meson_vpu_scaler *scaler = to_scaler_block(vblk);
+
+ if (state->checked)
+ return 0;
+
+ state->checked = true;
+ DRM_DEBUG("%s check_state called.\n", scaler->base.name);
+
+ return 0;
+}
+
+static void scaler_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ struct meson_vpu_scaler *scaler = to_scaler_block(vblk);
+ struct meson_vpu_scaler_state *scaler_state = to_scaler_state(state);
+ struct osd_scaler_reg_s *reg = scaler->reg;
+
+ if (!scaler_state) {
+ DRM_DEBUG("scaler or scaler_state is NULL!!\n");
+ return;
+ }
+ scaler_size_check(vblk, state);
+ scan_mode_check(vblk->pipeline, scaler_state);
+ DRM_DEBUG("scaler_state=0x%x\n", scaler_state->state_changed);
+ if (scaler_state->state_changed) {
+ osd_scaler_config(reg, scaler_state, vblk);
+ scaler_state->state_changed = 0;
+ }
+ DRM_DEBUG("scaler%d input/output w/h[%d, %d, %d, %d].\n",
+ scaler->base.index,
+ scaler_state->input_width, scaler_state->input_height,
+ scaler_state->output_width, scaler_state->output_height);
+}
+
+static void scaler_hw_enable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_scaler *scaler = to_scaler_block(vblk);
+ struct osd_scaler_reg_s *reg = scaler->reg;
+
+ osd_sc_en_set(reg, 1);
+ osd_sc_path_en_set(reg, 1);
+ DRM_DEBUG("%s enable done.\n", scaler->base.name);
+}
+
+static void scaler_hw_disable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_scaler *scaler = to_scaler_block(vblk);
+ struct osd_scaler_reg_s *reg = scaler->reg;
+
+ /*disable sc*/
+ osd_sc_en_set(reg, 0);
+ osd_sc_path_en_set(reg, 0);
+ DRM_DEBUG("%s disable called.\n", scaler->base.name);
+}
+
+static void scaler_hw_init(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_scaler *scaler = to_scaler_block(vblk);
+
+ scaler->reg = &osd_scaler_reg[vblk->index];
+ scaler->linebuffer = OSD_SCALE_LINEBUFFER;
+ scaler->bank_length = OSD_SCALE_BANK_LENGTH;
+ /*disable sc*/
+ osd_sc_en_set(scaler->reg, 0);
+ osd_sc_path_en_set(scaler->reg, 0);
+ DRM_DEBUG("%s hw_init called.\n", scaler->base.name);
+}
+
+struct meson_vpu_block_ops scaler_ops = {
+ .check_state = scaler_check_state,
+ .update_state = scaler_set_state,
+ .enable = scaler_hw_enable,
+ .disable = scaler_hw_disable,
+ .init = scaler_hw_init,
+};
diff --git a/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h b/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h
new file mode 100644
index 0000000..34ebb03
--- a/dev/null
+++ b/drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h
@@ -0,0 +1,118 @@
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef _MESON_OSD_SCALER_H_
+#define _MESON_OSD_SCALER_H_
+
+#define HW_OSD_SCALER_NUM 3
+
+/*vpp osd scaler*/
+#define VPP_OSD_VSC_PHASE_STEP 0x1dc0
+#define VPP_OSD_VSC_INI_PHASE 0x1dc1
+#define VPP_OSD_VSC_CTRL0 0x1dc2
+#define VPP_OSD_HSC_PHASE_STEP 0x1dc3
+#define VPP_OSD_HSC_INI_PHASE 0x1dc4
+#define VPP_OSD_HSC_CTRL0 0x1dc5
+#define VPP_OSD_HSC_INI_PAT_CTRL 0x1dc6
+#define VPP_OSD_SC_DUMMY_DATA 0x1dc7
+#define VPP_OSD_SC_CTRL0 0x1dc8
+#define VPP_OSD_SCI_WH_M1 0x1dc9
+#define VPP_OSD_SCO_H_START_END 0x1dca
+#define VPP_OSD_SCO_V_START_END 0x1dcb
+#define VPP_OSD_SCALE_COEF_IDX 0x1dcc
+#define VPP_OSD_SCALE_COEF 0x1dcd
+
+/* vpp osd2 scaler */
+#define OSD2_VSC_PHASE_STEP 0x3d00
+#define OSD2_VSC_INI_PHASE 0x3d01
+#define OSD2_VSC_CTRL0 0x3d02
+#define OSD2_HSC_PHASE_STEP 0x3d03
+#define OSD2_HSC_INI_PHASE 0x3d04
+#define OSD2_HSC_CTRL0 0x3d05
+#define OSD2_HSC_INI_PAT_CTRL 0x3d06
+#define OSD2_SC_DUMMY_DATA 0x3d07
+#define OSD2_SC_CTRL0 0x3d08
+#define OSD2_SCI_WH_M1 0x3d09
+#define OSD2_SCO_H_START_END 0x3d0a
+#define OSD2_SCO_V_START_END 0x3d0b
+#define OSD2_SCALE_COEF_IDX 0x3d18
+#define OSD2_SCALE_COEF 0x3d19
+
+/* vpp osd34 scaler */
+#define OSD34_VSC_PHASE_STEP 0x3d20
+#define OSD34_VSC_INI_PHASE 0x3d21
+#define OSD34_VSC_CTRL0 0x3d22
+#define OSD34_HSC_PHASE_STEP 0x3d23
+#define OSD34_HSC_INI_PHASE 0x3d24
+#define OSD34_HSC_CTRL0 0x3d25
+#define OSD34_HSC_INI_PAT_CTRL 0x3d26
+#define OSD34_SC_DUMMY_DATA 0x3d27
+#define OSD34_SC_CTRL0 0x3d28
+#define OSD34_SCI_WH_M1 0x3d29
+#define OSD34_SCO_H_START_END 0x3d2a
+#define OSD34_SCO_V_START_END 0x3d2b
+#define OSD34_SCALE_COEF_IDX 0x3d1e
+#define OSD34_SCALE_COEF 0x3d1f
+
+
+/*macro define for chip const*/
+/*bank length is related to scale fifo:4 line 1920??*/
+#define OSD_SCALE_BANK_LENGTH 4
+#define OSD_SCALE_LINEBUFFER 1920
+
+#define OSD_ZOOM_WIDTH_BITS 18
+#define OSD_ZOOM_HEIGHT_BITS 20
+#define OSD_ZOOM_TOTAL_BITS 24
+#define OSD_PHASE_BITS 16
+
+enum f2v_vphase_type_e {
+ F2V_IT2IT = 0,
+ F2V_IB2IB,
+ F2V_IT2IB,
+ F2V_IB2IT,
+ F2V_P2IT,
+ F2V_P2IB,
+ F2V_IT2P,
+ F2V_IB2P,
+ F2V_P2P,
+ F2V_TYPE_MAX
+};
+
+struct f2v_vphase_s {
+ u8 rcv_num;
+ u8 rpt_num;
+ u16 phase;
+};
+
+struct osd_scaler_reg_s {
+ u32 vpp_osd_scale_coef_idx;
+ u32 vpp_osd_scale_coef;
+ u32 vpp_osd_vsc_phase_step;
+ u32 vpp_osd_vsc_ini_phase;
+ u32 vpp_osd_vsc_ctrl0;
+ u32 vpp_osd_hsc_phase_step;
+ u32 vpp_osd_hsc_ini_phase;
+ u32 vpp_osd_hsc_ctrl0;
+ u32 vpp_osd_hsc_ini_pat_ctrl;
+ u32 vpp_osd_sc_dummy_data;
+ u32 vpp_osd_sc_ctrl0;
+ u32 vpp_osd_sci_wh_m1;
+ u32 vpp_osd_sco_h_start_end;
+ u32 vpp_osd_sco_v_start_end;
+};
+
+#endif
diff --git a/drivers/amlogic/drm/am_meson_vpu.h b/drivers/amlogic/drm/vpu-hw/meson_vpu_dev.c
index 03adbbe..e279690 100644
--- a/drivers/amlogic/drm/am_meson_vpu.h
+++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_dev.c
@@ -1,5 +1,5 @@
/*
- * drivers/amlogic/drm/am_meson_vpu.h
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_dev.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
@@ -14,11 +14,23 @@
* more details.
*
*/
-#ifndef __AM_MESON_VPU_H
-#define __AM_MESON_VPU_H
-struct am_meson_vpu_data {
- uint32_t version;
+struct vpu_dev_func {
+ void (*hw_init)();
+ void (*hw_exit)();
};
-#endif /* __AM_MESON_VPU_H */
+static struct vpu_dev_func g12a = {
+ .hw_init = g12a_hw_init,
+ .hw_exit = g12a_hw_exit,
+};
+
+static struct vpu_dev_func g12b = {
+ .hw_init = g12b_hw_init,
+ .hw_exit = g12b_hw_exit,
+};
+
+static struct vpu_dev_func tl1 = {
+ .hw_init = tl1_hw_init,
+ .hw_exit = tl1_hw_exit,
+};
diff --git a/drivers/amlogic/drm/vpu-hw/meson_vpu_hdr_dv.c b/drivers/amlogic/drm/vpu-hw/meson_vpu_hdr_dv.c
new file mode 100644
index 0000000..39563bf
--- a/dev/null
+++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_hdr_dv.c
@@ -0,0 +1,110 @@
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_hdr_dv.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include "meson_vpu_pipeline.h"
+
+static int hdr_check_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ struct meson_vpu_hdr *hdr = to_hdr_block(vblk);
+
+ if (state->checked)
+ return 0;
+
+ state->checked = true;
+
+ //vpu_block_check_input(vblk, state, mvps);
+
+ DRM_DEBUG("%s set_state called.\n", hdr->base.name);
+ return 0;
+}
+
+static void hdr_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ struct meson_vpu_hdr *hdr = to_hdr_block(vblk);
+ //struct meson_vpu_hdr_state *hdr_state = to_hdr_state(state);
+
+ DRM_DEBUG("%s set_state called.\n", hdr->base.name);
+}
+
+static void hdr_enable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_hdr *hdr = to_hdr_block(vblk);
+
+ DRM_DEBUG("%s enable called.\n", hdr->base.name);
+}
+
+static void hdr_disable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_hdr *hdr = to_hdr_block(vblk);
+
+ DRM_DEBUG("%s disable called.\n", hdr->base.name);
+}
+
+struct meson_vpu_block_ops hdr_ops = {
+ .check_state = hdr_check_state,
+ .update_state = hdr_set_state,
+ .enable = hdr_enable,
+ .disable = hdr_disable,
+};
+
+static int dolby_check_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ struct meson_vpu_dolby *dolby = to_dolby_block(vblk);
+
+ if (state->checked)
+ return 0;
+
+ state->checked = true;
+
+ //vpu_block_check_input(vblk, state, mvps);
+
+ DRM_DEBUG("%s check_state called.\n", dolby->base.name);
+ return 0;
+}
+static void dolby_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ struct meson_vpu_dolby *dolby = to_dolby_block(vblk);
+
+ DRM_DEBUG("%s set_state called.\n", dolby->base.name);
+}
+
+static void dolby_enable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_dolby *dolby = to_dolby_block(vblk);
+
+ DRM_DEBUG("%s enable called.\n", dolby->base.name);
+}
+
+static void dolby_disable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_dolby *dolby = to_dolby_block(vblk);
+
+ DRM_DEBUG("%s disable called.\n", dolby->base.name);
+}
+
+struct meson_vpu_block_ops dolby_ops = {
+ .check_state = dolby_check_state,
+ .update_state = dolby_set_state,
+ .enable = dolby_enable,
+ .disable = dolby_disable,
+};
diff --git a/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c b/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c
new file mode 100644
index 0000000..ddc9bc2
--- a/dev/null
+++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c
@@ -0,0 +1,436 @@
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifdef CONFIG_AMLOGIC_MEDIA_CANVAS
+#include <linux/amlogic/media/canvas/canvas.h>
+#include <linux/amlogic/media/canvas/canvas_mgr.h>
+#endif
+#include "meson_vpu_pipeline.h"
+#include "meson_vpu_reg.h"
+#include "meson_vpu_util.h"
+
+static struct osd_mif_reg_s osd_mif_reg[HW_OSD_MIF_NUM] = {
+ {
+ VIU_OSD1_CTRL_STAT,
+ VIU_OSD1_CTRL_STAT2,
+ VIU_OSD1_COLOR_ADDR,
+ VIU_OSD1_COLOR,
+ VIU_OSD1_TCOLOR_AG0,
+ VIU_OSD1_TCOLOR_AG1,
+ VIU_OSD1_TCOLOR_AG2,
+ VIU_OSD1_TCOLOR_AG3,
+ VIU_OSD1_BLK0_CFG_W0,
+ VIU_OSD1_BLK0_CFG_W1,
+ VIU_OSD1_BLK0_CFG_W2,
+ VIU_OSD1_BLK0_CFG_W3,
+ VIU_OSD1_BLK0_CFG_W4,
+ VIU_OSD1_BLK1_CFG_W4,
+ VIU_OSD1_BLK2_CFG_W4,
+ VIU_OSD1_FIFO_CTRL_STAT,
+ VIU_OSD1_TEST_RDDATA,
+ VIU_OSD1_PROT_CTRL,
+ VIU_OSD1_MALI_UNPACK_CTRL,
+ VIU_OSD1_DIMM_CTRL,
+ },
+ {
+ VIU_OSD2_CTRL_STAT,
+ VIU_OSD2_CTRL_STAT2,
+ VIU_OSD2_COLOR_ADDR,
+ VIU_OSD2_COLOR,
+ VIU_OSD2_TCOLOR_AG0,
+ VIU_OSD2_TCOLOR_AG1,
+ VIU_OSD2_TCOLOR_AG2,
+ VIU_OSD2_TCOLOR_AG3,
+ VIU_OSD2_BLK0_CFG_W0,
+ VIU_OSD2_BLK0_CFG_W1,
+ VIU_OSD2_BLK0_CFG_W2,
+ VIU_OSD2_BLK0_CFG_W3,
+ VIU_OSD2_BLK0_CFG_W4,
+ VIU_OSD2_BLK1_CFG_W4,
+ VIU_OSD2_BLK2_CFG_W4,
+ VIU_OSD2_FIFO_CTRL_STAT,
+ VIU_OSD2_TEST_RDDATA,
+ VIU_OSD2_PROT_CTRL,
+ VIU_OSD2_MALI_UNPACK_CTRL,
+ VIU_OSD2_DIMM_CTRL,
+ },
+ {
+ VIU_OSD3_CTRL_STAT,
+ VIU_OSD3_CTRL_STAT2,
+ VIU_OSD3_COLOR_ADDR,
+ VIU_OSD3_COLOR,
+ VIU_OSD3_TCOLOR_AG0,
+ VIU_OSD3_TCOLOR_AG1,
+ VIU_OSD3_TCOLOR_AG2,
+ VIU_OSD3_TCOLOR_AG3,
+ VIU_OSD3_BLK0_CFG_W0,
+ VIU_OSD3_BLK0_CFG_W1,
+ VIU_OSD3_BLK0_CFG_W2,
+ VIU_OSD3_BLK0_CFG_W3,
+ VIU_OSD3_BLK0_CFG_W4,
+ VIU_OSD3_BLK1_CFG_W4,
+ VIU_OSD3_BLK2_CFG_W4,
+ VIU_OSD3_FIFO_CTRL_STAT,
+ VIU_OSD3_TEST_RDDATA,
+ VIU_OSD3_PROT_CTRL,
+ VIU_OSD3_MALI_UNPACK_CTRL,
+ VIU_OSD3_DIMM_CTRL,
+ }
+};
+
+static unsigned int osd_canvas[3][2] = {
+ {0x41, 0x42}, {0x43, 0x44}, {0x45, 0x46} };
+static u32 osd_canvas_index[3] = {0, 0, 0};
+
+/*
+ * Internal function to query information for a given format. See
+ * meson_drm_format_info() for the public API.
+ */
+const struct meson_drm_format_info *__meson_drm_format_info(u32 format)
+{
+ static const struct meson_drm_format_info formats[] = {
+ { .format = DRM_FORMAT_XRGB8888,
+ .hw_blkmode = 5, .hw_colormat = 1, .alpha_replace = 1 },
+ { .format = DRM_FORMAT_XBGR8888,
+ .hw_blkmode = 5, .hw_colormat = 2, .alpha_replace = 1 },
+ { .format = DRM_FORMAT_RGBX8888,
+ .hw_blkmode = 5, .hw_colormat = 0, .alpha_replace = 1 },
+ { .format = DRM_FORMAT_BGRX8888,
+ .hw_blkmode = 5, .hw_colormat = 3, .alpha_replace = 1 },
+ { .format = DRM_FORMAT_ARGB8888,
+ .hw_blkmode = 5, .hw_colormat = 1, .alpha_replace = 0 },
+ { .format = DRM_FORMAT_ABGR8888,
+ .hw_blkmode = 5, .hw_colormat = 2, .alpha_replace = 0 },
+ { .format = DRM_FORMAT_RGBA8888,
+ .hw_blkmode = 5, .hw_colormat = 0, .alpha_replace = 0 },
+ { .format = DRM_FORMAT_BGRA8888,
+ .hw_blkmode = 5, .hw_colormat = 3, .alpha_replace = 0 },
+ { .format = DRM_FORMAT_RGB888,
+ .hw_blkmode = 7, .hw_colormat = 0, .alpha_replace = 0 },
+ { .format = DRM_FORMAT_RGB565,
+ .hw_blkmode = 4, .hw_colormat = 4, .alpha_replace = 0 },
+ { .format = DRM_FORMAT_ARGB1555,
+ .hw_blkmode = 4, .hw_colormat = 6, .alpha_replace = 0 },
+ { .format = DRM_FORMAT_ARGB4444,
+ .hw_blkmode = 4, .hw_colormat = 5, .alpha_replace = 0 },
+ };
+
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+ if (formats[i].format == format)
+ return &formats[i];
+ }
+
+ return NULL;
+}
+/**
+ * meson_drm_format_info - query information for a given format
+ * @format: pixel format (DRM_FORMAT_*)
+ *
+ * The caller should only pass a supported pixel format to this function.
+ * Unsupported pixel formats will generate a warning in the kernel log.
+ *
+ * Returns:
+ * The instance of struct meson_drm_format_info that describes the
+ * pixel format, or NULL if the format is unsupported.
+ */
+const struct meson_drm_format_info *meson_drm_format_info(u32 format)
+{
+ const struct meson_drm_format_info *info;
+
+ info = __meson_drm_format_info(format);
+ WARN_ON(!info);
+ return info;
+}
+/**
+ * meson_drm_format_hw_blkmode - get the hw_blkmode for format
+ * @format: pixel format (DRM_FORMAT_*)
+ *
+ * Returns:
+ * The hw_blkmode match the specified pixel format.
+ */
+static u8 meson_drm_format_hw_blkmode(uint32_t format)
+{
+ const struct meson_drm_format_info *info;
+
+ info = meson_drm_format_info(format);
+ return info ? info->hw_blkmode : 0;
+}
+/**
+ * meson_drm_format_hw_colormat - get the hw_colormat for format
+ * @format: pixel format (DRM_FORMAT_*)
+ *
+ * Returns:
+ * The hw_colormat match the specified pixel format.
+ */
+static u8 meson_drm_format_hw_colormat(uint32_t format)
+{
+ const struct meson_drm_format_info *info;
+
+ info = meson_drm_format_info(format);
+ return info ? info->hw_colormat : 0;
+}
+/**
+ * meson_drm_format_alpha_replace - get the alpha replace for format
+ * @format: pixel format (DRM_FORMAT_*)
+ *
+ * Returns:
+ * The alpha_replace match the specified pixel format.
+ */
+static u8 meson_drm_format_alpha_replace(uint32_t format)
+{
+ const struct meson_drm_format_info *info;
+
+ info = meson_drm_format_info(format);
+ return info ? info->alpha_replace : 0;
+}
+/*osd input size config*/
+void osd_input_size_config(struct osd_mif_reg_s *reg, struct osd_scope_s scope)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk0_cfg_w1,
+ (scope.h_end << 16) |/*x_end pixels[13bits]*/
+ scope.h_start/*x_start pixels[13bits]*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk0_cfg_w2,
+ (scope.v_end << 16) |/*y_end pixels[13bits]*/
+ scope.v_start/*y_start pixels[13bits]*/);
+}
+/*osd canvas config*/
+void osd_canvas_config(struct osd_mif_reg_s *reg, u32 canvas_index)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blk0_cfg_w0,
+ canvas_index, 16, 8);
+}
+/*osd mif enable*/
+void osd_block_enable(struct osd_mif_reg_s *reg, bool flag)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_ctrl_stat, flag, 0, 1);
+}
+
+/*osd ctrl config*/
+void osd_ctrl_set(struct osd_mif_reg_s *reg)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_ctrl_stat,
+ (0 << 31) |/*osd_cfg_sync_en*/
+ (0 << 30) |/*Enable free_clk*/
+ (0x100 << 12) |/*global alpha*/
+ (0 << 11) |/*TEST_RD_EN*/
+ (0 << 2) |/*osd_mem_mode 0:canvas_addr*/
+ (0 << 1) |/*premult_en*/
+ (0 << 0)/*OSD_BLK_ENABLE*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_ctrl_stat2,
+ (1 << 14) |/*replaced_alpha_en*/
+ (0xff << 6) |/*replaced_alpha*/
+ (0 << 4) |/*hold fifo lines 2bit*/
+ (0 << 3) |/*output fullrange enable 1bit*/
+ (0 << 2)/*alpha 9bit mode 1bit*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_tcolor_ag0,
+ (0xff << 24) |/*Y/R*/
+ (0xff << 16) |/*CB/G*/
+ (0xff << 24) |/*CR/B*/
+ (0xff << 24)/*ALPHA*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_tcolor_ag1,
+ (0xff << 24) |/*Y/R*/
+ (0xff << 16) |/*CB/G*/
+ (0xff << 24) |/*CR/B*/
+ (0xff << 24)/*ALPHA*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_tcolor_ag2,
+ (0xff << 24) |/*Y/R*/
+ (0xff << 16) |/*CB/G*/
+ (0xff << 24) |/*CR/B*/
+ (0xff << 24)/*ALPHA*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_tcolor_ag3,
+ (0xff << 24) |/*Y/R*/
+ (0xff << 16) |/*CB/G*/
+ (0xff << 24) |/*CR/B*/
+ (0xff << 24)/*ALPHA*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk0_cfg_w0,
+ (0 << 30) |/*read from ddr[0]/afbc[1]*/
+ (0 << 29) |/*y reverse disable*/
+ (0 << 28) |/*x reverse disable*/
+ (osd_canvas[0][0] << 16) |/*canvas index*/
+ (1 << 15) |/*little endian in ddr*/
+ (0 << 14) |/*no repeat display y pre line*/
+ (0 << 12) |/*no interpolation per pixel*/
+ (5 << 8) |/*read from ddr 32bit mode*/
+ (0 << 6) |/*TC_ALPHA_EN*/
+ (1 << 2) |/*ARGB format for 32bit mode*/
+ (0 << 1) |/*interlace en*/
+ (0 << 0)/*output odd/even lines sel*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk0_cfg_w1,
+ (1919 << 16) |/*x_end pixels[13bits]*/
+ (0 << 0)/*x_start pixels[13bits]*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk0_cfg_w2,
+ (1079 << 16) |/*y_end pixels[13bits]*/
+ (0 << 0)/*y_start pixels[13bits]*/);
+ /*frame addr in linear addr*/
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk1_cfg_w4, 0);
+ /*line_stride in linear addr*/
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blk2_cfg_w4, 0);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_fifo_ctrl_stat,
+ (1 << 31) |/*BURSET_LEN_SEL[2]*/
+ (0 << 30) |/*no swap*/
+ (0 << 29) |/*div swap*/
+ (2 << 24) |/*Fifo_lim 5bits*/
+ (2 << 22) |/*Fifo_ctrl 2bits*/
+ (0x20 << 12) |/*FIFO_DEPATH_VAL 7bits*/
+ (1 << 10) |/*BURSET_LEN_SEL[1:0]*/
+ (4 << 5) |/*hold fifo lines 5bits*/
+ (0 << 4) |/*CLEAR_ERR*/
+ (0 << 3) |/*fifo_sync_rst*/
+ (0 << 1) |/*ENDIAN:no conversion*/
+ (1 << 0)/*urgent enable*/);
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_mali_unpack_ctrl,
+ (0 << 31) |/*unpack normal src*/
+ (0 << 28) |/*alpha div en*/
+ (0 << 26) |/*dividor gating clk*/
+ (1 << 24) |/*alpha mapping mode 2bits*/
+ (0 << 16) |/*afbc swap 64bit 1bits*/
+ (1 << 12) |/*afbcd_r_reorder r 4bits*/
+ (2 << 8) |/*afbcd_r_reorder g 4bits*/
+ (3 << 4) |/*afbcd_r_reorder b 4bits*/
+ (4 << 0)/*afbcd_r_reorder alpha 4bits*/);
+}
+
+static void osd_color_config(struct osd_mif_reg_s *reg, u32 pixel_format)
+{
+ u8 blk_mode, colormat, alpha_replace;
+
+ blk_mode = meson_drm_format_hw_blkmode(pixel_format);
+ colormat = meson_drm_format_hw_colormat(pixel_format);
+ alpha_replace = meson_drm_format_alpha_replace(pixel_format);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blk0_cfg_w0,
+ blk_mode, 8, 4);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blk0_cfg_w0,
+ colormat, 2, 4);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_ctrl_stat2,
+ alpha_replace, 14, 1);
+}
+
+static int osd_check_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ struct meson_vpu_osd_layer_info *plane_info;
+ struct meson_vpu_osd *osd = to_osd_block(vblk);
+ struct meson_vpu_osd_state *mvos = to_osd_state(state);
+
+ if (state->checked)
+ return 0;
+
+ state->checked = true;
+
+ if (!mvos || mvos->plane_index >= MESON_MAX_OSDS) {
+ DRM_INFO("mvos is NULL!\n");
+ return -1;
+ }
+ DRM_DEBUG("%s check_state called.\n", osd->base.name);
+ plane_info = &mvps->plane_info[vblk->index];
+ mvos->src_x = plane_info->src_x;
+ mvos->src_y = plane_info->src_y;
+ mvos->src_w = plane_info->src_w;
+ mvos->src_h = plane_info->src_h;
+ mvos->byte_stride = plane_info->byte_stride;
+ mvos->phy_addr = plane_info->phy_addr;
+ mvos->pixel_format = plane_info->pixel_format;
+ return 0;
+}
+
+static void osd_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ struct meson_vpu_osd *osd = to_osd_block(vblk);
+ struct meson_vpu_osd_state *mvos = to_osd_state(state);
+ u32 pixel_format, canvas_index, src_h, byte_stride, phy_addr;
+ struct osd_scope_s scope_src = {0, 1919, 0, 1079};
+ struct osd_mif_reg_s *reg = osd->reg;
+
+ if (!vblk) {
+ DRM_DEBUG("set_state break for NULL.\n");
+ return;
+ }
+ src_h = mvos->src_h;
+ byte_stride = mvos->byte_stride;
+ phy_addr = mvos->phy_addr;
+ scope_src.h_start = mvos->src_x;
+ scope_src.h_end = mvos->src_x + mvos->src_w - 1;
+ scope_src.v_start = mvos->src_y;
+ scope_src.v_end = mvos->src_y + mvos->src_h - 1;
+ pixel_format = mvos->pixel_format;
+ canvas_index = osd_canvas[vblk->index][osd_canvas_index[vblk->index]];
+ canvas_config(canvas_index, phy_addr, byte_stride, src_h,
+ CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
+ osd_canvas_index[vblk->index] ^= 1;
+ osd_canvas_config(reg, canvas_index);
+ osd_input_size_config(reg, scope_src);
+ osd_color_config(reg, pixel_format);
+ DRM_DEBUG("plane_index=%d,HW-OSD=%d\n",
+ mvos->plane_index, vblk->index);
+ DRM_DEBUG("canvas_index[%d]=0x%x,phy_addr=0x%x\n",
+ osd_canvas_index[vblk->index], canvas_index, phy_addr);
+ DRM_DEBUG("scope h/v start/end:[%d/%d/%d/%d]\n",
+ scope_src.h_start, scope_src.h_end,
+ scope_src.v_start, scope_src.v_end);
+ DRM_DEBUG("%s set_state done.\n", osd->base.name);
+}
+
+static void osd_hw_enable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_osd *osd = to_osd_block(vblk);
+ struct osd_mif_reg_s *reg = osd->reg;
+
+ if (!vblk) {
+ DRM_DEBUG("enable break for NULL.\n");
+ return;
+ }
+ osd_block_enable(reg, 1);
+ DRM_DEBUG("%s enable done.\n", osd->base.name);
+}
+
+static void osd_hw_disable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_osd *osd = to_osd_block(vblk);
+ struct osd_mif_reg_s *reg = osd->reg;
+
+ if (!vblk) {
+ DRM_DEBUG("disable break for NULL.\n");
+ return;
+ }
+ osd_block_enable(reg, 0);
+ DRM_DEBUG("%s disable done.\n", osd->base.name);
+}
+
+static void osd_hw_init(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_osd *osd = to_osd_block(vblk);
+
+ if (!vblk || !osd) {
+ DRM_DEBUG("hw_init break for NULL.\n");
+ return;
+ }
+ osd->reg = &osd_mif_reg[vblk->index];
+ osd_ctrl_set(osd->reg);
+ DRM_DEBUG("%s hw_init done.\n", osd->base.name);
+}
+
+struct meson_vpu_block_ops osd_ops = {
+ .check_state = osd_check_state,
+ .update_state = osd_set_state,
+ .enable = osd_hw_enable,
+ .disable = osd_hw_disable,
+ .init = osd_hw_init,
+};
diff --git a/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.h b/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.h
new file mode 100644
index 0000000..2a37316
--- a/dev/null
+++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.h
@@ -0,0 +1,153 @@
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef _MESON_VPU_OSD_MIF_H_
+#define _MESON_VPU_OSD_MIF_H_
+
+#define HW_OSD_MIF_NUM 3
+
+#define VIU_OSD1_CTRL_STAT 0x1a10
+#define VIU_OSD1_CTRL_STAT2 0x1a2d
+#define VIU_OSD1_COLOR_ADDR 0x1a11
+#define VIU_OSD1_COLOR 0x1a12
+#define VIU_OSD1_TCOLOR_AG0 0x1a17
+#define VIU_OSD1_TCOLOR_AG1 0x1a18
+#define VIU_OSD1_TCOLOR_AG2 0x1a19
+#define VIU_OSD1_TCOLOR_AG3 0x1a1a
+#define VIU_OSD1_BLK0_CFG_W0 0x1a1b
+#define VIU_OSD1_BLK1_CFG_W0 0x1a1f
+#define VIU_OSD1_BLK2_CFG_W0 0x1a23
+#define VIU_OSD1_BLK3_CFG_W0 0x1a27
+#define VIU_OSD1_BLK0_CFG_W1 0x1a1c
+#define VIU_OSD1_BLK1_CFG_W1 0x1a20
+#define VIU_OSD1_BLK2_CFG_W1 0x1a24
+#define VIU_OSD1_BLK3_CFG_W1 0x1a28
+#define VIU_OSD1_BLK0_CFG_W2 0x1a1d
+#define VIU_OSD1_BLK1_CFG_W2 0x1a21
+#define VIU_OSD1_BLK2_CFG_W2 0x1a25
+#define VIU_OSD1_BLK3_CFG_W2 0x1a29
+#define VIU_OSD1_BLK0_CFG_W3 0x1a1e
+#define VIU_OSD1_BLK1_CFG_W3 0x1a22
+#define VIU_OSD1_BLK2_CFG_W3 0x1a26
+#define VIU_OSD1_BLK3_CFG_W3 0x1a2a
+#define VIU_OSD1_BLK0_CFG_W4 0x1a13
+#define VIU_OSD1_BLK1_CFG_W4 0x1a14
+#define VIU_OSD1_BLK2_CFG_W4 0x1a15
+#define VIU_OSD1_BLK3_CFG_W4 0x1a16
+#define VIU_OSD1_FIFO_CTRL_STAT 0x1a2b
+#define VIU_OSD1_TEST_RDDATA 0x1a2c
+#define VIU_OSD1_PROT_CTRL 0x1a2e
+#define VIU_OSD1_MALI_UNPACK_CTRL 0x1a2f
+#define VIU_OSD1_DIMM_CTRL 0x1adf
+
+#define VIU_OSD2_CTRL_STAT 0x1a30
+#define VIU_OSD2_CTRL_STAT2 0x1a4d
+#define VIU_OSD2_COLOR_ADDR 0x1a31
+#define VIU_OSD2_COLOR 0x1a32
+#define VIU_OSD2_HL1_H_START_END 0x1a33
+#define VIU_OSD2_HL1_V_START_END 0x1a34
+#define VIU_OSD2_HL2_H_START_END 0x1a35
+#define VIU_OSD2_HL2_V_START_END 0x1a36
+#define VIU_OSD2_TCOLOR_AG0 0x1a37
+#define VIU_OSD2_TCOLOR_AG1 0x1a38
+#define VIU_OSD2_TCOLOR_AG2 0x1a39
+#define VIU_OSD2_TCOLOR_AG3 0x1a3a
+#define VIU_OSD2_BLK0_CFG_W0 0x1a3b
+#define VIU_OSD2_BLK1_CFG_W0 0x1a3f
+#define VIU_OSD2_BLK2_CFG_W0 0x1a43
+#define VIU_OSD2_BLK3_CFG_W0 0x1a47
+#define VIU_OSD2_BLK0_CFG_W1 0x1a3c
+#define VIU_OSD2_BLK1_CFG_W1 0x1a40
+#define VIU_OSD2_BLK2_CFG_W1 0x1a44
+#define VIU_OSD2_BLK3_CFG_W1 0x1a48
+#define VIU_OSD2_BLK0_CFG_W2 0x1a3d
+#define VIU_OSD2_BLK1_CFG_W2 0x1a41
+#define VIU_OSD2_BLK2_CFG_W2 0x1a45
+#define VIU_OSD2_BLK3_CFG_W2 0x1a49
+#define VIU_OSD2_BLK0_CFG_W3 0x1a3e
+#define VIU_OSD2_BLK1_CFG_W3 0x1a42
+#define VIU_OSD2_BLK2_CFG_W3 0x1a46
+#define VIU_OSD2_BLK3_CFG_W3 0x1a4a
+#define VIU_OSD2_BLK0_CFG_W4 0x1a64
+#define VIU_OSD2_BLK1_CFG_W4 0x1a65
+#define VIU_OSD2_BLK2_CFG_W4 0x1a66
+#define VIU_OSD2_BLK3_CFG_W4 0x1a67
+#define VIU_OSD2_FIFO_CTRL_STAT 0x1a4b
+#define VIU_OSD2_TEST_RDDATA 0x1a4c
+#define VIU_OSD2_PROT_CTRL 0x1a4e
+#define VIU_OSD2_MALI_UNPACK_CTRL 0x1abd
+#define VIU_OSD2_DIMM_CTRL 0x1acf
+
+#define VIU_OSD3_CTRL_STAT 0x3d80
+#define VIU_OSD3_CTRL_STAT2 0x3d81
+#define VIU_OSD3_COLOR_ADDR 0x3d82
+#define VIU_OSD3_COLOR 0x3d83
+#define VIU_OSD3_TCOLOR_AG0 0x3d84
+#define VIU_OSD3_TCOLOR_AG1 0x3d85
+#define VIU_OSD3_TCOLOR_AG2 0x3d86
+#define VIU_OSD3_TCOLOR_AG3 0x3d87
+#define VIU_OSD3_BLK0_CFG_W0 0x3d88
+#define VIU_OSD3_BLK0_CFG_W1 0x3d8c
+#define VIU_OSD3_BLK0_CFG_W2 0x3d90
+#define VIU_OSD3_BLK0_CFG_W3 0x3d94
+#define VIU_OSD3_BLK0_CFG_W4 0x3d98
+#define VIU_OSD3_BLK1_CFG_W4 0x3d99
+#define VIU_OSD3_BLK2_CFG_W4 0x3d9a
+#define VIU_OSD3_FIFO_CTRL_STAT 0x3d9c
+#define VIU_OSD3_TEST_RDDATA 0x3d9d
+#define VIU_OSD3_PROT_CTRL 0x3d9e
+#define VIU_OSD3_MALI_UNPACK_CTRL 0x3d9f
+#define VIU_OSD3_DIMM_CTRL 0x3da0
+
+struct osd_mif_reg_s {
+ u32 viu_osd_ctrl_stat;
+ u32 viu_osd_ctrl_stat2;
+ u32 viu_osd_color_addr;
+ u32 viu_osd_color;
+ u32 viu_osd_tcolor_ag0;
+ u32 viu_osd_tcolor_ag1;
+ u32 viu_osd_tcolor_ag2;
+ u32 viu_osd_tcolor_ag3;
+ u32 viu_osd_blk0_cfg_w0;
+ u32 viu_osd_blk0_cfg_w1;
+ u32 viu_osd_blk0_cfg_w2;
+ u32 viu_osd_blk0_cfg_w3;
+ u32 viu_osd_blk0_cfg_w4;
+ u32 viu_osd_blk1_cfg_w4;
+ u32 viu_osd_blk2_cfg_w4;
+ u32 viu_osd_fifo_ctrl_stat;
+ u32 viu_osd_test_rddata;
+ u32 viu_osd_prot_ctrl;
+ u32 viu_osd_mali_unpack_ctrl;
+ u32 viu_osd_dimm_ctrl;
+};
+
+/**
+ * struct meson_drm_format_info - information about a DRM format
+ * @format: 4CC format identifier (DRM_FORMAT_*)
+ * @hw_blkmode: Define the OSD block’s input pixel format
+ * @hw_colormat: Applicable only to 16-bit color mode (OSD_BLK_MODE=4),
+ * 32-bit mode (OSD_BLK_MODE=5) and 24-bit mode (OSD_BLK_MODE=7),
+ * defines the bit-field allocation of the pixel data.
+ */
+struct meson_drm_format_info {
+ u32 format;
+ u8 hw_blkmode;
+ u8 hw_colormat;
+ u8 alpha_replace;
+};
+#endif
diff --git a/drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.c b/drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.c
new file mode 100644
index 0000000..f6aa7e8
--- a/dev/null
+++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.c
@@ -0,0 +1,520 @@
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+/* Amlogic Headers */
+#include <linux/amlogic/media/vout/vout_notify.h>
+
+#include "meson_vpu_pipeline.h"
+#include "meson_vpu_reg.h"
+#include "meson_vpu_util.h"
+#include "meson_vpu_osdblend.h"
+
+static struct osdblend_reg_s osdblend_reg = {
+ VIU_OSD_BLEND_CTRL,
+ VIU_OSD_BLEND_DIN0_SCOPE_H,
+ VIU_OSD_BLEND_DIN0_SCOPE_V,
+ VIU_OSD_BLEND_DIN1_SCOPE_H,
+ VIU_OSD_BLEND_DIN1_SCOPE_V,
+ VIU_OSD_BLEND_DIN2_SCOPE_H,
+ VIU_OSD_BLEND_DIN2_SCOPE_V,
+ VIU_OSD_BLEND_DIN3_SCOPE_H,
+ VIU_OSD_BLEND_DIN3_SCOPE_V,
+ VIU_OSD_BLEND_DUMMY_DATA0,
+ VIU_OSD_BLEND_DUMMY_ALPHA,
+ VIU_OSD_BLEND_BLEND0_SIZE,
+ VIU_OSD_BLEND_BLEND1_SIZE,
+ VIU_OSD_BLEND_CTRL1,
+};
+
+/*0:din0 go through blend0,1:bypass blend0,dirct to Dout0*/
+static void osd_din0_switch_set(struct osdblend_reg_s *reg,
+ bool bypass_state)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl,
+ bypass_state, 26, 1);
+}
+/*0:blend1 out to blend2,1:blend1 out to Dout1*/
+static void osd_blend1_dout_switch_set(struct osdblend_reg_s *reg,
+ bool bypass_state)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl,
+ bypass_state, 25, 1);
+}
+/*0:din3 pass through blend1,1:bypass blend1,direct to Dout1*/
+static void osd_din3_switch_set(struct osdblend_reg_s *reg,
+ bool bypass_state)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl,
+ bypass_state, 24, 1);
+}
+#if 0
+/*0:din0/1/2/3 input disable,1:enable*/
+static void osd_din_input_enable_set(struct osdblend_reg_s *reg,
+ bool enable, enum din_channel_e din_channel)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, enable,
+ (20 + din_channel), 1);
+}
+#endif
+/*0:din0 input disable,1:din0 input enable*/
+static void osd_din0_input_enable_set(struct osdblend_reg_s *reg,
+ bool input_enable)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl,
+ input_enable, 20, 1);
+}
+/*0:din1 input disable,1:din1 input enable*/
+static void osd_din1_input_enable_set(struct osdblend_reg_s *reg,
+ bool input_enable)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl,
+ input_enable, 21, 1);
+}
+/*0:din2 input disable,1:din2 input enable*/
+static void osd_din2_input_enable_set(struct osdblend_reg_s *reg,
+ bool input_enable)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl,
+ input_enable, 22, 1);
+}
+/*0:din3 input disable,1:din3 input enable*/
+static void osd_din3_input_enable_set(struct osdblend_reg_s *reg,
+ bool input_enable)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl,
+ input_enable, 23, 1);
+}
+#if 0
+/*0:din0/1/2/3 premult disable,1:enable*/
+static void osd_din_premult_enable_set(struct osdblend_reg_s *reg,
+ bool enable, enum din_channel_e din_channel)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, enable,
+ (16 + din_channel), 1);
+}
+#endif
+/*1/2/3:din0/1/2/3 select osd1/osd2/osd3,else select null*/
+static void osd_din_channel_mux_set(struct osdblend_reg_s *reg,
+ enum osd_channel_e osd_channel,
+ enum din_channel_e din_channel)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, osd_channel,
+ (0 + din_channel*4), 4);
+}
+/*din0 scope config*/
+static void osd_din0_scope_set(struct osdblend_reg_s *reg,
+ struct osd_scope_s scope)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din0_scope_h,
+ scope.h_start, 0, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din0_scope_h,
+ scope.h_end, 16, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din0_scope_v,
+ scope.v_start, 0, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din0_scope_v,
+ scope.v_end, 16, 13);
+}
+/*din1 scope config*/
+static void osd_din1_scope_set(struct osdblend_reg_s *reg,
+ struct osd_scope_s scope)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din1_scope_h,
+ scope.h_start, 0, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din1_scope_h,
+ scope.h_end, 16, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din1_scope_v,
+ scope.v_start, 0, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din1_scope_v,
+ scope.v_end, 16, 13);
+}
+/*din2 scope config*/
+static void osd_din2_scope_set(struct osdblend_reg_s *reg,
+ struct osd_scope_s scope)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din2_scope_h,
+ scope.h_start, 0, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din2_scope_h,
+ scope.h_end, 16, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din2_scope_v,
+ scope.v_start, 0, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din2_scope_v,
+ scope.v_end, 16, 13);
+}
+/*din3 scope config*/
+static void osd_din3_scope_set(struct osdblend_reg_s *reg,
+ struct osd_scope_s scope)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din3_scope_h,
+ scope.h_start, 0, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din3_scope_h,
+ scope.h_end, 16, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din3_scope_v,
+ scope.v_start, 0, 13);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_din3_scope_v,
+ scope.v_end, 16, 13);
+}
+/*osd blend dummy data config*/
+static void osd_blend_dummy_data_set(struct osdblend_reg_s *reg,
+ struct osd_dummy_data_s dummy_data)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blend_dummy_data0,
+ ((dummy_data.channel0 & 0xff) << 16) |
+ ((dummy_data.channel1 & 0xff) << 8) |
+ (dummy_data.channel2 & 0xff));
+}
+/*osd blend0 dummy data alpha config*/
+static void osd_blend0_dummy_alpha_set(struct osdblend_reg_s *reg,
+ unsigned int dummy_alpha)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_dummy_alpha,
+ dummy_alpha, 20, 9);
+}
+/*osd blend1 dummy data alpha config*/
+static void osd_blend1_dummy_alpha_set(struct osdblend_reg_s *reg,
+ unsigned int dummy_alpha)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_dummy_alpha,
+ dummy_alpha, 11, 9);
+}
+/*osd blend2 dummy data alpha config*/
+static void osd_blend2_dummy_alpha_set(struct osdblend_reg_s *reg,
+ unsigned int dummy_alpha)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_dummy_alpha,
+ dummy_alpha, 0, 9);
+}
+/*osd blend0 size config*/
+static void osd_blend0_size_set(struct osdblend_reg_s *reg,
+ unsigned int h_size, unsigned int v_size)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blend0_size,
+ (v_size << 16) | h_size);
+}
+/*osd blend1 size config*/
+static void osd_blend1_size_set(struct osdblend_reg_s *reg,
+ unsigned int h_size, unsigned int v_size)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->viu_osd_blend1_size,
+ (v_size << 16) | h_size);
+}
+/*osd blend0 & blend1 4 din inputs premult flag config as 0 default*/
+void osd_blend01_premult_config(struct osdblend_reg_s *reg)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, 0, 16, 4);
+}
+/*osd blend2 2 inputs premult flag config as 1 default*/
+void osd_blend2_premult_config(struct osdblend_reg_s *reg)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl, 3, 27, 2);
+}
+/*osd blend dout0 output div en config as 1,alpha 9bit default*/
+void osd_blend_dout0_div_config(struct osdblend_reg_s *reg)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl1, 3, 4, 2);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl1, 1, 0, 1);
+}
+/*osd blend dout1 output div en config as 1,alpha 9bit default*/
+void osd_blend_dout1_div_config(struct osdblend_reg_s *reg)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl1, 3, 16, 2);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->viu_osd_blend_ctrl1, 1, 12, 1);
+}
+/*osd blend premult config*/
+void osdblend_premult_config(struct osdblend_reg_s *reg)
+{
+ osd_blend01_premult_config(reg);
+ osd_blend2_premult_config(reg);
+ osd_blend_dout0_div_config(reg);
+ osd_blend_dout1_div_config(reg);
+}
+
+enum osd_channel_e osd2channel(u8 osd_index)
+{
+ u8 din_channel_seq[MAX_DIN_NUM] = {OSD_CHANNEL1, OSD_CHANNEL2,
+ OSD_CHANNEL3, OSD_CHANNEL_NUM};
+
+ if (osd_index >= MAX_DIN_NUM) {
+ DRM_DEBUG("osd_index:%d overflow!!.\n", osd_index);
+ return OSD_CHANNEL_NUM;
+ }
+ return din_channel_seq[osd_index];
+}
+
+static void osdblend_hw_update(struct osdblend_reg_s *reg,
+ struct meson_vpu_osdblend_state *mvobs)
+{
+ struct osd_dummy_data_s dummy_data = {0, 0, 0};
+
+ /*din channel mux config*/
+ osd_din_channel_mux_set(reg, mvobs->din_channel_mux[DIN0], DIN0);
+ osd_din_channel_mux_set(reg, mvobs->din_channel_mux[DIN1], DIN1);
+ osd_din_channel_mux_set(reg, mvobs->din_channel_mux[DIN2], DIN2);
+ osd_din_channel_mux_set(reg, mvobs->din_channel_mux[DIN3], DIN3);
+
+ /*dummy data config*/
+ osd_blend_dummy_data_set(reg, dummy_data);
+
+ /*alpha config*/
+ osd_blend0_dummy_alpha_set(reg, 0x1ff);
+ osd_blend1_dummy_alpha_set(reg, 0);
+ osd_blend2_dummy_alpha_set(reg, 0x1ff);
+
+ /*internal channel disable default*/
+ osd_din0_input_enable_set(reg, (mvobs->input_mask >> DIN0) & 0x1);
+ osd_din1_input_enable_set(reg, (mvobs->input_mask >> DIN1) & 0x1);
+ osd_din2_input_enable_set(reg, (mvobs->input_mask >> DIN2) & 0x1);
+ osd_din3_input_enable_set(reg, (mvobs->input_mask >> DIN3) & 0x1);
+
+ /*blend switch config*/
+ osd_din0_switch_set(reg, mvobs->din0_switch);
+ osd_din3_switch_set(reg, mvobs->din3_switch);
+ osd_blend1_dout_switch_set(reg, mvobs->blend1_switch);
+
+ /*scope config*/
+ osd_din0_scope_set(reg, mvobs->din_channel_scope[DIN0]);
+ osd_din1_scope_set(reg, mvobs->din_channel_scope[DIN1]);
+ osd_din2_scope_set(reg, mvobs->din_channel_scope[DIN2]);
+ osd_din3_scope_set(reg, mvobs->din_channel_scope[DIN3]);
+
+ /*premult config*/
+ osdblend_premult_config(reg);
+
+ /*blend0/blend1 size config*/
+ osd_blend0_size_set(reg, mvobs->input_width[OSD_SUB_BLEND0],
+ mvobs->input_height[OSD_SUB_BLEND0]);
+ osd_blend1_size_set(reg, mvobs->input_width[OSD_SUB_BLEND1],
+ mvobs->input_height[OSD_SUB_BLEND1]);
+}
+
+static int osdblend_check_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ int ret, num_planes;
+ u32 *out_port;
+ u32 i, j, m, n, num_plane_port0, num_plane_port1;
+ u32 plane_index_port0[MAX_DIN_NUM], plane_index_port1[MAX_DIN_NUM];
+ struct meson_vpu_osdblend_state *mvobs;
+ u32 zorder[MAX_DIN_NUM], max_height = 0, max_width = 0;
+ int delta_zorder[MAX_DIN_NUM] = {0};
+ bool delta_zorder_flag;
+ struct osd_scope_s scope_default = {0xffff, 0xffff, 0xffff, 0xffff};
+
+ mvobs = to_osdblend_state(state);
+ num_planes = mvps->num_plane;
+ out_port = mvps->dout_index;
+
+ if (state->checked)
+ return 0;
+
+ state->checked = true;
+
+ ret = 0;
+ num_plane_port0 = 0;
+ num_plane_port1 = 0;
+ DRM_DEBUG("%s check_state called.\n", vblk->name);
+ for (i = 0; i < MESON_MAX_OSDS; i++) {
+ if (!mvps->plane_info[i].enable) {
+ mvobs->input_osd_mask &= ~BIT(i);
+ continue;
+ }
+ mvobs->input_osd_mask |= BIT(i);
+ if (out_port[i] == OSD_LEND_OUT_PORT1) {
+ plane_index_port1[num_plane_port1] =
+ mvps->plane_index[i];
+ num_plane_port1++;
+ } else {
+ plane_index_port0[num_plane_port0] =
+ mvps->plane_index[i];
+ num_plane_port0++;
+ }
+ }
+ /*check the unsupport case firstly*/
+ if (num_plane_port0 > OSD_LEND_MAX_IN_NUM_PORT0 ||
+ num_plane_port1 > OSD_LEND_MAX_IN_NUM_PORT1)
+ return -1;
+ if (mvps->pipeline->osd_version <= OSD_V2 &&
+ num_plane_port1)
+ return -1;
+ /*zorder check for one dout-port with multi plane*/
+ for (i = 0; i < num_plane_port1; i++) {
+ m = plane_index_port1[i];
+ for (j = 0; j < num_plane_port0; j++) {
+ n = plane_index_port0[j];
+ delta_zorder[0] = mvps->plane_info[m].zorder -
+ mvps->plane_info[n].zorder;
+ delta_zorder_flag = ((delta_zorder[0] < 0) !=
+ (delta_zorder[1] < 0));
+ if (num_plane_port0 >= 2 && j > 0 &&
+ delta_zorder_flag)
+ return -1;
+ delta_zorder[1] = delta_zorder[0];
+ /*find the max zorder as dout port zorder*/
+ if (mvps->dout_zorder[OSD_LEND_OUT_PORT0] <
+ mvps->plane_info[n].zorder)
+ mvps->dout_zorder[OSD_LEND_OUT_PORT0] =
+ mvps->plane_info[n].zorder;
+ }
+ delta_zorder[2] = delta_zorder[0];
+ delta_zorder_flag = ((delta_zorder[2] < 0) !=
+ (delta_zorder[3] < 0));
+ if (num_plane_port1 >= 2 && i > 0 && delta_zorder_flag)
+ return -1;
+ delta_zorder[3] = delta_zorder[2];
+ if (mvps->dout_zorder[OSD_LEND_OUT_PORT1] <
+ mvps->plane_info[m].zorder)
+ mvps->dout_zorder[OSD_LEND_OUT_PORT1] =
+ mvps->plane_info[m].zorder;
+ }
+ /*
+ *confirm the Din enable and channel mux and sub blend input size
+ *according to input zorder and dout sel
+ */
+ mvobs->input_mask = 0;
+ for (i = 0; i < num_plane_port0; i++) {
+ mvobs->input_mask |= 1 << i;
+ j = plane_index_port0[i];
+ mvobs->din_channel_mux[i] = osd2channel(j);
+ zorder[i] = mvps->plane_info[j].zorder;
+ /*blend size calc*/
+ if (max_width < mvps->osd_scope_pre[j].h_end + 1)
+ max_width = mvps->osd_scope_pre[j].h_end + 1;
+ if (max_height < mvps->osd_scope_pre[j].v_end + 1)
+ max_height = mvps->osd_scope_pre[j].v_end + 1;
+ }
+ for (i = 0; i < num_plane_port0; i++) {
+ for (j = 1; j < num_plane_port0; j++) {
+ if (zorder[i] > zorder[j]) {
+ swap(zorder[i], zorder[j]);
+ swap(mvobs->din_channel_mux[i],
+ mvobs->din_channel_mux[j]);
+ }
+ }
+ }
+ for (i = 0; i < num_plane_port1; i++) {
+ m = MAX_DIN_NUM - i - 1;
+ mvobs->input_mask |= 1 << m;
+ j = plane_index_port1[i];
+ mvobs->din_channel_mux[m] = osd2channel(j);
+ zorder[i] = mvps->plane_info[j].zorder;
+ /*blend size calc*/
+ if (max_width < mvps->osd_scope_pre[j].h_end + 1)
+ max_width = mvps->osd_scope_pre[j].h_end + 1;
+ if (max_height < mvps->osd_scope_pre[j].v_end + 1)
+ max_height = mvps->osd_scope_pre[j].v_end + 1;
+ }
+ for (i = 0; i < num_plane_port1; i++) {
+ for (j = 1; j < num_plane_port1; j++) {
+ if (zorder[i] > zorder[j]) {
+ swap(zorder[i], zorder[j]);
+ swap(mvobs->din_channel_mux[i],
+ mvobs->din_channel_mux[j]);
+ }
+ }
+ }
+ for (i = 0; i < MAX_DIN_NUM; i++) {
+ if (!mvobs->din_channel_mux[i])
+ mvobs->din_channel_mux[i] = OSD_CHANNEL_NUM;
+ }
+ /*osdblend switch check*/
+ mvobs->din0_switch = 0;
+ if ((mvobs->input_mask & (BIT(DIN2) | BIT(DIN3))) &&
+ num_plane_port0 == 3 && num_plane_port1 == 1)
+ mvobs->din3_switch = 1;
+ else
+ mvobs->din3_switch = 0;
+ if ((mvobs->input_mask & BIT(DIN2)) &&
+ num_plane_port1 == 2)
+ mvobs->blend1_switch = 1;
+ else
+ mvobs->blend1_switch = 0;
+ /*scope check*/
+ for (i = 0; i < MAX_DIN_NUM; i++) {
+ if (mvobs->input_osd_mask & BIT(i))
+ memcpy(&mvobs->din_channel_scope[i],
+ &mvps->osd_scope_pre[i],
+ sizeof(struct osd_scope_s));
+ else
+ memcpy(&mvobs->din_channel_scope[i],
+ &scope_default,
+ sizeof(struct osd_scope_s));
+ }
+ /*sub blend size check*/
+ mvobs->input_width[OSD_SUB_BLEND0] = max_width;
+ mvobs->input_width[OSD_SUB_BLEND1] = max_width;
+ mvobs->input_height[OSD_SUB_BLEND0] = max_height;
+ mvobs->input_height[OSD_SUB_BLEND1] = max_height;
+ DRM_DEBUG("%s check done.\n", vblk->name);
+ return ret;
+}
+
+static void osdblend_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ struct meson_vpu_osdblend *osdblend = to_osdblend_block(vblk);
+ struct meson_vpu_pipeline *pipeline = osdblend->base.pipeline;
+ struct meson_vpu_osdblend_state *mvobs;
+ struct meson_vpu_pipeline_state *pipeline_state;
+ struct osdblend_reg_s *reg = osdblend->reg;
+
+ DRM_DEBUG("%s set_state called.\n", osdblend->base.name);
+ mvobs = to_osdblend_state(state);
+ pipeline_state = priv_to_pipeline_state(pipeline->obj.state);
+ if (!pipeline_state) {
+ DRM_DEBUG("pipeline_state is NULL!!\n");
+ return;
+ }
+
+ #ifdef OSDBLEND_CHECK_METHOD_COMBINATION
+ osdblend_layer_set(reg, osdblend, pipeline_state);
+ #else
+ osdblend_hw_update(reg, mvobs);
+ #endif
+
+ DRM_DEBUG("%s set_state done.\n", osdblend->base.name);
+}
+
+static void osdblend_hw_enable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_osdblend *osdblend = to_osdblend_block(vblk);
+
+ DRM_DEBUG("%s enable called.\n", osdblend->base.name);
+}
+
+static void osdblend_hw_disable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_osdblend *osdblend = to_osdblend_block(vblk);
+
+ DRM_DEBUG("%s disable called.\n", osdblend->base.name);
+}
+
+static void osdblend_hw_init(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_osdblend *osdblend = to_osdblend_block(vblk);
+
+ osdblend->reg = &osdblend_reg;
+ DRM_DEBUG("%s hw_init called.\n", osdblend->base.name);
+}
+
+struct meson_vpu_block_ops osdblend_ops = {
+ .check_state = osdblend_check_state,
+ .update_state = osdblend_set_state,
+ .enable = osdblend_hw_enable,
+ .disable = osdblend_hw_disable,
+ .init = osdblend_hw_init,
+};
+
diff --git a/drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.h b/drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.h
new file mode 100644
index 0000000..3c1f3a6
--- a/dev/null
+++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.h
@@ -0,0 +1,74 @@
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef _MESON_VPU_OSDBLEND_H_
+#define _MESON_VPU_OSDBLEND_H_
+
+#define OSD_LEND_OUT_PORT0 0
+#define OSD_LEND_OUT_PORT1 1
+#define OSD_SUB_BLEND0 0
+#define OSD_SUB_BLEND1 1
+#define OSD_LEND_MAX_IN_NUM_PORT0 4
+#define OSD_LEND_MAX_IN_NUM_PORT1 2
+
+#define VIU_OSD_BLEND_CTRL 0x39b0
+#define VIU_OSD_BLEND_DIN0_SCOPE_H 0x39b1
+#define VIU_OSD_BLEND_DIN0_SCOPE_V 0x39b2
+#define VIU_OSD_BLEND_DIN1_SCOPE_H 0x39b3
+#define VIU_OSD_BLEND_DIN1_SCOPE_V 0x39b4
+#define VIU_OSD_BLEND_DIN2_SCOPE_H 0x39b5
+#define VIU_OSD_BLEND_DIN2_SCOPE_V 0x39b6
+#define VIU_OSD_BLEND_DIN3_SCOPE_H 0x39b7
+#define VIU_OSD_BLEND_DIN3_SCOPE_V 0x39b8
+#define VIU_OSD_BLEND_DUMMY_DATA0 0x39b9
+#define VIU_OSD_BLEND_DUMMY_ALPHA 0x39ba
+#define VIU_OSD_BLEND_BLEND0_SIZE 0x39bb
+#define VIU_OSD_BLEND_BLEND1_SIZE 0x39bc
+#define VIU_OSD_BLEND_RO_CURRENT_XY 0x39bf
+#define VIU_OSD_BLEND_CTRL1 0x39c0
+
+struct osdblend_reg_s {
+ u32 viu_osd_blend_ctrl;
+ u32 viu_osd_blend_din0_scope_h;
+ u32 viu_osd_blend_din0_scope_v;
+ u32 viu_osd_blend_din1_scope_h;
+ u32 viu_osd_blend_din1_scope_v;
+ u32 viu_osd_blend_din2_scope_h;
+ u32 viu_osd_blend_din2_scope_v;
+ u32 viu_osd_blend_din3_scope_h;
+ u32 viu_osd_blend_din3_scope_v;
+ u32 viu_osd_blend_dummy_data0;
+ u32 viu_osd_blend_dummy_alpha;
+ u32 viu_osd_blend0_size;
+ u32 viu_osd_blend1_size;
+ u32 viu_osd_blend_ctrl1;
+};
+
+/*input mif channel*/
+enum osd_channel_e {
+ OSD_CHANNEL1 = 1,
+ OSD_CHANNEL2,
+ OSD_CHANNEL3,
+ OSD_CHANNEL_NUM
+};
+
+struct osd_dummy_data_s {
+ unsigned int channel0;/*y*/
+ unsigned int channel1;/*cb*/
+ unsigned int channel2;/*cr*/
+};
+#endif
diff --git a/drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.c b/drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.c
new file mode 100644
index 0000000..71ea0aa
--- a/dev/null
+++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.c
@@ -0,0 +1,184 @@
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+/* Amlogic Headers */
+#include <linux/amlogic/media/vout/vout_notify.h>
+
+#include "meson_vpu_pipeline.h"
+#include "meson_vpu_util.h"
+#include "meson_vpu_postblend.h"
+
+static struct postblend_reg_s postblend_reg = {
+ VPP_OSD1_BLD_H_SCOPE,
+ VPP_OSD1_BLD_V_SCOPE,
+ VPP_OSD2_BLD_H_SCOPE,
+ VPP_OSD2_BLD_V_SCOPE,
+ VD1_BLEND_SRC_CTRL,
+ VD2_BLEND_SRC_CTRL,
+ OSD1_BLEND_SRC_CTRL,
+ OSD2_BLEND_SRC_CTRL,
+};
+
+/*vpp post&post blend for osd1 premult flag config as 0 default*/
+static void osd1_blend_premult_set(struct postblend_reg_s *reg)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd1_blend_src_ctrl, 0, 4, 1);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd1_blend_src_ctrl, 0, 16, 1);
+}
+
+/*vpp pre&post blend for osd2 premult flag config as 0 default*/
+static void osd2_blend_premult_set(struct postblend_reg_s *reg)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd2_blend_src_ctrl, 0, 4, 1);
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd2_blend_src_ctrl, 0, 16, 1);
+}
+
+/*vpp osd1 blend sel*/
+static void osd1_blend_switch_set(struct postblend_reg_s *reg,
+ enum vpp_blend_e blend_sel)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd1_blend_src_ctrl, blend_sel, 20, 1);
+}
+
+/*vpp osd2 blend sel*/
+static void osd2_blend_switch_set(struct postblend_reg_s *reg,
+ enum vpp_blend_e blend_sel)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd2_blend_src_ctrl, blend_sel, 20, 1);
+}
+
+/*vpp osd1 preblend mux sel*/
+static void vpp_osd1_preblend_mux_set(struct postblend_reg_s *reg,
+ enum vpp_blend_src_e src_sel)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd1_blend_src_ctrl, src_sel, 0, 4);
+}
+
+/*vpp osd2 preblend mux sel*/
+static void vpp_osd2_preblend_mux_set(struct postblend_reg_s *reg,
+ enum vpp_blend_src_e src_sel)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd2_blend_src_ctrl, src_sel, 0, 4);
+}
+
+/*vpp osd1 postblend mux sel*/
+static void vpp_osd1_postblend_mux_set(struct postblend_reg_s *reg,
+ enum vpp_blend_src_e src_sel)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd1_blend_src_ctrl, src_sel, 8, 4);
+}
+/*vpp osd2 postblend mux sel*/
+static void vpp_osd2_postblend_mux_set(struct postblend_reg_s *reg,
+ enum vpp_blend_src_e src_sel)
+{
+ VSYNCOSD_WR_MPEG_REG_BITS(reg->osd2_blend_src_ctrl, src_sel, 8, 4);
+}
+/*vpp osd1 blend scope set*/
+static void vpp_osd1_blend_scope_set(struct postblend_reg_s *reg,
+ struct osd_scope_s scope)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd1_bld_h_scope,
+ (scope.h_start << 16) | scope.h_end);
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd1_bld_v_scope,
+ (scope.v_start << 16) | scope.v_end);
+}
+/*vpp osd2 blend scope set*/
+static void vpp_osd2_blend_scope_set(struct postblend_reg_s *reg,
+ struct osd_scope_s scope)
+{
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd2_bld_h_scope,
+ (scope.h_start << 16) | scope.h_end);
+ VSYNCOSD_WR_MPEG_REG(reg->vpp_osd2_bld_v_scope,
+ (scope.v_start << 16) | scope.v_end);
+}
+
+static int postblend_check_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state,
+ struct meson_vpu_pipeline_state *mvps)
+{
+ struct meson_vpu_postblend *postblend = to_postblend_block(vblk);
+
+ if (state->checked)
+ return 0;
+
+ state->checked = true;
+
+ DRM_DEBUG("%s check_state called.\n", postblend->base.name);
+ return 0;
+}
+
+static void postblend_set_state(struct meson_vpu_block *vblk,
+ struct meson_vpu_block_state *state)
+{
+ struct meson_vpu_postblend *postblend = to_postblend_block(vblk);
+ struct osd_scope_s scope = {0, 1919, 0, 1079};
+ struct meson_vpu_pipeline *pipeline = postblend->base.pipeline;
+ struct postblend_reg_s *reg = postblend->reg;
+ struct meson_vpu_pipeline_state *mvps;
+
+ DRM_DEBUG("%s set_state called.\n", postblend->base.name);
+ mvps = priv_to_pipeline_state(pipeline->obj.state);
+ scope.h_start = 0;
+ scope.h_end = mvps->scaler_param[0].output_width - 1;
+ scope.v_start = 0;
+ scope.v_end = mvps->scaler_param[0].output_height - 1;
+ vpp_osd1_blend_scope_set(reg, scope);
+ if (0)
+ vpp_osd2_blend_scope_set(reg, scope);
+ osd1_blend_premult_set(reg);
+ osd2_blend_premult_set(reg);
+ DRM_DEBUG("scope h/v start/end [%d,%d,%d,%d].\n",
+ scope.h_start, scope.h_end, scope.v_start, scope.v_end);
+}
+
+static void postblend_hw_enable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_postblend *postblend = to_postblend_block(vblk);
+
+ DRM_DEBUG("%s enable called.\n", postblend->base.name);
+}
+
+static void postblend_hw_disable(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_postblend *postblend = to_postblend_block(vblk);
+
+ DRM_DEBUG("%s disable called.\n", postblend->base.name);
+}
+
+static void postblend_hw_init(struct meson_vpu_block *vblk)
+{
+ struct meson_vpu_postblend *postblend = to_postblend_block(vblk);
+
+ postblend->reg = &postblend_reg;
+ /*dout switch config*/
+ osd1_blend_switch_set(postblend->reg, VPP_POSTBLEND);
+ osd2_blend_switch_set(postblend->reg, VPP_POSTBLEND);
+ /*vpp input config*/
+ vpp_osd1_preblend_mux_set(postblend->reg, VPP_NULL);
+ vpp_osd2_preblend_mux_set(postblend->reg, VPP_NULL);
+ vpp_osd1_postblend_mux_set(postblend->reg, VPP_OSD1);
+ vpp_osd2_postblend_mux_set(postblend->reg, VPP_NULL);
+ DRM_DEBUG("%s hw_init called.\n", postblend->base.name);
+}
+
+struct meson_vpu_block_ops postblend_ops = {
+ .check_state = postblend_check_state,
+ .update_state = postblend_set_state,
+ .enable = postblend_hw_enable,
+ .disable = postblend_hw_disable,
+ .init = postblend_hw_init,
+};
diff --git a/drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.h b/drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.h
new file mode 100644
index 0000000..9100074
--- a/dev/null
+++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.h
@@ -0,0 +1,59 @@
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef _MESON_VPU_POSTBLEND_H_
+#define _MESON_VPU_POSTBLEND_H_
+
+#define VPP_OSD1_IN_SIZE 0x1df1
+#define VPP_OSD1_BLD_H_SCOPE 0x1df5
+#define VPP_OSD1_BLD_V_SCOPE 0x1df6
+#define VPP_OSD2_BLD_H_SCOPE 0x1df7
+#define VPP_OSD2_BLD_V_SCOPE 0x1df8
+
+#define VD1_BLEND_SRC_CTRL 0x1dfb
+#define VD2_BLEND_SRC_CTRL 0x1dfc
+#define OSD1_BLEND_SRC_CTRL 0x1dfd
+#define OSD2_BLEND_SRC_CTRL 0x1dfe
+
+#define VPP_POST_BLEND_BLEND_DUMMY_DATA 0x3968
+#define VPP_POST_BLEND_DUMMY_ALPHA 0x3969
+
+struct postblend_reg_s {
+ u32 vpp_osd1_bld_h_scope;
+ u32 vpp_osd1_bld_v_scope;
+ u32 vpp_osd2_bld_h_scope;
+ u32 vpp_osd2_bld_v_scope;
+ u32 vd1_blend_src_ctrl;
+ u32 vd2_blend_src_ctrl;
+ u32 osd1_blend_src_ctrl;
+ u32 osd2_blend_src_ctrl;
+ u32 vpp_osd1_in_size;
+};
+
+enum vpp_blend_e {
+ VPP_PREBLEND = 0,
+ VPP_POSTBLEND,
+};
+
+enum vpp_blend_src_e {
+ VPP_NULL = 0,
+ VPP_VD1,
+ VPP_VD2,
+ VPP_OSD1,
+ VPP_OSD2
+};
+#endif
diff --git a/drivers/amlogic/drm/vpu-hw/meson_vpu_reg.h b/drivers/amlogic/drm/vpu-hw/meson_vpu_reg.h
new file mode 100644
index 0000000..6825636
--- a/dev/null
+++ b/drivers/amlogic/drm/vpu-hw/meson_vpu_reg.h
@@ -0,0 +1,1323 @@
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_reg.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __MESON_VPU_REG_H
+#define __MESON_VPU_REG_H
+
+#include "meson_osd_scaler.h"
+#include "meson_vpu_osd_mif.h"
+#include "meson_vpu_osdblend.h"
+
+/* vpp2 */
+#define VPP2_MISC 0x1e26
+#define VPP2_OFIFO_SIZE 0x1e27
+#define VPP2_INT_LINE_NUM 0x1e20
+#define VPP2_OFIFO_URG_CTRL 0x1e21
+#define VPP2_POSTBLEND_H_SIZE 0x1921
+
+/* viu */
+#define VIU_ADDR_START 0x1a00
+#define VIU_ADDR_END 0x1aff
+#define VIU_SW_RESET 0x1a01
+#define VIU_MISC_CTRL0 0x1a06
+#define D2D3_INTF_LENGTH 0x1a08
+#define D2D3_INTF_CTRL0 0x1a09
+
+
+#define VD1_IF0_GEN_REG 0x1a50
+#define VD1_IF0_CANVAS0 0x1a51
+#define VD1_IF0_CANVAS1 0x1a52
+#define VD1_IF0_LUMA_X0 0x1a53
+#define VD1_IF0_LUMA_Y0 0x1a54
+#define VD1_IF0_CHROMA_X0 0x1a55
+#define VD1_IF0_CHROMA_Y0 0x1a56
+#define VD1_IF0_LUMA_X1 0x1a57
+#define VD1_IF0_LUMA_Y1 0x1a58
+#define VD1_IF0_CHROMA_X1 0x1a59
+#define VD1_IF0_CHROMA_Y1 0x1a5a
+#define VD1_IF0_RPT_LOOP 0x1a5b
+#define VD1_IF0_LUMA0_RPT_PAT 0x1a5c
+#define VD1_IF0_CHROMA0_RPT_PAT 0x1a5d
+#define VD1_IF0_LUMA1_RPT_PAT 0x1a5e
+#define VD1_IF0_CHROMA1_RPT_PAT 0x1a5f
+#define VD1_IF0_LUMA_PSEL 0x1a60
+#define VD1_IF0_CHROMA_PSEL 0x1a61
+#define VD1_IF0_DUMMY_PIXEL 0x1a62
+#define VD1_IF0_LUMA_FIFO_SIZE 0x1a63
+#define VD1_IF0_RANGE_MAP_Y 0x1a6a
+#define VD1_IF0_RANGE_MAP_CB 0x1a6b
+#define VD1_IF0_RANGE_MAP_CR 0x1a6c
+#define VD1_IF0_GEN_REG2 0x1a6d
+#define VD1_IF0_PROT_CNTL 0x1a6e
+#define VIU_VD1_FMT_CTRL 0x1a68
+#define VIU_VD1_FMT_W 0x1a69
+#define VD2_IF0_GEN_REG 0x1a70
+#define VD2_IF0_CANVAS0 0x1a71
+#define VD2_IF0_CANVAS1 0x1a72
+#define VD2_IF0_LUMA_X0 0x1a73
+#define VD2_IF0_LUMA_Y0 0x1a74
+#define VD2_IF0_CHROMA_X0 0x1a75
+#define VD2_IF0_CHROMA_Y0 0x1a76
+#define VD2_IF0_LUMA_X1 0x1a77
+#define VD2_IF0_LUMA_Y1 0x1a78
+#define VD2_IF0_CHROMA_X1 0x1a79
+#define VD2_IF0_CHROMA_Y1 0x1a7a
+#define VD2_IF0_RPT_LOOP 0x1a7b
+#define VD2_IF0_LUMA0_RPT_PAT 0x1a7c
+#define VD2_IF0_CHROMA0_RPT_PAT 0x1a7d
+#define VD2_IF0_LUMA1_RPT_PAT 0x1a7e
+#define VD2_IF0_CHROMA1_RPT_PAT 0x1a7f
+#define VD2_IF0_LUMA_PSEL 0x1a80
+#define VD2_IF0_CHROMA_PSEL 0x1a81
+#define VD2_IF0_DUMMY_PIXEL 0x1a82
+#define VD2_IF0_LUMA_FIFO_SIZE 0x1a83
+#define VD2_IF0_RANGE_MAP_Y 0x1a8a
+#define VD2_IF0_RANGE_MAP_CB 0x1a8b
+#define VD2_IF0_RANGE_MAP_CR 0x1a8c
+#define VD2_IF0_GEN_REG2 0x1a8d
+#define VD2_IF0_PROT_CNTL 0x1a8e
+#define VIU_VD2_FMT_CTRL 0x1a88
+#define VIU_VD2_FMT_W 0x1a89
+
+#define VIU_OSD1_MATRIX_CTRL 0x1a90
+#define VIU_OSD1_MATRIX_COEF00_01 0x1a91
+#define VIU_OSD1_MATRIX_COEF02_10 0x1a92
+#define VIU_OSD1_MATRIX_COEF11_12 0x1a93
+#define VIU_OSD1_MATRIX_COEF20_21 0x1a94
+#define VIU_OSD1_MATRIX_COLMOD_COEF42 0x1a95
+#define VIU_OSD1_MATRIX_OFFSET0_1 0x1a96
+#define VIU_OSD1_MATRIX_OFFSET2 0x1a97
+#define VIU_OSD1_MATRIX_PRE_OFFSET0_1 0x1a98
+#define VIU_OSD1_MATRIX_PRE_OFFSET2 0x1a99
+#define VIU_OSD1_MATRIX_COEF22_30 0x1a9d
+#define VIU_OSD1_MATRIX_COEF31_32 0x1a9e
+#define VIU_OSD1_MATRIX_COEF40_41 0x1a9f
+
+#define VIU_OSD_BLENDO_H_START_END 0x1aa9
+#define VIU_OSD_BLENDO_V_START_END 0x1aaa
+#define VIU_OSD_BLEND_GEN_CTRL0 0x1aab
+#define VIU_OSD_BLEND_GEN_CTRL1 0x1aac
+#define VIU_OSD_BLEND_DUMMY_DATA 0x1aad
+#define VIU_OSD_BLEND_CURRENT_XY 0x1aae
+
+#define VIU_OSD2_MATRIX_CTRL 0x1ab0
+#define VIU_OSD2_MATRIX_COEF00_01 0x1ab1
+#define VIU_OSD2_MATRIX_COEF02_10 0x1ab2
+#define VIU_OSD2_MATRIX_COEF11_12 0x1ab3
+#define VIU_OSD2_MATRIX_COEF20_21 0x1ab4
+#define VIU_OSD2_MATRIX_COEF22 0x1ab5
+#define VIU_OSD2_MATRIX_OFFSET0_1 0x1ab6
+#define VIU_OSD2_MATRIX_OFFSET2 0x1ab7
+#define VIU_OSD2_MATRIX_PRE_OFFSET0_1 0x1ab8
+#define VIU_OSD2_MATRIX_PRE_OFFSET2 0x1ab9
+#define VIU_OSD2_MATRIX_PROBE_COLOR 0x1aba
+#define VIU_OSD2_MATRIX_HL_COLOR 0x1abb
+#define VIU_OSD2_MATRIX_PROBE_POS 0x1abc
+#define VIU_OSD1_EOTF_CTL 0x1ad4
+#define VIU_OSD1_EOTF_COEF00_01 0x1ad5
+#define VIU_OSD1_EOTF_COEF02_10 0x1ad6
+#define VIU_OSD1_EOTF_COEF11_12 0x1ad7
+#define VIU_OSD1_EOTF_COEF20_21 0x1ad8
+#define VIU_OSD1_EOTF_COEF22_RS 0x1ad9
+#define VIU_OSD1_EOTF_LUT_ADDR_PORT 0x1ada
+#define VIU_OSD1_EOTF_LUT_DATA_PORT 0x1adb
+#define VIU_OSD1_OETF_CTL 0x1adc
+#define VIU_OSD1_OETF_LUT_ADDR_PORT 0x1add
+#define VIU_OSD1_OETF_LUT_DATA_PORT 0x1ade
+
+/* vpp */
+#define VPP_DUMMY_DATA 0x1d00
+#define VPP_LINE_IN_LENGTH 0x1d01
+#define VPP_PIC_IN_HEIGHT 0x1d02
+#define VPP_SCALE_COEF_IDX 0x1d03
+#define VPP_SCALE_COEF 0x1d04
+#define VPP_VSC_REGION12_STARTP 0x1d05
+#define VPP_VSC_REGION34_STARTP 0x1d06
+#define VPP_VSC_REGION4_ENDP 0x1d07
+#define VPP_VSC_START_PHASE_STEP 0x1d08
+#define VPP_VSC_REGION0_PHASE_SLOPE 0x1d09
+#define VPP_VSC_REGION1_PHASE_SLOPE 0x1d0a
+#define VPP_VSC_REGION3_PHASE_SLOPE 0x1d0b
+#define VPP_VSC_REGION4_PHASE_SLOPE 0x1d0c
+#define VPP_VSC_PHASE_CTRL 0x1d0d
+#define VPP_VSC_INI_PHASE 0x1d0e
+#define VPP_HSC_REGION12_STARTP 0x1d10
+#define VPP_HSC_REGION34_STARTP 0x1d11
+#define VPP_HSC_REGION4_ENDP 0x1d12
+#define VPP_HSC_START_PHASE_STEP 0x1d13
+#define VPP_HSC_REGION0_PHASE_SLOPE 0x1d14
+#define VPP_HSC_REGION1_PHASE_SLOPE 0x1d15
+#define VPP_HSC_REGION3_PHASE_SLOPE 0x1d16
+#define VPP_HSC_REGION4_PHASE_SLOPE 0x1d17
+#define VPP_HSC_PHASE_CTRL 0x1d18
+#define VPP_SC_MISC 0x1d19
+#define VPP_PREBLEND_VD1_H_START_END 0x1d1a
+#define VPP_PREBLEND_VD1_V_START_END 0x1d1b
+#define VPP_POSTBLEND_VD1_H_START_END 0x1d1c
+#define VPP_POSTBLEND_VD1_V_START_END 0x1d1d
+#define VPP_BLEND_VD2_H_START_END 0x1d1e
+#define VPP_BLEND_VD2_V_START_END 0x1d1f
+#define VPP_PREBLEND_H_SIZE 0x1d20
+#define VPP_POSTBLEND_H_SIZE 0x1d21
+#define VPP_HOLD_LINES 0x1d22
+#define VPP_BLEND_ONECOLOR_CTRL 0x1d23
+#define VPP_PREBLEND_CURRENT_XY 0x1d24
+#define VPP_POSTBLEND_CURRENT_XY 0x1d25
+#define VPP_MISC 0x1d26
+#define VPP_OFIFO_SIZE 0x1d27
+#define VPP_FIFO_STATUS 0x1d28
+#define VPP_SMOKE_CTRL 0x1d29
+#define VPP_SMOKE1_VAL 0x1d2a
+#define VPP_SMOKE2_VAL 0x1d2b
+#define VPP_SMOKE3_VAL 0x1d2c
+#define VPP_SMOKE1_H_START_END 0x1d2d
+#define VPP_SMOKE1_V_START_END 0x1d2e
+#define VPP_SMOKE2_H_START_END 0x1d2f
+#define VPP_SMOKE2_V_START_END 0x1d30
+#define VPP_SMOKE3_H_START_END 0x1d31
+#define VPP_SMOKE3_V_START_END 0x1d32
+#define VPP_SCO_FIFO_CTRL 0x1d33
+#define VPP_HSC_PHASE_CTRL1 0x1d34
+#define VPP_HSC_INI_PAT_CTRL 0x1d35
+#define VPP_VADJ_CTRL 0x1d40
+#define VPP_VADJ1_Y 0x1d41
+#define VPP_VADJ1_MA_MB 0x1d42
+#define VPP_VADJ1_MC_MD 0x1d43
+#define VPP_VADJ2_Y 0x1d44
+#define VPP_VADJ2_MA_MB 0x1d45
+#define VPP_VADJ2_MC_MD 0x1d46
+#define VPP_HSHARP_CTRL 0x1d50
+#define VPP_HSHARP_LUMA_THRESH01 0x1d51
+#define VPP_HSHARP_LUMA_THRESH23 0x1d52
+#define VPP_HSHARP_CHROMA_THRESH01 0x1d53
+#define VPP_HSHARP_CHROMA_THRESH23 0x1d54
+#define VPP_HSHARP_LUMA_GAIN 0x1d55
+#define VPP_HSHARP_CHROMA_GAIN 0x1d56
+#define VPP_MATRIX_PROBE_COLOR 0x1d5c
+#define VPP_MATRIX_HL_COLOR 0x1d5d
+#define VPP_MATRIX_PROBE_POS 0x1d5e
+#define VPP_MATRIX_CTRL 0x1d5f
+#define VPP_MATRIX_COEF00_01 0x1d60
+#define VPP_MATRIX_COEF02_10 0x1d61
+#define VPP_MATRIX_COEF11_12 0x1d62
+#define VPP_MATRIX_COEF20_21 0x1d63
+#define VPP_MATRIX_COEF22 0x1d64
+#define VPP_MATRIX_OFFSET0_1 0x1d65
+#define VPP_MATRIX_OFFSET2 0x1d66
+#define VPP_MATRIX_PRE_OFFSET0_1 0x1d67
+#define VPP_MATRIX_PRE_OFFSET2 0x1d68
+#define VPP_DUMMY_DATA1 0x1d69
+#define VPP_GAINOFF_CTRL0 0x1d6a
+#define VPP_GAINOFF_CTRL1 0x1d6b
+#define VPP_GAINOFF_CTRL2 0x1d6c
+#define VPP_GAINOFF_CTRL3 0x1d6d
+#define VPP_GAINOFF_CTRL4 0x1d6e
+#define VPP_CHROMA_ADDR_PORT 0x1d70
+#define VPP_CHROMA_DATA_PORT 0x1d71
+#define VPP_GCLK_CTRL0 0x1d72
+#define VPP_GCLK_CTRL1 0x1d73
+#define VPP_SC_GCLK_CTRL 0x1d74
+#define VPP_MISC1 0x1d76
+#define VPP_BLACKEXT_CTRL 0x1d80
+#define VPP_DNLP_CTRL_00 0x1d81
+#define VPP_DNLP_CTRL_01 0x1d82
+#define VPP_DNLP_CTRL_02 0x1d83
+#define VPP_DNLP_CTRL_03 0x1d84
+#define VPP_DNLP_CTRL_04 0x1d85
+#define VPP_DNLP_CTRL_05 0x1d86
+#define VPP_DNLP_CTRL_06 0x1d87
+#define VPP_DNLP_CTRL_07 0x1d88
+#define VPP_DNLP_CTRL_08 0x1d89
+#define VPP_DNLP_CTRL_09 0x1d8a
+#define VPP_DNLP_CTRL_10 0x1d8b
+#define VPP_DNLP_CTRL_11 0x1d8c
+#define VPP_DNLP_CTRL_12 0x1d8d
+#define VPP_DNLP_CTRL_13 0x1d8e
+#define VPP_DNLP_CTRL_14 0x1d8f
+#define VPP_DNLP_CTRL_15 0x1d90
+#define VPP_PEAKING_HGAIN 0x1d91
+#define VPP_PEAKING_VGAIN 0x1d92
+#define VPP_PEAKING_NLP_1 0x1d93
+#define VPP_PEAKING_NLP_2 0x1d94
+#define VPP_PEAKING_NLP_3 0x1d95
+#define VPP_PEAKING_NLP_4 0x1d96
+#define VPP_PEAKING_NLP_5 0x1d97
+#define VPP_SHARP_LIMIT 0x1d98
+#define VPP_VLTI_CTRL 0x1d99
+#define VPP_HLTI_CTRL 0x1d9a
+#define VPP_CTI_CTRL 0x1d9b
+#define VPP_BLUE_STRETCH_1 0x1d9c
+#define VPP_BLUE_STRETCH_2 0x1d9d
+#define VPP_BLUE_STRETCH_3 0x1d9e
+#define VPP_CCORING_CTRL 0x1da0
+#define VPP_VE_ENABLE_CTRL 0x1da1
+#define VPP_VE_DEMO_LEFT_TOP_SCREEN_WIDTH 0x1da2
+#define VPP_VE_DEMO_CENTER_BAR 0x1da3
+#define VPP_VE_H_V_SIZE 0x1da4
+#define VPP_VDO_MEAS_CTRL 0x1da8
+#define VPP_VDO_MEAS_VS_COUNT_HI 0x1da9
+#define VPP_VDO_MEAS_VS_COUNT_LO 0x1daa
+#define VPP_INPUT_CTRL 0x1dab
+#define VPP_CTI_CTRL2 0x1dac
+#define VPP_PEAKING_SAT_THD1 0x1dad
+#define VPP_PEAKING_SAT_THD2 0x1dae
+#define VPP_PEAKING_SAT_THD3 0x1daf
+#define VPP_PEAKING_SAT_THD4 0x1db0
+#define VPP_PEAKING_SAT_THD5 0x1db1
+#define VPP_PEAKING_SAT_THD6 0x1db2
+#define VPP_PEAKING_SAT_THD7 0x1db3
+#define VPP_PEAKING_SAT_THD8 0x1db4
+#define VPP_PEAKING_SAT_THD9 0x1db5
+#define VPP_PEAKING_GAIN_ADD1 0x1db6
+#define VPP_PEAKING_GAIN_ADD2 0x1db7
+#define VPP_PEAKING_DNLP 0x1db8
+#define VPP_SHARP_DEMO_WIN_CTRL1 0x1db9
+#define VPP_SHARP_DEMO_WIN_CTRL2 0x1dba
+#define VPP_FRONT_HLTI_CTRL 0x1dbb
+#define VPP_FRONT_CTI_CTRL 0x1dbc
+#define VPP_FRONT_CTI_CTRL2 0x1dbd
+#define VPP_INT_LINE_NUM 0x1dce
+
+/* viu2 */
+#define VIU2_ADDR_START 0x1e00
+#define VIU2_ADDR_END 0x1eff
+#define VIU2_SW_RESET 0x1e01
+#define VIU2_SW_RESET0 0x1e02
+#define VIU2_SECURE_REG 0x1e05
+#define VIU2_MISC_CTRL0 0x1e06
+#define VIU2_OSD1_CTRL_STAT 0x1e30
+#define VIU2_OSD1_CTRL_STAT2 0x1e4d
+#define VIU2_OSD1_COLOR_ADDR 0x1e31
+#define VIU2_OSD1_COLOR 0x1e32
+#define VIU2_OSD1_HL1_H_START_END 0x1e33
+#define VIU2_OSD1_HL1_V_START_END 0x1e34
+#define VIU2_OSD1_HL2_H_START_END 0x1e35
+#define VIU2_OSD1_HL2_V_START_END 0x1e36
+#define VIU2_OSD1_TCOLOR_AG0 0x1e37
+#define VIU2_OSD1_TCOLOR_AG1 0x1e38
+#define VIU2_OSD1_TCOLOR_AG2 0x1e39
+#define VIU2_OSD1_TCOLOR_AG3 0x1e3a
+#define VIU2_OSD1_BLK0_CFG_W0 0x1e3b
+#define VIU2_OSD1_BLK1_CFG_W0 0x1e3f
+#define VIU2_OSD1_BLK2_CFG_W0 0x1e43
+#define VIU2_OSD1_BLK3_CFG_W0 0x1e47
+#define VIU2_OSD1_BLK0_CFG_W1 0x1e3c
+#define VIU2_OSD1_BLK1_CFG_W1 0x1e40
+#define VIU2_OSD1_BLK2_CFG_W1 0x1e44
+#define VIU2_OSD1_BLK3_CFG_W1 0x1e48
+#define VIU2_OSD1_BLK0_CFG_W2 0x1e3d
+#define VIU2_OSD1_BLK1_CFG_W2 0x1e41
+#define VIU2_OSD1_BLK2_CFG_W2 0x1e45
+#define VIU2_OSD1_BLK3_CFG_W2 0x1e49
+#define VIU2_OSD1_BLK0_CFG_W3 0x1e3e
+#define VIU2_OSD1_BLK1_CFG_W3 0x1e42
+#define VIU2_OSD1_BLK2_CFG_W3 0x1e46
+#define VIU2_OSD1_BLK3_CFG_W3 0x1e4a
+#define VIU2_OSD1_BLK0_CFG_W4 0x1e64
+#define VIU2_OSD1_BLK1_CFG_W4 0x1e65
+#define VIU2_OSD1_BLK2_CFG_W4 0x1e66
+#define VIU2_OSD1_BLK3_CFG_W4 0x1e67
+#define VIU2_OSD1_FIFO_CTRL_STAT 0x1e4b
+#define VIU2_OSD1_TEST_RDDATA 0x1e4c
+#define VIU2_OSD1_PROT_CTRL 0x1e4e
+#define VIU2_OSD1_MALI_UNPACK_CTRL 0x1e4f
+#define VIU2_OSD1_DIMM_CTRL 0x1e50
+#define VIU2_OSD1_UNSUPPORT VIU_OSD2_TCOLOR_AG3
+/* viu2 rotate */
+#define VIU2_RMIF_CTRL1 0x1e81
+#define VIU2_RMIF_SCOPE_X 0x1e83
+#define VIU2_RMIF_SCOPE_Y 0x1e84
+#define VIU2_ROT_BLK_SIZE 0x1e85
+#define VIU2_ROT_LBUF_SIZE 0x1e86
+#define VIU2_ROT_FMT_CTRL 0x1e87
+#define VIU2_ROT_OUT_VCROP 0x1e89
+
+/* encode */
+#define ENCP_VFIFO2VD_CTL 0x1b58
+#define ENCP_VFIFO2VD_PIXEL_START 0x1b59
+#define ENCP_VFIFO2VD_PIXEL_END 0x1b5a
+#define ENCP_VFIFO2VD_LINE_TOP_START 0x1b5b
+#define ENCP_VFIFO2VD_LINE_TOP_END 0x1b5c
+#define ENCP_VFIFO2VD_LINE_BOT_START 0x1b5d
+#define ENCP_VFIFO2VD_LINE_BOT_END 0x1b5e
+#define VENC_SYNC_ROUTE 0x1b60
+#define VENC_VIDEO_EXSRC 0x1b61
+#define VENC_DVI_SETTING 0x1b62
+#define VENC_C656_CTRL 0x1b63
+#define VENC_UPSAMPLE_CTRL0 0x1b64
+#define VENC_UPSAMPLE_CTRL1 0x1b65
+#define VENC_UPSAMPLE_CTRL2 0x1b66
+#define TCON_INVERT_CTL 0x1b67
+#define VENC_VIDEO_PROG_MODE 0x1b68
+#define VENC_ENCI_LINE 0x1b69
+#define VENC_ENCI_PIXEL 0x1b6a
+#define VENC_ENCP_LINE 0x1b6b
+#define VENC_ENCP_PIXEL 0x1b6c
+#define VENC_STATA 0x1b6d
+#define VENC_INTCTRL 0x1b6e
+#define VENC_INTFLAG 0x1b6f
+#define VENC_VIDEO_TST_EN 0x1b70
+#define VENC_VIDEO_TST_MDSEL 0x1b71
+#define VENC_VIDEO_TST_Y 0x1b72
+#define VENC_VIDEO_TST_CB 0x1b73
+#define VENC_VIDEO_TST_CR 0x1b74
+#define VENC_VIDEO_TST_CLRBAR_STRT 0x1b75
+#define VENC_VIDEO_TST_CLRBAR_WIDTH 0x1b76
+#define VENC_VIDEO_TST_VDCNT_STSET 0x1b77
+#define VENC_VDAC_DACSEL0 0x1b78
+#define VENC_VDAC_DACSEL1 0x1b79
+#define VENC_VDAC_DACSEL2 0x1b7a
+#define VENC_VDAC_DACSEL3 0x1b7b
+#define VENC_VDAC_DACSEL4 0x1b7c
+#define VENC_VDAC_DACSEL5 0x1b7d
+#define VENC_VDAC_SETTING 0x1b7e
+#define VENC_VDAC_TST_VAL 0x1b7f
+#define VENC_VDAC_DAC0_GAINCTRL 0x1bf0
+#define VENC_VDAC_DAC0_OFFSET 0x1bf1
+#define VENC_VDAC_DAC1_GAINCTRL 0x1bf2
+#define VENC_VDAC_DAC1_OFFSET 0x1bf3
+#define VENC_VDAC_DAC2_GAINCTRL 0x1bf4
+#define VENC_VDAC_DAC2_OFFSET 0x1bf5
+#define VENC_VDAC_DAC3_GAINCTRL 0x1bf6
+#define VENC_VDAC_DAC3_OFFSET 0x1bf7
+#define VENC_VDAC_DAC4_GAINCTRL 0x1bf8
+#define VENC_VDAC_DAC4_OFFSET 0x1bf9
+#define VENC_VDAC_DAC5_GAINCTRL 0x1bfa
+#define VENC_VDAC_DAC5_OFFSET 0x1bfb
+#define VENC_VDAC_FIFO_CTRL 0x1bfc
+#define ENCL_TCON_INVERT_CTL 0x1bfd
+#define ENCP_VIDEO_EN 0x1b80
+#define ENCP_VIDEO_SYNC_MODE 0x1b81
+#define ENCP_MACV_EN 0x1b82
+#define ENCP_VIDEO_Y_SCL 0x1b83
+#define ENCP_VIDEO_PB_SCL 0x1b84
+#define ENCP_VIDEO_PR_SCL 0x1b85
+#define ENCP_VIDEO_SYNC_SCL 0x1b86
+#define ENCP_VIDEO_MACV_SCL 0x1b87
+#define ENCP_VIDEO_Y_OFFST 0x1b88
+#define ENCP_VIDEO_PB_OFFST 0x1b89
+#define ENCP_VIDEO_PR_OFFST 0x1b8a
+#define ENCP_VIDEO_SYNC_OFFST 0x1b8b
+#define ENCP_VIDEO_MACV_OFFST 0x1b8c
+#define ENCP_VIDEO_MODE 0x1b8d
+#define ENCP_VIDEO_MODE_ADV 0x1b8e
+#define ENCP_DBG_PX_RST 0x1b90
+#define ENCP_DBG_LN_RST 0x1b91
+#define ENCP_DBG_PX_INT 0x1b92
+#define ENCP_DBG_LN_INT 0x1b93
+#define ENCP_VIDEO_YFP1_HTIME 0x1b94
+#define ENCP_VIDEO_YFP2_HTIME 0x1b95
+#define ENCP_VIDEO_YC_DLY 0x1b96
+#define ENCP_VIDEO_MAX_PXCNT 0x1b97
+#define ENCP_VIDEO_HSPULS_BEGIN 0x1b98
+#define ENCP_VIDEO_HSPULS_END 0x1b99
+#define ENCP_VIDEO_HSPULS_SWITCH 0x1b9a
+#define ENCP_VIDEO_VSPULS_BEGIN 0x1b9b
+#define ENCP_VIDEO_VSPULS_END 0x1b9c
+#define ENCP_VIDEO_VSPULS_BLINE 0x1b9d
+#define ENCP_VIDEO_VSPULS_ELINE 0x1b9e
+#define ENCP_VIDEO_EQPULS_BEGIN 0x1b9f
+#define ENCP_VIDEO_EQPULS_END 0x1ba0
+#define ENCP_VIDEO_EQPULS_BLINE 0x1ba1
+#define ENCP_VIDEO_EQPULS_ELINE 0x1ba2
+#define ENCP_VIDEO_HAVON_END 0x1ba3
+#define ENCP_VIDEO_HAVON_BEGIN 0x1ba4
+#define ENCP_VIDEO_VAVON_ELINE 0x1baf
+#define ENCP_VIDEO_VAVON_BLINE 0x1ba6
+#define ENCP_VIDEO_HSO_BEGIN 0x1ba7
+#define ENCP_VIDEO_HSO_END 0x1ba8
+#define ENCP_VIDEO_VSO_BEGIN 0x1ba9
+#define ENCP_VIDEO_VSO_END 0x1baa
+#define ENCP_VIDEO_VSO_BLINE 0x1bab
+#define ENCP_VIDEO_VSO_ELINE 0x1bac
+#define ENCP_VIDEO_SYNC_WAVE_CURVE 0x1bad
+#define ENCP_VIDEO_MAX_LNCNT 0x1bae
+#define ENCP_VIDEO_SY_VAL 0x1bb0
+#define ENCP_VIDEO_SY2_VAL 0x1bb1
+#define ENCP_VIDEO_BLANKY_VAL 0x1bb2
+#define ENCP_VIDEO_BLANKPB_VAL 0x1bb3
+#define ENCP_VIDEO_BLANKPR_VAL 0x1bb4
+#define ENCP_VIDEO_HOFFST 0x1bb5
+#define ENCP_VIDEO_VOFFST 0x1bb6
+#define ENCP_VIDEO_RGB_CTRL 0x1bb7
+#define ENCP_VIDEO_FILT_CTRL 0x1bb8
+#define ENCP_VIDEO_OFLD_VPEQ_OFST 0x1bb9
+#define ENCP_VIDEO_OFLD_VOAV_OFST 0x1bba
+#define ENCP_VIDEO_MATRIX_CB 0x1bbb
+#define ENCP_VIDEO_MATRIX_CR 0x1bbc
+#define ENCP_VIDEO_RGBIN_CTRL 0x1bbd
+#define ENCP_MACV_BLANKY_VAL 0x1bc0
+#define ENCP_MACV_MAXY_VAL 0x1bc1
+#define ENCP_MACV_1ST_PSSYNC_STRT 0x1bc2
+#define ENCP_MACV_PSSYNC_STRT 0x1bc3
+#define ENCP_MACV_AGC_STRT 0x1bc4
+#define ENCP_MACV_AGC_END 0x1bc5
+#define ENCP_MACV_WAVE_END 0x1bc6
+#define ENCP_MACV_STRTLINE 0x1bc7
+#define ENCP_MACV_ENDLINE 0x1bc8
+#define ENCP_MACV_TS_CNT_MAX_L 0x1bc9
+#define ENCP_MACV_TS_CNT_MAX_H 0x1bca
+#define ENCP_MACV_TIME_DOWN 0x1bcb
+#define ENCP_MACV_TIME_LO 0x1bcc
+#define ENCP_MACV_TIME_UP 0x1bcd
+#define ENCP_MACV_TIME_RST 0x1bce
+#define ENCP_VBI_CTRL 0x1bd0
+#define ENCP_VBI_SETTING 0x1bd1
+#define ENCP_VBI_BEGIN 0x1bd2
+#define ENCP_VBI_WIDTH 0x1bd3
+#define ENCP_VBI_HVAL 0x1bd4
+#define ENCP_VBI_DATA0 0x1bd5
+#define ENCP_VBI_DATA1 0x1bd6
+#define C656_HS_ST 0x1be0
+#define C656_HS_ED 0x1be1
+#define C656_VS_LNST_E 0x1be2
+#define C656_VS_LNST_O 0x1be3
+#define C656_VS_LNED_E 0x1be4
+#define C656_VS_LNED_O 0x1be5
+#define C656_FS_LNST 0x1be6
+#define C656_FS_LNED 0x1be7
+#define ENCI_VIDEO_MODE 0x1b00
+#define ENCI_VIDEO_MODE_ADV 0x1b01
+#define ENCI_VIDEO_FSC_ADJ 0x1b02
+#define ENCI_VIDEO_BRIGHT 0x1b03
+#define ENCI_VIDEO_CONT 0x1b04
+#define ENCI_VIDEO_SAT 0x1b05
+#define ENCI_VIDEO_HUE 0x1b06
+#define ENCI_VIDEO_SCH 0x1b07
+#define ENCI_SYNC_MODE 0x1b08
+#define ENCI_SYNC_CTRL 0x1b09
+#define ENCI_SYNC_HSO_BEGIN 0x1b0a
+#define ENCI_SYNC_HSO_END 0x1b0b
+#define ENCI_SYNC_VSO_EVN 0x1b0c
+#define ENCI_SYNC_VSO_ODD 0x1b0d
+#define ENCI_SYNC_VSO_EVNLN 0x1b0e
+#define ENCI_SYNC_VSO_ODDLN 0x1b0f
+#define ENCI_SYNC_HOFFST 0x1b10
+#define ENCI_SYNC_VOFFST 0x1b11
+#define ENCI_SYNC_ADJ 0x1b12
+#define ENCI_RGB_SETTING 0x1b13
+#define ENCI_DE_H_BEGIN 0x1b16
+#define ENCI_DE_H_END 0x1b17
+#define ENCI_DE_V_BEGIN_EVEN 0x1b18
+#define ENCI_DE_V_END_EVEN 0x1b19
+#define ENCI_DE_V_BEGIN_ODD 0x1b1a
+#define ENCI_DE_V_END_ODD 0x1b1b
+#define ENCI_VBI_SETTING 0x1b20
+#define ENCI_VBI_CCDT_EVN 0x1b21
+#define ENCI_VBI_CCDT_ODD 0x1b22
+#define ENCI_VBI_CC525_LN 0x1b23
+#define ENCI_VBI_CC625_LN 0x1b24
+#define ENCI_VBI_WSSDT 0x1b25
+#define ENCI_VBI_WSS_LN 0x1b26
+#define ENCI_VBI_CGMSDT_L 0x1b27
+#define ENCI_VBI_CGMSDT_H 0x1b28
+#define ENCI_VBI_CGMS_LN 0x1b29
+#define ENCI_VBI_TTX_HTIME 0x1b2a
+#define ENCI_VBI_TTX_LN 0x1b2b
+#define ENCI_VBI_TTXDT0 0x1b2c
+#define ENCI_VBI_TTXDT1 0x1b2d
+#define ENCI_VBI_TTXDT2 0x1b2e
+#define ENCI_VBI_TTXDT3 0x1b2f
+#define ENCI_MACV_N0 0x1b30
+#define ENCI_MACV_N1 0x1b31
+#define ENCI_MACV_N2 0x1b32
+#define ENCI_MACV_N3 0x1b33
+#define ENCI_MACV_N4 0x1b34
+#define ENCI_MACV_N5 0x1b35
+#define ENCI_MACV_N6 0x1b36
+#define ENCI_MACV_N7 0x1b37
+#define ENCI_MACV_N8 0x1b38
+#define ENCI_MACV_N9 0x1b39
+#define ENCI_MACV_N10 0x1b3a
+#define ENCI_MACV_N11 0x1b3b
+#define ENCI_MACV_N12 0x1b3c
+#define ENCI_MACV_N13 0x1b3d
+#define ENCI_MACV_N14 0x1b3e
+#define ENCI_MACV_N15 0x1b3f
+#define ENCI_MACV_N16 0x1b40
+#define ENCI_MACV_N17 0x1b41
+#define ENCI_MACV_N18 0x1b42
+#define ENCI_MACV_N19 0x1b43
+#define ENCI_MACV_N20 0x1b44
+#define ENCI_MACV_N21 0x1b45
+#define ENCI_MACV_N22 0x1b46
+#define ENCI_DBG_PX_RST 0x1b48
+#define ENCI_DBG_FLDLN_RST 0x1b49
+#define ENCI_DBG_PX_INT 0x1b4a
+#define ENCI_DBG_FLDLN_INT 0x1b4b
+#define ENCI_DBG_MAXPX 0x1b4c
+#define ENCI_DBG_MAXLN 0x1b4d
+#define ENCI_MACV_MAX_AMP 0x1b50
+#define ENCI_MACV_PULSE_LO 0x1b51
+#define ENCI_MACV_PULSE_HI 0x1b52
+#define ENCI_MACV_BKP_MAX 0x1b53
+#define ENCI_CFILT_CTRL 0x1b54
+#define ENCI_CFILT7 0x1b55
+#define ENCI_YC_DELAY 0x1b56
+#define ENCI_VIDEO_EN 0x1b57
+#define ENCI_DVI_HSO_BEGIN 0x1c00
+#define ENCI_DVI_HSO_END 0x1c01
+#define ENCI_DVI_VSO_BLINE_EVN 0x1c02
+#define ENCI_DVI_VSO_BLINE_ODD 0x1c03
+#define ENCI_DVI_VSO_ELINE_EVN 0x1c04
+#define ENCI_DVI_VSO_ELINE_ODD 0x1c05
+#define ENCI_DVI_VSO_BEGIN_EVN 0x1c06
+#define ENCI_DVI_VSO_BEGIN_ODD 0x1c07
+#define ENCI_DVI_VSO_END_EVN 0x1c08
+#define ENCI_DVI_VSO_END_ODD 0x1c09
+#define ENCI_CFILT_CTRL2 0x1c0a
+#define ENCI_DACSEL_0 0x1c0b
+#define ENCI_DACSEL_1 0x1c0c
+#define ENCP_DACSEL_0 0x1c0d
+#define ENCP_DACSEL_1 0x1c0e
+#define ENCP_MAX_LINE_SWITCH_POINT 0x1c0f
+#define ENCI_TST_EN 0x1c10
+#define ENCI_TST_MDSEL 0x1c11
+#define ENCI_TST_Y 0x1c12
+#define ENCI_TST_CB 0x1c13
+#define ENCI_TST_CR 0x1c14
+#define ENCI_TST_CLRBAR_STRT 0x1c15
+#define ENCI_TST_CLRBAR_WIDTH 0x1c16
+#define ENCI_TST_VDCNT_STSET 0x1c17
+#define ENCI_VFIFO2VD_CTL 0x1c18
+#define ENCI_VFIFO2VD_PIXEL_START 0x1c19
+#define ENCI_VFIFO2VD_PIXEL_END 0x1c1a
+#define ENCI_VFIFO2VD_LINE_TOP_START 0x1c1b
+#define ENCI_VFIFO2VD_LINE_TOP_END 0x1c1c
+#define ENCI_VFIFO2VD_LINE_BOT_START 0x1c1d
+#define ENCI_VFIFO2VD_LINE_BOT_END 0x1c1e
+#define ENCI_VFIFO2VD_CTL2 0x1c1f
+#define ENCT_VFIFO2VD_CTL 0x1c20
+#define ENCT_VFIFO2VD_PIXEL_START 0x1c21
+#define ENCT_VFIFO2VD_PIXEL_END 0x1c22
+#define ENCT_VFIFO2VD_LINE_TOP_START 0x1c23
+#define ENCT_VFIFO2VD_LINE_TOP_END 0x1c24
+#define ENCT_VFIFO2VD_LINE_BOT_START 0x1c25
+#define ENCT_VFIFO2VD_LINE_BOT_END 0x1c26
+#define ENCT_VFIFO2VD_CTL2 0x1c27
+#define ENCT_TST_EN 0x1c28
+#define ENCT_TST_MDSEL 0x1c29
+#define ENCT_TST_Y 0x1c2a
+#define ENCT_TST_CB 0x1c2b
+#define ENCT_TST_CR 0x1c2c
+#define ENCT_TST_CLRBAR_STRT 0x1c2d
+#define ENCT_TST_CLRBAR_WIDTH 0x1c2e
+#define ENCT_TST_VDCNT_STSET 0x1c2f
+#define ENCP_DVI_HSO_BEGIN 0x1c30
+#define ENCP_DVI_HSO_END 0x1c31
+#define ENCP_DVI_VSO_BLINE_EVN 0x1c32
+#define ENCP_DVI_VSO_BLINE_ODD 0x1c33
+#define ENCP_DVI_VSO_ELINE_EVN 0x1c34
+#define ENCP_DVI_VSO_ELINE_ODD 0x1c35
+#define ENCP_DVI_VSO_BEGIN_EVN 0x1c36
+#define ENCP_DVI_VSO_BEGIN_ODD 0x1c37
+#define ENCP_DVI_VSO_END_EVN 0x1c38
+#define ENCP_DVI_VSO_END_ODD 0x1c39
+#define ENCP_DE_H_BEGIN 0x1c3a
+#define ENCP_DE_H_END 0x1c3b
+#define ENCP_DE_V_BEGIN_EVEN 0x1c3c
+#define ENCP_DE_V_END_EVEN 0x1c3d
+#define ENCP_DE_V_BEGIN_ODD 0x1c3e
+#define ENCP_DE_V_END_ODD 0x1c3f
+#define ENCI_SYNC_LINE_LENGTH 0x1c40
+#define ENCI_SYNC_PIXEL_EN 0x1c41
+#define ENCI_SYNC_TO_LINE_EN 0x1c42
+#define ENCI_SYNC_TO_PIXEL 0x1c43
+#define ENCP_SYNC_LINE_LENGTH 0x1c44
+#define ENCP_SYNC_PIXEL_EN 0x1c45
+#define ENCP_SYNC_TO_LINE_EN 0x1c46
+#define ENCP_SYNC_TO_PIXEL 0x1c47
+#define ENCT_SYNC_LINE_LENGTH 0x1c48
+#define ENCT_SYNC_PIXEL_EN 0x1c49
+#define ENCT_SYNC_TO_LINE_EN 0x1c4a
+#define ENCT_SYNC_TO_PIXEL 0x1c4b
+#define ENCL_SYNC_LINE_LENGTH 0x1c4c
+#define ENCL_SYNC_PIXEL_EN 0x1c4d
+#define ENCL_SYNC_TO_LINE_EN 0x1c4e
+#define ENCL_SYNC_TO_PIXEL 0x1c4f
+#define ENCP_VFIFO2VD_CTL2 0x1c50
+#define VENC_DVI_SETTING_MORE 0x1c51
+#define VENC_VDAC_DAC4_FILT_CTRL0 0x1c54
+#define VENC_VDAC_DAC4_FILT_CTRL1 0x1c55
+#define VENC_VDAC_DAC5_FILT_CTRL0 0x1c56
+#define VENC_VDAC_DAC5_FILT_CTRL1 0x1c57
+#define VENC_VDAC_DAC0_FILT_CTRL0 0x1c58
+#define VENC_VDAC_DAC0_FILT_CTRL1 0x1c59
+#define VENC_VDAC_DAC1_FILT_CTRL0 0x1c5a
+#define VENC_VDAC_DAC1_FILT_CTRL1 0x1c5b
+#define VENC_VDAC_DAC2_FILT_CTRL0 0x1c5c
+#define VENC_VDAC_DAC2_FILT_CTRL1 0x1c5d
+#define VENC_VDAC_DAC3_FILT_CTRL0 0x1c5e
+#define VENC_VDAC_DAC3_FILT_CTRL1 0x1c5f
+#define ENCT_VIDEO_EN 0x1c60
+#define ENCT_VIDEO_Y_SCL 0x1c61
+#define ENCT_VIDEO_PB_SCL 0x1c62
+#define ENCT_VIDEO_PR_SCL 0x1c63
+#define ENCT_VIDEO_Y_OFFST 0x1c64
+#define ENCT_VIDEO_PB_OFFST 0x1c65
+#define ENCT_VIDEO_PR_OFFST 0x1c66
+#define ENCT_VIDEO_MODE 0x1c67
+#define ENCT_VIDEO_MODE_ADV 0x1c68
+#define ENCT_DBG_PX_RST 0x1c69
+#define ENCT_DBG_LN_RST 0x1c6a
+#define ENCT_DBG_PX_INT 0x1c6b
+#define ENCT_DBG_LN_INT 0x1c6c
+#define ENCT_VIDEO_YFP1_HTIME 0x1c6d
+#define ENCT_VIDEO_YFP2_HTIME 0x1c6e
+#define ENCT_VIDEO_YC_DLY 0x1c6f
+#define ENCT_VIDEO_MAX_PXCNT 0x1c70
+#define ENCT_VIDEO_HAVON_END 0x1c71
+#define ENCT_VIDEO_HAVON_BEGIN 0x1c72
+#define ENCT_VIDEO_VAVON_ELINE 0x1c73
+#define ENCT_VIDEO_VAVON_BLINE 0x1c74
+#define ENCT_VIDEO_HSO_BEGIN 0x1c75
+#define ENCT_VIDEO_HSO_END 0x1c76
+#define ENCT_VIDEO_VSO_BEGIN 0x1c77
+#define ENCT_VIDEO_VSO_END 0x1c78
+#define ENCT_VIDEO_VSO_BLINE 0x1c79
+#define ENCT_VIDEO_VSO_ELINE 0x1c7a
+#define ENCT_VIDEO_MAX_LNCNT 0x1c7b
+#define ENCT_VIDEO_BLANKY_VAL 0x1c7c
+#define ENCT_VIDEO_BLANKPB_VAL 0x1c7d
+#define ENCT_VIDEO_BLANKPR_VAL 0x1c7e
+#define ENCT_VIDEO_HOFFST 0x1c7f
+#define ENCT_VIDEO_VOFFST 0x1c80
+#define ENCT_VIDEO_RGB_CTRL 0x1c81
+#define ENCT_VIDEO_FILT_CTRL 0x1c82
+#define ENCT_VIDEO_OFLD_VPEQ_OFST 0x1c83
+#define ENCT_VIDEO_OFLD_VOAV_OFST 0x1c84
+#define ENCT_VIDEO_MATRIX_CB 0x1c85
+#define ENCT_VIDEO_MATRIX_CR 0x1c86
+#define ENCT_VIDEO_RGBIN_CTRL 0x1c87
+#define ENCT_MAX_LINE_SWITCH_POINT 0x1c88
+#define ENCT_DACSEL_0 0x1c89
+#define ENCT_DACSEL_1 0x1c8a
+#define ENCL_VFIFO2VD_CTL 0x1c90
+#define ENCL_VFIFO2VD_PIXEL_START 0x1c91
+#define ENCL_VFIFO2VD_PIXEL_END 0x1c92
+#define ENCL_VFIFO2VD_LINE_TOP_START 0x1c93
+#define ENCL_VFIFO2VD_LINE_TOP_END 0x1c94
+#define ENCL_VFIFO2VD_LINE_BOT_START 0x1c95
+#define ENCL_VFIFO2VD_LINE_BOT_END 0x1c96
+#define ENCL_VFIFO2VD_CTL2 0x1c97
+#define ENCL_TST_EN 0x1c98
+#define ENCL_TST_MDSEL 0x1c99
+#define ENCL_TST_Y 0x1c9a
+#define ENCL_TST_CB 0x1c9b
+#define ENCL_TST_CR 0x1c9c
+#define ENCL_TST_CLRBAR_STRT 0x1c9d
+#define ENCL_TST_CLRBAR_WIDTH 0x1c9e
+#define ENCL_TST_VDCNT_STSET 0x1c9f
+#define ENCL_VIDEO_EN 0x1ca0
+#define ENCL_VIDEO_Y_SCL 0x1ca1
+#define ENCL_VIDEO_PB_SCL 0x1ca2
+#define ENCL_VIDEO_PR_SCL 0x1ca3
+#define ENCL_VIDEO_Y_OFFST 0x1ca4
+#define ENCL_VIDEO_PB_OFFST 0x1ca5
+#define ENCL_VIDEO_PR_OFFST 0x1ca6
+#define ENCL_VIDEO_MODE 0x1ca7
+#define ENCL_VIDEO_MODE_ADV 0x1ca8
+#define ENCL_DBG_PX_RST 0x1ca9
+#define ENCL_DBG_LN_RST 0x1caa
+#define ENCL_DBG_PX_INT 0x1cab
+#define ENCL_DBG_LN_INT 0x1cac
+#define ENCL_VIDEO_YFP1_HTIME 0x1cad
+#define ENCL_VIDEO_YFP2_HTIME 0x1cae
+#define ENCL_VIDEO_YC_DLY 0x1caf
+#define ENCL_VIDEO_MAX_PXCNT 0x1cb0
+#define ENCL_VIDEO_HAVON_END 0x1cb1
+#define ENCL_VIDEO_HAVON_BEGIN 0x1cb2
+#define ENCL_VIDEO_VAVON_ELINE 0x1cb3
+#define ENCL_VIDEO_VAVON_BLINE 0x1cb4
+#define ENCL_VIDEO_HSO_BEGIN 0x1cb5
+#define ENCL_VIDEO_HSO_END 0x1cb6
+#define ENCL_VIDEO_VSO_BEGIN 0x1cb7
+#define ENCL_VIDEO_VSO_END 0x1cb8
+#define ENCL_VIDEO_VSO_BLINE 0x1cb9
+#define ENCL_VIDEO_VSO_ELINE 0x1cba
+#define ENCL_VIDEO_MAX_LNCNT 0x1cbb
+#define ENCL_VIDEO_BLANKY_VAL 0x1cbc
+#define ENCL_VIDEO_BLANKPB_VAL 0x1cbd
+#define ENCL_VIDEO_BLANKPR_VAL 0x1cbe
+#define ENCL_VIDEO_HOFFST 0x1cbf
+#define ENCL_VIDEO_VOFFST 0x1cc0
+#define ENCL_VIDEO_RGB_CTRL 0x1cc1
+#define ENCL_VIDEO_FILT_CTRL 0x1cc2
+#define ENCL_VIDEO_OFLD_VPEQ_OFST 0x1cc3
+#define ENCL_VIDEO_OFLD_VOAV_OFST 0x1cc4
+#define ENCL_VIDEO_MATRIX_CB 0x1cc5
+#define ENCL_VIDEO_MATRIX_CR 0x1cc6
+#define ENCL_VIDEO_RGBIN_CTRL 0x1cc7
+#define ENCL_MAX_LINE_SWITCH_POINT 0x1cc8
+#define ENCL_DACSEL_0 0x1cc9
+#define ENCL_DACSEL_1 0x1cca
+#define RDMA_AHB_START_ADDR_MAN 0x1100
+#define RDMA_AHB_END_ADDR_MAN 0x1101
+#define RDMA_AHB_START_ADDR_1 0x1102
+#define RDMA_AHB_END_ADDR_1 0x1103
+#define RDMA_AHB_START_ADDR_2 0x1104
+#define RDMA_AHB_END_ADDR_2 0x1105
+#define RDMA_AHB_START_ADDR_3 0x1106
+#define RDMA_AHB_END_ADDR_3 0x1107
+#define RDMA_AHB_START_ADDR_4 0x1108
+#define RDMA_AHB_END_ADDR_4 0x1109
+#define RDMA_AHB_START_ADDR_5 0x110a
+#define RDMA_AHB_END_ADDR_5 0x110b
+#define RDMA_AHB_START_ADDR_6 0x110c
+#define RDMA_AHB_END_ADDR_6 0x110d
+#define RDMA_AHB_START_ADDR_7 0x110e
+#define RDMA_AHB_END_ADDR_7 0x110f
+#define RDMA_ACCESS_AUTO 0x1110
+#define RDMA_ACCESS_AUTO2 0x1111
+#define RDMA_ACCESS_AUTO3 0x1112
+#define RDMA_ACCESS_MAN 0x1113
+#define RDMA_CTRL 0x1114
+#define RDMA_STATUS 0x1115
+#define RDMA_STATUS2 0x1116
+#define RDMA_STATUS3 0x1117
+#define L_GAMMA_CNTL_PORT 0x1400
+#define L_GAMMA_DATA_PORT 0x1401
+#define L_GAMMA_ADDR_PORT 0x1402
+#define L_GAMMA_VCOM_HSWITCH_ADDR 0x1403
+#define L_RGB_BASE_ADDR 0x1405
+#define L_RGB_COEFF_ADDR 0x1406
+#define L_POL_CNTL_ADDR 0x1407
+#define L_DITH_CNTL_ADDR 0x1408
+#define L_GAMMA_PROBE_CTRL 0x1409
+#define L_GAMMA_PROBE_COLOR_L 0x140a
+#define L_GAMMA_PROBE_COLOR_H 0x140b
+#define L_GAMMA_PROBE_HL_COLOR 0x140c
+#define L_GAMMA_PROBE_POS_X 0x140d
+#define L_GAMMA_PROBE_POS_Y 0x140e
+#define L_STH1_HS_ADDR 0x1410
+#define L_STH1_HE_ADDR 0x1411
+#define L_STH1_VS_ADDR 0x1412
+#define L_STH1_VE_ADDR 0x1413
+#define L_STH2_HS_ADDR 0x1414
+#define L_STH2_HE_ADDR 0x1415
+#define L_STH2_VS_ADDR 0x1416
+#define L_STH2_VE_ADDR 0x1417
+#define L_OEH_HS_ADDR 0x1418
+#define L_OEH_HE_ADDR 0x1419
+#define L_OEH_VS_ADDR 0x141a
+#define L_OEH_VE_ADDR 0x141b
+#define L_VCOM_HSWITCH_ADDR 0x141c
+#define L_VCOM_VS_ADDR 0x141d
+#define L_VCOM_VE_ADDR 0x141e
+#define L_CPV1_HS_ADDR 0x141f
+#define L_CPV1_HE_ADDR 0x1420
+#define L_CPV1_VS_ADDR 0x1421
+#define L_CPV1_VE_ADDR 0x1422
+#define L_CPV2_HS_ADDR 0x1423
+#define L_CPV2_HE_ADDR 0x1424
+#define L_CPV2_VS_ADDR 0x1425
+#define L_CPV2_VE_ADDR 0x1426
+#define L_STV1_HS_ADDR 0x1427
+#define L_STV1_HE_ADDR 0x1428
+#define L_STV1_VS_ADDR 0x1429
+#define L_STV1_VE_ADDR 0x142a
+#define L_STV2_HS_ADDR 0x142b
+#define L_STV2_HE_ADDR 0x142c
+#define L_STV2_VS_ADDR 0x142d
+#define L_STV2_VE_ADDR 0x142e
+#define L_OEV1_HS_ADDR 0x142f
+#define L_OEV1_HE_ADDR 0x1430
+#define L_OEV1_VS_ADDR 0x1431
+#define L_OEV1_VE_ADDR 0x1432
+#define L_OEV2_HS_ADDR 0x1433
+#define L_OEV2_HE_ADDR 0x1434
+#define L_OEV2_VS_ADDR 0x1435
+#define L_OEV2_VE_ADDR 0x1436
+#define L_OEV3_HS_ADDR 0x1437
+#define L_OEV3_HE_ADDR 0x1438
+#define L_OEV3_VS_ADDR 0x1439
+#define L_OEV3_VE_ADDR 0x143a
+#define L_LCD_PWR_ADDR 0x143b
+#define L_LCD_PWM0_LO_ADDR 0x143c
+#define L_LCD_PWM0_HI_ADDR 0x143d
+#define L_LCD_PWM1_LO_ADDR 0x143e
+#define L_LCD_PWM1_HI_ADDR 0x143f
+#define L_INV_CNT_ADDR 0x1440
+#define L_TCON_MISC_SEL_ADDR 0x1441
+#define L_DUAL_PORT_CNTL_ADDR 0x1442
+#define MLVDS_CLK_CTL1_HI 0x1443
+#define MLVDS_CLK_CTL1_LO 0x1444
+#define L_TCON_DOUBLE_CTL 0x1449
+#define L_TCON_PATTERN_HI 0x144a
+#define L_TCON_PATTERN_LO 0x144b
+#define LDIM_BL_ADDR_PORT 0x144e
+#define LDIM_BL_DATA_PORT 0x144f
+#define L_DE_HS_ADDR 0x1451
+#define L_DE_HE_ADDR 0x1452
+#define L_DE_VS_ADDR 0x1453
+#define L_DE_VE_ADDR 0x1454
+#define L_HSYNC_HS_ADDR 0x1455
+#define L_HSYNC_HE_ADDR 0x1456
+#define L_HSYNC_VS_ADDR 0x1457
+#define L_HSYNC_VE_ADDR 0x1458
+#define L_VSYNC_HS_ADDR 0x1459
+#define L_VSYNC_HE_ADDR 0x145a
+#define L_VSYNC_VS_ADDR 0x145b
+#define L_VSYNC_VE_ADDR 0x145c
+#define L_LCD_MCU_CTL 0x145d
+#define DUAL_MLVDS_CTL 0x1460
+#define DUAL_MLVDS_LINE_START 0x1461
+#define DUAL_MLVDS_LINE_END 0x1462
+#define DUAL_MLVDS_PIXEL_W_START_L 0x1463
+#define DUAL_MLVDS_PIXEL_W_END_L 0x1464
+#define DUAL_MLVDS_PIXEL_W_START_R 0x1465
+#define DUAL_MLVDS_PIXEL_W_END_R 0x1466
+#define DUAL_MLVDS_PIXEL_R_START_L 0x1467
+#define DUAL_MLVDS_PIXEL_R_CNT_L 0x1468
+#define DUAL_MLVDS_PIXEL_R_START_R 0x1469
+#define DUAL_MLVDS_PIXEL_R_CNT_R 0x146a
+#define V_INVERSION_PIXEL 0x1470
+#define V_INVERSION_LINE 0x1471
+#define V_INVERSION_CONTROL 0x1472
+#define MLVDS2_CONTROL 0x1474
+#define MLVDS2_CONFIG_HI 0x1475
+#define MLVDS2_CONFIG_LO 0x1476
+#define MLVDS2_DUAL_GATE_WR_START 0x1477
+#define MLVDS2_DUAL_GATE_WR_END 0x1478
+#define MLVDS2_DUAL_GATE_RD_START 0x1479
+#define MLVDS2_DUAL_GATE_RD_END 0x147a
+#define MLVDS2_SECOND_RESET_CTL 0x147b
+#define MLVDS2_DUAL_GATE_CTL_HI 0x147c
+#define MLVDS2_DUAL_GATE_CTL_LO 0x147d
+#define MLVDS2_RESET_CONFIG_HI 0x147e
+#define MLVDS2_RESET_CONFIG_LO 0x147f
+#define GAMMA_CNTL_PORT 0x1480
+#define GAMMA_DATA_PORT 0x1481
+#define GAMMA_ADDR_PORT 0x1482
+#define GAMMA_VCOM_HSWITCH_ADDR 0x1483
+#define RGB_BASE_ADDR 0x1485
+#define RGB_COEFF_ADDR 0x1486
+#define POL_CNTL_ADDR 0x1487
+#define DITH_CNTL_ADDR 0x1488
+#define GAMMA_PROBE_CTRL 0x1489
+#define GAMMA_PROBE_COLOR_L 0x148a
+#define GAMMA_PROBE_COLOR_H 0x148b
+#define GAMMA_PROBE_HL_COLOR 0x148c
+#define GAMMA_PROBE_POS_X 0x148d
+#define GAMMA_PROBE_POS_Y 0x148e
+#define STH1_HS_ADDR 0x1490
+#define STH1_HE_ADDR 0x1491
+#define STH1_VS_ADDR 0x1492
+#define STH1_VE_ADDR 0x1493
+#define STH2_HS_ADDR 0x1494
+#define STH2_HE_ADDR 0x1495
+#define STH2_VS_ADDR 0x1496
+#define STH2_VE_ADDR 0x1497
+#define OEH_HS_ADDR 0x1498
+#define OEH_HE_ADDR 0x1499
+#define OEH_VS_ADDR 0x149a
+#define OEH_VE_ADDR 0x149b
+#define VCOM_HSWITCH_ADDR 0x149c
+#define VCOM_VS_ADDR 0x149d
+#define VCOM_VE_ADDR 0x149e
+#define CPV1_HS_ADDR 0x149f
+#define CPV1_HE_ADDR 0x14a0
+#define CPV1_VS_ADDR 0x14a1
+#define CPV1_VE_ADDR 0x14a2
+#define CPV2_HS_ADDR 0x14a3
+#define CPV2_HE_ADDR 0x14a4
+#define CPV2_VS_ADDR 0x14a5
+#define CPV2_VE_ADDR 0x14a6
+#define STV1_HS_ADDR 0x14a7
+#define STV1_HE_ADDR 0x14a8
+#define STV1_VS_ADDR 0x14a9
+#define STV1_VE_ADDR 0x14aa
+#define STV2_HS_ADDR 0x14ab
+#define STV2_HE_ADDR 0x14ac
+#define STV2_VS_ADDR 0x14ad
+#define STV2_VE_ADDR 0x14ae
+#define OEV1_HS_ADDR 0x14af
+#define OEV1_HE_ADDR 0x14b0
+#define OEV1_VS_ADDR 0x14b1
+#define OEV1_VE_ADDR 0x14b2
+#define OEV2_HS_ADDR 0x14b3
+#define OEV2_HE_ADDR 0x14b4
+#define OEV2_VS_ADDR 0x14b5
+#define OEV2_VE_ADDR 0x14b6
+#define OEV3_HS_ADDR 0x14b7
+#define OEV3_HE_ADDR 0x14b8
+#define OEV3_VS_ADDR 0x14b9
+#define OEV3_VE_ADDR 0x14ba
+#define LCD_PWR_ADDR 0x14bb
+#define LCD_PWM0_LO_ADDR 0x14bc
+#define LCD_PWM0_HI_ADDR 0x14bd
+#define LCD_PWM1_LO_ADDR 0x14be
+#define LCD_PWM1_HI_ADDR 0x14bf
+#define INV_CNT_ADDR 0x14c0
+#define TCON_MISC_SEL_ADDR 0x14c1
+#define DUAL_PORT_CNTL_ADDR 0x14c2
+#define MLVDS_CONTROL 0x14c3
+#define MLVDS_RESET_PATTERN_HI 0x14c4
+#define MLVDS_RESET_PATTERN_LO 0x14c5
+#define MLVDS_RESET_PATTERN_EXT 0x14c6
+#define MLVDS_CONFIG_HI 0x14c7
+#define MLVDS_CONFIG_LO 0x14c8
+#define TCON_DOUBLE_CTL 0x14c9
+#define TCON_PATTERN_HI 0x14ca
+#define TCON_PATTERN_LO 0x14cb
+#define TCON_CONTROL_HI 0x14cc
+#define TCON_CONTROL_LO 0x14cd
+#define LVDS_BLANK_DATA_HI 0x14ce
+#define LVDS_BLANK_DATA_LO 0x14cf
+#define LVDS_PACK_CNTL_ADDR 0x14d0
+#define DE_HS_ADDR 0x14d1
+#define DE_HE_ADDR 0x14d2
+#define DE_VS_ADDR 0x14d3
+#define DE_VE_ADDR 0x14d4
+#define HSYNC_HS_ADDR 0x14d5
+#define HSYNC_HE_ADDR 0x14d6
+#define HSYNC_VS_ADDR 0x14d7
+#define HSYNC_VE_ADDR 0x14d8
+#define VSYNC_HS_ADDR 0x14d9
+#define VSYNC_HE_ADDR 0x14da
+#define VSYNC_VS_ADDR 0x14db
+#define VSYNC_VE_ADDR 0x14dc
+#define LCD_MCU_CTL 0x14dd
+#define LCD_MCU_DATA_0 0x14de
+#define LCD_MCU_DATA_1 0x14df
+#define LVDS_GEN_CNTL 0x14e0
+#define LVDS_PHY_CNTL0 0x14e1
+#define LVDS_PHY_CNTL1 0x14e2
+#define LVDS_PHY_CNTL2 0x14e3
+#define LVDS_PHY_CNTL3 0x14e4
+#define LVDS_PHY_CNTL4 0x14e5
+#define LVDS_PHY_CNTL5 0x14e6
+#define LVDS_SRG_TEST 0x14e8
+#define LVDS_BIST_MUX0 0x14e9
+#define LVDS_BIST_MUX1 0x14ea
+#define LVDS_BIST_FIXED0 0x14eb
+#define LVDS_BIST_FIXED1 0x14ec
+#define LVDS_BIST_CNTL0 0x14ed
+#define LVDS_CLKB_CLKA 0x14ee
+#define LVDS_PHY_CLK_CNTL 0x14ef
+#define LVDS_SER_EN 0x14f0
+#define LVDS_PHY_CNTL6 0x14f1
+#define LVDS_PHY_CNTL7 0x14f2
+#define LVDS_PHY_CNTL8 0x14f3
+#define MLVDS_CLK_CTL0_HI 0x14f4
+#define MLVDS_CLK_CTL0_LO 0x14f5
+#define MLVDS_DUAL_GATE_WR_START 0x14f6
+#define MLVDS_DUAL_GATE_WR_END 0x14f7
+#define MLVDS_DUAL_GATE_RD_START 0x14f8
+#define MLVDS_DUAL_GATE_RD_END 0x14f9
+#define MLVDS_SECOND_RESET_CTL 0x14fa
+#define MLVDS_DUAL_GATE_CTL_HI 0x14fb
+#define MLVDS_DUAL_GATE_CTL_LO 0x14fc
+#define MLVDS_RESET_CONFIG_HI 0x14fd
+#define MLVDS_RESET_CONFIG_LO 0x14fe
+#define VPU_OSD1_MMC_CTRL 0x2701
+#define VPU_OSD2_MMC_CTRL 0x2702
+#define VPU_VD1_MMC_CTRL 0x2703
+#define VPU_VD2_MMC_CTRL 0x2704
+#define VPU_DI_IF1_MMC_CTRL 0x2705
+#define VPU_DI_MEM_MMC_CTRL 0x2706
+#define VPU_DI_INP_MMC_CTRL 0x2707
+#define VPU_DI_MTNRD_MMC_CTRL 0x2708
+#define VPU_DI_CHAN2_MMC_CTRL 0x2709
+#define VPU_DI_MTNWR_MMC_CTRL 0x270a
+#define VPU_DI_NRWR_MMC_CTRL 0x270b
+#define VPU_DI_DIWR_MMC_CTRL 0x270c
+#define VPU_VDIN0_MMC_CTRL 0x270d
+#define VPU_VDIN1_MMC_CTRL 0x270e
+#define VPU_BT656_MMC_CTRL 0x270f
+#define VPU_TVD3D_MMC_CTRL 0x2710
+#define VPU_TVDVBI_MMC_CTRL 0x2711
+#define VPU_TVDVBI_VSLATCH_ADDR 0x2712
+#define VPU_TVDVBI_WRRSP_ADDR 0x2713
+#define VPU_VDIN_PRE_ARB_CTRL 0x2714
+#define VPU_VDISP_PRE_ARB_CTRL 0x2715
+#define VPU_VPUARB2_PRE_ARB_CTRL 0x2716
+#define VPU_OSD3_MMC_CTRL 0x2717
+#define VPU_OSD4_MMC_CTRL 0x2718
+#define VPU_VD3_MMC_CTRL 0x2719
+#define VPU_VIU_VENC_MUX_CTRL 0x271a
+#define VPU_HDMI_SETTING 0x271b
+#define ENCI_INFO_READ 0x271c
+#define ENCP_INFO_READ 0x271d
+#define ENCT_INFO_READ 0x271e
+#define ENCL_INFO_READ 0x271f
+#define VPU_SW_RESET 0x2720
+#define VPU_D2D3_MMC_CTRL 0x2721
+#define VPU_CONT_MMC_CTRL 0x2722
+#define VPU_CLK_GATE 0x2723
+#define VPU_RDMA_MMC_CTRL 0x2724
+#define VPU_MEM_PD_REG0 0x2725
+#define VPU_MEM_PD_REG1 0x2726
+#define VPU_HDMI_DATA_OVR 0x2727
+#define VPU_PROT1_MMC_CTRL 0x2728
+#define VPU_PROT2_MMC_CTRL 0x2729
+#define VPU_PROT3_MMC_CTRL 0x272a
+#define VPU_ARB4_V1_MMC_CTRL 0x272b
+#define VPU_ARB4_V2_MMC_CTRL 0x272c
+#define VPU_VPU_PWM_V0 0x2730
+#define VPU_VPU_PWM_V1 0x2731
+#define VPU_VPU_PWM_V2 0x2732
+#define VPU_VPU_PWM_V3 0x2733
+#define VPU_VPU_PWM_H0 0x2734
+#define VPU_VPU_PWM_H1 0x2735
+#define VPU_VPU_PWM_H2 0x2736
+#define VPU_VPU_PWM_H3 0x2737
+#define VPU_MISC_CTRL 0x2740
+#define VPU_ISP_GCLK_CTRL0 0x2741
+#define VPU_ISP_GCLK_CTRL1 0x2742
+#define VPU_VDIN_ASYNC_HOLD_CTRL 0x2743
+#define VPU_VDISP_ASYNC_HOLD_CTRL 0x2744
+#define VPU_VPUARB2_ASYNC_HOLD_CTRL 0x2745
+
+#define VPU_PROT1_CLK_GATE 0x2750
+#define VPU_PROT1_GEN_CNTL 0x2751
+#define VPU_PROT1_X_START_END 0x2752
+#define VPU_PROT1_Y_START_END 0x2753
+#define VPU_PROT1_Y_LEN_STEP 0x2754
+#define VPU_PROT1_RPT_LOOP 0x2755
+#define VPU_PROT1_RPT_PAT 0x2756
+#define VPU_PROT1_DDR 0x2757
+#define VPU_PROT1_RBUF_ROOM 0x2758
+#define VPU_PROT1_STAT_0 0x2759
+#define VPU_PROT1_STAT_1 0x275a
+#define VPU_PROT1_STAT_2 0x275b
+#define VPU_PROT1_REQ_ONOFF 0x275c
+#define VPU_PROT2_CLK_GATE 0x2760
+#define VPU_PROT2_GEN_CNTL 0x2761
+#define VPU_PROT2_X_START_END 0x2762
+#define VPU_PROT2_Y_START_END 0x2763
+#define VPU_PROT2_Y_LEN_STEP 0x2764
+#define VPU_PROT2_RPT_LOOP 0x2765
+#define VPU_PROT2_RPT_PAT 0x2766
+#define VPU_PROT2_DDR 0x2767
+#define VPU_PROT2_RBUF_ROOM 0x2768
+#define VPU_PROT2_STAT_0 0x2769
+#define VPU_PROT2_STAT_1 0x276a
+#define VPU_PROT2_STAT_2 0x276b
+#define VPU_PROT2_REQ_ONOFF 0x276c
+#define VPU_PROT3_CLK_GATE 0x2770
+#define VPU_PROT3_GEN_CNTL 0x2771
+#define VPU_PROT3_X_START_END 0x2772
+#define VPU_PROT3_Y_START_END 0x2773
+#define VPU_PROT3_Y_LEN_STEP 0x2774
+#define VPU_PROT3_RPT_LOOP 0x2775
+#define VPU_PROT3_RPT_PAT 0x2776
+#define VPU_PROT3_DDR 0x2777
+#define VPU_PROT3_RBUF_ROOM 0x2778
+#define VPU_PROT3_STAT_0 0x2779
+#define VPU_PROT3_STAT_1 0x277a
+#define VPU_PROT3_STAT_2 0x277b
+#define VPU_PROT3_REQ_ONOFF 0x277c
+#define VPU_RDARB_MODE_L1C2 0x2799
+
+/* osd afbcd on gxtvbb */
+#define OSD1_AFBCD_ENABLE 0x31a0
+#define OSD1_AFBCD_MODE 0x31a1
+#define OSD1_AFBCD_SIZE_IN 0x31a2
+#define OSD1_AFBCD_HDR_PTR 0x31a3
+#define OSD1_AFBCD_FRAME_PTR 0x31a4
+#define OSD1_AFBCD_CHROMA_PTR 0x31a5
+#define OSD1_AFBCD_CONV_CTRL 0x31a6
+#define OSD1_AFBCD_STATUS 0x31a8
+#define OSD1_AFBCD_PIXEL_HSCOPE 0x31a9
+#define OSD1_AFBCD_PIXEL_VSCOPE 0x31aa
+#define VIU_MISC_CTRL1 0x1a07
+
+
+/* add for gxm and 962e dv core2 */
+#define DOLBY_CORE2A_SWAP_CTRL1 0x3434
+#define DOLBY_CORE2A_SWAP_CTRL2 0x3435
+
+/* osd afbc on g12a */
+#define VPU_MAFBC_BLOCK_ID 0x3a00
+#define VPU_MAFBC_IRQ_RAW_STATUS 0x3a01
+#define VPU_MAFBC_IRQ_CLEAR 0x3a02
+#define VPU_MAFBC_IRQ_MASK 0x3a03
+#define VPU_MAFBC_IRQ_STATUS 0x3a04
+#define VPU_MAFBC_COMMAND 0x3a05
+#define VPU_MAFBC_STATUS 0x3a06
+#define VPU_MAFBC_SURFACE_CFG 0x3a07
+
+/* osd afbc on g12a */
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S0 0x3a10
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S0 0x3a11
+#define VPU_MAFBC_FORMAT_SPECIFIER_S0 0x3a12
+#define VPU_MAFBC_BUFFER_WIDTH_S0 0x3a13
+#define VPU_MAFBC_BUFFER_HEIGHT_S0 0x3a14
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S0 0x3a15
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S0 0x3a16
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S0 0x3a17
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S0 0x3a18
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S0 0x3a19
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S0 0x3a1a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S0 0x3a1b
+#define VPU_MAFBC_PREFETCH_CFG_S0 0x3a1c
+
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S1 0x3a30
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S1 0x3a31
+#define VPU_MAFBC_FORMAT_SPECIFIER_S1 0x3a32
+#define VPU_MAFBC_BUFFER_WIDTH_S1 0x3a33
+#define VPU_MAFBC_BUFFER_HEIGHT_S1 0x3a34
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S1 0x3a35
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S1 0x3a36
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S1 0x3a37
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S1 0x3a38
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S1 0x3a39
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S1 0x3a3a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S1 0x3a3b
+#define VPU_MAFBC_PREFETCH_CFG_S1 0x3a3c
+
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S2 0x3a50
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S2 0x3a51
+#define VPU_MAFBC_FORMAT_SPECIFIER_S2 0x3a52
+#define VPU_MAFBC_BUFFER_WIDTH_S2 0x3a53
+#define VPU_MAFBC_BUFFER_HEIGHT_S2 0x3a54
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S2 0x3a55
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S2 0x3a56
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S2 0x3a57
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S2 0x3a58
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S2 0x3a59
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S2 0x3a5a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S2 0x3a5b
+#define VPU_MAFBC_PREFETCH_CFG_S2 0x3a5c
+
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S3 0x3a70
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S3 0x3a71
+#define VPU_MAFBC_FORMAT_SPECIFIER_S3 0x3a72
+#define VPU_MAFBC_BUFFER_WIDTH_S3 0x3a73
+#define VPU_MAFBC_BUFFER_HEIGHT_S3 0x3a74
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S3 0x3a75
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S3 0x3a76
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S3 0x3a77
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S3 0x3a78
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S3 0x3a79
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S3 0x3a7a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S3 0x3a7b
+#define VPU_MAFBC_PREFETCH_CFG_S3 0x3a7c
+
+#define DOLBY_PATH_CTRL 0x1a0c
+#define OSD_PATH_MISC_CTRL 0x1a0e
+#define MALI_AFBCD_TOP_CTRL 0x1a0f
+
+#define VPP_OUT_H_V_SIZE 0x1da5
+
+#define VPP_VD2_HDR_IN_SIZE 0x1df0
+#define VPP_GCLK_CTRL2 0x1df2
+#define VD2_PPS_DUMMY_DATA 0x1df4
+#define VPP_WRBAK_CTRL 0x1df9
+#define VPP_SLEEP_CTRL 0x1dfa
+
+#define VPP_RDARB_MODE 0x3978
+#define VPP_RDARB_REQEN_SLV 0x3979
+#define VPU_RDARB_MODE_L2C1 0x279d
+
+/*VIU2 osd1 reg*/
+#define VIU2_OSD1_MATRIX_COEF00_01 0x1e70
+#define VIU2_OSD1_MATRIX_COEF02_10 0x1e71
+#define VIU2_OSD1_MATRIX_COEF11_12 0x1e72
+#define VIU2_OSD1_MATRIX_COEF20_21 0x1e73
+#define VIU2_OSD1_MATRIX_COEF22 0x1e74
+#define VIU2_OSD1_MATRIX_COEF13_14 0x1e75
+#define VIU2_OSD1_MATRIX_COEF23_24 0x1e76
+#define VIU2_OSD1_MATRIX_COEF15_25 0x1e77
+#define VIU2_OSD1_MATRIX_CLIP 0x1e78
+#define VIU2_OSD1_MATRIX_OFFSET0_1 0x1e79
+#define VIU2_OSD1_MATRIX_OFFSET2 0x1e7a
+#define VIU2_OSD1_MATRIX_PRE_OFFSET0_1 0x1e7b
+#define VIU2_OSD1_MATRIX_PRE_OFFSET2 0x1e7c
+#define VIU2_OSD1_MATRIX_EN_CTRL 0x1e7d
+
+/* reg definition */
+
+struct afbc_osd1_reg {
+ u32 vpu_mafbc_header_buf_addr_low_s0;
+ u32 vpu_mafbc_header_buf_addr_high_s0;
+ u32 vpu_mafbc_format_specifier_s0;
+ u32 vpu_mafbc_buffer_width_s0;
+ u32 vpu_mafbc_buffer_height_s0;
+ u32 vpu_mafbc_bounding_box_x_start_s0;
+ u32 vpu_mafbc_bounding_box_x_end_s0;
+ u32 vpu_mafbc_bounding_box_y_start_s0;
+ u32 vpu_mafbc_bounding_box_y_end_s0;
+ u32 vpu_mafbc_output_buf_addr_low_s0;
+ u32 vpu_mafbc_output_buf_addr_high_s0;
+ u32 vpu_mafbc_output_buf_stride_s0;
+ u32 vpu_mafbc_prefetch_cfg_s0;
+ u32 vpu_mafbc_payload_min_low_s0;
+ u32 vpu_mafbc_payload_min_high_s0;
+ u32 vpu_mafbc_payload_max_low_s0;
+ u32 vpu_mafbc_payload_max_high_s0;
+};
+
+struct afbc_osd2_reg {
+ u32 vpu_mafbc_header_buf_addr_low_s1;
+ u32 vpu_mafbc_header_buf_addr_high_s1;
+ u32 vpu_mafbc_format_specifier_s1;
+ u32 vpu_mafbc_buffer_width_s1;
+ u32 vpu_mafbc_buffer_height_s1;
+ u32 vpu_mafbc_bounding_box_x_start_s1;
+ u32 vpu_mafbc_bounding_box_x_end_s1;
+ u32 vpu_mafbc_bounding_box_y_start_s1;
+ u32 vpu_mafbc_bounding_box_y_end_s1;
+ u32 vpu_mafbc_output_buf_addr_low_s1;
+ u32 vpu_mafbc_output_buf_addr_high_s1;
+ u32 vpu_mafbc_output_buf_stride_s1;
+ u32 vpu_mafbc_prefetch_cfg_s1;
+ u32 vpu_mafbc_payload_min_low_s1;
+ u32 vpu_mafbc_payload_min_high_s1;
+ u32 vpu_mafbc_payload_max_low_s1;
+ u32 vpu_mafbc_payload_max_high_s1;
+};
+
+struct afbc_osd3_reg {
+ u32 vpu_mafbc_header_buf_addr_low_s2;
+ u32 vpu_mafbc_header_buf_addr_high_s2;
+ u32 vpu_mafbc_format_specifier_s2;
+ u32 vpu_mafbc_buffer_width_s2;
+ u32 vpu_mafbc_buffer_height_s2;
+ u32 vpu_mafbc_bounding_box_x_start_s2;
+ u32 vpu_mafbc_bounding_box_x_end_s2;
+ u32 vpu_mafbc_bounding_box_y_start_s2;
+ u32 vpu_mafbc_bounding_box_y_end_s2;
+ u32 vpu_mafbc_output_buf_addr_low_s2;
+ u32 vpu_mafbc_output_buf_addr_high_s2;
+ u32 vpu_mafbc_output_buf_stride_s2;
+ u32 vpu_mafbc_prefetch_cfg_s2;
+ u32 vpu_mafbc_payload_min_low_s2;
+ u32 vpu_mafbc_payload_min_high_s2;
+ u32 vpu_mafbc_payload_max_low_s2;
+ u32 vpu_mafbc_payload_max_high_s2;
+};
+
+struct afbc_status_reg {
+ u32 vpu_mafbc_block_id;
+ u32 vpu_mafbc_irq_raw_status;
+ u32 vpu_mafbc_irq_clear;
+ u32 vpu_mafbc_irq_mask;
+ u32 vpu_mafbc_irq_status;
+ u32 vpu_mafbc_command;
+ u32 vpu_mafbc_status;
+ u32 vpu_mafbc_surface_cfg;
+};
+
+union afbc_osd_reg {
+ struct afbc_osd1_reg afbc_osd1;
+ struct afbc_osd2_reg afbc_osd2;
+ struct afbc_osd3_reg afbc_osd3;
+};
+
+#endif
diff --git a/include/dt-bindings/display/meson-drm-ids.h b/include/dt-bindings/display/meson-drm-ids.h
new file mode 100644
index 0000000..b163eaa
--- a/dev/null
+++ b/include/dt-bindings/display/meson-drm-ids.h
@@ -0,0 +1,53 @@
+#ifndef _MESON_DRM_IDS_H_
+#define _MESON_DRM_IDS_H_
+
+#define OSD1_BLOCK 0
+#define OSD2_BLOCK 1
+#define OSD3_BLOCK 2
+#define AFBC_OSD1_BLOCK 3
+#define AFBC_OSD2_BLOCK 4
+#define AFBC_OSD3_BLOCK 5
+#define SCALER_OSD1_BLOCK 6
+#define SCALER_OSD2_BLOCK 7
+#define SCALER_OSD3_BLOCK 8
+#define OSD_BLEND_BLOCK 9
+#define OSD1_HDR_BLOCK 10
+#define VPP_POSTBLEND_BLOCK 11
+
+#define OSD1_PORT 0
+#define OSD2_PORT 1
+#define OSD3_PORT 2
+#define AFBC_OSD1_PORT 3
+#define AFBC_OSD2_PORT 4
+#define AFBC_OSD3_PORT 5
+#define SCALER_OSD1_PORT 6
+#define SCALER_OSD2_PORT 7
+#define SCALER_OSD3_PORT 8
+#define OSDBLEND_DIN1_PORT 9
+#define OSDBLEND_DIN2_PORT 10
+#define OSDBLEND_DIN3_PORT 11
+#define OSDBLEND_DOUT1_PORT 12
+#define OSDBLEND_DOUT2_PORT 13
+#define OSD1_HDR_PORT 14
+#define OSD1_DOLBY_PORT 15
+#define VPP_POSTBLEND_OSD1_IN_PORT 16
+#define VPP_POSTBLEND_OSD2_IN_PORT 17
+#define VPP_POSTBLEND_OUT_PORT 18
+
+/*
+ *OSD VERSION
+ *V1:G12A
+ *V2:G12B-revA:base G12A,add repeate last line function
+ *V3:G12B-RevB:add line interrupt support
+ *V4:TL1:base G12A,fix shift issue,delete osd3
+ *V5:SM1:base G12A,fix shift issue
+ *V6:TM2,base G12A,fix shift issue,add mux for osd1-sr
+ */
+#define OSD_V1 1
+#define OSD_V2 2
+#define OSD_V3 3
+#define OSD_V4 4
+#define OSD_V5 5
+#define OSD_V6 6
+
+#endif
diff --git a/include/linux/amlogic/meson_drm.h b/include/linux/amlogic/meson_drm.h
deleted file mode 100644
index cad57fe..0000000
--- a/include/linux/amlogic/meson_drm.h
+++ b/dev/null
@@ -1,72 +0,0 @@
-/*
- * include/uapi/drm/meson_drm.h
- *
- * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#ifndef _MESON_DRM_H
-#define _MESON_DRM_H
-
-#include <drm/drm.h>
-
-/* memory type definitions. */
-enum drm_meson_gem_mem_type {
- /* Physically Continuous memory. */
- MESON_BO_CONTIG = 1 << 0,
- /* cachable mapping. */
- MESON_BO_CACHABLE = 1 << 1,
- /* write-combine mapping. */
- MESON_BO_WC = 1 << 2,
- MESON_BO_SECURE = 1 << 3,
- MESON_BO_MASK = MESON_BO_CONTIG | MESON_BO_CACHABLE |
- MESON_BO_WC
-};
-
-/* Use flags */
-#define BO_USE_NONE 0
-#define BO_USE_SCANOUT (1ull << 0)
-#define BO_USE_CURSOR (1ull << 1)
-#define BO_USE_CURSOR_64X64 BO_USE_CURSOR
-#define BO_USE_RENDERING (1ull << 2)
-#define BO_USE_LINEAR (1ull << 3)
-#define BO_USE_SW_READ_NEVER (1ull << 4)
-#define BO_USE_SW_READ_RARELY (1ull << 5)
-#define BO_USE_SW_READ_OFTEN (1ull << 6)
-#define BO_USE_SW_WRITE_NEVER (1ull << 7)
-#define BO_USE_SW_WRITE_RARELY (1ull << 8)
-#define BO_USE_SW_WRITE_OFTEN (1ull << 9)
-#define BO_USE_EXTERNAL_DISP (1ull << 10)
-#define BO_USE_PROTECTED (1ull << 11)
-#define BO_USE_HW_VIDEO_ENCODER (1ull << 12)
-#define BO_USE_CAMERA_WRITE (1ull << 13)
-#define BO_USE_CAMERA_READ (1ull << 14)
-#define BO_USE_RENDERSCRIPT (1ull << 16)
-#define BO_USE_TEXTURE (1ull << 17)
-
-
-/**
- * User-desired buffer creation information structure.
- *
- * @size: user-desired memory allocation size.
- * @flags: user request for setting memory type or cache attributes.
- * @handle: returned a handle to created gem object.
- * - this handle will be set by gem module of kernel side.
- */
-struct drm_meson_gem_create {
- uint64_t size;
- uint32_t flags;
- uint32_t handle;
-};
-
-#define DRM_MESON_GEM_CREATE 0x00
-
-#define DRM_IOCTL_MESON_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \
- DRM_MESON_GEM_CREATE, struct drm_meson_gem_create)
-
-#endif /* _MESON_DRM_H */
-
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index fc0cac3..9f74715 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -160,6 +160,7 @@ extern "C" {
#define DRM_FORMAT_MOD_VENDOR_NV 0x03
#define DRM_FORMAT_MOD_VENDOR_SAMSUNG 0x04
#define DRM_FORMAT_MOD_VENDOR_QCOM 0x05
+#define DRM_FORMAT_MOD_VENDOR_AMLOGIC 0x09
/* add more to the end as needed */
#define DRM_FORMAT_RESERVED ((1ULL << 56) - 1)
@@ -255,6 +256,9 @@ extern "C" {
*/
#define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE fourcc_mod_code(SAMSUNG, 1)
+#define DRM_FORMAT_MOD_MESON_AFBC fourcc_mod_code(AMLOGIC, 1)
+#define DRM_FORMAT_MOD_MESON_AFBC_WB fourcc_mod_code(AMLOGIC, 2)
+
#if defined(__cplusplus)
}
#endif
diff --git a/include/uapi/drm/meson_drm.h b/include/uapi/drm/meson_drm.h
new file mode 100644
index 0000000..5b12674
--- a/dev/null
+++ b/include/uapi/drm/meson_drm.h
@@ -0,0 +1,49 @@
+/*
+ * include/uapi/drm/meson_drm.h
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef _MESON_DRM_H
+#define _MESON_DRM_H
+
+#include <drm/drm.h>
+
+/* Use flags */
+#define MESON_USE_NONE 0
+#define MESON_USE_SCANOUT (1ull << 0)
+#define MESON_USE_CURSOR (1ull << 1)
+#define MESON_USE_RENDERING (1ull << 2)
+#define MESON_USE_LINEAR (1ull << 3)
+#define MESON_USE_PROTECTED (1ull << 11)
+#define MESON_USE_HW_VIDEO_ENCODER (1ull << 12)
+#define MESON_USE_CAMERA_WRITE (1ull << 13)
+#define MESON_USE_CAMERA_READ (1ull << 14)
+#define MESON_USE_TEXTURE (1ull << 17)
+
+
+/**
+ * User-desired buffer creation information structure.
+ *
+ * @size: user-desired memory allocation size.
+ * @flags: user request for setting memory type or cache attributes.
+ * @handle: returned a handle to created gem object.
+ * - this handle will be set by gem module of kernel side.
+ */
+struct drm_meson_gem_create {
+ __u64 size;
+ __u32 flags;
+ __u32 handle;
+};
+
+#define DRM_MESON_GEM_CREATE 0x00
+
+#define DRM_IOCTL_MESON_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \
+ DRM_MESON_GEM_CREATE, struct drm_meson_gem_create)
+
+#endif /* _MESON_DRM_H */