video_composer: add multiple video layer display. [1/1]
authorjintao xu <jintao.xu@amlogic.com>
Mon, 12 Aug 2019 10:50:27 +0000 (18:50 +0800)
committerShuide Chen <shuide.chen@amlogic.com>
Mon, 25 Nov 2019 07:22:58 +0000 (15:22 +0800)
PD#SWPL-5991

Problem:
video_composer bringup

Solution:
add v4lvideo态dma to display on the video layer via video_composer

Verify:
on U212

Change-Id: Iec1b75cc8c9aa0475912148a0687d95250aeb8a0
Signed-off-by: jintao xu <jintao.xu@amlogic.com>
73 files changed:
MAINTAINERS
arch/arm/boot/dts/amlogic/g12a_s905x2_u212.dts
arch/arm/boot/dts/amlogic/g12a_s905x2_u212_1g.dts
arch/arm/boot/dts/amlogic/g12a_s905y2_deadpool.dts
arch/arm/boot/dts/amlogic/mesong12a.dtsi
arch/arm/boot/dts/amlogic/mesong12a_deadpool.dtsi
arch/arm/boot/dts/amlogic/mesonsm1.dtsi
arch/arm/boot/dts/amlogic/mesonsm1_sabrina.dtsi
arch/arm/boot/dts/amlogic/sm1_s905d3_ac200.dts [changed mode: 0755->0644]
arch/arm/boot/dts/amlogic/sm1_s905d3_ac202.dts
arch/arm/boot/dts/amlogic/sm1_s905d3_ac202_1g.dts
arch/arm/boot/dts/amlogic/sm1_s905d3_sabrina.dts
arch/arm/boot/dts/amlogic/sm1_s905x3_ac213.dts
arch/arm/boot/dts/amlogic/sm1_s905x3_ac214.dts
arch/arm/boot/dts/amlogic/sm1_s905x3_ac214_buildroot.dts
arch/arm/configs/meson64_a32_defconfig
arch/arm64/boot/dts/amlogic/g12a_s905x2_u212.dts
arch/arm64/boot/dts/amlogic/g12a_s905x2_u212_1g.dts
arch/arm64/boot/dts/amlogic/g12a_s905y2_deadpool.dts
arch/arm64/boot/dts/amlogic/mesong12a.dtsi
arch/arm64/boot/dts/amlogic/mesong12a_deadpool.dtsi
arch/arm64/boot/dts/amlogic/mesonsm1.dtsi
arch/arm64/boot/dts/amlogic/mesonsm1_sabrina.dtsi
arch/arm64/boot/dts/amlogic/sm1_s905d3_ac200.dts
arch/arm64/boot/dts/amlogic/sm1_s905d3_ac202.dts
arch/arm64/boot/dts/amlogic/sm1_s905d3_ac202_1g.dts
arch/arm64/boot/dts/amlogic/sm1_s905d3_sabrina.dts
arch/arm64/boot/dts/amlogic/sm1_s905x3_ac213.dts
arch/arm64/boot/dts/amlogic/sm1_s905x3_ac214.dts
arch/arm64/boot/dts/amlogic/sm1_s905x3_ac214_buildroot.dts
arch/arm64/configs/meson64_defconfig
drivers/amlogic/media/common/codec_mm/codec_mm_keeper.c
drivers/amlogic/media/deinterlace/deinterlace.c
drivers/amlogic/media/deinterlace/deinterlace_hw.c
drivers/amlogic/media/deinterlace/deinterlace_hw.h
drivers/amlogic/media/di_multi/deinterlace.c
drivers/amlogic/media/di_multi/deinterlace.h
drivers/amlogic/media/di_multi/deinterlace_dbg.c
drivers/amlogic/media/di_multi/deinterlace_hw.c
drivers/amlogic/media/di_multi/di_data_l.h
drivers/amlogic/media/di_multi/di_dbg.c
drivers/amlogic/media/di_multi/di_prc.c
drivers/amlogic/media/di_multi/di_prc.h
drivers/amlogic/media/di_multi/di_que.c
drivers/amlogic/media/di_multi/di_que.h
drivers/amlogic/media/di_multi/di_sys.c
drivers/amlogic/media/di_multi/di_task.c
drivers/amlogic/media/video_processor/Kconfig
drivers/amlogic/media/video_processor/Makefile
drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c
drivers/amlogic/media/video_processor/v4lvideo/Kconfig [new file with mode: 0644]
drivers/amlogic/media/video_processor/v4lvideo/Makefile [new file with mode: 0644]
drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.c [new file with mode: 0644]
drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.h [new file with mode: 0644]
drivers/amlogic/media/video_processor/video_composer/Kconfig [new file with mode: 0644]
drivers/amlogic/media/video_processor/video_composer/Makefile [new file with mode: 0644]
drivers/amlogic/media/video_processor/video_composer/vfq.h [new file with mode: 0644]
drivers/amlogic/media/video_processor/video_composer/vframe_ge2d_composer.c [new file with mode: 0644]
drivers/amlogic/media/video_processor/video_composer/vframe_ge2d_composer.h [new file with mode: 0644]
drivers/amlogic/media/video_processor/video_composer/video_composer.c [new file with mode: 0644]
drivers/amlogic/media/video_processor/video_composer/video_composer.h [new file with mode: 0644]
drivers/amlogic/media/video_sink/Makefile
drivers/amlogic/media/video_sink/video.c
drivers/amlogic/media/video_sink/video_hw.c
drivers/amlogic/media/video_sink/video_priv.h
drivers/amlogic/media/video_sink/video_receiver.c [new file with mode: 0644]
drivers/amlogic/media/video_sink/video_receiver.h [new file with mode: 0644]
include/linux/amlogic/major.h
include/linux/amlogic/media/utils/amstream.h
include/linux/amlogic/media/vfm/vframe.h
include/linux/amlogic/media/video_processor/video_composer_ext.h [new file with mode: 0644]
include/linux/amlogic/media/video_sink/v4lvideo_ext.h [new file with mode: 0644]
include/linux/amlogic/media/video_sink/video.h

index 649a0c9835b3b9352fb9a3e369e01b81b6da9fe5..7818286686ffeed1f62f8a3ae303a3e7d55c432e 100644 (file)
@@ -15221,3 +15221,32 @@ AMLOGIC VPP DRIVER
 M:     Brian Zhu <brian.zhu@amlogic.com>
 F: drivers/amlogic/media/video_sink/video_hw.c
 
+AMLOGIC T962X3 DRM DTS
+M:  Dezhi Kong <dezhi.kong@amlogic.com>
+F:  arch/arm/boot/dts/amlogic/tm2_t962x3_ab301_drm.dts
+F:  arch/arm/boot/dts/amlogic/tm2_t962e2_ab311_drm.dts
+F:  arch/arm64/boot/dts/amlogic/tm2_t962x3_ab301_drm.dts
+F:  arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311_drm.dts
+F:  arch/arm64/boot/dts/amlogic/mesontm2_drm.dtsi
+F:  arch/arm/boot/dts/amlogic/mesontm2_drm.dtsi
+
+AMLOGIC VIDEO COMPOSER
+M:     Jintao.Xu <jintao.xu@amlogic.com>
+F: drivers/amlogic/media/video_processor/v4lvideo/Kconfig
+F: drivers/amlogic/media/video_processor/v4lvideo/Makefile
+F: drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.c
+F: drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.h
+F: drivers/amlogic/media/video_processor/video_composer/Kconfig
+F: drivers/amlogic/media/video_processor/video_composer/Makefile
+F: drivers/amlogic/media/video_processor/video_composer/vfq.h
+F: drivers/amlogic/media/video_processor/video_composer/vframe_ge2d_composer.c
+F: drivers/amlogic/media/video_processor/video_composer/vframe_ge2d_composer.h
+F: drivers/amlogic/media/video_processor/video_composer/video_composer.c
+F: drivers/amlogic/media/video_processor/video_composer/video_composer.h
+F: include/linux/amlogic/media/video_processor/video_composer_ext.h
+F: include/linux/amlogic/media/video_sink/v4lvideo_ext.h
+
+AMLOGIC VPP DRIVER
+M:     Brian Zhu <brian.zhu@amlogic.com>
+F: drivers/amlogic/media/video_sink/video_receiver.c
+F: drivers/amlogic/media/video_sink/video_receiver.h
index 57c9719fa7e136aa28487c4bc36f7366d0d1729d..c752608675564689fa05888d75c5fd82931bbb91 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x02800000>;
+                       //size = <0x02800000>;
+                       size = <0x05800000>;
                        alignment = <0x400000>;
                };
                /*  POST PROCESS MANAGER */
                        compatible = "shared-dma-pool";
                        reusable;
                        /* ion_codec_mm max can alloc size 80M*/
-                       size = <0x13400000>;
+                       size = <0x16400000>;
                        alignment = <0x400000>;
                        linux,contiguous-region;
                };
                dev_name = "ppmgr";
                status = "okay";
        };
-
-       deinterlace {
-               compatible = "amlogic, deinterlace";
+       multi-di {
+               compatible = "amlogic, dim-g12a";
                status = "okay";
                /* 0:use reserved; 1:use cma; 2:use cma as reserved */
                flag_cma = <1>;
                nrds-enable = <1>;
                pps-enable = <1>;
        };
+       deinterlace {
+               compatible = "amlogic, deinterlace";
+               status = "disable";//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";
index b5a0411437c0f072db5833eafbd5ed8d3a23fb49..5370cce19f58286f10fc0466c372bf1eb926e13f 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x02800000>;
+                       //size = <0x02800000>;
+                       size = <0x05800000>;
                        alignment = <0x400000>;
                        alloc-ranges = <0x30000000 0x10000000>;
                };
                dev_name = "ppmgr";
                status = "okay";
        };
-
-       deinterlace {
-               compatible = "amlogic, deinterlace";
+       multi-di {
+               compatible = "amlogic, dim-g12a";
                status = "okay";
                /* 0:use reserved; 1:use cma; 2:use cma as reserved */
                flag_cma = <1>;
                nrds-enable = <1>;
                pps-enable = <1>;
        };
+       deinterlace {
+               compatible = "amlogic, deinterlace";
+               status = "disable";//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";
index 3e41535e45d7a94baf585f87032cda7120e020be..0e763fedaa077f192b10bbd0512d923e5283ee0f 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x02800000>;
+                       //size = <0x02800000>;
+                       size = <0x05800000>;
                        alignment = <0x400000>;
                };
                /*  POST PROCESS MANAGER */
                        compatible = "shared-dma-pool";
                        reusable;
                        /* ion_codec_mm max can alloc size 80M*/
-                       size = <0x13400000>;
+                       size = <0x16400000>;
                        alignment = <0x400000>;
                        linux,contiguous-region;
                        alloc-ranges = <0x30000000 0x50000000>;
                dev_name = "ppmgr";
                status = "okay";
        };
-
+       multi-di {
+               compatible = "amlogic, dim-g12a";
+               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>;
+       };
        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>;
+               //memory-region = <&di_cma_reserved>;
                interrupts = <0 46 1
                                0 40 1>;
                interrupt-names = "pre_irq", "post_irq";
index 16fb5edb84b3ed4aade09469b631a89880622521..c19c28262b2fce90e268b8754ae924fb4594b743 100644 (file)
                status = "okay";
        };
 
+       video_composer {
+               compatible = "amlogic, video_composer";
+               dev_name = "video_composer";
+               status = "okay";
+       };
+
        amvenc_avc{
                compatible = "amlogic, amvenc_avc";
                dev_name = "amvenc_avc";
index 68eb7cc9d3005b30b882dd06c4b751576c3c7f58..9a40a8df8ceab0f437d12300721076b16405db07 100644 (file)
                status = "okay";
        };
 
+       video_composer {
+               compatible = "amlogic, video_composer";
+               dev_name = "video_composer";
+               status = "okay";
+       };
+
        amvenc_avc{
                compatible = "amlogic, amvenc_avc";
                dev_name = "amvenc_avc";
index dc0a7541bb3bec96d2525e3ff28ff5106014b01f..559473c4c9a64e167fa57d8f14fcb94044235272 100644 (file)
                status = "okay";
        };
 
+       video_composer {
+               compatible = "amlogic, video_composer";
+               dev_name = "video_composer";
+               status = "okay";
+       };
+
        amvenc_avc{
                compatible = "amlogic, amvenc_avc";
                dev_name = "amvenc_avc";
index 7e18920a0cd5dad7e5138114b44b725e49c2f197..ab697c85a05553aa106f00e19ff1acc09ef62224 100644 (file)
                status = "okay";
        };
 
+       video_composer {
+               compatible = "amlogic, video_composer";
+               dev_name = "video_composer";
+               status = "okay";
+       };
+
        amvenc_avc{
                compatible = "amlogic, amvenc_avc";
                dev_name = "amvenc_avc";
old mode 100755 (executable)
new mode 100644 (file)
index 38530a7..8926afa
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x02800000>;
+                       size = <0x05800000>;
                        alignment = <0x400000>;
                };
                /*  POST PROCESS MANAGER */
                        compatible = "shared-dma-pool";
                        reusable;
                        /* ion_codec_mm max can alloc size 80M*/
-                       size = <0x13400000>;
+                       size = <0x16400000>;
                        alignment = <0x400000>;
                        linux,contiguous-region;
                        alloc-ranges = <0x30000000 0x50000000>;
                status = "okay";
        };
 
-       deinterlace {
-               compatible = "amlogic, deinterlace";
+       multi-di {
+               compatible = "amlogic, dim-sm1";
                status = "okay";
                /* 0:use reserved; 1:use cma; 2:use cma as reserved */
                flag_cma = <1>;
                nrds-enable = <1>;
                pps-enable = <1>;
        };
+
+       deinterlace {
+               compatible = "amlogic, deinterlace";
+               status = "disable";//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";
index bed7b014a18aeb6926838654dde1bfae8648c308..9371f6e90fa669ffab0f8e5d367b99f029e2cce3 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x02800000>;
+                       size = <0x05800000>;
                        alignment = <0x400000>;
                };
                /*  POST PROCESS MANAGER */
                        compatible = "shared-dma-pool";
                        reusable;
                        /* ion_codec_mm max can alloc size 80M*/
-                       size = <0x13400000>;
+                       size = <0x16400000>;
                        alignment = <0x400000>;
                        linux,contiguous-region;
                        alloc-ranges = <0x30000000 0x50000000>;
                status = "okay";
        };
 
-       deinterlace {
-               compatible = "amlogic, deinterlace";
+       multi-di {
+               compatible = "amlogic, dim-sm1";
                status = "okay";
                /* 0:use reserved; 1:use cma; 2:use cma as reserved */
                flag_cma = <1>;
                nrds-enable = <1>;
                pps-enable = <1>;
        };
+
+       deinterlace {
+               compatible = "amlogic, deinterlace";
+               status = "disable";//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";
index 17145c1443148f08d3acf50a1114c3d110df29d0..000684defb87eac24899c9ff18fbedc31cf2cd18 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x02800000>;
+                       size = <0x05800000>;
                        alignment = <0x400000>;
                };
                /*  POST PROCESS MANAGER */
                status = "okay";
        };
 
-       deinterlace {
-               compatible = "amlogic, deinterlace";
+       multi-di {
+               compatible = "amlogic, dim-sm1";
                status = "okay";
                /* 0:use reserved; 1:use cma; 2:use cma as reserved */
                flag_cma = <1>;
                nrds-enable = <1>;
                pps-enable = <1>;
        };
+
+       deinterlace {
+               compatible = "amlogic, deinterlace";
+               status = "disable";//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";
index 47df4f98f4b93ce43491efd3c54e2800debab4d2..cf1a86e8e5e8c1fafa409310b56b15bb8b8cb8d6 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x02800000>;
+                       size = <0x05800000>;
                        alignment = <0x400000>;
                };
                /*  POST PROCESS MANAGER */
                        compatible = "shared-dma-pool";
                        reusable;
                        /* ion_codec_mm max can alloc size 80M*/
-                       size = <0x13400000>;
+                       size = <0x16400000>;
                        alignment = <0x400000>;
                        linux,contiguous-region;
                        alloc-ranges = <0x30000000 0x50000000>;
                status = "okay";
        };
 
-       deinterlace {
-               compatible = "amlogic, deinterlace";
+       multi-di {
+               compatible = "amlogic, dim-sm1";
                status = "okay";
                /* 0:use reserved; 1:use cma; 2:use cma as reserved */
                flag_cma = <1>;
                nrds-enable = <1>;
                pps-enable = <1>;
        };
+
+       deinterlace {
+               compatible = "amlogic, deinterlace";
+               status = "disable";//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";
index 8951ce524ea1beb30b814baa9b86390618430297..a116ead97308c6fd9694d116ea88920e0bdfc59e 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x02800000>;
+                       size = <0x05800000>;
                        alignment = <0x400000>;
                };
                /*  POST PROCESS MANAGER */
                        compatible = "shared-dma-pool";
                        reusable;
                        /* ion_codec_mm max can alloc size 80M*/
-                       size = <0x13400000>;
+                       size = <0x16400000>;
                        alignment = <0x400000>;
                        linux,contiguous-region;
                        alloc-ranges = <0x30000000 0x50000000>;
                status = "okay";
        };
 
-       deinterlace {
-               compatible = "amlogic, deinterlace";
+       multi-di {
+               compatible = "amlogic, dim-sm1";
                status = "okay";
                /* 0:use reserved; 1:use cma; 2:use cma as reserved */
                flag_cma = <1>;
                nrds-enable = <1>;
                pps-enable = <1>;
        };
+       deinterlace {
+               compatible = "amlogic, deinterlace";
+               status = "disable";//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";
index 5244fb869270a25e5079c5216efc5081876b5db8..76b0d46c69f5a3f468a1012bf779e7db7ea69410 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x02800000>;
+                       size = <0x05800000>;
                        alignment = <0x400000>;
                };
                /*  POST PROCESS MANAGER */
                        compatible = "shared-dma-pool";
                        reusable;
                        /* ion_codec_mm max can alloc size 80M*/
-                       size = <0x13400000>;
+                       size = <0x16400000>;
                        alignment = <0x400000>;
                        linux,contiguous-region;
                        alloc-ranges = <0x30000000 0x50000000>;
                status = "okay";
        };
 
-       deinterlace {
-               compatible = "amlogic, deinterlace";
+       multi-di {
+               compatible = "amlogic, dim-sm1";
                status = "okay";
                /* 0:use reserved; 1:use cma; 2:use cma as reserved */
                flag_cma = <1>;
index 2b1246794e9a35d11b8e226dc8e35aaf609ff2af..238f82405e8c95e6feb324acd98575e38bcd22f5 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x02800000>;
+                       size = <0x05800000>;
                        alignment = <0x400000>;
                };
                /*  POST PROCESS MANAGER */
                        compatible = "shared-dma-pool";
                        reusable;
                        /* ion_codec_mm max can alloc size 80M*/
-                       size = <0x13400000>;
+                       size = <0x16400000>;
                        alignment = <0x400000>;
                        linux,contiguous-region;
                        alloc-ranges = <0x30000000 0x50000000>;
                status = "okay";
        };
 
-       deinterlace {
-               compatible = "amlogic, deinterlace";
+       multi-di {
+               compatible = "amlogic, dim-sm1";
                status = "okay";
                /* 0:use reserved; 1:use cma; 2:use cma as reserved */
                flag_cma = <1>;
                nrds-enable = <1>;
                pps-enable = <1>;
        };
+
+       deinterlace {
+               compatible = "amlogic, deinterlace";
+               status = "disable";//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";
index 3b361e078be6043cbbcf6833cd1fe790bcc9f919..aa3bf7d344da91ba27af29539043f83c5770279f 100644 (file)
@@ -335,6 +335,8 @@ CONFIG_AMLOGIC_VIDEOBUF2_ION=y
 CONFIG_AMLOGIC_IONVIDEO=y
 CONFIG_AMLOGIC_PIC_DEC=y
 CONFIG_AMLOGIC_VIDEOSYNC=y
+CONFIG_AMLOGIC_V4L_VIDEO3=y
+CONFIG_AMLOGIC_VIDEO_COMPOSER=y
 CONFIG_AMLOGIC_MEDIA_ENHANCEMENT=y
 CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y
 CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y
@@ -476,7 +478,6 @@ CONFIG_SPI_SPIDEV=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_PCA953X=y
 CONFIG_POWER_RESET=y
-CONFIG_POWER_SUPPLY=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_WRITABLE_TRIPS=y
 CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR=y
@@ -523,9 +524,9 @@ CONFIG_AMLOGIC_SND_SOC_MESON=y
 CONFIG_AMLOGIC_SND_SOC_AUGE=y
 CONFIG_AMLOGIC_SND_SPLIT_MODE=y
 CONFIG_AMLOGIC_SND_SOC_COMMON=y
-CONFIG_HID_SONY=y
 CONFIG_HIDRAW=y
 CONFIG_UHID=y
+CONFIG_HID_SONY=y
 CONFIG_USB_HIDDEV=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
index 378c1b173df6789808a730830bc822d40d298dec..cd2c614e321eb4471867341412354ad4c4371f8d 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x0 0x02800000>;
+                       size = <0x0 0x05800000>;
                        alignment = <0x0 0x400000>;
                };
                /*  POST PROCESS MANAGER */
                        compatible = "shared-dma-pool";
                        reusable;
                        /* ion_codec_mm max can alloc size 80M*/
-                       size = <0x0 0x13400000>;
+                       size = <0x0 0x16400000>;
                        alignment = <0x0 0x400000>;
                        linux,contiguous-region;
                };
                dev_name = "ppmgr";
                status = "okay";
        };
-
-       deinterlace {
-               compatible = "amlogic, deinterlace";
+       multi-di {
+               compatible = "amlogic, dim-g12a";
                status = "okay";
                /* 0:use reserved; 1:use cma; 2:use cma as reserved */
                flag_cma = <1>;
                nrds-enable = <1>;
                pps-enable = <1>;
        };
+       deinterlace {
+               compatible = "amlogic, deinterlace";
+               status = "disable";//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";
index d548a0e80afd494ede0c77684970d8d75779e85f..83adbbd1ffca82fdc423085c6a128cd48ed0e150 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x0 0x02800000>;
+                       size = <0x0 0x05800000>;
                        alignment = <0x0 0x400000>;
                };
                /*  POST PROCESS MANAGER */
                dev_name = "ppmgr";
                status = "okay";
        };
-
-       deinterlace {
-               compatible = "amlogic, deinterlace";
+       multi-di {
+               compatible = "amlogic, dim-g12a";
                status = "okay";
                /* 0:use reserved; 1:use cma; 2:use cma as reserved */
                flag_cma = <1>;
                nrds-enable = <1>;
                pps-enable = <1>;
        };
+       deinterlace {
+               compatible = "amlogic, deinterlace";
+               status = "disable";//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";
index 3b5cddf52045854475e221059ad32bc82c2e4720..d0a35f29a3253bbaf886cd942355faf2580d0d8b 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x0 0x02800000>;
+                       size = <0x0 0x05800000>;
                        alignment = <0x0 0x400000>;
                };
                /*  POST PROCESS MANAGER */
                        compatible = "shared-dma-pool";
                        reusable;
                        /* ion_codec_mm max can alloc size 80M*/
-                       size = <0x0 0x13400000>;
+                       size = <0x0 0x16400000>;
                        alignment = <0x0 0x400000>;
                        linux,contiguous-region;
                };
                dev_name = "ppmgr";
                status = "okay";
        };
-
+       multi-di {
+               compatible = "amlogic, dim-g12a";
+               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>;
+       };
        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>;
+               //memory-region = <&di_cma_reserved>;
                interrupts = <0 46 1
                                0 40 1>;
                interrupt-names = "pre_irq", "post_irq";
index 86ee9123f6c16578dcb0827fdbebc4415026e93a..f419244e69b865c570c59d4bafdd136c7860c039 100644 (file)
                status = "okay";
        };
 
+       video_composer {
+               compatible = "amlogic, video_composer";
+               dev_name = "video_composer";
+               status = "okay";
+       };
+
        amvenc_avc{
                compatible = "amlogic, amvenc_avc";
                dev_name = "amvenc_avc";
index 4048775b9b65afb598653fc0c34e2f5c4fdc273d..f4118f8064266e3a3676fb0576e5c65acb3ba8af 100644 (file)
                status = "okay";
        };
 
+       video_composer {
+               compatible = "amlogic, video_composer";
+               dev_name = "video_composer";
+               status = "okay";
+       };
+
        amvenc_avc{
                compatible = "amlogic, amvenc_avc";
                dev_name = "amvenc_avc";
index 370e214817db3607aeae701b3820741b297f2101..8af44d5fe66909b325ec5f6ffe5dcdedadb7e95e 100644 (file)
                status = "okay";
        };
 
+       video_composer {
+               compatible = "amlogic, video_composer";
+               dev_name = "video_composer";
+               status = "okay";
+       };
+
        amvenc_avc{
                compatible = "amlogic, amvenc_avc";
                dev_name = "amvenc_avc";
index b053d5c7c2e9c9ba0feb59ce5137b8c7df76a7af..a4ae378a8e09fbae370c6f880e5152a685c3453c 100644 (file)
                status = "okay";
        };
 
+       video_composer {
+               compatible = "amlogic, video_composer";
+               dev_name = "video_composer";
+               status = "okay";
+       };
+
        amvenc_avc{
                compatible = "amlogic, amvenc_avc";
                dev_name = "amvenc_avc";
index 43fb18244f9dfe45a2816888f72b96b186f6eb3a..3322c284d5dbcb9a1e1bf657e0880e6f4cdacbde 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x0 0x02800000>;
+                       size = <0x0 0x05800000>;
                        alignment = <0x0 0x400000>;
                };
                /*  POST PROCESS MANAGER */
                        compatible = "shared-dma-pool";
                        reusable;
                        /* ion_codec_mm max can alloc size 80M*/
-                       size = <0x0 0x13400000>;
+                       size = <0x0 0x16400000>;
                        alignment = <0x0 0x400000>;
                        linux,contiguous-region;
                };
                status = "okay";
        };
 
-       deinterlace {
-               compatible = "amlogic, deinterlace";
+       multi-di {
+               compatible = "amlogic, dim-sm1";
                status = "okay";
                /* 0:use reserved; 1:use cma; 2:use cma as reserved */
                flag_cma = <1>;
                nrds-enable = <1>;
                pps-enable = <1>;
        };
+       deinterlace {
+               compatible = "amlogic, deinterlace";
+               status = "disable";//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";
index 91360b69faba8daa6f9fa4a84bfe64617249dceb..d1d441d697304e8d70bcc5aa01d0ee7a7a408c3f 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x0 0x02800000>;
+                       size = <0x0 0x05800000>;
                        alignment = <0x0 0x400000>;
                };
                /*  POST PROCESS MANAGER */
                        compatible = "shared-dma-pool";
                        reusable;
                        /* ion_codec_mm max can alloc size 80M*/
-                       size = <0x0 0x13400000>;
+                       size = <0x0 0x16400000>;
                        alignment = <0x0 0x400000>;
                        linux,contiguous-region;
                };
                status = "okay";
        };
 
-       deinterlace {
-               compatible = "amlogic, deinterlace";
+       multi-di {
+               compatible = "amlogic, dim-sm1";
                status = "okay";
                /* 0:use reserved; 1:use cma; 2:use cma as reserved */
                flag_cma = <1>;
                nrds-enable = <1>;
                pps-enable = <1>;
        };
+       deinterlace {
+               compatible = "amlogic, deinterlace";
+               status = "disable";//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";
index fc6f2e3ba6ccad1a381d7c36d6381381219874c1..690ca65f5b85c61706485408b5c6ceb4d26a9302 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x0 0x02800000>;
+                       size = <0x0 0x05800000>;
                        alignment = <0x0 0x400000>;
                };
                /*  POST PROCESS MANAGER */
                status = "okay";
        };
 
-       deinterlace {
-               compatible = "amlogic, deinterlace";
+       multi-di {
+               compatible = "amlogic, dim-sm1";
                status = "okay";
                /* 0:use reserved; 1:use cma; 2:use cma as reserved */
                flag_cma = <1>;
                nrds-enable = <1>;
                pps-enable = <1>;
        };
+       deinterlace {
+               compatible = "amlogic, deinterlace";
+               status = "disable";//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";
index ff91c65330ff0f67781648844c07e8bb8a560595..e16d8631104f919f23f2f2c13a51939f799d3144 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x0 0x02800000>;
+                       size = <0x0 0x05800000>;
                        alignment = <0x0 0x400000>;
                };
                /*  POST PROCESS MANAGER */
                        compatible = "shared-dma-pool";
                        reusable;
                        /* ion_codec_mm max can alloc size 80M*/
-                       size = <0x0 0x13400000>;
+                       size = <0x0 0x16400000>;
                        alignment = <0x0 0x400000>;
                        linux,contiguous-region;
                };
                status = "okay";
        };
 
+       multi-di {
+               compatible = "amlogic, dim-sm1";
+               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>;
+       };
        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>;
+               //memory-region = <&di_cma_reserved>;
                interrupts = <0 46 1
                                0 40 1>;
                interrupt-names = "pre_irq", "post_irq";
index d5f1f0654c66ecf06b653d250d3f589b089fb46d..1b6c39d878b3b6181add569ee670fe97cb3e819a 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x0 0x02800000>;
+                       size = <0x0 0x05800000>;
                        alignment = <0x0 0x400000>;
                };
                /*  POST PROCESS MANAGER */
                        compatible = "shared-dma-pool";
                        reusable;
                        /* ion_codec_mm max can alloc size 80M*/
-                       size = <0x0 0x13400000>;
+                       size = <0x0 0x16400000>;
                        alignment = <0x0 0x400000>;
                        linux,contiguous-region;
                };
                status = "okay";
        };
 
-       deinterlace {
-               compatible = "amlogic, deinterlace";
+       multi-di {
+               compatible = "amlogic, dim-sm1";
                status = "okay";
                /* 0:use reserved; 1:use cma; 2:use cma as reserved */
                flag_cma = <1>;
                nrds-enable = <1>;
                pps-enable = <1>;
        };
-
+       deinterlace {
+               compatible = "amlogic, deinterlace";
+               status = "disable";//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>;
+       };
        dvb_avl6762 {
                compatible = "amlogic, dvb";
                dev_name = "dvb";
index 3f8b9774d657a59baa22c1f2c10d6a5c2e814235..c2723f1a2aca772420af03443cc81802d88e1752 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x0 0x02800000>;
+                       size = <0x0 0x05800000>;
                        alignment = <0x0 0x400000>;
                };
                /*  POST PROCESS MANAGER */
                        compatible = "shared-dma-pool";
                        reusable;
                        /* ion_codec_mm max can alloc size 80M*/
-                       size = <0x0 0x13400000>;
+                       size = <0x0 0x16400000>;
                        alignment = <0x0 0x400000>;
                        linux,contiguous-region;
                };
                status = "okay";
        };
 
-       deinterlace {
-               compatible = "amlogic, deinterlace";
+       multi-di {
+               compatible = "amlogic, dim-sm1";
                status = "okay";
                /* 0:use reserved; 1:use cma; 2:use cma as reserved */
                flag_cma = <1>;
                pps-enable = <1>;
        };
 
+       deinterlace {
+               compatible = "amlogic, deinterlace";
+               status = "disable";//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>;
+       };
+
        dvb_avl6762 {
                compatible = "amlogic, dvb";
                dev_name = "dvb";
index 336569a7c653f062f1719b4b9d4de33424d0ae9e..7aa731550c2c6ce3be0104898c154ad76c1ca2cd 100644 (file)
                         * 10x4736064=45.2M(0x2e) support 12bit
                         * 10x4074560=40M(0x28) support 10bit
                         */
-                       size = <0x0 0x02800000>;
+                       size = <0x0 0x05800000>;
                        alignment = <0x0 0x400000>;
                };
                /*  POST PROCESS MANAGER */
                        compatible = "shared-dma-pool";
                        reusable;
                        /* ion_codec_mm max can alloc size 80M*/
-                       size = <0x0 0x13400000>;
+                       size = <0x0 0x16400000>;
                        alignment = <0x0 0x400000>;
                        linux,contiguous-region;
                };
                status = "okay";
        };
 
-       deinterlace {
-               compatible = "amlogic, deinterlace";
+       multi-di {
+               compatible = "amlogic, dim-sm1";
                status = "okay";
                /* 0:use reserved; 1:use cma; 2:use cma as reserved */
                flag_cma = <1>;
                nrds-enable = <1>;
                pps-enable = <1>;
        };
+
+       deinterlace {
+               compatible = "amlogic, deinterlace";
+               status = "disable";//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>;
+       };
+
        dvb {
                compatible = "amlogic, dvb";
                dev_name = "dvb";
index 6fed4a796dcd86213b980634d237148b48378e7a..f71838b08ea45269548a67b223665d8186f16539 100644 (file)
@@ -331,6 +331,8 @@ CONFIG_AMLOGIC_VIDEOBUF2_ION=y
 CONFIG_AMLOGIC_IONVIDEO=y
 CONFIG_AMLOGIC_PIC_DEC=y
 CONFIG_AMLOGIC_VIDEOSYNC=y
+CONFIG_AMLOGIC_V4L_VIDEO3=y
+CONFIG_AMLOGIC_VIDEO_COMPOSER=y
 CONFIG_AMLOGIC_MEDIA_ENHANCEMENT=y
 CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM=y
 CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y
index 114ef6fa7914d7f0eb5b2c3a91aff758bb631295..4fbb1f4b8877026c3c8ada53c8d1bf60eb01373f 100644 (file)
@@ -29,7 +29,7 @@
 #include "codec_mm_priv.h"
 #include "codec_mm_scatter_priv.h"
 #define KEEP_NAME "keeper"
-#define MAX_KEEP_FRAME 16
+#define MAX_KEEP_FRAME 64
 #define START_KEEP_ID 0x9
 #define MAX_KEEP_ID    (INT_MAX - 1)
 
index 589834a670d7c4bae746e041979b0df317fc0cb1..9e3acb8300be03f5666a14f8d08dc43b4c76f8bb 100644 (file)
@@ -578,6 +578,11 @@ void di_trig_free_mirror_mem(void)
                up(&di_sema);
                di_pr_info("%s\n", __func__);
        }
+
+       if (atomic_read(&di_flag_unreg)) {
+               diwr_set_power_control_pst(0);
+               di_pr_info("disable pst pd\n");
+       }
 }
 EXPORT_SYMBOL(di_trig_free_mirror_mem);
 static bool di_free_mem_pre(void)
@@ -7092,6 +7097,7 @@ static void di_reg_process_irq(void)
                /*di pre h scaling down: sm1 tm2*/
                de_devp->h_sc_down_en = pre_hsc_down_en;
                switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, VPU_CLK_GATE_ON);
+               diwr_set_power_control_pst(1);
                if (post_wr_en && post_wr_support)
                        diwr_set_power_control(1);
                /* up for vpu clkb rate change */
index f8907af160767c1b14b888dce1b6b289235f5154..29b9918b624db0fe4960abc521ddabc88dd585be 100644 (file)
@@ -3367,6 +3367,12 @@ void diwr_set_power_control(unsigned char enable)
                enable?VPU_MEM_POWER_ON:VPU_MEM_POWER_DOWN);
 }
 
+void diwr_set_power_control_pst(unsigned char enable)
+{
+       switch_vpu_mem_pd_vmod(VPU_DI_POST,
+                              enable ? VPU_MEM_POWER_ON : VPU_MEM_POWER_DOWN);
+}
+
 void di_hdr2_hist_init(void)
 {
        if (cpu_after_eq(MESON_CPU_MAJOR_ID_TM2)) {
index 21cbf85234348b2225b0eb03835f265d64a30426..96699cef8cb644004d2c0b72190e86da63ebc77b 100644 (file)
@@ -189,6 +189,7 @@ void di_top_gate_control(bool top_en, bool mc_en);
 void di_pre_gate_control(bool enable, bool mc_enable);
 void di_post_gate_control(bool gate);
 void diwr_set_power_control(unsigned char enable);
+void diwr_set_power_control_pst(unsigned char enable);
 void di_hw_disable(bool mc_enable);
 void enable_di_pre_mif(bool enable, bool mc_enable);
 void enable_di_post_mif(enum gate_mode_e mode);
index 751b5ee43d5556e12cc67d83db62fc4c439d88b2..b17f45d0752b234e033990c3dd809f4dbb2ccebb 100644 (file)
@@ -1156,7 +1156,7 @@ static void dis2_di(void)
                ppre->di_inp_buf = NULL;
        }
        dim_uninit_buf(0, channel);
-       if (get_blackout_policy()) {
+       if (0/*get_blackout_policy()*/) {
                dim_DI_Wr(DI_CLKG_CTRL, 0x2);
                if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) {
                        dimh_enable_di_post_mif(GATE_OFF);
@@ -1839,7 +1839,9 @@ static unsigned int di_cma_alloc(struct di_dev_s *devp, unsigned int channel)
                        }
                }
        }
-       PR_INF("%s:num_local[%d]\n", __func__, mm->sts.num_local);
+       PR_INF("%s:num_local[%d]:[%d]\n", __func__, mm->sts.num_local,
+              alloc_cnt);
+       alloc_cnt = 0;
        if (dimp_get(eDI_MP_post_wr_en) && dimp_get(eDI_MP_post_wr_support)) {
                di_que_list(channel, QUE_POST_FREE, &tmpa[0], &psize);
 
@@ -1875,7 +1877,8 @@ static unsigned int di_cma_alloc(struct di_dev_s *devp, unsigned int channel)
                        if (dimp_get(eDI_MP_cma_print))
                                pr_info(" addr 0x%lx ok.\n", buf_p->nr_adr);
                }
-               PR_INF("%s:num_pst[%d]\n", __func__, mm->sts.num_post);
+               PR_INF("%s:num_pst[%d]:%d\n", __func__, mm->sts.num_post,
+                      alloc_cnt);
        }
        if (de_devp->flag_cma != 0 && de_devp->nrds_enable) {
                dim_nr_ds_buf_init(de_devp->flag_cma, 0,
@@ -1884,8 +1887,8 @@ static unsigned int di_cma_alloc(struct di_dev_s *devp, unsigned int channel)
 
        end_time = jiffies_to_msecs(jiffies);
        delta_time = end_time - start_time;
-       pr_info("%s:alloc %u buffer use %u ms(%u~%u)\n",
-               __func__, alloc_cnt, delta_time, start_time, end_time);
+       pr_info("%s:alloc use %u ms(%u~%u)\n",
+               __func__, delta_time, start_time, end_time);
        return 1;
 }
 
@@ -1895,7 +1898,7 @@ static void di_cma_release(struct di_dev_s *devp, unsigned int channel)
        struct di_buf_s *buf_p;
        struct di_buf_s *pbuf_local = get_buf_local(channel);
        struct di_buf_s *pbuf_post = get_buf_post(channel);
-       struct di_post_stru_s *ppost = get_post_stru(channel);
+/*     struct di_post_stru_s *ppost = get_post_stru(channel);*/
        struct di_dev_s *de_devp = get_dim_de_devp();
        bool ret;
        struct di_mm_s *mm = dim_mm_get();
@@ -1933,12 +1936,12 @@ static void di_cma_release(struct di_dev_s *devp, unsigned int channel)
                /*mm-0705 for (i = 0; i < ppost->di_post_num; i++) {*/
                for (i = 0; i < mm->cfg.num_post; i++) {
                        buf_p = &pbuf_post[i];
-                       if (ppost->keep_buf_post        &&
-                           i == ppost->keep_buf_post->index)
+
+                       if (di_que_is_in_que(channel, QUE_POST_KEEP, buf_p))
                                continue;
 
                        if (!buf_p->pages) {
-                               PR_ERR("2:%s:post buf[%d] is null\n",
+                               PR_INF("2:%s:post buf[%d] is null\n",
                                       __func__, i);
                                continue;
                        }
@@ -1995,11 +1998,11 @@ bool dim_cma_top_release(unsigned int ch)
 
 #ifdef CONFIG_CMA
        di_cma_release(de_devp, ch);
-
 #endif
        return true;
 }
 
+#ifdef DIM_HIS /*no use*/
 /*******************************************
  *
  *
@@ -2036,6 +2039,7 @@ void keep_buf_in_full(struct di_buf_s *ready_buf)
                        di_keep_buf[i] = ready_buf;
        }
 }
+#endif
 
 int di_cnt_buf(int width, int height, int prog_flag, int mc_mm,
               int bit10_support, int pack422)
@@ -2134,7 +2138,7 @@ static int di_init_buf(int width, int height, unsigned char prog_flag,
        struct di_post_stru_s *ppost = get_post_stru(channel);
        struct di_buf_s *keep_buf = ppost->keep_buf;
        struct di_dev_s *de_devp = get_dim_de_devp();
-       struct di_buf_s *keep_buf_post = ppost->keep_buf_post;
+/*     struct di_buf_s *keep_buf_post = ppost->keep_buf_post;*/
        struct di_mm_s *mm = dim_mm_get(); /*mm-0705*/
 
        unsigned int mem_st_local;
@@ -2361,11 +2365,11 @@ static int di_init_buf(int width, int height, unsigned char prog_flag,
                if (di_buf) {
                        if (dimp_get(eDI_MP_post_wr_en) &&
                            dimp_get(eDI_MP_post_wr_support)) {
-                               /*ary:for keep buf*/
-                               if (keep_buf_post && di_buf == keep_buf_post) {
-                                       dbg_reg("%s:post keep buf %d:%d\n",
+                               if (di_que_is_in_que(channel, QUE_POST_KEEP,
+                                                    di_buf)) {
+                                       dbg_reg("%s:post keep buf %d\n",
                                                __func__,
-                                               i, keep_buf_post->index);
+                                               di_buf->index);
                                        continue;
                                }
                        }
@@ -2405,6 +2409,7 @@ static int di_init_buf(int width, int height, unsigned char prog_flag,
        return 0;
 }
 
+#ifdef DIM_HIS /*no use*/
 void dim_keep_mirror_buffer(unsigned int channel)      /*not use*/
 {
        struct di_buf_s *p = NULL;
@@ -2444,6 +2449,7 @@ void dim_keep_mirror_buffer(unsigned int channel) /*not use*/
        }
        }
 }
+#endif
 
 void dim_post_keep_mirror_buffer(unsigned int channel)
 {
@@ -2471,6 +2477,247 @@ void dim_post_keep_mirror_buffer(unsigned int channel)
        }
 }
 
+void dim_post_keep_mirror_buffer2(unsigned int ch)
+{
+       struct di_buf_s *p = NULL;
+       int itmp;
+
+       queue_for_each_entry(p, ch, QUEUE_DISPLAY, list) {
+               if (p->type != VFRAME_TYPE_POST ||
+                   !p->process_fun_index) {
+                       dbg_keep("%s:not post buf:%d\n", __func__, p->type);
+                       continue;
+               }
+               if (di_que_is_in_que(ch, QUE_POST_BACK, p)) {
+                       dbg_keep("%s:is in back[%d]\n", __func__, p->index);
+                       continue;
+               }
+
+               p->queue_index = -1;
+               di_que_in(ch, QUE_POST_KEEP, p);
+               p->invert_top_bot_flag = 0;
+
+               dbg_keep("%s %d\n", __func__, p->index);
+       }
+}
+
+bool dim_post_keep_is_in(unsigned int ch, struct di_buf_s *di_buf)
+{
+       if (di_que_is_in_que(ch, QUE_POST_KEEP, di_buf))
+               return true;
+       return false;
+}
+
+bool dim_post_keep_release_one(unsigned int ch, unsigned int di_buf_index)
+{
+       struct di_buf_s *pbuf_post;
+       struct di_buf_s *di_buf;
+
+       /*must post or err*/
+       pbuf_post = get_buf_post(ch);
+       di_buf = &pbuf_post[di_buf_index];
+
+       if (!di_que_is_in_que(ch, QUE_POST_KEEP, di_buf)) {
+               PR_ERR("%s:buf[%d] is not in keep\n", __func__, di_buf_index);
+               return false;
+       }
+       di_que_out_not_fifo(ch, QUE_POST_KEEP, di_buf);
+       di_que_in(ch, QUE_POST_FREE, di_buf);
+       dbg_keep("%s:buf[%d]\n", __func__, di_buf_index);
+       return true;
+}
+
+bool dim_post_keep_release_all_2free(unsigned int ch)
+{
+       struct di_buf_s *di_buf;
+       struct di_buf_s *pbuf_post;
+       unsigned int i = 0;
+
+       if (di_que_is_empty(ch, QUE_POST_KEEP))
+               return true;
+
+       pbuf_post = get_buf_post(ch);
+       dbg_keep("%s:ch[%d]\n", __func__, ch);
+
+       while (i <= MAX_POST_BUF_NUM) {
+               i++;
+               di_buf = di_que_peek(ch, QUE_POST_KEEP);
+               if (!di_buf)
+                       break;
+
+               if (!di_que_out(ch, QUE_POST_KEEP, di_buf)) {
+                       PR_ERR("%s:out err\n", __func__);
+                       break;
+               }
+
+               di_que_in(ch, QUE_POST_FREE, di_buf);
+
+               dbg_keep("\ttype[%d],index[%d]\n", di_buf->type, di_buf->index);
+       }
+
+       return true;
+}
+
+void dim_post_keep_cmd_release(unsigned int ch, struct vframe_s *vframe)
+{
+       struct di_buf_s *di_buf;
+
+       if (!vframe)
+               return;
+
+       di_buf = (struct di_buf_s *)vframe->private_data;
+
+       if (!di_buf) {
+               PR_WARN("%s:ch[%d]:no di_buf\n", __func__, ch);
+               return;
+       }
+
+       if (di_buf->type != VFRAME_TYPE_POST) {
+               PR_WARN("%s:ch[%d]:not post\n", __func__, ch);
+               return;
+       }
+       dbg_keep("release keep ch[%d],index[%d]\n",
+                di_buf->channel,
+                di_buf->index);
+       task_send_cmd(LCMD2(ECMD_RL_KEEP, di_buf->channel, di_buf->index));
+}
+EXPORT_SYMBOL(dim_post_keep_cmd_release);
+
+void dim_post_keep_cmd_release2(struct vframe_s *vframe)
+{
+       struct di_buf_s *di_buf;
+
+       if (!vframe)
+               return;
+
+       di_buf = (struct di_buf_s *)vframe->private_data;
+
+       if (!di_buf) {
+               PR_WARN("%s:no di_buf\n", __func__);
+               return;
+       }
+
+       if (di_buf->type != VFRAME_TYPE_POST) {
+               PR_WARN("%s:ch[%d]:not post\n", __func__, di_buf->channel);
+               return;
+       }
+       dbg_keep("release keep ch[%d],index[%d]\n",
+                di_buf->channel,
+                di_buf->index);
+       task_send_cmd(LCMD2(ECMD_RL_KEEP, di_buf->channel, di_buf->index));
+}
+EXPORT_SYMBOL(dim_post_keep_cmd_release2);
+
+void dim_dbg_release_keep_all(unsigned int ch)
+{
+       unsigned int tmpa[MAX_FIFO_SIZE];
+       unsigned int psize, itmp;
+       struct di_buf_s *p;
+
+       di_que_list(ch, QUE_POST_KEEP, &tmpa[0], &psize);
+       dbg_keep("post_keep: curr(%d)\n", psize);
+
+       for (itmp = 0; itmp < psize; itmp++) {
+               p = pw_qindex_2_buf(ch, tmpa[itmp]);
+               dbg_keep("\ttype[%d],index[%d]\n", p->type, p->index);
+               dim_post_keep_cmd_release(ch, p->vframe);
+       }
+       dbg_keep("%s:end\n", __func__);
+}
+
+void dim_post_keep_back_recycle(unsigned int ch)
+{
+       unsigned int tmpa[MAX_FIFO_SIZE];
+       unsigned int psize, itmp;
+       struct di_buf_s *p;
+
+       if (di_que_is_empty(ch, QUE_POST_KEEP_BACK))
+               return;
+       di_que_list(ch, QUE_POST_KEEP_BACK, &tmpa[0], &psize);
+       dbg_keep("post_keep_back: curr(%d)\n", psize);
+       for (itmp = 0; itmp < psize; itmp++) {
+               p = pw_qindex_2_buf(ch, tmpa[itmp]);
+               dbg_keep("keep back recycle %d\n", p->index);
+               dim_post_keep_release_one(ch, p->index);
+       }
+       pw_queue_clear(ch, QUE_POST_KEEP_BACK);
+}
+
+void dim_post_keep_cmd_proc(unsigned int ch, unsigned int index)
+{
+       struct di_dev_s *di_dev;
+       enum EDI_TOP_STATE chst;
+       unsigned int len_keep, len_back;
+       struct di_buf_s *pbuf_post;
+       struct di_buf_s *di_buf;
+
+       /*must post or err*/
+       di_dev = get_dim_de_devp();
+
+       if (!di_dev || !di_dev->data_l) {
+               PR_WARN("%s: no di_dev\n", __func__);
+               return;
+       }
+
+       chst = dip_chst_get(ch);
+       switch (chst) {
+       case EDI_TOP_STATE_READY:
+               dim_post_keep_release_one(ch, index);
+               break;
+       case EDI_TOP_STATE_IDLE:
+       case eDI_TOP_STATE_BYPASS:
+               pbuf_post = get_buf_post(ch);
+               if (!pbuf_post) {
+                       PR_ERR("%s:no pbuf_post\n", __func__);
+                       break;
+               }
+
+               di_buf = &pbuf_post[index];
+               di_buf->queue_index = -1;
+               di_que_in(ch, QUE_POST_KEEP_BACK, di_buf);
+               len_keep = di_que_list_count(ch, QUE_POST_KEEP);
+               len_back = di_que_list_count(ch, QUE_POST_KEEP_BACK);
+               if (len_back >= len_keep) {
+                       /*release all*/
+                       pw_queue_clear(ch, QUE_POST_KEEP);
+                       pw_queue_clear(ch, QUE_POST_KEEP_BACK);
+                       dip_wq_cma_run(ch, false);
+               }
+               break;
+       case eDI_TOP_STATE_REG_STEP1:
+       case eDI_TOP_STATE_REG_STEP1_P1:
+       case eDI_TOP_STATE_REG_STEP2:
+               pbuf_post = get_buf_post(ch);
+               if (!pbuf_post) {
+                       PR_ERR("%s:no pbuf_post\n", __func__);
+                       break;
+               }
+
+               di_buf = &pbuf_post[index];
+               di_buf->queue_index = -1;
+               di_que_in(ch, QUE_POST_KEEP_BACK, di_buf);
+
+               break;
+       case eDI_TOP_STATE_UNREG_STEP1:
+               pbuf_post = get_buf_post(ch);
+               if (!pbuf_post) {
+                       PR_ERR("%s:no pbuf_post\n", __func__);
+                       break;
+               }
+
+               di_buf = &pbuf_post[index];
+               di_buf->queue_index = -1;
+               di_que_in(ch, QUE_POST_KEEP_BACK, di_buf);
+               break;
+       default:
+               PR_ERR("%s:do nothing? %s:%d\n",
+                      __func__,
+                      dip_chst_get_name(chst),
+                      index);
+               break;
+       }
+}
+
 void dim_uninit_buf(unsigned int disable_mirror, unsigned int channel)
 {
        /*int i = 0;*/
@@ -2498,7 +2745,7 @@ void dim_uninit_buf(unsigned int disable_mirror, unsigned int channel)
        }
 #else
        if (!disable_mirror)
-               dim_post_keep_mirror_buffer(channel);
+               dim_post_keep_mirror_buffer2(channel);
 #endif
        queue_init(channel, 0);
        di_que_init(channel); /*new que*/
@@ -6648,7 +6895,8 @@ void dim_unreg_process(unsigned int channel)
 
 void di_unreg_setting(void)
 {
-       unsigned int mirror_disable = get_blackout_policy();
+       /*unsigned int mirror_disable = get_blackout_policy();*/
+       unsigned int mirror_disable = 0;
 
        if (!get_hw_reg_flg()) {
                PR_ERR("%s:have setting?do nothing\n", __func__);
@@ -6748,7 +6996,8 @@ void di_unreg_variable(unsigned int channel)
 #endif
        pr_info("%s:\n", __func__);
        set_init_flag(channel, false);  /*init_flag = 0;*/
-       mirror_disable = get_blackout_policy();
+       /*mirror_disable = get_blackout_policy();*/
+       mirror_disable = 0;
        di_lock_irqfiq_save(irq_flag2);
        dim_print("%s: dim_uninit_buf\n", __func__);
        dim_uninit_buf(mirror_disable, channel);
@@ -7138,9 +7387,10 @@ void di_reg_setting(unsigned int channel, struct vframe_s *vframe)
                /*if (!use_2_interlace_buff) {*/
                if (1) {
                        dim_top_gate_control(true, true);
-                       dim_post_gate_control(true);
+                       /*dim_post_gate_control(true);*/
                        /* freerun for reg configuration */
-                       dimh_enable_di_post_mif(GATE_AUTO);
+                       /*dimh_enable_di_post_mif(GATE_AUTO);*/
+                       hpst_power_ctr(true);
                } else {
                        dim_top_gate_control(true, false);
                }
@@ -7622,7 +7872,7 @@ struct vframe_s *di_vf_l_get(unsigned int channel)
        }
 
        /**************************/
-       if (list_count(channel, QUEUE_DISPLAY) > 2) {
+       if (list_count(channel, QUEUE_DISPLAY) > DI_POST_GET_LIMIT) {
                dim_tr_ops.post_get2(2);
                return NULL;
        }
@@ -7794,7 +8044,12 @@ void di_vf_l_put(struct vframe_s *vf, unsigned char channel)
                recycle_vframe_type_post_print(di_buf, __func__, __LINE__);
 #endif
 #else
+               #ifdef DIM_HIS /*no use*/
                pw_queue_in(channel, QUE_POST_BACK, di_buf->index);
+               #else
+               di_buf->queue_index = -1;
+               di_que_in(channel, QUE_POST_BACK, di_buf);
+               #endif
 #endif
        } else {
                di_lock_irqfiq_save(irq_flag2);
@@ -7811,15 +8066,13 @@ void di_vf_l_put(struct vframe_s *vf, unsigned char channel)
 void dim_recycle_post_back(unsigned int channel)
 {
        struct di_buf_s *di_buf = NULL;
-       unsigned int post_buf_index;
-       struct di_buf_s *pbuf_post = get_buf_post(channel);
        ulong irq_flag2 = 0;
+       unsigned int i = 0;
 
-       struct di_post_stru_s *ppost = get_post_stru(channel);
-
-       if (pw_queue_empty(channel, QUE_POST_BACK))
+       if (di_que_is_empty(channel, QUE_POST_BACK))
                return;
 
+       #ifdef DIM_HIS /*history*/
        while (pw_queue_out(channel, QUE_POST_BACK, &post_buf_index)) {
                /*pr_info("dp2:%d\n", post_buf_index);*/
                if (post_buf_index >= MAX_POST_BUF_NUM) {
@@ -7836,6 +8089,39 @@ void dim_recycle_post_back(unsigned int channel)
                recycle_vframe_type_post(di_buf, channel);
                di_unlock_irqfiq_restore(irq_flag2);
        }
+       #else
+       while (i < MAX_FIFO_SIZE) {
+               i++;
+
+               di_buf = di_que_peek(channel, QUE_POST_BACK);
+               /*pr_info("dp2:%d\n", post_buf_index);*/
+               if (!di_buf)
+                       break;
+
+               if (di_buf->type != VFRAME_TYPE_POST) {
+                       queue_out(channel, di_buf);
+                       PR_ERR("%s:type is not post\n", __func__);
+                       continue;
+               }
+
+               dim_print("di_back:%d\n", di_buf->index);
+               di_lock_irqfiq_save(irq_flag2); /**/
+               di_que_out(channel, QUE_POST_BACK, di_buf);
+               di_buf->queue_index = QUEUE_DISPLAY;
+               queue_out(channel, di_buf);
+
+               if (!atomic_dec_and_test(&di_buf->di_cnt))
+                       PR_ERR("%s,di_cnt > 0\n", __func__);
+
+               /*recycle_vframe_type_post(di_buf, channel);*/
+               di_buf->invert_top_bot_flag = 0;
+               di_que_in(channel, QUE_POST_FREE, di_buf);
+
+               di_unlock_irqfiq_restore(irq_flag2);
+       }
+
+       #endif
+       #ifdef DIM_HIS /*history*/
        /*back keep_buf:*/
        if (ppost->keep_buf_post) {
                PR_INF("ch[%d]:%s:%d\n",
@@ -7847,6 +8133,10 @@ void dim_recycle_post_back(unsigned int channel)
                di_unlock_irqfiq_restore(irq_flag2);
                ppost->keep_buf_post = NULL;
        }
+       #else
+       if (di_cfg_top_get(EDI_CFG_KEEP_CLEAR_AUTO))
+               dim_post_keep_release_all_2free(channel);
+       #endif
 }
 
 struct vframe_s *di_vf_l_peek(unsigned int channel)
@@ -7878,7 +8168,7 @@ struct vframe_s *di_vf_l_peek(unsigned int channel)
        }
        /**************************/
        dim_log_buffer_state("pek", channel);
-
+       task_send_ready();
 #ifdef SUPPORT_START_FRAME_HOLD
        if ((disp_frame_count == 0) && (dim_is_bypass(NULL, channel) == 0)) {
                int ready_count = di_que_list_count(channel, QUE_POST_READY);
index 96abc673f676deb5be4f86a7dc66705e55524062..2cc8feb7f96c4187db499a6294041289ab514e9e 100644 (file)
 /* buffer management related */
 #define MAX_IN_BUF_NUM                         (4)
 #define MAX_LOCAL_BUF_NUM                      (7)
-#define MAX_POST_BUF_NUM                       (7)     /*(5)*/ /* 16 */
+#define MAX_POST_BUF_NUM                       (11)    /*(5)*/ /* 16 */
 
 #define VFRAME_TYPE_IN                         1
 #define VFRAME_TYPE_LOCAL                      2
 #define VFRAME_TYPE_POST                       3
 #define VFRAME_TYPE_NUM                                3
 
-#define DI_POST_GET_LIMIT                      4
+#define DI_POST_GET_LIMIT                      8
 #define DI_PRE_READY_LIMIT                     4
 /*vframe define*/
 #define vframe_t struct vframe_s
@@ -583,6 +583,7 @@ void dim_reg_timeout_inc(void);
 
 void dim_reg_process(unsigned int channel);
 bool is_bypass2(struct vframe_s *vf_in, unsigned int ch);
+void dim_post_keep_cmd_proc(unsigned int ch, unsigned int index);
 
 /*--------------------------*/
 int di_ori_event_unreg(unsigned int channel);
@@ -610,6 +611,8 @@ void di_vf_l_put(struct vframe_s *vf, unsigned char channel);
 struct vframe_s *di_vf_l_get(unsigned int channel);
 
 unsigned char pre_p_asi_de_buf_config(unsigned int ch);
+void dim_dbg_release_keep_all(unsigned int ch);
+void dim_post_keep_back_recycle(unsigned int ch);
 
 /*---------------------*/
 
index 153f6e07bbb531fffaf4bd3ddd2f06de8f28b760..8ddb257b397dc75aa7dcdf48759739c86554e7cb 100644 (file)
@@ -900,7 +900,6 @@ int dim_state_show(struct seq_file *seq, void *v, unsigned int channel)
        unsigned int psize; /*new que*/
        struct di_hpre_s  *pre = get_hw_pre();
        struct di_hpst_s *post = get_hw_pst();
-       struct di_buf_s *keep_buf_post = NULL;
        char *splt = "---------------------------";
        struct di_mm_s *mm = dim_mm_get();      /*mm-0705*/
 
@@ -933,17 +932,7 @@ int dim_state_show(struct seq_file *seq, void *v, unsigned int channel)
                                   IS_ERR_OR_NULL(p) ? -1 : p->index, p);
                }
        }
-       /********************************/
-       /* check keep buf post          */
-       /********************************/
-       keep_buf_post = di_post_stru_p->keep_buf_post;
 
-       if (IS_ERR_OR_NULL(keep_buf_post))
-               seq_printf(seq, "%s:NULL\n", "keep_buf_post");
-       else
-               seq_printf(seq, "%s:type=%d:index=%d\n",
-                          "keep_buf_post",
-                          keep_buf_post->type, keep_buf_post->index);
        /********************************/
        /* in_free_list                 */
        /********************************/
@@ -1056,8 +1045,33 @@ int dim_state_show(struct seq_file *seq, void *v, unsigned int channel)
        di_que_list(channel, QUE_POST_BACK, &tmpa[0], &psize); /*new que*/
        seq_printf(seq, "post_back: curr(%d)\n", psize);
 
-       for (itmp = 0; itmp < psize; itmp++) {                  /*new que*/
-               seq_printf(seq, "%d\n", tmpa[itmp]);
+       for (itmp = 0; itmp < psize; itmp++) {
+               p = pw_qindex_2_buf(channel, tmpa[itmp]);
+               seq_printf(seq, "\ttype[%d],index[%d]\n", p->type, p->index);
+       }
+       seq_printf(seq, "%s\n", splt);
+
+       /********************************/
+       /* post keep                    */
+       /********************************/
+       di_que_list(channel, QUE_POST_KEEP, &tmpa[0], &psize);
+       seq_printf(seq, "post_keep: curr(%d)\n", psize);
+
+       for (itmp = 0; itmp < psize; itmp++) {
+               p = pw_qindex_2_buf(channel, tmpa[itmp]);
+               seq_printf(seq, "\ttype[%d],index[%d]\n", p->type, p->index);
+       }
+       seq_printf(seq, "%s\n", splt);
+
+       /********************************
+        * post keep back
+        ********************************/
+       di_que_list(channel, QUE_POST_KEEP_BACK, &tmpa[0], &psize);
+       seq_printf(seq, "post_keep_back: curr(%d)\n", psize);
+
+       for (itmp = 0; itmp < psize; itmp++) {
+               p = pw_qindex_2_buf(channel, tmpa[itmp]);
+               seq_printf(seq, "\ttype[%d],index[%d]\n", p->type, p->index);
        }
        seq_printf(seq, "%s\n", splt);
 
index 5fa6bfb65c505f53df098a287ae26662151c0a7b..7a7baebd1ad6df06207e9bceba0ff3efcd7bd48b 100644 (file)
@@ -2680,8 +2680,10 @@ void dimh_initial_di_post_2(int hsize_post, int vsize_post,
                        DI_VSYNC_WR_MPEG_REG_BITS(VD1_AFBCD0_MISC_CTRL,
                                                  1, 8, 1);
                        #endif
+               #ifdef DIM_HIS
                        dim_VSYNC_WR_MPEG_REG_BITS(VD1_AFBCD0_MISC_CTRL,
                                                   0, 8, 1);
+               #endif
                } else {
                        dim_VSYNC_WR_MPEG_REG_BITS(VD1_AFBCD0_MISC_CTRL,
                                                   1, 8, 1);
@@ -3050,9 +3052,11 @@ void dimh_disable_post_deinterlace_2(void)
        if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) {
                /*dbg a dim_VSYNC_WR_MPEG_REG(DI_POST_GL_CTRL, 0);*/
                di_post_set_flow(1, eDI_POST_FLOW_STEP1_STOP);
+               #ifdef DIM_HIS
                dim_print("%s:VD1_AFBCD0_MISC_CTRL 0", __func__);
                dim_VSYNC_WR_MPEG_REG_BITS(VD1_AFBCD0_MISC_CTRL, 0, 8, 2);
                dim_VSYNC_WR_MPEG_REG_BITS(VD1_AFBCD0_MISC_CTRL, 0, 20, 2);
+               #endif
        }
 }
 
index bdec462730b3c9e8dc91fd02c1e5e46494adf687..b512d919a7abf1234988ed2051ce602fade2dc13 100644 (file)
@@ -64,6 +64,7 @@ enum eDI_CFG_TOP_IDX {
        eDI_CFG_BEGIN,
        eDI_CFG_first_bypass,
        eDI_CFG_ref_2,
+       EDI_CFG_KEEP_CLEAR_AUTO,
        eDI_CFG_END,
 
 };
@@ -360,16 +361,16 @@ struct di_hpst_s {
 /**************************************/
 /* channel status */
 /**************************************/
-enum eDI_TOP_STATE {
+enum EDI_TOP_STATE {
        eDI_TOP_STATE_NOPROB,
-       eDI_TOP_STATE_IDLE,     /*idle not work*/
+       EDI_TOP_STATE_IDLE,     /*idle not work*/
        /* STEP1
         * till peek vframe and set irq;before this state, event reg finish
         */
        eDI_TOP_STATE_REG_STEP1,
        eDI_TOP_STATE_REG_STEP1_P1,     /*2019-05-21*/
        eDI_TOP_STATE_REG_STEP2,        /*till alloc and ready*/
-       eDI_TOP_STATE_READY,            /*can do DI*/
+       EDI_TOP_STATE_READY,            /*can do DI*/
        eDI_TOP_STATE_BYPASS,           /*complet bypass*/
        eDI_TOP_STATE_UNREG_STEP1,      /*till pre/post is finish;*/
        /* do unreg and to IDLE.
@@ -415,6 +416,7 @@ union   DI_L_CMD_BITS {
 };
 
 #define LCMD1(id, ch)  ((id) | ((ch) << 8))
+#define LCMD2(id, ch, p2)      ((id) | ((ch) << 8) | ((p2) << 16))
 
 enum eCMD_LOCAL {
        eCMD_NONE,
@@ -422,18 +424,22 @@ enum eCMD_LOCAL {
        eCMD_UNREG,
        eCMD_READY,
        eCMD_CHG,
+       ECMD_RL_KEEP,
        NR_FINISH,
 };
 
-/**************************************/
-/*QUE*/
-/**************************************/
+/**************************************
+ * QUE
+ * keep same order as di_name_new_que
+ **************************************/
 enum QUE_TYPE {        /*mast start from 0 */
        QUE_IN_FREE,    /*5*/
        QUE_PRE_READY,  /*6*/
        QUE_POST_FREE,  /*7*/
        QUE_POST_READY, /*8*/
        QUE_POST_BACK,          /*new*/
+       QUE_POST_KEEP,  /*below use pw_queue_in*/
+       QUE_POST_KEEP_BACK,
        /*----------------*/
        QUE_DBG,
        QUE_NUB,
@@ -734,10 +740,11 @@ struct di_ores_s {
 };
 
 enum eDI_CMA_ST {
-       eDI_CMA_ST_IDL,
-       eDI_CMA_ST_ALLOC,       /*do*/
-       eDI_CMA_ST_READY,
-       eDI_CMA_ST_RELEASE,     /*do*/
+       EDI_CMA_ST_IDL,
+       EDI_CMA_ST_ALLOC,       /*do*/
+       EDI_CMA_ST_READY,
+       EDI_CMA_ST_RELEASE,     /*do*/
+       EDI_CMA_ST_PART,
 };
 
 /**********************************
@@ -805,10 +812,16 @@ struct di_meson_data {
        /*struct ddemod_reg_off regoff;*/
 };
 
-struct di_mng_s {
-       /*workqueue*/
+struct dim_wq_s {
+       char *name;
+       unsigned int ch;
        struct workqueue_struct *wq_cma;
        struct work_struct wq_work;
+};
+
+struct di_mng_s {
+       /*workqueue*/
+       struct dim_wq_s         wq;
 
        /*use enum eDI_CMA_ST*/
        atomic_t cma_mem_state[DI_CHANNEL_NUB];
@@ -958,6 +971,7 @@ struct di_data_l_s {
 
 #define DBG_M_POLLING          0x100
 #define DBG_M_ONCE             0x200
+#define DBG_M_KEEP             0x400
 
 extern unsigned int di_dbg;
 
@@ -986,6 +1000,7 @@ extern unsigned int di_dbg;
 #define dbg_first_frame(fmt, args ...) dbg_m(DBG_M_FIRSTFRAME, fmt, ##args)
 #define dbg_dbg(fmt, args ...)         dbg_m(DBG_M_DBG, fmt, ##args)
 #define dbg_once(fmt, args ...)                dbg_m(DBG_M_ONCE, fmt, ##args)
+#define dbg_keep(fmt, args ...)                dbg_m(DBG_M_KEEP, fmt, ##args)
 
 char *di_cfgx_get_name(enum eDI_CFGX_IDX idx);
 bool di_cfgx_get(unsigned int ch, enum eDI_CFGX_IDX idx);
index 9c7763bcd7339292edecae8015c867297cfd2b8b..e14346f603b280d1350531f93ebe3e26f07a14eb 100644 (file)
@@ -1010,6 +1010,40 @@ static ssize_t wcfgx_store(struct file *file, const char __user *userbuf,
        return count;
 }
 
+/***********************************************
+ *
+ ***********************************************/
+ssize_t keep_buf_clear_store(struct file *file, const char __user *userbuf,
+                            size_t count, loff_t *ppos)
+{
+       char buf[20];
+       int ret;
+
+       unsigned int ch;
+
+       count = min_t(size_t, count, (sizeof(buf) - 1));
+       if (copy_from_user(buf, userbuf, count))
+               return -EFAULT;
+
+       buf[count] = 0;
+       /*reg, bit, width, val*/
+
+       ret = kstrtouint(buf, 0, &ch);
+       if (ret) {
+               pr_info("war:please enter ch\n");
+               return 0;
+       }
+       pr_info("ch:%d", ch);
+
+       if (ch >= DI_CHANNEL_NUB) {
+               PR_ERR("%s:ch is overflow %d\n", __func__, ch);
+               return 0;
+       }
+
+       dim_dbg_release_keep_all(ch);
+
+       return count;
+}
 /***************************************************************
  * parameter show and store for top : DI
  **************************************************************/
@@ -1519,6 +1553,7 @@ DEFINE_STORE_ONLY(mpw_nr);
 DEFINE_STORE_ONLY(mpw_pd);
 DEFINE_STORE_ONLY(mpw_mtn);
 DEFINE_STORE_ONLY(buf_cnt);
+DEFINE_STORE_ONLY(keep_buf_clear);
 
 DEFINE_SHOW_STORE(reg);
 
@@ -1550,6 +1585,7 @@ static const struct di_dbgfs_files_t di_debugfs_files_top[] = {
        {"mr_mtn", S_IFREG | 0644, &mpr_mtn_fops},
        {"mw_mtn", S_IFREG | 0644, &mpw_mtn_fops},
        {"buf_cnt", S_IFREG | 0644, &buf_cnt_fops},
+       {"keep_clear", S_IFREG | 0644, &keep_buf_clear_fops},
 };
 
 static const struct di_dbgfs_files_t di_debugfs_files[] = {
index 8929fdfd4d12b69460395dfb42f2da1398c721e2..3e65aa47a6eb41bce5e221833d9df25ea1933bf5 100644 (file)
@@ -49,6 +49,8 @@ const struct di_cfg_ctr_s di_cfg_top_ctr[K_DI_CFG_NUB] = {
                eDI_CFG_first_bypass, 1},
        [eDI_CFG_ref_2]  = {"ref_2",
                eDI_CFG_ref_2, 0},
+       [EDI_CFG_KEEP_CLEAR_AUTO]  = {"keep_buf clear auto",
+               EDI_CFG_KEEP_CLEAR_AUTO, 1},
        [eDI_CFG_END]  = {"cfg top end ", eDI_CFG_END, 0},
 
 };
@@ -823,7 +825,7 @@ static void dip_cma_init_val(void)
 
        for (ch = 0; ch < DI_CHANNEL_NUB; ch++) {
                /* CMA state */
-               atomic_set(&pbm->cma_mem_state[ch], eDI_CMA_ST_IDL);
+               atomic_set(&pbm->cma_mem_state[ch], EDI_CMA_ST_IDL);
 
                /* CMA reg/unreg cmd */
                pbm->cma_reg_cmd[ch] = 0;
@@ -842,7 +844,7 @@ void dip_cma_close(void)
                if (!dip_cma_st_is_idle(ch)) {
                        dim_cma_top_release(ch);
                        pr_info("%s:force release ch[%d]", __func__, ch);
-                       atomic_set(&pbm->cma_mem_state[ch], eDI_CMA_ST_IDL);
+                       atomic_set(&pbm->cma_mem_state[ch], EDI_CMA_ST_IDL);
 
                        pbm->cma_reg_cmd[ch] = 0;
                }
@@ -851,48 +853,78 @@ void dip_cma_close(void)
 
 static void dip_wq_cma_handler(struct work_struct *work)
 {
-       unsigned int ch;
        struct di_mng_s *pbm = get_bufmng();
        enum eDI_CMA_ST cma_st;
        bool do_flg;
+       struct dim_wq_s *wq = container_of(work, struct dim_wq_s, wq_work);
 
-       pr_info("%s:start\n", __func__);
-       for (ch = 0; ch < DI_CHANNEL_NUB; ch++) {
-               do_flg = false;
-               cma_st = dip_cma_get_st(ch);
-               switch (cma_st) {
-               case eDI_CMA_ST_IDL:
-                       if (pbm->cma_reg_cmd[ch]) {
-                               do_flg = true;
-                               /*set:alloc:*/
+       unsigned int ch = wq->ch;
+
+       pr_info("%s:ch[%d],start\n", __func__, ch);
+
+       do_flg = false;
+       cma_st = dip_cma_get_st(ch);
+       switch (cma_st) {
+       case EDI_CMA_ST_IDL:
+               if (pbm->cma_reg_cmd[ch]) {
+                       do_flg = true;
+                       /*set:alloc:*/
+                       atomic_set(&pbm->cma_mem_state[ch], EDI_CMA_ST_ALLOC);
+                       if (dim_cma_top_alloc(ch)) {
                                atomic_set(&pbm->cma_mem_state[ch],
-                                          eDI_CMA_ST_ALLOC);
-                               if (dim_cma_top_alloc(ch)) {
-                                       atomic_set(&pbm->cma_mem_state[ch],
-                                                  eDI_CMA_ST_READY);
-                               }
+                                          EDI_CMA_ST_READY);
                        }
-                       break;
-               case eDI_CMA_ST_READY:
-                       if (!pbm->cma_reg_cmd[ch]) {
-                               do_flg = true;
+               }
+               break;
+       case EDI_CMA_ST_READY:
+
+               if (!pbm->cma_reg_cmd[ch]) {
+                       do_flg = true;
+                       atomic_set(&pbm->cma_mem_state[ch],
+                                  EDI_CMA_ST_RELEASE);
+                       dim_cma_top_release(ch);
+                       if (di_que_is_empty(ch, QUE_POST_KEEP))
+                               atomic_set(&pbm->cma_mem_state[ch],
+                                          EDI_CMA_ST_IDL);
+                       else
                                atomic_set(&pbm->cma_mem_state[ch],
-                                          eDI_CMA_ST_RELEASE);
-                               dim_cma_top_release(ch);
+                                          EDI_CMA_ST_PART);
+               }
+               break;
+       case EDI_CMA_ST_PART:
+               if (pbm->cma_reg_cmd[ch]) {
+                       do_flg = true;
+                       /*set:alloc:*/
+                       atomic_set(&pbm->cma_mem_state[ch], EDI_CMA_ST_ALLOC);
+                       if (dim_cma_top_alloc(ch)) {
                                atomic_set(&pbm->cma_mem_state[ch],
-                                          eDI_CMA_ST_IDL);
+                                          EDI_CMA_ST_READY);
                        }
-                       break;
-               case eDI_CMA_ST_ALLOC:  /*do*/
-               case eDI_CMA_ST_RELEASE:/*do*/
-               default:
-                       break;
+               } else {
+                       do_flg = true;
+                       atomic_set(&pbm->cma_mem_state[ch],
+                                  EDI_CMA_ST_RELEASE);
+                       dim_cma_top_release(ch);
+                       if (di_que_is_empty(ch, QUE_POST_KEEP))
+                               atomic_set(&pbm->cma_mem_state[ch],
+                                          EDI_CMA_ST_IDL);
+                       else
+                               atomic_set(&pbm->cma_mem_state[ch],
+                                          EDI_CMA_ST_PART);
+
                }
-               if (!do_flg)
-                       pr_info("\tch[%d],do nothing[%d]\n", ch, cma_st);
-               else
-                       task_send_ready();
+
+               break;
+       case EDI_CMA_ST_ALLOC:  /*do*/
+       case EDI_CMA_ST_RELEASE:/*do*/
+       default:
+               break;
        }
+       if (!do_flg)
+               pr_info("\tch[%d],do nothing[%d]\n", ch, cma_st);
+       else
+               task_send_ready();
+
        pr_info("%s:end\n", __func__);
 }
 
@@ -900,16 +932,16 @@ static void dip_wq_prob(void)
 {
        struct di_mng_s *pbm = get_bufmng();
 
-       pbm->wq_cma = create_singlethread_workqueue("deinterlace");
-       INIT_WORK(&pbm->wq_work, dip_wq_cma_handler);
+       pbm->wq.wq_cma = create_singlethread_workqueue("deinterlace");
+       INIT_WORK(&pbm->wq.wq_work, dip_wq_cma_handler);
 }
 
 static void dip_wq_ext(void)
 {
        struct di_mng_s *pbm = get_bufmng();
 
-       cancel_work_sync(&pbm->wq_work);
-       destroy_workqueue(pbm->wq_cma);
+       cancel_work_sync(&pbm->wq.wq_work);
+       destroy_workqueue(pbm->wq.wq_cma);
        pr_info("%s:finish\n", __func__);
 }
 
@@ -922,7 +954,8 @@ void dip_wq_cma_run(unsigned char ch, bool reg_cmd)
        else
                pbm->cma_reg_cmd[ch] = 0;
 
-       queue_work(pbm->wq_cma, &pbm->wq_work);
+       pbm->wq.ch = ch;
+       queue_work(pbm->wq.wq_cma, &pbm->wq.wq_work);
 }
 
 bool dip_cma_st_is_ready(unsigned int ch)
@@ -930,7 +963,7 @@ bool dip_cma_st_is_ready(unsigned int ch)
        struct di_mng_s *pbm = get_bufmng();
        bool ret = false;
 
-       if (atomic_read(&pbm->cma_mem_state[ch]) == eDI_CMA_ST_READY)
+       if (atomic_read(&pbm->cma_mem_state[ch]) == EDI_CMA_ST_READY)
                ret = true;
 
        return ret;
@@ -941,7 +974,7 @@ bool dip_cma_st_is_idle(unsigned int ch)
        struct di_mng_s *pbm = get_bufmng();
        bool ret = false;
 
-       if (atomic_read(&pbm->cma_mem_state[ch]) == eDI_CMA_ST_IDL)
+       if (atomic_read(&pbm->cma_mem_state[ch]) == EDI_CMA_ST_IDL)
                ret = true;
 
        return ret;
@@ -954,7 +987,7 @@ bool dip_cma_st_is_idl_all(void)
        bool ret = true;
 
        for (ch = 0; ch < DI_CHANNEL_NUB; ch++) {
-               if (atomic_read(&pbm->cma_mem_state[ch]) != eDI_CMA_ST_IDL) {
+               if (atomic_read(&pbm->cma_mem_state[ch]) != EDI_CMA_ST_IDL) {
                        ret = true;
                        break;
                }
@@ -981,7 +1014,7 @@ const char *di_cma_dbg_get_st_name(unsigned int ch)
        enum eDI_CMA_ST st = dip_cma_get_st(ch);
        const char *p = "";
 
-       if (st <= eDI_CMA_ST_RELEASE)
+       if (st <= EDI_CMA_ST_RELEASE)
                p = di_cma_state_name[st];
        return p;
 }
@@ -992,20 +1025,20 @@ void dip_cma_st_set_ready_all(void)
        struct di_mng_s *pbm = get_bufmng();
 
        for (ch = 0; ch < DI_CHANNEL_NUB; ch++)
-               atomic_set(&pbm->cma_mem_state[ch], eDI_CMA_ST_READY);
+               atomic_set(&pbm->cma_mem_state[ch], EDI_CMA_ST_READY);
 }
 
 /****************************/
 /*channel STATE*/
 /****************************/
-void dip_chst_set(unsigned int ch, enum eDI_TOP_STATE chSt)
+void dip_chst_set(unsigned int ch, enum EDI_TOP_STATE chst)
 {
        struct di_mng_s *pbm = get_bufmng();
 
-       atomic_set(&pbm->ch_state[ch], chSt);
+       atomic_set(&pbm->ch_state[ch], chst);
 }
 
-enum eDI_TOP_STATE dip_chst_get(unsigned int ch)
+enum EDI_TOP_STATE dip_chst_get(unsigned int ch)
 {
        struct di_mng_s *pbm = get_bufmng();
 
@@ -1017,12 +1050,12 @@ void dip_chst_init(void)
        unsigned int ch;
 
        for (ch = 0; ch < DI_CHANNEL_NUB; ch++)
-               dip_chst_set(ch, eDI_TOP_STATE_IDLE);
+               dip_chst_set(ch, EDI_TOP_STATE_IDLE);
 }
 
 bool dip_event_reg_chst(unsigned int ch)
 {
-       enum eDI_TOP_STATE chst;
+       enum EDI_TOP_STATE chst;
        struct di_pre_stru_s *ppre = get_pre_stru(ch);
        bool err_flg = false;
        bool ret = true;
@@ -1035,7 +1068,7 @@ bool dip_event_reg_chst(unsigned int ch)
                set_flag_trig_unreg(ch, false);
 #endif
        switch (chst) {
-       case eDI_TOP_STATE_IDLE:
+       case EDI_TOP_STATE_IDLE:
 
                queue_init2(ch);
                di_que_init(ch);
@@ -1048,7 +1081,7 @@ bool dip_event_reg_chst(unsigned int ch)
        case eDI_TOP_STATE_REG_STEP1:
        case eDI_TOP_STATE_REG_STEP1_P1:
        case eDI_TOP_STATE_REG_STEP2:
-       case eDI_TOP_STATE_READY:
+       case EDI_TOP_STATE_READY:
        case eDI_TOP_STATE_BYPASS:
                PR_WARN("have reg\n");
                ret = false;
@@ -1057,7 +1090,7 @@ bool dip_event_reg_chst(unsigned int ch)
        case eDI_TOP_STATE_UNREG_STEP2:
                /*wait*/
                ppre->reg_req_flag_cnt = 0;
-               while (dip_chst_get(ch) != eDI_TOP_STATE_IDLE) {
+               while (dip_chst_get(ch) != EDI_TOP_STATE_IDLE) {
                        usleep_range(10000, 10001);
                        if (ppre->reg_req_flag_cnt++ >
                                dim_get_reg_unreg_cnt()) {
@@ -1093,7 +1126,7 @@ bool dip_event_reg_chst(unsigned int ch)
 
 bool dip_event_unreg_chst(unsigned int ch)
 {
-       enum eDI_TOP_STATE chst, chst2;
+       enum EDI_TOP_STATE chst, chst2;
        struct di_pre_stru_s *ppre = get_pre_stru(ch);
        bool ret = false;
        bool err_flg = false;
@@ -1109,7 +1142,7 @@ bool dip_event_unreg_chst(unsigned int ch)
                set_flag_trig_unreg(ch, true);
 
        switch (chst) {
-       case eDI_TOP_STATE_READY:
+       case EDI_TOP_STATE_READY:
 
                di_vframe_unreg(ch);
                /*trig unreg*/
@@ -1121,7 +1154,7 @@ bool dip_event_unreg_chst(unsigned int ch)
                ppre->unreg_req_flag_cnt = 0;
                chst2 = dip_chst_get(ch);
 
-               while (chst2 != eDI_TOP_STATE_IDLE) {
+               while (chst2 != EDI_TOP_STATE_IDLE) {
                        task_send_ready();
                        usleep_range(10000, 10001);
                        /*msleep(5);*/
@@ -1161,18 +1194,18 @@ bool dip_event_unreg_chst(unsigned int ch)
                        dpre_init();
                        dpost_init();
                }
-               dip_chst_set(ch, eDI_TOP_STATE_IDLE);
+               dip_chst_set(ch, EDI_TOP_STATE_IDLE);
                ret = true;
 
                break;
-       case eDI_TOP_STATE_IDLE:
+       case EDI_TOP_STATE_IDLE:
                PR_WARN("have unreg\n");
                break;
        case eDI_TOP_STATE_REG_STEP1:
                dbg_dbg("%s:in reg step1\n", __func__);
                di_vframe_unreg(ch);
                set_reg_flag(ch, false);
-               dip_chst_set(ch, eDI_TOP_STATE_IDLE);
+               dip_chst_set(ch, EDI_TOP_STATE_IDLE);
 
                ret = true;
                break;
@@ -1199,7 +1232,7 @@ bool dip_event_unreg_chst(unsigned int ch)
                ppre->unreg_req_flag_cnt = 0;
                chst2 = dip_chst_get(ch);
 
-               while (chst2 != eDI_TOP_STATE_IDLE) {
+               while (chst2 != EDI_TOP_STATE_IDLE) {
                        task_send_ready();
                        usleep_range(10000, 10001);
                        /*msleep(5);*/
@@ -1232,7 +1265,7 @@ bool dip_event_unreg_chst(unsigned int ch)
                        dpost_init();
                }
 
-               dip_chst_set(ch, eDI_TOP_STATE_IDLE);
+               dip_chst_set(ch, EDI_TOP_STATE_IDLE);
 
                ret = true;
                break;
@@ -1242,7 +1275,7 @@ bool dip_event_unreg_chst(unsigned int ch)
 
                /*wait*/
                ppre->unreg_req_flag_cnt = 0;
-               while (dip_chst_get(ch) != eDI_TOP_STATE_IDLE) {
+               while (dip_chst_get(ch) != EDI_TOP_STATE_IDLE) {
                        usleep_range(10000, 10001);
                        if (ppre->unreg_req_flag_cnt++ >
                                dim_get_reg_unreg_cnt()) {
@@ -1269,7 +1302,7 @@ bool dip_event_unreg_chst(unsigned int ch)
 /*process for reg and unreg cmd*/
 void dip_chst_process_reg(unsigned int ch)
 {
-       enum eDI_TOP_STATE chst;
+       enum EDI_TOP_STATE chst;
        struct vframe_s *vframe;
        struct di_pre_stru_s *ppre = get_pre_stru(ch);
        bool reflesh = true;
@@ -1283,7 +1316,7 @@ void dip_chst_process_reg(unsigned int ch)
 
        switch (chst) {
        case eDI_TOP_STATE_NOPROB:
-       case eDI_TOP_STATE_IDLE:
+       case EDI_TOP_STATE_IDLE:
                break;
        case eDI_TOP_STATE_REG_STEP1:/*wait peek*/
                vframe = pw_vf_peek(ch);
@@ -1363,7 +1396,7 @@ void dip_chst_process_reg(unsigned int ch)
                reflesh = true;
                break;
        case eDI_TOP_STATE_REG_STEP2:/*now no change to do*/
-               if (dip_cma_get_st(ch) == eDI_CMA_ST_READY) {
+               if (dip_cma_get_st(ch) == EDI_CMA_ST_READY) {
                        if (di_cfg_top_get(eDI_CFG_first_bypass)) {
                                if (get_sum_g(ch) == 0)
                                        dim_bypass_first_frame(ch);
@@ -1371,12 +1404,12 @@ void dip_chst_process_reg(unsigned int ch)
                                        PR_INF("ch[%d],g[%d]\n",
                                               ch, get_sum_g(ch));
                        }
-                       dip_chst_set(ch, eDI_TOP_STATE_READY);
+                       dip_chst_set(ch, EDI_TOP_STATE_READY);
                        set_reg_flag(ch, true);
                        /*move to step1 dim_bypass_first_frame(ch);*/
                }
                break;
-       case eDI_TOP_STATE_READY:
+       case EDI_TOP_STATE_READY:
 
                break;
        case eDI_TOP_STATE_BYPASS:
@@ -1408,7 +1441,7 @@ void dip_chst_process_reg(unsigned int ch)
                        dpost_init();
                }
 
-               dip_chst_set(ch, eDI_TOP_STATE_IDLE);
+               dip_chst_set(ch, EDI_TOP_STATE_IDLE);
                /*debug only dbg_reg("ch[%d]UNREG_STEP2 end\n",ch);*/
                break;
        }
@@ -1424,7 +1457,7 @@ void dip_chst_process_ch(void)
                chst = dip_chst_get(ch);
                switch (chst) {
                case eDI_TOP_STATE_REG_STEP2:
-                       if (dip_cma_get_st(ch) == eDI_CMA_ST_READY) {
+                       if (dip_cma_get_st(ch) == EDI_CMA_ST_READY) {
                                if (di_cfg_top_get(eDI_CFG_first_bypass)) {
                                        if (get_sum_g(ch) == 0)
                                                dim_bypass_first_frame(ch);
@@ -1432,7 +1465,7 @@ void dip_chst_process_ch(void)
                                                PR_INF("ch[%d],g[%d]\n",
                                                       ch, get_sum_g(ch));
                                }
-                               dip_chst_set(ch, eDI_TOP_STATE_READY);
+                               dip_chst_set(ch, EDI_TOP_STATE_READY);
                                set_reg_flag(ch, true);
                        }
                        break;
@@ -1454,9 +1487,14 @@ void dip_chst_process_ch(void)
                                dpost_init();
                        }
 
-                       dip_chst_set(ch, eDI_TOP_STATE_IDLE);
+                       dip_chst_set(ch, EDI_TOP_STATE_IDLE);
                        dbg_reg("ch[%d]STEP2 end\n", ch);
                        break;
+               case EDI_TOP_STATE_READY:
+                       dim_post_keep_back_recycle(ch);
+                       break;
+               default:
+                       break;
                }
        }
 }
@@ -1517,7 +1555,7 @@ const char * const di_top_state_name[] = {
 const char *dip_chst_get_name_curr(unsigned int ch)
 {
        const char *p = "";
-       enum eDI_TOP_STATE chst;
+       enum EDI_TOP_STATE chst;
 
        chst = dip_chst_get(ch);
 
@@ -1527,7 +1565,7 @@ const char *dip_chst_get_name_curr(unsigned int ch)
        return p;
 }
 
-const char *dip_chst_get_name(enum eDI_TOP_STATE chst)
+const char *dip_chst_get_name(enum EDI_TOP_STATE chst)
 {
        const char *p = "";
 
@@ -1858,7 +1896,6 @@ void do_table_working(struct do_table_s *pdo)
 void dip_init_value_reg(unsigned int ch)
 {
        struct di_post_stru_s *ppost;
-       struct di_buf_s *keep_post_buf;
        struct di_pre_stru_s *ppre = get_pre_stru(ch);
 
        pr_info("%s:\n", __func__);
@@ -1866,11 +1903,10 @@ void dip_init_value_reg(unsigned int ch)
        /*post*/
        ppost = get_post_stru(ch);
        /*keep buf:*/
-       keep_post_buf = ppost->keep_buf_post;
+       /*keep_post_buf = ppost->keep_buf_post;*/
 
        memset(ppost, 0, sizeof(struct di_post_stru_s));
        ppost->next_canvas_id = 1;
-       ppost->keep_buf_post = keep_post_buf;
 
        /*pre*/
        memset(ppre, 0, sizeof(struct di_pre_stru_s));
@@ -1890,6 +1926,10 @@ static bool dip_init_value(void)
 
                /*que*/
                ret = di_que_alloc(ch);
+               if (ret) {
+                       pw_queue_clear(ch, QUE_POST_KEEP);
+                       pw_queue_clear(ch, QUE_POST_KEEP_BACK);
+               }
        }
        set_current_channel(0);
 
index 8083bc469c0478964716885779181baaa68dbe69..86f73642e80de544f3c5ab5f177bf4237913cf9d 100644 (file)
@@ -48,9 +48,9 @@ void dip_hw_process(void);
 void dip_chst_process_ch(void);
 bool dip_chst_change_2unreg(void);
 
-enum eDI_TOP_STATE dip_chst_get(unsigned int ch);
+enum EDI_TOP_STATE dip_chst_get(unsigned int ch);
 const char *dip_chst_get_name_curr(unsigned int ch);
-const char *dip_chst_get_name(enum eDI_TOP_STATE chst);
+const char *dip_chst_get_name(enum EDI_TOP_STATE chst);
 
 /**************************************
  *
index 1d96da95874381c866d779426b465de3b786cf0d..8e8bad67f0ad85e55ebe2aafde3efe8898a6609f 100644 (file)
@@ -35,6 +35,8 @@ const char * const di_name_new_que[QUE_NUB] = {
        "QUE_POST_FREE",        /*2*/
        "QUE_POST_READY",       /*3*/
        "QUE_POST_BACK",        /*4*/
+       "QUE_POST_KEEP",
+       "QUE_POST_KEEP_BACK",
        "QUE_DBG",
 /*     "QUE_NUB",*/
 
@@ -42,7 +44,7 @@ const char * const di_name_new_que[QUE_NUB] = {
 
 #define que_dbg                dim_print
 
-static void pw_queue_clear(unsigned int ch, enum QUE_TYPE qtype)
+void pw_queue_clear(unsigned int ch, enum QUE_TYPE qtype)
 {
        struct di_ch_s *pch = get_chdata(ch);
 
@@ -166,6 +168,9 @@ bool pw_queue_empty(unsigned int ch, enum QUE_TYPE qtype)
        return false;
 }
 
+/**********************************************************
+ *
+ **********************************************************/
 int di_que_list_count(unsigned int ch, enum QUE_TYPE qtype)
 {
        struct di_ch_s *pch = get_chdata(ch);
@@ -249,8 +254,12 @@ void di_que_init(unsigned int ch)
 {
        int i;
 
-       for (i = 0; i < QUE_NUB; i++)
+       for (i = 0; i < QUE_NUB; i++) {
+               if (i == QUE_POST_KEEP ||
+                   i == QUE_POST_KEEP_BACK)
+                       continue;
                pw_queue_clear(ch, i);
+       }
 }
 
 bool di_que_alloc(unsigned int ch)
@@ -437,6 +446,39 @@ bool di_que_is_in_que(unsigned int ch, enum QUE_TYPE qtype,
        return ret;
 }
 
+/* clear and rebuild que*/
+bool di_que_out_not_fifo(unsigned int ch, enum QUE_TYPE qtype,
+                        struct di_buf_s *di_buf)
+{
+       unsigned int q_index;
+       unsigned int arr[MAX_FIFO_SIZE + 1];
+       unsigned int asize = 0;
+       unsigned int i;
+       bool ret = false;
+
+       if (!pw_queue_peek(ch, qtype, &q_index))
+               return false;
+
+       q_index = pw_buf_2_qindex(ch, di_buf);
+
+       di_que_list(ch, qtype, &arr[0], &asize);
+
+       pw_queue_clear(ch, qtype);
+
+       if (asize == 0)
+               return ret;
+
+       for (i = 0; i < asize; i++) {
+               if (arr[i] == q_index) {
+                       ret = true;
+                       di_buf->queue_index = -1;
+                       continue;
+               }
+               pw_queue_in(ch, qtype, arr[i]);
+       }
+       return ret;
+}
+
 /*same as get_di_buf_head*/
 struct di_buf_s *di_que_peek(unsigned int ch, enum QUE_TYPE qtype)
 {
index f2f35ab0332d52672653c57f6c9904202479a800..237c80503ae3e8c3e81f4f230e7f9906f9052cc0 100644 (file)
@@ -37,6 +37,7 @@ bool pw_queue_in(unsigned int ch, enum QUE_TYPE qtype,
 bool pw_queue_out(unsigned int ch, enum QUE_TYPE qtype,
                  unsigned int *buf_index);
 bool pw_queue_empty(unsigned int ch, enum QUE_TYPE qtype);
+void pw_queue_clear(unsigned int ch, enum QUE_TYPE qtype);
 
 /******************************************/
 /*new api*/
@@ -60,6 +61,9 @@ bool di_que_out(unsigned int ch, enum QUE_TYPE qtype,
 
 struct di_buf_s *di_que_out_to_di_buf(unsigned int ch,
                                      enum QUE_TYPE qtype);
+bool di_que_out_not_fifo(unsigned int ch, enum QUE_TYPE qtype,
+                        struct di_buf_s *di_buf);
+
 bool di_que_in(unsigned int ch, enum QUE_TYPE qtype,
               struct di_buf_s *di_buf);
 bool di_que_is_in_que(unsigned int ch, enum QUE_TYPE qtype,
index 64be0556e67c74baa54efae48dfa3d9e3c6b2c56..ab462a863b314ee5bb8bd71a4dddd46af500f700 100644 (file)
@@ -528,7 +528,7 @@ static int dim_probe(struct platform_device *pdev)
 fail_cdev_add:
        pr_info("%s:fail_cdev_add\n", __func__);
        kfree(di_devp->data_l);
-
+       di_devp->data_l = NULL;
 fail_kmalloc_datal:
        pr_info("%s:fail_kmalloc datal\n", __func__);
 
@@ -539,6 +539,7 @@ fail_class_create:
        unregister_chrdev_region(di_pdev->devno, DI_COUNT);
 fail_alloc_cdev_region:
        kfree(di_pdev);
+       di_pdev = NULL;
 fail_kmalloc_dev:
 
        return ret;
@@ -612,8 +613,9 @@ static int dim_remove(struct platform_device *pdev)
 #endif
 
        kfree(di_devp->data_l);
+       di_devp->data_l = NULL;
        kfree(di_pdev);
-
+       di_pdev = NULL;
        PR_INF("%s:finish\n", __func__);
        return 0;
 }
@@ -649,7 +651,7 @@ static void di_clear_for_suspend(struct di_dev_s *di_devp)
 
        di_vframe_unreg(channel);/*have flag*/
 
-       if (dip_chst_get(channel) != eDI_TOP_STATE_IDLE)
+       if (dip_chst_get(channel) != EDI_TOP_STATE_IDLE)
                dim_unreg_process_irq(channel);
 
        dip_cma_close();
index 9912fd45500fe7109056f9377ee5296992b7d617..84d899708525110a9d37a951179bf5a8b6494591 100644 (file)
@@ -96,6 +96,10 @@ void task_polling_cmd(void)
        for (i = 0; i < MAX_KFIFO_L_CMD_NUB; i++) {
                if (!task_get_cmd(&cmdbyte.cmd32))
                        break;
+               if (cmdbyte.b.id == ECMD_RL_KEEP) {
+                       dim_post_keep_cmd_proc(cmdbyte.b.ch, cmdbyte.b.p2);
+                       continue;
+               }
                dip_chst_process_reg(cmdbyte.b.ch);
        }
 }
index ef42224d59d81831e9e3f799795dfc6eb71961fb..cd0d4013649687769fcaa641f35f8e97be26ff43 100644 (file)
@@ -18,6 +18,8 @@ source "drivers/amlogic/media/video_processor/ppmgr/Kconfig"
 source "drivers/amlogic/media/video_processor/ionvideo/Kconfig"
 source "drivers/amlogic/media/video_processor/pic_dev/Kconfig"
 source "drivers/amlogic/media/video_processor/videosync/Kconfig"
+source "drivers/amlogic/media/video_processor/v4lvideo/Kconfig"
+source "drivers/amlogic/media/video_processor/video_composer/Kconfig"
 endif
 
 endmenu
index 354b2478a55464d9496d421d0973bcc29fed95fd..1def20612a2911530b2aed00459ba857e8efac37 100644 (file)
@@ -2,4 +2,6 @@ obj-$(CONFIG_AMLOGIC_V4L_VIDEO2) += video_dev/
 obj-$(CONFIG_AMLOGIC_POST_PROCESS_MANAGER) += ppmgr/
 obj-$(CONFIG_AMLOGIC_IONVIDEO) += ionvideo/
 obj-$(CONFIG_AMLOGIC_PIC_DEC)  += pic_dev/
-obj-$(CONFIG_AMLOGIC_VIDEOSYNC)        += videosync/
\ No newline at end of file
+obj-$(CONFIG_AMLOGIC_VIDEOSYNC)        += videosync/
+obj-$(CONFIG_AMLOGIC_V4L_VIDEO3)       += v4lvideo/
+obj-$(CONFIG_AMLOGIC_VIDEO_COMPOSER)   += video_composer/
index 7e64cc6149aa574387a6803c019c0af84c63d927..6864740a274d6af185b1127158b7b1756011c648 100644 (file)
@@ -953,7 +953,7 @@ static int process_vf_tb_detect(struct vframe_s *vf,
 {
        struct canvas_s cs0, cs1, cs2, cd;
        int interlace_mode;
-       struct vframe_s src_vf;
+       int canvas_id;
        u32 format = GE2D_FORMAT_M24_YUV420;
        u32 h_scale_coef_type =
                context->config.h_scale_coef_type;
@@ -1000,36 +1000,32 @@ static int process_vf_tb_detect(struct vframe_s *vf,
        ge2d_config->src1_gb_alpha = 0;/* 0xff; */
        ge2d_config->dst_xy_swap = 0;
 
-       src_vf = *vf;
-
        if (vf->canvas0Addr == (u32)-1) {
                canvas_config_config(
                        tb_src_canvas[0] & 0xff,
-                       &src_vf.canvas0_config[0]);
-               if (src_vf.plane_num == 2) {
+                       &vf->canvas0_config[0]);
+               if (vf->plane_num == 2) {
                        canvas_config_config(
                                tb_src_canvas[1] & 0xff,
-                               &src_vf.canvas0_config[1]);
-               } else if (src_vf.plane_num == 3) {
+                               &vf->canvas0_config[1]);
+               } else if (vf->plane_num == 3) {
                        canvas_config_config(
                                tb_src_canvas[2] & 0xff,
-                               &src_vf.canvas0_config[2]);
+                               &vf->canvas0_config[2]);
                }
-               src_vf.canvas0Addr =
-                       (tb_src_canvas[0] & 0xff)
+               canvas_id = (tb_src_canvas[0] & 0xff)
                        | ((tb_src_canvas[1] & 0xff) << 8)
                        | ((tb_src_canvas[2] & 0xff) << 16);
 
-               canvas_read(
-                       src_vf.canvas0Addr & 0xff, &cs0);
-               canvas_read(
-                       (src_vf.canvas0Addr >> 8) & 0xff, &cs1);
-               canvas_read(
-                       (src_vf.canvas0Addr >> 16) & 0xff, &cs2);
+               canvas_read(canvas_id & 0xff, &cs0);
+               canvas_read((canvas_id >> 8) & 0xff, &cs1);
+               canvas_read((canvas_id >> 16) & 0xff, &cs2);
+               ge2d_config->src_para.canvas_index = canvas_id;
        } else {
                canvas_read(vf->canvas0Addr & 0xff, &cs0);
                canvas_read((vf->canvas0Addr >> 8) & 0xff, &cs1);
                canvas_read((vf->canvas0Addr >> 16) & 0xff, &cs2);
+               ge2d_config->src_para.canvas_index = vf->canvas0Addr;
        }
        ge2d_config->src_planes[0].addr = cs0.addr;
        ge2d_config->src_planes[0].w = cs0.width;
@@ -1047,7 +1043,6 @@ static int process_vf_tb_detect(struct vframe_s *vf,
        ge2d_config->src_key.key_enable = 0;
        ge2d_config->src_key.key_mask = 0;
        ge2d_config->src_key.key_mode = 0;
-       ge2d_config->src_para.canvas_index = src_vf.canvas0Addr;
        ge2d_config->src_para.mem_type = CANVAS_TYPE_INVALID;
        ge2d_config->src_para.format = format;
        ge2d_config->src_para.fill_color_en = 0;
diff --git a/drivers/amlogic/media/video_processor/v4lvideo/Kconfig b/drivers/amlogic/media/video_processor/v4lvideo/Kconfig
new file mode 100644 (file)
index 0000000..032b8c6
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# Amlogic v4lvideo device configuation
+#
+
+menu "Amlogic v4l video support"
+
+config AMLOGIC_V4L_VIDEO3
+       tristate "Amlogic v4l video3 device support"
+       depends on VIDEO_DEV
+       depends on VIDEO_V4L2
+       depends on VIDEOBUF2_CORE
+       depends on VIDEOBUF2_MEMOPS
+       depends on DMA_SHARED_BUFFER
+       default n
+
+       ---help---
+               Select to enable "Amlogic v4l video3 device support.
+
+endmenu
diff --git a/drivers/amlogic/media/video_processor/v4lvideo/Makefile b/drivers/amlogic/media/video_processor/v4lvideo/Makefile
new file mode 100644 (file)
index 0000000..a95a1a7
--- /dev/null
@@ -0,0 +1,4 @@
+asflags-y=-mfloat-abi=softfp -mfpu=neon
+ccflags-y += -Idrivers/staging/android/ion
+
+obj-$(CONFIG_AMLOGIC_V4L_VIDEO3) += v4lvideo.o
diff --git a/drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.c b/drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.c
new file mode 100644 (file)
index 0000000..acb973c
--- /dev/null
@@ -0,0 +1,1162 @@
+/*
+ * drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.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.
+ *
+ */
+
+#define DEBUG
+#include <linux/amlogic/media/vout/vout_notify.h>
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/amlogic/media/vfm/vframe_provider.h>
+#include <linux/amlogic/media/vfm/vframe_receiver.h>
+#include "v4lvideo.h"
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
+#include <linux/platform_device.h>
+#include <linux/amlogic/major.h>
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include <linux/amlogic/media/codec_mm/codec_mm_keeper.h>
+#include <linux/amlogic/media/utils/amstream.h>
+#include <linux/amlogic/media/video_sink/video_keeper.h>
+#include <linux/anon_inodes.h>
+#include <linux/file.h>
+#include <linux/amlogic/media/canvas/canvas_mgr.h>
+
+#define V4LVIDEO_MODULE_NAME "v4lvideo"
+
+#define V4LVIDEO_VERSION "1.0"
+#define RECEIVER_NAME "v4lvideo"
+#define V4LVIDEO_DEVICE_NAME   "v4lvideo"
+#define DUR2PTS(x) ((x) - ((x) >> 4))
+
+#define V4L2_CID_USER_AMLOGIC_V4LVIDEO_BASE  (V4L2_CID_USER_BASE + 0x1100)
+
+static unsigned int video_nr_base = 30;
+module_param(video_nr_base, uint, 0644);
+MODULE_PARM_DESC(video_nr_base, "videoX start number, 30 is the base nr");
+
+static unsigned int n_devs = 9;
+
+module_param(n_devs, uint, 0644);
+MODULE_PARM_DESC(n_devs, "number of video devices to create");
+
+static unsigned int debug;
+module_param(debug, uint, 0644);
+MODULE_PARM_DESC(debug, "activates debug info");
+
+#define MAX_KEEP_FRAME 64
+
+struct keep_mem_info {
+       void *handle;
+       int keep_id;
+       int count;
+};
+
+struct keeper_mgr {
+       /* lock*/
+       spinlock_t lock;
+       struct keep_mem_info keep_list[MAX_KEEP_FRAME];
+};
+
+static struct keeper_mgr keeper_mgr_private;
+
+static struct keeper_mgr *get_keeper_mgr(void)
+{
+       return &keeper_mgr_private;
+}
+
+void keeper_mgr_init(void)
+{
+       struct keeper_mgr *mgr = get_keeper_mgr();
+
+       memset(mgr, 0, sizeof(struct keeper_mgr));
+       spin_lock_init(&mgr->lock);
+}
+
+static const struct v4lvideo_fmt formats[] = {
+       {.name = "RGB32 (LE)",
+       .fourcc = V4L2_PIX_FMT_RGB32, /* argb */
+       .depth = 32, },
+
+       {.name = "RGB565 (LE)",
+       .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
+       .depth = 16, },
+
+       {.name = "RGB24 (LE)",
+       .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */
+       .depth = 24, },
+
+       {.name = "RGB24 (BE)",
+       .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */
+       .depth = 24, },
+
+       {.name = "12  Y/CbCr 4:2:0",
+       .fourcc = V4L2_PIX_FMT_NV12,
+       .depth = 12, },
+
+       {.name = "12  Y/CrCb 4:2:0",
+       .fourcc = V4L2_PIX_FMT_NV21,
+       .depth = 12, },
+
+       {.name = "YUV420P",
+       .fourcc = V4L2_PIX_FMT_YUV420,
+       .depth = 12, },
+
+       {.name = "YVU420P",
+       .fourcc = V4L2_PIX_FMT_YVU420,
+       .depth = 12, }
+};
+
+static const struct v4lvideo_fmt *__get_format(u32 pixelformat)
+{
+       const struct v4lvideo_fmt *fmt;
+       unsigned int k;
+
+       for (k = 0; k < ARRAY_SIZE(formats); k++) {
+               fmt = &formats[k];
+               if (fmt->fourcc == pixelformat)
+                       break;
+       }
+
+       if (k == ARRAY_SIZE(formats))
+               return NULL;
+
+       return &formats[k];
+}
+
+static const struct v4lvideo_fmt *get_format(struct v4l2_format *f)
+{
+       return __get_format(f->fmt.pix.pixelformat);
+}
+
+static void video_keeper_keep_mem(
+       void *mem_handle, int type,
+       int *id)
+{
+       int ret;
+       int old_id = *id;
+       struct keeper_mgr *mgr = get_keeper_mgr();
+       int i;
+       unsigned long flags;
+       int have_samed = 0;
+       int keep_id = -1;
+       int slot_i = -1;
+
+       if (!mem_handle)
+               return;
+
+       spin_lock_irqsave(&mgr->lock, flags);
+       for (i = 0; i < MAX_KEEP_FRAME; i++) {
+               if (!mgr->keep_list[i].handle && slot_i < 0) {
+                       slot_i = i;
+               } else if (mem_handle == mgr->keep_list[i].handle) {
+                       mgr->keep_list[i].count++;
+                       have_samed = true;
+                       keep_id = mgr->keep_list[i].keep_id;
+                       break;
+               }
+       }
+
+       if (have_samed) {
+               spin_unlock_irqrestore(&mgr->lock, flags);
+               *id = keep_id;
+               /* pr_info("v4lvideo: keep same mem handle=%p, keep_id=%d\n", */
+               /* mem_handle, keep_id); */
+               return;
+       }
+       mgr->keep_list[slot_i].count++;
+       if (mgr->keep_list[slot_i].count != 1)
+               pr_err("v4lvideo: keep error mem handle=%p\n", mem_handle);
+       mgr->keep_list[slot_i].handle = mem_handle;
+
+       spin_unlock_irqrestore(&mgr->lock, flags);
+
+       ret = codec_mm_keeper_mask_keep_mem(mem_handle,
+                                           type);
+       if (ret > 0) {
+               if (old_id > 0 && ret != old_id) {
+                       /* wait 80 ms for vsync post. */
+                       codec_mm_keeper_unmask_keeper(old_id, 0);
+               }
+               *id = ret;
+       }
+       mgr->keep_list[slot_i].keep_id = *id;
+}
+
+static void video_keeper_free_mem(
+       int keep_id, int delayms)
+{
+       struct keeper_mgr *mgr = get_keeper_mgr();
+       int i;
+       unsigned long flags;
+       int need_continue_keep = 0;
+
+       if (keep_id <= 0) {
+               pr_err("invalid keepid %d\n", keep_id);
+               return;
+       }
+
+       spin_lock_irqsave(&mgr->lock, flags);
+       for (i = 0; i < MAX_KEEP_FRAME; i++) {
+               if (keep_id == mgr->keep_list[i].keep_id) {
+                       mgr->keep_list[i].count--;
+                       if (mgr->keep_list[i].count > 0) {
+                               need_continue_keep = 1;
+                               break;
+                       } else if (mgr->keep_list[i].count == 0) {
+                               mgr->keep_list[i].keep_id = -1;
+                               mgr->keep_list[i].handle = NULL;
+                       } else
+                               pr_err("v4lvideo: free mem err count =%d\n",
+                                      mgr->keep_list[i].count);
+               }
+       }
+       spin_unlock_irqrestore(&mgr->lock, flags);
+
+       if (need_continue_keep) {
+               pr_info("v4lvideo: need_continue_keep keep_id=%d\n", keep_id);
+               return;
+       }
+       codec_mm_keeper_unmask_keeper(keep_id, delayms);
+}
+
+static void vf_keep(struct file_private_data *file_private_data)
+{
+       struct vframe_s *vf_p = file_private_data->vf_p;
+       int type = MEM_TYPE_CODEC_MM;
+       int keep_id = 0;
+       int keep_head_id = 0;
+
+       if (!file_private_data) {
+               V4LVID_ERR("vf_keep error: file_private_data is NULL");
+               return;
+       }
+       if (vf_p->type & VIDTYPE_SCATTER)
+               type = MEM_TYPE_CODEC_MM_SCATTER;
+       video_keeper_keep_mem(
+               vf_p->mem_handle,
+               type,
+               &keep_id);
+       video_keeper_keep_mem(
+               vf_p->mem_head_handle,
+               MEM_TYPE_CODEC_MM,
+               &keep_head_id);
+
+       file_private_data->keep_id = keep_id;
+       file_private_data->keep_head_id = keep_head_id;
+       file_private_data->is_keep = true;
+}
+
+static void vf_free(struct file_private_data *file_private_data)
+{
+       struct vframe_s *vf_p;
+       struct vframe_s vf;
+
+       if (file_private_data->keep_id > 0) {
+               video_keeper_free_mem(
+                               file_private_data->keep_id, 0);
+               file_private_data->keep_id = -1;
+       }
+       if (file_private_data->keep_head_id > 0) {
+               video_keeper_free_mem(
+                               file_private_data->keep_head_id, 0);
+               file_private_data->keep_head_id = -1;
+       }
+
+       vf = file_private_data->vf;
+       vf_p = file_private_data->vf_p;
+
+       if (vf.type & VIDTYPE_DI_PW)
+               dim_post_keep_cmd_release2(vf_p);
+}
+
+void init_file_private_data(struct file_private_data *file_private_data)
+{
+       if (file_private_data) {
+               memset(&file_private_data->vf, 0, sizeof(struct vframe_s));
+               file_private_data->vf_p = NULL;
+               file_private_data->is_keep = false;
+               file_private_data->keep_id = -1;
+               file_private_data->keep_head_id = -1;
+               file_private_data->file = NULL;
+       } else {
+               V4LVID_ERR("init_file_private_data is NULL!!");
+       }
+}
+
+static DEFINE_SPINLOCK(devlist_lock);
+static unsigned long v4lvideo_devlist_lock(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&devlist_lock, flags);
+       return flags;
+}
+
+static void v4lvideo_devlist_unlock(unsigned long flags)
+{
+       spin_unlock_irqrestore(&devlist_lock, flags);
+}
+
+static LIST_HEAD(v4lvideo_devlist);
+
+int v4lvideo_assign_map(char **receiver_name, int *inst)
+{
+       unsigned long flags;
+       struct v4lvideo_dev *dev = NULL;
+       struct list_head *p;
+
+       flags = v4lvideo_devlist_lock();
+
+       list_for_each(p, &v4lvideo_devlist) {
+               dev = list_entry(p, struct v4lvideo_dev, v4lvideo_devlist);
+
+               if (dev->inst == *inst) {
+                       *receiver_name = dev->vf_receiver_name;
+                       v4lvideo_devlist_unlock(flags);
+                       return 0;
+               }
+       }
+
+       v4lvideo_devlist_unlock(flags);
+
+       return -ENODEV;
+}
+EXPORT_SYMBOL(v4lvideo_assign_map);
+
+int v4lvideo_alloc_map(int *inst)
+{
+       unsigned long flags;
+       struct v4lvideo_dev *dev = NULL;
+       struct list_head *p;
+
+       flags = v4lvideo_devlist_lock();
+
+       list_for_each(p, &v4lvideo_devlist) {
+               dev = list_entry(p, struct v4lvideo_dev, v4lvideo_devlist);
+
+               if ((dev->inst >= 0) && (!dev->mapped)) {
+                       dev->mapped = true;
+                       *inst = dev->inst;
+                       v4lvideo_devlist_unlock(flags);
+                       return 0;
+               }
+       }
+
+       v4lvideo_devlist_unlock(flags);
+       return -ENODEV;
+}
+
+void v4lvideo_release_map(int inst)
+{
+       unsigned long flags;
+       struct v4lvideo_dev *dev = NULL;
+       struct list_head *p;
+
+       flags = v4lvideo_devlist_lock();
+
+       list_for_each(p, &v4lvideo_devlist) {
+               dev = list_entry(p, struct v4lvideo_dev, v4lvideo_devlist);
+               if ((dev->inst == inst) && (dev->mapped)) {
+                       dev->mapped = false;
+                       pr_debug("v4lvideo_release_map %d OK\n", dev->inst);
+                       break;
+               }
+       }
+
+       v4lvideo_devlist_unlock(flags);
+}
+
+void v4lvideo_release_map_force(struct v4lvideo_dev *dev)
+{
+       unsigned long flags;
+
+       flags = v4lvideo_devlist_lock();
+
+       if (dev->mapped) {
+               dev->mapped = false;
+               pr_debug("v4lvideo_release_map %d OK\n", dev->inst);
+       }
+
+       v4lvideo_devlist_unlock(flags);
+}
+
+void v4lvideo_data_copy(struct v4l_data_t *v4l_data)
+{
+       struct vframe_s *vf = NULL;
+       char *src_ptr_y = NULL;
+       char *src_ptr_uv = NULL;
+       char *dst_ptr = NULL;
+       u32 src_phy_addr_y;
+       u32 src_phy_addr_uv;
+       u32 size_y;
+       u32 size_uv;
+       u32 size_pic;
+
+       vf = v4l_data->vf;
+       size_y = vf->width * vf->height;
+       size_uv = size_y >> 1;
+       size_pic = size_y + size_uv;
+
+       if ((vf->canvas0Addr == vf->canvas1Addr) &&
+           (vf->canvas0Addr != 0) &&
+           (vf->canvas0Addr != -1)) {
+               src_phy_addr_y = canvas_get_addr(canvasY(vf->canvas0Addr));
+               src_phy_addr_uv = canvas_get_addr(canvasUV(vf->canvas0Addr));
+       } else {
+               src_phy_addr_y = vf->canvas0_config[0].phy_addr;
+               src_phy_addr_uv = vf->canvas0_config[1].phy_addr;
+       }
+       dst_ptr = v4l_data->dst_addr;
+
+       src_ptr_y = codec_mm_vmap(src_phy_addr_y, size_y);
+       if (!src_ptr_y) {
+               pr_err("src_phy_addr_y map fail size_y=%d\n", size_y);
+               return;
+       }
+       memcpy(dst_ptr, src_ptr_y, size_y);
+       codec_mm_unmap_phyaddr(src_ptr_y);
+
+       src_ptr_uv = codec_mm_vmap(src_phy_addr_uv, size_uv);
+       if (!src_ptr_uv) {
+               pr_err("src_phy_addr_uv map fail size_uv=%d\n", size_uv);
+               return;
+       }
+       memcpy(dst_ptr + size_y, src_ptr_uv, size_uv);
+       codec_mm_unmap_phyaddr(src_ptr_uv);
+}
+
+struct vframe_s *v4lvideo_get_vf(int fd)
+{
+       struct file *file_vf = NULL;
+       struct vframe_s *vf = NULL;
+       struct file_private_data *file_private_data;
+
+       file_vf = fget(fd);
+       file_private_data = (struct file_private_data *)file_vf->private_data;
+       vf = &file_private_data->vf;
+       fput(file_vf);
+       return vf;
+}
+
+/* ------------------------------------------------------------------
+ * DMA and thread functions
+ * ------------------------------------------------------------------
+ */
+unsigned int get_v4lvideo_debug(void)
+{
+       return debug;
+}
+EXPORT_SYMBOL(get_v4lvideo_debug);
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct v4lvideo_dev *dev = video_drvdata(file);
+
+       dprintk(dev, 2, "%s\n", __func__);
+
+       dprintk(dev, 2, "returning from %s\n", __func__);
+
+       return 0;
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct v4lvideo_dev *dev = video_drvdata(file);
+
+       dprintk(dev, 2, "%s\n", __func__);
+
+       /*
+        * Typical driver might need to wait here until dma engine stops.
+        * In this case we can abort imiedetly, so it's just a noop.
+        */
+       v4l2q_init(&dev->input_queue, V4LVIDEO_POOL_SIZE,
+                  (void **)&dev->v4lvideo_input_queue[0]);
+       return 0;
+}
+
+/* ------------------------------------------------------------------
+ * Videobuf operations
+ * ------------------------------------------------------------------
+ */
+
+static int vidioc_g_parm(struct file *file, void *priv,
+                        struct v4l2_streamparm *parms)
+{
+       struct v4lvideo_dev *dev = video_drvdata(file);
+
+       if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       memcpy(parms->parm.raw_data, (u8 *)&dev->am_parm,
+              sizeof(struct v4l2_amlogic_parm));
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------
+ * IOCTL vidioc handling
+ * ------------------------------------------------------------------
+ */
+static int vidioc_open(struct file *file)
+{
+       struct v4lvideo_dev *dev = video_drvdata(file);
+
+       if (dev->fd_num > 0) {
+               pr_err("vidioc_open error\n");
+               return -EBUSY;
+       }
+
+       dev->fd_num++;
+       dev->vf_wait_cnt = 0;
+
+       v4l2q_init(&dev->input_queue,
+                  V4LVIDEO_POOL_SIZE,
+                  (void **)&dev->v4lvideo_input_queue[0]);
+
+       //dprintk(dev, 2, "vidioc_open\n");
+       V4LVID_DBG("v4lvideo open\n");
+       return 0;
+}
+
+static int vidioc_close(struct file *file)
+{
+       struct v4lvideo_dev *dev = video_drvdata(file);
+
+       V4LVID_DBG("vidioc_close!!!!\n");
+       if (dev->mapped)
+               v4lvideo_release_map_force(dev);
+
+       if (dev->fd_num > 0)
+               dev->fd_num--;
+
+       return 0;
+}
+
+static int vidioc_querycap(struct file *file,
+                          void *priv,
+                          struct v4l2_capability *cap)
+{
+       struct v4lvideo_dev *dev = video_drvdata(file);
+
+       strcpy(cap->driver, "v4lvideo");
+       strcpy(cap->card, "v4lvideo");
+       snprintf(cap->bus_info,
+                sizeof(cap->bus_info),
+                "platform:%s",
+                dev->v4l2_dev.name);
+       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING
+                               | V4L2_CAP_READWRITE;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       const struct v4lvideo_fmt *fmt;
+
+       if (f->index >= ARRAY_SIZE(formats))
+               return -EINVAL;
+
+       fmt = &formats[f->index];
+
+       strlcpy(f->description, fmt->name, sizeof(f->description));
+       f->pixelformat = fmt->fourcc;
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct v4lvideo_dev *dev = video_drvdata(file);
+
+       f->fmt.pix.width = dev->width;
+       f->fmt.pix.height = dev->height;
+
+       f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+       f->fmt.pix.pixelformat = dev->fmt->fourcc;
+       f->fmt.pix.bytesperline = (f->fmt.pix.width * dev->fmt->depth) >> 3;
+       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+       if (dev->fmt->is_yuv)
+               f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+       else
+               f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
+
+       return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file,
+                                 void *priv,
+                                 struct v4l2_format *f)
+{
+       struct v4lvideo_dev *dev = video_drvdata(file);
+       const struct v4lvideo_fmt *fmt;
+
+       fmt = get_format(f);
+       if (!fmt) {
+               dprintk(dev, 1, "Fourcc format (0x%08x) unknown.\n",
+                       f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+       v4l_bound_align_image(&f->fmt.pix.width,
+                             48,
+                             MAX_WIDTH,
+                             4,
+                             &f->fmt.pix.height,
+                             32,
+                             MAX_HEIGHT,
+                             0,
+                             0);
+       f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
+       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+       if (fmt->is_yuv)
+               f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+       else
+               f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
+       f->fmt.pix.priv = 0;
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct v4lvideo_dev *dev = video_drvdata(file);
+
+       int ret = vidioc_try_fmt_vid_cap(file, priv, f);
+
+       if (ret < 0)
+               return ret;
+
+       dev->fmt = get_format(f);
+       dev->width = f->fmt.pix.width;
+       dev->height = f->fmt.pix.height;
+       if ((dev->width == 0) || (dev->height == 0))
+               V4LVID_ERR("ion buffer w/h info is invalid!!!!!!!!!!!\n");
+
+       return 0;
+}
+
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct v4lvideo_dev *dev = video_drvdata(file);
+       struct vframe_s *vf_p;
+       struct file *file_vf = NULL;
+       struct file_private_data *file_private_data = NULL;
+
+       dev->v4lvideo_input[p->index] = *p;
+
+       file_vf = fget(p->m.fd);
+       file_private_data = (struct file_private_data *)(file_vf->private_data);
+       vf_p = file_private_data->vf_p;
+
+       mutex_lock(&dev->mutex_input);
+       if (vf_p) {
+               if (file_private_data->is_keep) {
+                       vf_free(file_private_data);
+               } else {
+                       if (v4l2q_pop_specific(&dev->display_queue,
+                                              file_private_data)) {
+                               if (dev->receiver_register) {
+                                       vf_put(vf_p, dev->vf_receiver_name);
+                               } else {
+                                       vf_free(file_private_data);
+                                       pr_err("vidioc_qbuf: vfm is unreg\n");
+                               }
+                       } else {
+                               pr_err("vidioc_qbuf: maybe in unreg\n");
+                       }
+               }
+       } else {
+               dprintk(dev, 1,
+                       "vidioc_qbuf: vf is NULL, at the start of playback\n");
+       }
+       init_file_private_data(file_private_data);
+       fput(file_vf);
+
+       v4l2q_push(&dev->input_queue, &dev->v4lvideo_input[p->index]);
+       mutex_unlock(&dev->mutex_input);
+
+       return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct v4lvideo_dev *dev = video_drvdata(file);
+       struct v4l2_buffer *buf = NULL;
+       struct vframe_s *vf;
+       struct file *file_vf = NULL;
+       struct file_private_data *file_private_data = NULL;
+       u64 pts_us64 = 0;
+       u64 pts_tmp;
+
+       mutex_lock(&dev->mutex_input);
+       buf = v4l2q_peek(&dev->input_queue);
+       if (!buf) {
+               dprintk(dev, 3, "No active queue to serve\n");
+               mutex_unlock(&dev->mutex_input);
+               return -EAGAIN;
+       }
+       mutex_unlock(&dev->mutex_input);
+
+       vf = vf_peek(dev->vf_receiver_name);
+       if (!vf) {
+               dev->vf_wait_cnt++;
+               return -EAGAIN;
+       }
+       vf = vf_get(dev->vf_receiver_name);
+       if (!vf)
+               return -EAGAIN;
+       vf->omx_index = dev->frame_num;
+       dev->am_parm.signal_type = vf->signal_type;
+       dev->am_parm.master_display_colour
+               = vf->prop.master_display_colour;
+
+       mutex_lock(&dev->mutex_input);
+       buf = v4l2q_pop(&dev->input_queue);
+       dev->vf_wait_cnt = 0;
+       file_vf = fget(buf->m.fd);
+       file_private_data = (struct file_private_data *)(file_vf->private_data);
+       file_private_data->vf = *vf;
+       file_private_data->vf_p = vf;
+       //pr_err("dqbuf: file_private_data=%p, vf=%p\n", file_private_data, vf);
+       v4l2q_push(&dev->display_queue, file_private_data);
+       fput(file_vf);
+       mutex_unlock(&dev->mutex_input);
+
+       if (vf->pts_us64) {
+               dev->first_frame = 1;
+               pts_us64 = vf->pts_us64;
+       } else if (dev->first_frame == 0) {
+               dev->first_frame = 1;
+               pts_us64 = 0;
+       } else {
+               pts_tmp = DUR2PTS(vf->duration) * 100;
+               do_div(pts_tmp, 9);
+               pts_us64 = dev->last_pts_us64
+                       + pts_tmp;
+               pts_tmp = pts_us64 * 9;
+               do_div(pts_tmp, 100);
+               vf->pts = pts_tmp;
+       }
+       /*workrun for decoder i pts err, if decoder fix it, this should remove*/
+       if ((vf->type & VIDTYPE_DI_PW ||
+            vf->type & VIDTYPE_INTERLACE) &&
+           (vf->pts_us64 == dev->last_pts_us64)) {
+               dprintk(dev, 1, "pts same\n");
+               pts_tmp = DUR2PTS(vf->duration) * 100;
+               do_div(pts_tmp, 9);
+               pts_us64 = dev->last_pts_us64
+                       + pts_tmp;
+               pts_tmp = pts_us64 * 9;
+               do_div(pts_tmp, 100);
+               vf->pts = pts_tmp;
+       }
+
+       *p = *buf;
+        p->timestamp.tv_sec = pts_us64 >> 32;
+        p->timestamp.tv_usec = pts_us64 & 0xFFFFFFFF;
+        dev->last_pts_us64 = pts_us64;
+
+       if ((vf->type & VIDTYPE_COMPRESS) != 0) {
+               p->timecode.type = vf->compWidth;
+               p->timecode.flags = vf->compHeight;
+       } else {
+               p->timecode.type = vf->width;
+               p->timecode.flags = vf->height;
+       }
+       p->sequence = dev->frame_num++;
+       //pr_err("dqbuf: frame_num=%d\n", p->sequence);
+       return 0;
+}
+
+/* ------------------------------------------------------------------
+ * File operations for the device
+ * ------------------------------------------------------------------
+ */
+static const struct v4l2_file_operations v4lvideo_v4l2_fops = {
+       .owner = THIS_MODULE,
+       .open = vidioc_open,
+       .release = vidioc_close,
+       .read = vb2_fop_read,
+       .poll = vb2_fop_poll,
+       .unlocked_ioctl = video_ioctl2,/* V4L2 ioctl handler */
+       .mmap = vb2_fop_mmap,
+};
+
+static const struct v4l2_ioctl_ops v4lvideo_ioctl_ops = {
+       .vidioc_querycap = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+       .vidioc_qbuf = vidioc_qbuf,
+       .vidioc_dqbuf = vidioc_dqbuf,
+       .vidioc_streamon = vidioc_streamon,
+       .vidioc_streamoff = vidioc_streamoff,
+       .vidioc_g_parm = vidioc_g_parm,
+};
+
+static const struct video_device v4lvideo_template = {
+       .name = "v4lvideo",
+       .fops = &v4lvideo_v4l2_fops,
+       .ioctl_ops = &v4lvideo_ioctl_ops,
+       .release = video_device_release,
+};
+
+static int v4lvideo_v4l2_release(void)
+{
+       struct v4lvideo_dev *dev;
+       struct list_head *list;
+       unsigned long flags;
+
+       flags = v4lvideo_devlist_lock();
+
+       while (!list_empty(&v4lvideo_devlist)) {
+               list = v4lvideo_devlist.next;
+               list_del(list);
+               v4lvideo_devlist_unlock(flags);
+
+               dev = list_entry(list, struct v4lvideo_dev, v4lvideo_devlist);
+
+               v4l2_info(&dev->v4l2_dev,
+                         "unregistering %s\n",
+                         video_device_node_name(&dev->vdev));
+               video_unregister_device(&dev->vdev);
+               v4l2_device_unregister(&dev->v4l2_dev);
+               kfree(dev);
+
+               flags = v4lvideo_devlist_lock();
+       }
+       /* vb2_dma_contig_cleanup_ctx(v4lvideo_dma_ctx); */
+
+       v4lvideo_devlist_unlock(flags);
+
+       return 0;
+}
+
+static int video_receiver_event_fun(int type, void *data, void *private_data)
+{
+       struct v4lvideo_dev *dev = (struct v4lvideo_dev *)private_data;
+       struct file_private_data *file_private_data = NULL;
+
+       if (type == VFRAME_EVENT_PROVIDER_UNREG) {
+               mutex_lock(&dev->mutex_input);
+               dev->receiver_register = false;
+               while (!v4l2q_empty(&dev->display_queue)) {
+                       file_private_data = v4l2q_pop(&dev->display_queue);
+                       vf_keep(file_private_data);
+                       /*pr_err("unreg:v4lvideo, keep last frame\n");*/
+               }
+               mutex_unlock(&dev->mutex_input);
+               pr_err("unreg:v4lvideo\n");
+       } else if (type == VFRAME_EVENT_PROVIDER_REG) {
+               mutex_lock(&dev->mutex_input);
+               v4l2q_init(&dev->display_queue,
+                          VF_POOL_SIZE,
+                          (void **)&dev->v4lvideo_display_queue[0]);
+               dev->receiver_register = true;
+               dev->frame_num = 0;
+               dev->first_frame = 0;
+               mutex_unlock(&dev->mutex_input);
+               pr_err("reg:v4lvideo\n");
+       } else if (type == VFRAME_EVENT_PROVIDER_QUREY_STATE) {
+               if (dev->vf_wait_cnt > 1)
+                       return RECEIVER_INACTIVE;
+               return RECEIVER_ACTIVE;
+       }
+       return 0;
+}
+
+static const struct vframe_receiver_op_s video_vf_receiver = {
+       .event_cb = video_receiver_event_fun
+};
+
+static int __init v4lvideo_create_instance(int inst)
+{
+       struct v4lvideo_dev *dev;
+       struct video_device *vfd;
+       int ret;
+       unsigned long flags;
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+
+       snprintf(dev->v4l2_dev.name,
+                sizeof(dev->v4l2_dev.name),
+                "%s-%03d",
+                V4LVIDEO_MODULE_NAME,
+                inst);
+       ret = v4l2_device_register(NULL, &dev->v4l2_dev);
+       if (ret)
+               goto free_dev;
+
+       dev->fmt = &formats[0];
+       dev->width = 640;
+       dev->height = 480;
+       dev->fd_num = 0;
+
+       vfd = &dev->vdev;
+       *vfd = v4lvideo_template;
+       vfd->dev_debug = debug;
+       vfd->v4l2_dev = &dev->v4l2_dev;
+
+       /*
+        * Provide a mutex to v4l2 core. It will be used to protect
+        * all fops and v4l2 ioctls.
+        */
+       ret = video_register_device(vfd,
+                                   VFL_TYPE_GRABBER,
+                                   inst + video_nr_base);
+       if (ret < 0)
+               goto unreg_dev;
+
+       video_set_drvdata(vfd, dev);
+       dev->inst = inst;
+       snprintf(dev->vf_receiver_name,
+                ION_VF_RECEIVER_NAME_SIZE,
+                RECEIVER_NAME ".%x",
+                inst & 0xff);
+
+       vf_receiver_init(&dev->video_vf_receiver,
+                        dev->vf_receiver_name,
+                        &video_vf_receiver, dev);
+       vf_reg_receiver(&dev->video_vf_receiver);
+       v4l2_info(&dev->v4l2_dev,
+                 "V4L2 device registered as %s\n",
+                 video_device_node_name(vfd));
+
+       /* add to device list */
+       flags = v4lvideo_devlist_lock();
+       list_add_tail(&dev->v4lvideo_devlist, &v4lvideo_devlist);
+       v4lvideo_devlist_unlock(flags);
+
+       mutex_init(&dev->mutex_input);
+
+       return 0;
+
+unreg_dev:
+       v4l2_device_unregister(&dev->v4l2_dev);
+free_dev:
+       kfree(dev);
+       return ret;
+}
+
+static const struct file_operations v4lvideo_file_fops;
+
+static int v4lvideo_file_release(struct inode *inode, struct file *file)
+{
+       struct file_private_data *file_private_data = file->private_data;
+       /*pr_err("v4lvideo_file_release\n");*/
+
+       if (file_private_data) {
+               if (file_private_data->is_keep)
+                       vf_free(file_private_data);
+               memset(file_private_data, 0, sizeof(struct file_private_data));
+               kfree((u8 *)file_private_data);
+               file->private_data = NULL;
+       }
+       return 0;
+}
+
+static const struct file_operations v4lvideo_file_fops = {
+       .release = v4lvideo_file_release,
+       //.poll = v4lvideo_file_poll,
+       //.unlocked_ioctl = v4lvideo_file_ioctl,
+       //.compat_ioctl = v4lvideo_file_ioctl,
+};
+
+int v4lvideo_alloc_fd(int *fd)
+{
+       struct file *file = NULL;
+       struct file_private_data *private_date = NULL;
+       int file_fd = get_unused_fd_flags(O_CLOEXEC);
+
+       if (file_fd < 0) {
+               pr_err("v4lvideo_alloc_fd: get unused fd fail\n");
+               return -ENODEV;
+       }
+
+       private_date = kzalloc(sizeof(*private_date), GFP_KERNEL);
+       if (!private_date) {
+               put_unused_fd(file_fd);
+               pr_err("v4lvideo_alloc_fd: private_date fail\n");
+               return -ENOMEM;
+       }
+       init_file_private_data(private_date);
+
+       file = anon_inode_getfile("v4lvideo_file",
+                                 &v4lvideo_file_fops,
+                                 private_date, 0);
+       if (IS_ERR(file)) {
+               kfree((u8 *)private_date);
+               put_unused_fd(file_fd);
+               pr_err("v4lvideo_alloc_fd: anon_inode_getfile fail\n");
+               return -ENODEV;
+       }
+       fd_install(file_fd, file);
+       *fd = file_fd;
+       return 0;
+}
+
+static struct class_attribute ion_video_class_attrs[] = {
+};
+
+static struct class v4lvideo_class = {
+       .name = "v4lvideo",
+       .class_attrs = ion_video_class_attrs,
+};
+
+static int v4lvideo_open(struct inode *inode, struct file *file)
+{
+       return 0;
+}
+
+static int v4lvideo_release(struct inode *inode, struct file *file)
+{
+       return 0;
+}
+
+static long v4lvideo_ioctl(struct file *file,
+                          unsigned int cmd,
+                          ulong arg)
+{
+       long ret = 0;
+       void __user *argp = (void __user *)arg;
+
+       switch (cmd) {
+       case V4LVIDEO_IOCTL_ALLOC_ID:{
+                       u32 v4lvideo_id = 0;
+
+                       ret = v4lvideo_alloc_map(&v4lvideo_id);
+                       if (ret != 0)
+                               break;
+                       put_user(v4lvideo_id, (u32 __user *)argp);
+               }
+               break;
+       case V4LVIDEO_IOCTL_FREE_ID:{
+                       u32 v4lvideo_id;
+
+                       get_user(v4lvideo_id, (u32 __user *)argp);
+                       v4lvideo_release_map(v4lvideo_id);
+               }
+               break;
+       case V4LVIDEO_IOCTL_ALLOC_FD:{
+                       u32 v4lvideo_fd = 0;
+
+                       ret = v4lvideo_alloc_fd(&v4lvideo_fd);
+                       if (ret != 0)
+                               break;
+                       put_user(v4lvideo_fd, (u32 __user *)argp);
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+       return ret;
+}
+
+#ifdef CONFIG_COMPAT
+static long v4lvideo_compat_ioctl(struct file *file,
+                                 unsigned int cmd,
+                                 ulong arg)
+{
+       long ret = 0;
+
+       ret = v4lvideo_ioctl(file, cmd, (ulong)compat_ptr(arg));
+       return ret;
+}
+#endif
+static const struct file_operations v4lvideo_fops = {
+       .owner = THIS_MODULE,
+       .open = v4lvideo_open,
+       .release = v4lvideo_release,
+       .unlocked_ioctl = v4lvideo_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = v4lvideo_compat_ioctl,
+#endif
+       .poll = NULL,
+};
+
+static int __init v4lvideo_init(void)
+{
+       int ret = -1, i;
+       struct device *devp;
+
+       keeper_mgr_init();
+
+       ret = class_register(&v4lvideo_class);
+       if (ret < 0)
+               return ret;
+
+       ret = register_chrdev(V4LVIDEO_MAJOR, "v4lvideo", &v4lvideo_fops);
+       if (ret < 0) {
+               pr_err("Can't allocate major for v4lvideo device\n");
+               goto error1;
+       }
+
+       devp = device_create(&v4lvideo_class,
+                            NULL,
+                            MKDEV(V4LVIDEO_MAJOR, 0),
+                            NULL,
+                            V4LVIDEO_DEVICE_NAME);
+       if (IS_ERR(devp)) {
+               pr_err("failed to create v4lvideo device node\n");
+               ret = PTR_ERR(devp);
+               return ret;
+       }
+
+       if (n_devs <= 0)
+               n_devs = 1;
+       for (i = 0; i < n_devs; i++) {
+               ret = v4lvideo_create_instance(i);
+               if (ret) {
+                       /* If some instantiations succeeded, keep driver */
+                       if (i)
+                               ret = 0;
+                       break;
+               }
+       }
+
+       if (ret < 0) {
+               V4LVID_ERR("v4lvideo: error %d while loading driver\n", ret);
+               goto error1;
+       }
+
+       return 0;
+
+error1:
+       unregister_chrdev(V4LVIDEO_MAJOR, "v4lvideo");
+       class_unregister(&v4lvideo_class);
+       return ret;
+}
+
+static void __exit v4lvideo_exit(void)
+{
+       v4lvideo_v4l2_release();
+       device_destroy(&v4lvideo_class, MKDEV(V4LVIDEO_MAJOR, 0));
+       unregister_chrdev(V4LVIDEO_MAJOR, V4LVIDEO_DEVICE_NAME);
+       class_unregister(&v4lvideo_class);
+}
+
+MODULE_DESCRIPTION("Video Technology Magazine V4l Video Capture Board");
+MODULE_AUTHOR("Amlogic, Jintao Xu<jintao.xu@amlogic.com>");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(V4LVIDEO_VERSION);
+
+module_init(v4lvideo_init);
+module_exit(v4lvideo_exit);
diff --git a/drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.h b/drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.h
new file mode 100644 (file)
index 0000000..8042bef
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * drivers/amlogic/media/video_processor/v4lvideo/v4lvideo.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 _v4lvideo_H
+#define _v4lvideo_H
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/videodev2.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/delay.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-common.h>
+
+#include <linux/mm.h>
+/* #include <mach/mod_gate.h> */
+
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/amlogic/media/vfm/vframe_provider.h>
+#include <linux/amlogic/media/vfm/vframe_receiver.h>
+#include <linux/amlogic/media/ge2d/ge2d.h>
+#include <linux/amlogic/media/canvas/canvas.h>
+
+#include <linux/amlogic/media/frame_sync/timestamp.h>
+#include <linux/amlogic/media/frame_sync/tsync.h>
+#include <linux/amlogic/media/video_sink/v4lvideo_ext.h>
+
+#define MAX_WIDTH 4096
+#define MAX_HEIGHT 4096
+
+#define V4LVIDEO_POOL_SIZE 16
+#define VF_POOL_SIZE        32
+#define ION_VF_RECEIVER_NAME_SIZE 32
+
+#define V4LVID_INFO(fmt, args...) pr_info("v4lvid: info: " fmt, ## args)
+#define V4LVID_DBG(fmt, args...) pr_debug("v4lvid: dbg: " fmt, ## args)
+#define V4LVID_ERR(fmt, args...) pr_err("v4lvid: err: " fmt, ## args)
+
+#define dprintk(dev, level, fmt, arg...)                    \
+v4l2_dbg(level, debug, &(dev)->v4l2_dev, fmt, ## arg)
+
+struct v4l2q_s {
+       int rp;
+       int wp;
+       int size;
+       int pre_rp;
+       int pre_wp;
+       void **pool;
+};
+
+static inline void v4l2q_lookup_start(struct v4l2q_s *q)
+{
+       q->pre_rp = q->rp;
+       q->pre_wp = q->wp;
+}
+
+static inline void v4l2q_lookup_end(struct v4l2q_s *q)
+{
+       q->rp = q->pre_rp;
+       q->wp = q->pre_wp;
+}
+
+static inline void v4l2q_init(struct v4l2q_s *q, u32 size,
+                             void **pool)
+{
+       q->rp = 0;
+       q->wp = 0;
+       q->size = size;
+       q->pool = pool;
+}
+
+static inline bool v4l2q_empty(struct v4l2q_s *q)
+{
+       return q->rp == q->wp;
+}
+
+static inline int v4l2q_level(struct v4l2q_s *q)
+{
+       int level = q->wp - q->rp;
+
+       if (level < 0)
+               level += q->size;
+
+       return level;
+}
+
+static inline void v4l2q_push(struct v4l2q_s *q, void *vf)
+{
+       int wp = q->wp;
+
+       /*ToDo*/
+       smp_mb();
+
+       q->pool[wp] = vf;
+
+       /*ToDo*/
+       smp_wmb();
+
+       q->wp = (wp == (q->size - 1)) ? 0 : (wp + 1);
+}
+
+static inline void *v4l2q_pop(struct v4l2q_s *q)
+{
+       void *vf;
+       int rp;
+
+       if (v4l2q_empty(q))
+               return NULL;
+
+       rp = q->rp;
+
+       /*ToDo*/
+       smp_rmb();
+
+       vf = q->pool[rp];
+
+       /*ToDo*/
+       smp_mb();
+
+       q->rp = (rp == (q->size - 1)) ? 0 : (rp + 1);
+
+       return vf;
+}
+
+static inline void *v4l2q_peek(struct v4l2q_s *q)
+{
+       return (v4l2q_empty(q)) ? NULL : q->pool[q->rp];
+}
+
+static inline bool v4l2q_pop_specific(struct v4l2q_s *q, void *vf)
+{
+       void *vf_tmp = NULL;
+       int i = v4l2q_level(q);
+
+       if (i <= 0) {
+               pr_err("v4l2q_pop_specific fail i =%d\n", i);
+               return false;
+       }
+
+       while (i > 0) {
+               i--;
+               vf_tmp = v4l2q_pop(q);
+               if (vf_tmp != vf) {
+                       v4l2q_push(q, vf_tmp);
+                       if (i < 1) {
+                               pr_err("v4l2q_pop_specific fail\n");
+                               return false;
+                       }
+               } else {
+                       break;
+               }
+       }
+       return true;
+}
+
+/* ------------------------------------------------------------------
+ * Basic structures
+ * ------------------------------------------------------------------
+ */
+struct v4lvideo_fmt {
+       char *name;
+       u32 fourcc; /* v4l2 format id */
+       u8 depth;
+       bool is_yuv;
+};
+
+/* v4l2_amlogic_parm must < u8[200] */
+struct v4l2_amlogic_parm {
+               u32     signal_type;
+               struct vframe_master_display_colour_s
+                master_display_colour;
+       };
+
+struct v4lvideo_dev {
+       struct list_head v4lvideo_devlist;
+       struct v4l2_device v4l2_dev;
+       struct video_device vdev;
+       int fd_num;
+
+       /* video capture */
+       const struct v4lvideo_fmt *fmt;
+       unsigned int width, height;
+       struct vframe_receiver_s video_vf_receiver;
+       u64 last_pts_us64;
+
+       char vf_receiver_name[ION_VF_RECEIVER_NAME_SIZE];
+       int inst;
+       bool mapped;
+       int vf_wait_cnt;
+       bool receiver_register;
+       u32 frame_num;
+
+       struct v4l2q_s input_queue;
+       struct v4l2q_s display_queue;
+       struct v4l2_buffer *v4lvideo_input_queue[V4LVIDEO_POOL_SIZE];
+       struct file_private_data *v4lvideo_display_queue[VF_POOL_SIZE];
+       /* mutex_input */
+       struct mutex mutex_input;
+       struct v4l2_buffer v4lvideo_input[V4LVIDEO_POOL_SIZE];
+       struct v4l2_amlogic_parm am_parm;
+       u8 first_frame;
+};
+
+unsigned int get_v4lvideo_debug(void);
+
+#define V4LVIDEO_IOC_MAGIC  'I'
+#define V4LVIDEO_IOCTL_ALLOC_ID   _IOW(V4LVIDEO_IOC_MAGIC, 0x00, int)
+#define V4LVIDEO_IOCTL_FREE_ID    _IOW(V4LVIDEO_IOC_MAGIC, 0x01, int)
+#define V4LVIDEO_IOCTL_ALLOC_FD   _IOW(V4LVIDEO_IOC_MAGIC, 0x02, int)
+
+#endif
diff --git a/drivers/amlogic/media/video_processor/video_composer/Kconfig b/drivers/amlogic/media/video_processor/video_composer/Kconfig
new file mode 100644 (file)
index 0000000..83a9180
--- /dev/null
@@ -0,0 +1,15 @@
+#
+# Amlogic video_composer device configuation
+#
+
+menu "Amlogic video_composer support"
+
+config AMLOGIC_VIDEO_COMPOSER
+       tristate "Amlogic video_composer device support"
+       select VIDEO_DEV
+       default n
+
+       ---help---
+               Select to enable "Amlogic video_composer device support.
+
+endmenu
diff --git a/drivers/amlogic/media/video_processor/video_composer/Makefile b/drivers/amlogic/media/video_processor/video_composer/Makefile
new file mode 100644 (file)
index 0000000..786b2d1
--- /dev/null
@@ -0,0 +1,5 @@
+asflags-y=-mfloat-abi=softfp -mfpu=neon
+ccflags-y += -Idrivers/staging/android/
+
+obj-$(CONFIG_AMLOGIC_VIDEO_COMPOSER) += video_composer.o
+obj-$(CONFIG_AMLOGIC_VIDEO_COMPOSER) += vframe_ge2d_composer.o
\ No newline at end of file
diff --git a/drivers/amlogic/media/video_processor/video_composer/vfq.h b/drivers/amlogic/media/video_processor/video_composer/vfq.h
new file mode 100644 (file)
index 0000000..02423af
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * drivers/amlogic/media/video_processor/video_composer/vfq.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 __VFQ_H_
+#define __VFQ_H_
+
+struct vfq_s {
+       int rp;
+       int wp;
+       int size;
+       int pre_rp;
+       int pre_wp;
+       struct vframe_s **pool;
+};
+
+static inline void vfq_lookup_start(struct vfq_s *q)
+{
+       q->pre_rp = q->rp;
+       q->pre_wp = q->wp;
+}
+
+static inline void vfq_lookup_end(struct vfq_s *q)
+{
+       q->rp = q->pre_rp;
+       q->wp = q->pre_wp;
+}
+
+static inline void vfq_init(struct vfq_s *q, u32 size, struct vframe_s **pool)
+{
+       q->rp = 0;
+       q->wp = 0;
+       q->size = size;
+       q->pool = pool;
+}
+
+static inline bool vfq_empty(struct vfq_s *q)
+{
+       return q->rp == q->wp;
+}
+
+static inline bool vfq_full(struct vfq_s *q)
+{
+       bool ret = (((q->wp + 1) % q->size) == q->rp);
+
+       return ret;
+}
+
+static inline void vfq_push(struct vfq_s *q, struct vframe_s *vf)
+{
+       int wp = q->wp;
+
+       /*ToDo*/
+       smp_mb();
+
+       q->pool[wp] = vf;
+
+       /*ToDo*/
+       smp_wmb();
+
+       q->wp = (wp == (q->size - 1)) ? 0 : (wp + 1);
+}
+
+static inline struct vframe_s *vfq_pop(struct vfq_s *q)
+{
+       struct vframe_s *vf;
+       int rp;
+
+       if (vfq_empty(q))
+               return NULL;
+
+       rp = q->rp;
+
+       /*ToDo*/
+       smp_rmb();
+
+       vf = q->pool[rp];
+
+       /*ToDo*/
+       smp_mb();
+
+       q->rp = (rp == (q->size - 1)) ? 0 : (rp + 1);
+
+       return vf;
+}
+
+static inline struct vframe_s *vfq_peek(struct vfq_s *q)
+{
+       return (vfq_empty(q)) ? NULL : q->pool[q->rp];
+}
+
+static inline int vfq_level(struct vfq_s *q)
+{
+       int level = q->wp - q->rp;
+
+       if (level < 0)
+               level += q->size;
+
+       return level;
+}
+
+#endif /* __VFP_H_ */
diff --git a/drivers/amlogic/media/video_processor/video_composer/vframe_ge2d_composer.c b/drivers/amlogic/media/video_processor/video_composer/vframe_ge2d_composer.c
new file mode 100644 (file)
index 0000000..715d79d
--- /dev/null
@@ -0,0 +1,560 @@
+/*
+ * drivers/amlogic/media/video_processor/video_composer/vframe_ge2d_composer.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/amlogic/media/ge2d/ge2d.h>
+#include <linux/amlogic/media/canvas/canvas.h>
+#include <linux/amlogic/media/canvas/canvas_mgr.h>
+#include <linux/amlogic/media/utils/amlog.h>
+#include <linux/amlogic/media/ge2d/ge2d_func.h>
+#include "vframe_ge2d_composer.h"
+#include "vfq.h"
+#include <linux/amlogic/cpu_version.h>
+#include <linux/mm.h>
+#include <linux/file.h>
+#include <linux/delay.h>
+
+static unsigned int ge2d_com_debug;
+MODULE_PARM_DESC(ge2d_com_debug, "\n ge2d_com_debug\n");
+module_param(ge2d_com_debug, uint, 0664);
+
+static int get_source_type(struct src_data_para *src_data)
+{
+       enum videocom_source_type ret;
+       int interlace_mode;
+
+       interlace_mode = src_data->type & VIDTYPE_TYPEMASK;
+       if ((src_data->source_type == VFRAME_SOURCE_TYPE_HDMI) ||
+           (src_data->source_type == VFRAME_SOURCE_TYPE_CVBS)) {
+               if ((src_data->bitdepth & BITDEPTH_Y10)  &&
+                   (!(src_data->type & VIDTYPE_COMPRESS)) &&
+                   (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXL))
+                       ret = VDIN_10BIT_NORMAL;
+               else
+                       ret = VDIN_8BIT_NORMAL;
+       } else {
+               if ((src_data->bitdepth & BITDEPTH_Y10)  &&
+                   (!(src_data->type & VIDTYPE_COMPRESS)) &&
+                   (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXL)) {
+                       if (interlace_mode == VIDTYPE_INTERLACE_TOP)
+                               ret = DECODER_10BIT_TOP;
+                       else if (interlace_mode == VIDTYPE_INTERLACE_BOTTOM)
+                               ret = DECODER_10BIT_BOTTOM;
+                       else
+                               ret = DECODER_10BIT_NORMAL;
+               } else {
+                       if (interlace_mode == VIDTYPE_INTERLACE_TOP)
+                               ret = DECODER_8BIT_TOP;
+                       else if (interlace_mode == VIDTYPE_INTERLACE_BOTTOM)
+                               ret = DECODER_8BIT_BOTTOM;
+                       else
+                               ret = DECODER_8BIT_NORMAL;
+               }
+       }
+       return ret;
+}
+
+static int get_input_format(struct src_data_para *src_data)
+{
+       int format = GE2D_FORMAT_M24_YUV420;
+       enum videocom_source_type soure_type;
+
+       soure_type = get_source_type(src_data);
+       switch (soure_type) {
+       case DECODER_8BIT_NORMAL:
+               if (src_data->type & VIDTYPE_VIU_422)
+                       format = GE2D_FORMAT_S16_YUV422;
+               else if (src_data->type & VIDTYPE_VIU_NV21)
+                       format = GE2D_FORMAT_M24_NV21;
+               else if (src_data->type & VIDTYPE_VIU_444)
+                       format = GE2D_FORMAT_S24_YUV444;
+               else
+                       format = GE2D_FORMAT_M24_YUV420;
+               break;
+       case DECODER_8BIT_BOTTOM:
+               if (src_data->type & VIDTYPE_VIU_422)
+                       format = GE2D_FORMAT_S16_YUV422
+                               | (GE2D_FORMAT_S16_YUV422B & (3 << 3));
+               else if (src_data->type & VIDTYPE_VIU_NV21)
+                       format = GE2D_FORMAT_M24_NV21
+                               | (GE2D_FORMAT_M24_NV21B & (3 << 3));
+               else if (src_data->type & VIDTYPE_VIU_444)
+                       format = GE2D_FORMAT_S24_YUV444
+                               | (GE2D_FORMAT_S24_YUV444B & (3 << 3));
+               else
+                       format = GE2D_FORMAT_M24_YUV420
+                               | (GE2D_FMT_M24_YUV420B & (3 << 3));
+               break;
+       case DECODER_8BIT_TOP:
+               if (src_data->type & VIDTYPE_VIU_422)
+                       format = GE2D_FORMAT_S16_YUV422
+                               | (GE2D_FORMAT_S16_YUV422T & (3 << 3));
+               else if (src_data->type & VIDTYPE_VIU_NV21)
+                       format = GE2D_FORMAT_M24_NV21
+                               | (GE2D_FORMAT_M24_NV21T & (3 << 3));
+               else if (src_data->type & VIDTYPE_VIU_444)
+                       format = GE2D_FORMAT_S24_YUV444
+                               | (GE2D_FORMAT_S24_YUV444T & (3 << 3));
+               else
+                       format = GE2D_FORMAT_M24_YUV420
+                               | (GE2D_FMT_M24_YUV420T & (3 << 3));
+               break;
+       case DECODER_10BIT_NORMAL:
+               if (src_data->type & VIDTYPE_VIU_422) {
+                       if (src_data->bitdepth & FULL_PACK_422_MODE)
+                               format = GE2D_FORMAT_S16_10BIT_YUV422;
+                       else
+                               format = GE2D_FORMAT_S16_12BIT_YUV422;
+               }
+               break;
+       case DECODER_10BIT_BOTTOM:
+               if (src_data->type & VIDTYPE_VIU_422) {
+                       if (src_data->bitdepth & FULL_PACK_422_MODE)
+                               format = GE2D_FORMAT_S16_10BIT_YUV422
+                                       | (GE2D_FORMAT_S16_10BIT_YUV422B
+                                       & (3 << 3));
+                       else
+                               format = GE2D_FORMAT_S16_12BIT_YUV422
+                                       | (GE2D_FORMAT_S16_12BIT_YUV422B
+                                       & (3 << 3));
+               }
+               break;
+       case DECODER_10BIT_TOP:
+               if (src_data->type & VIDTYPE_VIU_422) {
+                       if (src_data->bitdepth & FULL_PACK_422_MODE)
+                               format = GE2D_FORMAT_S16_10BIT_YUV422
+                                       | (GE2D_FORMAT_S16_10BIT_YUV422T
+                                       & (3 << 3));
+                       else
+                               format = GE2D_FORMAT_S16_12BIT_YUV422
+                                       | (GE2D_FORMAT_S16_12BIT_YUV422T
+                                       & (3 << 3));
+               }
+               break;
+       case VDIN_8BIT_NORMAL:
+               if (src_data->type & VIDTYPE_VIU_422)
+                       format = GE2D_FORMAT_S16_YUV422;
+               else if (src_data->type & VIDTYPE_VIU_NV21)
+                       format = GE2D_FORMAT_M24_NV21;
+               else if (src_data->type & VIDTYPE_VIU_444)
+                       format = GE2D_FORMAT_S24_YUV444;
+               else
+                       format = GE2D_FORMAT_M24_YUV420;
+               break;
+       case VDIN_10BIT_NORMAL:
+               if (src_data->type & VIDTYPE_VIU_422) {
+                       if (src_data->bitdepth & FULL_PACK_422_MODE)
+                               format = GE2D_FORMAT_S16_10BIT_YUV422;
+                       else
+                               format = GE2D_FORMAT_S16_12BIT_YUV422;
+               }
+               break;
+       default:
+               format = GE2D_FORMAT_M24_YUV420;
+       }
+       return format;
+}
+
+static int alloc_src_canvas(struct ge2d_composer_para *ge2d_comp_para)
+{
+       const char *keep_owner = "ge2d_composer";
+
+       if (ge2d_comp_para->canvas_scr[0] < 0)
+               ge2d_comp_para->canvas_scr[0] =
+                       canvas_pool_map_alloc_canvas(keep_owner);
+       if (ge2d_comp_para->canvas_scr[1] < 0)
+               ge2d_comp_para->canvas_scr[1] =
+                       canvas_pool_map_alloc_canvas(keep_owner);
+       if (ge2d_comp_para->canvas_scr[2] < 0)
+               ge2d_comp_para->canvas_scr[2] =
+                       canvas_pool_map_alloc_canvas(keep_owner);
+
+       if ((ge2d_comp_para->canvas_scr[0] < 0) ||
+           (ge2d_comp_para->canvas_scr[1] < 0) ||
+           (ge2d_comp_para->canvas_scr[2] < 0)) {
+               VIDEOCOM_INFO("scr_canvas alloc failed\n");
+               return -1;
+       }
+       return 0;
+}
+
+static int free_src_canvas(struct ge2d_composer_para *ge2d_comp_para)
+{
+       if (ge2d_comp_para->canvas_scr[0] >= 0) {
+               canvas_pool_map_free_canvas(
+                                           ge2d_comp_para->canvas_scr[0]);
+               ge2d_comp_para->canvas_scr[0] = -1;
+       }
+
+       if (ge2d_comp_para->canvas_scr[1] >= 0) {
+               canvas_pool_map_free_canvas(
+                                           ge2d_comp_para->canvas_scr[1]);
+               ge2d_comp_para->canvas_scr[1] = -1;
+       }
+
+       if (ge2d_comp_para->canvas_scr[2] >= 0) {
+               canvas_pool_map_free_canvas(
+                                           ge2d_comp_para->canvas_scr[2]);
+               ge2d_comp_para->canvas_scr[2] = -1;
+       }
+       if ((ge2d_comp_para->canvas_scr[0] >= 0) ||
+           (ge2d_comp_para->canvas_scr[1] >= 0) ||
+           (ge2d_comp_para->canvas_scr[2] >= 0)) {
+               VIDEOCOM_INFO("scr_canvas free failed!\n");
+               return -1;
+       }
+       return 0;
+}
+
+int init_ge2d_composer(struct ge2d_composer_para *ge2d_comp_para)
+{
+       const char *keep_owner = "ge2d_dest_comp";
+
+       ge2d_comp_para->context = create_ge2d_work_queue();
+       if (IS_ERR_OR_NULL(ge2d_comp_para->context)) {
+               VIDEOCOM_INFO("creat ge2d work failed\n");
+               return -1;
+       }
+
+       if (ge2d_comp_para->plane_num > 0) {
+               if (ge2d_comp_para->canvas_dst[0] < 0)
+                       ge2d_comp_para->canvas_dst[0] =
+                               canvas_pool_map_alloc_canvas(keep_owner);
+               if (ge2d_comp_para->canvas_dst[0] < 0) {
+                       VIDEOCOM_ERR("ge2d init dst canvas_0 failed!\n");
+                       return -1;
+               }
+       }
+
+       if (ge2d_comp_para->plane_num > 1) {
+               if (ge2d_comp_para->canvas_dst[1] < 0)
+                       ge2d_comp_para->canvas_dst[1] =
+                               canvas_pool_map_alloc_canvas(keep_owner);
+               if (ge2d_comp_para->canvas_dst[1] < 0) {
+                       VIDEOCOM_ERR("ge2d init dst canvas_1 failed!\n");
+                       return -1;
+               }
+       }
+
+       if (ge2d_comp_para->plane_num > 2) {
+               if (ge2d_comp_para->canvas_dst[2] < 0)
+                       ge2d_comp_para->canvas_dst[2] =
+                               canvas_pool_map_alloc_canvas(keep_owner);
+               if (ge2d_comp_para->canvas_dst[2] < 0) {
+                       VIDEOCOM_ERR("ge2d init dst canvas_2 failed!\n");
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+int uninit_ge2d_composer(struct ge2d_composer_para *ge2d_comp_para)
+{
+       destroy_ge2d_work_queue(ge2d_comp_para->context);
+       ge2d_comp_para->context = NULL;
+
+       if (free_src_canvas(ge2d_comp_para) < 0) {
+               VIDEOCOM_ERR("free src canvas failed!\n");
+               return -1;
+       }
+
+       if (ge2d_comp_para->canvas_dst[0] >= 0) {
+               canvas_pool_map_free_canvas(
+                                           ge2d_comp_para->canvas_dst[0]);
+               ge2d_comp_para->canvas_dst[0] = -1;
+       }
+
+       if (ge2d_comp_para->canvas_dst[1] >= 0) {
+               canvas_pool_map_free_canvas(
+                                           ge2d_comp_para->canvas_dst[1]);
+               ge2d_comp_para->canvas_dst[1] = -1;
+       }
+
+       if (ge2d_comp_para->canvas_dst[2] >= 0) {
+               canvas_pool_map_free_canvas(
+                                           ge2d_comp_para->canvas_dst[2]);
+               ge2d_comp_para->canvas_dst[2] = -1;
+       }
+
+       if ((ge2d_comp_para->canvas_dst[0] >= 0) ||
+           (ge2d_comp_para->canvas_dst[1] >= 0) ||
+           (ge2d_comp_para->canvas_dst[2] >= 0)) {
+               VIDEOCOM_ERR("free dst canvas failed!\n");
+               return -1;
+       }
+       return 0;
+}
+
+int fill_vframe_black(struct ge2d_composer_para *ge2d_comp_para)
+{
+       struct canvas_config_s dst_canvas0_config[3];
+       u32 dst_plane_num;
+
+       memset(ge2d_comp_para->ge2d_config, 0, sizeof(struct config_para_ex_s));
+
+       if (ge2d_comp_para->format == GE2D_FORMAT_S24_YUV444) {
+               dst_canvas0_config[0].phy_addr = ge2d_comp_para->phy_addr[0];
+               dst_canvas0_config[0].width = ge2d_comp_para->buffer_w * 3;
+               dst_canvas0_config[0].height = ge2d_comp_para->buffer_h;
+               dst_canvas0_config[0].block_mode = 0;
+               dst_canvas0_config[0].endian = 0;
+       }
+       dst_plane_num = 1;
+
+       if (ge2d_comp_para->canvas0Addr == (u32)-1) {
+               canvas_config_config(
+                                    ge2d_comp_para->canvas_dst[0],
+                                    &dst_canvas0_config[0]);
+               if (dst_plane_num == 2) {
+                       canvas_config_config(
+                                            ge2d_comp_para->canvas_dst[1],
+                                            &dst_canvas0_config[1]);
+               } else if (dst_plane_num == 3) {
+                       canvas_config_config(
+                                            ge2d_comp_para->canvas_dst[2],
+                                            &dst_canvas0_config[2]);
+               }
+               ge2d_comp_para->ge2d_config->src_para.canvas_index =
+                       ge2d_comp_para->canvas_dst[0]
+                       | (ge2d_comp_para->canvas_dst[1] << 8)
+                       | (ge2d_comp_para->canvas_dst[2] << 16);
+
+       } else {
+               ge2d_comp_para->ge2d_config->src_para.canvas_index =
+                       ge2d_comp_para->canvas0Addr;
+       }
+       ge2d_comp_para->ge2d_config->alu_const_color = 0;/*0x000000ff;*/
+       ge2d_comp_para->ge2d_config->bitmask_en = 0;
+       ge2d_comp_para->ge2d_config->src1_gb_alpha = 0;/*0xff;*/
+       ge2d_comp_para->ge2d_config->dst_xy_swap = 0;
+
+       ge2d_comp_para->ge2d_config->src_key.key_enable = 0;
+       ge2d_comp_para->ge2d_config->src_key.key_mask = 0;
+       ge2d_comp_para->ge2d_config->src_key.key_mode = 0;
+
+       ge2d_comp_para->ge2d_config->src_para.mem_type =
+               CANVAS_TYPE_INVALID;
+       ge2d_comp_para->ge2d_config->src_para.format =
+               ge2d_comp_para->format;
+       ge2d_comp_para->ge2d_config->src_para.fill_color_en = 0;
+       ge2d_comp_para->ge2d_config->src_para.fill_mode = 0;
+       ge2d_comp_para->ge2d_config->src_para.x_rev = 0;
+       ge2d_comp_para->ge2d_config->src_para.y_rev = 0;
+       ge2d_comp_para->ge2d_config->src_para.color = 0;
+       ge2d_comp_para->ge2d_config->src_para.top = 0;
+       ge2d_comp_para->ge2d_config->src_para.left = 0;
+       ge2d_comp_para->ge2d_config->src_para.width =
+               ge2d_comp_para->buffer_w;
+       ge2d_comp_para->ge2d_config->src_para.height =
+               ge2d_comp_para->buffer_h;
+       ge2d_comp_para->ge2d_config->src2_para.mem_type =
+               CANVAS_TYPE_INVALID;
+       ge2d_comp_para->ge2d_config->dst_para.canvas_index =
+               ge2d_comp_para->ge2d_config->src_para.canvas_index;
+       ge2d_comp_para->ge2d_config->dst_para.mem_type =
+               CANVAS_TYPE_INVALID;
+       ge2d_comp_para->ge2d_config->dst_para.fill_color_en = 0;
+       ge2d_comp_para->ge2d_config->dst_para.fill_mode = 0;
+       ge2d_comp_para->ge2d_config->dst_para.x_rev = 0;
+       ge2d_comp_para->ge2d_config->dst_para.y_rev = 0;
+       ge2d_comp_para->ge2d_config->dst_para.color = 0;
+       ge2d_comp_para->ge2d_config->dst_para.top = 0;
+       ge2d_comp_para->ge2d_config->dst_para.left = 0;
+       ge2d_comp_para->ge2d_config->dst_para.format =
+               ge2d_comp_para->format;
+       ge2d_comp_para->ge2d_config->dst_para.width =
+               ge2d_comp_para->buffer_w;
+       ge2d_comp_para->ge2d_config->dst_para.height =
+               ge2d_comp_para->buffer_h;
+
+       if (ge2d_context_config_ex(ge2d_comp_para->context,
+                                  ge2d_comp_para->ge2d_config) < 0) {
+               VIDEOCOM_ERR("++ge2d configing error.\n");
+               return -1;
+       }
+       fillrect(ge2d_comp_para->context, 0, 0,
+                ge2d_comp_para->buffer_w,
+                ge2d_comp_para->buffer_h,
+               0x008080ff);
+       return 0;
+}
+
+int ge2d_data_composer(
+       struct src_data_para *scr_data,
+       struct ge2d_composer_para *ge2d_comp_para)
+{
+       int ret;
+       struct canvas_config_s dst_canvas0_config[3];
+       u32 dst_plane_num;
+       int src_canvas_id, dst_canvas_id;
+       int input_width, input_height;
+       int position_left, position_top;
+       int position_width, position_height;
+
+       memset(ge2d_comp_para->ge2d_config,
+              0, sizeof(struct config_para_ex_s));
+
+       if (ge2d_comp_para->format == GE2D_FORMAT_S24_YUV444) {
+               dst_canvas0_config[0].phy_addr = ge2d_comp_para->phy_addr[0];
+               dst_canvas0_config[0].width = ge2d_comp_para->buffer_w * 3;
+               dst_canvas0_config[0].height = ge2d_comp_para->buffer_h;
+               dst_canvas0_config[0].block_mode = 0;
+               dst_canvas0_config[0].endian = 0;
+       }
+       dst_plane_num = 1;
+
+       if (scr_data->canvas0Addr == (u32)-1) {
+               ret = alloc_src_canvas(ge2d_comp_para);
+               if (ret < 0) {
+                       VIDEOCOM_ERR("alloc src canvas failed!\n");
+                       return -1;
+               }
+               canvas_config_config(
+                                    ge2d_comp_para->canvas_scr[0],
+                                    &scr_data->canvas0_config[0]);
+               if (scr_data->plane_num == 2) {
+                       canvas_config_config(
+                                            ge2d_comp_para->canvas_scr[1],
+                                            &scr_data->canvas0_config[1]);
+               } else if (scr_data->plane_num == 3) {
+                       canvas_config_config(
+                                            ge2d_comp_para->canvas_scr[2],
+                                            &scr_data->canvas0_config[2]);
+               }
+               src_canvas_id = ge2d_comp_para->canvas_scr[0]
+                       | (ge2d_comp_para->canvas_scr[1] << 8)
+                       | (ge2d_comp_para->canvas_scr[2] << 16);
+       } else {
+               src_canvas_id = scr_data->canvas0Addr;
+       }
+
+       if (ge2d_comp_para->canvas0Addr == (u32)-1) {
+               canvas_config_config(
+                                    ge2d_comp_para->canvas_dst[0],
+                                    &dst_canvas0_config[0]);
+               if (dst_plane_num == 2) {
+                       canvas_config_config(
+                                            ge2d_comp_para->canvas_dst[1],
+                                            &dst_canvas0_config[1]);
+               } else if (dst_plane_num == 3) {
+                       canvas_config_config(
+                                            ge2d_comp_para->canvas_dst[2],
+                                            &dst_canvas0_config[2]);
+               }
+               dst_canvas_id = ge2d_comp_para->canvas_dst[0]
+                       | (ge2d_comp_para->canvas_dst[1] << 8)
+                       | (ge2d_comp_para->canvas_dst[2] << 16);
+       } else {
+               dst_canvas_id = ge2d_comp_para->canvas0Addr;
+       }
+       input_width = scr_data->width;
+       input_height = scr_data->height;
+
+       if (scr_data->type & VIDTYPE_INTERLACE)
+               input_height = scr_data->height >> 1;
+       else
+               input_height = scr_data->height;
+       ge2d_comp_para->ge2d_config->alu_const_color = 0;
+       ge2d_comp_para->ge2d_config->bitmask_en = 0;
+       ge2d_comp_para->ge2d_config->src1_gb_alpha = 0;
+       ge2d_comp_para->ge2d_config->dst_xy_swap = 0;
+
+       ge2d_comp_para->ge2d_config->src_key.key_enable = 0;
+       ge2d_comp_para->ge2d_config->src_key.key_mask = 0;
+       ge2d_comp_para->ge2d_config->src_key.key_mode = 0;
+       ge2d_comp_para->ge2d_config->src_para.mem_type =
+               CANVAS_TYPE_INVALID;
+       if (scr_data->is_vframe)
+               ge2d_comp_para->ge2d_config->src_para.format =
+                       get_input_format(scr_data);
+       else
+               ge2d_comp_para->ge2d_config->src_para.format =
+                       get_input_format(scr_data) | GE2D_LITTLE_ENDIAN;
+
+       ge2d_comp_para->ge2d_config->src_para.fill_color_en = 0;
+       ge2d_comp_para->ge2d_config->src_para.fill_mode = 0;
+       ge2d_comp_para->ge2d_config->src_para.x_rev = 0;
+       ge2d_comp_para->ge2d_config->src_para.y_rev = 0;
+       ge2d_comp_para->ge2d_config->src_para.color =
+               0xffffffff;
+       ge2d_comp_para->ge2d_config->src_para.top = 0;
+       ge2d_comp_para->ge2d_config->src_para.left = 0;
+       ge2d_comp_para->ge2d_config->src_para.width = input_width;
+       ge2d_comp_para->ge2d_config->src_para.height = input_height;
+       ge2d_comp_para->ge2d_config->src_para.canvas_index = src_canvas_id;
+
+       ge2d_comp_para->ge2d_config->src2_para.mem_type =
+               CANVAS_TYPE_INVALID;
+
+       ge2d_comp_para->ge2d_config->dst_para.mem_type =
+               CANVAS_TYPE_INVALID;
+
+       ge2d_comp_para->ge2d_config->dst_para.fill_color_en = 0;
+       ge2d_comp_para->ge2d_config->dst_para.fill_mode = 0;
+       ge2d_comp_para->ge2d_config->dst_para.x_rev = 0;
+       ge2d_comp_para->ge2d_config->dst_para.y_rev = 0;
+       ge2d_comp_para->ge2d_config->dst_xy_swap = 0;
+
+       if (ge2d_comp_para->angle == 1) {
+               ge2d_comp_para->ge2d_config->dst_xy_swap = 1;
+               ge2d_comp_para->ge2d_config->dst_para.x_rev = 1;
+       } else if (ge2d_comp_para->angle == 2) {
+               ge2d_comp_para->ge2d_config->dst_para.x_rev = 1;
+               ge2d_comp_para->ge2d_config->dst_para.y_rev = 1;
+       } else if (ge2d_comp_para->angle == 3) {
+               ge2d_comp_para->ge2d_config->dst_xy_swap = 1;
+               ge2d_comp_para->ge2d_config->dst_para.y_rev = 1;
+       }
+       ge2d_comp_para->ge2d_config->dst_para.canvas_index = dst_canvas_id;
+
+       ge2d_comp_para->ge2d_config->dst_para.color = 0;
+       ge2d_comp_para->ge2d_config->dst_para.top = 0;
+       ge2d_comp_para->ge2d_config->dst_para.left = 0;
+
+       ge2d_comp_para->ge2d_config->dst_para.format =
+               ge2d_comp_para->format;
+       ge2d_comp_para->ge2d_config->dst_para.width =
+               ge2d_comp_para->buffer_w;
+       ge2d_comp_para->ge2d_config->dst_para.height =
+               ge2d_comp_para->buffer_h;
+
+       if (ge2d_context_config_ex(ge2d_comp_para->context,
+                                  ge2d_comp_para->ge2d_config) < 0) {
+               VIDEOCOM_ERR("++ge2d configing error.\n");
+               return -1;
+       }
+
+       position_left = ge2d_comp_para->position_left;
+       position_top = ge2d_comp_para->position_top;
+       position_width = ge2d_comp_para->position_width;
+       position_height = ge2d_comp_para->position_height;
+
+       stretchblt_noalpha(ge2d_comp_para->context,
+                          0,
+                          0,
+                          input_width,
+                          input_height,
+                          position_left,
+                          position_top,
+                          position_width,
+                          position_height);
+       if (ge2d_com_debug & 1)
+               VIDEOCOM_INFO("scr format: %0x, dst format: %0x!\n",
+                             ge2d_comp_para->ge2d_config->src_para.format,
+                             ge2d_comp_para->ge2d_config->dst_para.format);
+       return 0;
+}
+
diff --git a/drivers/amlogic/media/video_processor/video_composer/vframe_ge2d_composer.h b/drivers/amlogic/media/video_processor/video_composer/vframe_ge2d_composer.h
new file mode 100644 (file)
index 0000000..de8ece8
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * drivers/amlogic/media/video_processor/video_composer/vframe_ge2d_composer.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 VFRAME_GE2D_COMPOSER_H
+#define VFRAME_GE2D_COMPOSER_H
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/amlogic/media/vout/vout_notify.h>
+#include <linux/amlogic/media/vfm/vframe.h>
+//#include "video_composer.h"
+
+#define VIDEOCOM_INFO(fmt, args...)    \
+       pr_info("video_composer: info:" fmt "", ## args)
+#define VIDEOCOM_DBG(fmt, args...)     \
+       pr_debug("video_composer: dbg:" fmt "", ## args)
+#define VIDEOCOM_WARN(fmt, args...)    \
+       pr_warn("video_composer: warn:" fmt "", ## args)
+#define VIDEOCOM_ERR(fmt, args...)     \
+       pr_err("video_composer: err:" fmt "", ## args)
+
+enum videocom_source_type {
+       DECODER_8BIT_NORMAL = 0,
+       DECODER_8BIT_BOTTOM,
+       DECODER_8BIT_TOP,
+       DECODER_10BIT_NORMAL,
+       DECODER_10BIT_BOTTOM,
+       DECODER_10BIT_TOP,
+       VDIN_8BIT_NORMAL,
+       VDIN_10BIT_NORMAL,
+};
+
+struct ge2d_composer_para {
+       int count;
+       int format;
+       int position_left;
+       int position_top;
+       int position_width;
+       int position_height;
+       int buffer_w;
+       int buffer_h;
+       int plane_num;
+       int canvas_scr[3];
+       int canvas_dst[3];
+       u32 phy_addr[3];
+       u32 canvas0Addr;
+       struct ge2d_context_s *context;
+       struct config_para_ex_s *ge2d_config;
+       int angle;
+};
+
+struct src_data_para {
+       u32 canvas0Addr;
+       u32 canvas1Addr;
+       u32 plane_num;
+       u32 type;
+       u32 width;
+       u32 height;
+       u32 bitdepth;
+       struct canvas_config_s canvas0_config[3];
+       struct canvas_config_s canvas1_config[3];
+       enum vframe_source_type_e source_type;
+       bool is_vframe;
+};
+
+int init_ge2d_composer(struct ge2d_composer_para *ge2d_comp_para);
+
+int uninit_ge2d_composer(struct ge2d_composer_para *ge2d_comp_para);
+
+int fill_vframe_black(struct ge2d_composer_para *ge2d_comp_para);
+
+int ge2d_data_composer(struct src_data_para *src_para,
+                      struct ge2d_composer_para *ge2d_comp_para);
+
+#endif
diff --git a/drivers/amlogic/media/video_processor/video_composer/video_composer.c b/drivers/amlogic/media/video_processor/video_composer/video_composer.c
new file mode 100644 (file)
index 0000000..9c1c563
--- /dev/null
@@ -0,0 +1,1901 @@
+/*
+ * drivers/amlogic/media/video_processor/video_composer/video_composer.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/amlogic/major.h>
+#include <linux/platform_device.h>
+#include <linux/time.h>
+#include <linux/uaccess.h>
+#include <linux/file.h>
+#include <linux/amlogic/media/video_sink/video.h>
+#include <linux/amlogic/aml_sync_api.h>
+#include <linux/amlogic/media/canvas/canvas.h>
+#include <linux/amlogic/media/canvas/canvas_mgr.h>
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include <linux/dma-buf.h>
+#include <ion/ion.h>
+#include <ion/ion_priv.h>
+#include "video_composer.h"
+
+#define VIDEO_COMPOSER_VERSION "1.0"
+
+#define VIDEO_COMPOSER_NAME_SIZE 32
+
+#define VIDEO_COMPOSER_DEVICE_NAME   "video_composer-dev"
+
+#define MAX_VIDEO_COMPOSER_INSTANCE_NUM ARRAY_SIZE(ports)
+
+#define WAIT_THREAD_STOPPED_TIMEOUT 20
+
+#define WAIT_READY_Q_TIMEOUT 100
+
+static u32 video_composer_instance_num;
+static unsigned int force_composer;
+MODULE_PARM_DESC(force_composer, "\n vidc_bypass\n");
+module_param(force_composer, uint, 0664);
+
+static unsigned int force_composer_pip;
+MODULE_PARM_DESC(force_composer_pip, "\n vidc_pip_bypass\n");
+module_param(force_composer_pip, uint, 0664);
+
+static unsigned int transform;
+MODULE_PARM_DESC(transform, "\n transform\n");
+module_param(transform, uint, 0664);
+
+static unsigned int vidc_debug;
+MODULE_PARM_DESC(vidc_debug, "\n vidc_debug\n");
+module_param(vidc_debug, uint, 0664);
+
+static u32 print_flag;
+MODULE_PARM_DESC(print_flag, "\n print_flag\n");
+module_param(print_flag, uint, 0664);
+
+static u32 full_axis;
+MODULE_PARM_DESC(full_axis, "\n print_flag\n");
+module_param(full_axis, uint, 0664);
+
+static u32 print_close;
+MODULE_PARM_DESC(print_close, "\n print_close\n");
+module_param(print_close, uint, 0664);
+
+static u32 receive_wait = 15;
+MODULE_PARM_DESC(receive_wait, "\n receive_wait\n");
+module_param(receive_wait, uint, 0664);
+
+static u32  margin_time = 2000;
+MODULE_PARM_DESC(margin_time, "\n margin_time\n");
+module_param(margin_time, uint, 0664);
+
+static u32 max_width = 2560;
+MODULE_PARM_DESC(max_width, "\n max_width\n");
+module_param(max_width, uint, 0664);
+
+static u32  max_height = 1440;
+MODULE_PARM_DESC(max_height, "\n max_height\n");
+module_param(max_height, uint, 0664);
+
+static u32 rotate_width = 1280;
+MODULE_PARM_DESC(rotate_width, "\n rotate_width\n");
+module_param(rotate_width, uint, 0664);
+
+static u32  rotate_height = 720;
+MODULE_PARM_DESC(rotate_height, "\n rotate_height\n");
+module_param(rotate_height, uint, 0664);
+
+static u32  close_black;
+MODULE_PARM_DESC(close_black, "\n close_black\n");
+module_param(close_black, uint, 0664);
+
+static struct class *video_composer_dev_class;
+
+static struct class_attribute video_composer_class_attrs[] = {
+};
+
+static struct class video_composer_class = {
+       .name = "video_composer",
+       .class_attrs = video_composer_class_attrs,
+};
+
+#define PRINT_ERROR            0X0
+#define PRINT_QUEUE_STATUS     0X0001
+#define PRINT_FENCE            0X0002
+#define PRINT_PERFORMANCE      0X0004
+#define PRINT_OTHER            0X0008
+
+#define to_dst_buf(vf) \
+       container_of(vf, struct dst_buf_t, frame)
+
+int vc_print(int index, int debug_flag, const char *fmt, ...)
+{
+       if (index + 1 == print_close)
+               return 0;
+
+       if ((print_flag & debug_flag) ||
+           (debug_flag == PRINT_ERROR)) {
+               unsigned char buf[256];
+               int len = 0;
+               va_list args;
+
+               va_start(args, fmt);
+               len = sprintf(buf, "vc:[%d]", index);
+               vsnprintf(buf + len, 256 - len, fmt, args);
+               pr_info("%s", buf);
+               va_end(args);
+       }
+       return 0;
+}
+
+static DEFINE_MUTEX(video_composer_mutex);
+
+static struct video_composer_port_s ports[] = {
+       {
+               .name = "video_composer.0",
+               .index = 0,
+               .open_count = 0,
+       },
+       {
+               .name = "video_composer.1",
+               .index = 1,
+               .open_count = 0,
+       },
+};
+
+static struct timeval vsync_time;
+static int get_count[MAX_VIDEO_COMPOSER_INSTANCE_NUM];
+
+void vsync_notify_video_composer(void)
+{
+       int i;
+       int count = MAX_VIDEO_COMPOSER_INSTANCE_NUM;
+
+       for (i = 0; i < count; i++)
+               get_count[i] = 0;
+       do_gettimeofday(&vsync_time);
+}
+
+static void *video_timeline_create(struct composer_dev *dev)
+{
+       const char *tl_name = "videocomposer_timeline_0";
+
+       if (dev->index == 0)
+               tl_name = "videocomposer_timeline_0";
+       else if (dev->index == 1)
+               tl_name = "videocomposer_timeline_1";
+
+       if (IS_ERR_OR_NULL(dev->video_timeline)) {
+               dev->cur_streamline_val = 0;
+               dev->video_timeline = aml_sync_create_timeline(tl_name);
+               vc_print(dev->index, PRINT_FENCE,
+                        "timeline create tlName =%s, video_timeline=%p\n",
+                        tl_name, dev->video_timeline);
+       }
+
+       return dev->video_timeline;
+}
+
+static int video_timeline_create_fence(struct composer_dev *dev)
+{
+       int out_fence_fd = -1;
+       u32 pt_val = 0;
+
+       pt_val = dev->cur_streamline_val + 1;
+       out_fence_fd = aml_sync_create_fence(dev->video_timeline, pt_val);
+       if (out_fence_fd >= 0) {
+               dev->cur_streamline_val++;
+               dev->fence_creat_count++;
+       } else {
+               vc_print(dev->index, PRINT_ERROR,
+                        "create fence returned %d", out_fence_fd);
+       }
+       return out_fence_fd;
+}
+
+static void video_timeline_increase(struct composer_dev *dev,
+                                   unsigned int value)
+{
+       aml_sync_inc_timeline(dev->video_timeline, value);
+       dev->fence_release_count += value;
+       vc_print(dev->index, PRINT_FENCE,
+                "receive_cnt=%lld,fen_creat_cnt=%lld,fen_release_cnt=%lld\n",
+                dev->received_count,
+                dev->fence_creat_count,
+                dev->fence_release_count);
+}
+
+static int video_composer_init_buffer(struct composer_dev *dev)
+{
+       int i, ret = 0;
+       u32 buf_width, buf_height;
+       u32 buf_size;
+       struct vinfo_s *video_composer_vinfo;
+       struct vinfo_s vinfo = {.width = 1280, .height = 720, };
+       int flags = CODEC_MM_FLAGS_DMA | CODEC_MM_FLAGS_CMA_CLEAR;
+
+       switch (dev->buffer_status) {
+       case UNINITIAL:/*not config*/
+               break;
+       case INIT_SUCCESS:/*config before , return ok*/
+               return 0;
+       case INIT_ERROR:/*config fail, won't retry , return failure*/
+               return -1;
+       default:
+               return -1;
+       }
+
+       video_composer_vinfo = get_current_vinfo();
+
+       if (IS_ERR_OR_NULL(video_composer_vinfo))
+               video_composer_vinfo = &vinfo;
+       dev->vinfo_w = video_composer_vinfo->width;
+       dev->vinfo_h = video_composer_vinfo->height;
+       buf_width = (video_composer_vinfo->width + 0x1f) & ~0x1f;
+       buf_height = video_composer_vinfo->height;
+       if (dev->need_rotate) {
+               buf_width = rotate_width;
+               buf_height = rotate_height;
+       }
+       if (buf_width > max_width)
+               buf_width = max_width;
+       if (buf_height > max_height)
+               buf_height = max_height;
+       buf_size = buf_width * buf_height * 3;
+       buf_size = PAGE_ALIGN(buf_size);
+       dev->composer_buf_w = buf_width;
+       dev->composer_buf_h = buf_height;
+
+       for (i = 0; i < BUFFER_LEN; i++) {
+               if (dev->dst_buf[i].phy_addr == 0)
+                       dev->dst_buf[i].phy_addr = codec_mm_alloc_for_dma(
+                               "video_composer",
+                               buf_size / PAGE_SIZE, 0, flags);
+               vc_print(dev->index, PRINT_OTHER,
+                        "video_composer: cma memory is %x , size is  %x\n",
+                        (unsigned int)dev->dst_buf[i].phy_addr,
+                        (unsigned int)buf_size);
+
+               if (dev->dst_buf[i].phy_addr == 0) {
+                       dev->buffer_status = INIT_ERROR;
+                       vc_print(dev->index, PRINT_ERROR,
+                                "cma memory config fail\n");
+                       return -1;
+               }
+               dev->dst_buf[i].index = i;
+               dev->dst_buf[i].dirty = true;
+               dev->dst_buf[i].buf_w = buf_width;
+               dev->dst_buf[i].buf_h = buf_height;
+               dev->dst_buf[i].buf_size = buf_size;
+               if (!kfifo_put(&dev->free_q, &dev->dst_buf[i].frame))
+                       vc_print(dev->index, PRINT_ERROR,
+                                "init buffer free_q is full\n");
+       }
+
+       if (IS_ERR_OR_NULL(dev->ge2d_para.context))
+               ret = init_ge2d_composer(&dev->ge2d_para);
+
+       if (ret < 0)
+               vc_print(dev->index, PRINT_ERROR,
+                        "create ge2d composer fail!\n");
+       //vf_local_init(dev);
+       dev->buffer_status = INIT_SUCCESS;
+
+       return 0;
+}
+
+static void video_composer_uninit_buffer(struct composer_dev *dev)
+{
+       int i;
+       int ret = 0;
+
+       if (dev->buffer_status == UNINITIAL) {
+               vc_print(dev->index, PRINT_OTHER,
+                        "%s buffer have uninit already finished!\n", __func__);
+               return;
+       }
+       dev->buffer_status = UNINITIAL;
+       for (i = 0; i < BUFFER_LEN; i++) {
+               if (dev->dst_buf[i].phy_addr != 0) {
+                       pr_info("video_composer: cma free addr is %x\n",
+                               (unsigned int)dev->dst_buf[i].phy_addr);
+                       codec_mm_free_for_dma("video_composer",
+                                             dev->dst_buf[i].phy_addr);
+                       dev->dst_buf[i].phy_addr = 0;
+               }
+       }
+
+       if (dev->ge2d_para.context)
+               ret = uninit_ge2d_composer(&dev->ge2d_para);
+       dev->ge2d_para.context = NULL;
+       if (ret < 0)
+               vc_print(dev->index, PRINT_ERROR,
+                        "uninit ge2d composer failed!\n");
+}
+
+static void frames_put_file(struct composer_dev *dev,
+                           struct received_frames_t *current_frames)
+{
+       struct file *file_vf;
+       int current_count;
+       int i;
+
+       current_count = current_frames->frames_info.frame_count;
+       for (i = 0; i < current_count; i++) {
+               file_vf = current_frames->file_vf[i];
+               fput(file_vf);
+       }
+       dev->fput_count++;
+}
+
+static void vf_pop_display_q(struct composer_dev *dev, struct vframe_s *vf)
+{
+       struct vframe_s *dis_vf = NULL;
+
+       int k = kfifo_len(&dev->display_q);
+
+       while (kfifo_len(&dev->display_q) > 0) {
+               if (kfifo_get(&dev->display_q, &dis_vf)) {
+                       if (dis_vf == vf)
+                               break;
+                       if (!kfifo_put(&dev->display_q, dis_vf))
+                               vc_print(dev->index, PRINT_ERROR,
+                                        "display_q is full!\n");
+               }
+               k--;
+               if (k < 0) {
+                       vc_print(dev->index, PRINT_ERROR,
+                                "can find vf in display_q\n");
+                       break;
+               }
+       }
+}
+
+static void display_q_uninit(struct composer_dev *dev)
+{
+       struct vframe_s *dis_vf = NULL;
+       int repeat_count;
+       int i;
+
+       vc_print(dev->index, PRINT_OTHER, "vc: unit display_q len=%d\n",
+                kfifo_len(&dev->display_q));
+
+       while (kfifo_len(&dev->display_q) > 0) {
+               if (kfifo_get(&dev->display_q, &dis_vf)) {
+                       if (dis_vf->flag
+                           & VFRAME_FLAG_VIDEO_COMPOSER_BYPASS) {
+                               repeat_count = dis_vf->repeat_count[dev->index];
+                               vc_print(dev->index, PRINT_OTHER,
+                                        "vc: unit repeat_count=%d\n",
+                                        repeat_count);
+                               for (i = 0; i <= repeat_count; i++) {
+                                       fput(dis_vf->file_vf);
+                                       dev->fput_count++;
+                               }
+                       } else if (!(dis_vf->flag
+                                    & VFRAME_FLAG_VIDEO_COMPOSER)) {
+                               pr_err("vc: unit display_q flag is null\n");
+                       }
+               }
+       }
+}
+
+static void receive_q_uninit(struct composer_dev *dev)
+{
+       int i = 0;
+       struct received_frames_t *received_frames = NULL;
+
+       vc_print(dev->index, PRINT_OTHER, "vc: unit receive_q len=%d\n",
+                kfifo_len(&dev->receive_q));
+       while (kfifo_len(&dev->receive_q) > 0) {
+               if (kfifo_get(&dev->receive_q, &received_frames))
+                       frames_put_file(dev, received_frames);
+       }
+
+       for (i = 0; i < FRAMES_INFO_POOL_SIZE; i++) {
+               atomic_set(&dev->received_frames[i].on_use,
+                          false);
+       }
+}
+
+static void ready_q_uninit(struct composer_dev *dev)
+{
+       struct vframe_s *dis_vf = NULL;
+       int repeat_count;
+       int i;
+
+       vc_print(dev->index, PRINT_OTHER, "vc: unit ready_q len=%d\n",
+                kfifo_len(&dev->ready_q));
+
+       while (kfifo_len(&dev->ready_q) > 0) {
+               if (kfifo_get(&dev->ready_q, &dis_vf)) {
+                       if (dis_vf->flag
+                           & VFRAME_FLAG_VIDEO_COMPOSER_BYPASS) {
+                               repeat_count = dis_vf->repeat_count[dev->index];
+                               for (i = 0; i <= repeat_count; i++) {
+                                       fput(dis_vf->file_vf);
+                                       dev->fput_count++;
+                               }
+                       }
+               }
+       }
+}
+
+static void videocom_vf_put(struct vframe_s *vf, struct composer_dev *dev)
+{
+       struct dst_buf_t *dst_buf;
+
+       if (IS_ERR_OR_NULL(vf)) {
+               vc_print(dev->index, PRINT_ERROR, "vf is NULL\n");
+               return;
+       }
+
+       dst_buf = to_dst_buf(vf);
+       if (IS_ERR_OR_NULL(dst_buf)) {
+               vc_print(dev->index, PRINT_ERROR, "dst_buf is NULL\n");
+               return;
+       }
+
+       if (IS_ERR_OR_NULL(dev)) {
+               vc_print(dev->index, PRINT_ERROR, "dev is NULL\n");
+               return;
+       }
+
+       if (!kfifo_put(&dev->free_q, vf))
+               vc_print(dev->index, PRINT_ERROR, "put free_q is full\n");
+       vc_print(dev->index, PRINT_OTHER,
+                "%s free buffer count: %d %d\n",
+                __func__, kfifo_len(&dev->free_q), __LINE__);
+
+       if (kfifo_is_full(&dev->free_q)) {
+               dev->need_free_buffer = true;
+               vc_print(dev->index, PRINT_ERROR,
+                        "free_q is full, could uninit buffer!\n");
+       }
+       wake_up_interruptible(&dev->wq);
+}
+
+static unsigned long get_dma_phy_addr(int fd)
+{
+       unsigned long phy_addr = 0;
+       struct dma_buf *dbuf = NULL;
+       struct sg_table *table = NULL;
+       struct page *page = NULL;
+       struct ion_buffer *buffer = NULL;
+
+       dbuf = dma_buf_get(fd);
+       buffer = dbuf->priv;
+       table = buffer->sg_table;
+       page = sg_page(table->sgl);
+       phy_addr = PFN_PHYS(page_to_pfn(page));
+       dma_buf_put(dbuf);
+       return phy_addr;
+}
+
+static struct vframe_s *get_dst_vframe_buffer(struct composer_dev *dev)
+{
+       struct vframe_s *dst_vf;
+
+       if (!kfifo_get(&dev->free_q, &dst_vf)) {
+               vc_print(dev->index, PRINT_OTHER, "free q is empty\n");
+               return NULL;
+       }
+       return dst_vf;
+}
+
+static void check_window_change(struct composer_dev *dev,
+                               struct frames_info_t cur_frame_info)
+{
+       int last_width, last_height, current_width, current_height;
+       int cur_pos_x, cur_pos_y, cur_pos_w, cur_pos_h;
+       int last_pos_x, last_pos_y, last_pos_w, last_pos_h;
+       struct frames_info_t last_frame_info;
+       int last_zorder, cur_zorder;
+       bool window_changed = false;
+       int i;
+
+       last_frame_info = dev->last_frames.frames_info;
+       if (cur_frame_info.frame_count != last_frame_info.frame_count) {
+               window_changed = true;
+               vc_print(dev->index, PRINT_ERROR,
+                        "last count=%d, current count=%d\n",
+                        last_frame_info.frame_count,
+                        cur_frame_info.frame_count);
+       } else {
+               for (i = 0; i < cur_frame_info.frame_count; i++) {
+                       current_width = cur_frame_info.frame_info[i].crop_w;
+                       current_height = cur_frame_info.frame_info[i].crop_h;
+                       last_width = last_frame_info.frame_info[i].crop_w;
+                       last_height = last_frame_info.frame_info[i].crop_h;
+
+                       if (current_width * last_height !=
+                               current_height * last_width) {
+                               vc_print(dev->index, PRINT_ERROR,
+                                        "frame width or height changed!");
+                               window_changed = true;
+                               break;
+                       }
+
+                       cur_pos_x = cur_frame_info.frame_info[i].dst_x;
+                       cur_pos_y = cur_frame_info.frame_info[i].dst_y;
+                       cur_pos_w = cur_frame_info.frame_info[i].dst_w;
+                       cur_pos_h = cur_frame_info.frame_info[i].dst_h;
+                       last_pos_x = last_frame_info.frame_info[i].dst_x;
+                       last_pos_y = last_frame_info.frame_info[i].dst_y;
+                       last_pos_w = last_frame_info.frame_info[i].dst_w;
+                       last_pos_h = last_frame_info.frame_info[i].dst_h;
+
+                       if ((cur_pos_x != last_pos_x) ||
+                           (cur_pos_y != last_pos_y) ||
+                           (cur_pos_w != last_pos_w) ||
+                           (cur_pos_h != last_pos_h)) {
+                               vc_print(dev->index, PRINT_ERROR,
+                                        "frame axis changed!");
+                               window_changed = true;
+                               break;
+                       }
+
+                       cur_zorder = cur_frame_info.frame_info[i].zorder;
+                       last_zorder = last_frame_info.frame_info[i].zorder;
+                       if (cur_zorder != last_zorder) {
+                               vc_print(dev->index, PRINT_ERROR,
+                                        "frame zorder changed!");
+                               window_changed = true;
+                               break;
+                       }
+               }
+       }
+
+       if (!window_changed)
+               return;
+
+       for (i = 0; i < BUFFER_LEN; i++)
+               dev->dst_buf[i].dirty = true;
+}
+
+static struct output_axis output_axis_adjust(
+       struct composer_dev *dev,
+       struct frame_info_t *vframe_info,
+       struct ge2d_composer_para *ge2d_comp_para)
+{
+       int input_width = 0, input_height = 0;
+       int output_w = 0, output_h = 0;
+       int disp_w, disp_h;
+       struct output_axis axis;
+
+       input_width = vframe_info->crop_w;
+       input_height = vframe_info->crop_h;
+       disp_w = ge2d_comp_para->position_width;
+       disp_h = ge2d_comp_para->position_height;
+
+       if (ge2d_comp_para->angle & 1) {
+               output_h = disp_h;
+               output_w =
+                       (input_height * disp_h) / input_width;
+               if (output_w > disp_w) {
+                       output_h =
+                               (output_h * disp_w) / output_w;
+                       output_w = disp_w;
+               }
+       } else {
+               output_w = disp_w;
+               output_h = disp_w * input_height / input_width;
+               if (output_h > disp_h) {
+                       output_h = disp_h;
+                       output_w = disp_h * input_width / input_height;
+               }
+       }
+       axis.left = ge2d_comp_para->position_left +
+               (ge2d_comp_para->position_width - output_w) / 2;
+       axis.top = ge2d_comp_para->position_top +
+               (ge2d_comp_para->position_height - output_h) / 2;
+       axis.width = output_w;
+       axis.height = output_h;
+
+       axis.left = axis.left * dev->composer_buf_w / dev->vinfo_w;
+       axis.top = axis.top * dev->composer_buf_h / dev->vinfo_h;
+       axis.width = axis.width * dev->composer_buf_w / dev->vinfo_w;
+       axis.height = axis.height * dev->composer_buf_h / dev->vinfo_h;
+
+       return axis;
+}
+
+static void vframe_composer(struct composer_dev *dev)
+{
+       struct received_frames_t *received_frames = NULL;
+       struct received_frames_t *received_frames_tmp = NULL;
+       struct frames_info_t *frames_info = NULL;
+       struct vframe_s *scr_vf = NULL;
+       struct file *file_vf = NULL;
+       int vf_dev[MXA_LAYER_COUNT];
+       struct frame_info_t *vframe_info[MXA_LAYER_COUNT];
+       int i, j, tmp;
+       u32 zd1, zd2;
+       struct file_private_data *file_private_data;
+       struct config_para_ex_s ge2d_config;
+       struct timeval begin_time;
+       struct timeval end_time;
+       int cost_time;
+       int ret = 0;
+       struct vframe_s *dst_vf = NULL;
+       int count;
+       struct dst_buf_t *dst_buf = NULL;
+       u32 cur_transform = 0;
+       struct src_data_para src_data;
+       u32 drop_count = 0;
+       struct output_axis dst_axis;
+       int min_left = 0, min_top = 0;
+       int max_right = 0, max_bottom = 0;
+
+       do_gettimeofday(&begin_time);
+
+       dev->ge2d_para.ge2d_config = &ge2d_config;
+       ret = video_composer_init_buffer(dev);
+       if (ret != 0) {
+               vc_print(dev->index, PRINT_ERROR, "vc: init buffer failed!\n");
+               video_composer_uninit_buffer(dev);
+       } else {
+               dst_vf = get_dst_vframe_buffer(dev);
+       }
+       if (IS_ERR_OR_NULL(dst_vf)) {
+               vc_print(dev->index, PRINT_OTHER, "dst vf is NULL\n");
+               return;
+       }
+       memset(dst_vf, 0, sizeof(struct vframe_s));
+       while (1) {
+               if (!kfifo_get(&dev->receive_q, &received_frames)) {
+                       vc_print(dev->index, PRINT_ERROR,
+                                "com: get failed\n");
+                       return;
+               }
+               if (!kfifo_peek(&dev->receive_q, &received_frames_tmp))
+                       break;
+               drop_count++;
+               frames_put_file(dev, received_frames);
+               vc_print(dev->index, PRINT_ERROR, "com: drop frame\n");
+               atomic_set(&received_frames->on_use, false);
+       }
+
+       frames_info = &received_frames->frames_info;
+       count = frames_info->frame_count;
+       check_window_change(dev, received_frames->frames_info);
+
+       dst_buf = to_dst_buf(dst_vf);
+       dev->ge2d_para.format = GE2D_FORMAT_S24_YUV444;
+       dev->ge2d_para.phy_addr[0] = dst_buf->phy_addr;
+       dev->ge2d_para.buffer_w = dst_buf->buf_w;
+       dev->ge2d_para.buffer_h = dst_buf->buf_h;
+       dev->ge2d_para.canvas0Addr = -1;
+
+       if (dst_buf->dirty && !close_black) {
+               ret = fill_vframe_black(&dev->ge2d_para);
+               if (ret < 0) {
+                       vc_print(dev->index, PRINT_ERROR,
+                                "ge2d fill black failed\n");
+               }
+               vc_print(dev->index, PRINT_OTHER, "fill black\n");
+               dst_buf->dirty = false;
+       }
+
+       for (i = 0; i < count; i++) {
+               vf_dev[i] = i;
+               vframe_info[i] = &frames_info->frame_info[i];
+       }
+
+       for (i = 0; i < count - 1; i++) {
+               for (j = 0; j < count - 1 - i; j++) {
+                       zd1 = vframe_info[vf_dev[j]]->zorder;
+                       zd2 = vframe_info[vf_dev[j + 1]]->zorder;
+                       if (zd1 > zd2) {
+                               tmp = vf_dev[j];
+                               vf_dev[j] = vf_dev[j + 1];
+                               vf_dev[j + 1] = tmp;
+                       }
+               }
+       }
+       min_left = vframe_info[0]->dst_x;
+       min_top = vframe_info[0]->dst_y;
+       max_right = vframe_info[0]->dst_x + vframe_info[0]->dst_w;
+       max_bottom = vframe_info[0]->dst_y + vframe_info[0]->dst_h;
+       for (i = 0; i < count; i++) {
+               if (vframe_info[vf_dev[i]]->type == 1) {
+                       src_data.canvas0Addr = -1;
+                       src_data.canvas1Addr = -1;
+                       src_data.canvas0_config[0].phy_addr = (u32)(
+                               received_frames->phy_addr[vf_dev[i]]);
+                       src_data.canvas0_config[0].width =
+                               (vframe_info[vf_dev[i]]->buffer_w
+                                + 0x1f) & ~0x1f;
+                       src_data.canvas0_config[0].height =
+                               vframe_info[vf_dev[i]]->buffer_h;
+                       src_data.canvas0_config[0].block_mode =
+                               CANVAS_BLKMODE_LINEAR;
+                       src_data.canvas0_config[0].endian = 0;
+                       src_data.canvas0_config[1].phy_addr =
+                               (u32)(received_frames->phy_addr[vf_dev[i]]
+                                     + (src_data.canvas0_config[0].width)
+                                     * (src_data.canvas0_config[0].height));
+
+                       src_data.canvas0_config[1].width =
+                               (vframe_info[vf_dev[i]]->buffer_w
+                                + 0x1f) & ~0x1f;
+                       src_data.canvas0_config[1].height =
+                               (vframe_info[vf_dev[i]]->buffer_h) / 2;
+                       src_data.canvas0_config[1].block_mode =
+                               CANVAS_BLKMODE_LINEAR;
+                       src_data.canvas0_config[1].endian = 0;
+
+                       src_data.bitdepth = BITDEPTH_Y8
+                                           | BITDEPTH_U8
+                                           | BITDEPTH_V8;
+                       src_data.source_type = 0;
+                       src_data.type = VIDTYPE_PROGRESSIVE
+                                       | VIDTYPE_VIU_FIELD
+                                       | VIDTYPE_VIU_NV21;
+                       src_data.plane_num = 2;
+                       src_data.width = vframe_info[vf_dev[i]]->buffer_w;
+                       src_data.height = vframe_info[vf_dev[i]]->buffer_h;
+                       src_data.is_vframe = false;
+               } else {
+                       file_vf = received_frames->file_vf[vf_dev[i]];
+                       file_private_data =
+                       (struct file_private_data *)(file_vf->private_data);
+                       scr_vf = &file_private_data->vf;
+
+                       src_data.canvas0Addr = scr_vf->canvas0Addr;
+                       src_data.canvas1Addr = scr_vf->canvas1Addr;
+                       src_data.canvas0_config[0] = scr_vf->canvas0_config[0];
+                       src_data.canvas0_config[1] = scr_vf->canvas0_config[1];
+                       src_data.canvas0_config[2] = scr_vf->canvas0_config[2];
+                       src_data.canvas1_config[0] = scr_vf->canvas1_config[0];
+                       src_data.canvas1_config[1] = scr_vf->canvas1_config[1];
+                       src_data.canvas1_config[2] = scr_vf->canvas1_config[2];
+                       src_data.bitdepth = scr_vf->bitdepth;
+                       src_data.source_type = scr_vf->source_type;
+                       src_data.type = scr_vf->type;
+                       src_data.plane_num = scr_vf->plane_num;
+                       src_data.width = scr_vf->width;
+                       src_data.height = scr_vf->height;
+                       if (scr_vf->flag & VFRAME_FLAG_VIDEO_LINEAR)
+                               src_data.is_vframe = false;
+                       else
+                               src_data.is_vframe = true;
+               }
+               cur_transform = vframe_info[vf_dev[i]]->transform;
+               if (min_left > vframe_info[vf_dev[i]]->dst_x)
+                       min_left = vframe_info[vf_dev[i]]->dst_x;
+               if (min_top > vframe_info[vf_dev[i]]->dst_y)
+                       min_top = vframe_info[vf_dev[i]]->dst_y;
+               if (max_right < (vframe_info[vf_dev[i]]->dst_x +
+                       vframe_info[vf_dev[i]]->dst_w))
+                       max_right = vframe_info[vf_dev[i]]->dst_x +
+                               vframe_info[vf_dev[i]]->dst_w;
+               if (max_bottom < (vframe_info[vf_dev[i]]->dst_y +
+                       vframe_info[vf_dev[i]]->dst_h))
+                       max_bottom = vframe_info[vf_dev[i]]->dst_y +
+                               vframe_info[vf_dev[i]]->dst_h;
+               dev->ge2d_para.position_left =
+                       vframe_info[vf_dev[i]]->dst_x;
+               dev->ge2d_para.position_top =
+                       vframe_info[vf_dev[i]]->dst_y;
+               dev->ge2d_para.position_width =
+                       vframe_info[vf_dev[i]]->dst_w;
+               dev->ge2d_para.position_height =
+                       vframe_info[vf_dev[i]]->dst_h;
+
+               if (cur_transform == VC_TRANSFORM_ROT_90)
+                       dev->ge2d_para.angle = 1;
+               else if (cur_transform == VC_TRANSFORM_ROT_180)
+                       dev->ge2d_para.angle = 2;
+               else if (cur_transform == VC_TRANSFORM_ROT_270)
+                       dev->ge2d_para.angle = 3;
+               else if (cur_transform != 0)
+                       vc_print(dev->index, PRINT_ERROR,
+                                "not support transform=%d\n", cur_transform);
+               if (!full_axis) {
+                       dst_axis =
+                               output_axis_adjust(dev, vframe_info[vf_dev[i]],
+                                                  &dev->ge2d_para);
+                       dev->ge2d_para.position_left = dst_axis.left;
+                       dev->ge2d_para.position_top = dst_axis.top;
+                       dev->ge2d_para.position_width = dst_axis.width;
+                       dev->ge2d_para.position_height = dst_axis.height;
+               }
+
+               ret = ge2d_data_composer(&src_data, &dev->ge2d_para);
+               if (ret < 0)
+                       vc_print(dev->index, PRINT_ERROR,
+                                "ge2d composer failed\n");
+       }
+
+       frames_put_file(dev, received_frames);
+
+       do_gettimeofday(&end_time);
+       cost_time = (1000000 * (end_time.tv_sec - begin_time.tv_sec)
+               + (end_time.tv_usec - begin_time.tv_usec)) / 1000;
+       vc_print(dev->index, PRINT_PERFORMANCE,
+                "ge2d cost: %d ms\n",
+                cost_time);
+
+       dst_vf->flag |=
+               VFRAME_FLAG_VIDEO_COMPOSER
+               | VFRAME_FLAG_COMPOSER_DONE;
+
+       dst_vf->bitdepth =
+               BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8;
+
+       dst_vf->type =
+               VIDTYPE_VIU_444
+               | VIDTYPE_VIU_SINGLE_PLANE
+               | VIDTYPE_VIU_FIELD;
+
+       dst_vf->axis[0] = 0;
+       dst_vf->axis[1] = 0;
+       dst_vf->axis[2] = 0;
+       dst_vf->axis[3] = 0;
+       dst_vf->crop[0] = min_top;
+       dst_vf->crop[1] = min_left;
+       dst_vf->crop[2] = dst_buf->buf_h - max_bottom;
+       dst_vf->crop[3] = dst_buf->buf_w - max_right;
+       dst_vf->zorder = frames_info->disp_zorder;
+       dst_vf->canvas0_config[0].phy_addr = dst_buf->phy_addr;
+       dst_vf->canvas0Addr = -1;
+       dst_vf->canvas1Addr = -1;
+       dst_vf->plane_num = 1;
+       dst_vf->width = dst_buf->buf_w;
+       dst_vf->height = dst_buf->buf_h;
+       dst_vf->canvas0_config[0].width = dst_vf->width * 3;
+       dst_vf->canvas0_config[0].height = dst_vf->height;
+       dst_vf->canvas0_config[0].block_mode = 0;
+       dst_vf->repeat_count[dev->index] = 0;
+
+       if (dev->last_dst_vf)
+               dev->last_dst_vf->repeat_count[dev->index] += drop_count;
+       else
+               dst_vf->repeat_count[dev->index] += drop_count;
+       dev->last_dst_vf = dst_vf;
+       dev->last_frames = *received_frames;
+       dev->fake_vf = *dev->last_dst_vf;
+
+       if (!kfifo_put(&dev->ready_q, (const struct vframe_s *)dst_vf))
+               vc_print(dev->index, PRINT_ERROR, "ready_q is full\n");
+
+       vc_print(dev->index, PRINT_PERFORMANCE,
+                "ready len=%d\n", kfifo_len(&dev->ready_q));
+
+       atomic_set(&received_frames->on_use, false);
+}
+
+static void empty_ready_queue(struct composer_dev *dev)
+{
+       int repeat_count;
+       int omx_index;
+       bool is_composer;
+       int i;
+       struct file *file_vf;
+       bool is_dma_buf;
+       struct vframe_s *vf = NULL;
+
+       vc_print(dev->index, PRINT_OTHER, "vc: empty ready_q len=%d\n",
+                kfifo_len(&dev->ready_q));
+
+       while (kfifo_len(&dev->ready_q) > 0) {
+               if (kfifo_get(&dev->ready_q, &vf)) {
+                       if (!vf)
+                               break;
+                       repeat_count = vf->repeat_count[dev->index];
+                       omx_index = vf->omx_index;
+                       is_composer = vf->flag & VFRAME_FLAG_COMPOSER_DONE;
+                       file_vf = vf->file_vf;
+                       is_dma_buf = vf->flag & VFRAME_FLAG_VIDEO_COMPOSER_DMA;
+                       vc_print(dev->index, PRINT_OTHER,
+                                "empty: repeat_count =%d, omx_index=%d\n",
+                                repeat_count, omx_index);
+                       video_timeline_increase(dev, repeat_count + 1);
+                       if (!is_composer) {
+                               for (i = 0; i <= repeat_count; i++) {
+                                       fput(file_vf);
+                                       dev->fput_count++;
+                               }
+                       } else {
+                               videocom_vf_put(vf, dev);
+                       }
+                       if (is_dma_buf) {
+                               if (!kfifo_put(&dev->dma_free_q, vf))
+                                       vc_print(dev->index, PRINT_ERROR,
+                                                "dma_free is full!\n");
+                       }
+               }
+       }
+}
+
+static void video_composer_task(struct composer_dev *dev)
+{
+       struct vframe_s *vf = NULL;
+       struct file *file_vf = NULL;
+       struct frame_info_t *frame_info = NULL;
+       struct file_private_data *file_private_data;
+       struct received_frames_t *received_frames = NULL;
+       struct frames_info_t *frames_info = NULL;
+       int count;
+       bool need_composer = false;
+       int ready_count = 0;
+       unsigned long phy_addr;
+       u64 time_us64;
+
+       if (!kfifo_peek(&dev->receive_q, &received_frames)) {
+               vc_print(dev->index, PRINT_ERROR, "task: peek failed\n");
+               return;
+       }
+
+       if (IS_ERR_OR_NULL(received_frames)) {
+               vc_print(dev->index, PRINT_ERROR,
+                        "task: get received_frames is NULL\n");
+               return;
+       }
+
+       count = received_frames->frames_info.frame_count;
+       time_us64 = received_frames->time_us64;
+
+       if (count == 1) {
+               if (transform)
+                       received_frames->frames_info.frame_info[0].transform =
+                               transform;
+               if (((dev->index == 0) && force_composer) ||
+                   ((dev->index == 1) && force_composer_pip))
+                       need_composer = true;
+               if (received_frames->frames_info.frame_info[0].transform) {
+                       need_composer = true;
+                       dev->need_rotate = true;
+               }
+       } else {
+               need_composer = true;
+       }
+       if (!need_composer) {
+               frames_info = &received_frames->frames_info;
+               frame_info = frames_info->frame_info;
+               phy_addr = received_frames->phy_addr[0];
+               vc_print(dev->index, PRINT_OTHER,
+                        "task:frame_cnt=%d,z=%d,index=%d,receive_q len=%d\n",
+                        frames_info->frame_count,
+                        frames_info->disp_zorder,
+                        dev->index,
+                        kfifo_len(&dev->receive_q));
+               file_vf = received_frames->file_vf[0];
+               if (frame_info->type == 0) {
+                       file_private_data =
+                       (struct file_private_data *)(file_vf->private_data);
+                       vf = &file_private_data->vf;
+               } else if (frame_info->type == 1) {
+                       if (!kfifo_get(&dev->dma_free_q, &vf)) {
+                               vc_print(dev->index, PRINT_ERROR,
+                                        "task: get dma_free_q failed\n");
+                               return;
+                       }
+                       memset(vf, 0, sizeof(struct vframe_s));
+               }
+               if (!kfifo_get(&dev->receive_q, &received_frames)) {
+                       vc_print(dev->index, PRINT_ERROR,
+                                "task: get failed\n");
+                       return;
+               }
+
+               vf->axis[0] = frame_info->dst_x;
+               vf->axis[1] = frame_info->dst_y;
+               vf->axis[2] = frame_info->dst_w + frame_info->dst_x - 1;
+               vf->axis[3] = frame_info->dst_h + frame_info->dst_y - 1;
+               vf->crop[0] = 0;
+               vf->crop[1] = 0;
+               vf->crop[2] = 0;
+               vf->crop[3] = 0;
+               vf->zorder = frames_info->disp_zorder;
+               vf->file_vf = file_vf;
+               //vf->zorder = 1;
+               vf->flag |= VFRAME_FLAG_VIDEO_COMPOSER
+                       | VFRAME_FLAG_VIDEO_COMPOSER_BYPASS;
+               vf->pts_us64 = time_us64;
+               vf->disp_pts = 0;
+
+               if (frame_info->type == 1) {
+                       vf->flag |= VFRAME_FLAG_VIDEO_COMPOSER_DMA;
+                       vf->flag |= VFRAME_FLAG_VIDEO_LINEAR;
+                       vf->canvas0Addr = -1;
+                       vf->canvas0_config[0].phy_addr = phy_addr;
+                       vf->canvas0_config[0].width = (frame_info->buffer_w
+                                                      + 0x1f) & ~0x1f;
+                       vf->canvas0_config[0].height = frame_info->buffer_h;
+                       vf->canvas1Addr = -1;
+                       vf->canvas0_config[1].phy_addr = phy_addr
+                               + vf->canvas0_config[0].width
+                               * vf->canvas0_config[0].height;
+                       vf->canvas0_config[1].width = (frame_info->buffer_w
+                                                      + 0x1f) & ~0x1f;
+                       vf->canvas0_config[1].height = frame_info->buffer_h;
+                       vf->width = frame_info->buffer_w;
+                       vf->height = frame_info->buffer_h;
+                       vf->plane_num = 2;
+                       vf->type = VIDTYPE_PROGRESSIVE
+                                       | VIDTYPE_VIU_FIELD
+                                       | VIDTYPE_VIU_NV21;
+                       vf->bitdepth =
+                               BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8;
+                       vf->crop[0] = frame_info->crop_y;
+                       vf->crop[1] = frame_info->crop_x;
+                       vf->crop[2] = frame_info->buffer_h
+                               - frame_info->crop_h
+                               - frame_info->crop_y;
+                       vf->crop[3] = frame_info->buffer_w
+                               - frame_info->crop_w
+                               - frame_info->crop_x;
+               }
+               vc_print(dev->index, PRINT_OTHER,
+                        "axis: %d %d %d %d\ncrop: %d %d %d %d\n",
+                        vf->axis[0], vf->axis[1], vf->axis[2], vf->axis[3],
+                        vf->crop[0], vf->crop[1], vf->crop[2], vf->crop[3]);
+               vc_print(dev->index, PRINT_OTHER,
+                        "vf_width: %d, vf_height: %d\n",
+                        vf->width, vf->height);
+               vc_print(dev->index, PRINT_OTHER,
+                        "=========frame info:==========\n");
+               vc_print(dev->index, PRINT_OTHER,
+                        "frame aixs x,y,w,h: %d %d %d %d\n",
+                        frame_info->dst_x, frame_info->dst_y,
+                        frame_info->dst_w, frame_info->dst_h);
+               vc_print(dev->index, PRINT_OTHER,
+                        "frame crop t,l,b,r: %d %d %d %d\n",
+                        frame_info->crop_y, frame_info->crop_x,
+                        frame_info->crop_h, frame_info->crop_w);
+               vc_print(dev->index, PRINT_OTHER,
+                        "frame buffer Width X Height: %d X %d\n",
+                        frame_info->buffer_w, frame_info->buffer_h);
+               vc_print(dev->index, PRINT_OTHER,
+                        "===============================\n");
+               if (dev->last_file == file_vf && frame_info->type == 0) {
+                       vf->repeat_count[dev->index]++;
+                       vc_print(dev->index, PRINT_OTHER,
+                                "repeat =%d, omx_index=%d\n",
+                                vf->repeat_count[dev->index],
+                                vf->omx_index);
+               } else {
+                       dev->last_file = file_vf;
+                       vf->repeat_count[dev->index] = 0;
+                       if (!kfifo_put(&dev->ready_q,
+                                      (const struct vframe_s *)vf))
+                               vc_print(dev->index, PRINT_ERROR,
+                                        "by_pass ready_q is full\n");
+                       ready_count = kfifo_len(&dev->ready_q);
+                       if (ready_count > 1)
+                               vc_print(dev->index, PRINT_ERROR,
+                                        "ready len=%d\n", ready_count);
+                       vc_print(dev->index, PRINT_OTHER,
+                                "ready len=%d\n", kfifo_len(&dev->ready_q));
+               }
+               dev->fake_vf = *vf;
+               atomic_set(&received_frames->on_use, false);
+       } else {
+               vframe_composer(dev);
+               dev->last_file = NULL;
+       }
+}
+
+static int video_composer_thread(void *data)
+{
+       struct composer_dev *dev = data;
+
+       vc_print(dev->index, PRINT_OTHER, "thread: started\n");
+       init_waitqueue_head(&dev->wq);
+
+       dev->thread_stopped = 0;
+       while (1) {
+               if (kthread_should_stop())
+                       break;
+
+               if (kfifo_len(&dev->receive_q) == 0) {
+                       wait_event_interruptible_timeout(
+                                       dev->wq,
+                                       ((kfifo_len(&dev->receive_q) > 0) &&
+                                        dev->enable_composer) ||
+                                        dev->need_free_buffer ||
+                                        dev->need_unint_receive_q ||
+                                        dev->need_empty_ready,
+                                        msecs_to_jiffies(5000));
+               }
+
+               if (dev->need_empty_ready) {
+                       vc_print(dev->index, PRINT_OTHER,
+                                "empty_ready_queue\n");
+                       dev->need_empty_ready = false;
+                       empty_ready_queue(dev);
+                       dev->fake_vf.flag |= VFRAME_FLAG_FAKE_FRAME;
+                       if (!kfifo_put(&dev->ready_q,
+                                      (const struct vframe_s *)&dev->fake_vf))
+                               vc_print(dev->index, PRINT_ERROR,
+                                        "by_pass ready_q is full\n");
+               }
+
+               if (dev->need_free_buffer) {
+                       dev->need_free_buffer = false;
+                       video_composer_uninit_buffer(dev);
+                       vc_print(dev->index, PRINT_OTHER,
+                                "%s video composer release!\n", __func__);
+                       continue;
+               }
+               if (kthread_should_stop())
+                       break;
+
+               if (!dev->enable_composer && dev->need_unint_receive_q) {
+                       receive_q_uninit(dev);
+                       dev->need_unint_receive_q = false;
+                       ready_q_uninit(dev);
+                       complete(&dev->task_done);
+                       continue;
+               }
+               if (kfifo_len(&dev->receive_q) > 0 && dev->enable_composer)
+                       video_composer_task(dev);
+       }
+       dev->thread_stopped = 1;
+       vc_print(dev->index, PRINT_OTHER, "thread: exit\n");
+       return 0;
+}
+
+static int video_composer_open(struct inode *inode, struct file *file)
+{
+       struct composer_dev *dev;
+       struct video_composer_port_s *port = &ports[iminor(inode)];
+       int i;
+       struct sched_param param = {.sched_priority = 2};
+
+       pr_err("video_composer_open iminor(inode) =%d\n", iminor(inode));
+       if (iminor(inode) >= video_composer_instance_num)
+               return -ENODEV;
+
+       mutex_lock(&video_composer_mutex);
+
+       if (port->open_count > 0) {
+               mutex_unlock(&video_composer_mutex);
+               pr_err("video_composer: instance %d is aleady opened",
+                      port->index);
+               return -EBUSY;
+       }
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (IS_ERR_OR_NULL(dev)) {
+               mutex_unlock(&video_composer_mutex);
+               pr_err("video_composer: instance %d alloc dev failed",
+                      port->index);
+               return -ENOMEM;
+       }
+       dev->ge2d_para.context = NULL;
+
+       dev->ge2d_para.count = 0;
+       dev->ge2d_para.canvas_dst[0] = -1;
+       dev->ge2d_para.canvas_dst[1] = -1;
+       dev->ge2d_para.canvas_dst[2] = -1;
+       dev->ge2d_para.canvas_scr[0] = -1;
+       dev->ge2d_para.canvas_scr[1] = -1;
+       dev->ge2d_para.canvas_scr[2] = -1;
+       dev->ge2d_para.plane_num = 1;
+
+       dev->buffer_status = UNINITIAL;
+
+       dev->port = port;
+       file->private_data = dev;
+       dev->index = port->index;
+       dev->need_free_buffer = false;
+       dev->last_frames.frames_info.frame_count = 0;
+       dev->is_sideband = false;
+       dev->need_empty_ready = false;
+
+       memcpy(dev->vf_provider_name, port->name,
+              strlen(port->name) + 1);
+
+       port->open_count++;
+       do_gettimeofday(&dev->start_time);
+
+       mutex_unlock(&video_composer_mutex);
+       dev->kthread = kthread_create(video_composer_thread,
+                                     dev, dev->port->name);
+       if (IS_ERR(dev->kthread)) {
+               pr_err("video_composer_thread creat failed\n");
+               return -ENOMEM;
+       }
+
+       if (sched_setscheduler(dev->kthread, SCHED_FIFO, &param))
+               pr_err("vc:Could not set realtime priority.\n");
+
+       wake_up_process(dev->kthread);
+       //mutex_init(&dev->mutex_input);
+
+       for (i = 0; i < FRAMES_INFO_POOL_SIZE; i++)
+               dev->received_frames[i].index = i;
+
+       video_timeline_create(dev);
+
+       return 0;
+}
+
+static int video_composer_release(struct inode *inode, struct file *file)
+{
+       struct composer_dev *dev = file->private_data;
+       struct video_composer_port_s *port = dev->port;
+       int i = 0;
+
+       if (iminor(inode) >= video_composer_instance_num)
+               return -ENODEV;
+
+       if (dev->kthread) {
+               kthread_stop(dev->kthread);
+               wake_up_interruptible(&dev->wq);
+               dev->kthread = NULL;
+       }
+
+       mutex_lock(&video_composer_mutex);
+
+       port->open_count--;
+
+       mutex_unlock(&video_composer_mutex);
+       while (1) {
+               i++;
+               if (dev->thread_stopped)
+                       break;
+               usleep_range(9000, 10000);
+               if (i > WAIT_THREAD_STOPPED_TIMEOUT) {
+                       pr_err("wait thread timeout\n");
+                       break;
+               }
+       }
+       kfree(dev);
+       return 0;
+}
+
+static void set_frames_info(struct composer_dev *dev,
+                           struct frames_info_t *frames_info)
+{
+       u32 fence_fd;
+       int i = 0;
+       int j = 0;
+       struct file *file_vf = NULL;
+       struct vframe_s *vf = NULL;
+       struct file_private_data *file_private_data;
+       struct timeval time1;
+       struct timeval time2;
+       u64 time_us64;
+       u64 time_vsync;
+       int axis[4];
+       int crop[4];
+       int ready_len = 0;
+       bool current_is_sideband = false;
+
+       for (j = 0; j < frames_info->frame_count; j++) {
+               if (frames_info->frame_info[j].type == 2) {
+                       vc_print(dev->index, PRINT_OTHER,
+                                "sideband:i=%d,z=%d\n",
+                                i,
+                                frames_info->disp_zorder);
+                       if (dev->index == 0)
+                               set_video_path_select("amvideo", 0);
+                       else if (dev->index == 1)
+                               set_video_path_select("pipvideo", 1);
+                       ready_len = kfifo_len(&dev->ready_q);
+                       vc_print(dev->index, PRINT_OTHER,
+                                "sideband: ready_len =%d\n",
+                                ready_len);
+                       frames_info->frame_info[j].composer_fen_fd = -1;
+                       axis[0] = frames_info->frame_info[j].dst_x;
+                       axis[1] = frames_info->frame_info[j].dst_y;
+                       axis[2] = frames_info->frame_info[j].dst_w
+                               + axis[0] - 1;
+                       axis[3] = frames_info->frame_info[j].dst_h
+                               + axis[1] - 1;
+                       crop[0] = frames_info->frame_info[j].crop_x;
+                       crop[1] = frames_info->frame_info[j].crop_y;
+                       crop[2] = frames_info->frame_info[j].crop_w;
+                       crop[3] = frames_info->frame_info[j].crop_h;
+                       set_video_window_ext(dev->index, axis);
+                       set_video_crop_ext(dev->index, crop);
+                       set_video_zorder_ext(dev->index,
+                                            frames_info->disp_zorder);
+                       if (!dev->is_sideband && dev->received_count > 0) {
+                               vc_print(dev->index, PRINT_OTHER,
+                                        "non change to sideband:wake_up\n");
+                               dev->need_empty_ready = true;
+                               wake_up_interruptible(&dev->wq);
+                       }
+                       dev->is_sideband = true;
+                       current_is_sideband = true;
+               }
+       }
+       if (current_is_sideband) {
+               if (frames_info->frame_count > 1)
+                       vc_print(dev->index, PRINT_ERROR,
+                                "sideband count not 1\n");
+               return;
+       }
+
+       if ((dev->is_sideband && !current_is_sideband) ||
+           (dev->received_count == 0)) {
+               if (dev->is_sideband && !current_is_sideband)
+                       vc_print(dev->index, PRINT_OTHER,
+                                "sideband to non\n");
+               dev->is_sideband = false;
+               if (dev->index == 0)
+                       set_video_path_select("video_render.0", 0);
+               else if (dev->index == 1)
+                       set_video_path_select("video_render.1", 1);
+       }
+       dev->is_sideband = false;
+
+       time1 = dev->start_time;
+       do_gettimeofday(&time2);
+       time_us64 = 1000000 * (time2.tv_sec - time1.tv_sec)
+                       + time2.tv_usec - time1.tv_usec;
+
+       time_vsync = 1000000 * (time2.tv_sec - vsync_time.tv_sec)
+                                       + time2.tv_usec - vsync_time.tv_usec;
+
+       if ((frames_info->frame_count > MXA_LAYER_COUNT) ||
+           frames_info->frame_count < 1) {
+               vc_print(dev->index, PRINT_ERROR,
+                        "vc: layer count %d\n", frames_info->frame_count);
+               return;
+       }
+
+       while (1) {
+               j = 0;
+               for (i = 0; i < FRAMES_INFO_POOL_SIZE; i++) {
+                       if (!atomic_read(&dev->received_frames[i].on_use))
+                               break;
+               }
+               if (i == FRAMES_INFO_POOL_SIZE) {
+                       j++;
+                       if (j > WAIT_READY_Q_TIMEOUT) {
+                               pr_err("receive_q is full, wait timeout!\n");
+                               return;
+                       }
+                       usleep_range(1000 * receive_wait,
+                                    1000 * (receive_wait + 1));
+                       pr_err("receive_q is full!!! need wait =%d\n", j);
+                       continue;
+               } else {
+                       break;
+               }
+       }
+
+       fence_fd = video_timeline_create_fence(dev);
+       dev->received_frames[i].frames_info = *frames_info;
+       dev->received_frames[i].frames_num = dev->received_count;
+       dev->received_frames[i].time_us64 = time_us64;
+
+       vc_print(dev->index, PRINT_PERFORMANCE,
+                "len =%d,frame_count=%d,i=%d,z=%d,time_us64=%lld,fd=%d, time_vsync=%lld\n",
+                kfifo_len(&dev->receive_q),
+                frames_info->frame_count,
+                i,
+                frames_info->disp_zorder,
+                time_us64,
+                fence_fd,
+                time_vsync);
+
+       for (j = 0; j < frames_info->frame_count; j++) {
+               frames_info->frame_info[j].composer_fen_fd = fence_fd;
+               file_vf = fget(frames_info->frame_info[j].fd);
+               dev->received_frames[i].file_vf[j] = file_vf;
+               if (frames_info->frame_info[j].type == 0) {
+                       file_private_data =
+                       (struct file_private_data *)(file_vf->private_data);
+                       vf = &file_private_data->vf;
+                       vc_print(dev->index, PRINT_OTHER,
+                                "received_cnt=%lld,i=%d,z=%d,omx_index=%d\n",
+                                dev->received_count + 1,
+                                i,
+                                frames_info->frame_info[j].zorder,
+                                vf->omx_index);
+               } else if (frames_info->frame_info[j].type == 1) {
+                       vc_print(dev->index, PRINT_OTHER,
+                                "received_cnt=%lld,i=%d,z=%d,DMA_fd=%d\n",
+                                dev->received_count + 1,
+                                i,
+                                frames_info->frame_info[j].zorder,
+                                frames_info->frame_info[j].fd);
+                       dev->received_frames[i].phy_addr[j] =
+                       get_dma_phy_addr(frames_info->frame_info[j].fd);
+               } else {
+                       vc_print(dev->index, PRINT_ERROR,
+                                "unsupport type=%d\n",
+                                frames_info->frame_info[j].type);
+               }
+       }
+       atomic_set(&dev->received_frames[i].on_use, true);
+
+       dev->received_count++;
+       if (!kfifo_put(&dev->receive_q, &dev->received_frames[i]))
+               vc_print(dev->index, PRINT_ERROR, "put ready fail\n");
+       wake_up_interruptible(&dev->wq);
+
+       //vc_print(dev->index, PRINT_PERFORMANCE, "set_frames_info_out\n");
+}
+
+/* -----------------------------------------------------------------
+ *           provider opeations
+ * -----------------------------------------------------------------
+ */
+static struct vframe_s *vc_vf_peek(void *op_arg)
+{
+       struct composer_dev *dev = (struct composer_dev *)op_arg;
+       struct vframe_s *vf = NULL;
+       struct timeval time1;
+       struct timeval time2;
+       u64 time_vsync;
+       int interval_time;
+
+       time1 = dev->start_time;
+       time2 = vsync_time;
+       if (kfifo_peek(&dev->ready_q, &vf)) {
+               if (vf && get_count[dev->index] > 0) {
+                       time_vsync = 1000000 * (time2.tv_sec - time1.tv_sec)
+                               + time2.tv_usec - time1.tv_usec;
+                       interval_time = abs(time_vsync - vf->pts_us64);
+                       vc_print(dev->index, PRINT_PERFORMANCE,
+                                "time_vsync=%lld, vf->pts_us64=%lld\n",
+                                time_vsync, vf->pts_us64);
+                       if (interval_time < margin_time) {
+                               vc_print(dev->index, PRINT_ERROR,
+                                        "display next vsync\n");
+                               return NULL;
+                       }
+               }
+               return vf;
+       } else {
+               return NULL;
+       }
+}
+
+static struct vframe_s *vc_vf_get(void *op_arg)
+{
+       struct composer_dev *dev = (struct composer_dev *)op_arg;
+       struct vframe_s *vf = NULL;
+
+       if (kfifo_get(&dev->ready_q, &vf)) {
+               if (vf) {
+                       if (!kfifo_put(&dev->display_q, vf))
+                               vc_print(dev->index, PRINT_ERROR,
+                                        "display_q is full!\n");
+                       get_count[dev->index]++;
+               }
+               vc_print(dev->index, PRINT_OTHER,
+                        "get: omx_index=%d\n",
+                        vf->omx_index);
+
+               return vf;
+       } else {
+               return NULL;
+       }
+}
+
+static void vc_vf_put(struct vframe_s *vf, void *op_arg)
+{
+       struct composer_dev *dev = (struct composer_dev *)op_arg;
+       int repeat_count;
+       int omx_index;
+       bool rendered;
+       bool is_composer;
+       int i;
+       struct file *file_vf;
+       bool is_dma_buf;
+
+       if (!vf)
+               return;
+
+       repeat_count = vf->repeat_count[dev->index];
+       omx_index = vf->omx_index;
+       rendered = vf->rendered;
+       is_composer = vf->flag & VFRAME_FLAG_COMPOSER_DONE;
+       file_vf = vf->file_vf;
+       is_dma_buf = vf->flag & VFRAME_FLAG_VIDEO_COMPOSER_DMA;
+
+       if (vf->flag & VFRAME_FLAG_FAKE_FRAME) {
+               vc_print(dev->index, PRINT_OTHER,
+                        "put: fake frame\n");
+               return;
+       }
+
+       vc_print(dev->index, PRINT_OTHER,
+                "put: repeat_count =%d, omx_index=%d\n",
+                repeat_count, omx_index);
+
+       vf_pop_display_q(dev, vf);
+
+       if (rendered) {
+               video_timeline_increase(dev, repeat_count
+                                       + 1 + dev->drop_frame_count);
+               dev->drop_frame_count = 0;
+       } else {
+               dev->drop_frame_count += repeat_count + 1;
+               vc_print(dev->index, PRINT_ERROR,
+                        "put: drop repeat_count=%d\n", repeat_count);
+       }
+
+       if (!is_composer) {
+               for (i = 0; i <= repeat_count; i++) {
+                       fput(file_vf);
+                       dev->fput_count++;
+               }
+       } else {
+               videocom_vf_put(vf, dev);
+       }
+       if (is_dma_buf) {
+               if (!kfifo_put(&dev->dma_free_q, vf))
+                       vc_print(dev->index, PRINT_ERROR,
+                                "dma_free is full!\n");
+       }
+}
+
+static int vc_event_cb(int type, void *data, void *private_data)
+{
+       if (type & VFRAME_EVENT_RECEIVER_PUT)
+               ;
+       else if (type & VFRAME_EVENT_RECEIVER_GET)
+               ;
+       else if (type & VFRAME_EVENT_RECEIVER_FRAME_WAIT)
+               ;
+       return 0;
+}
+
+static int vc_vf_states(struct vframe_states *states, void *op_arg)
+{
+       struct composer_dev *dev = (struct composer_dev *)op_arg;
+
+       states->vf_pool_size = COMPOSER_READY_POOL_SIZE;
+       states->buf_recycle_num = 0;
+       states->buf_free_num = COMPOSER_READY_POOL_SIZE
+               - kfifo_len(&dev->ready_q);
+       states->buf_avail_num = kfifo_len(&dev->ready_q);
+       return 0;
+}
+
+static const struct vframe_operations_s vc_vf_provider = {
+       .peek = vc_vf_peek,
+       .get = vc_vf_get,
+       .put = vc_vf_put,
+       .event_cb = vc_event_cb,
+       .vf_states = vc_vf_states,
+};
+
+static void disable_video_layer(struct composer_dev *dev, int val)
+{
+       pr_info("dev->index =%d, val=%d", dev->index, val);
+       if (dev->index == 0)
+               _video_set_disable(val);
+       else if (dev->index == 1)
+               _videopip_set_disable(val);
+}
+
+static int video_composer_creat_path(struct composer_dev *dev)
+{
+       if (dev->index == 0)
+               snprintf(dev->vfm_map_chain, VCOM_MAP_NAME_SIZE,
+                        "%s %s", dev->vf_provider_name,
+                        "video_render.0");
+       else if (dev->index == 1)
+               snprintf(dev->vfm_map_chain, VCOM_MAP_NAME_SIZE,
+                        "%s %s", dev->vf_provider_name,
+                        "video_render.1");
+
+       snprintf(dev->vfm_map_id, VCOM_MAP_NAME_SIZE,
+                "vcom-map-%d", dev->index);
+
+       if (vfm_map_add(dev->vfm_map_id,
+                       dev->vfm_map_chain) < 0) {
+               pr_err("vcom pipeline map creation failed %s.\n",
+                      dev->vfm_map_id);
+               dev->vfm_map_id[0] = 0;
+               return -ENOMEM;
+       }
+
+       vf_provider_init(&dev->vc_vf_prov, dev->vf_provider_name,
+                        &vc_vf_provider, dev);
+
+       vf_reg_provider(&dev->vc_vf_prov);
+
+       vf_notify_receiver(dev->vf_provider_name,
+                          VFRAME_EVENT_PROVIDER_START, NULL);
+       return 0;
+}
+
+static int video_composer_release_path(struct composer_dev *dev)
+{
+       vf_unreg_provider(&dev->vc_vf_prov);
+
+       if (dev->vfm_map_id[0]) {
+               vfm_map_remove(dev->vfm_map_id);
+               dev->vfm_map_id[0] = 0;
+       }
+       return 0;
+}
+
+static int video_composer_init(struct composer_dev *dev)
+{
+       int ret;
+       int i;
+
+       if (!dev)
+               return -1;
+       INIT_KFIFO(dev->ready_q);
+       INIT_KFIFO(dev->receive_q);
+       INIT_KFIFO(dev->free_q);
+       INIT_KFIFO(dev->display_q);
+       INIT_KFIFO(dev->dma_free_q);
+       kfifo_reset(&dev->ready_q);
+       kfifo_reset(&dev->receive_q);
+       kfifo_reset(&dev->free_q);
+       kfifo_reset(&dev->display_q);
+       kfifo_reset(&dev->dma_free_q);
+
+       for (i = 0; i < DMA_BUF_COUNT; i++)
+               kfifo_put(&dev->dma_free_q, &dev->dma_vf[i]);
+
+       dev->received_count = 0;
+       dev->fence_creat_count = 0;
+       dev->fence_release_count = 0;
+       dev->fput_count = 0;
+       dev->last_dst_vf = NULL;
+       dev->drop_frame_count = 0;
+       dev->is_sideband = false;
+       dev->need_empty_ready = false;
+       init_completion(&dev->task_done);
+
+       disable_video_layer(dev, 2);
+       video_set_global_output(dev->index, 1);
+
+       ret = video_composer_creat_path(dev);
+       if (dev->index == 0)
+               set_video_path_select("video_render.0", 0);
+       else if (dev->index == 1)
+               set_video_path_select("video_render.1", 1);
+
+       return ret;
+}
+
+static int video_composer_uninit(struct composer_dev *dev)
+{
+       int ret;
+       int timeout = 0;
+
+       disable_video_layer(dev, 1);
+       video_set_global_output(dev->index, 0);
+       ret = video_composer_release_path(dev);
+
+       dev->need_unint_receive_q = true;
+
+       /* free buffer */
+       dev->need_free_buffer = true;
+       wake_up_interruptible(&dev->wq);
+
+       timeout = wait_for_completion_timeout(&dev->task_done,
+                                             msecs_to_jiffies(100));
+       if (!timeout)
+               vc_print(dev->index, PRINT_ERROR, "unreg:wait timeout\n");
+
+       display_q_uninit(dev);
+
+       if (dev->fence_creat_count != dev->fput_count) {
+               vc_print(dev->index, PRINT_ERROR,
+                        "uninit: fence_r=%lld, fence_c=%lld\n",
+                        dev->fence_release_count,
+                        dev->fence_creat_count);
+               vc_print(dev->index, PRINT_ERROR,
+                        "uninit: received=%lld, fput=%lld, drop=%d\n",
+                        dev->received_count,
+                        dev->fput_count,
+                        dev->drop_frame_count);
+       }
+       video_timeline_increase(dev,
+                               dev->fence_creat_count
+                               - dev->fence_release_count);
+       dev->is_sideband = false;
+       dev->need_empty_ready = false;
+
+       return ret;
+}
+
+int video_composer_set_enable(struct composer_dev *dev, u32 val)
+{
+       int ret = 0;
+
+       if (val > VIDEO_COMPOSER_ENABLE_NORMAL)
+               return -EINVAL;
+
+       vc_print(dev->index, PRINT_ERROR,
+                "vc: set enable index=%d, val=%d\n",
+                dev->index, val);
+
+       if (dev->enable_composer == val) {
+               pr_err("vc: set_enable repeat set dev->index =%d,val=%d\n",
+                      dev->index, val);
+               return ret;
+       }
+       dev->enable_composer = val;
+       wake_up_interruptible(&dev->wq);
+
+       if (val == VIDEO_COMPOSER_ENABLE_NORMAL)
+               ret = video_composer_init(dev);
+       else if (val == VIDEO_COMPOSER_ENABLE_NONE)
+               ret = video_composer_uninit(dev);
+
+       if (ret != 0)
+               pr_err("vc: set failed\n");
+       return ret;
+}
+
+static long video_composer_ioctl(struct file *file,
+                                unsigned int cmd, ulong arg)
+{
+       long ret = 0;
+       void __user *argp = (void __user *)arg;
+       u32 val;
+       struct composer_dev *dev = (struct composer_dev *)file->private_data;
+       struct frames_info_t frames_info;
+
+       switch (cmd) {
+       case VIDEO_COMPOSER_IOCTL_SET_FRAMES:
+               if (copy_from_user(&frames_info, argp,
+                                  sizeof(frames_info)) == 0) {
+                       set_frames_info(dev, &frames_info);
+                       ret = copy_to_user(argp, &frames_info,
+                                          sizeof(struct frames_info_t));
+
+               } else {
+                       ret = -EFAULT;
+               }
+               break;
+       case VIDEO_COMPOSER_IOCTL_SET_ENABLE:
+               if (copy_from_user(&val, argp, sizeof(u32)) == 0)
+                       ret = video_composer_set_enable(dev, val);
+               else
+                       ret = -EFAULT;
+               break;
+       case VIDEO_COMPOSER_IOCTL_SET_DISABLE:
+               break;
+       default:
+               return -EINVAL;
+       }
+       return ret;
+}
+
+#ifdef CONFIG_COMPAT
+static long video_composer_compat_ioctl(struct file *file, unsigned int cmd,
+                                       ulong arg)
+{
+       long ret = 0;
+
+       ret = video_composer_ioctl(file, cmd, (ulong)compat_ptr(arg));
+       return ret;
+}
+#endif
+
+static const struct file_operations video_composer_fops = {
+       .owner = THIS_MODULE,
+       .open = video_composer_open,
+       .release = video_composer_release,
+       .unlocked_ioctl = video_composer_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = video_composer_compat_ioctl,
+#endif
+       .poll = NULL,
+};
+
+static int video_composer_probe(struct platform_device *pdev)
+{
+       int ret = 0;
+       int i = 0;
+       u32 layer_cap = 0;
+       struct video_composer_port_s *st;
+
+       layer_cap = video_get_layer_capability();
+       video_composer_instance_num = 0;
+       if (layer_cap & LAYER0_SCALER)
+               video_composer_instance_num++;
+       if (layer_cap & LAYER1_SCALER)
+               video_composer_instance_num++;
+
+       ret = class_register(&video_composer_class);
+       if (ret < 0)
+               return ret;
+
+       ret = register_chrdev(VIDEO_COMPOSER_MAJOR,
+                             "video_composer", &video_composer_fops);
+       if (ret < 0) {
+               pr_err("Can't allocate major for video_composer device\n");
+               goto error1;
+       }
+
+       video_composer_dev_class =
+               class_create(THIS_MODULE, VIDEO_COMPOSER_DEVICE_NAME);
+
+       for (st = &ports[0], i = 0;
+            i < video_composer_instance_num; i++, st++) {
+               pr_err("video_composer_probe_3.1:ports[i].name=%s, i=%d\n",
+                      ports[i].name, i);
+               st->class_dev = device_create(video_composer_dev_class, NULL,
+                               MKDEV(VIDEO_COMPOSER_MAJOR, i), NULL,
+                               ports[i].name);
+       }
+       pr_err("video_composer_probe num=%d\n", video_composer_instance_num);
+       return ret;
+
+error1:
+       pr_err("video_composer_probe error\n");
+       unregister_chrdev(VIDEO_COMPOSER_MAJOR, "video_composer");
+       class_unregister(&video_composer_class);
+       return ret;
+}
+
+static const struct of_device_id amlogic_video_composer_dt_match[] = {
+       {
+               .compatible = "amlogic, video_composer",
+       },
+       {},
+};
+
+static int video_composer_remove(struct platform_device *pdev)
+
+{
+       int i;
+       struct video_composer_port_s *st;
+
+       for (st = &ports[0], i = 0;
+            i < video_composer_instance_num; i++, st++)
+               device_destroy(video_composer_dev_class,
+                              MKDEV(VIDEO_COMPOSER_MAJOR, i));
+
+       class_destroy(video_composer_dev_class);
+
+       unregister_chrdev(VIDEO_COMPOSER_MAJOR, VIDEO_COMPOSER_DEVICE_NAME);
+
+       class_unregister(&video_composer_class);
+       return 0;
+};
+
+static struct platform_driver video_composer_driver = {
+       .probe = video_composer_probe,
+       .remove = video_composer_remove,
+       .driver = {
+               .owner = THIS_MODULE,
+               .name = "video_composer",
+               .of_match_table = amlogic_video_composer_dt_match,
+       }
+};
+
+static int __init video_composer_module_init(void)
+{
+       pr_err("video_composer_module_init_1\n");
+
+       if (platform_driver_register(&video_composer_driver)) {
+               pr_err("failed to register video_composer module\n");
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static void __exit video_composer_module_exit(void)
+{
+       platform_driver_unregister(&video_composer_driver);
+}
+
+MODULE_DESCRIPTION("Video Technology Magazine video composer Capture Boad");
+MODULE_AUTHOR("Amlogic, Jintao Xu<jintao.xu@amlogic.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(VIDEO_COMPOSER_VERSION);
+
+module_init(video_composer_module_init);
+module_exit(video_composer_module_exit);
diff --git a/drivers/amlogic/media/video_processor/video_composer/video_composer.h b/drivers/amlogic/media/video_processor/video_composer/video_composer.h
new file mode 100644 (file)
index 0000000..cbc5136
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * drivers/amlogic/media/video_processor/video_composer/video_composer.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 VIDEO_COMPOSER_H
+#define VIDEO_COMPOSER_H
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/videodev2.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/delay.h>
+#include <linux/amlogic/media/video_processor/video_composer_ext.h>
+#include <linux/amlogic/media/vout/vout_notify.h>
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/amlogic/media/vfm/vframe_provider.h>
+#include <linux/amlogic/media/vfm/vframe_receiver.h>
+#include <linux/amlogic/media/vfm/vfm_ext.h>
+
+#include <linux/kfifo.h>
+#include <linux/amlogic/media/video_sink/v4lvideo_ext.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-contiguous.h>
+#include "vfq.h"
+#include <linux/amlogic/media/ge2d/ge2d.h>
+#include "vframe_ge2d_composer.h"
+
+#define MXA_LAYER_COUNT 9
+#define COMPOSER_READY_POOL_SIZE 32
+#define FRAMES_INFO_POOL_SIZE 32
+
+/* disable video_composer mode */
+#define VIDEO_COMPOSER_ENABLE_NONE    0
+#define VIDEO_COMPOSER_ENABLE_NORMAL  1
+#define BUFFER_LEN 4
+#define DMA_BUF_COUNT 4
+
+#define VCOM_MAP_NAME_SIZE 90
+#define VCOM_PROVIDER_NAME_SIZE 32
+
+enum vc_transform_t {
+       /* flip source image horizontally */
+       VC_TRANSFORM_FLIP_H = 1,
+       /* flip source image vertically */
+       VC_TRANSFORM_FLIP_V = 2,
+       /* rotate source image 90 degrees clock-wise */
+       VC_TRANSFORM_ROT_90 = 4,
+       /* rotate source image 180 degrees */
+       VC_TRANSFORM_ROT_180 = 3,
+       /* rotate source image 270 degrees clock-wise */
+       VC_TRANSFORM_ROT_270 = 7,
+       /* flip source image horizontally, the rotate 90 degrees clock-wise */
+       VC_TRANSFORM_FLIP_H_ROT_90 = VC_TRANSFORM_FLIP_H | VC_TRANSFORM_ROT_90,
+       /* flip source image vertically, the rotate 90 degrees clock-wise */
+       VC_TRANSFORM_FLIP_V_ROT_90 = VC_TRANSFORM_FLIP_V | VC_TRANSFORM_ROT_90,
+};
+
+struct frame_info_t {
+       u32 fd;
+       u32 composer_fen_fd;
+       u32 disp_fen_fd;
+       u32 buffer_w;
+       u32 buffer_h;
+       u32 dst_x;
+       u32 dst_y;
+       u32 dst_w;
+       u32 dst_h;
+       u32 crop_x;
+       u32 crop_y;
+       u32 crop_w;
+       u32 crop_h;
+       u32 zorder;
+       u32 transform;
+       u32 type;
+       u32 reserved[4];
+};
+
+struct frames_info_t {
+       u32 frame_count;
+       struct frame_info_t frame_info[MXA_LAYER_COUNT];
+       u32 layer_index;
+       u32 disp_zorder;
+       u32 reserved[4];
+};
+
+enum com_buffer_status {
+       UNINITIAL = 0,
+       INIT_SUCCESS,
+       INIT_ERROR,
+};
+
+struct video_composer_port_s {
+       const char *name;
+       u32 index;
+       u32 open_count;
+       struct device *class_dev;
+};
+
+struct videocom_frame_s {
+       struct vframe_s frame;
+       int index;
+};
+
+struct vidc_buf_status {
+       int index;
+       int dirty;
+};
+
+struct dst_buf_t {
+       int index;
+       struct vframe_s frame;
+       bool dirty;
+       u32 phy_addr;
+       u32 buf_w;
+       u32 buf_h;
+       u32 buf_size;
+};
+
+struct output_axis {
+       int left;
+       int top;
+       int width;
+       int height;
+};
+
+struct received_frames_t {
+       int index;
+       atomic_t on_use;
+       struct frames_info_t frames_info;
+       unsigned long long frames_num;
+       struct file *file_vf[MXA_LAYER_COUNT];
+       unsigned long phy_addr[MXA_LAYER_COUNT];
+       u64 time_us64;
+};
+
+struct composer_dev {
+       u32 index;
+       struct video_composer_port_s *port;
+       u32 enable_composer;
+       DECLARE_KFIFO(ready_q, struct vframe_s *, COMPOSER_READY_POOL_SIZE);
+       DECLARE_KFIFO(receive_q, struct received_frames_t *,
+                     FRAMES_INFO_POOL_SIZE);
+       DECLARE_KFIFO(free_q, struct vframe_s *, BUFFER_LEN);
+       DECLARE_KFIFO(display_q, struct vframe_s *, COMPOSER_READY_POOL_SIZE);
+       DECLARE_KFIFO(dma_free_q, struct vframe_s *, BUFFER_LEN);
+       char vf_provider_name[VCOM_PROVIDER_NAME_SIZE];
+       char vfm_map_id[VCOM_MAP_NAME_SIZE];
+       char vfm_map_chain[VCOM_MAP_NAME_SIZE];
+       struct vframe_provider_s vc_vf_prov;
+       void *video_timeline;
+       u32 cur_streamline_val;
+       struct file *last_file;
+       enum com_buffer_status buffer_status;
+       struct ge2d_composer_para ge2d_para;
+       struct task_struct *kthread;
+       struct received_frames_t received_frames[FRAMES_INFO_POOL_SIZE];
+       unsigned long long received_count;
+       unsigned long long fence_creat_count;
+       unsigned long long fence_release_count;
+       unsigned long long fput_count;
+       bool need_free_buffer;
+       //struct mutex mutex_input;
+       wait_queue_head_t wq;
+       bool thread_stopped;
+       struct vframe_s *last_dst_vf;
+       bool need_unint_receive_q;
+       struct completion task_done;
+       struct dst_buf_t dst_buf[BUFFER_LEN];
+       struct vframe_s dma_vf[DMA_BUF_COUNT];
+       u32 drop_frame_count;
+       struct received_frames_t last_frames;
+       struct timeval start_time;
+       u32 vinfo_w;
+       u32 vinfo_h;
+       u32 composer_buf_w;
+       u32 composer_buf_h;
+       bool need_rotate;
+       bool is_sideband;
+       bool need_empty_ready;
+       struct vframe_s fake_vf;
+};
+
+#define VIDEO_COMPOSER_IOC_MAGIC  'V'
+#define VIDEO_COMPOSER_IOCTL_SET_FRAMES                \
+       _IOW(VIDEO_COMPOSER_IOC_MAGIC, 0x00, struct frames_info_t)
+#define VIDEO_COMPOSER_IOCTL_SET_ENABLE                \
+       _IOW(VIDEO_COMPOSER_IOC_MAGIC, 0x01, int)
+#define VIDEO_COMPOSER_IOCTL_SET_DISABLE       \
+       _IOW(VIDEO_COMPOSER_IOC_MAGIC, 0x02, int)
+
+#endif /* VIDEO_COMPOSER_H */
index 3ac0996d5ed1de529fde489cfa9a65265c8e974f..e83c7eade79987e7c38523d88a1c210058adbe34 100644 (file)
@@ -1,2 +1,2 @@
 obj-y  +=      amvideo.o
-amvideo-objs   +=      video.o video_keeper.o vpp.o video_hw.o
+amvideo-objs   +=      video.o video_keeper.o vpp.o video_hw.o video_receiver.o
index e425526b2930827507fb4d000f18e19330c24283..e11a0de72f0c28c6bb3b641b3b5a2662cc6e0b54 100644 (file)
@@ -93,6 +93,8 @@ MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_DEFAULT_LEVEL_DESC, LOG_MASK_DESC);
 #endif
 #include <linux/math64.h>
 
+#include "video_receiver.h"
+
 static int get_count;
 static int get_count_pip;
 
@@ -284,6 +286,8 @@ static int vpts_chase_pts_diff;
 static int step_enable;
 static int step_flag;
 
+struct video_recv_s *gvideo_recv[2] = {NULL, NULL};
+
 /*seek values on.video_define.h*/
 static int debug_flag;
 int get_video_debug_flags(void)
@@ -680,7 +684,7 @@ static u32 blackout;
 #else
 static u32 blackout = 1;
 #endif
-static u32 force_blackout;
+u32 force_blackout;
 static u32 blackout_pip;
 
 /* disable video */
@@ -894,7 +898,7 @@ static inline struct vframe_s *pip_vf_get(void)
        if (vf) {
                get_count_pip++;
                /* video_notify_flag |= VIDEO_NOTIFY_PROVIDER_GET; */
-               atomic_set(&vf->use_cnt, 1);
+               atomic_set(&vf->use_cnt_pip, 1);
        }
        return vf;
 
@@ -920,7 +924,7 @@ static inline void pip_vf_put(struct vframe_s *vf)
        if (pip_loop)
                return;
 
-       if (vfp && vf && atomic_dec_and_test(&vf->use_cnt)) {
+       if (vfp && vf && atomic_dec_and_test(&vf->use_cnt_pip)) {
                vf_put(vf, RECEIVERPIP_NAME);
 #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
                if ((glayer_info[0].display_path_id
@@ -1055,7 +1059,9 @@ static inline void video_vf_put(struct vframe_s *vf)
        if (vf == &hist_test_vf)
                return;
 
-       if (vfp && vf && atomic_dec_and_test(&vf->use_cnt)) {
+       if (!vfp || !vf)
+               return;
+       if (atomic_dec_and_test(&vf->use_cnt)) {
                vf_put(vf, RECEIVER_NAME);
 #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
                if (is_dolby_vision_enable())
@@ -1881,6 +1887,10 @@ static inline bool vpts_expire(struct vframe_s *cur_vf,
        if (next_vf->flag & VFRAME_FLAG_GAME_MODE)
                return true;
 
+       /* FIXME: remove it */
+       if (next_vf->flag & VFRAME_FLAG_VIDEO_COMPOSER)
+               return true;
+
        if (step_enable) {
                if (step_flag)
                        return false;
@@ -2379,7 +2389,6 @@ static int dvel_swap_frame(struct vframe_s *vf)
 
                /* check if el available first */
                if (!dvel_status) {
-                       //safe_switch_videolayer(1, true, true);
                        dvel_changed = true;
                        dvel_size = new_dvel_w;
                        need_disable_vd2 = false;
@@ -2392,7 +2401,6 @@ static int dvel_swap_frame(struct vframe_s *vf)
                        layer_info);
                dvel_status = true;
        } else if (dvel_status) {
-               //safe_switch_videolayer(1, false, true);
                dvel_changed = true;
                dvel_status = false;
                dvel_size = 0;
@@ -2752,10 +2760,160 @@ bool black_threshold_check(u8 id)
        return ret;
 }
 
+static void _set_video_crop(
+       struct disp_info_s *layer, int *p)
+{
+       int last_l, last_r, last_t, last_b;
+       int new_l, new_r, new_t, new_b;
+
+       if (!layer)
+               return;
+
+       last_t = layer->crop_top;
+       last_l = layer->crop_left;
+       last_b = layer->crop_bottom;
+       last_r = layer->crop_right;
+
+       layer->crop_top = p[0];
+       layer->crop_left = p[1];
+       layer->crop_bottom = p[2];
+       layer->crop_right = p[3];
+
+       new_t = layer->crop_top;
+       new_l = layer->crop_left;
+       new_b = layer->crop_bottom;
+       new_r = layer->crop_right;
+       if ((new_t != last_t) || (new_l != last_l) ||
+           (new_b != last_b) || (new_r != last_r)) {
+               if (layer->layer_id == 0)
+                       vd_layer[0].property_changed = true;
+               else if (layer->layer_id == 1)
+                       vd_layer[1].property_changed = true;
+       }
+}
+
+static void _set_video_window(
+       struct disp_info_s *layer, int *p)
+{
+       int w, h;
+       int *parsed = p;
+       int last_x, last_y, last_w, last_h;
+       int new_x, new_y, new_w, new_h;
+#ifdef TV_REVERSE
+       int temp, temp1;
+       const struct vinfo_s *info = get_current_vinfo();
+#endif
+
+       if (!layer)
+               return;
+
+#ifdef TV_REVERSE
+       if (reverse) {
+               temp = parsed[0];
+               temp1 = parsed[1];
+               parsed[0] = info->width - parsed[2] - 1;
+               parsed[1] = info->height - parsed[3] - 1;
+               parsed[2] = info->width - temp - 1;
+               parsed[3] = info->height - temp1 - 1;
+       }
+#endif
+
+       last_x = layer->layer_left;
+       last_y = layer->layer_top;
+       last_w = layer->layer_width;
+       last_h = layer->layer_height;
+
+       if (parsed[0] < 0 && parsed[2] < 2) {
+               parsed[2] = 2;
+               parsed[0] = 0;
+       }
+       if (parsed[1] < 0 && parsed[3] < 2) {
+               parsed[3] = 2;
+               parsed[1] = 0;
+       }
+       w = parsed[2] - parsed[0] + 1;
+       h = parsed[3] - parsed[1] + 1;
+
+#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
+       if (video_scaler_mode) {
+               if ((w == 1) && (h == 1)) {
+                       w = 0;
+                       h = 0;
+               }
+               if ((content_left != parsed[0]) ||
+                   (content_top != parsed[1]) ||
+                   (content_w != w) ||
+                   (content_h != h))
+                       scaler_pos_changed = 1;
+               content_left = parsed[0];
+               content_top = parsed[1];
+               content_w = w;
+               content_h = h;
+               /* video_notify_flag =*/
+               /*video_notify_flag|VIDEO_NOTIFY_POS_CHANGED; */
+       } else
+#endif
+       {
+               if ((w > 0) && (h > 0)) {
+                       if ((w == 1) && (h == 1)) {
+                               w = 0;
+                               h = 0;
+                       }
+                       layer->layer_left = parsed[0];
+                       layer->layer_top = parsed[1];
+                       layer->layer_width = w;
+                       layer->layer_height = h;
+               }
+       }
+
+       new_x = layer->layer_left;
+       new_y = layer->layer_top;
+       new_w = layer->layer_width;
+       new_h = layer->layer_height;
+
+       if ((last_x != new_x) || (last_y != new_y) ||
+           (last_w != new_w) || (last_h != new_h)) {
+               if (layer->layer_id == 0)
+                       vd_layer[0].property_changed = true;
+               else if (layer->layer_id == 1)
+                       vd_layer[1].property_changed = true;
+       }
+}
+
+void set_video_crop_ext(int layer_index, int *p)
+{
+       struct disp_info_s *layer = &glayer_info[layer_index];
+
+       _set_video_crop(layer, p);
+}
+
+void set_video_window_ext(int layer_index, int *p)
+{
+       struct disp_info_s *layer = &glayer_info[layer_index];
+
+       _set_video_window(layer, p);
+}
+
+void set_video_zorder_ext(int layer_index, int zorder)
+{
+       struct disp_info_s *layer = &glayer_info[layer_index];
+
+       if (layer->zorder != zorder) {
+               layer->zorder = zorder;
+               if (layer->layer_id == 0) {
+                       vd_layer[0].property_changed = true;
+               } else if (layer->layer_id == 1) {
+                       vd_layer[1].property_changed = true;
+               }
+       }
+}
+
 static void pip_swap_frame(struct vframe_s *vf)
 {
        struct video_layer_s *layer = NULL;
        struct disp_info_s *layer_info = NULL;
+       int axis[4];
+       int crop[4];
        int ret;
 
        if (!vf)
@@ -2768,6 +2926,21 @@ static void pip_swap_frame(struct vframe_s *vf)
                DEBUG_FLAG_PRINT_TOGGLE_FRAME)
                pr_info("%s()\n", __func__);
 
+       if (vf->flag & VFRAME_FLAG_VIDEO_COMPOSER) {
+               axis[0] = vf->axis[0];
+               axis[1] = vf->axis[1];
+               axis[2] = vf->axis[2];
+               axis[3] = vf->axis[3];
+               crop[0] = vf->crop[0];
+               crop[1] = vf->crop[1];
+               crop[2] = vf->crop[2];
+               crop[3] = vf->crop[3];
+               _set_video_window(&glayer_info[1], axis);
+               _set_video_crop(&glayer_info[1], crop);
+
+               glayer_info[1].zorder = vf->zorder;
+       }
+
        ret = layer_swap_frame(
                vf, layer->layer_id, false, vinfo);
 
@@ -2775,7 +2948,7 @@ static void pip_swap_frame(struct vframe_s *vf)
        if (!is_local_vf(layer->dispbuf)) {
                if (layer->keep_frame_id == 1)
                        video_pip_keeper_new_frame_notify();
-               else
+               else if (layer->keep_frame_id == 0)
                        video_keeper_new_frame_notify();
        }
        if (stop_update)
@@ -2865,6 +3038,8 @@ static void primary_swap_frame(
        int ret;
        struct video_layer_s *layer = NULL;
        struct disp_info_s *layer_info = NULL;
+       int axis[4];
+       int crop[4];
 
        ATRACE_COUNTER(__func__,  line);
 
@@ -2874,6 +3049,20 @@ static void primary_swap_frame(
        layer = &vd_layer[0];
        layer_info = &glayer_info[0];
 
+       if (vf->flag & VFRAME_FLAG_VIDEO_COMPOSER) {
+               axis[0] = vf->axis[0];
+               axis[1] = vf->axis[1];
+               axis[2] = vf->axis[2];
+               axis[3] = vf->axis[3];
+               crop[0] = vf->crop[0];
+               crop[1] = vf->crop[1];
+               crop[2] = vf->crop[2];
+               crop[3] = vf->crop[3];
+               _set_video_window(&glayer_info[0], axis);
+               _set_video_crop(&glayer_info[0], crop);
+               glayer_info[0].zorder = vf->zorder;
+       }
+
        if ((layer->layer_id == 0) && vf &&
            !(vf->type & VIDTYPE_COMPRESS) &&
            layer_info->need_no_compress) {
@@ -2891,7 +3080,8 @@ static void primary_swap_frame(
                        force_toggle = true;
        } else {
 #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE
-               if (is_di_on()) {
+               /* FIXME: is_di_on */
+               if (is_di_post_mode(vf)) {
                        /* check mif enable status, disable post di */
                        VSYNC_WR_MPEG_REG(DI_POST_CTRL, 0x3 << 30);
                        VSYNC_WR_MPEG_REG(
@@ -2974,7 +3164,7 @@ static void primary_swap_frame(
        if (!is_local_vf(layer->dispbuf)) {
                if (layer->keep_frame_id == 1)
                        video_pip_keeper_new_frame_notify();
-               else
+               else if (layer->keep_frame_id == 0)
                        video_keeper_new_frame_notify();
        }
 
@@ -3182,6 +3372,8 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id)
        struct vframe_s *dv_new_vf = NULL;
        struct vframe_s *path0_new_frame = NULL;
        struct vframe_s *path1_new_frame = NULL;
+       struct vframe_s *path2_new_frame = NULL;
+       struct vframe_s *path3_new_frame = NULL;
        struct vframe_s *new_frame = NULL;
        struct vframe_s *new_frame2 = NULL;
        struct vframe_s *cur_dispbuf_back = cur_dispbuf;
@@ -3293,6 +3485,8 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id)
                }
        }
 
+       vsync_notify_video_composer();
+
 #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
        if (is_dolby_vision_enable() && dovi_drop_flag) {
                struct vframe_s *vf = NULL;
@@ -3432,9 +3626,9 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id)
 #endif
 #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
        /* check video frame before VECM process */
-       if (is_dolby_vision_enable() &&
+       if (is_dolby_vision_enable() && vf &&
            ((vd1_path_id == VFM_PATH_AMVIDEO) ||
-            (vd1_path_id == VFM_PATH_DEF)) && vf) {
+            (vd1_path_id == VFM_PATH_DEF))) {
                dolby_vision_check_mvc(vf);
                dolby_vision_check_hdr10(vf);
                dolby_vision_check_hdr10plus(vf);
@@ -3444,6 +3638,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id)
        if (cur_vd1_path_id != vd1_path_id) {
                char *provider_name = NULL;
 
+               /* FIXME: add more receiver check */
                if (vd1_path_id == VFM_PATH_PIP) {
                        provider_name = vf_get_provider_name("videopip");
                        while (provider_name) {
@@ -3601,17 +3796,24 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id)
 
        for (i = 0; i < dispbuf_to_put_num; i++) {
                if (dispbuf_to_put[i]) {
+                       dispbuf_to_put[i]->rendered = true;
                        video_vf_put(dispbuf_to_put[i]);
                        dispbuf_to_put[i] = NULL;
                }
                dispbuf_to_put_num = 0;
        }
        if (pipbuf_to_put) {
+               pipbuf_to_put->rendered = true;
                pip_vf_put(pipbuf_to_put);
                pipbuf_to_put = NULL;
        }
 #endif
 
+       if (gvideo_recv[0])
+               gvideo_recv[0]->func->early_proc(gvideo_recv[0]);
+       if (gvideo_recv[1])
+               gvideo_recv[1]->func->early_proc(gvideo_recv[1]);
+
        if ((!cur_dispbuf) || (cur_dispbuf == &vf_local)) {
                vf = video_vf_peek();
                if (vf) {
@@ -3815,7 +4017,8 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id)
                        if (trickmode_fffb == 1) {
                                trickmode_vpts = vf->pts;
 #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
-                               if (is_di_on()) {
+                               /* FIXME: replace is_di_on */
+                               if (is_di_post_mode(vf)) {
                                        atomic_set(&trickmode_framedone, 1);
                                        video_notify_flag |=
                                            VIDEO_NOTIFY_TRICK_WAIT;
@@ -3831,6 +4034,15 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id)
                        if (slowsync_repeat_enable)
                                frame_repeat_count = 0;
                        vf = video_vf_peek();
+                       if (vf) {
+                               if ((vf->flag & VFRAME_FLAG_VIDEO_COMPOSER) &&
+                                   (debug_flag &
+                                    DEBUG_FLAG_COMPOSER_NO_DROP_FRAME)) {
+                                       pr_info("composer not drop\n");
+                                       vf = NULL;
+                               }
+                       }
+
                        if (!vf)
                                next_peek_underflow++;
 #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
@@ -3977,8 +4189,8 @@ SET_FILTER:
        videopip_get_vf_cnt = 0;
 #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
        /* check video frame before VECM process */
-       if (vd1_path_id == VFM_PATH_PIP &&
-           is_dolby_vision_enable() && vf) {
+       if (vd1_path_id == VFM_PATH_PIP && vf &&
+           is_dolby_vision_enable()) {
                dolby_vision_check_hdr10(vf);
                dolby_vision_check_hdr10plus(vf);
                dolby_vision_check_hlg(vf);
@@ -4050,6 +4262,85 @@ SET_FILTER:
                        pr_info("videopip drop frame: drop count %d\n",
                                videopip_drop_vf_cnt);
        }
+
+       /* video_render.0 toggle frame */
+       if (gvideo_recv[0]) {
+               path2_new_frame =
+                       gvideo_recv[0]->func->dequeue_frame(gvideo_recv[0]);
+               if (vd1_path_id == gvideo_recv[0]->path_id) {
+                       /* FIXME: need DV dual layer case */
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+                       dv_new_vf = dvel_toggle_frame(vf, true);
+#endif
+                       amvecm_on_vs(
+                               (gvideo_recv[0]->cur_buf !=
+                                &gvideo_recv[0]->local_buf)
+                               ? gvideo_recv[0]->cur_buf : NULL,
+                               path2_new_frame,
+                               CSC_FLAG_CHECK_OUTPUT,
+                               0,
+                               0,
+                               0,
+                               0,
+                               0,
+                               0,
+                               VD1_PATH);
+               }
+               if (vd2_path_id == gvideo_recv[0]->path_id)
+                       amvecm_on_vs(
+                               (gvideo_recv[0]->cur_buf !=
+                                &gvideo_recv[0]->local_buf)
+                               ? gvideo_recv[0]->cur_buf : NULL,
+                               path2_new_frame,
+                               CSC_FLAG_CHECK_OUTPUT,
+                               0,
+                               0,
+                               0,
+                               0,
+                               0,
+                               0,
+                               VD2_PATH);
+       }
+
+       /* video_render.1 toggle frame */
+       if (gvideo_recv[1]) {
+               path3_new_frame =
+                       gvideo_recv[1]->func->dequeue_frame(gvideo_recv[1]);
+               if (vd1_path_id == gvideo_recv[1]->path_id) {
+                       /* FIXME: need DV dual layer case */
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+                       dv_new_vf = dvel_toggle_frame(vf, true);
+#endif
+                       amvecm_on_vs(
+                               (gvideo_recv[1]->cur_buf !=
+                                &gvideo_recv[1]->local_buf)
+                               ? gvideo_recv[1]->cur_buf : NULL,
+                               path3_new_frame,
+                               CSC_FLAG_CHECK_OUTPUT,
+                               0,
+                               0,
+                               0,
+                               0,
+                               0,
+                               0,
+                               VD1_PATH);
+               }
+               if (vd2_path_id == gvideo_recv[1]->path_id)
+                       amvecm_on_vs(
+                               (gvideo_recv[1]->cur_buf !=
+                                &gvideo_recv[1]->local_buf)
+                               ? gvideo_recv[1]->cur_buf : NULL,
+                               path3_new_frame,
+                               CSC_FLAG_CHECK_OUTPUT,
+                               0,
+                               0,
+                               0,
+                               0,
+                               0,
+                               0,
+                               VD2_PATH);
+       }
+
        /* FIXME: if need enable for vd1 */
 #ifdef CHECK_LATER
        if (!vd_layer[0].global_output) {
@@ -4065,28 +4356,35 @@ SET_FILTER:
             cur_vd2_path_id != vd2_path_id) &&
            (debug_flag & DEBUG_FLAG_PRINT_PATH_SWITCH)) {
                pr_info("VID: === before path switch ===\n");
-               pr_info("VID: \tcur_path_id: %d, %d;\nVID: \tnew_path_id: %d, %d;\nVID: \ttoggle:%p, %p,\nVID: \tcur:%p, %p;\n",
+               pr_info("VID: \tcur_path_id: %d, %d;\nVID: \tnew_path_id: %d, %d;\nVID: \ttoggle:%p, %p, %p %p\nVID: \tcur:%p, %p, %p, %p;\n",
                        cur_vd1_path_id, cur_vd2_path_id,
                        vd1_path_id, vd2_path_id,
                        path0_new_frame, path1_new_frame,
-                       cur_dispbuf, cur_pipbuf);
-               pr_info("VID: \tdispbuf:%p, %p;\nVID: \tlocal:%p, %p\n",
+                       path2_new_frame, path3_new_frame,
+                       cur_dispbuf, cur_pipbuf,
+                       gvideo_recv[0] ? gvideo_recv[0]->cur_buf : NULL,
+                       gvideo_recv[1] ? gvideo_recv[1]->cur_buf : NULL);
+               pr_info("VID: \tdispbuf:%p, %p;\nVID: \tlocal:%p, %p, %p, %p\n",
                        vd_layer[0].dispbuf, vd_layer[1].dispbuf,
-                       &vf_local, &local_pip);
+                       &vf_local, &local_pip,
+                       gvideo_recv[0] ? &gvideo_recv[0]->local_buf : NULL,
+                       gvideo_recv[1] ? &gvideo_recv[1]->local_buf : NULL);
                pr_info("VID: \tblackout:%d %d force:%d;\n",
                        blackout, blackout_pip, force_blackout);
        }
 
        if (debug_flag & DEBUG_FLAG_PRINT_DISBUF_PER_VSYNC)
-               pr_info("VID: path id: %d, %d; new_frame:%p, %p, cur:%p, %p; vd dispbuf:%p, %p; local:%p, %p\n",
+               pr_info("VID: path id: %d, %d; new_frame:%p, %p, %p, %p cur:%p, %p, %p, %p; vd dispbuf:%p, %p; local:%p, %p, %p, %p\n",
                        vd1_path_id, vd2_path_id,
-                       path0_new_frame,
-                       path1_new_frame,
+                       path0_new_frame, path1_new_frame,
+                       path2_new_frame, path3_new_frame,
                        cur_dispbuf, cur_pipbuf,
-                       vd_layer[0].dispbuf,
-                       vd_layer[1].dispbuf,
-                       &vf_local,
-                       &local_pip);
+                       gvideo_recv[0] ? gvideo_recv[0]->cur_buf : NULL,
+                       gvideo_recv[1] ? gvideo_recv[1]->cur_buf : NULL,
+                       vd_layer[0].dispbuf, vd_layer[1].dispbuf,
+                       &vf_local, &local_pip,
+                       gvideo_recv[0] ? &gvideo_recv[0]->local_buf : NULL,
+                       gvideo_recv[1] ? &gvideo_recv[0]->local_buf : NULL);
 
        if ((vd_layer[0].dispbuf_mapping == &cur_dispbuf) &&
            ((cur_dispbuf == &vf_local) ||
@@ -4100,8 +4398,66 @@ SET_FILTER:
            (vd_layer[0].dispbuf != cur_pipbuf))
                vd_layer[0].dispbuf = cur_pipbuf;
 
+       if (gvideo_recv[0] &&
+           (vd_layer[0].dispbuf_mapping == &gvideo_recv[0]->cur_buf) &&
+           ((gvideo_recv[0]->cur_buf == &gvideo_recv[0]->local_buf) ||
+            !gvideo_recv[0]->cur_buf) &&
+           (vd_layer[0].dispbuf != gvideo_recv[0]->cur_buf))
+               vd_layer[0].dispbuf = gvideo_recv[0]->cur_buf;
+
+       if (gvideo_recv[1] &&
+           (vd_layer[0].dispbuf_mapping == &gvideo_recv[1]->cur_buf) &&
+           ((gvideo_recv[1]->cur_buf == &gvideo_recv[1]->local_buf) ||
+            !gvideo_recv[1]->cur_buf) &&
+           (vd_layer[0].dispbuf != gvideo_recv[1]->cur_buf))
+               vd_layer[0].dispbuf = gvideo_recv[1]->cur_buf;
+
        /* vd1 config */
-       if (vd1_path_id == VFM_PATH_PIP) {
+       if (gvideo_recv[0] &&
+           (gvideo_recv[0]->path_id == vd1_path_id)) {
+               /* video_render.0 display on VD1 */
+               new_frame = path2_new_frame;
+               if (!new_frame) {
+                       if (!gvideo_recv[0]->cur_buf) {
+                               /* video_render.0 no frame in display */
+                               if (cur_vd1_path_id != vd1_path_id)
+                                       safe_switch_videolayer(0, false, true);
+                               vd_layer[0].dispbuf = NULL;
+                       } else if (gvideo_recv[0]->cur_buf ==
+                               &gvideo_recv[0]->local_buf) {
+                               /* video_render.0 keep frame */
+                               vd_layer[0].dispbuf = gvideo_recv[0]->cur_buf;
+                       } else if (vd_layer[0].dispbuf
+                               != gvideo_recv[0]->cur_buf) {
+                               /* video_render.0 has frame in display */
+                               new_frame = gvideo_recv[0]->cur_buf;
+                       }
+               }
+               vd_layer[0].dispbuf_mapping = &gvideo_recv[0]->cur_buf;
+               cur_blackout = 1;
+       } else if (gvideo_recv[1] &&
+           (gvideo_recv[1]->path_id == vd1_path_id)) {
+               /* video_render.1 display on VD1 */
+               new_frame = path3_new_frame;
+               if (!new_frame) {
+                       if (!gvideo_recv[1]->cur_buf) {
+                               /* video_render.1 no frame in display */
+                               if (cur_vd1_path_id != vd1_path_id)
+                                       safe_switch_videolayer(0, false, true);
+                               vd_layer[0].dispbuf = NULL;
+                       } else if (gvideo_recv[1]->cur_buf ==
+                               &gvideo_recv[1]->local_buf) {
+                               /* video_render.1 keep frame */
+                               vd_layer[0].dispbuf = gvideo_recv[1]->cur_buf;
+                       } else if (vd_layer[0].dispbuf
+                               != gvideo_recv[1]->cur_buf) {
+                               /* video_render.1 has frame in display */
+                               new_frame = gvideo_recv[1]->cur_buf;
+                       }
+               }
+               vd_layer[0].dispbuf_mapping = &gvideo_recv[1]->cur_buf;
+               cur_blackout = 1;
+       } else if (vd1_path_id == VFM_PATH_PIP) {
                /* pip display on VD1 */
                new_frame = path1_new_frame;
                if (!new_frame) {
@@ -4149,7 +4505,7 @@ SET_FILTER:
            is_local_vf(vd_layer[0].dispbuf)) {
                if (cur_blackout) {
                        vd_layer[0].property_changed = false;
-               } else if (!is_di_on()) {
+               } else if (!is_di_post_mode(vd_layer[0].dispbuf)) {
                        vd_layer[0].dispbuf->canvas0Addr =
                                get_layer_display_canvas(0);
                }
@@ -4169,10 +4525,13 @@ SET_FILTER:
 #endif
        }
 
-       if (vd1_path_id == VFM_PATH_PIP)
+       if ((vd1_path_id == VFM_PATH_AMVIDEO) ||
+           (vd1_path_id == VFM_PATH_DEF))
+               vd_layer[0].keep_frame_id = 0;
+       else if (vd1_path_id == VFM_PATH_PIP)
                vd_layer[0].keep_frame_id = 1;
        else
-               vd_layer[0].keep_frame_id = 0;
+               vd_layer[0].keep_frame_id = 0xff;
 
 #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
        if (new_frame)
@@ -4218,8 +4577,66 @@ SET_FILTER:
            (vd_layer[1].dispbuf != cur_pipbuf))
                vd_layer[1].dispbuf = cur_pipbuf;
 
+       if (gvideo_recv[0] &&
+           (vd_layer[1].dispbuf_mapping == &gvideo_recv[0]->cur_buf) &&
+           ((gvideo_recv[0]->cur_buf == &gvideo_recv[0]->local_buf) ||
+            !gvideo_recv[0]->cur_buf) &&
+           (vd_layer[1].dispbuf != gvideo_recv[0]->cur_buf))
+               vd_layer[1].dispbuf = gvideo_recv[0]->cur_buf;
+
+       if (gvideo_recv[1] &&
+           (vd_layer[1].dispbuf_mapping == &gvideo_recv[1]->cur_buf) &&
+           ((gvideo_recv[1]->cur_buf == &gvideo_recv[1]->local_buf) ||
+            !gvideo_recv[1]->cur_buf) &&
+           (vd_layer[1].dispbuf != gvideo_recv[1]->cur_buf))
+               vd_layer[1].dispbuf = gvideo_recv[1]->cur_buf;
+
        /* vd2 config */
-       if (vd2_path_id == VFM_PATH_AMVIDEO) {
+       if (gvideo_recv[0] &&
+           (gvideo_recv[0]->path_id == vd2_path_id)) {
+               /* video_render.0 display on VD2 */
+               new_frame2 = path2_new_frame;
+               if (!new_frame2) {
+                       if (!gvideo_recv[0]->cur_buf) {
+                               /* video_render.0 no frame in display */
+                               if (cur_vd2_path_id != vd2_path_id)
+                                       safe_switch_videolayer(1, false, true);
+                               vd_layer[1].dispbuf = NULL;
+                       } else if (gvideo_recv[0]->cur_buf ==
+                               &gvideo_recv[0]->local_buf) {
+                               /* video_render.0 keep frame */
+                               vd_layer[1].dispbuf = gvideo_recv[0]->cur_buf;
+                       } else if (vd_layer[1].dispbuf
+                               != gvideo_recv[0]->cur_buf) {
+                               /* video_render.0 has frame in display */
+                               new_frame2 = gvideo_recv[0]->cur_buf;
+                       }
+               }
+               vd_layer[1].dispbuf_mapping = &gvideo_recv[0]->cur_buf;
+               cur_blackout = 1;
+       } else if (gvideo_recv[1] &&
+           (gvideo_recv[1]->path_id == vd2_path_id)) {
+               /* video_render.1 display on VD1 */
+               new_frame2 = path3_new_frame;
+               if (!new_frame2) {
+                       if (!gvideo_recv[1]->cur_buf) {
+                               /* video_render.1 no frame in display */
+                               if (cur_vd2_path_id != vd2_path_id)
+                                       safe_switch_videolayer(1, false, true);
+                               vd_layer[1].dispbuf = NULL;
+                       } else if (gvideo_recv[1]->cur_buf ==
+                               &gvideo_recv[1]->local_buf) {
+                               /* video_render.1 keep frame */
+                               vd_layer[1].dispbuf = gvideo_recv[1]->cur_buf;
+                       } else if (vd_layer[1].dispbuf
+                               != gvideo_recv[1]->cur_buf) {
+                               /* video_render.1 has frame in display */
+                               new_frame2 = gvideo_recv[1]->cur_buf;
+                       }
+               }
+               vd_layer[1].dispbuf_mapping = &gvideo_recv[1]->cur_buf;
+               cur_blackout = 1;
+       } else if (vd2_path_id == VFM_PATH_AMVIDEO) {
                /* priamry display in VD2 */
                new_frame2 = path0_new_frame;
                if (!new_frame2) {
@@ -4282,10 +4699,13 @@ SET_FILTER:
                need_disable_vd2 = false;
        }
 
-       if (vd2_path_id == VFM_PATH_AMVIDEO)
+       if ((vd2_path_id == VFM_PATH_PIP) ||
+           (vd2_path_id == VFM_PATH_DEF))
+               vd_layer[1].keep_frame_id = 1;
+       else if (vd2_path_id == VFM_PATH_AMVIDEO)
                vd_layer[1].keep_frame_id = 0;
        else
-               vd_layer[1].keep_frame_id = 1;
+               vd_layer[1].keep_frame_id = 0xff;
 
 #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
        amvecm_on_vs(
@@ -4324,18 +4744,30 @@ SET_FILTER:
        pip_render_frame(
                &vd_layer[1], vd_layer[1].dispbuf);
 
+       if (vd_layer[0].dispbuf &&
+           (vd_layer[0].dispbuf->flag & VFRAME_FLAG_FAKE_FRAME))
+               safe_switch_videolayer(0, false, true);
+
+       if (vd_layer[1].dispbuf &&
+           (vd_layer[1].dispbuf->flag & VFRAME_FLAG_FAKE_FRAME))
+               safe_switch_videolayer(1, false, true);
+
        if ((cur_vd1_path_id != vd1_path_id ||
             cur_vd2_path_id != vd2_path_id) &&
            (debug_flag & DEBUG_FLAG_PRINT_PATH_SWITCH)) {
                pr_info("VID: === After path switch ===\n");
-               pr_info("VID: \tpath_id: %d, %d;\nVID: \ttoggle:%p, %p\nVID: \tnew:%p, %p\nVID: \tcur:%p, %p;\n",
+               pr_info("VID: \tpath_id: %d, %d;\nVID: \ttoggle:%p, %p, %p %p\nVID: \tcur:%p, %p, %p, %p;\n",
                        vd1_path_id, vd2_path_id,
                        path0_new_frame, path1_new_frame,
-                       new_frame, new_frame2,
-                       cur_dispbuf, cur_pipbuf);
-               pr_info("VID: \tdispbuf:%p, %p;\nVID: \tlocal:%p, %p\n",
+                       path2_new_frame, path3_new_frame,
+                       cur_dispbuf, cur_pipbuf,
+                       gvideo_recv[0] ? gvideo_recv[0]->cur_buf : NULL,
+                       gvideo_recv[1] ? gvideo_recv[1]->cur_buf : NULL);
+               pr_info("VID: \tdispbuf:%p, %p;\nVID: \tlocal:%p, %p, %p, %p\n",
                        vd_layer[0].dispbuf, vd_layer[1].dispbuf,
-                       &vf_local, &local_pip);
+                       &vf_local, &local_pip,
+                       gvideo_recv[0] ? &gvideo_recv[0]->local_buf : NULL,
+                       gvideo_recv[1] ? &gvideo_recv[1]->local_buf : NULL);
                pr_info("VID: \tblackout:%d %d force:%d;\n",
                        blackout, blackout_pip, force_blackout);
        }
@@ -4370,15 +4802,22 @@ SET_FILTER:
                di_post_process_done = true;
        }
 exit:
+#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE
        if (legacy_vpp &&
            !di_post_process_done &&
            is_di_post_on())
                DI_POST_UPDATE_MC();
+#endif
 #if defined(PTS_LOGGING) || defined(PTS_TRACE_DEBUG)
        pts_trace++;
 #endif
        vpp_blend_update(vinfo);
 
+       if (gvideo_recv[0])
+               gvideo_recv[0]->func->late_proc(gvideo_recv[0]);
+       if (gvideo_recv[1])
+               gvideo_recv[1]->func->late_proc(gvideo_recv[1]);
+
 #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
        cur_rdma_buf = cur_dispbuf;
        pip_rdma_buf = cur_pipbuf;
@@ -5062,7 +5501,7 @@ int _video_set_disable(u32 val)
                /* FIXME */
                if (layer->keep_frame_id == 1)
                        try_free_keep_videopip(0);
-               else
+               else if (layer->keep_frame_id == 0)
                        try_free_keep_video(0);
        } else {
                if (layer->dispbuf &&
@@ -5076,120 +5515,28 @@ int _video_set_disable(u32 val)
        return 0;
 }
 
-static void _set_video_crop(
-       struct disp_info_s *layer, int *p)
+void video_set_global_output(u32 index, u32 val)
 {
-       int last_l, last_r, last_t, last_b;
-       int new_l, new_r, new_t, new_b;
-
-       if (!layer)
-               return;
-
-       last_t = layer->crop_top;
-       last_l = layer->crop_left;
-       last_b = layer->crop_bottom;
-       last_r = layer->crop_right;
-
-       new_t = layer->crop_top = p[0];
-       new_l = layer->crop_left = p[1];
-       new_b = layer->crop_bottom = p[2];
-       new_r = layer->crop_right = p[3];
-       if ((new_t != last_t) || (new_l != last_l) ||
-           (new_b != last_b) || (new_r != last_r)) {
-               if (layer->layer_id == 0)
-                       vd_layer[0].property_changed = true;
-               else if (layer->layer_id == 1)
-                       vd_layer[1].property_changed = true;
+       if (index == 0) {
+               if (val != 0)
+                       vd_layer[0].global_output = 1;
+               else
+                       vd_layer[0].global_output = 0;
+       } else if (index == 1) {
+               if (val != 0)
+                       vd_layer[1].global_output = 1;
+               else
+                       vd_layer[1].global_output = 0;
        }
+       pr_info("VID: VD%d set global output as %d\n",
+               index + 1, (val != 0) ? 1 : 0);
 }
 
-static void _set_video_window(
-       struct disp_info_s *layer, int *p)
+u32 video_get_layer_capability(void)
 {
-       int w, h;
-       int *parsed = p;
-       int last_x, last_y, last_w, last_h;
-       int new_x, new_y, new_w, new_h;
-#ifdef TV_REVERSE
-       int temp, temp1;
-       const struct vinfo_s *info = get_current_vinfo();
-#endif
-
-       if (!layer)
-               return;
-
-#ifdef TV_REVERSE
-       if (reverse) {
-               temp = parsed[0];
-               temp1 = parsed[1];
-               parsed[0] = info->width - parsed[2] - 1;
-               parsed[1] = info->height - parsed[3] - 1;
-               parsed[2] = info->width - temp - 1;
-               parsed[3] = info->height - temp1 - 1;
-       }
-#endif
-
-       last_x = layer->layer_left;
-       last_y = layer->layer_top;
-       last_w = layer->layer_width;
-       last_h = layer->layer_height;
-
-       if (parsed[0] < 0 && parsed[2] < 2) {
-               parsed[2] = 2;
-               parsed[0] = 0;
-       }
-       if (parsed[1] < 0 && parsed[3] < 2) {
-               parsed[3] = 2;
-               parsed[1] = 0;
-       }
-       w = parsed[2] - parsed[0] + 1;
-       h = parsed[3] - parsed[1] + 1;
-
-#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_PPSCALER
-       if (video_scaler_mode) {
-               if ((w == 1) && (h == 1)) {
-                       w = 0;
-                       h = 0;
-               }
-               if ((content_left != parsed[0]) ||
-                   (content_top != parsed[1]) ||
-                   (content_w != w) ||
-                   (content_h != h))
-                       scaler_pos_changed = 1;
-               content_left = parsed[0];
-               content_top = parsed[1];
-               content_w = w;
-               content_h = h;
-               /* video_notify_flag =*/
-               /*video_notify_flag|VIDEO_NOTIFY_POS_CHANGED; */
-       } else
-#endif
-       {
-               if ((w > 0) && (h > 0)) {
-                       if ((w == 1) && (h == 1)) {
-                               w = 0;
-                               h = 0;
-                       }
-                       layer->layer_left = parsed[0];
-                       layer->layer_top = parsed[1];
-                       layer->layer_width = w;
-                       layer->layer_height = h;
-               }
-       }
-
-       new_x = layer->layer_left;
-       new_y = layer->layer_top;
-       new_w = layer->layer_width;
-       new_h = layer->layer_height;
-
-       if ((last_x != new_x) || (last_y != new_y) ||
-           (last_w != new_w) || (last_h != new_h)) {
-               if (layer->layer_id == 0)
-                       vd_layer[0].property_changed = true;
-               else if (layer->layer_id == 1)
-                       vd_layer[1].property_changed = true;
-       }
+       return layer_cap;
 }
+
 #if ENABLE_UPDATE_HDR_FROM_USER
 static void config_hdr_info(const struct vframe_master_display_colour_s p)
 {
@@ -5865,19 +6212,7 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg)
 
        case AMSTREAM_IOC_GLOBAL_SET_VIDEOPIP_OUTPUT:
        case AMSTREAM_IOC_GLOBAL_SET_VIDEO_OUTPUT:
-               if (layer->layer_id == 0) {
-                       if (arg != 0)
-                               vd_layer[0].global_output = 1;
-                       else
-                               vd_layer[0].global_output = 0;
-               } else if (layer->layer_id == 1) {
-                       if (arg != 0)
-                               vd_layer[1].global_output = 1;
-                       else
-                               vd_layer[1].global_output = 0;
-               }
-               pr_info("VID: VD%d set global output as %d\n",
-                       layer->layer_id + 1, (arg != 0) ? 1 : 0);
+               video_set_global_output(layer->layer_id, arg ? 1 : 0);
                break;
 
        case AMSTREAM_IOC_GLOBAL_GET_VIDEOPIP_OUTPUT:
@@ -7968,7 +8303,7 @@ static ssize_t video_free_keep_buffer_store(struct class *cla,
        if (val == 1) {
                if (vd_layer[0].keep_frame_id == 1)
                        try_free_keep_videopip(1);
-               else
+               else if (vd_layer[0].keep_frame_id == 0)
                        try_free_keep_video(1);
        }
        return count;
@@ -8356,7 +8691,7 @@ int _videopip_set_disable(u32 val)
                /* FIXME */
                if (layer->keep_frame_id == 1)
                        try_free_keep_videopip(0);
-               else
+               else if (vd_layer[0].keep_frame_id == 0)
                        try_free_keep_video(0);
        } else {
                if (layer->dispbuf &&
@@ -8712,6 +9047,41 @@ static ssize_t videopip_state_show(
        return len;
 }
 
+s32 set_video_path_select(const char *recv_name, u8 layer_id)
+{
+       u32 new_path_id;
+       struct disp_info_s *layer_info;
+       struct video_layer_s *layer;
+
+       if (!recv_name ||
+           (layer_id >= MAX_VD_LAYERS))
+               return -1;
+
+       layer_info = &glayer_info[layer_id];
+       layer = &vd_layer[layer_id];
+       new_path_id = layer_info->display_path_id;
+       if (!strcmp(recv_name, "default"))
+               new_path_id = VFM_PATH_DEF;
+       else if (!strcmp(recv_name, RECEIVER_NAME))
+               new_path_id = VFM_PATH_AMVIDEO;
+       else if (!strcmp(recv_name, RECEIVERPIP_NAME))
+               new_path_id = VFM_PATH_PIP;
+       else if (!strcmp(recv_name, "video_render.0"))
+               new_path_id = VFM_PATH_VIDEO_RENDER0;
+       else if (!strcmp(recv_name, "video_render.1"))
+               new_path_id = VFM_PATH_VIDEO_RENDER1;
+       else if (!strcmp(recv_name, "invalid"))
+               new_path_id = VFM_PATH_INVAILD;
+       if (layer_info->display_path_id != new_path_id) {
+               pr_info("VID: store VD%d path_id changed %d->%d\n",
+                       layer_id, layer_info->display_path_id, new_path_id);
+               layer_info->display_path_id = new_path_id;
+               layer->property_changed = true;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(set_video_path_select);
+
 static ssize_t path_select_show(
        struct class *cla,
        struct class_attribute *attr,
@@ -9488,11 +9858,16 @@ static int __init video_init(void)
                dispbuf_to_put[dispbuf_to_put_num] = NULL;
        }
 #endif
+       gvideo_recv[0] = create_video_receiver(
+               "video_render.0", VFM_PATH_VIDEO_RENDER0);
+       gvideo_recv[1] = create_video_receiver(
+               "video_render.1", VFM_PATH_VIDEO_RENDER1);
 
        vsync_fiq_up();
 
-       vf_receiver_init(&video_vf_recv, RECEIVER_NAME, &video_vf_receiver,
-                        NULL);
+       vf_receiver_init(
+               &video_vf_recv, RECEIVER_NAME,
+               &video_vf_receiver, NULL);
        vf_reg_receiver(&video_vf_recv);
 
        vf_receiver_init(
@@ -9537,6 +9912,13 @@ static void __exit video_exit(void)
 
        vsync_fiq_down();
 
+       if (gvideo_recv[0])
+               destroy_video_receiver(gvideo_recv[0]);
+       gvideo_recv[0] = NULL;
+       if (gvideo_recv[1])
+               destroy_video_receiver(gvideo_recv[1]);
+       gvideo_recv[1] = NULL;
+
        device_destroy(&amvideo_class, MKDEV(AMVIDEO_MAJOR, 0));
        device_destroy(&amvideo_poll_class, MKDEV(amvideo_poll_major, 0));
 
index ab8d27ce974d1d5faadbe5795802b08d6ded6133..0a0ce1ede72765771880b894f435438b08ab403b 100644 (file)
@@ -64,6 +64,9 @@
 #include <linux/amlogic/media/video_sink/video.h>
 #include "../common/vfm/vfm.h"
 #include <linux/amlogic/media/amdolbyvision/dolby_vision.h>
+#include "video_receiver.h"
+
+/* #define DI_POST_PWR */
 
 struct video_layer_s vd_layer[MAX_VD_LAYER];
 struct disp_info_s glayer_info[MAX_VD_LAYERS];
@@ -118,7 +121,7 @@ static int vpu_mem_power_off_count;
                        spin_unlock_irqrestore(&delay_work_lock, flags); \
                } \
        } while (0)
-
+#ifdef DI_POST_PWR
 #define VD1_MEM_POWER_ON() \
        do { \
                unsigned long flags; \
@@ -132,6 +135,20 @@ static int vpu_mem_power_off_count;
                        switch_vpu_mem_pd_vmod( \
                                VPU_VD1_SCALE, VPU_MEM_POWER_ON); \
        } while (0)
+#else
+#define VD1_MEM_POWER_ON() \
+       do { \
+               unsigned long flags; \
+               spin_lock_irqsave(&delay_work_lock, flags); \
+               vpu_delay_work_flag &= ~VPU_DELAYWORK_MEM_POWER_OFF_VD1; \
+               spin_unlock_irqrestore(&delay_work_lock, flags); \
+               switch_vpu_mem_pd_vmod(VPU_VIU_VD1, VPU_MEM_POWER_ON); \
+               switch_vpu_mem_pd_vmod(VPU_AFBC_DEC, VPU_MEM_POWER_ON); \
+               if (!legacy_vpp) \
+                       switch_vpu_mem_pd_vmod( \
+                               VPU_VD1_SCALE, VPU_MEM_POWER_ON); \
+       } while (0)
+#endif
 #define VD2_MEM_POWER_ON() \
        do { \
                unsigned long flags; \
@@ -391,6 +408,16 @@ bool is_di_post_link_on(void)
        return ret;
 }
 
+bool is_di_post_mode(struct vframe_s *vf)
+{
+       bool ret = false;
+
+       if (vf && (vf->type & VIDTYPE_PRE_INTERLACE) &&
+           !(vf->type & VIDTYPE_DI_PW))
+               ret = true;
+       return ret;
+}
+
 bool is_afbc_enabled(u8 layer_id)
 {
        struct video_layer_s *layer = NULL;
@@ -416,6 +443,14 @@ bool is_local_vf(struct vframe_s *vf)
             (vf == &vf_local2) ||
             (vf == &local_pip)))
                return true;
+
+       /* FIXEME: remove gvideo_recv */
+       if (vf && gvideo_recv[0] &&
+           (vf == &gvideo_recv[0]->local_buf))
+               return true;
+       if (vf && gvideo_recv[1] &&
+           (vf == &gvideo_recv[1]->local_buf))
+               return true;
        return false;
 }
 
@@ -475,7 +510,7 @@ void safe_switch_videolayer(u8 layer_id, bool on, bool async)
 
 static void vd1_path_select(
        struct video_layer_s *layer,
-       bool afbc, bool di_afbc)
+       bool afbc, bool di_afbc, bool di_post)
 {
        u32 misc_off = layer->misc_reg_offt;
 
@@ -507,9 +542,7 @@ static void vd1_path_select(
                                /* Vd1_afbc0_mem_sel */
                                (afbc ? 1 : 0),
                                22, 1);
-               if ((glayer_info[0].display_path_id
-                    != VFM_PATH_PIP) &&
-                   is_di_post_on()) {
+               if (di_post) {
                        /* check di_vpp_out_en bit */
                        VSYNC_WR_MPEG_REG_BITS(
                                VD1_AFBCD0_MISC_CTRL,
@@ -523,9 +556,7 @@ static void vd1_path_select(
                                20, 2);
                }
        } else {
-               if ((glayer_info[0].display_path_id
-                    != VFM_PATH_PIP) &&
-                   is_di_post_on())
+               if (di_post)
                        VSYNC_WR_MPEG_REG_BITS(
                                VIU_MISC_CTRL0 + misc_off,
                                0, 16, 3);
@@ -593,6 +624,7 @@ static void vd1_set_dcu(
        u8 burst_len = 1;
        u32 vd_off = layer->vd_reg_offt;
        u32 afbc_off = layer->afbc_reg_offt;
+       bool di_post = false;
 
        if (!vf) {
                pr_info("vd1_set_dcu vf NULL, return\n");
@@ -606,6 +638,12 @@ static void vd1_set_dcu(
        pr_debug("%s for vd%d %p, type:0x%x\n",
                 __func__, layer->layer_id, vf, type);
 
+#ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE
+       if ((glayer_info[0].display_path_id != VFM_PATH_PIP) &&
+           is_di_post_mode(vf) && is_di_post_on())
+               di_post = true;
+#endif
+
        if (frame_par->nocomp)
                type &= ~VIDTYPE_COMPRESS;
 
@@ -696,7 +734,7 @@ static void vd1_set_dcu(
                                VSYNC_WR_MPEG_REG(
                                        AFBCDEC_IQUANT_ENABLE + afbc_off, 0);
                }
-               vd1_path_select(layer, true, false);
+               vd1_path_select(layer, true, false, di_post);
                if (is_mvc)
                        vd2_path_select(layer, true, false);
                VSYNC_WR_MPEG_REG(
@@ -737,6 +775,14 @@ static void vd1_set_dcu(
                VSYNC_WR_MPEG_REG_BITS(
                        G12_VD1_IF0_GEN_REG3,
                        (burst_len & 0x3), 1, 2);
+               if (vf->flag & VFRAME_FLAG_VIDEO_LINEAR)
+                       VSYNC_WR_MPEG_REG_BITS(
+                               G12_VD1_IF0_GEN_REG3,
+                               0, 0, 1);
+               else
+                       VSYNC_WR_MPEG_REG_BITS(
+                               G12_VD1_IF0_GEN_REG3,
+                               1, 0, 1);
                if (is_mvc) {
                        VSYNC_WR_MPEG_REG_BITS(
                                G12_VD2_IF0_GEN_REG3,
@@ -744,6 +790,14 @@ static void vd1_set_dcu(
                        VSYNC_WR_MPEG_REG_BITS(
                                G12_VD2_IF0_GEN_REG3,
                                (burst_len & 0x3), 1, 2);
+                       if (vf->flag & VFRAME_FLAG_VIDEO_LINEAR)
+                               VSYNC_WR_MPEG_REG_BITS(
+                                       G12_VD2_IF0_GEN_REG3,
+                                       0, 0, 1);
+                       else
+                               VSYNC_WR_MPEG_REG_BITS(
+                                       G12_VD2_IF0_GEN_REG3,
+                                       1, 0, 1);
                }
        } else {
                VSYNC_WR_MPEG_REG_BITS(
@@ -757,23 +811,25 @@ static void vd1_set_dcu(
                                (bit_mode & 0x3), 8, 2);
        }
 #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE
-       DI_POST_WR_REG_BITS(
-               DI_IF1_GEN_REG3,
-               (bit_mode & 0x3), 8, 2);
-       if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX))
+       if (is_di_post_mode(vf)) {
                DI_POST_WR_REG_BITS(
-                       DI_IF2_GEN_REG3,
-                       (bit_mode & 0x3), 8, 2);
-       if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A))
-               DI_POST_WR_REG_BITS(
-                       DI_IF0_GEN_REG3,
+                       DI_IF1_GEN_REG3,
                        (bit_mode & 0x3), 8, 2);
+               if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX))
+                       DI_POST_WR_REG_BITS(
+                               DI_IF2_GEN_REG3,
+                               (bit_mode & 0x3), 8, 2);
+               if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A))
+                       DI_POST_WR_REG_BITS(
+                               DI_IF0_GEN_REG3,
+                               (bit_mode & 0x3), 8, 2);
+       }
 #endif
        if (glayer_info[0].need_no_compress ||
            (vf->type & VIDTYPE_PRE_DI_AFBC)) {
-               vd1_path_select(layer, false, true);
+               vd1_path_select(layer, false, true, di_post);
        } else {
-               vd1_path_select(layer, false, false);
+               vd1_path_select(layer, false, false, di_post);
                if (is_mvc)
                        vd2_path_select(layer, false, false);
                VSYNC_WR_MPEG_REG(
@@ -801,6 +857,9 @@ static void vd1_set_dcu(
        if (frame_par->hscale_skip_count)
                r |= VDIF_CHROMA_HZ_AVG | VDIF_LUMA_HZ_AVG;
 
+       if (vf->flag & VFRAME_FLAG_VIDEO_LINEAR)
+               r |= (1 << 4);
+
        /*enable go field reset default according to vlsi*/
        r |= VDIF_RESET_ON_GO_FIELD;
        VSYNC_WR_MPEG_REG(VD1_IF0_GEN_REG + vd_off, r);
@@ -845,9 +904,8 @@ static void vd1_set_dcu(
        } else {
                /* TODO: if always use HFORMATTER_REPEAT */
                if (is_crop_left_odd(frame_par)) {
-                       if (!(type & VIDTYPE_PRE_INTERLACE) &&
-                           ((type & VIDTYPE_VIU_NV21) ||
-                            (type & VIDTYPE_VIU_422)))
+                       if ((type & VIDTYPE_VIU_NV21) ||
+                           (type & VIDTYPE_VIU_422))
                                hphase = 0x8 << HFORMATTER_PHASE_BIT;
                }
                if (is_dolby_vision_on())
@@ -1168,6 +1226,14 @@ static void vd2_set_dcu(
                VSYNC_WR_MPEG_REG_BITS(
                        G12_VD2_IF0_GEN_REG3,
                        (burst_len & 0x3), 1, 2);
+               if (vf->flag & VFRAME_FLAG_VIDEO_LINEAR)
+                       VSYNC_WR_MPEG_REG_BITS(
+                               G12_VD2_IF0_GEN_REG3,
+                               0, 0, 1);
+               else
+                       VSYNC_WR_MPEG_REG_BITS(
+                               G12_VD2_IF0_GEN_REG3,
+                               1, 0, 1);
        } else {
                VSYNC_WR_MPEG_REG_BITS(
                        VD2_IF0_GEN_REG3 + vd_off,
@@ -1198,6 +1264,9 @@ static void vd2_set_dcu(
        if (frame_par->hscale_skip_count)
                r |= VDIF_CHROMA_HZ_AVG | VDIF_LUMA_HZ_AVG;
 
+       if (vf->flag & VFRAME_FLAG_VIDEO_LINEAR)
+               r |= (1 << 4);
+
        VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG + vd_off, r);
 
        if (type & VIDTYPE_VIU_NV21)
@@ -1229,9 +1298,8 @@ static void vd2_set_dcu(
        } else {
                /* TODO: if always use HFORMATTER_REPEAT */
                if (is_crop_left_odd(frame_par)) {
-                       if (!(type & VIDTYPE_PRE_INTERLACE) &&
-                           ((type & VIDTYPE_VIU_NV21) ||
-                            (type & VIDTYPE_VIU_422)))
+                       if ((type & VIDTYPE_VIU_NV21) ||
+                           (type & VIDTYPE_VIU_422))
                                hphase = 0x8 << HFORMATTER_PHASE_BIT;
                }
                if (is_dolby_vision_on())
@@ -2295,11 +2363,13 @@ static void disable_vd1_blend(struct video_layer_s *layer)
        vd_off = layer->vd_reg_offt;
        afbc_off = layer->afbc_reg_offt;
        if (layer->global_debug & DEBUG_FLAG_BLACKOUT)
-               pr_info("VIDEO: VD1 AFBC off now. dispbuf:%p, *dispbuf_mapping:%p, local: %p-%p\n",
+               pr_info("VIDEO: VD1 AFBC off now. dispbuf:%p, *dispbuf_mapping:%p, local: %p, %p, %p, %p\n",
                        layer->dispbuf,
                        layer->dispbuf_mapping ?
                        *layer->dispbuf_mapping : NULL,
-                       &vf_local, &local_pip);
+                       &vf_local, &local_pip,
+                       gvideo_recv[0] ? &gvideo_recv[0]->local_buf : NULL,
+                       gvideo_recv[1] ? &gvideo_recv[1]->local_buf : NULL);
        VSYNC_WR_MPEG_REG(AFBC_ENABLE + afbc_off, 0);
        VSYNC_WR_MPEG_REG(VD1_IF0_GEN_REG + vd_off, 0);
        if (!legacy_vpp)
@@ -2350,11 +2420,13 @@ static void disable_vd2_blend(struct video_layer_s *layer)
        vd_off = layer->vd_reg_offt;
        afbc_off = layer->afbc_reg_offt;
        if (layer->global_debug & DEBUG_FLAG_BLACKOUT)
-               pr_info("VIDEO: VD2 AFBC off now. dispbuf:%p, *dispbuf_mapping:%p, local: %p-%p\n",
+               pr_info("VIDEO: VD2 AFBC off now. dispbuf:%p, *dispbuf_mapping:%p, local: %p, %p, %p, %p\n",
                        layer->dispbuf,
                        layer->dispbuf_mapping ?
                        *layer->dispbuf_mapping : NULL,
-                       &vf_local, &local_pip);
+                       &vf_local, &local_pip,
+                       gvideo_recv[0] ? &gvideo_recv[0]->local_buf : NULL,
+                       gvideo_recv[1] ? &gvideo_recv[1]->local_buf : NULL);
        VSYNC_WR_MPEG_REG(VD2_AFBC_ENABLE + afbc_off, 0);
        VSYNC_WR_MPEG_REG(VD2_IF0_GEN_REG + vd_off, 0);
        if (!legacy_vpp)
@@ -3454,6 +3526,14 @@ EXPORT_SYMBOL(get_video_mute);
 
 static void check_video_mute(void)
 {
+       u32 black_val;
+
+       if (is_meson_tl1_cpu())
+               black_val = (0x0 << 20) | (0x0 << 10) | 0; /* RGB */
+       else
+               black_val =
+                       (0x0 << 20) | (0x200 << 10) | 0x200; /* YUV */
+
        if (video_mute_on) {
                if (is_dolby_vision_on()) {
                        /* core 3 black */
@@ -3465,14 +3545,18 @@ static void check_video_mute(void)
                } else {
                        if (video_mute_status != VIDEO_MUTE_ON_VPP) {
                                /* vpp black */
-                               VSYNC_WR_MPEG_REG(VPP_CLIP_MISC0,
-                                                 (0x0 << 20) |
-                                                 (0x200 << 10) |
-                                                 0x200);
-                               VSYNC_WR_MPEG_REG(VPP_CLIP_MISC1,
-                                                 (0x0 << 20) |
-                                                 (0x200 << 10) |
-                                                 0x200);
+                               VSYNC_WR_MPEG_REG(
+                                       VPP_CLIP_MISC0,
+                                       black_val);
+                               VSYNC_WR_MPEG_REG(
+                                       VPP_CLIP_MISC1,
+                                       black_val);
+                               WRITE_VCBUS_REG(
+                                       VPP_CLIP_MISC0,
+                                       black_val);
+                               WRITE_VCBUS_REG(
+                                       VPP_CLIP_MISC1,
+                                       black_val);
                                pr_info("DOLBY: check_video_mute: VIDEO_MUTE_ON_VPP\n");
                        }
                        video_mute_status = VIDEO_MUTE_ON_VPP;
@@ -3486,13 +3570,15 @@ static void check_video_mute(void)
                        video_mute_status = VIDEO_MUTE_OFF;
                } else {
                        if (video_mute_status != VIDEO_MUTE_OFF) {
-                               VSYNC_WR_MPEG_REG(VPP_CLIP_MISC0,
-                                                 (0x3ff << 20) |
-                                                 (0x3ff << 10) |
-                                                 0x3ff);
-                               VSYNC_WR_MPEG_REG(VPP_CLIP_MISC1,
-                                                 (0x0 << 20) |
-                                                 (0x0 << 10) | 0x0);
+                               VSYNC_WR_MPEG_REG(
+                                       VPP_CLIP_MISC0,
+                                       (0x3ff << 20) |
+                                       (0x3ff << 10) |
+                                       0x3ff);
+                               VSYNC_WR_MPEG_REG(
+                                       VPP_CLIP_MISC1,
+                                       (0x0 << 20) |
+                                       (0x0 << 10) | 0x0);
                                pr_info("DOLBY: check_video_mute: VIDEO_MUTE_OFF dv off\n");
                        }
                        video_mute_status = VIDEO_MUTE_OFF;
@@ -4041,6 +4127,7 @@ int set_layer_display_canvas(
 
 #ifdef CONFIG_AMLOGIC_MEDIA_DEINTERLACE
        if ((layer_id == 0) &&
+           is_di_post_mode(vf) &&
            is_di_post_link_on())
                update_mif = false;
 #endif
@@ -4391,9 +4478,11 @@ static void do_vpu_delay_work(struct work_struct *work)
                                switch_vpu_mem_pd_vmod(
                                        VPU_AFBC_DEC,
                                        VPU_MEM_POWER_DOWN);
+#ifdef DI_POST_PWR
                                switch_vpu_mem_pd_vmod(
                                        VPU_DI_POST,
                                        VPU_MEM_POWER_DOWN);
+#endif
                                if (!legacy_vpp)
                                        switch_vpu_mem_pd_vmod(
                                                VPU_VD1_SCALE,
@@ -4569,7 +4658,7 @@ int video_early_init(void)
                vd_layer[i].next_canvas_id = 1;
 #endif
                /* vd_layer[i].global_output = 1; */
-               vd_layer[i].keep_frame_id = i;
+               vd_layer[i].keep_frame_id = 0xff;
                vd_layer[i].disable_video = VIDEO_DISABLE_FORNEXT;
                vpp_disp_info_init(&glayer_info[i], i);
                memset(&gpic_info[i], 0, sizeof(struct vframe_pic_mode_s));
index c33abd7b8cdb7e754b4c06a5b8610697cb29469a..f10625b436e57884add9d7f58bf933e90f2f1308 100644 (file)
@@ -44,6 +44,7 @@
 #define DEBUG_FLAG_OMX_DISABLE_DROP_FRAME        0x2000000
 #define DEBUG_FLAG_PRINT_DROP_FRAME        0x4000000
 #define DEBUG_FLAG_OMX_DV_DROP_FRAME        0x8000000
+#define DEBUG_FLAG_COMPOSER_NO_DROP_FRAME     0x10000000
 
 #define VOUT_TYPE_TOP_FIELD 0
 #define VOUT_TYPE_BOT_FIELD 1
@@ -86,6 +87,8 @@ enum vd_path_id {
        VFM_PATH_DEF = -1,
        VFM_PATH_AMVIDEO = 0,
        VFM_PATH_PIP = 1,
+       VFM_PATH_VIDEO_RENDER0 = 2,
+       VFM_PATH_VIDEO_RENDER1 = 3,
        VFM_PATH_INVAILD = 0xff
 };
 
@@ -272,6 +275,8 @@ u32 get_videopip_enabled(void);
 bool is_di_on(void);
 bool is_di_post_on(void);
 bool is_di_post_link_on(void);
+bool is_di_post_mode(struct vframe_s *vf);
+
 bool is_afbc_enabled(u8 layer_id);
 bool is_local_vf(struct vframe_s *vf);
 
@@ -383,10 +388,15 @@ extern struct vframe_s *cur_dispbuf;
 extern struct vframe_s *cur_pipbuf;
 extern bool need_disable_vd2;
 extern u32 last_el_status;
+extern u32 force_blackout;
+extern atomic_t video_unreg_flag;
+extern atomic_t video_inirq_flag;
+extern struct video_recv_s *gvideo_recv[2];
 
 bool black_threshold_check(u8 id);
 void update_cur_dispbuf(void *buf);
 struct vframe_s *get_cur_dispbuf(void);
+s32 set_video_path_select(const char *recv_name, u8 layer_id);
 
 /*for video related files only.*/
 void video_module_lock(void);
diff --git a/drivers/amlogic/media/video_sink/video_receiver.c b/drivers/amlogic/media/video_sink/video_receiver.c
new file mode 100644 (file)
index 0000000..db44392
--- /dev/null
@@ -0,0 +1,428 @@
+/*
+ * drivers/amlogic/media/video_sink/video_receiver.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/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/ctype.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
+#include "../common/rdma/rdma.h"
+#endif
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/amlogic/media/vfm/vframe_provider.h>
+#include <linux/amlogic/media/vfm/vframe_receiver.h>
+#include <linux/amlogic/media/video_sink/vpp.h>
+#include <linux/amlogic/media/video_sink/video.h>
+
+#include "video_priv.h"
+#include "video_receiver.h"
+
+/* #define ENABLE_DV */
+
+/*********************************************************
+ * vframe APIs
+ *********************************************************/
+static inline struct vframe_s *common_vf_peek(struct video_recv_s *ins)
+{
+       struct vframe_s *vf = NULL;
+
+       if (!ins || !ins->recv_name || !ins->active)
+               return NULL;
+
+       vf = vf_peek(ins->recv_name);
+       if (vf && vf->disp_pts && vf->disp_pts_us64) {
+               vf->pts = vf->disp_pts;
+               vf->pts_us64 = vf->disp_pts_us64;
+               vf->disp_pts = 0;
+               vf->disp_pts_us64 = 0;
+       }
+       return vf;
+}
+
+static inline struct vframe_s *common_vf_get(struct video_recv_s *ins)
+{
+       struct vframe_s *vf = NULL;
+
+       if (!ins || !ins->recv_name || !ins->active)
+               return NULL;
+
+       vf = vf_get(ins->recv_name);
+
+       if (vf) {
+               if (vf->disp_pts && vf->disp_pts_us64) {
+                       vf->pts = vf->disp_pts;
+                       vf->pts_us64 = vf->disp_pts_us64;
+                       vf->disp_pts = 0;
+                       vf->disp_pts_us64 = 0;
+               }
+               ins->notify_flag |= VIDEO_NOTIFY_PROVIDER_GET;
+       }
+       return vf;
+}
+
+#ifdef MORE_FUNCTION
+static int common_vf_get_states(
+       struct video_recv_s *ins,
+       struct vframe_states *states)
+{
+       int ret = -1;
+       unsigned long flags;
+
+       if (!ins || !ins->recv_name || !ins->active || !states)
+               return ret;
+
+       spin_lock_irqsave(&ins->lock, flags);
+       ret = vf_get_states_by_name(ins->recv_name, states);
+       spin_unlock_irqrestore(&ins->lock, flags);
+       return ret;
+}
+#endif
+
+static inline void common_vf_put(
+       struct video_recv_s *ins,
+       struct vframe_s *vf)
+{
+       struct vframe_provider_s *vfp = NULL;
+
+       if (!ins || !ins->recv_name)
+               return;
+
+       vfp = vf_get_provider(ins->recv_name);
+       if (vfp && vf) {
+               vf_put(vf, ins->recv_name);
+/* FIXME: chek if need enable */
+#ifdef ENABLE_DV /* CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION */
+               if ((glayer_info[0].display_path_id == ins->path_id) &&
+                   is_dolby_vision_enable())
+                       dolby_vision_vf_put(vf);
+#endif
+               ins->notify_flag |= VIDEO_NOTIFY_PROVIDER_PUT;
+       }
+}
+
+/* TODO: need add keep frame function */
+static void common_vf_unreg_provider(struct video_recv_s *ins)
+{
+       ulong flags;
+       bool layer1_used = false;
+       bool layer2_used = false;
+
+       if (!ins)
+               return;
+
+       /* FIXME: remove the global variable */
+       atomic_inc(&video_unreg_flag);
+       while (atomic_read(&video_inirq_flag) > 0)
+               schedule();
+
+       spin_lock_irqsave(&ins->lock, flags);
+       ins->buf_to_put = NULL;
+       ins->rdma_buf = NULL;
+
+       if (ins->cur_buf) {
+               ins->local_buf = *ins->cur_buf;
+               ins->cur_buf = &ins->local_buf;
+       }
+       spin_unlock_irqrestore(&ins->lock, flags);
+
+       if (vd_layer[0].dispbuf_mapping
+               == &ins->cur_buf) {
+               layer1_used = true;
+       }
+       if (vd_layer[1].dispbuf_mapping
+               == &ins->cur_buf) {
+               layer2_used = true;
+       }
+
+       if (!layer1_used && !layer2_used)
+               ins->cur_buf = NULL;
+
+       if (layer1_used)
+               safe_switch_videolayer(
+                       0, false, false);
+       if (layer2_used)
+               safe_switch_videolayer(
+                       1, false, false);
+
+       pr_info("common_vf_unreg_provider %s: vd1 used: %s, vd2 used: %s, black_out:%d, cur_buf:%p\n",
+               ins->recv_name,
+               layer1_used ? "true" : "false",
+               layer2_used ? "true" : "false",
+               ins->blackout | force_blackout,
+               ins->cur_buf);
+
+       ins->active = false;
+       atomic_dec(&video_unreg_flag);
+}
+
+static void common_vf_light_unreg_provider(
+       struct video_recv_s *ins)
+{
+       ulong flags;
+
+       if (!ins)
+               return;
+
+       /* FIXME: remove the global variable */
+       atomic_inc(&video_unreg_flag);
+       while (atomic_read(&video_inirq_flag) > 0)
+               schedule();
+
+       spin_lock_irqsave(&ins->lock, flags);
+       ins->buf_to_put = NULL;
+       ins->rdma_buf = NULL;
+
+       if (ins->cur_buf) {
+               ins->local_buf = *ins->cur_buf;
+               ins->cur_buf = &ins->local_buf;
+       }
+       spin_unlock_irqrestore(&ins->lock, flags);
+
+       atomic_dec(&video_unreg_flag);
+}
+
+static int common_receiver_event_fun(
+       int type, void *data, void *private_data)
+{
+       struct video_recv_s *ins = (struct video_recv_s *)private_data;
+
+       if (!ins) {
+               pr_err("common_receiver_event: ins invalid, type:%d\n", type);
+               return -1;
+       }
+       if (type == VFRAME_EVENT_PROVIDER_UNREG) {
+               common_vf_unreg_provider(ins);
+       } else if (type == VFRAME_EVENT_PROVIDER_RESET) {
+               common_vf_light_unreg_provider(ins);
+       } else if (type == VFRAME_EVENT_PROVIDER_LIGHT_UNREG) {
+               common_vf_light_unreg_provider(ins);
+       } else if (type == VFRAME_EVENT_PROVIDER_REG) {
+               common_vf_light_unreg_provider(ins);
+               ins->drop_vf_cnt = 0;
+               ins->active = true;
+       }
+       return 0;
+}
+
+static const struct vframe_receiver_op_s common_recv_func = {
+       .event_cb = common_receiver_event_fun
+};
+
+#ifdef ENABLE_DV /* CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION */
+static int dolby_vision_need_wait_common(struct video_recv_s *ins)
+{
+       struct vframe_s *vf;
+
+       if (!is_dolby_vision_enable() || !ins)
+               return 0;
+
+       vf = common_vf_peek(ins);
+       if (!vf || (dolby_vision_wait_metadata(vf) == 1))
+               return 1;
+       return 0;
+}
+#endif
+
+static void common_toggle_frame(
+       struct video_recv_s *ins, struct vframe_s *vf)
+{
+       if (!ins || !vf)
+               return;
+
+       if ((vf->width == 0) || (vf->height == 0)) {
+               pr_err("common_toggle_frame %s: invalid frame dimension\n",
+                      ins->recv_name);
+               return;
+       }
+       if (ins->cur_buf &&
+           (ins->cur_buf != &ins->local_buf) &&
+           (ins->cur_buf != vf)) {
+               ins->frame_count++;
+#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
+               if (is_vsync_rdma_enable()) {
+                       if (ins->rdma_buf == ins->cur_buf)
+                               ins->buf_to_put = ins->cur_buf;
+                       else
+                               common_vf_put(
+                                       ins, ins->cur_buf);
+               } else {
+                       if (ins->buf_to_put) {
+                               common_vf_put(
+                                       ins, ins->buf_to_put);
+                               ins->buf_to_put = NULL;
+                       }
+                       common_vf_put(ins, ins->cur_buf);
+               }
+#else
+               common_vf_put(ins, ins->cur_buf);
+#endif
+       }
+       if (ins->cur_buf != vf)
+               vf->type_backup = vf->type;
+       ins->cur_buf = vf;
+}
+
+/*********************************************************
+ * recv func APIs
+ *********************************************************/
+static s32 recv_common_early_process(
+       struct video_recv_s *ins)
+{
+       if (!ins) {
+               pr_err("recv_common_early_process error, empty ins\n");
+               return -1;
+       }
+
+       if (ins->buf_to_put) {
+               ins->buf_to_put->rendered = true;
+               common_vf_put(
+                       ins, ins->buf_to_put);
+               ins->buf_to_put = NULL;
+       }
+       return 0;
+}
+
+static struct vframe_s *recv_common_dequeue_frame(
+       struct video_recv_s *ins)
+{
+       struct vframe_s *vf = NULL;
+
+       if (!ins) {
+               pr_err("recv_common_dequeue_frame error, empty ins\n");
+               return NULL;
+       }
+
+       vf = common_vf_peek(ins);
+/* FIXME: chek if need enable */
+#ifdef ENABLE_DV /* CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION */
+       if ((glayer_info[0].display_path_id == ins->path_id) && vf &&
+           is_dolby_vision_enable()) {
+               dolby_vision_check_hdr10(vf);
+               dolby_vision_check_hdr10plus(vf);
+               dolby_vision_check_hlg(vf);
+       }
+#endif
+       while (vf) {
+               if (!vf->frame_dirty) {
+#ifdef ENABLE_DV /* CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION */
+                       if ((glayer_info[0].display_path_id == ins->path_id) &&
+                           dolby_vision_need_wait_common(ins))
+                               break;
+#endif
+                       vf = common_vf_get(ins);
+                       if (vf)
+                               common_toggle_frame(ins, vf);
+               } else {
+                       vf = common_vf_get(ins);
+                       if (vf)
+                               common_vf_put(ins, vf);
+               }
+               vf = common_vf_peek(ins);
+       }
+       return vf;
+}
+
+static s32 recv_common_return_frame(
+       struct video_recv_s *ins, struct vframe_s *vf)
+{
+       if (!ins) {
+               pr_err("recv_common_return_frame error, empty ins\n");
+               return -1;
+       }
+       if (vf)
+               common_vf_put(ins, vf);
+       return 0;
+}
+
+static s32 recv_common_late_proc(
+       struct video_recv_s *ins)
+{
+       if (!ins) {
+               pr_err("recv_common_late_proc error, empty ins\n");
+               return -1;
+       }
+#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
+       ins->rdma_buf = ins->cur_buf;
+#endif
+       return 0;
+}
+
+const struct recv_func_s recv_common_ops = {
+       .early_proc = recv_common_early_process,
+       .dequeue_frame = recv_common_dequeue_frame,
+       .return_frame = recv_common_return_frame,
+       .late_proc = recv_common_late_proc,
+};
+
+struct video_recv_s *create_video_receiver(const char *recv_name, u8 path_id)
+{
+       struct video_recv_s *ins = NULL;
+
+       if (!recv_name) {
+               pr_err("create_video_receiver: recv_name is NULL.\n");
+               goto CREATE_FAIL;
+       }
+       ins = kmalloc(sizeof(*ins), GFP_KERNEL);
+       if (!ins)
+               goto CREATE_FAIL;
+
+       memset(ins, 0, sizeof(struct video_recv_s));
+       ins->recv_name = (char *)recv_name;
+       ins->vf_ops = (struct vframe_receiver_op_s *)&common_recv_func;
+       ins->func = (struct recv_func_s *)&recv_common_ops;
+       ins->path_id = path_id;
+       spin_lock_init(&ins->lock);
+       vf_receiver_init(
+               &ins->handle,
+               ins->recv_name,
+               ins->vf_ops, ins);
+       if (vf_reg_receiver(&ins->handle)) {
+               pr_err(
+                       "create_video_receiver %s: reg recv fail\n",
+                       recv_name);
+               goto CREATE_FAIL;
+       }
+       pr_info(
+               "create_video_receiver %s  %p, path_id:%d success\n",
+               recv_name, ins, ins->path_id);
+       return ins;
+CREATE_FAIL:
+       kfree(ins);
+       return NULL;
+}
+
+void destroy_video_receiver(struct video_recv_s *ins)
+{
+       if (!ins) {
+               pr_err("destroy_video_receiver: ins is NULL.\n");
+               return;
+       }
+       vf_unreg_receiver(&ins->handle);
+       kfree(ins);
+       pr_info("destroy_video_receiver\n");
+}
diff --git a/drivers/amlogic/media/video_sink/video_receiver.h b/drivers/amlogic/media/video_sink/video_receiver.h
new file mode 100644 (file)
index 0000000..51f0b92
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * drivers/amlogic/media/video_sink/video_receiver.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 VIDEO_RECEIVER_HEADER_HH
+#define VIDEO_RECEIVER_HEADER_HH
+
+#include <linux/amlogic/media/vfm/vframe.h>
+
+struct video_layer_s;
+
+struct recv_func_s {
+       s32 (*early_proc)(struct video_recv_s *ins);
+       struct vframe_s *(*dequeue_frame)(struct video_recv_s *ins);
+       s32 (*return_frame)(struct video_recv_s *ins, struct vframe_s *vf);
+       s32 (*late_proc)(struct video_recv_s *ins);
+};
+
+struct video_recv_s {
+       char *recv_name;
+       /* recv lock */
+       spinlock_t lock;
+       struct vframe_receiver_s handle;
+       struct vframe_receiver_op_s *vf_ops;
+       struct vframe_s local_buf;
+       struct vframe_s *cur_buf;
+       struct vframe_s *rdma_buf;
+       struct vframe_s *buf_to_put;
+
+       bool active;
+
+       u32 notify_flag;
+       u32 blackout;
+       u32 frame_count;
+       u32 drop_vf_cnt;
+       u8 path_id;
+       struct recv_func_s *func;
+};
+
+struct video_recv_s *create_video_receiver(const char *recv_name, u8 path_id);
+void destroy_video_receiver(struct video_recv_s *ins);
+
+#endif
index d385f8887127b03ceb66c9d2efcb4ac80991b22f..459850e21645da69acd4edaa7889549719f98948 100644 (file)
@@ -32,6 +32,8 @@
 #define IONVIDEO_MAJOR         (15+(AML_BASE))
 #define VAD_MAJOR              (16+(AML_BASE))
 #define VIDEOSYNC_MAJOR                (17+(AML_BASE))
+#define V4LVIDEO_MAJOR         (18 + (AML_BASE))
+#define VIDEO_COMPOSER_MAJOR    (19 + (AML_BASE))
 /*
  *#define UIO_MAJOR                    4+(AML_BASE)
  *#define USB_DEV_EP_MAJOR     5+(AML_BASE)
index a684bf5b2e3917d3128772897a7f844321c6bb57..c13843daebdb6b6985c37e087ad417b590b0662e 100644 (file)
@@ -278,6 +278,7 @@ enum FRAME_BASE_VIDEO_PATH {
        FRAME_BASE_PATH_V4L_VIDEO,
        FRAME_BASE_PATH_TUNNEL_MODE,
        FRAME_BASE_PATH_V4L_OSD,
+       FRAME_BASE_PATH_DI_V4LVIDEO,
        FRAME_BASE_PATH_MAX
 };
 
index f801aa94a46174636d61f819fb12955e7e03aa16..04de43d4b1ccc176d95c6cd7a7e468dade5eb996 100644 (file)
 #define VFRAME_FLAG_ERROR_RECOVERY             8
 #define VFRAME_FLAG_SYNCFRAME                  0x10
 #define VFRAME_FLAG_GAME_MODE          0x20
+#define VFRAME_FLAG_VIDEO_COMPOSER     0x40
+#define VFRAME_FLAG_VIDEO_COMPOSER_BYPASS     0x80
+#define VFRAME_FLAG_COMPOSER_DONE     0x100
+#define VFRAME_FLAG_VIDEO_COMPOSER_DMA     0x200
+#define VFRAME_FLAG_VIDEO_LINEAR     0x400
 #define VFRAME_FLAG_EMPTY_FRAME_V4L            0x800
+#define VFRAME_FLAG_FAKE_FRAME         0x1000
 
 enum pixel_aspect_ratio_e {
        PIXEL_ASPECT_RATIO_1_1,
@@ -405,6 +411,7 @@ struct vframe_s {
        long long ready_clock[5];/*ns*/
        long long ready_clock_hist[2];/*ns*/
        atomic_t use_cnt;
+       atomic_t use_cnt_pip;
        u32 frame_dirty;
        /*
         *prog_proc_config:
@@ -428,6 +435,7 @@ struct vframe_s {
 
        u32 sar_width;
        u32 sar_height;
+
        /*****************
         * di pulldown info
         * bit 3: interlace
@@ -437,6 +445,12 @@ struct vframe_s {
         *****************/
        u32 di_pulldown;
        u32 di_gmv;
+       u32 axis[4];
+       u32 crop[4];
+       u32 zorder;
+       u32 repeat_count[2];
+       struct file *file_vf;
+       bool rendered;
 } /*vframe_t */;
 
 #if 0
diff --git a/include/linux/amlogic/media/video_processor/video_composer_ext.h b/include/linux/amlogic/media/video_processor/video_composer_ext.h
new file mode 100644 (file)
index 0000000..57ef9e1
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * include/linux/amlogic/media/video_processor/video_composer_ext.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 VIDEO_COMPOSER_EXT_H
+#define VIDEO_COMPOSER_EXT_H
+
+#include <linux/amlogic/media/vfm/vframe.h>
+
+struct composer_dst {
+       dma_addr_t phy_addr;
+       u32 buffer_width;
+       u32 buffer_height;
+       u32 content_left;
+       u32 content_top;
+       u32 content_w;
+       u32 content_h;
+       u32 format;
+};
+
+#endif /* VIDEO_COMPOSER_EXT_H */
+
diff --git a/include/linux/amlogic/media/video_sink/v4lvideo_ext.h b/include/linux/amlogic/media/video_sink/v4lvideo_ext.h
new file mode 100644 (file)
index 0000000..52d9127
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * include/linux/amlogic/media/video_sink/v4lvideo_ext.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 V4LVIDEO_EXT_H
+#define V4LVIDEO_EXT_H
+
+int v4lvideo_assign_map(char **receiver_name, int *inst);
+
+int v4lvideo_alloc_map(int *inst);
+
+void v4lvideo_release_map(int inst);
+
+struct file_private_data {
+       struct vframe_s vf;
+       struct vframe_s *vf_p;
+       bool is_keep;
+       int keep_id;
+       int keep_head_id;
+       struct file *file;
+};
+
+struct v4l_data_t {
+       struct vframe_s *vf;
+       char *dst_addr;
+};
+
+void v4lvideo_data_copy(struct v4l_data_t *v4l_data);
+struct vframe_s *v4lvideo_get_vf(int fd);
+void dim_post_keep_cmd_release2(struct vframe_s *vframe);
+
+#endif /* V4LVIDEO_EXT_H */
+
index a9b3c604611089fa797e71756137b48179c7cd4e..ce28fd1b873945bbdecbb38b746b66b915b52bfa 100644 (file)
@@ -260,4 +260,14 @@ void DI_POST_UPDATE_MC(void);
 
 extern void videosync_pcrscr_update(s32 inc, u32 base);
 void vsync_notify_videosync(void);
+void vsync_notify_video_composer(void);
+int _video_set_disable(u32 val);
+int _videopip_set_disable(u32 val);
+void video_set_global_output(u32 index, u32 val);
+u32 video_get_layer_capability(void);
+void set_video_crop_ext(int layer_index, int *p);
+void set_video_window_ext(int layer_index, int *p);
+void set_video_zorder_ext(int layer_index, int zorder);
+s32 set_video_path_select(const char *recv_name, u8 layer_id);
+
 #endif /* VIDEO_H */