drm: add multi-layer support [1/1]
authorDezhi Kong <dezhi.kong@amlogic.com>
Tue, 11 Jun 2019 12:29:40 +0000 (20:29 +0800)
committerDezhi Kong <dezhi.kong@amlogic.com>
Thu, 11 Jul 2019 02:10:57 +0000 (10:10 +0800)
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>
77 files changed:
MAINTAINERS
arch/arm/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts
arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts
arch/arm/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts
arch/arm/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts [new file with mode: 0644]
arch/arm/boot/dts/amlogic/mesong12a_drm.dtsi
arch/arm/boot/dts/amlogic/mesong12b_drm.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/amlogic/g12a_s905d2_u200_drm_buildroot.dts
arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot.dts
arch/arm64/boot/dts/amlogic/g12b_a311d_w400_drm_buildroot_a.dts
arch/arm64/boot/dts/amlogic/g12b_revb_a311d_w400_drm_buildroot.dts [new file with mode: 0644]
arch/arm64/boot/dts/amlogic/mesong12a_drm.dtsi
arch/arm64/boot/dts/amlogic/mesong12b_drm.dtsi [new file with mode: 0644]
drivers/amlogic/Makefile
drivers/amlogic/drm/Kconfig
drivers/amlogic/drm/Makefile
drivers/amlogic/drm/am_meson_fbdev.h [deleted file]
drivers/amlogic/drm/drm-v0/Kconfig [new file with mode: 0644]
drivers/amlogic/drm/drm-v0/Makefile [new file with mode: 0644]
drivers/amlogic/drm/drm-v0/am_meson_drv.c [moved from drivers/amlogic/drm/am_meson_drv.c with 94% similarity]
drivers/amlogic/drm/drm-v0/am_meson_drv.h [moved from drivers/amlogic/drm/am_meson_drv.h with 71% similarity]
drivers/amlogic/drm/drm-v0/am_meson_fb.c [moved from drivers/amlogic/drm/am_meson_fb.c with 98% similarity]
drivers/amlogic/drm/drm-v0/am_meson_fb.h [moved from drivers/amlogic/drm/am_meson_fb.h with 96% similarity]
drivers/amlogic/drm/drm-v0/am_meson_fbdev.c [moved from drivers/amlogic/drm/am_meson_fbdev.c with 91% similarity]
drivers/amlogic/drm/drm-v0/am_meson_fbdev.h [new file with mode: 0644]
drivers/amlogic/drm/drm-v0/am_meson_gem.c [moved from drivers/amlogic/drm/am_meson_gem.c with 98% similarity]
drivers/amlogic/drm/drm-v0/am_meson_gem.h [moved from drivers/amlogic/drm/am_meson_gem.h with 97% similarity]
drivers/amlogic/drm/drm-v0/am_meson_hdcp.c [moved from drivers/amlogic/drm/am_meson_hdcp.c with 99% similarity]
drivers/amlogic/drm/drm-v0/am_meson_hdcp.h [new file with mode: 0644]
drivers/amlogic/drm/drm-v0/am_meson_hdmi.c [moved from drivers/amlogic/drm/am_meson_hdmi.c with 99% similarity]
drivers/amlogic/drm/drm-v0/am_meson_hdmi.h [moved from drivers/amlogic/drm/am_meson_hdmi.h with 99% similarity]
drivers/amlogic/drm/drm-v0/am_meson_lcd.c [moved from drivers/amlogic/drm/am_meson_lcd.c with 99% similarity]
drivers/amlogic/drm/drm-v0/am_meson_lcd.h [moved from drivers/amlogic/drm/am_meson_lcd.h with 93% similarity]
drivers/amlogic/drm/drm-v0/am_meson_vpu.c [moved from drivers/amlogic/drm/am_meson_vpu.c with 99% similarity]
drivers/amlogic/drm/drm-v0/am_meson_vpu.h [moved from drivers/amlogic/drm/am_meson_vpu.h with 93% similarity]
drivers/amlogic/drm/meson_crtc.c [new file with mode: 0644]
drivers/amlogic/drm/meson_crtc.h [new file with mode: 0644]
drivers/amlogic/drm/meson_drv.c [new file with mode: 0644]
drivers/amlogic/drm/meson_drv.h [new file with mode: 0644]
drivers/amlogic/drm/meson_fb.c [new file with mode: 0644]
drivers/amlogic/drm/meson_fb.h [new file with mode: 0644]
drivers/amlogic/drm/meson_fbdev.c [new file with mode: 0644]
drivers/amlogic/drm/meson_fbdev.h [new file with mode: 0644]
drivers/amlogic/drm/meson_gem.c [new file with mode: 0644]
drivers/amlogic/drm/meson_gem.h [new file with mode: 0644]
drivers/amlogic/drm/meson_hdcp.c [new file with mode: 0644]
drivers/amlogic/drm/meson_hdcp.h [moved from drivers/amlogic/drm/am_meson_hdcp.h with 96% similarity]
drivers/amlogic/drm/meson_hdmi.c [new file with mode: 0644]
drivers/amlogic/drm/meson_hdmi.h [new file with mode: 0644]
drivers/amlogic/drm/meson_lcd.c [new file with mode: 0644]
drivers/amlogic/drm/meson_lcd.h [new file with mode: 0644]
drivers/amlogic/drm/meson_plane.c [new file with mode: 0644]
drivers/amlogic/drm/meson_plane.h [new file with mode: 0644]
drivers/amlogic/drm/meson_vpu.c [new file with mode: 0644]
drivers/amlogic/drm/meson_vpu.h [new file with mode: 0644]
drivers/amlogic/drm/meson_vpu_pipeline.c [new file with mode: 0644]
drivers/amlogic/drm/meson_vpu_pipeline.h [new file with mode: 0644]
drivers/amlogic/drm/meson_vpu_pipeline_private.c [new file with mode: 0644]
drivers/amlogic/drm/meson_vpu_pipeline_traverse.c [new file with mode: 0644]
drivers/amlogic/drm/meson_vpu_util.c [new file with mode: 0644]
drivers/amlogic/drm/meson_vpu_util.h [new file with mode: 0644]
drivers/amlogic/drm/vpu-hw/meson_osd_afbc.c [new file with mode: 0644]
drivers/amlogic/drm/vpu-hw/meson_osd_scaler.c [new file with mode: 0644]
drivers/amlogic/drm/vpu-hw/meson_osd_scaler.h [new file with mode: 0644]
drivers/amlogic/drm/vpu-hw/meson_vpu_dev.c [new file with mode: 0644]
drivers/amlogic/drm/vpu-hw/meson_vpu_hdr_dv.c [new file with mode: 0644]
drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.c [new file with mode: 0644]
drivers/amlogic/drm/vpu-hw/meson_vpu_osd_mif.h [new file with mode: 0644]
drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.c [new file with mode: 0644]
drivers/amlogic/drm/vpu-hw/meson_vpu_osdblend.h [new file with mode: 0644]
drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.c [new file with mode: 0644]
drivers/amlogic/drm/vpu-hw/meson_vpu_postblend.h [new file with mode: 0644]
drivers/amlogic/drm/vpu-hw/meson_vpu_reg.h [new file with mode: 0644]
include/dt-bindings/display/meson-drm-ids.h [new file with mode: 0644]
include/linux/amlogic/meson_drm.h [deleted file]
include/uapi/drm/drm_fourcc.h
include/uapi/drm/meson_drm.h [new file with mode: 0644]

index 0f36a16..5f1d410 100644 (file)
@@ -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
+
index 7b40c1c..c816c8f 100644 (file)
 &drm_vpu {
        status = "okay";
        logo_addr = "0x7f800000";
+       osd_ver = /bits/ 8 <OSD_V1>;
 };
 
 &drm_amhdmitx {
index 320f0aa..d9a3ed0 100644 (file)
@@ -19,7 +19,7 @@
 
 #include "mesong12b.dtsi"
 #include "mesong12b_skt-panel.dtsi"
-#include "mesong12a_drm.dtsi"
+#include "mesong12b_drm.dtsi"
 
 / {
        model = "Amlogic";
        status = "okay";
        compatible = "amlogic,meson-g12b-vpu";
        logo_addr = "0x7f800000";
+       osd_ver = /bits/ 8 <OSD_V3>;
 };
 
 &drm_amhdmitx {
index f21d6de..e889c24 100644 (file)
        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 (file)
index 0000000..3e069bc
--- /dev/null
@@ -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";
+};
index 00beafa..ceb5725 100644 (file)
  * 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>;
                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 (file)
index 0000000..48794f9
--- /dev/null
@@ -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>;
+               };
+       };
+};
index 380ba94..b43feaf 100644 (file)
 &drm_vpu {
        status = "okay";
        logo_addr = "0x7f800000";
+       osd_ver = /bits/ 8 <OSD_V1>;
 };
 
 &drm_amhdmitx {
index 512f9f5..adff020 100644 (file)
@@ -19,7 +19,7 @@
 
 #include "mesong12b.dtsi"
 #include "mesong12b_skt-panel.dtsi"
-#include "mesong12a_drm.dtsi"
+#include "mesong12b_drm.dtsi"
 
 / {
        model = "Amlogic";
        status = "okay";
        compatible = "amlogic,meson-g12b-vpu";
        logo_addr = "0x7f800000";
+       osd_ver = /bits/ 8 <OSD_V3>;
 };
 
 &drm_amhdmitx {
index b7c2bbf..109a044 100644 (file)
        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 (file)
index 0000000..207a2da
--- /dev/null
@@ -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>;
+};
index 60c3cff..175af58 100644 (file)
  * 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>;
                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 (file)
index 0000000..04e6f48
--- /dev/null
@@ -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>;
+               };
+       };
+};
index fec14e2..c8d62eb 100644 (file)
@@ -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/
 
index 6298cde..999b650 100644 (file)
@@ -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
index 2446575..bdbcd79 100644 (file)
@@ -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 (file)
index 218ddca..0000000
+++ /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 (file)
index 0000000..c463c64
--- /dev/null
@@ -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 (file)
index 0000000..dd06060
--- /dev/null
@@ -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
similarity index 94%
rename from drivers/amlogic/drm/am_meson_drv.c
rename to drivers/amlogic/drm/drm-v0/am_meson_drv.c
index 190cba3..2880b1c 100644 (file)
@@ -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>
similarity index 71%
rename from drivers/amlogic/drm/am_meson_drv.h
rename to drivers/amlogic/drm/drm-v0/am_meson_drv.h
index 77279a5..c935d91 100644 (file)
@@ -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
similarity index 98%
rename from drivers/amlogic/drm/am_meson_fb.c
rename to drivers/amlogic/drm/drm-v0/am_meson_fb.c
index 095f7ac..5ecd9e4 100644 (file)
@@ -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"
similarity index 96%
rename from drivers/amlogic/drm/am_meson_fb.h
rename to drivers/amlogic/drm/drm-v0/am_meson_fb.h
index faf0fce..1751f79 100644 (file)
@@ -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.
  *
similarity index 91%
rename from drivers/amlogic/drm/am_meson_fbdev.c
rename to drivers/amlogic/drm/drm-v0/am_meson_fbdev.c
index 610f3ca..1998697 100644 (file)
@@ -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/drm-v0/am_meson_fbdev.h b/drivers/amlogic/drm/drm-v0/am_meson_fbdev.h
new file mode 100644 (file)
index 0000000..c446f98
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * drivers/amlogic/drm/drm-v0/am_meson_fbdev.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 __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 */
similarity index 98%
rename from drivers/amlogic/drm/am_meson_gem.c
rename to drivers/amlogic/drm/drm-v0/am_meson_gem.c
index 9d731b8..b06d104 100644 (file)
@@ -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(
similarity index 97%
rename from drivers/amlogic/drm/am_meson_gem.h
rename to drivers/amlogic/drm/drm-v0/am_meson_gem.h
index f6dcc7e..166a73c 100644 (file)
@@ -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"
similarity index 99%
rename from drivers/amlogic/drm/am_meson_hdcp.c
rename to drivers/amlogic/drm/drm-v0/am_meson_hdcp.c
index 3c45c26..6e2f176 100644 (file)
@@ -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/drm-v0/am_meson_hdcp.h b/drivers/amlogic/drm/drm-v0/am_meson_hdcp.h
new file mode 100644 (file)
index 0000000..accf846
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * drivers/amlogic/drm/drm-v0/am_meson_hdcp.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 __AM_MESON_HDCP_H
+#define __AM_MESON_HDCP_H
+
+#define HDCP_SLAVE     0x3a
+#define HDCP2_VERSION  0x50
+#define HDCP_MODE14    1
+#define HDCP_MODE22    2
+
+#define HDCP_QUIT      0
+#define HDCP14_ENABLE  1
+#define HDCP14_AUTH    2
+#define HDCP14_SUCCESS 3
+#define HDCP14_FAIL    4
+#define HDCP22_ENABLE  5
+#define HDCP22_AUTH    6
+#define HDCP22_SUCCESS 7
+#define HDCP22_FAIL    8
+
+int am_hdcp_init(struct am_hdmi_tx *am_hdmi);
+int is_hdcp_hdmitx_supported(struct am_hdmi_tx *am_hdmi);
+int am_hdcp_work(void *data);
+void am_hdcp_disable(struct am_hdmi_tx *am_hdmi);
+
+#endif
similarity index 99%
rename from drivers/amlogic/drm/am_meson_hdmi.c
rename to drivers/amlogic/drm/drm-v0/am_meson_hdmi.c
index a2efd9c..7e1a3ee 100644 (file)
@@ -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>
similarity index 99%
rename from drivers/amlogic/drm/am_meson_hdmi.h
rename to drivers/amlogic/drm/drm-v0/am_meson_hdmi.h
index 37542dc..82a7bf0 100644 (file)
@@ -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
 
similarity index 99%
rename from drivers/amlogic/drm/am_meson_lcd.c
rename to drivers/amlogic/drm/drm-v0/am_meson_lcd.c
index 462338f..7613cf6 100644 (file)
@@ -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 = {
similarity index 93%
rename from drivers/amlogic/drm/am_meson_lcd.h
rename to drivers/amlogic/drm/drm-v0/am_meson_lcd.h
index 565f8eb..39ab4d4 100644 (file)
@@ -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.
  *
similarity index 99%
rename from drivers/amlogic/drm/am_meson_vpu.c
rename to drivers/amlogic/drm/drm-v0/am_meson_vpu.c
index 9c7850b..f44cbb3 100644 (file)
@@ -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>
similarity index 93%
rename from drivers/amlogic/drm/am_meson_vpu.h
rename to drivers/amlogic/drm/drm-v0/am_meson_vpu.h
index 03adbbe..5f94006 100644 (file)
@@ -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 (file)
index 0000000..f9a24d6
--- /dev/null
@@ -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 (file)
index 0000000..c02ff85
--- /dev/null
@@ -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/meson_drv.c b/drivers/amlogic/drm/meson_drv.c
new file mode 100644 (file)
index 0000000..eecde0e
--- /dev/null
@@ -0,0 +1,553 @@
+/*
+ * drivers/amlogic/drm/meson_drv.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/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/component.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_flip_work.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_rect.h>
+#include <drm/drm_fb_helper.h>
+
+#include "meson_fbdev.h"
+#ifdef CONFIG_DRM_MESON_USE_ION
+#include "meson_gem.h"
+#include "meson_fb.h"
+#endif
+#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
+       struct meson_drm *priv = dev->dev_private;
+
+       drm_fbdev_cma_hotplug_event(priv->fbdev);
+#endif
+}
+
+static const struct drm_mode_config_funcs meson_mode_config_funcs = {
+       .output_poll_changed = am_meson_fb_output_poll_changed,
+       .atomic_check        = drm_atomic_helper_check,
+       .atomic_commit       = drm_atomic_helper_commit,
+#ifdef CONFIG_DRM_MESON_USE_ION
+       .fb_create           = am_meson_fb_create,
+#else
+       .fb_create           = drm_fb_cma_create,
+#endif
+};
+
+int am_meson_register_crtc_funcs(struct drm_crtc *crtc,
+                                const struct meson_crtc_funcs *crtc_funcs)
+{
+       int pipe = drm_crtc_index(crtc);
+       struct meson_drm *priv = crtc->dev->dev_private;
+
+       if (pipe >= MESON_MAX_CRTC)
+               return -EINVAL;
+
+       priv->crtc_funcs[pipe] = crtc_funcs;
+
+       return 0;
+}
+EXPORT_SYMBOL(am_meson_register_crtc_funcs);
+
+void am_meson_unregister_crtc_funcs(struct drm_crtc *crtc)
+{
+       int pipe = drm_crtc_index(crtc);
+       struct meson_drm *priv = crtc->dev->dev_private;
+
+       if (pipe >= MESON_MAX_CRTC)
+               return;
+
+       priv->crtc_funcs[pipe] = NULL;
+}
+EXPORT_SYMBOL(am_meson_unregister_crtc_funcs);
+
+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)
+               return -EBADFD;
+
+       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)
+               return;
+
+       priv->crtc_funcs[crtc]->disable_vblank(priv->crtc);
+}
+
+static void am_meson_load(struct drm_device *dev)
+{
+#if 0
+       struct meson_drm *priv = dev->dev_private;
+       struct drm_crtc *crtc = priv->crtc;
+       int pipe = drm_crtc_index(crtc);
+
+       if (priv->crtc_funcs[pipe] &&
+               priv->crtc_funcs[pipe]->loader_protect)
+               priv->crtc_funcs[pipe]->loader_protect(crtc, true);
+#endif
+}
+
+#ifdef CONFIG_DRM_MESON_USE_ION
+static const struct drm_ioctl_desc meson_ioctls[] = {
+       DRM_IOCTL_DEF_DRV(MESON_GEM_CREATE, am_meson_gem_create_ioctl,
+               DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
+};
+#endif
+
+static const struct file_operations fops = {
+       .owner          = THIS_MODULE,
+       .open           = drm_open,
+       .release        = drm_release,
+       .unlocked_ioctl = drm_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = drm_compat_ioctl,
+#endif
+       .poll           = drm_poll,
+       .read           = drm_read,
+       .llseek         = no_llseek,
+#ifdef CONFIG_DRM_MESON_USE_ION
+       .mmap           = am_meson_gem_mmap,
+#else
+       .mmap           = drm_gem_cma_mmap,
+#endif
+};
+
+static struct drm_driver meson_driver = {
+       /*driver_features setting move to probe functions*/
+       .driver_features        = 0,
+       /* Vblank */
+       .enable_vblank          = am_meson_enable_vblank,
+       .disable_vblank         = am_meson_disable_vblank,
+       .get_vblank_counter     = drm_vblank_no_hw_counter,
+
+#ifdef CONFIG_DRM_MESON_USE_ION
+       /* PRIME Ops */
+       .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
+       .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
+
+       .gem_prime_export       = drm_gem_prime_export,
+       .gem_prime_get_sg_table = am_meson_gem_prime_get_sg_table,
+
+       .gem_prime_import       = drm_gem_prime_import,
+       /*
+        * If gem_prime_import_sg_table is NULL,only buffer created
+        * by meson driver can be imported ok.
+        */
+       /*.gem_prime_import_sg_table = am_meson_gem_prime_import_sg_table,*/
+
+       .gem_prime_vmap         = am_meson_gem_prime_vmap,
+       .gem_prime_vunmap       = am_meson_gem_prime_vunmap,
+       .gem_prime_mmap         = am_meson_gem_prime_mmap,
+
+       /* GEM Ops */
+       .dumb_create                    = am_meson_gem_dumb_create,
+       .dumb_destroy           = am_meson_gem_dumb_destroy,
+       .dumb_map_offset                = am_meson_gem_dumb_map_offset,
+       .gem_free_object_unlocked       = am_meson_gem_object_free,
+       .gem_vm_ops                     = &drm_gem_cma_vm_ops,
+       .ioctls                 = meson_ioctls,
+       .num_ioctls             = ARRAY_SIZE(meson_ioctls),
+#else
+       /* PRIME Ops */
+       .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
+       .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
+       .gem_prime_import       = drm_gem_prime_import,
+       .gem_prime_export       = drm_gem_prime_export,
+       .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
+       .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+       .gem_prime_vmap         = drm_gem_cma_prime_vmap,
+       .gem_prime_vunmap       = drm_gem_cma_prime_vunmap,
+       .gem_prime_mmap         = drm_gem_cma_prime_mmap,
+
+       /* GEM Ops */
+       .dumb_create            = drm_gem_cma_dumb_create,
+       .dumb_destroy           = drm_gem_dumb_destroy,
+       .dumb_map_offset        = drm_gem_cma_dumb_map_offset,
+       .gem_free_object_unlocked = drm_gem_cma_free_object,
+       .gem_vm_ops             = &drm_gem_cma_vm_ops,
+#endif
+
+       /* Misc */
+       .fops                   = &fops,
+       .name                   = DRIVER_NAME,
+       .desc                   = DRIVER_DESC,
+       .date                   = "20180321",
+       .major                  = 1,
+       .minor                  = 0,
+};
+
+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 |
+               DRIVER_MODESET | DRIVER_PRIME |
+               DRIVER_ATOMIC | DRIVER_IRQ_SHARED;
+
+       drm = drm_dev_alloc(&meson_driver, dev);
+       if (!drm)
+               return -ENOMEM;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv) {
+               ret = -ENOMEM;
+               goto err_free1;
+       }
+       drm->dev_private = priv;
+       priv->drm = drm;
+       priv->dev = dev;
+       dev_set_drvdata(dev, priv);
+
+#ifdef CONFIG_DRM_MESON_USE_ION
+       ret = am_meson_gem_create(priv);
+       if (ret)
+               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. */
+       ret = component_bind_all(dev, drm);
+       if (ret)
+               goto err_gem;
+       DRM_INFO("mode_config crtc number:%d\n", drm->mode_config.num_crtc);
+
+       ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
+       if (ret)
+               goto err_unbind_all;
+
+       drm_mode_config_reset(drm);
+       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.
+        */
+       drm->irq_enabled = true;
+
+       drm_kms_helper_poll_init(drm);
+
+       am_meson_load(drm);
+
+#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
+       ret = am_meson_drm_fbdev_init(drm);
+       if (ret)
+               goto err_poll_fini;
+#endif
+       ret = drm_dev_register(drm, 0);
+       if (ret)
+               goto err_fbdev_fini;
+
+       return 0;
+
+
+err_fbdev_fini:
+#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
+       am_meson_drm_fbdev_fini(drm);
+err_poll_fini:
+#endif
+       drm_kms_helper_poll_fini(drm);
+       drm->irq_enabled = false;
+       drm_vblank_cleanup(drm);
+err_unbind_all:
+       component_unbind_all(dev, drm);
+err_gem:
+       drm_mode_config_cleanup(drm);
+#ifdef CONFIG_DRM_MESON_USE_ION
+       am_meson_gem_cleanup(drm->dev_private);
+err_free2:
+#endif
+       drm->dev_private = NULL;
+       dev_set_drvdata(dev, NULL);
+err_free1:
+       drm_dev_unref(drm);
+
+       return ret;
+}
+
+static void am_meson_drm_unbind(struct device *dev)
+{
+       struct drm_device *drm = dev_get_drvdata(dev);
+
+       drm_dev_unregister(drm);
+#ifdef CONFIG_DRM_MESON_EMULATE_FBDEV
+       am_meson_drm_fbdev_fini(drm);
+#endif
+       drm_kms_helper_poll_fini(drm);
+       drm->irq_enabled = false;
+       drm_vblank_cleanup(drm);
+       component_unbind_all(dev, drm);
+       drm_mode_config_cleanup(drm);
+#ifdef CONFIG_DRM_MESON_USE_ION
+       am_meson_gem_cleanup(drm->dev_private);
+#endif
+       drm->dev_private = NULL;
+       dev_set_drvdata(dev, NULL);
+       drm_dev_unref(drm);
+}
+
+static int compare_of(struct device *dev, void *data)
+{
+       struct device_node *np = data;
+
+       return dev->of_node == np;
+}
+
+static void am_meson_add_endpoints(struct device *dev,
+                                  struct component_match **match,
+                                  struct device_node *port)
+{
+       struct device_node *ep, *remote;
+
+       for_each_child_of_node(port, ep) {
+               remote = of_graph_get_remote_port_parent(ep);
+               if (!remote || !of_device_is_available(remote)) {
+                       of_node_put(remote);
+                       continue;
+               } else if (!of_device_is_available(remote->parent)) {
+                       of_node_put(remote);
+                       continue;
+               }
+               component_match_add(dev, match, compare_of, remote);
+               of_node_put(remote);
+       }
+}
+
+static const struct component_master_ops am_meson_drm_ops = {
+       .bind = am_meson_drm_bind,
+       .unbind = am_meson_drm_unbind,
+};
+
+static bool am_meson_drv_use_osd(void)
+{
+       struct device_node *node;
+       const  char *str;
+       int ret;
+
+       node = of_find_node_by_path("/meson-fb");
+       if (node) {
+               ret = of_property_read_string(node, "status", &str);
+               if (ret) {
+                       DRM_INFO("get 'status' failed:%d\n", ret);
+                       return false;
+               }
+
+               if (strcmp(str, "okay") && strcmp(str, "ok")) {
+                       DRM_INFO("device %s status is %s\n",
+                               node->name, str);
+               } else {
+                       DRM_INFO("device %s status is %s\n",
+                               node->name, str);
+                       return true;
+               }
+       }
+       return false;
+}
+
+static int am_meson_drv_probe_prune(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct meson_drm *priv;
+       struct drm_device *drm;
+       int ret;
+
+       /*driver_features reset to DRIVER_GEM | DRIVER_PRIME, for prune drm*/
+       meson_driver.driver_features = DRIVER_GEM | DRIVER_PRIME;
+
+       drm = drm_dev_alloc(&meson_driver, dev);
+       if (!drm)
+               return -ENOMEM;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv) {
+               ret = -ENOMEM;
+               goto err_free1;
+       }
+       drm->dev_private = priv;
+       priv->drm = drm;
+       priv->dev = dev;
+
+       platform_set_drvdata(pdev, priv);
+
+#ifdef CONFIG_DRM_MESON_USE_ION
+       ret = am_meson_gem_create(priv);
+       if (ret)
+               goto err_free2;
+#endif
+
+       ret = drm_dev_register(drm, 0);
+       if (ret)
+               goto err_gem;
+
+       return 0;
+
+err_gem:
+#ifdef CONFIG_DRM_MESON_USE_ION
+       am_meson_gem_cleanup(drm->dev_private);
+err_free2:
+#endif
+       drm->dev_private = NULL;
+       platform_set_drvdata(pdev, NULL);
+err_free1:
+       drm_dev_unref(drm);
+       return ret;
+}
+
+static int am_meson_drv_remove_prune(struct platform_device *pdev)
+{
+       struct drm_device *drm = platform_get_drvdata(pdev);
+
+       drm_dev_unregister(drm);
+#ifdef CONFIG_DRM_MESON_USE_ION
+       am_meson_gem_cleanup(drm->dev_private);
+#endif
+       drm->dev_private = NULL;
+       platform_set_drvdata(pdev, NULL);
+       drm_dev_unref(drm);
+
+       return 0;
+}
+
+static int am_meson_drv_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct device_node *port;
+       struct component_match *match = NULL;
+       int i;
+
+       if (am_meson_drv_use_osd())
+               return am_meson_drv_probe_prune(pdev);
+
+       if (!np)
+               return -ENODEV;
+
+       /*
+        * Bind the crtc ports first, so that
+        * drm_of_find_possible_crtcs called from encoder .bind callbacks
+        * works as expected.
+        */
+       for (i = 0;; i++) {
+               port = of_parse_phandle(np, "ports", i);
+               if (!port)
+                       break;
+
+               if (!of_device_is_available(port->parent)) {
+                       of_node_put(port);
+                       continue;
+               }
+
+               component_match_add(dev, &match, compare_of, port->parent);
+               of_node_put(port);
+       }
+
+       if (i == 0) {
+               dev_err(dev, "missing 'ports' property.\n");
+               return -ENODEV;
+       }
+
+       if (!match) {
+               dev_err(dev, "No available vout found for display-subsystem.\n");
+               return -ENODEV;
+       }
+
+       /*
+        * For each bound crtc, bind the encoders attached to its
+        * remote endpoint.
+        */
+       for (i = 0;; i++) {
+               port = of_parse_phandle(np, "ports", i);
+               if (!port)
+                       break;
+
+               if (!of_device_is_available(port->parent)) {
+                       of_node_put(port);
+                       continue;
+               }
+
+               am_meson_add_endpoints(dev, &match, port);
+               of_node_put(port);
+       }
+
+       return component_master_add_with_match(dev, &am_meson_drm_ops, match);
+}
+
+static int am_meson_drv_remove(struct platform_device *pdev)
+{
+       if (am_meson_drv_use_osd())
+               return am_meson_drv_remove_prune(pdev);
+
+       component_master_del(&pdev->dev, &am_meson_drm_ops);
+       return 0;
+}
+
+static const struct of_device_id am_meson_drm_dt_match[] = {
+       { .compatible = "amlogic,drm-subsystem" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, am_meson_drm_dt_match);
+
+static struct platform_driver am_meson_drm_platform_driver = {
+       .probe      = am_meson_drv_probe,
+       .remove     = am_meson_drv_remove,
+       .driver     = {
+               .owner  = THIS_MODULE,
+               .name   = DRIVER_NAME,
+               .of_match_table = am_meson_drm_dt_match,
+       },
+};
+
+module_platform_driver(am_meson_drm_platform_driver);
+
+MODULE_AUTHOR("Jasper St. Pierre <jstpierre@mecheye.net>");
+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
+MODULE_AUTHOR("MultiMedia Amlogic <multimedia-sh@amlogic.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/amlogic/drm/meson_drv.h b/drivers/amlogic/drm/meson_drv.h
new file mode 100644 (file)
index 0000000..40ca261
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * drivers/amlogic/drm/meson_drv.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 __AM_MESON_DRV_H
+#define __AM_MESON_DRV_H
+
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <drm/drmP.h>
+#ifdef CONFIG_DRM_MESON_USE_ION
+#include <ion/ion_priv.h>
+#endif
+
+#define MESON_MAX_CRTC         2
+#define MESON_MAX_OSD          4
+
+/*
+ * Amlogic drm private crtc funcs.
+ * @loader_protect: protect loader logo crtc's power
+ * @enable_vblank: enable crtc vblank irq.
+ * @disable_vblank: disable crtc vblank irq.
+ */
+struct meson_crtc_funcs {
+       int (*loader_protect)(struct drm_crtc *crtc, bool on);
+       int (*enable_vblank)(struct drm_crtc *crtc);
+       void (*disable_vblank)(struct drm_crtc *crtc);
+};
+
+struct meson_drm {
+       struct device *dev;
+
+       struct drm_device *drm;
+       struct drm_crtc *crtc;
+       const struct meson_crtc_funcs *crtc_funcs[MESON_MAX_CRTC];
+       struct drm_fbdev_cma *fbdev;
+       struct drm_fb_helper *fbdev_helper;
+       struct drm_gem_object *fbdev_bo;
+       struct drm_plane *primary_plane;
+       struct drm_plane *cursor_plane;
+
+#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,
+                                         const char *compat)
+{
+       return of_device_is_compatible(priv->dev->of_node, compat);
+}
+
+extern int am_meson_register_crtc_funcs(struct drm_crtc *crtc,
+                                const struct meson_crtc_funcs *crtc_funcs);
+extern void am_meson_unregister_crtc_funcs(struct drm_crtc *crtc);
+
+#endif /* __AM_MESON_DRV_H */
diff --git a/drivers/amlogic/drm/meson_fb.c b/drivers/amlogic/drm/meson_fb.c
new file mode 100644 (file)
index 0000000..1c364da
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * drivers/amlogic/drm/meson_fb.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_helper.h>
+
+#include "meson_fb.h"
+
+#define to_am_meson_fb(x) container_of(x, struct am_meson_fb, base)
+
+void am_meson_fb_destroy(struct drm_framebuffer *fb)
+{
+       struct am_meson_fb *meson_fb = to_am_meson_fb(fb);
+
+       drm_gem_object_unreference_unlocked(&meson_fb->bufp->base);
+       drm_framebuffer_cleanup(fb);
+       kfree(meson_fb);
+}
+
+int am_meson_fb_create_handle(struct drm_framebuffer *fb,
+            struct drm_file *file_priv,
+            unsigned int *handle)
+{
+       struct am_meson_fb *meson_fb = to_am_meson_fb(fb);
+
+       return drm_gem_handle_create(file_priv,
+                                    &meson_fb->bufp->base, handle);
+}
+
+struct drm_framebuffer_funcs am_meson_fb_funcs = {
+       .create_handle = am_meson_fb_create_handle, //must for fbdev emulate
+       .destroy = am_meson_fb_destroy,
+};
+
+struct drm_framebuffer *
+am_meson_fb_alloc(struct drm_device *dev,
+                 struct drm_mode_fb_cmd2 *mode_cmd,
+                 struct drm_gem_object *obj)
+{
+       struct am_meson_fb *meson_fb;
+       struct am_meson_gem_object *meson_gem;
+       int ret = 0;
+
+       meson_fb = kzalloc(sizeof(*meson_fb), GFP_KERNEL);
+       if (!meson_fb)
+               return ERR_PTR(-ENOMEM);
+
+       meson_gem = container_of(obj, struct am_meson_gem_object, base);
+       meson_fb->bufp = meson_gem;
+
+       drm_helper_mode_fill_fb_struct(&meson_fb->base, mode_cmd);
+
+       ret = drm_framebuffer_init(dev, &meson_fb->base,
+                                  &am_meson_fb_funcs);
+       if (ret) {
+               dev_err(dev->dev, "Failed to initialize framebuffer: %d\n",
+                       ret);
+               goto err_free_fb;
+       }
+
+       return &meson_fb->base;
+
+err_free_fb:
+       kfree(meson_fb);
+       return ERR_PTR(ret);
+}
+
+struct drm_framebuffer *am_meson_fb_create(struct drm_device *dev,
+                                    struct drm_file *file_priv,
+                                    const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+       struct am_meson_fb *meson_fb = 0;
+       struct drm_gem_object *obj = 0;
+       struct am_meson_gem_object *meson_gem;
+       int ret;
+
+       meson_fb = kzalloc(sizeof(*meson_fb), GFP_KERNEL);
+       if (!meson_fb)
+               return ERR_PTR(-ENOMEM);
+
+       /* only support one handle now.*/
+       obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
+       if (!obj) {
+               dev_err(dev->dev, "Failed to lookup GEM handle\n");
+               kfree(meson_fb);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       meson_gem = container_of(obj, struct am_meson_gem_object, base);
+       meson_fb->bufp = meson_gem;
+
+       drm_helper_mode_fill_fb_struct(&meson_fb->base, mode_cmd);
+
+       ret = drm_framebuffer_init(dev, &meson_fb->base, &am_meson_fb_funcs);
+       if (ret) {
+               dev_err(dev->dev,
+                       "Failed to initialize framebuffer: %d\n",
+                       ret);
+               drm_gem_object_unreference(obj);
+               kfree(meson_fb);
+               return ERR_PTR(ret);
+       }
+
+       return &meson_fb->base;
+}
+
+struct drm_framebuffer *
+am_meson_drm_framebuffer_init(struct drm_device *dev,
+                             struct drm_mode_fb_cmd2 *mode_cmd,
+                             struct drm_gem_object *obj)
+{
+       struct drm_framebuffer *fb;
+
+       fb = am_meson_fb_alloc(dev, mode_cmd, obj);
+       if (IS_ERR(fb))
+               return NULL;
+
+       return fb;
+}
diff --git a/drivers/amlogic/drm/meson_fb.h b/drivers/amlogic/drm/meson_fb.h
new file mode 100644 (file)
index 0000000..9c76d2e
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * drivers/amlogic/drm/meson_fb.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 __AM_MESON_FB_H
+#define __AM_MESON_FB_H
+#include <drm/drmP.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_modeset_helper.h>
+
+#include "meson_gem.h"
+
+struct am_meson_fb {
+       struct drm_framebuffer base;
+       struct am_meson_gem_object *bufp;
+};
+
+struct drm_framebuffer *am_meson_fb_create(struct drm_device *dev,
+                                    struct drm_file *file_priv,
+                                    const struct drm_mode_fb_cmd2 *mode_cmd);
+struct drm_framebuffer *am_meson_drm_framebuffer_init(
+                                    struct drm_device *dev,
+                                    struct drm_mode_fb_cmd2 *mode_cmd,
+                                    struct drm_gem_object *obj);
+#endif
diff --git a/drivers/amlogic/drm/meson_fbdev.c b/drivers/amlogic/drm/meson_fbdev.c
new file mode 100644 (file)
index 0000000..b43788f
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * drivers/amlogic/drm/meson_fbdev.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.h>
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_crtc_helper.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
+
+static int am_meson_fbdev_mmap(struct fb_info *info,
+       struct vm_area_struct *vma)
+{
+       struct drm_fb_helper *helper = info->par;
+       struct meson_drm *private;
+       struct am_meson_gem_object *meson_gem;
+
+       private = helper->dev->dev_private;
+       meson_gem = container_of(private->fbdev_bo,
+               struct am_meson_gem_object, base);
+
+       return am_meson_gem_object_mmap(meson_gem, vma);
+}
+
+static int am_meson_drm_fbdev_sync(struct fb_info *info)
+{
+       return 0;
+}
+
+static int am_meson_drm_fbdev_ioctl(struct fb_info *info,
+       unsigned int cmd, unsigned long arg)
+{
+       return 0;
+}
+
+static struct fb_ops meson_drm_fbdev_ops = {
+       .owner          = THIS_MODULE,
+       .fb_mmap        = am_meson_fbdev_mmap,
+       .fb_fillrect    = drm_fb_helper_cfb_fillrect,
+       .fb_copyarea    = drm_fb_helper_cfb_copyarea,
+       .fb_imageblit   = drm_fb_helper_cfb_imageblit,
+       .fb_check_var   = drm_fb_helper_check_var,
+       .fb_set_par     = drm_fb_helper_set_par,
+       .fb_blank       = drm_fb_helper_blank,
+       .fb_pan_display = drm_fb_helper_pan_display,
+       .fb_setcmap     = drm_fb_helper_setcmap,
+       .fb_sync        = am_meson_drm_fbdev_sync,
+       .fb_ioctl       = am_meson_drm_fbdev_ioctl,
+#ifdef CONFIG_COMPAT
+       .fb_compat_ioctl = am_meson_drm_fbdev_ioctl,
+#endif
+};
+
+static int am_meson_drm_fbdev_create(struct drm_fb_helper *helper,
+       struct drm_fb_helper_surface_size *sizes)
+{
+       struct meson_drm *private = helper->dev->dev_private;
+       struct drm_mode_fb_cmd2 mode_cmd = { 0 };
+       struct drm_device *dev = helper->dev;
+       struct am_meson_gem_object *meson_obj;
+       struct drm_framebuffer *fb;
+       struct ion_client *client;
+       unsigned int bytes_per_pixel;
+       unsigned long offset;
+       struct fb_info *fbi;
+       size_t size;
+       int ret;
+
+       bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
+
+       mode_cmd.width = sizes->surface_width;
+       mode_cmd.height = sizes->surface_height;
+       mode_cmd.pitches[0] = ALIGN(sizes->surface_width * bytes_per_pixel, 64);
+       mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+               sizes->surface_depth);
+
+       size = mode_cmd.pitches[0] * mode_cmd.height;
+
+       client = (struct ion_client *)private->gem_client;
+       meson_obj = am_meson_gem_object_create(dev, 0, size, client);
+       if (IS_ERR(meson_obj))
+               return -ENOMEM;
+
+       private->fbdev_bo = &meson_obj->base;
+
+       fbi = drm_fb_helper_alloc_fbi(helper);
+       if (IS_ERR(fbi)) {
+               dev_err(dev->dev, "Failed to create framebuffer info.\n");
+               ret = PTR_ERR(fbi);
+               goto err_meson_gem_free_object;
+       }
+
+       helper->fb = am_meson_drm_framebuffer_init(dev, &mode_cmd,
+                                                  private->fbdev_bo);
+       if (IS_ERR(helper->fb)) {
+               dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n");
+               ret = PTR_ERR(helper->fb);
+               goto err_release_fbi;
+       }
+
+       fbi->par = helper;
+       fbi->flags = FBINFO_FLAG_DEFAULT;
+       fbi->fbops = &meson_drm_fbdev_ops;
+
+       fb = helper->fb;
+       drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
+       drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
+
+       offset = fbi->var.xoffset * bytes_per_pixel;
+       offset += fbi->var.yoffset * fb->pitches[0];
+
+       dev->mode_config.fb_base = 0;
+       fbi->screen_size = size;
+       fbi->fix.smem_len = size;
+
+       DRM_DEBUG_KMS("FB [%dx%d]-%d offset=%ld size=%zu\n",
+                     fb->width, fb->height, fb->depth, offset, size);
+
+       fbi->skip_vt_switch = true;
+
+       return 0;
+
+err_release_fbi:
+       drm_fb_helper_release_fbi(helper);
+err_meson_gem_free_object:
+       am_meson_gem_object_free(&meson_obj->base);
+       return ret;
+}
+
+static const struct drm_fb_helper_funcs meson_drm_fb_helper_funcs = {
+       .fb_probe = am_meson_drm_fbdev_create,
+};
+
+int am_meson_drm_fbdev_init(struct drm_device *dev)
+{
+       struct meson_drm *private = dev->dev_private;
+       struct drm_fb_helper *helper;
+       unsigned int num_crtc;
+       int ret;
+
+       if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector)
+               return -EINVAL;
+
+       num_crtc = dev->mode_config.num_crtc;
+
+       helper = devm_kzalloc(dev->dev, sizeof(*helper), GFP_KERNEL);
+       if (!helper)
+               return -ENOMEM;
+
+       drm_fb_helper_prepare(dev, helper, &meson_drm_fb_helper_funcs);
+
+       ret = drm_fb_helper_init(dev, helper, num_crtc,
+               MESON_DRM_MAX_CONNECTOR);
+       if (ret < 0) {
+               dev_err(dev->dev, "Failed to initialize drm fb helper - %d.\n",
+                       ret);
+               goto err_free;
+       }
+
+       ret = drm_fb_helper_single_add_all_connectors(helper);
+       if (ret < 0) {
+               dev_err(dev->dev, "Failed to add connectors - %d.\n", ret);
+               goto err_drm_fb_helper_fini;
+       }
+
+       ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP);
+       if (ret < 0) {
+               dev_err(dev->dev, "Failed to set initial hw config - %d.\n",
+                       ret);
+               goto err_drm_fb_helper_fini;
+       }
+
+       private->fbdev_helper = helper;
+
+       return 0;
+
+err_drm_fb_helper_fini:
+       drm_fb_helper_fini(helper);
+err_free:
+       kfree(fbdev_cma);
+       return ret;
+}
+
+void am_meson_drm_fbdev_fini(struct drm_device *dev)
+{
+       struct meson_drm *private = dev->dev_private;
+       struct drm_fb_helper *helper = private->fbdev_helper;
+
+       if (!helper)
+               return;
+
+       drm_fb_helper_unregister_fbi(helper);
+       drm_fb_helper_release_fbi(helper);
+
+       if (helper->fb)
+               drm_framebuffer_unreference(helper->fb);
+
+       drm_fb_helper_fini(helper);
+}
diff --git a/drivers/amlogic/drm/meson_fbdev.h b/drivers/amlogic/drm/meson_fbdev.h
new file mode 100644 (file)
index 0000000..898c262
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * drivers/amlogic/drm/meson_fbdev.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 __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/meson_gem.c b/drivers/amlogic/drm/meson_gem.c
new file mode 100644 (file)
index 0000000..051cfce
--- /dev/null
@@ -0,0 +1,475 @@
+/*
+ * drivers/amlogic/drm/meson_gem.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_gem.h>
+#include <drm/drm_vma_manager.h>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/dma-buf.h>
+#include <linux/meson_ion.h>
+#include <ion/ion.h>
+
+#include "meson_gem.h"
+
+#define to_am_meson_gem_obj(x) container_of(x, struct am_meson_gem_object, base)
+
+static int am_meson_gem_alloc_ion_buff(
+       struct ion_client *client,
+       struct am_meson_gem_object *meson_gem_obj,
+       int flags)
+{
+       struct ion_handle *handle;
+       bool bscatter = false;
+
+       if (!client)
+               return -EINVAL;
+
+       if (!meson_gem_obj)
+               return -EINVAL;
+
+       //check flags to set different ion heap type.
+       //if flags is set to 0, need to use ion dma buffer.
+       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 {
+               handle = ion_alloc(client, meson_gem_obj->base.size,
+                                       0, (1 << ION_HEAP_TYPE_SYSTEM), 0);
+               bscatter = true;
+       }
+
+       if (IS_ERR(handle)) {
+               DRM_ERROR("%s: FAILED, flags:0x%x.\n",
+                       __func__, flags);
+               return -ENOMEM;
+       }
+
+       meson_gem_obj->handle = handle;
+       meson_gem_obj->bscatter = bscatter;
+       DRM_DEBUG("%s: allocate handle (%p).\n",
+               __func__, meson_gem_obj->handle);
+       return 0;
+}
+
+static void am_meson_gem_free_ion_buf(
+       struct drm_device *dev,
+       struct am_meson_gem_object *meson_gem_obj)
+{
+       struct ion_client *client = NULL;
+
+       if (meson_gem_obj->handle) {
+               DRM_DEBUG("am_meson_gem_free_ion_buf free handle  (%p).\n",
+                       meson_gem_obj->handle);
+               client = meson_gem_obj->handle->client;
+               ion_free(client, meson_gem_obj->handle);
+               meson_gem_obj->handle = NULL;
+       } else {
+               DRM_ERROR("meson_gem_obj handle is null\n");
+       }
+}
+
+struct am_meson_gem_object *am_meson_gem_object_create(
+       struct drm_device *dev,
+       unsigned int flags,
+       unsigned long size,
+       struct ion_client *client)
+{
+       struct am_meson_gem_object *meson_gem_obj = NULL;
+       int ret;
+
+       if (!size) {
+               DRM_ERROR("invalid size.\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       size = roundup(size, PAGE_SIZE);
+       meson_gem_obj = kzalloc(sizeof(*meson_gem_obj), GFP_KERNEL);
+       if (!meson_gem_obj)
+               return ERR_PTR(-ENOMEM);
+
+       ret = drm_gem_object_init(dev, &meson_gem_obj->base, size);
+       if (ret < 0) {
+               DRM_ERROR("failed to initialize gem object\n");
+               goto error;
+       }
+
+       ret = am_meson_gem_alloc_ion_buff(client, meson_gem_obj, flags);
+       if (ret < 0) {
+               drm_gem_object_release(&meson_gem_obj->base);
+               goto error;
+       }
+
+       return meson_gem_obj;
+
+error:
+       kfree(meson_gem_obj);
+       return ERR_PTR(ret);
+}
+
+void am_meson_gem_object_free(struct drm_gem_object *obj)
+{
+       struct am_meson_gem_object *meson_gem_obj = to_am_meson_gem_obj(obj);
+
+       DRM_DEBUG("am_meson_gem_object_free %p handle count = %d\n",
+               meson_gem_obj, obj->handle_count);
+
+       if (obj->import_attach == false)
+               am_meson_gem_free_ion_buf(obj->dev, meson_gem_obj);
+       else
+               DRM_ERROR("Not support import buffer from other driver.\n");
+
+       drm_gem_free_mmap_offset(obj);
+
+       /* release file pointer to gem object. */
+       drm_gem_object_release(obj);
+
+       kfree(meson_gem_obj);
+       meson_gem_obj = NULL;
+}
+
+int am_meson_gem_object_mmap(
+       struct am_meson_gem_object *obj,
+       struct vm_area_struct *vma)
+{
+       int ret = 0;
+       struct ion_buffer *buffer;
+
+       /*
+        * Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the
+        * vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map
+        * the whole buffer.
+        */
+       vma->vm_flags &= ~VM_PFNMAP;
+       vma->vm_pgoff = 0;
+
+       if (obj->base.import_attach) {
+               DRM_ERROR("Not support import buffer from other driver.\n");
+       } else {
+               buffer = obj->handle->buffer;
+
+               if (!buffer->heap->ops->map_user) {
+                       DRM_ERROR("%s:heap does not define map to userspace\n",
+                              __func__);
+                       ret = -EINVAL;
+               } else {
+
+                       if (!(buffer->flags & ION_FLAG_CACHED))
+                               vma->vm_page_prot =
+                                       pgprot_writecombine(vma->vm_page_prot);
+
+                       mutex_lock(&buffer->lock);
+                       /* now map it to userspace */
+                       ret = buffer->heap->ops->map_user(
+                                               buffer->heap, buffer, vma);
+                       mutex_unlock(&buffer->lock);
+               }
+       }
+
+       if (ret) {
+               DRM_ERROR("%s: failure mapping buffer to userspace (%d)\n",
+                      __func__, ret);
+               drm_gem_vm_close(vma);
+       }
+
+       return ret;
+}
+
+int am_meson_gem_mmap(
+       struct file *filp,
+       struct vm_area_struct *vma)
+{
+       struct drm_gem_object *obj;
+       struct am_meson_gem_object *meson_gem_obj;
+       int ret;
+
+       ret = drm_gem_mmap(filp, vma);
+       if (ret)
+               return ret;
+
+       obj = vma->vm_private_data;
+       meson_gem_obj = to_am_meson_gem_obj(obj);
+       DRM_DEBUG("am_meson_gem_mmap %p.\n", meson_gem_obj);
+
+       ret = am_meson_gem_object_mmap(meson_gem_obj, vma);
+
+       return ret;
+}
+
+int am_meson_gem_object_get_phyaddr(
+       struct meson_drm *drm,
+       struct am_meson_gem_object *meson_gem)
+{
+       int addr;
+       size_t len;
+
+       if (!meson_gem->handle) {
+               DRM_INFO("%s handle null\n", __func__);
+               return -1;
+       }
+
+       ion_phys(drm->gem_client, meson_gem->handle,
+                                               (ion_phys_addr_t *)&addr, &len);
+
+       return addr;
+}
+EXPORT_SYMBOL(am_meson_gem_object_get_phyaddr);
+
+int am_meson_gem_dumb_create(
+       struct drm_file *file_priv,
+       struct drm_device *dev,
+       struct drm_mode_create_dumb *args)
+{
+       int ret = 0;
+       struct am_meson_gem_object *meson_gem_obj;
+       struct meson_drm *drmdrv = dev->dev_private;
+       struct ion_client *client = (struct ion_client *)drmdrv->gem_client;
+       int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+
+       args->pitch = ALIGN(min_pitch, 64);
+       if (args->size < args->pitch * args->height)
+               args->size = args->pitch * args->height;
+
+       args->size = round_up(args->size, PAGE_SIZE);
+
+       meson_gem_obj = am_meson_gem_object_create(
+                                       dev, args->flags, args->size, client);
+       if (IS_ERR(meson_gem_obj))
+               return PTR_ERR(meson_gem_obj);
+
+       /*
+        * allocate a id of idr table where the obj is registered
+        * and handle has the id what user can see.
+        */
+       ret = drm_gem_handle_create(file_priv,
+                       &meson_gem_obj->base, &args->handle);
+       /* drop reference from allocate - handle holds it now. */
+       drm_gem_object_unreference_unlocked(&meson_gem_obj->base);
+       if (ret) {
+               DRM_ERROR("%s: create dumb handle failed %d\n",
+                       __func__, ret);
+               return ret;
+       }
+
+       DRM_DEBUG("%s: create dumb %p  with gem handle (0x%x)\n",
+               __func__, meson_gem_obj, args->handle);
+       return 0;
+}
+
+int am_meson_gem_dumb_destroy(
+       struct drm_file *file,
+       struct drm_device *dev,
+       uint32_t handle)
+{
+       DRM_DEBUG("%s: destroy dumb with handle (0x%x)\n", __func__, handle);
+       drm_gem_handle_delete(file, handle);
+       return 0;
+}
+
+int am_meson_gem_dumb_map_offset(
+       struct drm_file *file_priv,
+       struct drm_device *dev,
+       uint32_t handle,
+       uint64_t *offset)
+{
+       struct drm_gem_object *obj;
+       int ret = 0;
+
+       mutex_lock(&dev->struct_mutex);
+
+       /*
+        * get offset of memory allocated for drm framebuffer.
+        * - this callback would be called by user application
+        *      with DRM_IOCTL_MODE_MAP_DUMB command.
+        */
+       obj = drm_gem_object_lookup(file_priv, handle);
+       if (!obj) {
+               DRM_ERROR("failed to lookup gem object.\n");
+               ret = -EINVAL;
+               goto unlock;
+       }
+
+       ret = drm_gem_create_mmap_offset(obj);
+       if (ret)
+               goto out;
+
+       *offset = drm_vma_node_offset_addr(&obj->vma_node);
+       DRM_DEBUG("offset = 0x%lx\n", (unsigned long)*offset);
+
+out:
+       drm_gem_object_unreference(obj);
+unlock:
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
+}
+
+int am_meson_gem_create_ioctl(
+       struct drm_device *dev,
+       void *data,
+       struct drm_file *file_priv)
+{
+       struct am_meson_gem_object *meson_gem_obj;
+       struct meson_drm *drmdrv = dev->dev_private;
+       struct ion_client *client = (struct ion_client *)drmdrv->gem_client;
+       struct drm_meson_gem_create *args = data;
+       int ret = 0;
+
+       meson_gem_obj = am_meson_gem_object_create(
+                                       dev, args->flags, args->size, client);
+       if (IS_ERR(meson_gem_obj))
+               return PTR_ERR(meson_gem_obj);
+
+       /*
+        * allocate a id of idr table where the obj is registered
+        * and handle has the id what user can see.
+        */
+       ret = drm_gem_handle_create(file_priv,
+                       &meson_gem_obj->base, &args->handle);
+       /* drop reference from allocate - handle holds it now. */
+       drm_gem_object_unreference_unlocked(&meson_gem_obj->base);
+       if (ret) {
+               DRM_ERROR("%s: create dumb handle failed %d\n",
+                       __func__, ret);
+               return ret;
+       }
+
+       DRM_DEBUG("%s: create dumb %p  with gem handle (0x%x)\n",
+               __func__, meson_gem_obj, args->handle);
+       return 0;
+}
+
+
+int am_meson_gem_create(struct meson_drm  *drmdrv)
+{
+       drmdrv->gem_client = meson_ion_client_create(-1, "meson-gem");
+       if (!drmdrv->gem_client) {
+               DRM_ERROR("open ion client error\n");
+               return -EFAULT;
+       }
+
+       DRM_DEBUG("open ion client: %p\n", drmdrv->gem_client);
+       return 0;
+}
+
+void am_meson_gem_cleanup(struct meson_drm  *drmdrv)
+{
+       struct ion_client *gem_ion_client = drmdrv->gem_client;
+
+       if (gem_ion_client) {
+               DRM_DEBUG(" destroy ion client: %p\n", gem_ion_client);
+               ion_client_destroy(gem_ion_client);
+       }
+}
+
+struct sg_table *am_meson_gem_prime_get_sg_table(
+       struct drm_gem_object *obj)
+{
+       struct am_meson_gem_object *meson_gem_obj;
+       struct sg_table *dst_table = NULL;
+       struct scatterlist *dst_sg = NULL;
+       struct sg_table *src_table = NULL;
+       struct scatterlist *src_sg = NULL;
+       int ret, i;
+
+       meson_gem_obj = to_am_meson_gem_obj(obj);
+       DRM_DEBUG("am_meson_gem_prime_get_sg_table %p.\n", meson_gem_obj);
+
+       if (meson_gem_obj->base.import_attach == false) {
+               src_table = meson_gem_obj->handle->buffer->sg_table;
+               dst_table = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
+               if (!dst_table) {
+                       ret = -ENOMEM;
+                       return ERR_PTR(ret);
+               }
+
+               ret = sg_alloc_table(dst_table, src_table->nents, GFP_KERNEL);
+               if (ret) {
+                       kfree(dst_table);
+                       return ERR_PTR(ret);
+               }
+
+               dst_sg = dst_table->sgl;
+               src_sg = src_table->sgl;
+               for (i = 0; i < src_table->nents; i++) {
+                       sg_set_page(dst_sg, sg_page(src_sg), src_sg->length, 0);
+                       dst_sg = sg_next(dst_sg);
+                       src_sg = sg_next(src_sg);
+               }
+               return dst_table;
+       }
+       DRM_ERROR("Not support import buffer from other driver.\n");
+       return NULL;
+}
+
+struct drm_gem_object *am_meson_gem_prime_import_sg_table(
+       struct drm_device *dev,
+       struct dma_buf_attachment *attach,
+       struct sg_table *sgt)
+{
+       struct am_meson_gem_object *meson_gem_obj;
+       int ret;
+
+       meson_gem_obj = kzalloc(sizeof(*meson_gem_obj), GFP_KERNEL);
+       if (!meson_gem_obj)
+               return ERR_PTR(-ENOMEM);
+
+       ret = drm_gem_object_init(dev,
+                       &meson_gem_obj->base,
+                       attach->dmabuf->size);
+       if (ret < 0) {
+               DRM_ERROR("failed to initialize gem object\n");
+               kfree(meson_gem_obj);
+               return  ERR_PTR(-ENOMEM);
+       }
+
+       DRM_DEBUG("%s: %p, sg_table %p\n", __func__, meson_gem_obj, sgt);
+       /*meson_gem_obj->sgt = sgt;*/
+       return &meson_gem_obj->base;
+}
+
+void *am_meson_gem_prime_vmap(struct drm_gem_object *obj)
+{
+       DRM_DEBUG("am_meson_gem_prime_vmap %p.\n", obj);
+
+       return NULL;
+}
+
+void am_meson_gem_prime_vunmap(
+       struct drm_gem_object *obj,
+       void *vaddr)
+{
+       DRM_DEBUG("am_meson_gem_prime_vunmap nothing to do.\n");
+}
+
+int am_meson_gem_prime_mmap(
+       struct drm_gem_object *obj,
+       struct vm_area_struct *vma)
+{
+       struct am_meson_gem_object *meson_gem_obj;
+       int ret;
+
+       ret = drm_gem_mmap_obj(obj, obj->size, vma);
+       if (ret < 0)
+               return ret;
+
+       meson_gem_obj = to_am_meson_gem_obj(obj);
+       DRM_DEBUG("am_meson_gem_prime_mmap %p.\n", meson_gem_obj);
+
+       return am_meson_gem_object_mmap(meson_gem_obj, vma);
+}
diff --git a/drivers/amlogic/drm/meson_gem.h b/drivers/amlogic/drm/meson_gem.h
new file mode 100644 (file)
index 0000000..212a6aa
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * drivers/amlogic/drm/meson_gem.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 __AM_MESON_GEM_H
+#define __AM_MESON_GEM_H
+#include <drm/drm_gem.h>
+#include <uapi/drm/meson_drm.h>
+#include <ion/ion_priv.h>
+
+#include "meson_drv.h"
+
+struct am_meson_gem_object {
+       struct drm_gem_object base;
+       unsigned int flags;
+
+       /*for buffer create from ion heap */
+       struct ion_handle *handle;
+       bool bscatter;
+};
+
+/* GEM MANAGER CREATE*/
+int am_meson_gem_create(struct meson_drm  *drmdrv);
+
+void am_meson_gem_cleanup(struct meson_drm  *drmdrv);
+
+int am_meson_gem_mmap(
+       struct file *filp,
+       struct vm_area_struct *vma);
+
+/* GEM DUMB OPERATIONS */
+int am_meson_gem_dumb_create(
+       struct drm_file *file_priv,
+       struct drm_device *dev,
+       struct drm_mode_create_dumb *args);
+
+int am_meson_gem_dumb_destroy(
+       struct drm_file *file,
+       struct drm_device *dev,
+       uint32_t handle);
+
+int am_meson_gem_create_ioctl(
+       struct drm_device *dev,
+       void *data,
+       struct drm_file *file_priv);
+
+int am_meson_gem_dumb_map_offset(
+       struct drm_file *file_priv,
+       struct drm_device *dev,
+       uint32_t handle,
+       uint64_t *offset);
+
+/* GEM OBJECT OPERATIONS */
+struct am_meson_gem_object *am_meson_gem_object_create(
+               struct drm_device *dev, unsigned int flags,
+               unsigned long size, struct ion_client *client);
+
+void am_meson_gem_object_free(struct drm_gem_object *gem_obj);
+
+int am_meson_gem_object_mmap(
+       struct am_meson_gem_object *obj,
+       struct vm_area_struct *vma);
+
+extern int am_meson_gem_object_get_phyaddr(
+       struct meson_drm *drm,
+       struct am_meson_gem_object *meson_gem);
+
+/* GEM PRIME OPERATIONS */
+struct sg_table *am_meson_gem_prime_get_sg_table(
+       struct drm_gem_object *obj);
+
+struct drm_gem_object *am_meson_gem_prime_import_sg_table(
+       struct drm_device *dev,
+       struct dma_buf_attachment *attach,
+       struct sg_table *sgt);
+
+void *am_meson_gem_prime_vmap(
+       struct drm_gem_object *obj);
+
+void am_meson_gem_prime_vunmap(
+       struct drm_gem_object *obj,
+       void *vaddr);
+
+int am_meson_gem_prime_mmap(
+       struct drm_gem_object *obj,
+       struct vm_area_struct *vma);
+
+#endif /* __AM_MESON_GEM_H */
diff --git a/drivers/amlogic/drm/meson_hdcp.c b/drivers/amlogic/drm/meson_hdcp.c
new file mode 100644 (file)
index 0000000..ab098fb
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * drivers/amlogic/drm/meson_hdcp.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_modeset_helper.h>
+#include <drm/drmP.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
+
+#include <linux/component.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/workqueue.h>
+#include <linux/amlogic/media/vout/vout_notify.h>
+#include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h>
+#include <linux/arm-smccc.h>
+
+#include "meson_hdmi.h"
+#include "meson_hdcp.h"
+
+static int hdcp_topo_st = -1;
+static int hdmitx_hdcp_opr(unsigned int val)
+{
+       struct arm_smccc_res res;
+
+       if (val == 1) { /* HDCP14_ENABLE */
+               arm_smccc_smc(0x82000010, 0, 0, 0, 0, 0, 0, 0, &res);
+       }
+       if (val == 2) { /* HDCP14_RESULT */
+               arm_smccc_smc(0x82000011, 0, 0, 0, 0, 0, 0, 0, &res);
+               return (unsigned int)((res.a0)&0xffffffff);
+       }
+       if (val == 0) { /* HDCP14_INIT */
+               arm_smccc_smc(0x82000012, 0, 0, 0, 0, 0, 0, 0, &res);
+       }
+       if (val == 3) { /* HDCP14_EN_ENCRYPT */
+               arm_smccc_smc(0x82000013, 0, 0, 0, 0, 0, 0, 0, &res);
+       }
+       if (val == 4) { /* HDCP14_OFF */
+               arm_smccc_smc(0x82000014, 0, 0, 0, 0, 0, 0, 0, &res);
+       }
+       if (val == 5) { /* HDCP_MUX_22 */
+               arm_smccc_smc(0x82000015, 0, 0, 0, 0, 0, 0, 0, &res);
+       }
+       if (val == 6) { /* HDCP_MUX_14 */
+               arm_smccc_smc(0x82000016, 0, 0, 0, 0, 0, 0, 0, &res);
+       }
+       if (val == 7) { /* HDCP22_RESULT */
+               arm_smccc_smc(0x82000017, 0, 0, 0, 0, 0, 0, 0, &res);
+               return (unsigned int)((res.a0)&0xffffffff);
+       }
+       if (val == 0xa) { /* HDCP14_KEY_LSTORE */
+               arm_smccc_smc(0x8200001a, 0, 0, 0, 0, 0, 0, 0, &res);
+               return (unsigned int)((res.a0)&0xffffffff);
+       }
+       if (val == 0xb) { /* HDCP22_KEY_LSTORE */
+               arm_smccc_smc(0x8200001b, 0, 0, 0, 0, 0, 0, 0, &res);
+               return (unsigned int)((res.a0)&0xffffffff);
+       }
+       if (val == 0xc) { /* HDCP22_KEY_SET_DUK */
+               arm_smccc_smc(0x8200001c, 0, 0, 0, 0, 0, 0, 0, &res);
+               return (unsigned int)((res.a0)&0xffffffff);
+       }
+       if (val == 0xd) { /* HDCP22_SET_TOPO */
+               arm_smccc_smc(0x82000083, hdcp_topo_st, 0, 0, 0, 0, 0, 0, &res);
+       }
+       if (val == 0xe) { /* HDCP22_GET_TOPO */
+               arm_smccc_smc(0x82000084, 0, 0, 0, 0, 0, 0, 0, &res);
+               return (unsigned int)((res.a0)&0xffffffff);
+       }
+       return -1;
+}
+
+static void get_hdcp_bstatus(void)
+{
+       int ret1 = 0;
+       int ret2 = 0;
+
+       hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 1, 0, 1);
+       hdmitx_poll_reg(HDMITX_DWC_A_KSVMEMCTRL, (1<<1), 2 * HZ);
+       ret1 = hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_0);
+       ret2 = hdmitx_rd_reg(HDMITX_DWC_HDCP_BSTATUS_1);
+       hdmitx_set_reg_bits(HDMITX_DWC_A_KSVMEMCTRL, 0, 0, 1);
+       DRM_INFO("BSTATUS0 = 0x%x   BSTATUS1 = 0x%x\n", ret1, ret2);
+}
+
+static void hdcp14_events_handle(unsigned long arg)
+{
+       struct am_hdmi_tx *am_hdmi = (struct am_hdmi_tx *)arg;
+       unsigned int bcaps_6_rp;
+       static unsigned int st_flag = -1;
+
+       bcaps_6_rp = !!(hdmitx_rd_reg(HDMITX_DWC_A_HDCPOBS3) & (1 << 6));
+       if (st_flag != hdmitx_rd_reg(HDMITX_DWC_A_APIINTSTAT)) {
+               st_flag = hdmitx_rd_reg(HDMITX_DWC_A_APIINTSTAT);
+               DRM_INFO("hdcp14: instat: 0x%x\n", st_flag);
+       }
+       if (st_flag & (1 << 7)) {
+               hdmitx_wr_reg(HDMITX_DWC_A_APIINTCLR, 1 << 7);
+               hdmitx_hdcp_opr(3);
+               get_hdcp_bstatus();
+       }
+
+       if (st_flag & (1 << 1)) {
+               hdmitx_wr_reg(HDMITX_DWC_A_APIINTCLR, (1 << 1));
+               hdmitx_wr_reg(HDMITX_DWC_A_KSVMEMCTRL, 0x1);
+               hdmitx_poll_reg(HDMITX_DWC_A_KSVMEMCTRL, (1<<1), 2 * HZ);
+               if (hdmitx_rd_reg(HDMITX_DWC_A_KSVMEMCTRL) & (1 << 1))
+                       ;//hdcp_ksv_sha1_calc(hdev); todo
+               else {
+                       DRM_INFO("hdcptx14: KSV List memory access denied\n");
+                       return;
+               }
+               hdmitx_wr_reg(HDMITX_DWC_A_KSVMEMCTRL, 0x4);
+       }
+
+       if (am_hdmi->hdcp_try_times)
+               mod_timer(&am_hdmi->hdcp_timer, jiffies + HZ / 100);
+       else
+               return;
+       am_hdmi->hdcp_try_times--;
+}
+
+static void hdcp14_start_timer(struct am_hdmi_tx *am_hdmi)
+{
+       static int init_flag;
+
+       if (!init_flag) {
+               init_flag = 1;
+               init_timer(&am_hdmi->hdcp_timer);
+               am_hdmi->hdcp_timer.data = (ulong)am_hdmi;
+               am_hdmi->hdcp_timer.function = hdcp14_events_handle;
+               am_hdmi->hdcp_timer.expires = jiffies + HZ / 100;
+               add_timer(&am_hdmi->hdcp_timer);
+               am_hdmi->hdcp_try_times = 500;
+               return;
+       }
+       am_hdmi->hdcp_try_times = 500;
+       am_hdmi->hdcp_timer.expires = jiffies + HZ / 100;
+       mod_timer(&am_hdmi->hdcp_timer, jiffies + HZ / 100);
+}
+
+static int am_hdcp14_enable(struct am_hdmi_tx *am_hdmi)
+{
+       am_hdmi->hdcp_mode = HDCP_MODE14;
+       hdmitx_ddc_hw_op(DDC_MUX_DDC);
+       hdmitx_hdcp_opr(6);
+       hdmitx_hdcp_opr(1);
+       hdcp14_start_timer(am_hdmi);
+       return 0;
+}
+
+static int am_hdcp14_disable(struct am_hdmi_tx *am_hdmi)
+{
+       hdmitx_hdcp_opr(4);
+       return 0;
+}
+
+static void set_pkf_duk_nonce(void)
+{
+       static int nonce_mode = 1; /* 1: use HW nonce   0: use SW nonce */
+
+       /* Configure duk/pkf */
+       hdmitx_hdcp_opr(0xc);
+       if (nonce_mode == 1)
+               hdmitx_wr_reg(HDMITX_TOP_SKP_CNTL_STAT, 0xf);
+       else {
+               hdmitx_wr_reg(HDMITX_TOP_SKP_CNTL_STAT, 0xe);
+/* Configure nonce[127:0].
+ * MSB must be written the last to assert nonce_vld signal.
+ */
+               hdmitx_wr_reg(HDMITX_TOP_NONCE_0,  0x32107654);
+               hdmitx_wr_reg(HDMITX_TOP_NONCE_1,  0xba98fedc);
+               hdmitx_wr_reg(HDMITX_TOP_NONCE_2,  0xcdef89ab);
+               hdmitx_wr_reg(HDMITX_TOP_NONCE_3,  0x45670123);
+               hdmitx_wr_reg(HDMITX_TOP_NONCE_0,  0x76543210);
+               hdmitx_wr_reg(HDMITX_TOP_NONCE_1,  0xfedcba98);
+               hdmitx_wr_reg(HDMITX_TOP_NONCE_2,  0x89abcdef);
+               hdmitx_wr_reg(HDMITX_TOP_NONCE_3,  0x01234567);
+       }
+       udelay(10);
+}
+
+static void am_sysfs_hdcp_event(struct drm_device *dev, unsigned int flag)
+{
+       char *envp1[2] = {  "HDCP22=1", NULL };
+       char *envp0[2] = {  "HDCP22=0", NULL };
+
+       DRM_INFO("generating hdcp22: %d\n  event\n", flag);
+       if (flag)
+               kobject_uevent_env(&dev->primary->kdev->kobj,
+               KOBJ_CHANGE, envp1);
+       else
+               kobject_uevent_env(&dev->primary->kdev->kobj,
+               KOBJ_CHANGE, envp0);
+}
+
+static int am_hdcp22_enable(struct am_hdmi_tx *am_hdmi)
+{
+       am_hdmi->hdcp_mode = HDCP_MODE22;
+       hdmitx_ddc_hw_op(DDC_MUX_DDC);
+       hdmitx_set_reg_bits(HDMITX_DWC_MC_CLKDIS, 1, 6, 1);
+       udelay(5);
+       hdmitx_set_reg_bits(HDMITX_DWC_HDCP22REG_CTRL, 3, 1, 2);
+       hdmitx_set_reg_bits(HDMITX_TOP_SW_RESET, 1, 5, 1);
+       udelay(10);
+       hdmitx_set_reg_bits(HDMITX_TOP_SW_RESET, 0, 5, 1);
+       udelay(10);
+       hdmitx_wr_reg(HDMITX_DWC_HDCP22REG_MASK, 0);
+       hdmitx_wr_reg(HDMITX_DWC_HDCP22REG_MUTE, 0);
+       set_pkf_duk_nonce();
+
+       /*uevent to open hdcp_tx22*/
+       am_sysfs_hdcp_event(am_hdmi->connector.dev, 1);
+       return 0;
+}
+
+static int am_hdcp22_disable(struct am_hdmi_tx *am_hdmi)
+{
+       hdmitx_hdcp_opr(6);
+       /*uevent to close hdcp_tx22*/
+       am_sysfs_hdcp_event(am_hdmi->connector.dev, 0);
+       return 0;
+}
+
+void am_hdcp_disable(struct am_hdmi_tx *am_hdmi)
+{
+       if (am_hdmi->hdcp_mode == HDCP_MODE22)
+               am_hdcp22_disable(am_hdmi);
+       else if (am_hdmi->hdcp_mode == HDCP_MODE14)
+               am_hdcp14_disable(am_hdmi);
+}
+EXPORT_SYMBOL(am_hdcp_disable);
+
+static int is_hdcp_hdmirx_supported(struct am_hdmi_tx *am_hdmi)
+{
+       unsigned int hdcp_rx_type = 0x1;
+       int st;
+
+       /*if tx has hdcp22, then check if rx support hdcp22*/
+       if (am_hdmi->hdcp_tx_type & 0x2) {
+               hdmitx_ddc_hw_op(DDC_MUX_DDC);
+               //mutex_lock(&am_hdmi->hdcp_mutex);
+               hdmitx_wr_reg(HDMITX_DWC_I2CM_SLAVE, HDCP_SLAVE);
+               hdmitx_wr_reg(HDMITX_DWC_I2CM_ADDRESS, HDCP2_VERSION);
+               hdmitx_wr_reg(HDMITX_DWC_I2CM_OPERATION, 1 << 0);
+               mdelay(2);
+               if (hdmitx_rd_reg(HDMITX_DWC_IH_I2CM_STAT0) & (1 << 0)) {
+                       st = 0;
+                       DRM_INFO("ddc rd8b error 0x%02x 0x%02x\n",
+                               HDCP_SLAVE, HDCP2_VERSION);
+               } else
+                       st = 1;
+               hdmitx_wr_reg(HDMITX_DWC_IH_I2CM_STAT0, 0x7);
+               if (hdmitx_rd_reg(HDMITX_DWC_I2CM_DATAI) & (1 << 2))
+                       hdcp_rx_type = 0x3;
+               //mutex_unlock(&am_hdmi->hdcp_mutex);
+       } else {
+       /*if tx has hdcp14 or no key, then rx support hdcp14 acquiescently*/
+               hdcp_rx_type = 0x1;
+       }
+       am_hdmi->hdcp_rx_type = hdcp_rx_type;
+
+       DRM_INFO("hdmirx support hdcp14: %d\n", hdcp_rx_type & 0x1);
+       DRM_INFO("hdmirx support hdcp22: %d\n", (hdcp_rx_type & 0x2) >> 1);
+       return hdcp_rx_type;
+}
+
+int am_hdcp14_auth(struct am_hdmi_tx *am_hdmi)
+{
+       return hdmitx_hdcp_opr(0x2);
+}
+
+int am_hdcp22_auth(struct am_hdmi_tx *am_hdmi)
+{
+       return hdmitx_hdcp_opr(0x7);
+}
+
+/*firstly,check the hdmirx key
+ *if hdmirx has hdcp22 key, start hdcp22. check auth status,
+ *if failure,then start hdcp14
+ *if hdmirx has hdcp14 key, start hdcp 14
+ */
+int am_hdcp_work(void *data)
+{
+       struct am_hdmi_tx *am_hdmi = data;
+       struct drm_connector_state *state = am_hdmi->connector.state;
+       int hdcp_fsm = 0;
+
+       is_hdcp_hdmirx_supported(am_hdmi);
+       if ((am_hdmi->hdcp_tx_type & 0x2) &&
+               (am_hdmi->hdcp_rx_type & 0x2))
+               hdcp_fsm = HDCP22_ENABLE;
+       else
+               hdcp_fsm = HDCP14_ENABLE;
+
+       while (hdcp_fsm) {
+               if (am_hdmi->hdcp_stop_flag)
+                       hdcp_fsm = HDCP_QUIT;
+
+               switch (hdcp_fsm) {
+               case HDCP22_ENABLE:
+                       am_hdcp22_enable(am_hdmi);
+                       DRM_INFO("hdcp22 work after 10s\n");
+                       /*this time is used to debug*/
+                       msleep_interruptible(10000);
+                       hdcp_fsm = HDCP22_AUTH;
+                       break;
+               case HDCP22_AUTH:
+                       if (am_hdcp22_auth(am_hdmi))
+                               hdcp_fsm = HDCP22_SUCCESS;
+                       else
+                               hdcp_fsm = HDCP22_FAIL;
+                       break;
+               case HDCP22_SUCCESS:
+                       state->content_protection =
+                               DRM_MODE_CONTENT_PROTECTION_ENABLED;
+                       DRM_DEBUG("hdcp22 is authenticated successfully\n");
+                       hdcp_fsm = HDCP22_AUTH;
+                       msleep_interruptible(200);
+                       break;
+               case HDCP22_FAIL:
+                       am_hdcp22_disable(am_hdmi);
+                       state->content_protection =
+                               DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
+                       DRM_INFO("hdcp22 failure and start hdcp14\n");
+                       hdcp_fsm = HDCP14_ENABLE;
+                       msleep_interruptible(2000);
+                       break;
+               case HDCP14_ENABLE:
+                       if ((am_hdmi->hdcp_tx_type & 0x1) == 0) {
+                               hdcp_fsm = HDCP_QUIT;
+                               break;
+                       }
+                       am_hdcp14_enable(am_hdmi);
+                       msleep_interruptible(500);
+                       hdcp_fsm = HDCP14_AUTH;
+                       break;
+               case HDCP14_AUTH:
+                       if (am_hdcp14_auth(am_hdmi))
+                               hdcp_fsm = HDCP14_SUCCESS;
+                       else
+                               hdcp_fsm = HDCP14_FAIL;
+                       break;
+               case HDCP14_SUCCESS:
+                       state->content_protection =
+                               DRM_MODE_CONTENT_PROTECTION_ENABLED;
+                       DRM_DEBUG("hdcp14 is authenticated successfully\n");
+                       hdcp_fsm = HDCP14_AUTH;
+                       msleep_interruptible(200);
+                       break;
+               case HDCP14_FAIL:
+                       am_hdcp14_disable(am_hdmi);
+                       state->content_protection =
+                               DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
+                       DRM_DEBUG("hdcp14 failure\n");
+                       hdcp_fsm = HDCP_QUIT;
+                       break;
+               case HDCP_QUIT:
+               default:
+                       break;
+               }
+       }
+       return 0;
+}
+EXPORT_SYMBOL(am_hdcp_work);
+
+int am_hdcp_init(struct am_hdmi_tx *am_hdmi)
+{
+       int ret;
+
+       ret = drm_connector_attach_content_protection_property(
+                       &am_hdmi->connector);
+       if (ret)
+               return ret;
+       return 0;
+}
+EXPORT_SYMBOL(am_hdcp_init);
+
+/*bit0:hdcp14 bit 1:hdcp22*/
+int is_hdcp_hdmitx_supported(struct am_hdmi_tx *am_hdmi)
+{
+       unsigned int hdcp_tx_type = 0;
+
+       hdcp_tx_type |= hdmitx_hdcp_opr(0xa);
+       hdcp_tx_type |= ((hdmitx_hdcp_opr(0xb)) << 1);
+       am_hdmi->hdcp_tx_type = hdcp_tx_type;
+       DRM_INFO("hdmitx support hdcp14: %d\n", hdcp_tx_type & 0x1);
+       DRM_INFO("hdmitx support hdcp22: %d\n", (hdcp_tx_type & 0x2) >> 1);
+       return hdcp_tx_type;
+}
+EXPORT_SYMBOL(is_hdcp_hdmitx_supported);
similarity index 96%
rename from drivers/amlogic/drm/am_meson_hdcp.h
rename to drivers/amlogic/drm/meson_hdcp.h
index f95d13f..9e4ede0 100644 (file)
@@ -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/meson_hdmi.c b/drivers/amlogic/drm/meson_hdmi.c
new file mode 100644 (file)
index 0000000..896444a
--- /dev/null
@@ -0,0 +1,706 @@
+/*
+ * drivers/amlogic/drm/meson_hdmi.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_modeset_helper.h>
+#include <drm/drmP.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_connector.h>
+
+#include <linux/component.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/kthread.h>
+#include <linux/device.h>
+
+#include <linux/workqueue.h>
+#include <linux/amlogic/media/vout/vout_notify.h>
+#include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_module.h>
+#include "meson_hdmi.h"
+#include "meson_hdcp.h"
+
+#define DEVICE_NAME "amhdmitx"
+struct am_hdmi_tx am_hdmi_info;
+
+struct am_vout_mode {
+       char name[DRM_DISPLAY_MODE_LEN];
+       enum vmode_e mode;
+       int width, height, vrefresh;
+       unsigned int flags;
+};
+
+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},
+       { "smpte30hz", VMODE_HDMI, 4096, 2160, 30, 0},
+       { "smpte60hz", VMODE_HDMI, 4096, 2160, 60, 0},
+       { "smpte50hz", VMODE_HDMI, 4096, 2160, 50, 0},
+       { "smpte25hz", VMODE_HDMI, 4096, 2160, 25, 0},
+       { "smpte24hz", VMODE_HDMI, 4096, 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},
+};
+
+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))
+                       return am_vout_modes[i].name;
+       }
+       return NULL;
+}
+
+static unsigned char default_edid[] = {
+       0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+       0x31, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x05, 0x16, 0x01, 0x03, 0x6d, 0x32, 0x1c, 0x78,
+       0xea, 0x5e, 0xc0, 0xa4, 0x59, 0x4a, 0x98, 0x25,
+       0x20, 0x50, 0x54, 0x00, 0x00, 0x00, 0xd1, 0xc0,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a,
+       0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
+       0x45, 0x00, 0xf4, 0x19, 0x11, 0x00, 0x00, 0x1e,
+       0x00, 0x00, 0x00, 0xff, 0x00, 0x4c, 0x69, 0x6e,
+       0x75, 0x78, 0x20, 0x23, 0x30, 0x0a, 0x20, 0x20,
+       0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x3b,
+       0x3d, 0x42, 0x44, 0x0f, 0x00, 0x0a, 0x20, 0x20,
+       0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
+       0x00, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x20, 0x46,
+       0x48, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x05,
+};
+
+int am_hdmi_tx_get_modes(struct drm_connector *connector)
+{
+       struct am_hdmi_tx *am_hdmi = to_am_hdmi(connector);
+       struct edid *edid;
+       int count = 0;
+
+       DRM_INFO("get_edid\n");
+       edid = drm_get_edid(connector, am_hdmi->ddc);
+
+       if (edid) {
+               drm_mode_connector_update_edid_property(connector, edid);
+               count = drm_add_edid_modes(connector, edid);
+               kfree(edid);
+       } else {
+               DRM_INFO("edid error and load default edid\n");
+               drm_mode_connector_update_edid_property(connector,
+                       (struct edid *)default_edid);
+               count = drm_add_edid_modes(connector,
+                       (struct edid *)default_edid);
+       }
+       return count;
+}
+
+enum drm_mode_status am_hdmi_tx_check_mode(struct drm_connector *connector,
+                                          struct drm_display_mode *mode)
+{
+       if (am_meson_hdmi_get_voutmode(mode))
+               return MODE_OK;
+       else
+               return MODE_NOMODE;
+}
+
+static struct drm_encoder *am_hdmi_connector_best_encoder
+       (struct drm_connector *connector)
+{
+       struct am_hdmi_tx *am_hdmi = to_am_hdmi(connector);
+
+       return &am_hdmi->encoder;
+}
+
+static enum drm_connector_status am_hdmi_connector_detect
+       (struct drm_connector *connector, bool force)
+{
+       struct am_hdmi_tx *am_hdmi = to_am_hdmi(connector);
+
+       /* HPD rising */
+       if (am_hdmi->hpd_flag == 1) {
+               DRM_INFO("connector_status_connected\n");
+               return connector_status_connected;
+       }
+       /* HPD falling */
+       if (am_hdmi->hpd_flag == 2) {
+               DRM_INFO("connector_status_disconnected\n");
+               /*
+                *clean the hdmi info and output : todo
+                */
+               return connector_status_disconnected;
+       }
+       /*if the status is unknown, read GPIO*/
+       if (hdmitx_hpd_hw_op(HPD_READ_HPD_GPIO)) {
+               DRM_INFO("connector_status_connected\n");
+               return connector_status_connected;
+       }
+       if (!(hdmitx_hpd_hw_op(HPD_READ_HPD_GPIO))) {
+               DRM_INFO("connector_status_disconnected\n");
+               return connector_status_disconnected;
+       }
+
+       DRM_INFO("connector_status_unknown\n");
+       return connector_status_unknown;
+}
+
+static int am_hdmi_connector_set_property(struct drm_connector *connector,
+       struct drm_property *property, uint64_t val)
+{
+       struct am_hdmi_tx *am_hdmi = to_am_hdmi(connector);
+       struct drm_connector_state *state = am_hdmi->connector.state;
+
+       if (property == connector->content_protection_property) {
+               DRM_INFO("property:%s       val: %lld\n", property->name, val);
+               if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
+                       DRM_DEBUG_KMS("only drivers can set CP Enabled\n");
+                       return -EINVAL;
+               }
+               state->content_protection = val;
+       }
+       /*other parperty todo*/
+       return 0;
+}
+
+static int am_hdmi_connector_atomic_get_property
+       (struct drm_connector *connector,
+       const struct drm_connector_state *state,
+       struct drm_property *property, uint64_t *val)
+{
+       if (property == connector->content_protection_property) {
+               DRM_INFO("get content_protection val: %d\n",
+                       state->content_protection);
+               *val = state->content_protection;
+       } else {
+               DRM_DEBUG_ATOMIC("Unknown property %s\n", property->name);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static void am_hdmi_connector_destroy(struct drm_connector *connector)
+{
+       drm_connector_unregister(connector);
+       drm_connector_cleanup(connector);
+}
+
+static const
+struct drm_connector_helper_funcs am_hdmi_connector_helper_funcs = {
+       .get_modes = am_hdmi_tx_get_modes,
+       .mode_valid = am_hdmi_tx_check_mode,
+       .best_encoder = am_hdmi_connector_best_encoder,
+};
+
+static const struct drm_connector_funcs am_hdmi_connector_funcs = {
+       .dpms                   = drm_atomic_helper_connector_dpms,
+       .detect                 = am_hdmi_connector_detect,
+       .fill_modes             = drm_helper_probe_single_connector_modes,
+       .set_property           = am_hdmi_connector_set_property,
+       .atomic_get_property    = am_hdmi_connector_atomic_get_property,
+       .destroy                = am_hdmi_connector_destroy,
+       .reset                  = drm_atomic_helper_connector_reset,
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+       .atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
+};
+
+void am_hdmi_encoder_mode_set(struct drm_encoder *encoder,
+                                  struct drm_display_mode *mode,
+                                  struct drm_display_mode *adjusted_mode)
+{
+       const char attr1[16] = "rgb,8bit";
+       const char attr2[16] = "420,8bit";
+       int vic;
+       struct am_hdmi_tx *am_hdmi = &am_hdmi_info;
+
+       DRM_INFO("mode : %s, adjusted_mode : %s\n",
+               mode->name,  adjusted_mode->name);
+       am_hdmi->hdmi_info.vic = drm_match_cea_mode(adjusted_mode);
+       vic = am_hdmi->hdmi_info.vic;
+       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)
+               setup_attr(attr2);
+       else
+               setup_attr(attr1);
+}
+
+void am_hdmi_encoder_enable(struct drm_encoder *encoder)
+{
+       enum vmode_e vmode = get_current_vmode();
+       struct am_hdmi_tx *am_hdmi = to_am_hdmi(encoder);
+       struct drm_connector_state *state = am_hdmi->connector.state;
+
+       if (vmode == VMODE_HDMI)
+               DRM_INFO("enable\n");
+       else
+               DRM_INFO("enable fail! vmode:%d\n", vmode);
+
+       vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE_PRE, &vmode);
+       set_vout_vmode(vmode);
+       vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &vmode);
+       mdelay(1000);
+       if (state->content_protection ==
+               DRM_MODE_CONTENT_PROTECTION_DESIRED) {
+               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 {
+                       DRM_INFO("hdmitx doesn't has hdcp key\n");
+               }
+       }
+}
+
+void am_hdmi_encoder_disable(struct drm_encoder *encoder)
+{
+       struct am_hdmi_tx *am_hdmi = to_am_hdmi(encoder);
+       struct drm_connector_state *state = am_hdmi->connector.state;
+
+       /*need to add hdmitx disable function ..todo*/
+       if (state->content_protection !=
+               DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
+               state->content_protection =
+                       DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
+               am_hdmi->hdcp_stop_flag = 1;
+               kthread_stop(am_hdmi->hdcp_work);
+               am_hdcp_disable(am_hdmi);
+       }
+}
+
+static int am_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
+                               struct drm_crtc_state *crtc_state,
+                               struct drm_connector_state *conn_state)
+{
+       struct am_hdmi_tx *am_hdmi = to_am_hdmi(encoder);
+
+       DRM_INFO("content_protection:%d\n", conn_state->content_protection);
+
+       if (conn_state->content_protection ==
+               DRM_MODE_CONTENT_PROTECTION_ENABLED) {
+               kthread_stop(am_hdmi->hdcp_work);
+               am_hdcp_disable(am_hdmi);
+               conn_state->content_protection =
+                       DRM_MODE_CONTENT_PROTECTION_DESIRED;
+       }
+       return 0;
+}
+
+static const struct drm_encoder_helper_funcs
+       am_hdmi_encoder_helper_funcs = {
+       .mode_set       = am_hdmi_encoder_mode_set,
+       .enable         = am_hdmi_encoder_enable,
+       .disable        = am_hdmi_encoder_disable,
+       .atomic_check   = am_hdmi_encoder_atomic_check,
+};
+
+static const struct drm_encoder_funcs am_hdmi_encoder_funcs = {
+       .destroy        = drm_encoder_cleanup,
+};
+
+static int am_hdmi_i2c_write(struct am_hdmi_tx *am_hdmi,
+       unsigned char *buf, unsigned int length)
+{
+       struct am_hdmi_i2c *i2c = am_hdmi->i2c;
+       int stat;
+
+       if (!i2c->is_regaddr) {
+               /* Use the first write byte as register address */
+               i2c->slave_reg = buf[0];
+               length--;
+               buf++;
+               i2c->is_regaddr = 1;
+       }
+
+       while (length--) {
+               reinit_completion(&i2c->cmp);
+
+               hdmitx_wr_reg(HDMITX_DWC_I2CM_DATAO, *buf++);
+               hdmitx_wr_reg(HDMITX_DWC_I2CM_ADDRESS, i2c->slave_reg++);
+               hdmitx_wr_reg(HDMITX_DWC_I2CM_OPERATION, 1 << 4);
+
+               stat = wait_for_completion_timeout(&i2c->cmp, HZ / 100);
+
+               stat = 1;
+               /* Check for error condition on the bus */
+               if (i2c->stat & 1)
+                       return -EIO;
+       }
+
+       return 0;
+}
+
+static int am_hdmi_i2c_read(struct am_hdmi_tx *am_hdmi,
+       unsigned char *buf, unsigned int length)
+{
+       struct am_hdmi_i2c *i2c = am_hdmi->i2c;
+       int stat;
+
+       if (!i2c->is_regaddr) {
+               dev_dbg(am_hdmi->dev, "set read register address to 0\n");
+               i2c->slave_reg = 0x00;
+               i2c->is_regaddr = 1;
+       }
+
+       while (length--) {
+               reinit_completion(&i2c->cmp);
+
+               hdmitx_wr_reg(HDMITX_DWC_I2CM_ADDRESS, i2c->slave_reg++);
+               if (i2c->is_segment)
+                       hdmitx_wr_reg(HDMITX_DWC_I2CM_OPERATION, 1 << 1);
+               else
+                       hdmitx_wr_reg(HDMITX_DWC_I2CM_OPERATION, 1 << 0);
+
+               stat = wait_for_completion_timeout(&i2c->cmp, HZ / 100);
+
+               stat = 1;
+
+               /* Check for error condition on the bus */
+               if (i2c->stat & 0x1)
+                       return -EIO;
+
+               *buf++ = hdmitx_rd_reg(HDMITX_DWC_I2CM_DATAI);
+       }
+       i2c->is_segment = 0;
+
+       return 0;
+}
+
+static int am_hdmi_i2c_xfer(struct i2c_adapter *adap,
+                             struct i2c_msg *msgs, int num)
+{
+       struct am_hdmi_tx *am_hdmi =  i2c_get_adapdata(adap);
+       struct am_hdmi_i2c *i2c = am_hdmi->i2c;
+       u8 addr = msgs[0].addr;
+       int i, ret = 0;
+
+       dev_dbg(am_hdmi->dev, "xfer: num: %d, addr: %#x\n", num, addr);
+
+       for (i = 0; i < num; i++) {
+               if (msgs[i].len == 0) {
+                       dev_dbg(am_hdmi->dev,
+                               "unsupported transfer %d/%d, no data\n",
+                               i + 1, num);
+                       return -EOPNOTSUPP;
+               }
+       }
+
+       mutex_lock(&i2c->lock);
+
+       /* Clear the EDID interrupt flag and unmute the interrupt */
+       hdmitx_wr_reg(HDMITX_DWC_I2CM_SOFTRSTZ, 0);
+       hdmitx_wr_reg(HDMITX_DWC_IH_MUTE_I2CM_STAT0, 0);
+       /* TODO */
+       hdmitx_ddc_hw_op(DDC_MUX_DDC);
+
+       /* Set slave device address taken from the first I2C message */
+       hdmitx_wr_reg(HDMITX_DWC_I2CM_SLAVE, addr);
+
+       /* Set slave device register address on transfer */
+       i2c->is_regaddr = 0;
+
+       /* Set segment pointer for I2C extended read mode operation */
+       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 = 1;
+                       hdmitx_wr_reg(HDMITX_DWC_I2CM_SEGADDR,
+                               DDC_SEGMENT_ADDR);
+                       hdmitx_wr_reg(HDMITX_DWC_I2CM_SEGPTR, *msgs[i].buf);
+               } else {
+                       if (msgs[i].flags & I2C_M_RD)
+                               ret = am_hdmi_i2c_read(am_hdmi, msgs[i].buf,
+                                                      msgs[i].len);
+                       else
+                               ret = am_hdmi_i2c_write(am_hdmi, msgs[i].buf,
+                                                       msgs[i].len);
+               }
+               if (ret < 0)
+                       break;
+       }
+
+       if (!ret)
+               ret = num;
+
+       mutex_unlock(&i2c->lock);
+
+       return ret;
+}
+
+static u32 am_hdmi_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm am_hdmi_algorithm = {
+       .master_xfer    = am_hdmi_i2c_xfer,
+       .functionality  = am_hdmi_i2c_func,
+};
+
+static struct i2c_adapter *am_hdmi_i2c_adapter(struct am_hdmi_tx *am_hdmi)
+{
+       struct i2c_adapter *adap;
+       struct am_hdmi_i2c *i2c;
+       int ret;
+
+       i2c = devm_kzalloc(am_hdmi->priv->dev, sizeof(*i2c), GFP_KERNEL);
+       if (!i2c) {
+               ret = -ENOMEM;
+               DRM_INFO("error : %d\n", ret);
+       }
+
+       mutex_init(&i2c->lock);
+       init_completion(&i2c->cmp);
+
+       adap = &i2c->adap;
+       adap->class = I2C_CLASS_DDC;
+       adap->owner = THIS_MODULE;
+       adap->dev.parent = am_hdmi->priv->dev;
+       adap->dev.of_node = am_hdmi->priv->dev->of_node;
+       adap->algo = &am_hdmi_algorithm;
+       strlcpy(adap->name, "Am HDMI", sizeof(adap->name));
+       i2c_set_adapdata(adap, am_hdmi);
+
+       ret = i2c_add_adapter(adap);
+       if (ret) {
+               DRM_INFO("cannot add %s I2C adapter\n",
+                       adap->name);
+               devm_kfree(am_hdmi->priv->dev, i2c);
+               return ERR_PTR(ret);
+       }
+       am_hdmi->i2c = i2c;
+       DRM_INFO("registered %s I2C bus driver\n", adap->name);
+
+       return adap;
+
+}
+static irqreturn_t am_hdmi_hardirq(int irq, void *dev_id)
+{
+       unsigned int data32 = 0;
+       irqreturn_t ret = IRQ_NONE;
+
+       data32 = hdmitx_rd_reg(HDMITX_TOP_INTR_STAT);
+
+       /* check HPD status */
+       if ((data32 & (1 << 1)) && (data32 & (1 << 2))) {
+               if (hdmitx_hpd_hw_op(HPD_READ_HPD_GPIO))
+                       data32 &= ~(1 << 2);
+               else
+                       data32 &= ~(1 << 1);
+       }
+
+       if ((data32 & (1 << 1)) || (data32 & (1 << 2))) {
+               ret = IRQ_WAKE_THREAD;
+               DRM_INFO("hotplug irq: %x\n", data32);
+               am_hdmi_info.hpd_flag = 0;
+               if (data32 & (1 << 1))
+                       am_hdmi_info.hpd_flag = 1;/* HPD rising */
+               if (data32 & (1 << 2))
+                       am_hdmi_info.hpd_flag = 2;/* HPD falling */
+               /* ack INTERNAL_INTR or else*/
+               hdmitx_wr_reg(HDMITX_TOP_INTR_STAT_CLR, data32 | 0x7);
+       }
+       return ret;
+}
+
+static irqreturn_t am_hdmi_irq(int irq, void *dev_id)
+{
+       struct am_hdmi_tx *am_hdmi = dev_id;
+
+       drm_helper_hpd_irq_event(am_hdmi->connector.dev);
+       return IRQ_HANDLED;
+}
+
+static int amhdmitx_get_dt_info(struct am_hdmi_tx *am_hdmi)
+{
+       struct device_node *hdcp_node;
+       unsigned char *hdcp_status;
+       int ret = 0;
+
+       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) {
+                       DRM_INFO("not find hdcp_feature\n");
+               } else {
+                       if (memcmp(hdcp_status, "okay", 4) == 0)
+                               am_hdmi->hdcp_feature = 1;
+                       else
+                               am_hdmi->hdcp_feature = 0;
+                       DRM_INFO("hdcp_feature: %d\n",
+                               am_hdmi->hdcp_feature);
+               }
+       } else {
+               DRM_INFO("not find drm_amhdmitx\n");
+       }
+       return 0;
+}
+
+
+static const struct of_device_id am_meson_hdmi_dt_ids[] = {
+       { .compatible = "amlogic,drm-amhdmitx", },
+       {},
+};
+
+MODULE_DEVICE_TABLE(of, am_meson_hdmi_dt_ids);
+
+static int am_meson_hdmi_bind(struct device *dev,
+       struct device *master, void *data)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct drm_device *drm = data;
+       struct meson_drm *priv = drm->dev_private;
+       struct am_hdmi_tx *am_hdmi;
+       struct drm_connector *connector;
+       struct drm_encoder *encoder;
+       int ret;
+       int irq;
+
+       am_hdmi = devm_kzalloc(priv->dev, sizeof(*am_hdmi),
+                                      GFP_KERNEL);
+       if (!am_hdmi)
+               return -ENOMEM;
+       memcpy(&am_hdmi_info, am_hdmi, sizeof(*am_hdmi));
+       am_hdmi = &am_hdmi_info;
+
+       DRM_INFO("drm hdmitx init and version:%s\n", DRM_HDMITX_VER);
+       am_hdmi->priv = priv;
+       encoder = &am_hdmi->encoder;
+       connector = &am_hdmi->connector;
+
+       /* Connector */
+       am_hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
+       drm_connector_helper_add(connector,
+                                &am_hdmi_connector_helper_funcs);
+
+       ret = drm_connector_init(drm, connector, &am_hdmi_connector_funcs,
+                                DRM_MODE_CONNECTOR_HDMIA);
+       if (ret) {
+               dev_err(priv->dev, "Failed to init hdmi tx connector\n");
+               return ret;
+       }
+
+       connector->interlace_allowed = 1;
+
+       /* Encoder */
+       drm_encoder_helper_add(encoder, &am_hdmi_encoder_helper_funcs);
+
+       ret = drm_encoder_init(drm, encoder, &am_hdmi_encoder_funcs,
+                              DRM_MODE_ENCODER_TVDAC, "am_hdmi_encoder");
+       if (ret) {
+               dev_err(priv->dev, "Failed to init hdmi encoder\n");
+               return ret;
+       }
+
+       encoder->possible_crtcs = BIT(0);
+
+       drm_mode_connector_attach_encoder(connector, encoder);
+
+       /*DDC init*/
+       am_hdmi->ddc = am_hdmi_i2c_adapter(am_hdmi);
+       DRM_INFO("hdmitx:DDC init complete\n");
+       /*Hotplug irq*/
+       irq = platform_get_irq(pdev, 0);
+       DRM_INFO("hdmi connector irq:%d\n", irq);
+       if (irq < 0)
+               return irq;
+       hdmitx_wr_reg(HDMITX_TOP_INTR_STAT_CLR, 0x7);
+       ret = devm_request_threaded_irq(am_hdmi->priv->dev, irq,
+               am_hdmi_hardirq, am_hdmi_irq, IRQF_SHARED,
+               dev_name(am_hdmi->priv->dev), am_hdmi);
+       if (ret) {
+               dev_err(am_hdmi->priv->dev,
+                       "failed to request hdmi irq: %d\n", ret);
+       }
+
+       /*HDCP INIT*/
+       amhdmitx_get_dt_info(am_hdmi);
+       if (am_hdmi->hdcp_feature) {
+               if (is_hdcp_hdmitx_supported(am_hdmi)) {
+                       ret = am_hdcp_init(am_hdmi);
+                       if (ret)
+                               DRM_DEBUG_KMS("HDCP init failed, skipping.\n");
+               }
+       }
+       return 0;
+}
+
+static void am_meson_hdmi_unbind(struct device *dev,
+       struct device *master, void *data)
+{
+       am_hdmi_info.connector.funcs->destroy(&am_hdmi_info.connector);
+       am_hdmi_info.encoder.funcs->destroy(&am_hdmi_info.encoder);
+}
+
+static const struct component_ops am_meson_hdmi_ops = {
+       .bind   = am_meson_hdmi_bind,
+       .unbind = am_meson_hdmi_unbind,
+};
+
+static int am_meson_hdmi_probe(struct platform_device *pdev)
+{
+       return component_add(&pdev->dev, &am_meson_hdmi_ops);
+}
+
+static int am_meson_hdmi_remove(struct platform_device *pdev)
+{
+       component_del(&pdev->dev, &am_meson_hdmi_ops);
+       return 0;
+}
+
+static struct platform_driver am_meson_hdmi_pltfm_driver = {
+       .probe  = am_meson_hdmi_probe,
+       .remove = am_meson_hdmi_remove,
+       .driver = {
+               .name = "meson-amhdmitx",
+               .of_match_table = am_meson_hdmi_dt_ids,
+       },
+};
+
+module_platform_driver(am_meson_hdmi_pltfm_driver);
+
+MODULE_AUTHOR("MultiMedia Amlogic <multimedia-sh@amlogic.com>");
+MODULE_DESCRIPTION("Amlogic Meson Drm HDMI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/amlogic/drm/meson_hdmi.h b/drivers/amlogic/drm/meson_hdmi.h
new file mode 100644 (file)
index 0000000..d4bea37
--- /dev/null
@@ -0,0 +1,1113 @@
+/*
+ * drivers/amlogic/drm/meson_hdmi.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 __AM_MESON_HDMI_H
+#define __AM_MESON_HDMI_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;
+       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 */
+       unsigned int  cr; /* limit, full */
+       struct hdmi_pwr_ctl *pwr_ctl;
+       unsigned int aud_output_ch;
+       unsigned int tx_aud_cfg; /* 0, off; 1, on */
+       unsigned int tmds_clk_div40;
+       unsigned int VIC[VIC_MAX_NUM];
+};
+
+struct am_hdmi_i2c {
+       struct i2c_adapter adap;
+       struct mutex lock;
+       struct completion cmp;
+       u8 ddc_addr;
+       u8 segment_addr;
+       u8 slave_reg;
+       u8 stat;
+       u8 is_regaddr;
+       u8 is_segment;
+};
+
+struct am_hdmi_tx {
+       struct device *dev;
+       struct drm_encoder      encoder;
+       struct drm_connector    connector;
+       struct meson_drm *priv;
+       int irq;
+       unsigned int input_color_format;
+       unsigned int output_color_format;
+       unsigned int color_depth;
+       struct drm_display_mode previous_mode;
+       struct am_hdmi_data hdmi_info;
+       struct am_hdmi_i2c *i2c;
+       struct i2c_adapter *ddc;
+       struct workqueue_struct *hdmi_wq;
+       const char *hpd_pin;
+       const char *ddc_pin;
+       unsigned int hpd_flag;/*0:none   1:up    2:down*/
+       struct mutex hdcp_mutex;
+       unsigned int hdcp_feature;
+       unsigned int hdcp_tx_type;/*bit0:hdcp14 bit 1:hdcp22*/
+       unsigned int hdcp_rx_type;/*bit0:hdcp14 bit 1:hdcp22*/
+       struct timer_list hdcp_timer;
+       unsigned int hdcp_mode;
+       unsigned int hdcp_state;
+       unsigned int hdcp_stop_flag;/*turn off hdcp state machine*/
+       unsigned int hdcp_try_times;
+       struct task_struct *hdcp_work;
+};
+
+#define to_am_hdmi(x)  container_of(x, struct am_hdmi_tx, x)
+
+#define HDMITX_REG_IDX         6
+#define HDMITX_SEC_REG_IDX     7
+#define BASE_REG_OFFSET                24
+
+#define HDMITX_SEC_REG_ADDR(reg) \
+       ((HDMITX_SEC_REG_IDX << BASE_REG_OFFSET) + ((reg) << 2))
+#define HDMITX_REG_ADDR(reg) \
+       ((HDMITX_REG_IDX << BASE_REG_OFFSET) + ((reg) << 2))
+
+/* TOP-level wrapper registers addresses
+ * bit24: 1 means secure access
+ * bit28: 1 means DWC, 0 means TOP
+ */
+#define SEC_OFFSET           (0x1UL << 24)
+#define TOP_OFFSET_MASK      (0x0UL << 24)
+#define TOP_SEC_OFFSET_MASK  ((TOP_OFFSET_MASK) | (SEC_OFFSET))
+#define DWC_OFFSET_MASK      (0x10UL << 24)
+#define DWC_SEC_OFFSET_MASK  ((DWC_OFFSET_MASK) | (SEC_OFFSET))
+
+/* Bit 7 RW Reserved. Default 1.
+ * Bit 6 RW Reserved. Default 1.
+ * Bit 5 RW Reserved. Default 1.
+ * Bit 4 RW sw_reset_phyif: PHY interface. 1=Apply reset; 0=Release from reset.
+ *     Default 1.
+ * Bit 3 RW sw_reset_intr:  interrupt module. 1=Apply reset;
+ *     0=Release from reset. Default 1.
+ * Bit 2 RW sw_reset_mem:   KSV/REVOC mem. 1=Apply reset; 0=Release from reset.
+ *     Default 1.
+ * Bit 1 RW sw_reset_rnd:   random number interface to HDCP. 1=Apply reset;
+ *     0=Release from reset. Default 1.
+ * Bit 0 RW sw_reset_core: connects to IP's ~irstz. 1=Apply reset;
+ *     0=Release from reset. Default 1.
+ */
+#define HDMITX_TOP_SW_RESET                     (TOP_OFFSET_MASK + 0x000)
+
+/* Bit 12 RW i2s_ws_inv:1=Invert i2s_ws; 0=No invert. Default 0. */
+/* Bit 11 RW i2s_clk_inv: 1=Invert i2s_clk; 0=No invert. Default 0. */
+/* Bit 10 RW spdif_clk_inv: 1=Invert spdif_clk; 0=No invert. Default 0. */
+/* Bit 9 RW tmds_clk_inv: 1=Invert tmds_clk; 0=No invert. Default 0. */
+/* Bit 8 RW pixel_clk_inv: 1=Invert pixel_clk; 0=No invert. Default 0. */
+/* Bit 4 RW cec_clk_en: 1=enable cec_clk; 0=disable. Default 0. */
+/* Bit 3 RW i2s_clk_en: 1=enable i2s_clk; 0=disable. Default 0. */
+/* Bit 2 RW spdif_clk_en: 1=enable spdif_clk; 0=disable. Default 0. */
+/* Bit 1 RW tmds_clk_en: 1=enable tmds_clk;  0=disable. Default 0. */
+/* Bit 0 RW pixel_clk_en: 1=enable pixel_clk; 0=disable. Default 0. */
+#define HDMITX_TOP_CLK_CNTL                     (TOP_OFFSET_MASK + 0x001)
+
+/* Bit 11: 0 RW hpd_valid_width: filter out width <= M*1024.    Default 0. */
+/* Bit 15:12 RW hpd_glitch_width: filter out glitch <= N.       Default 0. */
+#define HDMITX_TOP_HPD_FILTER                   (TOP_OFFSET_MASK + 0x002)
+
+/* intr_maskn: MASK_N, one bit per interrupt source.
+ *     1=Enable interrupt source; 0=Disable interrupt source. Default 0.
+ * [  4] hdcp22_rndnum_err
+ * [  3] nonce_rfrsh_rise
+ * [  2] hpd_fall_intr
+ * [  1] hpd_rise_intr
+ * [  0] core_intr
+ */
+#define HDMITX_TOP_INTR_MASKN                   (TOP_OFFSET_MASK + 0x003)
+
+/* Bit 30: 0 RW intr_stat: For each bit, write 1 to manually set the interrupt
+ *     bit, read back the interrupt status.
+ * Bit    31 R  IP interrupt status
+ * Bit     2 RW hpd_fall
+ * Bit     1 RW hpd_rise
+ * Bit     0 RW IP interrupt
+ */
+#define HDMITX_TOP_INTR_STAT                    (TOP_OFFSET_MASK + 0x004)
+
+/* [4]   hdcp22_rndnum_err */
+/* [3]   nonce_rfrsh_rise */
+/* [2]   hpd_fall */
+/* [1]   hpd_rise */
+/* [0]   core_intr_rise */
+#define HDMITX_TOP_INTR_STAT_CLR                (TOP_OFFSET_MASK + 0x005)
+
+/* Bit 14:12 RW tmds_sel: 3'b000=Output zero; 3'b001=Output normal TMDS data;
+ *     3'b010=Output PRBS data; 3'b100=Output shift pattern.         Default 0.
+ * Bit 11: 9 RW shift_pttn_repeat: 0=New pattern every clk cycle; 1=New pattern
+ *     every 2 clk cycles; ...; 7=New pattern every 8 clk cycles.  Default 0.
+ * Bit 8 RW shift_pttn_en: 1= Eanble shift pattern generator; 0=Disable.
+ *     Default 0.
+ * Bit 4: 3 RW prbs_pttn_mode: 0=PRBS11; 1=PRBS15; 2=PRBS7; 3=PRBS31. Default 0.
+ * Bit 2: 1 RW prbs_pttn_width: 0=idle; 1=output 8-bit pattern;
+ *     2=Output 1-bit pattern; 3=output 10-bit pattern. Default 0.
+ * Bit 0 RW prbs_pttn_en: 1=Enable PRBS generator; 0=Disable. Default 0.
+ */
+#define HDMITX_TOP_BIST_CNTL                    (TOP_OFFSET_MASK + 0x006)
+
+/* Bit 29:20 RW shift_pttn_data[59:50]. Default 0. */
+/* Bit 19:10 RW shift_pttn_data[69:60]. Default 0. */
+/* Bit  9: 0 RW shift_pttn_data[79:70]. Default 0. */
+#define HDMITX_TOP_SHIFT_PTTN_012               (TOP_OFFSET_MASK + 0x007)
+
+/* Bit 29:20 RW shift_pttn_data[29:20]. Default 0. */
+/* Bit 19:10 RW shift_pttn_data[39:30]. Default 0. */
+/* Bit  9: 0 RW shift_pttn_data[49:40]. Default 0. */
+#define HDMITX_TOP_SHIFT_PTTN_345               (TOP_OFFSET_MASK + 0x008)
+
+/* Bit 19:10 RW shift_pttn_data[ 9: 0]. Default 0. */
+/* Bit  9: 0 RW shift_pttn_data[19:10]. Default 0. */
+#define HDMITX_TOP_SHIFT_PTTN_67                (TOP_OFFSET_MASK + 0x009)
+
+/* Bit 25:16 RW tmds_clk_pttn[19:10]. Default 0. */
+/* Bit  9: 0 RW tmds_clk_pttn[ 9: 0]. Default 0. */
+#define HDMITX_TOP_TMDS_CLK_PTTN_01             (TOP_OFFSET_MASK + 0x00A)
+
+/* Bit 25:16 RW tmds_clk_pttn[39:30]. Default 0. */
+/* Bit  9: 0 RW tmds_clk_pttn[29:20]. Default 0. */
+#define HDMITX_TOP_TMDS_CLK_PTTN_23             (TOP_OFFSET_MASK + 0x00B)
+
+/* Bit 1 RW shift_tmds_clk_pttn:1=Enable shifting clk pattern,
+ * used when TMDS CLK rate = TMDS character rate /4.    Default 0.
+ * Bit 0 R  Reserved. Default 0.
+ */
+/* [   1] shift_tmds_clk_pttn */
+/* [   0] load_tmds_clk_pttn */
+#define HDMITX_TOP_TMDS_CLK_PTTN_CNTL           (TOP_OFFSET_MASK + 0x00C)
+
+/* Bit 0 RW revocmem_wr_fail: Read back 1 to indicate Host write REVOC MEM
+ * failure, write 1 to clear the failure flag.  Default 0.
+ */
+#define HDMITX_TOP_REVOCMEM_STAT                (TOP_OFFSET_MASK + 0x00D)
+
+/* Bit     0 R  filtered HPD status. */
+#define HDMITX_TOP_STAT0                        (TOP_OFFSET_MASK + 0x00E)
+#define HDMITX_TOP_SKP_CNTL_STAT                (TOP_SEC_OFFSET_MASK + 0x010)
+#define HDMITX_TOP_NONCE_0                      (TOP_SEC_OFFSET_MASK + 0x011)
+#define HDMITX_TOP_NONCE_1                      (TOP_SEC_OFFSET_MASK + 0x012)
+#define HDMITX_TOP_NONCE_2                      (TOP_SEC_OFFSET_MASK + 0x013)
+#define HDMITX_TOP_NONCE_3                      (TOP_SEC_OFFSET_MASK + 0x014)
+#define HDMITX_TOP_PKF_0                        (TOP_SEC_OFFSET_MASK + 0x015)
+#define HDMITX_TOP_PKF_1                        (TOP_SEC_OFFSET_MASK + 0x016)
+#define HDMITX_TOP_PKF_2                        (TOP_SEC_OFFSET_MASK + 0x017)
+#define HDMITX_TOP_PKF_3                        (TOP_SEC_OFFSET_MASK + 0x018)
+#define HDMITX_TOP_DUK_0                        (TOP_SEC_OFFSET_MASK + 0x019)
+#define HDMITX_TOP_DUK_1                        (TOP_SEC_OFFSET_MASK + 0x01A)
+#define HDMITX_TOP_DUK_2                        (TOP_SEC_OFFSET_MASK + 0x01B)
+#define HDMITX_TOP_DUK_3                        (TOP_SEC_OFFSET_MASK + 0x01C)
+/* [26:24] infilter_ddc_intern_clk_divide */
+/* [23:16] infilter_ddc_sample_clk_divide */
+/* [10: 8] infilter_cec_intern_clk_divide */
+/* [ 7: 0] infilter_cec_sample_clk_divide */
+#define HDMITX_TOP_INFILTER                     (TOP_OFFSET_MASK + 0x01D)
+#define HDMITX_TOP_NSEC_SCRATCH                 (TOP_OFFSET_MASK + 0x01E)
+#define HDMITX_TOP_SEC_SCRATCH                  (TOP_SEC_OFFSET_MASK + 0x01F)
+
+#define HDMITX_TOP_DONT_TOUCH0                  (TOP_OFFSET_MASK + 0x0FE)
+#define HDMITX_TOP_DONT_TOUCH1                  (TOP_OFFSET_MASK + 0x0FF)
+
+/* DWC_HDMI_TX Controller registers addresses */
+
+/* Identification Registers */
+#define HDMITX_DWC_DESIGN_ID                    (DWC_OFFSET_MASK + 0x0000)
+#define HDMITX_DWC_REVISION_ID                  (DWC_OFFSET_MASK + 0x0001)
+#define HDMITX_DWC_PRODUCT_ID0                  (DWC_OFFSET_MASK + 0x0002)
+#define HDMITX_DWC_PRODUCT_ID1                  (DWC_OFFSET_MASK + 0x0003)
+#define HDMITX_DWC_CONFIG0_ID                   (DWC_OFFSET_MASK + 0x0004)
+#define HDMITX_DWC_CONFIG1_ID                   (DWC_OFFSET_MASK + 0x0005)
+#define HDMITX_DWC_CONFIG2_ID                   (DWC_OFFSET_MASK + 0x0006)
+#define HDMITX_DWC_CONFIG3_ID                   (DWC_OFFSET_MASK + 0x0007)
+
+/* Interrupt Registers */
+#define HDMITX_DWC_IH_FC_STAT0                  (DWC_OFFSET_MASK + 0x0100)
+#define HDMITX_DWC_IH_FC_STAT1                  (DWC_OFFSET_MASK + 0x0101)
+#define HDMITX_DWC_IH_FC_STAT2                  (DWC_OFFSET_MASK + 0x0102)
+#define HDMITX_DWC_IH_AS_STAT0                  (DWC_OFFSET_MASK + 0x0103)
+#define HDMITX_DWC_IH_PHY_STAT0                 (DWC_OFFSET_MASK + 0x0104)
+#define HDMITX_DWC_IH_I2CM_STAT0                (DWC_OFFSET_MASK + 0x0105)
+#define HDMITX_DWC_IH_CEC_STAT0                 (DWC_OFFSET_MASK + 0x0106)
+#define HDMITX_DWC_IH_VP_STAT0                  (DWC_OFFSET_MASK + 0x0107)
+#define HDMITX_DWC_IH_I2CMPHY_STAT0             (DWC_OFFSET_MASK + 0x0108)
+#define HDMITX_DWC_IH_DECODE                    (DWC_OFFSET_MASK + 0x0170)
+/* [  7] mute_AUDI */
+/* [  6] mute_ACP */
+/* [  5] mute_HBR */
+/* [  4] mute_MAS */
+/* [  3] mute_NVBI */
+/* [  2] mute_AUDS */
+/* [  1] mute_ACR */
+/* [  0] mute_NULL */
+#define HDMITX_DWC_IH_MUTE_FC_STAT0             (DWC_OFFSET_MASK + 0x0180)
+/* [  7] mute_GMD */
+/* [  6] mute_ISRC1 */
+/* [  5] mute_ISRC2 */
+/* [  4] mute_VSD */
+/* [  3] mute_SPD */
+/* [  2] mute_AMP */
+/* [  1] mute_AVI */
+/* [  0] mute_GCP */
+#define HDMITX_DWC_IH_MUTE_FC_STAT1             (DWC_OFFSET_MASK + 0x0181)
+/* [  1] mute_LowPriority_fifo_full */
+/* [  0] mute_HighPriority_fifo_full */
+#define HDMITX_DWC_IH_MUTE_FC_STAT2             (DWC_OFFSET_MASK + 0x0182)
+/* [  4] mute_aud_fifo_underrun */
+/* [  3] mute_aud_fifo_overrun */
+/* [  2] mute_aud_fifo_empty_thr. oififoemptythr tied to 0. */
+/* [  1] mute_aud_fifo_empty */
+/* [  0] mute_aud_fifo_full */
+#define HDMITX_DWC_IH_MUTE_AS_STAT0             (DWC_OFFSET_MASK + 0x0183)
+#define HDMITX_DWC_IH_MUTE_PHY_STAT0            (DWC_OFFSET_MASK + 0x0184)
+/* [  2] mute_scdc_readreq */
+/* [  1] mute_edid_i2c_master_done */
+/* [  0] mute_edid_i2c_master_error */
+#define HDMITX_DWC_IH_MUTE_I2CM_STAT0           (DWC_OFFSET_MASK + 0x0185)
+/* [  6] cec_wakeup */
+/* [  5] cec_error_follower */
+/* [  4] cec_error_initiator */
+/* [  3] cec_arb_lost */
+/* [  2] cec_nack */
+/* [  1] cec_eom */
+/* [  0] cec_done */
+#define HDMITX_DWC_IH_MUTE_CEC_STAT0            (DWC_OFFSET_MASK + 0x0186)
+#define HDMITX_DWC_IH_MUTE_VP_STAT0             (DWC_OFFSET_MASK + 0x0187)
+#define HDMITX_DWC_IH_MUTE_I2CMPHY_STAT0        (DWC_OFFSET_MASK + 0x0188)
+/* [  1] mute_wakeup_interrupt */
+/* [  0] mute_all_interrupt */
+#define HDMITX_DWC_IH_MUTE                      (DWC_OFFSET_MASK + 0x01FF)
+
+/* Video Sampler Registers */
+/* [  7] internal_de_generator */
+/* [4:0] video_mapping */
+#define HDMITX_DWC_TX_INVID0                    (DWC_OFFSET_MASK + 0x0200)
+/* [  2] bcbdata_stuffing */
+/* [  1] rcrdata_stuffing */
+/* [  0] gydata_stuffing */
+#define HDMITX_DWC_TX_INSTUFFING                (DWC_OFFSET_MASK + 0x0201)
+#define HDMITX_DWC_TX_GYDATA0                   (DWC_OFFSET_MASK + 0x0202)
+#define HDMITX_DWC_TX_GYDATA1                   (DWC_OFFSET_MASK + 0x0203)
+#define HDMITX_DWC_TX_RCRDATA0                  (DWC_OFFSET_MASK + 0x0204)
+#define HDMITX_DWC_TX_RCRDATA1                  (DWC_OFFSET_MASK + 0x0205)
+#define HDMITX_DWC_TX_BCBDATA0                  (DWC_OFFSET_MASK + 0x0206)
+#define HDMITX_DWC_TX_BCBDATA1                  (DWC_OFFSET_MASK + 0x0207)
+
+/* Video Packetizer Registers */
+#define HDMITX_DWC_VP_STATUS                    (DWC_OFFSET_MASK + 0x0800)
+/* [3:0] desired_pr_factor */
+#define HDMITX_DWC_VP_PR_CD                     (DWC_OFFSET_MASK + 0x0801)
+/* [  5] default_phase */
+/* [  2] ycc422_stuffing */
+/* [  1] pp_stuffing */
+/* [  0] pr_stuffing */
+#define HDMITX_DWC_VP_STUFF                     (DWC_OFFSET_MASK + 0x0802)
+#define HDMITX_DWC_VP_REMAP                     (DWC_OFFSET_MASK + 0x0803)
+#define HDMITX_DWC_VP_CONF                      (DWC_OFFSET_MASK + 0x0804)
+/* [  7] mask_int_full_prpt */
+/* [  6] mask_int_empty_prpt */
+/* [  5] mask_int_full_ppack */
+/* [  4] mask_int_empty_ppack */
+/* [  3] mask_int_full_remap */
+/* [  2] mask_int_empty_remap */
+/* [  1] mask_int_full_byp */
+/* [  0] mask_int_empty_byp */
+#define HDMITX_DWC_VP_MASK                      (DWC_OFFSET_MASK + 0x0807)
+
+/* Frmae Composer Registers */
+/* [  7] HDCP_keepout */
+/* [  6] vs_in_pol: 0=active low; 1=active high. */
+/* [  5] hs_in_pol: 0=active low; 1=active high. */
+/* [  4] de_in_pol: 0=active low; 1=active high. */
+/* [  3] dvi_modez: 0=dvi; 1=hdmi. */
+/* [  1] r_v_blank_in_osc */
+/* [  0] in_I_P: 0=progressive; 1=interlaced. */
+#define HDMITX_DWC_FC_INVIDCONF                 (DWC_OFFSET_MASK + 0x1000)
+/* [7:0] H_in_active[7:0] */
+#define HDMITX_DWC_FC_INHACTV0                  (DWC_OFFSET_MASK + 0x1001)
+/* [5:0] H_in_active[13:8] */
+#define HDMITX_DWC_FC_INHACTV1                  (DWC_OFFSET_MASK + 0x1002)
+/* [7:0] H_in_blank[7:0] */
+#define HDMITX_DWC_FC_INHBLANK0                 (DWC_OFFSET_MASK + 0x1003)
+/* [4:0] H_in_blank[12:8] */
+#define HDMITX_DWC_FC_INHBLANK1                 (DWC_OFFSET_MASK + 0x1004)
+/* [7:0] V_in_active[7:0] */
+#define HDMITX_DWC_FC_INVACTV0                  (DWC_OFFSET_MASK + 0x1005)
+/* [4:0] V_in_active[12:8] */
+#define HDMITX_DWC_FC_INVACTV1                  (DWC_OFFSET_MASK + 0x1006)
+/* [7:0] V_in_blank */
+#define HDMITX_DWC_FC_INVBLANK                  (DWC_OFFSET_MASK + 0x1007)
+/* [7:0] H_in_delay[7:0] */
+#define HDMITX_DWC_FC_HSYNCINDELAY0             (DWC_OFFSET_MASK + 0x1008)
+/* [4:0] H_in_delay[12:8] */
+#define HDMITX_DWC_FC_HSYNCINDELAY1             (DWC_OFFSET_MASK + 0x1009)
+/* [7:0] H_in_width[7:0] */
+#define HDMITX_DWC_FC_HSYNCINWIDTH0             (DWC_OFFSET_MASK + 0x100A)
+/* [1:0] H_in_width[9:8] */
+#define HDMITX_DWC_FC_HSYNCINWIDTH1             (DWC_OFFSET_MASK + 0x100B)
+/* [7:0] V_in_delay */
+#define HDMITX_DWC_FC_VSYNCINDELAY              (DWC_OFFSET_MASK + 0x100C)
+/* [5:0] V_in_width */
+#define HDMITX_DWC_FC_VSYNCINWIDTH              (DWC_OFFSET_MASK + 0x100D)
+#define HDMITX_DWC_FC_INFREQ0                   (DWC_OFFSET_MASK + 0x100E)
+#define HDMITX_DWC_FC_INFREQ1                   (DWC_OFFSET_MASK + 0x100F)
+#define HDMITX_DWC_FC_INFREQ2                   (DWC_OFFSET_MASK + 0x1010)
+#define HDMITX_DWC_FC_CTRLDUR                   (DWC_OFFSET_MASK + 0x1011)
+#define HDMITX_DWC_FC_EXCTRLDUR                 (DWC_OFFSET_MASK + 0x1012)
+#define HDMITX_DWC_FC_EXCTRLSPAC                (DWC_OFFSET_MASK + 0x1013)
+#define HDMITX_DWC_FC_CH0PREAM                  (DWC_OFFSET_MASK + 0x1014)
+#define HDMITX_DWC_FC_CH1PREAM                  (DWC_OFFSET_MASK + 0x1015)
+#define HDMITX_DWC_FC_CH2PREAM                  (DWC_OFFSET_MASK + 0x1016)
+/* [3:2] YQ */
+/* [1:0] CN */
+#define HDMITX_DWC_FC_AVICONF3                  (DWC_OFFSET_MASK + 0x1017)
+/* [  2] default_phase */
+/* [  1] set_avmute */
+/* [  0] clear_avmute */
+#define HDMITX_DWC_FC_GCP                       (DWC_OFFSET_MASK + 0x1018)
+/* [  7] rgb_ycc_indication[2] */
+/* [  6] active_format_present */
+/* [5:4] scan_information */
+/* [3:2] bar_information */
+/* [1:0] rgb_ycc_indication[1:0] */
+#define HDMITX_DWC_FC_AVICONF0                  (DWC_OFFSET_MASK + 0x1019)
+/* [7:6] colorimetry */
+/* [5:4] picture_aspect_ratio */
+/* [3:0] active_aspect_ratio */
+#define HDMITX_DWC_FC_AVICONF1                  (DWC_OFFSET_MASK + 0x101A)
+/* [  7] IT_content */
+/* [6:4] extended_colorimetry */
+/* [3:2] quantization_range */
+/* [1:0] non_uniform_picture_scaling */
+#define HDMITX_DWC_FC_AVICONF2                  (DWC_OFFSET_MASK + 0x101B)
+#define HDMITX_DWC_FC_AVIVID                    (DWC_OFFSET_MASK + 0x101C)
+#define HDMITX_DWC_FC_AVIETB0                   (DWC_OFFSET_MASK + 0x101D)
+#define HDMITX_DWC_FC_AVIETB1                   (DWC_OFFSET_MASK + 0x101E)
+#define HDMITX_DWC_FC_AVISBB0                   (DWC_OFFSET_MASK + 0x101F)
+#define HDMITX_DWC_FC_AVISBB1                   (DWC_OFFSET_MASK + 0x1020)
+#define HDMITX_DWC_FC_AVIELB0                   (DWC_OFFSET_MASK + 0x1021)
+#define HDMITX_DWC_FC_AVIELB1                   (DWC_OFFSET_MASK + 0x1022)
+#define HDMITX_DWC_FC_AVISRB0                   (DWC_OFFSET_MASK + 0x1023)
+#define HDMITX_DWC_FC_AVISRB1                   (DWC_OFFSET_MASK + 0x1024)
+/* [3:0] CT: coding type */
+#define HDMITX_DWC_FC_AUDICONF0                 (DWC_OFFSET_MASK + 0x1025)
+/* [5:4] SS: sampling size */
+/* [2:0] SF: sampling frequency */
+#define HDMITX_DWC_FC_AUDICONF1                 (DWC_OFFSET_MASK + 0x1026)
+/* CA: channel allocation */
+#define HDMITX_DWC_FC_AUDICONF2                 (DWC_OFFSET_MASK + 0x1027)
+/* [6:5] LFEPBL: LFE playback info */
+/* [  4] DM_INH: down mix enable */
+/* [3:0] LSv: Level shift value */
+#define HDMITX_DWC_FC_AUDICONF3                 (DWC_OFFSET_MASK + 0x1028)
+#define HDMITX_DWC_FC_VSDIEEEID0                (DWC_OFFSET_MASK + 0x1029)
+#define HDMITX_DWC_FC_VSDSIZE                   (DWC_OFFSET_MASK + 0x102A)
+#define HDMITX_DWC_FC_VSDIEEEID1                (DWC_OFFSET_MASK + 0x1030)
+#define HDMITX_DWC_FC_VSDIEEEID2                (DWC_OFFSET_MASK + 0x1031)
+#define HDMITX_DWC_FC_VSDPAYLOAD0               (DWC_OFFSET_MASK + 0x1032)
+#define HDMITX_DWC_FC_VSDPAYLOAD1               (DWC_OFFSET_MASK + 0x1033)
+#define HDMITX_DWC_FC_VSDPAYLOAD2               (DWC_OFFSET_MASK + 0x1034)
+#define HDMITX_DWC_FC_VSDPAYLOAD3               (DWC_OFFSET_MASK + 0x1035)
+#define HDMITX_DWC_FC_VSDPAYLOAD4               (DWC_OFFSET_MASK + 0x1036)
+#define HDMITX_DWC_FC_VSDPAYLOAD5               (DWC_OFFSET_MASK + 0x1037)
+#define HDMITX_DWC_FC_VSDPAYLOAD6               (DWC_OFFSET_MASK + 0x1038)
+#define HDMITX_DWC_FC_VSDPAYLOAD7               (DWC_OFFSET_MASK + 0x1039)
+#define HDMITX_DWC_FC_VSDPAYLOAD8               (DWC_OFFSET_MASK + 0x103A)
+#define HDMITX_DWC_FC_VSDPAYLOAD9               (DWC_OFFSET_MASK + 0x103B)
+#define HDMITX_DWC_FC_VSDPAYLOAD10              (DWC_OFFSET_MASK + 0x103C)
+#define HDMITX_DWC_FC_VSDPAYLOAD11              (DWC_OFFSET_MASK + 0x103D)
+#define HDMITX_DWC_FC_VSDPAYLOAD12              (DWC_OFFSET_MASK + 0x103E)
+#define HDMITX_DWC_FC_VSDPAYLOAD13              (DWC_OFFSET_MASK + 0x103F)
+#define HDMITX_DWC_FC_VSDPAYLOAD14              (DWC_OFFSET_MASK + 0x1040)
+#define HDMITX_DWC_FC_VSDPAYLOAD15              (DWC_OFFSET_MASK + 0x1041)
+#define HDMITX_DWC_FC_VSDPAYLOAD16              (DWC_OFFSET_MASK + 0x1042)
+#define HDMITX_DWC_FC_VSDPAYLOAD17              (DWC_OFFSET_MASK + 0x1043)
+#define HDMITX_DWC_FC_VSDPAYLOAD18              (DWC_OFFSET_MASK + 0x1044)
+#define HDMITX_DWC_FC_VSDPAYLOAD19              (DWC_OFFSET_MASK + 0x1045)
+#define HDMITX_DWC_FC_VSDPAYLOAD20              (DWC_OFFSET_MASK + 0x1046)
+#define HDMITX_DWC_FC_VSDPAYLOAD21              (DWC_OFFSET_MASK + 0x1047)
+#define HDMITX_DWC_FC_VSDPAYLOAD22              (DWC_OFFSET_MASK + 0x1048)
+#define HDMITX_DWC_FC_VSDPAYLOAD23              (DWC_OFFSET_MASK + 0x1049)
+#define HDMITX_DWC_FC_SPDVENDORNAME0            (DWC_OFFSET_MASK + 0x104A)
+#define HDMITX_DWC_FC_SPDVENDORNAME1            (DWC_OFFSET_MASK + 0x104B)
+#define HDMITX_DWC_FC_SPDVENDORNAME2            (DWC_OFFSET_MASK + 0x104C)
+#define HDMITX_DWC_FC_SPDVENDORNAME3            (DWC_OFFSET_MASK + 0x104D)
+#define HDMITX_DWC_FC_SPDVENDORNAME4            (DWC_OFFSET_MASK + 0x104E)
+#define HDMITX_DWC_FC_SPDVENDORNAME5            (DWC_OFFSET_MASK + 0x104F)
+#define HDMITX_DWC_FC_SPDVENDORNAME6            (DWC_OFFSET_MASK + 0x1050)
+#define HDMITX_DWC_FC_SPDVENDORNAME7            (DWC_OFFSET_MASK + 0x1051)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME0           (DWC_OFFSET_MASK + 0x1052)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME1           (DWC_OFFSET_MASK + 0x1053)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME2           (DWC_OFFSET_MASK + 0x1054)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME3           (DWC_OFFSET_MASK + 0x1055)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME4           (DWC_OFFSET_MASK + 0x1056)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME5           (DWC_OFFSET_MASK + 0x1057)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME6           (DWC_OFFSET_MASK + 0x1058)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME7           (DWC_OFFSET_MASK + 0x1059)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME8           (DWC_OFFSET_MASK + 0x105A)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME9           (DWC_OFFSET_MASK + 0x105B)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME10          (DWC_OFFSET_MASK + 0x105C)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME11          (DWC_OFFSET_MASK + 0x105D)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME12          (DWC_OFFSET_MASK + 0x105E)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME13          (DWC_OFFSET_MASK + 0x105F)
+#define HDMITX_DWC_FC_SDPPRODUCTNAME14          (DWC_OFFSET_MASK + 0x1060)
+#define HDMITX_DWC_FC_SPDPRODUCTNAME15          (DWC_OFFSET_MASK + 0x1061)
+#define HDMITX_DWC_FC_SPDDEVICEINF              (DWC_OFFSET_MASK + 0x1062)
+/* [7:4] aud_packet_sampflat */
+/* [  0] aud_packet_layout */
+#define HDMITX_DWC_FC_AUDSCONF                  (DWC_OFFSET_MASK + 0x1063)
+#define HDMITX_DWC_FC_AUDSSTAT                  (DWC_OFFSET_MASK + 0x1064)
+/* [  7] V3r */
+/* [  6] V2r */
+/* [  5] V1r */
+/* [  4] V0r */
+/* [  3] V3l */
+/* [  2] V2l */
+/* [  1] V1l */
+/* [  0] V0l */
+#define HDMITX_DWC_FC_AUDSV                     (DWC_OFFSET_MASK + 0x1065)
+#define HDMITX_DWC_FC_AUDSU                     (DWC_OFFSET_MASK + 0x1066)
+/* bit5:4  CSB 41:40 */
+/* bit0  CSB 2 */
+#define HDMITX_DWC_FC_AUDSCHNLS0                (DWC_OFFSET_MASK + 0x1067)
+/* bit7:0  CSB 15:8 */
+#define HDMITX_DWC_FC_AUDSCHNLS1                (DWC_OFFSET_MASK + 0x1068)
+/* bit6:4  CSB 5:3 */
+/* bit3:0  CSB 17:16 */
+#define HDMITX_DWC_FC_AUDSCHNLS2                (DWC_OFFSET_MASK + 0x1069)
+/* bit7:4 CSB 22:21 2nd right sub */
+/* bit3:0 CSB 22:21 1st right sub */
+#define HDMITX_DWC_FC_AUDSCHNLS3                (DWC_OFFSET_MASK + 0x106A)
+/* bit?? CSB 22:21 4th right sub */
+/* bit?? CSB 22:21 3rd right sub */
+#define HDMITX_DWC_FC_AUDSCHNLS4                (DWC_OFFSET_MASK + 0x106B)
+/* bit7:4 CSB 22:21 2nd left sub */
+/* bit3:0 CSB 22:21 1st left sub */
+#define HDMITX_DWC_FC_AUDSCHNLS5                (DWC_OFFSET_MASK + 0x106C)
+/* bit?? CSB 22:21 4th left sub */
+/* bit?? CSB 22:21 3rd left sub */
+#define HDMITX_DWC_FC_AUDSCHNLS6                (DWC_OFFSET_MASK + 0x106D)
+#define HDMITX_DWC_FC_AUDSCHNLS7                (DWC_OFFSET_MASK + 0x106E)
+#define HDMITX_DWC_FC_AUDSCHNLS8                (DWC_OFFSET_MASK + 0x106F)
+#define HDMITX_DWC_FC_DATACH0FILL               (DWC_OFFSET_MASK + 0x1070)
+#define HDMITX_DWC_FC_DATACH1FILL               (DWC_OFFSET_MASK + 0x1071)
+#define HDMITX_DWC_FC_DATACH2FILL               (DWC_OFFSET_MASK + 0x1072)
+#define HDMITX_DWC_FC_CTRLQHIGH                 (DWC_OFFSET_MASK + 0x1073)
+#define HDMITX_DWC_FC_CTRLQLOW                  (DWC_OFFSET_MASK + 0x1074)
+#define HDMITX_DWC_FC_ACP0                      (DWC_OFFSET_MASK + 0x1075)
+#define HDMITX_DWC_FC_ACP16                     (DWC_OFFSET_MASK + 0x1082)
+#define HDMITX_DWC_FC_ACP15                     (DWC_OFFSET_MASK + 0x1083)
+#define HDMITX_DWC_FC_ACP14                     (DWC_OFFSET_MASK + 0x1084)
+#define HDMITX_DWC_FC_ACP13                     (DWC_OFFSET_MASK + 0x1085)
+#define HDMITX_DWC_FC_ACP12                     (DWC_OFFSET_MASK + 0x1086)
+#define HDMITX_DWC_FC_ACP11                     (DWC_OFFSET_MASK + 0x1087)
+#define HDMITX_DWC_FC_ACP10                     (DWC_OFFSET_MASK + 0x1088)
+#define HDMITX_DWC_FC_ACP9                      (DWC_OFFSET_MASK + 0x1089)
+#define HDMITX_DWC_FC_ACP8                      (DWC_OFFSET_MASK + 0x108A)
+#define HDMITX_DWC_FC_ACP7                      (DWC_OFFSET_MASK + 0x108B)
+#define HDMITX_DWC_FC_ACP6                      (DWC_OFFSET_MASK + 0x108C)
+#define HDMITX_DWC_FC_ACP5                      (DWC_OFFSET_MASK + 0x108D)
+#define HDMITX_DWC_FC_ACP4                      (DWC_OFFSET_MASK + 0x108E)
+#define HDMITX_DWC_FC_ACP3                      (DWC_OFFSET_MASK + 0x108F)
+#define HDMITX_DWC_FC_ACP2                      (DWC_OFFSET_MASK + 0x1090)
+#define HDMITX_DWC_FC_ACP1                      (DWC_OFFSET_MASK + 0x1091)
+#define HDMITX_DWC_FC_ISCR1_0                   (DWC_OFFSET_MASK + 0x1092)
+#define HDMITX_DWC_FC_ISCR1_16                  (DWC_OFFSET_MASK + 0x1093)
+#define HDMITX_DWC_FC_ISCR1_15                  (DWC_OFFSET_MASK + 0x1094)
+#define HDMITX_DWC_FC_ISCR1_14                  (DWC_OFFSET_MASK + 0x1095)
+#define HDMITX_DWC_FC_ISCR1_13                  (DWC_OFFSET_MASK + 0x1096)
+#define HDMITX_DWC_FC_ISCR1_12                  (DWC_OFFSET_MASK + 0x1097)
+#define HDMITX_DWC_FC_ISCR1_11                  (DWC_OFFSET_MASK + 0x1098)
+#define HDMITX_DWC_FC_ISCR1_10                  (DWC_OFFSET_MASK + 0x1099)
+#define HDMITX_DWC_FC_ISCR1_9                   (DWC_OFFSET_MASK + 0x109A)
+#define HDMITX_DWC_FC_ISCR1_8                   (DWC_OFFSET_MASK + 0x109B)
+#define HDMITX_DWC_FC_ISCR1_7                   (DWC_OFFSET_MASK + 0x109C)
+#define HDMITX_DWC_FC_ISCR1_6                   (DWC_OFFSET_MASK + 0x109D)
+#define HDMITX_DWC_FC_ISCR1_5                   (DWC_OFFSET_MASK + 0x109E)
+#define HDMITX_DWC_FC_ISCR1_4                   (DWC_OFFSET_MASK + 0x109F)
+#define HDMITX_DWC_FC_ISCR1_3                   (DWC_OFFSET_MASK + 0x10A0)
+#define HDMITX_DWC_FC_ISCR1_2                   (DWC_OFFSET_MASK + 0x10A1)
+#define HDMITX_DWC_FC_ISCR1_1                   (DWC_OFFSET_MASK + 0x10A2)
+#define HDMITX_DWC_FC_ISCR0_15                  (DWC_OFFSET_MASK + 0x10A3)
+#define HDMITX_DWC_FC_ISCR0_14                  (DWC_OFFSET_MASK + 0x10A4)
+#define HDMITX_DWC_FC_ISCR0_13                  (DWC_OFFSET_MASK + 0x10A5)
+#define HDMITX_DWC_FC_ISCR0_12                  (DWC_OFFSET_MASK + 0x10A6)
+#define HDMITX_DWC_FC_ISCR0_11                  (DWC_OFFSET_MASK + 0x10A7)
+#define HDMITX_DWC_FC_ISCR0_10                  (DWC_OFFSET_MASK + 0x10A8)
+#define HDMITX_DWC_FC_ISCR0_9                   (DWC_OFFSET_MASK + 0x10A9)
+#define HDMITX_DWC_FC_ISCR0_8                   (DWC_OFFSET_MASK + 0x10AA)
+#define HDMITX_DWC_FC_ISCR0_7                   (DWC_OFFSET_MASK + 0x10AB)
+#define HDMITX_DWC_FC_ISCR0_6                   (DWC_OFFSET_MASK + 0x10AC)
+#define HDMITX_DWC_FC_ISCR0_5                   (DWC_OFFSET_MASK + 0x10AD)
+#define HDMITX_DWC_FC_ISCR0_4                   (DWC_OFFSET_MASK + 0x10AE)
+#define HDMITX_DWC_FC_ISCR0_3                   (DWC_OFFSET_MASK + 0x10AF)
+#define HDMITX_DWC_FC_ISCR0_2                   (DWC_OFFSET_MASK + 0x10B0)
+#define HDMITX_DWC_FC_ISCR0_1                   (DWC_OFFSET_MASK + 0x10B1)
+#define HDMITX_DWC_FC_ISCR0_0                   (DWC_OFFSET_MASK + 0x10B2)
+/* [  4] spd_auto */
+/* [  3] vsd_auto */
+/* [  2] isrc2_auto */
+/* [  1] isrc1_auto */
+/* [  0] acp_auto */
+#define HDMITX_DWC_FC_DATAUTO0                  (DWC_OFFSET_MASK + 0x10B3)
+#define HDMITX_DWC_FC_DATAUTO1                  (DWC_OFFSET_MASK + 0x10B4)
+#define HDMITX_DWC_FC_DATAUTO2                  (DWC_OFFSET_MASK + 0x10B5)
+#define HDMITX_DWC_FC_DATMAN                    (DWC_OFFSET_MASK + 0x10B6)
+/* [  6] drm_auto: instert on Vsync */
+/* [  5] nvbi_auto: insert on Vsync */
+/* [  4] amp_auto: insert on Vsync */
+/* [  3] avi_auto: insert on Vsync */
+/* [  2] gcp_auto: insert on Vsync */
+/* [  1] audi_auto: insert on Vsync */
+/* [  0] acr_auto: insert on CTS update. Assert this bit later to avoid
+ * initial packets with false CTS value
+ */
+#define HDMITX_DWC_FC_DATAUTO3                  (DWC_OFFSET_MASK + 0x10B7)
+#define HDMITX_DWC_FC_RDRB0                     (DWC_OFFSET_MASK + 0x10B8)
+#define HDMITX_DWC_FC_RDRB1                     (DWC_OFFSET_MASK + 0x10B9)
+#define HDMITX_DWC_FC_RDRB2                     (DWC_OFFSET_MASK + 0x10BA)
+#define HDMITX_DWC_FC_RDRB3                     (DWC_OFFSET_MASK + 0x10BB)
+#define HDMITX_DWC_FC_RDRB4                     (DWC_OFFSET_MASK + 0x10BC)
+#define HDMITX_DWC_FC_RDRB5                     (DWC_OFFSET_MASK + 0x10BD)
+#define HDMITX_DWC_FC_RDRB6                     (DWC_OFFSET_MASK + 0x10BE)
+#define HDMITX_DWC_FC_RDRB7                     (DWC_OFFSET_MASK + 0x10BF)
+#define HDMITX_DWC_FC_RDRB8                     (DWC_OFFSET_MASK + 0x10C0)
+#define HDMITX_DWC_FC_RDRB9                     (DWC_OFFSET_MASK + 0x10C1)
+#define HDMITX_DWC_FC_RDRB10                    (DWC_OFFSET_MASK + 0x10C2)
+#define HDMITX_DWC_FC_RDRB11                    (DWC_OFFSET_MASK + 0x10C3)
+/* [  7] AUDI_int_mask */
+/* [  6] ACP_int_mask */
+/* [  5] HBR_int_mask */
+/* [  2] AUDS_int_mask */
+/* [  1] ACR_int_mask */
+/* [  0] NULL_int_mask */
+#define HDMITX_DWC_FC_MASK0                     (DWC_OFFSET_MASK + 0x10D2)
+/* [  7] GMD_int_mask */
+/* [  6] ISRC1_int_mask */
+/* [  5] ISRC2_int_mask */
+/* [  4] VSD_int_mask */
+/* [  3] SPD_int_mask */
+/* [  1] AVI_int_mask */
+/* [  0] GCP_int_mask */
+#define HDMITX_DWC_FC_MASK1                     (DWC_OFFSET_MASK + 0x10D6)
+/* [  2] Mask bit for FC_INT2.DRM interrupt bit */
+/* [  1] LowPriority_fifo_full */
+/* [  0] HighPriority_fifo_full */
+#define HDMITX_DWC_FC_MASK2                     (DWC_OFFSET_MASK + 0x10DA)
+/* [7:4] incoming_pr_factor */
+/* [3:0] output_pr_factor */
+#define HDMITX_DWC_FC_PRCONF                    (DWC_OFFSET_MASK + 0x10E0)
+/* [  4] scrambler_ucp_line */
+/* [  0] scrambler_en. Only update this bit once we've sent SCDC message*/
+#define HDMITX_DWC_FC_SCRAMBLER_CTRL            (DWC_OFFSET_MASK + 0x10E1)
+#define HDMITX_DWC_FC_MULTISTREAM_CTRL          (DWC_OFFSET_MASK + 0x10E2)
+/* [  7] drm_tx_en */
+/* [  6] nvbi_tx_en */
+/* [  5] amp_tx_en */
+/* [  4] aut_tx_en */
+/* [  3] audi_tx_en */
+/* [  2] avi_tx_en */
+/* [  1] gcp_tx_en */
+/* [  0] acr_tx_en */
+#define HDMITX_DWC_FC_PACKET_TX_EN              (DWC_OFFSET_MASK + 0x10E3)
+/* [  1] actspc_hdlr_tgl */
+/* [  0] actspc_hdlr_en */
+#define HDMITX_DWC_FC_ACTSPC_HDLR_CFG           (DWC_OFFSET_MASK + 0x10E8)
+#define HDMITX_DWC_FC_INVACT_2D_0               (DWC_OFFSET_MASK + 0x10E9)
+/* [3:0] fc_invact_2d_0[11:8] */
+/* [7:0] fc_invact_2d_0[7:0] */
+#define HDMITX_DWC_FC_INVACT_2D_1               (DWC_OFFSET_MASK + 0x10EA)
+
+#define HDMITX_DWC_FC_GMD_STAT                  (DWC_OFFSET_MASK + 0x1100)
+#define HDMITX_DWC_FC_GMD_EN                    (DWC_OFFSET_MASK + 0x1101)
+#define HDMITX_DWC_FC_GMD_UP                    (DWC_OFFSET_MASK + 0x1102)
+#define HDMITX_DWC_FC_GMD_CONF                  (DWC_OFFSET_MASK + 0x1103)
+#define HDMITX_DWC_FC_GMD_HB                    (DWC_OFFSET_MASK + 0x1104)
+#define HDMITX_DWC_FC_GMD_PB0                   (DWC_OFFSET_MASK + 0x1105)
+#define HDMITX_DWC_FC_GMD_PB1                   (DWC_OFFSET_MASK + 0x1106)
+#define HDMITX_DWC_FC_GMD_PB2                   (DWC_OFFSET_MASK + 0x1107)
+#define HDMITX_DWC_FC_GMD_PB3                   (DWC_OFFSET_MASK + 0x1108)
+#define HDMITX_DWC_FC_GMD_PB4                   (DWC_OFFSET_MASK + 0x1109)
+#define HDMITX_DWC_FC_GMD_PB5                   (DWC_OFFSET_MASK + 0x110A)
+#define HDMITX_DWC_FC_GMD_PB6                   (DWC_OFFSET_MASK + 0x110B)
+#define HDMITX_DWC_FC_GMD_PB7                   (DWC_OFFSET_MASK + 0x110C)
+#define HDMITX_DWC_FC_GMD_PB8                   (DWC_OFFSET_MASK + 0x110D)
+#define HDMITX_DWC_FC_GMD_PB9                   (DWC_OFFSET_MASK + 0x110E)
+#define HDMITX_DWC_FC_GMD_PB10                  (DWC_OFFSET_MASK + 0x110F)
+#define HDMITX_DWC_FC_GMD_PB11                  (DWC_OFFSET_MASK + 0x1110)
+#define HDMITX_DWC_FC_GMD_PB12                  (DWC_OFFSET_MASK + 0x1111)
+#define HDMITX_DWC_FC_GMD_PB13                  (DWC_OFFSET_MASK + 0x1112)
+#define HDMITX_DWC_FC_GMD_PB14                  (DWC_OFFSET_MASK + 0x1113)
+#define HDMITX_DWC_FC_GMD_PB15                  (DWC_OFFSET_MASK + 0x1114)
+#define HDMITX_DWC_FC_GMD_PB16                  (DWC_OFFSET_MASK + 0x1115)
+#define HDMITX_DWC_FC_GMD_PB17                  (DWC_OFFSET_MASK + 0x1116)
+#define HDMITX_DWC_FC_GMD_PB18                  (DWC_OFFSET_MASK + 0x1117)
+#define HDMITX_DWC_FC_GMD_PB19                  (DWC_OFFSET_MASK + 0x1118)
+#define HDMITX_DWC_FC_GMD_PB20                  (DWC_OFFSET_MASK + 0x1119)
+#define HDMITX_DWC_FC_GMD_PB21                  (DWC_OFFSET_MASK + 0x111A)
+#define HDMITX_DWC_FC_GMD_PB22                  (DWC_OFFSET_MASK + 0x111B)
+#define HDMITX_DWC_FC_GMD_PB23                  (DWC_OFFSET_MASK + 0x111C)
+#define HDMITX_DWC_FC_GMD_PB24                  (DWC_OFFSET_MASK + 0x111D)
+#define HDMITX_DWC_FC_GMD_PB25                  (DWC_OFFSET_MASK + 0x111E)
+#define HDMITX_DWC_FC_GMD_PB26                  (DWC_OFFSET_MASK + 0x111F)
+#define HDMITX_DWC_FC_GMD_PB27                  (DWC_OFFSET_MASK + 0x1120)
+
+/* Audio Metadata Packet Registers */
+#define HDMITX_DWC_FC_AMP_HB01                  (DWC_OFFSET_MASK + 0x1128)
+#define HDMITX_DWC_FC_AMP_HB02                  (DWC_OFFSET_MASK + 0x1129)
+#define HDMITX_DWC_FC_AMP_PB00                  (DWC_OFFSET_MASK + 0x112A)
+#define HDMITX_DWC_FC_AMP_PB01                  (DWC_OFFSET_MASK + 0x112B)
+#define HDMITX_DWC_FC_AMP_PB02                  (DWC_OFFSET_MASK + 0x112C)
+#define HDMITX_DWC_FC_AMP_PB03                  (DWC_OFFSET_MASK + 0x112D)
+#define HDMITX_DWC_FC_AMP_PB04                  (DWC_OFFSET_MASK + 0x112E)
+#define HDMITX_DWC_FC_AMP_PB05                  (DWC_OFFSET_MASK + 0x112F)
+#define HDMITX_DWC_FC_AMP_PB06                  (DWC_OFFSET_MASK + 0x1130)
+#define HDMITX_DWC_FC_AMP_PB07                  (DWC_OFFSET_MASK + 0x1131)
+#define HDMITX_DWC_FC_AMP_PB08                  (DWC_OFFSET_MASK + 0x1132)
+#define HDMITX_DWC_FC_AMP_PB09                  (DWC_OFFSET_MASK + 0x1133)
+#define HDMITX_DWC_FC_AMP_PB10                  (DWC_OFFSET_MASK + 0x1134)
+#define HDMITX_DWC_FC_AMP_PB11                  (DWC_OFFSET_MASK + 0x1135)
+#define HDMITX_DWC_FC_AMP_PB12                  (DWC_OFFSET_MASK + 0x1136)
+#define HDMITX_DWC_FC_AMP_PB13                  (DWC_OFFSET_MASK + 0x1137)
+#define HDMITX_DWC_FC_AMP_PB14                  (DWC_OFFSET_MASK + 0x1138)
+#define HDMITX_DWC_FC_AMP_PB15                  (DWC_OFFSET_MASK + 0x1139)
+#define HDMITX_DWC_FC_AMP_PB16                  (DWC_OFFSET_MASK + 0x113A)
+#define HDMITX_DWC_FC_AMP_PB17                  (DWC_OFFSET_MASK + 0x113B)
+#define HDMITX_DWC_FC_AMP_PB18                  (DWC_OFFSET_MASK + 0x113C)
+#define HDMITX_DWC_FC_AMP_PB19                  (DWC_OFFSET_MASK + 0x113D)
+#define HDMITX_DWC_FC_AMP_PB20                  (DWC_OFFSET_MASK + 0x113E)
+#define HDMITX_DWC_FC_AMP_PB21                  (DWC_OFFSET_MASK + 0x113F)
+#define HDMITX_DWC_FC_AMP_PB22                  (DWC_OFFSET_MASK + 0x1140)
+#define HDMITX_DWC_FC_AMP_PB23                  (DWC_OFFSET_MASK + 0x1141)
+#define HDMITX_DWC_FC_AMP_PB24                  (DWC_OFFSET_MASK + 0x1142)
+#define HDMITX_DWC_FC_AMP_PB25                  (DWC_OFFSET_MASK + 0x1143)
+#define HDMITX_DWC_FC_AMP_PB26                  (DWC_OFFSET_MASK + 0x1144)
+#define HDMITX_DWC_FC_AMP_PB27                  (DWC_OFFSET_MASK + 0x1145)
+
+/* NTSC VBI Packet Registers */
+#define HDMITX_DWC_FC_NVBI_HB01                 (DWC_OFFSET_MASK + 0x1148)
+#define HDMITX_DWC_FC_NVBI_HB02                 (DWC_OFFSET_MASK + 0x1149)
+#define HDMITX_DWC_FC_NVBI_PB01                 (DWC_OFFSET_MASK + 0x114A)
+#define HDMITX_DWC_FC_NVBI_PB02                 (DWC_OFFSET_MASK + 0x114B)
+#define HDMITX_DWC_FC_NVBI_PB03                 (DWC_OFFSET_MASK + 0x114C)
+#define HDMITX_DWC_FC_NVBI_PB04                 (DWC_OFFSET_MASK + 0x114D)
+#define HDMITX_DWC_FC_NVBI_PB05                 (DWC_OFFSET_MASK + 0x114E)
+#define HDMITX_DWC_FC_NVBI_PB06                 (DWC_OFFSET_MASK + 0x114F)
+#define HDMITX_DWC_FC_NVBI_PB07                 (DWC_OFFSET_MASK + 0x1150)
+#define HDMITX_DWC_FC_NVBI_PB08                 (DWC_OFFSET_MASK + 0x1151)
+#define HDMITX_DWC_FC_NVBI_PB09                 (DWC_OFFSET_MASK + 0x1152)
+#define HDMITX_DWC_FC_NVBI_PB10                 (DWC_OFFSET_MASK + 0x1153)
+#define HDMITX_DWC_FC_NVBI_PB11                 (DWC_OFFSET_MASK + 0x1154)
+#define HDMITX_DWC_FC_NVBI_PB12                 (DWC_OFFSET_MASK + 0x1155)
+#define HDMITX_DWC_FC_NVBI_PB13                 (DWC_OFFSET_MASK + 0x1156)
+#define HDMITX_DWC_FC_NVBI_PB14                 (DWC_OFFSET_MASK + 0x1157)
+#define HDMITX_DWC_FC_NVBI_PB15                 (DWC_OFFSET_MASK + 0x1158)
+#define HDMITX_DWC_FC_NVBI_PB16                 (DWC_OFFSET_MASK + 0x1159)
+#define HDMITX_DWC_FC_NVBI_PB17                 (DWC_OFFSET_MASK + 0x115A)
+#define HDMITX_DWC_FC_NVBI_PB18                 (DWC_OFFSET_MASK + 0x115B)
+#define HDMITX_DWC_FC_NVBI_PB19                 (DWC_OFFSET_MASK + 0x115C)
+#define HDMITX_DWC_FC_NVBI_PB20                 (DWC_OFFSET_MASK + 0x115D)
+#define HDMITX_DWC_FC_NVBI_PB21                 (DWC_OFFSET_MASK + 0x115E)
+#define HDMITX_DWC_FC_NVBI_PB22                 (DWC_OFFSET_MASK + 0x115F)
+#define HDMITX_DWC_FC_NVBI_PB23                 (DWC_OFFSET_MASK + 0x1160)
+#define HDMITX_DWC_FC_NVBI_PB24                 (DWC_OFFSET_MASK + 0x1161)
+#define HDMITX_DWC_FC_NVBI_PB25                 (DWC_OFFSET_MASK + 0x1162)
+#define HDMITX_DWC_FC_NVBI_PB26                 (DWC_OFFSET_MASK + 0x1163)
+#define HDMITX_DWC_FC_NVBI_PB27                 (DWC_OFFSET_MASK + 0x1164)
+#define HDMITX_DWC_FC_DRM_HB01                  (DWC_OFFSET_MASK + 0x1168)
+#define HDMITX_DWC_FC_DRM_HB02                  (DWC_OFFSET_MASK + 0x1169)
+#define HDMITX_DWC_FC_DRM_PB00                  (DWC_OFFSET_MASK + 0x116A)
+#define HDMITX_DWC_FC_DRM_PB01                  (DWC_OFFSET_MASK + 0x116B)
+#define HDMITX_DWC_FC_DRM_PB02                  (DWC_OFFSET_MASK + 0x116C)
+#define HDMITX_DWC_FC_DRM_PB03                  (DWC_OFFSET_MASK + 0x116D)
+#define HDMITX_DWC_FC_DRM_PB04                  (DWC_OFFSET_MASK + 0x116E)
+#define HDMITX_DWC_FC_DRM_PB05                  (DWC_OFFSET_MASK + 0x116F)
+#define HDMITX_DWC_FC_DRM_PB06                  (DWC_OFFSET_MASK + 0x1170)
+#define HDMITX_DWC_FC_DRM_PB07                  (DWC_OFFSET_MASK + 0x1171)
+#define HDMITX_DWC_FC_DRM_PB08                  (DWC_OFFSET_MASK + 0x1172)
+#define HDMITX_DWC_FC_DRM_PB09                  (DWC_OFFSET_MASK + 0x1173)
+#define HDMITX_DWC_FC_DRM_PB10                  (DWC_OFFSET_MASK + 0x1174)
+#define HDMITX_DWC_FC_DRM_PB11                  (DWC_OFFSET_MASK + 0x1175)
+#define HDMITX_DWC_FC_DRM_PB12                  (DWC_OFFSET_MASK + 0x1176)
+#define HDMITX_DWC_FC_DRM_PB13                  (DWC_OFFSET_MASK + 0x1177)
+#define HDMITX_DWC_FC_DRM_PB14                  (DWC_OFFSET_MASK + 0x1178)
+#define HDMITX_DWC_FC_DRM_PB15                  (DWC_OFFSET_MASK + 0x1179)
+#define HDMITX_DWC_FC_DRM_PB16                  (DWC_OFFSET_MASK + 0x117A)
+#define HDMITX_DWC_FC_DRM_PB17                  (DWC_OFFSET_MASK + 0x117B)
+#define HDMITX_DWC_FC_DRM_PB18                  (DWC_OFFSET_MASK + 0x117C)
+#define HDMITX_DWC_FC_DRM_PB19                  (DWC_OFFSET_MASK + 0x117D)
+#define HDMITX_DWC_FC_DRM_PB20                  (DWC_OFFSET_MASK + 0x117E)
+#define HDMITX_DWC_FC_DRM_PB21                  (DWC_OFFSET_MASK + 0x117F)
+#define HDMITX_DWC_FC_DRM_PB22                  (DWC_OFFSET_MASK + 0x1180)
+#define HDMITX_DWC_FC_DRM_PB23                  (DWC_OFFSET_MASK + 0x1181)
+#define HDMITX_DWC_FC_DRM_PB24                  (DWC_OFFSET_MASK + 0x1182)
+#define HDMITX_DWC_FC_DRM_PB25                  (DWC_OFFSET_MASK + 0x1183)
+#define HDMITX_DWC_FC_DRM_PB26                  (DWC_OFFSET_MASK + 0x1184)
+
+#define HDMITX_DWC_FC_DBGFORCE                  (DWC_OFFSET_MASK + 0x1200)
+#define HDMITX_DWC_FC_DBGAUD0CH0                (DWC_OFFSET_MASK + 0x1201)
+#define HDMITX_DWC_FC_DBGAUD1CH0                (DWC_OFFSET_MASK + 0x1202)
+#define HDMITX_DWC_FC_DBGAUD2CH0                (DWC_OFFSET_MASK + 0x1203)
+#define HDMITX_DWC_FC_DBGAUD0CH1                (DWC_OFFSET_MASK + 0x1204)
+#define HDMITX_DWC_FC_DBGAUD1CH1                (DWC_OFFSET_MASK + 0x1205)
+#define HDMITX_DWC_FC_DBGAUD2CH1                (DWC_OFFSET_MASK + 0x1206)
+#define HDMITX_DWC_FC_DBGAUD0CH2                (DWC_OFFSET_MASK + 0x1207)
+#define HDMITX_DWC_FC_DBGAUD1CH2                (DWC_OFFSET_MASK + 0x1208)
+#define HDMITX_DWC_FC_DBGAUD2CH2                (DWC_OFFSET_MASK + 0x1209)
+#define HDMITX_DWC_FC_DBGAUD0CH3                (DWC_OFFSET_MASK + 0x120A)
+#define HDMITX_DWC_FC_DBGAUD1CH3                (DWC_OFFSET_MASK + 0x120B)
+#define HDMITX_DWC_FC_DBGAUD2CH3                (DWC_OFFSET_MASK + 0x120C)
+#define HDMITX_DWC_FC_DBGAUD0CH4                (DWC_OFFSET_MASK + 0x120D)
+#define HDMITX_DWC_FC_DBGAUD1CH4                (DWC_OFFSET_MASK + 0x120E)
+#define HDMITX_DWC_FC_DBGAUD2CH4                (DWC_OFFSET_MASK + 0x120F)
+#define HDMITX_DWC_FC_DBGAUD0CH5                (DWC_OFFSET_MASK + 0x1210)
+#define HDMITX_DWC_FC_DBGAUD1CH5                (DWC_OFFSET_MASK + 0x1211)
+#define HDMITX_DWC_FC_DBGAUD2CH5                (DWC_OFFSET_MASK + 0x1212)
+#define HDMITX_DWC_FC_DBGAUD0CH6                (DWC_OFFSET_MASK + 0x1213)
+#define HDMITX_DWC_FC_DBGAUD1CH6                (DWC_OFFSET_MASK + 0x1214)
+#define HDMITX_DWC_FC_DBGAUD2CH6                (DWC_OFFSET_MASK + 0x1215)
+#define HDMITX_DWC_FC_DBGAUD0CH7                (DWC_OFFSET_MASK + 0x1216)
+#define HDMITX_DWC_FC_DBGAUD1CH7                (DWC_OFFSET_MASK + 0x1217)
+#define HDMITX_DWC_FC_DBGAUD2CH7                (DWC_OFFSET_MASK + 0x1218)
+#define HDMITX_DWC_FC_DBGTMDS0                  (DWC_OFFSET_MASK + 0x1219)
+#define HDMITX_DWC_FC_DBGTMDS1                  (DWC_OFFSET_MASK + 0x121A)
+#define HDMITX_DWC_FC_DBGTMDS2                  (DWC_OFFSET_MASK + 0x121B)
+
+/* HDMI Source PHY Registers */
+#define HDMITX_DWC_PHY_CONF0                    (DWC_OFFSET_MASK + 0x3000)
+#define HDMITX_DWC_PHY_TST0                     (DWC_OFFSET_MASK + 0x3001)
+#define HDMITX_DWC_PHY_TST1                     (DWC_OFFSET_MASK + 0x3002)
+#define HDMITX_DWC_PHY_TST2                     (DWC_OFFSET_MASK + 0x3003)
+#define HDMITX_DWC_PHY_STAT0                    (DWC_OFFSET_MASK + 0x3004)
+#define HDMITX_DWC_PHY_INT0                     (DWC_OFFSET_MASK + 0x3005)
+#define HDMITX_DWC_PHY_MASK0                    (DWC_OFFSET_MASK + 0x3006)
+#define HDMITX_DWC_PHY_POL0                     (DWC_OFFSET_MASK + 0x3007)
+
+/* I2C Master PHY Registers */
+#define HDMITX_DWC_I2CM_PHY_SLAVE               (DWC_OFFSET_MASK + 0x3020)
+#define HDMITX_DWC_I2CM_PHY_ADDRESS             (DWC_OFFSET_MASK + 0x3021)
+#define HDMITX_DWC_I2CM_PHY_DATAO_1             (DWC_OFFSET_MASK + 0x3022)
+#define HDMITX_DWC_I2CM_PHY_DATAO_0             (DWC_OFFSET_MASK + 0x3023)
+#define HDMITX_DWC_I2CM_PHY_DATAI_1             (DWC_OFFSET_MASK + 0x3024)
+#define HDMITX_DWC_I2CM_PHY_DATAI_0             (DWC_OFFSET_MASK + 0x3025)
+#define HDMITX_DWC_I2CM_PHY_OPERATION           (DWC_OFFSET_MASK + 0x3026)
+#define HDMITX_DWC_I2CM_PHY_INT                 (DWC_OFFSET_MASK + 0x3027)
+#define HDMITX_DWC_I2CM_PHY_CTLINT              (DWC_OFFSET_MASK + 0x3028)
+#define HDMITX_DWC_I2CM_PHY_DIV                 (DWC_OFFSET_MASK + 0x3029)
+#define HDMITX_DWC_I2CM_PHY_SOFTRSTZ            (DWC_OFFSET_MASK + 0x302A)
+#define HDMITX_DWC_I2CM_PHY_SS_SCL_HCNT_1       (DWC_OFFSET_MASK + 0x302B)
+#define HDMITX_DWC_I2CM_PHY_SS_SCL_HCNT_0       (DWC_OFFSET_MASK + 0x302C)
+#define HDMITX_DWC_I2CM_PHY_SS_SCL_LCNT_1       (DWC_OFFSET_MASK + 0x302D)
+#define HDMITX_DWC_I2CM_PHY_SS_SCL_LCNT_0       (DWC_OFFSET_MASK + 0x302E)
+#define HDMITX_DWC_I2CM_PHY_FS_SCL_HCNT_1       (DWC_OFFSET_MASK + 0x302F)
+#define HDMITX_DWC_I2CM_PHY_FS_SCL_HCNT_0       (DWC_OFFSET_MASK + 0x3030)
+#define HDMITX_DWC_I2CM_PHY_FS_SCL_LCNT_1       (DWC_OFFSET_MASK + 0x3031)
+#define HDMITX_DWC_I2CM_PHY_FS_SCL_LCNT_0       (DWC_OFFSET_MASK + 0x3032)
+#define HDMITX_DWC_I2CM_PHY_SDA_HOLD            (DWC_OFFSET_MASK + 0x3033)
+
+/* Audio Sampler Registers */
+
+  /* [  7] sw_audio_fifo_rst */
+  /* [  5] 0=select SPDIF; 1=select I2S. */
+  /* [3:0] i2s_in_en: enable it later in test.c */
+#define HDMITX_DWC_AUD_CONF0                    (DWC_OFFSET_MASK + 0x3100)
+/* [4:0] i2s_width */
+/* [7:5] i2s_mode: 0=standard I2S mode */
+#define HDMITX_DWC_AUD_CONF1                    (DWC_OFFSET_MASK + 0x3101)
+/* [  3] fifo_empty_mask: 0=enable int; 1=mask int. */
+/* [  2] fifo_full_mask: 0=enable int; 1=mask int. */
+#define HDMITX_DWC_AUD_INT                      (DWC_OFFSET_MASK + 0x3102)
+  /* [  1] NLPCM */
+#define HDMITX_DWC_AUD_CONF2                    (DWC_OFFSET_MASK + 0x3103)
+
+/* [  4] fifo_overrun_mask: 0=enable int; 1=mask int.
+ * Enable it later when audio starts.
+ */
+#define HDMITX_DWC_AUD_INT1                     (DWC_OFFSET_MASK + 0x3104)
+
+#define HDMITX_DWC_AUD_N1                       (DWC_OFFSET_MASK + 0x3200)
+#define HDMITX_DWC_AUD_N2                       (DWC_OFFSET_MASK + 0x3201)
+#define HDMITX_DWC_AUD_N3                       (DWC_OFFSET_MASK + 0x3202)
+#define HDMITX_DWC_AUD_CTS1                     (DWC_OFFSET_MASK + 0x3203)
+#define HDMITX_DWC_AUD_CTS2                     (DWC_OFFSET_MASK + 0x3204)
+#define HDMITX_DWC_AUD_CTS3                     (DWC_OFFSET_MASK + 0x3205)
+#define HDMITX_DWC_AUD_INPUTCLKFS               (DWC_OFFSET_MASK + 0x3206)
+/* [  7] sw_audio_fifo_rst */
+#define HDMITX_DWC_AUD_SPDIF0                   (DWC_OFFSET_MASK + 0x3300)
+/* [4:0] spdif_width */
+/* [  7] setnlpcm */
+#define HDMITX_DWC_AUD_SPDIF1                   (DWC_OFFSET_MASK + 0x3301)
+/* [  3] SPDIF fifo_empty_mask: 0=enable int; 1=mask int. */
+/* [  2] SPDIF fifo_full_mask: 0=enable int; 1=mask int. */
+#define HDMITX_DWC_AUD_SPDIFINT                 (DWC_OFFSET_MASK + 0x3302)
+/* [  4] SPDIF fifo_overrun_mask: 0=enable int; 1=mask int. */
+#define HDMITX_DWC_AUD_SPDIFINT1                (DWC_OFFSET_MASK + 0x3303)
+
+/* Generic Parallel Audio Interface Registers   (DWC_OFFSET_MASK + 0x3500) */
+/* Audio DMA Registers                          (DWC_OFFSET_MASK + 0x3600) */
+
+/* Main Controller Registers */
+/* [  6] hdcpclk_disable */
+/* [  5] cecclk_disable */
+/* [  4] cscclk_disable */
+/* [  3] audclk_disable */
+/* [  2] prepclk_disable */
+/* [  1] tmdsclk_disable */
+/* [  0] pixelclk_disable */
+#define HDMITX_DWC_MC_CLKDIS                    (DWC_OFFSET_MASK + 0x4001)
+/*
+ * [  7] gpaswrst_req: 0=generate reset pulse; 1=no reset.
+ * [  6] cecswrst_req: 0=generate reset pulse; 1=no reset.
+ * [  4] spdifswrst_req: 0=generate reset pulse; 1=no reset.
+ * [  3] i2sswrst_req: 0=generate reset pulse; 1=no reset.
+ * [  2] prepswrst_req: 0=generate reset pulse; 1=no reset.
+ * [  1] tmdsswrst_req: 0=generate reset pulse; 1=no reset.
+ * [  0] pixelswrst_req: 0=generate reset pulse; 1=no reset.
+ */
+#define HDMITX_DWC_MC_SWRSTZREQ                 (DWC_OFFSET_MASK + 0x4002)
+#define HDMITX_DWC_MC_OPCTRL                    (DWC_OFFSET_MASK + 0x4003)
+/* [  0] CSC enable */
+#define HDMITX_DWC_MC_FLOWCTRL                  (DWC_OFFSET_MASK + 0x4004)
+#define HDMITX_DWC_MC_PHYRSTZ                   (DWC_OFFSET_MASK + 0x4005)
+#define HDMITX_DWC_MC_LOCKONCLOCK               (DWC_OFFSET_MASK + 0x4006)
+
+/* Color Space Converter Registers */
+/* [  7] csc_limit */
+#define HDMITX_DWC_CSC_CFG                      (DWC_OFFSET_MASK + 0x4100)
+#define HDMITX_DWC_CSC_SCALE                    (DWC_OFFSET_MASK + 0x4101)
+#define HDMITX_DWC_CSC_COEF_A1_MSB              (DWC_OFFSET_MASK + 0x4102)
+#define HDMITX_DWC_CSC_COEF_A1_LSB              (DWC_OFFSET_MASK + 0x4103)
+#define HDMITX_DWC_CSC_COEF_A2_MSB              (DWC_OFFSET_MASK + 0x4104)
+#define HDMITX_DWC_CSC_COEF_A2_LSB              (DWC_OFFSET_MASK + 0x4105)
+#define HDMITX_DWC_CSC_COEF_A3_MSB              (DWC_OFFSET_MASK + 0x4106)
+#define HDMITX_DWC_CSC_COEF_A3_LSB              (DWC_OFFSET_MASK + 0x4107)
+#define HDMITX_DWC_CSC_COEF_A4_MSB              (DWC_OFFSET_MASK + 0x4108)
+#define HDMITX_DWC_CSC_COEF_A4_LSB              (DWC_OFFSET_MASK + 0x4109)
+#define HDMITX_DWC_CSC_COEF_B1_MSB              (DWC_OFFSET_MASK + 0x410A)
+#define HDMITX_DWC_CSC_COEF_B1_LSB              (DWC_OFFSET_MASK + 0x410B)
+#define HDMITX_DWC_CSC_COEF_B2_MSB              (DWC_OFFSET_MASK + 0x410C)
+#define HDMITX_DWC_CSC_COEF_B2_LSB              (DWC_OFFSET_MASK + 0x410D)
+#define HDMITX_DWC_CSC_COEF_B3_MSB              (DWC_OFFSET_MASK + 0x410E)
+#define HDMITX_DWC_CSC_COEF_B3_LSB              (DWC_OFFSET_MASK + 0x410F)
+#define HDMITX_DWC_CSC_COEF_B4_MSB              (DWC_OFFSET_MASK + 0x4110)
+#define HDMITX_DWC_CSC_COEF_B4_LSB              (DWC_OFFSET_MASK + 0x4111)
+#define HDMITX_DWC_CSC_COEF_C1_MSB              (DWC_OFFSET_MASK + 0x4112)
+#define HDMITX_DWC_CSC_COEF_C1_LSB              (DWC_OFFSET_MASK + 0x4113)
+#define HDMITX_DWC_CSC_COEF_C2_MSB              (DWC_OFFSET_MASK + 0x4114)
+#define HDMITX_DWC_CSC_COEF_C2_LSB              (DWC_OFFSET_MASK + 0x4115)
+#define HDMITX_DWC_CSC_COEF_C3_MSB              (DWC_OFFSET_MASK + 0x4116)
+#define HDMITX_DWC_CSC_COEF_C3_LSB              (DWC_OFFSET_MASK + 0x4117)
+#define HDMITX_DWC_CSC_COEF_C4_MSB              (DWC_OFFSET_MASK + 0x4118)
+#define HDMITX_DWC_CSC_COEF_C4_LSB              (DWC_OFFSET_MASK + 0x4119)
+#define HDMITX_DWC_CSC_LIMIT_UP_MSB             (DWC_OFFSET_MASK + 0x411A)
+#define HDMITX_DWC_CSC_LIMIT_UP_LSB             (DWC_OFFSET_MASK + 0x411B)
+#define HDMITX_DWC_CSC_LIMIT_DN_MSB             (DWC_OFFSET_MASK + 0x411C)
+#define HDMITX_DWC_CSC_LIMIT_DN_LSB             (DWC_OFFSET_MASK + 0x411D)
+
+/* HDCP Encryption Engine Registers */
+#define HDMITX_DWC_A_HDCPCFG0                   (DWC_SEC_OFFSET_MASK + 0x5000)
+/* [  4] hdcp_lock */
+/* [  3] dissha1check */
+/* [  2] ph2upshiftenc */
+/* [  1] encryptiondisable */
+/* [  0] swresetn. Write 0 to activate, self-clear to 1. */
+#define HDMITX_DWC_A_HDCPCFG1                   (DWC_SEC_OFFSET_MASK + 0x5001)
+#define HDMITX_DWC_A_HDCPOBS0                   (DWC_OFFSET_MASK + 0x5002)
+#define HDMITX_DWC_A_HDCPOBS1                   (DWC_OFFSET_MASK + 0x5003)
+#define HDMITX_DWC_A_HDCPOBS2                   (DWC_OFFSET_MASK + 0x5004)
+#define HDMITX_DWC_A_HDCPOBS3                   (DWC_OFFSET_MASK + 0x5005)
+#define HDMITX_DWC_A_APIINTCLR                  (DWC_OFFSET_MASK + 0x5006)
+#define HDMITX_DWC_A_APIINTSTAT                 (DWC_OFFSET_MASK + 0x5007)
+/* [  7] hdcp_engaged_int_mask */
+/* [  6] hdcp_failed_int_mask */
+/* [  4] i2c_nack_int_mask */
+/* [  3] lost_arbitration_int_mask */
+/* [  2] keepout_error_int_mask */
+/* [  1] ksv_sha1_calc_int_mask */
+/* [  0] ksv_access_int_mask */
+#define HDMITX_DWC_A_APIINTMSK                  (DWC_OFFSET_MASK + 0x5008)
+/* [6:5] unencryptconf */
+/* [  4] dataenpol */
+/* [  3] vsyncpol */
+/* [  1] hsyncpol */
+#define HDMITX_DWC_A_VIDPOLCFG                  (DWC_OFFSET_MASK + 0x5009)
+#define HDMITX_DWC_A_OESSWCFG                   (DWC_OFFSET_MASK + 0x500A)
+#define HDMITX_DWC_A_COREVERLSB                 (DWC_OFFSET_MASK + 0x5014)
+#define HDMITX_DWC_A_COREVERMSB                 (DWC_OFFSET_MASK + 0x5015)
+/* [  3] sha1_fail */
+/* [  2] ksv_ctrl_update */
+/* [  1] Rsvd for read-only ksv_mem_access */
+/* [  0] ksv_mem_request */
+#define HDMITX_DWC_A_KSVMEMCTRL                 (DWC_OFFSET_MASK + 0x5016)
+
+#define HDMITX_DWC_HDCP_BSTATUS_0               (DWC_OFFSET_MASK + 0x5020)
+#define HDMITX_DWC_HDCP_BSTATUS_1               (DWC_OFFSET_MASK + 0x5021)
+#define HDMITX_DWC_HDCP_M0_0                    (DWC_OFFSET_MASK + 0x5022)
+#define HDMITX_DWC_HDCP_M0_1                    (DWC_OFFSET_MASK + 0x5023)
+#define HDMITX_DWC_HDCP_M0_2                    (DWC_OFFSET_MASK + 0x5024)
+#define HDMITX_DWC_HDCP_M0_3                    (DWC_OFFSET_MASK + 0x5025)
+#define HDMITX_DWC_HDCP_M0_4                    (DWC_OFFSET_MASK + 0x5026)
+#define HDMITX_DWC_HDCP_M0_5                    (DWC_OFFSET_MASK + 0x5027)
+#define HDMITX_DWC_HDCP_M0_6                    (DWC_OFFSET_MASK + 0x5028)
+#define HDMITX_DWC_HDCP_M0_7                    (DWC_OFFSET_MASK + 0x5029)
+#define HDMITX_DWC_HDCP_KSV                     (DWC_OFFSET_MASK + 0x502A)
+#define HDMITX_DWC_HDCP_VH                      (DWC_OFFSET_MASK + 0x52A5)
+#define HDMITX_DWC_HDCP_REVOC_SIZE_0            (DWC_OFFSET_MASK + 0x52B9)
+#define HDMITX_DWC_HDCP_REVOC_SIZE_1            (DWC_OFFSET_MASK + 0x52BA)
+#define HDMITX_DWC_HDCP_REVOC_LIST              (DWC_OFFSET_MASK + 0x52BB)
+#define HDMITX_DWC_HDCP_REVOC_LIST_END          (DWC_OFFSET_MASK + 0x667E)
+
+/* HDCP BKSV Registers */
+#define HDMITX_DWC_HDCPREG_BKSV0                (DWC_OFFSET_MASK + 0x7800)
+#define HDMITX_DWC_HDCPREG_BKSV1                (DWC_OFFSET_MASK + 0x7801)
+#define HDMITX_DWC_HDCPREG_BKSV2                (DWC_OFFSET_MASK + 0x7802)
+#define HDMITX_DWC_HDCPREG_BKSV3                (DWC_OFFSET_MASK + 0x7803)
+#define HDMITX_DWC_HDCPREG_BKSV4                (DWC_OFFSET_MASK + 0x7804)
+
+/* HDCP AN Registers */
+#define HDMITX_DWC_HDCPREG_ANCONF               (DWC_OFFSET_MASK + 0x7805)
+#define HDMITX_DWC_HDCPREG_AN0                  (DWC_OFFSET_MASK + 0x7806)
+#define HDMITX_DWC_HDCPREG_AN1                  (DWC_OFFSET_MASK + 0x7807)
+#define HDMITX_DWC_HDCPREG_AN2                  (DWC_OFFSET_MASK + 0x7808)
+#define HDMITX_DWC_HDCPREG_AN3                  (DWC_OFFSET_MASK + 0x7809)
+#define HDMITX_DWC_HDCPREG_AN4                  (DWC_OFFSET_MASK + 0x780A)
+#define HDMITX_DWC_HDCPREG_AN5                  (DWC_OFFSET_MASK + 0x780B)
+#define HDMITX_DWC_HDCPREG_AN6                  (DWC_OFFSET_MASK + 0x780C)
+#define HDMITX_DWC_HDCPREG_AN7                  (DWC_OFFSET_MASK + 0x780D)
+#define HDMITX_DWC_HDCPREG_RMLCTL               (DWC_OFFSET_MASK + 0x780E)
+
+/* Encrypted DPK Embedded Storage Registers */
+#define HDMITX_DWC_HDCPREG_RMLSTS               (DWC_OFFSET_MASK + 0x780F)
+#define HDMITX_DWC_HDCPREG_SEED0                (DWC_SEC_OFFSET_MASK + 0x7810)
+#define HDMITX_DWC_HDCPREG_SEED1                (DWC_SEC_OFFSET_MASK + 0x7811)
+#define HDMITX_DWC_HDCPREG_DPK0                 (DWC_SEC_OFFSET_MASK + 0x7812)
+#define HDMITX_DWC_HDCPREG_DPK1                 (DWC_SEC_OFFSET_MASK + 0x7813)
+#define HDMITX_DWC_HDCPREG_DPK2                 (DWC_SEC_OFFSET_MASK + 0x7814)
+#define HDMITX_DWC_HDCPREG_DPK3                 (DWC_SEC_OFFSET_MASK + 0x7815)
+#define HDMITX_DWC_HDCPREG_DPK4                 (DWC_SEC_OFFSET_MASK + 0x7816)
+#define HDMITX_DWC_HDCPREG_DPK5                 (DWC_SEC_OFFSET_MASK + 0x7817)
+#define HDMITX_DWC_HDCPREG_DPK6                 (DWC_SEC_OFFSET_MASK + 0x7818)
+
+/* HDCP22 Registers */
+#define HDMITX_DWC_HDCP22REG_ID                 (DWC_OFFSET_MASK + 0x7900)
+#define HDMITX_DWC_HDCP22REG_CTRL               (DWC_SEC_OFFSET_MASK + 0x7904)
+#define HDMITX_DWC_HDCP22REG_CTRL1              (DWC_OFFSET_MASK + 0x7905)
+#define HDMITX_DWC_HDCP22REG_STS                (DWC_OFFSET_MASK + 0x7908)
+#define HDMITX_DWC_HDCP22REG_MASK               (DWC_OFFSET_MASK + 0x790C)
+#define HDMITX_DWC_HDCP22REG_STAT               (DWC_OFFSET_MASK + 0x790D)
+#define HDMITX_DWC_HDCP22REG_MUTE               (DWC_OFFSET_MASK + 0x790E)
+
+
+/* ********** CEC related ********** */
+
+/* CEC 2.0 Engine Registers */
+#define HDMITX_DWC_CEC_CTRL                     (DWC_OFFSET_MASK + 0x7D00)
+#define HDMITX_DWC_CEC_INTR_MASK                (DWC_OFFSET_MASK + 0x7D02)
+#define HDMITX_DWC_CEC_LADD_LOW                 (DWC_OFFSET_MASK + 0x7D05)
+#define HDMITX_DWC_CEC_LADD_HIGH                (DWC_OFFSET_MASK + 0x7D06)
+#define HDMITX_DWC_CEC_TX_CNT                   (DWC_OFFSET_MASK + 0x7D07)
+#define HDMITX_DWC_CEC_RX_CNT                   (DWC_OFFSET_MASK + 0x7D08)
+#define HDMITX_DWC_CEC_TX_DATA00                (DWC_OFFSET_MASK + 0x7D10)
+#define HDMITX_DWC_CEC_TX_DATA01                (DWC_OFFSET_MASK + 0x7D11)
+#define HDMITX_DWC_CEC_TX_DATA02                (DWC_OFFSET_MASK + 0x7D12)
+#define HDMITX_DWC_CEC_TX_DATA03                (DWC_OFFSET_MASK + 0x7D13)
+#define HDMITX_DWC_CEC_TX_DATA04                (DWC_OFFSET_MASK + 0x7D14)
+#define HDMITX_DWC_CEC_TX_DATA05                (DWC_OFFSET_MASK + 0x7D15)
+#define HDMITX_DWC_CEC_TX_DATA06                (DWC_OFFSET_MASK + 0x7D16)
+#define HDMITX_DWC_CEC_TX_DATA07                (DWC_OFFSET_MASK + 0x7D17)
+#define HDMITX_DWC_CEC_TX_DATA08                (DWC_OFFSET_MASK + 0x7D18)
+#define HDMITX_DWC_CEC_TX_DATA09                (DWC_OFFSET_MASK + 0x7D19)
+#define HDMITX_DWC_CEC_TX_DATA10                (DWC_OFFSET_MASK + 0x7D1A)
+#define HDMITX_DWC_CEC_TX_DATA11                (DWC_OFFSET_MASK + 0x7D1B)
+#define HDMITX_DWC_CEC_TX_DATA12                (DWC_OFFSET_MASK + 0x7D1C)
+#define HDMITX_DWC_CEC_TX_DATA13                (DWC_OFFSET_MASK + 0x7D1D)
+#define HDMITX_DWC_CEC_TX_DATA14                (DWC_OFFSET_MASK + 0x7D1E)
+#define HDMITX_DWC_CEC_TX_DATA15                (DWC_OFFSET_MASK + 0x7D1F)
+#define HDMITX_DWC_CEC_RX_DATA00                (DWC_OFFSET_MASK + 0x7D20)
+#define HDMITX_DWC_CEC_RX_DATA01                (DWC_OFFSET_MASK + 0x7D21)
+#define HDMITX_DWC_CEC_RX_DATA02                (DWC_OFFSET_MASK + 0x7D22)
+#define HDMITX_DWC_CEC_RX_DATA03                (DWC_OFFSET_MASK + 0x7D23)
+#define HDMITX_DWC_CEC_RX_DATA04                (DWC_OFFSET_MASK + 0x7D24)
+#define HDMITX_DWC_CEC_RX_DATA05                (DWC_OFFSET_MASK + 0x7D25)
+#define HDMITX_DWC_CEC_RX_DATA06                (DWC_OFFSET_MASK + 0x7D26)
+#define HDMITX_DWC_CEC_RX_DATA07                (DWC_OFFSET_MASK + 0x7D27)
+#define HDMITX_DWC_CEC_RX_DATA08                (DWC_OFFSET_MASK + 0x7D28)
+#define HDMITX_DWC_CEC_RX_DATA09                (DWC_OFFSET_MASK + 0x7D29)
+#define HDMITX_DWC_CEC_RX_DATA10                (DWC_OFFSET_MASK + 0x7D2A)
+#define HDMITX_DWC_CEC_RX_DATA11                (DWC_OFFSET_MASK + 0x7D2B)
+#define HDMITX_DWC_CEC_RX_DATA12                (DWC_OFFSET_MASK + 0x7D2C)
+#define HDMITX_DWC_CEC_RX_DATA13                (DWC_OFFSET_MASK + 0x7D2D)
+#define HDMITX_DWC_CEC_RX_DATA14                (DWC_OFFSET_MASK + 0x7D2E)
+#define HDMITX_DWC_CEC_RX_DATA15                (DWC_OFFSET_MASK + 0x7D2F)
+#define HDMITX_DWC_CEC_LOCK_BUF                 (DWC_OFFSET_MASK + 0x7D30)
+#define HDMITX_DWC_CEC_WAKEUPCTRL               (DWC_OFFSET_MASK + 0x7D31)
+
+/* I2C Master Registers(E-DDC/SCDC) */
+#define HDMITX_DWC_I2CM_SLAVE                   (DWC_OFFSET_MASK + 0x7E00)
+#define HDMITX_DWC_I2CM_ADDRESS                 (DWC_OFFSET_MASK + 0x7E01)
+#define HDMITX_DWC_I2CM_DATAO                   (DWC_OFFSET_MASK + 0x7E02)
+#define HDMITX_DWC_I2CM_DATAI                   (DWC_OFFSET_MASK + 0x7E03)
+#define HDMITX_DWC_I2CM_OPERATION               (DWC_OFFSET_MASK + 0x7E04)
+/* [  2] done_mask */
+/* [  6] read_req_mask */
+#define HDMITX_DWC_I2CM_INT                     (DWC_OFFSET_MASK + 0x7E05)
+/* [  6] nack_mask */
+/* [  2] arbitration_error_mask */
+#define HDMITX_DWC_I2CM_CTLINT                  (DWC_OFFSET_MASK + 0x7E06)
+/* [  3] i2c_fast_mode: 0=standard mode; 1=fast mode. */
+#define HDMITX_DWC_I2CM_DIV                     (DWC_OFFSET_MASK + 0x7E07)
+#define HDMITX_DWC_I2CM_SEGADDR                 (DWC_OFFSET_MASK + 0x7E08)
+#define HDMITX_DWC_I2CM_SOFTRSTZ                (DWC_OFFSET_MASK + 0x7E09)
+#define HDMITX_DWC_I2CM_SEGPTR                  (DWC_OFFSET_MASK + 0x7E0A)
+/* I2CM_SS_SCL_HCNT = RndUp(min_ss_scl_htime*Freq(sfrclkInMHz)/1000) */
+/* I2CM_SS_SCL_LCNT = RndUp(min_ss_scl_ltime*Freq(sfrclkInMHz)/1000) */
+/* I2CM_FS_SCL_HCNT = RndUp(min_fs_scl_htime*Freq(sfrclkInMHz)/1000) */
+/* I2CM_FS_SCL_LCNT = RndUp(min_fs_scl_ltime*Freq(sfrclkInMHz)/1000) */
+/* Where Freq(sfrclkInMHz)=24; */
+#define HDMITX_DWC_I2CM_SS_SCL_HCNT_1           (DWC_OFFSET_MASK + 0x7E0B)
+#define HDMITX_DWC_I2CM_SS_SCL_HCNT_0           (DWC_OFFSET_MASK + 0x7E0C)
+#define HDMITX_DWC_I2CM_SS_SCL_LCNT_1           (DWC_OFFSET_MASK + 0x7E0D)
+#define HDMITX_DWC_I2CM_SS_SCL_LCNT_0           (DWC_OFFSET_MASK + 0x7E0E)
+#define HDMITX_DWC_I2CM_FS_SCL_HCNT_1           (DWC_OFFSET_MASK + 0x7E0F)
+#define HDMITX_DWC_I2CM_FS_SCL_HCNT_0           (DWC_OFFSET_MASK + 0x7E10)
+#define HDMITX_DWC_I2CM_FS_SCL_LCNT_1           (DWC_OFFSET_MASK + 0x7E11)
+#define HDMITX_DWC_I2CM_FS_SCL_LCNT_0           (DWC_OFFSET_MASK + 0x7E12)
+#define HDMITX_DWC_I2CM_SDA_HOLD                (DWC_OFFSET_MASK + 0x7E13)
+/* [  5] updt_rd_vsyncpoll_en */
+/* [  4] read_request_en */
+/* [  0] read_update */
+#define HDMITX_DWC_I2CM_SCDC_UPDATE             (DWC_OFFSET_MASK + 0x7E14)
+#define HDMITX_DWC_I2CM_READ_BUFF0              (DWC_OFFSET_MASK + 0x7E20)
+#define HDMITX_DWC_I2CM_READ_BUFF1              (DWC_OFFSET_MASK + 0x7E21)
+#define HDMITX_DWC_I2CM_READ_BUFF2              (DWC_OFFSET_MASK + 0x7E22)
+#define HDMITX_DWC_I2CM_READ_BUFF3              (DWC_OFFSET_MASK + 0x7E23)
+#define HDMITX_DWC_I2CM_READ_BUFF4              (DWC_OFFSET_MASK + 0x7E24)
+#define HDMITX_DWC_I2CM_READ_BUFF5              (DWC_OFFSET_MASK + 0x7E25)
+#define HDMITX_DWC_I2CM_READ_BUFF6              (DWC_OFFSET_MASK + 0x7E26)
+#define HDMITX_DWC_I2CM_READ_BUFF7              (DWC_OFFSET_MASK + 0x7E27)
+#define HDMITX_DWC_I2CM_SCDC_UPDATE0            (DWC_OFFSET_MASK + 0x7E30)
+#define HDMITX_DWC_I2CM_SCDC_UPDATE1            (DWC_OFFSET_MASK + 0x7E31)
+#endif
diff --git a/drivers/amlogic/drm/meson_lcd.c b/drivers/amlogic/drm/meson_lcd.c
new file mode 100644 (file)
index 0000000..89f6556
--- /dev/null
@@ -0,0 +1,701 @@
+/*
+ * drivers/amlogic/drm/meson_lcd.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_modeset_helper.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_mipi_dsi.h>
+#include <video/display_timing.h>
+#include <linux/component.h>
+#include <linux/amlogic/media/vout/lcd/lcd_vout.h>
+#include <linux/amlogic/media/vout/lcd/lcd_notify.h>
+
+#include "meson_lcd.h"
+
+struct am_drm_lcd_s {
+       struct drm_panel panel;
+       struct drm_connector connector;
+       struct drm_encoder encoder;
+       struct mipi_dsi_host dsi_host;
+       struct drm_device *drm;
+       struct aml_lcd_drv_s *lcd_drv;
+       struct drm_display_mode *mode;
+       struct display_timing *timing;
+};
+
+static struct am_drm_lcd_s *am_drm_lcd;
+
+static struct drm_display_mode am_lcd_mode = {
+       .name = "panel",
+       .status = 0,
+       .clock = 74250,
+       .hdisplay = 1280,
+       .hsync_start = 1390,
+       .hsync_end = 1430,
+       .htotal = 1650,
+       .hskew = 0,
+       .vdisplay = 720,
+       .vsync_start = 725,
+       .vsync_end = 730,
+       .vtotal = 750,
+       .vscan = 0,
+       .vrefresh = 60,
+};
+
+static struct display_timing am_lcd_timing = {
+       .pixelclock = { 55000000, 65000000, 75000000 },
+       .hactive = { 1024, 1024, 1024 },
+       .hfront_porch = { 40, 40, 40 },
+       .hback_porch = { 220, 220, 220 },
+       .hsync_len = { 20, 60, 100 },
+       .vactive = { 768, 768, 768 },
+       .vfront_porch = { 7, 7, 7 },
+       .vback_porch = { 21, 21, 21 },
+       .vsync_len = { 10, 10, 10 },
+       .flags = DISPLAY_FLAGS_DE_HIGH,
+};
+
+/* ***************************************************************** */
+/*     drm driver function                                           */
+/* ***************************************************************** */
+#if 0
+static inline struct am_drm_lcd_s *host_to_lcd(struct mipi_dsi_host *host)
+{
+       return container_of(host, struct am_drm_lcd_s, dsi_host);
+}
+#endif
+
+static inline struct am_drm_lcd_s *con_to_lcd(struct drm_connector *con)
+{
+       return container_of(con, struct am_drm_lcd_s, connector);
+}
+
+static inline struct am_drm_lcd_s *encoder_to_lcd(struct drm_encoder *encoder)
+{
+       return container_of(encoder, struct am_drm_lcd_s, encoder);
+}
+
+static inline struct am_drm_lcd_s *panel_to_lcd(struct drm_panel *panel)
+{
+       return container_of(panel, struct am_drm_lcd_s, panel);
+}
+
+static int am_lcd_connector_get_modes(struct drm_connector *connector)
+{
+       struct drm_display_mode *mode;
+       struct am_drm_lcd_s *lcd;
+       int count = 0;
+
+       lcd = con_to_lcd(connector);
+
+       pr_info("***************************************************\n");
+       pr_info("am_drm_lcd: %s: lcd mode [%s] display size: %d x %d\n",
+               __func__, lcd->mode->name,
+               lcd->mode->hdisplay, lcd->mode->vdisplay);
+
+       mode = drm_mode_duplicate(connector->dev, lcd->mode);
+       pr_info("am_drm_lcd: %s: drm mode [%s] display size: %d x %d\n",
+               __func__, mode->name, mode->hdisplay, mode->vdisplay);
+       pr_info("am_drm_lcd: %s: lcd config size: %d x %d\n",
+               __func__, lcd->lcd_drv->lcd_config->lcd_basic.h_active,
+               lcd->lcd_drv->lcd_config->lcd_basic.v_active);
+
+       drm_mode_probed_add(connector, mode);
+       count = 1;
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+       pr_info("***************************************************\n");
+
+       return count;
+}
+
+enum drm_mode_status am_lcd_connector_mode_valid(
+               struct drm_connector *connector,
+               struct drm_display_mode *mode)
+{
+       struct am_drm_lcd_s *lcd;
+
+       lcd = con_to_lcd(connector);
+       if (!lcd)
+               return MODE_ERROR;
+       if (!lcd->lcd_drv)
+               return MODE_ERROR;
+
+       pr_info("am_drm_lcd: %s: mode [%s] display size: %d x %d\n",
+               __func__, mode->name, mode->hdisplay, mode->vdisplay);
+       pr_info("am_drm_lcd: %s: lcd config size: %d x %d\n",
+               __func__, lcd->lcd_drv->lcd_config->lcd_basic.h_active,
+               lcd->lcd_drv->lcd_config->lcd_basic.v_active);
+
+       if (mode->hdisplay != lcd->lcd_drv->lcd_config->lcd_basic.h_active)
+               return MODE_BAD_WIDTH;
+       if (mode->vdisplay != lcd->lcd_drv->lcd_config->lcd_basic.v_active)
+               return MODE_BAD_WIDTH;
+
+       pr_info("am_drm_lcd: %s %d: check mode OK\n", __func__, __LINE__);
+
+       return MODE_OK;
+}
+
+
+static const struct drm_connector_helper_funcs am_lcd_connector_helper_funcs = {
+       .get_modes = am_lcd_connector_get_modes,
+       .mode_valid = am_lcd_connector_mode_valid,
+       //.best_encoder
+       //.atomic_best_encoder
+};
+
+static enum drm_connector_status am_lcd_connector_detect(
+               struct drm_connector *connector, bool force)
+{
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+       return connector_status_connected;
+}
+
+#if 0
+static const struct drm_connector_funcs am_lcd_connector_funcs = {
+       .dpms                   = drm_atomic_helper_connector_dpms,
+       .detect                 = am_lcd_connector_detect,
+       .fill_modes             = drm_helper_probe_single_connector_modes,
+       .destroy                = drm_connector_cleanup,
+       .reset                  = drm_atomic_helper_connector_reset,
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+       .atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
+};
+#else
+
+static int am_lcd_connector_dpms(struct drm_connector *connector, int mode)
+{
+       int ret = 0;
+
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+       ret = drm_atomic_helper_connector_dpms(connector, mode);
+       return ret;
+}
+
+static int am_lcd_connector_fill_modes(struct drm_connector *connector,
+               uint32_t maxX, uint32_t maxY)
+{
+       int count = 0;
+
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+       count = drm_helper_probe_single_connector_modes(connector, maxX, maxY);
+       pr_info("am_drm_lcd: %s %d: count=%d\n", __func__, __LINE__, count);
+       return count;
+}
+
+static void am_lcd_connector_destroy(struct drm_connector *connector)
+{
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+       drm_connector_cleanup(connector);
+}
+
+static void am_lcd_connector_reset(struct drm_connector *connector)
+{
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+       drm_atomic_helper_connector_reset(connector);
+}
+
+static struct drm_connector_state *am_lcd_connector_duplicate_state(
+               struct drm_connector *connector)
+{
+       struct drm_connector_state *state;
+
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+       state = drm_atomic_helper_connector_duplicate_state(connector);
+       return state;
+}
+
+static void am_lcd_connector_destroy_state(struct drm_connector *connector,
+                                         struct drm_connector_state *state)
+{
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+       drm_atomic_helper_connector_destroy_state(connector, state);
+}
+
+static const struct drm_connector_funcs am_lcd_connector_funcs = {
+       .dpms                   = am_lcd_connector_dpms,
+       .detect                 = am_lcd_connector_detect,
+       .fill_modes             = am_lcd_connector_fill_modes,
+       .destroy                = am_lcd_connector_destroy,
+       .reset                  = am_lcd_connector_reset,
+       .atomic_duplicate_state = am_lcd_connector_duplicate_state,
+       .atomic_destroy_state   = am_lcd_connector_destroy_state,
+};
+#endif
+
+static void am_lcd_encoder_mode_set(struct drm_encoder *encoder,
+                                  struct drm_display_mode *mode,
+                                  struct drm_display_mode *adjusted_mode)
+{
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+}
+
+static void am_lcd_encoder_enable(struct drm_encoder *encoder)
+{
+       enum vmode_e vmode = get_current_vmode();
+       struct am_drm_lcd_s *lcd = encoder_to_lcd(encoder);
+
+       if (!lcd)
+               return;
+       if (!lcd->lcd_drv)
+               return;
+
+       if (vmode == VMODE_LCD)
+               DRM_INFO("enable\n");
+       else
+               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);
+       mutex_lock(&lcd->lcd_drv->power_mutex);
+       aml_lcd_notifier_call_chain(LCD_EVENT_PREPARE, NULL);
+       aml_lcd_notifier_call_chain(LCD_EVENT_ENABLE, NULL);
+
+       lcd->lcd_drv->lcd_config->retry_enable_cnt = 0;
+       while (lcd->lcd_drv->lcd_config->retry_enable_flag) {
+               if (lcd->lcd_drv->lcd_config->retry_enable_cnt++ >=
+                       LCD_ENABLE_RETRY_MAX)
+                       break;
+               pr_info("am_drm_lcd: retry enable...%d\n",
+                       lcd->lcd_drv->lcd_config->retry_enable_cnt);
+               aml_lcd_notifier_call_chain(LCD_EVENT_IF_POWER_OFF, NULL);
+               msleep(1000);
+               aml_lcd_notifier_call_chain(LCD_EVENT_IF_POWER_ON, NULL);
+       }
+       lcd->lcd_drv->lcd_config->retry_enable_cnt = 0;
+
+       mutex_unlock(&lcd->lcd_drv->power_mutex);
+       vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &vmode);
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+}
+
+static void am_lcd_encoder_disable(struct drm_encoder *encoder)
+{
+       struct am_drm_lcd_s *lcd = encoder_to_lcd(encoder);
+
+       if (!lcd)
+               return;
+       if (!lcd->lcd_drv)
+               return;
+
+       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);
+       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__);
+}
+
+static void am_lcd_encoder_commit(struct drm_encoder *encoder)
+{
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+}
+
+static int am_lcd_encoder_atomic_check(struct drm_encoder *encoder,
+                               struct drm_crtc_state *crtc_state,
+                               struct drm_connector_state *conn_state)
+{
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+       return 0;
+}
+
+static const struct drm_encoder_helper_funcs am_lcd_encoder_helper_funcs = {
+       .commit = am_lcd_encoder_commit,
+       .mode_set = am_lcd_encoder_mode_set,
+       .enable = am_lcd_encoder_enable,
+       .disable = am_lcd_encoder_disable,
+       .atomic_check = am_lcd_encoder_atomic_check,
+};
+
+static const struct drm_encoder_funcs am_lcd_encoder_funcs = {
+       .destroy        = drm_encoder_cleanup,
+};
+
+static int am_lcd_disable(struct drm_panel *panel)
+{
+       struct am_drm_lcd_s *lcd = panel_to_lcd(panel);
+
+       if (!lcd)
+               return -ENODEV;
+       if (!lcd->lcd_drv)
+               return -ENODEV;
+
+       mutex_lock(&lcd->lcd_drv->power_mutex);
+       aml_lcd_notifier_call_chain(LCD_EVENT_DISABLE, NULL);
+       mutex_unlock(&lcd->lcd_drv->power_mutex);
+
+       return 0;
+}
+
+static int am_lcd_unprepare(struct drm_panel *panel)
+{
+       struct am_drm_lcd_s *lcd = panel_to_lcd(panel);
+
+       if (!lcd)
+               return -ENODEV;
+       if (!lcd->lcd_drv)
+               return -ENODEV;
+
+       mutex_lock(&lcd->lcd_drv->power_mutex);
+       aml_lcd_notifier_call_chain(LCD_EVENT_UNPREPARE, NULL);
+       mutex_unlock(&lcd->lcd_drv->power_mutex);
+
+       return 0;
+}
+
+static int am_lcd_prepare(struct drm_panel *panel)
+{
+       struct am_drm_lcd_s *lcd = panel_to_lcd(panel);
+
+       if (!lcd)
+               return -ENODEV;
+       if (!lcd->lcd_drv)
+               return -ENODEV;
+
+       mutex_lock(&lcd->lcd_drv->power_mutex);
+       aml_lcd_notifier_call_chain(LCD_EVENT_PREPARE, NULL);
+       mutex_unlock(&lcd->lcd_drv->power_mutex);
+
+       return 0;
+}
+
+static int am_lcd_enable(struct drm_panel *panel)
+{
+       struct am_drm_lcd_s *lcd = panel_to_lcd(panel);
+
+       if (!lcd)
+               return -ENODEV;
+       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_ENABLE, NULL);
+       mutex_unlock(&lcd->lcd_drv->power_mutex);
+
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+       return 0;
+}
+
+static int am_lcd_get_modes(struct drm_panel *panel)
+{
+       struct am_drm_lcd_s *lcd = panel_to_lcd(panel);
+       struct drm_connector *connector = panel->connector;
+       struct drm_device *drm = panel->drm;
+       struct drm_display_mode *mode;
+       struct lcd_config_s *pconf;
+
+       if (!lcd->mode)
+               return 0;
+
+       mode = drm_mode_duplicate(drm, lcd->mode);
+       if (!mode)
+               return 0;
+
+       mode->type |= DRM_MODE_TYPE_DRIVER;
+       mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+       drm_mode_set_name(mode);
+
+       drm_mode_probed_add(connector, mode);
+
+       pconf = lcd->lcd_drv->lcd_config;
+       connector->display_info.bpc = pconf->lcd_basic.lcd_bits * 3;
+       connector->display_info.width_mm = pconf->lcd_basic.screen_width;
+       connector->display_info.height_mm = pconf->lcd_basic.screen_height;
+
+       connector->display_info.bus_flags = DRM_BUS_FLAG_DE_HIGH;
+
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+       return 1;
+}
+
+static int am_lcd_get_timings(struct drm_panel *panel,
+                                   unsigned int num_timings,
+                                   struct display_timing *timings)
+{
+       struct am_drm_lcd_s *lcd = panel_to_lcd(panel);
+
+       if (!lcd)
+               return 0;
+       if (!lcd->timing)
+               return 0;
+
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+       if (timings)
+               memcpy(&timings[0], lcd->timing, sizeof(struct display_timing));
+
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+       return 1;
+}
+
+static const struct drm_panel_funcs am_drm_lcd_funcs = {
+       .disable = am_lcd_disable,
+       .unprepare = am_lcd_unprepare,
+       .prepare = am_lcd_prepare,
+       .enable = am_lcd_enable,
+       .get_modes = am_lcd_get_modes,
+       .get_timings = am_lcd_get_timings,
+};
+
+static void am_drm_lcd_display_mode_timing_init(struct am_drm_lcd_s *lcd)
+{
+       struct lcd_config_s *pconf;
+       unsigned short tmp;
+
+       if (!lcd->lcd_drv) {
+               pr_info("invalid lcd driver\n");
+               return;
+       }
+
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+       pconf = lcd->lcd_drv->lcd_config;
+
+       lcd->mode = &am_lcd_mode;
+       lcd->timing = &am_lcd_timing;
+
+       lcd->mode->clock = pconf->lcd_timing.lcd_clk / 1000;
+       lcd->mode->hdisplay = pconf->lcd_basic.h_active;
+       tmp = pconf->lcd_basic.h_period - pconf->lcd_basic.h_active -
+                       pconf->lcd_timing.hsync_bp;
+       lcd->mode->hsync_start = pconf->lcd_basic.h_active + tmp -
+                       pconf->lcd_timing.hsync_width;
+       lcd->mode->hsync_end = pconf->lcd_basic.h_active + tmp;
+       lcd->mode->htotal = pconf->lcd_basic.h_period;
+       lcd->mode->vdisplay = pconf->lcd_basic.v_active;
+       tmp = pconf->lcd_basic.v_period - pconf->lcd_basic.v_active -
+                       pconf->lcd_timing.vsync_bp;
+       lcd->mode->vsync_start = pconf->lcd_basic.v_active + tmp -
+                       pconf->lcd_timing.vsync_width;
+       lcd->mode->vsync_end = pconf->lcd_basic.v_active + tmp;
+       lcd->mode->vtotal = pconf->lcd_basic.v_period;
+       lcd->mode->width_mm = pconf->lcd_basic.screen_width;
+       lcd->mode->height_mm = pconf->lcd_basic.screen_height;
+       lcd->mode->vrefresh = pconf->lcd_timing.sync_duration_num /
+                               pconf->lcd_timing.sync_duration_den;
+
+       lcd->timing->pixelclock.min = pconf->lcd_timing.lcd_clk;
+       lcd->timing->pixelclock.typ = pconf->lcd_timing.lcd_clk;
+       lcd->timing->pixelclock.max = pconf->lcd_timing.lcd_clk;
+       lcd->timing->hactive.min = pconf->lcd_basic.h_active;
+       lcd->timing->hactive.typ = pconf->lcd_basic.h_active;
+       lcd->timing->hactive.max = pconf->lcd_basic.h_active;
+       tmp = pconf->lcd_basic.h_period - pconf->lcd_basic.h_active -
+               pconf->lcd_timing.hsync_bp - pconf->lcd_timing.hsync_width;
+       lcd->timing->hfront_porch.min = tmp;
+       lcd->timing->hfront_porch.typ = tmp;
+       lcd->timing->hfront_porch.max = tmp;
+       lcd->timing->hback_porch.min = pconf->lcd_timing.hsync_bp;
+       lcd->timing->hback_porch.typ = pconf->lcd_timing.hsync_bp;
+       lcd->timing->hback_porch.max = pconf->lcd_timing.hsync_bp;
+       lcd->timing->hsync_len.min = pconf->lcd_timing.hsync_width;
+       lcd->timing->hsync_len.typ = pconf->lcd_timing.hsync_width;
+       lcd->timing->hsync_len.max = pconf->lcd_timing.hsync_width;
+       lcd->timing->vactive.min = pconf->lcd_basic.v_active;
+       lcd->timing->vactive.typ = pconf->lcd_basic.v_active;
+       lcd->timing->vactive.max = pconf->lcd_basic.v_active;
+       tmp = pconf->lcd_basic.v_period - pconf->lcd_basic.v_active -
+               pconf->lcd_timing.vsync_bp - pconf->lcd_timing.vsync_width;
+       lcd->timing->vfront_porch.min = tmp;
+       lcd->timing->vfront_porch.typ = tmp;
+       lcd->timing->vfront_porch.max = tmp;
+       lcd->timing->vback_porch.min = pconf->lcd_timing.vsync_bp;
+       lcd->timing->vback_porch.typ = pconf->lcd_timing.vsync_bp;
+       lcd->timing->vback_porch.max = pconf->lcd_timing.vsync_bp;
+       lcd->timing->vsync_len.min = pconf->lcd_timing.vsync_width;
+       lcd->timing->vsync_len.typ = pconf->lcd_timing.vsync_width;
+       lcd->timing->vsync_len.max = pconf->lcd_timing.vsync_width;
+
+       pr_info("am_drm_lcd: %s: lcd config:\n"
+               "lcd_clk             %d\n"
+               "h_active            %d\n"
+               "v_active            %d\n"
+               "screen_width        %d\n"
+               "screen_height       %d\n"
+               "sync_duration_den   %d\n"
+               "sync_duration_num   %d\n",
+               __func__,
+               lcd->lcd_drv->lcd_config->lcd_timing.lcd_clk,
+               lcd->lcd_drv->lcd_config->lcd_basic.h_active,
+               lcd->lcd_drv->lcd_config->lcd_basic.v_active,
+               lcd->lcd_drv->lcd_config->lcd_basic.screen_width,
+               lcd->lcd_drv->lcd_config->lcd_basic.screen_height,
+               lcd->lcd_drv->lcd_config->lcd_timing.sync_duration_den,
+               lcd->lcd_drv->lcd_config->lcd_timing.sync_duration_num);
+       pr_info("am_drm_lcd: %s: display mode:\n"
+               "clock       %d\n"
+               "hdisplay    %d\n"
+               "vdisplay    %d\n"
+               "width_mm    %d\n"
+               "height_mm   %d\n"
+               "vrefresh    %d\n",
+               __func__,
+               lcd->mode->clock,
+               lcd->mode->hdisplay,
+               lcd->mode->vdisplay,
+               lcd->mode->width_mm,
+               lcd->mode->height_mm,
+               lcd->mode->vrefresh);
+       pr_info("am_drm_lcd: %s: timing:\n"
+               "pixelclock   %d\n"
+               "hactive      %d\n"
+               "vactive      %d\n",
+               __func__,
+               lcd->timing->pixelclock.typ,
+               lcd->timing->hactive.typ,
+               lcd->timing->vactive.typ);
+
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+}
+
+static const struct of_device_id am_meson_lcd_dt_ids[] = {
+       { .compatible = "amlogic,drm-lcd", },
+       {},
+};
+
+static int am_meson_lcd_bind(struct device *dev, struct device *master,
+                                   void *data)
+{
+       struct drm_device *drm = data;
+       struct drm_connector *connector;
+       struct drm_encoder *encoder;
+       int encoder_type, connector_type;
+       int ret = 0;
+
+       am_drm_lcd = kzalloc(sizeof(*am_drm_lcd), GFP_KERNEL);
+       if (!am_drm_lcd)
+               return -ENOMEM;
+
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+       am_drm_lcd->lcd_drv = aml_lcd_get_driver();
+       if (!am_drm_lcd->lcd_drv) {
+               pr_err("invalid lcd driver, exit\n");
+               return -ENODEV;
+       }
+
+       am_drm_lcd_display_mode_timing_init(am_drm_lcd);
+
+       drm_panel_init(&am_drm_lcd->panel);
+       am_drm_lcd->panel.dev = NULL;
+       am_drm_lcd->panel.funcs = &am_drm_lcd_funcs;
+
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+       ret = drm_panel_add(&am_drm_lcd->panel);
+       if (ret < 0)
+               return ret;
+
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+       am_drm_lcd->drm = drm;
+
+       encoder = &am_drm_lcd->encoder;
+       connector = &am_drm_lcd->connector;
+       encoder_type = DRM_MODE_ENCODER_LVDS;
+       connector_type = DRM_MODE_CONNECTOR_LVDS;
+
+       /* Encoder */
+       drm_encoder_helper_add(encoder, &am_lcd_encoder_helper_funcs);
+       ret = drm_encoder_init(drm, encoder, &am_lcd_encoder_funcs,
+                              encoder_type, "am_lcd_encoder");
+       if (ret) {
+               pr_err("error: am_drm_lcd: Failed to init lcd encoder\n");
+               return ret;
+       }
+       pr_info("am_drm_lcd: %s %d: encoder possible_crtcs=%d\n",
+               __func__, __LINE__, encoder->possible_crtcs);
+
+       /* Connector */
+       drm_connector_helper_add(connector, &am_lcd_connector_helper_funcs);
+       ret = drm_connector_init(drm, connector, &am_lcd_connector_funcs,
+                               connector_type);
+       if (ret) {
+               pr_err("error: am_drm_lcd: Failed to init lcd connector\n");
+               return ret;
+       }
+
+       /* force possible_crtcs */
+       encoder->possible_crtcs = BIT(0);
+
+       drm_mode_connector_attach_encoder(connector, encoder);
+
+       pr_info("am_drm_lcd: register ok\n");
+
+       return ret;
+}
+
+static void am_meson_lcd_unbind(struct device *dev, struct device *master,
+                                   void *data)
+{
+       if (!am_drm_lcd)
+               return;
+
+       if (!am_drm_lcd->lcd_drv)
+               return;
+
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+
+       drm_panel_detach(&am_drm_lcd->panel);
+       drm_panel_remove(&am_drm_lcd->panel);
+
+       pr_info("am_drm_lcd: %s %d\n", __func__, __LINE__);
+}
+
+static const struct component_ops am_meson_lcd_ops = {
+       .bind   = am_meson_lcd_bind,
+       .unbind = am_meson_lcd_unbind,
+};
+
+static int am_meson_lcd_probe(struct platform_device *pdev)
+{
+       return component_add(&pdev->dev, &am_meson_lcd_ops);
+}
+
+static int am_meson_lcd_remove(struct platform_device *pdev)
+{
+       component_del(&pdev->dev, &am_meson_lcd_ops);
+       return 0;
+}
+
+static struct platform_driver am_meson_lcd_pltfm_driver = {
+       .probe  = am_meson_lcd_probe,
+       .remove = am_meson_lcd_remove,
+       .driver = {
+               .name = "meson-lcd",
+               .of_match_table = am_meson_lcd_dt_ids,
+       },
+};
+
+module_platform_driver(am_meson_lcd_pltfm_driver);
+
+MODULE_AUTHOR("MultiMedia Amlogic <multimedia-sh@amlogic.com>");
+MODULE_DESCRIPTION("Amlogic Meson Drm LCD driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/amlogic/drm/meson_lcd.h b/drivers/amlogic/drm/meson_lcd.h
new file mode 100644 (file)
index 0000000..32be56b
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * drivers/amlogic/drm/meson_lcd.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 __AM_DRM_LCD_H
+#define __AM_DRM_LCD_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 (file)
index 0000000..4e84a69
--- /dev/null
@@ -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 (file)
index 0000000..a1e6f4b
--- /dev/null
@@ -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 (file)
index 0000000..31ea494
--- /dev/null
@@ -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/meson_vpu.h b/drivers/amlogic/drm/meson_vpu.h
new file mode 100644 (file)
index 0000000..e288a33
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * drivers/amlogic/drm/meson_vpu.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 __AM_MESON_VPU_H
+#define __AM_MESON_VPU_H
+
+#include <linux/amlogic/media/vout/vout_notify.h>
+
+struct am_meson_vpu_data {
+       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 (file)
index 0000000..aef3b8d
--- /dev/null
@@ -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 (file)
index 0000000..258f8e9
--- /dev/null
@@ -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 (file)
index 0000000..a4ecb0e
--- /dev/null
@@ -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 (file)
index 0000000..2f3b211
--- /dev/null
@@ -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 (file)
index 0000000..652af8f
--- /dev/null
@@ -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 (file)
index 0000000..8c52df5
--- /dev/null
@@ -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 (file)
index 0000000..6fbec27
--- /dev/null
@@ -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 (file)
index 0000000..64eadf8
--- /dev/null
@@ -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 (file)
index 0000000..34ebb03
--- /dev/null
@@ -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/vpu-hw/meson_vpu_dev.c b/drivers/amlogic/drm/vpu-hw/meson_vpu_dev.c
new file mode 100644 (file)
index 0000000..e279690
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * drivers/amlogic/drm/vpu-hw/meson_vpu_dev.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.
+ *
+ */
+
+struct vpu_dev_func {
+       void (*hw_init)();
+       void (*hw_exit)();
+};
+
+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 (file)
index 0000000..39563bf
--- /dev/null
@@ -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 (file)
index 0000000..ddc9bc2
--- /dev/null
@@ -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 (file)
index 0000000..2a37316
--- /dev/null
@@ -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 (file)
index 0000000..f6aa7e8
--- /dev/null
@@ -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 (file)
index 0000000..3c1f3a6
--- /dev/null
@@ -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 (file)
index 0000000..71ea0aa
--- /dev/null
@@ -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 (file)
index 0000000..9100074
--- /dev/null
@@ -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 (file)
index 0000000..6825636
--- /dev/null
@@ -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 (file)
index 0000000..b163eaa
--- /dev/null
@@ -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 (file)
index cad57fe..0000000
+++ /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 */
-
index fc0cac3..9f74715 100644 (file)
@@ -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 (file)
index 0000000..5b12674
--- /dev/null
@@ -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 */